For a long time I've been wanting to build a computer based around a Motorola 68000 processor. After putting it off for various reasons I finally sat down, searched around for the basic parts I would need, and stripped a whole lot of wire.
As it stands the project consists of a MC68000 running at 4MHz, 2x 6164 8KB RAM chips giving me 16KB of RAM, and 2 Flash chips giving me 256KB of ROM. The board is capable of taking 2x 512KB EEPROMs and 4x 512KB SRAMs giving it 2MB of RAM and 1MB or ROM. For output it has a 68681 DUART driving both a serial port, and a display/keyboard interface. As well a YM2149 sound generator is hooked up.
68000 Microprocessor in a DIP64 package.
8KB - 8 bit - 25ns SRAM
Intel P28F001 BXT-150
128KB - 8 bit - 150ns Flash ROM
256KB - 8 bit - 70ns Flash ROM
Well the breadboard part of my computer is no longer there. It's been all moved onto a single 3U euro-card sized protoboard. So I guess now I've got to change the title of the project. Was quite a bit of work to wire up the hundreds of point to point connections. All of it was done using 30AWG wire wrap wire, soldered point to point.
Alright so it's been quite a while since I posted an update. Most of the work done on this update was done a few months ago, but school got in the way of getting it polished up a bit and written up. So, things that have been done since my last update. First things is that I've added a custom color NTSC serial terminal based on a ATMEGA328.
So a lot has changed since my last update on here, I've redone the address decoding to use a 74138 3-8 line decoder to allow me to partition the address space. I've added some status LEDs to help show the state the computer is sitting in, so I don't need to break out the logic probe as often. And the final, and probably the most important, addition is that I've added a 68681 Duart chip, giving me a means of input and output.
The 68681 chip wasn't a too difficult of a chip to add in, you just need to map it into the address space with it's chip select, attach it's 4 register select lines to the address bus, and tie it's 8 data lines onto one of the data buses. The other thing that adding it changed was necessitating me to add some /DTACK logic, rather than just grounding it, as the 68681 puts out a dtack signal. This was accomplished by using one of the open collector inverters to ground /DTACK when the 68681 isn't selected, but when it is selected it passes the /DTACK signal from the 68681 through a resistor to the 68000.
On the software side of things, my first tests were to get the 68681 to output something useful, for a while I wasn't succeeding and ended up putting the project on hold for a while. Fast forward to a couple weeks ago, I sat down to try and get it working again, and after writing the initialization code again (with the help of some online resources) I managed to get a Hello World! out of it. My computer was finally properly working.
My next thought was to try and get a simple BASIC interpreter ported over to it, I quickly found a 68000 version of Tiny BASIC, which I modified the I/O to match my setup. As well as changing where it assumed RAM was. After quite a bit of debugging I finally got it to a partially working state as shown below.
I was able to get it to do get it to do a few things in interactive mode, namely the PRINT statement, but when I tried to store a program line, it would lock up. I tried doing some debugging over the serial port (hence the 1256634 on the last line) but what it was doing wasn't making much sense. In the end I was getting frustrated with it and moved on to writing my own program for the machine from scratch.
Enter my ROM Monitor. I decided I wanted to have a simple ROM Monitor program that would let me examine memory, deposit values into memory, as well as jump and execute to any address. I used this project as a way of getting some experience coding 68k assembly, as this computer is the first time I had done so. MarkeyJester's 68k Tutorial was a very nice reference for quickly learning the instructions I needed. Since I didn't want to spend all the time debugging over the serial port, flashing many ROMs and such I chose to use the built in simulator in Easy68k. What I did was write the I/O routines into functions that used the simulators I/O routines, so that when I was ready I'd swap in the routines I had written for the Tiny BASIC. After getting the monitor working as I wanted it in the simulator I finally flashed it to my ROM. Now it would have been great if it had worked perfectly first time, but there turned out to be a bug, when the examine function was told to examine more than 16 bytes at a time it would increment the address by 0x110 bytes instead, after a bunch of debugging I found the culprit, I was using only a byte of r4 (and so was using .b instructions), but I was doing a suba.l with it on an address, thus in the simulator where r4 was initialized to 0, it would work since the upper bytes were all 0, but on the real hardware where r4's initial state was unknown it failed. After fixing the code to initialize r4 and r3 in the dumpRAM routine, it worked perfectly on the real hardware.
Now as for what I'll be doing next, I'm not too sure. I may start with merging this and my arduino NTSC serial terminal project to give this computer a real computer feel. And having a TV output and keyboard would definitely do that. I also might give another try to porting a BASIC interpreter...
Well now I'm feeling a little silly, the issue turned out to entirely be that I was flashing my Flash chips backwards. The tool I was using to output my byte code produces two bin files, name_0.bin and name_1.bin, for some reason I assumed that 0 would be the low bytes, and 1 the highs. However if you look in the program it does show that the even (low) bytes are in 1. Now with that sorted it worked! It finally worked! Though not before I had completely rewired the computer and added a proper reset circuit (based off this document the only changes made were that I used 470k resistors as I didn't have 1Meg handy, this gives a reset of 270ms which is still enough) .
The new computer:
And here's the circuit behaving as expected, top line is the chip select from the RAM, indicating that A18 is set which happens during the write to memory, middle line is the chip select for the ROM, finally the bottom is the output on the led. This picture was taken while the LED was on, the pulse on the bottom line appears when the LED is on, and doesn't appear when it's off. It's not a very precise output but it's enough to show that the code and processor are working.Video of it working to come tomorrow, (potentially with my Arduino acting as a parallel to serial converter to print a Hello World message)
Well sometimes it seems like it's working, but it only ever does half of what I expected. My initial attempt at getting visible output has been to use the A23 pin to blink an LED. I've gone through various iterations of the code, fixed bugs such as not have the the supervisor stack pointer in the ROM before the starting address. The problem I keep getting is yes the led blinks, and it even does it's pulses at seemingly the right time compared to the address strobe, but I can't control the rate at which it pulses. In the code I'm counting down d0 while writing to an address with A23 high, then I toggle A23 in the address and repeat the cycle. The problem being that changing the starting value from the count never affects the pulse rate. Another odd behavior noticed is that all the other address lines above A18 pulse at the same rate which makes little sense, they're all just floating (adding a pull down doesn't change it though) and the code is writing to address $840000 which should not be touching them.
DC.l $0043000 ; Supervisor Stack Pointer
DC.l start ; Initial PC
movea.l #$840000, a0 ; Address of the first byte of ram
; But with A23 set so it's written to LED
move.l #10000, d0delayloop:
subi.l #1, d0
move.b d0, (a0)
cmpi.l #0, d0
move.l a0, d1
eori.l #$800000, d1
move.l d1, a0
In the picture below you can see what I mean by it seeming to work, the top row is the ~AS line, every time it goes low there's a valid address on the bus, the second is the ~chip select for the RAM, and the third the ~chip select for the ROM. It kind of makes sense there being 4 ROM accesses, then a RAM as the RAM is getting written to one in the loop. However there only being 4 ROM accesses doesn't seem quite right as I believe there should be 6 16-bit accesses in that loop, plus the 1 8-bit access to write to the RAM.
I did some further experiments trying to read data straight off the bus using an Arduino and the A23 line as an interrupt trigger on the Arduino to latch. As well as trying to rig up some DTACK circuitry to make that more stable at triggering, I never quite succeeded as the Arduino was never quite triggering when I wanted it so I couldn't tell if the numbers that I sometimes got were the ones I was expecting or random noise.
At this point I'm tempted to re-wire the circuit, make a better halt/reset circuit with debounce so that I'm certain that it's reset correctly. Another idea may to be make a single step circuit to allow for easier debugging as I only have a 3 channel logic probe at the moment.
Amazing work. You are doing great job of making these small computer components model. I have also the collections of these models on my mostpc website.