← Zurück zum BlogArithmetisch-logische Einheit (ALU)

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.

DennyDenny
8 Min. Lesezeit
Chalkboard feature illustration for “Wie eine ALU funktioniert: Arithmetisch-logische Einheit aus Gattern”

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:

PortBreiteRichtungBedeutung
A4Eingangerster Operand
B4Eingangzweiter Operand
OP3EingangOperationsauswahl
Y4Ausgangausgewähltes Ergebnis
C1AusgangCarry bei ADD; Borrow bei SUB
Z1Ausgang1, wenn Y == 0000
N1AusgangY[3]
V1Ausgangvorzeichenbehafteter Overflow bei ADD oder SUB

Eine mögliche Operationszuordnung lautet:

OPFunktionDefinition
000ADDA+BA+B
001SUBA−BA-B
010ANDA∧BA\land B bitweise
011ORA∨BA\lor B bitweise
100XORA⊕BA\oplus B bitweise
101NOT AA‾\overline A
110logische LinksverschiebungNull tritt in Bit 0 ein
111logische RechtsverschiebungNull 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 ii:

Si=Ai⊕Bi′⊕ciS_i=A_i\oplus B'_i\oplus c_i ci+1=AiBi′+Aici+Bi′cic_{i+1}=A_iB'_i+A_ic_i+B'_ic_i

Verwenden Sie ein Steuerbit SUB, um B und den anfänglichen Übertrag zu transformieren:

Bi′=Bi⊕SUBB'_i=B_i\oplus SUB c0=SUBc_0=SUB

Bei SUB=0 berechnet das Netzwerk A+BA+B. Bei SUB=1 berechnet es:

A+B‾+1=A−B(mod24)A+\overline B+1=A-B\pmod {2^4}

Der finale Carry-Out des Addierers hat unterschiedliche Bedeutungen:

  • nach ADD bedeutet c4=1c_4=1, dass die vorzeichenlose Summe 15 überschritten hat;
  • nach SUB bedeutet c4=1c_4=1, 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:

CSUB=c4‾C_{\text{SUB}}=\overline{c_4}

Damit bedeutet C=1 nach einer Subtraktion, dass bei vorzeichenlosen Operanden ein Borrow aufgetreten ist (A<BA<B). Die Ergebnisbits stammen weiterhin aus derselben Modulo-242^4-Summe; nur die Polarität des Flags ändert sich.

Overflow ist nicht Carry

Vorzeichenbehafteter Overflow betrifft den Zweierkomplementbereich von −8-8 bis +7+7, während Carry den vorzeichenlosen Bereich von 0 bis 15 betrifft.

Für die Addition:

Vadd=A3⊕B3‾∧(A3⊕Y3)V_{\text{add}} = \overline{A_3\oplus B_3}\land(A_3\oplus Y_3)

Für die Subtraktion:

Vsub=(A3⊕B3)∧(A3⊕Y3)V_{\text{sub}} = (A_3\oplus B_3)\land(A_3\oplus Y_3)

Äquivalent gilt für diesen Addierer/Subtrahierer V=c3⊕c4V=c_3\oplus c_4. 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:

ANDi=AiBiAND_i=A_iB_i ORi=Ai+BiOR_i=A_i+B_i XORi=Ai⊕BiXOR_i=A_i\oplus B_i NOTi=Ai‾NOT_i=\overline{A_i}

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:

tALU,max≈max⁡(tcandidate functions)+tresult select+troutingt_{\text{ALU,max}} \approx \max(t_{\text{candidate functions}}) +t_{\text{result select}} +t_{\text{routing}}

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:

Z=Y3∨Y2∨Y1∨Y0‾Z=\overline{Y_3\lor Y_2\lor Y_1\lor Y_0} N=Y3N=Y_3

C und V sind operationsspezifisch. Eine stimmige Richtlinie für diese Lehr-ALU lautet:

OperationCV
ADDfinaler Carry-OutAdditions-Overflow
SUBBorrow (A<BA<B), das Komplement des finalen Carry-OutSubtraktions-Overflow
SHLaus dem MSB herausgeschobenes Bit0
SHRaus dem LSB herausgeschobenes Bit0
AND/OR/XOR/NOT00

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 N⊕VN\oplus V, 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:

  1. Quellregister stellen A und B bereit;
  2. die Steuereinheit wählt OP;
  3. die ALU und die Logik zur Flag-Erzeugung stabilisieren sich;
  4. ein Zielregister übernimmt Y an der aktiven Taktflanke;
  5. 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:

  1. Bauen Sie einen vierstufigen Addierer/Subtrahierer mit B XOR SUB und c0=SUB auf.
  2. Fügen Sie parallele Funktionspfade für UND, ODER, XOR und NICHT hinzu.
  3. Verdrahten Sie die logischen Schiebeoperationen und führen Sie die herausgeschobenen Bits weiter, falls C sie auswertet.
  4. Wählen Sie das Ergebnis mit einem 8-zu-1-Multiplexer mit 4-Bit-Datenpfad aus.
  5. Erzeugen Sie Z aus dem ausgewählten Ergebnis und N aus dessen MSB.
  6. Wählen Sie C und V gemäß der Operationstabelle aus.
  7. 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.

Referenzen

Machen Sie aus der Idee eine funktionierende Schaltung.