Forum: FPGA, VHDL & Co. FSM mit "zwei Clocks"


von Schotter (schottre)


Lesenswert?

Hi,

seit zwei Tagen zerbreche ich mir mittlerweile den Kopf, wie ich eine 
StateMachine aufsetze, die durch einen externen Impuls ans Laufen 
gebracht wird. Konkret will ich nur über 4 Werte mitteln, wobei 3 davon 
nacheinander eintreffenden und der vierte das Ergebnis der vorherigen 
Mittelung ist.

Mit Blick auf http://www.lothar-miller.de/s9y/categories/37-FSM habe ich 
mein Glück versucht^^ vorher hatte ich noch andere Gehversuche, die sich 
zwar wunderbar mit ghdl simulieren ließen, aber allesamt an
1
Error (10822): HDL error at meanvalue.vhdl(98): couldn't implement registers for assignments on this clock edge
gescheitert sind.

Mein aktueller Versuch sieht sinngemäß so aus:
1
signal new_data_available : std_logic := '0';
2
3
Averaging : process
4
begin
5
  wait until rising_edge(clk);
6
  case state is
7
    when reset =>  --alles auf 0
8
    when idle =>  --nur warten
9
    when start =>
10
      new_data_available <= '0'  --verursacht einen Fehler
11
      state <= etc...
12
    when etc...
13
  end case;
14
15
  if(rst = '1') then
16
    state <= reset;
17
  elsif(new_data_available = '1') then
18
    state <= start;
19
  endif;
20
end process;
21
22
NewData : process (v_in_new)
23
begin
24
  if(rising_edge(v_in_new)) then
25
    new_data_available = '1';
26
  end if;
27
end process;

Meine Hoffnung bestand natürlich darin, dass ich so der Fehlermeldung 
von oben entkomme, aber jetzt erhalte ich eine "andere". Die Simulation 
setzt mir ab dem Zeitpunkt zu dem new_data_available auf '0' zurück 
gesetzt wird den new_data_available auf 'u' :/

Kann mir da wer 'nen Tipp geben wie das unter einen Hut kriege? Meine 
Phantasie stößt so langsam an ihre Grenzen :)

Danke,
Thorsten

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


Lesenswert?

Thorsten S. schrieb:
1
  wait until rising_edge(clk);
2
       new_data_available <= '0'  --verursacht einen Fehler
3
4
5
 if(rising_edge(v_in_new)) then
6
     new_data_available = '1';
Das wäre ein Dual-Clock-Flipflop. Hast du sowas schon mal gesehen?
Zudem sieht das zweitere verdächtig böse nach einem asynchronen Eingang 
aus. Und jeder asynchrone Eingang muss erst mal irgendwie 
einsynchronisiert werden!

> Meine Hoffnung bestand natürlich darin, dass ich so der Fehlermeldung
> von oben entkomme
Ja, wenn die Hoffnung nicht wäre...

> Kann mir da wer 'nen Tipp geben wie das unter einen Hut kriege?
Und was ist dein Ziel?
Was sollen die Signale machen und bewirken?
Kannst du da mal ein Timingdiagramm/Ablaufdiagramm zeichnen?

von Schlumpf (Gast)


Lesenswert?

Abgesehen von dem, was Lothar bereits schrieb, versuchst du hier 
"new_data_available" in zwei verschiedenen Prozessen zu verändern. Und 
das geht auch schief.

von Schotter (schottre)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> Was sollen die Signale machen und bewirken?
> Kannst du da mal ein Timingdiagramm/Ablaufdiagramm zeichnen?
Timingdiagramm inkl. Code habe ich mal angehängt. Das ist allerdings 
noch meine vorherige Codeversion. Da wird beim Übersetzen auch 
gemeckert, aber die Simulation zeigt genau das was ich haben will.

> Und jeder asynchrone Eingang muss erst mal irgendwie
> einsynchronisiert werden!
http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html 
habe ich schon gelesen, das Problem dahinter auch verstanden, aber 
zwischen Problem verstanden und Abhilfe schaffen, ist's noch ein 
Schritt, der mir noch nicht aufleuchtet.

> Und was ist dein Ziel?
...mein Problem ist, dass
1
signal ff1_out  : std_logic;
2
signal ff2_out  : std_logic;
3
:
4
process begin -- Einsynchronisieren
5
   wait until rising_edge(clk);
6
   ff1_out <= async_in;
7
   ff2_out <= ff1_out;
8
end process;
9
10
process begin 
11
   wait until rising_edge(clk);
12
   if (ff2_out = '1') then   -- Synchronisierten Eingang verwenden
13
   :   end if;   
14
end process;
ff2 doch auch wieder an clk hängt und ich das aus der FSM heraus dann 
wieder nicht zurücksetzen könnte. Die Frage ist also letztlich wie ich 
das dann trotzdem mache? Schreibe ich mir da einen Zähler, der ff2_out 
und ff1_out wieder auf '0' setzt? Oder gibt es noch andere 
Möglichkeiten?

Ja und jetzt seh ich's erst. Dein Beispiel fängt doch keine Peaks am 
Eingang von ff1 ab. Aber genau das möchte ich ja....
D-Flipflop. Man man man, sorry für die Blöderlasfragen^^

von Schlumpf (Gast)


Lesenswert?

Ich glaube, bis jetzt konnte keiner hier so recht verstehen, was du 
eigentlich willst.
Du willst ne FSM machen, die irgendwas tut und bastelst da wilde 
Konstruktionen mit Registern in mehreren Prozessen.

"Ordentlich" macht man sowas, indem man dem gesamten Design einen 
Systemtakt verpasst. Dieser Takt taktet ALLE Register (ausnahmslos)

Deine eingehenden Signale werden dann wie Daten interpretiert. Wenn du 
eine steigende Flanke auf einem eingehenden Signal erkennen willst, dann 
schiebst du das Signal durch zwei Register und vergleichst, ob das eine 
auf Low und das andere auf High ist. Damit hast du die Flanke erkannt.

von Schotter (schottre)


Lesenswert?

Ja ne, ein D-FF reicht mit dem Takt nur das weiter was am Eingang 
anliegt. Wenn mein Peak abgeklungen ist, kann er auch nicht 
weitergereicht werden.

Schlumpf schrieb:
> Wenn du eine steigende Flanke auf einem eingehenden Signal erkennen
> willst, dann schiebst du das Signal durch zwei Register und vergleichst,
> ob das eine auf Low und das andere auf High ist. Damit hast du die
> Flanke erkannt.
Und damit fange ich "Peaks" ab? Also Eingangssignale, die kürzer als 
mein clk sind?

von Schlumpf (Gast)


Lesenswert?

Thorsten S. schrieb:
> Und damit fange ich "Peaks" ab?

Ach so, ist jetzt ein Peak das Problem? Ich dachte, dein problem sei, 
dass du ne FSM hast, die nicht laufen will, weil du da irgendeine 
volgelwilde Konstrunktion mit mehreren Takten hast.

Aber Peaks kann man auch abfangen, indem man den Eingang durch mehrere 
Register schiebt und z.B. einen Mehrheitsentscheid macht.

Aber auch hier gilt: Alle Register arbeiten schön brav mit dem 
Systemtakt

von Schlumpf (Gast)


Lesenswert?

Oder willst du auf Peaks reagiere?
Sorry, ich versteh nicht, was du eigentlich vor hast. Und deinen Code 
mag ich mir beim besten Willen nicht anschauen.
Formuliere doch einfach mal in ein paar zusammenhängenden Sätzen, was 
dein Design können soll, dann kann man dir hier auch sicher helfen

von Schotter (schottre)


Lesenswert?

Schlumpf schrieb:
> Oder willst du auf Peaks reagiere?
> Sorry, ich versteh nicht, was du eigentlich vor hast. Und deinen Code
> mag ich mir beim besten Willen nicht anschauen.
> Formuliere doch einfach mal in ein paar zusammenhängenden Sätzen, was
> dein Design können soll, dann kann man dir hier auch sicher helfen

Dann versuche ich's nochmal^^
1
v_in_new : in std_logic;           --soll als Peak interpretiert werden
2
v_in : in unsigned (11 downto 0);  --hier sind dann die Werte die v_in_new ankündigt
Wenn ich es mir recht überlege, dürfte es von den zeitlichen Abläufen 
her vollkommen ausreichend sein, wenn ich mit dem Systemtakt nachschau, 
ob v_in_new = '1' ist, sprich ich könnte das auch in die FSM 
verschieben. Aber ich würde schon gerne wissen, wie ich das asynchroner 
hinbekomme.

Man nehme ein flankengesteuertes RS-FF bei dem v_in_new auf S liegt und 
dieses im Falle eines Peaks auf '1' setzt. Zurückgesetzt wird das FF 
über R, was mit dem clk verbunden ist. Der Ausgang von diesem FF geht in 
ein weiteres D-FF das ich von der FSM aus abfrage.

Das wäre jetzt mein analoger Ansatz (Verzögerungen etc. außen vor 
gelassen). War das einigermaßen verständlich?

Das von dir angesprochene Schieberegister habe ich mittlerweile auch 
gefunden,
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung
aber mit Peaks könnte ich damit nicht handhaben oder?

von Schotter (schottre)


Lesenswert?

So, es hat ewig gedauert, aber ich habe mein eigentliches Problem 
endlich gelöst und jetzt kann ich es auch in Worte fassen :D

Nochmal zur Situation: Ich habe ein asynchrones Eingangssignal, das mir 
neue Daten meldet. Damit ich die Daten nur 1x lese, dachte ich mir ich 
triggere auf eine steigende Flanke und ob das Signal dann 5 oder 50 ns 
lang high ist, kann mir dann egal sein. Und hier hatte ich mich dann 
verrannt.

Das Schieberegister hat mich dann vom Flankentriggern abgebracht, aber 
der mehrmalige Durchlauf der FSM war noch nicht unterbunden.
1
signal insr  : std_logic_vector(2 downto 0);
2
:
3
process begin
4
   wait until rising_edge(clk);
5
   -- Schieberegister
6
   insr <= insr(1 downto 0) & input;
7
end process;
8
9
process begin
10
   wait until rising_edge(clk);
11
   if (insr(2 downto 1) = "10") then 
12
      -- fallende Flanke von input
13
      new_data_available <= '0';
14
   end if;
15
   if (insr(2 downto 1) = "01") then 
16
      -- steigende Flanke von input
17
      new_data_available <= '1';
18
   end if;
19
end process;
Dazu bedurfte es noch eines weiteren Bits und die Sache war gegessen.
1
    :
2
  end case;
3
4
  if(rst = '1') then
5
    state <= reset;
6
  elsif (new_data_available = '1' and state = idle) then
7
    triggered <= '1';
8
    if(triggered = '0') then
9
      state <= inc;
10
    end if;
11
  elsif (new_data_available = '0') then
12
    triggered <= '0';
13
  end if;
14
end process;  --FSM

Nochmals Danke für die Beiträge...auch wenn mich keiner verstanden hat^^ 
geholfen hat's mir trotzdem ;)

von Klaus F. (kfalser)


Lesenswert?

Thorsten S. schrieb:
> Nochmal zur Situation: Ich habe ein asynchrones Eingangssignal, das mir
> neue Daten meldet. Damit ich die Daten nur 1x lese, dachte ich mir ich
> triggere auf eine steigende Flanke und ob das Signal dann 5 oder 50 ns
> lang high ist, kann mir dann egal sein. Und hier hatte ich mich dann
> verrannt.

In einem solchen Fall sollte man die Funktionalität trennen.
Du schreibst Dir
a) ein Modul, das das Eingangssignal einsynchronisiert und bei einer 
Flanke am Ausgang einen Puls mit genau einer Taktperiode High liefert
b) die FSM, die auf diesen Puls reagiert und die Verarbeitung macht

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


Lesenswert?

Thorsten S. schrieb:
> im Falle eines Peaks
Was ist ein Peak?
Willst du eher einen "Spike" erkennen können (also einen Impuls, der 
fürs reguläre Eintakten zu kurz ist oder sein kann)?
Offensichtlich ja:
> ob das Signal dann 5 oder 50 ns lang high ist, kann mir dann egal sein.
Dann kannst du die Sache so angehen:
http://www.lothar-miller.de/s9y/categories/19-SpikePuls

von Schlumpf (Gast)


Lesenswert?

Du willst glaub offensichtlich genau das, was Lothar vermutet hat.
Falls dein "new-data-avilable" Signal so kurz ist, dass du es nicht mit 
dem Systemtakt erfassen kannst, dann mach es so, wie Lothar es 
beschrieben hat.
Falls du aber sicherstellen kannst, dass das Signal länger als 2 
Systemtakte ist, dann sample es mit dem Systemtakt ein und mach mit der 
unter anderem von mir beschriebenen Methode eine Flankenerkennung.
Also schieben durch mehrere Register und vergleich der Registerinhalte.

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.