Verwendung von „initial“ in der Beschreibung des Verilog-Moduls

Ich schreibe einen Code und ich habe 2 dumme Fragen:

1- Ist es eine schlechte Praxis, „initial“ in der Modulbeschreibung zu verwenden?

Ich frage das, weil ich einen Frequenzteiler mit 2 Signalen (clk_in und clk_out) habe. Wenn ich das Verhalten in der Simulation sehen möchte, muss ich clk_out einen Anfangswert geben, sonst bleibt clk_out immer X. Dann habe ich "initial" verwendet, anstatt ein Reset-Signal zu verwenden.

2- Warum funktioniert der Code ohne Initialisierung der Ausgabe im FPGA gut, aber nicht in der Simulation?

Mein Code macht im Grunde Folgendes: Clk_out <= ~Clk_out;

Vielen Dank im Voraus.

Ich habe die Frage mit FPGA markiert, da Sie anscheinend über FPGAs sprechen. Fühlen Sie sich frei, einen Rollback durchzuführen, wenn Sie Fragen zu Verilog im Allgemeinen haben (z. B. einschließlich ASICs).
überhaupt keine blöden Fragen

Antworten (4)

1/ Ist es schlechte Praxis?

Es ist völlig in Ordnung und wird oft in Prüfständen durchgeführt. Aber ich nehme an, das ist nicht das, worauf Sie anspielen. Ich würde eher sagen, dass es selten gemacht wird. Der Grund ist, dass es nicht für alle FPGAs und schon gar nicht für ASICs synthetisiert werden kann. Dies führt dazu, dass Ihrem Design nicht mehr vertraut werden kann, da das, was Sie simulieren, möglicherweise nicht mit der tatsächlichen Logik übereinstimmt.

Es gibt jedoch einige Ausnahmefälle, in denen Sie in Ihrem Modul einen Anfangsbuchstaben verwenden müssen, damit der Code funktioniert. Um ein Beispiel zu geben: Unten ist eine Division durch vier, die kein Zurücksetzen erfordert. Es ist eine sichere Schaltung, da alle möglichen Zustände verwendet werden, es spielt also keine Rolle, in welchem ​​Zustand sie startet. Aber ohne 'initial' kann es nicht simuliert werden, da es den 2'bxx-Zustand nicht verlassen wird.

reg [1:0] div_4;
always @(posedge clk)
   div_4 <= {div_4[0],~div_4[1]};

Wie ich in anderen Verilog-Beiträgen kommentiert habe: Verwenden Sie es nur, wenn Sie wirklich, wirklich wissen, was Sie tun.

2/ Warum funktioniert der Code ohne Initialisierung der Ausgabe im FPGA gut, aber nicht in der Simulation?

Es kann in Ihrem FPGA funktionieren, aber das bedeutet nicht, dass es im Allgemeinen funktioniert.

  • FPGAs setzen oft alle internen Register auf Null. In diesem Fall funktioniert es, wenn Ihr Anfangszustand auch Null ist.
  • Einige FPGAs können die Register beim Laden voreinstellen. Somit können Sie den anfänglichen Registerzustand 'setzen' oder 'löschen'.

Bei beiden funktioniert es nur einmal beim Start. Wenn Sie beispielsweise Ihre Logik zurücksetzen, ist sie möglicherweise nicht mehr in dem Zustand, in dem Sie Ihre Simulation zum ersten Mal gestartet haben. Daher könnte Ihr Code funktionieren oder nicht.

Wenn „initial“ nicht synthetisiert werden kann, warum gibt mir Xilinx ISE keine Fehler aus? Es synthetisiert den Code perfekt.
Es ist ein weit verbreitetes Missverständnis, dass initialBlöcke nicht synthetisiert werden können. Zumindest für FPGAs können sie das sogar - es ist durchaus üblich, Anfangsblöcke zu verwenden, um den Einschaltwert von Strukturen wie RAMs, ROMs und Registern festzulegen.
reg [1:0] div_4 = 2'b00;ist ein identisches Konstrukt zum reg [1:0] div_4; initial begin div_4 = 2'b00; endSetzen des anfänglichen Einschaltwerts eines Registers.

Es ist ein weit verbreitetes Missverständnis, dass initialBlöcke niemals synthetisiert werden können.

Tatsächlich können sie für FPGAs in den meisten Fällen synthetisiert werden. Tatsächlich ist die Verwendung von Anfangsblöcken ziemlich üblich. Sie können sie verwenden, um den Einschaltwert von Strukturen wie RAMs, ROMs und Registern einzustellen.

Dies ist überhaupt keine schlechte Praxis und hilft sowohl bei Simulations- als auch bei Synthesecode.

In vielen Fällen mit Registern ist es jedoch besser, ein Reset-Signal zu verwenden, um den Wert des Registers zu steuern. Dies liegt daran, dass Sie die Möglichkeit haben, das Register jederzeit in einen bekannten Zustand zu versetzen. Wenn Sie nur eine Teilgruppe von Registern in einer Schaltung zurücksetzen, können am Ende seltsame Zustände vorhanden sein.

In freilaufenden Schaltungen wie Ihrem clock <= ~clockBeispiel ist es wahrscheinlich nicht erforderlich, einen Reset einzufügen, und die Verwendung eines Anfangswerts hilft sicherzustellen, dass das Simulations- und Syntheseverhalten übereinstimmen.


In Bezug darauf, warum Ihr Code in der Simulation nicht funktioniert, liegt es daran, dass die Simulation tatsächlich vier Zustände hat, während die Synthese wirklich nur drei hat.

Der x(unbekannte) Zustand ist die Voreinstellung für Signale, die nicht in der Simulation initialisiert werden. Unbekannt stellt eine Bedingung dar, bei der der Simulator den Wert nicht kennt, es könnte eine 1 oder eine 0 sein.

Wenn Sie einen unbekannten Wert nehmen und ihn umkehren, erhalten Sie am Ende einen anderen unbekannten Wert. Daher wird Ihre Simulation immer xden Wert anzeigen, da sie nie weiß, wo sie anfangen soll.

Im Synthesecode stoppt dies die Ausführung nicht (*) - es ist entweder eine 1 oder eine 0, und das FPGA berechnet einfach die Ausgabe basierend auf dem Wert, den dieser Wert haben mag.


(*) Das Problem liegt eigentlich darin, dass Sie nicht wissen, wie es beginnen wird. Dies ist kein Problem, wenn Sie es simuliert haben, um es herauszufinden, aber wenn Ihre Simulation fehlschlägt, kann es schwierig sein, das Verhalten vorherzusagen.

Es gibt Fälle, in denen es kein Problem ist, keinen Anfangswert zu haben – zum Beispiel ein Datenbus, der ein gültiges Signal hat. Solange das gültige Signal auf niedrig initialisiert wird, um anzuzeigen, dass der Datenbus ungültig ist, spielt es keine Rolle, mit welchem ​​​​Wert der Datenbus beginnt. Bei Registern wie der Variablen "launchMissile" bleibt es jedoch dem Zufall überlassen, ob diese hoch beginnt oder niedrig ist gefährlich.

Es ist ein weit verbreitetes Missverständnis, dass anfängliche Blöcke nicht synthetisiert werden können. Dem stimme ich nicht zu. Es kann nur in FPGAs verwendet werden, nicht in CPLDs, nicht in ASICs. (Ich habe meine vorherige Antwort korrigiert.)
@oldfart Ich stimme dem nicht in allen Fällen zu, aber ich behaupte das nicht. Zu sagen, dass sie nicht synthetisiert werden können, ist falsch, weil sie es in einigen Fällen sein können. Siehe Wenn und nur wenn .
Capenter: Ich schreibe es als Unterschied im Sprachgebrauch ab. Besonders bei vielen nicht-englischsprachigen Personen versuche ich einfache Sätze zu verwenden, aber meine Sprache immer auf der „sicheren“ Seite zu halten. Daher stimme ich Ihrer Bemerkung zu, dass meine Verwendung von "falsch" ein Fehler war, und habe sie korrigiert. Gleichzeitig finde ich einen Satz, wie Sie ihn verwenden, um die obige Antwort zu beginnen, äußerst gefährlich, da die meisten Leser ihn nicht als "wenn und nur wenn" lesen werden, sondern eher als "Ihm geht es gut", während er leicht zu Simulationskonflikten führen kann . Es kann auch daran liegen, dass viele Jahre im ASIC-Design mich paranoid für Simulationsfehlanpassungen machen.

Sie können zwar Anfangswerte in Verilog oder VHDL verwenden, aber sie verringern die Portabilität Ihres Designs. Sie sind daher zu vermeiden und werden nicht empfohlen.

Die Gründe...

Ihr Design verhält sich je nach Zielgerät unterschiedlich. Synthetisieren Sie es für ein RAM-basiertes FPGA (Typ Altera, Xilinx) und Ihr Design wird funktionieren, da die Anfangswerte erkannt werden.

Synthetisieren Sie es für ein Flash-basiertes FPGA (Typ Microsemi), ein CPLD (Typ Altera, Lattice) oder einen ASIC und Ihr Design wird nicht funktionieren, weil die Anfangswerte bedeutungslos sind. Die Ursache ist nicht sofort ersichtlich, insbesondere wenn es sich nicht um Ihr eigenes Design handelt, so dass es Zeit und Kosten für die Entwicklung gibt, um es zu entdecken und zu überarbeiten.

Die Alternative...

Verwenden Sie einen Reset. RAM-basierte FPGAs bieten asynchrone (oder seltener synchrone) Resets auf ihren DFFs, sodass Sie das Routing, aber keine Ressourcen kosten. Das Design ist jetzt über alle CPLDs, FPGAs und ASICs hinweg portierbar.

Jedes Zielgerät muss nun für sich selbst einen Reset bereitstellen.

Dies könnte extern erzeugt und dann durch eine einfache Eingangsstufe geleitet werden, um ein asynchron behauptetes, synchron negiertes Reset durchzuführen, das Metastabilität in DFFs bei Negation vermeidet.

Oder es kann intern in einem RAM-basierten Gerät generiert werden, indem ein einfaches n-Bit-Schieberegister (ich verwende 4-Bit) mit einem Anfangswert von '0' verwendet und eine '1' verschoben wird. Ein Anfangswert kann hier auf diesem Schieberegister verwendet werden, und hier allein, weil (a) es zu demselben Rücksetzsignal an alle DFFs führt, wie es ein externes Rücksetzen tun würde, und (b) dies der einzige Teil ist, der sich ändert, wenn es sich um ein anderes Gerät handelt gezielt. Alle anderen Verilog/VHDL bleiben bei einem Geräte-Re-Target vollständig unverändert.

Der Abschluss...

Anfangswerte haben Fallstricke und können unsichtbare Probleme verursachen. Ein Reset geht und wird nicht.

Ich könnte sagen, es liegt an den professionellen Designern, was sie wählen ... aber das ist es nicht. Denn wenn sie nicht komplett alleine arbeiten, zahlen sie weder die Entwicklung noch tragen sie die Kosten der Folgen.

Wenn Sie professionell entwerfen, sollten Sie Ihrem Arbeitgeber oder Kunden möglichst problemlose Designs liefern, und dazu gehört auch die Portabilität. Sie machen es auch schwieriger, Ihre eigenen Designs wiederzuverwenden, wenn Sie in einem Jahr, fünf Jahren oder zehn Jahren woanders auf verschiedenen Geräten arbeiten. Die Designbesitzer (Ihr Arbeitgeber oder Kunde) erwarten, dass andere Ingenieure Ihre Designs, für die sie bezahlt haben, in verschiedenen Produkten mit verschiedenen Zielgeräten wiederverwenden können.

Die Tatsache, dass Ihr Design hier synthetisiert und funktioniert hat, beweist nichts, fürchte ich. In der Technik ist es sehr einfach, Designs zu erstellen, die funktionieren. (Denken Sie an diesen Kerl, dessen Regale kaum mit einem Nagel hängen, aber immer noch da sind.) Unser Ziel ist es, Designs zu machen, die niemals nicht funktionieren. Beim Entwurf digitaler Schaltungen ist dies eine Möglichkeit, dies viel wahrscheinlicher zu machen.

Viele Kunden, für die ich gearbeitet habe, verbieten aus all diesen Gründen einfach Anfangswerte in ihren Codierungsstandards. Die Mehrheit der IP, die Sie finden werden, insbesondere die IP von PLD-Anbietern, verwendet Resets aus den gleichen Gründen.

Zusammenfassend: Verwenden Sie keine Anfangswerte. Halten Sie Ihre Designs tragbar. Bleiben Sie berufs- und branchenübergreifend mobil. Verringern Sie die Fehlersuche aller.

Es gibt einen einfachen Weg, das zu vermeiden initial, der synthetisierbar ist: ein expliziter Reset-Mechanismus. Geben Sie Ihrem Modul eine resetEingabe und eine Anforderung, damit es während und für einige Zyklen nach dem Start bestätigt wird, um das Modul in einen gesunden Zustand zu versetzen.

Diese Anforderung kann leicht von einer Testbench erfüllt werden, Sie können auch überprüfen, dass keine XAusgaben durch das vollständige Design generiert werden (wir kümmern uns intern nicht so sehr darum), und Sie erhalten ein Design, das mit einem Syntheseprozess verwendet werden kann, der dies tut keine Anfangswerte zulassen oder in einem Kontext, der einen Shutdown-Mechanismus für Ihr Modul erfordert.