-- reg_file_32_8_5port_tb.arch entity reg_file_32_8_6port_tb is end; library IEEE; use work.components.all; use IEEE.std_logic_1164.all; use ieee.numeric_std.all; use work.reg_file_pkg.all; architecture modular of reg_file_32_8_6port_tb is constant num_write_ports : integer := 3; constant num_read_ports : integer := 3; constant num_bidirectional_ports : integer := 0; constant data_width : integer := 8; signal write_sig : std_logic_vector(0 to num_write_ports-1); signal read_sig : std_logic_vector(0 to num_read_ports-1); type reg_file_data_bus is array (integer range <>) of std_logic_vector(data_width-1 downto 0); type reg_file_address_bus is array (integer range <>) of std_logic_vector(log_2(depth)-1 downto 0); -- the range constraints defined for data_in and data_out must -- be large enough to match the largest single port width signal data_in : reg_file_data_bus(0 to num_write_ports-1); signal data_out : reg_file_data_bus(0 to num_read_ports-1); signal address_write : reg_file_address_bus(0 to num_write_ports-1); signal address_read : reg_file_address_bus(0 to num_read_ports-1); signal data_in_2D : std_logic_2D_array(0 to num_write_ports-1, data_width-1 downto 0); signal data_out_2D : std_logic_2D_array(0 to 2, 7 downto 0); signal address_write_2D : std_logic_2D_array(0 to 2, 4 downto 0); signal address_read_2D : std_logic_2D_array(0 to 2, 4 downto 0); constant num_cycles : integer := 434; constant period : time := 200 ns; constant half_period : time := period / 2; signal clk : std_logic := '1'; signal simulation_time : integer := 0; type integer_array is array (natural range <>) of integer; signal address_write_int : integer_array(0 to num_write_ports-1); signal address_read_int : integer_array(0 to num_read_ports-1); signal data_write_int : integer_array(0 to num_write_ports-1); begin dut: reg_file_32_8_6port generic map ( num_write_ports => num_write_ports, num_read_ports => num_read_ports, num_bidirectional_ports => num_bidirectional_ports ) port map ( write => write_sig, read => read_sig, address_write => address_write_2D, address_read => address_read_2D, data_in => data_in_2D, data_out => data_out_2D ); -- need to convert bus types between stimulus and DUT instance g0: for i in 0 to num_write_ports-1 generate -- num of ports g1: for j in 0 to log_2(depth)-1 generate -- num of bits in address bus address_write_2D(i,j) <= address_write(i)(j); end generate g1; end generate g0; g2: for i in 0 to num_write_ports-1 generate -- num of ports g3: for j in 0 to data_width-1 generate -- num of bits in data bus data_in_2D(i,j) <= data_in(i)(j); end generate g3; end generate g2; g4: for i in 0 to num_read_ports-1 generate -- num of ports g5: for j in 0 to log_2(depth)-1 generate -- num of bits in data bus address_read_2D(i,j) <= address_read(i)(j); end generate g5; end generate g4; g6: for i in 0 to num_read_ports-1 generate -- num of ports g7: for j in 0 to data_width-1 generate -- num of bits in data bus data_out(i)(j) <= data_out_2D(i,j); end generate g7; end generate g6; s1: simulation_time <= simulation_time + 1 after period; process begin for i in 0 to num_cycles-1 loop clk <= '1'; wait for half_period; clk <= '0'; wait for half_period; end loop; wait; end process; -- data pattern to be written into each location is -- port number * 32 + address thus a write to address 0 on port 0 = 0 for data -- therefore when you read back data you should be able to tell which port it came in on -- just by subtracting the address from the data value and /'ing by 32 -- sequence -- write to addresses 0 thru 31 on ports 0..2 at same time this gives a 96-cycle -- begin reading back by a slip of 2-cycles address_write(0) <= std_logic_vector(to_unsigned(address_write_int(0), log_2(depth))); address_write(1) <= std_logic_vector(to_unsigned(address_write_int(1), log_2(depth))); address_read(0) <= std_logic_vector(to_unsigned(address_read_int(0), log_2(depth))); address_read(1) <= std_logic_vector(to_unsigned(address_read_int(1), log_2(depth))); data_in(0) <= std_logic_vector(to_unsigned(data_write_int(0), data_width)); data_in(1) <= std_logic_vector(to_unsigned(data_write_int(1), data_width)); process use std.textio.all; use ieee.std_logic_textio.all; -- file opfile : TEXT is out "_opfile.txt"; file opfile : TEXT open WRITE_MODE is "_opfile.txt"; -- file ipfile : TEXT is out "_ipfile.txt"; variable opline : line; -- variable data_out_as_string : string(1 to data_out'LENGTH); -- variable int_thing : integer; begin address_write_int(0) <= 0; address_write_int(1) <= 0; address_read_int(0) <= 0; address_read_int(1) <= 0; write_sig <= (others => '1'); read_sig <= (others => '1'); wait for period; -- 1st of all, single location write and read -- write address_write_int(0) <= 3; data_write_int(0) <= 41; write_sig(0) <= '1'; wait for period; write_sig(0) <= '0'; wait for period; write_sig(0) <= '1'; wait for period; -- read address_read_int(0) <= 3; read_sig(0) <= '1'; wait for period; read_sig(0) <= '0'; wait for half_period; -- check output here -- readline (ipfile, data_val); -- READ (data_val, int_thing); -- writeline (opfile, data_val); assert data_out(0) = data_in(0) report "Error on data_out(0) bus at time ..." severity WARNING; -- data_out_as_string := to_string(data_out(0)); -- write (data_val, data_out_as_string); -- write (opline, data_out(0)); writeline (opfile, opline); wait for half_period; read_sig(0) <= '1'; wait for period; -- two location write and read -- write address_write_int(0) <= 11; address_write_int(1) <= 19; data_write_int(0) <= 23; data_write_int(1) <= 37; write_sig(0) <= '1'; write_sig(1) <= '1'; wait for period; write_sig(0) <= '0'; write_sig(1) <= '0'; wait for period; write_sig(0) <= '1'; write_sig(1) <= '1'; wait for period; -- read address_read_int(0) <= 11; address_read_int(1) <= 19; read_sig(0) <= '1'; read_sig(1) <= '1'; wait for period; read_sig(0) <= '0'; read_sig(1) <= '0'; wait for half_period; -- check output here wait for half_period; read_sig(0) <= '1'; read_sig(1) <= '1'; wait for period; report "STOP" severity failure; wait; end process; end modular;