Forum: FPGA, VHDL & Co. Seltsames Verhalten, Flanke wird nicht erkannt?!


von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Hallo, ich bin gerade in ein Problem gelaufen und zwar habe ich eine 
FSM.
1
process begin
2
3
if fsm = s_Wait then
4
  wait until falling_edge(nCS);
5
  fsm <= s_Active;
6
elsif fsm = s_Active then
7
  wait until rising_edge(nCS);
8
  fsm <= s_Wait;
9
end if;
10
11
end process;

Die soll das nCS verwenden und darauf reagieren. Ich brauche das nur in 
einer Testbech, also nicht in Hardware. Allerdings ist es jetzt so, dass 
da die Flanken oft nicht beachtet werden und ich weiß nicht wieso.

Ja, normalerweise hat man nur einen Takt und hätte das wait until ganz 
man Anzang im process, aber in der Simulation wird doch der ganze 
process bei jedem Tick neu angeschaut. Und da sollte klar sein, dass 
aktuell fsm z. B. s_Wait ist und dann wird da auf die fallende Flanke 
gewartet.

Was ich seltsam finde ist, dass es eben doch manchmal auf Flanken 
reagiert.

Im Anhang die Dateien und das Demoprojekt.

: Bearbeitet durch User
von Samuel C. (neoexacun)


Lesenswert?

Vertausch mal beide "wait"s mit den beiden Zuweisungen.

von Gustl B. (-gb-)


Lesenswert?

Wie meinst du das und was sollte das bewirken?
1
process begin
2
3
if fsm = s_Wait then
4
  wait until rising_edge(nCS);
5
  fsm <= s_Wait;
6
elsif fsm = s_Active then
7
  wait until falling_edge(nCS);
8
  fsm <= s_Active;
9
end if;
10
11
end process;

So macht das nämlich keinen Sinn.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Gustl B. schrieb:
> Was ich seltsam finde ist, dass es eben doch manchmal auf Flanken
> reagiert.
Das sieht für mich wie das normale Verhalten von Signalen in Prozessen 
aus: weil keine Sensitivliste involviert ist, wird die letzte 
Zuweisung erst beim nächsten wait übernommen, aber eben *nicht am 
Prozessende*!

Deshalb hat nach der Zuweisung bei der nächsten if-Runde der Zustand der 
FSM sich noch nicht geändert.

Probiers mal so
1
process begin
2
wait until falling_edge(nCS);
3
4
if fsm = s_Wait then
5
  fsm <= s_Active;
6
elsif fsm = s_Active then
7
  fsm <= s_Wait;
8
end if;
9
10
end process;

: Bearbeitet durch Moderator
von Gustl B. (-gb-)


Lesenswert?

Ja, richtig, aber Sensitivliste und wait will der Simulator nicht.

Bei deiner Lösung kann ich aber leider nur auf eine Flankenart von einem 
Signal reagieren.

Ich möchte aber eben eine FSM in der ich in Abhängigkeit vom State auf 
eine andere Flankenart von unterschiedlichen Signalen reagieren kann.

Vielleicht sollte ich das ganz ohne Process mit einem

fsm <= s_Wait when ... lösen.

Oder doch mit einem Takt der schnell genug ist dass es aussieht als wäre 
das instantan.

Gerne würde ich aber, weil es hier um ein SPIähnliches Signal geht, auch 
mehrere Flanken warten ohne das getaktet zählen zu müssen. Ein

Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);

Wartet dann eben bis nach der 4. SCLK Flanke.

Ich hatte vermutet, dass das in der Testbench alles möglich ist.

von Samuel C. (neoexacun)


Lesenswert?

Gustl B. schrieb:
> Wie meinst du das und was sollte das bewirken?
1
process begin
2
3
if fsm = s_Wait then
4
  fsm <= s_Active;
5
  wait until rising_edge(nCS);
6
elsif fsm = s_Active then
7
  fsm <= s_Wait;
8
  wait until falling_edge(nCS);
9
end if;
10
11
end process;

Erst zuweisen, dann warten. Sonst musst du natürlich nochmal warten.

: Bearbeitet durch User
von Sigi (Gast)


Lesenswert?

Dein Problem ist, dass dein Prozess nicht
gestartet wird, bevor nCS sich ändert.
Er müsste aber bei jeder Änderung von <fsm>
durchlaufen werden (wegen der IF-Anweisung),
dazu müsste aber <fsm> in der Sensitiv-Liste
stehen, die es aber wegen deiner wait's nicht
geben darf. Und genau deshalb wird jede erste
Flanke (je nach WAIT/ACTIVE) ignoriert und
jede zweite Flanke berücksichtigt.

Dass die Signale schon richtig gesetzt werden,
erkennst du ja an deiner Ausgabe, aber ebenso
lässt sich ja mithilfte meines Arguments erkennen,
dass <fsm> nicht sofort berücksichtigt wird.

Dir bleibt also nichts anderes übrig,
als deinen Ansatz komplett anders zu
formulieren.

von Gustl B. (-gb-)


Lesenswert?

OK verstanden.

Ich hatte gehofft, dass das in der Simulation, also die Testbench wie 
Software abgearbeitet wird. Das spring also in einen If Zweig und wartet 
dann dort bis die Flanke kommt. Aber ist wohl nicht so ... naja, dann 
schreibe ich das eben getaktet ...

Oh nein!!!
1
begin
2
3
process (fsm, nCS) begin
4
5
if fsm = s_Wait then
6
  if falling_edge(nCS) then
7
    fsm <= s_Active;
8
  end if;
9
elsif fsm = s_Active then
10
  if rising_edge(nCS) then
11
    fsm <= s_Wait;
12
  end if;
13
end if;
14
15
end process;

Das gute alte If funktioniert statt einem Wait. Ist aber eben nicht 
blockierend wie ich das bei dem Wait gehofft hatte.

von Samuel C. (neoexacun)


Lesenswert?

Es wird auch sequentiell abgearbeitet. Dein Problem ist die 
Funktionsweise von Signalen.

Dein Prozess läuft bis zum nächsten "wait" in 0 Zeit. Dein Signal ändert 
sich jedoch erst nach einem beliebig kleinen Zeitschritt. Daher hat sich 
das Signal bis zum erreichen des if's noch nicht geändert, sondern erst 
nach dem nächsten "wait".

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Gut, aber dann würde es ja genügen hinter jede Zuweisung ein kurzes wait 
100 ps; zu schreiben.

Tatsache, schick! Vielen Dank, jetzt habe ich das auch verstanden.

: Bearbeitet durch User
von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Gustl B. schrieb:
> Bei deiner Lösung kann ich aber leider nur auf eine Flankenart von einem
> Signal reagieren.
Aha, übersehen.
Dann etwa so:
1
process (nCS) begin
2
  if fsm = s_Wait and falling_edge(nCS) then
3
    fsm <= s_Active;
4
  elsif fsm = s_Active and rising_edge(nCS) then
5
    fsm <= s_Wait;
6
  end if;
7
end process;
Oder so:
1
process (nCS) begin
2
  if    fsm = s_Wait   and nCS='0' then
3
    fsm <= s_Active;
4
  elsif fsm = s_Active and nCS='1' then
5
    fsm <= s_Wait;
6
  end if;
7
end process;
Oder so:
1
process begin
2
  wait on nCS;
3
  if    fsm = s_Wait   and nCS='0' then
4
    fsm <= s_Active;
5
  elsif fsm = s_Active and nCS='1' then
6
    fsm <= s_Wait;
7
  end if;
8
end process;

Gustl B. schrieb:
> die Testbench wie Software abgearbeitet wird.
Ein Prozess wird natürlich sequenziell abgearbeitet. Allerdings sind 
Signale eben Signale und damit stur bis zum nächsten wait.
> wie Software
Auch wenn VHDL gern mal als "Programmiersprache" bezeichnet wird, ist 
sie trotzdem keine prozedurale Programmiersprache. Deshalb darf man 
nicht erwarten, mit VHDL genauso "top-down" wie mit Java oder C/++/# 
programmieren zu können.

Gustl B. schrieb:
> hinter jede Zuweisung ein kurzes wait 100 ps; zu schreiben.
> Tatsache, schick!
Ähm, naja...
Irgendwann fällt dir so ein Pseudo-Delay garantiert auf die Nase. Denn 
das Delay kommt ja nicht aus dem System, das du beschreibst und 
simulieren willst. Sondern du brauchst es, weil du etwas machen willst, 
was die Sprache im Grunde nicht kann.

: Bearbeitet durch Moderator
von Duke Scarring (Gast)


Lesenswert?

Gustl B. schrieb:
> Gut, aber dann würde es ja genügen hinter jede Zuweisung ein kurzes wait
> 100 ps; zu schreiben.

Es genügt sogar ein
1
wait for 0 ps;

Indirekte Quelle:
http://www.lothar-miller.de/s9y/archives/91-Schalter-und-Bruecke.html

Duke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Duke Scarring schrieb:
> Es genügt sogar ein wait for 0 ps;
Aber nicht in allen Fällen. Es kann sein, dass da Delta-Zyklen in die 
Suppe spucken und das Simulationsergebnis verfälschen...   :-(

Sieh den Beitrag "Re: VHDL: Problem bei assert Anweisung"

von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> Dann etwa so:process (nCS) begin
>   if fsm = s_Wait and falling_edge(nCS) then
>     fsm <= s_Active;
>   elsif fsm = s_Active and rising_edge(nCS) then
>     fsm <= s_Wait;
>   end if;
> end process;

Das hatte ich oben schon getan, aber die Flankenerkennung jeweils in ein 
weiteres IF getan - auch das funktioniert.

Lothar M. schrieb:
> Irgendwann fällt dir so ein Pseudo-Delay garantiert auf die Nase.

Ja. Wie so oft sollte man wissen was man tut und wenn man ein Werkzeug 
anders als gedacht verwendet sollte man auch die Nachteile und Risiken 
dabei bedenken. Bei meinem aktuellen Problem ist das kleine Delay kein 
Problem. Statt 100 ps kann ich ja auch 2 ps schreiben. Ich würde aber 
vermuten, dass da etwas größeres als die Simulator Zeitauflösung stehen 
sollte.
Eben wegen deiner letzten Antwort.

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Das kommt eben davon, wenn man Wartekommandos nimmt, Prozesse scheinbar 
schlafen legt, dann aber permanent abzufragende Bedingungen vorschaltet. 
Das gibt nur Kompikationen.

Ich täte das konventionell mit if rising_edge machen und einen Prozess 
mit kompletter Sensi schreiben. Das spart Rechenzeit, weil das nur 
angefahren wird, wenn sich an den Signalen was tut.

von Gustl B. (-gb-)


Lesenswert?

Ja das stimmt schon, aber wie willst du dann zwischen der ersten und 
zweiten Flanke gleichen Typs unterscheiden?

Mit

Wait until falling_edge(nCS);
Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);
Wait until rising_edge(SCLK);
Wait until rising_edge(nCS);

kann man schön von Flanke zu Flanke springen.

Ich weiß jetzt jedenfalls wie das funktioniert und eben dass Zuweisungen 
nicht sofort passieren, sondern erst mit dem nächsten 
Simulationsschritt.

von Christoph Z. (christophz)


Lesenswert?

Lothar M. schrieb:
> wait on nCS;

Danke, wieder etwas gelernt über VHDL!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Christoph Z. schrieb:
>> wait on nCS;
> Danke, wieder etwas gelernt über VHDL!
Kein Ursache, geht aber leider nur in der Simulation...  :-(
Für die Synthese funktioniert nach wie vor bestenfalls "wait until". 
Generell hilft da dann das Handbuch zum Synthesizer weiter.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.