Machines à États (Mealy/Moore)
Conception et implémentation des machines à états finis (FSM) en VHDL : Moore et Mealy.
Machines à États Finis (FSM)
Une FSM (Finite State Machine) est un circuit séquentiel qui :
- Se trouve dans un état à la fois
- Passe d'un état à l'autre selon des transitions (dépendent des entrées)
- Produit des sorties selon l'état (et éventuellement les entrées)
Moore vs Mealy
| Moore | Mealy | |
|---|---|---|
| Sorties dépendent de | État uniquement | État + Entrées |
| Sorties | Plus stables | Réagit plus vite |
| Latence | 1 cycle supplémentaire | Réponse immédiate |
| Recommandé pour FPGA | Oui (plus simple à synthétiser) | Possible mais attention aux glitches |
Modèle 2 process (recommandé)
Exemple : détecteur de séquence 101 (Moore).
| État actuel | Entrée i_data | État suivant | Sortie o_found |
|---|---|---|---|
| IDLE | 0 | IDLE | 0 |
| IDLE | 1 | GOT_1 | 0 |
| GOT_1 | 1 | GOT_1 | 0 |
| GOT_1 | 0 | GOT_10 | 0 |
| GOT_10 | 1 | FOUND | 0 |
| GOT_10 | 0 | IDLE | 0 |
| FOUND | x | IDLE | 1 |
Le style le plus courant sur FPGA : un process pour l'état, un pour les sorties.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity fsm_detector is
port (
i_clk : in std_logic;
i_rst : in std_logic;
i_data : in std_logic;
o_found : out std_logic
);
end entity fsm_detector;
architecture rtl of fsm_detector is
-- Déclaration du type état
type t_state is (IDLE, GOT_1, GOT_10, FOUND);
signal r_state : t_state;
signal w_next : t_state;
begin
-- Process 1 : registre d'état (séquentiel)
p_state_reg : process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_state <= IDLE;
else
r_state <= w_next;
end if;
end if;
end process p_state_reg;
-- Process 2 : logique de transition (combinatoire)
p_next_state : process(r_state, i_data)
begin
w_next <= r_state; -- par défaut : rester dans l'état
case r_state is
when IDLE =>
if i_data = '1' then
w_next <= GOT_1;
end if;
when GOT_1 =>
if i_data = '0' then
w_next <= GOT_10;
else
w_next <= GOT_1;
end if;
when GOT_10 =>
if i_data = '1' then
w_next <= FOUND;
else
w_next <= IDLE;
end if;
when FOUND =>
w_next <= IDLE;
when others =>
w_next <= IDLE;
end case;
end process p_next_state;
-- Sorties Moore : dépendent uniquement de r_state
o_found <= '1' when r_state = FOUND else '0';
end architecture rtl;Modèle 3 process (variante)
Un troisième process pour les sorties (utile si les sorties sont complexes).
-- Process 3 : logique de sortie (combinatoire - Moore)
p_outputs : process(r_state)
begin
-- Valeurs par défaut (évite les latches)
o_found <= '0';
o_active <= '0';
case r_state is
when FOUND =>
o_found <= '1';
when GOT_1 | GOT_10 =>
o_active <= '1';
when others =>
null;
end case;
end process p_outputs;Exemple complet : FSM feux de circulation
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity traffic_light is
generic (
g_CLK_FREQ : integer := 100_000_000 -- 100 MHz
);
port (
i_clk : in std_logic;
i_rst : in std_logic;
o_rouge : out std_logic;
o_orange: out std_logic;
o_vert : out std_logic
);
end entity traffic_light;
architecture rtl of traffic_light is
type t_light is (ROUGE, ORANGE, VERT);
constant
| État | Durée | État suivant |
|---|---|---|
| ROUGE | 30 s | VERT |
| VERT | 25 s | ORANGE |
| ORANGE | 3 s | ROUGE |
Bonnes pratiques FSM
1. Toujours initialiser au reset
if i_rst = '1' then
r_state <= IDLE; -- état de départ défini
end if;2. Couvrir tous les états avec when others
when others =>
r_state <= IDLE; -- état sûr par défaut3. Valeurs de sortie par défaut
-- En début de process de sortie
o_valid <= '0';
o_data <= (others => '0');
-- Puis surcharger dans chaque case4. Un type énuméré par FSM
type t_uart_state is (IDLE, START, DATA, PARITY, STOP);
-- Chaque FSM a son propre type → nommage clairEncodage des états
Le synthétiseur choisit automatiquement l'encodage. Il est possible de le forcer :
| Encodage | Usage | Ressources |
|---|---|---|
| Binaire | Peu d'états | Minimum de bascules |
| One-hot | Beaucoup d'états | Plus de bascules, plus rapide |
| Gray | Compteurs séquentiels | Transitions d'un seul bit |
Sur FPGA moderne, laisser le synthétiseur décider est généralement optimal.
Catégories de FSM (Pedroni)
Il est utile de classer les machines à états en trois catégories selon leur complexité :
Catégorie 1 - FSM régulière (simple)
La machine passe d'un état à l'autre uniquement selon des signaux d'entrée externes. Pas de temporisation, pas de récursivité.
C'est la FSM classique : détecteur de séquence, contrôleur de protocole, décodeur de commandes.
-- Exemple : détecteur de flanc montant
type t_edge is (IDLE, DETECT);
signal r_state : t_edge;
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_state <= IDLE;
else
case r_state is
when IDLE => if i_sig = '1' then r_state <= DETECT; end if;
when DETECT => r_state <= IDLE;
when others => r_state <= IDLE;
end case;
end if;
end if;
end
Catégorie 2 - FSM temporisée (avec compteur)
La machine attend un nombre de cycles défini avant de changer d'état. Un compteur interne mesure le temps écoulé.
C'est le cas des feux de circulation, des générateurs PWM, des délais de démarrage.
-- FSM avec compteur interne
type t_timed is (WAIT_LOW, WAIT_HIGH);
signal r_state : t_timed;
signal r_timer : unsigned(19 downto 0) := (others => '0');
constant c_T_LOW : unsigned(19 downto 0) := to_unsigned(499_999, 20); -- 5 ms @ 100 MHz
constant c_T_HIGH : unsigned(19 downto 0) := to_unsigned(999_999, 20); -- 10 ms @ 100 MHz
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_state
Bonne pratique : remettre le compteur à zéro (
r_timer <= (others => '0')) dès qu'on change d'état pour garantir un timing précis.
Catégorie 3 - FSM récursive (avec paramètre variable)
La machine passe par des états un nombre variable de fois selon un paramètre d'entrée (boucle sur N cycles, traitement de N octets, etc.).
C'est le cas des sérialiseurs, des contrôleurs SPI/UART, des moteurs de compression.
-- Sérialiseur 8 bits : envoie 8 bits un par un
type t_ser is (IDLE, SHIFT);
signal r_state : t_ser;
signal r_shreg : std_logic_vector(7 downto 0);
signal r_count : unsigned(2 downto 0);
process(i_clk)
begin
if rising_edge(i_clk) then
if i_rst = '1' then
r_state <= IDLE;
r_count <= (others => '0');
o_bit <= '0';
o_done <= '0';
else
o_done <= '0';
case r_state is
Tableau de synthèse
| Catégorie | Déclencheur de transition | Exemples |
|---|---|---|
| Régulière | Entrées externes | Détecteur de séquence, décodeur |
| Temporisée | Compteur interne (N cycles fixes) | Feux, PWM, délai de démarrage |
| Récursive | Compteur interne (N variable) | UART TX, SPI, sérialiseur |
Machines à états sûres (safe state machines)
Un FPGA peut se retrouver dans un état non défini au démarrage ou suite à un glitch. Une FSM sûre gère explicitement tous les cas imprévus.
-- Toujours inclure when others
case r_state is
when IDLE => ...
when RUN => ...
when DONE => ...
when others =>
-- État inconnu : retour à l'état sûr
r_state <= IDLE;
end case;-- Forcer l'encodage one-hot pour réduire les états illégaux (Vivado)
attribute fsm_encoding : string;
attribute fsm_encoding of r_state : signal is "one_hot";Sur FPGA, les bascules ne se réinitialisent pas automatiquement à la mise sous tension. Toujours initialiser au reset et toujours couvrir
when others.
📝 Tester mes connaissances - Quiz du chapitre