VHDL: la simulación del flip flop D sale mal

Estoy tratando de simular un flip-flop D usando el código VHDL que compilo y ejecuto usando GHDL y luego trazo la forma de onda usando GTKwave.

El problema es que mi maestro me dijo que, al usar flip-flops D, si el reloj y la señal de datos aumentan al mismo tiempo, el estado del flip-flop no se actualiza hasta el siguiente flanco ascendente del reloj. Pero cuando simulo ese comportamiento en un banco de pruebas, obtengo esto:

ingrese la descripción de la imagen aquí

Lo que parece funcionar perfectamente, excepto por el aumento de la última señal D, donde Q debería actualizarse a ALTO después de 10 nanosegundos. No sé dónde está el problema, y ​​puede deberse a una mala codificación, así que le doy mi código si puede ayudar a resolver el problema.

Módulo biestable D:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity d_flip_flop is
    port (
        clk:    in  STD_LOGIC;
        d:      in  STD_LOGIC;
        reset:  in  STD_LOGIC;
        q:      out STD_LOGIC
    );
end entity;

architecture asynchronous of d_flip_flop is
begin
    process (clk, reset) begin
        if reset = '1' then
            q <= '0';
        elsif clk'event and clk = '1' then
            q <= d;
        end if;
    end process;
end architecture;

Banco de pruebas de chanclas D:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity d_flip_flop_tb is
end entity;

architecture testbench of d_flip_flop_tb is
    component d_flip_flop
        port (
            clk:    in  STD_LOGIC;
            d:      in  STD_LOGIC;
            reset:  in  STD_LOGIC;
            q:      out STD_LOGIC
        );
    end component;

    signal clk, d, reset, q: STD_LOGIC;
begin
    uut: d_flip_flop port map (clk, d, reset, q);

    process begin
        clk <= '0'; wait for 5 ns;
        clk <= '1'; wait for 5 ns;
    end process;

    process begin
        reset <= '1'; d <= '1'; wait for 12500 ps;
        reset <= '0';           wait for 10 ns;
        d <= '0';               wait for 12500 ps;
        d <= '1';               wait for 20 ns;
        assert false report "End of simulation" severity failure;
        wait;
    end process;
end architecture;
¿Qué sucede exactamente, eso es EXACTAMENTE, a 35 nS? ¿El clk y D suben al mismo tiempo? ¿5ns+5nS+5nS... es igual al mismo tiempo que 12500pS+10nS+12500pS? ¿O hay errores de redondeo cuando el simulador los convierte en dobles IEE754 internamente y los agrega? Entonces pregunta, ¿la d de hecho sube primero, en una pequeña fracción? En la vida real, el reloj y los datos que cambian al mismo tiempo no están definidos, podrían ser 0, podrían ser 1, podrían ser metaestables.
Tu maestro está simplificando demasiado y, de todos modos, nada sucede realmente simultáneamente en un simulador. En realidad, este es un comportamiento del que debe mantenerse alejado en sus diseños. En general, una cadena de flip-flops controlados por un reloj común se comportará como un registro de desplazamiento tanto en la vida real como en la simulación.
Aprenda el modelo de ciclo delta de VHDL y verá lo que está mal.

Respuestas (4)

El problema es que mi maestro me dijo que, al usar flip-flops D, si el reloj y la señal de datos aumentan al mismo tiempo, el estado del flip-flop no se actualiza hasta el siguiente flanco ascendente del reloj.

Esta es una descripción muy idealizada, y ni siquiera muy útil.

Un modelo mucho mejor para el comportamiento, que sigue siendo bastante simple, es que

Si la entrada es estable durante el borde del reloj, durante un "tiempo de configuración" antes y un "tiempo de espera" después, ese mismo nivel estable emergerá de la salida después de un "tiempo de retraso".

Y no se ofrecen garantías si, como en su simulación, la entrada está cambiando dentro de la ventana de configuración y espera.

En los circuitos reales, la distribución del reloj está diseñada para ser más rápida que la distribución de la señal, de modo que los cambios se produzcan después del flanco del reloj. Y el requisito de retención en la lógica moderna es casi cero. En tales casos las cosas funcionan.

Pero si los retrasos en la lógica que produce la entrada del flip-flop suman casi un ciclo de reloj completo, puede tener problemas con las violaciones del tiempo de configuración.

Y si está haciendo su propio diseño de PCB y no tiene cuidado de hacer que el reloj sea el trazo más corto, entonces las señales sincronizadas con el reloj en una parte del circuito pueden superarlo y verse en transición en otra parte antes del borde del reloj, que también viola el requisito de configuración y retención.

El problema está en cómo conduces den tu banco de pruebas.

Aunque en hardware, la lógica se ejecutaría simultáneamente, el simulador tiene que ejecutar una de las asignaciones antes que la otra como un paso de tiempo delta. Dado que el proceso en su banco de pruebas no es sensible a clk, la simulación tiene problemas para decidir si clk<='1'sucede d<='1'primero.

Mi solución preferida sería cronometrar el proceso en el banco de pruebas en lugar de confiar en wait fordeclaraciones, pero si está buscando una solución de una línea, agregue wait until clk'event and clk='1';entre d<='0'línea y d<='1'línea. Esto permitirá que el simulador sepa que el evento del reloj viene antes de la transición d<='1'.

Para esta simulación, asigna d a HIGH al mismo tiempo que sube el reloj.

La simulación toma ese valor y se lo asigna a d. Al mismo tiempo, entra en su camino elseif porque el reloj está alto y le asigna el valor de D.

... y puede deberse a una mala codificación, así que le doy mi código si puede ayudar a resolver el problema.

Sí, es una mala codificación, una mala codificación del banco de pruebas.

Está tratando de configurar los bordes para que sean simultáneos, lo cual es una mala idea de todos modos. En la vida real, los bordes que son simultáneos (dentro de la definición de tiempos de preparación y espera) son peligrosos. Podrían llegar en cualquier orden, o podrían hacer que la salida sea metaestable, lo que es incluso peor que no saber si se supone que la salida es 0 o 1.

Entonces, aparte de la conveniencia de producir cambios simultáneos, la forma en que lo ha hecho no es la forma de hacerlo. Tiene dos procesos diferentes, uno esperando múltiplos de 5 nS, el otro esperando 12,5 nS, luego 10 nS, luego 12,5 nS, con la esperanza de que se alineen en 35 nS.

Una forma bien conocida de equivocarse en la computación es asumir que los números de coma flotante son exactos. Por ejemplo, 1.0 + 0.1 - 1.1 no es 0.0, no en los dobles IEE754 de todos modos. Es probable que sus dos formas diferentes de llegar a 35nS sean diferentes, al menos en el nivel de pocos LSB.

Si aún desea probar cambios simultáneos, consulte la documentación de su simulador VDHL para ver si los genera en el mismo proceso al mismo tiempo, los implementará simultáneamente o si aún se ordenarán.