-- ============================================================
-- TESTBENCH EDGE CASES (ESTESO) - Progetto Reti Logiche 2025/2026
-- ============================================================
-- Copre i seguenti gruppi di test:
--
-- GRUPPO 0: Reset e inizializzazione
--   0.0  Reset -> addr 0 = 0, DONE = 1 durante reset poi torna 0
--   0.1  Reset mentre operazione in corso (START=1)
--
-- GRUPPO 1: OP=10 - Inserimento
--   1.0  Insert in lista vuota
--   1.1  Insert con priorità più alta di tutti (va in testa)
--   1.2  Insert con priorità più bassa di tutti (va in fondo)
--   1.3  Insert con priorità uguale -> va in CODA agli uguali
--   1.4  Insert con tutti i task alla stessa priorità -> sempre in fondo
--   1.5  Insert con ID duplicato -> operazione ignorata
--
-- GRUPPO 2: OP=01 - Rimozione
--   2.0  Rimozione da lista vuota -> o_task_id = 000000
--   2.1  Rimozione con un solo task -> lista diventa vuota
--   2.2  Rimozione da lista con tutti task alla stessa priorità
--
-- GRUPPO 3: OP=00 - Decremento priorità
--   3.0  Decremento con lista vuota -> nessuna scrittura, no crash
--   3.1  Saturazione: task a priorità 3 restano a 3
--   3.2  Lista con TUTTI i task già a priorità 3 -> nessuna modifica
--   3.3  Mix priorità 2 e 3: i "nuovi 3" (ex-2) vengono PRIMA dei "vecchi 3"
--
-- GRUPPO 4: OP=11 - Svuota lista
--   4.0  Svuota lista popolata -> addr 0 = 0
--   4.1  Svuota lista già vuota -> addr 0 rimane 0
--   4.2  Svuota poi rimuovi -> o_task_id = 000000
--   4.3  Svuota poi decrementa -> nessun effetto
--
-- GRUPPO 5: Sequenze composite (originali)
--   5.0  Insert -> Decremento -> Rimozione: verifica ID estratto corretto
--   5.1  Sequenza di insert con priorità miste -> verifica ordinamento completo
--
-- ============================================================
-- NUOVI GRUPPI (casi limite mancanti):
-- ============================================================
--
-- GRUPPO 6: Rimozione multipla e ordinamento
--   6.0  Rimozione multipla consecutiva fino a lista vuota
--        (lista con priorità miste, verifica ordine esatto degli ID estratti
--         e che il contatore scenda correttamente a ogni step)
--   6.1  Rimozione da lista con priorità miste -> viene rimosso SEMPRE
--        il task in posizione 1 (indirizzo 1), non quello con prio numericamente
--        più bassa
--
-- GRUPPO 7: Decremento ripetuto
--   7.0  Decremento applicato più volte -> saturazione progressiva
--        (prio 0->1->2->3->3->3, verifica a ogni step)
--   7.1  Decremento su lista con un solo task (edge case singolo)
--   7.2  Decrementa -> Svuota (ordine inverso rispetto a 4.3)
--
-- GRUPPO 8: Insert dopo rimozione parziale
--   8.0  Insert -> Rimozione parziale -> Insert -> verifica ordinamento completo
--   8.1  Insert con priority=0 in lista con tutti prio=0
--        (il nuovo va sempre in fondo, indipendentemente da prio uguale)
--   8.2  Insert con priority=3 in lista con tutti prio=3
--        (simmetrico: il nuovo va sempre in fondo)
--
-- GRUPPO 9: Verifica o_task_id per OP != 01
--   9.0  OP=10 (insert) -> o_task_id deve essere 0x00 quando DONE=1
--   9.1  OP=00 (decremento) -> o_task_id deve essere 0x00 quando DONE=1
--   9.2  OP=11 (svuota) -> o_task_id deve essere 0x00 quando DONE=1
--   9.3  OP=01 lista vuota -> o_task_id deve essere 0x00 quando DONE=1
--
-- GRUPPO 10: Protocollo START-DONE e reset
--   10.0 Operazione immediata al primo fronte dopo DONE->0 post-reset
--        (nessun ciclo di margine tra fine reset e primo START)
--   10.1 Sequenza lunga stress: insert x8 -> dec x3 -> remove x4
--        -> insert x3 -> remove fino a vuota (verifica coerenza totale)
--   10.2 Reset dopo OP=11 (svuota -> reset -> verifica lista vuota)
--
-- GRUPPO 11: OP=10 con ID=0 (condizione di errore da specifica)
--   11.0 Insert ID=0 in lista vuota -> ignorato, DONE arriva comunque
--   11.1 Insert ID=0 in lista popolata (prio alta e bassa) -> lista invariata
--
-- GRUPPO 12: Capacita' massima (63 task, errata del 24.02.2026)
--   12.0 Insert di TUTTI i 63 ID possibili, verifica completa della memoria
--   12.1 Inserimenti oltre il 63esimo (ogni ID e' duplicato) -> ignorati
--   12.2 Drain completo: 63 pop con verifica dell'ordine di estrazione
--
-- GRUPPO 13: Memoria stale e duplicati ai bordi della lista
--   13.0 Re-insert di ID appena rimosso (copia stale oltre il count)
--   13.1 Duplicato in PRIMA posizione -> ignorato
--   13.2 Duplicato in ULTIMA posizione -> ignorato
--   13.3 Clear poi re-insert dello stesso ID (cella stale) -> deve riuscire
--
-- GRUPPO 14: Reset asincrono avanzato (spec: RESET in qualsiasi momento)
--   14.0 Reset a meta' dello shift di OP=01
--   14.1 Reset nel ciclo di scrittura del count (fine OP=01)
--   14.2 Reset a meta' della scansione di OP=00
--   14.3 Reset mentre DONE=1
--   14.4 Reset corto (7 ns, non allineato al clock)
--
-- GRUPPO 15: Protocollo START-DONE con abbassamento lento di START
--   15.0 Pop con START alto 1 ciclo extra -> niente doppio pop
--   15.1 Age con START alto 1 ciclo extra -> niente doppio age
--   15.2 Insert con START alto 2 cicli extra
--   NOTA: il gruppo 15 FALLISCE con l'RTL attuale finche' non viene
--   aggiunto uno stato S_DONE che attende START=0 prima di tornare in IDLE.
--
-- MONITOR concorrente: nessuna scrittura in memoria quando il modulo
-- dovrebbe essere idle (RST=0, START=0, DONE=0).
--
-- ============================================================

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

entity project_tb_edge is
end project_tb_edge;

architecture project_tb_edge_arch of project_tb_edge is

    constant CLOCK_PERIOD : time := 20 ns;
    signal tb_clk         : std_logic := '0';
    signal tb_rst         : std_logic;
    signal tb_start       : std_logic;
    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);
    signal tb_op            : std_logic_vector(1 downto 0);
    signal tb_i_task_id     : std_logic_vector(5 downto 0);

    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");

    -- --------------------------------------------------------
    -- Utility: tipo per verifiche memoria
    -- --------------------------------------------------------
    type mem_check_t is record
        addr     : integer;
        expected : std_logic_vector(7 downto 0);
    end record;

    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
    tb_clk <= not tb_clk after CLOCK_PERIOD / 2;

    -- Memoria
    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;

    -- Mux memoria: init_o / exc_o
    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;

    -- ============================================================
    -- MONITOR: scritture spurie
    -- Se il modulo e' idle (RST=0, START=0, DONE=0) non deve scrivere
    -- in memoria. Una scrittura qui indica o una ri-esecuzione indebita
    -- dell'operazione (protocollo START-DONE violato) o segnali di
    -- controllo memoria non azzerati.
    -- Campionato sul fronte di discesa per evitare race con i registri.
    -- ============================================================
    protocol_monitor : process (tb_clk)
    begin
        if falling_edge(tb_clk) then
            if tb_rst = '0' and tb_done = '0' and tb_start = '0' then
                assert not (exc_o_mem_en = '1' and exc_o_mem_we = '1')
                    report "FAIL [MONITOR] scrittura in memoria con modulo idle "
                           & "(RST=0, START=0, DONE=0): possibile ri-esecuzione "
                           & "dell'operazione o segnali di scrittura spuri"
                    severity failure;
            end if;
        end if;
    end process;

    -- ============================================================
    -- Processo principale di test
    -- ============================================================
    main_test : process

        -- --------------------------------------------------------
        -- Procedure di supporto
        -- --------------------------------------------------------

        -- Reset del componente (attende DONE=1 durante reset poi DONE=0)
        procedure do_reset is
        begin
            tb_start <= '0';
            tb_rst   <= '1';
            wait for 100 ns;
            -- DONE deve essere 1 durante il reset (modulo non pronto)
            assert tb_done = '1'
                report "FAIL: DONE dovrebbe essere 1 durante reset"
                severity failure;
            tb_rst <= '0';
            -- Attende che il modulo completi l'inizializzazione (DONE->0)
            wait until tb_done = '0';
            wait until falling_edge(tb_clk);
        end procedure;

        -- Lancia un'operazione e attende DONE=1
        procedure do_op (
            op       : std_logic_vector(1 downto 0);
            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             <= op;
            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;

        -- Lancia un'operazione, cattura o_task_id al momento di DONE=1,
        -- e restituisce il valore campionato nel segnale out_id
        procedure do_op_capture (
            op       : std_logic_vector(1 downto 0);
            task_id  : std_logic_vector(5 downto 0);
            priority : std_logic_vector(1 downto 0);
            captured : out std_logic_vector(5 downto 0)
        ) is
        begin
            wait until falling_edge(tb_clk);
            tb_op             <= op;
            tb_i_task_id      <= task_id;
            tb_task_priority  <= priority;
            tb_start          <= '1';
            wait until rising_edge(tb_done);
            captured  := tb_o_task_id;   -- campiona al momento esatto di DONE=1
            tb_start  <= '0';
            wait until falling_edge(tb_done);
        end procedure;

        -- Verifica un singolo indirizzo di memoria
        procedure check_mem (
            step     : string;
            addr     : integer;
            expected : std_logic_vector(7 downto 0)
        ) is
        begin
            assert RAM(addr) = expected
                report "FAIL [" & step & "] addr=" & integer'image(addr)
                       & " expected=0x" & integer'image(to_integer(unsigned(expected)))
                       & " actual=0x"   & integer'image(to_integer(unsigned(RAM(addr))))
                severity failure;
        end procedure;

        -- Verifica o_task_id (usata dopo do_op_capture)
        procedure check_captured_id (
            step     : string;
            actual   : std_logic_vector(5 downto 0);
            expected : std_logic_vector(5 downto 0)
        ) is
        begin
            assert actual = expected
                report "FAIL [" & step & "] o_task_id expected="
                       & integer'image(to_integer(unsigned(expected)))
                       & " actual="
                       & integer'image(to_integer(unsigned(actual)))
                severity failure;
        end procedure;

        -- Verifica o_task_id (campionato in tempo reale)
        procedure check_task_id (
            step     : string;
            expected : std_logic_vector(5 downto 0)
        ) is
        begin
            assert tb_o_task_id = expected
                report "FAIL [" & step & "] o_task_id expected="
                       & integer'image(to_integer(unsigned(expected)))
                       & " actual="
                       & integer'image(to_integer(unsigned(tb_o_task_id)))
                severity failure;
        end procedure;

        -- Azzera la RAM (usato per isolare i gruppi di test)
        procedure clear_ram is
        begin
            memory_control <= '0';
            for i in 0 to 70 loop
                init_o_mem_addr <= std_logic_vector(to_unsigned(i, 16));
                init_o_mem_data <= "00000000";
                init_o_mem_en   <= '1';
                init_o_mem_we   <= '1';
                wait until rising_edge(tb_clk);
            end loop;
            init_o_mem_en   <= '0';
            init_o_mem_we   <= '0';
            memory_control  <= '1';
        end procedure;

        -- Inserisce N task nella lista
        procedure fill_list (n : integer; base_id : integer; prio : std_logic_vector(1 downto 0)) is
        begin
            for k in 0 to n-1 loop
                do_op("10",
                      std_logic_vector(to_unsigned(base_id + k, 6)),
                      prio);
            end loop;
        end procedure;

        -- Variabili locali per catturare il task_id restituito
        variable captured_id : std_logic_vector(5 downto 0);

        -- Modello di riferimento per il test a capacita' massima (gruppo 12)
        type int_array63_t is array (1 to 63) of integer;
        variable exp_id   : int_array63_t;
        variable exp_prio : int_array63_t;
        variable idx      : integer;
        variable exp_byte : std_logic_vector(7 downto 0);

    begin
        -- Inizializzazione segnali
        tb_start         <= '0';
        tb_rst           <= '0';
        tb_op            <= "00";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        memory_control   <= '1';

        wait for 50 ns;

        -- ============================================================
        -- GRUPPO 0: Reset e inizializzazione
        -- ============================================================

        -- 0.0: Reset base -> addr 0 deve essere 0, DONE=1 durante reset
        report "=== GRUPPO 0: Reset ===";
        memory_control <= '0';
        tb_rst <= '1';
        wait for 100 ns;
        assert tb_done = '1'
            report "FAIL [0.0] DONE deve essere 1 durante reset"
            severity failure;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("0.0 reset-addr0", 0, "00000000");
        memory_control <= '1';
        report "Test 0.0 OK: reset base";

        -- 0.1: Reset mentre operazione in corso
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "10";
        tb_i_task_id     <= "000001";
        tb_task_priority <= "01";
        tb_start         <= '1';
        wait until rising_edge(tb_clk);
        wait until rising_edge(tb_clk);
        tb_rst   <= '1';
        tb_start <= '0';
        wait for 50 ns;
        assert tb_done = '1'
            report "FAIL [0.1] DONE deve essere 1 durante reset asincrono"
            severity failure;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("0.1 reset-async", 0, "00000000");
        report "Test 0.1 OK: reset asincrono durante operazione";

        -- ============================================================
        -- GRUPPO 1: OP=10 - Inserimento
        -- ============================================================
        report "=== GRUPPO 1: Inserimento ===";

        -- 1.0: Insert in lista vuota
        clear_ram;
        do_reset;
        do_op("10", "000001", "10");
        check_mem("1.0 count",  0, "00000001");
        check_mem("1.0 task",   1, "00000110");
        report "Test 1.0 OK: insert in lista vuota";

        -- 1.1: Insert con priorità più alta di tutti (va in testa)
        clear_ram;
        do_reset;
        do_op("10", "000010", "10");
        do_op("10", "000011", "10");
        do_op("10", "000001", "00");
        check_mem("1.1 count", 0, "00000011");
        check_mem("1.1 pos1",  1, "00000100");
        check_mem("1.1 pos2",  2, "00001010");
        check_mem("1.1 pos3",  3, "00001110");
        report "Test 1.1 OK: insert con priorità massima in testa";

        -- 1.2: Insert con priorità più bassa di tutti (va in fondo)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("10", "000010", "01");
        do_op("10", "000011", "11");
        check_mem("1.2 count", 0, "00000011");
        check_mem("1.2 pos1",  1, "00000100");
        check_mem("1.2 pos2",  2, "00001001");
        check_mem("1.2 pos3",  3, "00001111");
        report "Test 1.2 OK: insert con priorità minima in fondo";

        -- 1.3: Insert con priorità uguale -> va in CODA agli uguali
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "01");
        do_op("10", "000011", "01");
        check_mem("1.3 count", 0, "00000011");
        check_mem("1.3 pos1",  1, "00000101");
        check_mem("1.3 pos2",  2, "00001001");
        check_mem("1.3 pos3",  3, "00001101");
        report "Test 1.3 OK: insert stesso prio -> va in coda agli uguali";

        -- 1.4: Insert con tutti task stessa priorità -> sempre in fondo
        clear_ram;
        do_reset;
        do_op("10", "000001", "10");
        do_op("10", "000010", "10");
        do_op("10", "000011", "10");
        do_op("10", "000100", "10");
        check_mem("1.4 count", 0, "00000100");
        check_mem("1.4 pos1",  1, "00000110");
        check_mem("1.4 pos2",  2, "00001010");
        check_mem("1.4 pos3",  3, "00001110");
        check_mem("1.4 pos4",  4, "00010010");
        report "Test 1.4 OK: insert con tutti uguale prio -> sempre in fondo";

        -- 1.5: Insert con ID duplicato -> operazione ignorata
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "01");
        do_op("10", "000011", "01");
        check_mem("1.5 count-pre",  0, "00000011");
        check_mem("1.5 pos1-pre",   1, "00000101");
        check_mem("1.5 pos2-pre",   2, "00001001");
        check_mem("1.5 pos3-pre",   3, "00001101");
        do_op("10", "000010", "00");
        check_mem("1.5 count-post", 0, "00000011");
        check_mem("1.5 pos1-post",  1, "00000101");
        check_mem("1.5 pos2-post",  2, "00001001");
        check_mem("1.5 pos3-post",  3, "00001101");
        check_mem("1.5 pos4-post",  4, "00000000");
        report "Test 1.5 OK: insert con ID duplicato ignorato";

        -- ============================================================
        -- GRUPPO 2: OP=01 - Rimozione
        -- ============================================================
        report "=== GRUPPO 2: Rimozione ===";

        -- 2.0: Rimozione da lista vuota -> o_task_id = 000000
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("2.0 empty-remove", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        check_mem("2.0 count", 0, "00000000");
        report "Test 2.0 OK: rimozione da lista vuota -> o_task_id=0";

        -- 2.1: Rimozione con un solo task -> lista diventa vuota
        clear_ram;
        do_reset;
        do_op("10", "000101", "01");
        check_mem("2.1 pre-count", 0, "00000001");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("2.1 single-remove", "000101");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        check_mem("2.1 post-count", 0, "00000000");
        report "Test 2.1 OK: rimozione unico task -> lista vuota, task_id corretto";

        -- 2.2: Rimozione da lista con tutti task alla stessa priorità -> FIFO
        clear_ram;
        do_reset;
        do_op("10", "000001", "10");
        do_op("10", "000010", "10");
        do_op("10", "000011", "10");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("2.2 same-prio-remove", "000001");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        check_mem("2.2 count", 0, "00000010");
        check_mem("2.2 pos1",  1, "00001010");
        check_mem("2.2 pos2",  2, "00001110");
        report "Test 2.2 OK: rimozione con prio uguali -> FIFO rispettato";

        -- ============================================================
        -- GRUPPO 3: OP=00 - Decremento priorità
        -- ============================================================
        report "=== GRUPPO 3: Decremento priorità ===";

        -- 3.0: Decremento con lista vuota -> nessun crash
        clear_ram;
        do_reset;
        do_op("00", "000000", "00");
        check_mem("3.0 count", 0, "00000000");
        report "Test 3.0 OK: decremento su lista vuota";

        -- 3.1: Saturazione: task a priorità 3 restano a 3
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "11");
        do_op("00", "000000", "00");
        check_mem("3.1 count", 0, "00000010");
        check_mem("3.1 pos1",  1, "00000110");
        check_mem("3.1 pos2",  2, "00001011");
        report "Test 3.1 OK: saturazione a priorità 3";

        -- 3.2: Lista con TUTTI i task già a priorità 3 -> nessuna modifica
        clear_ram;
        do_reset;
        do_op("10", "000001", "11");
        do_op("10", "000010", "11");
        do_op("10", "000011", "11");
        do_op("00", "000000", "00");
        check_mem("3.2 count", 0, "00000011");
        check_mem("3.2 pos1",  1, "00000111");
        check_mem("3.2 pos2",  2, "00001011");
        check_mem("3.2 pos3",  3, "00001111");
        report "Test 3.2 OK: tutti a prio 3 -> nessuna modifica";

        -- 3.3: Mix priorità 2 e 3: gli ex-2 precedono gli ex-3
        clear_ram;
        do_reset;
        do_op("10", "000001", "10");
        do_op("10", "000010", "10");
        do_op("10", "000011", "11");
        do_op("10", "000100", "11");
        do_op("00", "000000", "00");
        check_mem("3.3 count", 0, "00000100");
        check_mem("3.3 pos1",  1, "00000111");
        check_mem("3.3 pos2",  2, "00001011");
        check_mem("3.3 pos3",  3, "00001111");
        check_mem("3.3 pos4",  4, "00010011");
        report "Test 3.3 OK: ex-prio2 vengono prima di ex-prio3 (no riordino)";

        -- ============================================================
        -- GRUPPO 4: OP=11 - Svuota lista
        -- ============================================================
        report "=== GRUPPO 4: Svuota lista ===";

        -- 4.0: Svuota lista popolata -> addr 0 = 0
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("10", "000010", "01");
        do_op("10", "000011", "10");
        do_op("11", "000000", "00");
        check_mem("4.0 count", 0, "00000000");
        report "Test 4.0 OK: svuota lista popolata";

        -- 4.1: Svuota lista già vuota -> addr 0 rimane 0, nessun crash
        clear_ram;
        do_reset;
        do_op("11", "000000", "00");
        check_mem("4.1 count", 0, "00000000");
        report "Test 4.1 OK: svuota lista già vuota";

        -- 4.2: Svuota poi rimuovi -> o_task_id = 000000
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("11", "000000", "00");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("4.2 remove-after-clear", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        report "Test 4.2 OK: svuota poi rimozione -> o_task_id=0";

        -- 4.3: Svuota poi decrementa -> nessun effetto
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("11", "000000", "00");
        do_op("00", "000000", "00");
        check_mem("4.3 count", 0, "00000000");
        report "Test 4.3 OK: svuota poi decrementa -> nessun effetto";

        -- ============================================================
        -- GRUPPO 5: Sequenze composite (originali)
        -- ============================================================
        report "=== GRUPPO 5: Sequenze composite ===";

        -- 5.0: Insert -> Decremento -> Rimozione
        clear_ram;
        do_reset;
        do_op("10", "001010", "00");
        do_op("10", "010100", "01");
        do_op("10", "011110", "10");
        do_op("00", "000000", "00");
        check_mem("5.0 after-dec pos1", 1, "00101001");
        check_mem("5.0 after-dec pos2", 2, "01010010");
        check_mem("5.0 after-dec pos3", 3, "01111011");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("5.0 remove-after-dec", "001010");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        check_mem("5.0 count",  0, "00000010");
        check_mem("5.0 pos1",   1, "01010010");
        check_mem("5.0 pos2",   2, "01111011");
        report "Test 5.0 OK: insert->dec->remove, ID estratto corretto";

        -- 5.1: Ordinamento completo con priorità miste
        clear_ram;
        do_reset;
        do_op("10", "000101", "11");
        do_op("10", "000011", "01");
        do_op("10", "000111", "10");
        do_op("10", "000001", "00");
        do_op("10", "001001", "01");
        check_mem("5.1 count", 0, "00000101");
        check_mem("5.1 pos1",  1, "00000100");
        check_mem("5.1 pos2",  2, "00001101");
        check_mem("5.1 pos3",  3, "00100101");
        check_mem("5.1 pos4",  4, "00011110");
        check_mem("5.1 pos5",  5, "00010111");
        report "Test 5.1 OK: ordinamento completo con priorità miste";


        -- ============================================================
        -- GRUPPO 6: Rimozione multipla e ordinamento
        -- ============================================================
        report "=== GRUPPO 6: Rimozione multipla e ordinamento ===";

        -- 6.0: Rimozione multipla consecutiva fino a lista vuota
        --
        -- Lista inserita: id=1 prio=0, id=2 prio=1, id=3 prio=1, id=4 prio=2
        -- Ordine atteso di estrazione: 1, 2, 3, 4 (la rimozione prende sempre pos 1)
        -- Dopo ogni rimozione verifichiamo: l'ID estratto, il count e la struttura
        -- della lista residua.
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, prio=0
        do_op("10", "000010", "01");  -- id=2, prio=1
        do_op("10", "000011", "01");  -- id=3, prio=1
        do_op("10", "000100", "10");  -- id=4, prio=2
        check_mem("6.0 init-count", 0, "00000100");

        -- Prima rimozione: deve uscire id=1
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.0 remove1-id", captured_id, "000001");
        check_mem("6.0 after-rem1 count", 0, "00000011");
        check_mem("6.0 after-rem1 pos1",  1, "00001001");  -- id=2, prio=1
        check_mem("6.0 after-rem1 pos2",  2, "00001101");  -- id=3, prio=1
        check_mem("6.0 after-rem1 pos3",  3, "00010010");  -- id=4, prio=2

        -- Seconda rimozione: deve uscire id=2
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.0 remove2-id", captured_id, "000010");
        check_mem("6.0 after-rem2 count", 0, "00000010");
        check_mem("6.0 after-rem2 pos1",  1, "00001101");  -- id=3, prio=1
        check_mem("6.0 after-rem2 pos2",  2, "00010010");  -- id=4, prio=2

        -- Terza rimozione: deve uscire id=3
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.0 remove3-id", captured_id, "000011");
        check_mem("6.0 after-rem3 count", 0, "00000001");
        check_mem("6.0 after-rem3 pos1",  1, "00010010");  -- id=4, prio=2

        -- Quarta rimozione: deve uscire id=4, lista diventa vuota
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.0 remove4-id", captured_id, "000100");
        check_mem("6.0 after-rem4 count", 0, "00000000");

        -- Quinta rimozione su lista vuota: deve restituire id=0
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.0 remove5-empty", captured_id, "000000");
        check_mem("6.0 after-rem5 count", 0, "00000000");

        report "Test 6.0 OK: rimozioni multiple consecutive fino a lista vuota";

        -- 6.1: Rimozione da lista con priorità miste
        --
        -- SCOPO: verificare che OP=01 rimuova SEMPRE il task in posizione 1 (addr 1),
        -- NON il task con il valore di priorità numericamente più basso.
        -- In questo test, il task in posizione 1 ha prio=2 (non la "migliore"),
        -- perché la lista è stata costruita in un ordine specifico tramite inserimenti
        -- successivi con decremento.
        --
        -- Costruiamo: id=5 prio=1, id=7 prio=3, poi decrementiamo.
        -- Dopo il decremento: id=5 diventa prio=2, id=7 resta prio=3
        -- La lista è: [pos1: id=5 prio=2] [pos2: id=7 prio=3]
        -- La rimozione deve estrarre id=5 (posizione 1), non id=7.
        clear_ram;
        do_reset;
        do_op("10", "000101", "01");  -- id=5, prio=1
        do_op("10", "000111", "11");  -- id=7, prio=3
        -- Lista: [id=5,p1] [id=7,p3]
        do_op("00", "000000", "00");  -- decremento
        -- Lista dopo dec: [id=5,p2] [id=7,p3]
        check_mem("6.1 pre-pos1", 1, "00010110");  -- id=5, prio=2
        check_mem("6.1 pre-pos2", 2, "00011111");  -- id=7, prio=3
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("6.1 remove-from-mixed", captured_id, "000101");  -- deve uscire id=5 (pos 1)
        check_mem("6.1 post-count", 0, "00000001");
        check_mem("6.1 post-pos1",  1, "00011111");  -- rimane id=7
        report "Test 6.1 OK: rimozione da lista con prio miste -> sempre posizione 1";


        -- ============================================================
        -- GRUPPO 7: Decremento ripetuto
        -- ============================================================
        report "=== GRUPPO 7: Decremento ripetuto ===";

        -- 7.0: Decremento applicato 4 volte su un task partendo da prio=0
        --      Sequenza attesa: 0 -> 1 -> 2 -> 3 -> 3 (satura)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, prio=0
        check_mem("7.0 init",  1, "00000100");  -- id=1, prio=0

        do_op("00", "000000", "00");  -- 1° decremento: prio 0->1
        check_mem("7.0 dec1",  1, "00000101");  -- id=1, prio=1
        check_mem("7.0 dec1-count", 0, "00000001");

        do_op("00", "000000", "00");  -- 2° decremento: prio 1->2
        check_mem("7.0 dec2",  1, "00000110");  -- id=1, prio=2

        do_op("00", "000000", "00");  -- 3° decremento: prio 2->3
        check_mem("7.0 dec3",  1, "00000111");  -- id=1, prio=3

        do_op("00", "000000", "00");  -- 4° decremento: prio 3->3 (saturazione)
        check_mem("7.0 dec4-sat", 1, "00000111");  -- id=1, prio=3 (invariato)
        check_mem("7.0 dec4-count", 0, "00000001");  -- count invariato

        do_op("00", "000000", "00");  -- 5° decremento: ancora saturazione
        check_mem("7.0 dec5-sat", 1, "00000111");  -- id=1, prio=3 (ancora invariato)
        report "Test 7.0 OK: saturazione progressiva 0->1->2->3->3->3";

        -- 7.0b: Decremento ripetuto su lista con task a priorità miste
        --       Verifica che ogni task segua la propria traiettoria di saturazione
        --       indipendentemente dagli altri
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, prio=0
        do_op("10", "000010", "01");  -- id=2, prio=1
        do_op("10", "000011", "10");  -- id=3, prio=2
        do_op("10", "000100", "11");  -- id=4, prio=3

        do_op("00", "000000", "00");  -- 1° decremento
        -- id=1: 0->1, id=2: 1->2, id=3: 2->3, id=4: 3->3 (sat)
        -- ATTENZIONE: dopo il decremento l'ORDINE rimane invariato (no riordino)
        -- quindi la struttura fisica della lista NON cambia posizione
        check_mem("7.0b dec1-pos1", 1, "00000101");  -- id=1, prio=1
        check_mem("7.0b dec1-pos2", 2, "00001010");  -- id=2, prio=2
        check_mem("7.0b dec1-pos3", 3, "00001111");  -- id=3, prio=3
        check_mem("7.0b dec1-pos4", 4, "00010011");  -- id=4, prio=3 (saturato)

        do_op("00", "000000", "00");  -- 2° decremento
        -- id=1: 1->2, id=2: 2->3, id=3: 3->3 (sat), id=4: 3->3 (sat)
        check_mem("7.0b dec2-pos1", 1, "00000110");  -- id=1, prio=2
        check_mem("7.0b dec2-pos2", 2, "00001011");  -- id=2, prio=3
        check_mem("7.0b dec2-pos3", 3, "00001111");  -- id=3, prio=3 (saturato)
        check_mem("7.0b dec2-pos4", 4, "00010011");  -- id=4, prio=3 (saturato)

        do_op("00", "000000", "00");  -- 3° decremento: tutti saturano a 3
        check_mem("7.0b dec3-pos1", 1, "00000111");  -- id=1, prio=3
        check_mem("7.0b dec3-pos2", 2, "00001011");  -- id=2, prio=3
        check_mem("7.0b dec3-pos3", 3, "00001111");  -- id=3, prio=3
        check_mem("7.0b dec3-pos4", 4, "00010011");  -- id=4, prio=3
        report "Test 7.0b OK: decremento ripetuto su prio miste, saturazione indipendente";

        -- 7.1: Decremento su lista con un solo task
        clear_ram;
        do_reset;
        do_op("10", "001111", "01");  -- id=15, prio=1
        do_op("00", "000000", "00");  -- decremento
        check_mem("7.1 count", 0, "00000001");
        check_mem("7.1 pos1",  1, "00111110");  -- id=15, prio=2
        do_op("00", "000000", "00");  -- secondo decremento
        check_mem("7.1 pos1b", 1, "00111111");  -- id=15, prio=3
        do_op("00", "000000", "00");  -- terzo decremento: satura
        check_mem("7.1 pos1c", 1, "00111111");  -- id=15, prio=3 (invariato)
        report "Test 7.1 OK: decremento su lista con un solo task";

        -- 7.2: Decrementa poi Svuota
        --      (ordine inverso rispetto al test 4.3 che fa svuota->decrementa)
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "10");
        do_op("00", "000000", "00");  -- decremento: modifica i task
        -- Ora svuotiamo: deve azzerare solo il count
        do_op("11", "000000", "00");
        check_mem("7.2 count", 0, "00000000");
        -- Rimozione su lista appena svuotata deve restituire 0
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("7.2 remove-after-clear", captured_id, "000000");
        report "Test 7.2 OK: decrementa -> svuota -> rimozione su vuota";


        -- ============================================================
        -- GRUPPO 8: Insert dopo rimozione parziale e casi limite prio 0/3
        -- ============================================================
        report "=== GRUPPO 8: Insert dopo rimozione e casi limite ===";

        -- 8.0: Insert -> Rimozione parziale -> Insert -> verifica ordinamento
        --
        -- Fase 1: inseriamo id=1(p0), id=2(p1), id=3(p2)
        -- Fase 2: rimuoviamo 2 volte -> restano: id=2(p1), id=3(p2)
        -- Fase 3: inseriamo id=10(p0) e id=20(p2)
        -- Risultato atteso: id=10(p0), id=2(p1), id=3(p2), id=20(p2)
        --   id=20 va in coda agli elementi con prio=2 (dopo id=3)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, prio=0
        do_op("10", "000010", "01");  -- id=2, prio=1
        do_op("10", "000011", "10");  -- id=3, prio=2

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.0 rem1", captured_id, "000001");  -- esce id=1

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.0 rem2", captured_id, "000010");  -- esce id=2

        -- Ora la lista contiene solo id=3(p2)
        check_mem("8.0 mid-count", 0, "00000001");
        check_mem("8.0 mid-pos1",  1, "00001110");  -- id=3, prio=2

        do_op("10", "001010", "00");  -- id=10, prio=0 -> va in testa
        do_op("10", "010100", "10");  -- id=20, prio=2 -> va in coda agli p2

        check_mem("8.0 final-count", 0, "00000011");
        check_mem("8.0 final-pos1",  1, "00101000");  -- id=10, prio=0
        check_mem("8.0 final-pos2",  2, "00001110");  -- id=3,  prio=2
        check_mem("8.0 final-pos3",  3, "01010010");  -- id=20, prio=2
        report "Test 8.0 OK: insert dopo rimozione parziale, ordinamento corretto";

        -- 8.1: Insert con priority=0 in lista dove tutti hanno prio=0
        --      Il nuovo task deve andare sempre IN FONDO (FIFO tra pari priorità)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, prio=0
        do_op("10", "000010", "00");  -- id=2, prio=0
        do_op("10", "000011", "00");  -- id=3, prio=0 -> va in fondo agli p=0
        check_mem("8.1 count", 0, "00000011");
        check_mem("8.1 pos1",  1, "00000100");  -- id=1, prio=0
        check_mem("8.1 pos2",  2, "00001000");  -- id=2, prio=0
        check_mem("8.1 pos3",  3, "00001100");  -- id=3, prio=0
        -- Rimuoviamo per verificare l'ordine FIFO
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.1 rem1-fifo", captured_id, "000001");  -- esce il primo inserito
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.1 rem2-fifo", captured_id, "000010");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.1 rem3-fifo", captured_id, "000011");
        report "Test 8.1 OK: insert prio=0 in lista tutto-prio=0, FIFO rispettato";

        -- 8.2: Insert con priority=3 in lista dove tutti hanno prio=3
        --      Simmetrico all'8.1: il nuovo va sempre in fondo
        clear_ram;
        do_reset;
        do_op("10", "000001", "11");  -- id=1, prio=3
        do_op("10", "000010", "11");  -- id=2, prio=3
        do_op("10", "000011", "11");  -- id=3, prio=3 -> va in fondo agli p=3
        check_mem("8.2 count", 0, "00000011");
        check_mem("8.2 pos1",  1, "00000111");  -- id=1, prio=3
        check_mem("8.2 pos2",  2, "00001011");  -- id=2, prio=3
        check_mem("8.2 pos3",  3, "00001111");  -- id=3, prio=3
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.2 rem1-fifo", captured_id, "000001");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.2 rem2-fifo", captured_id, "000010");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("8.2 rem3-fifo", captured_id, "000011");
        report "Test 8.2 OK: insert prio=3 in lista tutto-prio=3, FIFO rispettato";


        -- ============================================================
        -- GRUPPO 9: Verifica o_task_id per OP != 01
        -- ============================================================
        -- La specifica richiede che o_task_id sia valido (= ID estratto) quando
        -- DONE=1 per OP=01. Per le altre operazioni, il modulo non estrae nessun
        -- task e quindi o_task_id deve valere 0x00 al momento di DONE=1.
        -- Questi test verificano che non ci siano "fughe" di valori spuri.
        report "=== GRUPPO 9: o_task_id per OP diverso da 01 ===";

        -- 9.0: OP=10 (insert) -> o_task_id deve essere 000000 a DONE=1
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "10";
        tb_i_task_id     <= "001111";  -- id=15
        tb_task_priority <= "01";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("9.0 insert-task-id", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        report "Test 9.0 OK: OP=10 -> o_task_id=0 quando DONE=1";

        -- 9.1: OP=00 (decremento) -> o_task_id deve essere 000000 a DONE=1
        clear_ram;
        do_reset;
        do_op("10", "001111", "01");  -- prima inseriamo qualcosa
        wait until falling_edge(tb_clk);
        tb_op            <= "00";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("9.1 decrement-task-id", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        report "Test 9.1 OK: OP=00 -> o_task_id=0 quando DONE=1";

        -- 9.2: OP=11 (svuota) -> o_task_id deve essere 000000 a DONE=1
        clear_ram;
        do_reset;
        do_op("10", "001111", "01");
        wait until falling_edge(tb_clk);
        tb_op            <= "11";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("9.2 clear-task-id", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        report "Test 9.2 OK: OP=11 -> o_task_id=0 quando DONE=1";

        -- 9.3: OP=01 su lista vuota -> o_task_id deve essere 000000 a DONE=1
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("9.3 remove-empty-task-id", "000000");
        tb_start <= '0';
        wait until falling_edge(tb_done);
        report "Test 9.3 OK: OP=01 lista vuota -> o_task_id=0 quando DONE=1";


        -- ============================================================
        -- GRUPPO 10: Protocollo START-DONE, reset avanzato e stress test
        -- ============================================================
        report "=== GRUPPO 10: Protocollo, reset avanzato, stress ===";

        -- 10.0: Operazione immediata sul primo fronte disponibile dopo DONE->0
        --       Verifica che il modulo accetti START=1 senza cicli di margine
        --       tra la fine del reset e l'inizio dell'operazione.
        clear_ram;
        tb_start <= '0';
        tb_rst   <= '1';
        wait for 100 ns;
        tb_rst <= '0';
        -- Aspettiamo DONE->0 e SUL FRONTE DI DISCESA STESSO alziamo START
        wait until falling_edge(tb_done);
        -- Non usiamo wait until falling_edge(tb_clk) extra: start immediato
        tb_op            <= "10";
        tb_i_task_id     <= "000111";  -- id=7
        tb_task_priority <= "01";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("10.0 immediate-start-task-id", "000000");  -- non è OP=01
        tb_start <= '0';
        wait until falling_edge(tb_done);
        check_mem("10.0 count", 0, "00000001");
        check_mem("10.0 pos1",  1, "00011101");  -- id=7, prio=1
        report "Test 10.0 OK: operazione immediata dopo DONE->0 post-reset";

        -- 10.1: Sequenza lunga di stress
        --
        -- Fase A: insert 8 task con priorità miste
        --   id=1 p=0, id=2 p=2, id=3 p=1, id=4 p=3,
        --   id=5 p=0, id=6 p=2, id=7 p=1, id=8 p=3
        -- Ordine atteso dopo tutti gli insert:
        --   pos1: id=1 p=0    (00000100)
        --   pos2: id=5 p=0    (00010100)
        --   pos3: id=3 p=1    (00001101)
        --   pos4: id=7 p=1    (00011101)
        --   pos5: id=2 p=2    (00001010)
        --   pos6: id=6 p=2    (00011010)
        --   pos7: id=4 p=3    (00010011)
        --   pos8: id=8 p=3    (00100011)
        --
        -- Fase B: 3 decrementi
        -- Dopo 1° dec: p=0->1, p=1->2, p=2->3, p=3->3(sat)
        -- Dopo 2° dec: p=1->2, p=2->3, p=3->3(sat)
        -- Dopo 3° dec: p=2->3, p=3->3(sat) -> tutti a prio=3, ordine fisico invariato
        --
        -- Fase C: rimuovi 4 task -> escono i primi 4 nell'ordine fisico
        --   esc1: id=1, esc2: id=5, esc3: id=3, esc4: id=7
        --   Rimangono: id=2(p3), id=6(p3), id=4(p3), id=8(p3)
        --
        -- Fase D: re-insert 3 task: id=10 p=0, id=11 p=1, id=12 p=3
        -- Ordine atteso: id=10(p0), id=11(p1), id=2(p3), id=6(p3),
        --                id=4(p3), id=8(p3), id=12(p3)
        --
        -- Fase E: rimuovi fino a lista vuota, verifica count=0

        clear_ram;
        do_reset;

        -- Fase A: insert
        do_op("10", "000001", "00");  -- id=1,  p=0
        do_op("10", "000010", "10");  -- id=2,  p=2
        do_op("10", "000011", "01");  -- id=3,  p=1
        do_op("10", "000100", "11");  -- id=4,  p=3
        do_op("10", "000101", "00");  -- id=5,  p=0
        do_op("10", "000110", "10");  -- id=6,  p=2
        do_op("10", "000111", "01");  -- id=7,  p=1
        do_op("10", "001000", "11");  -- id=8,  p=3

        check_mem("10.1 phaseA count", 0, "00001000");
        check_mem("10.1 phaseA pos1", 1, "00000100");  -- id=1, p=0
        check_mem("10.1 phaseA pos2", 2, "00010100");  -- id=5, p=0
        check_mem("10.1 phaseA pos3", 3, "00001101");  -- id=3, p=1
        check_mem("10.1 phaseA pos4", 4, "00011101");  -- id=7, p=1
        check_mem("10.1 phaseA pos5", 5, "00001010");  -- id=2, p=2
        check_mem("10.1 phaseA pos6", 6, "00011010");  -- id=6, p=2
        check_mem("10.1 phaseA pos7", 7, "00010011");  -- id=4, p=3
        check_mem("10.1 phaseA pos8", 8, "00100011");  -- id=8, p=3

        -- Fase B: 3 decrementi
        do_op("00", "000000", "00");  -- 1° dec
        do_op("00", "000000", "00");  -- 2° dec
        do_op("00", "000000", "00");  -- 3° dec: tutti a p=3, ordine fisico invariato

        check_mem("10.1 phaseB count", 0, "00001000");
        check_mem("10.1 phaseB pos1", 1, "00000111");  -- id=1, p=3
        check_mem("10.1 phaseB pos2", 2, "00010111");  -- id=5, p=3
        check_mem("10.1 phaseB pos3", 3, "00001111");  -- id=3, p=3
        check_mem("10.1 phaseB pos4", 4, "00011111");  -- id=7, p=3
        check_mem("10.1 phaseB pos5", 5, "00001011");  -- id=2, p=3
        check_mem("10.1 phaseB pos6", 6, "00011011");  -- id=6, p=3
        check_mem("10.1 phaseB pos7", 7, "00010011");  -- id=4, p=3
        check_mem("10.1 phaseB pos8", 8, "00100011");  -- id=8, p=3

        -- Fase C: rimuovi 4 task
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseC rem1", captured_id, "000001");  -- id=1

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseC rem2", captured_id, "000101");  -- id=5

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseC rem3", captured_id, "000011");  -- id=3

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseC rem4", captured_id, "000111");  -- id=7

        check_mem("10.1 phaseC count", 0, "00000100");
        check_mem("10.1 phaseC pos1", 1, "00001011");  -- id=2, p=3
        check_mem("10.1 phaseC pos2", 2, "00011011");  -- id=6, p=3
        check_mem("10.1 phaseC pos3", 3, "00010011");  -- id=4, p=3
        check_mem("10.1 phaseC pos4", 4, "00100011");  -- id=8, p=3

        -- Fase D: re-insert 3 task
        do_op("10", "001010", "00");  -- id=10, p=0 -> va in testa (p=0 < p=3)
        do_op("10", "001011", "01");  -- id=11, p=1 -> va dopo id=10 (p=1 < p=3)
        do_op("10", "001100", "11");  -- id=12, p=3 -> va in coda ai p=3

        check_mem("10.1 phaseD count", 0, "00000111");
        check_mem("10.1 phaseD pos1", 1, "00101000");  -- id=10, p=0
        check_mem("10.1 phaseD pos2", 2, "00101101");  -- id=11, p=1
        check_mem("10.1 phaseD pos3", 3, "00001011");  -- id=2,  p=3
        check_mem("10.1 phaseD pos4", 4, "00011011");  -- id=6,  p=3
        check_mem("10.1 phaseD pos5", 5, "00010011");  -- id=4,  p=3
        check_mem("10.1 phaseD pos6", 6, "00100011");  -- id=8,  p=3
        check_mem("10.1 phaseD pos7", 7, "00110011");  -- id=12, p=3

        -- Fase E: rimuovi tutti fino a lista vuota verificando count
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem1", captured_id, "001010");  -- id=10
        check_mem("10.1 phaseE cnt1", 0, "00000110");

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem2", captured_id, "001011");  -- id=11
        check_mem("10.1 phaseE cnt2", 0, "00000101");

        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem3", captured_id, "000010");  -- id=2
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem4", captured_id, "000110");  -- id=6
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem5", captured_id, "000100");  -- id=4
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem6", captured_id, "001000");  -- id=8
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE rem7", captured_id, "001100");  -- id=12

        check_mem("10.1 phaseE final-count", 0, "00000000");  -- lista vuota

        -- Tentativo su lista vuota: deve restituire 0
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.1 phaseE empty-rem", captured_id, "000000");

        report "Test 10.1 OK: stress test completo (insert/dec/remove/re-insert)";

        -- 10.2: Reset dopo OP=11 (svuota poi reset)
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "10");
        do_op("11", "000000", "00");  -- svuota
        check_mem("10.2 pre-reset count", 0, "00000000");
        -- Ora resettiamo
        tb_start <= '0';
        tb_rst   <= '1';
        wait for 100 ns;
        assert tb_done = '1'
            report "FAIL [10.2] DONE deve essere 1 durante reset post-svuota"
            severity failure;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("10.2 post-reset count", 0, "00000000");
        -- Verifica che il modulo sia operativo: insert e rimozione corretti
        do_op("10", "001111", "00");  -- id=15, p=0
        check_mem("10.2 post-reset-insert count", 0, "00000001");
        check_mem("10.2 post-reset-insert pos1",  1, "00111100");  -- id=15, p=0
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("10.2 post-reset-remove", captured_id, "001111");  -- id=15
        check_mem("10.2 post-reset-remove count", 0, "00000000");
        report "Test 10.2 OK: reset dopo svuota, modulo correttamente reinizializzato";


        -- ============================================================
        -- GRUPPO 11: OP=10 con ID=0 (condizione di errore da specifica)
        -- ============================================================
        -- La specifica definisce ID_TASK=0 come condizione di errore:
        -- un inserimento con ID=0 deve essere ignorato, ma il protocollo
        -- START-DONE deve comunque completarsi.
        report "=== GRUPPO 11: Insert con ID=0 ===";

        -- 11.0: Insert ID=0 in lista vuota -> ignorato, DONE arriva comunque
        clear_ram;
        do_reset;
        do_op_capture("10", "000000", "01", captured_id);
        check_captured_id("11.0 id0-task-id", captured_id, "000000");
        check_mem("11.0 count", 0, "00000000");
        check_mem("11.0 pos1",  1, "00000000");
        report "Test 11.0 OK: insert ID=0 su lista vuota ignorato";

        -- 11.1: Insert ID=0 in lista popolata -> lista invariata
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, p=0
        do_op("10", "000010", "01");  -- id=2, p=1
        do_op("10", "000000", "00");  -- ID=0, prio massima: NON deve andare in testa
        do_op("10", "000000", "11");  -- ID=0, prio minima: NON deve andare in coda
        check_mem("11.1 count", 0, "00000010");
        check_mem("11.1 pos1",  1, "00000100");  -- id=1, p=0
        check_mem("11.1 pos2",  2, "00001001");  -- id=2, p=1
        check_mem("11.1 pos3",  3, "00000000");  -- nessun task aggiunto
        report "Test 11.1 OK: insert ID=0 su lista popolata ignorato";


        -- ============================================================
        -- GRUPPO 12: Capacita' massima (63 task)
        -- ============================================================
        -- L'errata del 24.02.2026 precisa che il limite e' 63 task (ID a
        -- 6 bit, ID=0 escluso). Inseriamo TUTTI i 63 ID possibili con
        -- prio = id mod 4, verifichiamo l'intera memoria, tentiamo
        -- inserimenti oltre il limite (necessariamente duplicati) e
        -- svuotiamo con 63 pop verificando l'ordine di estrazione.
        report "=== GRUPPO 12: Capacita' massima 63 task ===";

        -- Modello di riferimento: bucket per priorita' crescente,
        -- FIFO (ordine di inserimento = id crescente) dentro ogni bucket
        idx := 1;
        for p in 0 to 3 loop
            for id in 1 to 63 loop
                if (id mod 4) = p then
                    exp_id(idx)   := id;
                    exp_prio(idx) := p;
                    idx := idx + 1;
                end if;
            end loop;
        end loop;

        clear_ram;
        do_reset;

        -- 12.0: insert di tutti i 63 ID in ordine crescente, prio = id mod 4
        for id in 1 to 63 loop
            do_op("10",
                  std_logic_vector(to_unsigned(id, 6)),
                  std_logic_vector(to_unsigned(id mod 4, 2)));
        end loop;
        check_mem("12.0 count", 0, std_logic_vector(to_unsigned(63, 8)));
        for pos in 1 to 63 loop
            exp_byte := std_logic_vector(to_unsigned(exp_id(pos) * 4 + exp_prio(pos), 8));
            check_mem("12.0 pos" & integer'image(pos), pos, exp_byte);
        end loop;
        report "Test 12.0 OK: 63 task inseriti, memoria completa verificata";

        -- 12.1: inserimenti oltre il 63esimo: ogni ID possibile e' gia'
        --       in lista -> tutti ignorati (dup in testa, in mezzo, in fondo)
        do_op("10", "000001", "11");  -- dup ID=1
        do_op("10", "100000", "00");  -- dup ID=32
        do_op("10", "111111", "00");  -- dup ID=63
        do_op("10", "000000", "00");  -- ID=0 a lista piena
        check_mem("12.1 count", 0, std_logic_vector(to_unsigned(63, 8)));
        for pos in 1 to 63 loop
            exp_byte := std_logic_vector(to_unsigned(exp_id(pos) * 4 + exp_prio(pos), 8));
            check_mem("12.1 pos" & integer'image(pos), pos, exp_byte);
        end loop;
        report "Test 12.1 OK: inserimenti oltre il 63esimo tutti ignorati";

        -- 12.2: drain completo, 63 pop con verifica dell'ordine di estrazione
        for pos in 1 to 63 loop
            do_op_capture("01", "000000", "00", captured_id);
            check_captured_id("12.2 pop" & integer'image(pos),
                              captured_id,
                              std_logic_vector(to_unsigned(exp_id(pos), 6)));
        end loop;
        check_mem("12.2 count", 0, "00000000");
        -- pop numero 64 su lista appena svuotata -> 0
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("12.2 pop-empty", captured_id, "000000");
        report "Test 12.2 OK: drain di 63 task nell'ordine atteso";


        -- ============================================================
        -- GRUPPO 13: Memoria stale e duplicati ai bordi della lista
        -- ============================================================
        report "=== GRUPPO 13: Stale memory e duplicati ai bordi ===";

        -- 13.0: Re-insert di un ID appena rimosso
        --       Dopo il pop lo shift lascia una copia stale dell'ultimo
        --       task oltre il count: lo scan duplicati NON deve vederla
        --       e il re-insert dell'ID estratto deve riuscire.
        clear_ram;
        do_reset;
        do_op("10", "000101", "01");  -- id=5, p=1
        do_op("10", "000110", "10");  -- id=6, p=2
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("13.0 pop", captured_id, "000101");  -- esce id=5
        -- mem: [1]=id6,p2 (count=1), [2] stale = id6,p2
        do_op("10", "000101", "11");  -- re-insert id=5 con prio diversa
        check_mem("13.0 count", 0, "00000010");
        check_mem("13.0 pos1",  1, "00011010");  -- id=6, p=2
        check_mem("13.0 pos2",  2, "00010111");  -- id=5, p=3 (sovrascrive la stale)
        report "Test 13.0 OK: re-insert di ID appena rimosso";

        -- 13.1: Duplicato in PRIMA posizione (i gruppi 0-10 testano solo
        --       il dup in posizione centrale)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, p=0
        do_op("10", "000010", "01");  -- id=2, p=1
        do_op("10", "000011", "10");  -- id=3, p=2
        do_op("10", "000001", "11");  -- dup del task in pos 1
        check_mem("13.1 count", 0, "00000011");
        check_mem("13.1 pos1",  1, "00000100");
        check_mem("13.1 pos2",  2, "00001001");
        check_mem("13.1 pos3",  3, "00001110");
        check_mem("13.1 pos4",  4, "00000000");
        report "Test 13.1 OK: duplicato in prima posizione ignorato";

        -- 13.2: Duplicato in ULTIMA posizione (stessa lista del 13.1)
        do_op("10", "000011", "00");  -- dup del task in pos 3 (ultima)
        check_mem("13.2 count", 0, "00000011");
        check_mem("13.2 pos1",  1, "00000100");
        check_mem("13.2 pos2",  2, "00001001");
        check_mem("13.2 pos3",  3, "00001110");
        check_mem("13.2 pos4",  4, "00000000");
        report "Test 13.2 OK: duplicato in ultima posizione ignorato";

        -- 13.3: Clear poi re-insert dello STESSO ID
        --       Il clear azzera solo il count: la cella task resta scritta
        --       (stale). L'insert dello stesso ID non deve essere scambiato
        --       per duplicato.
        clear_ram;
        do_reset;
        do_op("10", "001001", "01");  -- id=9, p=1
        do_op("11", "000000", "00");  -- clear: mem[1] resta stale con id=9
        do_op("10", "001001", "10");  -- re-insert id=9, p=2: deve riuscire
        check_mem("13.3 count", 0, "00000001");
        check_mem("13.3 pos1",  1, "00100110");  -- id=9, p=2
        report "Test 13.3 OK: re-insert stesso ID dopo clear";


        -- ============================================================
        -- GRUPPO 14: Reset asincrono avanzato
        -- ============================================================
        -- La specifica consente RESET "in qualsiasi momento
        -- dell'esecuzione": qui lo applichiamo nei punti piu' scomodi.
        -- Dopo ogni reset si verifica che addr 0 = 0 e che il modulo
        -- sia di nuovo pienamente operativo.
        report "=== GRUPPO 14: Reset asincrono avanzato ===";

        -- 14.0: Reset a meta' dello shift di OP=01 (fase COPY del 1° shift)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("10", "000010", "01");
        do_op("10", "000011", "10");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        for k in 1 to 6 loop
            wait until rising_edge(tb_clk);
        end loop;
        wait until falling_edge(tb_clk);
        tb_rst   <= '1';
        tb_start <= '0';
        wait for 60 ns;
        assert tb_done = '1'
            report "FAIL [14.0] DONE deve essere 1 durante reset a meta' shift"
            severity failure;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("14.0 count", 0, "00000000");
        do_op("10", "000111", "01");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("14.0 op-after-reset", captured_id, "000111");
        report "Test 14.0 OK: reset a meta' shift di OP=01";

        -- 14.1: Reset nel ciclo della scrittura del count (fine OP=01)
        --       Con 3 task i segnali di scrittura del count vengono
        --       registrati al 12° fronte dopo il campionamento di START:
        --       il reset arriva tra la registrazione e il commit in
        --       memoria. S_RESET deve comunque lasciare addr 0 = 0.
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("10", "000010", "01");
        do_op("10", "000011", "10");
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        for k in 1 to 12 loop
            wait until rising_edge(tb_clk);
        end loop;
        tb_rst   <= '1';
        tb_start <= '0';
        wait for 60 ns;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("14.1 count", 0, "00000000");
        do_op("10", "001000", "10");
        check_mem("14.1 op-after-reset count", 0, "00000001");
        check_mem("14.1 op-after-reset pos1",  1, "00100010");  -- id=8, p=2
        report "Test 14.1 OK: reset durante la scrittura del count";

        -- 14.2: Reset a meta' della scansione di OP=00
        --       (durante il ciclo di commit della scrittura del 1° task)
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");
        do_op("10", "000010", "01");
        wait until falling_edge(tb_clk);
        tb_op            <= "00";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        for k in 1 to 4 loop
            wait until rising_edge(tb_clk);
        end loop;
        wait until falling_edge(tb_clk);
        tb_rst   <= '1';
        tb_start <= '0';
        wait for 60 ns;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("14.2 count", 0, "00000000");
        do_op("10", "000101", "00");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("14.2 op-after-reset", captured_id, "000101");
        report "Test 14.2 OK: reset durante OP=00";

        -- 14.3: Reset mentre DONE=1 (tra il completamento dell'operazione
        --       e l'abbassamento di START)
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "10";
        tb_i_task_id     <= "000100";  -- id=4
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        tb_rst   <= '1';               -- reset proprio mentre DONE=1
        tb_start <= '0';
        wait for 60 ns;
        assert tb_done = '1'
            report "FAIL [14.3] DONE deve restare 1 durante reset"
            severity failure;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("14.3 count", 0, "00000000");  -- lista di nuovo vuota
        do_op("10", "000110", "11");
        check_mem("14.3 op-after-reset count", 0, "00000001");
        check_mem("14.3 op-after-reset pos1",  1, "00011011");  -- id=6, p=3
        report "Test 14.3 OK: reset mentre DONE=1";

        -- 14.4: Reset corto (7 ns, non allineato al clock)
        --       RESET e' asincrono: anche un impulso piu' corto del
        --       periodo e fuori fase deve reinizializzare il modulo.
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");
        do_op("10", "000010", "10");
        wait until falling_edge(tb_clk);
        wait for 3 ns;                 -- disallinea dal fronte
        tb_rst <= '1';
        wait for 7 ns;
        tb_rst <= '0';
        wait until tb_done = '0';
        wait until falling_edge(tb_clk);
        check_mem("14.4 count", 0, "00000000");
        do_op("10", "001100", "01");
        do_op_capture("01", "000000", "00", captured_id);
        check_captured_id("14.4 op-after-reset", captured_id, "001100");
        report "Test 14.4 OK: reset corto non allineato";


        -- ============================================================
        -- GRUPPO 15: Protocollo START-DONE con abbassamento lento di START
        -- ============================================================
        -- La specifica NON garantisce che START scenda entro lo stesso
        -- ciclo in cui DONE va a 1: dice solo che l'esterno lo riporta a 0
        -- quando DONE e' 1, e che il modulo puo' abbassare DONE quando
        -- START torna a 0. Qui START resta alto per 1-2 cicli interi dopo
        -- DONE=1: il modulo NON deve rieseguire l'operazione.
        --
        -- NOTA: con l'RTL attuale (senza stato S_DONE che attende START=0)
        -- questi test FALLISCONO: e' il comportamento da correggere.
        report "=== GRUPPO 15: START lento dopo DONE=1 ===";

        -- 15.0: Pop con START tenuto alto 1 ciclo extra -> NIENTE doppio pop
        clear_ram;
        do_reset;
        do_op("10", "000001", "01");  -- id=1, p=1
        do_op("10", "000010", "10");  -- id=2, p=2
        wait until falling_edge(tb_clk);
        tb_op            <= "01";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        check_task_id("15.0 pop-id", "000001");
        wait until rising_edge(tb_clk);   -- START resta alto un ciclo intero
        wait until falling_edge(tb_clk);
        tb_start <= '0';
        wait for 300 ns;                  -- tempo abbondante per un eventuale re-run
        assert tb_done = '0'
            report "FAIL [15.0] DONE non e' tornato a 0 dopo START=0"
            severity failure;
        check_mem("15.0 count", 0, "00000001");  -- UN solo pop: count=1
        check_mem("15.0 pos1",  1, "00001010");  -- id=2, p=2 ancora in lista
        report "Test 15.0 OK: nessun doppio pop con START lento";

        -- 15.1: Age con START tenuto alto 1 ciclo extra -> NIENTE doppio age
        clear_ram;
        do_reset;
        do_op("10", "000001", "00");  -- id=1, p=0
        wait until falling_edge(tb_clk);
        tb_op            <= "00";
        tb_i_task_id     <= "000000";
        tb_task_priority <= "00";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        wait until rising_edge(tb_clk);
        wait until falling_edge(tb_clk);
        tb_start <= '0';
        wait for 300 ns;
        assert tb_done = '0'
            report "FAIL [15.1] DONE non e' tornato a 0 dopo START=0"
            severity failure;
        check_mem("15.1 pos1", 1, "00000101");  -- prio 0->1, NON 0->2
        report "Test 15.1 OK: nessun doppio age con START lento";

        -- 15.2: Insert con START tenuto alto 2 cicli extra
        --       (un re-run qui sarebbe mascherato dal filtro duplicati:
        --       il test verifica soprattutto la tenuta del protocollo DONE)
        clear_ram;
        do_reset;
        wait until falling_edge(tb_clk);
        tb_op            <= "10";
        tb_i_task_id     <= "000111";  -- id=7
        tb_task_priority <= "01";
        tb_start         <= '1';
        wait until rising_edge(tb_done);
        wait until rising_edge(tb_clk);
        wait until rising_edge(tb_clk);   -- 2 cicli extra
        wait until falling_edge(tb_clk);
        tb_start <= '0';
        wait for 300 ns;
        assert tb_done = '0'
            report "FAIL [15.2] DONE non e' tornato a 0 dopo START=0"
            severity failure;
        check_mem("15.2 count", 0, "00000001");
        check_mem("15.2 pos1",  1, "00011101");  -- id=7, p=1
        report "Test 15.2 OK: insert con START tenuto 2 cicli extra";


        -- ============================================================
        -- Fine
        -- ============================================================
        assert false
            report "======================================" & LF
                   & " Tutti i test edge case sono PASSATI " & LF
                   & "======================================"
            severity failure;

    end process;

end architecture;