-- ============================================================ -- TESTBENCH TIMING - Progetto Reti Logiche 2025/2026 -- ============================================================ -- Verifica il numero di cicli di clock per ciascuna operazione. -- -- Formule attese (calibrate sull'FSM con stato S_DONE, che aggiunge -- 1 ciclo a fine operazione per garantire DONE dopo il commit in memoria): -- OP=10 inserimento: stati = 6 + 2*max(N,1) + 3k -- (N = task gia' in lista, scanditi dal controllo -- duplicati; k = task spostati per fare posto) -- OP=01 rimozione: stati = 6 + 3k (k = task spostati, lista vuota = 2) -- OP=00 decremento: stati = 4 + 3n (n = task in lista) -- -- Per ogni test viene stampato: -- - il numero di cicli misurati -- - il numero di cicli attesi -- - PASS o FAIL -- ============================================================ library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity project_tb_timing is end project_tb_timing; architecture timing_arch of project_tb_timing is constant CLOCK_PERIOD : time := 20 ns; signal tb_clk : std_logic := '0'; signal tb_rst : std_logic := '0'; signal tb_start : std_logic := '0'; signal tb_done : std_logic; signal tb_o_task_id : std_logic_vector(5 downto 0); signal tb_task_priority : std_logic_vector(1 downto 0) := "00"; signal tb_op : std_logic_vector(1 downto 0) := "00"; signal tb_i_task_id : std_logic_vector(5 downto 0) := "000000"; signal exc_o_mem_addr : std_logic_vector(15 downto 0); signal exc_o_mem_data : std_logic_vector(7 downto 0); signal exc_o_mem_we : std_logic; signal exc_o_mem_en : std_logic; signal init_o_mem_addr : std_logic_vector(15 downto 0) := (others => '0'); signal init_o_mem_data : std_logic_vector(7 downto 0) := (others => '0'); signal init_o_mem_we : std_logic := '0'; signal init_o_mem_en : std_logic := '0'; signal tb_o_mem_addr : std_logic_vector(15 downto 0); signal tb_o_mem_data : std_logic_vector(7 downto 0); signal tb_o_mem_we : std_logic; signal tb_o_mem_en : std_logic; signal tb_i_mem_data : std_logic_vector(7 downto 0); signal memory_control : std_logic := '0'; type ram_type is array (65535 downto 0) of std_logic_vector(7 downto 0); signal RAM : ram_type := (others => "00000000"); 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; 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 ); tb_clk <= not tb_clk after CLOCK_PERIOD / 2; 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 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; -- ============================================================ -- Processo principale -- ============================================================ main : process -- Cicli misurati e attesi variable t_start : time; variable cycles : integer; variable expected : integer; -- -------------------------------------------------------- -- Reset -- -------------------------------------------------------- procedure do_reset is begin tb_start <= '0'; tb_rst <= '1'; wait for 100 ns; tb_rst <= '0'; wait until tb_done = '0'; wait until falling_edge(tb_clk); end procedure; -- -------------------------------------------------------- -- Esegue un'operazione e misura i cicli dal primo fronte -- di clock dopo START=1 fino al fronte che porta DONE=1 -- -------------------------------------------------------- procedure run_and_measure ( op : std_logic_vector(1 downto 0); task_id : std_logic_vector(5 downto 0); priority : std_logic_vector(1 downto 0); exp : integer; test_num : integer ) is begin wait until falling_edge(tb_clk); tb_op <= op; tb_i_task_id <= task_id; tb_task_priority <= priority; tb_start <= '1'; -- Il primo fronte di clock dopo START campiona l'ingresso -- ed entra nel primo stato dell'operazione: inizia il conteggio wait until rising_edge(tb_clk); t_start := now; wait until rising_edge(tb_done); -- DONE viene registrato sul fronte: questo è l'ultimo stato cycles := (now - t_start) / CLOCK_PERIOD; expected := exp; if cycles = expected then report "[PASS] test=" & integer'image(test_num) & " | cicli misurati=" & integer'image(cycles) & " attesi=" & integer'image(expected); else report "[FAIL] test=" & integer'image(test_num) & " | cicli misurati=" & integer'image(cycles) & " attesi=" & integer'image(expected) severity failure; end if; tb_start <= '0'; wait until falling_edge(tb_done); end procedure; -- -------------------------------------------------------- -- Inserisce un task senza misurarlo (solo per preparare la lista) -- -------------------------------------------------------- procedure insert_silent ( task_id : std_logic_vector(5 downto 0); priority : std_logic_vector(1 downto 0) ) is begin wait until falling_edge(tb_clk); tb_op <= "10"; tb_i_task_id <= task_id; tb_task_priority <= priority; tb_start <= '1'; wait until rising_edge(tb_done); tb_start <= '0'; wait until falling_edge(tb_done); end procedure; begin memory_control <= '1'; wait for 50 ns; -- ============================================================ -- OP=10: Inserimento -> stati attesi = 6 + 4k -- ============================================================ report "=============================="; report "OP=10 Inserimento: 6 + 2*max(N,1) + 3k stati"; report "=============================="; -- N=0, k=0: lista vuota -> 6 + 2 + 0 = 8 stati -- OP=10 N=0 k=0 (lista vuota) do_reset; run_and_measure("10", "000001", "01", 8, 1); -- N=1, k=1: 1 task con priorità minore -> spostato -> 6 + 2 + 3 = 11 -- OP=10 N=1 k=1 (1 task spostato) do_reset; insert_silent("000001", "10"); run_and_measure("10", "000010", "01", 11, 2); -- N=2, k=2: 2 task da spostare -> 6 + 4 + 6 = 16 -- OP=10 N=2 k=2 (2 task spostati) do_reset; insert_silent("000001", "10"); insert_silent("000010", "10"); run_and_measure("10", "000011", "01", 16, 3); -- N=3, k=3: 3 task da spostare -> 6 + 6 + 9 = 21 -- OP=10 N=3 k=3 (3 task spostati) do_reset; insert_silent("000001", "10"); insert_silent("000010", "10"); insert_silent("000011", "10"); run_and_measure("10", "000100", "01", 21, 4); -- N=2, k=0: inserimento in fondo, lista non vuota -> 6 + 4 + 0 = 10 -- OP=10 N=2 k=0 (inserimento in fondo) do_reset; insert_silent("000001", "00"); insert_silent("000010", "01"); run_and_measure("10", "000011", "11", 10, 5); -- ============================================================ -- OP=01: Rimozione -> stati attesi = 5 + 3k (lista vuota = 1) -- ============================================================ report "=============================="; report "OP=01 Rimozione: 6 + 3k stati (lista vuota = 2)"; report "=============================="; -- Lista vuota -> 2 stati (CHECK_NUMBER + S_DONE) -- OP=01 lista vuota do_reset; run_and_measure("01", "000000", "00", 2, 6); -- k=0: 1 solo task, nessuno spostamento -> 6 stati -- OP=01 k=0 (1 task, nessuno spostamento) do_reset; insert_silent("000001", "01"); run_and_measure("01", "000000", "00", 6, 7); -- k=1: 2 task, 1 da spostare -> 9 stati -- OP=01 k=1 (1 task spostato) do_reset; insert_silent("000001", "01"); insert_silent("000010", "01"); run_and_measure("01", "000000", "00", 9, 8); -- k=2: 3 task, 2 da spostare -> 12 stati -- OP=01 k=2 (2 task spostati) do_reset; insert_silent("000001", "01"); insert_silent("000010", "01"); insert_silent("000011", "01"); run_and_measure("01", "000000", "00", 12, 9); -- k=3: 4 task, 3 da spostare -> 15 stati -- OP=01 k=3 (3 task spostati) do_reset; insert_silent("000001", "01"); insert_silent("000010", "01"); insert_silent("000011", "01"); insert_silent("000100", "01"); run_and_measure("01", "000000", "00", 15, 10); -- ============================================================ -- OP=00: Decremento -> stati attesi = 3 + 3n -- ============================================================ report "=============================="; report "OP=00 Decremento: 4 + 3n stati"; report "=============================="; -- n=0: lista vuota -> 4 stati -- OP=00 n=0 (lista vuota) do_reset; run_and_measure("00", "000000", "00", 4, 11); -- n=1 -> 7 stati -- OP=00 n=1 do_reset; insert_silent("000001", "01"); run_and_measure("00", "000000", "00", 7, 12); -- n=2 -> 10 stati -- OP=00 n=2 do_reset; insert_silent("000001", "01"); insert_silent("000010", "10"); run_and_measure("00", "000000", "00", 10, 13); -- n=3 -> 13 stati -- OP=00 n=3 do_reset; insert_silent("000001", "01"); insert_silent("000010", "10"); insert_silent("000011", "11"); run_and_measure("00", "000000", "00", 13, 14); -- n=4 con saturazione (tutti prio=3) -> 4 + 3*4 = 16 stati -- OP=00 n=4 (tutti gia prio=3, saturazione) do_reset; insert_silent("000001", "11"); insert_silent("000010", "11"); insert_silent("000011", "11"); insert_silent("000100", "11"); run_and_measure("00", "000000", "00", 16, 15); -- ============================================================ -- Fine -- ============================================================ assert false report "Tutti i test di timing sono PASSATI" severity failure; end process; end architecture;