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.

Illustration der Programmiersprachen bei Coddy

Lerne mit Coddy zu programmieren

Los geht's