Zwei Namen, ein Job
Jedes Signal in Verilog hat einen Typ. Die zwei Typen, die du zuerst kennenlernst, sind wire und reg. Beide können einen Wert halten. Beide können einzelbittig oder mehrbittig sein. Der Unterschied bezieht sich nicht darauf, was das Signal ist - sondern darauf, wer es treibt.
wire-Signale werden außerhalb prozeduraler Blöcke getrieben - durchassign-Anweisungen, durch Ausgänge von Submodulen oder durch Eingangsports des Moduls.reg-Signale werden innerhalb prozeduraler Blöcke getrieben -initialoderalways.
Das ist die ganze Regel. Die Schlüsselwörter sind sperrig, weil sie aus der Frühzeit der Sprache stammen. reg wird in Hardware nicht immer zu einem Register. Warum, liest du gleich.
wire: Die kontinuierliche Verbindung
Ein wire ist eine elektrische Leitung. Sie trägt kontinuierlich das, was ihr Treiber produziert. Zwei Wege, wie ein wire getrieben wird:
Drei Punkte fallen auf:
yundzsind im Modul alswiredeklariert und in der Testbench wieder alswire.- Sie werden durch
assigngetrieben - die Form der kontinuierlichen Zuweisung. Die rechte Seite des=wird jedes Mal neu berechnet, wenn sich ein darin enthaltenes Signal ändert. - Wir können
y = a & bnicht innerhalb einesalways-Blocks schreiben, solangeyeinwirebleibt. Der Compiler würde es ablehnen.
Vergisst du das wire-Schlüsselwort, deklariert Verilog das Signal implizit als einzelbittiges wire - was manchmal praktisch und manchmal ein stiller Bug ist. Die meisten Teams aktivieren eine Tool-Option, die bei impliziten wires einen Fehler ausgibt. Sei explizit und vermeide die Falle.
reg: Speicher innerhalb eines prozeduralen Blocks
Ein reg ist ein Signal, dem du innerhalb von initial oder always zuweist. Der Name ist ein Relikt aus den frühen Tagen der Sprache, als "reg" wie "register" klang; im modernen Gebrauch ist ein reg einfach der Typ jedes Signals, dem prozeduraler Code schreibt.
count ist im Modul reg (weil der always-Block ihm zuweist) und in der Testbench wire (weil der DUT-Ausgangsport ihn treibt). Dasselbe Signal, unterschiedliche Rollen, unterschiedliche Typen in jedem Scope.
Warum "reg" nicht immer "Register" heißt
Hier ist die häufigste Anfängerfalle. Dieses Modul deklariert y als reg - aber die synthetisierte Hardware enthält kein Flip-Flop:
Der always @(*)-Block ist sensitiv auf jede Eingangsänderung. Er ist kombinatorisch. Ein Synthese-Tool sieht das Muster und erzeugt ein AND-Gatter - kein Flip-Flop, kein Takt, nur Logik. Das reg-Schlüsselwort ist hier rein eine syntaktische Anforderung, weil y innerhalb eines always zugewiesen wird.
Um ein echtes Flip-Flop zu bekommen, muss der always-Block auf eine Taktflanke sensitiv sein:
always @(posedge clk) begin
q <= d;
end
Das ist das Muster "Synthese-Tool, bitte ein Flip-Flop bauen": getaktete Sensitivitätsliste, non-blocking-Zuweisung. Dasselbe reg-Schlüsselwort, völlig andere Hardware. Wir behandeln den Unterschied in Always-Block und Blocking vs Non-blocking.
Die Entscheidung in der Praxis
Bei jeder Signal-Deklaration frage dich: Wie werde ich es treiben?
- Mit
assigntreiben? →wire. - An einen Submodul-Ausgangsport anschließen? →
wire. - Eingangsport des Moduls? →
wire. (Eingänge sind immer wire.) - Aus
initialoderalwaystreiben? →reg. - Ausgangsport, vom prozeduralen Code getrieben? →
output reg. - Ausgangsport, durch
assigngetrieben? →output wire. (Oder nuroutput- allein die Richtung impliziert wire.)
Dieser Entscheidungsbaum deckt jede Situation ab, die dir in klassischem Verilog begegnet.
Treiber-Konflikte
wire-Signale können theoretisch mehrere Treiber haben - so funktionieren Tri-State-Busse, bei denen mehrere Module dieselbe Leitung treiben können und die inaktiven in High-Impedance (z) gehen. Für gewöhnliche Logik produzieren zwei assign-Anweisungen, die denselben wire schreiben, undefiniertes Verhalten:
assign y = a;
assign y = b; // BAD - y hat zwei Treiber
Der Simulator wählt vielleicht einen aus, vielleicht macht er das Signal zu x, je nach Tool. So oder so: Bug. Ein Treiber pro wire, außer du baust explizit einen Bus.
reg-Signale dürfen nur aus einem prozeduralen Block getrieben werden. Zwei always-Blöcke, die beide demselben reg zuweisen, sind ein Syntheserfehler und in der Simulation bizarr. Gleiche Regel: ein Treiber.
Das SystemVerilog-Update: logic
SystemVerilog (die Obermenge, zu der sich Verilog entwickelt hat) fügt ein einziges Schlüsselwort hinzu, das beide ersetzt: logic. Ein logic-Signal kann von assign oder von einem prozeduralen Block getrieben werden - aber nicht von beidem gleichzeitig - und der Compiler hindert dich daran, versehentlich einen Multi-Driver-Bug zu bauen.
module modern(input logic a, input logic b, output logic y);
assign y = a ^ b;
endmodule
Wenn du ein Projekt von Grund auf startest und dein Tool SystemVerilog unterstützt (was der Editor auf dieser Seite mit -g2012 tut), vereinfacht es die Regeln, überall logic zu verwenden. Reine .v-Dateien brauchen weiterhin den wire/reg-Split, und du wirst beide Stile für immer im wilden Code sehen.
Wie es weitergeht
Das nächste Doc - Vektoren und Arrays - nimmt dieselben zwei Typen und zeigt, wie man sie mehrbittig macht. Busbreiten, Bereiche, Packed-Dimensionen, der Unterschied zwischen einem Vektor aus Bits und einem Array aus Vektoren. All das brauchst du, bevor du etwas Größeres bauen kannst als einen Ein-Bit-Addierer.
Häufig gestellte Fragen
Was ist der Unterschied zwischen wire und reg in Verilog?
wire und reg halten beide zu jedem Zeitpunkt der Simulation einen Signalwert, aber du wählst zwischen ihnen anhand davon, wer das Signal treibt. Ein wire wird außerhalb eines prozeduralen Blocks getrieben - durch ein assign oder den Ausgang eines Submoduls. Ein reg wird innerhalb eines initial- oder always-Blocks getrieben. Die Namen sind historisch und irreführend; reg heißt nicht zwangsläufig 'Register'.
Heißt reg in Verilog ein Flip-Flop?
Nicht unbedingt. Ein reg wird nur dann zu einem Flip-Flop synthetisiert, wenn sein always-Block auf eine Taktflanke sensitiv ist und non-blocking-Zuweisung verwendet. Ein reg, dem in einem kombinatorischen always @(*)-Block zugewiesen wird, synthetisiert zu reiner kombinatorischer Logik. Das Schlüsselwort wählt den Verilog-Datentyp, nicht die Hardware.
Wann sollte ich wire vs reg nehmen?
Faustregel: Wenn du das Signal mit assign treibst oder es an den Ausgang eines Submoduls anschließt, nimm wire. Wenn du es innerhalb eines always- oder initial-Blocks zuweist, nimm reg. Eingänge eines Moduls sind immer wire. Ausgänge sind wire, wenn von assign getrieben, und reg, wenn von einem prozeduralen Block getrieben.
Kann man einem wire innerhalb eines always-Blocks zuweisen?
Nein - das ist ein Syntaxfehler. wire-Signale dürfen nur durch kontinuierliche Zuweisungen (assign) oder durch Anbindung an einen Submodul-Ausgang getrieben werden. Alles innerhalb von initial oder always muss ein reg (oder in SystemVerilog ein logic) als Ziel haben. Der Compiler fängt das ab und meldet einen 'left-hand side type mismatch'.
Was ist logic in SystemVerilog?
logic ist die Vereinheitlichung von wire und reg in SystemVerilog. Es kann entweder durch eine kontinuierliche Zuweisung oder durch einen prozeduralen Block getrieben werden (aber nicht beides gleichzeitig). Moderner Code nutzt zunehmend überall logic und vergisst die Unterscheidung wire/reg. Klassische Verilog-Dateien müssen sich weiterhin entscheiden.