VHDL - macchine a stati finiti e testbench sequenziale
In questa pagina 5
Una macchina a stati finiti (FSM) è un registro di stato più due reti combinatorie (Sintesi delle reti sequenziali - riconoscitore di sequenza e codifica degli statiSintesi di una rete sequenziale sincrona: specifiche $\to$ diagramma degli stati $\to$ tabella (riduzione degli stati equivalenti) $\to$ codifica binaria degli stati $\to$ scelta del FF (D PET) $\to$ equazioni di ingresso dei FF e delle uscite $\to$ minimizzazione $\to$ circuito e verifica. Lo stato riassume la parte di storia utile; per i riconoscitori si ha uno stato per ogni prefisso riconosciuto, riusando gli stati (sovrapposizioni). Reset: stato iniziale noto. Codifica Gray (numero minimo di FF) vs 1-hot (un FF per stato, logica più semplice): per il riconoscitore 1101 Gray costa circa la metà.Sintesi delle reti sequenziali - riconoscitore di sequenza e codifica degli stati →): lo stato futuro e l'uscita. In VHDL la struttura si riflette direttamente nel codice, con tre process che lavorano in parallelo. È lo schema richiesto in questo corso per scrivere una FSM, e il tipico terzo esercizio d'esame.
Il modello a tre process
- Registro di stato (parte sequenziale): sul fronte di clock aggiorna
state <= next_state, e il reset porta in uno stato iniziale noto. - Stato futuro (logica combinatoria): calcola
next_statein funzione distatee degli ingressi. - Uscita (logica combinatoria): la calcola in funzione di
state(Moore) oppure distatee ingresso (Mealy).
I process 2 e 3 descrivono logica puramente combinatoria (liste di sensibilità con tutti gli ingressi, assegnazioni complete); solo il primo ha memoria. I tre process interagiscono attraverso i segnali comuni (state, next_state).
Il tipo enumerato
type state_type is (S1, S2, S3, S4); -- nuovo tipo con valori simbolici
signal state, next_state : state_type;Con type si definisce un tipo elencando i valori tra parentesi, separati da virgole (enumerazione): serve per segnali con un numero finito di valori, indicati con nomi e non con numeri, per leggibilità. Lo stesso std_logic è un'enumerazione (9 valori). Il sintetizzatore sceglie la codifica binaria degli stati, a meno che non la si imponga (per esempio con costanti std_logic_vector, come nell'esempio del semaforo).
Esempio completo: riconoscitore di sequenza 1101 (Mealy)
Ingresso , uscita ; quando si è presentata la sequenza e ; reset asincrono in . Il diagramma è quello della sintesi (Sintesi delle reti sequenziali - riconoscitore di sequenza e codifica degli statiSintesi di una rete sequenziale sincrona: specifiche $\to$ diagramma degli stati $\to$ tabella (riduzione degli stati equivalenti) $\to$ codifica binaria degli stati $\to$ scelta del FF (D PET) $\to$ equazioni di ingresso dei FF e delle uscite $\to$ minimizzazione $\to$ circuito e verifica. Lo stato riassume la parte di storia utile; per i riconoscitori si ha uno stato per ogni prefisso riconosciuto, riusando gli stati (sovrapposizioni). Reset: stato iniziale noto. Codifica Gray (numero minimo di FF) vs 1-hot (un FF per stato, logica più semplice): per il riconoscitore 1101 Gray costa circa la metà.Sintesi delle reti sequenziali - riconoscitore di sequenza e codifica degli stati →).
library IEEE;
use IEEE.std_logic_1164.all;
entity seq_rec is
port ( clk, rst, X : in std_logic;
Z : out std_logic );
end seq_rec;
architecture beh of seq_rec is
type state_type is (S1, S2, S3, S4);
signal state, next_state : state_type;
begin
-- process 1: registro di stato con reset asincrono
state_register : process (rst, clk)
begin
if rst = '1' then
state <= S1;
elsif clk'event and clk = '1' then
state <= next_state;
end if;
end process;
-- process 2: stato futuro = f(stato, ingresso)
next_state_comb : process (X, state)
begin
case state is
when S1 =>
if X = '0' then next_state <= S1; else next_state <= S2; end if;
when S2 =>
if X = '0' then next_state <= S1; else next_state <= S3; end if;
when S3 =>
if X = '0' then next_state <= S4; else next_state <= S3; end if;
when S4 =>
if X = '0' then next_state <= S1; else next_state <= S2; end if;
end case;
end process;
-- process 3: uscita = f(stato, ingresso) (Mealy)
output_comb : process (X, state)
begin
case state is
when S4 =>
if X = '1' then Z <= '1'; else Z <= '0'; end if;
when others =>
Z <= '0';
end case;
end process;
end beh;Osservazioni.
- Il codice è behavioral: non dice come codificare gli stati né come realizzare la logica; descrive il comportamento. Per macchine semplici i sintetizzatori trovano da soli la realizzazione migliore.
- Nel process 1 il reset è testato per primo (asincrono, 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 →).
- Nei process 2 e 3 ogni ramo assegna l'uscita (
next_state,Z): niente memoria involontaria. - Moore invece di Mealy: la lista di sensibilità del process dell'uscita contiene solo
statee ilcasenon guarda l'ingresso:case state is when R4 => Z <= '1'; when others => Z <= '0'; end case;. - Se il testo dice "in tutti i casi non indicati il sistema non cambia stato", si può scrivere come prima istruzione del process 2 il valore di default
next_state <= state;e poi solo i casi che cambiano stato: l'ultima assegnazione vince, i casi non nominati restano al default.
Testbench
library IEEE;
use IEEE.std_logic_1164.all;
entity test_seq_rec is
end test_seq_rec;
architecture test of test_seq_rec is
signal clock, reset, X, Z : std_logic;
signal test_sequence : std_logic_vector(0 to 10) := "01110101100";
constant PERIOD : time := 100 ns;
begin
DUT : entity work.seq_rec(beh) port map (clock, reset, X, Z);
generate_clock : process
begin
clock <= '1'; wait for PERIOD/2;
clock <= '0'; wait for PERIOD/2;
end process;
apply_inputs : process
begin
reset <= '1'; X <= '0';
wait for 3*PERIOD/2; -- reset iniziale: il sistema parte da uno stato noto
reset <= '0';
for i in 0 to 10 loop
X <= test_sequence(i); -- un bit per ciclo, applicato sul fronte di discesa
wait for PERIOD;
end loop;
std.env.stop;
end process;
end test;Il clock sale a ns e scende a ; gli ingressi cambiano a ns, cioè sul fronte di discesa, lontano dal fronte di salita. Il reset iniziale dura ns e porta lo stato in .
Atteso con la sequenza : stati ( all'inizio) dopo i fronti successivi, e solo durante il sesto bit (il bit in cui compare ). Poiché è una macchina di Mealy, sale appena cambia l'ingresso (a ns, fronte di discesa), non al fronte di clock successivo: l'uscita può variare anche tra due fronti.
Esempio di Moore con vettore di uscita: controllore semaforico
Ingresso = auto in attesa in direzione E-O; sei luci in uscita (R = rosso, G = giallo, V = verde). Reset: verde N-S, rosso E-O. Se la sequenza porta al verde E-O e poi ritorna al verde N-S; prima di ogni rosso c'è un giallo. Stati e uscite (Moore):
| stato | uscita luci |
significato | se | se |
|---|---|---|---|---|
| VNS | 001100 |
verde N-S, rosso E-O | VNS | GNS |
| GNS | 010100 |
giallo N-S | VEO | VEO |
| VEO | 100001 |
verde E-O, rosso N-S | GEO | GEO |
| GEO | 100010 |
giallo E-O | VNS | VNS |
entity semaforo is
port ( clk, rst, X : in std_logic;
luci : out std_logic_vector(5 downto 0) ); -- (RNS, GNS, VNS, REO, GEO, VEO)
end semaforo;
architecture impl_beh of semaforo is
type state_type is (VNS, GNS, VEO, GEO);
signal state, next_state : state_type;
begin
state_register : process (clk, rst)
begin
if rst = '1' then state <= VNS;
elsif clk'event and clk = '1' then state <= next_state;
end if;
end process;
next_state_comb : process (X, state)
begin
case state is
when VNS => if X = '0' then next_state <= VNS; else next_state <= GNS; end if;
when GNS => next_state <= VEO;
when VEO => next_state <= GEO;
when GEO => next_state <= VNS;
end case;
end process;
output_comb : process (state) -- Moore: solo lo stato
begin
case state is
when VNS => luci <= "001100";
when GNS => luci <= "010100";
when VEO => luci <= "100001";
when GEO => luci <= "100010";
end case;
end process;
end impl_beh;Un testbench che attraversa tutti gli stati e tutte le transizioni: reset; per 2 cicli (resta in VNS); per 3 cicli (entra nella sequenza); per 2 cicli; ancora per un nuovo ciclo completo.
Schema per l'esame
- Scrivere
library/usee la entity (clock, reset, ingressi, uscite). - Nell'architecture: tipo enumerato degli stati e segnali
state,next_state. - Process 1: registro di stato con reset (nell'esame si indica spesso "FF D positive edge triggered con reset asincrono").
- Process 2:
case statecon tutte le transizioni (default: restare). - Process 3: uscite (solo
stateper Moore; anche l'ingresso per Mealy). - Testbench: entity vuota, DUT, process del clock, process degli ingressi con reset iniziale e sequenza che raggiunge tutti gli stati (a volte "con il minor numero di transizioni").
Errori comuni
- Dimenticare il reset (in simulazione lo stato iniziale non è definito:
'U'). - Mettere nel process 2 o 3 una lista di sensibilità incompleta.
- Descrivere un'uscita di Moore con una dipendenza dall'ingresso (diventa Mealy).
- Non coprire tutti gli stati nel
case(mancawhen otherso uno stato): memoria involontaria. - Cambiare gli ingressi del testbench in coincidenza con il fronte di salita.
- Pensare che l'uscita di Mealy cambi solo al fronte: può cambiare con l'ingresso.
Versione ripasso
- Tre process: (1) registro di stato
if rst='1' then state<=S1; elsif clk'event and clk='1' then state<=next_state;; (2)next_state=case state+if X=...(combinatorio, lista(X, state)); (3) uscita: Mealy(X, state), Moore(state). - Tipo enumerato:
type state_type is (S1,S2,S3,S4); signal state, next_state : state_type;. Defaultnext_state <= state;per i casi non indicati. - Esempio 1101 (Mealy): con ; Moore: uscita solo da
state. - Testbench:
generate_clock(+ ns),apply_inputs: reset ns, poi un bit ogni ns sul fronte di discesa,std.env.stop. Sequenza : solo al sesto bit; Mealy: cambia con , non al fronte. - Semaforo (Moore): VNS
001100, GNS010100, VEO100001, GEO100010; avvia la sequenza (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 →). - Errori: niente reset;
caseincompleto; sensitivity list incompleta; Moore con ingresso.
Esercizi su questo argomento
- Esercizio 3 · descrizione VHDL di una macchina a stati con ingressi x e y e testbench (tema d'esame giugno 2022)
- Esercizio 6 · descrizione VHDL di una macchina di Moore con uscita a due bit (tema d'esame luglio 2022)
- Esercizio 9 · descrizione VHDL con ingresso a due bit x1x0 (tema d'esame settembre 2022)
- Esercizio 12 · descrizione VHDL di una macchina di Mealy con ingressi a e b e testbench (tema d'esame febbraio 2023)
- Esercizio 15 · descrizione VHDL behavioral di una macchina a tre stati e testbench (tema d'esame settembre 2025)
- Esercizio 25 · trovare gli errori in una descrizione VHDL di una macchina a stati (esercizio sul modello del tema d'esame giugno 2026)
Teoria collegata
- Analisi delle reti sequenziali - tabella e diagramma degli stati, Mealy e Moore
- Datapath e unità di controllo - un sistema digitale non programmabile
- Introduzione al VHDL - entity, architecture, tipi e livelli di descrizione
- Temporizzazione dei flip-flop - setup, hold e frequenza massima di clock
- VHDL - istruzioni concorrenti, process e testbench