-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)

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

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

entity L2_Testbench_Lib5 is
    port (
        -- SYSTEM
        clk                                 : in std_logic;
        reset                               : in std_logic;
        time                                : in TIME_TYPE;
        -- INPUT
        empty                               : in std_logic;
        read                                : out std_logic;
        data_in                             : in std_logic_vector(WORD_WIDTH-1 downto 0);
        -- OUTPUT
        full                                : in std_logic;
        write                               : out std_logic;
        data_out                            : out std_logic_vector(WORD_WIDTH-1 downto 0);
        -- READER
        start_r                             : in std_logic;
        ack_r                               : out std_logic;
        opcode_r                            : in DDS_READER_OPCODE_TYPE;
        instance_state_r                    : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
        view_state_r                        : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
        sample_state_r                      : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
        instance_handle_r                   : in INSTANCE_HANDLE_TYPE;
        max_samples_r                       : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
        get_data_r                          : in std_logic;
        done_r                              : out std_logic;
        return_code_r                       : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        sample_info_r                       : out SAMPLE_INFO_TYPE;
        sample_info_valid_r                 : out std_logic;
        sample_info_ack_r                   : in std_logic;
        eoc_r                               : out std_logic;
        status_r                            : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
        decode_error_r                      : out std_logic;
        id_r                                : out std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        a_r                                 : out std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        valid_r                             : out std_logic;
        -- WRITER
        start_w                             : in std_logic;
        ack_w                               : out std_logic;
        opcode_w                            : in DDS_WRITER_OPCODE_TYPE;
        instance_handle_in_w                : in INSTANCE_HANDLE_TYPE;
        source_ts_w                         : in TIME_TYPE;
        max_wait_w                          : in DURATION_TYPE;
        done_w                              : out std_logic;
        return_code_w                       : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        instance_handle_out_w               : out INSTANCE_HANDLE_TYPE;
        status_w                            : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
        id_w                                : in std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        a_w                                 : in std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        encode_done_w                       : out std_logic
    );
end entity;

architecture arch of L2_Testbench_Lib5 is
    
    -- TODO: Better Names?
    type EARRAY_DATA_TYPE is array (0 to NUM_ENDPOINTS-1) of std_logic_vector(WORD_WIDTH downto 0);
    type HISTORY_CACHE_OPCODE_RARRAY_TYPE is array (0 to NUM_READERS-1) of HISTORY_CACHE_OPCODE_TYPE;
    type HISTORY_CACHE_OPCODE_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of HISTORY_CACHE_OPCODE_TYPE;
    type HISTORY_CACHE_RESPONSE_RARRAY_TYPE is array (0 to NUM_READERS-1) of HISTORY_CACHE_RESPONSE_TYPE;
    type HISTORY_CACHE_RESPONSE_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of HISTORY_CACHE_RESPONSE_TYPE;
    type RARRAY_DATA_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(WORD_WIDTH downto 0);
    type WARRAY_DATA_TYPE is array (0 to NUM_WRITERS-1) of std_logic_vector(WORD_WIDTH downto 0);
    type SEQUENCENUMBER_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of SEQUENCENUMBER_TYPE;
    type INSTANCE_HANDLE_RARRAY_TYPE is array (0 to NUM_READERS-1) of INSTANCE_HANDLE_TYPE;
    type INSTANCE_HANDLE_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of INSTANCE_HANDLE_TYPE;
    type CACHE_CHANGE_KIND_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of CACHE_CHANGE_KIND_TYPE;
    type TIME_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of TIME_TYPE;
    type DDS_READER_OPCODE_RARRAY_TYPE is array (0 to NUM_READERS-1) of DDS_READER_OPCODE_TYPE;
    type DDS_WRITER_OPCODE_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of DDS_WRITER_OPCODE_TYPE;
    type INSTANCE_STATE_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
    type VIEW_STATE_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
    type SAMPLE_STATE_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
    type MAX_SAMPLES_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
    type RETURN_CODE_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
    type RETURN_CODE_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
    type STATUS_KIND_RARRAY_TYPE is array (0 to NUM_READERS-1) of std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
    type STATUS_KIND_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
    type DURATION_WARRAY_TYPE is array (0 to NUM_WRITERS-1) of DURATION_TYPE;
    type SAMPLE_INFO_RARRAY_TYPE is array (0 to NUM_READERS-1) of SAMPLE_INFO_TYPE;
    
    signal full_fire_rh, write_rh_fire : std_logic_vector(0 to NUM_ENDPOINTS-1);
    signal data_rh_fire, data_rh_firb : std_logic_vector(WORD_WIDTH downto 0);
    signal full_firb_rh, write_rh_firb : std_logic;
    signal read_rb_firb, empty_firb_rb : std_logic;
    signal data_firb_rb : std_logic_vector(WORD_WIDTH downto 0);
    signal read_re_fire, empty_fire_re : std_logic_vector(0 to NUM_ENDPOINTS);
    signal data_fire_re : EARRAY_DATA_TYPE;
    signal alive_re_rb, full_frbre_re, write_rb_frbre : std_logic_vector(0 to NUM_ENDPOINTS-1);
    signal data_rb_frbre , data_rb_firo : std_logic_vector(WORD_WIDTH downto 0);
    signal full_firo_rb, write_rb_firo : std_logic;
    signal empty_frbre_re, read_re_frbre : std_logic_vector(0 to NUM_ENDPOINTS-1);
    signal data_frbre_re : EARRAY_DATA_TYPE;
    signal full_firo_re, write_re_firo : std_logic_vector(0 to NUM_ENDPOINTS-1);
    signal data_re_firo : EARRAY_DATA_TYPE;
    signal start_rr_dr, ack_dr_rr, done_dr_rr, valid_rr_dr, ready_dr_rr : std_logic_vector(0 to NUM_READERS-1);
    signal opcode_rr_dr : HISTORY_CACHE_OPCODE_RARRAY_TYPE;
    signal ret_dr_rr : HISTORY_CACHE_RESPONSE_RARRAY_TYPE;
    signal data_rr_dr : RARRAY_DATA_TYPE;
    signal liveliness_assertion_dw_rw, data_available_dw_rw, start_rw_dw, ack_dw_rw, done_rw_dw, get_data_rw_dw, valid_dw_rw, ready_rw_dw : std_logic_vector(0 to NUM_WRITERS-1);
    signal opcode_rw_dw : HISTORY_CACHE_OPCODE_WARRAY_TYPE;
    signal seq_nr_rw_dw, cc_seq_nr_dw_rw : SEQUENCENUMBER_WARRAY_TYPE;
    signal ret_dw_rw : HISTORY_CACHE_RESPONSE_WARRAY_TYPE;
    signal data_dw_rw : WARRAY_DATA_TYPE;
    signal cc_instance_handle_dw_rw : INSTANCE_HANDLE_WARRAY_TYPE;
    signal cc_kind_dw_rw : CACHE_CHANGE_KIND_WARRAY_TYPE;
    signal cc_source_timestamp_dw_rw : TIME_WARRAY_TYPE;
    signal sample_info_dr_ri : SAMPLE_INFO_RARRAY_TYPE;
    signal start_ri_dr, ack_dr_ri, get_data_ri_dr, done_dr_ri, ready_ri_dr, valid_dr_ri, sample_info_valid_dr_ri, sample_info_ack_ri_dr, eoc_dr_ri : std_logic_vector(0 to NUM_READERS-1);
    signal opcode_ri_dr : DDS_READER_OPCODE_RARRAY_TYPE;
    signal instance_state_ri_dr : INSTANCE_STATE_RARRAY_TYPE;
    signal view_state_ri_dr : VIEW_STATE_RARRAY_TYPE;
    signal sample_state_ri_dr : SAMPLE_STATE_RARRAY_TYPE;
    signal instance_handle_ri_dr : INSTANCE_HANDLE_RARRAY_TYPE;
    signal max_samples_ri_dr : MAX_SAMPLES_RARRAY_TYPE;
    signal return_code_dr_ri : RETURN_CODE_RARRAY_TYPE;
    signal data_dr_ri : RARRAY_DATA_TYPE;
    signal status_dr_ri : STATUS_KIND_RARRAY_TYPE;
    signal start_wi_dw, ack_dw_wi, done_dw_wi, valid_wi_dw, valid_dw_wi, ready_wi_dw, ready_dw_wi : std_logic_vector(0 to NUM_WRITERS-1);
    signal opcode_wi_dw : DDS_WRITER_OPCODE_WARRAY_TYPE;
    signal instance_handle_wi_dw, instance_handle_dw_wi : INSTANCE_HANDLE_WARRAY_TYPE;
    signal source_ts_wi_dw : TIME_WARRAY_TYPE;
    signal max_wait_wi_dw : DURATION_WARRAY_TYPE;
    signal return_code_dw_wi : RETURN_CODE_WARRAY_TYPE;
    signal data_dw_wi, data_wi_dw : WARRAY_DATA_TYPE;
    signal status_dw_wi : STATUS_KIND_WARRAY_TYPE;
    signal empty_firo_ro, read_ro_firo, last_word_firo_ro : std_logic_vector(0 to NUM_ENDPOINTS);
    signal data_firo_ro : RTPS_OUT_DATA_TYPE;
    
begin
    
    
    rtps_handler_inst : entity work.rtps_handler(arch)
        port map (
            -- SYSTEM
            clk                 => clk,
            reset               => reset,
            -- INPUT
            empty               => empty,
            rd                  => read,
            data_in             => data_in,
            -- TO DISCOVERY MODULE
            full_dm             => full_firb_rh,
            wr_dm               => write_rh_firb,
            data_out_dm         => data_rh_firb(WORD_WIDTH-1 downto 0),
            last_word_out_dm    => data_rh_firb(WORD_WIDTH),
            -- TO USER ENDPOINTS
            full_rtps             => full_fire_rh,
            wr_rtps               => write_rh_fire,
            data_out_rtps         => data_rh_fire(WORD_WIDTH-1 downto 0),
            last_word_out_rtps    => data_rh_fire(WORD_WIDTH)
        );
    
    
    fifo_in_rb_inst : configuration work.FWFT_FIFO_cfg
            generic map (
                FIFO_DEPTH  => 2,
                DATA_WIDTH  => WORD_WIDTH+1
            )
            port map (
                -- SYSTEM
                reset       => reset,
                clk         => clk,
                -- INPUT
                full        => full_firb_rh,
                write       => write_rh_firb,
                data_in     => data_rh_firb,
                -- OUTPUT
                empty       => empty_firb_rb,
                read        => read_rb_firb,
                data_out    => data_firb_rb,
                -- MISC
                free        => open
            );
    
    
    fifo_in_re_gen : for i in 0 to NUM_ENDPOINTS-1 generate
        fifo_in_re_inst : configuration work.FWFT_FIFO_cfg
            generic map (
                FIFO_DEPTH  => 2,
                DATA_WIDTH  => WORD_WIDTH+1
            )
            port map (
                -- SYSTEM
                reset       => reset,
                clk         => clk,
                -- INPUT
                full        => full_fire_rh(i),
                write       => write_rh_fire(i),
                data_in     => data_rh_fire, -- Multicast
                -- OUTPUT
                empty       => empty_fire_re(i),
                read        => read_re_fire(i),
                data_out    => data_fire_re(i),
                -- MISC
                free        => open
            );
    end generate;
    
    
    rtps_discovery_module_inst : entity work.rtps_discovery_module(arch)
        generic map (
            MAX_REMOTE_PARTICIPANTS => MAX_REMOTE_PARTICIPANTS,
            PREFER_MULTICAST        => PREFER_MULTICAST_LOCATORS
        )
        port map (
            clk                 => clk,
            reset               => reset,
            time                => time,
            -- FROM RTPS HANDLER
            empty               => empty_firb_rb,
            rd                  => read_rb_firb,
            data_in             => data_firb_rb(WORD_WIDTH-1 downto 0),
            last_word_in        => data_firb_rb(WORD_WIDTH),
            -- FROM USER ENDPOINTS
            alive               => alive_re_rb,
            -- TO USER ENDPOINTS
            full_rtps             => full_frbre_re,
            wr_rtps               => write_rb_frbre,
            data_out_rtps         => data_rb_frbre(WORD_WIDTH-1 downto 0),
            last_word_out_rtps    => data_rb_frbre(WORD_WIDTH),
            -- TO RTPS OUT
            full_ro             => full_firo_rb,
            wr_ro               => write_rb_firo,
            data_out_ro         => data_rb_firo(WORD_WIDTH-1 downto 0),
            last_word_out_ro    => data_rb_firo(WORD_WIDTH)
        );
    
    
    fifo_rb_re_gen : for i in 0 to NUM_ENDPOINTS-1 generate
        fifo_rb_re_inst : configuration work.FWFT_FIFO_cfg
            generic map (
                FIFO_DEPTH  => 2,
                DATA_WIDTH  => WORD_WIDTH+1
            )
            port map (
                -- SYSTEM
                reset       => reset,
                clk         => clk,
                -- INPUT
                full        => full_frbre_re(i),
                write       => write_rb_frbre(i),
                data_in     => data_rb_frbre, -- Multicast
                -- OUTPUT
                empty       => empty_frbre_re(i),
                read        => read_re_frbre(i),
                data_out    => data_frbre_re(i),
                -- MISC
                free        => open
            );
    end generate;
    
    
    rtps_endpoint_gen : for i in 0 to NUM_ENDPOINTS-1 generate
        rtps_endpoint_if : if (i < NUM_READERS) generate
            rtps_reader_inst : entity work.rtps_reader(arch)
                generic map (
                    ENTITYID                    => ENTITYID(i),
                    RELIABILITY_QOS             => ENDPOINT_CONFIG(i).RELIABILITY_QOS,
                    LIVELINESS_QOS              => ENDPOINT_CONFIG(i).LIVELINESS_QOS,
                    DURABILITY_QOS              => ENDPOINT_CONFIG(i).DURABILITY_QOS,
                    HEARTBEAT_RESPONSE_DELAY    => ENDPOINT_CONFIG(i).HEARTBEAT_RESPONSE_DELAY,
                    HEARTBEAT_SUPPRESSION_DELAY => ENDPOINT_CONFIG(i).HEARTBEAT_SUPPRESSION_DELAY,
                    LEASE_DURATION              => ENDPOINT_CONFIG(i).LEASE_DURATION,
                    WITH_KEY                    => ENDPOINT_CONFIG(i).WITH_KEY,
                    MAX_REMOTE_ENDPOINTS        => MAX_REMOTE_ENDPOINTS
                )
                port map (
                    -- SYSTEM
                    clk                     => clk,
                    reset                   => reset,
                    time                    => time,
                    -- FROM RTPS_HANDLER (USER TRAFFIC)
                    empty_user              => empty_fire_re(i),
                    rd_user                 => read_re_fire(i),
                    data_in_user            => data_fire_re(i)(WORD_WIDTH-1 downto 0),
                    last_word_in_user       => data_fire_re(i)(WORD_WIDTH),
                    -- FROM DISCOVERY MODULE (META TRAFFIC)
                    empty_meta              => empty_frbre_re(i),
                    rd_meta                 => read_re_frbre(i),
                    data_in_meta            => data_frbre_re(i)(WORD_WIDTH-1 downto 0),
                    last_word_in_meta       => data_frbre_re(i)(WORD_WIDTH),
                    -- RTPS OUTPUT
                    full_ro                 => full_firo_re(i),
                    wr_ro                   => write_re_firo(i),
                    data_out_ro             => data_re_firo(i)(WORD_WIDTH-1 downto 0),
                    last_word_out_ro        => data_re_firo(i)(WORD_WIDTH),
                    -- TO HISTORY CACHE
                    start_hc                => start_rr_dr(i),
                    opcode_hc               => opcode_rr_dr(i),
                    ack_hc                  => ack_dr_rr(i),
                    done_hc                 => done_dr_rr(i),
                    ret_hc                  => ret_dr_rr(i),
                    valid_out_hc            => valid_rr_dr(i),
                    ready_out_hc            => ready_dr_rr(i),
                    data_out_hc             => data_rr_dr(i)(WORD_WIDTH-1 downto 0),
                    last_word_out_hc        => data_rr_dr(i)(WORD_WIDTH)
                );
            
            -- Set Alive Signals of Readers to Zero
            alive_re_rb(i) <= ('0');
        else generate
            rtps_writer_inst : entity work.rtps_writer(arch)
                generic map (
                    RELIABILITY_QOS             => ENDPOINT_CONFIG(i).RELIABILITY_QOS,
                    LIVELINESS_QOS              => ENDPOINT_CONFIG(i).LIVELINESS_QOS,
                    DURABILITY_QOS              => ENDPOINT_CONFIG(i).DURABILITY_QOS,
                    DESTINATION_ORDER_QOS       => ENDPOINT_CONFIG(i).DESTINATION_ORDER_QOS,
                    ACKNACK_RESPONSE_DELAY      => ENDPOINT_CONFIG(i).ACKNACK_RESPONSE_DELAY,
                    ACKNACK_SUPPRESSION_DELAY   => ENDPOINT_CONFIG(i).ACKNACK_SUPPRESSION_DELAY,
                    LEASE_DURATION              => ENDPOINT_CONFIG(i).LEASE_DURATION,
                    HEARTBEAT_PERIOD            => ENDPOINT_CONFIG(i).HEARTBEAT_PERIOD,
                    ENTITYID                    => ENTITYID(i),
                    WITH_KEY                    => ENDPOINT_CONFIG(i).WITH_KEY,
                    PUSH_MODE                   => ENDPOINT_CONFIG(i).PUSH_MODE,
                    INLINE_QOS                  => gen_inline_qos(i),
                    MAX_REMOTE_ENDPOINTS        => MAX_REMOTE_ENDPOINTS
                )
                port map (
                    -- SYSTEM
                    clk                     => clk,
                    reset                   => reset,
                    time                    => time,
                    -- FROM RTPS_HANDLER (USER TRAFFIC)
                    empty_user              => empty_fire_re(i),
                    rd_user                 => read_re_fire(i),
                    data_in_user            => data_fire_re(i)(WORD_WIDTH-1 downto 0),
                    last_word_in_user       => data_fire_re(i)(WORD_WIDTH),
                    -- FROM DISCOVERY MODULE (META TRAFFIC)
                    empty_meta              => empty_frbre_re(i),
                    rd_meta                 => read_re_frbre(i),
                    data_in_meta            => data_frbre_re(i)(WORD_WIDTH-1 downto 0),
                    last_word_in_meta       => data_frbre_re(i)(WORD_WIDTH),
                    -- TO DISCOVERY MODULE (META TRAFFIC)
                    alive_sig               => alive_re_rb(i),
                    -- RTPS OUTPUT
                    full_ro                 => full_firo_re(i),
                    wr_ro                   => write_re_firo(i),
                    data_out_ro             => data_re_firo(i)(WORD_WIDTH-1 downto 0),
                    last_word_out_ro        => data_re_firo(i)(WORD_WIDTH),
                    -- FROM HC
                    liveliness_assertion    => liveliness_assertion_dw_rw(i-NUM_READERS),
                    data_available          => data_available_dw_rw(i-NUM_READERS),
                    start_hc                => start_rw_dw(i-NUM_READERS),
                    opcode_hc               => opcode_rw_dw(i-NUM_READERS),
                    ack_hc                  => ack_dw_rw(i-NUM_READERS),
                    seq_nr_hc               => seq_nr_rw_dw(i-NUM_READERS),
                    done_hc                 => done_rw_dw(i-NUM_READERS),
                    ret_hc                  => ret_dw_rw(i-NUM_READERS),
                    get_data_hc             => get_data_rw_dw(i-NUM_READERS),
                    valid_in_hc             => valid_dw_rw(i-NUM_READERS),
                    ready_in_hc             => ready_rw_dw(i-NUM_READERS),
                    data_in_hc              => data_dw_rw(i-NUM_READERS)(WORD_WIDTH-1 downto 0),
                    last_word_in_hc         => data_dw_rw(i-NUM_READERS)(WORD_WIDTH),
                    cc_instance_handle      => cc_instance_handle_dw_rw(i-NUM_READERS),
                    cc_kind                 => cc_kind_dw_rw(i-NUM_READERS),
                    cc_source_timestamp     => cc_source_timestamp_dw_rw(i-NUM_READERS),
                    cc_seq_nr               => cc_seq_nr_dw_rw(i-NUM_READERS)
                );
        end generate;
    end generate;
    
    
    dds_endpoint_gen : for i in 0 to NUM_ENDPOINTS-1 generate
        dds_endpoint_if : if (i < NUM_READERS) generate
            dds_reader_inst : entity work.dds_reader(arch)
                generic map (
                    TIME_BASED_FILTER_QOS       => ENDPOINT_CONFIG(i).TIME_BASED_FILTER_QOS,
                    DEADLINE_QOS                => ENDPOINT_CONFIG(i).DEADLINE_QOS,
                    MAX_INSTANCES               => ENDPOINT_CONFIG(i).MAX_INSTANCES,
                    MAX_SAMPLES_PER_INSTANCE    => ENDPOINT_CONFIG(i).MAX_SAMPLES_PER_INSTANCE,
                    MAX_SAMPLES                 => ENDPOINT_CONFIG(i).MAX_SAMPLES,
                    HISTORY_QOS                 => ENDPOINT_CONFIG(i).HISTORY_QOS,
                    RELIABILITY_QOS             => ENDPOINT_CONFIG(i).RELIABILITY_QOS,
                    PRESENTATION_QOS            => ENDPOINT_CONFIG(i).PRESENTATION_QOS,
                    DESTINATION_ORDER_QOS       => ENDPOINT_CONFIG(i).DESTINATION_ORDER_QOS,
                    COHERENT_ACCESS             => ENDPOINT_CONFIG(i).COHERENT_ACCESS,
                    ORDERED_ACCESS              => ENDPOINT_CONFIG(i).ORDERED_ACCESS,
                    WITH_KEY                    => ENDPOINT_CONFIG(i).WITH_KEY,
                    PAYLOAD_FRAME_SIZE          => ENDPOINT_CONFIG(i).MAX_PAYLOAD_SIZE,
                    MAX_REMOTE_ENDPOINTS        => MAX_REMOTE_ENDPOINTS
                )
                port map (
                    -- SYSTEM
                    clk                             => clk,
                    reset                           => reset,
                    time                            => time,
                    -- FROM RTPS ENDPOINT
                    start_rtps                      => start_rr_dr(i),
                    opcode_rtps                     => opcode_rr_dr(i),
                    ack_rtps                        => ack_dr_rr(i),
                    done_rtps                       => done_dr_rr(i),
                    ret_rtps                        => ret_dr_rr(i),
                    valid_in_rtps                   => valid_rr_dr(i),
                    ready_in_rtps                   => ready_dr_rr(i),
                    data_in_rtps                    => data_rr_dr(i)(WORD_WIDTH-1 downto 0),
                    last_word_in_rtps               => data_rr_dr(i)(WORD_WIDTH),
                    -- TO USER ENTITY
                    start_dds                       => start_ri_dr(i),
                    ack_dds                         => ack_dr_ri(i),
                    opcode_dds                      => opcode_ri_dr(i),
                    instance_state_dds              => instance_state_ri_dr(i),
                    view_state_dds                  => view_state_ri_dr(i),
                    sample_state_dds                => sample_state_ri_dr(i),
                    instance_handle_dds             => instance_handle_ri_dr(i),
                    max_samples_dds                 => max_samples_ri_dr(i),
                    get_data_dds                    => get_data_ri_dr(i),
                    done_dds                        => done_dr_ri(i),
                    return_code_dds                 => return_code_dr_ri(i),
                    valid_out_dds                   => valid_dr_ri(i),
                    ready_out_dds                   => ready_ri_dr(i),
                    data_out_dds                    => data_dr_ri(i)(WORD_WIDTH-1 downto 0),
                    last_word_out_dds               => data_dr_ri(i)(WORD_WIDTH),
                    sample_info                     => sample_info_dr_ri(i),
                    sample_info_valid               => sample_info_valid_dr_ri(i),
                    sample_info_ack                 => sample_info_ack_ri_dr(i),
                    eoc                             => eoc_dr_ri(i),
                    -- Communication Status
                    status                          => status_dr_ri(i)
                );
        else generate
            dds_writer_inst : entity work.dds_writer(arch)
                generic map (
                    HISTORY_QOS                 => ENDPOINT_CONFIG(i).HISTORY_QOS,
                    DEADLINE_QOS                => ENDPOINT_CONFIG(i).DEADLINE_QOS,
                    LIFESPAN_QOS                => ENDPOINT_CONFIG(i).LIFESPAN_QOS,
                    LEASE_DURATION              => ENDPOINT_CONFIG(i).LEASE_DURATION,
                    WITH_KEY                    => ENDPOINT_CONFIG(i).WITH_KEY,
                    MAX_SAMPLES                 => ENDPOINT_CONFIG(i).MAX_SAMPLES,
                    MAX_INSTANCES               => ENDPOINT_CONFIG(i).MAX_INSTANCES,
                    MAX_SAMPLES_PER_INSTANCE    => ENDPOINT_CONFIG(i).MAX_SAMPLES_PER_INSTANCE,
                    PAYLOAD_FRAME_SIZE          => ENDPOINT_CONFIG(i).MAX_PAYLOAD_SIZE
                )
                port map (
                    -- SYSTEM
                    clk                     => clk,
                    reset                   => reset,
                    time                    => time,
                    -- TO/FROM RTPS ENDPOINT
                    start_rtps              => start_rw_dw(i-NUM_READERS),
                    opcode_rtps             => opcode_rw_dw(i-NUM_READERS),
                    ack_rtps                => ack_dw_rw(i-NUM_READERS),
                    done_rtps               => done_rw_dw(i-NUM_READERS),
                    ret_rtps                => ret_dw_rw(i-NUM_READERS),
                    seq_nr_rtps             => seq_nr_rw_dw(i-NUM_READERS),
                    get_data_rtps           => get_data_rw_dw(i-NUM_READERS),
                    valid_out_rtps          => valid_dw_rw(i-NUM_READERS),
                    ready_out_rtps          => ready_rw_dw(i-NUM_READERS),
                    data_out_rtps           => data_dw_rw(i-NUM_READERS)(WORD_WIDTH-1 downto 0),
                    last_word_out_rtps      => data_dw_rw(i-NUM_READERS)(WORD_WIDTH),
                    liveliness_assertion    => liveliness_assertion_dw_rw(i-NUM_READERS),
                    data_available          => data_available_dw_rw(i-NUM_READERS),
                    -- Cache Change
                    cc_instance_handle      => cc_instance_handle_dw_rw(i-NUM_READERS),
                    cc_kind                 => cc_kind_dw_rw(i-NUM_READERS),
                    cc_source_timestamp     => cc_source_timestamp_dw_rw(i-NUM_READERS),
                    cc_seq_nr               => cc_seq_nr_dw_rw(i-NUM_READERS),
                    -- TO/FROM USER ENTITY
                    start_dds               => start_wi_dw(i-NUM_READERS),
                    ack_dds                 => ack_dw_wi(i-NUM_READERS),
                    opcode_dds              => opcode_wi_dw(i-NUM_READERS),
                    instance_handle_in_dds  => instance_handle_wi_dw(i-NUM_READERS),
                    source_ts_dds           => source_ts_wi_dw(i-NUM_READERS),
                    max_wait_dds            => max_wait_wi_dw(i-NUM_READERS),
                    done_dds                => done_dw_wi(i-NUM_READERS),
                    return_code_dds         => return_code_dw_wi(i-NUM_READERS),
                    instance_handle_out_dds => instance_handle_dw_wi(i-NUM_READERS),
                    valid_in_dds            => valid_wi_dw(i-NUM_READERS),
                    ready_in_dds            => ready_dw_wi(i-NUM_READERS),
                    data_in_dds             => data_wi_dw(i-NUM_READERS)(WORD_WIDTH-1 downto 0),
                    last_word_in_dds        => data_wi_dw(i-NUM_READERS)(WORD_WIDTH),
                    valid_out_dds           => valid_dw_wi(i-NUM_READERS),
                    ready_out_dds           => ready_wi_dw(i-NUM_READERS),
                    data_out_dds            => data_dw_wi(i-NUM_READERS)(WORD_WIDTH-1 downto 0),
                    last_word_out_dds       => data_dw_wi(i-NUM_READERS)(WORD_WIDTH),
                    -- Communication Status
                    status                  => status_dw_wi(i-NUM_READERS)
                );
        end generate;
    end generate;
    
    
    fifo_in_ro_gen : for i in 0 to NUM_ENDPOINTS generate
        fifo_in_ro_if : if (i = NUM_ENDPOINTS) generate
            fifo_in_ro_inst : configuration work.FWFT_FIFO_cfg
                generic map (
                    FIFO_DEPTH  => 2,
                    DATA_WIDTH  => WORD_WIDTH+1
                )
                port map (
                    -- SYSTEM
                    reset       => reset,
                    clk         => clk,
                    -- INPUT
                    full        => full_firo_rb,
                    write       => write_rb_firo,
                    data_in     => data_rb_firo,
                    -- OUTPUT
                    empty       => empty_firo_ro(i),
                    read        => read_ro_firo(i),
                    data_out(WORD_WIDTH)            => last_word_firo_ro(i),
                    data_out(WORD_WIDTH-1 downto 0) => data_firo_ro(i),
                    -- MISC
                    free        => open
                );
        else generate        
            fifo_in_ro_inst : configuration work.FWFT_FIFO_cfg
                generic map (
                    FIFO_DEPTH  => 2,
                    DATA_WIDTH  => WORD_WIDTH+1
                )
                port map (
                    -- SYSTEM
                    reset       => reset,
                    clk         => clk,
                    -- INPUT
                    full        => full_firo_re(i),
                    write       => write_re_firo(i),
                    data_in     => data_re_firo(i),
                    -- OUTPUT
                    empty       => empty_firo_ro(i),
                    read        => read_ro_firo(i),
                    data_out(WORD_WIDTH)            => last_word_firo_ro(i),
                    data_out(WORD_WIDTH-1 downto 0) => data_firo_ro(i),
                    -- MISC
                    free        => open
                );
        end generate;
    end generate;
    
    
    rtps_out_inst : entity work.rtps_out(arch)
        port map (
            -- SYSTEM
            clk             => clk,
            reset           => reset,
            -- INPUT
            empty           => empty_firo_ro,
            rd              => read_ro_firo,
            data_in         => data_firo_ro,
            last_word_in    => last_word_firo_ro,
            -- OUTPUT
            full            => full,
            wr              => write,
            data_out        => data_out
        );
    
    
    --#####################################################################
    
    
    Type1_reader_interface_inst : entity work.Type1_reader_interface(arch)
        port map (
            -- SYSTEM
            clk                                 => clk,
            reset                               => reset,
            -- FROM DDS READER
            start_dds                           => start_ri_dr(0),
            ack_dds                             => ack_dr_ri(0),
            opcode_dds                          => opcode_ri_dr(0),
            instance_state_dds                  => instance_state_ri_dr(0),
            view_state_dds                      => view_state_ri_dr(0),
            sample_state_dds                    => sample_state_ri_dr(0),
            instance_handle_dds                 => instance_handle_ri_dr(0),
            max_samples_dds                     => max_samples_ri_dr(0),
            get_data_dds                        => get_data_ri_dr(0),
            done_dds                            => done_dr_ri(0),
            return_code_dds                     => return_code_dr_ri(0),
            valid_in_dds                        => valid_dr_ri(0),
            ready_in_dds                        => ready_ri_dr(0),
            data_in_dds                         => data_dr_ri(0)(WORD_WIDTH-1 downto 0),
            last_word_in_dds                    => data_dr_ri(0)(WORD_WIDTH),
            sample_info_dds                     => sample_info_dr_ri(0),
            sample_info_valid_dds               => sample_info_valid_dr_ri(0),
            sample_info_ack_dds                 => sample_info_ack_ri_dr(0),
            eoc_dds                             => eoc_dr_ri(0),
            -- Communication Status
            status_dds                          => status_dr_ri(0),
            -- TO USER ENTITY
            start_user                          => start_r,
            ack_user                            => ack_r,
            opcode_user                         => opcode_r,
            instance_state_user                 => instance_state_r,
            view_state_user                     => view_state_r,
            sample_state_user                   => sample_state_r,
            instance_handle_user                => instance_handle_r,
            max_samples_user                    => max_samples_r,
            get_data_user                       => get_data_r,
            done_user                           => done_r,
            return_code_user                    => return_code_r,
            sample_info_user                    => sample_info_r,
            sample_info_valid_user              => sample_info_valid_r,
            sample_info_ack_user                => sample_info_ack_r,
            eoc_user                            => eoc_r,
            -- Communication Status
            status_user                         => status_r,
            decode_error                        => decode_error_r,
            -- ###GENERATED START###
            id                                  => id_r,
            a                                   => a_r,
            -- ###GENERATED END###
            valid                               => valid_r
        );
    
    
    Type1_writer_interface_inst : entity work.Type1_writer_interface(arch)
        port map (
            -- SYSTEM
            clk                         => clk,
            reset                       => reset,
            -- FROM DDS WRITER
            start_dds                   => start_wi_dw(0),
            ack_dds                     => ack_dw_wi(0),
            opcode_dds                  => opcode_wi_dw(0),
            instance_handle_in_dds      => instance_handle_wi_dw(0),
            source_ts_dds               => source_ts_wi_dw(0),
            max_wait_dds                => max_wait_wi_dw(0),
            done_dds                    => done_dw_wi(0),
            return_code_dds             => return_code_dw_wi(0),
            instance_handle_out_dds     => instance_handle_dw_wi(0),
            valid_out_dds               => valid_wi_dw(0),
            ready_out_dds               => ready_dw_wi(0),
            data_out_dds                => data_wi_dw(0)(WORD_WIDTH-1 downto 0),
            last_word_out_dds           => data_wi_dw(0)(WORD_WIDTH),
            valid_in_dds                => valid_dw_wi(0),
            ready_in_dds                => ready_wi_dw(0),
            data_in_dds                 => data_dw_wi(0)(WORD_WIDTH-1 downto 0),
            last_word_in_dds            => data_dw_wi(0)(WORD_WIDTH),
            -- Communication Status
            status_dds                  => status_dw_wi(0),
            -- TO USER ENTITY
            start_user                  => start_w,
            ack_user                    => ack_w,
            opcode_user                 => opcode_w,
            instance_handle_in_user     => instance_handle_in_w,
            source_ts_user              => source_ts_w,
            max_wait_user               => max_wait_w,
            done_user                   => done_w,
            return_code_user            => return_code_w,
            instance_handle_out_user    => instance_handle_out_w,
            -- Communication Status
            status_user                 => status_w,
            -- ###GENERATED START###
            id                          => id_w,
            a                           => a_w,
            -- ###GENERATED END###
            encode_done                 => encode_done_w
        );
    
end architecture;
