Synchrone Schaltwerke

Prinzipiell lässt sich jede von einem Computer ausführbare Operation durch ein Schaltnetz realisieren. Allerdings wäre es unpraktisch, für jede Anwendung eigens spezielle Hardware anzufertigen. Ein großer Vorteil gängiger Computer ist ihre Vielseitigkeit. Sie erlauben eine unbegrenzte Zahl unterschiedlicher Operationen mit Hilfe von Software zu realisieren. Die begrenzte Anzahl der von der ALU bereitgestellten Operationen reicht dazu aus.

Der dabei entscheidende Mechanismus ist es, mehrere Instruktionen nacheinander auszuführen und dabei auftretende Zwischenergebnisse zu speichern. Statt Schaltnetze hintereinanderzuschalten, um komplexe Instruktionen auszuführen, kann dabei das Ergebnis der ersten Operation gespeichert und dann mit dem selben Schaltnetz weiter verarbeitet werden.

Diesem Mechanismus liegt ein Konzept zugrunde, das wir bei Schaltnetzen bisher nicht berücksichtigt haben: das der Zeit. Instruktionen werden zeitlich nacheinander ausgeführt und zu einem Zeitpunkt gespeicherte Werte können zu einem späteren Zeitpunkt abgefragt werden.

Zeit wird in Computern durch ein periodisches Signal modelliert. Eine Periode des Signals entspricht dabei einem Taktzyklus des Hauptprozessors. Ein Taktzyklus muss lang genug für die Signallaufzeiten aller beteiligten Schaltnetze sein. Ist dies gegeben, brauchen wir die einzelnen Signallaufzeiten nicht mehr zu berücksichtigen, um das Verhalten eines Computers zu erklären.

Flip-Flops

Schaltnetze, die zusätzlich zu ihren logischen Eingängen auch auf das Taktsignal zugreifen, heißen synchrone Schaltwerke. Wie bei den Schaltnetzen gibt es auch hier ein primitives Bauteil, dass allen synchronen Schaltwerken zugrunde gelegt werden kann: das Flip-Flop. Die Implementierung eines Flip-Flop ist aus informatischer Sicht uninteressant. Wir begnügen uns damit, sein Verhalten zu beschreiben und für die Implementierung komplexerer synchroner Schaltwerke zu nutzen.

Das Verhalten eines Flip-Flops ist einfach zu beschreiben. Es hat (neben dem Eingang für das Taktsignal) einen Eingang und einen Ausgang, wobei der Ausgang immer das Eingangssignal aus dem vorigen Taktzyklus liefert.

Speicher

Ein 1-Bit-Register ist der kleinste aller Speicherbausteine. Es hat (neben einem Eingang für das Taktsignal) zwei Eingänge in und load und einen Ausgang out. Wenn das load-Bit gesetzt ist, wird der an in anliegende Wert gespeichert. Der Wert von out ist immer der momentan gespeicherte Wert. Ist das load-Bit nicht gesetzt, bleibt der Wert aus dem vorigen Taktzyklus gespeichert.

Die Implementierung eines 1-Bit-Registers verwendet ein Flip-Flop und einen 2-zu-1 Multiplexer, der je nach load-Eingang zwischen dem Eingang und dem Ausgang auswählt.

Reg1(clock, load, in; out):
  2MUX1(load, out, in; a)
  FlipFlop(clock, a; out)

Dadurch wird bei gesetztem load-Bit der Eingang des Registers auf den Eingang des Flip-Flops gelegt. Ist das load-Bit nicht gesetzt, wird das Flip-Flop mit seinem Ausgang verbunden, wodurch der Wert aus dem vorigen Taktzyklus gespeichert bleibt.

Register der Wortgröße \(w\) können aus \(w\) 1-Bit-Registern zusammengeschaltet werden. Ein- und Ausgang werden dabei zu einem Bus der Wortgröße \(w\), deren Zustand bei gesetztem load-Bit komplett im Register abgelegt wird.

Der Hauptspeicher eines Computers kann wiederum aus mehreren Registern der Wortgröße \(w\) zusammengesetzt werden. Ein- und Ausgang behalten dabei die Größe \(w\) und werden durch einen Adressierungs-Eingang erweitert, der mit Hilfe eines De-Multiplexers bestimmt, in welchem Register die angelegte Bit-Kombination abgespeichert werden soll. De-Multiplexer sind wie umgedrehte Multiplexer, leiten also ein Eingangssignal gemäß angelegter Steuerungs-Bits auf einen von mehreren möglichen Ausgängen um. Der Ausgang des Hauptspeichers ergibt sich mit Hilfe eines Multiplexers aus dem Ausgang des addressierten Registers.

Instruktionsspeicher und Programmzähler

Das vom Computer ausgeführte Programm wird in einem speziellen Bereich des Hauptspeichers (dem sogenannten Instruktionsspeicher) abgelegt, ist also nichts weiter als eine speziell interpretierte Bitfolge. Der Einfachheit halber können wir annehmen, dass jede Maschineninstruktion in einem Register des Instruktionsspeichers abgelegt ist.

Typischerweise gibt es zwei Arten von Maschineninstruktionen, die zum Beispiel durch ihr erstes Bit voneinander unterschieden werden können.

  • LOAD-Instruktionen erlauben, einen vorgegebenen Wert in einem Register des Hauptprozessors abzuspeichern
  • Andere Instruktionen bestehen aus Steuerungs-Bits für die ALU und Adressierungs-Bits für die Ein- und Ausgabe der von der ALU ausgeführten Operation.

Die Ausführung des im Instruktionsspeicher enthaltenen Programms steuert der sogenannte Programmzähler, der die Adresse der als Nächstes auszuführenden Instruktion enthält. Der Programmzähler ist ein Register, kann also (insbesondere durch sogenannte JUMP-Instruktionen) auf eine beliebige Adresse gesetzt werden und diese speichern. Zusätzlich verfügt er in der Regel über Eingänge reset und inc. Ist das reset-Bit gesetzt, wird der Zähler auf Null zurückgesetzt. Ein angelegtes inc-Bit hat zur Folge, dass der Zähler erhöht wird, also auf die nächste Instruktion im Instruktionsspeicher zeigt.