K1-16/16 Microprozessor SSW - Schrittschaltwerk Version 5.D 2009-01-29 General ------- Das Schrittschaltwerk (SSW) umfasst: • eine normale Taktquelle mit wählbarem Vorteiler, • einen Eingang für eine externe Taktquelle, • Interrupt-, Reset- und Wait-Logik, • ein 2 x 16k x 24 Bit Microcode-ROM mit 2 Codeebenen für Verzweigungen, • das in der Startphase in ein schnelles RAM umgeladen wird. Die 24 Bit eines Microcodes werden aufgespreißelt in: • 2 x 16 Steuerleitungen für den Datenbus (je 1x /OE und clk), • 2 x 8 Steuerleitungen für den Adressbus, • 6 Optionsbits OPT0 .. OPT5, • 3 Bits zur Auswahl einer Bedingung zur Auswahl der Codeebene • und ein Command-Enable-Bit /CMD_EN, das ggf. die Ausführung des Codes unterdrückt. Das SSW hat eine 2-stufige Pipeline: Während ein Code ausgeführt wird, wird der darauf folgende aus den MCode-Rams gelesen. Mit jedem Takt des Systemtaktes CLK wird die Adresse für das MCode-Rom weitergezählt oder neu geladen, während gleichzeitig der gerade gelesene Code in die Ausführungsschicht kopiert wird. Die Pipeline kann nicht gelöscht werden. Nach einem Sprungbefehl wird immer noch der direkt darauf folgende Code ausgeführt. Teilerkette Die Teilerkette besteht aus vier 4-stufigen, synchronen Zählern 74163 mit synchronem Clear und synchronem Parallel Load. Die Schaltung von TCO (Trickle Count Out = Ripple Count Out = RCO), CENP (Clock Enable - Parallel) und CENT (Clock Enable - Tickle) ermöglicht eine höhere Höchstfrequenz für die synchrone Teilerkette, als die konventionelle TCO-to-CENT Schaltung. /SCLR (Synchronous Clear) wird von Reset und bei den unteren Zählern beim Laden des Interruptvektors und bei Opcodes, die im unteren Byte ein 8-Bit-Direktargument mitbringen, aktiviert und bedingt ein Nullen der jeweiligen Zähler beim nächsten Takt. /SLD (Synchronous Load) wird beim Laden eines Befehlswortes, d.h. einer Microcode-Adresse, aktiviert. Ansonsten zählen die Zähler die Adresse mit jedem Takt weiter. Das Microcode-Rom umfasst 16k, so dass Datenbit D14 und D15 nicht zur Adressierung nutzbar sind. D14 in einem Opcode aktiviert jedoch /SCLR der beiden unteren Adresszähler, so dass Opcodes mit einem 8-Bit-Direktargument immer auf Adresse $xx00 anfangen. Microcode-Rom und -Ram D15 eines Opcodes wird nicht ausgewertet. Der entsprechende Ausgang des obersten Zählers dient jedoch zur Unterscheidung zwischen Initialisierungsphase und Betrieb. Nur Reset löscht dieses Bit und sein Ausgang /INIT unterdrückt die Befehlsausführung und aktiviert die Eproms und schaltet die Rams auf Lesen, so dass nach Weggehen des Resetsignals zuerst die Eproms in die Rams kopiert werden. Sobald dieses Bit auf 1 gezählt wird, ist die Initialisierungsphase beendet. Je ein Rom und Ram sind parallel geschaltet. Nach Reset, in der INIT-Phase, wird der Rom-Inhalt in die Rams kopiert. Statt der Roms können auch, von extern versorgte, Schieberegister o.Ä. den zu ladenden Microcode liefern. Die Roms werden von der Teilerkette adressiert und liefern zusammen 24 Bit Steuersignale. Synchronisations-Datenregister MC.FF1 bis MC.FF3 Da das Auslesen der Rams ein wildes Geflacker auf deren Datenleitungen produziert, werden diese erneut in Flip-Flops geladen. Dies geschieht erneut synchron zum Systemtakt CLK. Mit einem Takt Verzögerung steht der 24-Bit Microcode an deren Ausgängen bereit. 3:8 Demultiplexer 14 der 24 Microcode-Bits werden zur Adressierung von Registern und Funktionen auf dem Daten- und Adressbus verwendet. 4 Bit selektieren eine Einheit am Datenbus, die Daten auf den Bus ausgeben soll. 4 Bit selektieren eine Einheit am Datenbus, die diese Daten einlesen soll. 3 Bit selektieren eine Einheit am Adressbus, die Daten auf den Bus ausgeben soll. 3 Bit selektieren eine Einheit am Adressbus, die diese Daten einlesen soll. Die Datenausgangsleitungen wechseln mit CLK ohne Übergangsfenster. Zur Verringerung von Kurzschlüssen auf dem Bus, wenn eine FU noch, und die nächste schon Daten auf den Bus legt, sind diese Steuerleitungen mit Pullups heftig nach '1' (inaktiver Zustand) vorgespannt, was die entsprechenden Zeitfenster verschmälert. (soll) Die Dateneingangsleitungen werden von Systemtakt CLK gestrobet. Das ist aus mehreren Gründen nötig. s.u. Einige Funktionseinheiten benötigen jedoch ein ungestrobetes clk-Signal, deshalb ist ein 3:8-Decoder für den Datenbus nicht gestrobet. Befehlsverzweigung durch COND Drei der Microcode-Leitungen adressieren den 8:1 Datenselektor 74HC151 COND. Dieser wählt eine von sechs möglichen Flag-Bedingungen, oder 0 oder 1 aus. Sein Ausgang liefert Adressbit 14 für den Microcode. Entsprechend werden Microcode-Befehle aus einer der beiden Code-Ebenen ausgeführt. Ansteuerung ----------- Die Teilerkette wird von Systemtakt CLK synchron weitergezählt oder, ebenfalls synchron, zum Teil auf 0 gesetzt oder mit dem Wert (=Opcode/Microcodeadresse) vom Datenbus geladen. Reset /BUS.RESET resettet die gesamte Teilerkette auf $0000. Dadurch wird auch A15, die letzte Stelle der Teilerkette, auf 0 gesetzt. A15 dient als Statusleitung /INIT: Ist A15 = 0, wird das Rom ins Ram kopiert. Nach Reset ist der Systemtakt zum Kopieren der Roms auf 1/8 herabgesetzt. (siehe SSW - Takt) ACHTUNG: /BUS.RESET ist asynchron, ggf. ist der erste Halbtakt nur 7/16 lang. Durch /INIT ist die Befehlsausführung unterdrückt, indem auch das FF für MCode-Datenbit 20 (MD4) /CMD_EN gesetzt wird. Da dies auch das Laden von Bits in das adressierbare Register DIV.FF aktiviert, war besonderer Hirnschmalz nötig, hier nicht den Eingangstakt vorzeitig zu beeinflussen. Der Reset der 74HC259 ist nämlich bedingt, und übersteuert nicht die Ladeleitung /LE. (Sterben sollen sie...!) Deshalb war es notwendig, MC.FF3 auch von /INIT zu löschen. Dann wird nämlich das 74HC259 zwar permanent geladen, aber Bit 0 mit Wert 0, und das ist ungefährlich. /INIT aktiviert die Roms mit /CE. /INIT deaktiviert die Ausgänge der Rams. /INIT, gestrobet mmit CLK, lädt mit jedem Takt ein Microcode-Wort in die Rams. CLK ist im 1. Halbtakt '1' und im 2. Halbtakt '0', d.h. /WE wird im 2. Halbtakt aktiviert. Mit Ende des 2. Halbtakts geht /WE wieder auf '1' und die Teilerkette schaltet im gleichen Augenblick eine Adresse weiter. Die Daten der Eproms bleiben aber noch ein Momentchen stehen, bevor sie purzeln, was in jedem Fall die benötigte Datenhaltezeit für die Rams befriedigen sollte. (TODO) Nach Adresse $7FFF wechselt MA15, also /INIT, von 0 auf 1. Damit werden die Roms deaktiviert und die Rams auf Ausgabe geschaltet. ACHTUNG: Der Microcode hinter MC.FF1..3 ist noch nicht gültig, wird jetzt aber ausgeführt! Das darf keine unglücklichen Seiteneffekte haben! -> Es ist der Microcode von MA $7fff -> Sicherheitshalber im letzten Opcode Bit MD4 auf 1 setzen (/CMD_EN = 1 => disable) setzen oder sinnvoll nutzen. Direct Value - DVAL Der Microcode kann ein 16-Bit-Wort auf den Datenbus ausgeben. Dadurch kann er Immediate Const Werte erzeugen oder Sprungadressen (im Microcode!) auf den Datenbus legen. Dazu dienen zwei aufeinanderfolgende Codes. Der erste aktiviert die Datenausgabe auf den Datenbus mit /CMD.OE und das gewünschte Datenziel, das mit /CMD.CLK das SSW selbst sein kann. Der darauf folgende Code enthält den auszugebenden Wert, der gerade aus den MCode-Rams ausgelesen wird, wenn der erste Code ausgeführt wird. Die Bereitstellungszeit des Datums entspricht in etwa der aus dem normalen RAM. Im nächsten Takt wandert das Datum in die Ausführungsschicht, wo seine Ausführung unterdrückt werden muss, indem darin das Bit /CMD_EN auf 1 gesetzt ist. Das lädt implizit die Bits MD0 bis MD3 in das adressierbare Register DIV.FF, wofür man z.B. DIV.FF.RES (Reset: Addr=7, Bit=0) als Wegwerf-Datensenke angeben kann. Ansteuerung der Zählerkette Normalerweise wird die Zählerkette mit jedem Takt des Systemtaktes CLK synchron weitergezählt, um den nächsten Microcode auszulesen. Ein neuer Opcode, oder eine Sprungadresse im Microcode, wird eingelesen, wenn der aktuell ausgeführte Microcode die Datenleseleitung /CMD.CLK aktiviert. Damit wird statt dessen der Wert vom Datenbus in die Zählerkette geladen. ACHTUNG: In dem Takt, in dem der Sprungbefehl ausgeführt wird, wird der Microcodebefehl nach dem Sprungbefehl gelesen. Im nächsten Takt wird der Sprung zwar wirksam, d.h. es wird jetzt Microcode ab der neuen Adresse gelesen, aber jetzt ist der Befehl direkt hinter dem Sprungbefehl in der Ausführungsschicht und wird noch ausgeführt! Beim Laden des Microcodes gibt es folgende Ausnahmen: /BUS.RESET ist aktiv: Statt dessen werden alle Zähler auf $0 gesetzt, insbes. auch MA15 = /INIT = 0. Bit D14 im Opcode ist '0': In die beiden unteren Zähler wird statt dessen das Byte $00 geladen. Vorgesehen ist, dass das untere Byte immer auch zusätzlich in ein speziellen Register CMD.LO geladen wird. Dadurch kann ein Opcode einen 1-Byte Immediate Value als Argument mitbringen. Der Opcode selbst startet seine Ausführung auf MA $xx00 und kann zu gegebener Zeit CMD.LO auf den Datenbus (oder Adressbus) als Konstante ausgeben. Bit D14 im Opcode ist '1': Die Startadresse des Opcodes wird mit allen 14 Bits signifikant geladen. /INT ist aktiv und der Opcode wird via PC aus dem RAM gelesen: Der Opcode wird vollständig unterdrückt und statt dessen wird $3000 als Start der Interrupt-Behandlungsroutine geladen. /INT ist das bereits mit CLK synchronisierte und mit DIV.FF.IE (Interrupt Enable) maskierte Interruptsignal vom I/O-Bus. (siehe SSW - Takt) Der Interruptvektor darf nur untergeschoben werden, wenn der so übergangene Befehl rekonstruiert werden kann. Da ein Befehl aus beliebigen Quellen auf den Datenbus gelegt werden kann, werden die Leitungen /PC.OE (PC ist auf den Adressbus gelegt) und /MEM.OE (RAM gibt Daten auf den Datenbus aus) geprüft. Damit kann der übergangene Befehl wiederholt werden, wenn man den PC wieder um 1 zurückstellt. 8:1 Datenselector COND Die Ausführung eines Microcodes kann zwischen 2 Code-Ebenen umschalten. Dazu dienen im Microcode die Bedingungsleitungen CMD.COND1..4, die eine Leitung im 8:1 Datenselector COND auswählen. Zwei Bedingungen sind unbedingt und halten die Ausführung in der jeweiligen Code-Ebene. 6 Bedingungen benutzen CY, Z und andere Bedingungen um in die beiden Code-Ebenen zu verzweigen. Alle Bedingungen sind nur zum Zeitpunkt des Tests gültig und werden nicht gespeichert. Es gibt kein Flag-Register! Der Bedingungscode wird direkt hinter den MCode-Rams abgegriffen und das Ergebnis mit dem nächsten Takt als Adressbit MA14 gelatcht. Das ergibt eine Latenz von einem Code. Bei Sprungbefehlen (Laden einer neuen Codeadresse) startet der Zielcode in der Code-Ebene, die im Sprungbefehl codiert war! Pullup-Widerstände Die Output-Steuerleitungen /Ax.OE und /Dx.OE werden ohne Übergangsphase von Takt zu Takt umgeschaltet. In der Übergangsphase sind auf den Daten- und Adressleitungen jeweils zwei Bustreiber für einen Augenblick gleichzeitig aktiv und treiben einzelne Leitungen in die umgekehrte Richtung. Dieser Zustand muss so kurz wie möglich sein, wenn er sich nicht sogar ganz unterbinden lässt. Deshalb werden die /OE-Leitungen mit niedrigohmigen Pullup-Widerständen nach '1' (inaktiv) gezogen, was die '1'-Phase minimal auslängt und die '0'-Phase entsprechend verkürzt. (TO BE TESTED)