Diseño de máquina de estados finitos en VHDL: Ejemplo práctico de semáforo
Una máquina de estados finitos (FSM) es un modelo lógico determinista cuya salida depende no solo de la entrada actual sino también de la secuencia de entradas y salidas pasadas. En diseño FPGA y algoritmos VHDL dependientes del tiempo, una FSM es la abstracción de referencia para capturar comportamiento con estado.
Las FSM en VHDL se implementan típicamente como procesos con reloj que usan una señal state para recordar la última configuración. La señal de estado actúa como un registro interno, permitiendo que el diseño reaccione a eventos que abarcan múltiples ciclos de reloj.
Tutoriales Básicos de VHDL – Parte 3
Semáforos como FSM
Considere una intersección de cuatro vías controlada por semáforos. Las luces ciclan a través de un conjunto finito de estados visibles —por ejemplo, Norte/Sur rojo, Norte/Sur verde, Oeste/Este rojo, etc. La temporización de cada estado (5 s para rojo o amarillo, 60 s para verde) es impulsada por ciclos de reloj transcurridos.

Modelamos estos comportamientos definiendo un tipo enumerado que lista todos los estados posibles:
type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest);
Luego declaramos una señal de ese tipo para mantener el estado actual:
signal State : t_State;
Con la señal de estado en su lugar, la lógica FSM vive dentro de un solo proceso con reloj que usa una sentencia case. Cada rama when corresponde a un estado distinto y contiene las asignaciones de salida para ese estado. Un contador rastrea el tiempo transcurrido e impulsa la transición al siguiente estado cuando su valor alcanza un umbral predefinido.
Plantilla FSM de un proceso
process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
State <= ;
Counter<= 0;
else
case State is
when =>
if then
State <= ;
end if;
...
end case;
end if;
end if;
end process;
Nota: Puede implementar FSMs usando estilos de uno, dos o tres procesos. Ver Estilos FSM Explicados.
Ejercicio práctico
A continuación se muestra un ejemplo completo y sintetizable que implementa un controlador de semáforo. El diseño usa un reloj de 100 Hz para simplificar la simulación mientras demuestra temporización realista.
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
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;
Módulo Máquina de Estados
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; -- Reset activo bajo
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
-- Salidas por defecto
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;
Ejecutar la simulación durante cinco minutos produce una forma de onda que muestra la FSM ciclando a través de sus ocho estados, con fases verdes durando un minuto cada una.

Análisis
Conclusiones clave del código:
- Los tipos enumerados restringen la señal
Statea un conjunto conocido de valores válidos, mejorando seguridad y legibilidad. - Todas las salidas se conducen con un valor por defecto al inicio del proceso; las ramas de estado subsiguientes sobrescriben solo las señales que cambian.
- La variable
Counteres el motor de temporización, y sus valores umbral (5 s, 60 s) se derivan de la frecuencia de reloj.
La forma de onda resultante confirma que la FSM avanza correctamente: la señal State alterna a través de los ocho estados definidos, y cada fase verde persiste durante un minuto.
Conclusión
- Las máquinas de estados finitos son la forma estándar de implementar lógica secuencial en VHDL.
- Una sentencia
casedentro de un proceso con reloj mapea limpiamente cada estado a su comportamiento. - Los tipos enumerados dan seguridad en tiempo de compilación limitando el conjunto de valores de estado permisibles.
Proceda al siguiente tutorial para técnicas avanzadas de FSM.
VHDL
- Máquina de Estados Finitos: Aprovechando Realimentación para Construir Controladores de Secuencia Programables
- Cómo la máquina láser CNC OMNI crea regalos de Navidad personalizados
- Maximizando rendimiento de máquinas de estado Qt
- Creación de listas de cadenas en VHDL: Buenas prácticas y ejemplo
- Creación de un testbench dirigido por Tcl para un módulo VHDL de cerradura por código
- Finalizar elegantemente una simulación de testbench VHDL
- Implementación de un controlador PWM en VHDL: Diseño, simulación y demo en FPGA
- Generación de números aleatorios en VHDL: De uniforme a OSVVM
- Diseño de un búfer circular FIFO robusto en VHDL usando RAM de bloques
- Cómo construir un testbench de auto-comprobación en VHDL: Guía práctica
- Implementación de lista enlazada dinámica en VHDL con tipos protegidos y punteros de acceso