vhdl
D-Flip-Flops (DFF) y cierres
Buscar..
Observaciones
Los D-Flip-Flops (DFF) y los pestillos son elementos de memoria. Un DFF muestra su entrada en uno u otro borde de su reloj (no en ambos) mientras que un pestillo es transparente en un nivel de su habilitación y memoriza en el otro. La siguiente figura ilustra la diferencia:
Modelar DFFs o pestillos en VHDL es fácil, pero hay algunos aspectos importantes que deben tenerse en cuenta:
Las diferencias entre los modelos VHDL de DFFs y latches.
Cómo describir los bordes de una señal.
Cómo describir conjuntos o reinicios síncronos o asíncronos.
D-Flip-Flops (DFF)
En todos los ejemplos:
-
clkes el reloj, -
des la entrada, -
qes la salida, -
srstes un reinicio alto síncrono activo, -
srstnes un reinicio bajo sincronizado activo, -
arstes un alto reinicio asíncrono activo, -
arstnes un restablecimiento asíncrono bajo activo, -
ssetes un conjunto alto síncrono activo, -
ssetnes un conjunto sincrónico bajo activo, -
asetes un conjunto alto asíncrono activo, -
asetnes un conjunto asíncrono bajo activo.
Todas las señales son de tipo ieee.std_logic_1164.std_ulogic . La sintaxis utilizada es la que lleva a corregir los resultados de síntesis con todos los sintetizadores lógicos. Consulte el ejemplo de detección del borde del reloj para ver una discusión sobre la sintaxis alternativa.
Reloj de vanguardia
process(clk)
begin
if rising_edge(clk) then
q <= d;
end if;
end process;
Reloj de borde descendente
process(clk)
begin
if falling_edge(clk) then
q <= d;
end if;
end process;
Reloj de flanco ascendente, reinicio alto activo síncrono
process(clk)
begin
if rising_edge(clk) then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Reloj de flanco ascendente, alto reinicio activo asíncrono
process(clk, arst)
begin
if arst = '1' then
q <= '0';
elsif rising_edge(clk) then
q <= d;
end if;
end process;
Falling edge clock, restablecimiento activo bajo asíncrono, ajuste alto activo síncrono
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;
Reloj de flanco ascendente, reinicio alto activo asíncrono, conjunto bajo activo asíncrono
Nota: el conjunto tiene mayor prioridad que el reinicio
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;
Pestillos
En todos los ejemplos:
-
enestá como señal de activación, -
des la entrada, -
qes la salida, -
srstes un reinicio alto síncrono activo, -
srstnes un reinicio bajo sincronizado activo, -
arstes un alto reinicio asíncrono activo, -
arstnes un restablecimiento asíncrono bajo activo, -
ssetes un conjunto alto síncrono activo, -
ssetnes un conjunto sincrónico bajo activo, -
asetes un conjunto alto asíncrono activo, -
asetnes un conjunto asíncrono bajo activo.
Todas las señales son de tipo ieee.std_logic_1164.std_ulogic . La sintaxis utilizada es la que lleva a corregir los resultados de síntesis con todos los sintetizadores lógicos. Consulte el ejemplo de detección del borde del reloj para ver una discusión sobre la sintaxis alternativa.
Alta habilitación activa
process(en, d)
begin
if en = '1' then
q <= d;
end if;
end process;
Activación baja activa
process(en, d)
begin
if en = '0' then
q <= d;
end if;
end process;
Activación alta activa, reinicio alto síncrono activo
process(en, d)
begin
if en = '1' then
if srst = '1' then
q <= '0';
else
q <= d;
end if;
end if;
end process;
Activación alta activa, reinicio alto asíncrono activo
process(en, d, arst)
begin
if arst = '1' then
q <= '0';
elsif en = '1' then
q <= d;
end if;
end process;
Activación baja activa, reinicio bajo asíncrono activo, ajuste alto activo síncrono
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;
Activación alta activa, reinicio alto activo asíncrono, conjunto bajo activo asíncrono
Nota: el conjunto tiene mayor prioridad que el reinicio
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;
Detección del borde del reloj
La historia corta
Con VHDL 2008 y si el tipo de reloj es bit , boolean , ieee.std_logic_1164.std_ulogic o ieee.std_logic_1164.std_logic , se puede codificar una detección de borde de reloj para borde ascendente
-
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
y para caer al filo
-
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
Esto se comportará como se espera, tanto para la simulación como para la síntesis.
Nota: la definición de un flanco ascendente en una señal de tipo
std_ulogices un poco más compleja que la simpleif clock'event and clock = '1' then. La función estándarrising_edge, por ejemplo, tiene una definición diferente. Incluso si probablemente no hará ninguna diferencia para la síntesis, podría hacer uno para la simulación.
Se recomienda rising_edge el uso de las funciones estándar rising_edge y falling_edge . Con versiones anteriores de VHDL, el uso de estas funciones puede requerir declarar explícitamente el uso de paquetes estándar (por ejemplo, ieee.numeric_bit para el tipo de bit ) o incluso definirlos en un paquete personalizado.
Nota: no utilice las funciones estándar
rising_edgeyfalling_edgepara detectar bordes de señales que no sean de reloj. Algunos sintetizadores podrían concluir que la señal es un reloj. Sugerencia: la detección de un borde en una señal que no es de reloj se puede hacer frecuentemente muestreando la señal en un registro de desplazamiento y comparando los valores muestreados en diferentes etapas del registro de desplazamiento.
La larga historia
La descripción correcta de la detección de los bordes de una señal de reloj es esencial al modelar D-Flip-Flops (DFF). Un borde es, por definición, una transición de un valor particular a otro. Por ejemplo, podemos definir el flanco ascendente de una señal de tipo bit (el tipo enumerado VHDL estándar que toma dos valores: '0' y '1' ) como la transición de '0' a '1' . Para el tipo boolean podemos definirlo como una transición de false a true .
Con frecuencia, se utilizan tipos más complejos. El tipo ieee.std_logic_1164.std_ulogic , por ejemplo, también es un tipo enumerado, como bit o boolean , pero tiene 9 valores en lugar de 2:
| Valor | Sentido |
|---|---|
'U' | Sin inicializar |
'X' | Forzando desconocido |
'0' | Forzando bajo nivel |
'1' | Forzando alto nivel |
'Z' | Alta impedancia |
'W' | Débil desconocido |
'L' | Débil bajo nivel |
'H' | Débil alto nivel |
'-' | No importa |
Definir un flanco ascendente en un tipo de este tipo es un poco más complejo que para bit o boolean . Podemos, por ejemplo, decidir que es una transición de '0' a '1' . Pero también podemos decidir que es una transición de '0' o 'L' a '1' o 'H' .
Nota: esta es la segunda definición que usa el estándar para la función
rising_edge(signal s: std_ulogic)definida enieee.std_logic_1164.
Cuando se analizan las diversas formas de detectar bordes, es importante considerar el tipo de señal. También es importante tener en cuenta el objetivo de modelado: ¿solo simulación o síntesis lógica? Vamos a ilustrar esto con algunos ejemplos:
Flanco DFF con bit de tipo
signal clock, d, q: bit;
...
P1: process(clock)
begin
if clock = '1' then
q <= d;
end if;
end process P1;
Técnicamente, en un punto de vista semántico de simulación puro, el proceso P1 modela un DFF de flanco ascendente. De hecho, la asignación q <= d se ejecuta si y solo si:
-
clockcambiado (esto es lo que expresa la lista de sensibilidad) y - El valor actual del
clockes'1'.
Como el clock es de tipo bit y tipo bit solo tiene valores '0' y '1' , esto es exactamente lo que definimos como un flanco ascendente de una señal de tipo bit. Cualquier simulador manejará este modelo como esperamos.
Nota: para los sintetizadores lógicos, las cosas son un poco más complejas, como veremos más adelante.
DFF de flanco ascendente con restablecimiento alto activo asíncrono y bit de tipo
Para agregar un restablecimiento alto activo asíncrono a nuestro DFF, se podría intentar algo como:
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;
Pero esto no funciona . La condición para que se ejecute la asignación q <= d debe ser: un flanco ascendente del clock mientras se reset = '0' . Pero lo que modelamos es:
-
clockoreseto ambos cambiados y -
reset = '0'y -
clock = '1'
Que no es lo mismo: si reset cambia de '1' a '0' , mientras que clock = '1' la asignación se ejecutarán si bien no es un flanco ascendente de clock .
De hecho, no hay forma de modelar esto en VHDL sin la ayuda de un atributo de señal:
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;
El clock'event es el event atributo de señal aplicado al clock señal. Se evalúa como un valor boolean y es true si y solo si el clock señal cambió durante la fase de actualización de la señal que precedió a la fase de ejecución actual. Gracias a esto, el proceso P2_OK ahora modela perfectamente lo que queremos en simulación (y síntesis).
Semántica de síntesis
Muchos sintetizadores lógicos identifican detecciones de borde de señal basadas en patrones sintácticos, no en la semántica del modelo VHDL. En otras palabras, consideran cómo se ve el código VHDL, no qué comportamiento modela. Uno de los patrones que todos reconocen es:
if clock = '1' and clock'event then
Entonces, incluso en el ejemplo del proceso P1 , deberíamos usarlo si queremos que nuestro sintetizador sea sintetizable por todos los sintetizadores lógicos:
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 de la condición de " and clock'event es completamente redundante con la lista de sensibilidad, pero como algunos sintetizadores lo necesitan ...
DFF de flanco ascendente con restablecimiento alto activo asíncrono y tipo std_ulogic
En este caso, la expresión del flanco ascendente del reloj y la condición de restablecimiento puede complicarse. Si mantenemos la definición de un flanco ascendente que propusimos anteriormente y si consideramos que el restablecimiento está activo si es '1' o 'H' , el modelo se convierte en:
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_valuees otro atributo de señal que devuelve el valor que tenía la señal antes del último cambio de valor.
Funciones de ayuda
El estándar VHDL 2008 ofrece varias funciones de ayuda para simplificar la detección de bordes de señal, especialmente con tipos enumerados de valores múltiples como std_ulogic . El paquete std.standard define las funciones rising_edge y falling_edge en los tipos bit y boolean y el paquete ieee.std_logic_1164 las define en los tipos std_ulogic y std_logic .
Nota: con versiones anteriores de VHDL, el uso de estas funciones puede requerir declarar explícitamente el uso de paquetes estándar (por ejemplo, ieee.numeric_bit para el tipo de bit) o incluso definirlos en un paquete de usuario.
Revisemos los ejemplos anteriores y usemos las funciones de ayuda:
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: en este último ejemplo también simplificamos la prueba en el reinicio. Los reinicios flotantes, de alta impedancia son bastante raros y, en la mayoría de los casos, esta versión simplificada funciona para simulación y síntesis.
