Salta al contenuto
Note per Studenti VHDL - latch, flip-flop e reset sincrono e asincrono

VHDL - latch, flip-flop e reset sincrono e asincrono

In questa pagina 5

Qui si descrivono in VHDL gli elementi sequenziali di base visti in Elementi di memoria - latch SR, latch D e flip-flop DUn circuito sequenziale ha uscite che dipendono da ingressi e stato (memoria); è un circuito combinatorio con elementi di memoria in retroazione; stato presente = uscite dei FF, stato futuro = ingressi dei FF. Sincrono (clock) o asincrono. Latch SR (NOR): S=1,R=0 set; S=0,R=1 reset; 00 memoria; 11 proibito. Latch D: C=1 trasparente (Q=D), C=0 memoria, sensibile al livello. Flip-flop D edge-triggered = due latch D in cascata (master-slave) con clock opposti: cambia solo sul fronte attivo e non è trasparente. Si assume D flip-flop positive-edge-triggered.Elementi di memoria - latch SR, latch D e flip-flop D →. Si ricorda (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 →) che dentro un process le istruzioni sono sequenziali e che un segnale non assegnato in tutti i rami mantiene il valore: è proprio questa la memoria.

Latch SR con enable

Dataflow, con le porte NAND (ingressi S,RS,R attivi alti e controllo CC):

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity SRlatch is
  port ( S, R, C : in  std_logic;
         Q, Q_n  : out std_logic );
end SRlatch;

architecture dataflow of SRlatch is
  signal S_n, R_n : std_logic;
begin
  S_n <= S nand C;
  R_n <= R nand C;
  Q   <= S_n nand Q_n;
  Q_n <= R_n nand Q;        -- retroazione: Q e Q_n si pilotano a vicenda
end dataflow;

La retroazione è nel codice: le due uscite compaiono anche a destra delle assegnazioni. Leggere una porta di modo out è consentito da VHDL-2008; nelle versioni precedenti si introducono dei segnali interni che poi si assegnano alle uscite.

Behavioral, con un case sulla coppia SRSR (condizione C=1C=1 come abilitazione, nessun else):

vhdl
architecture behavioral of SRlatch is
  signal SR : std_logic_vector(1 downto 0);
begin
  SR <= S & R;
  process (SR, C)
  begin
    if C = '1' then
      case SR is
        when "00"   => null;                       -- memoria: nessuna assegnazione
        when "01"   => Q <= '0'; Q_n <= '1';       -- reset
        when "10"   => Q <= '1'; Q_n <= '0';       -- set
        when "11"   => Q <= '1'; Q_n <= '1';       -- proibito
        when others => Q <= 'X'; Q_n <= 'X';
      end case;
    end if;                                         -- C = '0': nessuna assegnazione, memoria
  end process;
end behavioral;

Lo null e l'if senza else fanno non assegnare le uscite: restano al valore precedente, cioè il latch conserva lo stato.

Latch D

vhdl
entity Dlatch is
  port ( D, C : in  std_logic;
         Q, Q_n : out std_logic );
end Dlatch;

architecture arch of Dlatch is
begin
  process (D, C)
  begin
    if C = '1' then          -- nessun else: per C = '0' le uscite mantengono il valore
      Q   <= D;
      Q_n <= not D;
    end if;
  end process;
end arch;

La lista di sensibilità contiene sia DD sia CC: con C=1C=1 ogni cambio di DD riattiva il process e si propaga all'uscita (trasparenza).

Flip-flop D positive-edge-triggered

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity dff is
  port ( CLK, D : in  std_logic;
         Q      : out std_logic );
end dff;

architecture simple of dff is
begin
  process (CLK)
  begin
    if CLK'event and CLK = '1' then    -- fronte di salita
      Q <= D;
    end if;
  end process;
end simple;

CLK'event è vero quando CLK ha appena cambiato valore; CLK'event and CLK = '1' identifica il fronte di salita (con '0' si avrebbe un flip-flop negative-edge-triggered). In VHDL moderno si scrive spesso rising_edge(CLK) (equivalente a meno dei passaggi da valori non definiti). Il process è sensibile solo a CLK: DD non compare nella lista, perché un cambio di DD da solo non deve fare nulla.

Reset asincrono e reset sincrono

Il reset porta il flip-flop a 0 e serve per avere uno stato iniziale noto (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 →).

Reset asincrono (agisce subito, in qualunque istante, anche senza fronte di clock). RST è nella lista di sensibilità ed è testato per primo:

vhdl
architecture async_reset of dff is
begin
  process (RST, CLK)
  begin
    if RST = '1' then                 -- ha priorità sul clock
      Q <= '0';
    elsif CLK'event and CLK = '1' then
      Q <= D;
    end if;
  end process;
end async_reset;

(con RST aggiunto alla entity: port (CLK, RST, D : in std_logic; Q : out std_logic)).

Reset sincrono (sincronizzato con il clock: ha effetto solo sul fronte attivo; richiede un fronte di clock per essere efficace). La lista contiene solo CLK e RST è testato dentro il ramo del fronte:

vhdl
architecture sync_reset of dff is
begin
  process (CLK)
  begin
    if CLK'event and CLK = '1' then
      if RST = '1' then
        Q <= '0';
      else
        Q <= D;
      end if;
    end if;
  end process;
end sync_reset;

Come riconoscerli leggendo il codice (quiz frequente):

codice circuito
process(CLK) + if (CLK'event and CLK='1') + dentro if (RST='1') FF positive-edge, reset sincrono
process(RST, CLK) + if RST='1' ... elsif (CLK'event and CLK='1') FF positive-edge, reset asincrono
CLK'event and CLK='0' negative-edge
RST = '0' per resettare reset attivo basso
nessun RST, solo if C='1' then Q<=D; latch D

Un caso da leggere con attenzione: process(CLK) ... if (CLK'event and CLK='0') then if (RST='1') then Q<='0'; else Q<=D; è un FF negative-edge con reset sincrono attivo alto (non basso: RST='1' resetta).

Load enable

Per un flip-flop che aggiorna lo stato solo quando richiesto si aggiunge una condizione senza else:

vhdl
if CLK'event and CLK = '1' then
  if load = '1' then Q <= D; end if;      -- se load = '0' Q conserva il valore
end if;

È la forma "a load enable" del registro, preferibile alla gestione del clock (Registri e microoperazioniUn registro a $n$ bit è formato da $n$ flip-flop (più porte) con clock comune; il caricamento si controlla con clock gating (OR con il clock: risparmia potenza ma introduce ritardi e clock skew) oppure, meglio, con load enable (MUX + D FF: $Q\leftarrow D$ se EN=1, $Q\leftarrow Q$ altrimenti). Un sistema digitale complesso si divide in datapath (registri e blocchi aritmetico-logici) e unità di controllo (FSM che invia i segnali di controllo e riceve i segnali di stato). Le microoperazioni, scritte in RTL (es. $K_1:R_2\leftarrow R_1$), sono di trasferimento, aritmetiche, logiche (con maschere: AND azzera, OR pone a 1, XOR complementa) e di scorrimento.Registri e microoperazioni →).

Testbench di un circuito sincrono

Si simula applicando il clock e ingressi opportunamente sfasati. Regole (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 →): cambiare gli ingressi lontano dal fronte attivo (per esempio sul fronte di discesa nel caso PET) e leggere le uscite quando sono stabili. Si usano due process in parallelo:

  1. il generatore del clock (non si ferma mai: ricomincia da capo quando finisce);
  2. il process che applica gli ingressi (incluso il reset), che alla fine termina la simulazione con std.env.stop; (VHDL-2008) o con un semplice wait;.
vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity test_dff is
end test_dff;

architecture test of test_dff is
  signal clk, rst, input, output : std_logic;
begin
  DUT : entity work.dff(async_reset) port map (CLK => clk, RST => rst, D => input, Q => output);

  generate_clock : process
  begin
    clk <= '1';  wait for 5 ns;      -- semiperiodo alto
    clk <= '0';  wait for 5 ns;      -- semiperiodo basso: periodo 10 ns
  end process;

  apply_inputs : process
  begin
    rst <= '0';  input <= '0';
    wait for 15 ns;
    input <= '1';
    wait for 10 ns;
    rst <= '1';
    wait for 20 ns;
    rst <= '0';
    wait for 10 ns;
    input <= '0';
    wait for 10 ns;
    input <= '1';
    std.env.stop;
  end process;
end test;

Fronti di salita del clock a 0,10,20,30,…0,10,20,30,\dots ns. Con il reset asincrono l'uscita QQ evolve così:

istante (ns) 0 20 25 50 60
evento fronte, D=0D=0 fronte, D=1D=1 RST→1RST\to1 fronte, D=1D=1 fronte, D=0D=0
QQ dopo l'evento 0 1 0 (subito, senza fronte) 1 0

(Tra 3030 e 4040 ns i fronti trovano RST=1RST=1 e QQ resta a 0.) Con il reset sincrono e gli stessi stimoli, ma con RST=1RST=1 da 2525 a 3535 ns: Q=1Q=1 a partire da 2020 ns; a 2525 ns non succede niente (RSTRST è salito ma non c'è fronte); al fronte di 3030 ns Q→0Q\to0; al fronte di 4040 ns (RST=0RST=0, D=1D=1) Q→1Q\to1. Differenza visibile: l'asincrono azzera a 2525 ns, il sincrono a 3030 ns.

Errori comuni

  • RST fuori dalla lista di sensibilità in un reset asincrono (non reagisce al reset da solo).
  • Reset asincrono scritto dentro il ramo del clock: diventa sincrono.
  • process (CLK, D) per un flip-flop: se non si usa il fronte è un latch.
  • if ... then senza else in un process combinatorio: memoria involontaria.
  • Cambiare gli ingressi del testbench sullo stesso istante del fronte di salita (violazioni di setup/hold).

Versione ripasso

Esercizi su questo argomento

Teoria collegata