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).
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.
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