Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

So erstellen Sie einen endlichen Automaten in VHDL

Ein endlicher Automat (FSM) ist ein Mechanismus, dessen Ausgabe nicht nur vom aktuellen Zustand der Eingabe abhängt, sondern auch von vergangenen Eingabe- und Ausgabewerten.

Wann immer Sie einen zeitabhängigen Algorithmus in VHDL erstellen müssen oder wenn Sie vor dem Problem stehen, ein Computerprogramm in einem FPGA zu implementieren, kann dies normalerweise durch die Verwendung eines FSM gelöst werden.

Zustandsmaschinen in VHDL sind getaktete Prozesse, deren Ausgänge durch den Wert eines Zustandssignals gesteuert werden. Das Zustandssignal dient als interner Speicher dessen, was in der vorherigen Iteration passiert ist.

Dieser Blogpost ist Teil der Reihe Basic VHDL Tutorials.

Beachten Sie die Zustände der Ampeln an dieser Kreuzung:

Die Ampeln haben eine endliche Anzahl von Zuständen, denen wir identifizierbare Namen gegeben haben. Unsere beispielhafte Zustandsmaschine hat keine steuernden Eingaben, die Ausgabe ist der Zustand der Lichter in Nord/Süd- und West/Ost-Richtung. Es ist die verstrichene Zeit und der vorherige Zustand der Ausgänge, der diese Zustandsmaschine vorrückt.

Wir können Zustände in VHDL mit einem Aufzählungstyp darstellen . Dies sind Datentypen wie signed oder unsigned , aber anstelle von Ganzzahlen können wir eine benutzerdefinierte Liste möglicher Werte bereitstellen. Wenn Sie einen Blick in das Paket std_logic_1164 werfen, werden Sie tatsächlich feststellen, dass der std_ulogic Typ ist nichts anderes als ein Aufzählungstyp mit den Werten 'U' , 'X' , '0' , '1' , 'Z' , 'W' , 'L' , 'H' , und '-' als Aufzählungswerte aufgelistet.

Sobald wir unseren Aufzählungstyp haben, können wir ein Signal des neuen Typs deklarieren, das verwendet werden kann, um den aktuellen Zustand des FSM zu verfolgen.

Die Syntax zum Deklarieren eines Signals mit einem Aufzählungstyp in VHDL lautet:
type <type_name> is (<state_name1>, <state_name2>, ...);
signal <signal_name> : <type_name>;

Unter Verwendung des Zustandssignals kann der Zustandsautomat dann in einem Prozess mit einer Case-Anweisung implementiert werden. Die Case-Anweisung enthält eine When-Anweisung für jeden der möglichen Zustände, was dazu führt, dass das Programm für jeden Zustand unterschiedliche Pfade einschlägt. Die When-Anweisung kann auch Code enthalten, der in diesem bestimmten Zustand ausgeführt werden soll. Der Status ändert sich dann typischerweise, wenn eine vordefinierte Bedingung erfüllt ist.

Dies ist eine Vorlage für eine Ein-Prozess-Zustandsmaschine:
process(Clk) is
begin
    if rising_edge(Clk) then
        if nRst = '0' then
            State <= <reset_state>;
        else
            case State is
                when <state_name> =>
                    <set_outputs_for_this_state_here>
                    if <state_change_condition_is_true> then
                        State <= <next_state_name>;
                    end if;
                ...
            end case;
        end if;
    end if;
end process;

Hinweis:
Es gibt mehrere Möglichkeiten, einen FSM in VHDL zu erstellen. Lesen Sie hier mehr über die verschiedenen Stile:
Ein-Prozess- vs. Zwei-Prozess- vs. Drei-Prozess-Zustandsmaschine

Übung

In diesem Video-Tutorial lernen wir, wie man einen endlichen Automaten in VHDL erstellt:

Der endgültige Code für die Zustandsmaschine Testbench :

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T20_FiniteStateMachineTb is
end entity;

architecture sim of T20_FiniteStateMachineTb is

    -- We are using a low clock frequency to speed up the simulation
    constant ClockFrequencyHz : integer := 100; -- 100 Hz
    constant ClockPeriod : time := 1000 ms / ClockFrequencyHz;

    signal Clk         : std_logic := '1';
    signal nRst        : std_logic := '0';
    signal NorthRed    : std_logic;
    signal NorthYellow : std_logic;
    signal NorthGreen  : std_logic;
    signal WestRed     : std_logic;
    signal WestYellow  : std_logic;
    signal WestGreen   : std_logic;

begin

    -- The Device Under Test (DUT)
    i_TrafficLights : entity work.T20_TrafficLights(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk         => Clk,
        nRst        => nRst,
        NorthRed    => NorthRed,
        NorthYellow => NorthYellow,
        NorthGreen  => NorthGreen,
        WestRed     => WestRed,
        WestYellow  => WestYellow,
        WestGreen   => WestGreen);

    -- Process for generating clock
    Clk <= not Clk after ClockPeriod / 2;

    -- Testbench sequence
    process is
    begin
        wait until rising_edge(Clk);
        wait until rising_edge(Clk);

        -- Take the DUT out of reset
        nRst <= '1';

        wait;
    end process;

end architecture;

Der endgültige Code für das Modul der Zustandsmaschine :

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T20_TrafficLights is
generic(ClockFrequencyHz : integer);
port(
    Clk         : in std_logic;
    nRst        : in std_logic; -- Negative reset
    NorthRed    : out std_logic;
    NorthYellow : out std_logic;
    NorthGreen  : out std_logic;
    WestRed     : out std_logic;
    WestYellow  : out std_logic;
    WestGreen   : out std_logic);
end entity;

architecture rtl of T20_TrafficLights is

    -- Enumerated type declaration and state signal declaration
    type t_State is (NorthNext, StartNorth, North, StopNorth,
                        WestNext, StartWest, West, StopWest);
    signal State : t_State;

    -- Counter for counting clock periods, 1 minute max
    signal Counter : integer range 0 to ClockFrequencyHz * 60;

begin

    process(Clk) is
    begin
        if rising_edge(Clk) then
            if nRst = '0' then
                -- Reset values
                State   <= NorthNext;
                Counter <= 0;
                NorthRed    <= '1';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '1';
                WestYellow  <= '0';
                WestGreen   <= '0';

            else
                -- Default values
                NorthRed    <= '0';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '0';
                WestYellow  <= '0';
                WestGreen   <= '0';

                Counter <= Counter + 1;

                case State is

                    -- Red in all directions
                    when NorthNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= StartNorth;
                        end if;

                    -- Red and yellow in north/south direction
                    when StartNorth =>
                        NorthRed    <= '1';
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= North;
                        end if;

                    -- Green in north/south direction
                    when North =>
                        NorthGreen <= '1';
                        WestRed    <= '1';
                        -- If 1 minute has passed
                        if Counter = ClockFrequencyHz * 60 -1 then
                            Counter <= 0;
                            State   <= StopNorth;
                        end if;

                    -- Yellow in north/south direction
                    when StopNorth =>
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= WestNext;
                        end if;

                    -- Red in all directions
                    when WestNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= StartWest;
                        end if;

                    -- Red and yellow in west/east direction
                    when StartWest =>
                        NorthRed   <= '1';
                        WestRed    <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= West;
                        end if;

                    -- Green in west/east direction
                    when West =>
                        NorthRed  <= '1';
                        WestGreen <= '1';
                        -- If 1 minute has passed
                        if Counter = ClockFrequencyHz * 60 -1 then
                            Counter <= 0;
                            State   <= StopWest;
                        end if;

                    -- Yellow in west/east direction
                    when StopWest =>
                        NorthRed   <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = ClockFrequencyHz * 5 -1 then
                            Counter <= 0;
                            State   <= NorthNext;
                        end if;

                end case;

            end if;
        end if;
    end process;

end architecture;

Die Wellenform nachdem wir run 5 min eingegeben haben Befehl in der ModelSim-Konsole:

Analyse

Wir haben einen Aufzählungstyp mit allen acht verschiedenen Zuständen unserer Ampeln deklariert. Dann haben wir einen state deklariert Signal dieses neuen Typs, den wir geschaffen haben. Das bedeutet, dass das Signal nur einen der acht genannten Zustandswerte haben kann und keine anderen Werte.

Die FSM wurde unter Verwendung einer Case-Anweisung innerhalb eines getakteten Prozesses implementiert. Bei jeder steigenden Flanke der Uhr wacht der Prozess auf und der state Signal ausgewertet. Der Code in genau einem der when Choices (Zweige) dürfen ausgeführt werden, je nach aktuellem Status.

In unserem Code ist es der Wert von Counter Signal, das Zustandsänderungen auslöst. Wenn der Zähler einen vordefinierten Wert erreicht, der 5 Sekunden oder 1 Minute darstellt, wird State eine neue Zustandscodierung zugewiesen Signal. Wenn der Prozess dann bei der nächsten steigenden Flanke der Uhr aufwacht, nachdem der Zustandswert aktualisiert wurde, befindet sich die FSM in einem anderen Zustand.

Beachten Sie, dass wir '0' nicht zuweisen zu jedem Signal in einem der when Auswahlmöglichkeiten. Dies liegt daran, dass wir allen Ausgangssignalen einen Standardwert von '0' gegeben haben zu Beginn des Prozesses. Sie erinnern sich vielleicht aus einem früheren Tutorial, dass der letzte Wert, der einem Signal zugewiesen wird, wirksam wird. Signalzuweisungen werden erst wirksam, nachdem der Prozess beendet ist. Wenn wir '0' zuweisen zum Signal am Anfang des Prozesses und dann '1' in einem der when Auswahlmöglichkeiten erhält das Signal den Wert '1' .

Wir können an der Wellenform erkennen, dass State Signal durchläuft die acht Zustände. Die grünen Dauerzustände dauern eine Minute, das Wellenformbild wurde daher in North geschnitten und West Staaten.

Imbiss

Weiter zum nächsten Tutorial »


VHDL

  1. Finite-State-Maschine
  2. So stellen Sie die beste Leistung der Qt-Zustandsmaschine sicher
  3. So erstellen Sie eine Liste von Zeichenfolgen in VHDL
  4. So erstellen Sie eine Tcl-gesteuerte Testbench für ein VHDL-Code-Sperrmodul
  5. So stoppen Sie die Simulation in einer VHDL-Testbench
  6. So erstellen Sie einen PWM-Controller in VHDL
  7. So generieren Sie Zufallszahlen in VHDL
  8. So erstellen Sie eine selbstüberprüfende Testbench
  9. So erstellen Sie eine verknüpfte Liste in VHDL
  10. Wie erstellt OMNI CNC-Lasermaschinen personalisierte Weihnachtsgeschenke?