산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

VHDL에서 유한 상태 기계를 만드는 방법

유한 상태 기계(FSM)는 출력이 입력의 현재 상태뿐만 아니라 과거 입력 및 출력 값에 따라 달라지는 메커니즘입니다.

VHDL에서 일종의 시간 종속 알고리즘을 생성해야 할 때마다 또는 FPGA에서 컴퓨터 프로그램을 구현하는 문제에 직면한 경우 일반적으로 FSM을 사용하여 해결할 수 있습니다.

VHDL의 상태 머신은 상태 신호 값에 의해 출력이 제어되는 클럭 프로세스입니다. 상태 신호는 이전 반복에서 발생한 일의 내부 메모리 역할을 합니다.

이 블로그 게시물은 기본 VHDL 자습서 시리즈의 일부입니다.

이 교차로의 신호등 상태를 고려하십시오.

신호등에는 식별 가능한 이름을 부여한 제한된 수의 상태가 있습니다. 우리의 예제 상태 머신에는 제어 입력이 없으며 출력은 북쪽/남쪽 및 서쪽/동쪽 방향의 조명 상태입니다. 이 상태 머신을 진행시키는 것은 경과 시간과 출력의 이전 상태입니다.

열거형을 사용하여 VHDL로 상태를 나타낼 수 있습니다. . signed와 같은 데이터 유형입니다. 또는 unsigned 하지만 정수 대신 가능한 값의 사용자 지정 목록을 제공할 수 있습니다. 실제로 std_logic_1164 패키지를 살펴보면 std_ulogic type은 값이 'U'인 열거형에 불과합니다. , 'X' , '0' , '1' , 'Z' , 'W' , 'L' , 'H''-' 열거형 값으로 나열됩니다.

열거된 유형이 있으면 FSM의 현재 상태를 추적하는 데 사용할 수 있는 새 유형의 신호를 선언할 수 있습니다.

VHDL에서 열거형으로 신호를 선언하는 구문은 다음과 같습니다.
type <type_name> is (<state_name1>, <state_name2>, ...);
signal <signal_name> : <type_name>;

상태 신호를 사용하여 유한 상태 기계는 Case 문이 있는 프로세스에서 구현될 수 있습니다. Case 문에는 가능한 각 상태에 대한 When 문이 포함되어 있어 프로그램이 모든 상태에 대해 다른 경로를 사용하도록 합니다. When 문에는 특정 상태에 있는 동안 실행되어야 하는 코드도 포함될 수 있습니다. 그러면 일반적으로 미리 정의된 조건이 충족되면 상태가 변경됩니다.

다음은 단일 프로세스 상태 시스템에 대한 템플릿입니다.
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;

참고:
VHDL에서 FSM을 만드는 방법에는 여러 가지가 있습니다. 여기에서 다양한 스타일에 대해 읽어보세요.
1-프로세스 vs. 2-프로세스 vs. 3-프로세스 상태 머신

운동

이 비디오 자습서에서는 VHDL에서 유한 상태 기계를 만드는 방법을 배웁니다.

상태 머신 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;

상태 시스템 모듈의 최종 코드 :

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;

run 5 min를 입력한 후의 파형 ModelSim 콘솔의 명령:

분석

우리는 신호등의 8가지 다른 상태를 모두 사용하여 열거형을 선언했습니다. 그런 다음 state를 선언했습니다. 우리가 만든 이 새로운 유형의 신호. 이것은 신호가 8개의 명명된 상태 값 중 하나만 가질 수 있고 다른 값은 가질 수 없음을 의미합니다.

FSM은 클럭 프로세스 내에서 Case-statement를 사용하여 구현되었습니다. 클록의 각 상승 에지에서 프로세스가 깨어나고 state 신호가 평가됩니다. when 중 정확히 하나 내의 코드 현재 상태에 따라 선택 항목(가지)을 실행할 수 있습니다.

우리 코드에서는 Counter의 값입니다. 상태 변화를 유발하는 신호. 카운터가 5초 또는 1분을 나타내는 사전 정의된 값에 도달하면 새 상태 인코딩이 State에 할당됩니다. 신호. 그런 다음 상태 값이 업데이트된 후 클록의 다음 상승 에지에서 프로세스가 깨어나면 FSM은 다른 상태가 됩니다.

'0'을 할당하지 않습니다. when의 모든 신호에 선택. 이는 모든 출력 신호에 기본값 '0'를 지정했기 때문입니다. 프로세스의 시작 부분에서. 이전 튜토리얼에서 유효하게 되는 신호에 할당된 마지막 값이라는 것을 기억할 수 있습니다. 신호 할당은 프로세스가 종료된 후에만 유효합니다. '0'를 할당하면 프로세스 시작 시 신호에 연결한 다음 '1' when 중 하나에서 선택하면 신호는 '1' 값을 얻습니다. .

파형에서 State 신호는 8개 상태를 순환합니다. 안정적인 녹색 상태는 1분 동안 지속되므로 파형 이미지가 North에서 잘립니다. 및 West 상태.

테이크아웃

다음 튜토리얼로 이동 »


VHDL

  1. 유한 상태 기계
  2. 최상의 Qt 상태 시스템 성능을 보장하는 방법
  3. VHDL에서 문자열 목록을 만드는 방법
  4. VHDL 코드 잠금 모듈을 위한 Tcl 기반 테스트벤치를 만드는 방법
  5. VHDL 테스트벤치에서 시뮬레이션을 중지하는 방법
  6. VHDL에서 PWM 컨트롤러를 만드는 방법
  7. VHDL에서 난수를 생성하는 방법
  8. 자가 점검 테스트벤치를 만드는 방법
  9. VHDL에서 연결 목록을 만드는 방법
  10. OMNI CNC 레이저 기계가 개인화된 크리스마스 선물을 만드는 방법은 무엇입니까?