Search code examples
vhdl

Simulation of a register and an incrementer with VHDL


I designed a circuit composed of a register and an incrementer. Each one is supposed to feed the input of the other, resulting in the PC being incremented by 4 on each rising edge of the clock. The code is show below:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity Register1 is
    port (
        CLK : in  STD_LOGIC;
        d   : in  STD_LOGIC_VECTOR(31 downto 0);
        q   : out STD_LOGIC_VECTOR(31 downto 0)
    );
end;

architecture Behavioral of Register1 is
begin
    process (CLK)
    begin
        if rising_edge(CLK) then
            q <= d;
        end if;
    end process;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;


entity Incrementer is
    port (
        din  : in  STD_LOGIC_VECTOR(31 downto 0);
        dout : out STD_LOGIC_VECTOR(31 downto 0)
    );
end;

architecture DataFLow of Incrementer is
begin
    dout <= STD_LOGIC_VECTOR(UNSIGNED(din) + 4);
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Test is
end Test;

architecture Struct of Test is

    component Register1 is
        port (
            CLK : in  STD_LOGIC;
            d   : in  STD_LOGIC_VECTOR(31 downto 0);
            q   : out STD_LOGIC_VECTOR(31 downto 0)
        );
    end component;

    component Incrementer is
        port (
            din  : in  STD_LOGIC_VECTOR(31 downto 0);
            dout : out STD_LOGIC_VECTOR(31 downto 0)
        );
    end component;
    
    signal CLK : STD_LOGIC := '0';
    signal PCN : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');
    signal PC  : STD_LOGIC_VECTOR(31 downto 0) := (others => '0');

    constant CLK_period: TIME := 10 ns;

begin
    -- The concurent clock signal
    CLK <= not CLK after CLK_period/2;

    PCreg:    Register1 port map (
                  CLK,
                  d => PCN,
                  q => PC
              );

    Incr1:    Incrementer port map (
                  din  => PC,
                  dout => PCN
              );

    -- The stimulus process
    verify: process
    begin
        wait for 80 ns;
    end process;
end;

However the relevant signals (PC, PCN) are shown with "X" in my simulator (vivado). What am I doing wrong?

enter image description here


Solution

  • The problem is, you do not initialize the signal q of the register1 module. So at simulation start q has the value 'U' (unassigned). When you add 1 to 'U' a 'X' results. So you must initialize q. This is often done by a synchronous or asynchronous reset signal or by a signal definition with initialization statement, which resets all storing elements in your design to a value different from 'U'. So with a asynchronous reset signal your code would look like:

    process (RESET, CLK)
    begin
        if RESET='1' then
            q <= (others => '0');
        elsif rising_edge(CLK) then
            q <= d;
        end if;
    end process;