5D3 reveals
that this NMOS circuit was created in late April of 1985.
I reserved six breadboards for this project. Compared to the Z80 project, which had just four, this is a rather large increase. The 68000 is a 64 pin DIP which takes up the majority of a breadboard. The layout I chose for this project, from top to bottom, is (i) SRAMs and bus timeout counter, (ii) EEPROMs and initial GAL decode logic, (iii) reset circuitry and (iii/iv) the 68000 spanning over two breadboards, (v) more decode logic, and lastly, (vi) the I/O.
Part list
- HD68000 (NMOS, 8 MHz) 'M68k'
- MC68B21 (NMOS, 2 MHz) 'PIA' (Peripheral Interface Adapter)
- MC6840 (NMOS, 1 MHz) 'PTM' (Programmable Timer Module)
- MC6850 (NMOS, 1 MHz) 'ACIA' (Asynchronous Communications Interface Adapter)
- PCF8584 (CMOS) I^2C Bus Controller
- PCF8583 (CMOS) I^2C Real-Time Clock
- W27C020 (256 KiB) EEPROM
- AS6C4008 (512 KiB) SRAM
- MAX1232 Supervisor Circuit
- BC546 Transistor
- GAL16V8A Programmable Logic Device
- SN74HC238N 3-to-8 Line Decoder
- SN74LS148N 8-to-3 Priority Encoder
- SN74LS161AN Binary Counter
- SN74LS03N NANDs (Open Collector)
- SN74S04N Hex Inverters
- SN7422N 4-Input NANDs (Open Collector)
- SN74LS32N ORs
I'm using Generic Array Logic (GAL) to provide some of my address decoding logic. Without this, I would've needed around 15 discrete ICs and lots more propagation delay to manage this. Currently, it's down to 6 discrete ICs, and mostly being open-collector or encoders/decoders. With the additional space, I was able to add a bus timeout counter as well as an I2^C and Real Time Clock (RTC) interface to the system.
Net list
| M68k | W27C020 | AS6C4008 | MC6821 | MC6840 | MC6850 | Watchdog | PCF8584 |
|---|---|---|---|---|---|---|---|
| A1 | A0 | A0 | A0 | A0 | A0 | - | A0 |
| A2 | A1 | A1 | A1 | A1 | - | - | - |
| A3 | A2 | A2 | A2 | A2 | - | - | - |
| A4 | A3 | A3 | - | A3 | - | - | - |
| A5 | A4 | A4 | - | - | - | - | - |
| A6 | A5 | A5 | - | - | - | - | - |
| A7 | A6 | A6 | - | - | - | - | - |
| A8 | A7 | A7 | - | - | - | - | - |
| A9 | A8 | A8 | - | - | - | - | - |
| A10 | A9 | A9 | - | - | - | - | - |
| A11 | A10 | A10 | - | - | - | - | - |
| A12 | A11 | A11 | - | - | - | - | - |
| A13 | A12 | A12 | - | - | - | - | - |
| A14 | A13 | A13 | - | - | - | - | - |
| A15 | A14 | A14 | - | - | - | - | - |
| A16 | A15 | A15 | 0 | 1 | 0 | 1 | 0 |
| A17 | A16 | A16 | 0 | 0 | 1 | 1 | 0 |
| A18 | A17 | A17 | 1 | 1 | 1 | 1 | 0 |
| A19 | 0 | A18 | 1 | 1 | 1 | 1 | 1 |
| A20 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| A21 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| A22 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| A23 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Unlike the 6502, Z80, and 6809, this decode logic will exhaustively
address all relevant devices on the asynchronous part of the bus. This
is to accurately generate the DTACK signal and hang when
an address failed to be present on the bus. An 8-cycle counter provides
a timeout (bus error) signal when a device is not mapped or not
responding. This allows safe expansion of the system bus.
A watchdog timer is created with the MAX1232. An I/O operation on the watchdog address functions as a strobe to the supervisory circuit. This resets the CPU when the software doesn't regularly provide a notification to the watchdog. The MAX1232 provides a power-on reset and also functions as a voltage monitor because it will halt/reset the 68000 if it drops below 5% of 5V. There are three indicator LEDs:
- Power applied (blue, left)
- 68000 is running (red, middle)
- Voltage and strobe OK (red, right)
The difference between the two red LEDs is that the 68000 itself can also halt the system. If that happens, only the middle LED turns off, and both turn off when the voltage supply and strobe are bad. Normally, all indicators should be active. There are also two buttons available:
- Manual reset
- Abort interrupt
The I/O space contains four possible synchronous peripherals. In the
synchronous 6800-family VPA range, the -
(dashes) indicate loosely decoded peripherals. Supervisor mode (FC2)
must be asserted in order to access I/O space, otherwise a bus error
is asserted; this way, only an operating system kernel can communicate
with peripherals. Additionally, the top 256 KiB of EEPROM and SRAM are
also supervisor protected.
Memory map
000000 - 03FFFF :EEPROM (256k)040000 - 07FFFF :EEPROM (256k) (supervisor protected)080000 - 0FFFFF :I/O (supervisor protected)100000 - 1BFFFF :SRAM (768k)1C0000 - 1FFFFF :SRAM (256k) (supervisor protected)200000 - 2FFFFF :System expansion slot 0300000 - FFFFFF :System expansion
The following I/O devices are mapped in the I/O space:
080000 :PCF8584 I^2C090000 :Unmapped0A0000 :Unmapped0B0000 :Unmapped0C0000 :MC6821 PIA (VPA range)0D0000 :MC6840 PTM (VPA range)0E0000 :MC6850 ACIA (VPA range)0F0000 :MAX1232 Watchdog (VPA range)
The following I/O priorities are used:
- MC6821 PORT A (lowest priority)
- PCF8584 I^2C MASTER
- MC6821 PORT B
- MC6850 ACIA
- MC6840 PTM
- PCF8583 I^2C ALARM
- Abort (highest priority, non-maskable)
By far, this 68000 system has been the most complex broadboard project that I've done as of now. Thankfully the GAL has simplified the use of discrete logic and enables the multiple bus error logic conditions.
Given that the 68000 has a 24 bit address bus, and an asynchronous
DTACK is used to terminate a bus cycle, an idea came to
mind. It is possible to allow the 68000 to hook into another system's
16 bit system bus like some kind of DMA (and unlike the 6502, even bus
request architectures like the Z80). A couple of line drivers for the
address will be necessary, together with a transceiver for data and a
tiny bit of logic to handle requesting the bus and propagating
DTACK at the right time (and also masking the bus timeout
counter, if necessary). This way, the 68000 can address a completely
different secondary system and write into its memory to assign tasks.
This 68000 system is quite expandable. The GAL already decodes 'expansion slot 0' due to free space on the decoder, which allows other peripherals to just hook into the system. If an unmapped address is referred to, the bus timeout counter will generate a bus error.
Whilst wiring the control logic of the 68000 system, I performed a test
to see if the chip enables function correctly, with zeros (effectively
NOPs) bound to the data bus. I expected to see a bus timeout and error
being generated when the address overflows to I/O space, as there is no
automatic DTACK generation for I/O (and VPA
is only asserted in the latter half of I/O space).
In the waveform, you can see just that: after EEPROM bus cycles, an I/O
bus cycle is asserted. A bus timeout is generated which results in the
bus cycle being terminated. However, remembering that I wired the data
bus to zeros, I did not think through that handling the exception would
write to a pre-decremented stack address (with 0 underflowing to
unmapped memory at address 0xFFFFFF). A bus
timeout was asserted again, resulting in a double bus fault and the
68000 halting.
It was unexpected, but very correct!
