So vermeiden Sie Latches während der Synthese

Ich möchte einen Block kombinatorischer Logik mit VHDL entwerfen, aber gelegentlich enthält das synthetisierte Ergebnis einen unbeabsichtigten Latch.

Welche Codierungsrichtlinien muss ich befolgen, um zu vermeiden, dass der Synthesizer auf Latches schlussfolgert?

Beispiel: Sollte ich in einem kleinen Codesegment if-else-Anweisungen verwenden?

Ich war mir nicht sicher, was du mit deinem Beispiel meinst. Bitte überprüfen Sie, ob die Umformulierung Ihrer ursprünglichen Absicht entspricht.

Antworten (4)

Um Latches zu vermeiden, müssen Sie sicherstellen, dass alle Ihre Ausgänge allen möglichen Zweigen des Codes zugewiesen sind.

zum Beispiel,

if a = '1' then
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

würde einen Latch erzeugen, da in der ersten Bedingung der Wert von b(1) nicht angegeben ist, sodass der Compiler entschieden hat, dass Sie den vorherigen Wert von b(1) dort behalten möchten. Eine Möglichkeit, dies zu schreiben, die keinen Latch erzeugen würde, ist:

if a = '1' then
   b <= prev_b;
   b(0) <= '1';
else
   b(1 downto 0) <= "00";
end if;

...

if rising_edge (clk)
    prev_b <= b;
end if;

Hier geben Sie explizit an, dass b seinen alten Wert behalten soll, und überschreiben dann b(0) mit dem neuen Wert.

Eine andere Möglichkeit besteht darin, einen Standardwert anzugeben, wie in der Antwort von @TomiJ.

Wenn Sie den Code posten, den Sie erhalten, können wir Ihnen helfen, den genauen Grund zu finden.

Ich glaube nicht, dass Ihr Ansatz b <= beine Verriegelung vermeiden wird, da der Zustand des Signals immer noch erhalten bleiben muss.
Du könntest Recht haben; Ich bin zu sehr an getaktete Logik gewöhnt. Ich werde bearbeiten.

Vier Regeln zur Vermeidung von Latches:

  • Lesen Sie nicht von den Signalen, auf die Sie schreiben.
  • Haben Sie eine korrekte Sensitivitätsliste (alle Signale, die Sie lesen, sollten in der Sensitivitätsliste enthalten sein)
  • Stellen Sie sicher, dass alle Signale, denen Sie schreiben, in jedem Pfad zugewiesen sind. (zum Beispiel: in jedem Zweig einer if-else-Anweisung)
  • Stellen Sie bei Prozessen, die Variablen verwenden, sicher, dass jede Variable mit einem Standardwert initialisiert wird, bevor Sie sie lesen (in einer anderen Variablen oder einem anderen Signal).

Wenn Sie mehrere kombinatorische Prozesse haben, stellen Sie außerdem sicher, dass Sie keine Schleife erstellen.

Mehrere Codierungsstile können Ihnen helfen, sich an diese Regeln zu halten, zum Beispiel der Stil in der Antwort von @TomiJ. Wie @Martin Thompson betont, ist es möglicherweise besser, kombinatorische Logik insgesamt zu vermeiden. Legen Sie stattdessen alles in einen getakteten Prozess.

+1 Schönes Regelwerk. Würden Sie zustimmen, dass Ihre Regel Nr. 2 (über die Sensitivitätsliste) tatsächlich wichtig ist, um konsistente Ergebnisse zwischen Synthese und Simulationen sicherzustellen, aber keinen wirklichen Unterschied bei der Inferenz von Latches macht?
@rick AFAIK, es gibt keine Garantie dafür , was ein Synthesetool mit unvollständigen Sensitivitätslisten macht. Der IEEE-Standard für VHDL-Synthese (1076.6-1999) besagt: „Die Prozesssensitivitätsliste muss alle Signale enthalten, die in der Prozessanweisung gelesen werden. Prozesse mit unvollständigen Sensitivitätslisten werden nicht unterstützt.“ Allerdings weiß ich, dass bestimmte Synthesewerkzeuge (vielleicht alle?) unvollständige Sensitivitätslisten akzeptieren , aber die Sensitivitätsliste einfach insgesamt ignorieren . Wenn Sie sich auf dieses Verhalten anstelle des strengeren IEEE-Standards verlassen würden, wäre Ihre Aussage wohl richtig.
Danke, das klingt richtig, es würde mein Modell nicht mit diesem Standard konform machen. Es hat nur meine Neugier geweckt, weil alle Synthesewerkzeuge, die ich bisher gesehen habe, die Empfindlichkeitsliste ignorieren, aber ich habe Gerüchte gehört, dass einige Latches ableiten könnten.

Wenn Sie Prozesse für kombinatorische Logik verwenden (und ich rate aus genau diesem Grund davon ab), dann stellen Sie sicher, dass jeder Pfad durch den Prozess jedem Signal, das der Prozess antreibt, etwas zuweist. Keine der Ausgaben kann von irgendeiner der Ausgaben vom "letzten Mal", als der Prozess lief, abhängig sein.

Andernfalls leiten Sie ein Latch ab, da der Prozess beim nächsten Einplanen den Wert des Signals beibehalten muss, das beim letzten Mal keinen neuen Wert erhalten hat.

Ich ziehe es vor, eine rein kombinatorische Logik als kontinuierliche Zuweisungen beizubehalten und Prozesse für getaktete Logik zu verwenden, dann bekomme ich keine Latches.

Wie von @fbo und @Martin Thompson betont, müssen Sie sicherstellen, dass jedem vom Prozess angesteuerten Signal in jedem Zweig des Prozesses ein bestimmter Wert zugewiesen wird, und dieser Wert darf nicht vom vorherigen Zustand eines der Ausgänge abhängen des Prozesses.

Der einfachste Weg, dies sicherzustellen, besteht darin, jedem Ausgang ganz am Anfang des Prozesses einen Standardwert zuzuweisen, zum Beispiel (Kooptierung des Beispiels von fbo):

COMBO: process(a)
begin
    b <= (others => '0'); -- Assign default value to b
    if a = '1' then
        b(0) <= '1';
    else
        b(1 downto 0) <= "00";
    end if;
end process COMBO;
Dies ist eine gute Methode, die ich oft verwende. Manchmal kann Ihnen eine Latch-Warnung jedoch anzeigen, dass Sie vergessen haben, einige Bits zuzuweisen, während diese Methode das Auffinden des Fehlers möglicherweise erschwert. Zum Beispiel, wenn Sie alle Bits eines breiten Signals separat zugewiesen und versehentlich falsch gezählt haben.
Nur in einem kombinatorischen Prozess. In einem getakteten Prozess leiten Sie ein Flipflop ab, das genau das sein kann, was Sie wollen.