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:

Comportamento DFF vs. latch

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 semplice if clock'event and clock = '1' then . La funzione rising_edge standard, 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_edge e falling_edge per 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 in ieee.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:

  • clock modificato (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 è:

  • clock o reset o 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.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow