Rudi's Homepage - Elektronik

EnglishDeutsch

Übersicht

Hier finden sich klassische Einplatinenrechner auf der Basis legendärer Prozessoren. Neben dem pädagogischen Aspekt (wie entwerfe ich eine Speichersteuerung, wie interpretiere ich die Busprotokolle der Prozessoren) sind diese Projekte kleine private Denkmäler für Meilensteine der Computerentwicklung. Denn der Z80 stand einmal synonym für CP/M und Büromaschinen, der 68000 für Macintosh, Commodore Amiga und Atari ST.
Zuletzt aktualisiert: 2010.02.05 10:53 AM

Z80 Computer

Beschreibung:

RUDI-1 Z80 Computer von oben.
RUDI-1 Z80 Computer von oben.
Hierbei handelt es sich um meinen ersten Selbstbau-Computer. Es ist ein minimales Z80-System, bestehend aus einer mit 2.4576 Mhz getakteten Z80-CPU, 8 kByte ROM, 8 kByte SRAM und einer 16C550 UART-Schnittstelle. Über die UART findet die serielle Kommunikation (9600 baud, 8N1) mit dem Rechner statt. Darüber hinaus verfügt der Rechner als Ausgabemöglichkeit nur über 3 LED's. Eine signalisiert den HALT-Zustand der CPU, die anderen beiden sind frei programmierbar an die UART angeschlossen.
Komponentenbeschreibung.
Komponentenbeschreibung.

Aufbau

Aufgebaut ist der Rechner auf einer Euro-Prozessor-Lochrasterplatine. Als Gehäuse eignete sich vorzüglich eine volltransparente Ferrero-Konfektschachtel, und das quasi zum Nulltarif.

Unterseite des Z80-Computers.
Unterseite des Z80-Computers.
Gerade durch das volltransparente Gehäuse stellt der Rechner auch eine Art Dokumentation eines wichtigen Zeitalters in der Computergeschichte dar, die der 8-Bit Mikroprozessoren - für welche der Z80 wohl das gelungenste Exemplar darstellt.

Schaltung - Übersicht

Schaltplan
Schaltplan
Die Stromversorgung wurde durch einen Vollwegegleichrichter mit dahintergeschaltetem 7805 5V Festspannungsregler realisiert. Den Takt stellt ein Oszillatormodul (OSC) als vollintegrierte Lösung bereit. Die Eingangspins WAIT und BUSRQ werden mit 2k2 Pull-Up-Widerstand auf inaktivem Pegel gehalten, ebenso der NMI-Pin, welcher aber durch einen Taster zur Auslösung eines nichtmaskierbaren Interrupts aktiviert werden kann. Die Resetschaltung (im Schaltplan direkt unter der CPU) besteht aus einer RC-Kombination und zwei kaskadierten 74HCT14 Schmidt-Trigger-Invertern U1 und U2. Dadurch kann sowohl ein Reset-Signal mit L-Aktivpegel für die CPU wie ein Resetsignal mit H-Aktivpegel für die UART bereitgestellt werden. Hinsichtlich der Resetschaltung ist zu bemerken, daß die angegebene Dimensionierung für das RC-Glied nicht für die gewünschte Power-On-Reset-Funktionalität ausreichte. Nicht eingezeichnet sind die 100n Pufferkondensatoren, die direkt an die Versorgungsanschlüsse jedes IC gelötet wurden. Ebenfalls nicht eingezeichnet sind die auf definierten Pegel gelegten Eingänge der nicht benutzten Gatter der Logikbausteine 74HCT14 und 74HCT32.

Schaltung - Speichersteuerung

Die Speichersteuerung hatte die Aufgabe, die Chip-Select-Signale für die externen Bausteine (8 kByte EEPROM, 8 kByte SRAM und die 16C550 UART zu erzeugen. Eine komplizierte dynamische Speichersteuerung ist nicht vonnöten, da die Speicherbausteine schnell genug sind, um die Operationen innerhalb eines Buszykluses abzuschließen. Ansonsten hätte die Speichersteuerung zusätzlich über das WAIT-Signal des Prozessors Wartezyklen realisieren müssen. Da der Z80 über getrennte Speicherräume für den Hauptspeicher und die E/A besitzt, wurde folgende Aufteilung getroffen: Der Hauptspeicheradreßraum ist in 2 gleich große Teile für RAM und ROM getrennt. Das ROM liegt in den unteren 32 kByte, das RAM beginnt bei den oberen 32 kByte. Da nur ein E/A-Baustein, nämlich die UART, angeschlossen ist, hätte man diese direkt an den Anfang des E/A-Adreßraums legen können. Dem Ehrgeiz halber wurde die Basisadresse der UART auf 0x80h gelegt. Zur Realisierung muß man den Ablauf des Z80-Buszykluses kennen: die CPU legt die Adresse auf den Adreßbus und aktiviert entweder MEMRQ oder IORQ, je nachdem ob sie einen Speicherzugriff oder einen E/A-Zugriff haben möchte. Mit aktivem Pegel auf RD oder WR zeigt die CPU zudem an, ob sie lesen oder schreiben möchte. Der logische Ausdruck für das L-aktive Chip-Select-Signal für das ROM (ROMCS) ist also: A15=L UND MEMRQ=L, daraus folgt ROMCS = A15 UND MEMRQ, was durch U4 realisiert wird. Für das RAM gilt: RAMCS aktiv = L wenn A15 = H und MEMRQ = L. Generiert wurde es mit RAMCS = (NICHT A15) UND MEMRQ, realisiert durch U3 und U5. Für die UART gilt: UARTCS = aktiv L wenn A7=H und IORQ=L. Daraus folgt: UARTCS = (NICHT A7) UND IORQ, realisiert durch U6 und U7.

Das Monitor-Programm

Die entwickelte Software umfaßt zwei Teile: zum einen Routinen für ein rudimentäres BIOS (Basis-E/A-System), welche die Ein- und Ausgabe von Zeichen und Zahlen anbieten, zum anderen ein klassisches, auf dem E/A-System aufbauenden Monitorprogramm, welches der Anzeige der Register und des Hauptspeicherinhaltes dient und auch das Laden von Maschinenprogrammen ermöglicht. Der Assembler-Quelltext des Monitorprogramms ist hier bzw. als Binärprogramm verfügbar. Folgende Systemroutinen stehen zur Verfügung: PRINT_CHAR (0xd3) Gibt ein Zeichen über die UART aus. Der ASCII-Code des Zeichens wird im Register A erwartet. PRINT_STRING (0xb9) Gibt eine Zeichenkette über die UART aus. Die Basisadresse der nullterminierten Zeichenkette wird in BC erwartet. PRINT_HEX (0x144) Gibt den Inhalt des HL-Registers im Hexadezimalcode über die UART aus. PRINT_BINARY (0x1ba) Gibt den Inhalt des Akkumulators (A) im Binärcode aus. DUMP_MEM2 (0x1cb) Gibt den Inhalt der durch HL referenzierten Speicherstelle im Hexadezimalcode aus. Num2Dec (0xfd) Konvertiert den Inhalt des HL-Registers in einen den Dezimalcode beinhaltende Zeichenkette, deren Basisadresse durch das DE-Register übergeben wird. Num2Hex (0x125) Konvertiert den Inhalt des HL-Registers in einen den Hexadezimalcode beinhaltende Zeichenkette, deren Basisadresse durch das DE-Register übergeben wird. input_char (0xe6) Wartet auf die Eingabe eines Zeichens über die UART und gibt den ASCII-Code über das A-Register zurück (blockierend). input_string (0x193) Liest eine nullterminierte Zeichenkette an die über HL angegebene Stelle ein. HL beinhaltet danach das Ende der Zeichenkette. input_stringl (0x1a6) Liest eine nullterminierte Zeichenkette an die über HL angegebene Stelle ein. Dabei werden nur BC viele Zeichen eingelesen. HL beinhaltet danach das Ende der Zeichenkette. atoi8u (0x172) Konvertiert die durch HL referenzierte nullterminierte Zeichenkette, welche als Dezimalzahl interpretiert wird, in eine 8-Bit-Ganzzahl, die im A-Register abgelegt wird. atohex8u (0x21a) Konvertiert die durch HL referenzierte nullterminierte Zeichenkette, welche als Hexadezimalzahl interpretiert wird, in eine 8-Bit-Ganzzahl, die im C-Register abgelegt wird. Das B-Register beinhaltet 0 bei fehlerfreier Konversion oder den Index des abgelehnten Zeichens. toggle_1 (0x3a5) Schaltet die erste an der UART angeschlossene LED um. toggle_2 (0x3c1) Schaltet die zweite an der UART angeschlossene LED um. mul8u8u (0x5cd) Multipliziert die vorzeichenlosen 8-Bit Multiplikanten H und L und schreibt das Ergebnis nach HL. div8u8u (0x5f6) Vorzeichenlose 8-Bit-Integerdivision D/E, Quotient in D, Rest in A. Nach dem Starten gibt der Computer eine Startmeldung und das Hauptmenü aus (serielle Kommunikation mit 9600 Baud, 8N1).

Hauptmenü des Monitorprogramms.
Hauptmenü des Monitorprogramms.
Über dieses Menü können die an die UART angeschlossenen LED's umgeschaltet werden, die CPU in den Haltezustand gebracht werden aber auch (s.u.) der Zustand der CPU- und UART-Register angezeigt werden.
Registeranzeige.
Registeranzeige.
Weiterhin kann der gesamte Speicheradreßraum in hexadezimaler Form dargestellt werden.
Speicheranzeige.
Speicheranzeige.

Ein einfaches Programm.

Auch Maschinenprogramme können geladen und ausgeführt werden. Dies soll am Beispiel einer einfachen Summenberechnung gezeigt werden. Das Programm soll eine natürliche Zahl N aus dem Hauptspeicher laden, die Summe aller Zahlen zwischen 1 und N berechnen und den errechneten Wert in den Speicher zurückzuschreiben. Das Programm wird als Assemblercode eingegeben:

Eingabe des Assemblerprogramms.
Eingabe des Assemblerprogramms.
Das Programm definiert zuerst einmal die Adresse der Speicherstelle, von der gelesen wird, als Symbol N. Die Adresse selbst wurde auf 0x8200 festgesetzt. Danach werden die benutzten Register auf den Stack gerettet und den Wert von N in das Register A geladen. Danach wird dieser Wert in das Zählregister B umgeladen und das Register A auf 0 gesetzt. Die folgende Schleife wird solange durchlaufen, bis B 0 ist. Dabei wird B automatisch dekrementiert (DJNZ-Befehl!) und der Wert von B auf A addiert. Nach der Schleife wird der Wert der Summe zurückgeschrieben, die alten Werte der Register A und B zurückgeladen und mit dem RET-Befehl zum Hauptmenü zurückgesprungen. Nach der Übersetzung des Programms mit dem Assember (z80-asm, lokale Kopie)
			  z80-asm Prog1.asm Prog1.z80
		  
kann das Programm mit einem Hex-Editor angezeigt werden:
Anzeige des Maschinenprogramms.
Anzeige des Maschinenprogramms.
Die ersten 10 Bytes sind ein von dem verwendeten Assembler erzeugten Header und müssen ignoriert werden. Die folgenden Bytes werden mittels des l-Befehl geladen:
Eingabe des Maschinenprogramms.
Eingabe des Maschinenprogramms.
Mit dem d-Befehl kann die Eingabe auf Erfolg kontrolliert werden:
Kontrolle der Programmeingabe.
Kontrolle der Programmeingabe.
Nun kann der Zahlenwert von N in die Speicherstelle 0x8200 eingegeben werden:
Eingabe des Zahlenwerts.
Eingabe des Zahlenwerts.
Auch hier kann man mit dem d-Befehl die Eingabe kontrollieren:
Kontrolle der Werteingabe.
Kontrolle der Werteingabe.
Nach der Programmausführung mit dem g-Befehl liegt das Ergebnis an dieser Speicherstelle vor:
Anzeige des Ergebnisses.
Anzeige des Ergebnisses.
Das Ergebnis 0xF=15 ist die Summe der Zahlen 1+2+3+4+5 = (5+1)*5/2.

Das verbesserte Programm.

Nun soll das Programm mit Hilfe der angebotenen BIOS-Routinen so umgeschrieben werden, daß es eine komfortable Ein/Ausgabe in Textform anbietet. Der Quelltext des Programms findet sich hier. Da die manuelle Eingabe des Maschinenprogramms zu aufwendig wäre, wurde das Monitor-Programm um einen Befehl zum Laden von Binärprogrammen (b) erweitert. Dazu wurde ein C++-Programm geschrieben, welches das Ausgabeformat des Z80-Assemblers auf das vom Monitorprogramm erwartete Format umwandelt. Der Aufrufsyntax ist wie folgt:

			  z80-asm Prog2.asm 0x8400::Prog2.z80
			  convertZ80 Prog2.z80 Prog2.bin
		  
Das konvertierte Binärprogramm Prog2.bin kann dann mit der "Sende Raw-File"-Option des Terminalprogramms gtk-term gesendet werden.
Eine komfortablere Version.
Eine komfortablere Version.


68000 Computer

Beschreibung:

Impressionen aus der Bauzeit

Zwischenstand.
Zwischenstand.
Der Arbeitsplatz.
Der Arbeitsplatz.