Blockierende vs. nicht blockierende Zuweisung in Verilog

Beide sind Zuweisungen innerhalb eines always-Blocks in Verilog, unterscheiden sich aber im Zeitpunkt, zu dem die linke Seite aktualisiert wird. Die blockierende Zuweisung (=) aktualisiert die linke Seite sofort bei Ausführung der Zeile, und die nächste Zeile verwendet bereits den neuen Wert. Die nicht blockierende Zuweisung (<=) wertet zunächst alle rechten Seiten desselben Zeitpunkts aus und aktualisiert danach die linken Seiten gemeinsam. Grundregel: <= für taktgesteuerte sequenzielle Logik, = für always-Blöcke mit kombinatorischer Logik.

MerkmalBlockierende Zuweisung (=)Nicht blockierende Zuweisung (<=)
Schreibweisea = b;a <= b;
Zeitpunkt der Aktualisierung der linken SeiteSofort bei Ausführung der ZeileGemeinsam, nachdem alle rechten Seiten desselben Zeitpunkts ausgewertet wurden
In der nächsten Zeile sichtbarer WertDer neue, aktualisierte WertDer alte Wert vor der Aktualisierung
Abhängigkeit von der ReihenfolgeJa. Vertauschen der Zeilen ändert das ErgebnisKaum. Wird derselben Variablen jedoch zweimal zugewiesen, bleibt die spätere Zuweisung wirksam
Entsprechendes SchaltungsverhaltenKombinatorische Logik, die Zwischenwerte von oben nach unten berechnetFlip-Flops, die an der Taktflanke gleichzeitig Werte übernehmen
Hauptsächlicher Einsatzortalways @(*) für kombinatorische Logik, prozedurale Abläufe in Testbenchesalways @(posedge clk) für taktgesteuerte sequenzielle Logik
Zweistufiges Schieberegister (taktgesteuerter Block)Bei q1 = d; q2 = q1; erhält auch q2 an derselben Flanke d; nur eine Stufe VerzögerungBei q1 <= d; q2 <= q1; erhält q2 das q1 von vor der Flanke; zwei Stufen
Vertauschen von Werten (taktgesteuerter Block)Bei a = b; b = a; erhalten a und b denselben WertBei a <= b; b <= a; werden a und b vertauscht
Zwischen mehreren always-BlöckenZwischen Blöcken an derselben Flanke entstehen leicht Race Conditions, bei denen das Ergebnis von der Ausführungsreihenfolge abhängtDa die Auswertung der rechten Seiten zuerst abgeschlossen wird, entstehen kaum Race Conditions
Bei falscher VerwendungIn sequenzieller Logik hängt das Ergebnis von der Ausführungsreihenfolge der Blöcke ab und kann vom Verhalten der synthetisierten Schaltung abweichenIn kombinatorischer Logik werden Zwischenwerte veraltet gelesen; die Simulation weicht von der synthetisierten Schaltung ab oder wird unnötig erneut ausgeführt

Die Zahlenwerte sind typische Größenordnungen und variieren je nach Prozessgeneration und Produkt.

Wann welche Variante?

Blockierende Zuweisung (=)
Wenn in always @(*) für kombinatorische Logik Zwischenwerte nacheinander berechnet werden. Wenn in Testbenches Abläufe der Reihe nach beschrieben werden.
Nicht blockierende Zuweisung (<=)
Wenn taktgesteuerte Flip-Flops beschrieben werden, etwa in always @(posedge clk): Register, Zähler, Zustandsaktualisierung von Zustandsautomaten.
Nicht mischen
Innerhalb eines always-Blocks = und <= nicht mischen und dieselbe Variable nicht aus mehreren always-Blöcken zuweisen. In SystemVerilog lässt sich die Absicht mit always_ff und always_comb an die Werkzeuge übermitteln.

Häufige Fragen

Was passiert, wenn man in sequenzieller Logik blockierende Zuweisungen verwendet?

Je nach Zeilenreihenfolge wird ein an derselben Flanke aktualisierter Wert direkt an die nächste Zeile weitergegeben, und es entsteht eine Schaltung mit weniger Stufen als beabsichtigt. Außerdem entstehen mit anderen always-Blöcken am selben Takt Race Conditions, bei denen das Ergebnis von der Ausführungsreihenfolge abhängt; dies führt zu Abweichungen zwischen Simulation und synthetisierter Schaltung.

Warum werden bei nicht blockierender Zuweisung mit a <= b; b <= a; die Werte vertauscht?

Weil beide rechten Seiten zuerst mit den alten Werten ausgewertet und die linken Seiten danach gemeinsam aktualisiert werden. Das Verhalten entspricht einer Schaltung, bei der die Ausgänge zweier Flip-Flops mit dem Eingang des jeweils anderen verbunden sind.

Welche Zuweisung sollte man in Testbenches verwenden?

Für Teile, die Abläufe der Reihe nach beschreiben, ist die blockierende Zuweisung in Ordnung. Ändert man jedoch die Eingänge der Schaltung zum selben Zeitpunkt wie die Taktflanke, hängt es von der Ausführungsreihenfolge ab, ob der alte oder der neue Wert übernommen wird; daher werden sie leicht versetzt zur Flanke oder mit nicht blockierender Zuweisung geändert.

Verständnis prüfen

Welche Aussage zum Verhalten der nichtblockierenden Zuweisung (<=) in Verilog ist korrekt?

  1. ADie linke Seite wird im Moment der Zuweisung aktualisiert, und in der nächsten Zeile wird dieser neue Wert verwendet
  2. BAlle rechten Seiten des gleichen Zeitpunkts werden zuerst ausgewertet, danach werden die linken Seiten gemeinsam aktualisiert
  3. CDas Ergebnis der Zuweisung wird verworfen, und nichts ändert sich
Antwort und Erläuterung anzeigen

Antwort: B. Alle rechten Seiten des gleichen Zeitpunkts werden zuerst ausgewertet, danach werden die linken Seiten gemeinsam aktualisiert

Bei nichtblockierenden Zuweisungen werden an der Taktflanke zuerst die rechten Seiten aller <= mit den alten Werten ausgewertet und danach alle linken Seiten gleichzeitig überschrieben. Das entspricht dem Verhalten einer realen Schaltung, in der viele Flipflops mit demselben Takt gleichzeitig die Werte unmittelbar vor der Flanke übernehmen. Daher gilt für die Beschreibung getakteter sequentieller Schaltungen grundsätzlich die nichtblockierende Zuweisung.

Welche Richtlinie zur Verwendung der Zuweisungsarten in Verilog ist allgemein korrekt?

  1. AÜberall nur blockierende Zuweisungen (=) verwenden
  2. BFür getaktete sequentielle Schaltungen nichtblockierende Zuweisungen (<=), für always-Blöcke kombinatorischer Schaltungen blockierende Zuweisungen (=) verwenden
  3. CIn einem always-Block beide willkürlich mischen
Antwort und Erläuterung anzeigen

Antwort: B. Für getaktete sequentielle Schaltungen nichtblockierende Zuweisungen (<=), für always-Blöcke kombinatorischer Schaltungen blockierende Zuweisungen (=) verwenden

Wird eine sequentielle Schaltung mit nichtblockierenden Zuweisungen beschrieben, entspricht dies dem Verhalten einer Schaltung, in der alle Flipflops gleichzeitig Werte übernehmen, und das Ergebnis hängt weder von der Schreibreihenfolge noch von der Ausführungsreihenfolge anderer always-Blöcke ab. Bei kombinatorischen Schaltungen ist es natürlich, Zwischenwerte von oben nach unten zu berechnen, daher werden blockierende Zuweisungen verwendet. Wichtig ist auch, in einem always-Block nicht beide zu mischen.

Ändert man in einer Testbench die Eingänge der Schaltung zum selben Zeitpunkt wie die steigende Taktflanke mit blockierender Zuweisung, kann ein Problem auftreten. Welche Kombination aus Hauptgrund und Gegenmaßnahme ist korrekt?

  1. AWeil je nach Ausführungsreihenfolge entweder der Wert vor oder nach der Änderung übernommen wird (Race). Eingänge werden etwas gegen die Taktflanke versetzt oder per nichtblockierender Zuweisung geändert
  2. BWeil die Taktfrequenz automatisch sinkt. Der Takt wird schneller gemacht
  3. CWeil blockierende Zuweisungen in Testbenches nicht verwendbar sind. Alles wird mit assign-Anweisungen geschrieben
Antwort und Erläuterung anzeigen

Antwort: A. Weil je nach Ausführungsreihenfolge entweder der Wert vor oder nach der Änderung übernommen wird (Race). Eingänge werden etwas gegen die Taktflanke versetzt oder per nichtblockierender Zuweisung geändert

Treffen im selben Zeitpunkt die Änderung der Eingänge durch die Testbench und die Übernahme der Eingänge durch die Flipflops der Schaltung zusammen, kann je nachdem, welches der Simulator zuerst ausführt, der alte oder der neue Wert übernommen werden. Das ist ein Race in der Simulation, und das Ergebnis kann je nach Simulator abweichen. Vermieden wird es, indem man Eingänge an der fallenden Flanke ändert, leicht verzögert, nichtblockierende Zuweisungen oder in SystemVerilog Clocking-Blöcke verwendet.

  1. Bei der obigen Beschreibung war unmittelbar vor der steigenden Taktflanke a=0 und b=1. Welche Werte haben a und b nach der steigenden Flanke?
  2. Ein zweistufiges Schieberegister sollte entstehen, wurde aber wie oben mit blockierenden Zuweisungen (=) geschrieben. Welches Problem tritt auf?
  3. Die obige Beschreibung sollte eine kombinatorische Schaltung sein. Welches mögliche Problem ist korrekt beschrieben?

Übungsfragen zu Hardwarebeschreibungssprachen und Verifikation

Wichtige Begriffe erklärt

Blockierende Zuweisung
Zuweisung mit „=“ in Verilog. Die linke Seite wird sofort aktualisiert und der neue Wert in der nächsten Zeile verwendet. Sie wird in always-Blöcken kombinatorischer Schaltungen und in Testbenches verwendet.
Nicht blockierende Zuweisung
Zuweisung „<=“ in Verilog. Alle rechten Seiten desselben Zeitpunkts werden zuerst ausgewertet, dann werden die linken Seiten gemeinsam aktualisiert. Entspricht dem Verhalten von Flipflops und wird daher für sequenzielle Schaltungen verwendet.
Sensitivitätsliste
Liste der Signale im @( ) nach einem Verilog-always, die die Ausführung des Blocks auslösen. Fehlt in kombinatorischen Schaltungen ein Signal, weichen Simulation und Schaltung voneinander ab.
Verilog
Weit verbreitete Hardwarebeschreibungssprache für Entwurf und Verifikation digitaler Schaltungen. Schaltungen werden in module-Einheiten geschrieben, das Verhalten mit assign und always beschrieben.

Verwandte Vergleiche