inferring latches - was ist hier die Ursache?

Persönliche Seite #7404566
Lesenswert?

Hallo Leute,

ich überarbeite gerade ein etwas älteres Verilog-Projekt und möchte dort die Anzahl der Warnings mal wieder auf ein akzeptables Niveau bringen. Das ganze findet unter Quartus Prime 22.1 lite statt.

An einer Sache beisse ich mir leider die Zähne aus: Warning (10240): Verilog HDL Always Construct warning at registers.v(22): inferring latch(es) for variable "r_flash_addr", which holds its previous value in one or more paths through the always construct (Im Anhang findet ihr registers_.v - ein Auszug aus der genannten registers.v - die Zeilennummer in der Warning habe ich an registers_.v angepasst)

Diese warning kommt genau so für die reg variablen r_flash_addr, r_flash_ctrl, r_flash_data_out, r_flash_write, r_flash_autoinc, r_flash_ctrl_wr, r_flash_data_wr, r_reconfig aber NICHT für die anderen reg variablen, die in diesem always construct verwendet werden.

Wo liegt also das Problem? Sicher weise ich nicht allen r_* variablen in jedem Zweig des doch etwas verschachtelten if/case Konstrukts einen Wert zu. Aber das ist ja nichts Ungewöhnliches, dass man Register updated, wenn eine Bedingung erfüllt ist. Und ein (synchrones) latch-Verhalten ist ja sogar gewünscht. Aber wieso warnt mich Quartus davor? Und wenn die Warning aus der Kategorie "kann man ignorieren" ist, würde ich trotzdem gerne verstehen, warum sie gerade in diesem speziellen Fall getriggert wird.

Und ja ich weiss, der Code ist gruselig. Er ist über die Zeit "gewachsen" und gehört auch dringend aufgeräumt. Aber da werdet ihr mich sicher noch ein paarmal drauf hinweisen, wofür ich mich schon jetzt bedanke. Noch viel mehr bin ich auf wirklich sachdienliche Beitraege gespannt! ;-)

Andi

Angehängte Dateien:
Moderator (Firma: Titel) Persönliche Seite #7404692
Lesenswert?

Thomas U. schrieb:

Weil dann ein Register entsteht?

Ja.

Und wenn dann die Meldung weg ist, dann hat es was mit dem asynchronen Reset zu tun.

Ist aber meine ich eine etwas diffuse Methode, latches zu vermeiden, oder?

Ja, sicher. Aber ich würde den Reset eh komplett rausmachen und mich auf die Initialwerte verlassen. Das FPGA wird beim Start sowieso Register für Register mit definierten Werten vorbelegt.

#7404702
Lesenswert?

Lothar M. schrieb:

Das Weglassen des Resets in der Sensitivliste macht implizit aus einem asynchronen Reset einen synchronen Reset.

Im Grunde ja, aber ... das ist keine Sensitivitätsliste, sondern da wird neben einer echten Taktflanke auch noch die Flanke vom Reset verwendet. Also in vhdl wäre das ein if falling_edge() then ... Und das wird wohl so nicht gebaut weil das nicht geht oder weil erkannt word, dass der Reset kein Takt ist.

Persönliche Seite #7404710
Lesenswert?

Gustl B> Nimm mal die negative Flanke von rstb raus Also, das negedge vom reset zu entfernen ist nicht zielführend. Danach glaubt die Synthese, dass es sich um einen reinen Logikblock handelt und will alle anderen Signale im always block auch noch in der sensitivity list haben. Das fuerhrt zu nichts

Lothar M.> Aber ich würde den Reset eh komplett rausmachen und mich auf Lothar M.> die Initialwerte verlassen. äh, ich möchte aber, das die Register bei einem externen Reset zurückgesetzt werden und nicht nur beim Konfigurieren des FPGA. Den Reset werde ich daher ganz sicher nicht weglassen!

Lothar M.> Das Weglassen des Resets in der Sensitivliste macht implizit aus
Lothar M.> einem asynchronen Reset einen synchronen Reset. Lothar M.> Und spätestens dann darf natürlich keine Warnung mehr kommen... Stimmt! Wenn ich den Reset ganz aus der sensivity list entferne, sind die Warnings weg. Damit habe ich den Reset fuer genau diesen Block jetzt also synchron gemacht. Das ist glaube ich auch ganz OK so, denn das rstb Signal wird ohnehin vom externen Reset Signal noch in die clkb-domain eingesynct. Der Reset ist daher also schon mehr oder weniger synchron.

Ich verstehe trotzdem noch nicht, warum ich die Warning in diesem speziellen Fall bekommen habe. Ich habe im Design hunderte solche always Blöcke mit genau diesem asynchronen reset. Ich habe nirgends inferred latches gemeldet bekommen. Nur hier! Warum? Und warum nicht für alle reg-Variablen im always block? Es bleibt für mich ein Rätsel.

Moderator (Firma: Titel) Persönliche Seite #7404766
Lesenswert?

Gustl B. schrieb:

da wird neben einer echten Taktflanke auch noch die Flanke vom Reset verwendet

Das ist zwar seltsam, dass der Reset augenscheinlich flankensensitiv aussieht, aber das ist halt einfach Verilog:

Andi M. schrieb:

äh, ich möchte aber, das die Register bei einem externen Reset zurückgesetzt werden und nicht nur beim Konfigurieren des FPGA.

Brauchst es das Design auch? Oder brauchst du das nur während der Entwicklung?

#7405200
Lesenswert?

Andi M. schrieb:

Gustl B.> Kannst du mal den kompletten Code posten? Leider nein :-(

Ein minimum working example wäre schon schick. Den obigen Code zu einem module machen und zeigen, dass sich das Verhalten damit reproduzieren lässt. Evtl. siehst du ja dann schon selbst ein Problem oder es wirft die Warnung gar nicht, so dass wir den Fehler anhand dieses Auszugs nie identifizieren könnten.

Worüber ich bei Verilog-Syntax gelegentlich stolpere, ist das begin und end (zumindest mein Editor zeigt die jeweilige Zugehörigkeit nicht so schön wie bei der Verwendung von Klammern). Entweder man vergisst es komplett, und dann wird nur die erste Zeile nach der Anweisung als zugehörig interpretiert; oder man setzt das end zu früh.

Mal angenommen, das end zu deinem clock-Block wäre zu früh, dann steht der Rest halt nicht synchron im Prozess und es baut einen Latch.

Moderator (Firma: Titel) Persönliche Seite #7405474
Lesenswert?

G. B. schrieb:

... aber nicht auf der Flanke des Resetsignals oder?

Nochmal: genau so, mit "negedge" oder "posedge", sieht in Verilog die Beschreibung eines Low- bzw. Highaktiven asynchronen Resets aus. Lies die Links.

So ungewohnt und unlogisch sich das liest: es ist einfach eines der Dinge, die man wissen muss und die bei Verilog halt einfach so sind.

Ich finde das auch sehr "tuitiv" (was das Gegenteil von "intuitiv" ist, so wie "tolerant" das Gegenteil von "intolerant" ist).

Gast #7405576
Lesenswert?

äh, ich möchte aber, das die Register bei einem externen Reset zurückgesetzt werden und nicht nur beim Konfigurieren des FPGA. Brauchst es das Design auch? Oder brauchst du das nur während der Entwicklung?

Brauchst es das Design auch? Oder brauchst du das nur während der Entwicklung?

Das Design verlangt dies.

Was verlangt die Spec. aka Design?

Einen Flanken-sensitiven Reset? Oder genügt das das FF auf ein externes Sugnal Pegelgesteuert hin einendefinierten Zustand (0 oder 1) annimmt.

Letzteres könnte man auch bei einem FF ohne dedizierten Reseteintgang erreichen, beispielsweise DD-FF mit Muxer?

Dort hat Xilinx ab p. 337 auf über 100 Seiten u.a. Verilog-Beispiele geliefert wie man die verschiedenen FF-Typen vom D-FF bis zum FJKSRE so coded, das der Synthesizer auch das geforderte macht. Also was forderst? Ein Register mit externen Reset? Erfüllt ein FDCP deine Anforderungen? Dann nimm den dort genannten Verilog Code.

Eine (ungeprüfte) Verhaltensbeschreibung ist im Anhang, enrnohmen aus https://www.physi.uni-heidelberg.de/~angelov/VHDL/VHDL_SS09_Teil10.pdf .


Ich finde das auch sehr "tuitiv" (was das Gegenteil von "intuitiv" ist, so wie "tolerant" das Gegenteil von "intolerant" ist).

Naja, das gesprochenen Wort ist nicht den harten Regeln der Logik wie bspw. Negation unterworfen. Als "Gegen-wort/-phrase" von intuitiv ("auf Vermutung beruhend") könnte man IMHO da eher "Nachrecherchiert" oder "verlangt auswendiges Lernen" setzen. Auswendig Lernen ist nicht so bequem wie "seinem Bauchgefühl folgen" oder "aus den Finger saugen", aber eben oft notwendig.

https://de.wiktionary.org/wiki/intuitiv

Angehängte Dateien:
#7405677
Lesenswert?

Der Code ist vermutlich nicht vor dir und deswegen willst du möglichst wenig ändern, das ist verständlich. Aber das Problem ließe sich vermutlich relativ leicht finden, wenn du den absurd komlizierten always-Block zerlegen würdest, indem die ganze kombiatorische Logik in eine eigene always-Umgebung kommt und der getaktete always-Block nur die Register enthält. So verlangen es die meisten Verilog-Designguides (außer bei sehr einfachen Designs) und das aus gutem Grund.

Zum Reset: Bist du sicher, dass der Reset einfach komplett einsynchronisiert wird, oder nur die inaktive (also steigende) Flanke? Manche Designs müssen auch Reset-fähig sein, wenn der Takt ausfällt oder noch nicht da ist, und dann verbietet sich ein synchroner Reset. In diesem Fall wird nur die "Rückseite" des Resets synchonisiert (https://www.embedded.com/asynchronous-reset-synchronization-and-distribution-challenges-and-solutions/) um Metastbilitäten zu vermeiden.

Abgesehen davon würde ich mich auf keinen Fall darauf verlassen, dass das Problem der obskuren Latches gelöst ist, nur weil dann die Fehlermeldung verschwindet, wenn du einen synchronen Reset verwendest.

Persönliche Seite #7405791
Lesenswert?

Lothar M. schrieb:

Thomas U. schrieb:

Weil dann ein Register entsteht?

Ja.

Das scheint einigen nicht so klar zu sein. Jüngst gab es eine Diskussion im Rahmen einer Projektbewerbung, da wollte ein Schlaumeier unbedingt testen, ob ich wüsste, wie solche latches entstehen. Mein Beispiel war genau dieses, das Weglassen eines Registers durch mangelnde Beschreibung. Er war wehemend der Meinung dass das nicht gehe und dadurch nichts passieren könne. War ein Physiker, der sich VHDL selber beigebracht hat. :-)

Vancouver schrieb:

Manche Designs müssen auch Reset-fähig sein, wenn der Takt ausfällt oder noch nicht da ist,

ja, die Panik vom vor sich hin schludernden FPGA, dessen Ausgänge nicht definiert sind, weil die PLL nicht will oder noch nicht kann. Schaut man sich mal an, wie lange ein FPGA beim power up lädt und praktisch nicht in der Schaltung ist und wie schnell ein Oszillator anfängt, dann bleiben von den Sekunden des Tiefschlafs bis zum Erwachen gerade einige us, in denen ein solcher Reset überhaupt noch einen kleinen Unterschied macht. Wenn man die Elektronik so baut, dass sie mit einem schlafenden FPGA klarkommt, also die Ausgänge steuert und damit alles innendrin abhängt, braucht man keine gewaltigen Resetbäume und die auch nicht asynchron.

In diesem Fall wird nur die "Rückseite" des Resets synchonisiert

was auch schon resourcen verbraucht und zusammen mit dem aysynch Part noch mehr verbrutzelt ohne wirklichen Wert. Ein FPGA dessen PLL nicht will und das nicht synchron arbeitet, kann auch nach dem schönsten reset nicht mehr weiterarbeiten, von daher ist das eh Wuppe. Wichtiger ist ein PLL-unabhängier Anlauf- und Überwachungsschaltkreis, der power on losläuft, die Ausgänge bedient und PLLs bootet (und alles andere, was so in Blockdiagrammen an MCU- und AXI Gedöhns instanziiert wird).

Vancouver schrieb:

um Metastbilitäten zu vermeiden.

Naja, die MS sind eher unwahrscheinlich - es geht einfach um den Resetbaum an sich und den Umstand, dass auch ganz ohne Meta das Signal an unterschiedlichen Stellen anders eingetaktet wird und damit ungültige Zustände entstehen, weil die vielen lokalen FFs es zu leicht anderen Zeiten "sehen". Das passiert im Übrigen auch beim Resetten selber: Je nach Länge der Kombinarik in einer Schaltung, produziert der aysnch reset auch kurz ungültige Zustände und so kann man beim resetten durchaus Hazzards an den Ausgängen sehen, die es im synchronen Fall nicht gäbe.

Daher: Primär die Ausgänge des FPGAs steuern und gut ist. Dann brauchen viele Schaltungsteile keinen Reset und schon gar keinen asynchronen.

#7406702
Lesenswert?

Jürgen S. schrieb:

ja, die Panik vom vor sich hin schludernden FPGA, dessen Ausgänge nicht definiert sind, weil die PLL nicht will oder noch nicht kann. Schaut man sich mal an, wie lange ein FPGA beim power up lädt und praktisch nicht in der Schaltung ist und wie schnell ein Oszillator anfängt,

Es gibt schlichtweg Designs, die solche Anforderungen haben, weil sie sonst keine Sicherheitszertifizierung bekommen. Und manchmal muss erst ein Microcontroller booten und die PLL konfigurieren, bevor der FPGA loslegen kann. Und machmal möchte man eben nur Teile des FPGAs resetten, während der Rest weiterlaufen soll. Und manchmal möchte man hinterher wissen, welches Ereignis für den Reset verantwortlich war, und es dazu in einem Register speichert. Und manchmal verwendet man FPGA als Prototyping für ASICs, und bei denen klappt der Trick mit dem Neukonfigurieren nicht. Und machmal möchte man ein Design einfach nur plattformumabhängig halten. In allen anderen Fällen braucht man keinen Reset.

Jürgen S. schrieb:

was auch schon resourcen verbraucht und zusammen mit dem aysynch Part noch mehr verbrutzelt ohne wirklichen Wert.

Wenn die drei zusätzlichen FFs ein Problem sind, ist das Design ohnehin schon reichlich auf Kante genäht, dann hast du andere Probleme...

Gast #7412124
Lesenswert?

Lothar M. schrieb:

Ja, sicher. Aber ich würde den Reset eh komplett rausmachen und mich auf die Initialwerte verlassen. Das FPGA wird beim Start sowieso Register für Register mit definierten Werten vorbelegt.

Beim Xilinx allemal. Beim Altera war das aber doch anders? Die propklamieren doch ihren asynchronen Eingang für die FlipFlops.

Moderator (Firma: Titel) Persönliche Seite #7415498
Lesenswert?

T.U.Darmstadt schrieb:

Beim Altera war das aber doch anders? Die propklamieren doch ihren asynchronen Eingang für die FlipFlops.

Auch bei Altera/Intel können die Flipflops schon lange mit Initalwerten vorbelegt werden:

Und das, was im Code oben als Resetwerte angegeben ist, sind also eigentlich genau solche Initialwerte.

Ein Reset ist das, was im FPGA laufend passiert: ein Zähler oder ein Register oder ein Flipflop wird zurückgesetzt. Dafür ist der Reset-Eingang am Flipflop da. Und dafür sollte der Code dann so geschrieben sein, dass passend zum verwendeten FPGA was Effizientes herauskommt:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren