MC68020/68881 Coprocessor Card for the Apple II
This is a partial mirror of http://www.brouhaha.com/~eric/retrocomputing/apple/apple2/68020/
In late 1985 I designed a MC68020/68881 coprocessor card for the Apple II, based on an earlier 68008 card designed by Richard Ottosen. Richard and I built the card. The MC68020 and MC68881 are run from a common clock, which is jumper selectable from either an on-board oscillator or the Apple II 7M clock.
The card has a 2764 boot EPROM, and 32 Kbyte of SRAM organized as 8K*32.
Communication with the Apple II is by means of four eight-bit parallel I/O ports, two in each direction, and by one interrupt "doorbell" in each direction. Typically one port in each direction is used for data, and the other for status and/or handshaking.
On system reset, the MC68020 CPU is held in reset until the Apple II releases it by writing to an I/O location.
We used two PAL16L8 chips (U2 and U12) for the address and byte strobe decode, bus error, and interrupt auto-vector.
p001.palasm: PAL16L8A - chip select/BERR/AVEC/DSACK0 decoder
P001 - PAL16L8A - chip select/BERR/AVEC/DSACK0 decoder AS* 1 20 Vcc CPU* 2 19 nc A17 3 18 BERR* A16 4 17 RAMCS* A15 5 16 IOCS* A14 6 15 ROMCS* A13 7 14 AVEC* CPP* 8 13 FPCPCS* nc 9 12 DSACK0* GND 10 11 nc AVEC = AS & CPU & A17 & A16 FPCPCS = CPU & CPP & A17 & A16* # include AS? BERR = AS & CPU & CPP* & A17 & A16* # FPCP not installed + AS & CPU & CPP & A17 & A16* & A15 # wrong coprocessor ID + AS & CPU & CPP & A17 & A16* & A14 # wrong coprocessor ID + AS & CPU & CPP & A17 & A16* & A13 # wrong coprocessor ID + AS & CPU & A16 # access level control + AS & CPU* & A17 # 0x20000-3ffff + AS & CPU* & A16 # 0x10000-1ffff + AS & CPU* & A17* & A16* & A15 & A14 & A13* # 0x0c000-0dfff + AS & CPU* & A17* & A16* & A15 & A14* & A13 # 0x0a000-0bfff RAMCS = AS & CPU* & ((A17* & A16* & A15* & A14* & A13) | # 0x2000-3fff (A17* & A16* & A15* & A14 & A13*) | # 0x4000-5fff (A17* & A16* & A15* & A14 & A13) | # 0x6000-7fff (A17* & A16* & A15 & A14* & A13*)) # 0x8000-9fff ROMCS = AS & CPU* & A17* & A16* & A15* & A14* & A13* # 0x0000-1fff IOCS = AS & CPU* & A17* & A16* & A15 & A14 & A13 # 0xe000-ffff FPCPCS = CPU + CPP + A17 + A16* + A15* + A14* + A13* DSACK0 = ROMCS + IOCS + RAMCS # DSACK0* is externally buffered (OC) to drive the MC68020 DSACK0* # (8-bit ROM, I/O) # (32-bit RAM) # RAMCS* is externally buffered (OC) to drive the MC68020 DSACK1* # (32-bit RAM)
p002.palasm: PAL16L8A - byte enable decoder
P002 - PAL16L8A - byte enable decoder DS* 1 20 Vcc R/W* 2 19 nc SIZ1 3 18 nc SIZ0 4 17 nc A1 5 16 WE3* A0 6 15 WE2* nc 7 14 WE1* nc 8 13 WE0* nc 9 12 OE* GND 10 11 nc # Note WE0 is MSB (D31..24) # WE3 is LSB (D7..0) rd = R/W* wr = ! rd OE = DS & rd WE3 = DS & wr & ((A1 = 1 & A0 = 1) | (SIZ1 = 1 & A1 = 1 & A0 = 0) | (SIZ0 = 0 & A1 = 1 & A0 = 0) | (SIZ1 = 1 & SIZ0 = 1 & A1 = 0 & A0 = 1) | (SIZ1 = 0 & SIZ0 = 0 & A1 = 0)) WE2 = DS & wr & ((A1 = 1 & A0 = 0) | (SIZ1 = 1 & A1 = 0 & A0 = 1) | (SIZ0 = 0 & A1 = 0 & A0 = 1) | (SIZ1 = 1 & SIZ0 = 1 & A1 = 0 & A0 = 0) | (SIZ1 = 0 & SIZ0 = 0 & A1 = 0 & A0 = 0)) WE1 = DS & wr & ((A1 = 0 & A0 = 1) | (SIZ1 = 1 & A1 = 0 & A0 = 0) | (SIZ0 = 0 & A1 = 0 & A0 = 0)) WE0 = DS & wr & (A1 = 0 & A0 = 0)
We didn't have wire-wrap sockets for the PGAs, so Richard constructed custom ones by removing the pins from machined-pin DIP wire-wrap sockets, and inserting them into suitably sized (13x13, 10x10) pieces of perf board with the holes drilled out to a slightly larger diameter. Most of the remaining circuitry was wired using 3M Scotchflex insulation-displacement prototyping, which is much faster to wire than wire-wrap, but not as mechanically robust.
This was the first time either Richard or I had used PALs. Even though the concept seemed fairly simple, we weren't 100% confident that we'd get it right the first time. We purchased five parts, in order to have three spares. We borrowed a Structured Design SD10 programmer. This was a self-contained box that had PALASM built-in, and a wafer-tape drive for storing your source code and/or JEDEC files. All you need with the SD10 is a dumb terminal. In practice, though, we used the Apple II as the terminal, and kept our source files on disk.
Debugging the hardware
I checked and rechecked the wiring. When we plugged it into the Apple, there was a problem with lots of noise on the +5V supply, and the card didn't run the boot code. In short order Richard and I traced this to a fault on the R/W* line. Once this was fixed, the hardware worked. And the PALs did in fact work the first time.
A simple monitor program was put in the EPROM, which provided a means for the Apple II to load code into the card. Loren Blaney modified the XPL0 compiler to generate native 68020 and 68881 code. http://www.idcomm.com/personal/lorenblaney/
Hardware design notes from 19 years later
With the benefit of hindsight, some issues with the design are apparent:
- As designed, the current drawn from the Apple II +5V supply will be around 1000 mA based on the components' typical Icc specifications, up to around 1500 mA based on the maximum Icc specifications. The Apple II Reference Manual states that 500 mA of +5V is available to be shared by ALL of the peripheral cards. Obviously this card should not be used in a heavily loaded Apple II family machine.
- Had we used 74HCT logic instead of 74LS where possible, and lower-power PALs or GALs, and other minor changes to the component selection, we could have reduced the current draw to around 623 mA typical, 756 mA maximum.
- The 74LS374 latches present two LS loads on each data line on the system bus, but the Apple II reference manual states that each peripheral card can present a single LS load on each data line. Arguably a separate data bus buffer (e.g., 74LS245) should have also been used, or 74HCT374 latches could have been used.
- To save board space, the four 74LS374 latches could have been replaced by two 74LS652 registered bus transceivers (uncommon), or two 74HCT652 (even more uncommon) to meet the Apple II data bus specification.
Share your opinion