Forum: FPGA, VHDL & Co. Conunter für waiting-Time


von Daniel C. (Gast)


Lesenswert?

Hallo liebe mikrocontroller - Community,

Ich bin gerade dabei eine Statemachine zu bauen. Dafür muss ich in zwei 
States die Verweilzeit überwachen - Sprich wenn sich der State zu früh 
ändert soll ein Fehler erkannt werden.

Der Counter soll mit der Clock von der PLL versorgt werden welche 200MHz 
liefert (Periodendauer von 5ns). Die zu erreichende Verweilzeit sollte 
bei 700ns sein, mein Ansatz wäre also einen Counter mit dem Startwert 
(700/5 = 140) zu dekremetieren bis er den Wert 0 erreicht hat. In der 
exit-Strategy des jeweiligen Zustandes der Statemachine würde ich dann 
den Zählerstand abfragen und entscheiden ob dieser den Wert 0 erreicht 
hat. Abhängig davon verzweige ich dann ob es eine gültige Transition ist 
oder nicht.

Den Counter würde ich als eigene Entity generieren, da ich diesen in der 
Statemachine mehrfach instanziiere.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
6
entity Counter is
7
8
  generic
9
  (
10
    MIN_COUNT : natural := 0;
11
    MAX_COUNT : natural := 140
12
  );
13
14
  port
15
  (
16
    clk        : in STD_ULOGIC;
17
    reset        : in STD_ULOGIC;
18
    enable      : in STD_ULOGIC;
19
    q          : out integer
20
  );
21
22
end entity;
23
24
architecture rtl of Counter is
25
begin
26
27
  process (clk)
28
    variable   cnt       : integer range MIN_COUNT to MAX_COUNT;
29
  begin
30
    if (rising_edge(clk)) then
31
32
      if reset = '1' then
33
        -- Reset the counter to 140
34
        cnt := 140;
35
36
      elsif enable = '1' and (cnt > 0)
37
  ) then
38
        -- Decrement the counter if counting is enabled         
39
        cnt := cnt - 1;
40
41
      end if;
42
    end if;
43
44
    -- Output the current count
45
    q <= cnt;
46
  end process;
47
end rtl;

Hier noch wie der jeweilige State mit der exit-Strategy aussieht:
1
        when q2=>                      --q2 state
2
        
3
        
4
        
5
          if input = inputQ3 and (count = 0)  then
6
            lastState <= currentState;
7
            currentState <= q3;
8
            resetCounter <= '1';
9
            enableCounter <= '0';
10
            
11
            
12
            elsif input = inputIdle and (count = 0)  then
13
            lastState <= currentState;
14
            currentState <= idle;
15
            resetCounter <= '1';
16
            enableCounter <= '0';
17
            
18
            elsif input = inputQ1 and (count = 0)  then
19
            lastState <= currentState;
20
            currentState <= q1;
21
            resetCounter <= '1';
22
            enableCounter <= '0';
23
            
24
            
25
            elsif input = inputQ4 and (count = 0)  then
26
            lastState <= currentState;
27
            currentState <= q4;
28
            resetCounter <= '1';
29
            enableCounter <= '0';
30
            
31
            
32
            elsif input = inputQ2 and (count = 0)  then
33
            lastState <= currentState;
34
            currentState <= q2;
35
            resetCounter <= '1';
36
            enableCounter <= '0';
37
            
38
          else
39
            currentState <= error;
40
        end if;
41
        
42
        LED <= "00000100";

Bitte verzeiht mir diverse Verstöße gegen VHDL-Konventionen, ich stehe 
noch ziemlich in der Einarbeitungsphase mit VHDL.

LG,
Daniel

von Klakx (Gast)


Lesenswert?

Klingt vom Prinzip nicht verkehrt.

Deine eigentliche Frage konnte ich aber nicht herauslesen :-)

von Arduinoquäler (Gast)


Lesenswert?

Klakx schrieb:
> Deine eigentliche Frage konnte ich aber nicht herauslesen :-)

Die Fragestellung zu finden ist offensichtlich sehr oft die
Aufgabe des Forums bzw. der Leserschaft. Weil es der TO nicht
schafft ganz einfach eine konkrete Frage zu stellen. Das
wäre ja auch zuviel verlangt.

Nach dem Motto: hallo Leute ich habe da gerade ein Problem,
und im Anhang findet ihr meine gesammelten Werke ....

von Daniel C. (danny1)


Lesenswert?

Hallo nochmal,

Sorry das war eindeutig mein Versehen.
Ich habe das Design mit ModelSim simuliert und habe die entsprechenden 
Signale so angelegt, dass die Transisiton zwar gültig wäre aber die 
Verweilzeit verletzt war.
Die FSM ist aber nicht in Fehler gegangen.

Ich denke ich habe den Fehler inzwischen gefunden:
Muss wohl ein syntax-Fehler meiner entry-Action der FSM gewesen sein:

Hab es von
1
elsif falling_edge(trigger) then
2
    
3
    if not(lastState = currentState) then
4
    
5
    resetCounter <= '0';
6
    enableCounter <= '1';
7
    
8
    end if;

auf
1
elsif falling_edge(trigger) then
2
    
3
    if lastState /= currentState then
4
    
5
    resetCounter <= '0';
6
    enableCounter <= '1';
7
    
8
    end if;

geändert, nun scheint es zu funktionieren.

Entschuldigt nochmal die vergessene Fragestellung, war nicht mit 
Absicht,

LG,
Daniel

von Gallioleo (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Die Fragestellung zu finden ist offensichtlich sehr oft die
> Aufgabe des Forums bzw. der Leserschaft.

Ich glaube das Spiel heißt dann Jeopardy
https://de.wikipedia.org/wiki/Jeopardy!



Viele Grüße

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


Lesenswert?

Daniel C. schrieb:
> elsif falling_edge(trigger) then
Das gibt mir sehr, sehr zu denken. Wie viele unterschiedliche 
rising_edge und falling_edge mit wie vielen unterschiedlichen Signalen 
hat dein Design?
Wenn die Antwort größer 1 ist, dann wirst du in der Praxis überraschende 
Probleme mit sporadischen (eher schlecht, weil schwer zu finden) oder 
häufigen (Glück gehabt) Fehlfunktionen bekommen....

Die Stichworte dazu sind: Synchronisieren von Taktdomänenübergängen

: Bearbeitet durch Moderator
von Daniel C. (danny1)


Lesenswert?

Lothar M. schrieb:
> Daniel C. schrieb:
>> elsif falling_edge(trigger) then
> Das gibt mir sehr, sehr zu denken. Wie viele unterschiedliche
> rising_edge und falling_edge mit wie vielen unterschiedlichen Signalen
> hat dein Design?
> Wenn die Antwort größer 1 ist, dann wirst du in der Praxis überraschende
> Probleme mit sporadischen (eher schlecht, weil schwer zu finden) oder
> häufigen (Glück gehabt) Fehlfunktionen bekommen....
>
> Die Stichworte dazu sind: Synchronisieren von Taktdomänenübergängen

Hallo Lothar M.,

Ich hab in meinem Gesamtdesign eine eigene Entity zur Edgedetection. 
Diese soll von 4 Eingangssignalen eine steigende oder fallende Flanke 
erkennen und dann einen Ausgang triggern.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
4
entity EdgeDetector is
5
      Port ( 
6
          -- Input ports
7
          clk       :  in  STD_ULOGIC;
8
          signal_in   :   in  STD_ULOGIC_VECTOR(3 downto 0);
9
          
10
          -- Output ports
11
               output       :  out STD_ULOGIC
12
          );
13
          
14
end EdgeDetector;
15
16
17
architecture Behavioral of EdgeDetector is
18
19
     signal signal_buf:STD_ULOGIC_VECTOR(3 downto 0);
20
    signal detectedEdge:STD_ULOGIC_VECTOR(3 downto 0);    
21
begin
22
23
    signal_buf     <= signal_in when rising_edge(clk);
24
    detectedEdge   <= signal_buf xor signal_in;
25
    output       <= detectedEdge(0) or detectedEdge(1) or detectedEdge(2) or detectedEdge(3);
26
    
27
end Behavioral;

Die Edgedetection nutze ich dann, als "trigger" für meine FSM.

In der Entity wo meine FSM arbeitet habe ich 2 Verzeigungen mit einer 
Edge-Auswertung, die die du oben genannt hast und noch eine in einer 
zweiten Process, welche das Schalten der LEDs übernimmt.
1
process (currentState, clk)
2
  begin
3
      if rising_edge(clk) then
4
      case currentState is
5
        when idle=>
6
        
7
        LED <= "00000001";
8
          
9
        when q1=>
10
        
11
        LED <= "00000010";
12
        
13
        when q2=>
14
        
15
        LED <= "00000100";
16
        
17
        when q3=>
18
        
19
        LED <= "00001000";
20
        
21
        when q4=>
22
        
23
        LED <= "00010000";
24
        
25
        when q5=>
26
        
27
        LED <= "00100000";
28
        
29
        when error=>
30
        
31
        LED <= "11111111";
32
        
33
34
      end case;
35
      end if;
36
  end process;

In der Simulation mit ModelSim funktioniert es soweit erst einmal, aber 
für jede Kritik wäre ich sehr Dankbar.

LG,
Daniel

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


Lesenswert?

Daniel C. schrieb:
> Ich hab in meinem Gesamtdesign eine eigene Entity zur Edgedetection
Irgendwie wären mir das zu viele klitzekleine Submodule, bei denen der 
Overhead zur Instantierung mehr Aufwand macht als die Funktion an sich.

> In der Simulation mit ModelSim funktioniert es soweit erst einmal
Wie war das mit dem  signal_in hier:
> detectedEdge   <= signal_buf xor signal_in;
Das ist schon synchron zum Takt und nicht ein asynchrones Signal von 
einem Pin?

> Die Edgedetection nutze ich dann, als "trigger" für meine FSM.
Als diesen "trigger" hier?:
Daniel C. schrieb:
>>> elsif falling_edge(trigger) then
Falls ja: so macht man das nicht, denn das wäre ein Takt und davon gibt 
es (in einem Anfängerdesign) nur einen einzigen.

Noch ein paar Anmerkungen...
Das hier ist tendenziell suboptimal:
1
  generic
2
  (
3
    MIN_COUNT : natural := 0;
4
    :
5
    :
6
    variable   cnt       : integer range MIN_COUNT to MAX_COUNT;
7
    :
8
    :
9
       elsif enable = '1' and (cnt > 0)
Was, wenn einer auf die Idee kommt, den Generic MIN_COUNT auf 1 zu 
setzen?

Und pass sehr gut auf bei Variablen. Du brauchst sie nicht für sowas 
Simples wie einen Zähler. Siehe dazu den 
Beitrag "Variable vs Signal"

Eines noch:
> (currentState, clk)
currrentState ist hier unnötig, weil der Prozess nur mit einer Änderung 
von clk neu berechnet werden muss.

von Daniel C. (danny1)


Angehängte Dateien:

Lesenswert?

Danke Lothar Mike für deine hilfreichen Hinweise,

Lothar M. schrieb:
> Daniel C. schrieb:
>> Ich hab in meinem Gesamtdesign eine eigene Entity zur Edgedetection
> Irgendwie wären mir das zu viele klitzekleine Submodule, bei denen der
> Overhead zur Instantierung mehr Aufwand macht als die Funktion an sich.

Leuchtet mir ein, habe es gut gemeint und wollte damit erreichen, dass 
das Gesamtdesgin so übersichtlich wie möglich bleibt.

Lothar M. schrieb:
> Wie war das mit dem  signal_in hier:
>> detectedEdge   <= signal_buf xor signal_in;
> Das ist schon synchron zum Takt und nicht ein asynchrones Signal von
> einem Pin?

Irgendwie habe ich die synchronisations-Thematik noch nicht ganz 
verstanden. Was hat es genau auf sich mit dem synchronisieren der 
Eingänge?

Ich habe das Design jetzt noch einmal mit ModelSim simuliert und 
speziell darauf geachtet, dass die Eingangsänderungen von SW nicht 
synchron zum Takt erfolgen. Das Ergebnis der Simulations-Waveform habe 
ich als Scrennshot angehängt.

Das Prinzip ist folgendermaßen: Das obere Signal ist der Takt vom 
externen Quarz mit 50MHz. Das darunterliegende Signal ist der 200MHz 
Takt von der PLL der für alle Teile des Designs verwendet wird. Das 
Signal "npc_stateanalyzer/SW" sind die vier digitalen Eingänge der 
Schaltung. Jedes Mal wenn sich ein Eingang ändert soll der Ausgang vom 
Edge-Detector (Die untere Signalform) getriggert werden. Soweit ich das 
vom Wavechart ablese tut er das oder nicht?

Lothar M. schrieb:
>> Die Edgedetection nutze ich dann, als "trigger" für meine FSM.
> Als diesen "trigger" hier?:
> Daniel C. schrieb:
>>>> elsif falling_edge(trigger) then
> Falls ja: so macht man das nicht, denn das wäre ein Takt und davon gibt
> es (in einem Anfängerdesign) nur einen einzigen.

Ok, würdest du hier also auch den Systemclock also das Signal "clk" zum 
triggern der FSM verwenden?

Die restlichen Anmerkungen leuchten mir ein.

Danke nochmal, das ist mir echt eine große Hilfe,

LG,
Daniel

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


Lesenswert?

Daniel C. schrieb:
> Irgendwie habe ich die synchronisations-Thematik noch nicht ganz
> verstanden. Was hat es genau auf sich mit dem synchronisieren der
> Eingänge?
Zum Thema "Warum externe Eingänge einsynchronisieren?" das da:
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren
Und zum Thema Flankenerkennung das hier:
http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung

> Ok, würdest du hier also auch den Systemclock also das Signal "clk" zum
> triggern der FSM verwenden?
Ich tu mir da jetzt ein wenig schwer mit dem "Triggern einer FSM". Das 
Wort "triggern" wird üblicherweise nicht in diesem Zusammenhang 
eingesetzt.

Die FSM besteht aus Flipflops und Logik. An die Flipflops kommt der eine 
einzige FPGA-Takt. Und die Logik bestimmt, ob und wohin bei jedem 
FPGA-Takt "weitergeschaltet" soll.

Sieh dir einfach mal ein paar Beispiele auf meiner HP an...
In deinem Fall besonders auch den:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

: Bearbeitet durch Moderator
von Daniel C. (danny1)


Lesenswert?

Lothar M. schrieb:
> Daniel C. schrieb:
>> Irgendwie habe ich die synchronisations-Thematik noch nicht ganz
>> verstanden. Was hat es genau auf sich mit dem synchronisieren der
>> Eingänge?
> Zum Thema "Warum externe Eingänge einsynchronisieren?" das da:
> http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren
> Und zum Thema Flankenerkennung das hier:
> http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung
>
>> Ok, würdest du hier also auch den Systemclock also das Signal "clk" zum
>> triggern der FSM verwenden?
> Ich tu mir da jetzt ein wenig schwer mit dem "Triggern einer FSM". Das
> Wort "triggern" wird üblicherweise nicht in diesem Zusammenhang
> eingesetzt.
>
> Die FSM besteht aus Flipflops und Logik. An die Flipflops kommt der eine
> einzige FPGA-Takt. Und die Logik bestimmt, ob und wohin bei jedem
> FPGA-Takt "weitergeschaltet" soll.
>
> Sieh dir einfach mal ein paar Beispiele auf meiner HP an...
> In deinem Fall besonders auch den:
> 
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

Vielen Dank,

Das Lesen auf deiner Webseite hat mich um einiges weitergebracht!

LG,
Daniel

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.