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

library osvvm; -- Utility Library
context osvvm.OsvvmContext;

use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
use work.rtps_test_package.all;
use work.Type2_package.all;

-- This testbench tests the Payload encoding/decoding of the TYPE2_interface entities.
-- It does so by interconnecting the writer and reader interface, setting some inputs to the writer and checking if the reader returns the same data.
-- This testbench tests only the Little Endian encoding/decoding.

entity L1_Type2_interface_test2 is
end entity;

architecture testbench of L1_Type2_interface_test2 is
    
    constant DEFAULT_SAMPLE_INFO : SAMPLE_INFO_TYPE := (
        sample_state                => (others => '0'),
        view_state                  => (others => '0'),
        instance_state              => (others => '0'),
        source_timestamp            => TIME_ZERO,
        instance_handle             => HANDLE_NIL,
        publication_handle          => HANDLE_NIL,
        disposed_generation_count   => (others => '0'),
        no_writers_generation_count => (others => '0'),
        sample_rank                 => (others => '0'),
        generation_rank             => (others => '0'),
        absolute_generation_rank    => (others => '0'),
        valid_data                  => '1'
    );
    
    signal clk, reset : std_logic := '0';
    signal ready, valid, last_word : std_logic := '0';
    signal data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    signal start_w, get_data_r, decode_error, valid_r, encode_done : std_logic := '0';
    
    signal id_in, id_out : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_len_in, TestSequence_len_out, TestSequence_addr_in, TestSequence_addr_out : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_ready_in, TestSequence_ready_out, TestSequence_ren_in, TestSequence_ren_out, TestSequence_wen_in, TestSequence_valid_in, TestSequence_valid_out, TestSequence_ack_in, TestSequence_ack_out : std_logic := '0';
    signal TestSequence_TestArray_addr_in, TestSequence_TestArray_addr_out : std_logic_vector(TESTSEQUENCE_TESTARRAY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestArray_ready_in, TestSequence_TestArray_ready_out, TestSequence_TestArray_ren_in, TestSequence_TestArray_ren_out, TestSequence_TestArray_wen_in, TestSequence_TestArray_valid_in, TestSequence_TestArray_valid_out, TestSequence_TestArray_ack_in, TestSequence_TestArray_ack_out : std_logic := '0';
    signal TestSequence_TestArray_r_in, TestSequence_TestArray_w_in, TestSequence_TestArray_out : std_logic_vector(CDR_OCTET_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestChar_r_in, TestSequence_TestChar_w_in, TestSequence_TestChar_out : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestWChar_r_in, TestSequence_TestWChar_w_in, TestSequence_TestWChar_out : std_logic_vector(CDR_WCHAR_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestLongLong_r_in, TestSequence_TestLongLong_w_in, TestSequence_TestLongLong_out : std_logic_vector(CDR_LONG_LONG_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestLongDouble_r_in, TestSequence_TestLongDouble_w_in, TestSequence_TestLongDouble_out : std_logic_vector(CDR_LONG_DOUBLE_WIDTH-1 downto 0) := (others => '0');
    signal TestSequence_TestLongDouble_opt_r_in, TestSequence_TestLongDouble_opt_w_in, TestSequence_TestLongDouble_opt_out : std_logic := '0';
    signal TestMap_len_in, TestMap_len_out, TestMap_addr_in, TestMap_addr_out : std_logic_vector(TESTMAP_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal TestMap_ready_in, TestMap_ready_out, TestMap_ren_in, TestMap_ren_out, TestMap_wen_in, TestMap_valid_in, TestMap_valid_out, TestMap_ack_in, TestMap_ack_out : std_logic := '0';
    signal TestMap_key_r_in, TestMap_key_w_in, TestMap_key_out : std_logic_vector(CDR_OCTET_WIDTH-1 downto 0) := (others => '0');
    signal TestMap_value_r_in, TestMap_value_w_in, TestMap_value_out : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0) := (others => '0');
    signal TestEnum_in, TestEnum_out : std_logic_vector(TESTENUM_WIDTH-1 downto 0) := (others => '0');
    signal TestUnion_opt_in, TestUnion_opt_out : std_logic := '0';
    signal TestUnion_d_in, TestUnion_d_out : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0) := (others => '0');
    signal TestUnion_LongU_in, TestUnion_LongU_out : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal TestUnion_OctetU_in, TestUnion_OctetU_out : std_logic_vector(CDR_OCTET_WIDTH-1 downto 0) := (others => '0');
    signal TestBitmask_in, TestBitmask_out : std_logic_vector(TESTBITMASK_WIDTH-1 downto 0) := (others => '0');
    signal TestString_len_in, TestString_len_out, TestString_addr_in, TestString_addr_out : std_logic_vector(TESTSTRING_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal TestString_ready_in, TestString_ready_out, TestString_ren_in, TestString_ren_out, TestString_wen_in, TestString_valid_in, TestString_valid_out, TestString_ack_in, TestString_ack_out : std_logic := '0';
    signal TestString_r_in, TestString_w_in, TestString_out : std_logic_vector(CDR_CHAR_WIDTH-1 downto 0) := (others => '0');
begin
    
    uut_w : entity work.Type2_writer_interface(arch)
        generic map (
            LITTLE_ENDIAN   => '1'
        )
        port map (
            clk                                 => clk,
            reset                               => reset,
            start_dds                           => open,
            ack_dds                             => '1',
            opcode_dds                          => open,
            instance_handle_out_dds             => HANDLE_NIL,
            source_ts_dds                       => open,
            max_wait_dds                        => open,
            done_dds                            => '1',
            return_code_dds                     => RETCODE_OK,
            instance_handle_in_dds              => open,
            ready_out_dds                       => ready,
            valid_out_dds                       => valid,
            data_out_dds                        => data,
            last_word_out_dds                   => last_word,
            ready_in_dds                        => open,
            valid_in_dds                        => '0',
            data_in_dds                         => (others => '0'),
            last_word_in_dds                    => '0',
            status_dds                          => (others => '0'),
            start_user                          => start_w,
            ack_user                            => open,
            opcode_user                         => WRITE,
            instance_handle_in_user             => HANDLE_NIL,
            source_ts_user                      => TIME_ZERO,
            max_wait_user                       => TIME_INFINITE,
            done_user                           => open,
            return_code_user                    => open,
            instance_handle_out_user            => open,
            status_user                         => open,
            id                                  => id_in,
            TestSequence_len                    => TestSequence_len_in,
            TestSequence_addr                   => TestSequence_addr_in,
            TestSequence_ready                  => TestSequence_ready_in,
            TestSequence_ren                    => TestSequence_ren_in,
            TestSequence_wen                    => TestSequence_wen_in,
            TestSequence_valid                  => TestSequence_valid_in,
            TestSequence_ack                    => TestSequence_ack_in,
            TestSequence_TestArray_addr         => TestSequence_TestArray_addr_in,
            TestSequence_TestArray_ready        => TestSequence_TestArray_ready_in,
            TestSequence_TestArray_ren          => TestSequence_TestArray_ren_in,
            TestSequence_TestArray_wen          => TestSequence_TestArray_wen_in,
            TestSequence_TestArray_valid        => TestSequence_TestArray_valid_in,
            TestSequence_TestArray_ack          => TestSequence_TestArray_ack_in,
            TestSequence_TestArray_r            => TestSequence_TestArray_r_in,
            TestSequence_TestArray_w            => TestSequence_TestArray_w_in,
            TestSequence_TestChar_r             => TestSequence_TestChar_r_in,
            TestSequence_TestChar_w             => TestSequence_TestChar_w_in,
            TestSequence_TestWChar_r            => TestSequence_TestWChar_r_in,
            TestSequence_TestWChar_w            => TestSequence_TestWChar_w_in,
            TestSequence_TestLongLong_r         => TestSequence_TestLongLong_r_in,
            TestSequence_TestLongLong_w         => TestSequence_TestLongLong_w_in,
            TestSequence_TestLongDouble_r       => TestSequence_TestLongDouble_r_in,
            TestSequence_TestLongDouble_w       => TestSequence_TestLongDouble_w_in,
            TestSequence_TestLongDouble_opt_r   => TestSequence_TestLongDouble_opt_r_in,
            TestSequence_TestLongDouble_opt_w   => TestSequence_TestLongDouble_opt_w_in,
            TestMap_len                         => TestMap_len_in,
            TestMap_addr                        => TestMap_addr_in,
            TestMap_ready                       => TestMap_ready_in,
            TestMap_ren                         => TestMap_ren_in,
            TestMap_wen                         => TestMap_wen_in,
            TestMap_valid                       => TestMap_valid_in,
            TestMap_ack                         => TestMap_ack_in,
            TestMap_key_r                       => TestMap_key_r_in,
            TestMap_key_w                       => TestMap_key_w_in,
            TestMap_value_r                     => TestMap_value_r_in,
            TestMap_value_w                     => TestMap_value_w_in,
            TestEnum                            => TestEnum_in,
            TestUnion_opt                       => TestUnion_opt_in,
            TestUnion_d                         => TestUnion_d_in,
            TestUnion_LongU                     => TestUnion_LongU_in,
            TestUnion_OctetU                    => TestUnion_OctetU_in,
            TestBitmask                         => TestBitmask_in,
            TestString_len                      => TestString_len_in,
            TestString_addr                     => TestString_addr_in,
            TestString_ready                    => TestString_ready_in,
            TestString_ren                      => TestString_ren_in,
            TestString_wen                      => TestString_wen_in,
            TestString_valid                    => TestString_valid_in,
            TestString_ack                      => TestString_ack_in,
            TestString_r                        => TestString_r_in,
            TestString_w                        => TestString_w_in,
            encode_done                         => encode_done
        );
    
    uut_r : entity work.Type2_reader_interface(arch)
        port map (
            clk                                 => clk,
            reset                               => reset,
            start_dds                           => open,
            ack_dds                             => '1',
            opcode_dds                          => open,
            instance_state_dds                  => open,
            view_state_dds                      => open,
            sample_state_dds                    => open,
            instance_handle_dds                 => open,
            max_samples_dds                     => open,
            get_data_dds                        => open,
            done_dds                            => '1',
            return_code_dds                     => RETCODE_OK,
            ready_in_dds                        => ready,
            valid_in_dds                        => valid,
            data_in_dds                         => data,
            last_word_in_dds                    => last_word,
            sample_info_dds                     => DEFAULT_SAMPLE_INFO,
            sample_info_valid_dds               => '1',
            sample_info_ack_dds                 => open,
            eoc_dds                             => '1',
            status_dds                          => (others => '0'),
            start_user                          => '0',
            ack_user                            => open,
            opcode_user                         => NOP,
            instance_state_user                 => (others => '0'),
            view_state_user                     => (others => '0'),
            sample_state_user                   => (others => '0'),
            instance_handle_user                => HANDLE_NIL,
            max_samples_user                    => (others => '0'),
            get_data_user                       => get_data_r,
            done_user                           => open,
            return_code_user                    => open,
            sample_info_user                    => open,
            sample_info_valid_user              => open,
            sample_info_ack_user                => '1',
            eoc_user                            => open,
            status_user                         => open,
            decode_error                        => decode_error,
            id                                  => id_out,
            TestSequence_len                    => TestSequence_len_out,
            TestSequence_addr                   => TestSequence_addr_out,
            TestSequence_ready                  => TestSequence_ready_out,
            TestSequence_ren                    => TestSequence_ren_out,
            TestSequence_valid                  => TestSequence_valid_out,
            TestSequence_ack                    => TestSequence_ack_out,
            TestSequence_TestArray_addr         => TestSequence_TestArray_addr_out,
            TestSequence_TestArray_ready        => TestSequence_TestArray_ready_out,
            TestSequence_TestArray_ren          => TestSequence_TestArray_ren_out,
            TestSequence_TestArray_valid        => TestSequence_TestArray_valid_out,
            TestSequence_TestArray_ack          => TestSequence_TestArray_ack_out,
            TestSequence_TestArray              => TestSequence_TestArray_out,
            TestSequence_TestChar               => TestSequence_TestChar_out,
            TestSequence_TestWChar              => TestSequence_TestWChar_out,
            TestSequence_TestLongLong           => TestSequence_TestLongLong_out,
            TestSequence_TestLongDouble         => TestSequence_TestLongDouble_out,
            TestSequence_TestLongDouble_opt     => TestSequence_TestLongDouble_opt_out,
            TestMap_len                         => TestMap_len_out,
            TestMap_addr                        => TestMap_addr_out,
            TestMap_ready                       => TestMap_ready_out,
            TestMap_ren                         => TestMap_ren_out,
            TestMap_valid                       => TestMap_valid_out,
            TestMap_ack                         => TestMap_ack_out,
            TestMap_key                         => TestMap_key_out,
            TestMap_value                       => TestMap_value_out,
            TestEnum                            => TestEnum_out,
            TestUnion_opt                       => TestUnion_opt_out,
            TestUnion_d                         => TestUnion_d_out,
            TestUnion_LongU                     => TestUnion_LongU_out,
            TestUnion_OctetU                    => TestUnion_OctetU_out,
            TestBitmask                         => TestBitmask_out,
            TestString_len                      => TestString_len_out,
            TestString_addr                     => TestString_addr_out,
            TestString_ready                    => TestString_ready_out,
            TestString_ren                      => TestString_ren_out,
            TestString_valid                    => TestString_valid_out,
            TestString_ack                      => TestString_ack_out,
            TestString                          => TestString_out,
            valid                               => valid_r
        );
    
    stimulus_prc : process
        variable RV : RandomPType;
        variable ID, TS_TA, TS_TC, TS_TWC, TS_TLL, TS_TLD, TM, TE, TU, TB, TS : AlertLogIDType;
        
        procedure wait_on_sig(signal sig : std_logic) is
        begin
            if (sig /= '1') then
                wait on sig until sig = '1';
            end if;
        end procedure;
    begin
        
        SetAlertLogName("L1_Type2_interface_test2 - (Little Endian) - Encoding/Decoding");
        SetAlertEnable(FAILURE, TRUE);
        SetAlertEnable(ERROR, TRUE);
        SetAlertEnable(WARNING, TRUE);
        SetLogEnable(DEBUG, FALSE);
        SetLogEnable(PASSED, FALSE);
        SetLogEnable(INFO, TRUE);
        RV.InitSeed(RV'instance_name);
        ID      := GetAlertLogID("ID", ALERTLOG_BASE_ID);
        TS_TA   := GetAlertLogID("TestSequence_TestArray", ALERTLOG_BASE_ID);
        TS_TC   := GetAlertLogID("TestSequence_TestChar", ALERTLOG_BASE_ID);
        TS_TWC  := GetAlertLogID("TestSequence_TestWChar", ALERTLOG_BASE_ID);
        TS_TLL  := GetAlertLogID("TestSequence_TestLongLong", ALERTLOG_BASE_ID);
        TS_TLD  := GetAlertLogID("TestSequence_TestLongDouble", ALERTLOG_BASE_ID);
        TM      := GetAlertLogID("TestMap", ALERTLOG_BASE_ID);
        TE      := GetAlertLogID("TestEnum", ALERTLOG_BASE_ID);
        TU      := GetAlertLogID("TestUnion", ALERTLOG_BASE_ID);
        TB      := GetAlertLogID("TestBitmask", ALERTLOG_BASE_ID);
        TS      := GetAlertLogID("TestString", ALERTLOG_BASE_ID);
        
        Log("Initial Reset", INFO);
        start_w     <= '0';
        get_data_r  <= '0';
        reset       <= '1';
        wait until rising_edge(clk);
        wait until rising_edge(clk);
        reset   <= '0';
        
        Log("Setting Data in Writer Side", INFO);
        -- Static
        id_in               <= RV.RandSlv(id_in'length);
        TestEnum_in         <= RV.RandSlv(TestEnum_in'length);
        TestUnion_opt_in    <= '1';
        TestUnion_d_in      <= (others => '0');
        TestUnion_LongU_in  <= RV.RandSlv(TestUnion_LongU_in'length);
        TestUnion_OctetU_in <= RV.RandSlv(TestUnion_OctetU_in'length);
        TestBitmask_in      <= RV.RandSlv(TestBitmask_in'length);
        
        -- Memory
        for i in 0 to 1 loop
            TestSequence_len_in                     <= int(2,TestSequence_len_in'length);
            TestSequence_addr_in                    <= int(i,TestSequence_addr_in'length);
            TestSequence_TestChar_w_in              <= RV.RandSlv(TestSequence_TestChar_w_in'length);
            TestSequence_TestWChar_w_in             <= RV.RandSlv(TestSequence_TestWChar_w_in'length);
            TestSequence_TestLongLong_w_in          <= RV.RandSlv(TestSequence_TestLongLong_w_in'length);
            TestSequence_TestLongDouble_w_in        <= RV.RandSlv(TestSequence_TestLongDouble_w_in'length);
            TestSequence_TestLongDouble_opt_w_in    <= RV.RandSlv(1)(1);
            for j in 0 to 4 loop
                TestSequence_TestArray_addr_in  <= int(j,TestSequence_TestArray_addr_in'length);
                TestSequence_TestArray_w_in     <= RV.RandSlv(TestSequence_TestArray_w_in'length);
                wait_on_sig(TestSequence_TestArray_ready_in);
                TestSequence_TestArray_wen_in   <= '1';
                wait for TEST_CLOCK_PERIOD;
                TestSequence_TestArray_wen_in   <= '0';
            end loop;
            wait_on_sig(TestSequence_ready_in);
            TestSequence_wen_in <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestSequence_wen_in <= '0';
        end loop;
        
        for i in 0 to 0 loop
            TestMap_len_in      <= int(1,TestMap_len_in'length);
            TestMap_addr_in     <= int(i,TestMap_addr_in'length);
            TestMap_key_w_in    <= RV.RandSlv(TestMap_key_w_in'length);
            TestMap_value_w_in  <= RV.RandSlv(TestMap_value_w_in'length);
            wait_on_sig(TestMap_ready_in);
            TestMap_wen_in      <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestMap_wen_in      <= '0';
        end loop;
        
        for i in 0 to 9 loop
            TestString_len_in   <= int(10,TestString_len_in'length);
            TestString_addr_in  <= int(i,TestString_addr_in'length);
            TestString_w_in     <= RV.RandSlv(TestString_w_in'length);
            wait_on_sig(TestString_ready_in);
            TestString_wen_in   <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestString_wen_in   <= '0';
        end loop;
        
        Log("Initiate Writer->Reader Transfer", INFO);
        
        start_w     <= '1';
        get_data_r  <= '1';
        wait for TEST_CLOCK_PERIOD;
        start_w     <= '0';
        get_data_r  <= '0';
        
        Log("Wait until Transfer done", INFO);
        wait_on_sig(encode_done);
        wait_on_sig(valid_r);
        
        Log("Compare Writer and Reader Side", INFO);
        AffirmIfEqual(ID, id_out, id_in);
        AffirmIfEqual(TE, TestEnum_out,TestEnum_in);
        AffirmIfEqual(TU, TestUnion_opt_out, TestUnion_opt_in);
        if (TestUnion_opt_in = '1') then
            AffirmIfEqual(TU, TestUnion_d_out, TestUnion_d_in);
            --AffirmIfEqual(TU, TestUnion_LongU_out, TestUnion_LongU_in);
            AffirmIfEqual(TU, TestUnion_OctetU_out, TestUnion_OctetU_in);
        end if;
        AffirmIfEqual(TB, TestBitmask_out, TestBitmask_in);
        
        AffirmIfEqual(TestSequence_len_out,TestSequence_len_in);
        for i in 0 to to_integer(unsigned(TestSequence_len_in)) loop
            TestSequence_addr_out   <= int(i,TestSequence_addr_out'length);
            TestSequence_addr_in    <= int(i,TestSequence_addr_in'length);
            wait_on_sig(TestSequence_ready_out);
            wait_on_sig(TestSequence_ready_in);
            TestSequence_ren_out    <= '1';
            TestSequence_ren_in     <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestSequence_ren_out    <= '0';
            TestSequence_ren_in     <= '0';
            wait_on_sig(TestSequence_valid_out);
            wait_on_sig(TestSequence_valid_in);
            AffirmIfEqual(TS_TC, TestSequence_TestChar_out, TestSequence_TestChar_r_in);
            AffirmIfEqual(TS_TWC, TestSequence_TestWChar_out, TestSequence_TestWChar_r_in);
            AffirmIfEqual(TS_TLL, TestSequence_TestLongLong_out, TestSequence_TestLongLong_r_in);
            AffirmIfEqual(TS_TLD, TestSequence_TestLongDouble_opt_out, TestSequence_TestLongDouble_opt_r_in);
            if (TestSequence_TestLongDouble_opt_r_in = '1') then
                AffirmIfEqual(TS_TLD, TestSequence_TestLongDouble_out, TestSequence_TestLongDouble_r_in);
            end if;
            for j in 0 to 4 loop
                TestSequence_TestArray_addr_out <= int(j,TestSequence_TestArray_addr_out'length);
                TestSequence_TestArray_addr_in  <= int(j,TestSequence_TestArray_addr_in'length);
                wait_on_sig(TestSequence_TestArray_ready_out);
                wait_on_sig(TestSequence_TestArray_ready_in);
                TestSequence_TestArray_ren_out  <= '1';
                TestSequence_TestArray_ren_in   <= '1';
                wait for TEST_CLOCK_PERIOD;
                TestSequence_TestArray_ren_out  <= '0';
                TestSequence_TestArray_ren_in   <= '0';
                wait_on_sig(TestSequence_TestArray_valid_out);
                wait_on_sig(TestSequence_TestArray_valid_in);
                AffirmIfEqual(TS_TA, TestSequence_TestArray_out, TestSequence_TestArray_r_in);
                TestSequence_TestArray_ack_out  <= '1';
                TestSequence_TestArray_ack_in   <= '1';
                wait for TEST_CLOCK_PERIOD;
                TestSequence_TestArray_ack_out  <= '0';
                TestSequence_TestArray_ack_in   <= '0';
            end loop;
            TestSequence_ack_out    <= '1';
            TestSequence_ack_in     <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestSequence_ack_out    <= '0';
            TestSequence_ack_in     <= '0';
        end loop;
        
        AffirmIfEqual(TestMap_len_out, TestMap_len_in);
        for i in 0 to to_integer(unsigned(TestMap_len_in)) loop
            TestMap_addr_out    <= int(i,TestMap_addr_out'length);
            TestMap_addr_in     <= int(i,TestMap_addr_in'length);
            wait_on_sig(TestMap_ready_out);
            wait_on_sig(TestMap_ready_in);
            TestMap_ren_out <= '1';
            TestMap_ren_in  <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestMap_ren_out <= '0';
            TestMap_ren_in  <= '0';
            wait_on_sig(TestMap_valid_out);
            wait_on_sig(TestMap_valid_in);
            AffirmIfEqual(TM, TestMap_key_out, TestMap_key_r_in);
            AffirmIfEqual(TM, TestMap_value_out, TestMap_value_r_in);
            TestMap_ack_out <= '1';
            TestMap_ack_in  <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestMap_ack_out <= '0';
            TestMap_ack_in  <= '0';
        end loop;
        
        AffirmIfEqual(TestString_len_out, TestString_len_in);
        for i in 0 to to_integer(unsigned(TestString_len_in)) loop
            TestString_addr_out <= int(i,TestString_addr_out'length);
            TestString_addr_in  <= int(i,TestString_addr_in'length);
            wait_on_sig(TestString_ready_out);
            wait_on_sig(TestString_ready_in);
            TestString_ren_out  <= '1';
            TestString_ren_in   <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestString_ren_out  <= '0';
            TestString_ren_in   <= '0';
            wait_on_sig(TestString_valid_out);
            wait_on_sig(TestString_valid_in);
            AffirmIfEqual(TS, TestString_out, TestString_r_in);
            TestString_ack_out  <= '1';
            TestString_ack_in   <= '1';
            wait for TEST_CLOCK_PERIOD;
            TestString_ack_out  <= '0';
            TestString_ack_in   <= '0';
        end loop;
        
        TranscriptOpen(RESULTS_FILE, APPEND_MODE);
        SetTranscriptMirror;
        ReportAlerts;
        TranscriptClose;
        std.env.stop;
        wait;
    end process;
    
    clock_prc : process
    begin
        clk <= '0';
        wait for TEST_CLOCK_PERIOD/2;
        clk <= '1';
        wait for TEST_CLOCK_PERIOD/2;
    end process;
    
    alert_prc : process(all)
    begin
        if rising_edge(clk) then
            alertif(decode_error = '1', "The Reader signals a DECODE Error", ERROR);
        end if;
    end process;
    
    watchdog : process
    begin
        wait for 1 ms;
        Alert("Test timeout", FAILURE);
        std.env.stop;
    end process;
    
end architecture;