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:
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.
Related
My code will not simulate an output when running the VWF file.
I have tried changing the code several different time and don't really understand what I'm doing wrong.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Counter_JM is
Port (
up_down : in std_logic;
LED : out std_logic;
Q : Buffer integer Range 0 to 7);
end Counter_JM;
architecture archi of Counter_JM is
Begin
-- up/down counter
process (up_down)
begin
if (Q=7) then
Q<=0;
end if;
if (up_down = '1') then
Q <= Q + 1;
else
Q<=0;
end if;
if (Q=0 or Q=1) then
LED <= '0';
else
LED <= '1';
end if;
end process;
end archi;
The LED output should show high for 4 cycles and low for 2 on the VWF file
I don't know why you use up_down. But as Oldfart said, you don't have a clock. I have simplified and modified your code (it works for me (in modelsim):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Counter_JM is
Port (
clk: in std_logic;
up_down : in std_logic;
LED : out std_logic
);
end Counter_JM;
architecture archi of Counter_JM is
Begin
process (clk)
variable Q: integer range 0 to 7;
begin
if rising_edge(clk) then
-- up/down counter
Q := Q + 1;
if Q=1 or Q=2 then
LED <= '0';
else
LED <= '1';
end if;
if Q = 7 then
Q := 0;
end if;
end if;
end process;
end archi;
and also created/generated a simple testbench here :
`-- Testbench automatically generated online
-- at http://vhdl.lapinoo.net
-- Generation date : 7.6.2019 11:22:53 GMT
library ieee;
use ieee.std_logic_1164.all;
entity tb_Counter_JM is
end tb_Counter_JM;
architecture tb of tb_Counter_JM is
component Counter_JM
port (clk : in std_logic;
up_down : in std_logic;
LED : out std_logic);
end component;
signal clk : std_logic;
signal up_down : std_logic;
signal LED : std_logic;
constant TbPeriod : time := 1000 ns; -- EDIT Put right period here
signal TbClock : std_logic := '0';
signal TbSimEnded : std_logic := '0';
begin
dut : Counter_JM
port map (clk => clk,
up_down => up_down,
LED => LED);
-- Clock generation
TbClock <= not TbClock after TbPeriod/2 when TbSimEnded /= '1' else '0';
-- EDIT: Check that clk is really your main clock signal
clk <= TbClock;
stimuli : process
begin
-- EDIT Adapt initialization as needed
up_down <= '0';
-- EDIT Add stimuli here
wait for 100 * TbPeriod;
-- Stop the clock and hence terminate the simulation
TbSimEnded <= '1';
wait;
end process;
end tb;
-- Configuration block below is required by some simulators. Usually no need to edit.
configuration cfg_tb_Counter_JM of tb_Counter_JM is
for tb
end for;
end cfg_tb_Counter_JM;`
I want to have two combinational processes driving one signal in wired-or style. Each process can drive 'Z' or '1' value to the signal and there is a global pull-down to 'L'.
Vivado 2017.1 synthesis 'optimizes' my code to drive a constant 0 to the output port. Why does this happen? How do I work around this issue?
Code:
library ieee;
use ieee.std_logic_1164.all;
entity test is
port(
input_0 : in std_logic;
input_1 : in std_logic;
output : out std_logic
);
end entity test;
architecture rtl of test is
signal s_output : std_logic;
begin
output <= to_X01(to_bit(s_output));
process(input_0)
begin
s_output <= 'Z';
if input_0='1' then
s_output <= '1';
end if;
end process;
process(input_1)
begin
s_output <= 'Z';
if input_1='1' then
s_output <= '1';
end if;
end process;
s_output <= 'L';
end architecture rtl;
Synthesis result:
WARNING: [Synth 8-3917] design test has port output driven by constant 0
I have written a simple entity in VHDL to blink an LED and am trying to simulate it in ModelSim but am getting no transitions on the output.
Here is my HDL file for the LED_Blink entity:
Library IEEE;
use IEEE.Std_logic_1164.all;
entity LED_Blink is
generic (
g_SYSTEM_CLOCK_PERIOD : in time := 10 ns; -- 100 MHz clock period
g_LED_ON_TIME : in time := 1 sec
);
port(
system_clock : in Std_logic;
reset_fpga_L : in Std_logic;
led_out : out Std_logic
);
end entity LED_Blink;
architecture RTL of LED_Blink is
signal led_state : Std_logic;
constant COUNTER_RELOAD_VAL : natural := g_LED_ON_TIME/g_SYSTEM_CLOCK_PERIOD;
begin
process(reset_fpga_L, system_clock)
variable counter : natural range 0 to COUNTER_RELOAD_VAL := COUNTER_RELOAD_VAL;
begin
if reset_fpga_L = '0' then
counter := COUNTER_RELOAD_VAL;
led_state <= '0';
elsif rising_edge(system_clock) then
if counter = 0 then
led_state <= not led_state;
counter := COUNTER_RELOAD_VAL;
else
counter := counter - 1;
end if;
end if;
led_out <= led_state;
end process;
end architecture RTL;
And here is my test-bench:
Library IEEE;
use IEEE.Std_logic_1164.all;
entity LED_Blink_TB is
end entity LED_Blink_TB;
architecture RTL of LED_Blink_TB is
signal reset_fpga_L : Std_logic := '0';
signal system_clock : Std_logic := '0';
signal led_out : Std_logic := '0';
begin
G1: entity work.LED_Blink(RTL) port map(reset_fpga_L, system_clock, led_out);
CLK: process
begin
while now <= 5 sec loop
system_clock <= not system_clock;
wait for 5 ns;
end loop;
wait;
end process CLK;
STIM: process
begin
reset_fpga_L <= '0';
wait for 100 ns;
reset_fpga_L <= '1';
wait for 4 sec;
reset_fpga_L <= '0';
wait for 50 ns;
reset_fpga_L <= '1';
wait;
end process STIM;
end architecture RTL;
I can't figure out why I'm not seeing any transitions on led_out when I run my test-bench in the simulator. I've taken care to add the waves for system_clock, reset_fpga_L, and led_out to the trace view. Do you see anything in my code that might be an issue? Thanks for your help.
A second form of the testbench can be used make generation of inputs to LED_Blink depend on the values supplied as generics:
library ieee;
use ieee.std_logic_1164.all;
entity led_blink_tb is
end entity;
architecture foo of led_blink_tb is
constant CLK_PERIOD: time := 100 ms;
constant LED_ON: time := 500 ms;
signal clk: std_logic := '0';
signal reset_n: std_logic;
signal led: std_logic;
begin
DUT:
entity work.led_blink
generic map ( CLK_PERIOD, LED_ON)
port map (
system_clock => clk,
reset_fpga_l => reset_n,
led_out => led
);
CLOCK:
process
begin
wait for CLK_PERIOD/2;
clk <= not clk;
if now > 2.5 sec then
wait;
end if;
end process;
STIMULI:
process
begin
reset_n <= '0';
wait for CLK_PERIOD * 2;
reset_n <= '1';
wait;
end process;
end architecture;
The idea, both the testbench and the model depend on constants supplied as generics making changing the parameters require less work.
Also note the association list in the port map uses named association.
If we take a look at the original testbench port map:
G1: entity work.LED_Blink(RTL) port map(reset_fpga_L, system_clock, led_out);
We see that the first positional association to the formal system_clock is associated with the actual reset_fpga_L while the second positional association representing formal reset_fpga_L is associated with the actual system_clock.
The two actual associations are in reversed order.
I am currently slightly confused about my simple counter.
It is implemented as follows:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity simple_counter is
port(
DOUT : out std_logic_vector(3 downto 0);
CE : in std_logic;
CLK : in std_logic;
RSTN : in std_logic
);
end simple_counter;
architecture behavioral of simple_counter is
signal temp : unsigned(3 downto 0);
begin
process(CLK)
begin
if RSTN = '0' then
temp <= (others => '0');
elsif(rising_edge(CLK)) then
if CE = '1' then
if std_logic_vector(temp) = (temp'range => '1') then
temp <= (others => '0');
else
temp <= temp + 1;
end if;
end if;
end if;
end process;
DOUT <= std_logic_vector(temp);
end behavioral;
I use the following testbench for simulation:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;
use work.tools_pkg.all;
library work;
--! #class tools_tb
--! #brief Test bench for the tools_tb design
entity counter_tb is
generic (
VOID : integer := 0);
port (
void_i : in std_logic);
end entity counter_tb;
--! #brief
--! #details
architecture sim of counter_tb is
-- Clock period definitions
-- Clock, reset and baud rate definitions
constant CLK_FREQ : integer := 100_000_000;
constant clk_period : time := (1.0 / real(CLK_FREQ)) * (1 sec);
signal end_sim : boolean := false;
signal rstn : std_logic;
signal clk : std_logic;
signal s_en : std_logic := '0';
------------------------------------------------------------------------------
-- DUT signals
------------------------------------------------------------------------------
signal s_dout : std_logic_vector(3 downto 0) := (others => '0');
signal s_ce : std_logic := '0';
begin -- architecture
fifo : entity work.simple_counter
port map (
DOUT => s_dout,
CE => s_ce,
RSTN => rstn,
CLK => clk
);
-- Clock process definitions (clock with 50% duty cycle is generated here).
clk_process : process
begin
if end_sim = false then
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
else
wait;
end if;
end process;
-- Stimulus process
stim_proc: process
begin
-- startup and wait for some time
rstn <= '0';
wait for clk_period;
rstn <= '1';
wait for clk_period;
wait for clk_period;
wait for clk_period;
s_ce <= '1';
wait;
end process;
end architecture sim;
I am confused why the counter increases instantly when I set CE <= '1
(see the attached simulation).
Since the counter is implemented in a synchrous process, shouldn't it take a single clock cycle until it is increased from '0' to '1'?
Thanks a lot!
You most likely have a race condition between s_ce and clk. If you will generate the s_ce on the rising edge of clk then you should see that counter works correctly.
I don't know this simulator but to check the race you can expand deltas when counter changes 0->1
I am trying to run a code that I have picked up online, but it somehow the testbench is failing to run the expected output on GHDL.
Architecture Code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity clk200Hz is
Port (
clk_in : in STD_LOGIC;
reset : in STD_LOGIC;
clk_out: out STD_LOGIC
);
end clk200Hz;
architecture Behavioral of clk200Hz is
signal temporal: STD_LOGIC;
signal counter : integer range 0 to 124999 := 0;
begin
frequency_divider: process (reset, clk_in) begin
if (reset = '1') then
temporal <= '0';
counter <= 0;
elsif rising_edge(clk_in) then
if (counter = 124999) then
temporal <= NOT(temporal);
counter <= 0;
else
counter <= counter + 1;
end if;
end if;
end process;
clk_out <= temporal;
end Behavioral;
Test Bench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY clk200Hz_tb IS
END clk200Hz_tb;
ARCHITECTURE behavior OF clk200Hz_tb IS
COMPONENT clk200Hz
PORT(
clk_in : IN std_logic;
reset : IN std_logic;
clk_out: OUT std_logic
);
END COMPONENT;
-- Inputs
signal clk_in : std_logic := '0';
signal reset : std_logic := '0';
-- Outputs
signal clk_out : std_logic;
constant clk_in_t : time := 20 ns;
BEGIN
-- Instance of unit under test.
uut: clk200Hz PORT MAP (
clk_in => clk_in,
reset => reset,
clk_out => clk_out
);
-- Clock definition.
entrada_process :process
begin
clk_in <= '0';
wait for clk_in_t / 2;
clk_in <= '1';
wait for clk_in_t / 2;
end process;
-- Processing.
stimuli: process
begin
reset <= '1'; -- Initial conditions.
wait for 100 ns;
reset <= '0'; -- Down to work!
wait;
end process;
END;
I expect a wave that would form a clock pulsing up and down, however that does not seem to be the case. I wonder what is wrong with the design.
I ran the following commands:
ghdl -s *.vhd
ghdl -a *.vhd
ghdl -e clk200Hz_tb
ghdl -r clk200Hz_tb --vcd=led.vcd
gtkwave led.vcd
and this is my output
but for clock out, I expect a up and down signal, not a signal of 0.
Thanks
I have fixed the problem, in my running command, I simply added ghdl -r clk200Hz_tb --vcd=led.vcd --stop-time=100ns.
ghdl -a clk200Hz_tb.vhdl
ghdl -e clk200Hz_tb
ghdl -r clk200Hz_tb --wave=clk200hz_tb.ghw --stop-time=500ns
Gave:
(clickable)