Hallo,
ich möchte in VHDL eine Finite-State-Machine programmieren.
Ich habe 4 Zustände, die die SM annehmen kann. Allerdings ist mir das
Prinzip noch nicht klar, wie man in VHDL gewährleistet, dass die FSM ab
Start im Zustand_1(z0) beginnt und nicht irgendwo anders.
Danke im Voraus!
library IEEE;
use IEEE.std_logic_1164.all;
ENTITY fsm_tst IS
PORT( clk, Sin : IN std_logic;
Zustand : BUFFER std_logic_vector(1 downto 0);
Sout : OUT std_logic);
END fsm_tst;
ARCHITECTURE arch_fsm_tst OF fsm_tst IS
CONSTANT z0 : std_logic_vector(1 downto 0) := "00";
CONSTANT z1 : std_logic_vector(1 downto 0) := "01";
CONSTANT z2 : std_logic_vector(1 downto 0) := "10";
BEGIN
Zustandsfolge : PROCESS( clk )
BEGIN
IF( clk'EVENT AND clk = '1' ) then
CASE Zustand IS
WHEN z0 =>
IF Sin = '1' THEN
Zustand <= z1;
ELSE
Zustand <= z0;
END IF;
WHEN z1 =>
Zustand <= z2;
WHEN z2 =>
Zustand <= z0;
WHEN OTHERS => -- Dummy-Zustand
Zustand <= z0;
END CASE;
END IF;
END PROCESS;
Ausgaenge : PROCESS( Zustand, Sin )
BEGIN
CASE Zustand IS
WHEN z0 =>
Sout <= '0';
WHEN z1 =>
Sout <= '1';
WHEN z2 =>
Sout <= Sin;
WHEN OTHERS =>
Sout <= '0';
END CASE;
END PROCESS;
END arch_fsm_tst;
Dazu gibt's mehrere Möglichkeiten.
- Du verwendest ein RESET Signal welches den Zustand z0 erzwingt.
Dies funktioniert immer und Simulation und HW stimmen garantiert
überein.
- Du verwendest einen Initialisierungswert.
Dazu ist es besser, wenn Dein Zustandsvektor ein internes Signal ist,
und nicht ein BUFFER-Signal deiner Entity.
1
ENTITYfsm_tstIS
2
PORT(clk,Sin:INstd_logic;
3
Zustand:OUTstd_logic_vector(1downto0);
4
Sout:OUTstd_logic);
5
ENDfsm_tst;
6
7
ARCHITECTUREarch_fsm_tstOFfsm_tstIS
8
CONSTANTz0:std_logic_vector(1downto0):="00";
9
CONSTANTz1:std_logic_vector(1downto0):="01";
10
CONSTANTz2:std_logic_vector(1downto0):="10";
11
12
signalZ:std_logic_vector(1downto0):=z0;
13
14
BEGIN
15
Zustandsfolge:PROCESS(clk)
16
BEGIN
17
IFrising_edge(clk)then
18
CASEZustandIS
19
...
20
ENDPROCESS;
21
22
Zustand<=Z;
23
END
Das Problem dabei ist, daß ältere Compiler nicht imstande sind, den
Initialisierungswert in HW umzusetzen.
Wenn Du aber z.B. Xilinx Webpack/ISE ab Version 7.1 verwendest, dann
sollte es klappen.
@Klaus Felser
-ARCHITECTURE arch_fsm_tst OF fsm_tst IS
-CONSTANT z0 : std_logic_vector(1 downto 0) := "00";
-CONSTANT z1 : std_logic_vector(1 downto 0) := "01";
-CONSTANT z2 : std_logic_vector(1 downto 0) := "10";
-signal Z : std_logic_vector(1 downto 0) := z0;
-BEGIN
-Zustandsfolge : PROCESS( clk )
1:
Das Signal Z wird in Architekture initialisiert. Bedeutet dies, dass
VHDL diesen Teil des Moduls nur 1x durchläuft, und nicht unendlich oft,
wie es bei anderen Teilen des Programmes der Fall ist?
Als Bsp: Jeder Prozess wird so oft gestartet, so oft der Prozess
aufgerufen wird.
2:
-Das Problem dabei ist, daß ältere Compiler nicht imstande sind, den
-Initialisierungswert in HW umzusetzen.
-Wenn Du aber z.B. Xilinx Webpack/ISE ab Version 7.1 verwendest, dann
-sollte es klappen.
Kann ich mit Quartus 5.1 sicher sein, dass der Initialisierunswert in
HW umgesetzt wird?
1) Im Prinzip ja. Z wird mit 1 x mit z0 initialisiert.
2) Weiss ich leider nicht, ich habe mit Altera noch nie gearbeitet.
Vielleicht weiss es jemand anderer.
Man kann zwar z0 als "00" wählen, wie Du es gemacht hast und sich
drauf verlassen, daß alle FF mit '0' aufwachen.
Falls aber der Compiler oder Fitter deine Gleichungen optimiert und ein
Bit deines Zustandsvektors invertiert, weil es günstiger zum
Implementieren ist, dann wacht deine FSM mit dem falschen Startwert
auf.
Dies ist zwar unwahrscheinlich, könnte aber passieren.
Hallo,
die oben gezeigte Zwei-Prozess Dartsellung einer FSM läßt sich auch in
eine Ein-Prozess-Darstellung vereinfachen, zudem läßt sich über die
Typendeklaration eine FSM (Typ Moore) inklu Zuständen deklarieren.
Desweiteren wird das Eingangssignal auf den Systemtakt "clk"
eingesampelt (Synchronisierung)
1
ENTITYFSM_exampleIS
2
PORT(clk:std_logic;
3
reset:std_logic;
4
input:std_logic_vector(1DOWNTO0);
5
output:std_logic_vector(3DOWNTO0);
6
);
7
ENDFSM_example;
8
9
10
ARCHITECTUREFSM_behOFFSM_exampleIS
11
12
TYPEFSM_1IS(State_1,State_2,State_3);
13
SIGNALState_FSM:FSM_1:=State_1;
14
.
15
SIGNALinput_q:std_logic;
16
.
17
18
One_Procss_Discription:PROCESS(clk,reset)
19
IFreset='1'THEN
20
input_q<='0';-- Reset-Initialisierung
21
output<=(OTHERS=>'0');-- "
22
State_FSM<=State_1;-- " ,
23
Startzustand
24
ELSIFrising_edge(clk)THEN
25
input_q<=input;-- Einsampeln des
26
EingangssignalaufSystemtakt"clk"
27
CASEFSM_1IS
28
WHENState_1=>
29
IFinput_q='1'THEN-- Startwert der FSM vom Typ Moore
30
output<="1000";
31
State_FSM<=State_2;
32
ENDIF;
33
34
WHENState_2=>
35
output<="0110";
36
State_FSM<=State_3;
37
38
WHENState_3=>
39
output<="1111";
40
State_FSM<=State_1;
41
42
WHENOTHERS=>-- alle irregulären Zustände
43
output<="0000";-- werden mit mit
44
Reset-Values
45
State_FSM<=State_1;-- initialisiert, d.h.
46
"Aufhängen"derFSMwirdvermieden
47
48
ENDCASEFSM_1;
49
ENDIF;
50
ENDPROCESS;
51
ENDFSM_beh;
Habe die FSM mal auf die Schnelle eingehackt....hoffe, es haben sich
keine Fehler eingeschlichen.
Die Ein-Prozess-Darstellung erreicht die beste Simulationseffizienz und
da die Übergangs- und Ausgangsschaltnetze in dem getakteten Prozess
integriert sind, werden für alle im Prozess verwendeten Signale D-FF
durch das Synthesetool D-FF generiert.
Gruß
Tom