-- TB EXAMPLE PFRL 2023-2024 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use std.textio.all; entity project_tb is end project_tb; architecture project_tb_arch of project_tb is constant CLOCK_PERIOD : time := 20 ns; signal tb_clk : std_logic := '0'; signal tb_rst, tb_start, tb_done : std_logic; signal tb_o_task_id : std_logic_vector(5 downto 0); signal tb_task_priority, tb_op : std_logic_vector(1 downto 0); signal tb_i_task_id : std_logic_vector(5 downto 0); signal tb_o_mem_addr, exc_o_mem_addr, init_o_mem_addr : std_logic_vector(15 downto 0); signal tb_o_mem_data, exc_o_mem_data, init_o_mem_data : std_logic_vector(7 downto 0); signal tb_i_mem_data : std_logic_vector(7 downto 0); signal tb_o_mem_we, tb_o_mem_en, exc_o_mem_we, exc_o_mem_en, init_o_mem_we, init_o_mem_en : std_logic; type ram_type is array (65535 downto 0) of std_logic_vector(7 downto 0); signal RAM : ram_type := (OTHERS => "00000000"); type scenario_config_type_t is record task_id : std_logic_vector(5 downto 0); task_priority : std_logic_vector(1 downto 0); op : std_logic_vector(1 downto 0); end record scenario_config_type_t; constant SCENARIO_SIZE : integer := 9; type scenario_config_type is array (0 to SCENARIO_SIZE-1) of scenario_config_type_t; signal scenario_config : scenario_config_type := ( (task_id => "000001", task_priority => "01", op => "10"), -- Post memory: [00000001,00000101] (task_id => "000000", task_priority => "00", op => "11"), -- Post memory: [00000000] (task_id => "000001", task_priority => "01", op => "10"), -- Post memory: [00000001,00000101] (task_id => "000010", task_priority => "01", op => "10"), -- Post memory: [00000010,00000101,00001001] (task_id => "000011", task_priority => "10", op => "10"), -- Post memory: [00000011,00000101,00001001,00001110] (task_id => "000100", task_priority => "00", op => "10"), -- Post memory: [00000100,00010000,00000101,00001001,00001110] (task_id => "000000", task_priority => "00", op => "01"), -- Post memory: [00000011,00000101,00001001,00001110] (task_id => "000000", task_priority => "00", op => "00"), -- Post memory: [00000011,00000110,00001010,00001111] (task_id => "000000", task_priority => "00", op => "00") -- Post memory: [00000011,00000111,00001011,00001111] ); type scenario_single_result_type is array (0 to 32) of std_logic_vector(7 downto 0); type scenario_result_type is array (0 to 100) of scenario_single_result_type; type int_array_t is array (0 to SCENARIO_SIZE - 1) of integer; constant CHECK_SIZE_ARRAY : int_array_t := ( 2,1,2,3,4,5,4,4,4 ); signal scenario_result : scenario_result_type := ( ( "00000001", "00000101", others => "00000000"), ( "00000000", others => "00000000"), ( "00000001", "00000101", others => "00000000"), ( "00000010", "00000101", "00001001", others => "00000000"), ( "00000011", "00000101", "00001001", "00001110", others => "00000000"), ( "00000100", "00010000", "00000101", "00001001", "00001110", others => "00000000"), ( "00000011", "00000101", "00001001", "00001110", others => "00000000"), ( "00000011", "00000110", "00001010", "00001111", others => "00000000"), ( "00000011", "00000111", "00001011", "00001111", others => "00000000"), others => (others => "00000000") ); signal memory_control : std_logic := '0'; signal first_task_queue : std_logic_vector(5 downto 0); component project_reti_logiche is port ( i_clk : in std_logic; i_rst : in std_logic; i_start : in std_logic; i_task_id : in std_logic_vector(5 downto 0); i_task_priority : in std_logic_vector(1 downto 0); i_op : in std_logic_vector(1 downto 0); o_done : out std_logic; o_task_id : out std_logic_vector(5 downto 0); o_mem_addr : out std_logic_vector(15 downto 0); i_mem_data : in std_logic_vector(7 downto 0); o_mem_data : out std_logic_vector(7 downto 0); o_mem_we : out std_logic; o_mem_en : out std_logic ); end component project_reti_logiche; begin UUT : project_reti_logiche port map( i_clk => tb_clk, i_rst => tb_rst, i_start => tb_start, i_task_id => tb_i_task_id, i_task_priority => tb_task_priority, i_op => tb_op, o_done => tb_done, o_task_id => tb_o_task_id, o_mem_addr => exc_o_mem_addr, i_mem_data => tb_i_mem_data, o_mem_data => exc_o_mem_data, o_mem_we => exc_o_mem_we, o_mem_en => exc_o_mem_en ); -- Clock generation tb_clk <= not tb_clk after CLOCK_PERIOD/2; -- Process related to the memory MEM : process (tb_clk) begin if tb_clk'event and tb_clk = '1' then if tb_o_mem_en = '1' then if tb_o_mem_we = '1' then RAM(to_integer(unsigned(tb_o_mem_addr))) <= tb_o_mem_data after 1 ns; tb_i_mem_data <= tb_o_mem_data after 1 ns; else tb_i_mem_data <= RAM(to_integer(unsigned(tb_o_mem_addr))) after 1 ns; end if; end if; end if; end process; memory_signal_swapper : process(memory_control, init_o_mem_addr, init_o_mem_data, init_o_mem_en, init_o_mem_we, exc_o_mem_addr, exc_o_mem_data, exc_o_mem_en, exc_o_mem_we) begin -- This is necessary for the testbench to work: we swap the memory -- signals from the component to the testbench when needed. tb_o_mem_addr <= init_o_mem_addr; tb_o_mem_data <= init_o_mem_data; tb_o_mem_en <= init_o_mem_en; tb_o_mem_we <= init_o_mem_we; if memory_control = '1' then tb_o_mem_addr <= exc_o_mem_addr; tb_o_mem_data <= exc_o_mem_data; tb_o_mem_en <= exc_o_mem_en; tb_o_mem_we <= exc_o_mem_we; end if; end process; -- This process provides the correct scenario on the signal controlled by the TB create_scenario : process begin wait for 50 ns; -- Signal initialization and reset of the component tb_start <= '0'; tb_rst <= '1'; -- Wait some time for the component to reset... wait for 100 ns; --assert tb_done = '1' report "TEST FALLITO o_done !=1 during reset" severity failure; tb_rst <= '0'; memory_control <= '1'; -- Memory controlled by the component wait until tb_done = '0'; assert RAM(0) = "00000000" report "TEST FALLITO @ OFFSET=0 expected=0 actual=" & integer'image(to_integer(unsigned(RAM(0)))) severity failure; wait until falling_edge(tb_clk); for i in 0 to SCENARIO_SIZE - 1 loop if i > 0 then -- Save top of the queue for later use first_task_queue <= scenario_result(i-1)(1)(7 downto 2); end if; tb_op <= scenario_config(i).op; tb_i_task_id <= scenario_config(i).task_id; tb_task_priority <= scenario_config(i).task_priority; tb_start <= '1'; wait until rising_edge(tb_done); if scenario_config(i).op = "01" then -- Check output task only if the operation was the task removal assert first_task_queue = tb_o_task_id report "TEST FALLITO @ STEP=" & integer'image(i) & " expected task_id=" & integer'image(to_integer(unsigned(first_task_queue))) & " actual task_id=" & integer'image(to_integer(unsigned(tb_o_task_id))) ; end if; -- Check memory contents for j in 0 to CHECK_SIZE_ARRAY(i) - 1 loop assert RAM(j) = scenario_result(i)(j) report "TEST FALLITO @ STEP=" & integer'image(i) & " OFFSET=" & integer'image(j) & " expected=" & integer'image(to_integer(unsigned(scenario_result(i)(j)))) & " actual=" & integer'image(to_integer(unsigned(RAM(j)))) ; end loop; tb_start <= '0'; wait until falling_edge(tb_done); wait until falling_edge(tb_clk); report "Test step " & integer'image(i) & " OK."; end loop; assert false report "Simulation Ended! TEST PASSATO (EXAMPLE)" severity failure; end process; end architecture;