Macchine a stati finiti in VHDL
In questa pagina 5
Un sistema sequenziale (Latch, registri e parametri temporaliUn circuito sequenziale ha uno stato memorizzato in due modi: retroazione positiva (due inverter in anello, bistabile, i latch statici) o immagazzinamento di carica (circuiti dinamici). Un latch è sensibile al livello del clock (trasparente quando il clock è attivo, memorizza quando non lo è), un registro (flip-flop) è sensibile al fronte e si realizza con due latch sulle fasi opposte (master-slave). Il latch SR a porte NOR/NAND non ammette la combinazione S = R = 1 perché passando da lì alla memoria lo stato finale è imprevedibile. Parametri temporali del registro: ritardo clock-uscita t_c-q, tempo di setup t_su (dato stabile prima del fronte), tempo di hold t_hold (dato stabile dopo il fronte). Periodo minimo: T_min = t_c-q + t_p,logic(max) + t_su; vincolo di hold: t_cd,reg + t_cd,logic > t_hold. La pipeline spezza la logica con registri per aumentare la frequenza (a spese della latenza).Latch, registri e parametri temporali →) si modella come macchina a stati finiti (FSM, finite state machine): un numero finito di stati, un registro che ne memorizza uno, e logica combinatoria che ne calcola l'evoluzione. È anche il modello dell'unità di controllo di un processore (Blocchi logici di un microprocessore - ALU, bus e logica tri-stateUn microprocessore semplice è formato da un'unità di controllo (decodifica le istruzioni e abilita gli altri blocchi), una ALU (operazioni aritmetiche e logiche), la memoria e i registri, collegati da bus (linee condivise unidirezionali o bidirezionali). La ALU combina un sommatore con un'unità logica e un multiplexer di selezione dell'operazione: la sottrazione è A + B̄ + 1 (XOR su B e riporto in ingresso a 1), le flag (zero, riporto, segno, overflow) descrivono il risultato. Un bus è una linea pilotata da più sorgenti: per evitare conflitti ogni uscita collegata è tri-state (il segnale enable la mette in alta impedenza) oppure open-drain (solo PDN: ciascuna può imporre 0, serve un pull-up per l'1).Blocchi logici di un microprocessore - ALU, bus e logica tri-state →).
Modelli di Mealy e di Moore
Con stato al periodo e ingresso:
- Moore: l'uscita dipende solo dallo stato: cambia soltanto dopo un fronte di clock (cioè quando cambia lo stato), ed è priva di glitch dovuti agli ingressi. Nel diagramma l'uscita è scritta dentro lo stato.
- Mealy: l'uscita dipende da stato e ingresso: può cambiare appena cambia l'ingresso (anche tra due fronti) e di solito richiede meno stati per lo stesso comportamento. Nel diagramma l'uscita è scritta sull'arco (
x/y).
Il registro di stato è un banco di registri D con retroazione dallo stato prossimo (VHDL - logica sequenziale e registriIn VHDL la logica sequenziale si descrive con processi sensibili al clock. Un registro D (flip-flop sul fronte) si scrive process(clk) con if rising_edge(clk); un latch è un processo sensibile al livello (if clk='1' then q<=d) senza altri rami. Il reset è sincrono se testato dentro rising_edge(clk) (la lista di sensibilità contiene solo clk), asincrono se testato prima, con RST nella lista di sensibilità (if rst='1' then ... elsif rising_edge(clk)). Registri a n bit con generic, registri a scorrimento (con load), contatori (up/down, con enable) si ottengono con la stessa struttura. In un progetto sincrono tutti i registri usano lo stesso clock (nessun clock generato da logica: si usano abilitazioni), i segnali esterni asincroni come i pulsanti si campionano con uno o più flip-flop (debouncing) e le cifre di un display si multiplexano con un contatore.VHDL - logica sequenziale e registri →). Gli stati si codificano con bit (codifica binaria), con un solo bit a (one-hot: flip-flop ma logica semplice e veloce, la scelta tipica nelle FPGA) o in Gray; in VHDL si usa un tipo enumerato e il sintetizzatore sceglie la codifica.
Struttura VHDL a due processi
architecture RTL of FSM1 is
type STATE_T is (idle, counting);
signal state_reg, state_next : STATE_T;
begin
-- processo sequenziale: registro di stato, reset asincrono
process (RST, CLK)
begin
if RST = '1' then
state_reg <= idle;
elsif rising_edge(CLK) then
state_reg <= state_next;
end if;
end process;
-- processo combinatorio: funzione di stato prossimo e di uscita
process (state_reg, START)
begin
state_next <= state_reg; -- valore di default: resta nello stato
case state_reg is
when idle =>
CHECK <= '0';
if START = '1' then state_next <= counting; end if;
when counting =>
CHECK <= '1';
if START = '0' then state_next <= idle; end if;
end case;
end process;
end RTL;Questa è una macchina di Moore a doppio processo: CHECK è assegnata nei rami del case come funzione del solo state_reg (in idle vale '0', in counting vale '1'; la dipendenza da START riguarda solo state_next). Se CHECK dipendesse anche da START sarebbe di Mealy. Il valore di default state_next <= state_reg; evita di inferire un latch (e rende il codice più compatto). Il processo sequenziale ha la lista di sensibilità (RST, CLK) perché il reset è asincrono; la parte combinatoria ha tutti i segnali letti (state_reg, START).
Il comportamento dell'esempio, per START (un valore per ciclo, stato letto prima del fronte):
| ciclo | START |
state_reg |
CHECK |
stato prossimo |
|---|---|---|---|---|
| 0 | 0 | idle | 0 | idle |
| 1 | 1 | idle | 0 | counting |
| 2 | 1 | counting | 1 | counting |
| 3 | 0 | counting | 1 | idle |
| 4 | 0 | idle | 0 | idle |
| 5 | 1 | idle | 0 | counting |
| 6 | 1 | counting | 1 | counting |
L'uscita (Moore) segue START con un periodo di ritardo, perché passa attraverso il registro di stato.
Stile a processo singolo: un solo processo sequenziale con case e rising_edge(CLK) in cui anche le uscite sono registrate (assegnate al fronte): l'uscita è sincrona e priva di glitch ma in ritardo di un ciclo in più.
Progettazione: dal diagramma al codice
- Specifiche diagramma degli stati (nodi: stati; archi: condizioni sugli ingressi; uscite nei nodi o sugli archi).
- Tabella di transizione: per ogni stato presente e ingresso, stato prossimo e uscita.
- Codice VHDL: tipo enumerato, processo di registro, processo combinatorio.
- Verifica con testbench (Simulazione, testbench, vincoli di temporizzazione e flusso su FPGAUn progetto VHDL si verifica per simulazione con un testbench: una entity senza porte che istanzia il circuito sotto test (UUT), genera il clock (process con wait for e inversione), applica gli stimoli e controlla le uscite con assert/report/severity (note, warning, error, failure) o leggendo vettori da file (textio). Il flusso su FPGA è: descrizione VHDL, simulazione funzionale, sintesi (rete di LUT e flip-flop), implementazione (piazzamento e instradamento), analisi di temporizzazione, generazione del bitstream e programmazione della scheda. I vincoli (file XDC) assegnano i pin e definiscono il clock (periodo); l'analisi di temporizzazione verifica per ogni cammino registro-registro lo slack di setup, T − (t_c-q + t_logica + t_routing + t_su), e di hold; con slack negativo la frequenza è troppo alta: f_max = 1/(T − WNS).Simulazione, testbench, vincoli di temporizzazione e flusso su FPGA →).
Esempio (Mealy, dalle slide). Quattro stati , ingresso , uscita :
| stato | ||
|---|---|---|
| A | A / 0 | B / 0 |
| B | A / 0 | C / 0 |
| C | D / 0 | C / 0 |
| D | A / 0 | A / 1 |
(formato: stato prossimo / uscita). Si arriva in solo dopo almeno due consecutivi seguiti da uno ; l'uscita è solo se in arriva un : la macchina riconosce la sequenza "due o più , uno , un ". Con gli stati attraversati sono e l'uscita : riconosce due volte la sequenza (in corrispondenza del quarto e del decimo ingresso). Il codice VHDL ha il processo (combinatorio: case STATO_PRES, if FSM_IN = '0' ..., che assegna STATO_FUT e Y) e il processo (registri). Poiché Y dipende da FSM_IN, è una macchina di Mealy.
Altre macchine tipiche dei laboratori
- Contatore come FSM con stati (stato prossimo stato ).
- Controllore del display a cifre: il contatore di scansione fa da stato.
- Interfaccia di comunicazione (I2C del sensore di temperatura del laboratorio): FSM con stati di start, invio indirizzo, lettura bit, stop; si parte dal diagramma e si implementa con il tipo enumerato.
Errori comuni
- Non assegnare
state_nextin tutti i rami (latch inferito): si usa il valore di default. - Chiamare Moore una macchina la cui uscita dipende dall'ingresso (sarebbe Mealy).
- Dimenticare lo stato di reset (le FSM devono partire da uno stato noto).
- Mettere nel processo combinatorio solo lo stato nella lista di sensibilità e non gli ingressi.
- Usare un tipo enumerato in uno stato non raggiunto: stati inutilizzati con codifica binaria possono "bloccare" la macchina (rimedio:
when others => state_next <= idle;).
Versione ripasso
- Modelli: ; Moore (cambia solo al fronte, uscita nello stato); Mealy (cambia con l'ingresso, uscita sull'arco, meno stati).
- Codifica: binaria, one-hot (tipica nelle FPGA), Gray; in VHDL tipo enumerato.
- Due processi: sequenziale (
RSTasincrono:state_reg<=idle;rising_edge:state_reg<=state_next) + combinatorio (state_next<=state_reg;default;case state_reg, uscite). Esempio idle/counting:CHECKfunzione del solo stato Moore a doppio processo; uscita in ritardo di un ciclo suSTART. - Processo singolo: uscite registrate, glitch-free, un ciclo in più.
- Progetto: diagramma tabella codice testbench. Esempio Mealy (): riconosce " uni, uno zero, un uno" (uscite agli ingressi e di ).
- Errori:
state_nextnon assegnata; Moore vs Mealy; reset mancante; sensibilità incompleta; stati inutilizzati.