Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Een eindige-toestandsmachine maken in VHDL

Een eindige-toestandsmachine (FSM) is een mechanisme waarvan de uitvoer niet alleen afhankelijk is van de huidige status van de invoer, maar ook van eerdere invoer- en uitvoerwaarden.

Wanneer u een soort tijdsafhankelijk algoritme in VHDL moet maken, of als u wordt geconfronteerd met het probleem van het implementeren van een computerprogramma in een FPGA, kan dit meestal worden opgelost met behulp van een FSM.

State-machines in VHDL zijn geklokte processen waarvan de uitgangen worden bestuurd door de waarde van een statussignaal. Het statussignaal dient als een intern geheugen van wat er in de vorige iteratie is gebeurd.

Deze blogpost maakt deel uit van de serie Basic VHDL Tutorials.

Houd rekening met de toestand van de verkeerslichten op dit kruispunt:

De verkeerslichten hebben een eindig aantal toestanden, die we herkenbare namen hebben gegeven. Onze voorbeeldstatusmachine heeft geen controlerende inputs, de output is de status van de lichten in noord/zuid en west/oost richtingen. Het is de verstreken tijd en de vorige toestand van de uitgangen die deze toestandsmachine vooruithelpen.

We kunnen staten in VHDL weergeven met behulp van een opgesomd type . Dit zijn gegevenstypen, net als signed of unsigned , maar in plaats van gehele getallen kunnen we een aangepaste lijst met mogelijke waarden leveren. Als je in het std_logic_1164-pakket kijkt, zul je zien dat de std_ulogic type is niets meer dan een opgesomd type met de waarden 'U' , 'X' , '0' , '1' , 'Z' , 'W' , 'L' , 'H' , en '-' vermeld als opsommingswaarden.

Zodra we ons opgesomde type hebben, kunnen we een signaal van het nieuwe type declareren dat kan worden gebruikt om de huidige status van de FSM bij te houden.

De syntaxis voor het declareren van een signaal met een opgesomd type in VHDL is:
type <type_name> is (<state_name1>, <state_name2>, ...);
signal <signal_name> : <type_name>;

Met behulp van het toestandssignaal kan de eindige-toestandsmachine vervolgens worden geïmplementeerd in een proces met een Case-statement. Het Case-statement bevat een When-statement voor elk van de mogelijke toestanden, waardoor het programma voor elke toestand een ander pad volgt. Het When-statement kan ook code bevatten die moet worden uitgevoerd in die specifieke staat. De status verandert dan meestal wanneer aan een vooraf gedefinieerde voorwaarde wordt voldaan.

Dit is een sjabloon voor een-proces-statusmachine:
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;

Opmerking:
Er zijn verschillende manieren om een ​​FSM in VHDL te maken. Lees hier meer over de verschillende stijlen:
Een-proces vs twee-process vs drie-process toestandsmachine

Oefening

In deze video-tutorial leren we hoe we een eindige-toestandsmachine in VHDL kunnen maken:

De definitieve code voor de toestandsmachine 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;

De laatste code voor de state machine module :

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;

De golfvorm nadat we de run 5 min . hebben ingevoerd commando in de ModelSim-console:

Analyse

We hebben een opgesomd type aangegeven met alle acht verschillende toestanden van onze verkeerslichten. Vervolgens hebben we een state . gedeclareerd signaal van dit nieuwe type dat we hebben gemaakt. Dit betekent dat het signaal slechts één van de acht genoemde statuswaarden kan hebben, en geen andere waarden.

De FSM is geïmplementeerd met behulp van een Case-statement binnen een geklokt proces. Op elke stijgende flank van de klok wordt het proces wakker en de state signaal wordt beoordeeld. De code binnen precies één van de when keuzes (takken) mogen worden uitgevoerd, afhankelijk van de huidige status.

In onze code is dit de waarde van de Counter signaal dat toestandsveranderingen veroorzaakt. Wanneer de teller een vooraf gedefinieerde waarde bereikt, die 5 seconden of 1 minuut vertegenwoordigt, wordt een nieuwe statuscodering toegewezen aan de State signaal. Wanneer het proces vervolgens ontwaakt op de volgende stijgende flank van de klok nadat de statuswaarde is bijgewerkt, bevindt de FSM zich in een andere status.

Merk op dat we '0' . niet toewijzen op elk signaal in een van de when keuzes. Dit komt omdat we alle uitgangssignalen een standaardwaarde van '0' . hebben gegeven aan het begin van het proces. U herinnert zich misschien van een vorige tutorial dat het de laatste waarde is die wordt toegewezen aan een signaal dat effectief wordt. Signaaltoewijzingen worden pas van kracht nadat het proces is beëindigd. Als we '0' . toewijzen naar het signaal aan het begin van het proces, en dan '1' in een van de when keuzes, het signaal krijgt de waarde '1' .

We kunnen aan de golfvorm zien dat de State signaal doorloopt de acht toestanden. De ononderbroken groene toestanden duren één minuut, het golfvormbeeld is daarom in de North . gesneden en West staten.

Afhaalmaaltijden

  • Algoritmen worden meestal geïmplementeerd als finite-state machines (FSM's)
  • Een FSM kan worden geïmplementeerd door een case-statement te gebruiken in een geklokt proces
  • FSM-statussen kunnen worden geïmplementeerd in een opgesomd type

Ga naar de volgende tutorial »


VHDL

  1. Finite-state machine
  2. Hoe de beste Qt-statusmachineprestaties te garanderen
  3. Een lijst met strings maken in VHDL
  4. Hoe maak je een Tcl-gestuurde testbench voor een VHDL-codeslotmodule?
  5. Simulatie stoppen in een VHDL-testbench
  6. Een PWM-controller maken in VHDL
  7. Hoe willekeurige getallen te genereren in VHDL
  8. Hoe maak je een ringbuffer FIFO in VHDL
  9. Hoe maak je een zelfcontrolerende testbank aan
  10. Een gekoppelde lijst maken in VHDL
  11. Hoe OMNI CNC-lasermachine gepersonaliseerde kerstcadeaus maakt?