Output get initialized with U logic in simulation in vhdl

10,713

Solution 1

The PC signal drivers the addressIR output through the continuous assign:

addressIR <= PC;

However, the PC not assigned any value until the first rising edge of clk, so the PC is initially all 'U', called "uninitialized" in std_logic_1164 packge, which is the first and thus initial value for unassigned std_logic elements.

The PC signal can be given an initial value using:

signal PC : std_logic_vector(31 downto 0) := (others => '0');

but it is generally better not to do that, since showing non-'0'/'1' values in simulation is one of the benefits, as it may reveal actual problems with missing assigns, e.g. due to left out reset or similar.

Solution 2

The signal addressIR is all 'U' before the first rising clock edge because you didn't assigned any other value to it. The assignment comes from this statement:

addressIR <= PC;

and is executed once after simulation startup and every time PC changes. That is, addressIR equals PC after a delta-cycle. The signal PC is assigned the first time in your clocked process at the rising clock edge. Before this, the signal value of PC is defined by its declaration. You didn't specified a value there, so that all elements of the std_logic_vector are initialized to the first value in the enumeration of the type std_logic. And that is 'U', denoting that the signal is uninitialized.

The simulation shows real world behaviour here, especially if you synthesize the VHDL code for a standard cell technology. On FPGAs you have sometimes the option to program the initial value of a flip-flop. But, you will have to reset the FPGA design after startup anyway as discussed in the question "Do I need to reset my FPGA design after startup?" on Electrical Engineering. My answer there includes a screenshot of a failed initialization. Thus, you will have to assert reset anyway.

The value of addressIR before the first rising clock edge should be of no interest because the unit which uses this signal value should be in reset too. For example, the instruction bus unit should not issue a bus transaction while in reset.

All components of the whole system should execute a reset at the first rising clock edge.


You should include a reset synchronizer in your testbench. Later on, this reset synchronizer will part of the whole system. You will need these declarations:

signal reset_sync : std_logic_vector(1 downto 0) := (others => '1');
signal reset : std_logic;

and these statements in the architecture body (register chain):

reset_sync <= reset_sync(reset_sync'high-1 downto 0) & reset_pin when rising_edge(clock);
reset <= reset_sync(reset_sync'high); -- active-high

The signal reset_pin is the external reset input. If you don't need it, than just replace it by '0'.

Yes, this reset synchronizer uses initialized flip-flops on FPGAs. But, only the flip-flop reset_sync(0) is subject to the initialization problem. The value of this flip-flop may be '0' or '1' after the first rising clock edge after the Global Write Enable (GWE) on Xilinx FPGAs is released. The flip-flop reset_sync(1) will be '1' for at least one full clock-cycle.

Share:
10,713

Related videos on Youtube

Sunil Kumar
Author by

Sunil Kumar

I am software developer having a 3 years of industry experience. Still learning a lot of things.

Updated on June 04, 2022

Comments

  • Sunil Kumar
    Sunil Kumar almost 2 years

    I am using Xilinx. Currently I am working on a project to develop a pipelined MIPS processor. I have made a component file called Program_Counter.vhd. When I simulate it using a testbench the output get initialised with U and then it's fine afterwards. I can't understand this behavior. Any help will be highly appreciated.

    My Program_Counter.vhd

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.NUMERIC_STD.ALL;
    
    entity Program_Counter is
      port (clk,reset,Last : in std_logic;
            addressALU : in std_logic_vector(31 downto 0);
            addressIR : out std_logic_vector(31 downto 0)
         ) ;
    end entity ; -- Program_Counter
    
    architecture Behavioral of Program_Counter is
    
    signal PC : std_logic_vector(31 downto 0);
    
    begin
    process(clk)
    begin
    if rising_edge(clk) then
        if reset = '1' then
            PC <= (others => '0');
        elsif Last ='1' then
            null;
        else
            PC <= addressALU;       
        end if ;
    end if ;
    end process;
    addressIR <= PC;
    end Behavioral;
    

    Here is the testbench

    LIBRARY ieee;
    USE ieee.std_logic_1164.ALL;
    use ieee.std_logic_unsigned.all;
    USE ieee.numeric_std.ALL;
    
    ENTITY PC_tb IS
    END PC_tb;
    
    ARCHITECTURE behavior OF PC_tb IS 
    
        COMPONENT Program_Counter
        PORT(
             clk : IN  std_logic;
             reset : IN  std_logic;
             Last : IN  std_logic;
             addressALU : IN  std_logic_vector(31 downto 0);
             addressIR : OUT  std_logic_vector(31 downto 0)
            );
        END COMPONENT;
    
    
       --Inputs
       signal clk : std_logic := '0';
       signal reset : std_logic := '0';
       signal Last : std_logic := '0';
       signal addressALU : std_logic_vector(31 downto 0) := (others => '0');
    
        --Outputs
       signal addressIR : std_logic_vector(31 downto 0);
    
       -- Clock period definitions
       constant clk_period : time := 10 ns;
    
    BEGIN
    
        -- Instantiate the Unit Under Test (UUT)
       uut: Program_Counter PORT MAP (
              clk => clk,
              reset => reset,
              Last => Last,
              addressALU => addressALU,
              addressIR => addressIR
            );
    
       -- 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        
    
          wait for 35 ns;
            --reset <= '0';
                for i in 1 to 10 loop
                    addressALU <= addressALU + "1";
                    wait for clk_period ;
                end loop;
    
          wait for clk_period*10;
    
          wait;
       end process;
    END;
    

    please refer the waveform after simulation. Thanks in advance.

    enter image description here

  • Sunil Kumar
    Sunil Kumar about 8 years
    So sir I should have to change my clock to asynchronous from synchronous then or is there any other method to avoid it?
  • Morten Zilmer
    Morten Zilmer about 8 years
    No, my point is don't avoid it; embrace it as a feature. It is not a problem in itself that signals are undefined at start up; in fact it is just the way that real hardware usually works, so simulation should reflect it. If you need well-defined values in the design, then add a reset signal that can reset the flip-flop state, either through asynchronous or synchronous reset.
  • Sunil Kumar
    Sunil Kumar about 8 years
    Thank you sir, I fixed it by starting the clk signal with 1 in stead of 0.
  • Morten Zilmer
    Morten Zilmer about 8 years
    That does not fix it; it only hides real world behavior from simulation, and so you may face the problem in hardware instead, where it is much harder to debug.