유한 상태 머신(FSM)은 현재 입력뿐만 아니라 과거 입력과 출력의 시퀀스에 따라 출력이 결정되는 결정론적 논리 모델입니다. FPGA 설계와 시간 의존적 VHDL 알고리즘에서 FSM은 상태ful 동작을 포착하는 표준 추상화입니다.
VHDL에서 FSM은 일반적으로 state 시그널을 사용해 마지막 구성을 기억하는 클록된 프로세스로 구현됩니다. 상태 시그널은 내부 레지스터 역할을 해 설계가 여러 클록 사이클에 걸친 이벤트에 반응할 수 있게 합니다.
Basic VHDL Tutorials – Part 3
신호등을 FSM으로
교통 신호등으로 제어되는 사거리를 생각해 보세요. 신호등은 유한한 가시 상태 집합을 순환합니다. 예: 남북 적색, 남북 녹색, 동서 적색 등. 각 상태의 타이밍(적색/황색 5초, 녹색 60초)은 경과된 클록 사이클로 구동됩니다.
이 동작을 모델링하려면 가능한 모든 상태를 나열하는 열거 타입을 정의합니다:
type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest);
그리고 현재 상태를 저장할 해당 타입의 시그널을 선언합니다:
signal State : t_State;
상태 시그널이 준비되면 FSM 로직은 case 문을 사용하는 단일 클록된 프로세스에 들어갑니다. 각 when 분기는 고유한 상태에 해당하며 해당 상태의 출력 할당을 포함합니다. 카운터가 경과 시간을 추적하고 값이 미리 정의된 임계값에 도달하면 다음 상태로 전이시킵니다.
단일 프로세스 FSM 템플릿
process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then State <= <reset_state>; Counter <= 0; 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;
아래는 신호등 컨트롤러를 구현한 완전 합성 가능 예제입니다. 시뮬레이션 단순화를 위해 100Hz 클록을 쓰면서도 현실적 타이밍을 시연합니다.
테스트벤치
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 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 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); Clk <= not Clk after ClockPeriod / 2; process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); 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; -- Active low 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 type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; signal Counter : integer range 0 to ClockFrequencyHz * 60; begin process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then State <= NorthNext; Counter <= 0; NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; else -- 기본 출력 NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is when NorthNext => NorthRed <= '1'; WestRed <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= StartNorth; end if; when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= North; end if; when North => NorthGreen <= '1'; WestRed <= '1'; if Counter = ClockFrequencyHz * 60 - 1 then Counter <= 0; State <= StopNorth; end if; when StopNorth => NorthYellow <= '1'; WestRed <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= WestNext; end if; when WestNext => NorthRed <= '1'; WestRed <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= StartWest; end if; when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= West; end if; when West => NorthRed <= '1'; WestGreen <= '1'; if Counter = ClockFrequencyHz * 60 - 1 then Counter <= 0; State <= StopWest; end if; when StopWest => NorthRed <= '1'; WestYellow <= '1'; if Counter = ClockFrequencyHz * 5 - 1 then Counter <= 0; State <= NorthNext; end if; end case; end if; end if; end process; end architecture;
5분간 시뮬레이션 실행 시 FSM이 8개 상태를 순환하며 각 녹색 단계가 1분씩 지속되는 파형이 나옵니다.
분석
코드에서 얻을 수 있는 핵심 사항:
열거 타입으로 State 시그널을 알려진 유효 값 집합으로 제한해 안전성과 가독성 향상.
프로세스 시작 시 모든 출력에 기본값 드라이브, 이후 상태 분기에서 변경되는 시그널만 오버라이드.
Counter 변수가 타이밍 엔진 역할을 하며 임계값(5초, 60초)은 클록 주파수에서 유도.
결과 파형은 FSM이 올바르게 전진함을 확인시켜 줍니다: State 시그널이 정의된 8개 상태를 토글하고 각 녹색 단계가 1분간 지속됩니다.