Forum: FPGA, VHDL & Co. State_Machine


von VHDL-Beginner (Gast)


Lesenswert?

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;

von Klaus Falser (Gast)


Lesenswert?

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
ENTITY fsm_tst IS
2
    PORT( clk, Sin : IN std_logic;
3
          Zustand  : OUT std_logic_vector(1 downto 0);
4
          Sout     : OUT std_logic);
5
END fsm_tst;
6
7
ARCHITECTURE arch_fsm_tst OF fsm_tst IS
8
    CONSTANT z0 : std_logic_vector(1 downto 0) := "00";
9
    CONSTANT z1 : std_logic_vector(1 downto 0) := "01";
10
    CONSTANT z2 : std_logic_vector(1 downto 0) := "10";
11
12
    signal   Z  : std_logic_vector(1 downto 0) := z0;
13
14
BEGIN
15
    Zustandsfolge : PROCESS( clk )
16
    BEGIN
17
      IF rising_edge(clk) then
18
        CASE Zustand IS
19
...
20
    END PROCESS;
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.

von Sebastian (Gast)


Lesenswert?

Eine schöne Methode für die Zustandsdeklaration.
1
architecture beh1 of fsm is
2
 type state_type is (s1,s2,s3,s4);
3
 signal state: state_type;
4
begin
5
process1: process (clk, reset)
6
begin
7
 if (reset =&#8217;1&#8217;) then
8
    state <= s1;
9
 elsif (clk=&#8217;1&#8217; and clk&#8217;Event) then
10
    case state is
11
     when s1 =>
12
       if x1=&#8217;1&#8217; then
13
       state <= s2;
14
       else .....

und nie das when others vergessen....

Sebastian

von VHDL-Beginner (Gast)


Lesenswert?

@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?

von Klaus F. (kfalser)


Lesenswert?

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.

von VHDL-Beginner (Gast)


Lesenswert?

Vielen Dank für diese Infos!

von Sascha (Gast)


Lesenswert?

>Kann ich mit Quartus 5.1 sicher sein, dass der Initialisierunswert in
>HW umgesetzt wird?

Kurz und knapp: Ja

von Tom (Gast)


Lesenswert?

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
ENTITY FSM_example IS
2
   PORT ( clk    : std_logic;
3
          reset  : std_logic;
4
          input  : std_logic_vector(1 DOWNTO 0);
5
          output : std_logic_vector(3 DOWNTO 0);
6
        );
7
END FSM_example;
8
9
10
ARCHITECTURE FSM_beh OF FSM_example IS
11
12
TYPE FSM_1 IS (State_1, State_2, State_3);
13
SIGNAL State_FSM : FSM_1 := State_1;
14
.
15
SIGNAL input_q   : std_logic;
16
.
17
18
One_Procss_Discription : PROCESS(clk,reset)
19
 IF reset = '1' THEN
20
   input_q           <= '0';             -- Reset-Initialisierung
21
   output            <= (OTHERS => '0'); --           "
22
   State_FSM         <= State_1;         --           " ,
23
Startzustand
24
 ELSIF rising_edge(clk) THEN
25
   input_q           <= input;           -- Einsampeln des
26
Eingangssignal auf Systemtakt "clk"
27
   CASE FSM_1 IS
28
     WHEN State_1 =>
29
       IF input_q = '1' THEN    -- Startwert der FSM vom Typ Moore
30
          output     <= "1000"; 
31
          State_FSM  <= State_2;
32
       END IF;
33
   
34
     WHEN State_2 =>
35
       output       <= "0110";
36
       State_FSM    <= State_3;
37
38
     WHEN State_3 =>
39
       output       <= "1111";
40
       State_FSM    <= State_1;
41
42
     WHEN OTHERS =>                     -- 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" der FSM wird vermieden
47
 
48
   END CASE FSM_1; 
49
  END IF;
50
 END PROCESS;
51
END FSM_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

von Tom (Gast)


Lesenswert?

Sorry,

Zeilen 23,26,44,46 gehören zu den vorherigen Kommentaren....

von Tom (Gast)


Lesenswert?

Noch ein Fehler gefunden....
So ist richtig
1
ENTITY FSM_example IS
2
    PORT ( clk    : IN std_logic;
3
           reset  : IN std_logic;
4
           input  : IN std_logic_vector(1 DOWNTO 0);
5
           output : OUT std_logic_vector(3 DOWNTO 0);
6
         );
7
END FSM_example;

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.