Leçon 12 sur 22

Chapitre 12 — Machines à états finis

Objectif — Finalité du chapitre

Modéliser des systèmes séquentiels complexes par des machines de Moore ou de Mealy, appliquer une méthode de conception rigoureuse, choisir un style VHDL et valider plusieurs contrôleurs par simulation.

Objectifs pédagogiques

À la fin de ce chapitre, l’étudiant devra être capable de :

  • définir les états, transitions, entrées, sorties et état initial d’une machine ;
  • distinguer une machine de Moore d’une machine de Mealy ;
  • construire un diagramme d’états et une table de transition ;
  • décomposer une machine en registre d’état, logique de transition et logique de sortie ;
  • écrire des machines à un, deux ou trois processus ;
  • choisir un codage binaire, one-hot ou Gray ;
  • éviter les latches et transitions non définies ;
  • synchroniser les entrées externes avant leur utilisation ;
  • simuler les transitions, sorties et situations invalides ;
  • concevoir un détecteur de séquence, un feu de circulation, une porte automatique et un distributeur.

Prérequis

  • processus combinatoires et cadencés ;
  • bascules, registres, compteurs et ticks ;
  • instructions if et case ;
  • types énumérés et signaux ;
  • bancs de test et assertions.

Organisation du chapitre

Section

Contenu

Compétence principale

12.1Définition d’une machine à étatsIdentifier les éléments d’un automate
12.2Machine de MooreProduire les sorties à partir de l’état
12.3Machine de MealyCombiner état et entrées dans les sorties
12.4Méthode de conceptionPasser du cahier des charges au VHDL
12.5Styles de descriptionOrganiser les processus
12.6Codage des étatsChoisir une représentation matérielle
TP 9Conception de machinesMettre en œuvre quatre contrôleurs

 

Concept clé — Structure générale

Une machine à états finis associe un registre d’état à une logique combinatoire. Le registre mémorise l’état courant ; la logique calcule l’état suivant et les sorties.

 

12.1 Définition d’une machine à états

Une machine à états finis, ou FSM (Finite State Machine), est un modèle de commande dont le comportement dépend d’un nombre fini de situations mémorisées appelées états. Elle évolue d’un état à un autre au rythme d’une horloge.

12.1.1 État

Un état résume l’histoire utile du système. Il représente une situation dans laquelle les mêmes règles de transition et de sortie s’appliquent.

Exemple de système

États possibles

Feu de circulationVERT, ORANGE, ROUGE
Porte automatiqueFERMEE, OUVERTURE, OUVERTE, FERMETURE
DistributeurCREDIT_0, CREDIT_1, CREDIT_2, DISTRIBUTION
Récepteur sérieATTENTE, START, DONNEES, STOP

 

12.1.2 Transition

Une transition est un passage d’un état courant vers un état suivant. Elle est déclenchée par une condition sur les entrées, un temporisateur ou un événement interne.

Transition conceptuelle  |  Diagramme textuel
ETAT_A -- condition --> ETAT_B

 

12.1.3 Entrée

Une entrée est une information observée par la machine : bouton, capteur, bit série, tick de temporisation, crédit inséré ou résultat d’un comparateur.

12.1.4 Sortie

Une sortie commande le système : moteur, feu, signal de validation, impulsion de distribution, alarme ou autorisation.

12.1.5 État initial

L’état initial est l’état imposé au démarrage ou par le reset. Il doit placer le système dans une situation sûre et déterministe.

Registre d’état avec reset  |  VHDL
process(clk, reset)
begin
    if reset = '1' then
        etat_courant <= ATTENTE;
    elsif rising_edge(clk) then
        etat_courant <= etat_suivant;
    end if;
end process;

 

12.1.6 Modèle matériel

Bloc

Rôle

Registre d’étatMémorise l’état courant au front d’horloge.
Logique de transitionCalcule l’état suivant à partir de l’état courant et des entrées.
Logique de sortieCalcule les sorties selon le modèle Moore ou Mealy.
ResetForce l’état initial.

 

12.1.7 Représentation par diagramme

Un diagramme d’états utilise des cercles ou rectangles pour les états et des flèches pour les transitions. Les conditions sont écrites sur les flèches. Pour une machine de Moore, les sorties peuvent être indiquées à l’intérieur de l’état.

Exemple simplifié  |  Diagramme textuel
[ATTENTE / pret=1]
      |
      | start=1
      v
[TRAITEMENT / pret=0]
      |
      | fini=1
      v
[ATTENTE / pret=1]

 

12.1.8 Table de transition

État courant

Entrées

État suivant

Sorties

ATTENTEstart=0ATTENTEpret=1
ATTENTEstart=1TRAITEMENTpret=1
TRAITEMENTfini=0TRAITEMENTpret=0
TRAITEMENTfini=1ATTENTEpret=0

 

12.1.9 Finie ne signifie pas petite

Le nombre d’états est fini, mais peut être important. Une bonne méthode cherche à limiter les états aux situations réellement distinctes et à factoriser les comportements identiques.

12.1.10 Machine déterministe

Pour chaque combinaison état courant/entrées, l’état suivant doit être défini sans ambiguïté. Une machine déterministe ne possède qu’une transition applicable à la fois.

Bonne pratique — Complétude

Dans une description combinatoire de FSM, définir une valeur par défaut pour l’état suivant et pour toutes les sorties afin d’éviter les latches et les situations non couvertes.

 

12.2 Machine de Moore

Dans une machine de Moore, les sorties dépendent uniquement de l’état courant. Elles ne changent normalement qu’après la mise à jour du registre d’état.

12.2.1 Principe

Relation de Moore  |  Modèle
etat_suivant = F(etat_courant, entrees)
sorties       = G(etat_courant)

 

12.2.2 Conséquences

  • sorties stables entre deux changements d’état ;
  • faible sensibilité aux variations instantanées des entrées ;
  • latence possible d’un cycle pour certaines réactions ;
  • diagrammes souvent simples à relire.

12.2.3 Exemple : commande start/done

Diagramme de Moore  |  Diagramme textuel
[ATTENTE / busy=0, done=0]
   | start=1
   v
[ACTIF / busy=1, done=0]
   | fini=1
   v
[FIN / busy=0, done=1]
   | acquit=1
   v
[ATTENTE / busy=0, done=0]

 

12.2.4 Table de transition

État

Condition

État suivant

busy

done

ATTENTEstart=0ATTENTE00
ATTENTEstart=1ACTIF00
ACTIFfini=0ACTIF10
ACTIFfini=1FIN10
FINacquit=0FIN01
FINacquit=1ATTENTE01

 

12.2.5 Déclaration des états

Type énuméré  |   VHDL
type etat_t is (ATTENTE, ACTIF, FIN);
signal etat_courant : etat_t;
signal etat_suivant : etat_t;

 

12.2.6 Registre d’état

Mémorisation synchrone  |  VHDL
registre_etat : process(clk, reset)
begin
    if reset = '1' then
        etat_courant <= ATTENTE;
    elsif rising_edge(clk) then
        etat_courant <= etat_suivant;
    end if;
end process;

 

12.2.7 Logique de transition

Transition Moore — Partie 1  |  VHDL
logique_transition : process(all)
begin
    etat_suivant <= etat_courant;

    case etat_courant is
        when ATTENTE =>
            if start = '1' then
                etat_suivant <= ACTIF;
            end if;
Transition Moore — Partie 2  |  VHDL
        when ACTIF =>
            if fini = '1' then
                etat_suivant <= FIN;
            end if;

        when FIN =>
            if acquit = '1' then
                etat_suivant <= ATTENTE;
            end if;
    end case;
end process;

 

12.2.8 Logique de sortie

Sorties de Moore  |  VHDL
logique_sortie : process(all)
begin
    busy <= '0';
    done <= '0';

    case etat_courant is
        when ATTENTE =>
            null;

        when ACTIF =>
            busy <= '1';

        when FIN =>
            done <= '1';
    end case;
end process;

 

12.2.9 Sorties concurrentes

Alternative compacte  |  VHDL
busy <= '1' when etat_courant = ACTIF else '0';
done <= '1' when etat_courant = FIN    else '0';

 

12.2.10 Chronologie

Instant

start

État courant

busy

Avant front1ATTENTE0
Après front1ACTIF1
Entre fronts0 ou 1ACTIF1

 

Caractéristique — Sortie Moore

La sortie réagit au changement d’état enregistré. Une condition d’entrée ne modifie pas directement la sortie tant que le registre n’a pas changé.

 

12.3 Machine de Mealy

Dans une machine de Mealy, les sorties dépendent de l’état courant et des entrées. Une sortie peut donc changer immédiatement après une variation d’entrée, sans attendre le front suivant.

12.3.1 Principe

Relation de Mealy  |  Modèle
etat_suivant = F(etat_courant, entrees)
sorties       = G(etat_courant, entrees)

 

12.3.2 Exemple de sortie immédiate

Validation en Mealy  |  VHDL
valide <= '1'
    when etat_courant = ATTENTE and start = '1'
    else '0';

 

12.3.3 Diagramme de Mealy

Les sorties associées à une transition sont écrites sur la flèche sous la forme condition/sortie.

Exemple  |   Diagramme textuel
[ATTENTE] -- start=1 / valide=1 --> [ACTIF]
[ACTIF]  -- fini=1  / done=1    --> [ATTENTE]

 

12.3.4 Différences Moore/Mealy

Critère

Moore

Mealy

Dépendance des sortiesÉtat courantÉtat courant + entrées
RéactionAprès transition d’étatPotentiellement immédiate
Nombre d’étatsParfois plus élevéSouvent plus faible
Stabilité des sortiesTrès bonneDépend de la stabilité des entrées
Lecture du diagrammeSorties dans les étatsSorties sur les transitions

 

12.3.5 Avantages de Mealy

  • réponse rapide ;
  • réduction possible du nombre d’états ;
  • impulsions de sortie naturelles sur une transition ;
  • description compacte de certains protocoles.

12.3.6 Inconvénients de Mealy

  • sorties sensibles aux glitches des entrées ;
  • chemins combinatoires directs entrée-sortie ;
  • chronogrammes plus délicats ;
  • nécessité de synchroniser et filtrer les entrées externes.

12.3.7 Exemple VHDL Mealy

Sorties et transitions combinées  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;
    impulsion <= '0';

    case etat_courant is
        when ATTENTE =>
            if entree = '1' then
                etat_suivant <= ACTIF;
                impulsion <= '1';
            end if;

        when ACTIF =>
            if entree = '0' then
                etat_suivant <= ATTENTE;
            end if;
    end case;
end process;

 

12.3.8 Enregistrement d’une sortie Mealy

Une sortie Mealy critique peut être enregistrée pour supprimer les glitches, au prix d’une latence supplémentaire.

Sortie enregistrée  |  VHDL
process(clk, reset)
begin
    if reset = '1' then
        sortie_reg <= '0';
    elsif rising_edge(clk) then
        sortie_reg <= sortie_mealy;
    end if;
end process;

 

12.3.9 Choisir Moore ou Mealy

Besoin

Choix souvent adapté

Sorties stables commandant un actionneurMoore
Impulsion immédiate sur une combinaisonMealy
Entrées asynchrones ou bruitéesMoore après synchronisation
Réduction du nombre d’étatsMealy
Lisibilité pédagogiqueMoore

 

Attention — Entrées synchrones

Même une machine de Moore peut mal fonctionner si ses entrées violent les temps de setup/hold. Toute entrée provenant de l’extérieur du domaine d’horloge doit être synchronisée.

 

12.4 Méthode de conception

Une FSM fiable résulte d’une démarche structurée. Le code VHDL ne doit être écrit qu’après clarification du comportement et des transitions.

12.4.1 Analyse du cahier des charges

  • identifier les entrées, sorties et horloge ;
  • préciser les niveaux actifs ;
  • définir les temporisations en cycles ou ticks ;
  • déterminer le comportement au reset ;
  • traiter les erreurs et cas simultanés ;
  • définir les priorités.

12.4.2 Identification des états

Créer un état lorsque le système doit mémoriser une situation différente. Deux situations peuvent partager le même état si elles produisent les mêmes sorties et les mêmes règles de transition.

12.4.3 Construction du diagramme

1. Placer l’état initial.

2. Ajouter les états fonctionnels.

3. Tracer toutes les transitions possibles.

4. Annoter les conditions.

5. Ajouter les sorties Moore ou Mealy.

6. Vérifier qu’aucun état n’est isolé.

12.4.4 Définition des transitions

Chaque état doit définir le comportement pour toutes les combinaisons d’entrées significatives. Une transition implicite de maintien peut être représentée par etat_suivant <= etat_courant.

12.4.5 Codage des états

Le type énuméré est recommandé dans le code RTL. Le choix physique du codage peut être laissé au synthétiseur ou guidé par des attributs.

Type énuméré  |   VHDL
type etat_t is (
    ATTENTE,
    INITIALISATION,
    TRAITEMENT,
    ERREUR,
    FIN
);

 

12.4.6 Description du registre d’état

Processus séquentiel  |  VHDL
process(clk, reset)
begin
    if reset = '1' then
        etat_courant <= ATTENTE;
    elsif rising_edge(clk) then
        etat_courant <= etat_suivant;
    end if;
end process;

 

12.4.7 Logique de l’état suivant

Patron combinatoire  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;

    case etat_courant is
        when ATTENTE =>
            -- transitions

        when INITIALISATION =>
            -- transitions

        when TRAITEMENT =>
            -- transitions

        when ERREUR =>
            -- transitions

        when FIN =>
            -- transitions
    end case;
end process;

 

12.4.8 Logique de sortie

Valeurs par défaut  |  VHDL
process(all)
begin
    sortie_a <= '0';
    sortie_b <= '0';
    alarme   <= '0';

    case etat_courant is
        when ATTENTE =>
            sortie_a <= '1';

        when ERREUR =>
            alarme <= '1';

        when others =>
            null;
    end case;
end process;

 

12.4.9 Simulation

  • appliquer le reset ;
  • tester chaque transition ;
  • tester les boucles de maintien ;
  • tester les entrées simultanées ;
  • vérifier les sorties dans chaque état ;
  • tester les états invalides si un codage explicite est utilisé ;
  • utiliser des assertions.

12.4.10 Assertions d’état

Vérification fonctionnelle  |  VHDL
assert not (ouvrir = '1' and fermer = '1')
    report "Commandes ouvrir et fermer simultanees"
    severity error;

 

12.4.11 Temporisations

Une durée est généralement convertie en nombre de ticks. Un compteur interne déclenche ensuite une transition.

Transition après temporisation  |  VHDL
if tick = '1' then
    if temporisateur = DUREE-1 then
        temporisateur <= 0;
        etat_suivant <= ETAT_SUIVANT;
    else
        temporisateur <= temporisateur + 1;
    end if;
end if;

 

12.4.12 Séparation commande/données

La FSM doit piloter des signaux de contrôle tandis que les registres de données et opérateurs effectuent les calculs. Cette séparation facilite la réutilisation et le test.

12.4.13 Gestion d’un état illégal

Récupération sûre  |   VHDL
when others =>
    etat_suivant <= ATTENTE;

 

Avec un type énuméré, tous les états déclarés doivent être traités. Le synthétiseur peut cependant produire des codes physiques inutilisés ; les options de récupération dépendent de l’outil.

12.4.14 Checklist de conception

  • État initial sûr et explicite.
  • Toutes les transitions sont couvertes.
  • Sorties définies dans tous les chemins.
  • Aucune entrée asynchrone utilisée directement.
  • Temporisations exprimées en ticks synchrones.
  • Priorités documentées.
  • Banc de test couvrant les scénarios normaux et défauts.

12.5 Styles de description

Une même machine peut être décrite avec un, deux ou trois processus. Le choix influence l’organisation du code, pas nécessairement le matériel final.

12.5.1 Machine à un processus

Le registre d’état, les transitions et les sorties enregistrées sont regroupés dans un processus cadencé.

Patron à un processus — Partie 1  |  VHDL
process(clk, reset)
begin
    if reset = '1' then
        etat_courant <= ATTENTE;
        sortie <= '0';
    elsif rising_edge(clk) then
        case etat_courant is
            when ATTENTE =>
                sortie <= '0';
                if start = '1' then
                    etat_courant <= ACTIF;
                end if;

 

Patron à un processus — Partie 2  |  VHDL
            when ACTIF =>
                sortie <= '1';
                if fini = '1' then
                    etat_courant <= ATTENTE;
                end if;
        end case;
    end if;
end process;

 

  • sorties naturellement enregistrées ;
  • code compact ;
  • état suivant moins visible ;
  • attention aux sorties conservées si elles ne sont pas affectées dans une branche.

12.5.2 Machine à deux processus

Un processus mémorise l’état ; un processus combinatoire calcule l’état suivant et les sorties.

Processus 1 : registre  |  VHDL
process(clk, reset)
begin
    if reset = '1' then
        etat_courant <= ATTENTE;
    elsif rising_edge(clk) then
        etat_courant <= etat_suivant;
    end if;
end process;

 

Processus 2 : transition et sorties  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;
    sortie <= '0';

    case etat_courant is
        when ATTENTE =>
            if start = '1' then
                etat_suivant <= ACTIF;
            end if;

        when ACTIF =>
            sortie <= '1';
            if fini = '1' then
                etat_suivant <= ATTENTE;
            end if;
    end case;
end process;

 

12.5.3 Machine à trois processus

Le registre, la logique de transition et la logique de sortie sont séparés.

Processus de transition  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;

    case etat_courant is
        when ATTENTE =>
            if start = '1' then
                etat_suivant <= ACTIF;
            end if;

        when ACTIF =>
            if fini = '1' then
                etat_suivant <= ATTENTE;
            end if;
    end case;
end process;

 

Processus de sortie  |  VHDL
process(all)
begin
    sortie <= '0';

    case etat_courant is
        when ACTIF =>
            sortie <= '1';
        when others =>
            null;
    end case;
end process;

 

12.5.4 Comparaison

Critère

Un processus

Deux processus

Trois processus

CompacitéTrès forteBonneMoyenne
Lisibilité état suivantFaibleBonneTrès bonne
Séparation sortiesFaibleMoyenneForte
Sorties enregistréesNaturellesÀ ajouter si nécessaireÀ ajouter si nécessaire
Risque de latch combinatoireFaibleÀ contrôlerÀ contrôler
Usage pédagogiqueMoyenTrès bonTrès bon

 

12.5.5 Choix pratique

  • deux processus : compromis fréquent pour les FSM RTL ;
  • trois processus : séparation claire des sorties Moore ;
  • un processus : contrôleurs compacts avec sorties enregistrées ;
  • respecter les conventions de l’équipe et de l’outil.

12.5.6 Sensibilité

Les processus combinatoires utilisent process(all) en VHDL-2008. Le registre d’état utilise clk et les resets asynchrones uniquement.

12.5.7 Valeurs par défaut

Prévention des latches  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;
    sortie_1 <= '0';
    sortie_2 <= '0';

    -- case / if
end process;

 

12.5.8 Sorties enregistrées

Une sortie peut être générée combinatoirement puis enregistrée dans un processus séparé. Cette option stabilise les interfaces mais ajoute un cycle de latence.

12.6 Codage des états

Le codage associe une valeur binaire à chaque état. Avec un type énuméré, le synthétiseur choisit souvent automatiquement la représentation.

12.6.1 Codage binaire

Le codage binaire utilise le nombre minimal de bascules : ceil(log2(nombre d’états)).

Nombre d’états

Bits minimaux

21
3 à 42
5 à 83
9 à 164

 

12.6.2 Exemple binaire

Codage explicite  |  VHDL
constant ATTENTE : std_logic_vector(1 downto 0) := "00";
constant ACTIF   : std_logic_vector(1 downto 0) := "01";
constant FIN     : std_logic_vector(1 downto 0) := "10";

 

  • peu de bascules ;
  • logique de décodage parfois plus complexe ;
  • codes inutilisés possibles.

12.6.3 Codage one-hot

Chaque état possède une bascule dédiée. Un seul bit vaut 1 à la fois.

Exemple one-hot  |  Codage
ATTENTE = "001"
ACTIF   = "010"
FIN     = "100"

 

  • plus de bascules ;
  • décodage simple ;
  • souvent performant dans les FPGA riches en registres ;
  • détection possible des codes zéro-hot ou multi-hot.

12.6.4 Codage Gray

Deux états successifs sont choisis de façon à ne différer que par un bit, lorsque le graphe de transitions le permet.

Exemple Gray  |   Codage
E0 = "00"
E1 = "01"
E2 = "11"
E3 = "10"

 

  • réduit les commutations simultanées ;
  • utile dans certains compteurs et traversées de domaines ;
  • ne garantit pas un bit de différence pour un graphe arbitraire.

12.6.5 Attribut de codage

Certains outils acceptent un attribut enum_encoding. Sa prise en charge et sa syntaxe peuvent dépendre du synthétiseur.

Exemple indicatif  |  VHDL
type etat_t is (ATTENTE, ACTIF, FIN);
attribute enum_encoding : string;
attribute enum_encoding of etat_t : type is "001 010 100";

 

Attention — Portabilité

Les attributs de synthèse sont souvent spécifiques aux outils. Le comportement fonctionnel ne doit pas dépendre d’un codage particulier sauf nécessité démontrée.

 

12.6.6 Comparaison

Critère

Binaire

One-hot

Gray

BasculesMinimumUne par étatMinimum ou proche
DécodageModéréSimpleModéré
CommutationsPlusieurs bits possiblesDeux bits typiquementUn bit sur transitions prévues
FPGABon généralisteSouvent rapideCas ciblés
Lisibilité physiqueMoyenneBonneMoyenne

 

12.6.7 Choix du codage

  • laisser le synthétiseur choisir pour commencer ;
  • mesurer fréquence, surface et consommation ;
  • utiliser one-hot si le chemin critique bénéficie d’un décodage simple ;
  • utiliser Gray pour une séquence appropriée ;
  • documenter tout codage imposé.

12.6.8 États sûrs

Des options de synthèse peuvent ajouter une récupération depuis les codes illégaux. Elles augmentent parfois la logique et doivent être validées par simulation post-synthèse ou analyse appropriée.

Méthode synthétique de développement

1. Reformuler le cahier des charges sous forme de scénarios.

2. Lister les entrées, sorties et temporisations.

3. Identifier les états nécessaires.

4. Dessiner le diagramme.

5. Construire la table de transition.

6. Choisir Moore ou Mealy.

7. Choisir le style de processus.

8. Écrire le registre d’état.

9. Écrire les transitions et sorties avec valeurs par défaut.

10. Créer un banc de test couvrant tous les arcs.

11. Examiner le schéma RTL et les rapports de synthèse.

Erreurs fréquentes

Erreur

Conséquence

Correction

État suivant non initialiséLatch combinatoireMaintien par défaut
Sortie non affectéeLatch ou valeur conservéeValeurs par défaut
Entrée asynchrone directeMétastabilitéSynchroniseur
Transition manquanteBlocage ou comportement impliciteTable complète
Sortie Mealy bruitéeGlitchesFiltrage ou enregistrement
Compteur non remis à zéro lors d’un changement d’étatDurée incorrecteRéinitialiser selon état
Reset vers un état dangereuxActionneur activé au démarrageÉtat initial sûr

 

Travaux pratiques

TP 9 — Conception de machines à états

1. Objectifs du TP

  • concevoir un détecteur de séquence binaire ;
  • concevoir un feu de circulation temporisé ;
  • concevoir le contrôleur d’une porte automatique ;
  • concevoir un distributeur acceptant des pièces de £1 et £2 ;
  • comparer Moore et Mealy ;
  • utiliser des assertions et chronogrammes.

2. Organisation proposée

Arborescence  |   Arborescence
tp9_machines_etats/
├── src/
│   ├── detecteur_1011_moore.vhd
│   ├── detecteur_1011_mealy.vhd
│   ├── feu_tricolore.vhd
│   ├── controleur_porte.vhd
│   └── distributeur.vhd
└── sim/
    ├── tb_detecteur_1011.vhd
    ├── tb_feu_tricolore.vhd
    ├── tb_controleur_porte.vhd
    └── tb_distributeur.vhd

 

3. Partie A — Détecteur de séquence 1011

Le détecteur reçoit un bit par cycle et active detection lorsqu’il reconnaît 1011. Les occurrences peuvent se chevaucher.

États Moore  |   Définition
S0 : aucun préfixe reconnu
S1 : préfixe "1"
S2 : préfixe "10"
S3 : préfixe "101"
S4 : séquence "1011" reconnue

 

Diagramme textuel Moore  |  Transitions
S0 --1--> S1 ; S0 --0--> S0
S1 --0--> S2 ; S1 --1--> S1
S2 --1--> S3 ; S2 --0--> S0
S3 --1--> S4 ; S3 --0--> S2
S4 --1--> S1 ; S4 --0--> S2
Sortie detection=1 uniquement en S4

 

detecteur_1011_moore.vhd — Entité  |  VHDL
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity detecteur_1011_moore is
    port (
        clk       : in   std_logic;
        reset     : in   std_logic;
        bit_entree: in  std_logic;
        detection : out std_logic
    );
end entity detecteur_1011_moore;

 

Moore — Registre et types  |  VHDL
architecture rtl of detecteur_1011_moore is
    type etat_t is (S0, S1, S2, S3, S4);
    signal etat_courant, etat_suivant : etat_t;
begin
    process(clk, reset)
    begin
        if reset = '1' then
            etat_courant <= S0;
        elsif rising_edge(clk) then
            etat_courant <= etat_suivant;
        end if;
    end process;

 

Moore — Transitions, partie 1  |  VHDL
    process(all)
    begin
        etat_suivant <= etat_courant;

        case etat_courant is
            when S0 =>
                if bit_entree = '1' then
                    etat_suivant <= S1;
                end if;

            when S1 =>
                if bit_entree = '0' then
                    etat_suivant <= S2;
                else
                    etat_suivant <= S1;
                end if;

 

Moore — Transitions, partie 2A  |  VHDL
            when S2 =>
                if bit_entree = '1' then
                    etat_suivant <= S3;
                else
                    etat_suivant <= S0;
                end if;

            when S3 =>
                if bit_entree = '1' then
                    etat_suivant <= S4;
                else
                    etat_suivant <= S2;
                end if;
Moore — Transitions, partie 2B  |  VHDL
            when S4 =>
                if bit_entree = '1' then
                    etat_suivant <= S1;
                else
                    etat_suivant <= S2;
                end if;
        end case;
    end process;

    detection <= '1' when etat_courant = S4 else '0';
end architecture rtl;

 

4. Version Mealy du détecteur

La version Mealy peut utiliser seulement quatre états. La sortie est activée sur la transition depuis S3 lorsque bit_entree vaut 1.

Mealy — Sortie sur transition  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;
    detection <= '0';

    case etat_courant is
        when S0 =>
            if bit_entree = '1' then
                etat_suivant <= S1;
            end if;

        when S1 =>
            if bit_entree = '0' then
                etat_suivant <= S2;
            end if;

        when S2 =>
            if bit_entree = '1' then
                etat_suivant <= S3;
            else
                etat_suivant <= S0;
            end if;

        when S3 =>
            if bit_entree = '1' then
                detection <= '1';
                etat_suivant <= S1;
            else
                etat_suivant <= S2;
            end if;
    end case;
end process;

 

5. Banc de test du détecteur

Séquence de test  |   VHDL
constant MOT : std_logic_vector(15 downto 0)
    := "0010110101101011";

for i in MOT'range loop
    bit_entree <= MOT(i);
    wait until rising_edge(clk);
    wait for 1 ns;

    -- Observer et compter les impulsions detection.
end loop;

 

Assertion d’impulsion  |  VHDL
if detection = '1' then
    nb_detections := nb_detections + 1;
end if;

assert nb_detections = 3
    report "Nombre de sequences detectees incorrect"
    severity error;

 

6. Partie B — Feu de circulation

Le feu suit VERT pendant 5 ticks, ORANGE pendant 2 ticks et ROUGE pendant 5 ticks. Les sorties sont de Moore.

Diagramme  |   Diagramme textuel
VERT --5 ticks--> ORANGE
ORANGE --2 ticks--> ROUGE
ROUGE --5 ticks--> VERT

 

feu_tricolore.vhd — Entité  |  VHDL
entity feu_tricolore is
    generic (
        DUREE_VERT   : positive := 5;
        DUREE_ORANGE : positive := 2;
        DUREE_ROUGE  : positive := 5
    );
    port (
        clk, reset, tick : in std_logic;
        feu_vert, feu_orange, feu_rouge : out std_logic
    );
end entity feu_tricolore;

 

Feu — Registre et temporisateur  |  VHDL
architecture rtl of feu_tricolore is
    type etat_t is (VERT, ORANGE, ROUGE);
    signal etat_courant, etat_suivant : etat_t;
    signal temps : natural range 0 to
        DUREE_VERT + DUREE_ORANGE + DUREE_ROUGE;
begin
    process(clk, reset)
    begin
        if reset = '1' then
            etat_courant <= ROUGE;
            temps <= 0;
        elsif rising_edge(clk) then
            etat_courant <= etat_suivant;

            if etat_suivant /= etat_courant then
                temps <= 0;
            elsif tick = '1' then
                temps <= temps + 1;
            end if;
        end if;
    end process;

 

Feu — Transitions  |  VHDL
    process(all)
    begin
        etat_suivant <= etat_courant;

        case etat_courant is
            when VERT =>
                if tick = '1' and temps = DUREE_VERT-1 then
                    etat_suivant <= ORANGE;
                end if;

            when ORANGE =>
                if tick = '1' and temps = DUREE_ORANGE-1 then
                    etat_suivant <= ROUGE;
                end if;

            when ROUGE =>
                if tick = '1' and temps = DUREE_ROUGE-1 then
                    etat_suivant <= VERT;
                end if;
        end case;
    end process;

 

Feu — Sorties  |   VHDL
    feu_vert   <= '1' when etat_courant = VERT   else '0';
    feu_orange <= '1' when etat_courant = ORANGE else '0';
    feu_rouge  <= '1' when etat_courant = ROUGE  else '0';
end architecture rtl;

 

Amélioration — Dimension du temporisateur

Dans un code générique complet, la plage du temporisateur doit être dimensionnée à partir de la plus grande durée. On peut utiliser une constante MAX_DUREE calculée par une fonction.

 

7. Partie C — Contrôleur d’une porte automatique

La porte s’ouvre lorsqu’une présence est détectée, reste ouverte tant que la zone est occupée, puis se ferme. Un obstacle pendant la fermeture provoque une réouverture.

États de la porte  |  États
FERMEE
OUVERTURE
OUVERTE
FERMETURE
DEFAUT

 

Table de transitions  |  Règles
FERMEE + presence         -> OUVERTURE
OUVERTURE + fin_ouverture -> OUVERTE
OUVERTE + absence         -> FERMETURE
FERMETURE + obstacle      -> OUVERTURE
FERMETURE + fin_fermeture -> FERMEE
Tout état + arret_urgence -> DEFAUT
DEFAUT + reset            -> FERMEE

 

controleur_porte.vhd — Sorties Moore  |  VHDL
process(all)
begin
    moteur_ouvrir  <= '0';
    moteur_fermer  <= '0';
    alarme         <= '0';

    case etat_courant is
        when OUVERTURE =>
            moteur_ouvrir <= '1';

        when FERMETURE =>
            moteur_fermer <= '1';

        when DEFAUT =>
            alarme <= '1';

        when others =>
            null;
    end case;
end process;

 

Porte — Logique de transition, partie 1  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;

    if arret_urgence = '1' then
        etat_suivant <= DEFAUT;
    else
        case etat_courant is
            when FERMEE =>
                if presence = '1' then
                    etat_suivant <= OUVERTURE;
                end if;

            when OUVERTURE =>
                if fin_ouverture = '1' then
                    etat_suivant <= OUVERTE;
                end if;

 

Porte — Logique de transition, partie 2  |  VHDL
            when OUVERTE =>
                if presence = '0' then
                    etat_suivant <= FERMETURE;
                end if;

            when FERMETURE =>
                if obstacle = '1' then
                    etat_suivant <= OUVERTURE;
                elsif fin_fermeture = '1' then
                    etat_suivant <= FERMEE;
                end if;

            when DEFAUT =>
                null;
        end case;
    end if;
end process;

 

Assertion de sécurité  |  VHDL
assert not (moteur_ouvrir = '1' and moteur_fermer = '1')
    report "Commandes moteur contradictoires"
    severity failure;

 

8. Partie D — Distributeur

Le produit coûte £3. Le distributeur accepte une pièce de £1 ou £2 par cycle. Il délivre le produit lorsque le crédit atteint au moins £3 et rend £1 si le crédit total atteint £4.

États du crédit  |  États Moore
C0 : crédit £0
C1 : crédit £1
C2 : crédit £2
DISTRIBUE : produit délivré, aucune monnaie
DISTRIBUE_MONNAIE : produit délivré + retour £1

 

distributeur.vhd — Interface  |  VHDL
entity distributeur is
    port (
        clk, reset : in std_logic;
        piece_1    : in std_logic;
        piece_2    : in std_logic;
        distribuer : out std_logic;
        monnaie_1  : out std_logic
    );
end entity distributeur;

 

Distributeur — Transitions, partie 1  |  VHDL
process(all)
begin
    etat_suivant <= etat_courant;

    case etat_courant is
        when C0 =>
            if piece_2 = '1' then
                etat_suivant <= C2;
            elsif piece_1 = '1' then
                etat_suivant <= C1;
            end if;

        when C1 =>
            if piece_2 = '1' then
                etat_suivant <= DISTRIBUE;
            elsif piece_1 = '1' then
                etat_suivant <= C2;
            end if;

 

Distributeur — Transitions, partie 2  |  VHDL
        when C2 =>
            if piece_2 = '1' then
                etat_suivant <= DISTRIBUE_MONNAIE;
            elsif piece_1 = '1' then
                etat_suivant <= DISTRIBUE;
            end if;

        when DISTRIBUE | DISTRIBUE_MONNAIE =>
            etat_suivant <= C0;
    end case;
end process;

 

Distributeur — Sorties Moore  |  VHDL
distribuer <= '1'
    when etat_courant = DISTRIBUE
      or etat_courant = DISTRIBUE_MONNAIE
    else '0';

monnaie_1 <= '1'
    when etat_courant = DISTRIBUE_MONNAIE
    else '0';

 

Cas limite — Pièces simultanées

Le cahier des charges doit préciser le comportement si piece_1 et piece_2 valent 1 simultanément. Dans cet exemple, piece_2 est prioritaire. Un vrai système utiliserait un validateur de pièces produisant un code exclusif.

 

9. Banc de test du distributeur

Scénario £1 + £2  |   VHDL
piece_1 <= '1';
wait until rising_edge(clk);
piece_1 <= '0';

piece_2 <= '1';
wait until rising_edge(clk);
piece_2 <= '0';
wait for 1 ns;

assert distribuer = '1' and monnaie_1 = '0'
    report "Distribution £3 incorrecte"
    severity error;

wait until rising_edge(clk);
wait for 1 ns;
assert distribuer = '0' severity error;

 

Scénario £2 + £2  |   VHDL
piece_2 <= '1';
wait until rising_edge(clk);
piece_2 <= '0';

piece_2 <= '1';
wait until rising_edge(clk);
piece_2 <= '0';
wait for 1 ns;

assert distribuer = '1' and monnaie_1 = '1'
    report "Monnaie £1 attendue"
    severity error;

wait until rising_edge(clk);
wait for 1 ns;
assert distribuer = '0' severity error;

 

10. Comparaison Moore/Mealy

Critère

Détecteur Moore

Détecteur Mealy

Nombre d’états54
Moment de detectionAprès entrée en S4Sur transition depuis S3
Dépendance directe entrée-sortieNonOui
Risque de glitchPlus faiblePlus élevé
LatenceSouvent un cycle supplémentaireRéaction immédiate

 

11. Compilation avec GHDL

Compilation  |   Terminal
ghdl -a --std=08 src/detecteur_1011_moore.vhd
ghdl -a --std=08 src/detecteur_1011_mealy.vhd
ghdl -a --std=08 src/feu_tricolore.vhd
ghdl -a --std=08 src/controleur_porte.vhd
ghdl -a --std=08 src/distributeur.vhd

 

Simulation  |   Terminal
ghdl -a --std=08 sim/tb_detecteur_1011.vhd
ghdl -e --std=08 tb_detecteur_1011
ghdl -r --std=08 tb_detecteur_1011    --vcd=tb_detecteur_1011.vcd

gtkwave tb_detecteur_1011.vcd

 

12. Observations demandées

  • Afficher l’état courant dans le chronogramme si le simulateur le permet.
  • Vérifier les séquences qui se chevauchent.
  • Mesurer la latence Moore/Mealy.
  • Vérifier les durées des feux.
  • Tester un obstacle pendant la fermeture.
  • Tester l’arrêt d’urgence.
  • Tester toutes les combinaisons de pièces.
  • Vérifier qu’aucune sortie contradictoire n’est active.

13. Tableau de résultats

Machine

Scénario

Résultat attendu

Observé

Conforme

DétecteurEntrée 1011Une détection  
DétecteurSéquences chevauchéesDétections correctes  
Feu5/2/5 ticksVERT/ORANGE/ROUGE  
PorteObstacle en fermetureRéouverture  
PorteArrêt urgenceDEFAUT  
Distributeur£1 + £2Produit, pas de monnaie  
Distributeur£2 + £2Produit + £1  

 

14. Questions d’analyse

1. Pourquoi le détecteur Moore nécessite-t-il un état supplémentaire ?

2. Comment le chevauchement de séquences est-il conservé ?

3. Pourquoi les sorties du feu sont-elles adaptées à Moore ?

4. Comment dimensionner le temporisateur du feu ?

5. Pourquoi l’obstacle est-il prioritaire sur fin_fermeture ?

6. Quel état initial est le plus sûr pour le feu et la porte ?

7. Comment gérer deux pièces simultanées ?

8. Quelle sortie Mealy pourrait être enregistrée ?

9. Quel codage d’états choisir sur un FPGA ?

10. Comment prouver que tous les arcs du diagramme ont été testés ?

15. Extensions proposées

  • Détecter une séquence paramétrable.
  • Ajouter un feu piéton avec bouton.
  • Ajouter une durée minimale de porte ouverte.
  • Ajouter un capteur de panne moteur.
  • Ajouter plusieurs produits et prix.
  • Créer une machine de remboursement.
  • Comparer codage binaire et one-hot après synthèse.
  • Implanter une des machines sur carte FPGA.

16. Barème indicatif

Critère

Points

Détecteur Moore3
Détecteur Mealy et comparaison3
Feu de circulation3
Porte automatique3
Distributeur3
Bancs de test et assertions3
Analyse et qualité du compte rendu2
Total20

 

Synthèse du chapitre

Notion

Résumé

ÉtatSituation mémorisée du système.
TransitionPassage conditionnel vers un autre état.
MooreSorties dépendant uniquement de l’état.
MealySorties dépendant de l’état et des entrées.
Registre d’étatMémorise l’état au front d’horloge.
Logique de transitionCalcule l’état suivant.
Un processusFSM compacte, sorties souvent enregistrées.
Deux processusRegistre + logique combinatoire.
Trois processusRegistre + transition + sorties séparées.
BinaireCodage compact en bascules.
One-hotUne bascule par état.
GrayUn bit change entre états successifs prévus.

 

Autoévaluation

1. De quoi dépend une sortie Moore ?

Réponse : Uniquement de l’état courant.

2. De quoi dépend une sortie Mealy ?

Réponse : De l’état courant et des entrées.

3. Quel bloc mémorise l’état ?

Réponse : Le registre d’état.

4. Pourquoi initialiser etat_suivant ?

Réponse : Pour définir le maintien et éviter un latch.

5. Quel style sépare le mieux les sorties ?

Réponse : Le style à trois processus.

6. Combien de bits binaires pour cinq états ?

Réponse : Trois bits.

7. Combien de bascules one-hot pour cinq états ?

Réponse : Cinq bascules.

8. Où apparaissent les sorties dans un diagramme Mealy ?

Réponse : Sur les transitions.

9. Pourquoi synchroniser une entrée externe ?

Réponse : Pour réduire le risque de métastabilité.

10. Que doit couvrir le banc de test ?

Réponse : Tous les états, transitions et cas limites.

Exercice de consolidation

Concevoir une FSM Moore commandant une pompe. La pompe démarre sur demande si le niveau est suffisant, s’arrête lorsque la demande disparaît et passe en alarme si le niveau devient trop bas.

Correction proposée — États et transitions  |  VHDL
type etat_t is (ARRET, MARCHE, ALARME);

case etat_courant is
    when ARRET =>
        if niveau_bas = '1' then
            etat_suivant <= ALARME;
        elsif demande = '1' then
            etat_suivant <= MARCHE;
        end if;

    when MARCHE =>
        if niveau_bas = '1' then
            etat_suivant <= ALARME;
        elsif demande = '0' then
            etat_suivant <= ARRET;
        end if;

    when ALARME =>
        if acquit = '1' and niveau_bas = '0' then
            etat_suivant <= ARRET;
        end if;
end case;

 

Correction proposée — Sorties  |  VHDL
pompe <= '1' when etat_courant = MARCHE else '0';
alarme <= '1' when etat_courant = ALARME else '0';