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
libraryieee;
2
useieee.std_logic_1164.all;
3
useieee.numeric_std.all;
4
5
6
entityCounteris
7
8
generic
9
(
10
MIN_COUNT:natural:=0;
11
MAX_COUNT:natural:=140
12
);
13
14
port
15
(
16
clk:inSTD_ULOGIC;
17
reset:inSTD_ULOGIC;
18
enable:inSTD_ULOGIC;
19
q:outinteger
20
);
21
22
endentity;
23
24
architecturertlofCounteris
25
begin
26
27
process(clk)
28
variablecnt:integerrangeMIN_COUNTtoMAX_COUNT;
29
begin
30
if(rising_edge(clk))then
31
32
ifreset='1'then
33
-- Reset the counter to 140
34
cnt:=140;
35
36
elsifenable='1'and(cnt>0)
37
)then
38
-- Decrement the counter if counting is enabled
39
cnt:=cnt-1;
40
41
endif;
42
endif;
43
44
-- Output the current count
45
q<=cnt;
46
endprocess;
47
endrtl;
Hier noch wie der jeweilige State mit der exit-Strategy aussieht:
1
whenq2=>--q2 state
2
3
4
5
ifinput=inputQ3and(count=0)then
6
lastState<=currentState;
7
currentState<=q3;
8
resetCounter<='1';
9
enableCounter<='0';
10
11
12
elsifinput=inputIdleand(count=0)then
13
lastState<=currentState;
14
currentState<=idle;
15
resetCounter<='1';
16
enableCounter<='0';
17
18
elsifinput=inputQ1and(count=0)then
19
lastState<=currentState;
20
currentState<=q1;
21
resetCounter<='1';
22
enableCounter<='0';
23
24
25
elsifinput=inputQ4and(count=0)then
26
lastState<=currentState;
27
currentState<=q4;
28
resetCounter<='1';
29
enableCounter<='0';
30
31
32
elsifinput=inputQ2and(count=0)then
33
lastState<=currentState;
34
currentState<=q2;
35
resetCounter<='1';
36
enableCounter<='0';
37
38
else
39
currentState<=error;
40
endif;
41
42
LED<="00000100";
Bitte verzeiht mir diverse Verstöße gegen VHDL-Konventionen, ich stehe
noch ziemlich in der Einarbeitungsphase mit VHDL.
LG,
Daniel
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 ....
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
elsiffalling_edge(trigger)then
2
3
ifnot(lastState=currentState)then
4
5
resetCounter<='0';
6
enableCounter<='1';
7
8
endif;
auf
1
elsiffalling_edge(trigger)then
2
3
iflastState/=currentStatethen
4
5
resetCounter<='0';
6
enableCounter<='1';
7
8
endif;
geändert, nun scheint es zu funktionieren.
Entschuldigt nochmal die vergessene Fragestellung, war nicht mit
Absicht,
LG,
Daniel
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
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.
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
ifrising_edge(clk)then
4
casecurrentStateis
5
whenidle=>
6
7
LED<="00000001";
8
9
whenq1=>
10
11
LED<="00000010";
12
13
whenq2=>
14
15
LED<="00000100";
16
17
whenq3=>
18
19
LED<="00001000";
20
21
whenq4=>
22
23
LED<="00010000";
24
25
whenq5=>
26
27
LED<="00100000";
28
29
whenerror=>
30
31
LED<="11111111";
32
33
34
endcase;
35
endif;
36
endprocess;
In der Simulation mit ModelSim funktioniert es soweit erst einmal, aber
für jede Kritik wäre ich sehr Dankbar.
LG,
Daniel
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
variablecnt:integerrangeMIN_COUNTtoMAX_COUNT;
7
:
8
:
9
elsifenable='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.
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
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
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