Salta al contenuto
Note per Studenti Esercizio 3 · descrizione VHDL di una macchina a stati con ingressi x e y e testbench (tema d'esame giugno 2022)

Esercizio 3descrizione VHDL di una macchina a stati con ingressi x e y e testbench (tema d'esame giugno 2022)

Esame
In questa pagina 4

Testo (tema d'esame giugno 2022, primo appello, esercizio 3). 1) Descrivere in VHDL la macchina a stati finiti con ingressi xx e yy e uscita zz, avente il seguente diagramma degli stati. In tutti i casi non indicati, il sistema non cambia stato e l'uscita è 0. Separare nel codice gli elementi di memoria dalle parti puramente combinatorie. 2) Creare un test bench in VHDL che faccia attraversare tutti gli stati.

Diagramma (letto dalla figura del tema): stato iniziale S0S_0 (freccia con rst=1rst=1, z=0z=0);

  • S0→S1S_0\to S_1 se x=1x=1 and y=0y=0, con z=1z=1;
  • S0→S3S_0\to S_3 se x=0x=0 and y=1y=1, con z=1z=1;
  • S1→S2S_1\to S_2 se x=1x=1, con z=0z=0;
  • S3→S2S_3\to S_2 se x=0x=0 or y=1y=1, con z=0z=0;
  • S2→S0S_2\to S_0 senza condizione (l'arco non ha etichetta), con z=0z=0.

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 →, 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 →.

Passo 1: tipo di macchina e tabella

L'uscita zz è scritta sulle frecce (z=1z=1 sulle transizioni uscenti da S0S_0): dipende da stato e ingressi, è una macchina di Mealy. Si interpreta il tema così: l'arco da S2S_2 a S0S_0 non ha condizione ed è percorso al ciclo successivo; il reset (rst=1rst=1) porta a S0S_0 da ogni stato. Tabella (stato futuro / zz; ingressi xyxy):

stato xy=00xy=00 0101 1010 1111
S0S_0 S0/0S_0/0 S3/1S_3/1 S1/1S_1/1 S0/0S_0/0
S1S_1 S1/0S_1/0 S1/0S_1/0 S2/0S_2/0 S2/0S_2/0
S2S_2 S0/0S_0/0 S0/0S_0/0 S0/0S_0/0 S0/0S_0/0
S3S_3 S2/0S_2/0 S2/0S_2/0 S3/0S_3/0 S2/0S_2/0

(S3→S2S_3\to S_2 se x=0x=0 o y=1y=1: resta in S3S_3 solo con xy=10xy=10. S0S_0 non cambia stato per xy=00xy=00 e xy=11xy=11.)

Passo 2: codice VHDL

Tre process: registro di stato con reset (asincrono), stato futuro, uscita. Il reset è specificato dal tema (rst=1rst=1), si usa quindi asincrono attivo alto.

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

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

architecture beh of fsm_xy is
  type state_type is (S0, S1, S2, S3);
  signal state, next_state : state_type;
begin
  -- elementi di memoria: registro di stato, reset asincrono
  state_register : process (clk, rst)
  begin
    if rst = '1' then
      state <= S0;
    elsif clk'event and clk = '1' then
      state <= next_state;
    end if;
  end process;

  -- parte combinatoria: stato futuro
  next_state_comb : process (state, x, y)
  begin
    next_state <= state;                               -- casi non indicati: non cambia stato
    case state is
      when S0 =>
        if x = '1' and y = '0' then
          next_state <= S1;
        elsif x = '0' and y = '1' then
          next_state <= S3;
        end if;
      when S1 =>
        if x = '1' then next_state <= S2; end if;
      when S2 =>
        next_state <= S0;
      when S3 =>
        if x = '0' or y = '1' then next_state <= S2; end if;
    end case;
  end process;

  -- parte combinatoria: uscita (Mealy: dipende anche dagli ingressi)
  output_comb : process (state, x, y)
  begin
    z <= '0';                                          -- valore di default
    if state = S0 and ((x = '1' and y = '0') or (x = '0' and y = '1')) then
      z <= '1';
    end if;
  end process;
end beh;

L'assegnazione di default next_state <= state; (e z <= '0';) all'inizio dei process realizza la frase "in tutti i casi non indicati il sistema non cambia stato e l'uscita è 0" e impedisce memoria involontaria: ogni percorso assegna sempre i segnali.

Passo 3: testbench

Si devono percorrere tutti gli stati (e conviene anche tutte le transizioni). Sequenza di ingressi xyxy, un valore per ciclo, dopo il reset iniziale:

ciclo 0 1 2 3 4 5 6 7 8 9
xyxy 10 00 10 00 01 10 00 11 11 00
stato presente S0S_0 S1S_1 S1S_1 S2S_2 S0S_0 S3S_3 S3S_3 S2S_2 S0S_0 S0S_0
zz 1 0 0 0 1 0 0 0 0 0
stato futuro S1S_1 S1S_1 S2S_2 S0S_0 S3S_3 S3S_3 S2S_2 S0S_0 S0S_0 S0S_0

Questa sequenza usa tutte e 8 le transizioni del diagramma: S0→S1S_0\to S_1 (ciclo 0), S1S_1 che resta (1), S1→S2S_1\to S_2 (2), S2→S0S_2\to S_0 (3), S0→S3S_0\to S_3 (4), S3S_3 che resta (5), S3→S2S_3\to S_2 (6), S0S_0 che resta (8, 9).

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity tb_fsm_xy is
end tb_fsm_xy;

architecture test of tb_fsm_xy is
  signal clk, rst, x, y, z : std_logic;
  constant PERIOD : time := 10 ns;
  type vec_array is array (0 to 9) of std_logic_vector(1 downto 0);
  constant tv : vec_array := ("10", "00", "10", "00", "01", "10", "00", "11", "11", "00");
begin
  DUT : entity work.fsm_xy(beh) port map (clk, rst, x, y, z);

  generate_clock : process
  begin
    clk <= '1'; wait for PERIOD/2;
    clk <= '0'; wait for PERIOD/2;
  end process;

  apply_inputs : process
  begin
    rst <= '1'; x <= '0'; y <= '0';
    wait for 3*PERIOD/2;                 -- reset iniziale, finisce sul fronte di discesa
    rst <= '0';
    for i in 0 to 9 loop
      x <= tv(i)(1);                     -- primo bit del vettore = x
      y <= tv(i)(0);                     -- secondo bit = y
      wait for PERIOD;                   -- un vettore per ciclo di clock
    end loop;
    std.env.stop;
  end process;
end test;

Il clock sale a 0,10,20,…0,10,20,\dots ns e scende a 5,15,…5,15,\dots; gli ingressi cambiano sui fronti di discesa (15,25,…15,25,\dots), lontano dal fronte di salita (Temporizzazione dei flip-flop - setup, hold e frequenza massima di clockUn flip-flop memorizza il dato corretto solo se l'ingresso è stabile per $t_s$ (setup) prima e $t_h$ (hold) dopo il fronte di clock; l'uscita cambia dopo il tempo di propagazione $t_{pd,FF}$ dal fronte. In un circuito sincrono il periodo deve soddisfare $T\ge t_{pd,FF}+t_{COMB}+t_{s,FF}+t_{slack}$, quindi $f_{max}=1/T_{min}$; abbassare la frequenza risolve le violazioni di setup. Il vincolo di hold $t_{pd,FF,min}+t_{COMB,min}\ge t_h$ non dipende dal clock (e non si risolve rallentandolo). Il clock skew modifica i vincoli.Temporizzazione dei flip-flop - setup, hold e frequenza massima di clock →). Con la sequenza della tabella zz vale 11 nei cicli 0 e 4 (transizioni S0→S1S_0\to S_1 e S0→S3S_0\to S_3) e 00 negli altri. Il comportamento atteso della tabella è stato confrontato con un modello della macchina.

Errori comuni

  • Dimenticare lo stato S2S_2 (passaggio obbligato) o il suo ritorno non condizionato a S0S_0.
  • Mettere z=1z=1 anche nelle transizioni verso S2S_2.
  • Non separare memoria e combinatoria (un solo process con tutto).
  • Dimenticare i valori di default: case incompleti producono memoria involontaria.

Versione ripasso

Esercizi su questo argomento

Teoria collegata