I recently pulled out the
Z80 project computer I built several years ago in the hopes of adding some hardware and features to it, but was sad to find that it didn't want to operate in the slightest. A quick connection of the logic analyzer showed that the CPU was not fetching instructions. Hrm. I needed to determine if my delicate, hand-wired little computer was at fault somewhere, or if the CPU itself was upset.
First, I breadboarded the following setup to test the Z80. Since the opcode for the NOP instruction is 0x00, setting the data bus to zeros and providing correct external state causes the chip to simply count up the address bus when clocked. I pulled the data bus to 0s with 1k resistors since the chip is in an undefined state before reset and could attempt to write to the bus - bad news if you're tied to a rail. I then set WAIT_, INT_, NMI_, and BUSREQ_, leaving just a RESET_ and a clock source to add.
I really like the simplicity of Z80: not only can I run the chip with only four pullups and no external components, but it will run with clock speeds all the way down to DC. That means you can single step your computer with a debounced push button as your clock - try that on a modern CPU! For this particular exercise, I rigged a
555 timer to generate a 10hz clock - slow enough to watch the address bus with LEDs.
At the moment of truth, I got... nothing. The chip was tri-stating the address bus and not responding to RESET_. Unfortunately this meant I needed to dig deep into the depths to locate my box of Z80 items that I hadn't seen since college. However, not only did I find the box I was looking for quite quickly, I found a downright awesome pile of parts in there! I recalled that I had 3 extra Z80s and two
82C55's, but in reality I owned 16 Z80s of different vintages and speed grades, a few different types of 82C55, and an awesome pile of Z84 family peripheral controllers. I was very pleased.
Back at my desk, I tested all 17 CPUs (the one that was in my computer, plus the 16 extra ones I had). It turns out that all of my spares are in perfect working condition, and the one in the computer was in fact dead as a door nail. Good to know!
Next, I put a working CPU back in the computer, then wrote, assembled (using
z80asm-1.2), and burned the following test program into flash:
LD A,0x80 ; 1000 0000 - tell the 82C55 to set all ports to outputs
OUT (3),A ; 0x03 is the control word address
LD A,1 ; set one bit that we will rotate in the loop
loop: OUT (0),A ; put the word out on port A of the 82C55
NOP
RLCA ; left-rotate reg A
JP loop
Sure enough, it worked great in hardware. Unfortunately, I decided to test the code in an emulator before running the hardware, and ended up spending many hours debugging and rewriting the emulator's memory loading functionality to be properly endian-safe and to autodetect binary blob types, but I'll leave that rant for another time. In any event, this was a great refresher in Z80 architecture and assembly as well as the interworkings of the emulator. Now that my Z80 computer is working, I have no excuse not to add more cool things to the project...