This is a short log[*] describing the 16-bit expansion card interface in the 68000 system. I've deliberately kept the design of this interface as simple as possible, in order to make it easy and quick to build expansion cards. I know I could have implemented a standard interface, like VME, S100, or (shudder) ISA, but I didn't. I felt like I'd learn more by implementing my own interface, mainly so that I could discover all of its shortcomings!
The motherboard has four expansion sockets, all with an identical pinout. Here's the setup:
The motherboard sockets are actually DIN41612 "Q" connectors - i.e. the motherboard has a male (pins) connector, and the peripheral card uses a right-angled female (sockets) connector.
Most of the pins are directly mapped to the 68000 bus interface; some are a little different. This table describes the pinout. In the table, "input" means "signal generated by the host", and "output" means "signal generated by the peripheral". "Host pullup" indicates that there's a 10K resistor pulling the pin to VCC on the motherboard.
|VCC||Power||Regulated +5V rail|
|D0-D15||Bidirectional, 3-state||Buffered CPU data bus; only valid when nCS is asserted.|
|A1-A23||Input, 3-state||Buffered CPU address bus; only valid when nCS is asserted.|
|nID||Input||When asserted with nCS, indicates that the host processor is running an "identify peripheral" cycle. The peripheral should place its ID on D15-D8 and assert nACK.|
|nIACK||Input||Asserted when the host processor is acknowledging an interrupt raised by the peripheral.|
|nRESET||Bidirectional, open-drain, host pullup||System reset input. Can be pulled low by a peripheral to reset the system.|
|CLK||Input||Host processor clock.|
|nIRQ||Output, host pullup||Peripheral interrupt request.|
|nBERR||Output, host pullup||Peripheral bus error output.|
|E||Input||6800 peripheral interface: "E" clock signal (10% of f(CLK), 60:40 duty cycle).|
|nACK||Output, host pullup||Peripheral bus cycle transfer acknowledge: asserted by the peripheral to complete a bus cycle.|
|nCS||Input||Peripheral chip select: asserted by the host during a bus cycle addressed to the peripheral.|
|nUR||Input||"Upper byte read": asserted when the host wishes to read bits D15-D8. Only valid when nCS is asserted.|
|nLR||Input||"Lower byte read": same as nUR, but applies to bits D7-D0.|
|nUW||Input||"Upper byte write": asserted when the host has placed valid data on bits D15-D8 during a write cycle. Only valid when nCS is asserted.|
|nLW||Input||"Lower byte write": same as nUW, but applies to bits D7-D0.|
|nVMA||Input||6800 peripheral interface: "valid memory address" strobe.|
|nVPA||Output, host pullup||6800 peripheral interface: "valid peripheral address" strobe.|
|nPD||Output, host pullup||"Presence detect": should be tied to GND by the peripheral. Enables the host to detect that a peripheral is plugged in to an expansion slot.|
Each slot is mapped to a fixed 1MB region of the MC68000 address space. The expansion interface exposes all 23 of the MC68000's address lines. This might seem pointless, given that only the lower 19 lines are needed to address a 1MB space; however, exposing the entire address creates the possibility of plugging a bus analyser into a slot in order to help with debugging.
The nPD (presence detect) lines on each of the four expansion slots are connected to general-purpose inputs on an MC68681 DUART. At boot, the operating system code uses the status of these pins to determine whether any peripheral cards are attached. If a card is found, the OS runs an "identify" cycle to work out what's plugged in. To do this, the host asserts the nID line and runs an eight-bit read cycle on each occupied expansion slot. The peripheral must respond by placing an ID number on the upper eight bits of the data bus and terminating the cycle with nACK. This enables the OS to initialise a driver for the attached peripheral.
Here's a screenshot of the output generated by the system during the boot process, showing the OS identifying some peripheral cards (lines highlighted in red). Having found two Ethernet cards, the OS subsequently initialises its network stack (lines highlighted in green). The output in the screenshot probably looks somewhat Linux-ey, but it's not Linux - all of this code is home-grown.
(For those who care, I got tired of referring to the OS as the "As Yet Unnamed Mc68k Operating System", and started calling it "ayumos" instead)
Overall this expansion interface suits my requirements fairly well. It's not particularly generic - I can't imagine it ever being used in any other system - but it works. There are several shortcomings, including:
- Bus mastering by attached peripherals isn't supported
- Only one supply voltage is exposed - if I were doing this again, I'd probably route +12V to the expansion cards
- Each slot gets only one IRQ line
- The DIN41612 connectors (especially the "Q" variants) are the most expensive components on the board. I should probably have used edge connectors instead
[*] - well, that was the intention when I started writing it...