Arduino Z80 CPU Tester
Here is a way to test Z80 CPUs that I created. I got the idea after seeing something about an Arduino being used as some sort of logic analyzer. For this I have used the Arduino Mega 2560 since this has a lot of digital I/O pins available.
It is a simple Arduino sketch, that uses the built-in USB CDC serial interface to communicate. It will respond to certain commands and on every cycle dump the status of the pins, which will look something like this:
|------\_/------| 0 | A11 A10 | 0 0 | A12 A9 | 0 0 | A13 A8 | 0 0 | A14 A7 | 0 0 | A15 A6 | 0 1 | CLK A5 | 0 0 | D4 A4 | 0 1 | D3 A3 | 0 0 | D5 A2 | 1 0 | D6 A1 | 0 - | +5V A0 | 1 1 | D2 GND | - 0 | D7 ~RFSH | - 1 | D0 ~M1 | - 1 | D1 ~RESET | 1 - | ~INT ~BUSRQ | - - | ~NMI ~WAIT | - - | ~HALT ~BUSAK | - - | ~MREQ ~WR | 1 - | ~IORQ ~RD | 1 |---------------| Address: 0x5 Data: 0xF
The commands available in this version is 'c' to toogle the CLK clock pin, 'r' to toggle the RESET pin and 0 through 7 to toggle the data bit pins. It is possible to easily expand on this, but these are the minimum pins required to make the sketch program useful. A simple test that can be done with the Z80 is to put 0xC3 on the data bit pins, and then just toggle the clock over and over. This will cause it to read the opcodes 0xC3 0xC3 0xC3, meaning an absolute jump to address 0xC3C3 which will get reflected back on the address pins.
There is no circuit diagram, instead use the #define in the Arduino sketch to determine the connections. In addition to the signals defined there, +5V and GND is also needed of course, gotten from the Arduino as well.
Here is the sketch:
#define PIN_A0 11 #define PIN_A1 12 #define PIN_A2 10 #define PIN_A3 61 #define PIN_A4 60 #define PIN_A5 59 #define PIN_A6 58 #define PIN_A7 57 #define PIN_A8 56 #define PIN_A9 55 #define PIN_A10 54 #define PIN_A11 62 #define PIN_A12 63 #define PIN_A13 64 #define PIN_A14 65 #define PIN_A15 66 #define PIN_D0 17 #define PIN_D1 16 #define PIN_D2 19 #define PIN_D3 69 #define PIN_D4 68 #define PIN_D5 21 #define PIN_D6 20 #define PIN_D7 18 #define PIN_CLK 67 #define PIN_RESET 8 #define PIN_WR 4 #define PIN_RD 3 void setup() { Serial.begin(115200); pinMode(LED_BUILTIN, OUTPUT); pinMode(PIN_A0, INPUT); pinMode(PIN_A1, INPUT); pinMode(PIN_A2, INPUT); pinMode(PIN_A3, INPUT); pinMode(PIN_A4, INPUT); pinMode(PIN_A5, INPUT); pinMode(PIN_A6, INPUT); pinMode(PIN_A7, INPUT); pinMode(PIN_A8, INPUT); pinMode(PIN_A9, INPUT); pinMode(PIN_A10, INPUT); pinMode(PIN_A11, INPUT); pinMode(PIN_A12, INPUT); pinMode(PIN_A13, INPUT); pinMode(PIN_A14, INPUT); pinMode(PIN_A15, INPUT); pinMode(PIN_D0, OUTPUT); pinMode(PIN_D1, OUTPUT); pinMode(PIN_D2, OUTPUT); pinMode(PIN_D3, OUTPUT); pinMode(PIN_D4, OUTPUT); pinMode(PIN_D5, OUTPUT); pinMode(PIN_D6, OUTPUT); pinMode(PIN_D7, OUTPUT); pinMode(PIN_CLK, OUTPUT); pinMode(PIN_RESET, OUTPUT); pinMode(PIN_WR, INPUT); pinMode(PIN_RD, INPUT); } void dump() { uint16_t bus; Serial.println(" |------\\_/------| "); Serial.print(digitalRead(PIN_A11), DEC); Serial.print(" | A11 A10 | "); Serial.println(digitalRead(PIN_A10), DEC); Serial.print(digitalRead(PIN_A12), DEC); Serial.print(" | A12 A9 | "); Serial.println(digitalRead(PIN_A9), DEC); Serial.print(digitalRead(PIN_A13), DEC); Serial.print(" | A13 A8 | "); Serial.println(digitalRead(PIN_A8), DEC); Serial.print(digitalRead(PIN_A14), DEC); Serial.print(" | A14 A7 | "); Serial.println(digitalRead(PIN_A7), DEC); Serial.print(digitalRead(PIN_A15), DEC); Serial.print(" | A15 A6 | "); Serial.println(digitalRead(PIN_A6), DEC); Serial.print(digitalRead(PIN_CLK), DEC); Serial.print(" | CLK A5 | "); Serial.println(digitalRead(PIN_A5), DEC); Serial.print(digitalRead(PIN_D4), DEC); Serial.print(" | D4 A4 | "); Serial.println(digitalRead(PIN_A4), DEC); Serial.print(digitalRead(PIN_D3), DEC); Serial.print(" | D3 A3 | "); Serial.println(digitalRead(PIN_A3), DEC); Serial.print(digitalRead(PIN_D5), DEC); Serial.print(" | D5 A2 | "); Serial.println(digitalRead(PIN_A2), DEC); Serial.print(digitalRead(PIN_D6), DEC); Serial.print(" | D6 A1 | "); Serial.println(digitalRead(PIN_A1), DEC); Serial.print("- | +5V A0 | "); Serial.println(digitalRead(PIN_A0), DEC); Serial.print(digitalRead(PIN_D2), DEC); Serial.println(" | D2 GND | -"); Serial.print(digitalRead(PIN_D7), DEC); Serial.println(" | D7 ~RFSH | -"); Serial.print(digitalRead(PIN_D0), DEC); Serial.println(" | D0 ~M1 | -"); Serial.print(digitalRead(PIN_D1), DEC); Serial.print(" | D1 ~RESET | "); Serial.println(digitalRead(PIN_RESET), DEC); Serial.println("- | ~INT ~BUSRQ | -"); Serial.println("- | ~NMI ~WAIT | -"); Serial.println("- | ~HALT ~BUSAK | -"); Serial.print("- | ~MREQ ~WR | "); Serial.println(digitalRead(PIN_WR), DEC); Serial.print("- | ~IORQ ~RD | "); Serial.println(digitalRead(PIN_RD), DEC); Serial.println(" |---------------| "); bus = digitalRead(PIN_A15); bus <<= 1; bus += digitalRead(PIN_A14); bus <<= 1; bus += digitalRead(PIN_A13); bus <<= 1; bus += digitalRead(PIN_A12); bus <<= 1; bus += digitalRead(PIN_A11); bus <<= 1; bus += digitalRead(PIN_A10); bus <<= 1; bus += digitalRead(PIN_A9); bus <<= 1; bus += digitalRead(PIN_A8); bus <<= 1; bus += digitalRead(PIN_A7); bus <<= 1; bus += digitalRead(PIN_A6); bus <<= 1; bus += digitalRead(PIN_A5); bus <<= 1; bus += digitalRead(PIN_A4); bus <<= 1; bus += digitalRead(PIN_A3); bus <<= 1; bus += digitalRead(PIN_A2); bus <<= 1; bus += digitalRead(PIN_A1); bus <<= 1; bus += digitalRead(PIN_A0); Serial.print("Address: 0x"); Serial.print(bus, HEX); Serial.print(" "); bus = digitalRead(PIN_D7); bus <<= 1; bus += digitalRead(PIN_D6); bus <<= 1; bus += digitalRead(PIN_D5); bus <<= 1; bus += digitalRead(PIN_D4); bus <<= 1; bus += digitalRead(PIN_D3); bus <<= 1; bus += digitalRead(PIN_D2); bus <<= 1; bus += digitalRead(PIN_D1); bus <<= 1; bus += digitalRead(PIN_D0); Serial.print("Data: 0x"); Serial.println(bus, HEX); } void loop() { if (Serial.available() > 0) { switch (Serial.read()) { case 'r': digitalWrite(PIN_RESET, digitalRead(PIN_RESET) ? 0 : 1); break; case 'c': digitalWrite(PIN_CLK, digitalRead(PIN_CLK) ? 0 : 1); break; case '0': digitalWrite(PIN_D0, digitalRead(PIN_D0) ? 0 : 1); break; case '1': digitalWrite(PIN_D1, digitalRead(PIN_D1) ? 0 : 1); break; case '2': digitalWrite(PIN_D2, digitalRead(PIN_D2) ? 0 : 1); break; case '3': digitalWrite(PIN_D3, digitalRead(PIN_D3) ? 0 : 1); break; case '4': digitalWrite(PIN_D4, digitalRead(PIN_D4) ? 0 : 1); break; case '5': digitalWrite(PIN_D5, digitalRead(PIN_D5) ? 0 : 1); break; case '6': digitalWrite(PIN_D6, digitalRead(PIN_D6) ? 0 : 1); break; case '7': digitalWrite(PIN_D7, digitalRead(PIN_D7) ? 0 : 1); break; default: break; } dump(); } digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) ? 0 : 1); delay(100); }
The LED blinking is used as a indicator to see that the sketch program is actually running.
Here is a photo of the setup: