Eine CPU von Grund auf in einem Simulator bauen
Eine zusammenhängende, testbare Anleitung für eine 8-Bit-Lehr-CPU mit Registern, ALU, gemeinsamem Bus, bytebreitem RAM, 16-Bit-Befehlen, Flags und einer mikrosequenzierten Steuereinheit.
Kurzfassung: Diese Anleitung legt vor dem Verdrahten eine vollständige Lehrarchitektur fest: einen 8-Bit-Datenpfad und Adressraum, einheitliches bytebreites RAM, 16-Bit-Befehle, die als zwei Bytes geholt werden, vier Universalregister, eine ALU und Flags, einen einzelnen gemeinsamen Bus sowie einen mikrosequenzierten Controller. Bauen und überprüfen Sie jedes Teilsystem, erzwingen Sie stets genau einen Bustreiber und führen Sie anschließend ein Programm mit fünf Befehlen aus, das
5 + 3berechnet und8im Speicher ablegt.
„Eine CPU bauen“ kann alles bedeuten, vom Verbinden fertiger Blöcke bis zum Layouten von Transistoren. Dieses Tutorial liegt zwischen diesen Extremen. Sie konstruieren einen Prozessor aus digitalen Bausteinen – Registern, Multiplexern, Decodern, einer ALU, Speicher und einem Kontrollspeicher – und behandeln zugleich die internen Gatter jedes Blocks als separat testbaren Entwurf.
Das Ziel ist nicht, einen modernen kommerziellen Kern nachzuahmen. Es geht darum, den Vertrag offenzulegen, den jede Befehlsimplementierung erfüllen muss:
- die richtigen Befehlsbytes holen;
- sie beim Decodieren bewahren;
- genau die vorgesehenen Operanden bewegen;
- die definierte Operation ausführen;
- nur den erlaubten Architekturzustand aktualisieren; und
- die richtige Adresse des nächsten Befehls wählen.
1. Die Architektur zuerst festschreiben
Viele CPU-Projekte scheitern, weil sich Speicherbreite, Befehlsbreite und PC-Inkrement mitten im Aufbau ändern. Verwenden Sie diese Spezifikation durchgängig:
| Eigenschaft | Definition der Lehr-CPU |
|---|---|
| Datenbreite | 8 Bit |
| Adressbreite | 8 Bit |
| Speicher | 256 byteadressierte Speicherstellen, gemeinsame Befehle und Daten |
| Befehlsbreite | 16 Bit, als zwei aufeinanderfolgende Bytes gespeichert |
| Byte-Reihenfolge des Befehls | Höherwertiges Byte zuerst an der Startadresse des Befehls |
| Sequentieller PC-Fortschritt | Zwei Inkremente um je ein Byte während des Holens |
| Allgemeine Register | Vier 8-Bit-Register: R0–R3 |
| Operanden-Latches | A und B, je 8 Bit |
| Instruktionsregister | 16 Bit |
| Flags | Z (Null), N (negativ), C (Übertrag), V (vorzeichenbehafteter Überlauf) |
| Verbindungsstruktur | Ein 8-Bit-Lehrbus |
| Steuerung | Mikrostep-Zähler plus Steuer-ROM |
Eine 8-Bit-Adresse wählt 256 Speicherstellen; der Speicher umfasst 256 Bytes, weil diese Architektur jede Speicherstelle ausdrücklich als ein Byte definiert. Die Startadressen der Befehle sind normalerweise gerade, da jeder Befehl zwei Bytes belegt.
Blockdiagramm
┌──────────────────────┐
│ control ROM + │
│ microstep sequencer │
└──────────┬───────────┘
│ control signals
▼
┌────┐ ┌─────┐ ┌────────────── 8-bit shared bus ───────────────┐
│ PC │──▶│ MAR │ │ │ │ │ │ │ │
└────┘ └──┬──┘ ┌▼──┐ ┌▼──┐ ┌▼──┐ ┌▼──┐ ┌▼──┐ ┌▼──┐ ┌▼───┐
│ │MDR│ │ R0│ │ R1│ │ R2│ │ R3│ │ A │ │ B │
▼ └─┬─┘ └───┘ └───┘ └───┘ └───┘ └┬──┘ └┬───┘
┌────────┐ │ └──┬───┘
│256 × 8 │ │ ┌────▼────┐
│ RAM │ │ │ 8-bit │
└────────┘ │ │ ALU │
│ └────┬────┘
└──────▶ 16-bit IR ◀────────────────────┘
│
▼
opcode / fields
Die Zeichnung ist konzeptionell. Das IR lädt zwei getrennte Bytes vom Bus, und das ALU-Ergebnis erreicht den Bus über seinen eigenen ausgewählten Ausgangspfad.
Öffnen Sie den Sequential Instruction Executor als Referenz, behandeln Sie jedoch diese schriftliche Architektur als maßgeblich für die Übung. Falls die Vorlage eine andere interne Konvention verwendet, dokumentieren Sie den Unterschied, statt beide stillschweigend zu vermischen.
2. Die Befehlsformate definieren
Die eigene ISA verwendet zwei 16-Bit-Formate.
Registerformat
15 12 11 8 7 4 3 0
┌───────────────┬────────────────┬────────────────┬────────────────┐
│ opcode [3:0] │ RA [3:0] │ RB [3:0] │ RD [3:0] │
└───────────────┴────────────────┴────────────────┴────────────────┘
Immediate-/Adressformat
15 12 11 8 7 0
┌───────────────┬────────────────┬─────────────────────────────────┐
│ opcode [3:0] │ RD [3:0] │ immediate / address [7:0] │
└───────────────┴────────────────┴─────────────────────────────────┘
In dieser Maschine mit vier Registern sind nur die Registercodes 0–3 zulässig. Der Decoder muss die Werte 4–15 zurückweisen oder sicher abfangen, statt versehentlich eine Steuerleitung auszuwählen.
| Opcode | Mnemonik | Format | Definierte Wirkung |
|---|---|---|---|
0 | NOP | – | Keine Änderung des Architekturzustands außer dem bereits erhöhten PC |
1 | LDI | Immediate | RD ← imm8 |
2 | LD | Immediate | RD ← RAM[addr8] |
3 | ST | Immediate | RAM[addr8] ← RD |
4 | ADD | Register | RD ← RA + RB; Flags aktualisieren |
5 | SUB | Register | RD ← RA − RB; Flags aktualisieren |
6 | JMP | Immediate | PC ← addr8 |
7 | JZ | Immediate | Falls Z = 1, PC ← addr8 |
8 | HLT | – | In den angehaltenen Controllerzustand wechseln |
Alle anderen Opcodes sind ungültig. Fügen Sie einen ausdrücklichen Pfad illegal_instruction hinzu oder ordnen Sie sie während des Debuggens einer sicheren Trap/einem sicheren Halt zu.
3. Register ohne Takt-Gating aufbauen
Ein 8-Bit-Register besteht aus acht flankengesteuerten D-Flipflops mit gemeinsamem Takt und einem logischen Lade-Enable.
Für jedes Bit:
Implementieren Sie diese Gleichung mit einem 2:1-Multiplexer vor dem D-Eingang oder verwenden Sie die dedizierte Clock-Enable-Funktion eines Bauteils. Halten Sie jedes Zustandslement am selben globalen Takt.
Erzeugen Sie keinen lokalen Takt, indem Sie den globalen Takt mit load verunden. Unkontrolliertes Clock-Gating kann in Hardware Skew und Glitches verursachen. Integrierte Clock-Gating-Zellen und FPGA-Taktsteuerungsressourcen sind getrennte, timingbewusste Mechanismen.
Jedes mit dem Bus verbundene Register benötigt:
- einen 8-Bit-Eingang vom Bus;
- einen gespeicherten 8-Bit-Ausgang;
- ein Steuersignal
load_x; und - einen Pfad
oe_x, der den Lehrbus treiben darf.
Der PC benötigt zusätzlich einen Inkrementpfad und einen expliziten Ladepfad. Das IR benötigt unabhängige Ladevorgänge für High- und Low-Byte. MAR hält eine Speicheradresse; MDR erfasst oder liefert ein Speicher-Datenbyte.
Ein Register prüfen, bevor Sie es vervielfältigen
Testen Sie diese Fälle:
load = 0: Mehrere Takte lassen Q unverändert.load = 1: Q übernimmt den Bus an der aktiven Flanke.- Daten ändern sich fern von der Flanke: Q ändert sich erst an der nächsten aktivierten Flanke.
- Reset, falls vorhanden: Q erreicht den dokumentierten Zustand.
- Output Enable aus: Das Register treibt den Bus nicht.
Ein digitaler Simulator kann die logische Abfolge dieses Modells überprüfen. Er bildet keine analoge Metastabilität nach und beweist kein physisches Setup- und Hold-Timing.
4. Die ALU aufbauen und jedes Flag definieren
Verwenden Sie A und B als stabile Operanden-Latches. Die ALU ist kombinatorisch: Sie darf keinen verborgenen Architekturzustand enthalten.
alu_op | Operation | Ergebnis |
|---|---|---|
000 | ADD | A + B |
001 | SUB | A − B |
010 | AND | A & B |
011 | OR | A | B |
100 | XOR | A ^ B |
101 | NOT | ~A |
110 | SHL | A << 1, mit Nullen auffüllen |
111 | SHR | logisches A >> 1, mit Nullen auffüllen |
Der ALU-Leitfaden erläutert die Rechenpfade und den Ausgangsmultiplexer ausführlich. Der Kern des arithmetischen Entwurfs besteht aus:
- einer Kette aus acht Volladdierern;
- einer Subtraktion, umgesetzt als
A + (~B) + 1; - parallelen bitweisen Gattern;
- fest verdrahteten Ein-Bit-Shiftern; und
- einem durch
alu_opausgewählten Ausgangsmultiplexer.
Flag-Definitionen
Definieren Sie Flags als Teil der ISA, einschließlich der Frage, was Logik- und Shift-Befehle mit C und V tun.
- Z: 1, wenn jedes Ergebnisbit null ist.
- N: Ergebnisbit 7, das nur bei vorzeichenbehafteten Operationen als Vorzeichenbit interpretiert wird.
- C bei ADD: Übertrag aus Bit 7.
- C bei SUB: Wählen und dokumentieren Sie entweder „kein Borrow“ oder „Borrow“. Diese Anleitung verwendet kein Borrow, passend zur Carry-out-Konvention des Addierers.
- V bei ADD: Die Operanden haben dasselbe Vorzeichen und das Ergebnis das entgegengesetzte Vorzeichen.
- V bei SUB: Die Operanden haben unterschiedliche Vorzeichen und das Ergebnisvorzeichen unterscheidet sich von A.
Die äquivalente XOR-Formel aus Carry-in und Carry-out gilt für Zweierkomplement-Addition und -Subtraktion, wenn der Subtraktionspfad mit invertiertem B-Operand und Carry-in umgesetzt wird. Unter CPU-Flags finden Sie durchgerechnete Fälle.
Diese Lehr-ISA aktualisiert Z, N, C und V bei ADD und SUB. Wählen Sie für Logik- und Shift-Operationen eine dokumentierte Regel – C/V beibehalten oder neue Bedeutungen festlegen – bevor Sie Mikrocode schreiben. „Was immer die Leitungen gerade enthalten“ ist keine gültige Regel.
ALU-Prüftabelle
Testen Sie mindestens:
| Fall | Erwarteter Schwerpunkt |
|---|---|
0x00 + 0x00 | Z |
0xFF + 0x01 | vorzeichenloser Übertrag und Null |
0x7F + 0x01 | vorzeichenbehafteter Überlauf und N |
0x80 + 0x80 | Übertrag plus vorzeichenbehafteter Überlauf |
0x00 − 0x01 | Borrow-Konvention und N |
0x80 − 0x01 | vorzeichenbehafteter Überlauf |
| UND-/ODER-/XOR-Identitäten | bitweise Rechenpfade |
Shifts von 0x81 | Richtung, Auffüllbit, Regel für herausgeschobenes Bit |
5. Den gemeinsamen Bus aufbauen
Der Lehrbus besteht aus acht Leitungen mit mehreren möglichen Quellen. Es gilt eine zentrale Invariante:
Zu den möglichen Treibern gehören PC, MDR, R0–R3, A, B, ein IR-Byte und das ALU-Ergebnis. Die genaue Liste ist länger als „die Anzahl der Register“, zählen Sie daher jede Quelle in der Steuerspezifikation auf.
In DigiSim können Tri-State-Puffer einen gemeinsamen Bus modellieren:
- aktivieren Sie während einer Übertragung genau eine Quelle;
- setzen Sie ein oder mehrere Lade-Steuersignale für die nächste aktive Flanke; und
- erfassen Sie den Bus niemals, wenn keine Quelle ihn treibt.
Buskonflikte sind Entwurfsfehler. Ein physischer Ausgangskonflikt kann falsche Spannung und übermäßigen Strom verursachen; die Folge hängt von Technologie und Dauer ab, daher ist „der Chip brennt immer durch“ keine hilfreiche Regel.
Moderne FPGA-Strukturen implementieren interne gemeinsame Busse im Allgemeinen als Multiplexer statt als echte interne Tri-State-Verdrahtung. Auch ASIC-Stile unterscheiden sich. Der Tri-State-Bus bleibt ein anschauliches Lehrmodell für Besitz und Übertragung.
Bus-Arbitrierungstest
Legen Sie bekannte Werte in R0 und R1 ab:
- R0 =
0xAA - R1 =
0x55
Überprüfen Sie R0 allein, R1 allein, keinen Treiber und beide Treiber. Die letzten beiden Fälle müssen als ungültige Controllerzustände behandelt werden. Fügen Sie anschließend eine Assertion oder sichtbare Anzeige hinzu, damit spätere Mikrocodefehler sofort erkannt werden.
6. Bytebreiten Speicher anschließen
Verwenden Sie die RAM-Komponente des Simulators als architektonisches Speichermodell. Behaupten Sie nicht, dass physisches RAM buchstäblich ein Array aus D-Latches ist: SRAM, DRAM, Block-RAM und synthetisierte Registerarrays verwenden unterschiedliche Speicherzellen und Timings.
Die Schnittstelle dieser CPU lautet:
ADDR[7:0], getrieben von MAR;DATA[7:0], übertragen über MDR oder die gesteuerte Busschnittstelle;mem_read;mem_write; und- optional
ready, falls das Modell variable Latenz unterstützt.
Diese Anleitung nimmt an, dass ein Lesevorgang in einem eigenen Mikrostep angefordert und erfasst werden kann. Ist der gewählte Speicher synchron oder hat sichtbare Latenz, fügen Sie einen Wartezustand ein und erfassen Daten erst, wenn sie gültig sind.
Befehlsspeicher und Daten teilen sich dieselben 256 Bytes. Ein Harvard-Entwurf mit getrennten Speichern ist ebenfalls gültig, wäre jedoch eine andere Architektur mit einem anderen Fetch-Ablauf.
Zur Unterscheidung zwischen beschreibbaren und nichtflüchtigen/konstanten Speicherabstraktionen siehe RAM vs. ROM.
7. Den mikrosequenzierten Controller aufbauen
Der Controller wandelt Opcode, Mikrostep, Flags und Maschinenzustand um in:
- Bus-Output-Enables;
- Register-Lade-Enables;
- ALU-Operation;
- Speicher-Lese-/Schreibsteuerungen;
- PC-Inkrement-/Ladesteuerungen;
- Flag-Laden;
- Laden des IR-High-/Low-Bytes; und
- Steuerung des nächsten Mikrosteps oder des Befehlsendes.
Eine Implementierung verwendet ein Steuer-ROM:
control address = {opcode, microstep}
control word = {oe signals, load signals, alu_op, memory controls, next control}
Flags können ausgewählte Aktionen qualifizieren – beispielsweise load_pc = microcode_load_pc AND Z für JZ – oder an der Adresse des Steuerspeichers beteiligt sein. Explizite Logik für den Folgezustand ist häufig klarer, als anzunehmen, dass der Mikrostep-Zähler immer inkrementiert.
Dies ist ein pädagogischer mikroprogrammierter Controller. Reale Prozessoren verwenden viele Kombinationen aus kombinatorischem Decode, programmierbaren Steuerspeichern, Zustandsautomaten und Sequenzern. Verwenden Sie das Label RISC/CISC nicht als Abkürzung für die Implementierung.
Sichere Standardwerte
Jeder unbenutzte Steuer-ROM-Eintrag sollte:
- alle Bustreiber deaktivieren;
- Speicherschreibvorgänge deaktivieren;
- Schreibvorgänge in Architekturregister deaktivieren; und
- einen definierten Pfad für ungültige Befehle oder Halt einschlagen.
Ein nicht initialisiertes Steuerwort darf niemals zu „beliebige Daten an beliebige Speicheradresse schreiben“ werden.
8. Zwei Befehlsbytes konsistent holen
Da RAM und Datenpfad acht Bits breit sind, jeder Befehl jedoch 16 Bits umfasst, benötigt das Holen zwei Byte-Lesevorgänge. Das High-Byte wird definitionsgemäß zuerst gespeichert.
Unter der Annahme, dass ein Mikrostep für den gewählten RAM-Lesevorgang ausreicht:
| Schritt | Registertransfer | Wichtige Steuerungen |
|---|---|---|
| F0 | MAR ← PC | oe_pc, load_mar |
| F1 | MDR ← RAM[MAR]; PC ← PC + 1 | mem_read, load_mdr, inc_pc |
| F2 | IR[15:8] ← MDR | oe_mdr, load_ir_hi |
| F3 | MAR ← PC | oe_pc, load_mar |
| F4 | MDR ← RAM[MAR]; PC ← PC + 1 | mem_read, load_mdr, inc_pc |
| F5 | IR[7:0] ← MDR | oe_mdr, load_ir_lo |
Nach F5 enthält das IR einen vollständigen Befehl, und der PC zeigt bereits auf den folgenden Befehl. Das Decode wählt die Ausführungssequenz.
Benötigt das RAM eine Wartezeit von Adresse zu Daten, teilen Sie F1 und F4 in Anforderungs-, Warte- und Erfassungsschritte auf. Verbergen Sie niemals einen 16-Bit-Fetch in einer bytebreiten Übertragung.
9. Ausführungs-Mikrooperationen definieren
ADD RD, RA, RB
| Schritt | Übertragung |
|---|---|
| E0 | A ← R[RA] |
| E1 | B ← R[RB] |
| E2 | R[RD] ← A + B; FLAGS ← ALU flags |
| E3 | Befehl beenden; zu F0 zurückkehren |
RA, RB und RD wählen über decodierte Enables eines von R0–R3. Ungültige Registercodes müssen den Pfad für ungültige Befehle einschlagen.
LDI RD, imm8
| Schritt | Übertragung |
|---|---|
| E0 | R[RD] ← IR[7:0] |
| E1 | Befehl beenden |
LD RD, addr8
| Schritt | Übertragung |
|---|---|
| E0 | MAR ← IR[7:0] |
| E1 | MDR ← RAM[MAR] |
| E2 | R[RD] ← MDR |
| E3 | Befehl beenden |
ST RD, addr8
| Schritt | Übertragung |
|---|---|
| E0 | MAR ← IR[7:0] |
| E1 | MDR ← R[RD] |
| E2 | RAM[MAR] ← MDR |
| E3 | Befehl beenden |
JMP und JZ
- JMP:
PC ← IR[7:0], dann beenden. - JZ: PC nur laden, wenn Z gleich 1 ist, dann unabhängig davon beenden.
HLT
Wechseln Sie in einen stabilen Controllerzustand, der keine Schreibvorgänge ausgibt. Einen manuell angesteuerten Simulator-Takt anzuhalten ist praktisch, doch der Architekturzustand muss klar definiert bleiben, selbst wenn weitere Taktflanken eintreffen.
10. Das Testprogramm von Hand assemblieren und laden
Das Programm lädt 5 und 3, addiert sie in R2, speichert das Ergebnis an Adresse 0x10 und hält an.
| Startadresse | Befehl | 16-Bit-Wort | Bytes im Speicher |
|---|---|---|---|
0x00 | LDI R0, #5 | 0x1005 | 0x10 0x05 |
0x02 | LDI R1, #3 | 0x1103 | 0x11 0x03 |
0x04 | ADD R2, R0, R1 | 0x4012 | 0x40 0x12 |
0x06 | ST R2, 0x10 | 0x3210 | 0x32 0x10 |
0x08 | HLT | 0x8000 | 0x80 0x00 |
Laden Sie diese zehn Bytes an die Adressen 0x00 bis 0x09, dann setzen Sie zurück:
- PC =
0x00 - Controller-Mikrostep = F0
- angehalten = 0
- alle Bustreiber deaktiviert, außer wenn das Steuerwort einen auswählt
Führen Sie den ersten Fetch im Einzelschritt aus und bestätigen Sie:
- nach F2 beträgt das IR-High-Byte
0x10; - nach F5 lautet das IR
0x1005; - der PC ist
0x02; - LDI legt
0x05in R0 ab; und - kein anderes Register und keine andere Speicherstelle ändert sich.
Beim Halt:
- R0 =
0x05 - R1 =
0x03 - R2 =
0x08 - RAM[
0x10] =0x08 - PC =
0x0A
Diese Endwerte sind notwendig, aber nicht hinreichend. Eine fehlerhafte CPU könnte eine andere Speicherstelle beschädigen und sie dennoch erzeugen.
11. Invarianten prüfen, nicht nur das Endergebnis
Fügen Sie Prüfungen hinzu für:
- nie mehr als ein Bus-Output-Enable gleichzeitig;
- Speicherschreiben nur während des ST-Schreibschritts;
- IR-Bytes nur während F2 und F5 geladen;
- PC bei jedem normalen Fetch genau zweimal inkrementiert;
- Flags nur von den Befehlen geschrieben, die sie laut Definition aktualisieren;
- ein ungültiger Opcode oder Registercode verursacht keinen unbeabsichtigten Schreibvorgang;
- der angehaltene Zustand erzeugt keine Architektur-Nebeneffekte; und
- Reset erreicht einen bekannten Controllerzustand.
Zeichnen Sie für jeden Befehl einen Trace auf aus:
clock, microstep, PC, IR, bus owner, bus value,
register loads, memory read/write, ALU op, flags
Wenn ein Test fehlschlägt, suchen Sie den ersten Zyklus, der vom erwarteten Trace abweicht. Vom falschen Endwert aus zu debuggen führt Sie gewöhnlich mehrere Schritte zu spät.
Der Leitfaden zum Debuggen mit dem Oszilloskop erklärt, wie Sie modellierte Wellenformen untersuchen, ohne sie mit physischem Timing-Sign-off zu verwechseln.
12. Häufige Fehlermodi
| Symptom | Wahrscheinliche Ursache | Zuerst prüfen |
|---|---|---|
| IR enthält vertauschte Bytes | Die Byte-Reihenfolge des Befehls unterscheidet sich zwischen Lader und Fetch | Adressen PC und PC+1 |
| PC erhöht sich um vier | Das Inkrement geschieht zweimal je Byte oder Breitenannahmen wurden vermischt | F0–F5-Trace |
| Bus ist umkämpft | Zwei Output-Enables teilen sich ein Steuerbit | Decodiertes Steuerwort |
| Bus wird undriven erfasst | Quell-Enable fehlt | Assertion zum Busbesitzer |
| ADD schreibt in das falsche Register | RD-Feld-Decodierung oder Registercode-Reihenfolge | IR[3:0] und Ladeleitungen |
| Store beschädigt Befehlsspeicher | Adresse/Immediate oder Timing von mem_write | MAR und ST E2 |
| Branch verwendet veraltetes Z | Flags wurden nicht geschrieben oder JZ tastet den falschen Zustand ab | ADD/SUB E2 und JZ |
| Controller kehrt nie zum Fetch zurück | End-/Folgezustandseintrag fehlt | Mikrostep-Übergang |
| Ungültiger Opcode führt eine Operation aus | Unbenutztes Steuer-ROM wurde nicht sicher initialisiert | Standard-Steuerwort |
13. Was diese CPU lehrt – und was nicht
Dieser Entwurf lehrt Registertransfer, Befehlsencodierung, Busbesitz, ALU-Flags, Speichersequenzierung und Controllerzustand.
Er modelliert nicht:
- RAM oder Logik auf Transistorebene;
- Cache-Hierarchie oder virtuellen Speicher;
- spekulative oder Out-of-Order-Ausführung;
- analoges Taktverhalten oder Metastabilität;
- physische Ausbreitungs-, Routing-, Leistungs- oder Temperaturgrenzen; oder
- eine produktive Sicherheits- oder Ausnahme-Architektur.
Sein einzelner gemeinsamer Bus ist absichtlich leicht zu beobachten, keine Behauptung über die interne Topologie einer modernen CPU.
Erweiterungen in einer sicheren Reihenfolge
- Automatisierte Befehlstests hinzufügen. Überprüfen Sie jeden Opcode und jede ungültige Codierung, bevor Sie Funktionen ergänzen.
- UND, ODER, XOR und Schiebeoperationen hinzufügen. Definieren Sie zunächst das Verhalten der Statusflags und fügen Sie anschließend die Steuersequenzen hinzu.
- Einen bedingten Branch mit direktem Vergleich hinzufügen. Das zeigt den Unterschied zwischen flagbasierten und Compare-and-Branch-ISAs.
- Einen Stack-Pointer und Call/Return hinzufügen. Legen Sie Stack-Wachstum, Byte-Reihenfolge und Überlaufverhalten fest.
- Einen Interrupt-Zustandsautomaten hinzufügen. Sichern Sie Rückkehradresse und Flags vor dem Laden eines Vektors; definieren Sie Priorität und Maskierung.
- Befehls- und Datenspeicher trennen. Vergleichen Sie den neuen Fetch-Ablauf mit dem Entwurf mit gemeinsamem Speicher.
- Erst pipelinen, nachdem die Mehrzyklus-Referenz besteht. Definieren Sie dann Stage-Gültigkeit, Stalls, Forwarding, Flushes und Ausnahmen.
Nutzen Sie die Fetch-Decode-Execute-Vertiefung und den Leitfaden zu Instruktionsregister/Decode, bevor Sie die Pipeline-Erweiterung versuchen.
Ausprobieren
Nutzen Sie den Sequential Instruction Executor zur Orientierung, das 8-Bit-ALU-System zur separaten Überprüfung der Arithmetik und das CPU-Flags-Register zum Testen des Statusverhaltens. Halten Sie eine schriftliche Architektur und eine Mikrooperationstabelle neben dem Schaltplan bereit.
Der wichtige Meilenstein ist nicht, die 8 einmal zu sehen. Er besteht darin, erklären zu können, warum jede Zustandsänderung autorisiert war, sie in einem Trace zu reproduzieren und zu beweisen, dass sich kein anderer Zustand geändert hat.



