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 attivi alti e controllo ):
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 (condizione come abilitazione, nessun else):
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
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 sia : con ogni cambio di riattiva il process e si propaga all'uscita (trasparenza).
Flip-flop D positive-edge-triggered
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: non compare nella lista, perché un cambio di da solo non deve fare nulla.
Reset asincrono e reset sincrono
Reset asincrono (agisce subito, in qualunque istante, anche senza fronte di clock). RST è nella lista di sensibilità ed è testato per primo:
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:
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:
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:
- il generatore del clock (non si ferma mai: ricomincia da capo quando finisce);
- il process che applica gli ingressi (incluso il reset), che alla fine termina la simulazione con
std.env.stop;(VHDL-2008) o con un semplicewait;.
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 ns. Con il reset asincrono l'uscita evolve così:
| istante (ns) | 0 | 20 | 25 | 50 | 60 |
|---|---|---|---|---|---|
| evento | fronte, | fronte, | fronte, | fronte, | |
| dopo l'evento | 0 | 1 | 0 (subito, senza fronte) | 1 | 0 |
(Tra e ns i fronti trovano e resta a 0.) Con il reset sincrono e gli stessi stimoli, ma con da a ns: a partire da ns; a ns non succede niente ( è salito ma non c'è fronte); al fronte di ns ; al fronte di ns (, ) . Differenza visibile: l'asincrono azzera a ns, il sincrono a ns.
Errori comuni
RSTfuori 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 ... thensenzaelsein un process combinatorio: memoria involontaria.- Cambiare gli ingressi del testbench sullo stesso istante del fronte di salita (violazioni di setup/hold).
Versione ripasso
- Memoria in VHDL: un segnale non assegnato in tutti i rami mantiene il valore. Latch D:
process(D,C) if C='1' then Q<=D;(trasparente per ). Latch SR:case SRconnullper ; dataflow con NAND. - FF D PET:
process(CLK) if CLK'event and CLK='1' then Q<=D;(orising_edge);'0'negative-edge. - Reset asincrono:
process(RST,CLK) if RST='1' then Q<='0'; elsif CLK'event and CLK='1' then Q<=D;. Sincrono:process(CLK),RSTdentro il ramo del fronte. - Riconoscimento:
RSTin lista asincrono; soloCLKeRSTdentro sincrono;CLK='0'NET;if load='1'senzaelseload enable. - Testbench sincrono: process del clock ( ns alto + ns basso) + process degli ingressi (lontani dal fronte),
std.env.stop. Esempio: async azzera a ns, sincrono al fronte di ns (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 →). - Errori:
RSTnon in lista; reset asincrono dentro il clock; ingressi sul fronte.
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 23 · quiz su VHDL, assegnazioni, process e flip-flop (temi d'esame 2022-2026)
- Esercizio 25 · trovare gli errori in una descrizione VHDL di una macchina a stati (esercizio sul modello del tema d'esame giugno 2026)