Enjoy this project?

This project is in this list

Description

The design and construction of a hombrew computer based on the Motorola 68000 CPU

Details

​This project is a homebrew computer based on the Motorola 68000 CPU. Design includes four megabytes of RAM, 128kB of ROM, A Yamaha V9938 VDP (the video chip in the MSX2), two serial ports at 9600 baud, and eventually networking and a hard disk.

The purpose of this computer is two-fold: To show it's really not much harder to build a 16-bit homebrew computer than it is to build an 8-bit homebrew computer, and to build a server for ​Hackaday's retro site.

Project logs

This is something I've written about in a front page Hackaday post, but I think it's time to go over a little more of the theory of what I'm doing here. First, a video:

This is called freerunning the processor. Basically, it executes one instruction, the program counter is incremented, the address is increased by one, and the CPU just sits there, doing nothing, cycling through its address space. Attach a few LEDs to the address pins, and you have an incredibly complex binary counter, also known as blinkenlights.

That's the simple explanation. It's a fair bit more complex in practice. I need to tie a few pins to +5 volts, and ground DTACK. Oh, what about the instruction to freerun the processor? NOP, right? NOPe.

When the 68k first resets, it reads the program counter vector. The program counter vector must be an even address, and the opcode for NOP is $8E71. See that one at the end? That means NOPping the CPU from boot would create an illegal address exception. Then bad things happen.

So, I need an instruction that does nothing, and is even. Inclusive OR Immediate (ORI) does this. Specifically OR.b #0,d0. Bonus, this instruction in hex is $0000, or all zeros. All I need to do to freerun the processor is ground all the data lines.

My first go at freerunning the CPU only used one LED. This LED was tied to the A20 line through an inverter. I hate to waste the five extra inverters on that chip for a single LED, so I added another three.

Now I have status lights for the top four addresses in the computer. Since I'm putting the ROM at $FF0000, the serial port at $FE0000, the video peripherals at $FD0000, the microcontroller at $FB0000, I have a graphic representation of what the CPU is doing with all its peripherals. That's pretty cool. Useful blinkenlights.

Although it might make sense to start this project by building a CPU module first, I decided it would make more sense to start with the memory for this system. This serves two purposes: as an explanation of how the 68000's memory-mapped I/O works, and to have a relatively simple circuit built before embarking on the more complex that include the CPU module.

As with the 6502, 6800, and 6809, memory access is controlled by the R/W line. Basically, when the R/W line is high, the 68000 reads from the data bus. When the R/W line is low, the 68000 writes to the data bus.

Before designing our memory modules with these signals in mind, it's very important to figure out how this computer is going to boot. All computers require some amount of RAM somewhere in the address space, and at least a few instructions telling CPU what to do on a restart somewhere else. The 6502, for instance, requires an instruction in ROM at $FFFC, and a few bytes of RAM at $0000.

The 68000 is different. It's reset vector, or the place it looks for instructions on a reset, is at $000000. The 68000 also requires a small amount of RAM at address $000000. Let that sink in. The naive analysis of these two facts means we must store the first instruction in RAM. RAM that will be uninitialized when we boot the computer.

Fortunately, Motorola application notes give us an easy way to get around this. The solution is to deselect the RAM and select the ROM during the first four bus cycles. This can be done with a 74164 binary counter, using the /AS line as the clock input, and making a /ROMSELECTcontrol signal with one of the outputs. This /ROMSELECT or /BOOT signal (I'm using the two interchangeably) will allow CPU to read instructions from the ROM on reset.

Above is a fairly broad overview of the ROM board's circuitry. I'm using two 32kB EEPROMs for the ROM, split between high bytes and low bytes. This gives me 64kB of ROM for this computer, more than enough to set up a few things on boot and eventually pull data off a hard drive.

According to the memory map I have in my notebook, the 64kB of ROM will be decoded at $500000 through $50FFFF. This means the ROM is selected whenever address lines 22 and 20 are high, and lines 23 and 21 are low. A three-input NAND gate (74ls10) and a few inverters are all that are needed to enable the RAM.

The ROM memory control is used to toggle the output enable pins on the EEPROMs. The Motorola 68000 user manual has a table going over when valid data should be on the data bus according to the /UDS, /LDS, and R/W lines. Long story short, the above circuit will work just fine for enabling either EEPROM.

Compared to the 8080, the Z80, the 6809, 6502, and all the other 8-bit microprocessors used in boxxen of yore, the CPU I’m using for this project - the Motorola 68000 is both extremely powerful and extraordinarily complex. The power comes from a huge address space and some neat features like a divide instruction. The complexity comes from it’s asynchronous nature.

A single-board computer using the 8-bit 6502 processor is very simple compared to a 68k computer. Conjuring up a simple 8-bit computer is as simple as getting a RAM and ROM chip, connecting all the data and address lines together, and throwing together a little logic glue to get the whole thing working. The 68k is another story entirely. Thanks to its asynchronous nature, you have to deal with something called the DTACK, or Data Transfer Acknowledge. This is an input pin on the processor that indicates the the data transfer from RAM or ROM is completed. If this isn’t low at the right time, the entire system just stops.

The bus arbitration pins - /BR, /BG. and /BGACK control which device in the system controls the data and address busses. It’s great for DMA operations, crazy video schemes, and shoving data from a cassette port directly to memory without going through the processor. DMA would require a good bit of circuitry, though, and I won’t be using it anyway.

Oh. There’s also processor status pins on the 68k. These are output pins that tell the system if the current cycle is being used for user data, user program, supervisor data, supervisor program, or an interrupt. Very cool, and a good example of how the 68000 was inspired by the minicomputers of the 70s, but utterly useless for a small box that will sit on my desk, tweet, and play Breakout.

Complex, yes, but I don’t actually need to use all those pins. Those processor status pins can be easily ignored. I won’t be doing any cool DMA stuff with this computer, so I can just tie the /BR, /BG, and /BGACK pins to +5 Volts. Pins /IPL0, /IPL1, and /IPL2 only indicate the priority level of an interrupt, and I can’t imagine designing hardware in response to an interrupt in this system.

This is a line going into the 68000 to tell the CPU a device has received data on the data bus. If I were not using 6800-compatable parts or the 6800 peripheral control pins, I could simply tie /DTACK to ground and hope my memory is fast enough. That’s the easy way out, and I’d really like to do this project right. Generation of the /DTACK signal is easy enough.

And that’s it. There are a ton of pins on the 68000, but if you want to build a simple computer you can ignore everything except the data and address pins and four bus control pins. The amazingly complex 68k then turns into a very very simple synchronous CPU just like the 6802 and Z80. Really, other than the fact a 16-bit homebrew computer requires twice as many RAM chips (although you could always use a 16-bit...

Discussions

Become a member

The last project log is 11 months old now (the time flies, I feel like I signed up the projects page yesterday...). Do you plan any updates on this project? I believe I'm not the only one who likes it.

Agreed-I quite enjoy reading about homebrew computers (such as this one and Quinn Dunki's Veronica) and would love to see an update soon. Wasn't this going to be used as the Hackaday Retro Edition server someday?

It still will be, and there will be an update "soon". I know I haven't been working on this as much as I should, but <i>holy crap</i> getting switches lined up with a milled front panel is a pain in the ass.

consider using a atmega or pic as your reset handler/boot vector installer. With address lines pulled LOW, while the processor is reset and in HI-Z state, let the atmega328 access the bus to put an instruction there, or a bunch of them. then the atmega gets off the bus, and releases the reset.

How about using IS66WVE4M16BLL for memory? Dense and cheap, but BGA. It looks like it was made for the 68000 bus.

This is very awesome! I'm actually in the planning and design phase of my own 68k microcomputer project. Though I have to point out, a TON of images in your posts are broken. Can you please fix them up?

The 6850 is so braindead... ugh... I'm happy to donate one or two 68681 and/or 68901 chips to your project. I've got at least a dozen of each scurried away... I'm sure I've got one or two 68230 as well.

As much as these 68xxx chips are convenient to use with the async bus of the 68K, I've come to the conclusion that the only real reason that I, personally, would ever use most of these devices is for software compatibility with some older system. The state logic required to interface a synchronous bus peripheral device (i.e. without DTACK) to the async 68K bus is straightforward and easy enough to implement in a GAL or CPLD.

I think the exception (pun intended) I would make to this statement is that the 68901 in particular makes a fine vectored interrupt controller. I have no desire to re-invent THAT wheel...

You're right that the 6850 is dumb. I'd really rather not bother with DTACK and 6800 stuff. I'm kinda in a bind with this project, though: I want to make it as simple as possible, but also give people a chance to replicate it. So far, all the chips can be ordered off jameco (with the exception of the 68000 and V9938/V9958). The other 68XXX chips... they're hard to find.

If you want to donate something, email me at (my last name) @hackaday.com. Give me your address and I'll send out a T-shirt and some stickers for your trouble. I'll also promise to use the '681... after I've brought the system up with the 6850. Beauty of the backplane, I guess.

The idea is that the ROM and not the RAM is mapped at addr 0 at reset. When the ROM is addressed at its runtime address the RAM is mapped instead at addr 0.
The ROM is in this picture mapped at $500000-$5FFFFF, it is better to move that to a high address.

Try to find a 68681 DUART instead of the 6850. And a 68901 that includes UART, timer and an 8-bit port. You need a timer don't you? ;)
Move peripheral and ROM to as high address as possible to get continous RAM from address 0 and up.
And I have some comments how to simplify the ROM/RAM address decoding:
Use a simple flip-flop instead of the counter at reset and see comment in text about RAM.
I had better draw a figure than explain it in text.