Der Mikroprozessor U 880


Der in der DDR am häufigsten eingesetzte Prozessor war der U 880. Er war die DDR-Variante des Z 80 von Zilog. Man fand ihn in förmlich jedem Gerät, welches annähernd mit Computer zu tun hatte, wieder. Er war in Computerbausätzen, Bürocomputern vorhanden, man konnte ihm bei der Prozeßautomatisierung begegnen und natürlich war er auch das treibende Herz in den Kleincomputern angefangen vom Z 1013 bis hin zum KC Compact. Aus diesem Grunde soll der U880 näher beleuchtet werden. 

Nachfolgende Aufzeichnungen entstammen zum Großteil privaten Aufzeichnungen und natürlich "dem Buch zum U 880" mit dem Titel "8-Bit-Mikrorechentechnik" [Bar88] von Bäurich/Barthold aus dem Militärverlag der Deutschen Demokratischen Republik.


Der U880


Registerstruktur

Der U 880 ist ein in NMOS [n-Channel Metal Oxide Semiconductor] Technologie gefertigter LSI [Large Scale Integration] Schaltkreis. Er besitzt einen bidirektionalen 8-Bit-Datenbus von dem aus alle Register erreichbar sind und einen 16 Bit breiten Adreßbus.

Der Registersatz umfaßt:

  • 2 Registersätze bestehend aus je acht 8-Bit-Registern. Der erste Satz umfaßt die Register A, F, B, C, D, E, H, und L. Der zweite Satz stellt die sogenannten Schattenregister A', F', B', C', D', E', H', und L' zur Verfügung. Durch einen Austauschbefehl können die Inhalte der beiden Registersätze vertauscht werden. Dieser Austausch ermöglicht so die Zuordnung von unterschiedlichen Registerinhalten an unterschiedliche Programmteile.
  • einen Stackpointer. Dieser beinhaltet eine 16-Bit-Adresse, die die Spitze des Stacks adressiert. 
  • einen Programmcounter, der die Adresse enthält, in der der aktuelle Befehl zu finden ist.
  • zwei Indexregister IX und IY. Sie können zwei 16-Bit-Adressen enthalten. Bei der Adressenberechnung wird aus dieser Basisadresse und einem Offset die eigentliche Adresse berechnet.
  • Das Refreshregister R stellt eine 7-Bit-Adresse bereit, die in Verbindung mit dem Refreshsignal RFSH auf den niederwertigen 7 Bit des Adreßbusses während der Operationscodeentschlüsselung gesendet wird. Sie dient dem Refresh des Speichers. Während eines jeden Operationscodeholezyklus wird der Inhalt von R inkrementiert.
  • Interruptregister I hält eine 8-Bit-Adresse bereit, die den höherwertigen Teil einer Adresse, deren niederwertige Teil bei einem Interrupt vom entsprechenden Gerät generiert wird, repräsentiert.
  • das Flagregister F.  Es bietet die gängigen Flags, die in Abhängigkeit von einzelnen Befehlen gesetzt werden  und ermöglicht ihre Auswertung.
    • C - Carry-Flag 
      • C = 1 bei Additionsübertrag in die 8. Stelle oder beim Borgen  von der 8. Stelle bei der Subtraktion
    • N - Subtraktions-Flag 
      • N = 1, wenn Operation eine Subtraktion war.
    • P/V - Parity-Überlauf-Flag 
      • P/V = 1

      • bei logischen Operationen: Anzahl der Einsen im Ergebnis ist gerade 
        bei Rechenoperationen: Überlauf ist aufgetreten
    • H - Half-Carry-Flag
      • H = 1, analog C-Flag, allerdings auf die 4. Stelle bezogen
    • Z - Zero-Flag
      • Z = 1, wenn im Ergebnis alle Bitstellen 0 sind 
    • S - Sign-Flag
      • S = 1, wenn Vorzeichen im Ergebnis gesetzt
  • das Befehlsregister BR. Es beinhaltet den aktuellen Operationscode. Im Befehlsregister kommt es zur Decodierung des Befehls und zur Bildung der Steuersignale zu seiner Abarbeitung. Steuersignale umfassen Befehls- und Zeitsignale, wobei die Befehlssignale durch die Befehlsentschlüsselung und die Zeitsignale durch die Zeitsteuerung gebildet werden. Der Zyklengenerator bildet die Zeitsteuerung. Er wird durch einen externen Takt und die Befehlssignale gesteuert. Er bildet ebenfalls die Signale zur Steuerung der externen Bausteine und tastet ihre Signale ab.

Prozessorstart

Für den Start des Prozessors existieren drei Möglichkeiten, wobei eine der RESET darstellt. Der Startimpuls kann ausgelöst werden über:
  1. die NMI-Leitung, wobei ab Adresse 66H das Startprogramm stehen muß,
  2. die INT-Leitung, wobei zuvor der INT-Eingang mit EI freigeschaltet werden muß, der Interrupt-Mode muß eingestellt und das Interrupt-Wort auf dem Datenbus bereitgestellt werden
  3. oder über ein RESET. Hier beginnt die Abarbeitung im Prozessor mit der Adresse 0, in der damit der erste Befehl des Startprogramms steht.

Befehle

1 bis 4 Byte benötigt man zur Darstellung eines Befehles, der aus Operationsteil und Adreßteil besteht, dabei kann der Operationsteil 1 bis 3 Byte und der Adreßteil 1 bis 2 Byte lang sein. Meist hat der Operationsteil eine Länge von einem Byte. Bei 2 Byte Länge gibt das 1. Byte die Befehlsgruppe an, 2. und 3. Byte kennzeichnen einen speziellen Befehl innerhalb dieser Gruppe.

Eine tabellarische Übersicht ist im Anhang E.1 zu finden.

Zu jedem Befehl gehören ein bis zwei Operanden. Für Operanden gibt es die unterschiedlichsten Speicherorte: 

  1. Registeroperand 
    • Operand steht in einem Register, welches im Befehl angegeben wird.
  2. Direktoperand
    • Operand steht im Anschluß an den Operationscode. 
    • 1. Byte Operationscode 
    •  2. Byte niederwertige Teil des Operanden 
    •  3. Byte höherwertiger Teil des Operanden
  3. Adressierter Operand
    • Im Befehl steht die Adresse, in der der Operand zu finden ist. 
    • 1. Byte Operationscode 
    • 2. Byte niederwertiger Teil der Adresse 
    • 3. Byte höherwertiger Teil der Adresse 
  4. Relative Adressierung
    • Befehl enthält eine positive oder negative Zahl x, Operand steht um x-Zellen vor oder nach dem Befehl 
    • 1. Byte Operationscode 
    • 2. Byte positive oder negative Zahl x im Zweierkomplement 
    • 3. Byte nächster Befehl 
    • Adresse = Adresse Zelle 3 + x
  5. Indirekte Adressierung
    • Adresse des Operanden steht in einem Register 
    • Registerpaare HL, DE, BC, SP, IX und IY sind möglich 
  6. Indexierung
    • Adresse des Operanden errechnet sich aus der im Befehl angegebenen Zahl x und dem Inhalt eines Indexregisters 
    • 1. Byte Operationscode 
    • 2. Byte positive oder negative Zahl x im Zweierkomplement 
    • Adresse = x + <Indexregister> 

Abarbeitung

Die Abarbeitung eines Befehls läßt sich in mehrere Schritte unterteilen, wobei die einzelnen Arbeitsgänge in Maschinenzyklen ausgeführt werden. Diese einzelnen Arbeitsgänge umfassen: den Befehl holen, den Befehl entschlüsseln, den Operanden holen, den Befehl ausführen und die Adresse des nächsten Befehls ermitteln.

Ein Maschinenzyklus wird charakterisiert durch die Befehlssignale, die aus der Befehlsentschlüsselung hervorgehen. Interne Steuersignale entstehen wie schon erwähnt aus dem Hinzufügen von Zeitsignalen zu den Befehlssignalen. Diese Steuersignale steuern die Abarbeitung in Form von Registertransporten. Zur Steuerung des Datentransfers mit angeschlossenen Bausteinen werden gleichzeitig äußere Steuersignale gebildet. 

Gleichzeitig zur Abarbeitung interner Prozessorfunktionen erfolgt in einem Maschinenzyklus auch der Zugriff auf den Bus, daher gibt es verschiedene Funktionen, die ein Maschinenzyklus erfüllen kann:

  • Operationscode holen,
  • Speicher lesen,
  • Speicher schreiben,
  • Eingabe,
  • Ausgabe,
  • Interrupt,
  • DMA und
  • HALT-Operation.
Die Abarbeitung eines Maschinenzyklusses kann 3 bis 6 Takte in Anspruch nehmen.

Hierzu ein Beispiel.

Maschinenzyklen zum Lesen eines Byte aus dem Speicher

Der zum Lesen eines Byte durchzuführende Befehlszyklus umfaßt das Holen des Operationcodes und das Lesen des Speichers. 

Der Befehlszähler enthält zu Beginn die Adresse des Operationscodes.  Bei fallender Flanke von T1 werden die Signale /MREQ und  /RD aktiv, d.h Memory Request, also Anforderung zum Speicher und Read, eine Lese-Operation soll ablaufen. Das Einlesen geschieht mit der Vorderflanke während T3. Während der Zyklen T3 und T4 liegt eine Auffrischadresse für dynamische Speicher am Adreßbus an - an den Adreßbits A0 bis A6, die restlichen Bit sind 0 und das Signal /RFSH ist aktiv. Ist bei einer Rückflanke im Zustand T2 das /WAIT aktiv, so wird nach T2 solange ein Wartezyklus eingeschoben, bis /WAIT inaktiv wird.

Zu Beginn des Speicher-Lesezyklusses, ausgelöst durch die Taktvorderflanke in T1, wird die Speicheradresse auf den Adreßbus gelegt. Die Rückflanke in T1 aktiviert die Signale /MREQ und /RD. /MREQ wird zur Ansteuerung des betreffenden Speichers genutzt, /RD schaltet den Speicher auf Lesen. Bei der Taktrückflanke in T2 wird das Signal /WAIT abgetastet. Bei aktiven /WAIT wird nach T2 ein Wartezyklus eingefügt. Während des Wartezyklusses bleiben  die Adressen am Adreßbus und die Daten am Datenbus erhalten. Bei der nächsten Taktrückflanke wird die Abfrage von /WAIT wiederholt und gegebenenfalls erneut ein Wartezyklus eingefügt. Bei nicht mehr aktivem /WAIT wird der Zustand T3 eingenommen. Während des Taktes in T3 werden die Daten vom Speicher in den Prozessor übernommen und mit der Taktrückflanke werden /MREQ und /RD abgeschaltet.


Interrupt - Betrieb


Interrupt - Typen

Der U 880 kennt zwei Interrupteingänge, den maskierbaren (INT) und den nicht maskierbaren Interrupt (NMI). Maskierbar bedeutet, daß ein Öffnen und Sperren des Eingangstores durch das Programm mittels den Befehlen EI bzw. DI geschehen kann. Der maskierbare Interrupt wird zum Aufbau umfangreicher Unterbrechungsschaltungen genutzt. Zur Steuerung des Eingangstores INT dienen die im Prozessor enthaltenen Flip-Flop IFF1 und IFF2. IFF1 steuert das Eingangstor unmittelbar, ist es eingeschaltet, ist das Tor offen, ist es ausgeschaltet, ist das Tor geschlossen. IFF2 dient als Zwischenspeicher für IFF1 für den Fall, das ein Signal über den NMI-Eingang kommt. Der NMI wird für besonders wichtige Ereignisse verwendet und hat daher die höchste Priorität und unterbricht in jedem Fall das laufende Programm. Ab Adresse 66H muß ein Bedienprogramm stehen, da der NMI immer dort sein Programm startet. 

Nach Auftreten eines Signals an einem der beiden Interrupteingänge wird der laufende Befehl abgearbeitet und danach der Interruptzyklus ausgeführt. Dieser bereitet den Übergang zu einem entsprechenden Bedienprogramm vor - anschließend wird es ausgeführt.

Beeinflussung der Flip-Flops IFF1 und IFF2

Hier sei die Wirkung von Befehlen und Signalen auf die Flip-Flops aufgeführt. 
 
IFF1 IFF2
RESET 0 -> IFF1 0 -> IFF2 Interrupt - Mode 0
DI 0 -> IFF1 0 -> IFF2
EI 1 -> IFF1 1 -> IFF2
LD A,I bleibt bleibt IFF2 -> Parity-Flag
LD A,R bleibt bleibt IFF2 -> Parity-Flag
INT 0 -> IFF1 0 -> IFF2
NMI 0 -> IFF1 IFF1 -> IFF2
RETN IFF2 -> IFF1 bleibt
RETI IFF2 -> IFF1 bleibt
Wirkung von Befehlen und Signalen auf Flip-Flops

Ablauf

Jeder Interrupt, sowohl NMI (Anhang E.2) als auch INT (Anhang E.3), schaltet als erstes IFF1 aus, nachdem das laufende Programm unterbrochen wurde. Der Unterschied zwischen dem nicht maskierbaren und dem maskierbaren Interrupt besteht darin, daß bei einem nichtmaskierbaren Interrupt NMI IFF1 zuvor nach IFF2 gerettet wird. Nach Beendigung des Bedienprogramms für den NMI wird IFF2 nach IFF1 zurückgeschrieben.

Der Übergang in das Bedienprogramm für NMI und INT unterscheidet sich folgendermaßen: 

  • Bei einem NMI wird im Prozessor automatisch der Befehl CALL 66H gebildet und ausgeführt. Er bewirkt den Programmaufruf an Adresse 66H. 
  • Der maskierbare Interrupt INT stellt drei Modi zur Verfügung, die sich vorher durch die Befehle IM0, IM1 und IM2 einstellen lassen.

  •  
    1. MODE 0

    2. Während des Interrupt-Zyklusses wird ein 8-Bit-Wort eingelesen und sofort im Zusammenhang mit RST z ausgeführt. RST z ist ein 1-Byte-CALL-Befehl zu der Adresse z, die hier den vom Datenbus eingelesenen Wert darstellt.
    3. MODE 1

    4. MODE 1 verhält sich ähnlich einem nichtmaskierbaren Interrupt NMI, mit dem Unterschied, das der Sprung zur Adresse 38H führt - also CALL 38H. 
    5. MODE 2

    6. Hier wird die Adresse aus dem I-Register und dem eingelesenen 8-Bit-Wort vom Datenbus, dem Interrupt-Vektor, gebildet.

      Die Produktionsvorschrift lautet demnach: Adresse = I-Register, Interrupt-Vektor.

      Der Inhalt des I-Registers bildet somit den höherwertigen Teil, während der Interrupt-Vektor den niederwertigen Teil bereitstellt. Diese hier konstruierte Adresse zeigt auf eine Speicherzelle, deren Inhalt als Argument für einen CALL-Befehl dient

      -> CALL <I-Register, Interrupt-Vektor>.

      Es wird demnach eine Interrupt-Tabelle verwendet, die alle Adressen der Bedienprogramme enthält.