Menu

Verilog Operatoren: Arithmetik, Vergleich, Logik und bedingter Operator

Die Kern-Operatoren in Verilog - Arithmetik, Vergleich, Logik und der bedingte ?: - mit den Regeln und Fallstricken rund um gemischte Breiten und Vorzeichen.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Was "Operator" in Verilog bedeutet

Operatoren nehmen signalführende Ausdrücke und produzieren neue signalführende Ausdrücke. a + b ist Hardware - der Synthesizer macht daraus einen Addierer. a == b ist Hardware - es baut einen Komparator. Nichts davon ist "Code, der läuft"; alles ist "Schaltungen, die der Operator beschreibt".

Das gesamte Operator-Menü ist klein genug, um es auswendig zu lernen. Dieses Doc deckt die arithmetischen, vergleichenden, logischen und bedingten Operatoren ab. Bitweise und Reduktion behandelt die Bit-Operatoren ohne direkte Software-Entsprechung.

Arithmetik: + - * / %

Drei Dinge wissen:

  1. Division ist Ganzzahldivision. 7/2 ist 3, nicht 3.5. Verilog hat keinen Float-Typ (gut, real, aber der ist simulation-only).
  2. Division und Modulo sind in Hardware teuer. Ein /4 ist fein (der Synthesizer macht daraus ein Rechtsshift), aber ein /n mit laufzeit-variablem n baut einen mehrtaktigen Dividierer, den du fast nie willst.
  3. Überlauf läuft um. Werden zwei N-Bit-Unsigned-Werte addiert, die N Bits überschreiten, wird auf N Bits abgeschnitten. Willst du den Carry erfassen, deklariere das Ergebnis ein Bit breiter:
wire [7:0] a, b;
wire [8:0] sum = a + b;   // 9-Bit-Summe erfasst Carry-Out

Vergleich: == != < > <= >=

Alle sechs Vergleichsoperatoren liefern ein 1-Bit-Ergebnis: 1, wenn wahr, 0, wenn falsch, x, wenn einer der Operanden ein x- oder z-Bit hat. Um den x/z-Fall zu handhaben, greife zu === und !== (den Case-Equality-Operatoren), behandelt in X- und Z-Werte.

<= ist hier der Vergleichsoperator (kleiner-gleich). Dieselben Zeichen bedeuten auch non-blocking-Zuweisung in einem prozeduralen Block (q <= d). Der Kontext unterscheidet: in einem Ausdruck ein Vergleich; links von einem zugewiesenen Wert eine Zuweisung. Die Überschneidung ist verwirrend, aber für den Parser eindeutig.

Logik: && || !

Logische Operatoren behandeln ihre Operanden als Booleans (alles ungleich Null ist wahr, Null ist falsch) und liefern ein 1-Bit-Ergebnis:

Der entscheidende Unterschied, den du verinnerlichen musst: Logisches && ist nicht bitweises &.

4'b1100 && 4'b0011   // 1 (beide ungleich Null, logisches AND wahr)
4'b1100 &  4'b0011   // 4'b0000 (keine Bitposition in beiden 1)

Gleiches für || vs |. Nimm logisch in if-Bedingungen und ?:-Prädikaten; nimm bitweise, wenn du jede Bitposition unabhängig AND/OR willst.

&& und || sind im C-Sinn kurzschließend: die rechte Seite wird nicht ausgewertet, wenn das Ergebnis bereits durch die linke feststeht. Das zählt für Testbenches, die Pointer oder Funktionsaufrufe prüfen; für synthetisierbares RTL spielt es selten eine Rolle, weil dort sowieso alles parallel passiert.

Der bedingte Operator: ?:

Der Ternäre ist dein bester Freund für Multiplexer und bedingte Ausdrücke:

Das Muster cond ? a : b ist ein 1-Bit-Select 2-zu-1-Multiplexer in Hardware. Sie zu verketten ist für 3- und 4-Wege-Selects okay, aber darüber hinaus ist eine case-Anweisung (siehe Case-Anweisung) deutlich lesbarer.

Der ?:-Operator ist auch die übliche Art, einem Register einen Default-Wert zu geben, den du nur manchmal überschreibst:

next_value = update ? new_data : next_value;

Breitenregeln: Die Anfängerfalle

Die Breitenregeln von Verilogs Arithmetik-Operatoren sind berüchtigt für ihre Überraschungen. Kurzfassung:

  • Die Breite des Ergebnisses ist das Maximum der Breiten der Eingänge.
  • Wird das Ergebnis einem breiteren Ziel zugewiesen, wird mit Nullen erweitert (oder mit Vorzeichen erweitert, wenn signed).
  • Die Breite von Zwischenrechnungen ist ebenfalls die Ergebnisbreite, also passiert Überlauf in der Zwischenrechnung.

Die erste Multiplikation läuft über, weil die Operandenbreiten beide 8 Bit sind, die Ergebnisbreite damit 8 Bit, und 40000 passt nicht. Die zweite funktioniert, weil wir a vor der Multiplikation explizit erweitert haben.

Die Fix-Techniken:

  • Nutze den Konkatenationsoperator {8'b0, a} zur Null-Erweiterung.
  • Nutze $unsigned(a) oder $signed(a), um die Interpretation zu beeinflussen.
  • Caste Zwischenausdrücke auf breitere Größen, wenn du unsicher bist.

Operator-Präzedenz

Die Tabelle wirst du nicht auswendig lernen, aber ein paar Regeln helfen:

  • *, /, % binden enger als +, -.
  • Vergleich bindet enger als Logik (&&, ||).
  • Der bedingte Operator ?: hat sehr niedrige Präzedenz - in größeren Ausdrücken meist Klammern um seine Zweige nötig.
  • Im Zweifel klammern. Der Simulator rechnet pro Zeichen nichts ab.
out = (mode == 2'd0) ? a + b : a - b;   // mit Klammern klarer

Wie es weitergeht

Du hast jeden Operator gesehen, der wie sein Software-Verwandter aussieht. Das nächste Doc - Bitweise und Reduktion - behandelt die Operatoren ohne direkte Software-Entsprechung: bitweises AND/OR/XOR pro Bit, plus die Reduktionsformen, die einen ganzen Vektor auf ein einzelnes Bit kollabieren.

Häufig gestellte Fragen

Welche Operatoren unterstützt Verilog?

Verilog hat vier große Operator-Familien: Arithmetik (+, -, *, /, %), Vergleich (==, !=, <, >, <=, >=), Logik (&&, ||, !) und bitweise/Reduktion (&, |, ^, ~, ~&, ~|, ~^). Dazu kommen Shift-Operatoren (<<, >>, <<<, >>>), Konkatenation {}, Replikation {N{...}} und der bedingte ?:.

Was ist der Unterschied zwischen && und & in Verilog?

&& ist logisches AND - es behandelt jeden Operanden als Boolean (Null oder Nicht-Null) und gibt ein 1-Bit-Ergebnis. & ist bitweises AND - es paart Bits positionsweise. 4'b1100 && 4'b0011 ist 1 (beide sind ungleich Null); 4'b1100 & 4'b0011 ist 4'b0000. Nimm && in Bedingungen, & für Bit-Operationen.

Wie funktioniert Division in Verilog?

Ganzzahldivision - der Nachkommateil wird verworfen. 7 / 2 ist 3, nicht 3.5. Der %-Operator liefert den Rest: 7 % 2 ist 1. Division durch Null produziert in der Simulation x (Unknown). Beide Operatoren sind theoretisch synthetisierbar, erzeugen aber auf FPGAs und ASICs sehr große, langsame Hardware - vermeide sie in synthetisierbaren Pfaden, außer der Divisor ist eine Zweierpotenz.

Was ist der bedingte Operator in Verilog?

?: ist der ternäre oder bedingte Operator, übernommen von C. cond ? a : b ergibt a, wenn cond wahr (ungleich Null) ist, und b sonst. Es ist das meistgenutzte Konstrukt für Multiplexer-artige Logik: out = sel ? in1 : in0 baut einen 2-zu-1-Mux. Ketten von ?: bauen breitere Multiplexer, aber case ist ab zwei Eingängen meist klarer.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S