Nein. Ein getakteter Prozess (clk'event ... oder "korrekter" mit
rising/falling_edge) erzeugt IMMER "echte" Flipflops
(taktflankengesteuert/Master-Slave/... *) für ALLE Signale, denen was
zugewiesen wird (oder werden könnte).
Kritisch sind Prozesse die auf "alles" reagieren und nicht nur auf eine
Flanke. **)
*) Latches vs. Flipflop: Üblicherweise sagt man zu pegelgesteuerten
Speichergliedern (zB. RS) "Latches", zu flankengesteuerten
(edge-triggered) nur "Flipflop". Leider wird FF auch gern als
Oberbegriff für alles benutzt.
**) Die Phobie vor Latches bei FPGAs kommt daher, dass sie (meistens)
nicht auf spezialisierte HW implementiert werden (wie FFs) sondern mit
einem Feedback über die Verdrahtung. Das sorgt für recht
unvorhersehbares Timing und potentiell Glitches. Letzteres haben
Schaltungen mit Latches aber eh so an sich ;)
Die üblichen Synthesetools warnen dich übrigens, wenn Latches inferiert
werden. Also keine Panik, einfach die Logs prüfen, ggf. den Code schief
von der Seite angucken und das Problem entdecken.
Jup danke.
---------------------
Nein. Ein getakteter Prozess (clk'event ... oder "korrekter" mit
rising/falling_edge) erzeugt IMMER "echte" Flipflops
-----------------------
Wie sieht es aus wenn dieser Process eine Empfindlichkeitsliste hat ohne
"clk" ?
Danke.
Gruss
peter schrieb:> Wie sieht es aus wenn dieser Process eine Empfindlichkeitsliste hat ohne> "clk" ?
Das kommt darauf an, ob im Prozess trotzdem ein 'event oder ein *_edge()
abgefragt wird. Die Sensitivliste an sich ist NUR und AUSSCHLIESSLICH
für die Simulation relevant!
-----------------------------------------
Die Sensitivliste an sich ist NUR und AUSSCHLIESSLICH
für die Simulation relevant!
-----------------------------------------
Ohne Sensitivliste und ohne Event wird der Process nicht compiliert. Es
kommt ein Error. Wenn ich diese Sensitiv ohne Event mache , wird das
Programm compiliert.
Danke.
Gruss
peter schrieb:> -----------------------------------------> Die Sensitivliste an sich ist NUR und AUSSCHLIESSLICH> für die Simulation relevant!> -----------------------------------------
Nicht ganz richtig.
Um Flipflops aus der Bechreibung abzuleiten wird eine Clock in der
Sensitivityliste gebraucht. Wenn dieses Register einen asynchronen Reset
haben soll, auch noch das Reset Signal.
Details dazu stehen in den Coding Guidlines des verwendeten
Synthesetools.
1
process(clk)
2
begin
3
ifclk'eventandclk='1'then
4
ff<=Sonstwas;
5
endif;
6
endprocess;
oder moderner
1
process(clk)
2
begin
3
ifraising_edge(clk)then
4
ff<=Sonstwas;
5
endif;
6
endprocess;
"Sonstwas" muss nicht in die Liste, denn auch der Simulator braucht den
Prozess für eine funktionale Simulation nur bei der Clockflanke
berechnet zu werden.
Lattice User schrieb:> Um Flipflops aus der Bechreibung abzuleiten wird eine Clock in der> Sensitivityliste gebraucht.
Nein.
Sowas wird tadellos synthetisiert aber vollkommen falsch simuliert:
1
process(taster)begin-- eine falsche Sensitivliste
2
ifrising_edge(clk)then
3
toggle<=nottoggle;
4
endif;
5
endprocess;
> Um Flipflops aus der Bechreibung abzuleiten wird eine Clock in der> Sensitivityliste gebraucht.
Sowas wird tadellos synthetisiert und korrekt simuliert:
1
processbegin-- überhaupt keine Sensitivliste
2
waituntilrising_edge(clk);-- aber dafür ein wait
3
toggle<=nottoggle;
4
endprocess;
peter schrieb:> Ohne Sensitivliste und ohne Event wird der Process nicht compiliert.
Das ist eine andere Baustelle. Dass man natürlich syntaktisch eine
Sensitivliste und/oder ein "wait" im Prozess braucht, ist im VHDL
Standard definiert.
Jup danke.
was heisst hier "moderner"? Ist das andere Fehlerbehaftet?
--------------------------
oder moderner
process(clk)
begin
if raising_edge(clk)then
ff <= Sonstwas;
end if;
end process;
----------------------------
Danke.
peter schrieb:> Ohne Sensitivliste und ohne Event wird der Process nicht compiliert. Es> kommt ein Error.
Klar:
Es gibt 2 Arten von Prozessen:
Ein Prozess braucht entweder eine Sensitivity List oder (mindestens) ein
wait Statement.
VHDL ist wie schon oft geschrieben, eine Sprache für die Simulation von
Hardware und die Hardware wird mit Prozessen modelliert.
Man stellt sich Hardware einfach als Blöcke vor.
Diese Blöcke haben Eingänge, und aus dem Zustand der Eingänge ergeben
sich die Aufgänge.
Die Simulation braucht die Ausgänge nicht dauernd neu zu berechnen, das
wäre unsinnig.
Nur wenn sich an den Eingängen etwas ändert, muss der Ausgang
aktualisiert werden.
Das ist der Sinn einen Prozesses. Die Eingänge sind in der sensitivity
list auflistet und der Prozess startet die Berechnung der Ausgänge wenn
sich dort etwas ändert. Deshalb heißt sie auch sensitivity list, könnte
auch trigger list heißen.
Der solcher Prozess startet am Beginn, führt alle Statements sequentiell
aus und stoppt am Ende.
Ein solcher Prozess ohne sensitivity list macht somit keinen Sinn, da er
niemals startet.
Bei der zweiten Veriante von Prozessen läuft der Prozess dauernd die
Runde (salopp gesprochen) und startet beim Erreichen des letzten
Statements wieder am Beginn.
Damit die Berechnung aber irgendwann aufhört und die Simulation in der
Zeit weiterrücken kann, müssen irgendwo im Prozess wait-Statements
vorhanden sein, wo der Prozess stoppt und erst bei Erreichen eine
bestimmten Bedingung weitergeführt wird.
Auch damit kann man FF simulieren und das wird in der Zwischenzeit von
der Synthse auch unterstützt.
Liebe Experten: Eingige Details habe ich unterschlagen, also bitte nicht
hauen.
Klaus Falser schrieb:> Eingige Details habe ich unterschlagen
Einen hätte ich noch...
> Damit die Berechnung aber irgendwann aufhört und die Simulation in der> Zeit weiterrücken kann, müssen irgendwo im Prozess wait-Statements> vorhanden sein, wo der Prozess stoppt
Das ist dann genau die Stelle, an der Signalen der zuletzt zugewiesene
Wert übergeben wird. Einen kombinatorischen Prozess könnte ich also so
schreiben:
1
process(A,B,C)begin
2
D<=AandBorC;
3
endprocess;
Und dieser Prozess ist exakt verhaltensgleich mit:
1
processbegin
2
waitonA,B,C;
3
D<=AandBorC;
4
endprocess;
Nur leider lässt sich der zweite Fall nicht synthetisieren. XST z.B.
meint dazu:
"Supported with one signal in the sensitivity list"
Lothar Miller schrieb:> Ein Übergang von 'U' nach '1' wird im ersten Fall als steigende Flanke> gewertet. In der Funktion rising_egde() wird auch noch> clk'last_value='0' abgefragt.
Der Unterschied hat aber doch wohl nur Auswirkungen auf die
Simulation (falls tatsächlich undefinierte Zustände auftreten),
nicht aber auf die Synthese. Oder sehe ich das falsch?
Josef G. schrieb:> Der Unterschied hat aber doch wohl nur Auswirkungen auf die> Simulation (falls tatsächlich undefinierte Zustände auftreten),> nicht aber auf die Synthese.
Ja, nur für die Simulation. Das der Takt in der Simulation undefiniert
ist, sollte ein unwahrscheinlicher Fall sein.
Nichtsdestotrotz ist rising_edge besser lesbar und schon deswegen zu
bevorzugen.
Duke
Duke Scarring schrieb:> Ja, nur für die Simulation. Das der Takt in der Simulation undefiniert> ist, sollte ein unwahrscheinlicher Fall sein.
Jedes Signal ist zu Beginn der Simulation undefiniert ('U').
Christoph Z. schrieb:> Duke Scarring schrieb:>> Ja, nur für die Simulation. Das der Takt in der Simulation undefiniert>> ist, sollte ein unwahrscheinlicher Fall sein.>> Jedes Signal ist zu Beginn der Simulation undefiniert ('U').
Nö.
Man kann ein Signal auch initialisieren:
Klaus Falser schrieb:>> Jedes Signal ist zu Beginn der Simulation undefiniert ('U').>> Nö.> Man kann ein Signal auch initialisieren:signal clk : std_logic := '0';
Ok, erwischt. Wenn die Signale in der Testbench initialisiert werden,
dann sind sie nicht 'U' zu Beginn.
Ich mache das aber nicht. Sehr bewusst nicht, da beim Einschalten eines
Gerätes ja auch nicht sofort alle Signale die in den FPGA hineingehen
definierte Zustände haben.
Ich mache das bewusst um die Realität besser ab zu bilden. Aber jetzt wo
ich mir die Frage noch mals stelle bin ich mir nicht mehr Sicher, ob ich
dadurch überhaupt einen Vorteil habe, gewisse Fehler zu finden oder
nicht.
Christoph Z. schrieb:> Ich mache das aber nicht. Sehr bewusst nicht, da beim Einschalten eines> Gerätes ja auch nicht sofort alle Signale die in den FPGA hineingehen> definierte Zustände haben.> Ich mache das bewusst um die Realität besser ab zu bilden. Aber jetzt wo> ich mir die Frage noch mals stelle bin ich mir nicht mehr Sicher, ob ich> dadurch überhaupt einen Vorteil habe, gewisse Fehler zu finden oder> nicht.
Richtig, denn du müsstest eigentlich einen Zufallsgenerator über diese
"undefinierten" Eingänge laufen lassen. Ein 'U' gibt es im echten Leben
nicht. Auch wenn das Design mit einem 'U' umgehen könnte, die reale
Hardware kann es nicht. Es gibt nur eine '0' oder eine '1'. Und
schlimmstenfalls einen ungünstigen Zeitpunkt für eines der beiden...
Die Initialisierung von Signalen ist schon deshalb sinnvoll, weil sonst
die Simulation u.U. bei Zeitpunkt 0 mit "metavalue detected" u.ä. um
sich wirft. Einen Reset braucht man natürlich normalerweise trotzdem.
Lothar Miller schrieb:> greg schrieb:>> Einen Reset braucht man natürlich normalerweise trotzdem.> Normalerweise nicht. Eher ausnahmsweise...
Naja, in der Testbench nicht, aber die Hardware möchte man doch häufig
auch ohne Neukonfiguration des FPGA zurücksetzen können.
greg schrieb:> die Hardware möchte man doch häufig> auch ohne Neukonfiguration des FPGA zurücksetzen können.
Nö. Warum einen Reset einbauen, wenn eine Rekonfiguration das gleiche
(und das viel besser) bewirkt? Bei BRAMs z.B. wird es problematisch, die
haben gar keinen Reset.
Anders sieht die Sache aus, wenn später mal aus meinem Design ein ASIC
werden würde.
Duke
> Naja, in der Testbench nicht,
Eigentlich gerade in der Testbench, um zB. den sauberen Startup unter
verschiedenen Bedingungen zu testen ;)
IMO hängt das auch stark vom Coding-Style bzw. der Art der Entwicklung
ab.
Ich mache zB. nur was mit FPGAs, bislang hatte auch noch keines meiner
diversen FPGAs einen externen (globalen) Reseteingang.
Trotzdem mache ich in den Prozessen immer if reset .. elsif rising_edge
statt Defaultzuweisung bei der Signaldeklaration. Die ist nämlich
einerseits zeilenmässig "weit" vom Prozess weg, andererseits ist sie
eine konzentrierte Zusammenfassung des Startzustands für genau den
Prozess. Sonst muss man die gesamte Deklaration scannen, ob bzw. wo es
da einen Defaultwert gibt.