-- 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.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;

entity rtps_writer is
    generic (
        -- HACK: FIXME: Quartus Workaround
        --  Quartus does not allow to reference a generic insisde the generic block.
        --  So we constrain the range later as constant
        NUM_WRITERS             : natural;
        CONFIG_ARRAY            : QUARTUS_CONFIG_ARRAY_TYPE;
            -- RELIABILITY_QOS
            -- LIVELINESS_QOS
            -- DURABILITY_QOS
            -- DESTINATION_ORDER_QOS
            -- LEASE_DURATION
            -- WITH_KEY
            -- PUSH_MODE
            -- HEARTBEAT_PERIOD
            -- ACKNACK_RESPONSE_DELAY
            -- ACKNACK_SUPPRESSION_DELAY
        ENTITYID                : ENTITYID_ARRAY_TYPE;
        INLINE_QOS              : OUTPUT_DATA_ARRAY_TYPE;
        MAX_REMOTE_ENDPOINTS    : natural := 50
    );
    port (
        -- SYSTEM
        clk                     : in std_logic;
        reset                   : in std_logic;
        time                    : in TIME_TYPE;
        -- FROM RTPS HANDLER (USER TRAFFIC)
        empty_user              : in std_logic_vector(0 to NUM_WRITERS-1);
        rd_user                 : out std_logic;
        data_in_user            : in std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_in_user       : in std_logic;
        -- FROM DISCOVERY MODULE (META TRAFFIC)
        empty_meta              : in std_logic_vector(0 to NUM_WRITERS-1);
        rd_meta                 : out std_logic;
        data_in_meta            : in std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_in_meta       : in std_logic;
        -- TO DISCOVERY MODULE (META TRAFFIC)
        alive_sig               : out std_logic_vector(0 to NUM_WRITERS-1);
        -- RTPS OUTPUT
        full_ro                 : in std_logic;
        wr_ro                   : out std_logic;
        data_out_ro             : out std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_out_ro        : out std_logic;
        -- FROM HISTORY CACHE
        liveliness_assertion    : in std_logic_vector(0 to NUM_WRITERS-1);
        data_available          : in std_logic_vector(0 to NUM_WRITERS-1);
        start_hc                : out std_logic_vector(0 to NUM_WRITERS-1);
        opcode_hc               : out HISTORY_CACHE_OPCODE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        ack_hc                  : in std_logic_vector(0 to NUM_WRITERS-1);
        seq_nr_hc               : out SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1);
        done_hc                 : in std_logic_vector(0 to NUM_WRITERS-1);
        ret_hc                  : in HISTORY_CACHE_RESPONSE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        get_data_hc             : out std_logic_vector(0 to NUM_WRITERS-1);
        valid_in_hc             : in std_logic_vector(0 to NUM_WRITERS-1);
        ready_in_hc             : out std_logic_vector(0 to NUM_WRITERS-1);
        data_in_hc              : in WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
        last_word_in_hc         : in std_logic_vector(0 to NUM_WRITERS-1);
        cc_instance_handle      : in INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_kind                 : in CACHE_CHANGE_KIND_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_source_timestamp     : in TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_seq_nr               : in SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1)
    );
end entity;

architecture arch of rtps_writer is
    
    constant CONFIG_ARRAY_T : QUARTUS_CONFIG_ARRAY_TYPE(0 to NUM_WRITERS-1) := CONFIG_ARRAY;
    constant ENTITYID_T     : ENTITYID_ARRAY_TYPE(0 to NUM_WRITERS-1) := ENTITYID;
    constant INLINE_QOS_T   : OUTPUT_DATA_ARRAY_TYPE(0 to NUM_WRITERS-1) := INLINE_QOS;
    
    --*****CONSTANT DECLARATION*****
    function gen_manual_by_topic_livelines_writers(qos : QUARTUS_CONFIG_ARRAY_TYPE) return std_logic_vector is
        variable ret : std_logic_vector(0 to NUM_WRITERS-1) := (others => '0');
    begin
        assert (qos'length = NUM_WRITERS) severity FAILURE;
        
        for i in 0 to NUM_WRITERS-1 loop
            if (qos(i).LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then
                ret(i)  := '1';
            end if;
        end loop;
        return ret;
    end function;
    constant MANUAL_BY_TOPIC_LIVELINESS_WRITERS : std_logic_vector(0 to NUM_WRITERS-1) := gen_manual_by_topic_livelines_writers(CONFIG_ARRAY_T);
    
    function gen_reliable_writers(qos : QUARTUS_CONFIG_ARRAY_TYPE) return std_logic_vector is
        variable ret : std_logic_vector(0 to NUM_WRITERS-1) := (others => '0');
    begin
        assert (qos'length = NUM_WRITERS) severity FAILURE;
        
        for i in 0 to NUM_WRITERS-1 loop
            if (qos(i).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                ret(i)  := '1';
            end if;
        end loop;
        return ret;
    end function;
    constant RELIABLE_WRITERS : std_logic_vector(0 to NUM_WRITERS-1) := gen_reliable_writers(CONFIG_ARRAY_T);
    
    constant ZERO_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := (others => (others => '0'));
    -- *ENDPOINT MEMORY*
    -- 4-Byte Word Size of a Remote Endpoint Entry in Memory
    constant ENDPOINT_FRAME_SIZE            : natural := 17;
    -- Endpoint Memory Size in 4-Byte Words
    constant ENDPOINT_MEMORY_SIZE           : natural := MAX_REMOTE_ENDPOINTS * ENDPOINT_FRAME_SIZE;
    -- Endpoint Memory Address Width
    constant ENDPOINT_MEMORY_ADDR_WIDTH     : natural := log2c(ENDPOINT_MEMORY_SIZE);
    -- Highest Endpoint Memory Address
    constant ENDPOINT_MEMORY_MAX_ADDRESS    : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH);
    -- Highest Endpoint Frame Address
    constant MAX_ENDPOINT_ADDRESS           : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := ENDPOINT_MEMORY_MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Endpoint Data Frame
    constant FIRST_ENDPOINT_ADDRESS         : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *ENDPOINT MEMORY FRAME FIELD FLAGS*
    -- Flags mapping to the respective Endpoint Memory Frame Fields
    constant EMF_FLAG_WIDTH             : natural := 9;
    constant EMF_ENTITYID_FLAG          : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (0 => '1', others => '0');
    constant EMF_GUIDPREFIX_FLAG        : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (1 => '1', others => '0');
    constant EMF_IPV4_ADDR_FLAG         : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (2 => '1', others => '0');
    constant EMF_UDP_PORT_FLAG          : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (3 => '1', others => '0');
    constant EMF_LEASE_DEADLINE_FLAG    : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (4 => '1', others => '0');
    constant EMF_RES_TIME_FLAG          : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (5 => '1', others => '0');
    constant EMF_ACK_SEQ_NR_BASE_FLAG   : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (6 => '1', others => '0');
    constant EMF_REQ_SEQ_NR_BASE_FLAG   : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (7 => '1', others => '0');
    constant EMF_REQ_SEQ_NR_BITMAP_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (8 => '1', others => '0');
    
    
    -- *ENDPOINT MEMORY FRAME FIELD OFFSETS*
    -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
    constant EMF_ENTITYID_OFFSET            : natural := 0;
    constant EMF_GUIDPREFIX_OFFSET          : natural := 1;
    constant EMF_IPV4_ADDR_OFFSET           : natural := 4;
    constant EMF_UDP_PORT_OFFSET            : natural := 5;
    constant EMF_LEASE_DEADLINE_OFFSET      : natural := 6;
    constant EMF_RES_TIME_OFFSET            : natural := 8;
    constant EMF_ACK_SEQ_NR_BASE_OFFSET     : natural := 10;
    constant EMF_REQ_SEQ_NR_BASE_OFFSET     : natural := 12;
    constant EMF_REQ_SEQ_NR_BITMAP_OFFSET   : natural := 14;
    constant EMF_NEXT_ADDR_OFFSET           : natural := 15;
    constant EMF_PREV_ADDR_OFFSET           : natural := 16;
    
    
    --*****TYPE DECLARATION*****
    type EMPTY_HEAD_SIG_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of natural;
    type ENDPOINT_ADDRESS_ARRAY_TYPE is array(0 to NUM_WRITERS-1) of unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
    type HEARTBEAT_COUNT_ARRAY is array (0 to NUM_WRITERS-1) of unsigned(COUNT_WIDTH-1 downto 0);
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE, LATCH_GUIDPREFIX, LATCH_ENTITYID, INITIATE_ENDPOINT_SEARCH, LATCH_ENDPOINT_DATA, METATRAFFIC_OPERATION, 
        LATCH_SRC_ADDR, LATCH_ACKNACK, PROCESS_ACK, UPDATE_GLOBAL_ACK, PROCESS_NACK, PARSE_NACK_BITMAP, ENDPOINT_STALE_CHECK, 
        HANDLE_REQUESTS, HANDLE_HEARTBEATS, HANDLE_NEW, HANDLE_HISTORICAL, SEND_HEADER, SEND_INFO_TS, 
        SEND_DATA_A, SEND_INLINE_QOS, SEND_DATA_B, SEND_GAP_A, SEND_GAP_B, SEND_HEARTBEAT, SKIP_PACKET, SKIP_META_OPERATION);
    -- Memory FSM states. Explained below in detail
    type MEM_STAGE_TYPE is (IDLE, SEARCH_ENDPOINT, GET_ENDPOINT_DATA, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, 
        GET_NEXT_ENDPOINT, RESET_MEMORY);
    -- *Memory FSM Opcodes*
    --  OPCODE              DESCRIPTION
    --  SEARCH_ENDPOINT     Search memory for Endpoint with GUID equal to "guid" signal.
    --                      Set "mem_endpoint_data.addr" to base Address of found Endpoint, or ENDPOINT_MEMORY_MAX_ADDRESS if nothing found.
    --                      "mem_endpoint_data" contains Endpoint Data according to "mem_r.field_flags".
    --  INSERT_ENDPOINT     Insert Endpoint in memory
    --  UPDATE_ENDPOINT     Update Endpoint pointed by "mem_r.addr" according to "mem_r.field_flags".
    --  REMOVE_ENDPOINT     Remove Endpoint pointed by "mem_r.addr".
    --                      "mem_endpoint_data.addr" is set to the next Endpoint (or ENDPOINT_MEMORY_MAX_ADDRESS if no next Endpoint exists)
    --  GET_NEXT_ENDPOINT   Get Endpoint Data of next Endpoint (from the Endpoint pointed by "mem_r.addr") according to "mem_r.field_flags".
    --                      Set "mem_endpoint_data.addr" to Address of Endpoint, or ENDPOINT_MEMORY_MAX_ADDRESS if no other Endpoint in Memory.
    --  GET_ENDPOINT        Get Endpoint Data from Endpoint pointed by "mem_r.addr" according to "mem_r.field_flags".
    --                      Already fetched data of the same Endpoint is not modified.
    type MEM_OPCODE_TYPE is (NOP, SEARCH_ENDPOINT, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, GET_NEXT_ENDPOINT, GET_ENDPOINT);
    -- Record of Endpoint Data
    type ENDPOINT_DATA_TYPE is record
        i                   : natural range 0 to NUM_WRITERS-1;
        addr                : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
        guid                : GUID_TYPE;
        ip_addr             : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
        portn               : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
        reader_flags        : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
        lease_deadline      : TIME_TYPE;
        res_time            : TIME_TYPE;
        ack_seq_nr_base     : SEQUENCENUMBER_TYPE;
        req_seq_nr_base     : SEQUENCENUMBER_TYPE;
        req_seq_nr_bitmap   : std_logic_vector(0 to WORD_WIDTH-1);
        field_flags         : std_logic_vector(0 to EMF_FLAG_WIDTH-1);
    end record;
    -- Zero initialized Endpoint Data
    constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := (
        i                   => 0,
        addr                => ENDPOINT_MEMORY_MAX_ADDRESS,
        guid                => GUID_UNKNOWN,
        ip_addr             => IPv4_ADDRESS_INVALID,
        portn               => UDP_PORT_INVALID,
        reader_flags        => (others => '0'),
        lease_deadline      => TIME_INVALID,
        res_time            => TIME_INVALID,
        ack_seq_nr_base     => SEQUENCENUMBER_UNKNOWN,
        req_seq_nr_base     => SEQUENCENUMBER_UNKNOWN,
        req_seq_nr_bitmap   => (others => '0'),
        field_flags         => (others => '0')
    );
    
    function get_max_length(input : OUTPUT_DATA_ARRAY_TYPE) return natural is
        variable ret : natural := 0;
    begin
        for i in input'range loop
            if (input(i).length-1 > ret) then
                ret := input(i).length-1;
            end if;
        end loop;
        return ret;
    end function;
    
    --*****SIGNAL DECLARATION*****
    -- *MAIN PROCESS*
    -- FSM state
    signal stage, stage_next : STAGE_TYPE;
    -- FSM state latch. Used to transition dynamically to different states from the same state.
    signal return_stage, return_stage_next : STAGE_TYPE;
    -- General Purpose Counter
    signal cnt, cnt_next : natural range 0 to 13;
    -- Counter Latch. Used to transition dynamically to different sub-states from the same state.
    signal return_cnt, return_cnt_next : natural range 0 to 13;
    -- Packet Opcode Latch (RTPS Message ID)
    signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0);
    -- Metatraffic Opcode Latch
    signal meta_opcode, meta_opcode_next : std_logic_vector(EMO_WIDTH-1 downto 0);
    -- Signifies if the received packet is a metatraffic operation
    signal is_meta, is_meta_next : std_logic;
    -- Source GUID Latch
    signal guid, guid_next : GUID_TYPE;
    -- Source IPv4 Address Latch
    signal addr, addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- UDP Port Latch
    signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- RTPS Header Flags Latch
    signal rtps_flags, rtps_flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0);
    -- Remote Endpoint Reader Flags Latch
    signal reader_flags, reader_flags_next : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
    -- Generic Sequence Number Latch
    signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE;
    -- Generic Sequence Number Latch
    signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE;
    -- Generic Sequence Number Latch
    signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE;
    -- ACKNACK ACK Base Sequencenumber
    signal ack_base, ack_base_next : SEQUENCENUMBER_TYPE;
    -- ACKNACK NACK Base Sequencenumber
    signal nack_base, nack_base_next : SEQUENCENUMBER_TYPE;
    -- General Purpose Long Latch
    signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    -- Toggle latching the "last_word_in_user" signal until reset
    signal last_word_in_latch, last_word_in_latch_next : std_logic;
    -- Toggle latch for Liveliness Assertion
    signal assert_liveliness_latch, assert_liveliness_latch_next : std_logic_vector(0 to NUM_WRITERS-1); -- TODO: mark
    -- Signifies which writers will get their liveliness manually asserted
    signal w_assert_liveliness, w_assert_liveliness_next : std_logic_vector(0 to NUM_WRITERS-1); -- TODO: mark
    -- Time of next Stale Endpoint Check
    signal check_time, check_time_next : TIME_TYPE;
    -- Time of next Heartbeat sending
    signal heartbeat_time, heartbeat_time_next : TIME_TYPE;
    -- Signifies if a Stale Endpoint Check is in progress
    signal stale_check, stale_check_next : std_logic;
    -- Signifies the new Cache Changes are currently being send out
    signal new_push, new_push_next : std_logic;
    -- Signifies that Historical Cache Changes are currently being sent out
    signal historical_push, historical_push_next : std_logic;
    -- Signifies that the first half of a GAP Message has been written, and needs to be "closed"
    signal gap_in_progress, gap_in_progress_next : std_logic;
    -- Signifies that the GAP is the Last Submessage
    signal gap_is_last, gap_is_last_next : std_logic;
    -- Signifies that an initial Heartbeat is sent to a remote Endpoint
    signal initial_heartbeat_next, initial_heartbeat : std_logic;
    -- Signal containing the RTPS Heartbeat Count Field
    signal count, count_next : HEARTBEAT_COUNT_ARRAY;
    -- Signal containing the lowest common Sequence Number ACKed by ALL remote Readers
    signal global_ack_seq_nr_base, global_ack_seq_nr_base_next : SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- Signal containing the highest Sequence Number sent out by the writer
    signal last_seq_nr, last_seq_nr_next : SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- Denotes the number of valid Bitmap longs (4-Byte words)
    signal bitmap_cnt, bitmap_cnt_next : unsigned(log2c(MAX_BITMAP_WIDTH/CDR_LONG_WIDTH)-1 downto 0);
    -- NumberSet Bitmap Latch
    signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE;
    -- Counter used to read out Bitmaps
    signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length;
    -- Counter used to read out the In-Line QoS
    signal cnt3, cnt3_next : natural range 0 to get_max_length(INLINE_QOS_T);
    -- Signal used to iterate through NACK Bitmaps
    signal nack_bitmap_pos, nack_bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1;
    -- Signals the start of a Memory Operation
    signal mem_op_start : std_logic;
    -- Opcode of the Memory Operation (Valid only when mem_op_start is high)
    signal mem_opcode : MEM_OPCODE_TYPE;
    -- Signals the end of a Memory Operation
    signal mem_op_done : std_logic;
    -- Signal used to pass data to memeory process
    signal mem_r : ENDPOINT_DATA_TYPE;
    -- Signal used to pass the Request Sequence Number Bitmap from main to memory process
    signal req_seq_nr_bitmap, req_seq_nr_bitmap_next : std_logic_vector(0 to WORD_WIDTH-1);
    -- Signal used to iterate through Request Bitmaps
    signal req_bitmap_pos, req_bitmap_pos_next : natural range 0 to req_seq_nr_bitmap'length;
    -- Bitmap used to index the writers
    signal w_map, w_map_next : std_logic_vector(0 to NUM_WRITERS-1);
    -- Signal used to index the writers
    signal ind, ind_next : natural range 0 to NUM_WRITERS-1;
    -- Test signal used for testbench synchronisation
    signal idle_sig : std_logic;
    -- Test signal used in testbenches for removal check
    signal empty_head_sig : EMPTY_HEAD_SIG_ARRAY_TYPE;
    
    -- *MEMORY PROCESS*
    -- Memory FSM state
    signal mem_stage, mem_stage_next : MEM_STAGE_TYPE;
    -- Head of Occupied Memory Endpoint List
    signal mem_occupied_head, mem_occupied_head_next : ENDPOINT_ADDRESS_ARRAY_TYPE;
    -- Head of Empty Memory Endpoint List
    signal mem_empty_head, mem_empty_head_next : ENDPOINT_ADDRESS_ARRAY_TYPE;
    -- Pointer to current relevant Endpoint Address
    signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Memory Address Latch
    signal mem_addr_latch, mem_addr_latch_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Couter
    signal mem_cnt, mem_cnt_next : natural range 0 to 29;
    -- Latch for Endpoint Data from Memory
    signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE;
    -- Latch for Endpoint Data from main process
    signal mem_endpoint_latch_data, mem_endpoint_latch_data_next : ENDPOINT_DATA_TYPE;
    -- Signal used to write to ALL memories simutanously
    signal multi_w : std_logic;
    
    -- *MEMORY CONTROL CONNECTION SIGNALS*
    signal mem_addr : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
    signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0);
    signal mem_ready_in, mem_valid_in : std_logic;
    signal mem_ready_out, mem_valid_out : std_logic;
    signal mem_read : std_logic;
    signal abort_read : std_logic;
    signal mem_addr_i : ENDPOINT_ADDRESS_ARRAY_TYPE;
    signal mem_read_data_i, mem_write_data_i : WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal mem_ready_in_i, mem_valid_in_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal mem_ready_out_i, mem_valid_out_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal mem_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal abort_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    
    
    --*****ALIAS DECLARATION*****
    -- ENDPOINT FRAME HEADER
    alias header_opcode         : std_logic_vector(7 downto 0) is data_in_user(31 downto 24);
    alias header_flags          : std_logic_vector(7 downto 0) is data_in_user(23 downto 16);
    alias header_udp_port       : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
    -- RTPS SUBMESSAGE FLAGS
    alias endian_flag           : std_logic is rtps_flags(0);
    alias final_flag            : std_logic is rtps_flags(1);
    alias liveliness_flag       : std_logic is rtps_flags(2);
    -- RTPS OUT DATA SUBMESSAGE FLAGS
    alias qos_flag              : std_logic is data_out_ro(17);
    alias data_flag             : std_logic is data_out_ro(18);
    alias key_flag              : std_logic is data_out_ro(19);
    alias non_std_flag          : std_logic is data_out_ro(20);
    -- MISC
    alias new_global_ack        : SEQUENCENUMBER_TYPE is sn_latch_1;
    alias new_global_ack_next   : SEQUENCENUMBER_TYPE is sn_latch_1_next;
    alias min_sn                : SEQUENCENUMBER_TYPE is sn_latch_1;
    alias min_sn_next           : SEQUENCENUMBER_TYPE is sn_latch_1_next;
    alias max_sn                : SEQUENCENUMBER_TYPE is sn_latch_1;
    alias max_sn_next           : SEQUENCENUMBER_TYPE is sn_latch_1_next;
    alias next_seq_nr           : SEQUENCENUMBER_TYPE is sn_latch_2;
    alias next_seq_nr_next      : SEQUENCENUMBER_TYPE is sn_latch_2_next;
    
    
    
    --*****FUNCTION DECLARATION*****
    -- Helper function to convert BITMAP_TYPE to std_logic_vector
    function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is
        variable ret : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0');
    begin
        for i in 0 to BITMAP_TYPE'length-1 loop
            ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i);
        end loop;
        return ret;
    end function;
    
    function check_heartbeat_period(qos : QUARTUS_CONFIG_ARRAY_TYPE) return boolean is
    begin
        for i in 0 to NUM_WRITERS-1 loop
            if (qos(0).HEARTBEAT_PERIOD /= qos(i).HEARTBEAT_PERIOD) then
                return FALSE;
            end if;
        end loop;
        return TRUE;
    end function;
    
    -- HACK: Due to delta cycle race condition some assertions trigger false positives,
    --       so we check the signals on the falling edge
    function stable(clk : std_logic; a : boolean) return boolean is
    begin
        if (clk = '0') then
            return a;
        else
            return TRUE;
        end if;
    end function;
    
    -- HACK: Quartus Workaround (Does not support unary and [VHDL 2008])
    function and_reduce(input : std_logic_vector) return std_logic is
        variable ret : std_logic := '1';
    begin
        for i in 0 to input'length-1 loop
            ret := ret and input(i);
        end loop;
        return ret;
    end function;
    
begin
    
    --*****COMPONENT INSTANTIATION*****
    mem_ctrl_gen : for i in 0 to NUM_WRITERS-1 generate
        mem_ctrl_inst : entity work.mem_ctrl(arch)
            generic map (
                ADDR_WIDTH          => ENDPOINT_MEMORY_ADDR_WIDTH,
                DATA_WIDTH          => WORD_WIDTH,
                MEMORY_DEPTH        => ENDPOINT_MEMORY_SIZE,
                MAX_BURST_LENGTH    => ENDPOINT_FRAME_SIZE
            )
            port map (
                clk         => clk,
                reset       => reset or abort_read_i(i),
                addr        => std_logic_vector(mem_addr_i(i)),
                read        => mem_read_i(i),
                ready_in    => mem_ready_in_i(i),
                valid_in    => mem_valid_in_i(i),
                data_in     => mem_write_data_i(i),
                ready_out   => mem_ready_out_i(i),
                valid_out   => mem_valid_out_i(i),
                data_out    => mem_read_data_i(i)
            );
    end generate;
    
    memory_mux : process (all)
    begin
        abort_read_i        <= (others => '0');
        mem_addr_i          <= (others => (others => '0'));
        mem_read_i          <= (others => '0');
        mem_valid_in_i      <= (others => '0');
        mem_write_data_i    <= (others => (others => '0'));
        mem_ready_out_i     <= (others => '0');
        if (multi_w = '0')  then
            abort_read_i(mem_endpoint_latch_data.i)     <= abort_read;
            mem_addr_i(mem_endpoint_latch_data.i)       <= mem_addr;
            mem_read_i(mem_endpoint_latch_data.i)       <= mem_read;
            mem_valid_in_i(mem_endpoint_latch_data.i)   <= mem_valid_in;
            mem_write_data_i(mem_endpoint_latch_data.i) <= mem_write_data;
            mem_ready_out_i(mem_endpoint_latch_data.i)  <= mem_ready_out;
            
            mem_ready_in    <= mem_ready_in_i(mem_endpoint_latch_data.i);
            mem_valid_out   <= mem_valid_out_i(mem_endpoint_latch_data.i);
            mem_read_data   <= mem_read_data_i(mem_endpoint_latch_data.i);
        else
            abort_read_i        <= (others => abort_read);
            mem_addr_i          <= (others => mem_addr);
            mem_read_i          <= (others => mem_read);
            mem_valid_in_i      <= (others => mem_valid_in);
            mem_write_data_i    <= (others => mem_write_data);
            mem_ready_out_i     <= (others => mem_ready_out);
            
            mem_ready_in    <= and_reduce(mem_ready_in_i); --and mem_ready_in_i;
            mem_valid_out   <= '0';
            mem_read_data   <= (others => '0');
        end if;
    end process;
    
    alive_sig   <= liveliness_assertion;
    
    -- *Main State Machine*
    -- STATE                        DESCRIPTION
    -- IDLE                         Idle State. Initiates Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order.
    -- LATCH_SRC_ADDR               Store source IPv4 Address
    -- LATCH_GUIDPREFIX             Store source GUID Prefix
    -- LATCH_ENTITYID               Store source Entity ID
    -- LATCH_ENDPOINT_DATA          Store Remote Endpoint Data
    -- LATCH_ACKNACK                Store ACKNACK Heartbeat Sequence Numbers
    -- PARSE_NACK_BITMAP            Parse the bitmap containing the requested Sequence Numbers
    -- INITIATE_ENDPOINT_SEARCH     Initiate Endpoint Search Memory Operation. This state is used to start the Search operation as soon as the required data is available
    -- METATRAFFIC_OPERATION        State handling the Metatraffic Operations
    -- PROCESS_NACK                 Process Requested (Negatively Acknowledged) Sequence Numbers
    -- PROCESS_ACK                  Process Acknowledged Sequence Numbers. Assert Liveliness of remore Reader.
    -- UPDATE_GLOBAL_ACK            Iterate over all remote Readers and update the global_ack_seq_nr_base to the lowest common ACKed Sequence Number
    -- ENDPOINT_STALE_CHECK         Check remote Endpoint Entries for Liveliness Lease Expiration, and Response Timeouts.
    -- HANDLE_REQUESTS              Send requested Cache Changes to remote Reader
    -- HANDLE_HEARTBEATS            Send Heartbeat to all remote Readers
    -- HANDLE_NEW                   Send new Cache Change to all remote Readers
    -- HANDLE_HISTORICAL            Send all available Cache Changes to remote Endpoint    
    -- SEND_HEADER                  Send Output Data Header and RTPS Message Header
    -- SEND_INFO_TS                 Send INFO_TS Submessage
    -- SEND_DATA_A                  Send DATA Submessage Part 1
    -- SEND_INLINE_QOS              Send DATA Submessage in-line QoS
    -- SEND_DATA_B                  Send DATA Submessage Part 2
    -- SEND_GAP_A                   Send GAP Submessage Part 1
    -- SEND_GAP_B                   Send GAP Submessage Part 2
    -- SEND_HEARTBEAT               Send HEARTBEAT Submessage
    -- SKIP_PACKET                  Skip rest of Packet
    -- SKIP_META_OPERATION          Skip Metatraffic Operation
    parse_prc : process(all)
        variable tmp_dw     : DOUBLE_WORD_ARRAY;
        -- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally)
        variable tmp_bitmap : std_logic_vector(0 to MAX_BITMAP_WIDTH-1);
        variable tmp_flags  : std_logic_vector(0 to EMF_FLAG_WIDTH-1);
    begin
        -- DEFAULT Registered
        stage_next                  <= stage;
        meta_opcode_next            <= meta_opcode;
        cnt_next                    <= cnt;
        cnt2_next                   <= cnt2;
        cnt3_next                   <= cnt3;
        guid_next                   <= guid;
        addr_next                   <= addr;
        portn_next                  <= portn;
        is_meta_next                <= is_meta;
        opcode_next                 <= opcode;
        rtps_flags_next             <= rtps_flags;
        reader_flags_next           <= reader_flags;
        sn_latch_1_next             <= sn_latch_1;
        sn_latch_2_next             <= sn_latch_2;
        ack_base_next               <= ack_base;
        nack_base_next              <= nack_base;
        nack_bitmap_pos_next        <= nack_bitmap_pos;
        req_bitmap_pos_next         <= req_bitmap_pos;
        last_word_in_latch_next     <= last_word_in_latch;
        stale_check_next            <= stale_check;
        count_next                  <= count;
        return_stage_next           <= return_stage;
        check_time_next             <= check_time;
        long_latch_next             <= long_latch;
        global_ack_seq_nr_base_next <= global_ack_seq_nr_base;
        req_seq_nr_bitmap_next      <= req_seq_nr_bitmap;
        gap_in_progress_next        <= gap_in_progress;
        heartbeat_time_next         <= heartbeat_time;
        last_seq_nr_next            <= last_seq_nr;
        new_push_next               <= new_push;
        historical_push_next        <= historical_push;
        initial_heartbeat_next      <= initial_heartbeat;    
        assert_liveliness_latch_next<= assert_liveliness_latch;
        w_assert_liveliness_next    <= w_assert_liveliness;
        bitmap_cnt_next             <= bitmap_cnt;
        bitmap_latch_next           <= bitmap_latch;
        gap_is_last_next            <= gap_is_last;
        return_cnt_next             <= return_cnt;
        w_map_next                  <= w_map;
        ind_next                    <= ind;
        -- DEFAULT Unregistered
        mem_opcode                  <= NOP;
        opcode_hc                   <= (others => NOP);
        mem_r                       <= ZERO_ENDPOINT_DATA;
        rd_meta                     <= '0';
        rd_user                     <= '0';
        wr_ro                       <= '0';
        last_word_out_ro            <= '0';
        mem_op_start                <= '0';
        start_hc                    <= (others => '0');
        ready_in_hc                 <= (others => '0');
        get_data_hc                 <= (others => '0');
        idle_sig                    <= '0';
        seq_nr_hc                   <= (others => SEQUENCENUMBER_UNKNOWN);
        data_out_ro                 <= (others => '0');
        
        -- Assert Liveliness Latch Setter
        if ((MANUAL_BY_TOPIC_LIVELINESS_WRITERS and liveliness_assertion) /= (liveliness_assertion'range => '0')) then
            assert_liveliness_latch_next    <= assert_liveliness_latch or (MANUAL_BY_TOPIC_LIVELINESS_WRITERS and liveliness_assertion);
        end if;
        
        -- Last Word Latch Setter
        -- NOTE: Assumes meta and user traffic are not consumed concurrently
        if (last_word_in_user = '1' or last_word_in_meta = '1') then
            last_word_in_latch_next    <= '1';
        end if;
        
        case (stage) is
            when IDLE =>
                idle_sig    <= '1';
                -- RESET
                addr_next                   <= (others => '0');
                portn_next                  <= (others => '0');
                is_meta_next                <= '0';
                
                -- New Cache Change in HC
                if (data_available /= (data_available'range => '0')) then
                    w_map_next  <= data_available;
                    ind_next    <= 0;
                    
                    new_push_next   <= '1';
                    
                    stage_next  <= HANDLE_NEW;
                    cnt_next    <= 1;   -- GET MAX_SN
                -- Manual Liveliness Assertion
                elsif (assert_liveliness_latch /= (assert_liveliness_latch'range => '0')) then
                    w_map_next  <= assert_liveliness_latch;
                    ind_next    <= 0;
                    
                    w_assert_liveliness_next    <= assert_liveliness_latch;
                    
                    stage_next  <= HANDLE_HEARTBEATS;
                    cnt_next    <= 1; -- GET MIN_SN
                -- Heartbeat Timeout
                elsif (RELIABLE_WRITERS /= (RELIABLE_WRITERS'range => '0') and time >= heartbeat_time) then
                    assert check_heartbeat_period(CONFIG_ARRAY_T) report "Writer does not support different HEARTBEAT_PERIODs. Writer will use CONFIG_ARRAY_T(0).HEARTBEAT_PERIOD" severity WARNING;
                    -- Reset
                    heartbeat_time_next <= time + CONFIG_ARRAY_T(0).HEARTBEAT_PERIOD;
                    
                    w_map_next  <= RELIABLE_WRITERS;
                    ind_next    <= 0;
                    
                    stage_next  <= HANDLE_HEARTBEATS;
                    cnt_next    <= 1; -- GET MIN_SN
                -- Stale Check Timeout
                elsif (time >= check_time) then
                    -- Reset Timeout
                    check_time_next     <= TIME_INFINITE;
                    stale_check_next    <= '1';
                    
                    w_map_next  <= (others => '1');
                    ind_next    <= 0;
                    
                    stage_next  <= ENDPOINT_STALE_CHECK;
                    cnt_next    <= 1; -- GET FIRST Endpoint
                -- Input FIFO Guard
                elsif (empty_meta /= (empty_meta'range => '1')) then
                    rd_meta     <= '1';
                    
                    w_map_next  <= not empty_meta;
                    ind_next    <= 0;
                    
                    -- Mark as METATRAFFIC
                    is_meta_next        <= '1';
                    
                    -- Latch Endpoint Metatraffic Opcode
                    meta_opcode_next    <= data_in_meta;
                    
                    case (data_in_meta) is
                        when EMO_ENDPOINT_MATCH =>
                            stage_next  <= LATCH_GUIDPREFIX;
                            cnt_next    <= 0;
                        when EMO_ENDPOINT_UNMATCH =>
                            stage_next  <= LATCH_GUIDPREFIX;
                            cnt_next    <= 0;
                        when EMO_PARTICIPANT_UNMATCH =>
                            stage_next  <= LATCH_GUIDPREFIX;
                            cnt_next    <= 0;
                        when others =>
                            assert FALSE report "RTPS Writer received unknown META Operation" severity WARNING;
                            stage_next  <= SKIP_META_OPERATION;
                    end case;
                -- Input FIFO Guard
                elsif (empty_user /= (empty_user'range => '1')) then
                    rd_user     <= '1';
                    
                    w_map_next  <= not empty_user;
                    ind_next    <= 0;
                    
                    -- Latch DATA
                    opcode_next     <= header_opcode;
                    rtps_flags_next <= header_flags;
                    portn_next      <= header_udp_port;
                    
                    case (header_opcode) is
                        when SID_ACKNACK =>
                            stage_next  <= LATCH_SRC_ADDR;
                        when others =>
                            stage_next  <= SKIP_PACKET;
                    end case;
                end if;
            when LATCH_SRC_ADDR =>
                -- Input FIFO Guard
                if (empty_user /= (empty_user'range => '1')) then
                    assert ((empty_user xor w_map) = (empty_user'range => '1')) severity FAILURE;
                    
                    rd_user     <= '1';
                    
                    -- Latch Source IP Address
                    addr_next   <= data_in_user;
                    
                    stage_next  <= LATCH_GUIDPREFIX;
                    cnt_next    <= 0;
                end if;
            when LATCH_GUIDPREFIX =>
                -- Input FIFO Guard
                if ((is_meta = '1' and empty_meta /= (empty_meta'range => '1')) or (is_meta = '0' and empty_user /= (empty_user'range => '1'))) then
                    
                    if (is_meta = '1') then
                        assert ((empty_meta xor w_map) = (empty_meta'range => '1')) severity FAILURE;
                        rd_meta     <= '1';
                    else
                        assert ((empty_user xor w_map) = (empty_user'range => '1')) severity FAILURE;
                        rd_user     <= '1';
                    end if;
                    
                    case (cnt) is
                        -- GUID Prefix 1/3
                        when 0 =>
                            if (is_meta = '1') then
                                guid_next(0)    <= data_in_meta;
                            else
                                guid_next(0)    <= data_in_user;
                            end if;
                            cnt_next    <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 1 =>
                            if (is_meta = '1') then
                                guid_next(1)    <= data_in_meta;
                            else
                                guid_next(1)    <= data_in_user;
                            end if;
                            cnt_next    <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 2 =>
                            if (is_meta = '1') then
                                guid_next(2)    <= data_in_meta;
                            else
                                guid_next(2)    <= data_in_user;
                            end if;
                            
                            if (is_meta = '1') then
                                case (meta_opcode) is
                                    when EMO_PARTICIPANT_UNMATCH =>
                                        assert stable(clk, last_word_in_meta = '1') severity FAILURE;
                                        stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                        cnt_next    <= 0;
                                    when others =>
                                        stage_next  <= LATCH_ENTITYID;
                                end case;
                            else
                                stage_next  <= LATCH_ENTITYID;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when LATCH_ENTITYID =>
                -- Input FIFO Guard
                if ((is_meta = '1' and empty_meta /= (empty_meta'range => '1')) or (is_meta = '0' and empty_user /= (empty_user'range => '1'))) then
                    
                    if (is_meta = '1') then
                        assert ((empty_meta xor w_map) = (empty_meta'range => '1')) severity FAILURE;
                        rd_meta         <= '1';
                        guid_next(3)    <= data_in_meta;
                        
                        case (meta_opcode) is
                            when EMO_ENDPOINT_MATCH =>
                                stage_next  <= LATCH_ENDPOINT_DATA;
                                cnt_next    <= 0;
                            when EMO_ENDPOINT_UNMATCH =>
                                assert stable(clk, last_word_in_meta = '1') severity FAILURE;
                                stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                cnt_next    <= 0;
                            when others =>
                                null;
                        end case;
                    -- Memory Operation Guard
                    else
                        assert ((empty_user xor w_map) = (empty_user'range => '1')) severity FAILURE;
                        rd_user         <= '1';
                        guid_next(3)    <= data_in_user;
                        
                        stage_next  <= LATCH_ACKNACK;
                        cnt_next    <= 0;
                    end if;
                end if;
            when LATCH_ENDPOINT_DATA =>
                assert (is_meta = '1') severity FAILURE;
                
                -- Input FIFO Guard
                if (empty_meta /= (empty_meta'range => '1')) then
                    assert ((empty_meta xor w_map) = (empty_meta'range => '1')) severity FAILURE;
                    
                    rd_meta     <= '1';
                    
                    case (cnt) is
                        -- IPv4 Address
                        when 0 =>
                            addr_next   <= data_in_meta;
                            cnt_next    <= cnt + 1;
                        -- UDP Port
                        when 1 =>
                            portn_next          <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH);
                            reader_flags_next   <= data_in_meta(reader_flags'length-1 downto 0);
                            
                            case (meta_opcode) is
                                when EMO_ENDPOINT_MATCH =>
                                    assert stable(clk, last_word_in_meta = '1') severity FAILURE;
                                    
                                    stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                    cnt_next    <= 0;
                                when others =>
                                    null;
                            end case;
                        when others =>
                            null;
                    end case;
                end if;
            when LATCH_ACKNACK =>
                assert (is_meta = '0') severity FAILURE;
                
                -- Input FIFO Guard
                if (empty_user /= (empty_user'range => '1')) then
                    assert ((empty_user xor w_map) = (empty_user'range => '1')) severity FAILURE;
                    
                    case (cnt) is
                        -- ReaderSNState.Base 1/2
                        when 0 =>
                            nack_base_next(0)   <= unsigned(data_in_user);
                            rd_user     <= '1';
                            cnt_next    <= cnt + 1;
                        -- ReaderSNState.Base 2/2
                        when 1 =>
                            nack_base_next(1)   <= unsigned(data_in_user);
                            rd_user     <= '1';
                            cnt_next    <= cnt + 1;
                        -- ReaderSNState.NumBits
                        when 2 =>
                            ack_base_next   <= nack_base - 1;
                            long_latch_next <= data_in_user;
                            bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
                            rd_user         <= '1';
                            cnt_next        <= cnt + 1;
                            cnt2_next       <= 0;
                        -- ReaderSNState.Bitmap
                        when 3 =>
                            -- Read Bitmap
                            if (cnt2 < bitmap_cnt) then
                                cnt2_next <= cnt2 + 1;
                                
                                bitmap_latch_next(cnt2) <= data_in_user;
                                rd_user                 <= '1';
                                
                            else
                                -- NACK Bitmap is not Empty
                                if (long_latch /= (long_latch'reverse_range => '0')) then
                                    nack_bitmap_pos_next    <= 0;
                                    stage_next  <= PARSE_NACK_BITMAP;
                                    cnt_next    <= 0;
                                else
                                    stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                    cnt_next    <= 0;
                                end if;
                            end if;
                        when others => 
                            null;
                    end case;
                end if;
            when PARSE_NACK_BITMAP =>
                tmp_bitmap  := to_slv_bitmap(bitmap_latch);
                
                case (cnt) is
                    -- Find Beginning
                    when 0 =>
                        -- First Requested Sequence Number
                        if (tmp_bitmap(nack_bitmap_pos) = '1') then
                            req_seq_nr_bitmap_next  <= (others => '0');
                            req_bitmap_pos_next     <= 0;
                            cnt_next    <= cnt + 1;
                        else
                            nack_bitmap_pos_next    <= nack_bitmap_pos + 1;
                            nack_base_next          <= nack_base + 1;
                        end if;
                    -- Parse Rest
                    when 1 =>
                        -- Next Requested Sequence Number
                        if (tmp_bitmap(nack_bitmap_pos) = '1') then
                            req_seq_nr_bitmap_next(req_bitmap_pos)  <= '1';
                        end if;
                        
                        -- End of Bitmap
                        if (nack_bitmap_pos = unsigned(long_latch) or req_bitmap_pos = req_seq_nr_bitmap'length-1) then
                            stage_next  <= INITIATE_ENDPOINT_SEARCH;
                            cnt_next    <= 0;
                        else
                            nack_bitmap_pos_next    <= nack_bitmap_pos + 1;
                            req_bitmap_pos_next     <= req_bitmap_pos + 1;
                        end if;
                    -- Find Requested
                    when others =>
                        null;
                end case;
            when INITIATE_ENDPOINT_SEARCH =>
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    case (cnt) is
                        when 0 =>
                            if (w_map(ind) = '1') then
                                if (is_meta = '1') then
                                    case (meta_opcode) is
                                        when EMO_ENDPOINT_MATCH =>
                                            mem_op_start        <= '1';
                                            mem_opcode          <= SEARCH_ENDPOINT;
                                            mem_r.i             <= ind;
                                            mem_r.guid          <= guid;
                                            stage_next          <= METATRAFFIC_OPERATION;
                                            cnt_next            <= 0;
                                        when EMO_ENDPOINT_UNMATCH =>
                                            mem_op_start        <= '1';
                                            mem_opcode          <= SEARCH_ENDPOINT;
                                            mem_r.i             <= ind;
                                            mem_r.field_flags   <= EMF_ACK_SEQ_NR_BASE_FLAG;
                                            mem_r.guid          <= guid;
                                            stage_next          <= METATRAFFIC_OPERATION;
                                            cnt_next            <= 0;
                                        when EMO_PARTICIPANT_UNMATCH =>
                                            mem_op_start        <= '1';
                                            mem_opcode          <= GET_ENDPOINT;
                                            mem_r.i             <= ind;
                                            mem_r.addr          <= mem_occupied_head(ind);
                                            mem_r.field_flags   <= EMF_GUIDPREFIX_FLAG;
                                            stage_next          <= METATRAFFIC_OPERATION;
                                            cnt_next            <= 0;
                                        when others =>
                                            null;
                                    end case;
                                else
                                    if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_ENDPOINT;
                                        mem_r.i             <= ind;
                                        mem_r.field_flags   <= EMF_ACK_SEQ_NR_BASE_FLAG or EMF_RES_TIME_FLAG;
                                        mem_r.guid          <= guid;
                                        
                                        if (long_latch /= (long_latch'reverse_range => '0')) then
                                            stage_next  <= PROCESS_NACK;
                                            cnt_next    <= 0;
                                        else
                                            stage_next  <= PROCESS_ACK;
                                            cnt_next    <= 0;
                                        end if;
                                    else
                                        cnt_next    <= cnt + 1; -- NEXT WRITER
                                    end if;
                                end if;
                            else
                                cnt_next    <= cnt + 1; -- NEXT WRITER
                            end if;
                        -- NEXT WRITER
                        when 1 =>
                            -- No more Writers
                            if (ind = NUM_WRITERS-1) then
                                -- DONE
                                if (is_meta = '1') then
                                    stage_next  <= SKIP_META_OPERATION;
                                else
                                    stage_next  <= SKIP_PACKET;
                                end if;
                            else
                                -- Next Writer
                                ind_next    <= ind + 1;
                                cnt_next    <= 0;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when METATRAFFIC_OPERATION =>
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    case (meta_opcode) is
                        when EMO_ENDPOINT_MATCH =>
                            case (cnt) is
                                -- ENDPOINT MATCH
                                when 0 =>
                                    -- Endpoint already in Memory
                                    if (mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                                        -- Update the Endpoint Data
                                        -- NOTE: The Lease is NOT renewed in case of an update. That is the responsibility of the Liveliness Update
                                        mem_op_start        <= '1';
                                        mem_opcode          <= UPDATE_ENDPOINT;
                                        mem_r.i             <= ind;
                                        mem_r.addr          <= mem_endpoint_data.addr;
                                        mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
                                        mem_r.ip_addr       <= addr;
                                        mem_r.portn         <= portn;
                                        mem_r.reader_flags  <= reader_flags;
                                        
                                        -- Continue
                                        stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                        cnt_next    <= 1; -- GET NEXT WRITER
                                    -- Endpoint Memory Full
                                    elsif (mem_empty_head(ind) = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                        -- Ignore
                                        stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                        cnt_next    <= 1; -- GET NEXT WRITER
                                    else
                                        assert stable(clk, mem_empty_head(ind) /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                                        
                                        -- Insert Matched Remote Endpoint
                                        mem_op_start        <= '1';
                                        mem_opcode          <= INSERT_ENDPOINT;
                                        mem_r.i             <= ind;
                                        mem_r.guid          <= guid;
                                        mem_r.ip_addr       <= addr;
                                        mem_r.portn         <= portn;
                                        mem_r.reader_flags  <= reader_flags;
                                        
                                        if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and CONFIG_ARRAY_T(ind).LEASE_DURATION /= DURATION_INFINITE and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') then
                                            tmp_dw  := time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                            mem_r.lease_deadline    <= tmp_dw;
                                            
                                            -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                                            -- Update Check Time
                                            if (tmp_dw < check_time) then
                                                check_time_next <= tmp_dw;
                                            end if;
                                        else
                                            mem_r.lease_deadline    <= TIME_INVALID;
                                        end if;
                                        -- Initialize ACK Sequence Number
                                        if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS /= RELIABLE_RELIABILITY_QOS or reader_flags(READER_IS_BEST_EFFORT_FLAG) = '1') then
                                            mem_r.ack_seq_nr_base   <= SEQUENCENUMBER_UNKNOWN;
                                        elsif (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then
                                            mem_r.ack_seq_nr_base   <= ZERO_SEQUENCENUMBER;
                                            -- Initialize Global ACK
                                            if (global_ack_seq_nr_base(ind) = SEQUENCENUMBER_UNKNOWN) then
                                                global_ack_seq_nr_base_next(ind)    <= ZERO_SEQUENCENUMBER;
                                            end if;
                                        else
                                            mem_r.ack_seq_nr_base   <= last_seq_nr(ind);
                                            -- Initialize Global ACK
                                            if (global_ack_seq_nr_base(ind) = SEQUENCENUMBER_UNKNOWN) then
                                                global_ack_seq_nr_base_next(ind)    <= last_seq_nr(ind);
                                            end if;
                                        end if;
                                        
                                        if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                                            cnt_next    <= cnt + 1;
                                        else
                                            cnt_next    <= 3; -- POST-HEARTBEAT
                                        end if;
                                    end if;
                                -- GET MIN_SN
                                when 1 =>
                                    start_hc(ind)   <= '1';
                                    opcode_hc(ind)  <= GET_MIN_SN;
                                    
                                    if (ack_hc(ind) = '1') then
                                        -- Increment Heartbeat Count
                                        count_next(ind) <= count(ind) + 1;
                                        
                                        cnt_next        <= cnt + 1;
                                    end if;
                                -- SEND HEARTBEAT
                                when 2 =>
                                    -- Wait for HC
                                    if (done_hc(ind) = '1') then
                                        assert (ret_hc(ind) = OK) severity FAILURE;
                                        
                                        -- HC Empty (No cache Changes Available)
                                        if (cc_seq_nr(ind) = SEQUENCENUMBER_UNKNOWN) then
                                            -- NOTE: Identifies the lowest SN that is yet to be written by the writter.
                                            min_sn_next <= last_seq_nr(ind) + 1;
                                        else
                                            min_sn_next <= cc_seq_nr(ind);
                                        end if;
                                        
                                        -- Send Initial Heartbeat
                                        initial_heartbeat_next  <= '1';
                                        stage_next              <= SEND_HEADER;
                                        cnt_next                <= 0;
                                        return_stage_next       <= SEND_HEARTBEAT;
                                        return_cnt_next         <= 0;
                                    end if;
                                -- POST-HEARTBEAT
                                when 3 =>
                                    -- Reader needs Historical Data
                                    if (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then
                                        -- Send Historical Data
                                        historical_push_next    <= '1';
                                        
                                        stage_next  <= HANDLE_HISTORICAL;
                                        cnt_next    <= 0; -- GET MIN_SN
                                    else
                                        -- Continue
                                        stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                        cnt_next    <= 1; -- GET NEXT WRITER
                                    end if;
                                when others => 
                                    null;
                            end case;
                        when EMO_ENDPOINT_UNMATCH =>
                            
                            -- Endpoint not in Memory
                            if (mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                -- Continue
                                stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                cnt_next    <= 1; -- GET NEXT WRITER
                            else
                                assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_ACK_SEQ_NR_BASE_FLAG)) severity FAILURE;
                                
                                -- Remove Unmatched Remote Endpoint
                                mem_op_start    <= '1';
                                mem_opcode      <= REMOVE_ENDPOINT;
                                mem_r.i         <= ind;
                                mem_r.addr      <= mem_endpoint_data.addr;
                                
                                -- Global ACK SN possibly changed
                                if (global_ack_seq_nr_base(ind) /= SEQUENCENUMBER_UNKNOWN and global_ack_seq_nr_base(ind) = mem_endpoint_data.ack_seq_nr_base) then
                                    -- Update Global ACK
                                    stage_next          <= UPDATE_GLOBAL_ACK;
                                    cnt_next            <= 0;
                                    return_stage_next   <= INITIATE_ENDPOINT_SEARCH;
                                    return_cnt_next     <= 1; -- GET NEXT WRITER
                                else
                                    -- Continue
                                    stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                    cnt_next    <= 1; -- GET NEXT WRITER
                                end if;
                            end if;
                        when EMO_PARTICIPANT_UNMATCH =>
                            case (cnt) is
                                when 0 =>
                                    -- Reached End of Endpoints
                                    if (mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                        -- Global ACK SN possibly changed
                                        if (global_ack_seq_nr_base(ind) /= SEQUENCENUMBER_UNKNOWN) then
                                            -- NOTE: We are triggering a Global ACK SN Update on each Participant Removal. This should not happen as often, and is therefore acceptable.
                                            --       Otherwise we need to check the ack_seq_nr_base in the other sub-state and mark when equal to current Global ACK SN.
                                            -- Update Global ACK
                                            stage_next          <= UPDATE_GLOBAL_ACK;
                                            cnt_next            <= 0;
                                            return_stage_next   <= INITIATE_ENDPOINT_SEARCH;
                                            return_cnt_next     <= 1; -- GET NEXT WRITER
                                        else
                                            -- Continue
                                            stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                            cnt_next    <= 1; -- GET NEXT WRITER
                                        end if;
                                    else
                                        assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_GUIDPREFIX_FLAG)) severity FAILURE;
                                        
                                        -- Participant Match
                                        if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then
                                            -- Remove Unmatched Remote Endpoint
                                            mem_op_start    <= '1';
                                            mem_opcode      <= REMOVE_ENDPOINT;
                                            mem_r.i         <= ind;
                                            mem_r.addr      <= mem_endpoint_data.addr;
                                            -- NOTE: After removal, mem_endpoint_data.addr is pointing to the next slot (or ENDPOINT_MEMORY_MAX_ADDRESS)
                                            cnt_next    <= 2; -- GET Endpoint
                                        else
                                            cnt_next    <= 1; -- GET NEXT Endpoint
                                        end if;
                                        
                                    end if;
                                -- GET NEXT Endpoint
                                when 1 =>
                                    -- Continue Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= GET_NEXT_ENDPOINT;
                                    mem_r.i             <= ind;
                                    mem_r.addr          <= mem_endpoint_data.addr;
                                    mem_r.field_flags   <= EMF_GUIDPREFIX_FLAG;
                                    cnt_next            <= 0;
                                -- GET Endpoint
                                when 2 =>
                                    -- Continue Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= GET_ENDPOINT;
                                    mem_r.i             <= ind;
                                    mem_r.addr          <= mem_endpoint_data.addr;
                                    mem_r.field_flags   <= EMF_GUIDPREFIX_FLAG;
                                    cnt_next            <= 0;
                                when others =>
                                    null;
                            end case;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_NACK =>
                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                
                -- Wait for Endpoint Data
                if (mem_op_done = '1') then
                    -- Known Remote Endpoint
                    if (mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_RES_TIME_FLAG)) severity FAILURE;
                        
                        -- Liveliness Assertion
                        mem_op_start        <= '1';
                        mem_opcode          <= UPDATE_ENDPOINT;
                        mem_r.i             <= ind;
                        mem_r.addr          <= mem_endpoint_data.addr;
                        mem_r.field_flags   <= EMF_LEASE_DEADLINE_FLAG;
                        if (CONFIG_ARRAY_T(ind).LEASE_DURATION /= DURATION_INFINITE) then
                            tmp_dw  := time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                            mem_r.lease_deadline    <= tmp_dw;
                            
                            -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                            -- Update Check Time
                            if (tmp_dw < check_time) then
                                check_time_next <= tmp_dw;
                            end if;
                        else
                            mem_r.lease_deadline    <= TIME_INVALID;
                        end if;
                        
                        -- No Pending Response
                        if (mem_endpoint_data.res_time = TIME_INVALID) then
                            mem_r.field_flags       <= EMF_LEASE_DEADLINE_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG;
                            mem_r.req_seq_nr_base   <= nack_base;
                            mem_r.req_seq_nr_bitmap <= req_seq_nr_bitmap;
                            
                            if (CONFIG_ARRAY_T(ind).ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
                                tmp_dw  := time + CONFIG_ARRAY_T(ind).ACKNACK_RESPONSE_DELAY;
                                mem_r.res_time  <= tmp_dw;
                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                mem_r.res_time(1)(0)    <= '0';
                                
                                -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                                -- Update Check Time
                                if (tmp_dw < check_time) then
                                    check_time_next <= tmp_dw;
                                end if;
                            else
                                mem_r.res_time  <= TIME_INVALID;
                            end if;
                        -- Currently in Acknack Response Delay
                        elsif (mem_endpoint_data.res_time(1)(0) = '0') then
                            -- Overwrite previous Request
                            mem_r.field_flags       <= EMF_LEASE_DEADLINE_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG;
                            mem_r.req_seq_nr_base   <= nack_base;
                            mem_r.req_seq_nr_bitmap <= req_seq_nr_bitmap;
                        end if;
                        
                        stage_next  <= PROCESS_ACK;
                    else
                        -- EXIT
                        stage_next  <= INITIATE_ENDPOINT_SEARCH;
                        cnt_next    <= 1; -- GET NEXT WRITER
                    end if;
                end if;
            when PROCESS_ACK =>
                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                assert (global_ack_seq_nr_base(ind) /= SEQUENCENUMBER_UNKNOWN) severity FAILURE;
                    
                -- Wait for Endpoint Search
                if (mem_op_done = '1') then
                    
                    -- DEFAULT: GET NEXT WRITER
                    stage_next  <= INITIATE_ENDPOINT_SEARCH;
                    cnt_next    <= 1; -- GET NEXT WRITER
                    
                    -- Known Remote Endpoint
                    if (mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_ACK_SEQ_NR_BASE_FLAG)) severity FAILURE;
                        
                        -- New Sequence Numbers are ACKed
                        if (ack_base > mem_endpoint_data.ack_seq_nr_base) then
                            -- Update ACK Sequence Number Base
                            mem_op_start            <= '1';
                            mem_opcode              <= UPDATE_ENDPOINT;
                            mem_r.i                 <= ind;
                            mem_r.addr              <= mem_endpoint_data.addr;
                            mem_r.field_flags       <= EMF_ACK_SEQ_NR_BASE_FLAG;
                            mem_r.ack_seq_nr_base   <= ack_base;
                            -- NOTE: The global_ack_seq_nr_base contains the lowest SN of all remote Endpoints.
                            --       It only needs to be updated, if the remote Endpoint with the lowest ACKed SN is updated.
                            --       This does not necesserily mean, that the Global ACK SN will change, as there can 
                            --       be multiple remote Endpoints with the same lowest ACK SN.
                            -- Global ACK SN needs updating
                            if (mem_endpoint_data.ack_seq_nr_base = global_ack_seq_nr_base(ind)) then
                                stage_next          <= UPDATE_GLOBAL_ACK;
                                cnt_next            <= 0;
                                return_stage_next   <= INITIATE_ENDPOINT_SEARCH;
                                return_cnt_next     <= 1; -- GET NEXT WRITER
                            end if;
                        end if;
                    end if;
                end if;
            when UPDATE_GLOBAL_ACK =>
                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    case (cnt) is
                        -- GET FIRST Endpoint
                        when 0 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_occupied_head(ind);
                            mem_r.field_flags   <= EMF_ACK_SEQ_NR_BASE_FLAG;
                            cnt_next            <= cnt + 2;
                            
                            new_global_ack_next <= SEQUENCENUMBER_UNKNOWN;
                        -- GET NEXT Endpoint
                        when 1 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_NEXT_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_ACK_SEQ_NR_BASE_FLAG;
                            cnt_next            <= cnt + 1;
                        -- FIND NEW global_ack_seq_nr_base
                        when 2 =>
                            -- End of Endpoints
                            if (mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                -- No Reliable Remote Endpoints
                                if (new_global_ack = SEQUENCENUMBER_UNKNOWN) then
                                    -- Reset Global ACK SN
                                    global_ack_seq_nr_base_next(ind)    <= SEQUENCENUMBER_UNKNOWN;
                                    
                                    -- NACKed SNs available in HC
                                    if (global_ack_seq_nr_base(ind) /= last_seq_nr(ind)) then
                                        assert (global_ack_seq_nr_base(ind) < last_seq_nr(ind)) severity FAILURE;
                                        
                                        -- Mark ALL known SNs as ACKed
                                        new_global_ack_next <= last_seq_nr(ind);
                                        next_seq_nr_next    <= global_ack_seq_nr_base(ind) + 1;
                                        cnt_next            <= cnt + 1;
                                    else
                                        -- EXIT
                                        stage_next  <= return_stage;
                                        cnt_next    <= return_cnt;
                                    end if;
                                -- New SNs have been ACKed by ALL remote Endpoints
                                elsif (new_global_ack /= global_ack_seq_nr_base(ind)) then
                                    assert (global_ack_seq_nr_base(ind) < new_global_ack) severity FAILURE;
                                    
                                    -- Update Global ACK SN
                                    global_ack_seq_nr_base_next(ind) <= new_global_ack;
                                    -- Mark common ACKed SNs
                                    next_seq_nr_next    <= global_ack_seq_nr_base(ind) + 1;
                                    cnt_next            <= cnt + 1;
                                else
                                    -- DONE
                                    stage_next  <= return_stage;
                                    cnt_next    <= return_cnt;
                                end if;
                            else
                                assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_ACK_SEQ_NR_BASE_FLAG)) severity FAILURE;
                                
                                -- NOTE: Remote Endpoints with RELIABILITY BEST_EFFORT have a ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN, since
                                --       they cannot send ACKNACKs.
                                -- XXX: Assumes SEQUENCENUMBER_UNKNOWN is higher than all valid Sequence Numbers.
                                -- Mark lowest common ACKed SN
                                if (mem_endpoint_data.ack_seq_nr_base < new_global_ack) then
                                    new_global_ack_next <= mem_endpoint_data.ack_seq_nr_base;
                                end if;
                                
                                cnt_next    <= 1; -- GET NEXT Endpoint
                            end if;
                        -- ACK Sequence Numbers
                        when 3 =>
                            assert (new_global_ack /= SEQUENCENUMBER_UNKNOWN) severity FAILURE;
                            
                            if (CONFIG_ARRAY_T(ind).DURABILITY_QOS = VOLATILE_DURABILITY_QOS) then
                                start_hc(ind)   <= '1';
                                opcode_hc(ind)  <= REMOVE_CACHE_CHANGE;
                                seq_nr_hc(ind)  <= next_seq_nr;
                            else
                                start_hc(ind)   <= '1';
                                opcode_hc(ind)  <= ACK_CACHE_CHANGE;
                                seq_nr_hc(ind)  <= next_seq_nr;
                            end if;
                            -- NOTE: Ignore return Code
                            
                            -- Wait for Operation Acknowledgement
                            if (ack_hc(ind) = '1') then
                                -- Exit Condition
                                if (next_seq_nr = new_global_ack) then
                                    -- DONE
                                    stage_next  <= return_stage;
                                    cnt_next    <= return_cnt;
                                else
                                    next_seq_nr_next    <= next_seq_nr + 1;
                                end if;
                            end if;
                        when others =>
                    end case;
                end if;
            when ENDPOINT_STALE_CHECK =>
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    case (cnt) is
                        -- GET NEXT WRITER
                        when 0 =>
                            -- No more Writers
                            if (ind = NUM_WRITERS-1) then
                                -- Reset
                                stale_check_next    <= '0';
                                
                                -- DONE
                                stage_next      <= IDLE;
                            else
                                -- Next Writer
                                ind_next    <= ind + 1;
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GET FIRST Endpoint
                        when 1 =>
                            if (w_map(ind) = '1') then
                                mem_op_start        <= '1';
                                mem_opcode          <= GET_ENDPOINT;
                                mem_r.i             <= ind;
                                mem_r.addr          <= mem_occupied_head(ind);
                                mem_r.field_flags   <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG;
                                cnt_next            <= 4; -- CHECK Lease
                            else
                                cnt_next    <= 0; -- GET NEXT WRITER
                            end if;
                        -- GET Endpoint
                        when 2 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG;
                            cnt_next            <= 4; -- CHECK Lease
                        -- GET NEXT Endpoint
                        when 3 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_NEXT_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG;
                            cnt_next            <= 4; -- CHECK Lease
                        -- CHECK Lease
                        when 4 =>
                            -- End of Endpoints
                            if (mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT Writer
                            else
                                assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_LEASE_DEADLINE_FLAG)) severity FAILURE;
                                
                                -- DEFAULT
                                cnt_next    <= cnt + 1;
                                
                                -- Lease Deadline valid
                                if (mem_endpoint_data.lease_deadline /= TIME_INVALID) then
                                    -- Endpoint Lease Expired
                                    if (mem_endpoint_data.lease_deadline <= time) then
                                        -- Remove Participant
                                        mem_op_start    <= '1';
                                        mem_opcode      <= REMOVE_ENDPOINT;
                                        mem_r.i         <= ind;
                                        mem_r.addr      <= mem_endpoint_data.addr;
                                        -- Continue Search
                                        cnt_next    <= 2; -- GET Endpoint
                                    elsif (mem_endpoint_data.lease_deadline < check_time) then
                                        check_time_next <= mem_endpoint_data.lease_deadline;
                                    end if;
                                end if;
                            end if;
                        -- CHECK Response Time
                        when 5 =>
                            assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_RES_TIME_FLAG)) severity FAILURE;
                            
                            -- DEFAULT: Continue Search
                            cnt_next    <= 3; -- GET NEXT Endpoint
                            
                            -- Response Time valid
                            if (mem_endpoint_data.res_time /= TIME_INVALID) then
                                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                                
                                -- Response Time reached
                                if (mem_endpoint_data.res_time <= time) then
                                    -- If Suppression Delay passed, zero the time
                                    if(mem_endpoint_data.res_time(1)(0) = '1') then
                                        -- Disable Suppression
                                        mem_op_start        <= '1';
                                        mem_opcode          <= UPDATE_ENDPOINT;
                                        mem_r.i             <= ind;
                                        mem_r.addr          <= mem_endpoint_data.addr;
                                        mem_r.field_flags   <= EMF_RES_TIME_FLAG;
                                        mem_r.res_time      <= TIME_INVALID;
                                    -- If Response Delay Passed
                                    else
                                        -- Get Additional Data
                                        mem_op_start        <= '1';
                                        mem_opcode          <= GET_ENDPOINT;
                                        mem_r.i             <= ind;
                                        mem_r.addr          <= mem_endpoint_data.addr;
                                        mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG;
                                        
                                        -- Send Requests
                                        stage_next          <= HANDLE_REQUESTS;
                                        cnt_next            <= 0; -- INITIALIZE
                                    end if;
                                elsif (mem_endpoint_data.res_time < check_time) then
                                    check_time_next <= mem_endpoint_data.res_time;
                                end if;
                            end if;
                        -- UPDATE Endpoint
                        when 6 =>
                            assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                            assert (mem_op_done = '1') severity FAILURE;
                            assert (mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            mem_op_start        <= '1';
                            mem_opcode          <= UPDATE_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG;
                            -- Reset Requests
                            mem_r.req_seq_nr_base   <= SEQUENCENUMBER_UNKNOWN;
                            mem_r.req_seq_nr_bitmap <= (others => '0');
                            
                            -- Set Acknack Suppression Time
                            if (CONFIG_ARRAY_T(ind).ACKNACK_SUPPRESSION_DELAY /= DURATION_INFINITE and CONFIG_ARRAY_T(ind).ACKNACK_SUPPRESSION_DELAY /= DURATION_ZERO) then
                                tmp_dw  := time + CONFIG_ARRAY_T(ind).ACKNACK_SUPPRESSION_DELAY;
                                -- Set Acknack Suppression Time
                                mem_r.res_time  <= tmp_dw;
                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                mem_r.res_time(1)(0)    <= '1';
                                
                                -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                                -- Update Check Time
                                if (tmp_dw < check_time) then
                                    check_time_next <= tmp_dw;
                                end if;
                            else
                                -- Disable Suppression
                                mem_r.res_time  <= TIME_INVALID;
                            end if;
                            
                            cnt_next    <= 3; -- GET NEXT Endpoint
                        when others =>
                            null;
                    end case;
                end if;
            when HANDLE_REQUESTS =>
                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                assert (stale_check = '1') severity FAILURE;
                
                -- Wait for Endpoint Data
                if (mem_op_done = '1') then
                    assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG)) severity FAILURE;
                    assert stable(clk, mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    
                    case (cnt) is
                        -- INITIALIZE
                        when 0 =>
                            next_seq_nr_next    <= mem_endpoint_data.req_seq_nr_base;
                            req_bitmap_pos_next <= 0;
                            cnt_next            <= 2; -- FIND SN
                        -- NEXT Bitmap Pos
                        when 1 =>
                            req_bitmap_pos_next <= req_bitmap_pos + 1;
                            next_seq_nr_next    <= next_seq_nr + 1;
                            cnt_next            <= cnt + 1;
                        -- FIND SN
                        when 2 =>
                            -- End of Bitmap or Requested SN is above last Written
                            if (req_bitmap_pos = req_seq_nr_bitmap'length or next_seq_nr > last_seq_nr(ind)) then
                                if (gap_in_progress = '1') then
                                    -- Close GAP Message
                                    gap_in_progress_next    <= '0';
                                    stage_next              <= SEND_GAP_B;
                                    cnt_next                <= 0;
                                    -- DONE
                                    return_stage_next       <= ENDPOINT_STALE_CHECK;
                                    return_cnt_next         <= 6; -- UPDATE Endpoint
                                    gap_is_last_next        <= '1';
                                else
                                    -- DONE
                                    stage_next  <= ENDPOINT_STALE_CHECK;
                                    cnt_next    <= 6; -- UPDATE Endpoint
                                end if;
                            -- Next Requested SN found
                            elsif (mem_endpoint_data.req_seq_nr_bitmap(req_bitmap_pos) = '1') then
                                cnt_next    <= cnt + 1;
                            elsif (gap_in_progress = '1') then
                                -- Close GAP Message
                                gap_in_progress_next    <= '0';
                                stage_next              <= SEND_GAP_B;
                                cnt_next                <= 0;
                                -- Continue
                                return_stage_next       <= HANDLE_REQUESTS;
                                return_cnt_next         <= 1; -- NEXT BITMAP POS
                                gap_is_last_next        <= '1';
                            else
                                req_bitmap_pos_next <= req_bitmap_pos + 1;
                                next_seq_nr_next    <= next_seq_nr + 1;
                            end if;
                        -- Get SN
                        when 3 =>
                            start_hc(ind)   <= '1';
                            opcode_hc(ind)  <= GET_CACHE_CHANGE;
                            seq_nr_hc(ind)  <= next_seq_nr;
                            
                            -- Wait until Operation Acknowledgement
                            if (ack_hc(ind) = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        -- HANDLE Request
                        when 4 =>
                            -- Wait until Operation Response
                            if (done_hc(ind) = '1') then
                                if (ret_hc(ind) = OK) then  
                                    -- Only request Payload if necessary (Contains DATA or Serialized  Key)
                                    if (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                                        get_data_hc(ind)    <= '1';
                                    end if;
                                    
                                    if (gap_in_progress = '1') then
                                        -- Close GAP and send DATA
                                        gap_in_progress_next    <= '0';
                                        stage_next              <= SEND_GAP_B;
                                        cnt_next                <= 0;
                                        if (CONFIG_ARRAY_T(ind).DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                            return_stage_next   <= SEND_INFO_TS;
                                        else
                                            return_stage_next   <= SEND_DATA_A;
                                        end if;
                                        return_cnt_next         <= 0;
                                    else
                                        -- Send DATA
                                        stage_next  <= SEND_HEADER;
                                        cnt_next    <= 0;
                                        if (CONFIG_ARRAY_T(ind).DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                            return_stage_next   <= SEND_INFO_TS;
                                        else
                                            return_stage_next   <= SEND_DATA_A;
                                        end if;
                                        return_cnt_next     <= 0;
                                    end if;
                                else
                                    assert (ret_hc(ind) = INVALID) report "Unexpected HC response" severity WARNING;
                                    
                                    if (gap_in_progress = '0') then
                                        -- Open new GAP
                                        gap_in_progress_next    <= '1';
                                        stage_next              <= SEND_HEADER;
                                        cnt_next                <= 0;
                                        return_stage_next       <= SEND_GAP_A;
                                        return_cnt_next         <= 0;
                                    else
                                        -- Continue
                                        req_bitmap_pos_next <= req_bitmap_pos + 1;
                                        next_seq_nr_next    <= next_seq_nr + 1;
                                        cnt_next            <= 2; -- FIND SN
                                    end if;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when HANDLE_HEARTBEATS =>
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    case (cnt) is
                        -- GET NEXT WRITER
                        when 0 =>
                            -- No more Writers
                            if (ind = NUM_WRITERS-1) then
                                -- Assert Liveliness Resetter
                                assert_liveliness_latch_next    <= assert_liveliness_latch and (not w_assert_liveliness);
                                w_assert_liveliness_next        <= (others => '0');
                                
                                -- DONE
                                stage_next  <= IDLE;
                            else
                                -- Next Writer
                                ind_next    <= ind + 1;
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GET MIN_SN
                        when 1 =>
                            if (w_map(ind) = '1') then
                                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS or CONFIG_ARRAY_T(ind).LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) severity FAILURE;
                                
                                start_hc(ind)   <= '1';
                                opcode_hc(ind)  <= GET_MIN_SN;
                                
                                if (ack_hc(ind) = '1') then
                                    -- Increment Heartbeat Count
                                    count_next(ind) <= count(ind) + 1;
                                    
                                    cnt_next        <= cnt + 1;
                                end if;
                            else
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            end if;
                        -- READ MIN_SN
                        when 2 =>
                            -- Wait for HC
                            if (done_hc(ind) = '1') then
                                assert (ret_hc(ind) = OK) severity FAILURE;
                                
                                -- HC Empty (No cache Changes Available)
                                if (cc_seq_nr(ind) = SEQUENCENUMBER_UNKNOWN) then
                                    -- NOTE: Identifies the lowest SN that is yet to be written by the writter.
                                    min_sn_next <= last_seq_nr(ind) + 1;
                                else
                                    min_sn_next <= cc_seq_nr(ind);
                                end if;
                                
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GET FIRST Endpoint
                        when 3 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_occupied_head(ind);
                            mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
                            cnt_next            <= cnt + 1;
                        -- SEND HEARTBEAT
                        when 4 =>
                            -- End of Endpoint
                            if (mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            else
                                stage_next          <= SEND_HEADER;
                                cnt_next            <= 0;
                                return_stage_next   <= SEND_HEARTBEAT;
                                return_cnt_next     <= 0;
                            end if;
                        -- GET NEXT Endpoint
                        when 5 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_NEXT_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
                            cnt_next            <= 4; -- SEND HEARTBEAT
                        when others =>
                            null;
                    end case;
                end if;
            when HANDLE_NEW =>
                case (cnt) is
                    -- GET NEXT WRITER
                    when 0 =>
                        -- No more Writers
                        if (ind = NUM_WRITERS-1) then
                            -- DONE
                            new_push_next   <= '0';
                            stage_next      <= IDLE;
                        else
                            -- Next Writer
                            ind_next    <= ind + 1;
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET MAX_SN
                    when 1 =>
                        if (w_map(ind) = '1') then
                            start_hc(ind)   <= '1';
                            opcode_hc(ind)  <= GET_MAX_SN;
                            
                            if (ack_hc(ind) = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        else
                            cnt_next    <= 0; -- GET NEXT WRITER
                        end if;
                    -- READ MAX_SN
                    when 2 =>
                        -- Wait for HC
                        if (done_hc(ind) = '1') then
                            assert (ret_hc(ind) = OK) severity FAILURE;
                            
                            max_sn_next <= cc_seq_nr(ind);
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- NEXT SN
                    when 3 =>
                        -- No New Cache Changes
                        if (max_sn = last_seq_nr(ind)) then
                            -- Continue
                            cnt_next    <= 0; -- GET NEXT WRITER
                        else
                            last_seq_nr_next(ind)   <= last_seq_nr(ind) + 1;
                            next_seq_nr_next        <= last_seq_nr(ind) + 1;
                            if (CONFIG_ARRAY_T(ind).PUSH_MODE) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= 5; -- GET SN
                            end if;
                        end if;
                    -- GET FIRST Endpoint
                    when 4 =>
                        -- Memory Operation Guard
                        if (mem_op_done = '1') then
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_occupied_head(ind);
                            mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
                            cnt_next            <= cnt + 1;
                        end if;
                    -- GET SN
                    when 5 =>
                        -- Wait for Endpoint Data
                        if (mem_op_done = '1') then
                            -- End of Endpoints
                            if ((not CONFIG_ARRAY_T(ind).PUSH_MODE) or mem_endpoint_data.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                
                                -- NOTE: If PUSH_MODE false and remote reliable endpoints are available, this just does NOPs 
                                --       (leaves the CCs NACKed in the HC) and updates the last_seq_nr.
                                
                                -- ACK newly sent Cache Changes if Writer is BEST_EFFORT, or if all remore Readers are BEST_EFFORT
                                if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS /= RELIABLE_RELIABILITY_QOS or global_ack_seq_nr_base(ind) = SEQUENCENUMBER_UNKNOWN) then
                                    start_hc(ind)   <= '1';
                                    if (CONFIG_ARRAY_T(ind).DURABILITY_QOS = VOLATILE_DURABILITY_QOS) then
                                        opcode_hc(ind)  <= REMOVE_CACHE_CHANGE;
                                    else
                                        opcode_hc(ind)  <= ACK_CACHE_CHANGE;
                                    end if;
                                    seq_nr_hc(ind)  <= next_seq_nr;
                                    
                                    -- NOTE: Ignore return Code
                                    
                                    -- Wait until Operation Acknowledgement
                                    if (ack_hc(ind) = '1') then
                                        -- Continue
                                        cnt_next    <= 3; -- NEXT SN
                                    end if;
                                else
                                    -- Continue
                                    cnt_next    <= 3; -- NEXT SN
                                end if;
                            else
                                start_hc(ind)   <= '1';
                                opcode_hc(ind)  <= GET_CACHE_CHANGE;
                                seq_nr_hc(ind)  <= next_seq_nr;
                                
                                -- Wait until Operation Acknowledgement
                                if (ack_hc(ind) = '1') then
                                    cnt_next    <= cnt + 1;
                                end if;
                            end if;
                        end if;
                    -- READ SN
                    when 6 =>
                        -- Wait until Operation Response
                        if (done_hc(ind) = '1') then
                            -- Cache Change Available
                            if (ret_hc(ind) = OK) then
                                -- Only request Payload if necessary (Contains DATA or Serialized  Key)
                                if (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                                    get_data_hc(ind)    <= '1';
                                end if;
                                
                                stage_next          <= SEND_HEADER;
                                cnt_next            <= 0;
                                if (CONFIG_ARRAY_T(ind).DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                    return_stage_next   <= SEND_INFO_TS;
                                else
                                    return_stage_next   <= SEND_DATA_A;
                                end if;
                                return_cnt_next <= 0;
                            -- Cache Change Unavailable
                            else
                                assert (ret_hc(ind) = INVALID) report "Unexpected HC response" severity WARNING;
                                
                                cnt_next    <= 3; -- NEXT SN
                            end if;
                        end if;
                    -- GET NEXT Endpoint
                    when 7 =>
                        -- Memory Operation Guard
                        if (mem_op_done = '1') then
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_NEXT_ENDPOINT;
                            mem_r.i             <= ind;
                            mem_r.addr          <= mem_endpoint_data.addr;
                            mem_r.field_flags   <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
                            cnt_next            <= 5; -- GET SN
                        end if;
                    when others =>
                        null;
                end case;
            when HANDLE_HISTORICAL =>
                assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                
                case (cnt) is
                    -- GET MIN_SN
                    when 0 =>
                        start_hc(ind)   <= '1';
                        opcode_hc(ind)  <= GET_MIN_SN;
                        
                        if (ack_hc(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ MIN_SN
                    when 1 =>
                        -- Wait for HC
                        if (done_hc(ind) = '1') then
                            assert (ret_hc(ind) = OK) severity FAILURE;
                            
                            -- No Cache Changes Available
                            if (cc_seq_nr(ind) = SEQUENCENUMBER_UNKNOWN) then
                                -- Reset
                                historical_push_next    <= '0';
                                
                                -- EXIT
                                stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                cnt_next    <= 1; -- GET NEXT WRITER
                            else
                                next_seq_nr_next    <= cc_seq_nr(ind);
                                -- If remote Reader is RELIABLE, NACK the SN
                                if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') then
                                    cnt_next    <= 2; -- NACK SN
                                elsif (not CONFIG_ARRAY_T(ind).PUSH_MODE) then
                                    cnt_next    <= 5; -- NEXT SN
                                else
                                    cnt_next    <= 3; -- GET SN
                                end if;
                            end if;
                        end if;
                    -- NACK SN
                    when 2 =>
                        assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                        
                        start_hc(ind)   <= '1';
                        opcode_hc(ind)  <= NACK_CACHE_CHANGE;
                        seq_nr_hc(ind)  <= next_seq_nr;
                        -- NOTE: Ignore Return Code
                        
                        -- Update Global ACK
                        if (next_seq_nr <= global_ack_seq_nr_base(ind)) then
                            global_ack_seq_nr_base_next(ind) <= next_seq_nr - 1;
                        end if;
                        
                        -- Wait until Operation Acknowledgement
                        if (ack_hc(ind) = '1') then
                            if (CONFIG_ARRAY_T(ind).PUSH_MODE) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= 5; -- NEXT SN
                            end if;
                        end if;
                    -- GET SN
                    when 3 =>
                        assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                        
                        start_hc(ind)   <= '1';
                        opcode_hc(ind)  <= GET_CACHE_CHANGE;
                        seq_nr_hc(ind)  <= next_seq_nr;
                        
                        -- Wait until Operation Acknowledgement
                        if (ack_hc(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- HANDLE Request
                    when 4 =>
                        assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                        
                        -- Wait until Operation Response
                        if (done_hc(ind) = '1') then
                            -- Wait for Operation Response
                            if (ret_hc(ind) = OK) then  
                                -- Only request Payload if necessary (Contains DATA or Serialized  Key)
                                if (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                                    get_data_hc(ind)    <= '1';
                                end if;
                                
                                if (gap_in_progress = '1') then
                                    -- Close GAP and send DATA
                                    gap_in_progress_next    <= '0';
                                    stage_next              <= SEND_GAP_B;
                                    cnt_next                <= 0;
                                    if (CONFIG_ARRAY_T(ind).DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                        return_stage_next       <= SEND_INFO_TS;
                                    else
                                        return_stage_next       <= SEND_DATA_A;
                                    end if;
                                    return_cnt_next         <= 0;
                                else
                                    -- Send DATA
                                    stage_next          <= SEND_HEADER;
                                    cnt_next            <= 0;
                                    if (CONFIG_ARRAY_T(ind).DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                        return_stage_next   <= SEND_INFO_TS;
                                    else
                                        return_stage_next   <= SEND_DATA_A;
                                    end if;
                                    return_cnt_next     <= 0;
                                end if;
                            -- Cache Change unavialable
                            else
                                assert (ret_hc(ind) = INVALID) report "Unexpected HC response" severity WARNING;
                                
                                if (gap_in_progress = '0') then
                                    -- Open new GAP
                                    gap_in_progress_next    <= '1';
                                    stage_next              <= SEND_HEADER;
                                    cnt_next                <= 0;
                                    return_stage_next       <= SEND_GAP_A;
                                    return_cnt_next         <= 0;
                                else
                                    -- Continue
                                    cnt_next    <= 5; -- NEXT SN
                                end if;
                            end if;
                        end if;
                    -- NEXT SN
                    when 5 =>
                        -- End of Historical Data
                        if (next_seq_nr = last_seq_nr(ind)) then
                            if (gap_in_progress) then
                                -- Close GAP Message
                                gap_in_progress_next    <= '0';
                                stage_next              <= SEND_GAP_B;
                                cnt_next                <= 0;
                                gap_is_last_next        <= '1';
                                
                                -- Reset
                                historical_push_next    <= '0';
                                
                                -- EXIT
                                return_stage_next       <= INITIATE_ENDPOINT_SEARCH;
                                return_cnt_next         <= 1; -- GET NEXT WRITER
                            else
                                -- Reset
                                historical_push_next    <= '0';
                                
                                -- EXIT
                                stage_next  <= INITIATE_ENDPOINT_SEARCH;
                                cnt_next    <= 1; -- GET NEXT WRITER
                            end if;
                        else
                            next_seq_nr_next    <= next_seq_nr + 1;
                            -- If remote Reader is RELIABLE, NACK the SN
                            if (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') then
                                cnt_next    <= 2; -- NACK SN
                            elsif (not CONFIG_ARRAY_T(ind).PUSH_MODE) then
                                cnt_next    <= 5; -- NEXT SN
                            else
                                cnt_next    <= 3; -- GET SN
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when SEND_HEADER =>
                -- Precondition: mem_endpoint_data set (EMF_IPV4_ADDR_FLAG, EMF_UDP_PORT_FLAG)
                
                -- Wait for Endpoint Data
                if (mem_op_done = '1') then
                    assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG)) severity FAILURE;
                    assert stable(clk, mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    
                    -- Output FIFO Guard
                    if (full_ro = '0') then
                        wr_ro   <= '1';
                        
                        case (cnt) is
                            -- OUTPUT HEADER
                            -- Src IPv4 Address
                            when 0 =>
                                data_out_ro     <= DEFAULT_IPv4_ADDRESS;
                                cnt_next        <= cnt + 1;
                            -- Dest IPv4 Address
                            when 1 =>
                                data_out_ro     <= mem_endpoint_data.ip_addr;
                                cnt_next        <= cnt + 1;
                            -- Src and Dest UDPv4 Ports
                            when 2 =>
                                data_out_ro     <= USER_IPv4_UNICAST_PORT & mem_endpoint_data.portn;
                                cnt_next        <= cnt + 1;
                            -- RTPS MESSAGE HEADER
                            when 3 =>
                                data_out_ro     <= PROTOCOL_RTPS;
                                cnt_next        <= cnt + 1;
                            when 4 =>
                                data_out_ro     <= PROTOCOLVERSION_2_4 & VENDORID;
                                cnt_next        <= cnt + 1;
                            when 5 =>
                                data_out_ro     <= GUIDPREFIX(0);
                                cnt_next        <= cnt + 1;
                            when 6 =>
                                data_out_ro     <= GUIDPREFIX(1);
                                cnt_next        <= cnt + 1;
                            when 7 =>
                                data_out_ro   <= GUIDPREFIX(2);
                                
                                -- Continue with respective RTPS Submessage
                                stage_next  <= return_stage;
                                cnt_next    <= return_cnt;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when SEND_INFO_TS =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_ro   <= '1';
                    
                    case (cnt) is
                        -- INFO_TS RTPS SUBMESSAGE
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_ro     <= SID_INFO_TS & "00000000" & std_logic_vector(to_unsigned(8, SUBMESSAGE_LENGTH_WIDTH));
                            cnt_next        <= cnt + 1;
                        -- Source Timestamp 1/2
                        when 1 =>
                            data_out_ro     <= std_logic_vector(cc_source_timestamp(ind)(0));
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 2 =>
                            data_out_ro <= std_logic_vector(cc_source_timestamp(ind)(1));
                            
                            stage_next  <= SEND_DATA_A;
                            cnt_next    <= 0;    
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_DATA_A =>
                -- Precondition: mem_endpoint_data set (EMF_UDP_PORT_FLAG)
                
                -- Wait for Endpoint Data
                if (mem_op_done = '1') then
                    assert stable(clk, mem_endpoint_data.i = ind and check_mask(mem_endpoint_data.field_flags, EMF_UDP_PORT_FLAG)) severity FAILURE;
                    assert stable(clk, mem_endpoint_data.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    
                    -- Output FIFO Guard
                    if (full_ro = '0') then
                        case (cnt) is
                            -- DATA RTPS SUBMESSAGE
                            -- RTPS Submessage Header
                            when 0 =>
                                data_out_ro     <= SID_DATA & "00000000" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH));
                                if (cc_kind(ind) = ALIVE) then
                                    data_flag       <= '1';
                                else
                                    data_flag       <= '0';
                                end if;
                                if (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE) then
                                    key_flag        <= '1';
                                else
                                    key_flag        <= '0';
                                end if;
                                if (cc_kind(ind) /= ALIVE or CONFIG_ARRAY_T(ind).WITH_KEY or mem_endpoint_data.reader_flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
                                    qos_flag        <= '1';
                                else
                                    qos_flag        <= '0';
                                end if;
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- extraFlags, octetsToInlineQoS
                            when 1 =>
                                data_out_ro     <= x"0000" & std_logic_vector(to_unsigned(16, 16));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Reader Entity ID
                            when 2 =>
                                data_out_ro     <= ENTITYID_UNKNOWN;
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Writer Entity ID
                            when 3 =>
                                data_out_ro     <= ENTITYID_T(ind);
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Sequence Number 1/2
                            when 4 =>
                                data_out_ro     <= std_logic_vector(next_seq_nr(0));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Sequence Number 2/2
                            when 5 =>
                                data_out_ro     <= std_logic_vector(next_seq_nr(1));
                                wr_ro           <= '1';
                                
                                -- Need to send Key Hash
                                if (CONFIG_ARRAY_T(ind).WITH_KEY) then
                                    cnt_next    <= cnt + 1;
                                -- Need to send Status Info
                                elsif (cc_kind(ind) /= ALIVE) then
                                    cnt_next    <= cnt + 6;
                                -- Reader expect in-line QoS
                                elsif(mem_endpoint_data.reader_flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
                                    stage_next  <= SEND_INLINE_QOS;
                                    cnt3_next   <= 0;
                                -- Payload Available (DATA or Serialized Key)
                                elsif (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                                    stage_next  <= SEND_DATA_B;
                                    cnt_next    <= 0;
                                else
                                    last_word_out_ro    <= '1';
                                    -- Continue
                                    if (stale_check = '1') then
                                        stage_next  <= HANDLE_REQUESTS;
                                        cnt_next    <= 1; -- NEXT BITMAP POS
                                    elsif (new_push = '1') then
                                        assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                                        
                                        stage_next  <= HANDLE_NEW;
                                        cnt_next    <= 7; -- GET NEXT Endpoint
                                    elsif (historical_push = '1') then
                                        assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                                        
                                        stage_next  <= HANDLE_HISTORICAL;
                                        cnt_next    <= 5; -- NEXT SN
                                    else
                                        assert FALSE severity FAILURE;
                                    end if;
                                end if;
                            -- Key Hash PID
                            when 6 =>
                                data_out_ro     <= PID_KEY_HASH & std_logic_vector(to_unsigned(16, SUBMESSAGE_LENGTH_WIDTH));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Key Hash 1/4
                            when 7 =>
                                data_out_ro     <= std_logic_vector(cc_instance_handle(ind)(0));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Key Hash 2/4
                            when 8 =>
                                data_out_ro     <= std_logic_vector(cc_instance_handle(ind)(1));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Key Hash 3/4
                            when 9 =>
                                data_out_ro     <= std_logic_vector(cc_instance_handle(ind)(2));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Key Hash 4/4
                            when 10 =>
                                data_out_ro     <= std_logic_vector(cc_instance_handle(ind)(3));
                                wr_ro           <= '1';
                                
                                -- Need to send Status Info
                                if (cc_kind(ind) /= ALIVE) then
                                    cnt_next    <= cnt + 1;
                                -- Reader expects in-line QoS
                                elsif (mem_endpoint_data.reader_flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
                                    stage_next  <= SEND_INLINE_QOS;
                                    cnt3_next   <= 0;
                                else
                                    cnt_next    <= cnt + 3;
                                end if;
                            -- Status Info PID
                            when 11 =>
                                data_out_ro     <= PID_STATUS_INFO & std_logic_vector(to_unsigned(4, SUBMESSAGE_LENGTH_WIDTH));
                                wr_ro           <= '1';
                                cnt_next        <= cnt + 1;
                            -- Status Info
                            when 12 =>
                                data_out_ro   <= (others => '0');
                                wr_ro          <= '1';
                                case (cc_kind(ind)) is
                                    when ALIVE_FILTERED =>
                                        data_out_ro(STATUS_INFO_FILTERED_FLAG)      <= '1';
                                    when NOT_ALIVE_DISPOSED =>
                                        data_out_ro(STATUS_INFO_DISPOSED_FLAG)      <= '1';
                                    when NOT_ALIVE_UNREGISTERED =>
                                        data_out_ro(STATUS_INFO_UNREGISTERED_FLAG)  <= '1';
                                    when others =>
                                        null;
                                end case;
                                
                                -- Reader expects in-line QoS
                                if (mem_endpoint_data.reader_flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
                                    stage_next  <= SEND_INLINE_QOS;
                                    cnt3_next   <= 0;
                                else
                                    cnt_next    <= cnt + 1;
                                end if;
                            -- Sentinel
                            when 13 =>
                                data_out_ro <= PID_SENTINEL & std_logic_vector(to_unsigned(0, PARAMETER_LENGTH_WIDTH));
                                wr_ro       <= '1';
                                
                                -- Payload Available (DATA or Serialized Key)
                                if (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                                    stage_next      <= SEND_DATA_B;  
                                else
                                    last_word_out_ro    <= '1';
                                    -- Continue
                                    if (stale_check = '1') then
                                        assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                                        
                                        stage_next          <= HANDLE_REQUESTS;
                                        cnt_next            <= 1; -- NEXT BITMAP POS
                                    elsif (new_push = '1') then
                                        assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                                        
                                        stage_next  <= HANDLE_NEW;
                                        cnt_next    <= 7; -- GET NEXT Endpoint
                                    elsif (historical_push = '1') then
                                        assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                                        
                                        stage_next  <= HANDLE_HISTORICAL;
                                        cnt_next    <= 5; -- NEXT SN
                                    else
                                        assert FALSE severity FAILURE;
                                    end if;
                                end if;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when SEND_INLINE_QOS =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    data_out_ro <= INLINE_QOS_T(ind).data(cnt3);
                    wr_ro       <= '1';
                    
                    -- Exit Condition
                    if (cnt3 = INLINE_QOS_T(ind).length-1) then
                        -- Payload Available (DATA or Serialized Key)
                        if (cc_kind(ind) = ALIVE or (CONFIG_ARRAY_T(ind).WITH_KEY and cc_kind(ind) /= ALIVE)) then
                            stage_next      <= SEND_DATA_B;  
                        else
                            last_word_out_ro    <= '1';
                            -- Continue
                            if (stale_check = '1') then
                                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                                
                                stage_next  <= HANDLE_REQUESTS;
                                cnt_next    <= 1; -- NEXT BITMAP POS
                            elsif (new_push = '1') then
                                assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                                
                                stage_next  <= HANDLE_NEW;
                                cnt_next    <= 7; -- GET NEXT Endpoint
                            elsif (historical_push = '1') then
                                assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                                
                                stage_next  <= HANDLE_HISTORICAL;
                                cnt_next    <= 5; -- NEXT SN
                            else
                                assert FALSE severity FAILURE;
                            end if;
                        end if;
                    else
                        cnt3_next   <= cnt3 + 1;
                    end if;
                end if;
            when SEND_DATA_B =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    ready_in_hc(ind)    <= '1';
                    
                    if (valid_in_hc(ind) = '1') then
                        data_out_ro <= data_in_hc(ind);
                        wr_ro       <= '1';
                        
                        if (last_word_in_hc(ind) = '1') then
                            last_word_out_ro    <= '1';
                            
                            -- Continue
                            if (stale_check = '1') then
                                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                                
                                stage_next          <= HANDLE_REQUESTS;
                                cnt_next            <= 1; -- NEXT BITMAP POS
                            elsif (new_push = '1') then
                                assert (CONFIG_ARRAY_T(ind).PUSH_MODE) severity FAILURE;
                                
                                stage_next  <= HANDLE_NEW;
                                cnt_next    <= 7; -- GET NEXT Endpoint
                            elsif (historical_push = '1') then
                                assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                                
                                stage_next  <= HANDLE_HISTORICAL;
                                cnt_next    <= 5; -- NEXT SN
                            else
                                assert FALSE severity FAILURE;
                            end if;
                        end if;
                    end if;
                end if;
            when SEND_GAP_A =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_ro   <= '1';
                    
                    case (cnt) is
                        -- DATA RTPS SUBMESSAGE (Participant Message)
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_ro     <= SID_GAP & "00000000" & std_logic_vector(to_unsigned(28, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 1 =>
                            data_out_ro     <= ENTITYID_UNKNOWN;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 2 =>
                            data_out_ro     <= ENTITYID_T(ind);
                            cnt_next        <= cnt + 1;
                        -- GAP Start Sequence Number 1/2
                        when 3 =>
                            data_out_ro     <= std_logic_vector(next_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- GAP Start Sequence Number 2/2
                        when 4 =>
                            data_out_ro     <= std_logic_vector(next_seq_nr(1));
                            
                            -- Continue
                            if (stale_check = '1') then
                                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) severity FAILURE;
                                
                                stage_next  <= HANDLE_REQUESTS;
                                cnt_next    <= 1; -- NEXT BITMAP POS
                            elsif (historical_push = '1') then
                                assert (CONFIG_ARRAY_T(ind).DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) severity FAILURE;
                                
                                stage_next  <= HANDLE_HISTORICAL;
                                cnt_next    <= 5; -- NEXT SN
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_GAP_B =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_ro   <= '1';
                    
                    case (cnt) is
                        -- GAP List Sequence Number Set (Bitmap Base 1/2)
                        when 0 =>
                            data_out_ro     <= std_logic_vector(next_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- GAP List Sequence Number Set (Bitmap Base 2/2)
                        when 1 =>
                            data_out_ro     <= std_logic_vector(next_seq_nr(1));
                            cnt_next        <= cnt + 1;
                        -- GAP List Sequence Number Set (NumBits)
                        when 2 =>
                            data_out_ro     <= (others => '0');
                            
                            if (gap_is_last = '1') then
                                last_word_out_ro    <= '1';
                                -- Reset
                                gap_is_last_next    <= '0';
                            end if;
                            
                            -- Continue
                            stage_next  <= return_stage;
                            cnt_next    <= return_cnt;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_HEARTBEAT =>
                assert (CONFIG_ARRAY_T(ind).RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS or CONFIG_ARRAY_T(ind).LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) severity FAILURE;
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_ro   <= '1';
                    
                    case (cnt) is
                        -- HEARTBEAT RTPS SUBMESSAGE
                        -- RTPS Submessage Header
                        when 0 =>
                            if (w_assert_liveliness(ind) = '1') then
                                data_out_ro <= SID_HEARTBEAT & "00000100" & std_logic_vector(to_unsigned(28, 16));
                            else
                                data_out_ro <= SID_HEARTBEAT & "00000000" & std_logic_vector(to_unsigned(28, 16));
                            end if;
                            cnt_next    <= cnt + 1;
                        -- Reader Entity ID
                        when 1 =>
                            data_out_ro     <= ENTITYID_UNKNOWN;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 2 =>
                            data_out_ro     <= ENTITYID_T(ind);
                            cnt_next        <= cnt + 1;
                        -- First Sequence Number 1/2
                        when 3 =>
                            data_out_ro     <= std_logic_vector(min_sn(0));
                            cnt_next        <= cnt + 1;
                        -- First Sequence Number 2/2
                        when 4 =>
                            data_out_ro     <= std_logic_vector(min_sn(1));
                            cnt_next        <= cnt + 1;
                        -- Last Sequence Number 1/2
                        when 5 =>
                            data_out_ro     <= std_logic_vector(last_seq_nr(ind)(0));
                            cnt_next        <= cnt + 1;
                        -- Last Sequence Number 2/2
                        when 6 =>
                            data_out_ro     <= std_logic_vector(last_seq_nr(ind)(1));
                            cnt_next        <= cnt + 1;
                        -- Count
                        when 7 =>
                            data_out_ro         <= std_logic_vector(count(ind));
                            last_word_out_ro    <= '1';
                            
                            if (initial_heartbeat = '1') then
                                assert (meta_opcode = EMO_ENDPOINT_MATCH) severity FAILURE;
                                
                                -- Reset
                                initial_heartbeat_next  <= '0';
                                
                                stage_next  <= METATRAFFIC_OPERATION;
                                cnt_next    <= 3; -- POST-HEARTBEAT
                            else
                                stage_next  <= HANDLE_HEARTBEATS;
                                cnt_next    <= 5; -- GET NEXT Endpoint
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SKIP_PACKET =>
                assert (is_meta = '0') severity FAILURE;
                
                -- Consumed last word of Packet
                if (last_word_in_latch = '1' and last_word_in_user = '0') then
                    -- Reset Last Word In Latch
                    last_word_in_latch_next <= '0';
                    -- DONE
                    stage_next  <= IDLE;
                -- Input FIFO Guard
                elsif (empty_user /= (empty_user'range => '1')) then
                    assert ((empty_user xor w_map) = (empty_user'range => '1')) severity FAILURE;
                    -- Skip-Read
                    rd_user     <= '1';
                end if;
            when SKIP_META_OPERATION =>
                assert (is_meta = '1') severity FAILURE;
                
                -- Consumed last word of Packet
                if (last_word_in_latch = '1' and last_word_in_meta = '0') then
                    -- Reset Last Word In Latch
                    last_word_in_latch_next <= '0';
                    -- DONE
                    stage_next  <= IDLE;
                -- Input Guard
                elsif (empty_meta /= (empty_meta'range => '1')) then
                    assert ((empty_meta xor w_map) = (empty_meta'range => '1')) severity FAILURE;
                    -- Skip-Read
                    rd_meta <= '1';
                end if;
        end case;
    end process;
    
    empty_head_sig_prc : process(all)
    begin
        for i in 0 to NUM_WRITERS-1 loop
            empty_head_sig(i)   <= to_integer(mem_empty_head(i));
        end loop;
    end process;
    
    -- *Memory State Machine*
    -- STATE                DESCRIPTION
    -- IDLE                 Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
    -- SEARCH_ENDPOINT      See Memory OPCODE Description
    -- GET_ENDPOINT_DATA    Latch specified Endpoint Data for use by main FSM
    -- INSERT_ENDPOINT      See Memory OPCODE Description
    -- UPDATE_ENDPOINT      See Memory OPCODE Description
    -- REMOVE_ENDPOINT      See Memory OPCODE Description
    -- GET_NEXT_ENDPOINT    See Memory OPCODE Description
    -- RESET_MEMORY         Reset Endpoint Memory to Empty State
    mem_ctrl_prc : process(all)
    begin
        -- DEFAULT Registered
        mem_stage_next                  <= mem_stage;
        mem_addr_base_next              <= mem_addr_base;
        mem_occupied_head_next          <= mem_occupied_head;
        mem_empty_head_next             <= mem_empty_head;
        mem_cnt_next                    <= mem_cnt;
        mem_addr_latch_next             <= mem_addr_latch;
        mem_endpoint_data_next          <= mem_endpoint_data;
        mem_endpoint_latch_data_next    <= mem_endpoint_latch_data;
        -- DEFAULT Unregistered
        mem_addr        <= (others => '0');
        mem_write_data  <= (others => '0');
        mem_read        <= '0';
        mem_valid_in    <= '0';
        mem_ready_out   <= '0';
        mem_op_done     <= '0';
        abort_read      <= '0';
        multi_w         <= '0';
        
        
        case (mem_stage) is
            when IDLE =>
                mem_op_done <= '1';
                
                if (mem_op_start = '1') then
                    -- Latch Signals needed for Mermory Operation
                    mem_endpoint_latch_data_next      <= mem_r;
                    
                    case(mem_opcode) is
                        when SEARCH_ENDPOINT =>
                            mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                            mem_endpoint_data_next.i    <= mem_r.i;
                            
                            if (mem_occupied_head(mem_r.i) /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next  <= mem_occupied_head(mem_r.i);
                                mem_stage_next      <= SEARCH_ENDPOINT;
                                mem_cnt_next        <= 0;
                            end if;
                        when INSERT_ENDPOINT =>
                            assert (mem_empty_head(mem_r.i) /= ENDPOINT_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                            mem_endpoint_data_next.i    <= mem_r.i;
                            
                            mem_endpoint_data_next.addr <= mem_empty_head(mem_r.i);
                            mem_addr_base_next          <= mem_empty_head(mem_r.i);
                            mem_stage_next              <= INSERT_ENDPOINT;
                            mem_cnt_next                <= 0;
                        when UPDATE_ENDPOINT =>
                            if (mem_r.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                                mem_endpoint_data_next.i    <= mem_r.i;
                            else
                                if (mem_r.i /= mem_endpoint_data.i or mem_r.addr /= mem_endpoint_data.addr) then
                                    mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                                    mem_endpoint_data_next.i    <= mem_r.i;
                                end if;
                                
                                mem_endpoint_data_next.addr <= mem_r.addr;
                                mem_addr_base_next          <= mem_r.addr;
                                mem_stage_next              <= UPDATE_ENDPOINT;
                                if check_mask(mem_r.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_r.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 1;
                                elsif check_mask(mem_r.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 2;
                                elsif check_mask(mem_r.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(mem_r.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(mem_r.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(mem_r.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                    mem_cnt_next    <= 10;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        when REMOVE_ENDPOINT =>
                            mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                            mem_endpoint_data_next.i    <= mem_r.i;
                            
                            if (mem_r.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= REMOVE_ENDPOINT;
                                mem_cnt_next        <= 0;
                            end if;
                        when GET_NEXT_ENDPOINT =>
                            mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                            mem_endpoint_data_next.i    <= mem_r.i;
                            
                            if (mem_r.addr /= ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= GET_NEXT_ENDPOINT;
                                mem_cnt_next        <= 0;
                            end if;
                        when GET_ENDPOINT =>
                            if (mem_r.addr = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                                mem_endpoint_data_next.i    <= mem_r.i;
                            else
                                if (mem_r.i /= mem_endpoint_data.i or mem_r.addr /= mem_endpoint_data.addr) then
                                    mem_endpoint_data_next  <= ZERO_ENDPOINT_DATA;
                                    mem_endpoint_data_next.i    <= mem_r.i;
                                end if;
                                
                                -- Fetch Endpoint Data
                                mem_endpoint_data_next.addr <= mem_r.addr;
                                mem_addr_base_next      <= mem_r.addr;
                                mem_stage_next          <= GET_ENDPOINT_DATA;
                                if check_mask(mem_r.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_r.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 1;
                                elsif check_mask(mem_r.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(mem_r.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(mem_r.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(mem_r.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(mem_r.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(mem_r.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(mem_r.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                    mem_cnt_next    <= 14;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEARCH_ENDPOINT =>
                case (mem_cnt) is
                    -- GET Entity ID
                    when 0 =>
                        mem_addr        <= mem_addr_base + EMF_ENTITYID_OFFSET;
                        mem_read        <= '1';
                        mem_valid_in    <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET GUID Prefix 1/3
                    when 1 =>
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
                        mem_read        <= '1';
                        mem_valid_in    <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET GUID Prefix 2/3
                    when 2 =>
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
                        mem_read        <= '1';
                        mem_valid_in    <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET GUID Prefix 3/3
                    when 3 =>
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
                        mem_read        <= '1';
                        mem_valid_in    <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Entity ID
                    when 4 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No Match
                            if (mem_read_data /= mem_endpoint_latch_data.guid(3)) then
                                abort_read      <= '1';
                                mem_cnt_next    <= 8; -- GET Next Addr
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- READ GUID Prefix 1/3
                    when 5 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No  Match
                            if (mem_read_data /= mem_endpoint_latch_data.guid(0)) then
                                abort_read  <= '1';
                                mem_cnt_next    <= 8; -- GET Next Addr
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- READ GUID Prefix 2/3
                    when 6 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No  Match
                            if (mem_read_data /= mem_endpoint_latch_data.guid(1)) then
                                abort_read  <= '1';
                                mem_cnt_next    <= 8; -- GET Next Addr
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- READ GUID Prefix 3/3
                    when 7 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No  Match
                            if (mem_read_data /= mem_endpoint_latch_data.guid(2)) then
                                abort_read  <= '1';
                                mem_cnt_next    <= 8; -- GET Next Addr
                            -- Match
                            else
                                mem_endpoint_data_next.addr <= mem_addr_base;
                                -- Fetch Endpoint Data
                                mem_stage_next  <= GET_ENDPOINT_DATA;
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 1;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                    mem_cnt_next    <= 14;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        end if;
                    -- GET Next Addr
                    when 8 =>
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_read        <= '1';
                        mem_valid_in    <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 9 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No more Endpoints
                            if (resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH) = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_endpoint_data_next.addr <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                mem_stage_next      <= IDLE;
                            else
                                -- Continue
                                mem_addr_base_next  <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                                mem_cnt_next        <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_ENDPOINT_DATA =>
                
                case (mem_cnt) is
                    -- GET Entity ID
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ENTITYID_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                mem_cnt_next    <= 1;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                mem_cnt_next    <= 15;
                            end if;
                        end if;
                    -- GET GUID Prefix 1/3
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET GUID Prefix 2/3
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET GUID Prefix 3/3
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                else
                                    mem_cnt_next    <= 16;
                                end if;
                            end if;
                        end if;
                    -- GET IPv4 Address
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                else
                                    mem_cnt_next    <= 19;
                                end if;
                            end if;
                        end if;
                    -- GET UDP Port & Reader Flags
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_UDP_PORT_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 19;
                                else
                                    mem_cnt_next    <= 20;
                                end if;
                            end if;
                        end if;
                    -- GET Lease Deadline 1/2
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET Lease Deadline 2/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 20;
                                else
                                    mem_cnt_next    <= 21;
                                end if;
                            end if;
                        end if;
                    -- GET Response Time 1/2
                    when 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET Response Time 2/2
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 20;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 21;
                                else
                                    mem_cnt_next    <= 23;
                                end if;
                            end if;
                        end if;
                    -- GET ACK Sequence Number 1/2
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET ACK Sequence Number 2/2
                    when 11 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 20;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 21;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 23;
                                else
                                    mem_cnt_next    <= 25;
                                end if;
                            end if;
                        end if;
                    -- GET Request Sequence Number Base 1/2
                    when 12 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET Request Sequence Number Base 2/2
                    when 13 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 14;
                            else
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 20;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 21;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 25;
                                else
                                    mem_cnt_next    <= 27;
                                end if;
                            end if;
                        end if;
                    -- GET Request Bitmap
                    when 14 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 20;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 21;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            else
                                mem_cnt_next    <= 29;
                            end if;
                        end if;
                    -- READ Entity ID
                    when 15 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.guid(3)      <= mem_read_data;
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_ENTITYID_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 20;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 21;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ GUID Prefix 1/3
                    when 16 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.guid(0)  <= mem_read_data;
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ GUID Prefix 2/3
                    when 17 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.guid(1)  <= mem_read_data;
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ GUID Prefix 3/3
                    when 18 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.guid(2)      <= mem_read_data;
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_GUIDPREFIX_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 20;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 21;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ IPv4 Address
                    when 19 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.ip_addr      <= mem_read_data;
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_IPV4_ADDR_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 20;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 21;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ UDP Port & Reader Flags
                    when 20 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.portn    <= mem_read_data(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH);
                            mem_endpoint_data_next.reader_flags    <= mem_read_data(CDR_SHORT_WIDTH-1 downto 0);
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_UDP_PORT_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 21;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Lease Deadline 1/2
                    when 21 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.lease_deadline(0)    <= unsigned(mem_read_data);
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Lease Deadline 2/2
                    when 22 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.lease_deadline(1)    <= unsigned(mem_read_data);
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_LEASE_DEADLINE_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Response Time 1/2
                    when 23 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.res_time(0)  <= unsigned(mem_read_data);
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Response Time 2/2
                    when 24 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.res_time(1)  <= unsigned(mem_read_data);
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_RES_TIME_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 25;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ ACK Sequence Number 1/2
                    when 25 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.ack_seq_nr_base(0)   <= unsigned(mem_read_data);
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ ACK Sequence Number 2/2
                    when 26 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.ack_seq_nr_base(1)   <= unsigned(mem_read_data);
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_ACK_SEQ_NR_BASE_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Request Sequence Number Base 1/2
                    when 27 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.req_seq_nr_base(0)   <= unsigned(mem_read_data);
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Request Sequence Number Base 2/2
                    when 28 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.req_seq_nr_base(1)   <= unsigned(mem_read_data);
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BASE_FLAG;
                            
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 29;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Request Bitmap
                    when 29 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_endpoint_data_next.req_seq_nr_bitmap    <= mem_read_data;
                            mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BITMAP_FLAG;
                            
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when INSERT_ENDPOINT =>
                case (mem_cnt) is
                    -- GET Next Addr
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Entity ID
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ENTITYID_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.guid(3);
                        mem_endpoint_data_next.guid(3)  <= mem_endpoint_latch_data.guid(3);
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_ENTITYID_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET GUID Prefix 1/3
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.guid(0);
                        mem_endpoint_data_next.guid(0)  <= mem_endpoint_latch_data.guid(0);
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET GUID Prefix 2/3
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
                        mem_write_data  <= mem_endpoint_latch_data.guid(1);
                        mem_endpoint_data_next.guid(1)  <= mem_endpoint_latch_data.guid(1);
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET GUID Prefix 3/3
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
                        mem_write_data  <= mem_endpoint_latch_data.guid(2);
                        mem_endpoint_data_next.guid(2)  <= mem_endpoint_latch_data.guid(2);
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_GUIDPREFIX_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET IPv4 Address
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.ip_addr;
                        mem_endpoint_data_next.ip_addr <= mem_endpoint_latch_data.ip_addr;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_IPV4_ADDR_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET UDPv4 Ports and Reader Flags
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_UDP_PORT_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.portn & mem_endpoint_latch_data.reader_flags;
                        mem_endpoint_data_next.portn    <= mem_endpoint_latch_data.portn;
                        mem_endpoint_data_next.reader_flags    <= mem_endpoint_latch_data.reader_flags;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_UDP_PORT_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Deadline 1/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(0));
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Deadline 2/2
                    when 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(1));
                        mem_endpoint_data_next.lease_deadline   <= mem_endpoint_latch_data.lease_deadline;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_LEASE_DEADLINE_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Response Time 1/2
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(0));
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Response Time 2/2
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(1));
                        mem_endpoint_data_next.res_time <= TIME_INVALID;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_RES_TIME_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACK Sequence Number 1/2
                    when 11 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(0));
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACK Sequence Number 2/2
                    when 12 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(1));
                        mem_endpoint_data_next.ack_seq_nr_base  <= mem_endpoint_latch_data.ack_seq_nr_base;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_ACK_SEQ_NR_BASE_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Request Sequence Number Base 1/2
                    when 13 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET;
                        mem_write_data  <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(0));
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Request Sequence Number Base 2/2
                    when 14 =>
                        mem_write_data  <= (others => '0');
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(1));
                        mem_endpoint_data_next.req_seq_nr_base  <= SEQUENCENUMBER_UNKNOWN;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BASE_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Request Bitmap
                    when 15 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
                        mem_write_data  <= (others => '0');
                        mem_endpoint_data_next.req_seq_nr_bitmap    <= (others => '0');
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BITMAP_FLAG;
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Next Addr
                    when 16 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_occupied_head(mem_endpoint_latch_data.i),WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Prev Addr
                    when 17 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_PREV_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(ENDPOINT_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            if (mem_occupied_head(mem_endpoint_latch_data.i) = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_cnt_next    <= mem_cnt + 2; -- Skip Next Step
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- SET Prev Addr (Occupied Head)
                    when 18 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_occupied_head(mem_endpoint_latch_data.i) + EMF_PREV_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_addr_base,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 19 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            
                            -- Update List Heads
                            mem_empty_head_next(mem_endpoint_latch_data.i)      <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                            mem_occupied_head_next(mem_endpoint_latch_data.i)   <= mem_addr_base;
                            
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others => 
                        null;
                end case;
            when UPDATE_ENDPOINT =>
                case (mem_cnt) is
                    -- SET IPv4 Address
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.ip_addr;
                        mem_endpoint_data_next.ip_addr <= mem_endpoint_latch_data.ip_addr;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_IPV4_ADDR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 1;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 2;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET UDPv4 Ports & Reader Flags
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_UDP_PORT_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.portn & mem_endpoint_latch_data.reader_flags;
                        mem_endpoint_data_next.portn    <= mem_endpoint_latch_data.portn;
                        mem_endpoint_data_next.reader_flags    <= mem_endpoint_latch_data.reader_flags;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_UDP_PORT_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 2;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Lease Deadline 1/2
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1')  then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Deadline 2/2
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(1));
                        mem_endpoint_data_next.lease_deadline   <= mem_endpoint_latch_data.lease_deadline;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_LEASE_DEADLINE_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1')  then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Response Time 1/2
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.res_time(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1')  then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Response Time 2/2
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.res_time(1));
                        mem_endpoint_data_next.res_time <= mem_endpoint_latch_data.res_time;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_RES_TIME_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1')  then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET ACK Sequence Number 1/2
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACK Sequence Number 2/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(1));
                        mem_endpoint_data_next.ack_seq_nr_base  <= mem_endpoint_latch_data.ack_seq_nr_base;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_ACK_SEQ_NR_BASE_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Request Sequence Number Base 1/2
                    when 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.req_seq_nr_base(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Request Sequence Number Base 2/2
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(mem_endpoint_latch_data.req_seq_nr_base(1));
                        mem_endpoint_data_next.req_seq_nr_base  <= mem_endpoint_latch_data.req_seq_nr_base;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BASE_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                mem_cnt_next    <= 10;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Request Bitmap
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
                        mem_write_data  <= mem_endpoint_latch_data.req_seq_nr_bitmap;
                        mem_endpoint_data_next.req_seq_nr_bitmap    <= mem_endpoint_latch_data.req_seq_nr_bitmap;
                        mem_endpoint_data_next.field_flags  <= mem_endpoint_data.field_flags or EMF_REQ_SEQ_NR_BITMAP_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when REMOVE_ENDPOINT =>                
                case (mem_cnt) is
                    -- GET Next Addr
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- GET Prev Addr
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_PREV_ADDR_OFFSET;
                        mem_read        <= '1';
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Next Addr
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_empty_head(mem_endpoint_latch_data.i),WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            -- Set New Empty Head
                            mem_empty_head_next(mem_endpoint_latch_data.i)  <= mem_addr_base;
                            
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 3 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            mem_addr_latch_next <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Prev Addr
                    when 4 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            if (mem_addr_latch = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                if (resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH) = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                    -- RESET Occupied List Head
                                    mem_occupied_head_next(mem_endpoint_latch_data.i)   <= ENDPOINT_MEMORY_MAX_ADDRESS;
                                    
                                    mem_endpoint_data_next.addr <= ENDPOINT_MEMORY_MAX_ADDRESS;
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                else
                                    mem_addr_base_next  <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                                    mem_cnt_next        <= mem_cnt + 2; -- Skip Next Step
                                end if;
                            else
                                mem_addr_base_next  <= mem_addr_latch;
                                mem_addr_latch_next <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                                mem_cnt_next        <= mem_cnt + 1;
                            end if;
                        end if;
                    -- SET Prev Addr (Next Slot)
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_PREV_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_addr_latch,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            if (mem_addr_latch = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                -- Set New Occupied List Head
                                mem_occupied_head_next(mem_endpoint_latch_data.i)   <= mem_addr_base;
                                
                                mem_endpoint_data_next.addr <= mem_addr_base;
                                -- DONE
                                mem_stage_next  <= IDLE;
                            else
                                mem_addr_base_next  <= mem_addr_latch;
                                mem_addr_latch_next <= mem_addr_base;
                                mem_cnt_next        <= mem_cnt + 1;
                            end if;
                        end if;
                    -- SET Next Addr (Previous Slot)
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_addr_latch,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            mem_endpoint_data_next.addr <= mem_addr_latch;
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others => 
                        null;
                end case;
            when GET_NEXT_ENDPOINT =>
                case (mem_cnt) is
                    -- GET Next Addr
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_read        <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 1 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            if (resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH) = ENDPOINT_MEMORY_MAX_ADDRESS) then
                                mem_endpoint_data_next.addr <= ENDPOINT_MEMORY_MAX_ADDRESS;
                                -- DONE
                                mem_stage_next  <= IDLE;
                            else
                                mem_endpoint_data_next.addr <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                                
                                -- Fetch Endpoint Data
                                mem_addr_base_next          <= resize(unsigned(mem_read_data),ENDPOINT_MEMORY_ADDR_WIDTH);
                                mem_stage_next  <= GET_ENDPOINT_DATA;
                                if check_mask(mem_endpoint_latch_data.field_flags,EMF_ENTITYID_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 1;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_ACK_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BASE_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(mem_endpoint_latch_data.field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG) then
                                    mem_cnt_next    <= 14;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_MEMORY =>
                multi_w <= '1';
                case (mem_cnt) is
                    -- SET Next Pointer
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_NEXT_ADDR_OFFSET;
                        if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then
                            mem_write_data  <= std_logic_vector(resize(ENDPOINT_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        else
                            mem_write_data  <= std_logic_vector(resize(mem_addr_base + ENDPOINT_FRAME_SIZE,WORD_WIDTH));
                        end if;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Previous Pointer
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + EMF_PREV_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_addr_latch,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then
                                -- Initialize Empty and Occupied Heads
                                mem_empty_head_next     <= (others => FIRST_ENDPOINT_ADDRESS);
                                mem_occupied_head_next  <= (others => ENDPOINT_MEMORY_MAX_ADDRESS);
                                
                                -- DONE
                                mem_stage_next  <= IDLE;
                            else
                                mem_addr_latch_next <= mem_addr_base;
                                mem_addr_base_next  <= mem_addr_base + ENDPOINT_FRAME_SIZE;
                                mem_cnt_next        <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
        end case;
    end process;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage                       <= IDLE;
                return_stage                <= IDLE;
                mem_stage                   <= RESET_MEMORY;
                sn_latch_1                  <= SEQUENCENUMBER_UNKNOWN;
                sn_latch_2                  <= SEQUENCENUMBER_UNKNOWN;
                ack_base                    <= SEQUENCENUMBER_UNKNOWN;
                nack_base                   <= SEQUENCENUMBER_UNKNOWN;
                check_time                  <= TIME_INVALID;
                heartbeat_time              <= time + CONFIG_ARRAY_T(0).HEARTBEAT_PERIOD;
                guid                        <= GUID_UNKNOWN;
                addr                        <= IPv4_ADDRESS_INVALID;
                portn                       <= UDP_PORT_INVALID;
                mem_endpoint_data           <= ZERO_ENDPOINT_DATA;
                mem_endpoint_latch_data     <= ZERO_ENDPOINT_DATA;
                cnt                         <= 0;
                cnt2                        <= 0;
                cnt3                        <= 0;
                nack_bitmap_pos             <= 0;
                req_bitmap_pos              <= 0;
                mem_cnt                     <= 0;
                return_cnt                  <= 0;
                ind                         <= 0;
                gap_is_last                 <= '0';
                is_meta                     <= '0';
                last_word_in_latch          <= '0';
                stale_check                 <= '0';
                gap_in_progress             <= '0';
                new_push                    <= '0';
                historical_push             <= '0';
                initial_heartbeat           <= '0';
                assert_liveliness_latch     <= (others => '0');
                w_assert_liveliness         <= (others => '0');
                bitmap_cnt                  <= (others => '0');
                meta_opcode                 <= EMO_NOP;
                opcode                      <= SID_PAD;
                rtps_flags                  <= (others => '0');
                reader_flags                <= (others => '0');
                count                       <= (others => (others => '0'));
                long_latch                  <= (others => '0');
                req_seq_nr_bitmap           <= (others => '0');
                w_map                       <= (others => '0');
                mem_addr_base               <= FIRST_ENDPOINT_ADDRESS;
                mem_occupied_head           <= (others => ENDPOINT_MEMORY_MAX_ADDRESS);
                mem_empty_head              <= (others => ENDPOINT_MEMORY_MAX_ADDRESS);
                mem_addr_latch              <= ENDPOINT_MEMORY_MAX_ADDRESS;
                global_ack_seq_nr_base      <= (others => SEQUENCENUMBER_UNKNOWN);
                last_seq_nr                 <= (others => ZERO_SEQUENCENUMBER);
                bitmap_latch                <= (others => (others => '0'));
            else
                stage                       <= stage_next;
                return_stage                <= return_stage_next;
                mem_stage                   <= mem_stage_next;
                sn_latch_1                  <= sn_latch_1_next;
                sn_latch_2                  <= sn_latch_2_next;
                ack_base                    <= ack_base_next;
                nack_base                   <= nack_base_next;
                check_time                  <= check_time_next;
                heartbeat_time              <= heartbeat_time_next;
                guid                        <= guid_next;
                addr                        <= addr_next;
                portn                       <= portn_next;
                mem_endpoint_data           <= mem_endpoint_data_next;
                mem_endpoint_latch_data     <= mem_endpoint_latch_data_next;
                cnt                         <= cnt_next;
                cnt2                        <= cnt2_next;
                cnt3                        <= cnt3_next;
                nack_bitmap_pos             <= nack_bitmap_pos_next;
                req_bitmap_pos              <= req_bitmap_pos_next;
                mem_cnt                     <= mem_cnt_next;
                return_cnt                  <= return_cnt_next;
                ind                         <= ind_next;
                gap_is_last                 <= gap_is_last_next;
                is_meta                     <= is_meta_next;
                last_word_in_latch          <= last_word_in_latch_next;
                stale_check                 <= stale_check_next;
                gap_in_progress             <= gap_in_progress_next;
                new_push                    <= new_push_next;
                historical_push             <= historical_push_next;
                initial_heartbeat           <= initial_heartbeat_next;
                bitmap_cnt                  <= bitmap_cnt_next;
                assert_liveliness_latch     <= assert_liveliness_latch_next;
                w_assert_liveliness         <= w_assert_liveliness_next;
                meta_opcode                 <= meta_opcode_next;
                opcode                      <= opcode_next;
                rtps_flags                  <= rtps_flags_next;
                reader_flags                <= reader_flags_next;
                count                       <= count_next;
                long_latch                  <= long_latch_next;
                req_seq_nr_bitmap           <= req_seq_nr_bitmap_next;
                w_map                       <= w_map_next;
                mem_addr_base               <= mem_addr_base_next;
                mem_occupied_head           <= mem_occupied_head_next;
                mem_empty_head              <= mem_empty_head_next;
                mem_addr_latch              <= mem_addr_latch_next;
                global_ack_seq_nr_base      <= global_ack_seq_nr_base_next;
                last_seq_nr                 <= last_seq_nr_next;
                bitmap_latch                <= bitmap_latch_next;
            end if;
        end if;
    end process;
    
end architecture;
