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;
Post-synthesis functional simulation:
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;
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.