bzrk89
bzrk89

Reputation: 55

VHDL - iSIM output uninitialised, doesn't change states

Hi I am a new Xilinx user and been having trouble with how to write stimulus/simulate in a test bench. My output(Kd) isn't giving me any sensible values and gives 'u' for the first few clock cycles before moving and staying at '1' throughout.

Not sure if I have written the correct stimulus but hoping someone would help me out here!

My VHDL code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity codeFig2b is
    Port ( R0 : in  STD_LOGIC;
           R1 : in  STD_LOGIC;
           R2 : in  STD_LOGIC;
           R3 : in  STD_LOGIC;
           Kd : out  STD_LOGIC;
           clock : in  STD_LOGIC);
end codeFig2b;

architecture Behavioral of codeFig2b is
    signal Qa, Qb: STD_LOGIC;
begin
    process(clock, R0, R1, R2, R3)
        begin
        if clock = '1' and clock'event then
        Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
        Qb <= Qa;
        end if;
    end process;
Kd <= Qa and Qb;    

end Behavioral;

My Testbench ##

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 codeFig2b_test IS
END codeFig2b_test;

ARCHITECTURE behavior OF codeFig2b_test IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT codeFig2b
    PORT(
         R0 : IN  std_logic;
         R1 : IN  std_logic;
         R2 : IN  std_logic;
         R3 : IN  std_logic;
         Kd : OUT  std_logic;
         clock : IN  std_logic
        );
    END COMPONENT;


   --Inputs
   signal R0 : std_logic := '0';
   signal R1 : std_logic := '0';
   signal R2 : std_logic := '0';
   signal R3 : std_logic := '0';
   signal clock : std_logic := '0';

    --Outputs
   signal Kd : std_logic;

   -- Clock period definitions
   constant clock_period : time := 100 ns;

BEGIN
    -- Instantiate the Unit Under Test (UUT)
   uut: codeFig2b PORT MAP (
          R0 => R0,
          R1 => R1,
          R2 => R2,
          R3 => R3,
          Kd => Kd,
          clock => clock
        );

   -- Clock process definitions
   clock_process :process
   begin
        clock <= '0';
        wait for clock_period/2;
        clock <= '1';
        wait for clock_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
       wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '0';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '0';
            R1 <= '1';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '0';
            R2 <= '1';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '0';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '0';
            R3 <= '1';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '1';
            R3 <= '0';

        wait for 100 ns;
            R0 <= '1';
            R1 <= '1';
            R2 <= '1';
            R3 <= '1';

      wait for clock_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;

Upvotes: 3

Views: 2952

Answers (2)

FlyerDragon
FlyerDragon

Reputation: 222

What you built is a sequential logic, meaning that the outputs depend on the previous hystory of the inputs/outputs. In your case we have Qa, and Qb which is the last value of Qa.

Keeping this in mind, the approach you have used in the testbench is not optimal, because you are trying every combination of the inputs without taking into account that the last Qa is actually important.

This is what happens:

Start :   Qa = U    Qb = U     =>    Kb = U
Inputs 1: Qa = 1    Qb = U     =>    Kb = U
Inputs 2: Qa = 1    Qb = 1     =>    Kb = 1
Inputs 3: Qa = 1    Qb = 1     =>    Kb = 1
Inputs 4: Qa = 1    Qb = 1     =>    Kb = 1
....

As soon as one of the Rs goes high, Qa is high. Given the order of your combinations of inputs, there is no case where Qa goes low again. This means that after the second input combination, Qb gets a known value and Kb goes high.


Sensitivity list

This is not part of the answer but it's a consideration on the code you have written: you have put on the sensitivity list R0, R1, R2, R3 but, given what you have written after that, this is not necessary.

The process does something only if

if clock'event and clock = 1 then

this means that any event on the Rs are ignored. I'm sure that the synthetizer actually realizes that and ignores it, but it's a good practice to set a proper sensitivity list and, when possible, only use clocked processes for sequential logic and finite state machines.

I also suggest that you use the more readable rising_edge(clock) and falling_edge(clock) functions:

process(clock)
begin
    if rising_edge(clock) then
        Qa <= R0 or R1 or R2 or R3 or (Qa and Qb);
        Qb <= Qa;
    end if;
end process;

Signals and processes

Another thing you should know is how the process work: you are not assigning new values to the signals, but rather planning values for them. If you reprogram a certain signal you are just overwriting the previous planning, and the first value is never assigned. The values are finally assigned at the end of the process.

Here is a simple example:

-- Let's assume A = 0 and B = 0 at startup
clocked_process : process(clk)
begin
    if rising_edge(clk) then
        A <= '1';
        B <= A;
        A <= '0';
    end if;
end process;

At the end B is still 0, this because A = 0 for the whole process and only gets a planned value of 1, actually never assigned because it is overwritten before the end of the process (in this specific case the synthetizer will ignore A <= '1' for the implementation).

Overwriting the planned value can be used to simplify the logic: what I usually do is setting some default values and then overwriting them only when I need to.

So, instead of writing

...
case A is
when "00" =>
    B <= '0';
when "01" =>
    B <= '0';
when "10" =>
    B <= '0';
when "11" =>
    B <= '1';
end case;
...

I write this (I may retain the case structure if I need it for other signals, typically in Finite State Machines):

...
B <= '0';
if A = "11" then
    B <= '1';
end if;
...

For this simple examples the synthetizer may be able to infer the semplification. However, you should get used to think in logic level ports because the same thing written in two equivalent ways from a behavioral point of view, is actually implemented differently.

Upvotes: 1

user1155120
user1155120

Reputation:

This can be answered without simulating. Kd's output will go to a '1' and stay there.

    process(clock, R0, R1, R2, R3)
        begin
        if clock = '1' and clock'event then
        Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
        Qb <= Qa;
        end if;
    end process;
Kd <= Qa and Qb;  

Qa goes high for any of R0, R1, R2 or R2 or (Qa and Qb);

So once Qa and Qb goes high Qa stays high.

Qb goes high one clock after the first occurrence of Qa going high.

The way this happens is o consecutive '1' inputs on any of R0, R1, R2 or R3.

You clock period is 100 ns and your stimulus interval is too.

You have no stimulus following the first clock where all of R0, R1, R2 and R3 are all low at the same time to demonstrate.

Unfortunately the waveform image on your Xilinx post (iSIM output Unintialised, doesn't change states.) doesn't show QA and Qb to see that they both go high and stay there:

codefig2b image (clickable)

When you add them this point comes through:

codefig2b_test.png clickable)

Upvotes: 3

Related Questions