Output get initialized with U logic in simulation in vhdl
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.
Related videos on Youtube
Sunil Kumar
I am software developer having a 3 years of industry experience. Still learning a lot of things.
Updated on June 04, 2022Comments
-
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.
-
Sunil Kumar about 8 yearsSo sir I should have to change my clock to asynchronous from synchronous then or is there any other method to avoid it?
-
Morten Zilmer about 8 yearsNo, 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 about 8 yearsThank you sir, I fixed it by starting the clk signal with 1 in stead of 0.
-
Morten Zilmer about 8 yearsThat 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.