Salta al contenuto
Note per Studenti Esercizio 25 · trovare gli errori in una descrizione VHDL di una macchina a stati (esercizio sul modello del tema d'esame giugno 2026)

Esercizio 25trovare gli errori in una descrizione VHDL di una macchina a stati (esercizio sul modello del tema d'esame giugno 2026)

Esame
In questa pagina 5

Testo. Nel terzo esercizio del primo appello di giugno 2026 era dato un codice VHDL di una macchina a stati che conteneva un errore: bisognava trovarlo, riscrivere il codice corretto e disegnare il diagramma degli stati finale. Il testo originale non è disponibile (la foto del foglio manca), quindi qui si propone un esercizio costruito sullo stesso modello, con gli errori più tipici.

Si vuole un riconoscitore di due 1 consecutivi (con sovrapposizioni) di Mealy: ingresso x, uscita z che vale 1 quando l'ultimo bit ricevuto e il precedente sono entrambi 1; reset asincrono attivo alto (rst = '1' porta nello stato iniziale), D-FF positive edge triggered. Il codice seguente dovrebbe descriverlo, ma contiene tre errori.

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity det11 is
  port ( clk, rst : in  std_logic;
         x        : in  std_logic;
         z        : out std_logic );
end det11;

architecture beh of det11 is
  type state_type is (S0, S1);
  signal state, next_state : state_type;
begin
  reg : process (clk)
  begin
    if rst = '1' then
      state <= S0;
    elsif clk'event and clk = '1' then
      state <= next_state;
    end if;
  end process;

  comb : process (state)
  begin
    case state is
      when S0 =>
        if x = '1' then next_state <= S1; end if;
        z <= '0';
      when S1 =>
        if x = '1' then next_state <= S1; z <= '1';
        else next_state <= S0; z <= '0';
        end if;
    end case;
  end process;
end beh;
  1. Trovare e correggere gli errori. 2. Scrivere il codice corretto. 3. Disegnare (tabella) il diagramma degli stati della macchina e controllarlo con la sequenza di ingresso 0,1,1,0,1,1,10,1,1,0,1,1,1.

Teoria usata: VHDL - macchine a stati finiti e testbench sequenzialeUna macchina a stati finiti (FSM) si descrive in VHDL, in stile behavioral, con un tipo enumerato per gli stati e tre process: (1) registro di stato con reset (asincrono) e aggiornamento state<=next_state sul fronte; (2) stato futuro come funzione combinatoria di stato e ingresso (case state, default next_state<=state); (3) uscita come funzione combinatoria di stato (Moore) o di stato e ingresso (Mealy). Il testbench ha il process del clock e il process degli ingressi (reset iniziale, sequenza di test che percorre tutti gli stati).VHDL - macchine a stati finiti e testbench sequenziale →, VHDL - latch, flip-flop e reset sincrono e asincronoIn VHDL un elemento di memoria si descrive con un process il cui ramo non assegna sempre il segnale: latch D = process(D,C) con if C='1' then Q<=D; flip-flop positive-edge-triggered = process(CLK) con if CLK'event and CLK='1'. Reset asincrono: RST nella sensitivity list e testato per primo (if RST='1' ... elsif fronte); reset sincrono: solo CLK in lista e RST testato dentro al ramo del fronte (serve un fronte per averne effetto). Il testbench di un circuito sincrono ha un process che genera il clock e uno che applica gli ingressi lontano dal fronte attivo.VHDL - latch, flip-flop e reset sincrono e asincrono →, VHDL - istruzioni concorrenti, process e testbenchLe istruzioni concorrenti VHDL sono l'assegnazione di segnale, when-else (logica prioritaria, condizioni valutate in ordine) e with-select (logica parallela: tutti i casi coperti da una sola scelta, others obbligatorio). Un process è un'istruzione concorrente il cui corpo è sequenziale (if, case, loop); parte quando cambia un segnale della sensitivity list (per la logica combinatoria: tutti gli ingressi); i segnali si aggiornano alla sospensione e vince l'ultima assegnazione. Un if senza else (o un caso non coperto) crea memoria non voluta. Il testbench è codice di simulazione con entity vuota, DUT istanziato e un process di stimoli con wait.VHDL - istruzioni concorrenti, process e testbench →, Analisi delle reti sequenziali - tabella e diagramma degli stati, Mealy e MooreAnalizzare una rete sequenziale sincrona significa ricavare, dal circuito, le equazioni di ingresso dei flip-flop (stato futuro) e dell'uscita, la tabella degli stati ($2^{m+n}$ righe per $m$ FF e $n$ ingressi), il diagramma degli stati (cerchi = stati, frecce = transizioni con ingresso/uscita) e la simulazione temporale. Mealy: uscita funzione di stato e ingresso (scritta sulle frecce, può cambiare tra due fronti di clock); Moore: uscita funzione del solo stato (scritta nel cerchio, cambia solo al fronte). Due stati sono equivalenti se danno le stesse uscite e portano a stati equivalenti: si fondono per ridurre i FF.Analisi delle reti sequenziali - tabella e diagramma degli stati, Mealy e Moore →.

Metodo: cosa controllare in ordine

Per ogni process di una macchina a stati:

  1. Registro di stato: il reset è nella sensitivity list? Il suo test è fuori (asincrono) o dentro (sincrono) il ramo del fronte, come chiede il testo? Il fronte è quello richiesto?
  2. Logica combinatoria: la lista di sensibilità contiene tutti gli ingressi letti (stato e ingressi)? Ogni segnale (next_state e z) è assegnato in ogni ramo, per ogni stato e per ogni valore degli ingressi? Un caso non coperto crea un latch.
  3. Uscita: Moore (dipende solo dallo stato) o Mealy (anche dall'ingresso), come chiede il testo.

Gli errori

Errore 1: reset asincrono senza rst nella lista di sensibilità (process reg). Il test if rst = '1' è fuori dal controllo del fronte (giusto per un reset asincrono), ma il process si risveglia solo quando cambia clk: se rst sale a metà del periodo non succede nulla fino al successivo cambio di clk. Il reset non è asincrono in simulazione, e il comportamento descritto non corrisponde a quello sintetizzato. Correzione: process (clk, rst).

Errore 2: x manca dalla lista di sensibilità (process comb). Il process legge x ma si attiva solo se cambia state: se x cambia con lo stato fermo, next_state e z non vengono ricalcolati. In simulazione la macchina sbaglia; il sintetizzatore ignora la lista e crea una rete corretta, per cui simulazione e circuito divergono. Correzione: process (state, x).

Errore 3: next_state non assegnato nel caso S0 con x = '0' (if senza else). Per quel caso next_state conserva il valore precedente: il sintetizzatore inserisce un latch su next_state. Il valore conservato è quello dello stato futuro precedente: se era S1S_1, la macchina passa in S1S_1 anche con x=0x=0. Correzione: aggiungere else next_state <= S0; (con x=0x=0 da S0S_0 si resta in S0S_0).

Non sono errori: z <= '0' nel ramo S0 prima dell'if (ogni ramo assegna z); l'assenza di when others nel case perché il tipo enumerato ha solo i due stati S0 e S1, entrambi coperti; il reset a S0 con rst = '1' (attivo alto, come chiede il testo).

Codice corretto

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity det11 is
  port ( clk, rst : in  std_logic;
         x        : in  std_logic;
         z        : out std_logic );
end det11;

architecture beh of det11 is
  type state_type is (S0, S1);
  signal state, next_state : state_type;
begin
  -- D-FF positive edge triggered con reset asincrono attivo alto
  reg : process (clk, rst)
  begin
    if rst = '1' then
      state <= S0;
    elsif clk'event and clk = '1' then
      state <= next_state;
    end if;
  end process;

  -- stato futuro e uscita di Mealy (dipende da stato e ingresso)
  comb : process (state, x)
  begin
    case state is
      when S0 =>
        z <= '0';
        if x = '1' then next_state <= S1;
        else            next_state <= S0;
        end if;
      when S1 =>
        if x = '1' then next_state <= S1; z <= '1';
        else            next_state <= S0; z <= '0';
        end if;
    end case;
  end process;
end beh;

Diagramma degli stati

S0S_0 = "l'ultimo bit non è un 11 (o nessun bit)", S1S_1 = "l'ultimo bit è un 11". Le etichette sono x/zx/z:

stato x=0x=0 x=1x=1
S0S_0 (iniziale) S0S_0 / 00 S1S_1 / 00
S1S_1 S0S_0 / 00 S1S_1 / 11

Archi: S0→0/0S0S_0\xrightarrow{0/0}S_0, S0→1/0S1S_0\xrightarrow{1/0}S_1, S1→0/0S0S_1\xrightarrow{0/0}S_0, S1→1/1S1S_1\xrightarrow{1/1}S_1. Sono i due stati minimi: non si possono unire perché con x=1x=1 danno uscite diverse.

Controllo con x=0,1,1,0,1,1,1x=0,1,1,0,1,1,1 (partendo da S0S_0):

bit xx stato prima uscita zz stato dopo
1 0 S0S_0 0 S0S_0
2 1 S0S_0 0 S1S_1
3 1 S1S_1 1 S1S_1
4 0 S1S_1 0 S0S_0
5 1 S0S_0 0 S1S_1
6 1 S1S_1 1 S1S_1
7 1 S1S_1 1 S1S_1

Uscita z=0,0,1,0,0,1,1z=0,0,1,0,0,1,1: z=1z=1 ai bit 3, 6, 7, cioè ogni volta che il bit corrente e il precedente sono 11 (compreso il caso sovrapposto 111111).

Errori comuni

  • Cercare un solo errore e fermarsi: il tema ne conteneva uno, ma conviene rileggere tutto il codice con la lista di controllo.
  • Mettere rst nella lista ma testarlo dentro il ramo del fronte: diventa un reset sincrono.
  • Dimenticare di ricavare il diagramma dal codice corretto (e non da quello errato).
  • Completare con when others un case su un tipo enumerato già coperto: non serve (serve invece per std_logic).

Versione ripasso

Teoria collegata