Test bench of a 32×8 register file VHDL

vhdl

I wrote the assembly code for this circuit in vhdl already. I want to simulate it with a test bench.

enter image description here

  • RegWrite: 1 bit input (clock)
  • Write Register Number: 3-bit input(write addresses)
  • Write Data: 32-bit input (data in) Read
  • Register Number A: 3-bit input (read addresses)
  • Read Register Number B: 3-bit input (read adddresses)
  • Port A: 32-bit output (data out)
  • Port B: 32-bit output (data out)

I think my problem is that I don't understand what this circuit does. I chose random values to assign to the inputs, but it didn't output anything. What are good inputs to choose for this circuit?

here is my test bench file for reference:

library ieee; 
use ieee.std_logic_1164.all; 

entity Reg_TB is     -- entity declaration 
end Reg_TB; 

architecture TB of Reg_TB is 
component RegisterFile_32x8
port (  RegWrite: in std_logic; 
    WriteRegNum: in std_logic_vector(2 downto 0);
    WriteData: in std_logic_vector(31 downto 0);
    ReadRegNumA: in std_logic_vector(2 downto 0);
    ReadRegNumB: in std_logic_vector(2 downto 0);
    PortA: out std_logic_vector(31 downto 0);
    PortB: out std_logic_vector(31 downto 0)
 ); 
end component; 

signal T_RegWrite : std_logic;
signal T_WriteRegNum: std_logic_vector(2 downto 0);
signal T_WriteData: std_logic_vector(31 downto 0);
signal T_ReadRegNumA: std_logic_vector(2 downto 0);
signal T_ReadRegNumB: std_logic_vector(2 downto 0);
signal T_PortA : std_logic_vector(31 downto 0);
signal T_PortB : std_logic_vector(31 downto 0);

begin 
T_WriteRegNum <= "011";
T_WriteData <= "00000000000000000000000000000001";
T_ReadRegNumA <= "001";
T_ReadRegNumB <= "100";
U_RegFile: RegisterFile_32x8 port map 
(T_RegWrite, T_WriteRegNum,    T_WriteData,T_ReadRegNumA, T_ReadRegNumB, T_PortA, T_PortB); 

-- concurrent process to offer clock signal 
process 
begin 


T_RegWrite <= '0'; 
wait for 5 ns; 
T_RegWrite <= '1'; 
wait for 5 ns; 
end process; 
process 
 begin 
wait for 12 ns; 
-- case 2 
wait for 28 ns; 
-- case 3 
wait for 2 ns; 
-- case 4 
wait for 10 ns; 
-- case 5 
wait for 20 ns; 
wait; 
 end process; 
end TB; 

as you can see I chose

  • WriteRegNum = "011"
  • WriteData = "00000000000000000000000000000001"
  • ReadRegNumA = "001"
  • ReadRegNumB = "100"

I think that I chose bad inputs. The simulation does this:

enter image description here

Best Answer

In general reading an address before it is written doesn't produce any useful results.

Your block diagram shows a 32 bit wide 8 word deep register file with two read ports and one write port with RegWrite used as a clock gated by the decode of the write address. A stable WriteRegNum value and a rising edge on RegWrite effects a write to the address specified by WriteRegNum.

The two read ports appear completely independent. Specifying an address on the respective ReadRegNumA or ReadRegNumB should output the contents of that register to the respective output port.

To get something useful out, you have to write to that location first, otherwise it will be the default value ((others => 'U'),) suspiciously like your waveform.

Trying writing to a location before expecting valid read data from it. Use values that are distinguishable by register location. Theoretically you should be preserving set up and hold time on WriteRegNum with respect to the rising edge of RegWrite.

Example stimulus producing output:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity registerfile_32x8 is
    port (
        RegWrite:       in  std_logic;
        WriteRegNum:    in  std_logic_vector (2 downto 0);
        WriteData:      in  std_logic_vector (31 downto 0);
        ReadRegNumA:    in  std_logic_vector (2 downto 0);
        ReadRegNumB:    in  std_logic_vector (2 downto 0);
        PortA:          out std_logic_vector (31 downto 0);
        PortB:          out std_logic_vector (31 downto 0)
    );
end entity;

architecture fum of registerfile_32x8 is

    type reg_array is array (0 to 7) of std_logic_vector(31 downto 0);
    signal reg_file: reg_array;

    begin 
    process(RegWrite)
    begin 
        if rising_edge(RegWrite) then
            reg_file(to_integer(unsigned(WriteRegNum))) <= WriteData;
        end if;
    end process;

    PortA <= reg_file(to_integer(unsigned(ReadRegNumA)));

    PortB  <= reg_file(to_integer(unsigned(ReadRegNumB)));

end architecture;

library ieee; 
use ieee.std_logic_1164.all; 

entity reg_tb is    
end entity; 

architecture fum of reg_tb is 

component registerfile_32x8
    port (  
        RegWrite:       in  std_logic; 
        WriteRegNum:    in  std_logic_vector (2 downto 0);
        WriteData:      in  std_logic_vector (31 downto 0);
        ReadRegNumA:    in  std_logic_vector (2 downto 0);
        ReadRegNumB:    in  std_logic_vector (2 downto 0);
        PortA:          out std_logic_vector (31 downto 0);
        PortB:          out std_logic_vector (31 downto 0)
        ); 
    end component; 

signal RegWrite:        std_logic := '1';
signal WriteRegNum:     std_logic_vector (2 downto 0) := "000";
signal WriteData:       std_logic_vector (31 downto 0) := (others => '0');
signal ReadRegNumA:     std_logic_vector (2 downto 0) := "000";
signal ReadRegNumB:     std_logic_vector (2 downto 0) := "000";
signal PortA:           std_logic_vector (31 downto 0);
signal PortB:           std_logic_vector (31 downto 0);

begin 

DUT: 
    registerfile_32x8 
        port map (
            RegWrite => RegWrite,
            WriteRegNum => WriteRegNum,
            WriteData  => WriteData,
            ReadRegNumA => ReadRegNumA, 
            ReadRegNumB => ReadRegNumB, 
            PortA => PortA, 
            PortB => PortB
        ); 


STIMULUS:
    process 
    begin 
    wait for 20 ns;
    RegWrite <= '0';
    wait for 20 ns;
    RegWrite <= '1';
    wait for 20 ns;
    WriteData <= x"feedface";
    WriteRegnum <= "001";
    RegWrite <= '0';
    wait for 20 ns;
    RegWrite <= '1';
    ReadRegNumA <= "001";
    wait for 20 ns;
    WriteData <= x"deadbeef";
    WriteRegNum <= "010";
    ReadRegNumB <= "010";
    RegWrite <= '0';
    wait for 20 ns;
    RegWrite <= '1';
    wait for 20 ns;
    wait for 20 ns;
    wait;
 end process; 
end architecture; 

david_koontz@Macbook: ghdl -a regfile_32x8.vhdl
david_koontz@Macbook: ghdl -e reg_tb
david_koontz@Macbook: ghdl -r reg_tb --wave=reg_tb.ghw
david_koontz@Macbook: open reg_tb.gtkw

reg_tb showing register contents

Essentially, the point is to have non 'U' values in a register file that's being read. If you notice the last write to WriteRegNum = "010", PortB shows undefined output until the write occurs.

Related Topic