Wie eine ALU funktioniert: Arithmetisch-logische Einheit aus Gattern
Bauen Sie eine kleine ALU aus Addierer, bitweiser Logik, Schiebewerk und Ergebnis-Multiplexer auf und leiten Sie anschließend die Statusausgänge Carry, Zero, Negative und Overflow her.
Kurzfassung: Eine kleine ALU ist ein kombinatorischer Datenpfad: Kandidaten für arithmetische Funktionen, Logikfunktionen und Schiebeoperationen arbeiten auf denselben Eingabewörtern, und ein Multiplexer wählt das sichtbare Ergebnis. Der Entwurf ist erst vollständig, wenn Operationskodierungen, Carry-/Borrow-Semantik, Overflow-Verhalten und die Richtlinie zum Schreiben von Flags ausdrücklich festgelegt sind.
Eine arithmetisch-logische Einheit ist der Ort, an dem ein Prozessor Daten umformt. ADD und SUB benötigen einen Addierer; AND, OR und XOR benötigen parallele Gatterbahnen; Verschiebungen benötigen Verdrahtung oder ein Schiebewerk; und ein Ergebnis-Multiplexer wählt, welcher Kandidat das Ziel erreicht.
Dieses Blockdiagramm ist einfach genug, um es mit vier oder acht Bit aufzubauen, und dennoch reich genug, um mehrere echte Konstruktionsentscheidungen offenzulegen:
- Meldet die Subtraktion Borrow oder Not-Borrow?
- Füllt eine Rechtsverschiebung mit null auf oder kopiert sie das Vorzeichenbit?
- Für welche Operationen ist der Overflow-Ausgang definiert?
- Speichert die ALU selbst Flags, oder hält ein separates Register sie fest?
- Wird nach paralleler Berechnung eine große Funktion ausgewählt, oder wird Logik geteilt, um Fläche zu sparen?
Dieser Leitfaden entwickelt eine stimmige 4-Bit-Lehr-ALU und kennzeichnet die Stellen, an denen eine andere Architektur anders entscheiden kann.
Mit einem Schnittstellenvertrag beginnen
Nehmen Sie zunächst vorzeichenlose Bitvektoren an, sofern eine Operation nicht ausdrücklich eine vorzeichenbehaftete Interpretation erfordert:
| Port | Breite | Richtung | Bedeutung |
|---|---|---|---|
A | 4 | Eingang | erster Operand |
B | 4 | Eingang | zweiter Operand |
OP | 3 | Eingang | Operationsauswahl |
Y | 4 | Ausgang | ausgewähltes Ergebnis |
C | 1 | Ausgang | Carry bei ADD; Borrow bei SUB |
Z | 1 | Ausgang | 1, wenn Y == 0000 |
N | 1 | Ausgang | Y[3] |
V | 1 | Ausgang | vorzeichenbehafteter Overflow bei ADD oder SUB |
Eine mögliche Operationszuordnung lautet:
OP | Funktion | Definition |
|---|---|---|
000 | ADD | |
001 | SUB | |
010 | AND | bitweise |
011 | OR | bitweise |
100 | XOR | bitweise |
101 | NOT A | |
110 | logische Linksverschiebung | Null tritt in Bit 0 ein |
111 | logische Rechtsverschiebung | Null tritt in Bit 3 ein |
Dies ist eine Lehrspezifikation, keine Standardkodierung. Reale Befehlssätze können Verschiebungen, Multiplikation, Adressberechnung und Vergleiche auf andere Ausführungseinheiten verteilen. Sie können auch mehrere ALUs mit unterschiedlichen Fähigkeiten besitzen.
Die hier beschriebene ALU besitzt keinen internen Zustand. Ihre Ausgänge stabilisieren sich nach Eingabeänderungen und der Ausbreitung durch das kombinatorische Netzwerk. Operandenregister, Zielregister und das Flags-Register sind separate sequentielle Elemente.
Block 1: Ein Addierer für Addition und Subtraktion
Ein Ripple-Carry-Addierer verbindet vier Volladdierer-Stufen. Für Bit :
Verwenden Sie ein Steuerbit SUB, um B und den anfänglichen Übertrag zu transformieren:
Bei SUB=0 berechnet das Netzwerk . Bei SUB=1 berechnet es:
Der finale Carry-Out des Addierers hat unterschiedliche Bedeutungen:
- nach ADD bedeutet , dass die vorzeichenlose Summe 15 überschritten hat;
- nach SUB bedeutet , dass kein vorzeichenloses Borrow erforderlich war.
Die DigiSim-ALU gibt nach ADD den unveränderten Carry-Out als C aus, nach SUB jedoch dessen Komplement:
Damit bedeutet C=1 nach einer Subtraktion, dass bei vorzeichenlosen Operanden ein Borrow aufgetreten ist (). Die Ergebnisbits stammen weiterhin aus derselben Modulo--Summe; nur die Polarität des Flags ändert sich.
Overflow ist nicht Carry
Vorzeichenbehafteter Overflow betrifft den Zweierkomplementbereich von bis , während Carry den vorzeichenlosen Bereich von 0 bis 15 betrifft.
Für die Addition:
Für die Subtraktion:
Äquivalent gilt für diesen Addierer/Subtrahierer . C und V getrennt zu halten, ermöglicht es denselben vier Ergebnisbits, vorzeichenlose und vorzeichenbehaftete Interpretationen korrekt zu unterstützen.
Block 2: Parallele bitweise Logik
Jede Bitbahn berechnet ihre Logik unabhängig:
In einer konzeptionellen Implementierung existieren alle vier Kandidatenbusse parallel. Ein Synthesewerkzeug kann Terme gemeinsam nutzen, Funktionen auf Lookup-Tabellen abbilden oder zusammengesetzte Standardzellen wählen. „Ein Gatter pro Bit“ beschreibt die boolesche Struktur, keine garantierte Transistorzahl oder physische Verzögerung.
Bitweise Funktionen vermeiden eine wortweite Carry-Abhängigkeit, doch ihr ausgewähltes Ergebnis durchläuft weiterhin Gatter, Verdrahtung und den Ausgangsmultiplexer. Sie sind nicht augenblicklich.
Block 3: Verschiebungen
Eine feste logische Verschiebung um eine Position lässt sich als Verdrahtung ausdrücken:
SHL(A): Y3=A2, Y2=A1, Y1=A0, Y0=0
SHR(A): Y3=0, Y2=A3, Y1=A2, Y0=A1
Das herausgeschobene Bit kann als Carry-Kandidat erhalten bleiben, wenn die ISA dies festlegt:
SHL carry candidate = A3
SHR carry candidate = A0
Eine arithmetische Rechtsverschiebung unterscheidet sich nur am oberen Ende: Sie kopiert A3 nach Y3, sodass das Vorzeichen erweitert wird. Eine Verschiebung um variable Distanzen benötigt ein wählbares Verdrahtungsnetzwerk wie einen Barrel-Shifter; eine feste Verschiebung um eins nicht.
Block 4: Der Ergebnis-Multiplexer
Der Ausgangsmultiplexer gibt OP seine Bedeutung. Konzeptionell:
case OP
000: Y = arithmetic_sum
001: Y = arithmetic_difference
010: Y = bitwise_and
011: Y = bitwise_or
100: Y = bitwise_xor
101: Y = bitwise_not_a
110: Y = shift_left
111: Y = shift_right
Bei vier Bit lässt sich dies als ein 8-zu-1-Multiplexer für jedes Ergebnisbit zeichnen. In programmierbarer Logik kann es auf Lookup-Tabellen und Verdrahtungsressourcen abgebildet werden. In einem ASIC kann es zu Mux-Zellen, AOI/OAI-Strukturen oder einem anderen durch die Synthese gewählten faktorisierten Netzwerk werden.
Die Ergebnisauswahl ist Teil des kritischen Timing-Pfads:
Dieser Ausdruck ist eine Entwurfsabschätzung, keine Signoff-Gleichung. Das physische Timing hängt von Zellen, Fan-out, Verdrahtung, Spannung, Temperatur und Implementierung ab.
Ergebnisflags
Der ausgewählte Y-Wert erzeugt zwei operationsunabhängige Kandidaten:
C und V sind operationsspezifisch. Eine stimmige Richtlinie für diese Lehr-ALU lautet:
| Operation | C | V |
|---|---|---|
| ADD | finaler Carry-Out | Additions-Overflow |
| SUB | Borrow (), das Komplement des finalen Carry-Out | Subtraktions-Overflow |
| SHL | aus dem MSB herausgeschobenes Bit | 0 |
| SHR | aus dem LSB herausgeschobenes Bit | 0 |
| AND/OR/XOR/NOT | 0 | 0 |
Ein anderer Entwurf könnte C und V bei logischen Operationen bewahren, statt sie zu löschen. Das ist eine Entscheidung des Befehlssatzes und der Steuerrichtlinie. Die kombinatorische ALU kann Kandidatensignale bereitstellen, während ein getaktetes Flags-Register entscheidet, ob gespeicherte Bits geladen, bewahrt oder selektiv aktualisiert werden.
Das Vorzeichenflag N entspricht dem MSB des Ergebnisses. Nach einer Subtraktion ist N allein kein korrekter Test für einen vorzeichenbehafteten Kleiner-als-Vergleich: Verwenden Sie , um einen vorzeichenbehafteten Überlauf zu berücksichtigen.
Durchgerechnete 4-Bit-Fälle
6 - 3
A = 0110
B = 0011
~B = 1100
A + ~B+1 = 1 0011
Das gespeicherte Ergebnis ist 0011 (3). Der unveränderte Carry-Out ist 1; es trat also kein Borrow auf und der als Borrow kodierte C-Ausgang von DigiSim ist 0:
Y=0011, Z=0, C=0, N=0, V=0
3 - 6
A = 0011
B = 0110
A + ~B+1 = 0 1101
1101 ist vorzeichenlos 13 oder vorzeichenbehaftet -3. Der unveränderte Carry-Out ist 0; daher trat bei der vorzeichenlosen Subtraktion ein Borrow auf und C ist 1:
Y=1101, Z=0, C=1, N=1, V=0
7 + 1
0111 + 0001 = 1000
Es gibt keinen vorzeichenlosen Carry, aber +8 passt nicht in ein vorzeichenbehaftetes 4-Bit-Zweierkomplement:
Y=1000, Z=0, C=0, N=1, V=1
15 + 1
1111 + 0001 = 1 0000
Das vorzeichenlose Ergebnis läuft über und erzeugt einen Carry. Als vorzeichenbehaftete Arithmetik ist -1 + 1 = 0 gültig:
Y=0000, Z=1, C=1, N=0, V=0
Diese letzten beiden Vektoren beweisen, dass C und V keine Synonyme sind.
Wo die ALU in einer CPU sitzt
Ein kleiner Datenpfad mit einem einzigen Taktzyklus könnte diese Folge ausführen:
- Quellregister stellen A und B bereit;
- die Steuereinheit wählt
OP; - die ALU und die Logik zur Flag-Erzeugung stabilisieren sich;
- ein Zielregister übernimmt Y an der aktiven Taktflanke;
- wenn aktiviert, übernimmt das Flags-Register die ausgewählten Statusbits.
Die maximale Taktfrequenz hängt vom längsten vollständigen Register-zu-Register-Pfad ab, nicht allein von der ALU. Dieser Pfad kann die Clock-to-Q-Verzögerung eines Registers, Operandenauswahl, ALU-Logik, Ergebnisverdrahtung, Setup-Zeit des Ziels, Taktunsicherheit und Skew umfassen. Die ALU kann kritisch sein, aber Cache-Zugriff, Bypass-Netzwerke, Decodierung oder andere Logik können in einer anderen Mikroarchitektur dominieren.
Einen Addierer zu optimieren verbessert die Systemfrequenz nicht automatisch eins zu eins. Es hilft nur, wenn dieser Pfad nach Platzierung und Verdrahtung begrenzend ist und die gewonnene Reserve nicht an anderer Stelle verbraucht wird. Siehe Ausbreitungsverzögerung und Clock Skew und seine Auswirkung auf Timing für den vollständigen Timing-Kontext.
Der 74181 als historische Referenz
Die 4-Bit-Familie 74181 ist ein nützliches Beispiel, weil ihre Schnittstelle Funktionsauswahl, Modusauswahl, Carry-Eingang, Carry-Ausgang und Gruppen-Carry-Signale offenlegt. Sie unterstützt einen Katalog arithmetischer und logischer Funktionen und lässt sich mit Carry-Lookahead-Unterstützung zu breiteren Wörtern kombinieren.
Sie sollte nicht als Blaupause auf Transistorebene für eine moderne CPU verstanden werden. Heutige Prozessoren können mehrere spezialisierte ganzzahlige Ausführungseinheiten, getrennte Vektor- und Gleitkomma-Datenpfade, verteilte Vergleichslogik für Sprünge und implementierungsspezifische Addiererstrukturen verwenden. Beständig bleibt das Architekturmuster: Operandenwörter umformen, ein Ergebnis auswählen und präzise definierte Statusinformationen melden.
Die 4-Bit-Version bauen und verifizieren
Verwenden Sie DigiSims 8-Bit-ALU-Vorlage als umfangreichere Referenz oder bauen Sie die 4-Bit-Schnittstelle direkt auf:
- Bauen Sie einen vierstufigen Addierer/Subtrahierer mit
B XOR SUBundc0=SUBauf. - Fügen Sie parallele Funktionspfade für UND, ODER, XOR und NICHT hinzu.
- Verdrahten Sie die logischen Schiebeoperationen und führen Sie die herausgeschobenen Bits weiter, falls C sie auswertet.
- Wählen Sie das Ergebnis mit einem 8-zu-1-Multiplexer mit 4-Bit-Datenpfad aus.
- Erzeugen Sie Z aus dem ausgewählten Ergebnis und N aus dessen MSB.
- Wählen Sie C und V gemäß der Operationstabelle aus.
- Prüfen Sie A, B, OP, Y, C, Z, N und V.
Verifizieren Sie jeden Opcode zunächst mit typischen Werten und testen Sie anschließend gezielt die Grenzfälle:
- Ergebnis null;
- nur Einsen plus eins;
- größte vorzeichenbehaftete positive Zahl plus eins;
- kleinste vorzeichenbehaftete negative Zahl minus eins;
- Subtraktion sowohl mit als auch ohne Borrow;
- Links- und Rechtsverschiebungen mit gesetztem herausgeschobenem Bit;
- Flag-Verhalten beim Wechsel zwischen Operationsklassen.
Ein funktionaler Simulator kann die Wahrheitstabelle und die Steuersequenzierung nachweisen. Er beweist nicht die maximale Frequenz eines physischen Chips, analoges Metastabilitätsverhalten oder Timing über Prozess- und Umweltbereiche hinweg.
Sobald der Datenpfad funktioniert, verbinden Sie ihn mit einem getakteten CPU-Statusregister und einem Sprungdecoder. Dadurch wird das Ergebnis einer kombinatorischen Berechnung in einen persistenten Architekturzustand übernommen und kann den Programmzähler umlenken.



