vhdl
D-flip-flop (DFF) e fermi
Ricerca…
Osservazioni
D-Flip-Flops (DFF) e latch sono elementi di memoria. Un DFF campiona il suo input su uno o sull'altro bordo del suo clock (non su entrambi) mentre un latch è trasparente su un livello della sua abilitazione e memorizza sull'altro. La seguente figura illustra la differenza:
La modellazione di DFF o latch in VHDL è semplice, ma ci sono alcuni aspetti importanti che devono essere presi in considerazione:
Le differenze tra i modelli VHDL di DFF e latch.
Come descrivere i bordi di un segnale.
Come descrivere set o reset sincroni o asincroni.
D-flip-flop (DFF)
In tutti gli esempi:
-
clkè l'orologio, -
dè l'input, -
qè l'output, -
srstè un reset high sincrono attivo, -
srstnè un reset sincrono basso attivo, -
arstè un'alta reset asincrono attivo, -
arstnè un reset asincrono basso attivo, -
ssetè un set high sincrono attivo, -
ssetnè un set basso sincrono attivo, -
asetè un set asincrono attivo alto, -
asetnè un set asincrono basso attivo
Tutti i segnali sono di tipo ieee.std_logic_1164.std_ulogic . La sintassi utilizzata è quella che porta a risultati di sintesi corretti con tutti i sintetizzatori logici. Si prega di consultare l'esempio di rilevamento del bordo dell'orologio per una discussione sulla sintassi alternativa.
Orologio a bordo in aumento
process(clk)
begin
if rising_edge(clk) then
q <= d;
end if;
end process;
Orologio a caduta
process(clk)
begin
if falling_edge(clk) then
q <= d;
end if;
end process;
Orologio con fronte di salita, reset alto sincrono attivo
process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Orologio con fronte di salita, reset alto attivo asincrono
process(clk, arst)
begin
if arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Orologio con fronte di discesa, reset basso attivo asincrono, set attivo sincrono alto
process(clk, arstn)
begin
if arstn = '0' then
q <= '0';
elsif falling_edge(clk) then
if sset = '1' then
q <= '1';
else
q <= d;
end if;
end if;
end process;
Orologio con fronte di salita, reset alto attivo asincrono, set basso attivo asincrono
Nota: il set ha una priorità più alta del reset
process(clk, arst, asetn)
begin
if asetn = '0' then
q <= '1';
elsif arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Chiusure
In tutti gli esempi:
-
enè il segnale di abilitazione, -
dè l'input, -
qè l'output, -
srstè un reset high sincrono attivo, -
srstnè un reset sincrono basso attivo, -
arstè un'alta reset asincrono attivo, -
arstnè un reset asincrono basso attivo, -
ssetè un set high sincrono attivo, -
ssetnè un set basso sincrono attivo, -
asetè un set asincrono attivo alto, -
asetnè un set asincrono basso attivo
Tutti i segnali sono di tipo ieee.std_logic_1164.std_ulogic . La sintassi utilizzata è quella che porta a risultati di sintesi corretti con tutti i sintetizzatori logici. Si prega di consultare l'esempio di rilevamento del bordo dell'orologio per una discussione sulla sintassi alternativa.
Attiva alta abilita
process(en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
Attiva basso attivo
process(en, d)
begin
if en = '0' then
q <= d;
end if;
end process;
Abilitazione alta attiva, reset alto attivo sincrono
process(en, d)
begin
if en = '1' then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Attiva alta attiva, reset alto attivo asincrono
process(en, d, arst)
begin
if arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Attiva basso attivo, reset basso attivo asincrono, set attivo sincrono alto
process(en, d, arstn)
begin
if arstn = '0' then
q <= '0';
elsif en = '0' then
if sset = '1' then
q <= '1';
else
q <= d;
end if;
end if;
end process;
Abilitazione alta attiva, reset alto attivo asincrono, set basso attivo asincrono
Nota: il set ha una priorità più alta del reset
process(en, d, arst, asetn)
begin
if asetn = '0' then
q <= '1';
elsif arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Rilevamento del bordo dell'orologio
Il racconto
Con VHDL 2008 e se il tipo di clock è bit , boolean , ieee.std_logic_1164.std_ulogic o ieee.std_logic_1164.std_logic , è possibile codificare un rilevamento del fronte di clock per il fronte di salita
-
if rising_edge(clock) then -
if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic -
if clock'event and clock then -- type boolean
e per la caduta
-
if falling_edge(clock) then -
if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic -
if clock'event and not clock then -- type boolean
Questo si comporterà come previsto, sia per la simulazione che per la sintesi.
Nota: la definizione di un fronte di salita su un segnale di tipo
std_ulogicè un po 'più complessa della sempliceif clock'event and clock = '1' then. La funzionerising_edgestandard, ad esempio, ha una definizione diversa. Anche se probabilmente non farà alcuna differenza per la sintesi, potrebbe farne uno per la simulazione.
L'uso delle funzioni standard rising_edge e falling_edge è fortemente incoraggiato. Con le versioni precedenti di VHDL l'uso di queste funzioni potrebbe richiedere di dichiarare esplicitamente l'uso di pacchetti standard (ad es. ieee.numeric_bit per il bit tipo) o persino di definirli in un pacchetto personalizzato.
Nota: non utilizzare le funzioni standard
rising_edgeefalling_edgeper rilevare i bordi dei segnali senza orologio. Alcuni sintetizzatori potrebbero concludere che il segnale è un orologio. Suggerimento: il rilevamento di un fronte su un segnale senza orologio può essere spesso effettuato campionando il segnale in un registro a scorrimento e confrontando i valori campionati in diverse fasi del registro a scorrimento.
La lunga storia
Descrivere correttamente il rilevamento dei bordi di un segnale di clock è essenziale quando si modella D-Flip-Flops (DFF). Un bordo è, per definizione, una transizione da un particolare valore a un altro. Ad esempio, possiamo definire il fronte di salita di un segnale di tipo bit (il tipo enumerato VHDL standard che prende due valori: '0' e '1' ) come transizione da '0' a '1' . Per tipo boolean possiamo definirlo come una transizione da false a true .
Spesso vengono utilizzati tipi più complessi. Il tipo ieee.std_logic_1164.std_ulogic , ad esempio, è anche un tipo enumerato, proprio come bit o boolean , ma ha 9 valori anziché 2:
| Valore | Senso |
|---|---|
'U' | non inizializzata |
'X' | Forzare sconosciuto |
'0' | Forzando basso livello |
'1' | Forzare alto livello |
'Z' | Alta impedenza |
'W' | Debole sconosciuto |
'L' | Basso livello debole |
'H' | Alto livello debole |
'-' | Non importa |
Definire un fronte di salita su un tipo di questo tipo è un po 'più complesso rispetto a bit o boolean . Ad esempio, possiamo decidere che è una transizione da '0' a '1' . Ma possiamo anche decidere che si tratta di una transizione da '0' o 'L' a '1' o 'H' .
Nota: è questa seconda definizione che lo standard usa per la funzione
rising_edge(signal s: std_ulogic)definita inieee.std_logic_1164.
Quando si discutono i vari modi per rilevare i bordi, è quindi importante considerare il tipo di segnale. È anche importante prendere in considerazione l'obiettivo della modellizzazione: solo simulazione o sintesi logica? Cerchiamo di illustrare questo su alcuni esempi:
DFF con fronte di salita con bit di tipo
signal clock, d, q: bit;
...
P1: process(clock)
begin
if clock = '1' then
q <= d;
end if;
end process P1;
Tecnicamente, su un punto di vista della semantica di pura simulazione, il processo P1 modella un DFF attivato dal fronte di salita. In effetti, l'assegnazione q <= d viene eseguita se e solo se:
-
clockmodificato (questo è ciò che esprime la lista di sensibilità) e - il valore corrente
clockè'1'.
Poiché l' clock è di tipo bit e tipo bit ha solo valori '0' e '1' , questo è esattamente ciò che abbiamo definito come un fronte di salita di un segnale di tipo bit. Qualsiasi simulatore gestirà questo modello come ci aspettiamo.
Nota: per i sintetizzatori logici, le cose sono un po 'più complesse, come vedremo in seguito.
DFF con fronte di salita con reset alto attivo asincrono e bit di tipo
Per aggiungere un reset alto attivo asincrono al nostro DFF, si potrebbe provare qualcosa come:
signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif clock = '1' then
q <= d;
end if;
end process P2_BOGUS;
Ma questo non funziona . La condizione per l'assegnazione q <= d da eseguire dovrebbe essere: un fronte di salita clock mentre reset = '0' . Ma ciò che abbiamo modellato è:
-
clockoreseto entrambi cambiati e -
reset = '0'e -
clock = '1'
Il che non è la stessa: se reset cambia da '1' a '0' , mentre clock = '1' l'assegnazione verranno eseguiti anche se non è un fronte di salita di clock .
In realtà, non c'è modo di modellarlo in VHDL senza l'aiuto di un attributo di segnale:
P2_OK: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif clock = '1' and clock'event then
q <= d;
end if;
end process P2_OK;
Il clock'event è l' event attributo del segnale applicato al clock segnale. Valuta come boolean ed è true se e solo se il clock segnale clock cambiato durante la fase di aggiornamento del segnale che ha appena preceduto la fase di esecuzione corrente. Grazie a questo, il processo P2_OK ora modella perfettamente ciò che vogliamo nella simulazione (e nella sintesi).
Semantica di sintesi
Molti sintetizzatori logici identificano i rilevamenti del bordo del segnale basati su modelli sintattici, non sulla semantica del modello VHDL. In altre parole, considerano come si presenta il codice VHDL e non come si comporta. Uno dei modelli che tutti riconoscono è:
if clock = '1' and clock'event then
Quindi, anche nell'esempio del processo P1 dovremmo usarlo se vogliamo che il nostro modello sia sintetizzabile da tutti i sintetizzatori logici:
signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
if clock = '1' and clock'event then
q <= d;
end if;
end process P1_OK;
La parte relativa alla condizione di and clock'event è completamente ridondante con la lista di sensibilità ma come alcuni sintetizzatori ne hanno bisogno ...
DFF con fronte di salita con reset alto attivo asincrono e tipo std_ulogic
In questo caso, esprimere il fronte di salita dell'orologio e la condizione di reset può diventare complicato. Se manteniamo la definizione di un fronte di salita che abbiamo proposto sopra e se consideriamo che il reset è attivo se è '1' o 'H' , il modello diventa:
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
if reset = '1' or reset = 'H' then
q <= '0';
elsif clock'event and
(clock'last_value = '0' or clock'last_value = 'L') and
(clock = '1' or clock = 'H') then
q <= d;
end if;
end process P4;
Nota:
'last_valueè un altro attributo del segnale che restituisce il valore che il segnale aveva prima dell'ultima modifica del valore.
Funzioni di supporto
Lo standard VHDL 2008 offre diverse funzioni di supporto per semplificare il rilevamento dei fronti del segnale, in particolare con tipi enumerati multivalore come std_ulogic . Il pacchetto std.standard definisce le funzioni rising_edge e falling_edge sui tipi bit e boolean e il pacchetto ieee.std_logic_1164 li definisce sui tipi std_ulogic e std_logic .
Nota: con le versioni precedenti di VHDL l'uso di queste funzioni potrebbe richiedere di dichiarare esplicitamente l'uso di pacchetti standard (ad esempio ieee.numeric_bit per il bit di tipo) o persino di definirli in un pacchetto utente.
Cerchiamo di rivisitare gli esempi precedenti e utilizzare le funzioni di supporto:
signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
if rising_edge(clock) then
q <= d;
end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clock) then
q <= d;
end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
if reset = '1' then
q <= '0';
elsif rising_edge(clock) then
q <= d;
end if;
end process P4_NEW;
Nota: in questo ultimo esempio abbiamo anche semplificato il test sul reset. I ripristini flottanti ad alta impedenza sono piuttosto rari e, nella maggior parte dei casi, questa versione semplificata funziona per la simulazione e la sintesi.
