D-Flip-Flop-Simulation: Welcher Simulationsausgang ist richtig?

Ich habe mich immer gefragt, was die richtige Lösung für das D-Flip-Flop ist, wenn sich der Eingang direkt an der steigenden Flanke des Takts ändert? Ich habe zwei Lösungen davon online gefunden, habe aber keine Ahnung, welche die richtige ist.

Bild 1

oder

Bild 2

Ich denke, die richtige Antwort sollte Bild 1 (oben) sein, wo der Ausgang q bei der nächsten steigenden Taktflanke erscheint. Dies ist, was Flip-Flop tun sollte, dh eine Verzögerung von einem Zyklus erzeugen.

Aber ich bekomme immer Bild 2 (unteres Bild), wenn ich meinen Verilog-Code ausführe. Mein Code ist:

module beh(q,d,en,clk);
input q,clk,en;
output d;
reg d;
always@(posedge clk)
begin
if(en==1)
d<=q;
end
endmodule

Was mache ich falsch?

Antworten (1)

Das erste ist im Allgemeinen , wie es aussehen soll, da der Ausgangspegel NACH der aktiven Taktflanke den Eingangspegel VOR der aktiven Taktflanke widerspiegeln sollte. Wenn der Eingangsübergang jedoch auf die aktive Taktflanke fällt, ist dies mehrdeutig, da es sich technisch gesehen um eine Verletzung der Setup-and-Hold-Zeit handelt. In diesem Fall bestimmt der Unterschied zwischen der Verwendung von <= und = in Ihrer Testbench, ob Sie #1 oder #2 erhalten. Dies liegt an der Funktionsweise von Delta-Zyklen. Wenn Sie = in der Testbench verwenden, wird der neue Wert sofort zu Beginn des Zyklus am Eingang des Flipflops gespiegelt und Sie erhalten #2. Wenn Sie jedoch <= verwenden, wird der neue Wert am Ende des Aktualisierungszyklus widergespiegelt und Sie erhalten #1.

Ich habe mehrere verschiedene Testbench-Iterationen durchlaufen, um die effektivste zu finden. Zuerst habe ich = in der Testbench für den Taktgenerator und für die Testbench-Logik verwendet und die Testbench-Logik lief auf der fallenden statt auf der steigenden Flanke. Dadurch wurden die Spuren im Simulator etwas offensichtlicher (auf halbem Weg zwischen Nr. 1 und Nr. 2), jedoch stieß ich auf einige Zeitprobleme, als ich versuchte, eine tiefere Interaktion zwischen der Testbench und dem DUT zu erreichen. Am Ende bin ich dazu übergegangen, = im Taktgenerator und <= in der Testbench zu verwenden und die Testbench auf die Verwendung der steigenden Flanke der Uhr umzustellen. Dies sah am Ende wie Ihre Nr. 1 aus und löste die Interaktionsprobleme, die ich hatte. Jetzt verwende ich das Python-basierte MyHDL für den funktionalen Teil der Testbench mit einem Verilog-Wrapper für das DUT, aber das ist eine ganz andere Geschichte.

"es ist mehrdeutig, da es technisch gesehen eine Verletzung der Setup-and-Hold-Zeit ist." Es hängt alles von der Hardware ab. In FPGAs sind Null-Haltezeit-Spezifikationen üblich. In der 7400-Logik ist eine positive Haltezeit erforderlich. Ich arbeite nicht in ASICs, also kann ich dazu nichts sagen.
Ja, ich nehme an, es ist nicht in allen Fällen eine Verletzung. Ich denke, es ist ein größeres Problem in der Simulation als in einer realen Schaltung, weil das Setup-and-Hold im Simulator im Grunde genommen null ist, da es den Pegel in einem ganz bestimmten Simulatorzyklus überprüft und nicht früher oder später.
Wenn sich der Eingang direkt an der Taktflanke ändert, wird die Einrichtungszeitspezifikation der realen Hardware ungleich Null verletzt. Die Haltezeitspezifikation ist oft 0, aber ich habe noch nie ein FPGA oder eine andere echte digitale Logik mit null Einrichtungszeit gesehen. (Die reale Einrichtungszeit variiert von Teil zu Teil und variiert mit der Temperatur.) Die Simulation sollte versuchen, der Realität zu entsprechen, was sonst der Sinn ist. Ich wette, wenn Sie die Simulation anstelle post-synthesis modeldes idealen behavioralModells ausführen, sollten Sie die richtige Wellenform sehen (Q-Ausgang um einen Taktzyklus verzögert).
@MarkU, wenn Sie gleichzeitige Übergänge auf Uhr und Daten als Nullhaltezeit behandeln, ist die Einrichtungszeit ein vollständiger Taktzyklus.
Großartig! Wie wäre es, wenn ich die Bild 1-Lösung in VHDL haben möchte, welche Änderungen dort in der Testbench vorgenommen werden?
@MarkU: Es ist möglich, echte Hardware ohne Einrichtungszeit zu konstruieren, indem eine kleine Verzögerung zwischen dem eingehenden Taktsignal und dem Takteingang der internen Register hinzugefügt wird. Dies wird nicht sehr oft gemacht (Null-Haltezeit, die durch Verzögern der Dateneingabe erreicht wird, ist häufiger nützlich), kann aber nützlich sein, wenn Sie versuchen, bestimmte Protokolle zu realisieren.