Search code examples
vhdlsynthesis

Vivado: Mismatch between behavioral simulation and post-synthesis functional simulation


I have a strange problem in Vivado. The goal is to initialize spi for an adc with the Xilinx Artix-100T FPGA in VHDL. But, there is a mismatch between the behavioral simulation and post-synthesis functional simulation in Vivado 2021.1.

In the behavioral simulation, the signal reset_n is 0 for one clock cycle and then rises to 1 (as it should). But, in the post-synthesis functional simulation, it is always 0. Is there any explanation for this? I also tried synthesis attributes like KEEP, DONT_TOUCH, but with no luck.

I reduced the whole logic to a few lines of code to show the part where this happens.

The Main file:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity Main is

    port(
        clock   : IN     STD_LOGIC;                      --system clock;
        res : out std_logic := '0';
        reset_done : out std_logic := '0');

    signal init_done :boolean := false;
    --    signal res : std_logic := '0';

end Main;

architecture Behavioral of Main is

begin

    test: process is
    begin
        if (reset_done = '0') then
            res <= '0';
            wait until rising_edge(clock);
            res <= '1';
            reset_done <= '1';
        else
            wait until rising_edge(clock);
        end if;
    end process test;

end Behavioral;

The test bench file:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity Main_tb is
end Main_tb;

architecture Behavioral of Main_tb is

component Main is

port(
    clock   : IN     STD_LOGIC;                             
    res : out std_logic := '0';
    reset_done : out std_logic := '0');                            
end component;

--signals
signal clock : std_logic := '1';
signal res :std_logic := '0';
signal reset_done : std_logic := '0';

begin

    simulation: Main
        port map (clock, res, reset_done);
        
    --100 MHz clock
    clk_stimulus: process
    begin
        wait for 5 ns;
        clock <= not clock;
    end process clk_stimulus;

end Behavioral;

Behavioral simulation: sim

Post-synthesis functional simulation: post-sim

New working code:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity Main is

    port(
        clock   : IN     STD_LOGIC;     --system clock;
        res : out std_logic := '0';     --init signal
        reset_done : out std_logic := '0');     --init signal
end Main;

architecture Behavioral of Main is

begin

    test: process(clock) is 
    begin
        if (rising_edge(clock)) then -- preferred syntax
            res <= '1';
            reset_done <= '1';
        end if;
    end process test;

end Behavioral;

Solution

  • A mismatch means that the synthesizer could not infer the correct logic form your VHDL description: the synthesis doesn't understand the entirety of VHDL. You have to program it in a specific way, as described in the HDL coding guidelines.

    That's the whole reason we do post-synthesis simulation: to verify that the synthesizer understood our code.

    Due to signal initialization, power-on-reset is rarely needed in good designs.

    Anyhow, if you strip your code down to the core, it says:

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    
    entity Main is
        port(
            clock : in std_logic;
            res : out std_logic;
            reset_done : out std_logic);
    end Main;
    
    architecture Behavioral of Main is
        signal i_res : std_logic := '0'; -- initialize
        signal i_reset_done : std_logic := '0';
    begin
        test: process(clk) is 
        begin
            if (rising_edge(clk)) then -- preferred syntax
                i_res <= i_reset_done;
                i_reset_done <= '1'; -- set once.
            end if;
        end process test;
        res <= i_res;
        reset_done <= i_reset_done;
    end Behavioral;
    

    I don't get why reset_done has to be asserted one clock before res, but anyhow.

    You could also infer a shift-register to realize a multi-clock cycle reset.