Error de simulación VHDL (¿Lo estoy perdiendo?)

2

Tengo una simulación que simplemente toma una dirección como entrada y 64 ciclos de reloj más tarde, simplemente la envía a otro puerto. Por alguna razón, cuando registro los datos de salida, no se retrasa por un ciclo de reloj (vea la forma de onda). ¿Es esto una parte loca del estándar o encontré un error en el paso delta de mi simulador?

Testbench:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bug_report_tb is
end bug_report_tb;


architecture TB of bug_report_tb is
-- MIG UI signal declarations
signal app_addr                 : std_logic_vector(29 downto 0);
signal app_en                   : std_logic;
signal app_rdy                  : std_logic;
signal app_rd_data              : std_logic_vector(29 downto 0);
signal app_rd_data_r        :   std_logic_vector(app_rd_data'RANGE);

signal ui_rst                   : std_logic;
signal ui_clk                   : std_logic;


begin


process(ui_rst,ui_clk)
begin
    if ui_rst = '1' then
        app_en <= '0';
        app_addr <= (others => '0');
    elsif rising_edge(ui_clk) then
        app_en <= '0';
        if app_rdy = '1' then
            app_en <= '1';
            if app_en = '1' then
                app_addr <= std_logic_vector(unsigned(app_addr)+1);
            end if;
        end if;
    end if;
end process;

process(ui_clk)
begin
    if rising_edge(ui_clk) then
        app_rd_data_r <= app_rd_data;
    end if;
end process;

--*********************************************************
module : entity work.bug_report_mod
    port map
    (
        ui_clk          => ui_clk,
        ui_rst          => ui_rst,

        app_rd_data     => app_rd_data,
        app_rdy         => app_rdy,
        app_en          => app_en,
        app_addr        => app_addr
    );

end TB;

Módulo:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity bug_report_mod is
    port
    (
        ui_clk          : out   std_logic;
        ui_rst          : out   std_logic;

        app_rd_data     : out   std_logic_vector(29 downto 0);
        app_rdy         : out   std_logic;
        app_en          : in    std_logic;
        app_addr        : in    std_logic_vector(29 downto 0)
    );
end bug_report_mod;


architecture behavioral of bug_report_mod is
signal clk                  :   std_logic;
signal reset                :   std_logic := '1';

signal app_en_sr        :   std_logic_vector(63 downto 0) := (others => '0');
signal dly_counter      :   unsigned(6 downto 0);
signal rdy_counter      :   unsigned(6 downto 0);
signal app_rdy_int      :   std_logic;

type int_array   is array(natural range <>) of integer;
signal addr_array       :   int_array(63 downto 0);

begin

process
begin
    clk <= '1'; wait for 2.5 ns;
    clk <= '0'; wait for 2.5 ns;
end process;
ui_clk <= clk;
ui_rst <= reset;

app_rdy <= app_rdy_int;

process
begin
wait for 50 ns;
wait until clk'event and clk = '1';
reset <= '0';
wait for 2 ms;
end process;


process(clk)
begin
    if rising_edge(clk) then
        if app_en_sr(63) = '1' then
            app_rd_data <= std_logic_vector(to_unsigned(addr_array(63),app_rd_data'LENGTH));
        end if;
    end if;
end process;

process(clk,reset)
begin
    if reset = '1' then
        app_rdy_int <= '0';
        rdy_counter <= (others => '0');
        dly_counter <= (others => '0');
    elsif rising_edge(clk) then
        app_en_sr <= app_en_sr(62 downto 0) & (app_en and app_rdy_int);
        addr_array <= addr_array(62 downto 0) & (to_integer(unsigned(app_addr))*4);
        rdy_counter <= ('0' & rdy_counter(5 downto 0)) + 1;
        app_rdy_int <= not rdy_counter(6) and dly_counter(3);
        if dly_counter(3) = '0' then
            dly_counter <= dly_counter + 1;
        end if;
    end if;
end process;

end behavioral;

    
pregunta ks0ze

2 respuestas

2

Has hecho algo muy extraño: ¡El DUT está generando su propio reloj!

Esto significa que cuando tanto el reloj como los datos se propaguen al banco de pruebas, los datos ya habrán cambiado antes de que se procese el borde del reloj, creando efectivamente el efecto de "cero demora" que estás viendo.

Si bien es cierto que el hardware real no se comportaría de esta manera, no me sorprende en absoluto que la mayoría, si no todos los simuladores, harían exactamente lo mismo con este código.

Intente generar el reloj (y el reinicio) en el banco de pruebas (el escenario habitual) y creo que verá el comportamiento esperado.

La alternativa sería agregar un retardo nominal a la asignación del bus de datos de salida dentro del módulo

app_rd_data <= std_logic_vector(to_unsigned(addr_array(63),app_rd_data'LENGTH));

para modelar correctamente esta interfaz.

    
respondido por el Dave Tweed
-2

La deficiencia fundamental en este código es que no tiene un modelo explícito para el retraso inherente entre los bordes del reloj y los datos de enclavamiento. Cada asignación no bloqueante Reg1 < = Reg0 debe incluir un retardo (retardo de apoyo típico en una puerta), algo como Reg1 < = # 0.5 Reg0; (o lo que sea en VHDL)

Cada declaración "<=" debe tener este retraso.

Sin este retraso, una simulación de comportamiento podría tener transiciones inesperadas y ridículas. Si intenta corregir el comportamiento basándose en estas simulaciones, el dispositivo sintetizado fallará.

Estos retrasos serán ignorados en la síntesis, verdaderos, pero serán reemplazados por retrasos reales después del lugar y la ruta. Sin embargo, cuando se ejecutan simulaciones de comportamiento sin demoras, los resultados suelen ser erróneos. La mayoría de los simuladores evalúan los nodos simultáneamente, y el retardo cero a veces puede causar un comportamiento impredecible, que generalmente se atribuye a los compiladores. Es un conocido dilema "# 1", y este artículo, "Verilog Asignaciones sin bloqueo con retardo, Mytys / amppios / Mypcs / Mypcs / Mypty / Mystertys / Mystic; a> aborda el problema.

EN RESUMEN , si cree que su simulador de comportamiento siempre resuelve correctamente las transferencias de registro simultáneas en la secuencia adecuada de causa-efecto, entonces sí, es un error en su simulador. Puede llevar semanas y semanas resolver esto con el proveedor del simulador. Alternativamente, puede "ayudar" al simulador insertando demoras nominales en su RTL, y olvidarse de cómo impulsa la lista de redes a través de los módulos, de arriba hacia abajo o de abajo hacia arriba, o cualquiera de los algoritmos no revelados de este simulador en particular. p>     

respondido por el Ale..chenski

Lea otras preguntas en las etiquetas