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:

DFF vs. comportamiento de pestillos

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:

  • clk es el reloj,
  • d es la entrada,
  • q es la salida,
  • srst es un reinicio alto síncrono activo,
  • srstn es un reinicio bajo sincronizado activo,
  • arst es un alto reinicio asíncrono activo,
  • arstn es un restablecimiento asíncrono bajo activo,
  • sset es un conjunto alto síncrono activo,
  • ssetn es un conjunto sincrónico bajo activo,
  • aset es un conjunto alto asíncrono activo,
  • asetn es 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:

  • en está como señal de activación,
  • d es la entrada,
  • q es la salida,
  • srst es un reinicio alto síncrono activo,
  • srstn es un reinicio bajo sincronizado activo,
  • arst es un alto reinicio asíncrono activo,
  • arstn es un restablecimiento asíncrono bajo activo,
  • sset es un conjunto alto síncrono activo,
  • ssetn es un conjunto sincrónico bajo activo,
  • aset es un conjunto alto asíncrono activo,
  • asetn es 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_ulogic es un poco más compleja que la simple if clock'event and clock = '1' then . La función estándar rising_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_edge y falling_edge para 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 en ieee.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:

  • clock cambiado (esto es lo que expresa la lista de sensibilidad) y
  • El valor actual del clock es '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:

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



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow