Aller au contenu

Machines à états finis

Une machine à états mémorise un état discret et choisit le suivant à partir de l'état courant et des entrées.

Concevoir d'abord sur papier

Écrivez :

  1. Chaque état et sa signification.
  2. L'état de reset.
  3. Les conditions de chaque transition sortante.
  4. Les sorties actives dans chaque état ou transition.
  5. Le comportement en cas d'entrées invalides ou simultanées.
  6. Le timing : sorties cadencées ou combinatoires.

Moore et Mealy

Style Dépendance des sorties Effet
Moore État courant Généralement stables pendant tout un cycle
Mealy État courant et entrées Réponse dans le cycle, risque de glitch

Des sorties enregistrées simplifient souvent le timing des interfaces.

Patron à deux processus

type state_t is (IDLE, ACTIVE, DONE);
signal state_q : state_t := IDLE;
signal state_d : state_t;

state_register : process(clk_i)
begin
  if rising_edge(clk_i) then
    if reset_i = '1' then
      state_q <= IDLE;
    else
      state_q <= state_d;
    end if;
  end if;
end process;

next_state_logic : process(all)
begin
  state_d <= state_q;

  case state_q is
    when IDLE =>
      if start_i = '1' then
        state_d <= ACTIVE;
      end if;
    when ACTIVE =>
      if complete_i = '1' then
        state_d <= DONE;
      end if;
    when DONE =>
      if acknowledge_i = '1' then
        state_d <= IDLE;
      end if;
  end case;
end process;

busy_o <= '1' when state_q = ACTIVE else '0';
done_o <= '1' when state_q = DONE else '0';

Atouts : séparation nette du registre et des transitions, sorties de Moore lisibles, état présent et suivant visibles. Risque : oublier les valeurs par défaut et inférer un latch.

Patron à un processus

process(clk_i)
begin
  if rising_edge(clk_i) then
    if reset_i = '1' then
      state_q <= IDLE;
      busy_o  <= '0';
      done_o  <= '0';
    else
      done_o <= '0';
      case state_q is
        when IDLE =>
          busy_o <= '0';
          if start_i = '1' then
            state_q <= ACTIVE;
            busy_o  <= '1';
          end if;
        when ACTIVE =>
          if complete_i = '1' then
            state_q <= DONE;
            busy_o  <= '0';
            done_o  <= '1';
          end if;
        when DONE =>
          if acknowledge_i = '1' then
            state_q <= IDLE;
          end if;
      end case;
    end if;
  end if;
end process;

Atouts : tout état et toute sortie enregistrée changent au front, aucun latch combinatoire accidentel. Risque : les grandes machines deviennent longues et la latence des sorties doit être soigneusement comprise.

Les deux styles sont valables. Adoptez une convention et testez le contrat temporel.

Priorité des transitions

Si deux conditions peuvent être vraies ensemble, l'ordre if/elsif crée une priorité :

if emergency_i = '1' then
  state_d <= SAFE;
elsif complete_i = '1' then
  state_d <= DONE;
end if;

Documentez cette priorité.

Encodage

Vivado peut choisir :

  • binaire : peu de bascules, davantage de décodage ;
  • one-hot : une bascule par état, décodage souvent simple et rapide ;
  • Gray : un bit change entre états voisins lorsque le graphe le permet.

N'optimisez pas trop tôt. Validez d'abord fonction et timing, puis appuyez-vous sur les rapports.

Plan de vérification

Testez :

  • le reset depuis chaque situation importante ;
  • chaque transition légale ;
  • les conditions qui doivent maintenir l'état ;
  • les priorités entre conditions simultanées ;
  • les durées minimales et maximales ;
  • les sorties autour des fronts ;
  • la récupération d'un état illégal si elle est exigée.
assert not (busy_o = '1' and done_o = '1')
  report "busy and done must never be active together"
  severity failure;

Tenez une table de couverture des transitions.

Erreurs fréquentes

  • Coder avant d'établir le diagramme.
  • Laisser une condition de transition ambiguë.
  • Créer des glitches sur une sortie de commande.
  • Oublier les valeurs par défaut d'une machine à deux processus.
  • Confondre initialisation et stratégie de reset.
  • Compter les cycles sans définir si l'entrée dans l'état vaut cycle zéro ou un.