Search code examples
vhdl

"Forcing unknown" values on output in tests


I'm trying to write register file in VHDL. Firstly I'm define storing element for N bits. Secondly implement register file, with WA(write address), RA(read address), WDR/RDP (write/read data port) and other things. After that generate testbench for regfile, but in test getting "X", when taken any data by RA address. How I can fix this? Maybe something wrong in implentation of my regfile?

waveform

a) Store element for data

library ieee;
use ieee.std_logic_1164.all;

entity REGn is 
    generic(INITREG: std_logic_vector:="1001");
    port(Din : in std_logic_vector(INITREG'range);
         EN  : in std_logic;    
         INIT: in std_logic;
         CLK : in std_logic;
         OE  : in std_logic;
         Dout: out std_logic_vector(INITREG'range));
end REGn;

architecture beh_regn of REGn is
    signal reg: std_logic_vector(INITREG'range);    
    constant ALLZ: std_logic_vector(INITREG'range):=(others => 'Z');
begin
    Main: process(Din, EN, INIT, CLK)
    begin                              
        if INIT = '1' then
            reg <= INITREG;
        elsif EN = '1' then
            if rising_edge(CLK) then
                reg <= Din;
            end if;
        end if;
    end process;
    Dout <= reg when OE='0' else ALLZ;
end beh_regn;

b) Register file

library ieee;
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all;

entity REGFile is
    generic(INITREG: std_logic_vector:="0000";
            a      : integer:=2);
    port(INIT:  in std_logic;
         WDP :  in std_logic_vector(INITREG'range);
         WA  :  in std_logic_vector(a-1 downto 0);
         RA  :  in std_logic_vector(a-1 downto 0);
         WE  :  in std_logic;
         RDP : out std_logic_vector(INITREG'range));
end REGFile;

architecture beh_regfile of REGFile is
    component REGn is
        generic(INITREG: std_logic_vector:="1001");
        port(Din:  in std_logic_vector(INITREG'range);
            EN  :  in std_logic;                   
            INIT:  in std_logic;
            CLK :  in std_logic;
            OE  :  in std_logic;
            Dout: out std_logic_vector(INITREG'range));
    end component;    
    signal wen: std_logic_vector(2**a-1 downto 0);
    signal ren: std_logic_vector(2**a-1 downto 0);
    signal readd: std_logic_vector(INITREG'range);
begin                    
    -- Write decoder
    WAD: process(WA)
    begin
        for i in 0 to 2**a-1 loop   
            if i = CONV_INTEGER(WA) then
                wen(i) <= '1';
            else
                wen(i) <= '0';
            end if;
        end loop;
    end process;               

    -- Read decoder
    RAD: process(RA)
    begin       
        for i in 0 to 2**a-1 loop
            if i = CONV_INTEGER(RA) then
                ren(i) <= '1';
            else
                ren(i) <= '0';
            end if;
        end loop;
    end process;

REGi: for i in 2**a-1 downto 0 generate
    REGi: REGn generic map (INITREG)
               port map (WDP, wen(i), INIT, WE, ren(i), readd);
end generate;

RDP <= readd;
end beh_regfile;

c) Testbench for register file

library ieee;       
library std;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use std.textio.all;

    -- Add your library and packages declaration here ...

entity regfile_tb is
    -- Generic declarations of the tested unit
        generic(
        INITREG : STD_LOGIC_VECTOR := "0000";
        a : INTEGER := 2 );
end regfile_tb;

architecture TB_ARCHITECTURE of regfile_tb is
    -- Component declaration of the tested unit
    component regfile
        generic(
        INITREG : STD_LOGIC_VECTOR := "0000";
              a : INTEGER := 2 );
    port(
        INIT : in STD_LOGIC;
        WDP : in STD_LOGIC_VECTOR(INITREG'range);
        WA : in STD_LOGIC_VECTOR(a-1 downto 0);
        RA : in STD_LOGIC_VECTOR(a-1 downto 0);
        WE : in STD_LOGIC;
        RDP : out STD_LOGIC_VECTOR(INITREG'range) );
    end component;

    -- Stimulus signals - signals mapped to the input and inout ports of tested entity
    signal INIT : STD_LOGIC;
    signal WDP  : STD_LOGIC_VECTOR(INITREG'range);
    signal WA   : STD_LOGIC_VECTOR(a-1 downto 0);
    signal RA   : STD_LOGIC_VECTOR(a-1 downto 0);
    signal WE   : STD_LOGIC;
    -- Observed signals - signals mapped to the output ports of tested entity
    signal RDP : STD_LOGIC_VECTOR(INITREG'range);

    -- Add your code here ...               
    type TEST_REC is record          
           INIT : STD_LOGIC;
            WDP : STD_LOGIC_VECTOR(INITREG'range);
            WA  : STD_LOGIC_VECTOR(a-1 downto 0);
            RA  : STD_LOGIC_VECTOR(a-1 downto 0);    
            WE  : STD_LOGIC;
    end record;

    type TEST_ARRAY is array(positive range <>) of TEST_REC;
    constant PATTERN : test_array:= (        
        -- initialize
        (INIT=>'1', WDP=>"0000", WA=>"00", RA=>"00", WE=>'0'),
        (INIT=>'1', WDP=>"0000", WA=>"01", RA=>"01", WE=>'0'),
        (INIT=>'1', WDP=>"0000", WA=>"10", RA=>"10", WE=>'0'),
        (INIT=>'1', WDP=>"0000", WA=>"11", RA=>"11", WE=>'0'),
        --- test vectors      
        (INIT=>'0', WDP=>"1000", WA=>"00", RA=>"00", WE=>'1'),
        (INIT=>'0', WDP=>"1000", WA=>"00", RA=>"00", WE=>'0')
    );

begin

    -- Unit Under Test port map
    UUT : regfile
        generic map (
            INITREG => INITREG,
            a => a
        )

        port map (
            INIT => INIT,
            WDP  => WDP,
            WA   => WA,
            RA   => RA,
            WE   => WE,
            RDP  => RDP
        );

    -- Add your stimulus here ...     
    process
        variable VECTOR: TEST_REC;
    begin
        for i in PATTERN'range loop
            VECTOR:= PATTERN(i);     
            INIT  <= VECTOR.INIT;
            WDP   <= VECTOR.WDP;
            WA    <= VECTOR.WA;
            RA    <= VECTOR.RA;    
            WE    <= VECTOR.WE;
            wait for 100 ns;
        end loop;
    end process;          

    process
        variable my_line: line;
    begin                         
        wait for 5ns;
        write(my_line,"WDP=");
        write(my_line,WDP);  
        write(my_line," INIT=");
        write(my_line,INIT);
        write(my_line," WA=");
        write(my_line,WA);
        write(my_line," RA=");
        write(my_line,RA);       
        write(my_line," RDP=");
        write(my_line,RDP);
        writeline(output,my_line);   
        wait for 96ns;
    end process;


end TB_ARCHITECTURE;

configuration TESTBENCH_FOR_regfile of regfile_tb is
    for TB_ARCHITECTURE
        for UUT : regfile
            use entity work.regfile(beh_regfile);
        end for;
    end for;
end TESTBENCH_FOR_regfile;

Solution

  • Your output enables aren't correct:

    regfile_tb_ghw.png (image linked to full size image)

    Notice three are low at the same time for all four Regn instances and they cause a conflict for the bit of Readd that's different.

    In architecture beh_regn of Regn:

    Dout <= reg when OE='0' else ALLZ;
    

    With three output enables '0', a conflict between a '1' and '0' resolves to 'X' (see package std_logic_1164, the body, resolution_table).

    You have the assignments to ren(i) inverted, should be:

    -- Read decoder
    RAD: process(RA)
    begin       
        for i in 0 to 2**a-1 loop
            if i = CONV_INTEGER(RA) then
                ren(i) <= '0';  -- was '1'
            else
                ren(i) <= '1';  -- was '0'
            end if;
        end loop;
    end process;
    

    No guarantee this is all that is wrong, but answers "... in test getting "X", when taken any data by RA address. How I can fix this? Maybe something wrong in implentation of my regfile?"

    (Invert the assignments to ren(i), yes there is something wrong in REGFile).

    Also note despite your VHDL tool allowing it you are required to have white space between a numerical literal and a following identifier (e.g. 96ns in your test bench). That won't change in the next revision of the standard.