Endlicher Automat in VHDL entwerfen: Praktisches Ampel-Beispiel
Ein endlicher Automat (FSM) ist ein deterministisches Logikmodell, dessen Ausgabe nicht nur vom aktuellen Eingang, sondern auch von der Folge vergangener Ein- und Ausgänge abhängt. In FPGA-Design und zeitabhängigen VHDL-Algorithmen ist der FSM die Standardabstraktion für zustandsbehaftetes Verhalten.
VHDL-FSMs werden typischerweise als getaktete Prozesse mit einem state-Signal realisiert, das die letzte Konfiguration speichert. Das State-Signal wirkt als internes Register, um auf Ereignisse zu reagieren, die sich über mehrere Taktzyklen erstrecken.
Basic VHDL Tutorials – Teil 3
Ampel als FSM
Vierwege-Kreuzung mit Ampeln: Endliche sichtbare Zustände (Nord/Süd rot, Nord/Süd grün, West/Ost rot …). Timing je Zustand (5 s rot/gelb, 60 s grün) über abgelaufene Taktzyklen.
Enumerierter Typ für alle Zustände:
type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest);
State-Signal:
signal State : t_State;
FSM-Logik in einem getakteten Prozess mit case-Statement. Jeder when-Zweig entspricht einem Zustand und setzt die Ausgänge. Ein Zähler verfolgt die verstrichene Zeit und triggert den Übergang beim Erreichen des Schwellenwerts.
One-Process FSM Template
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;
Hinweis: FSMs lassen sich auch im Two- oder Three-Process-Stil implementieren. Siehe FSM Styles Explained.
Praxisbeispiel
Vollständiges, synthetisierbares Beispiel: Ampel-Controller mit 100 Hz-Takt für schnelle Simulation bei realistischem Timing.
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;
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;
State-Machine Modul
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;
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;
Simulation über 5 Minuten: Wellenform zeigt Zyklus durch alle acht Zustände, Grünphasen je 1 Minute.
Analyse
- Enumerierte Typen beschränken
Stateauf bekannte Werte – Compile-Time-Sicherheit, bessere Lesbarkeit. - Alle Ausgänge erhalten Default-Werte zu Prozessbeginn; Zustandszweige überschreiben nur geänderte Signale.
Counterist Timing-Maschine; Schwellenwerte (5 s, 60 s) aus Taktfrequenz abgeleitet.
Wellenform bestätigt: State durchläuft alle acht Zustände, jede Grünphase hält 1 Minute.
Merksätze
- Endliche Automaten sind Standard für sequenzielle Logik in VHDL.
casein getaktetem Prozess ordnet jedem Zustand sein Verhalten sauber zu.- Enumerierte Typen geben Compile-Time-Sicherheit durch begrenzte Wertevorrat.
Nächstes Tutorial: Fortgeschrittene FSM-Techniken.
VHDL
- Endlicher Zustandsautomat: Rückführung nutzen für programmierbare Sequenzsteuerung
- Performance von Qt State Machines maximieren
- String-Listen in VHDL erstellen: Best Practices & Beispiel
- Tcl-gesteuerter Testbench für ein VHDL Code-Lock-Modul erstellen
- VHDL-Testbench-Simulation sauber beenden
- PWM-Controller in VHDL implementieren: Design, Simulation & FPGA-Demo
- Zufallszahlen in VHDL generieren: Von Uniform zu OSVVM
- Selbstprüfenden VHDL-Testbench erstellen – Praxisleitfaden
- Dynamische verkettete Liste in VHDL mit Protected Types und Access-Pointern
- Wie die OMNI CNC-Lasermaschine persönliche Weihnachtsgeschenke fertigt