Hallo zusammen,
ich beschäftige mich neuerdings etwas mit VHDL und teste erste einfache
VHDL Beispiele und versuche mich selber reinzufinden.
Nun habe ich folgenden Code und die im Bild gezeigte Simulation:
1
PROCESS(CLK,NRES)
2
BEGIN
3
IFNRES='0'THEN
4
data<=(OTHERS=>'0');
5
ELSIFrising_edge(CLK)THEN
6
IFen='1'THEN
7
data<=16#A2EB#;
8
ENDIF;
9
ENDIF;
10
ENDPROCESS;
Ich denke, dass dieser Prozess 16 FlipFlops beschreibt, die bei einer
steigenden Taktflanke den Wert 0xA2EB übernehmen sollen.
Wieso aber passiert das erst genau einen Takt später?
Mit en = '1' und der steigenden Flanke sind doch beide Kriterien
erfüllt, damit die Daten übernommen werden.
Irgendwie hätte ich erwartet, dass die Daten kurz nach der Flanke
anliegen. Sie werden mit der Flanke gespeichert und dann dauert es ein
paar ns (Gatterlaufzeit?), bis der Wert am Ausgang erscheint?!
Oder wird mit der ersten Flanke nur das en = '1' und dann erst genau
einen Takt später die Daten übernommen?
Was könnte ich tun um den Takt Verzögerung zu umgehen, aber dennoch
synchron zu arbeiten, was ja immer empfohlen wird?
Könnte mir das bitte jemand erklären, dass auch ein Anfänger das
versteht?
Vielen Dank!
Michael
Michael K. schrieb:> Wieso aber passiert das erst genau einen Takt später?
tut es nicht
> Mit en = '1' und der steigenden Flanke sind doch beide Kriterien> erfüllt, damit die Daten übernommen werden.
bei der "ersten" Taktflanke ist en noch auf 0, es schaltet erst mit
dieser Taktflanke auf 1.
Bei der nächsten Taktflanke wird dann en als 1 ausgewertet und die Daten
werden übernommen (und en schaltet unmittelbar danach wieder auf 0). Die
Daten werden also genau bei der Taktflanke übernommen, bei der en='1'
erfüllt ist.
Michael K. schrieb:> Mit en = '1' und der steigenden Flanke sind doch beide Kriterien> erfüllt, damit die Daten übernommen werden.> Irgendwie hätte ich erwartet, dass die Daten kurz nach der Flanke> anliegen. Sie werden mit der Flanke gespeichert und dann dauert es ein> paar ns (Gatterlaufzeit?), bis der Wert am Ausgang erscheint?!
Du hast hier offenbar eine Verhaltenssimulation. Die bildet keine
Laufzeiten ab, und das ist auch nicht nötig. Denn das Timingdiagramm ist
so zu lesen: vor der Taktflanke ist das enable-Signal '1' und deshalb
werden mit der Taktflanke die dort anliegenden Daten übernommen. Für ein
Flipflop ist also bei der Verhaltensimulation nur das interessant, was
links der Taktflanke liegt. Und durch den Takt ergibt sich das, was
rechts der Taktflanke liegt.
> en = '1' und der steigenden Flanke
Das ist also erst an der Taktflanke gegeben, wo auch korrekterweise der
Wechsel auf data passiert.
Also müsste man die Simulation übertrieben gesehen so zeichnen, damit es
korrekt ist?
Die blauen Linien markieren die steigenden Flanken und die Zeit bis zum
Event sind dann die Gatterlaufzeiten? Sind also alle Signale außer der
CLK um die Gatterlaufzeiten nach rechts verschoben?
Wenn ja, finde ich die Darstellung des Simulators echt verwirrend...
Michael K. schrieb:> Also müsste man die Simulation übertrieben gesehen so zeichnen, damit es> korrekt ist?
Sie wird im echten Leben in etwa so aussehen. Allerdings werden da evtl.
noch deutlich unterschiedlichere Zeiten zu sehen sein.
> Wenn ja, finde ich die Darstellung des Simulators echt verwirrend...
Naja, du hast einfach noch nicht die ausreichend abstrakte Denkweise
erreicht ;-)
Du machst da eine Verhaltenssimulation ohne jeglichen Zeitbezug, und
deshalb passiert der Wechsel eben sofort mit (weil durch) die
Taktflanke. Wenn du das mal kapiert hast, dann gibt es nur noch ein
"links der Flanke" und "rechts der Flanke".
Du könntest jetzt natürlich eine Timingsimulation machen, da könntest
du dann diese Laufzeiten sehen. Aber glaub mir: du brauchst das nicht,
die Verhaltenssimulation ist schneller und es gibt keine wegoptimierten
Signale oder sonstwas...
Michael K. schrieb:> Also wäre es in diesem Fall immer "rechts der Flanke"...
Interessanter für das Enable Signal und irgendwelche Datenübernahmen ist
immer links vom Takt (also vor dem Takt). Denn dort müssen die
Steuersignale und Daten angelegt werden oder worden sein, dass sie mit
dem Takt übernommen werden können...
Lothar hat´s ja schon gesagt, aber vielleicht eine plakativere
Erklärung:
Ein FlipFlop schaut BEI der Flanke, in welchen Zustand sich die Eingänge
befinden. Dazu müssen in diesem Moment die Eingänge stabil SEIN.
Ein reales FlipFlop benötigt dafür sogar eine gewisse "Vorlaufzeit". Das
heißt, es gibt eine Zeitspanne VOR der Flanke, wo die Eingänge sich
nicht mehr ändern dürfen, sonst funktioniert das FlipFlop nicht
erwartungsgemäß.
Diese Setup-Zeit muss immer eingehalten werden.
Weiterhin gibt es dann eine Verzögerungszeit, die es braucht, bis sich
die Eingangsinformation nach der Flanke auf den Ausgang des FlipFlop
durchgeschlagen haben.
Daher wird sich in einem realen (und funktionierendem Design) niemals
ein Signal exakt MIT der Taktflanke ändern.
Die Eingänge der FFs müssen VOR der Flanke stabil sein und die Ausgänge
der FFs werden erst kurz NACH der Flanke aktualisiert.
Dazu noch die üblichen Fachbegriffe für die weitere Recherche:
tsu Setup Time (vor Flanke stabil)
th Hold Time (nach Flanke stabil)
tco Clock to Output Delay (Laufzeit durch das Flipflop)
Und für Kombinatorik:
tpd Propagation Delay (Laufzeit durch Kombinatorik)
Aber wie schon erwähnt: in der Verhaltenssimulation sind alle diese
Zeiten Null. Deshalb ändern sich die Signale alle genau zur und mit der
Taktflanke.
Mir hilft immer eine symbolische Laufzeit
PROCESS (CLK, NRES)
BEGIN
IF NRES = '0' THEN
data <= (OTHERS => '0');
ELSIF rising_edge(CLK) THEN
IF en = '1' THEN
data <= 16#A2EB# after 5 ns;
END IF;
END IF;
END PROCESS;
en <= a and b after 5 ns;
Frank schrieb:> Mir hilft immer eine symbolische Laufzeit
Damit modellierst du aber nur tco (eines schnarchlangsamen FF) und tpd
Und synthetisierbar ist das auch nicht..
zur Anschauung im Simulator vielleicht mal geeignet, aber technisch
bringt einen das Einfügen von after-statements nicht weiter.
Aber klar, man kann es sich mal im Simulator anschauen
Frank schrieb:> Mir hilft immer eine symbolische Laufzeit
Mein Tipp: niemals so eine Denkkrücke einbauen!
Der Kollege im Beitrag "Functional Simulation mit Modelsim" hat
das selbe Problem. Und darin gibt es dann den Link auf den
Beitrag "Re: Frage zu Pseudozufallsgenerator!?", wo die Gefahr auch
mal näher erläutert wird: der Simulator verwendet die symbolischen
Zeiten, der Synthesizer aber nicht.
Fazit: Simulation passt nicht zur Realität. wozu dann also eine
Simulation?
Die Laufzeiten tauchen natürlich nur in der Simulation auf. Darum auch
symbolisch... Ohne diese liegt bei der Simulation Signal sofort am FF an
in der Realität gibt es Laufzeiten. Wozu also noch simulieren?
Frank schrieb:> in der Realität gibt es Laufzeiten.> Wozu also noch simulieren?
Eine Verhaltenssimulation simuliert das Verhalten einer
VHDL-Beschreibung. Eine Timingsimulation simuliert das Timing eines
implementierten Designs mit den echten Laufzeiten des Bausteins.
Wenn man weiß, wie man so eine Waveform zu lesen hat, dann reicht in
99,x% (x nahe bei 9) eine Verhaltenssimulation zusammen mit vernünftigen
Constraints aus.
> in der Realität gibt es Laufzeiten.> Wozu also noch simulieren?
Ind er Realität läuft so ein Design mit 100MHz, im Simulator gerade mal
mit (wenns hoch kommt) 100Hz. Wozu also noch simulieren? Und zudem hat
der Simulator keine Verbindung zur realen Hardware. Wozu also noch
simulieren?
Es gibt zig belegbare Gründe gegen die Verwendung von symbolischen
Laufzeiten und keinen vernünftigen dafür. Dass die Darstellung
"ungewohnt" ist, ist für mich kein rationaler Grund!
Lothar Miller schrieb:
Eine Timingsimulation simuliert das Timing eines
> implementierten Designs mit den echten Laufzeiten des Bausteins.> Wenn man weiß, wie man so eine Waveform zu lesen hat, dann reicht in> 99,x% (x nahe bei 9) eine Verhaltenssimulation zusammen mit vernünftigen> Constraints aus.
Naja die Timing Simulation arbeitet keineswegs mit den echten
Laufzeiten. Allerhöchstens mit realitätsgetreuen Laufzeiten.
Ich habe schonmal was von Abweichungen von bis zu 100% gehört.
Frank schrieb:> Naja die Timing Simulation arbeitet keineswegs mit den echten> Laufzeiten. Allerhöchstens mit realitätsgetreuen Laufzeiten.> Ich habe schonmal was von Abweichungen von bis zu 100% gehört.
Sie rechnet mit Worst-Case (und evtl. wählbar mit BestCase) Zeiten, aber
sie bildet eben auch keine Realität nach (Temperatur- und
Spannungabhängigkeit der Zeiten), und insbesondere keinen Jitter durch
Einkopplungen oder sonstwas...
Gerade darum ist eine Timing Simulation idR. rausgeowrfene Zeit. eine
funktionelle simulation und richtige Constraints bringen da mehr.
Darum schreibe ich "after 2 ns" damit es für mich deutlicher wir das
Prinzip rechts oder links vom Flip Flop. Pseudotakte könnten tatsächlich
ein Problem sein. Aber wenn ich eine symbolische Laufzeit von 2 ns
einbaue und einen Takt von 50 MHz simuliere, denn erwarte ich in dieser
Hinsicht keine Probleme. Wenn man Pseudotakte erkennt, kann man
immernoch nachschauen woran es liegt. Vielleicht bin ich aber auch
unbelehrbar....
Timingsimulationen halte ich auch für verschwendete Zeit. Kritische
Stellen lassen sich auch bei der Sichtung der Timinganalyse erkennen.
Frank schrieb:> Wenn man Pseudotakte erkennt, kann man immernoch nachschauen woran es> liegt.
Nun, eine kombinatorische Schleife ist dann eben keine mehr und der
Simlator simuliert hier mit dem Pseudotakt munter weiter (Fall A), statt
sofort mit einem Iterationsüberlauf abzubrechen (Fall B):
1
Fall_A:process(cntA)begin
2
cntA<=cntA+1after10ns;
3
endprocess;
4
5
Fall_B:process(cntB)begin
6
cntB<=cntB+1;
7
endprocess;
Üblicherweise sind solche Fehler deutlich besser versteckt und zudem
noch gegated, so dass sie erst nach einer beliebigen Zeit auftreten...
OK, soetwas ist mir noch nicht passiert. Was Kombinatorische Schleifen
angeht magst du Recht haben. Allerdings kann man die bei der Simulation
immernoch als soche erkennen. Lediglich abbrechen würde der Simulator
nicht mehr.