用VHDL设计有限状态机:红绿灯实战范例
有限状态机(FSM)是一种确定性逻辑模型,其输出不仅取决于当前输入,还取决于过去输入和输出的序列。在FPGA设计和时序相关VHDL算法中,FSM是捕捉有状态行为的首选抽象。
VHDL中FSM通常实现为时钟进程,用state信号记忆上一配置。状态信号充当内部寄存器,使设计能对跨越多个时钟周期的事件做出反应。
基础VHDL教程 – 第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;
注意: FSM可用单进程、双进程或三进程风格实现。见FSM风格详解。
实战练习
下面是实现红绿灯控制器的完整可综合示例。设计用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 -- Default outputs 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循环经过其八个状态,绿相各持续一分钟。

分析
代码关键点:
- 枚举类型将
State信号限制在已知有效值集,提升安全性和可读性。 - 进程开始处用默认值驱动所有输出;后续状态分支仅覆盖变化的信号。
Counter变量是定时引擎,其阈值(5秒、60秒)源自时钟频率。
波形确认FSM正确推进:State信号切换经过八个定义状态,每个绿相持续一分钟。
要点
- 有限状态机是VHDL实现时序逻辑的标准方式。
- 时钟进程内的
case语句清晰映射各状态到其行为。 - 枚举类型通过限制允许状态值提供编译期安全性。
进入下一教程学习高级FSM技术。
VHDL