Anleitung zum Z80 CPU-Tester und Analyzer

Es handelt sich bei diesem Text um eine Übersetzung der Anleitung von Goran Devic, die ich entsprechend ergänzt habe.

Wird der CPU-Tester über die serielle Schnittstelle verbunden, stehen mehrere Befehle zur Verfügung („?“ Oder „h“ in der Konsole eingeben):

l #num       - lade Programm #num in den Speicher (es stehen ein paar Beispiele zur Verfügung)
s            - zeige Simulationsvariablen
s #var value - setzte Simulationsvariablen #var auf den Wert "value"
sc           - setzte die Simulationsvariablen auf Standardwerte zurück
r            - Starte die Simulation
:INTEL-HEX   - lade RAM mit dem INTEL-HEX Stream
m            - gib den Inhalt des RAM aus
mc           - lösche den RAM

Es gibt mehrere interne Simulationsvariablen, die geändert werden können, um die Tests auf dem Z80 auf verschiedene Weisen auszuführen. Der beste Weg, um einen Z80-Test zu erstellen, geht über einen Z80-Compiler, wie z.B. zmac.  Erstelle ein Programm, wie z.B. folgendes:

start:
ei
im 2
ld ix, 80h
srl (ix+20h), b
adc hl, de
ld hl, 30h
ld de, 40h
ld bc, 3h
ldir
ld bc, 1
ldir
halt
org 38h
ei
reti
org 66h
ei
reti
end

Funktionell macht diese Sequenz wenig Sinn, sie lässt uns aber verschiedene Dinge testen: Befehlspräfix IX, ein undokumentierter Opcode, LDIR-Schleife, HALT. Durch einen HALT kann durch einen NMI oder INT an bestimmten Stellen das Verhalten der CPU verfolgen werden.

Der Code wird mit

zmac --od . --oo hex filename.c

assembliert und die erzeugte IntelHex (*.hex) Datei kann in das Arduino-Terminal kopiert werden.

:10000000FBED5EDD218000DDCB2038ED5A21300094
:0E001000114000010300EDB0010100EDB076DB
:03003800FBED4D90
:03006600FBED4D62
:0000000000

Als Antwort gibt der Arduino zurück, dass der Code erfolgreich gespeichert wurde. Mit dem Befehl „m“ kann er angezeigt werden:

    00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
   +-----------------------------------------------
00 |FB ED 5E DD 21 80 00 DD CB 20 38 ED 5A 21 30 00
01 |11 40 00 01 03 00 ED B0 01 01 00 ED B0 76 00 00
02 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03 |00 00 00 00 00 00 00 00 FB ED 4D 00 00 00 00 00
04 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06 |00 00 00 00 00 00 FB ED 4D 00 00 00 00 00 00 00
07 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
08 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
09 |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0A |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0B |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0C |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0D |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0E |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0F |00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

Durch den Befehl „s“ werden die Simulationsvariablen angezeigt:

------ Simulation variables ------
#0 Trace both clock phases = 0
#1 Trace refresh cycles = 1
#2 Pause for keypress every = -1
#3 Stop after clock # = 40
#4 Stop after # M1 cycles = -1
#5 Stop at HALT = 1
#6 Issue INT at clock # = -1
#7 Issue NMI at clock # = -1
#8 Issue BUSRQ at clock # = -1
#9 Issue RESET at clock # = -1
#10 Issue WAIT at clock # = -1
#11 Clear all at clock # = -1
#12 Push IORQ vector #(hex) = FF
#13 change length of one clock cycle (msec, for H and L cycle each).

Während der Ausführung zählt das Programm die Zyklen und durch Setzen der Variablen können bestimmte Steuersignale zu bestimmten Zeiten erzeugt werden. Wenn beispielsweise bei Taktzyklus 20 ein NMI erzeugt werden soll, einfach „s 6 20“ eingeben. Optional kann auch das Verhalten bei fallender Flanke ausgegeben werden (Variable #0 aus „1“ setzen). Die Variable #1 zeigt oder versteckt die Speicheraktualisierungszyklen, die M1 begleiten.

Mit „r“ wird das Programm gestartet. Der Arduino gibt eine RESET-Sequenz an den Z80, der den Code danach schrittweise ausführt. Die Buswerte werden dann für jeden Zyklus ausgegeben.

Der Tristate wird über einen Spannungsteiler am Adress- und Datenbus erkannt (das Programm gibt für diesen Zustand ein „-“ aus).  Eine etwas gekürzte Ausgabe sieht wie folgt aus

Performing a RESET
Starting the clock
-----------------------------------------------------------+
#001H T1 AB:--- DB:-- RD                                   |
#002H T2 AB:--- DB:--                                      |
-----------------------------------------------------------+
#003H T1 AB:000 DB:-- M1                                   |
#004H T2 AB:000 DB:FB M1 MREQ RD      Opcode read from 000 -> FB
#005H T3 AB:000 DB:-- RFSH                                 |
#006H T4 AB:000 DB:-- RFSH MREQ       Refresh address 000  |
-----------------------------------------------------------+
#007H T1 AB:001 DB:-- M1                                   |
#008H T2 AB:001 DB:ED M1 MREQ RD      Opcode read from 001 -> ED
#009H T3 AB:001 DB:-- RFSH                                 |
#010H T4 AB:001 DB:-- RFSH MREQ       Refresh address 001  |
-----------------------------------------------------------+

Das folgende Video zeigt, wie die CPU ein kleines Programm schrittweise abarbeitet (200msec pro Taktzyklus).

Z80 CPU Tester

Nach einem RESET macht die Z80 CPU für zwei Taktzyklen nichts. Die T-Zyklen werden ab jedem M1-Zyklus automatisch gezählt. Eingangs- und Ausgangspins, die aktiv sind, werden ebenfalls angezeigt (z.B. RD oder RFSH).

Weiterhin werden alle Lese- und Schreibzugriffe der Z80 CPU auf den Speicher angezeigt. Insgesamt visualisiert die Arduino-Software das gesamte Verhalten der Z80 CPU.

In der aktuellen Version unterstützt die Software auch ein LCD2004. Dabei wird der Speicher ab 400H (die Adresse wird im Arduino-Sketch durch SCREENBASE definiert) als Bildschirmspeicher verwendet (4 x 20 Bytes). Soll ein ‚A‘ an Position (0/0) ausgegeben werden, geschieht dieses durch ein Schreiben an Adresse 400H <- 41H. Ein Beispiel kann durch „l 3“ geladen werden. Danach Variable s 3 hoch setzen: „s 3 1000“ und das Programm mit „r“ starten.

Z80 CPU Tester mit Display

Der Status der Taster kann durch Lesen von Adresse 4000H bzw. 4001H ermittelt werden. Ein Beispiel kann durch „l 4“ geladen werden. Danach Variable s 3 hoch setzen: „s 3 10000“ und das Programm mit „r“ starten. Durch Drücken von SELECT erscheint „ON“ auf dem Display, wird OK gedrückt, erscheint „OFF“.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert