My Homebrew 68000 System

While studying at the University of Stellenbosch in 1987 I built a 68000 computer system. I had very little resources, for example I could only get single-sided PCBs made*, and it was difficult to arrange access to equipment like a logic analyser or digital oscilloscope, even an eprom emulator was out of the question. All of these factors influenced the design.

The system ended up as three separate Eurocards (100x160mm)** with DIN41612 A/C connectors. The bus pinouts were chosen to minimise routing problems. All PCBs are single sided, with parallel vertical wire jumpers on the component side. PCB layout was done using smARTWORK.

* Actually not true. Double sided PCBs were available, but through hole plating not. So there wasn't that much sense in having the top layer, it was about the same amount of work to design most of the top layer to consist of straight traces and to then use jumper wires instead of actual traces.

** I had access to a really nice HP A3 plotter. I bought a Rapidograph type pen for that plotter and made gorgeous plots. But at 2:1, A3 paper gives a maximum PCB size of just a little more than a Eurocard, hence the choice.

Page 1 of my black book (Every project should have a black book)

Gore's Law of design engineering:

  1. The primary function of the design engineer is to make things difficult for the fabricator and impossible for the serviceman.
  2. That component of any circuit which has the shortest service life will be placed in the least accessible location.
  3. Any circuit design must contain at least one part which is obsolete, two parts which are unobtainable and three parts which are still under development.
Corollaries:
  1. The project engineer will change the design to suit state-of-the-art.
  2. The changes will not be mentioned in the service manual.

Meyer's Law

It is a simple task to make things complex, but a complex task to make them simple.


OK, with the mental state of the Chief Engineer out of the way, let's get to the design.

The bus

The key design parameter here was expediency. From the processor, through the buffers, to the DIN 41612 connector. Yes, I buffered everything. Overkill, maybe, but in that era you only shorted a pin to ground once to blow the output driver, chips these days are much more forgiving. And cheaper. I used bidirectional (74LS245) drivers throughout. The pinout of the 74LS244 unidirectional driver is a pain, routing was a lot easier with '245s hard-wired to go in one direction only (Actually, single-sided routing with '244s would have been impossible).

C A
+5V1+5V
D02D1
D23D3
D44D5
D65D7
D86D9
D107D11
D128D13
D149D15
A2310A22
A2111A20
A1912A18
A1713A16
A1514A14
A1315A12
A1116A10
A917A8
A718A6
A519A4
A320A2
A121R/W
/LDS22/UDS
/AS23/VMA
/IACK24/IOSEL
/DTACK25/BR
/BG26/BGACK
E27/VPA
CK28/RESET
/6800INT29/IRQ1
/IRQ2/330/IRQ4
/IRQ531/IRQ6
0V320V

CPU board

68000, Interrupt logic, clock, buffers on all data and address lines.

Hand-drawn schematic, of course. I don't think there ever was a final version, but this is close. Changes would mostly have involved mapping gates into packages so that everything fitted on the PCB and could be routed.

This is the CPU PCB plot, with component overlay. Everything had to be checked by hand, smARTWORK didn't do netlists.

CPU Board, April 1987

Memory

Another Eurocard, with eight 256 kilobit devices -- two 42256 32k x 8 CMOS RAM chips and two, four or six 27C256 32k x 8 EPROMs, for 64K of RAM and 192K of ROM. Yes, only a few of the pictures* on this page will fit into that much (little?) RAM. Moore's law at work.

* And I mean one at a time.

Anyway. The 68000 was different from the Motorola 8-bitters that preceded it. In the case of the 6800, 6809, 6502 and so on, the reset vector lives at the top of memory, at FFFE/FFFF. These two bytes are read into the Program Counter on reset, and program execution then begins at that address.

The 68000, however, stores the initial Stack Pointer and Program Counter at 0x00000000 (16 bit address) to 0x00000007 (eight bytes, two 32-bit addresses). This is followed by pointers to all the exception handlers, including the Interrupt Pointers. It is nice*, but not essential, to use writeable memory so that the exception address can be changed (another option would be to point each exception at a bit of code in Read-Only Memory (ROM) which then fetches a vector from somewhere else. Cumbersome).

* Also, the 68000 also has a short form for accessing memory in the first 32k of address space, so it's a bit faster if you use this short form access for commonly used variables.

So, we need a bit of circuitry to make sure there's ROM at 0x00000000 for the first four cycles, and then to change things around so that the whole area maps to RAM (another approach would be to completely decode the address space and to map ROM to 0x00000000 to 0x00000007 and RAM from there on up, but the cycle counting approach is simpler). This is done with a 74LS164 shift register. The input is tied high (= "1") and the register is cleared at reset. With each address strobe, the 1 advances, eventually gets to the address decoder and changes the mapping (This comes straight from Motorola Application Note AN-897 except that the fourth output is used and not the eight, since the 68008 takes twice as long to fetch memory eight bits at a time).


A note on the side: From the Hackaday 68000 Backplane Computer discussion I learnt that there's another (arguably better) approach (schematic) to the problem -- map a flip-flop to RESET and to the ROM chip select. The first time ROM is selected, the mapping flips and 0x00000000 is mapped to RAM.

Schematic, part 1. From the top left hand side: A23, A21, A22, A18, A19, A20 (the order is of course to make routing easier) and /AS are used to generate /CARDSEL (0x0000000 to 0x0003FFFF, 256 kilobytes. Although the 68k architecture allows for a full 32 bit address bus, the 68000 only uses 24 address bits, something which caused great chaos when the Apple Macintosh got a processor capable of addressing more than 16 megabytes). Effectively, address lines 24-31 are ignored.

/AS and /RESET tickle the LS164 counter, as previously mentioned.

A17 is buffered, since it goes to two inputs on the LS139 address decoder. It works out well, because in the end there are exactly 16 address lines that needs to be buffered (Here's the schematic of the buffers for what it's worth -- the only slightly odd thing is that 68000 A1 goes to ROM/RAM A0, because of course 68000 A0 drives /LDS and /UDS which select one of the two devices). A16 is OR-ed with the MAP signal, giving:

A17A16/MAPMAPLS37 pin 11Device selected
000111 - ROM 1
010111 - ROM 1
100113 - ROM 3
110113 - ROM 3
001000 - RAM
011011 - ROM 1
101002 - ROM 2
111013 - ROM 3

For the first four cycles after reset, A16 and A17 will be zero, so only the first entry and the last four entries are relevant. The other three Can't Happen.

What else? /UDS and /LDS are OR-ed with /CARDSEL to select between the LO and HI banks (because the 27C256 EPROM and 42256 RAM devices are eight bit, you need two per bank). And R/W is buffered with an OR gate because (1) there are no more free buffers after the 16 address lines mentioned above are buffered and (2) there's a spare OR gate. Elegant, if I say so myself.

And then there's the wait state generator. The CMOS RAM is fast enough to keep up with the 68000, but the EPROM isn't. The wait state generator is four flip-flops being held in reset by /AS, inverted. When /AS goes low, the flip-flops start clocking the state of /CARDSEL through, i.e. nothing happens unless the decoding circuitry decides that 0x00000000 to 0x003FFFFF is being accessed). The jumpers on the right hand side determine when /DTACK is asserted to let the processor know it's OK to read data. Since /DTACK is driven from many sources, a 7407 open collector buffer is used here. And since we don't need wait states for RAM, selecting either RAM chip drives /DTACK via one of the other open collector gates.

If I were to do the same thing today, I would strongly consider using a PAL (the technology was available at the time, I just didn't want to complicate matters). Using a PAL would allow the RAM to be mapped at 0x000xxxxx and the EPROMs to all be mapped at 0x00Fxxxxx leaving the whole address space free for RAM expansion. But in those days 640k was still enough for everybody (not really, but it was and still is enough for this tinkerer).

Memory Board, June 1987

No I didn't cover the EPROM windows to erase-protect them. But believe it or not, the data is still good, 20+ years later.

I/O

Of course one needs I/O as well. I figured that a serial port would have to do for starters, graphics could come later.

My first I/O board has a 6850 UART, a WD1770 floppy controller, and a 58174 real-time clock.

Decode circuitry

I don't know why I put two inverters there between the OR gate and the LS139 enable. I'm also not so sure that /VPA should be asserted so soon or for the whole FFxxxx block -- the former might be a problem, the latter will do no harm. Each I/O device takes up two kilobytes of memory -- far more than is needed, but it saved a whole lot of TTL.

At the time I figured that RS422 was the way to go, so that's what I used (remember that the Macintosh was new, and it used RS-422. Also, I didn't want to have to supply +12V and -12V just for the serial port).

74LS93 divide by 13

Cascaded 74LS163s

The Baud Rate Generator uses a 74LS93 and one AND gate to form a divide by 13 counter, which feeds two cascaded 74LS163 counters. The 615 kHz output can be used (in x16 mode) to generate 38.4 kbps, the first seven outputs of the dividers then give everything down to 300 baud.

First I/O Board, June 1987

Second I/O Board

In January 1989 I did some holiday work work (a requirement, then, when studying engineering) at Truvelo. There they had a Motorola MVME101 system they used for software development, and I had ripped a copy of the ROM (MVME101BUG) and the manual for it. (I think the statute of limitations applies, and seeing how I lost the binaries when the boat capsized hard drive crashed ages ago I suspect it's OK).

Because of this, my I/O requirements became 6840 PTM, 6821 PIA and 2 x MC68661 EPCI (UART) devices (I used SCN2661s but it's the same thing). So I designed a second I/O board.

Decode circuitry #1

Decode circuitry #2

There's nothing interesting about it really, the devices are mapped to 0x00FF0000 to 0x00FF007F (The MVME101 maps these to 0x00FE00xx but I had this thing about minimising the memory footprint of I/O devices. Also, it saves an inverter, all the high address lines go straight to a 74LS30. In hindsight this doesn't matter that much).

Line drivers

By now they'd invented the MAX232 (introduced 1987) and that's what I used to get RS-232. But I kept the RS-422 option. I used three MAX232s, one per port, the third being optional to give DTR and DSR for both serial ports.

Second I/O Board, June 1989
CTS+TxD+
CTS-TxD-
GNDGND
RxD-RTS-
RxD+RTS+

/DTR
/RTS
TxD
GND
RxD
/RTS
/DSR

/DTR
/RTS
TxD
GND
RxD
/RTS
/DSR

Software

In the beginning the software development cycle was fun. (OK, so I'm a masochist :-). I used to write assembler code, hand-compile it, type it into a PC, burn two EPROMs, and then take the EPROMs home and stick them in the system. Single-stepping the 68000 is easy since the whole chip is CMOS. The 68K will wait for the data acknowledge signal DTACK forever. I wire-wrapped a fourth card with LEDs on all data and address lines, and a flip-flop wired to a switch to take DTACK low for one cycle at a time. Removed the jumper on the memory card that selects the number of wait states when EPROM is selected, and I could single-step through EPROM while RAM accesses happened in the background.

I got a small monitor working this way, but I wouldn't recommend it :-). I wrote my own disassembler in C, and after I had got hold of a copy of Dr. Dobbs Toolbook of 68000 Programming I typed in the Tiny Basic interpreter which works well. I wanted to put Forth on there, but I got busy with other things, so it never happened.

Some day I might resurrect this system and make something like Peter Stark's SK*DOS run on it.

Options for a monitor / debugger.

Overclocking

Using a 32 MHz clock module and a dual flip flop to get to 8 MHz meant I had two overclocking options, namely 16 MHz and 32 MHz. 16 MHz actually worked. 32 MHz... didn't.

[Image] Hit Count
hits since 1999-05-27.

Back to Wouter's 68000 Page (This page last modified 2017-05-19)