mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Gustl B. (-gb-)


Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich bin gerade in ein Problem gelaufen und zwar habe ich eine 
FSM.
process begin

if fsm = s_Wait then
  wait until falling_edge(nCS);
  fsm <= s_Active;
elsif fsm = s_Active then
  wait until rising_edge(nCS);
  fsm <= s_Wait;
end if;

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)


Bewertung
0 lesenswert
nicht lesenswert
Vertausch mal beide "wait"s mit den beiden Zuweisungen.

von Gustl B. (-gb-)


Bewertung
0 lesenswert
nicht lesenswert
Wie meinst du das und was sollte das bewirken?
process begin

if fsm = s_Wait then
  wait until rising_edge(nCS);
  fsm <= s_Wait;
elsif fsm = s_Active then
  wait until falling_edge(nCS);
  fsm <= s_Active;
end if;

end process;

So macht das nämlich keinen Sinn.

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


Bewertung
0 lesenswert
nicht 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
process begin
wait until falling_edge(nCS);

if fsm = s_Wait then
  fsm <= s_Active;
elsif fsm = s_Active then
  fsm <= s_Wait;
end if;

end process;

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


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Gustl B. schrieb:
> Wie meinst du das und was sollte das bewirken?
process begin

if fsm = s_Wait then
  fsm <= s_Active;
  wait until rising_edge(nCS);
elsif fsm = s_Active then
  fsm <= s_Wait;
  wait until falling_edge(nCS);
end if;

end process;

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

: Bearbeitet durch User
von Sigi (Gast)


Bewertung
0 lesenswert
nicht 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-)


Bewertung
0 lesenswert
nicht 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!!!
begin

process (fsm, nCS) begin

if fsm = s_Wait then
  if falling_edge(nCS) then
    fsm <= s_Active;
  end if;
elsif fsm = s_Active then
  if rising_edge(nCS) then
    fsm <= s_Wait;
  end if;
end if;

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)


Bewertung
0 lesenswert
nicht 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-)


Bewertung
0 lesenswert
nicht 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. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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:
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;
Oder so:
process (nCS) begin
  if    fsm = s_Wait   and nCS='0' then
    fsm <= s_Active;
  elsif fsm = s_Active and nCS='1' then
    fsm <= s_Wait;
  end if;
end process;
Oder so:
process begin
  wait on nCS;
  if    fsm = s_Wait   and nCS='0' then
    fsm <= s_Active;
  elsif fsm = s_Active and nCS='1' then
    fsm <= s_Wait;
  end if;
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)


Bewertung
0 lesenswert
nicht 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
wait for 0 ps;

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

Duke

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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-)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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-)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> wait on nCS;

Danke, wieder etwas gelernt über VHDL!

von Lothar M. (lkmiller) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.