Unterschied zwischen blockierender und nicht blockierender Zuordnung Verilog

Ich las diese Seite http://www.asic-world.com/verilog/verilog_one_day3.html , als ich auf Folgendes stieß:

Normalerweise müssen wir Flip-Flops zurücksetzen, daher prüfen wir jedes Mal, wenn die Uhr den Übergang von 0 auf 1 (Posedge) durchführt, ob das Zurücksetzen aktiviert ist (synchrones Zurücksetzen), und fahren dann mit der normalen Logik fort. Wenn wir genau hinsehen, 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 sequentiell innerhalb eines begin / end aus, während nicht blockierendes "<=" 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 Assign-Anweisungen außerhalb von Always-Blöcken 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?

Antworten (3)

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

Die blockierende Zuweisung wird "in Serie" ausgeführt, da eine blockierende Zuweisung 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 gleichzeitig auftreten. 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 so ausgeführt, als wäre die 1. Zeile noch nicht geschehen.

Was ist also mit Assign-Anweisungen? Sind sie einfach eine Klasse für sich?
Ja, assignAnweisungen treten außerhalb von Always-Blöcken auf und werden im Allgemeinen verwendet, um kombinatorische (nicht zwischengespeicherte) Logik zu beschreiben (während Always-Blöcke, mit einigen Ausnahmen, sequentielle Logik beschreiben). AFAIK, assignAnweisungen werden immer "parallel" ausgeführt, wenn ihre LHS eine Wertänderung aufweist.
Okay ... Ich bekomme allmählich den Eindruck, dass Verilog einfach nicht die am elegantesten gestaltete Sprache ist. Das wird so sein wie das Lernen von C.
Verilog wurde entwickelt, um bereits vorhandene Hardware zu "beschreiben". Es als Sprache zum Entwerfen (Synthetisieren) von Hardware zu verwenden, ist ein Hack.
Wenn Verilog "wie das Lernen von C" ein Problem darstellt, werfen Sie einen Blick auf VHDL. Manche Menschen haben ziemlich starke Vorlieben für das eine oder andere. Manchen ist VHDL einfach zu ausführlich. Für mich viel durchdachter. (Signal-/Variablenzuweisungssemantik ist viel klarer als beispielsweise Blockieren/Nicht). stackoverflow.com/questions/13954193/… und sigasi.com/content/vhdls-crown-jewel Sie können es bevorzugen oder hassen. Aber es ist einen Blick wert.
Ja, verstehen Sie mich nicht falsch, ich liebe C, aber es ist schön, Optionen zu haben. Ich werde mir VHDL ansehen, danke.
Der Hauptunterschied zwischen VHDL und Verilog besteht darin, dass VHDL ein viel strengeres Typsystem hat und das "Entity/Architecture"-Durcheinander hat. Die Prinzipien des RTL-Designs wie der Unterschied zwischen blockierenden und nicht blockierenden Zuweisungen und die Verwendung spezifischer Verhaltensformulierungen, um sequenzielles Verhalten so zu beschreiben, dass Synthesewerkzeuge es verstehen können, gelten gleichermaßen in beiden Sprachen.

Zuweisungsanweisungen sind weder "blockierend" noch "nichtblockierend", sie sind "kontinuierlich". Die Ausgabe einer Assign-Anweisung ist immer gleich der angegebenen Funktion ihrer Eingaben. "blockierende" und "nicht blockierende" Zuweisungen existieren nur innerhalb von Always-Blöcken.

Eine Sperrzuweisung wird sofort nach ihrer Bearbeitung wirksam. Am Ende der Verarbeitung des aktuellen "Zeitdeltas" findet eine nichtblockierende Zuweisung statt.

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). Beim Modellieren der kombinatorischen Logik ist es normalerweise effizienter, = zu verwenden, aber es spielt normalerweise keine Rolle.

Bei der Modellierung sequentieller Logik (z. B. immer @(posedge clk) ) verwenden Sie normalerweise nichtblockierende Zuweisungen. Damit lässt sich der „Zustand nach der Taktflanke“ im Sinne des „Zustands vor der Taktflanke“ bestimmen.

Manchmal ist es sinnvoll, blockierende Zuweisungen in sequentiellen Always-Blöcken 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 Blockierungszuweisungen innerhalb eines sequentiellen Always-Blocks von außerhalb des Always-Blocks gesetzt ist, in dem sie zugewiesen ist.
  2. Mischen Sie keine blockierenden und nicht blockierenden Zuweisungen in derselben Registrierung.

Das Brechen dieser Regeln führt wahrscheinlich zu Synthesefehlern und/oder Verhaltensunterschieden zwischen Simulation und Synthese.

""Greifen Sie nicht auf eine Registrierung zu, die mit blockierenden Zuweisungen innerhalb eines sequentiellen Always-Blocks von außerhalb des Always-Blocks gesetzt ist, in dem sie zugewiesen ist."" Können Sie es bitte erklären?
Unterschiedliche sequentielle Always-Blöcke haben keine definierte Reihenfolge. Das Lesen eines "reg"-Satzes mit einer blockierenden Zuweisung in einem Always-Block aus einem anderen Always-Block führt zu unvorhersehbarem Verhalten.
Und selbst wenn es in der Simulation zu funktionieren scheint, sollte sich ein Synthesewerkzeug das ansehen und "nein" sagen. Ich verwende lokale Registrierungen für diese Zwischenvariablen und stelle sicher, dass sie immer auf jeder Uhr zugewiesen werden, bevor sie gelesen werden, sodass keine „Speicherung“ impliziert wird.
IIRC wird zumindest in quartus nur als Warnung und nicht als Fehler angesehen.
Sie sollten in der kombinatorischen Logik keine nicht blockierende Zuweisung verwenden, da dies die Simulation blockieren kann. Weitere Einzelheiten finden Sie in dieser Antwort: electronic.stackexchange.com/a/506047/238188

Der Begriff Blocking Assignment verwirrt die Leute, weil das Wort Blocking eine zeitsequentielle Logik vorzuschlagen scheint. Aber in der synthetischen Logik bedeutet es das nicht , weil alles parallel funktioniert .

Ein vielleicht weniger verwirrender Begriff wäre sofortige Zuweisung , was die Zwischenergebnisse der kombinatorischen Logik immer noch von den Eingängen zu nicht transparenten Speicherelementen (z. B. getakteten Registern) unterscheiden würde, die eine verzögerte Zuweisung haben können .

Aus juristischer Sicht funktioniert das alles sehr gut. Sie können sogar innerhalb von Sequenzen den =als blockierende (zeitsequentielle) Operation betrachten. always_combDie Unterscheidung zwischen zeitsequentiell und parallel macht in diesem Fall jedoch absolut keinen Unterschied, da der always_combBlock so definiert ist, dass er wiederholt wird, bis die Befehlsfolge zu einem stabilen Zustand konvergiert – genau das wird die Hardwareschaltung tun (wenn sie das Timing erfüllt). Bedarf).

Die synthetisierbare Teilmenge von Verilog (und insbesondere SystemVerilog) ist extrem einfach und leicht zu verwenden – sobald Sie die notwendigen Redewendungen kennen. Sie müssen nur die geschickte Verwendung von Terminologie überwinden, die mit den sogenannten Verhaltenselementen in der Sprache verbunden ist.

Bei Verhaltenscodierungsstilen ( im Vergleich zu RTL ) kann die Unterscheidung zwischen Blockierung und Nichtblockierung relevant sein. In einigen Fällen kann das Synthesetool in der Lage sein, funktional äquivalente RTL aus Verhaltenskomponentenentwürfen abzuleiten.
Der vor allem für Anweisungen innerhalb von Blöcken anwendbare Verfahrensmodus von SystemVerilog verwendet natürlich ausschließlich die (zeitsequentielle) Blockzuweisung . Dies ist nützlich für das Testbench- Design, aber im Allgemeinen nicht für die RTL-Spezifikation. initialprogram