What the cause of different delays of signals Q_VLD1 and Q_VLD2 in simulator?
Result of simulation. Is it expected behaviour of simulator or not?
I use Xilinx Isim.
There is the code and testbench for it:
entity assign_test is
port(CLK : in STD_LOGIC;
D_VLD : in STD_LOGIC;
Q_VLD1 : out STD_LOGIC;
Q_VLD2 : out STD_LOGIC
);
end assign_test;
architecture Behavioral of assign_test is
signal D_VLD_i : std_logic;
signal d_vld_dly1 : std_logic;
signal d_vld_dly2 : std_logic;
begin
D_VLD_i <= D_VLD;
process (clk) is
begin
if rising_edge(clk) then
d_vld_dly1 <= D_VLD;
d_vld_dly2 <= D_VLD_i;
end if;
end process ;
Q_VLD1 <= d_vld_dly1;
Q_VLD2 <= d_vld_dly2;
end Behavioral;
ENTITY tb_assign_test IS
END tb_assign_test;
ARCHITECTURE behavior OF tb_assign_test IS
COMPONENT assign_test
PORT(
CLK : IN std_logic;
D_VLD : IN std_logic;
Q_VLD1 : OUT std_logic;
Q_VLD2 : OUT std_logic
);
END COMPONENT;
--Inputs
signal CLK : std_logic := '0';
signal D_VLD : std_logic := '0';
--Outputs
signal Q_VLD1 : std_logic;
signal Q_VLD2 : std_logic;
constant CLK_period : time := 10 ns;
BEGIN
uut: assign_test PORT MAP (
CLK => CLK,
D_VLD => D_VLD,
Q_VLD1 => Q_VLD1,
Q_VLD2 => Q_VLD2
);
CLK_process :process
begin
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end process;
stim_proc: process
begin
wait for 100 ns;
wait for 5 ns;
wait for CLK_period*10;
D_VLD <= '1';
wait for CLK_period*3;
D_VLD <= '0';
wait;
end process;
END;
So if you look at the internal signals in the assign_test module, based on simulation time only, it may look as in figure below (d_vld_dly* is before assign to Q_VLD*).
But the figure is misleading, since that figure does not show the VHDL concept of delta delay. If the waveform is expanded to show delta delays (using ModelSim in this case), it looks like below.
So this reveals that the D_VLD_i <= D_VLD; in the assign_test actually delays the D_VLD_i a delta delay, whereby the new value is not seen at the clock until next rising clock edge.
The reason for this problem, is that the test bench does not generate input data as a cause of the clock, which would make data one delta delay after the clock, but independently and at the same simulation time and same delta delay as the clock.
The test bench can be updated to generate data as a cause of the clock, if wait for clock is changed from:
wait for CLK_period*10;
to:
for i in 1 to 10 loop
wait until rising_edge(CLK);
end loop;
which will then give a waveform as:
So based on this, a rule for good test bench design is to generate stimuli the same way as generating data in synthesized modules, so the stimuli from the test bench is like data between modules in general, in order to get expected and reliable and test bench behavior.
Related
I'm new on StackOverflow and I'm sorry for eventual error.
I'm workin on VHDL and I have a problem with the Post-Place & Route. While behavioral works correctly, Post-Place & Route has problem and the result remain UNDEFINED for the all the time.
entity step1 is
port ( d: in std_logic_vector (0 to 5);
clk : in std_logic;
RESET: in std_logic;
q: out std_logic_vector (0 to 5)
);
end step1;
architecture Behavioral of step1 is
begin
ff: process (clk)
begin
if (clk'event and clk='1') then
if (RESET = '1') then
q <= "000000";
else
q <= d;
end if;
end if;
end process;
end Behavioral;
I place here the code. It should be a flip flop D that I use to make a pipeline architecture. Thanks for your reply, and please excuse me for any mistake.
Here's the test bench:
entity test_step1 is
end test_step1
ARCHITECTURE behavior OF test_step1 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT step1
PORT(
input : IN std_logic_vector(0 to 5);
clk : IN std_logic;
RESET : IN std_logic;
output : OUT std_logic_vector(0 to 5)
);
END COMPONENT;
--Inputs
signal input : std_logic_vector(0 to 5) := (others => '0');
signal clk : std_logic := '0';
signal RESET : std_logic := '0';
--Outputs
signal output : std_logic_vector(0 to 5);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: step1 PORT MAP (
input => input,
clk => clk,
RESET => RESET,
output => output
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
RESET <= '1';
wait for 10 ns;
RESET <= '0';
input <= "111111";
wait for clk_period*10;
input <= "101010";
-- insert stimulus here
wait;
end process;
END;
The first warning messages for HDL Compiler 89 and 648 found on the internet are:
WARNING:HDLCompiler:89 - "my_module" remains a black-box since it has no binding entity.
WARNING:Simulator:648 - "Top_LCD_test.vhd" Line 35. Instance top_lcd is unboundCompiling architecture behavior of entity testbench
This means that the compiler has not fount any entity corresponding to the component used in your testbench.
In your case, the port names of your entity and component didn't match !
Try to use the same names in port for the component and entity :
entity test_step1 is
end test_step1;
ARCHITECTURE behavior OF test_step1 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT step1
PORT(
d : IN std_logic_vector(0 to 5);
clk : IN std_logic;
RESET : IN std_logic;
q : OUT std_logic_vector(0 to 5)
);
END COMPONENT;
--Inputs
signal input : std_logic_vector(0 to 5) := (others => '0');
signal clk : std_logic := '0';
signal RESET : std_logic := '0';
--Outputs
signal output : std_logic_vector(0 to 5);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: step1 PORT MAP (
d => input,
clk => clk,
RESET => RESET,
q => output
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
RESET <= '1';
wait for 10 ns;
RESET <= '0';
input <= "111111";
wait for clk_period*10;
input <= "101010";
-- insert stimulus here
wait;
end process;
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
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity D_flip_flop is
port (
D : in STD_LOGIC;
Q : inout STD_LOGIC;
Q_tonos : out STD_LOGIC;
CLK : in STD_LOGIC;
RST : in STD_LOGIC
);
end D_flip_flop;
architecture Behavioral of D_flip_flop is
begin
process_flip_flip: process
begin
wait until CLK'EVENT AND CLK = '1';
if(RST='1') then
Q <= '0';
else
Q <= D;
end if;
Q_tonos <= not Q;
end process process_flip_flip;
end Behavioral;
-------------------------
--testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY test_flip_flop IS
END test_flip_flop;
ARCHITECTURE tb OF test_flip_flop IS
COMPONENT D_flip_flop
PORT(
D : IN std_logic;
Q : INout std_logic;
Q_tonos : OUT std_logic;
CLK : IN std_logic;
RST : IN std_logic
);
END COMPONENT;
signal D : std_logic ;
signal CLK : std_logic ;
signal RST : std_logic ;
signal Q : std_logic;
signal Q_tonos : std_logic;
constant CLK_period : time := 10 ns;
signal stopClk : boolean;
BEGIN
-- Instantiate the Unit Under Test (UUT)
dut: D_flip_flop PORT MAP (
D => D,
Q => Q,
Q_tonos => Q_tonos,
CLK => CLK,
RST => RST
);
CLK_process :process
begin
while not stopClk loop
CLK <= '0';
wait for CLK_period/2;
CLK <= '1';
wait for CLK_period/2;
end loop;
wait;
end process CLK_process;
-- Stimulus process
stim_proc: process
begin
-- insert stimulus here
D <= '0';
RST <= '1';
wait for 100 ns;
D <= '0';
RST <= '0';
wait for 100 ns;
D <= '1';
RST <= '0';
wait for 100 ns;
D <= '1';
RST <= '0';
wait for 100 ns;
wait;
end process;
END;
You are missing one line in your testbench, I think:
D <= '1';
RST <= '0';
wait for 100 ns;
stopClk <= TRUE; -- add this line
wait;
end process;
END;
http://www.edaplayground.com/x/56Mm
That way, when the test is finished, the clock stopClk signal turns off the clock generator and the simulation finishes. It finishes because it reaches a state called event starvation. Every time a line of code containing a signal assignment is executed, an event is added to the simulators event queue (its "to do list"). If you create a situation where no such lines continue to be executed, then the event queue becomes empty. This is event starvation. The simulator detects that and the simulation stops. (If you think about, what else could it do?)
Without this extra line, the simulation runs forever, because the clock generation process executes signal assignments forever, so the event queue is never empty.
Not really an answer, but: consider using if rising_edge(CLK) or maybe if CLK='1' and CLK'event instead of wait until. Not all synhtesis tools support that kind of code and anyway it's rare to see it in professional world ;)
p.s. stopClk signal is not driven (or was it?) Your TB clock is enably by that, yet I guess it remains 'u' for the whole simulation. Unless forced in the simulation.
I'm starting out trying to learn VHDL after doing a little bit of Verilog.
This is my attempt at creating a clock divider:
(largely taken from Making a clock divider)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity clock_192 is
Port ( clk : in STD_LOGIC;
clr : in STD_LOGIC;
clk_out : out STD_LOGIC);
end clock_192;
architecture Behavioral of clock_192 is
signal q : std_logic_vector (23 downto 0);
begin
clk_out <= q(23);
process(clk,clr)
begin
if clr = '1' then
q <= "000000000000000000000000";
elsif clk'event and clk = '1' then
q <= std_logic_vector(unsigned(q)+1);
end if;
end process;
end Behavioral;
And here is the test bench I'm using:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test_clock_192 IS
END test_clock_192;
ARCHITECTURE behavior OF test_clock_192 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT clock_192
PORT(
clk : IN std_logic;
clr : IN std_logic;
clk_out : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal clr : std_logic := '0';
--Outputs
signal clk_out : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
constant clk_out_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: clock_192 PORT MAP (
clk => clk,
clr => clr,
clk_out => clk_out
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
clk_out_process :process
begin
clk_out <= '0';
wait for clk_out_period/2;
clk_out <= '1';
wait for clk_out_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
clr <= '1';
wait for 97 ns;
clr <= '0';
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The trouble is my clk_out signal keeps flipping between 0 and X with every cycle of clk. As seen here:
Does anyone have an idea of what is going on?
EDIT:
To fix the problem I had to change my test bench to look like this:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY test_clock_192 IS
END test_clock_192;
ARCHITECTURE behavior OF test_clock_192 IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT clock_192
PORT(
clk : IN std_logic;
clr : IN std_logic;
clk_out : OUT std_logic
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal clr : std_logic := '0';
--Outputs
signal clk_out : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
constant clk_out_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: clock_192 PORT MAP (
clk => clk,
clr => clr,
clk_out => clk_out
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
clr <= '1';
wait for 97 ns;
clr <= '0';
wait for clk_period*10;
-- insert stimulus here
wait;
end process;
END;
The test bench drives the clk_out signal both from the uut instance and the clk_out_process process, and this makes the resolution function for the std_logic take effect.
When both sources drive '0' then the resulting clk_out value will be '0', but if one source drives '0' and the other drives '1' then the resolution function will return 'X', as you see.
You can look here for some description of "VHDL resolution function", or try google it.
I'm having some trouble implementing a ring oscillator. I don't care about it working on an FPGA. I only want to simulate using Xilinx ISE. Is the code below acceptable? I also addded the test bench. Thanks!
Code
library ieee;
use ieee.std_logic_1164.all;
-- 5 Ring Oscillator
entity ring_osc is
port (ro_en : in std_logic;
delay : in time;
ro_out : out std_logic);
end ring_osc;
architecture behavioral of ring_osc is
signal gate_out : std_logic_vector(5 downto 0) := (others => '0');
begin
process
begin
gate_out(0) <= ro_en and gate_out(5);
wait for delay;
gate_out(1) <= not(gate_out(0));
wait for delay;
gate_out(2) <= not(gate_out(1));
wait for delay;
gate_out(3) <= not(gate_out(2));
wait for delay;
gate_out(4) <= not(gate_out(3));
wait for delay;
gate_out(5) <= not(gate_out(4));
wait for delay;
ro_out <= gate_out(5);
end process;
end behavioral;
Test Bench
library ieee;
use ieee.std_logic_1164.all;
entity ring_osc_tb is
end ring_osc_tb;
architecture behavior of ring_osc_tb is
-- component declaration for the unit under test (uut)
component ring_osc
port (ro_en : in std_logic;
delay : in time;
ro_out : out std_logic);
end component;
-- Inputs
signal ro_en : std_logic := '0';
signal delay : time := 0.5 ns;
-- Outputs
signal ro_out : std_logic;
signal clk : std_logic := '0';
constant clk_period : time := 10 ns;
begin
-- instantiate the unit under test (uut)
uut: ring_osc port map (
ro_en => ro_en,
delay => delay,
ro_out => ro_out
);
-- clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- stimulus process
stim_proc: process
begin
ro_en <= '1';
delay <= 0.5 ns;
wait for 10*clk_period;
delay <= 1 ns;
wait for 5*clk_period;
assert false report "End of Simulation" severity failure;
end process;
end;
The process with sequential wait does not describe the concurrent nature of the gates in the Ring oscillator, since execution is suspended for delay time at each wait, which is not the way a real word design operates.
A description with concurrent evaluation of all the gates can be:
gate_out(0) <= ro_en and gate_out(5) after delay;
inv_g : for i in 1 to gate_out'high generate
gate_out(i) <= not gate_out(i - 1) after delay;
end generate;
ro_out <= gate_out(5);
This is for simulation only, as also noted in the question, due to the inherent loop nature of a ring oscillator.
Using test bench, with added disable at start:
-- Disable at start
ro_en <= '0';
delay <= 0.5 ns;
wait for 10 * 0.5 ns;
Then the resulting waveform is: