Unterschied zwischen blockierender und nicht blockierender Zuweisung Verilog

15

Ich habe diese Seite http://www.asic-world.com/verilog/verilog_one_day3.html gelesen, als ich auf Folgendes gestoßen bin:

Normalerweise müssen wir Flip-Flops zurücksetzen. Jedes Mal, wenn die Uhr von 0 auf 1 wechselt (Posedge), prüfen wir, ob ein Reset aktiviert ist (synchroner Reset), und fahren dann mit der normalen Logik fort. Wenn wir genau hinschauen, sehen wir, dass wir im Fall der kombinatorischen Logik "=" für die Zuweisung und für den sequentiellen Block den Operator "<=" hatten. Nun, "=" ist eine blockierende Zuweisung und "<=" ist eine nicht blockierende Zuweisung. "=" führt Code sequenziell innerhalb eines Anfangs / Endes aus, während "<=" nicht blockierend parallel ausgeführt wird.

Ich war mir ziemlich sicher, dass nicht blockierende Zuweisungen sequentiell waren, während blockierende Zuweisungen parallel waren. Schließlich können Sie blockierende Zuweisungen mit Anweisungen assign außerhalb von always blocks vornehmen, und diese werden alle parallel ausgeführt. Ist das ein Fehler oder ist das Verhalten innerhalb eines Always-Blocks anders? Und wenn das Verhalten innerhalb eines Always-Blocks unterschiedlich ist, können nicht blockierende Zuweisungen außerhalb eines Always-Blocks vorgenommen werden?

Leerer Stern
quelle

Antworten:

21

Ich war mir ziemlich sicher, dass nicht blockierende Zuweisungen sequentiell waren, während blockierende Zuweisungen parallel waren.

Die Blockierungszuweisung wird "in Serie" ausgeführt, da eine Blockierungszuweisung die Ausführung der nächsten Anweisung blockiert, bis sie abgeschlossen ist. Daher können die Ergebnisse der nächsten Anweisung davon abhängen, ob die erste abgeschlossen ist.

Die nicht blockierende Zuweisung wird parallel ausgeführt, da sie Zuweisungen beschreibt, die alle zur gleichen Zeit erfolgen. Das Ergebnis einer Anweisung in der 2. Zeile hängt nicht von den Ergebnissen der Anweisung in der 1. Zeile ab. Stattdessen wird die 2. Zeile ausgeführt, als ob die 1. Zeile noch nicht geschehen wäre.

Das Photon
quelle
Was ist mit Anweisungen zuweisen? Sind sie nur eine Klasse für sich?
Void Star
4
Ja, assignAnweisungen kommen außerhalb von always-Blöcken vor und werden im Allgemeinen zur Beschreibung der kombinatorischen (nicht zwischengespeicherten) Logik verwendet (während always-Blöcke mit einigen Ausnahmen die sequentielle Logik beschreiben). AFAIK, assignAnweisungen werden immer "parallel" ausgeführt, wenn sich der LHS-Wert ändert.
Das Photon
Okay ... Ich bekomme allmählich den Eindruck, dass Verilog einfach nicht die eleganteste Sprache ist. Das wird so, als würde man C lernen.
Void Star
1
Verilog wurde entwickelt, um bereits vorhandene Hardware zu "beschreiben". Die Verwendung als Sprache zum Entwerfen (Synthetisieren) von Hardware ist ein Hack.
Das Photon
4
Wenn Verilog "wie das Lernen von C" ein Problem ist, werfen Sie einen Blick auf VHDL. Einige Leute haben ziemlich starke Vorlieben für das eine oder andere. Für manche ist VHDL einfach zu ausführlich. Für mich ist es viel besser durchdacht. (Die Semantik der Signal- / Variablenzuweisung ist viel klarer als beispielsweise "Blockieren / Nicht"). stackoverflow.com/questions/13954193/... und sigasi.com/content/vhdls-crown-jewel Sie es vorziehen, oder hassen. Aber es ist einen Blick wert.
Brian Drummond
5

Zuweisungsanweisungen sind weder "blockierend" noch "nicht blockierend", sondern "kontinuierlich". Die Ausgabe einer assign-Anweisung entspricht immer der angegebenen Funktion ihrer Eingaben. "blockierende" und "nicht blockierende" Zuordnungen existieren nur innerhalb von Always-Blöcken.

Eine Sperrung wird sofort wirksam, wenn sie bearbeitet wird. Eine nicht blockierende Zuordnung erfolgt am Ende der Bearbeitung des aktuellen "Zeitdeltas".

always-Blöcke können verwendet werden, um entweder kombinatorische oder sequentielle Logik zu modellieren (systemverilog hat always_comb und always_ff, um dies explizit zu machen). Bei der Modellierung von kombinatorischer Logik ist es normalerweise effizienter, = zu verwenden, aber es spielt normalerweise keine Rolle.

Bei der Modellierung der sequentiellen Logik (z. B. immer @ (posedge clk)) werden normalerweise nicht blockierende Assingments verwendet. Auf diese Weise können Sie den "Zustand nach der Taktflanke" als "Zustand vor der Taktflanke" bestimmen.

Es ist manchmal nützlich, blockierende Zuweisungen in sequentiellen Blöcken immer als "Variablen" zu verwenden. Wenn Sie dies tun, müssen Sie zwei wichtige Regeln beachten.

  1. Greifen Sie nicht auf eine Registrierung zu, die mit blockierenden Zuweisungen innerhalb eines sequentiellen Always-Blocks von außerhalb des Always-Blocks festgelegt ist, in dem sie zugewiesen ist.
  2. Mischen Sie blockierende und nicht blockierende Zuweisungen nicht mit derselben Registrierung.

Ein Verstoß gegen diese Regeln kann zu Synthesefehlern und / oder Verhaltensunterschieden zwischen Simulation und Synthese führen.

Peter Green
quelle
"" Greifen Sie nicht auf eine Registrierung zu, die mit blockierenden Zuweisungen innerhalb eines sequentiellen Always-Blocks von außerhalb des Always-Blocks festgelegt ist, in dem sie zugewiesen ist. "" Können Sie das bitte erklären?
user125575
Unterschiedliche sequentielle Immer-Blöcke haben keine definierte Reihenfolge. Das Lesen eines "reg" -Satzes mit einer blockierenden Zuweisung in einem Always-Block von einem anderen Always-Block führt zu unvorhersehbarem Verhalten.
Peter Green
Und selbst wenn es in der Simulation zu funktionieren scheint, sollte sich ein Synthesewerkzeug das ansehen und "Nein" sagen. Ich verwende lokale Register für diese Zwischenvariablen und stelle sicher, dass sie immer bei jeder Uhr zugewiesen werden, bevor sie gelesen werden, damit kein "Speicher" impliziert wird.
Greggo
IIRC zumindest im Quartus ist es nur eine Warnung, kein Fehler.
Peter Green
4

Der Begriff Blockierungszuweisung verwirrt die Menschen, da das Wort Blockierung anscheinend eine zeitlich sequentielle Logik suggeriert. In der synthetisierten Logik bedeutet dies jedoch nicht , da alles parallel arbeitet .

Ein weniger verwirrender Begriff wäre möglicherweise die sofortige Zuweisung , die die Zwischenergebnisse der Kombinationslogik immer noch von den Eingaben zu nicht transparenten Speicherelementen (zum Beispiel getakteten Registern) unterscheidet, die eine verzögerte Zuweisung haben können .

Aus legalistischer Sicht läuft alles sehr gut. Tatsächlich können Sie davon ausgehen, dass es sich auch innerhalb von Sequenzen =um eine blockierende (zeitlich sequentielle) Operation handelt always_comb. Die Unterscheidung zwischen zeitlich sequentiell und parallel macht in diesem Fall jedoch absolut keinen Unterschied , da diealways_comb Block so definiert ist, dass er sich wiederholt, bis die Befehlssequenz in einem stabilen Zustand konvergiert Anforderungen).

Die synthetisierbare Teilmenge von Verilog (und insbesondere von SystemVerilog) ist äußerst einfach und benutzerfreundlich - sobald Sie die erforderlichen Redewendungen kennen. Sie müssen nur den geschickten Gebrauch der Terminologie hinter sich lassen, die mit den sogenannten Verhaltenselementen in der Sprache verbunden ist.

kein Balken
quelle
Bei Verhaltenskodierungsstilen ( im Vergleich zu RTL ) kann die Unterscheidung zwischen blockierend und nicht blockierend relevant sein. In einigen Fällen kann das Synthesewerkzeug funktionell äquivalente RTL aus Verhaltenskomponentenentwürfen ableiten.
Nobar
Selbstverständlich verwendet der prozedurale Modus von SystemVerilog, der insbesondere für initialAnweisungen innerhalb von programBlöcken gilt, ausschließlich (zeitlich sequentielle) Blockierungszuweisungen . Dies ist nützlich für das Testbench- Design, im Allgemeinen jedoch nicht für die RTL-Spezifikation.
Nobar