Hallo, ich fange gerade mit VHDL und FPGAs an. Bei meinen ersten
Versuchen bin ich nun auf ein Problem gestoßen. Alles funktioniert so
wie es soll, ich bin mir aber nicht sicher warum.
Das Programm (nennt man Synthetisierten VHDL Code so?) soll einen Taster
entprellen und bei steigender Flanke eine Variable bis 255 hoch zählen
und den Wert der Variable dann an 8 LEDs ausgeben. (Kompletter Code
unten)
Was mir Kopfzerbrechen bereitet ist nun die Auswertung der steigenden
Flanke. Schließlich wird ein vorher Wert mit einem nachher Wert
verglichen.
Aus der Zeile:
1
if((sig0xorsig1)andnotsig1)='1'then
geht für mich hervor, dass sig1 der vorher Wert ist und sig0 der nachher
Wert. Beim Schreiben des Codes habe ich mir eigentlich gedacht es wäre
anders herum.
Ich sehe jetzt irgendwie nicht wo der nachher Wert sig0 zugeordnet wird.
Schließlich wird unmittelbar nach der Zuweisung
1
sig1<=sig0
eine if Abfrage gemacht die beide Signale auf eine steigende Flanke
untersucht.
Eine andere Sache die ich nicht ganz verstehe ist folgender Fall:
Was passiert wenn der vorher Wert gerade zugewiesen wird während sich
der nachher Wert ändert.
1
ifsysclk'eventandsysclk='1'then
2
sig1<=sig0;
3
if((sig0xorsig1)andnotsig1)='1'then
Bei jeder Steigenden Flanke wird sig0 sig1 zugeordnet. Der Rest läuft
asynchron ab. Gäbe es hier die Möglichkeit, dass sig0 seinen Zustand
nochmal ändert bevor die if Abfrage abgearbeitet ist, und ist es
sicherer hier nochmal sysclk auf eine steigende Flanke zu prüfen und
nicht nur sig0 und sig1? Meine Befürchtung ist, dass bei einer längeren
if Abfrage eben dieser Fall eintritt und eine steigende Flanke mit sig1
und sig0 nicht erkannt werden kann.
------------------------------------------------
Code:
M. M. schrieb:> Ich sehe jetzt irgendwie nicht wo der nachher Wert sig0 zugeordnet wird.> Schließlich wird unmittelbar nach der Zuweisungsig1 <= sig0 eine if> Abfrage gemacht die beide Signale auf eine steigende Flanke> untersucht.
diese Abfrage bezieht sich aber noch nicht auf den gerade eben
zugewiesenen Wert von sig1. Zuweisungen an Signale in Prozessen werden
erst "am Ende des Prozesses" wirksam. Während aller Abfragen innerhalb
des Prozesses hat Sig1 noch den "vorherigen" Wert.
Konkret in Hardware umgesetzt bedeutet das:
du generierst ein Flip-Flop für Sig1. Bei jeder steigenden Taktflanke
übernimmt das Flip-Flop seinen Eingangswert
Abfragen von Sig1 beziehen sich auf den Ausgang des FlipFlops, der bei
der letzten Taktflanke gesetzt wurde.
Zuweisungen an Sig1 legen den Eingang des FipFlops fest, der bei der
steigenden Taktflanke als Ausgang übernommen wird.
Um die Abfolge erst mal besser zu verstehen gibt es die sog.
Zwei-Prozess-Schreibweise (insbesondere für State-Machines), bei der
Eingang und Ausgang des FlipFlops als getrennte Signale betrachtet
werden. Wenn man es dann aber mal verinnerlicht hat, dann nerven der
Zusatzaufwand und die Fallstricke der Zwei-Prozess-Schreibweise (geht
zumindest mir so), und man schreibt stattdessen die Zuweisung ans
FlipFlop in einem Prozess (so wie in deinem Beispiel).
Achim S. schrieb:> Zuweisungen an Signale in Prozessen werden erst "am Ende des Prozesses"> wirksam.
Das führt zu dem für Software-Programmierer seltsam verwirrenden Effekt,
dass die Reihenfolge der Abfrage eines Signals und die Zuweisung von
Werten an ein Signal in beliebiger Reihenfolge im Prozess stehen können.
Diese beiden Beschreibungen ergeben das selbe Resultat:
1
count:process(clk)
2
begin
3
ifrising_edge(clk)then
4
cnt<=cnt+1;---------
5
ifcnt=55then
6
y<=1;
7
else
8
y<=0;
9
endif;
10
endif;
11
endprocess;
Ergibt genau das Selbe:
1
count:process(clk)
2
begin
3
ifrising_edge(clk)then
4
ifcnt=55then
5
y<=1;
6
else
7
y<=0;
8
endif;
9
cnt<=cnt+1;----------
10
endif;
11
endprocess;
Denn während des Prozesses wird mit dem "alten" Wert von cnt gerechnet.
Erst am Prozessende wird der neue Wert zugewiesen.
M. M. schrieb:> Was läuft parallel im FPGA? - Verständnisfragen
Mein wirchtigster Tipp: sieh dir den RTL-Schaltplan des Synthesizers an.
Dann siehst du nämlich genaz genau, wie deine Beschreibung in Hardware
umgesetzt wurde...
> use ieee.std_logic_unsigned.all;
Lies den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"
Und nimm fürderhin die numeric_std:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
Ein philosophischer Ansatz: "Ist nicht alles in einem FPGA parallel"?
Ein Tipp:
Das hier " if ((sig0 xor sig1) and not sig1) ='1' then" ist viel zu
abstrakt formuliert.
Andreas S. schrieb:> M. M. schrieb:>>if ((sig0 xor sig1) and not sig1) ='1' then> Das ist identisch mit:if (sig0 = '1') then
Nein, check mal den Fall sig1 = '1'.
Lothar M. schrieb:> Achim S. schrieb:>> Zuweisungen an Signale in Prozessen werden erst "am Ende des Prozesses">> wirksam.> Das führt zu dem für Software-Programmierer seltsam verwirrenden Effekt,> dass die Reihenfolge der Abfrage eines Signals und die Zuweisung von> Werten an ein Signal in beliebiger Reihenfolge im Prozess stehen können.>> Diese beiden Beschreibungen ergeben das selbe Resultat:
Dass Signale immer erst am Ende eines Prozesses zugewiesen werden ist
mir bekannt, ich versuche es immer im Hinterkopf zu behalten aber es ist
doch schwierig aus der Zeile-für-Zeile Denkweise herauszukommen wenn man
so lange mit Mikrocontrollern vorher zu tun hatte.
Nun scheint es mir, dass ich begriffen habe wie das ganze abläuft.
Wenn der Taster nicht gedrückt wird, haben bei Signale den Wert 0.
Nun wird der Taster gedrückt und in dem Takt danach wird dem Signal0 der
Wert 1 zugeschrieben, Signal1 behält seinen aktuellen Wert. Außerdem
werden beide Signale in diesem Takt auf eine steigende Flanke untersucht
und dann auch erkannt.
Im nächsten Takt haben beide Signale den Wert 1 und nichts passiert.
Gibt es zur RTL Analyse ein Dokument welche die Blöcke erklärt? Die
meisten sind mir zwar bekannt aber es wäre auch schön nochmal nach
gucken zu können.
Danke soweit für die Hilfe, die andere Lib werde ich mir mal anschauen.
M. M. schrieb:> Wenn der Taster nicht gedrückt wird, haben bei Signale den Wert 0.> Nun wird der Taster gedrückt und in dem Takt danach wird dem Signal0 der> Wert 1 zugeschrieben, Signal1 behält seinen aktuellen Wert.
Nein, sig1 bekommt immer den alten Wert von sig0. sigt1 ist damit nichts
anderes als eine um einen Takt verzögerte Kopie von sig0
> Außerdem> werden beide Signale in diesem Takt auf eine steigende Flanke untersucht> und dann auch erkannt.
Der FPGA untersucht nichts auf Flanke, sondern das steht in deiner
Beschreibung. Deine orginale Variante ist da schwer zu durchschauen,
in Lothars verreinfachter Form ist es offensichtlich wie es
funktioniert,
1
if(sig0='1'andsig1='0')then
esultat:
>> Dass Signale immer erst am Ende eines Prozesses zugewiesen werden ist> mir bekannt, ich versuche es immer im Hinterkopf zu behalten aber es ist> doch schwierig aus der Zeile-für-Zeile Denkweise herauszukommen wenn man> so lange mit Mikrocontrollern vorher zu tun hatte.
Einfache Betrachtungsweise:
Was rechts von einer Zuweisung steht ist der Zustand vor der
Taktflanke, die Zuweisung bestimmt was bei der Flanke passieren soll,
und damit den Zustand nach der Taktflanke.
Wenn ein Signal mehrfach auf der linken Seite einer Zuweisung vorkommt,
gilt die letzte im Prozess, eventuell in Abhängigkeit von Bedingungen.
Kombinatorische Prozesse sind etwas komplexer, da bei korrekter
Sensititvitylist der Prozess gleich noch mal zum Tragen kommt, wenn sich
ein Signal ändert, das sowohl auf der rechten als auf der linken Seite
einer Zuweisung steht. Das ist fast immer unerwünscht (Kombinatorische
Schleife) also unbedingt vermeiden.
Auch sollte man im kombinatorischen Prozess darauf achten, dass ein
Signal unter allen Bedingungen zugeweisen wird, sond kassiert man
unerwünschte Latches. Kann man damit sicherstellen, dass man am Anfang
Defaultzuweisungen hinschreibt, und erst danach bedingte Zuweisungen.
Lattice User schrieb:> Nein, sig1 bekommt immer den alten Wert von sig0. sigt1 ist damit nichts> anderes als eine um einen Takt verzögerte Kopie von sig0
Da habe ich mich wohl ungeschickt ausgedrückt, das habe ich nämlich
damit sagen wollen.
Lattice User schrieb:> Der FPGA untersucht nichts auf Flanke, sondern das steht in deiner> Beschreibung. Deine orginale Variante ist da schwer zu durchschauen,> in Lothars verreinfachter Form ist es offensichtlich wie es> funktioniert,
1
if(sig0='1'andsig1='0')then
Nun verstehe ich genau wie das gemeint ist. Tatsächlich so ist es immens
einfacher.
Danke euch allen, ihr habt mir sehr weiter geholfen!