This post describes GAL22V10 portion of the design.
WinCUPL provides a table entry in the form of
Table Input => Output { list of Input and corresponding Output}
This is a convenient form to enter a small ROM where Input are ROM addresses and Output are ROM data. The size of ROM is variable, depending on the ROM contents and pin assignment of output bits. The pin assignment matters because 22V10's AND-OR fabric are different for different pins. For an example pin 23's AND-OR fabric has 8 AND product lines while pin 18 has 16 AND product lines. If the ROM design won't fit, it may be useful to reassign the data pins. Changing pin assignments is problematic for pc board so I've found 32-byte ROM seems to fit most of the time.
The goal is to bootstrap from CF disk (or serial EEPROM or SD) and run a particular application automatically from power-on. This a multi-stage bootstrap process so it is fairly difficult to create and test various software directly on the CF disk. A near-term solution is bootstrapping from the serial port so I can load/test individual software pieces then assemble them into a CF disk. So there are at least two bootstrap codes, serial bootstrap and CF bootstrap. 22V10 is too small to accommodate both bootstraps so there will be two different versions of 22V10. This post will only address the serial bootstrap.
22V10 has up to 10 outputs and 12 inputs; 32-byte ROM only needs 8 data outputs and 5 address inputs plus one tri-state control. The other 2 outputs and 7 inputs can be used for something else. Address decodes for RAM and I/O are logical uses of these extra input/output. The extra inputs are assigned to 6502's address A15 to A10 and read_write_not. The outputs are RAM output enable and I/O base address. ROM's output enable is driven by A[15..10] all high thus ROM is in address space $FC00-$FFFF. IO is in address space $F800-$FBFF and RAM is from $0-$F7FF. ROM and RAM are enabled all the time, these decodes determine when the data bus is driven by ROM or RAM. IO is the base address signal further decoded by 74138 for CF control signals and additional address for 6551 and 6522.
This is the contents of serial bootstrap 22V10.
Code:
Name ROMSerbt;
Partno ;
Revision ;
Date 11/25/23;
Designer H. SHEN;
Company ;
Location ;
Assembly ;
Device g22v10;
/****************************************************************/
/* Serial Bootstrap */
/* RAM is from 0x0-0xF7FF */
/* ROM is from 0xFC00-0xFFFF */
/* IO is from 0xF800-0xFBFF */
/* Connecting to IO are 65C22, 65C21, and compact flash */
/* compact flash read and write are decoded via 74138 with clock and rwb in inputs */
/* CF addresses are 0xF800-0xF8FF */
/****************************************************************/
/** Inputs **/
Pin 1 = rwb;
Pin 2 = A0;
Pin 3 = A1;
Pin 4 = A2;
Pin 5 = A3;
Pin 6 = A4;
Pin 7 = A10;
Pin 8 = A11;
Pin 9 = A12;
Pin 10 = A13;
Pin 11 = A14;
Pin 13 = A15;
/** Outputs **/
Pin 15 = D0;
Pin 16 = D1;
Pin 17 = D2;
Pin 18 = D3;
Pin 19 = D5;
Pin 20 = D7;
Pin 21 = D6;
Pin 22 = D4;
Pin 14 = !RAMOE;
Pin 23 = !IO;
/** Declarations and Intermediate Variable Definitions **/
Field Addr = [A4..0];
Field Data = [D7..0];
/** Logic Equations **/
RAMOE = rwb & !(A15 & A14 & A13 & A12 & A11);
IO = A15 & A14 & A13 & A12 & A11 & !A10; /* I/O base decode */
D0.oe = A15 & A14 & A13 & A12 & A11 & A10;
D1.oe = A15 & A14 & A13 & A12 & A11 & A10;
D2.oe = A15 & A14 & A13 & A12 & A11 & A10;
D3.oe = A15 & A14 & A13 & A12 & A11 & A10;
D4.oe = A15 & A14 & A13 & A12 & A11 & A10;
D5.oe = A15 & A14 & A13 & A12 & A11 & A10;
D6.oe = A15 & A14 & A13 & A12 & A11 & A10;
D7.oe = A15 & A14 & A13 & A12 & A11 & A10;
Table Addr => Data {
/* Addr Data */
/* ------ --------- */
'h'00 => 'h'a2;
'h'01 => 'h'05;
'h'02 => 'h'8e;
'h'03 => 'h'02;
'h'04 => 'h'fa;
'h'05 => 'h'a9;
'h'06 => 'h'1e;
'h'07 => 'h'8d;
'h'08 => 'h'03;
'h'09 => 'h'fa;
'h'0a => 'h'ad;
'h'0b => 'h'01;
'h'0c => 'h'fa;
'h'0d => 'h'29;
'h'0e => 'h'08;
'h'0f => 'h'f0;
'h'10 => 'h'f9;
'h'11 => 'h'ad;
'h'12 => 'h'00;
'h'13 => 'h'fa;
'h'14 => 'h'9d;
'h'15 => 'h'00;
'h'16 => 'h'c0;
'h'17 => 'h'e8;
'h'18 => 'h'd0;
'h'19 => 'h'f0;
'h'1a => 'h'4c;
'h'1b => 'h'05;
'h'1c => 'h'c0;
'h'1d => 'h'ff;
'h'1e => 'h'00;
'h'1f => 'h'02;
}
------------------------------------------------
Code:
000000r 1 ;11/25/23
000000r 1 ;ROM in 22V10
000000r 1 ;boot from serial port
000000r 1 ;load 251-byte binary file to 0xC005
000000r 1 ;serial port is w65c51 located in range $FA00-$FBFF
000000r 1 ; Use addresses of $FA00 to allow expansion of other I/O devices
000000r 1 W65C51Data = $FA00 ;External ACIA data
000000r 1 W65C51Stat = $FA01 ;external ACIA status
000000r 1 W65C51Cmd = $FA02 ;external ACIA command
000000r 1 W65C51Ctrl = $FA03 ;external ACIA control
000000r 1 .pc02 ;W65C02
000000r 1
000000r 1 .ORG $ffc0
00FFC0 1 A2 05 LDX #$5 ;no parity, RTSB low, DTRB low, interrupt enabled
00FFC2 1 8E 02 FA STX W65C51Cmd ;enable ACIA transmit and receive reg
00FFC5 1 A9 1E LDA #$1e
00FFC7 1 8D 03 FA STA W65C51Ctrl ;internal baud, 38400
00FFCA 1 serboot1:
00FFCA 1 AD 01 FA LDA W65C51Stat ;chk serial receive ready flag
00FFCD 1 29 08 AND #8
00FFCF 1 F0 F9 BEQ serboot1
00FFD1 1 AD 00 FA LDA W65C51Data
00FFD4 1 9D 00 C0 STA $c000,x
00FFD7 1 E8 INX
00FFD8 1 D0 F0 BNE serboot1
00FFDA 1 4C 05 C0 JMP $c005
00FFDD 1
00FFDD 1 FF 00 02 .byte $ff,0,2 ;IRQ vector is $200, reset vector is $FFC0
Above is program listing for the 32-byte serial bootstrap code. It initializes W65C51 then loads 251 bytes of program into $C005-$C0FF then jumps into $C005. The vectors are $200 for interrupt, $FFC0 for reset, and $54C for NMI. These rather odd numbers are results of "putting square pegs in round holes"--this particular solution happens to fit. No doubt there are other working combinations. This is a case where I/O in zero page can reduce the code size.
Bill