-- 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_discovery_module is
    generic (
        PREFER_MULTICAST        : boolean := FALSE;
        MAX_REMOTE_PARTICIPANTS : natural := 50
    );
    port (
        -- SYSTEM
        clk                 : in std_logic;
        reset               : in std_logic;
        time                : in TIME_TYPE;
        -- FROM RTPS HANDLER
        empty               : in std_logic;
        rd                  : out std_logic;
        data_in             : in std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_in        : in std_logic;
        -- FROM RTPS ENDPOINTS
        alive               : in std_logic_vector(0 to NUM_ENDPOINTS-1);
        -- TO RTPS ENDPOINTS
        full_rtps           : in std_logic_vector(0 to NUM_ENDPOINTS-1);
        wr_rtps             : out std_logic_vector(0 to NUM_ENDPOINTS-1);
        data_out_rtps       : out std_logic_vector(WORD_WIDTH-1 downto 0);  -- one-to-many (Multicast) Connection
        last_word_out_rtps  : out std_logic;                                -- one-to-many (Multicast) Connection
        -- 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
    );
end entity;

architecture arch of rtps_discovery_module is
    
    --*****CONSTANT DECLARATION*****
    -- Max Serialized Payload Size in a UDP Stream (Bytes) [MAX_PAYLOAD(65536) - IPv4_HEADER(20) - UDP_HEADER(8) - RTPS_HEADER(20) - DATA_HEADER(24)]
    constant UDP_MAX_SIZE_SERIALIZED    : natural := 65464;
    -- Highest Sequence Number of Publisher Data
    constant PUB_SEQUENCENUMBER         : SEQUENCENUMBER_TYPE := to_double_word(to_unsigned(NUM_WRITERS, 64));
    -- Highest Sequence Number of Subscriber Data
    constant SUB_SEQUENCENUMBER         : SEQUENCENUMBER_TYPE := to_double_word(to_unsigned(NUM_READERS, 64));
    -- Heartbeat/Liveliness Assertion Period
    constant HEARTBEAT_PERIOD           : DURATION_TYPE := work.rtps_package.min(MIN_ENDPOINT_LEASE_DURATION, PARTICIPANT_HEARTBEAT_PERIOD) - DURATION_DELTA;
    
    -- *PARTICIPANT MEMORY*
    -- 4-Byte Word Size of a Participant Entry in Memory
    constant PARTICIPANT_FRAME_SIZE         : natural := 25;
    -- Memory Size in 4-Byte Words
    constant PARTICIPANT_MEMORY_SIZE        : natural := MAX_REMOTE_PARTICIPANTS * PARTICIPANT_FRAME_SIZE;
    -- Memory Address Width
    constant PARTICIPANT_MEMORY_ADDR_WIDTH  : natural := log2c(PARTICIPANT_MEMORY_SIZE);
    -- Highest Memory Address
    constant PARTICIPANT_MEMORY_MAX_ADDRESS : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PARTICIPANT_MEMORY_SIZE-1, PARTICIPANT_MEMORY_ADDR_WIDTH);
    -- Highest participant Frame Address
    constant MAX_PARTICIPANT_ADDRESS        : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := PARTICIPANT_MEMORY_MAX_ADDRESS - PARTICIPANT_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Participant Data Frame
    constant FIRST_PARTICIPANT_ADDRESS      : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *PARTICIPANT MEMORY FRAME FIELD FLAGS*
    -- Flags mapping to the respective Participant Memory Frame Fields
    constant PMF_FLAG_WIDTH                 : natural := 13;
    constant PMF_GUIDPREFIX_FLAG            : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (0 => '1', others => '0');
    constant PMF_META_IPV4_ADDR_FLAG        : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (1 => '1', others => '0');
    constant PMF_DEFAULT_IPV4_ADDR_FLAG     : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (2 => '1', others => '0');
    constant PMF_UDP_PORT_FLAG              : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (3 => '1', others => '0');
    constant PMF_SPDP_SEQ_NR_FLAG           : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (4 => '1', others => '0');
    constant PMF_LEASE_DURATION_FLAG        : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (5 => '1', others => '0');
    constant PMF_LEASE_DEADLINE_FLAG        : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (6 => '1', others => '0');
    constant PMF_EXTRA_FLAGS_FLAG           : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (7 => '1', others => '0');
    constant PMF_ACKNACK_RES_TIME_FLAG      : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (8 => '1', others => '0');
    constant PMF_HEARTBEAT_RES_TIME_FLAG    : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (9 => '1', others => '0');
    constant PMF_PUB_SEQ_NR_FLAG            : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (10 => '1', others => '0');
    constant PMF_SUB_SEQ_NR_FLAG            : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (11 => '1', others => '0');
    constant PMF_MES_SEQ_NR_FLAG            : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (12 => '1', others => '0');
    
    -- *PARTICIPANT MEMORY FRAME FIELD OFFSETS*
    constant PMF_GUIDPREFIX_OFFSET          : natural := 0;
    constant PMF_META_IPV4_ADDR_OFFSET      : natural := 3;
    constant PMF_DEFAULT_IPV4_ADDR_OFFSET   : natural := 4;
    constant PMF_UDP_PORT_OFFSET            : natural := 5;
    constant PMF_SPDP_SEQ_NR_OFFSET         : natural := 6;
    constant PMF_LEASE_DURATION_OFFSET      : natural := 8;
    constant PMF_LEASE_DEADLINE_OFFSET      : natural := 10;
    constant PMF_EXTRA_FLAGS_OFFSET         : natural := 12;
    constant PMF_ACKNACK_RES_TIME_OFFSET    : natural := 13;
    constant PMF_HEARTBEAT_RES_TIME_OFFSET  : natural := 15;
    constant PMF_PUB_SEQ_NR_OFFSET          : natural := 17;
    constant PMF_SUB_SEQ_NR_OFFSET          : natural := 19;
    constant PMF_MES_SEQ_NR_OFFSET          : natural := 21;
    constant PMF_NEXT_ADDR_OFFSET           : natural := 23;
    constant PMF_PREV_ADDR_OFFSET           : natural := 24;
    
    -- *EXTRA FLAGS*
    -- Width of extra_flags signal
    constant EF_FLAG_WIDTH  : natural := 3;
    -- Signifies that the Message Data (Liveliness) should be sent
    constant EF_MES_DATA_FLAG              : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (0 => '1', others => '0');
    -- Signifies that the Subscriber Data should be sent
    constant EF_SUB_DATA_FLAG              : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (1 => '1', others => '0');
    -- Signifies that the Publisher Data should be sent
    constant EF_PUB_DATA_FLAG              : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (2 => '1', others => '0');
    
    -- *RECV FLAGS*
    -- Width of the received array
    constant RCVD_FLAG_WIDTH                    : natural := 9;
    -- Signifies that the DOMAIN_TAG was received
    constant RCVD_DOMAIN_TAG_FLAG               : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (0 => '1', others => '0');
    -- Signifies that the DURABILITY QoS was received
    constant RCVD_DURABILITY_QOS_FLAG           : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (1 => '1', others => '0');
    -- Signifies that the PRESENTATION QoS was received
    constant RCVD_PRESENTATION_QOS_FLAG         : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (2 => '1', others => '0');
    -- Signifies that the DEADLINE QoS was received
    constant RCVD_DEADLINE_QOS_FLAG             : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (3 => '1', others => '0');
    -- Signifies that the LATENCY_BUDGET QoS was received
    constant RCVD_LATENCY_BUDGET_QOS_FLAG       : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (4 => '1', others => '0');
    -- Signifies that the OWNERSHIP QoS was received
    constant RCVD_OWNERSHIP_QOS_FLAG            : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (5 => '1', others => '0');
    -- Signifies that the LIVELINESS QoS was received
    constant RCVD_LIVELINESS_QOS_FLAG           : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (6 => '1', others => '0');
    -- Signifies that the RELIABILITY QoS was received
    constant RCVD_RELIABILITY_QOS_FLAG          : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (7 => '1', others => '0');
    -- Signifies that the DESTINATION_ORDER QoS was received
    constant RCVD_DESTINATION_ORDER_QOS_FLAG    : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (8 => '1', others => '0');
    
    --*****TYPE DECLARATION*****
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID, 
        CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, FIND_NEXT_VALID_IN_BITMAP, 
        PROCESS_PL, CHECK_DEFAULT, SELECT_LOCATOR, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, 
        LATCH_LIFESPAN_DURATION, RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, 
        MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, CHECK_STATUS_INFO, 
        PARTICIPANT_MATCH_STAGE, INFORM_ENDPOINTS_MATCH, INFORM_ENDPOINTS_UNMATCH, INFORM_ENDPOINTS_PARTICIPANT_UNMATCH, PARTICIPANT_STALE_CHECK, 
        PROCESS_HEARTBEAT, PROCESS_HEARTBEAT_SEQUENCE_NUMBERS, SEND_ACKNACK, SEND_HEARTBEAT, PROCESS_ACKNACK, 
        PROCESS_ACKNACK_SEQUENCE_NUMBERS, FIND_PARTICIPANT_DEST, SEND_HEADER, SEND_PARTICIPANT_ANNOUNCEMENT, SEND_PUB_DATA, SEND_SUB_DATA, 
        SEND_MES_MAN_LIVE, SEND_MES_GAP, SEND_MES_AUTO_LIVE, LIVELINESS_UPDATE, SKIP_PARAMETER, SKIP_PACKET);
    -- Memory FSM states. Explained below in detail
    type MEM_STAGE_TYPE is (IDLE, SEARCH_PARTICIPANT, GET_NEXT_PARTICIPANT, GET_PARTICIPANT_DATA, INSERT_PARTICIPANT, UPDATE_PARTICIPANT, REMOVE_PARTICIPANT, RESET_MEMORY);
    -- Memory FSM Opcodes
    -- OPCODE                   DESCRIPTION
    -- SEARCH_PARTICIPANT       Search memory for Participant Entry with GUID Prefix equal to "guid" signal. 
    --                          Set "participant_data.addr" to Base Address of found Participant Entry or PARTICIPANT_MEMORY_MAX_ADDRESS if nothing found.
    --                          "participant_data" contains memory Participant Data according to "mem_r.field_flags".
    -- INSERT_PARTICIPANT       Write Participant Data to next avialable empty slot.
    -- UPDATE_PARTICIPANT       Update the Participant Data of the Participant Entry pointed by "participant_data.addr" according to the "mem_r.field_flags" flags.
    -- REMOVE_PARTICIPANT       Remove the Participant Entry pointed by "participant_data.addr".
    --                          "participant_data.addr" is set to the next Endpoint (or ENDPOINT_MEMORY_MAX_ADDRESS if no next Endpoint exists)
    -- GET_NEXT_PARTICIPANT     Get Participant Data of next participant (from the one pointed by "participant_data.addr") according to "mem_r.field_flags".
    --                          "participant_data.addr" is set to the Address of the Participant, or PARTICIPANT_MEMORY_MAX_ADDRESS if no Participant in Memory
    -- GET_PATICIPANT           Get Participant Data of participant pointed by "mem_r.addr" according to "mem_r.field_flags". 
    --                          Already fetched Data of the same Participant is not modified
    type MEM_OPCODE_TYPE is (NOP, SEARCH_PARTICIPANT, INSERT_PARTICIPANT, UPDATE_PARTICIPANT, GET_NEXT_PARTICIPANT, REMOVE_PARTICIPANT, GET_PARTICIPANT);
    -- RTPS Data Submessage Content:
    --  * PDP       Simple Participant Discovery Protocol Data
    --  * EDP       Simple Endpoint Discovery Protocol Data
    --  * MESSAGE   Participant Message Data
    type MESSAGE_TYPE_TYPE is (NONE, PDP, EDP, MESSAGE);
    -- String Content
    type STRING_CONTENT_TYPE is (TOPIC_NAME_TYPE, TYPE_NAME_TYPE, DOMAIN_TAG_TYPE);
    -- Record of all Participant Data stored in memory
    type PARTICIPANT_DATA_TYPE is record
        addr                : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0);
        guid_prefix         : GUIDPREFIX_TYPE;
        meta_addr           : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
        def_addr            : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
        meta_port           : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
        def_port            : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
        extra_flags         : std_logic_vector(EF_FLAG_WIDTH-1 downto 0);
        lease_duration      : DURATION_TYPE;
        lease_deadline      : TIME_TYPE;
        heartbeat_res_time  : TIME_TYPE;
        acknack_res_time    : TIME_TYPE;
        spdp_seq_nr         : SEQUENCENUMBER_TYPE;
        pub_seq_nr          : SEQUENCENUMBER_TYPE;
        sub_seq_nr          : SEQUENCENUMBER_TYPE;
        mes_seq_nr          : SEQUENCENUMBER_TYPE;
        field_flags         : std_logic_vector(0 to PMF_FLAG_WIDTH-1);
    end record;
    -- Zero initialized Participant Data
    constant ZERO_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := (
        addr                => PARTICIPANT_MEMORY_MAX_ADDRESS,
        guid_prefix         => GUIDPREFIX_UNKNOWN,
        meta_addr           => IPv4_ADDRESS_INVALID,
        def_addr            => IPv4_ADDRESS_INVALID,
        meta_port           => UDP_PORT_INVALID,
        def_port            => UDP_PORT_INVALID,
        extra_flags         => (others => '0'),
        lease_duration      => DURATION_ZERO,
        lease_deadline      => TIME_INVALID,
        heartbeat_res_time  => TIME_INVALID,
        acknack_res_time    => TIME_INVALID,
        spdp_seq_nr         => SEQUENCENUMBER_UNKNOWN,
        pub_seq_nr          => SEQUENCENUMBER_UNKNOWN,
        sub_seq_nr          => SEQUENCENUMBER_UNKNOWN,
        mes_seq_nr          => SEQUENCENUMBER_UNKNOWN,
        field_flags         => (others => '0')
    );
    
    
    --*****SIGNAL DECLARATION*****
    -- 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;
    -- Intermediate input read signal. (Read from output port not allowed)
    signal rd_sig : std_logic;
    -- Signal used to reset the word counter
    signal reset_read_cnt : std_logic;
    -- Word (4-Byte) counter (Counts words read from input fifo)
    signal read_cnt : unsigned(SUBMESSAGE_LENGTH_WIDTH-3 downto 0);
    -- RTPS Submessage ID Latch
    signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0);
    -- RTPS Submessage Flags Latch
    signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0);
    -- UDPv4 Source Port Latch
    signal src_port, src_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- IPv4 Source Address Latch
    signal src_addr, src_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- Source Entity ID Latch
    signal src_entityid, src_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
    -- Destination Entity ID Latch
    signal dest_entityid, dest_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
    -- Source GUID Latch
    signal guid, guid_next : GUID_TYPE;
    -- RTPS DATA Submessage Sequence Number Latch
    signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE;
    -- Word aligned End of Parameter
    signal parameter_end, parameter_end_next : unsigned(PARAMETER_LENGTH_WIDTH-1 downto 0);
    -- RTPS DATA Submessage Content Type
    signal message_type, message_type_next : MESSAGE_TYPE_TYPE;
    -- Data in represented in Big Endian
    signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0);
    -- Byte Length of string
    signal string_length, string_length_next : unsigned(WORD_WIDTH-1 downto 0);
    -- Counter of compared string words (4-Byte)
    signal compare_length, compare_length_next : unsigned(WORD_WIDTH-3 downto 0);
    -- Bitmask of local Endpoint Matches
    signal endpoint_mask, endpoint_mask_next : std_logic_vector(0 to NUM_ENDPOINTS-1);
    -- Signifies if the source of the Participant Data is compatible with our Participant
    signal participant_match, participant_match_next : std_logic;
    -- Signifies if the Packet is comming from a Subscriber Endpoint
    signal is_subscriber, is_subscriber_next : std_logic;
    -- Signifies that the read Locator is a Metatraffic Locator
    signal is_meta_addr, is_meta_addr_next : std_logic;
    -- Signifies that the read Locator is a Multicast Locator
    signal is_multicast_addr, is_multicast_addr_next : std_logic;
    -- General Purpose counter
    signal cnt, cnt_next : natural range 0 to 23;
    -- Counter used to index STRING_WORD_ARRAY_TYPEs
    signal string_cnt, string_cnt_next : natural range 0 to STRING_WORD_ARRAY_TYPE'length-1;
    -- NOTE: In order to avoid synthesizing indexing for the full range of the OUTPUT_DATA_TYPE, we explicitly use counters constrained to the actual size
    -- Counter used to index the Participant Data
    signal participant_data_cnt, participant_data_cnt_next : natural range 0 to LOCAL_PARTICIPANT_DATA.length-1;
    -- Counter used to index the Publisher Data
    signal publisher_data_cnt, publisher_data_cnt_next : natural range 0 to work.math_pkg.max(WRITER_ENDPOINT_DATA.length-1, 0);
    -- Counter used to index the Subscriber Data
    signal subscriber_data_cnt, subscriber_data_cnt_next : natural range 0 to work.math_pkg.max(READER_ENDPOINT_DATA.length-1, 0);
    -- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data)
    signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE;
    -- 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;
    -- Intermediate write enable signal.
    signal wr_sig : std_logic;
    -- Signifies if a Stale Endpoint Check is in progress
    signal stale_check, stale_check_next : std_logic;
    -- Time of next Stale Endpoint Check
    signal check_time, check_time_next : TIME_TYPE;
    -- Toggle latching the "last_word_in" signal until reset
    signal last_word_in_latch, last_word_in_latch_next : std_logic;
    -- Signal containing the HEARTBEAT/ACKNACK count of all built-in Endpoints
    signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0);
    -- Toggle set when at least one Endpoint has asserted the "alive" signal, until reset
    signal endpoint_alive : std_logic;
    -- Resets the "endpoint_alive" signal
    signal reset_endpoint_alive : std_logic;
    -- NOTE: The "auto_live_seq_nr" is always higher than "man_live_seq_nr"
    -- Contains the highest Sequence Number for automatic liveliness updates
    signal auto_live_seq_nr, auto_live_seq_nr_next : SEQUENCENUMBER_TYPE;
    -- Contains the highest Sequence Number for manual by participant liveliness updates
    signal man_live_seq_nr, man_live_seq_nr_next : SEQUENCENUMBER_TYPE;
    -- Points to the first Sequence Number after "man_live_seq_nr" (Signifies the start of the GAP between "man_live_seq_nr" and "auto_live_seq_nr")
    signal live_gap_start, live_gap_start_next : SEQUENCENUMBER_TYPE;
    -- Points to the first Sequence Number before "auto_live_seq_nr" (Signifies the end of the GAP between "man_live_seq_nr" and "auto_live_seq_nr")
    signal live_gap_end, live_gap_end_next : SEQUENCENUMBER_TYPE;
    -- 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;
    -- Signal used to iterate through Bitmaps
    signal bitmap_pos, bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1;
    -- Participant Announcement Timeout Time
    signal announcement_time, announcement_time_next : TIME_TYPE;
    -- Heartbeat/Liveliness Assertion Timeout Time
    signal heartbeat_time, heartbeat_time_next : TIME_TYPE;
    -- Signifies if we are currently in a Liveliness Assertion
    signal is_live_assert, is_live_assert_next : std_logic;
    -- Signifies the content of the string read from input
    signal string_content, string_content_next : STRING_CONTENT_TYPE;
    -- Reader Flags of remote Reader
    signal reader_flags, reader_flags_next : std_logic_vector(READER_FLAGS_WIDTH-1 downto 0);
    -- Endpoint Multicast Locator IPv4 Address Latch
    signal def_mc_addr, def_mc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- Metatraffic Multicast Locator IPv4 Address Latch
    signal meta_mc_addr, meta_mc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- Endpoint Multicast UDPv4 Port Latch
    signal def_mc_port, def_mc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- Metatraffic Multicast UDPv4 Port Latch
    signal meta_mc_port, meta_mc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- Endpoint Unicast Locator IPv4 Address Latch
    signal def_uc_addr, def_uc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- Metatraffic Unicast Locator IPv4 Address Latch
    signal meta_uc_addr, meta_uc_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
    -- Endpoint Unicast UDPv4 Port Latch
    signal def_uc_port, def_uc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- Metatraffic Unicast UDPv4 Port Latch
    signal meta_uc_port, meta_uc_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
    -- Participant Lease Duration Latch
    signal lease_duration, lease_duration_next : DURATION_TYPE;
    -- Endpoint Lifespan Duration Latch
    signal lifespan_duration, lifespan_duration_next : DURATION_TYPE;
    -- General Purpose Long latch
    signal long_latch, long_latch_next  : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    -- Contains flags that signify which PIDs where received. This is done in order to use the default value for
    -- not received elements.
    signal rcvd, rcvd_next : std_logic_vector(RCVD_FLAG_WIDTH-1 downto 0);
    -- Signal used to pass data to the memory process
    signal mem_r : PARTICIPANT_DATA_TYPE;
    -- Test signal used for testbench synchronisation
    signal idle_sig : std_logic;
    -- Signifies that we received an Unregister/Dispose Status Info
    signal ud_status, ud_status_next : std_logic;
    -- Internal Signal for data_out
    signal data_out_sig :  std_logic_vector(WORD_WIDTH-1 downto 0);
    -- Internal Signal for last_word_out
    signal last_word_out_sig : std_logic;
    -- Test signal used in testbenches for removal check
    signal empty_head_sig : natural;
    
    -- *MEMORY PROCESS*
    -- Memory FSM State
    signal mem_stage, mem_stage_next : MEM_STAGE_TYPE;
    -- General Purpose Counter (Memory FSM)
    signal mem_cnt, mem_cnt_next : natural range 0 to 46;
    -- Signals the start of a Memory Operation (Should be pulled high only when mem_op_done is high)
    signal mem_op_start : std_logic;
    -- Signals the end of a Memory Operation
    signal mem_op_done : std_logic;
    -- Opcode of the Memory Operation (Valid only when mem_op_start is high)
    signal mem_opcode : MEM_OPCODE_TYPE;
    -- Base Memory Address of current Participant Frame
    signal mem_addr_base, mem_addr_base_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Memory Address Latch
    signal mem_addr_latch, mem_addr_latch_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Head of Empty Participant List
    signal mem_empty_head, mem_empty_head_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Head of Occupied Participant List
    signal mem_occupied_head, mem_occupied_head_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Latch for the Participant Data stored in memory
    signal participant_data, participant_data_next : PARTICIPANT_DATA_TYPE;
    -- Latch for Participant Data from main FSM
    signal participant_latch_data, participant_latch_data_next : PARTICIPANT_DATA_TYPE;
    
    
    -- *MEMORY CONTROL CONNECTION SIGNALS*
    signal mem_addr : unsigned(PARTICIPANT_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 mem_abort_read : std_logic;
    
    --*****ALIAS DEFINATION*****
    -- ENDPOINT FRAME HEADER
    alias header_opcode             : std_logic_vector(7 downto 0) is data_in(31 downto 24);
    alias header_flags              : std_logic_vector(7 downto 0) is data_in(23 downto 16);
    alias header_udp_port           : std_logic_vector(15 downto 0) is data_in(15 downto 0);
    -- RTPS PARAMETER LIST HEADER
    alias parameter_id              : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) is data_in(WORD_WIDTH-1 downto WORD_WIDTH-PARAMETER_ID_WIDTH);
    alias parameter_length          : std_logic_vector(PARAMETER_LENGTH_WIDTH-1 downto 0) is data_in(PARAMETER_LENGTH_WIDTH-1 downto 0);
    -- RTPS DATA PAYLOAD HEADER
    alias representation_id         : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(WORD_WIDTH-1 downto WORD_WIDTH-PAYLOAD_REPRESENTATION_ID_WIDTH);
    alias representation_options    : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(PAYLOAD_REPRESENTATION_OPTIONS_WIDTH-1 downto 0);
    -- RTPS SUBMESSAGE FLAGS
    alias endian_flag               : std_logic is flags(0);
    alias endian_flag_next          : std_logic is flags_next(0);
    alias qos_flag                  : std_logic is flags(1);
    alias qos_flag_next             : std_logic is flags_next(1);
    alias data_flag                 : std_logic is flags(2);
    alias key_flag                  : std_logic is flags(3);
    alias final_flag                : std_logic is flags(1);
    alias non_std_flag              : std_logic is flags(4);
    -- HEARTBEAT
    alias first_seq_nr              : SEQUENCENUMBER_TYPE is sn_latch_1;
    alias first_seq_nr_next         : SEQUENCENUMBER_TYPE is sn_latch_1_next;
    alias last_seq_nr               : SEQUENCENUMBER_TYPE is sn_latch_2;
    alias last_seq_nr_next          : SEQUENCENUMBER_TYPE is sn_latch_2_next;
    -- GAP
    alias gap_start                 : SEQUENCENUMBER_TYPE is sn_latch_1;
    alias gap_start_next            : SEQUENCENUMBER_TYPE is sn_latch_1_next;
    alias gap_list_base             : SEQUENCENUMBER_TYPE is sn_latch_2;
    alias gap_list_base_next        : SEQUENCENUMBER_TYPE is sn_latch_2_next;
    alias gap_list_end              : SEQUENCENUMBER_TYPE is sn_latch_3;
    alias gap_list_end_next         : SEQUENCENUMBER_TYPE is sn_latch_3_next;
    
    -- TARGET LOCATOR
    alias def_addr                  : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is def_uc_addr;
    alias def_addr_next             : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is def_uc_addr_next;
    alias meta_addr                 : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is meta_uc_addr;
    alias meta_addr_next            : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) is meta_uc_addr_next;
    alias def_port                  : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is def_uc_port;
    alias def_port_next             : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is def_uc_port_next;
    alias meta_port                 : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is meta_uc_port;
    alias meta_port_next            : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) is meta_uc_port_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;
    
    -- 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;
    
    procedure assert_sn is
    begin
        if (message_type = EDP and is_subscriber = '0') then
            assert stable(clk, check_mask(participant_data.field_flags, PMF_PUB_SEQ_NR_FLAG)) severity FAILURE;
        elsif (message_type = EDP and is_subscriber = '1') then
            assert stable(clk, check_mask(participant_data.field_flags, PMF_SUB_SEQ_NR_FLAG)) severity FAILURE;
        elsif (message_type = MESSAGE) then
            assert stable(clk, check_mask(participant_data.field_flags, PMF_MES_SEQ_NR_FLAG)) severity FAILURE;
        elsif (message_type = PDP) then
            assert stable(clk, check_mask(participant_data.field_flags, PMF_SPDP_SEQ_NR_FLAG)) severity FAILURE;
        else
            assert FALSE report "assert_sn: Unknown Message Type" severity FAILURE;
        end if;
    end procedure;
begin
    
    --*****COMPONENT INSTANTIATION*****
    mem_ctrl_inst : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => PARTICIPANT_MEMORY_ADDR_WIDTH,
            DATA_WIDTH          => WORD_WIDTH,
            MEMORY_DEPTH        => PARTICIPANT_MEMORY_SIZE,
            MAX_BURST_LENGTH    => PARTICIPANT_FRAME_SIZE
        )
        port map (
            clk         => clk,
            reset       => reset or mem_abort_read,
            addr        => std_logic_vector(mem_addr),
            read        => mem_read,
            ready_in    => mem_ready_in,
            valid_in    => mem_valid_in,
            data_in     => mem_write_data,
            ready_out   => mem_ready_out,
            valid_out   => mem_valid_out,
            data_out    => mem_read_data
        );
    
    
    rd  <= rd_sig;
    
    -- Big Endian Representation
    data_in_swapped <= endian_swap(endian_flag, data_in);
    
    -- This process is responsible for toggling the "endpoint_alive" signal
    -- The signal is set high when at least one bit of the "alive" signal is high for at least one clock cycle,
    -- and is set low when "reset_endpoint_alive" signal is high for at least one clock cycle.
    endpoint_alive_prc: process(all)
    begin
        if rising_edge(clk) then
            -- Reset Endpoint Alive Signal
            if (reset = '1' or reset_endpoint_alive = '1') then
                endpoint_alive  <= '0';
            -- Set Endpoint Alive Signal, if at least one endpoint asserts liveliness
            elsif (alive /= (alive'range => '0')) then
                endpoint_alive  <= '1';
            end if;
        end if;
    end process;
    
    -- This process connects the Intermediate Output Signals to the actual output FIFOs
    output_prc : process(all)
    begin
        wr_rtps <= (others => '0');
        wr_ro   <= '0';
        case (stage) is
            when INFORM_ENDPOINTS_MATCH =>
                if (wr_sig = '1') then
                    wr_rtps <= endpoint_mask;
                end if;
            when INFORM_ENDPOINTS_UNMATCH =>
                if (wr_sig = '1') then
                    wr_rtps <= not endpoint_mask;
                end if;
            when INFORM_ENDPOINTS_PARTICIPANT_UNMATCH =>
                if (wr_sig = '1') then
                    wr_rtps <= (others => '1');
                end if;
            when LIVELINESS_UPDATE =>
                if (wr_sig = '1') then
                    wr_rtps <= endpoint_mask;
                end if;
            when others =>
                wr_ro   <= wr_sig;
        end case;
    end process;
    
    data_out_rtps       <= data_out_sig;
    data_out_ro         <= data_out_sig;
    last_word_out_rtps  <= last_word_out_sig;
    last_word_out_ro    <= last_word_out_sig;
    
    -- Main State Machine
    -- STATE                                DESCRIPTION
    -- IDLE                                 Idle state. Initiates Participant Announcements, Heartbeat/Liveliness Assertions, Stale Participant Entry Checks ,and Packet Processing, in that priority order.
    -- PACKET_HEADER                        Read the Endpoint FIFO Packet Format Header (RTPS Submessage ID/Opcode, Submessage Flags, Source UDPv4 Port)
    -- PACKET_SRC_ADDR                      Read Source IPv4 Address    
    -- PACKET_SRC_GUIDPREFIX                Read Source GUID Prefix
    -- PACKET_SRC_ENTITYID                  Read Source Entity ID
    -- PACKET_DEST_ENTITYID                 Read Destination Entity ID. Determine content of Packet (Participant Data, Publisher/Subscriber/Message Data/GAP/HEARTBEAT/ACKNACK) and initiate processing.
    -- CHECK_SRC_ENTITYID                   Read Source Entity ID. Determine content of Packet (Participant Data, Publisher/Subscriber/Message Data/GAP/HEARTBEAT/ACKNACK) and initiate processing.
    --                                      This state is taken if the Packet content could not be determined in the PACKET_DEST_ENTITYID state.
    -- LATCH_SEQ_NR                         Store RTPS Data Submessage Sequence Number
    -- PROCESS_DATA                         Parse RTPS Data Submessage Payload Header. Determine content of Data (Parameter List, Participant Message CDR Data) or if Data Message contains in-line QoS and initiate respective handling.
    -- PROCESS_MESSAGE_SEQUENCE_NUMBERS     Process ParticipantMessageData Sequence Numbers. Update Sequence Numbers if necessary and initiate Message processing
    -- PROCESS_MESSAGE                      Parse Participant Data Message and extract liveliness assertion of remote Participant
    -- LIVELINESS_UPDATE                    Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints
    -- PROCESS_GAP                          Parse RTPS GAP Submessage
    -- PROCESS_GAP_SEQUENCE_NUMBERS         Process GAP Sequence Numbers. Update stored Sequence Numbers if necessary
    -- FIND_NEXT_VALID_IN_BITMAP            Iterate through Bitmap and find the next valid Sequence Number.
    -- PROCESS_HEARTBEAT                    Parse RTPS HEARTBEAT Submessage
    -- PROCESS_HEARTBEAT_SEQUENCE_NUMBERS   Process HEARTBEAT Sequence Numbers. Update stored Sequence Numbers if necessary. Set HEARTBEAT response timeout accordingly.
    -- PROCESS_ACKNACK                      Parse RTPS ACKNACK Submessage
    -- PROCESS_ACKNACK_SEQUENCE_NUMBERS     Process ACKNACK Sequence Numbers. Update stored Sequence Numbers if necessary. Set ACKNACK response timeout accordingly.
    -- FIND_PARTICIPANT_DEST                Find next stored Participant to send Participant Announcement and Liveliness Assertion to.
    -- PARTICIPANT_STALE_CHECK              Check memory for remote stale Participant Entries (Lease Duration Exceeded, HEARTBEAT/ACKNACK timeout passed) and take appropriate action.
    -- PROCESS_PL                           Parse RTPS Parameter List
    -- CHECK_DEFAULT                        Match local endpoints against non-received QoS (default values) of remote
    -- SELECT_LOCATOR                       Select the appropriate Locator (in respect to configured defaults and generics)
    -- LATCH_STRING_LENGTH                  Store String Length
    -- COMPARE_STRING                       Compare string to constants depending on string contents.
    -- MATCH_GUID                           Compare GUID Prefix to source GUID Prefix of Packet
    -- MATCH_DOMAIN_ID                      Compare Domain ID
    -- MATCH_PROTOCOL_VERSION               Compare RTPS Protocol Version
    -- LATCH_LOCATOR                        Store Locator. NOTE: Only Metatraffic and User Locators are differentiated. Unicast and Multicast are overwriting each other and the last parsed is the one to be used.
    -- LATCH_EXPECTS_INLINE_QOS             Store 'expectsInlineQoS' Flag
    -- LATCH_LEASE_DURATION                 Store remote Participant Lease Duration
    -- LATCH_LIFESPAN_DURATION              Store remote Endpoint Lifespan Duration
    -- CHECK_REMOTE_BUILTIN_ENDPOINTS       Check if the remote Participant has the required built-in Endpoints
    -- RXO_DURABILITY                       Check Compatibility of Durability QoS
    -- RXO_DEADLINE                         Check Compatibility of Deadline QoS
    -- RXO_LIVELINESS                       Check Compatibility of Liveliness QoS
    -- RXO_LEASE_DURATION                   Check Compatibility of Liveliness QoS
    -- RXO_RELIABILITY                      Check Compatibility of Reliability QoS
    -- RXO_DESTINATION_ORDER                Check Compatibility of Destination Order QoS
    -- RXO_OWNERSHIP                        Check Compatibility of Ownership QoS
    -- RXO_PRESENTATION                     Check Compatibility of Presentation QoS
    -- RXO_PARTITION                        Check Compatibility of Partition QoS
    -- RXO_LATENCY_BUDGET                   Check Compatibility of Latency Budget QoS
    -- CHECK_MAX_SIZE_SERIALIZED            Check if Publishers Max sent Payload Size is Compatible
    -- CHECK_STATUS_INFO                    Check inline QoS Status Info for Unregister/Dispose Status
    -- PARTICIPANT_MATCH_STAGE              Add compatible remote and remove incompatible remote Participants to and from memory. Update stored Sequence Numbers respectively (also for EDP)
    -- INFORM_ENDPOINTS_MATCH               Propagate local Endpoint matches
    -- INFORM_ENDPOINTS_UNMATCH             Propagate local Endpoint unmatches
    -- INFORM_ENDPOINTS_PARTICIPANT_UNMATCH Propagate remote Participant unmatch
    -- SEND_HEADER                          Send Output Data Header and RTPS Message Header
    -- SEND_PARTICIPANT_ANNOUNCEMENT        Send Participant Announcement Data Submessage
    -- SEND_ACKNACK                         Send ACKNACK Submessages
    -- SEND_HEARTBEAT                       Send HEARTBEAT Submessages
    -- SEND_PUB_DATA                        Send Endpoint Discovery Publication Data Submessage
    -- SEND_SUB_DATA                        Send Endpoint Discovery Subscriber Data Submessage
    -- SEND_MES_MAN_LIVE                    Send Participant Message Automatic Liveliness Assertion Data Submessage
    -- SEND_MES_GAP                         Send Participant Message GAP Submessages
    -- SEND_MES_AUTO_LIVE                   Send Participant Message Manual-by-Participant Liveliness Assertion Data Submessage
    -- SKIP_PARAMETER                       Skip rest of Parameter
    -- SKIP_PACKET                          Skip rest of Packet
    parse_prc: process(all)
        variable tmp_endpoint_mask      : std_logic_vector(0 to NUM_ENDPOINTS-1);
        variable rd_guard               : std_logic;
        variable tmp_default_qos_match  : DEFAULT_QOS_MATCH_TYPE;
        variable tmp_dw                 : DOUBLE_WORD_ARRAY;
        variable mem_seq_nr             : SEQUENCENUMBER_TYPE;
        -- 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);
    begin
        --DEFAULT Registered
        stage_next                      <= stage;
        return_stage_next               <= return_stage;
        opcode_next                     <= opcode;
        flags_next                      <= flags;
        src_port_next                   <= src_port;
        src_addr_next                   <= src_addr;
        guid_next                       <= guid;
        src_entityid_next               <= src_entityid;
        dest_entityid_next              <= dest_entityid;
        parameter_end_next              <= parameter_end;
        message_type_next               <= message_type;
        string_length_next              <= string_length;
        compare_length_next             <= compare_length;
        endpoint_mask_next              <= endpoint_mask;
        participant_match_next          <= participant_match;
        is_subscriber_next              <= is_subscriber;
        lease_duration_next             <= lease_duration;
        lifespan_duration_next          <= lifespan_duration;
        def_mc_addr_next                <= def_mc_addr;
        def_uc_addr_next                <= def_uc_addr;
        meta_mc_addr_next               <= meta_mc_addr;
        meta_uc_addr_next               <= meta_uc_addr;
        def_mc_port_next                <= def_mc_port;
        def_uc_port_next                <= def_uc_port;
        meta_mc_port_next               <= meta_mc_port;
        meta_uc_port_next               <= meta_uc_port;
        is_meta_addr_next               <= is_meta_addr;
        is_multicast_addr_next          <= is_multicast_addr;
        cnt_next                        <= cnt;
        reader_flags_next               <= reader_flags;
        stale_check_next                <= stale_check;
        sn_latch_1_next                 <= sn_latch_1;
        sn_latch_2_next                 <= sn_latch_2;
        sn_latch_3_next                 <= sn_latch_3;
        auto_live_seq_nr_next           <= auto_live_seq_nr;
        man_live_seq_nr_next            <= man_live_seq_nr;
        live_gap_start_next             <= live_gap_start;
        live_gap_end_next               <= live_gap_end;
        announcement_time_next          <= announcement_time;
        heartbeat_time_next             <= heartbeat_time;
        is_live_assert_next             <= is_live_assert;
        string_content_next             <= string_content;
        string_cnt_next                 <= string_cnt;
        participant_data_cnt_next       <= participant_data_cnt;
        publisher_data_cnt_next         <= publisher_data_cnt;
        subscriber_data_cnt_next        <= subscriber_data_cnt;
        seq_nr_next                     <= seq_nr;
        next_seq_nr_next                <= next_seq_nr;
        last_word_in_latch_next         <= last_word_in_latch;
        count_next                      <= count;
        long_latch_next                 <= long_latch;
        rcvd_next                       <= rcvd;
        check_time_next                 <= check_time;
        cnt2_next                       <= cnt2;
        bitmap_cnt_next                 <= bitmap_cnt;
        bitmap_latch_next               <= bitmap_latch;
        bitmap_pos_next                 <= bitmap_pos;
        ud_status_next                  <= ud_status;
        -- DEFAULT Unregistered
        mem_r                           <= ZERO_PARTICIPANT_DATA;
        rd_sig                          <= '0';
        rd_guard                        := '0';
        reset_read_cnt                  <= '0';
        wr_sig                          <= '0';
        mem_opcode                      <= NOP;
        mem_op_start                    <= '0';
        last_word_out_sig               <= '0';
        reset_endpoint_alive            <= '0';
        idle_sig                        <= '0';
        data_out_sig                    <= (others => '0');
        
        -- Last Word Latch Setter
        if (last_word_in = '1') then
            last_word_in_latch_next <= '1';
        end if;
        
        -- Set mem_seq_nr to correct sequence number
        -- NOTE: The stored Sequence Numbers are the next expected
        case (message_type) is
            -- Participant Data Sequence Number
            when PDP =>
                mem_seq_nr      := participant_data.spdp_seq_nr;
            when EDP =>
                -- Subscriber Data Sequence Number
                if (is_subscriber = '1') then
                    mem_seq_nr  := participant_data.sub_seq_nr;
                -- Publisher Data Sequence Number
                else
                    mem_seq_nr  := participant_data.pub_seq_nr;
                end if;
            -- Participant Message Data Sequence Number
            when MESSAGE =>
                mem_seq_nr      := participant_data.mes_seq_nr;
            when others =>
                mem_seq_nr      := SEQUENCENUMBER_UNKNOWN;
        end case;
        
        case(stage) is
            -- Initial/Idle State
            when IDLE =>
                idle_sig    <= '1';
                -- Participant Announcement Time Trigger
                if (time > announcement_time) then
                    announcement_time_next  <= time + PARTICIPANT_ANNOUNCEMENT_PERIOD;
                    stage_next              <= SEND_HEADER;
                    return_stage_next       <= SEND_PARTICIPANT_ANNOUNCEMENT;
                    cnt_next                <= 0;
                -- Heartbeat Time Trigger
                -- NOTE: Liveliness assertion and Heartbeat sending is done together
                elsif (time > heartbeat_time) then
                    -- Memory Operation Guard
                    if (mem_op_done = '1') then
                        -- NOTE:    The sequence number of the automatic liveliness is always higher than that of the manual liveliness
                        -- If Manual By Participant Liveliness asserted, send both manual and automatic liveliness
                        if (endpoint_alive = '1') then
                            -- Reset the endpoint alive toggle signal
                            reset_endpoint_alive    <= '1';
                            man_live_seq_nr_next    <= auto_live_seq_nr + 1;
                            auto_live_seq_nr_next   <= auto_live_seq_nr + 2;
                            -- GAP Start is always man_live_seq_nr+1
                            live_gap_start_next     <= auto_live_seq_nr + 2;
                            -- GAP End is always auto_live_seq_nr-1
                            live_gap_end_next       <= auto_live_seq_nr + 1;
                        -- Else send only automatic liveliness
                        else
                            auto_live_seq_nr_next   <= auto_live_seq_nr + 1;
                            live_gap_end_next       <= live_gap_end + 1;
                        end if;
                        heartbeat_time_next <= time + HEARTBEAT_PERIOD;
                        -- Send Heartbeat and Liveliness Assertions to all stored Participants
                        mem_op_start        <= '1';
                        mem_opcode          <= GET_PARTICIPANT;
                        mem_r.addr          <= mem_occupied_head;    
                        mem_r.field_flags   <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                        stage_next          <= FIND_PARTICIPANT_DEST;
                        -- Increment the counter for the new Heartbeat Messages
                        count_next      <= count + 1;
                        -- Mark this as liveliness assertion (Allows the "SEND_MES_AUTO_LIVE" stage to decide on return stage)
                        is_live_assert_next <= '1';
                    end if;
                -- Stale Check Timeout
                elsif (check_time <= time) then
                    -- Memory Operation Guard
                    if (mem_op_done = '1') then
                        mem_op_start        <= '1';
                        mem_opcode          <= GET_PARTICIPANT;
                        mem_r.addr          <= mem_occupied_head;
                        mem_r.field_flags   <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                        
                        stale_check_next    <= '1';
                        stage_next          <= PARTICIPANT_STALE_CHECK;
                        cnt_next            <= 2; -- EXIT CONDITION
                        
                        -- Reset Timeout
                        check_time_next <= TIME_INFINITE;
                    end if;
                -- Process Packet
                elsif (empty = '0') then
                    stage_next          <= PACKET_HEADER;
                    
                    -- Reset Latches
                    meta_mc_addr_next       <= IPv4_ADDRESS_INVALID;
                    meta_uc_addr_next       <= IPv4_ADDRESS_INVALID;
                    def_mc_addr_next        <= IPv4_ADDRESS_INVALID;
                    def_uc_addr_next        <= IPv4_ADDRESS_INVALID;
                    meta_mc_port_next       <= UDP_PORT_INVALID;
                    meta_uc_port_next       <= UDP_PORT_INVALID;
                    def_mc_port_next        <= UDP_PORT_INVALID;
                    def_uc_port_next        <= UDP_PORT_INVALID;
                    lease_duration_next     <= DEFAULT_PARTICIPANT_LEASE_DURATION;
                    lifespan_duration_next  <= DURATION_INFINITE;
                    reader_flags_next       <= (READER_EXPECTS_INLINE_QOS_FLAG => DEFAULT_EXPECTS_INLINE_QOS, READER_EXPECTS_HISTORICAL_DATA_FLAG => DEFAULT_EXPECTS_HISTORICAL_DATA_FLAG, READER_IS_BEST_EFFORT_FLAG => DEFAULT_IS_BEST_EFFORT_FLAG, others => '0');
                    rcvd_next               <= (others => '0');
                    ud_status_next          <= '0';
                    -- NOTE: We work with a "mark by default, and unmark on first missmatch" System.
                    --       This assumes that each RxO QoS parameter occur only once in the list, else the behavior is undefined.
                    participant_match_next  <= '1';
                    endpoint_mask_next      <= (others => '1');
                end if;
            when PACKET_HEADER =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard        := '1';
                    -- Latch Opcode
                    opcode_next     <= header_opcode;
                    -- Latch Flags
                    flags_next      <= header_flags;
                    -- Latch Source UDP Port
                    src_port_next   <= header_udp_port;
                    
                    stage_next      <= PACKET_SRC_ADDR;
                    -- SANITY CHECK: Skip Packet if non-standard Payload
                    if(header_opcode = SID_DATA and non_std_flag = '1') then
                        stage_next  <= SKIP_PACKET;
                    end if;
                end if;
            when PACKET_SRC_ADDR =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard        := '1';
                    -- Latch Source IP Address
                    src_addr_next   <= data_in;
                    
                    stage_next      <= PACKET_SRC_GUIDPREFIX;
                    cnt_next        <= 0;
                end if;
            when PACKET_SRC_GUIDPREFIX =>
                -- Input FIFO Guard and Memory Operation Guard
                if (empty = '0' and mem_op_done = '1') then
                    rd_guard    := '1';
                    
                    -- Latch Src GUIDPrefix
                    case (cnt) is
                        when 0 =>
                            guid_next(0)    <= data_in;
                            cnt_next        <= cnt + 1;
                        when 1 =>
                            guid_next(1)    <= data_in;
                            cnt_next        <= cnt + 1;
                        when 2 =>
                            guid_next(2)    <= data_in;
                            guid_next(3)    <= ENTITYID_PARTICIPANT;
                            
                            stage_next      <= PACKET_SRC_ENTITYID;
                        when others =>
                            null;
                    end case;
                end if;
            when PACKET_SRC_ENTITYID =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard        := '1';
                    -- Latch Source Entity ID
                    src_entityid_next   <= data_in;
                    
                    stage_next  <= PACKET_DEST_ENTITYID;
                end if;
            when PACKET_DEST_ENTITYID =>
                assert (mem_op_done = '1') severity FAILURE;
                
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- DEFAULT
                    stage_next          <= SKIP_PACKET;
                    is_subscriber_next  <= '0';
                    
                    -- *Check Destination Entity ID*
                    case (data_in) is
                        when ENTITYID_UNKNOWN =>
                            -- Wildcard Destination
                            -- Content has to be determined through Source Entity ID
                            stage_next  <= CHECK_SRC_ENTITYID;
                        when ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR =>
                            -- Only DATA relevant
                            if (opcode = SID_DATA) then
                                -- Packet Contains Participant Data
                                message_type_next       <= PDP;
                                
                                stage_next              <= LATCH_SEQ_NR;
                                cnt_next                <= 0;
                                
                                -- Start Participant Search
                                mem_op_start        <= '1';
                                mem_opcode          <= SEARCH_PARTICIPANT;
                                mem_r.field_flags   <= PMF_SPDP_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                            end if;
                        when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER =>
                            -- SANITY CHECK: Ignore if no Writers
                            -- Only ACKNACKs are relevant
                            if (NUM_WRITERS /= 0 and opcode = SID_ACKNACK) then
                                message_type_next   <= EDP;
                                is_subscriber_next  <= '1';
                                
                                stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                                cnt_next            <= 0;
                                
                                -- Start Participant Search
                                mem_op_start        <= '1';
                                mem_opcode          <= SEARCH_PARTICIPANT;
                                mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                                mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                            end if;
                        when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR =>
                            -- SANITY CHECK: Ignore if no Readers
                            if (NUM_READERS /= 0) then
                                message_type_next   <= EDP;
                                
                                
                                -- Only HEARTBEATs, GAPs and DATA are relevant
                                case (opcode) is
                                    when SID_HEARTBEAT =>
                                        stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_PUB_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_GAP =>
                                        stage_next          <= PROCESS_GAP; -- GAP Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_DATA =>
                                        stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                        cnt_next            <= 0;
                                        
                                        -- Unmark all Writers
                                        endpoint_mask_next  <= ENDPOINT_READERS;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when others =>
                                        null;
                                end case;
                            end if;
                        when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER =>
                            -- SANITY CHECK: Ignore if no Readers
                            -- Only ACKNACKs are relevant
                            if (NUM_READERS /= 0 and opcode = SID_ACKNACK) then
                                message_type_next   <= EDP;
                                
                                stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                                cnt_next            <= 0;
                                
                                -- Start Participant Search
                                mem_op_start        <= '1';
                                mem_opcode          <= SEARCH_PARTICIPANT;
                                mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                                mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                            end if;
                        when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR =>
                            -- SANITY CHECK: Ignore if no Writers
                            if (NUM_WRITERS /= 0) then
                                message_type_next   <= EDP;
                                is_subscriber_next  <= '1';
                                
                                -- Only HEARTBEATs, GAPs and DATA are relevant
                                case (opcode) is
                                    when SID_HEARTBEAT =>
                                        stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_SUB_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_GAP =>
                                        stage_next          <= PROCESS_GAP; -- GAP Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_DATA =>
                                        stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                        cnt_next            <= 0;
                                        
                                        -- Unmark all Readers
                                        endpoint_mask_next  <= not ENDPOINT_READERS;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when others =>
                                        null;
                                end case;
                            end if;
                        when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER =>
                            -- SANITY CHECK: Ignore if no Writers
                            if (NUM_WRITERS /= 0) then
                                -- Only ACKNACKs are relevant
                                if (opcode = SID_ACKNACK) then
                                    message_type_next   <= MESSAGE;
                                    
                                    stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                end if;
                            end if;
                        when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER =>
                            -- SANITY CHECK: Ignore if no Readers
                            if (NUM_READERS /= 0) then
                                message_type_next   <= MESSAGE;
                                
                                -- Only HEARTBEATs, GAPs and DATA are relevant
                                case (opcode) is
                                    when SID_HEARTBEAT =>
                                        stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_MES_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_GAP =>
                                        stage_next          <= PROCESS_GAP; -- GAP Processing
                                        cnt_next            <= 0;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when SID_DATA =>
                                        stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                        cnt_next            <= 0;
                                        
                                        -- Unmark all Writers
                                        endpoint_mask_next  <= ENDPOINT_READERS;
                                        
                                        -- Start Participant Search
                                        mem_op_start        <= '1';
                                        mem_opcode          <= SEARCH_PARTICIPANT;
                                        mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                        mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                    when others =>
                                        null;
                                end case;
                            end if;
                        when others =>
                            -- Skip Packet
                            null;
                    end case;
                end if;
            when CHECK_SRC_ENTITYID =>
                assert (mem_op_done = '1') severity FAILURE;
                
                -- DEFAULT
                stage_next          <= SKIP_PACKET;
                is_subscriber_next  <= '0';
                
                -- *Check Dest Entity ID*
                case (src_entityid) is
                    when ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER =>
                        -- Only DATA relevant
                        if (opcode = SID_DATA) then
                            -- Packet Contains Participant Data
                            message_type_next   <= PDP;
                            
                            stage_next          <= LATCH_SEQ_NR;
                            cnt_next            <= 0;
                            
                            -- Start Participant Search
                            mem_op_start        <= '1';
                            mem_opcode          <= SEARCH_PARTICIPANT;
                            mem_r.field_flags   <= PMF_SPDP_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                            mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                        end if;
                    when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR =>
                        -- SANITY CHECK: Ignore if no Writers
                        -- Only ACKNACKs are relevant
                        if (NUM_WRITERS /= 0 and opcode = SID_ACKNACK) then
                            message_type_next   <= EDP;
                            is_subscriber_next  <= '1';
                            
                            stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                            cnt_next            <= 0;
                            
                            -- Start Participant Search
                            mem_op_start        <= '1';
                            mem_opcode          <= SEARCH_PARTICIPANT;
                            mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                            mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                        end if;
                    when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER =>
                        -- SANITY CHECK: Ignore if no Readers
                        if (NUM_READERS /= 0) then
                            message_type_next   <= EDP;
                            
                            -- Only HEARTBEATs, GAPs and DATA are relevant
                            case (opcode) is
                                when SID_HEARTBEAT =>
                                    stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_PUB_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_GAP =>
                                    stage_next          <= PROCESS_GAP; -- GAP Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_DATA =>
                                    stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                    cnt_next            <= 0;
                                    
                                    -- Unmark all Writers
                                    endpoint_mask_next  <= ENDPOINT_READERS;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when others =>
                                    null;
                            end case;
                        end if;
                    when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR =>
                        -- SANITY CHECK: Ignore if no Readers
                        -- Only ACKNACKs are relevant
                        if (NUM_READERS /= 0 and opcode = SID_ACKNACK) then
                            message_type_next   <= EDP;
                            
                            stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                            cnt_next            <= 0;
                            
                            -- Start Participant Search
                            mem_op_start        <= '1';
                            mem_opcode          <= SEARCH_PARTICIPANT;
                            mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                            mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                        end if;
                    when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER =>
                        -- SANITY CHECK: Ignore if no Writers
                        if (NUM_WRITERS /= 0) then
                            message_type_next   <= EDP;
                            is_subscriber_next  <= '1';
                            
                            -- Only HEARTBEATs, GAPs and DATA are relevant
                            case (opcode) is
                                when SID_HEARTBEAT =>
                                    stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_SUB_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_GAP =>
                                    stage_next          <= PROCESS_GAP; -- GAP Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_DATA =>
                                    stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                    cnt_next            <= 0;
                                    
                                    -- Unmark all Readers
                                    endpoint_mask_next  <= not ENDPOINT_READERS;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when others =>
                                    null;
                            end case;
                        end if;
                    when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER =>
                        -- SANITY CHECK: Ignore if no Writers
                        if (NUM_WRITERS /= 0) then
                            -- Only ACKNACKs are relevant
                            if (opcode = SID_ACKNACK) then
                                message_type_next   <= MESSAGE;
                                
                                stage_next          <= PROCESS_ACKNACK; --ACKNACK Processing
                                cnt_next            <= 0;
                                
                                -- Start Participant Search
                                mem_op_start        <= '1';
                                mem_opcode          <= SEARCH_PARTICIPANT;
                                mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                                mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                            end if;
                        end if;
                    when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER =>
                        -- SANITY CHECK: Ignore if no Readers
                        if (NUM_READERS /= 0) then
                            message_type_next       <= MESSAGE;
                            
                            -- Only HEARTBEATs, GAPs and DATA are relevant
                            case (opcode) is
                                when SID_HEARTBEAT =>
                                    stage_next          <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_MES_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_GAP =>
                                    stage_next          <= PROCESS_GAP; -- GAP Processing
                                    cnt_next            <= 0;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when SID_DATA =>
                                    stage_next          <= LATCH_SEQ_NR; -- DATA Processing
                                    cnt_next            <= 0;
                                    
                                    -- Unmark all Writers
                                    endpoint_mask_next  <= ENDPOINT_READERS;
                                    
                                    -- Start Participant Search
                                    mem_op_start        <= '1';
                                    mem_opcode          <= SEARCH_PARTICIPANT;
                                    mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                    mem_r.guid_prefix   <= GUIDPREFIX_TYPE(guid(0 to 2));
                                when others =>
                                    null;
                            end case;
                        end if;
                    when others =>
                        null;
                end case;
            when LATCH_SEQ_NR =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch Sequence Number
                    case (cnt) is
                        when 0 =>
                            seq_nr_next(0)  <= unsigned(data_in);
                            cnt_next        <= cnt + 1;
                        when 1 =>
                            seq_nr_next(1)  <= unsigned(data_in);
                            -- Store Next Sequence Number
                            tmp_dw              := (0 => seq_nr(0), 1 => unsigned(data_in));
                            next_seq_nr_next    <= tmp_dw + 1;
                            
                            stage_next      <= PROCESS_DATA;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_DATA =>
                -- Data Message contains inline QoS
                if (qos_flag = '1') then
                    stage_next  <= PROCESS_PL;
                -- Data Message contains Data Payload
                elsif (data_flag = '1') then
                    -- Input FIFO Guard
                    if (empty = '0') then
                        rd_guard    := '1';
                        -- DEFAULT STAGE
                        stage_next  <= SKIP_PACKET;
                        
                        -- Process Payload Header
                        case(representation_id) is
                            when PL_CDR_BE =>
                                -- Override Endian Flag
                                endian_flag_next    <= '0';
                                
                                stage_next          <= PROCESS_PL;
                            when PL_CDR_LE =>
                                -- Override Endian Flag
                                endian_flag_next    <= '1';
                                
                                stage_next          <= PROCESS_PL;
                            when CDR_BE =>
                                -- Accept CDR Representation only for Participant Messages
                                if (message_type = MESSAGE) then
                                    -- Override Endian Flag
                                    endian_flag_next    <= '0';
                                    
                                    stage_next          <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
                                end if;
                            when CDR_LE =>
                                -- Accept CDR Representation only for Participant Messages
                                if (message_type = MESSAGE) then
                                    -- Override Endian Flag
                                    endian_flag_next    <= '1';
                                    
                                    stage_next          <= PROCESS_MESSAGE_SEQUENCE_NUMBERS;
                                end if;
                            when others =>
                                -- Skip Packet
                                null;
                        end case;
                    end if;
                elsif (ud_status = '1') then
                    -- NOTE: If the DATA message has a paylaod with DATA, the parsed in-line QoS (i.e. PID_STATUS_INFO) is ignored
                    -- NOTE: A Sanity check is made on the GUID. It is expected that the GUID is correctly configured by parsing of an PID_KEY_HASH.
                    --       According to the specification the PID_KEY_HASH is not a requirement, and the Key should be sent as serialized key in the DATA
                    --       message payload. We do not parse the serialized key (because, quite frankly, we can't since we do not have a definition of it...)
                    --       This means that if the sender does not send a PID_KEY_HASH and the sanity check here fails, the Packet will be skipped, and thus
                    --       processing from the sender will effectively stall, since the SN will never be acknowledged.
                    -- Participant Unamtch
                    if (message_type = PDP and guid(3) = ENTITYID_PARTICIPANT) then
                        participant_match_next  <= '0';
                        stage_next              <= PARTICIPANT_MATCH_STAGE;
                    -- Endpoint Unmatch
                    elsif (message_type = EDP and guid(3)(ENTITY_KIND_H_RANGE) /= BUILT_IN_ENTITY) then
                        endpoint_mask_next  <= (others => '0');
                        stage_next          <= PARTICIPANT_MATCH_STAGE;
                    else
                        -- Skip
                        stage_next  <= SKIP_PACKET;
                    end if;
                else
                    -- Skip
                    stage_next  <= SKIP_PACKET;
                end if;
            when PROCESS_MESSAGE_SEQUENCE_NUMBERS =>
                -- Precondition: participant_data set (PMF_MES_SEQ_NR_FLAG)
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    -- Participant in Buffer
                    if (participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, check_mask(participant_data.field_flags, PMF_MES_SEQ_NR_FLAG)) severity FAILURE;
                        
                        -- NOTE: Since the BuiltinParticipantMessageWriter has a History Depth of 1 (see DDSI-RTPS 2.3 8.4.13.3), we accept all newer SNs, since
                        --       if the Writer has sent a newer SN he doesn't have the previous one anymore.
                        -- Next Valid Sequence Number
                        if (seq_nr >= mem_seq_nr) then
                            mem_op_start        <= '1';
                            mem_opcode          <= UPDATE_PARTICIPANT;
                            mem_r.addr          <= participant_data.addr;
                            mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG;
                            mem_r.mes_seq_nr    <= next_seq_nr;
                            
                            -- Process Message Data
                            stage_next  <= PROCESS_MESSAGE;
                            cnt_next    <= 0;
                        else
                            -- DONE
                            stage_next  <= SKIP_PACKET;
                        end if;
                    else
                        -- DONE
                        stage_next  <= SKIP_PACKET;
                    end if;
                end if;
            when PROCESS_MESSAGE =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        -- Check if GUID Prefix valid (Should be the same as the GUID Prefix of the Packet)
                        -- GUID Prefix 1/3
                        when 0 =>
                            if (data_in /= guid(0)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GUID Prefix 2/3
                        when 1 =>
                            if (data_in /= guid(1)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GUID Prefix 3/3
                        when 2 =>
                            if (data_in /= guid(2)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        -- Participant Mesasge Kind
                        when 3 =>
                            -- NOTE: Rest of Participant Message is ignored
                            -- XXX: The Participant Message Data may contain additional data, and according to DDSI-RTPS 2.3 
                            --      implementations must be able to support up to 128 Bytes of additional data. Due to the unnecessary 
                            --      high complexity this would add, this is currently not supported.
                            case (data_in) is
                                -- Automatic Liveliness Assertion
                                when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE =>
                                    -- Mark all readers with automatic liveliness QoS
                                    endpoint_mask_next  <= AUTOMATIC_LIVELINESS_READERS;
                                    stage_next          <= LIVELINESS_UPDATE;
                                    cnt_next            <= 0;
                                -- Manual by Participant Liveliness Assertion
                                when PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE =>
                                    -- Mark all readers with manual by participant liveliness QoS
                                    endpoint_mask_next  <= MANUAL_BY_PARTICIPANT_LIVELINESS_READERS;
                                    stage_next          <= LIVELINESS_UPDATE;
                                    cnt_next            <= 0;
                                -- No Liveliness Update, skip packet
                                when others =>
                                    stage_next  <= SKIP_PACKET;
                            end case;
                        when others =>
                            null;
                    end case;
                end if;
            when LIVELINESS_UPDATE =>
                -- If no Endpoint interested for Liveliness Assertion, skip
                if (endpoint_mask = (endpoint_mask'range => '0')) then
                    -- DONE
                    stage_next  <= SKIP_PACKET;
                -- Output FIFO Guard
                elsif ((endpoint_mask and full_rtps) = (full_rtps'range => '0')) then
                    wr_sig  <= '1';
                    
                    case (cnt) is
                        -- Liveliness Assertion Opcode
                        when 0 =>
                            data_out_sig    <= EMO_LIVELINESS_UPDATE;
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 1/3
                        when 1 =>
                            data_out_sig    <= guid(0);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 2 =>
                            data_out_sig    <= guid(1);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 3 =>
                            data_out_sig        <= guid(2);
                            last_word_out_sig   <= '1';
                            
                            -- DONE
                            stage_next  <= SKIP_PACKET;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_GAP =>
                -- NOTE: Data is already endain swapped by rtps_handler
                
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        -- GapStart Sequence Number  1/2
                        when 0 =>
                            gap_start_next(0)       <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        -- GapStart Sequence Number  2/2
                        when 1 =>
                            gap_start_next(1)       <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        -- GapList.Base 1/2
                        when 2 =>
                            gap_list_base_next(0)   <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        -- GapList.Base 2/2
                        when 3 =>
                            gap_list_base_next(1)   <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        -- GapList.NumBits
                        when 4 =>
                            gap_list_end_next   <= gap_list_base + to_integer(unsigned(data_in));
                            bitmap_cnt_next     <= unsigned(round_slv(data_in(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
                            cnt2_next           <= 0;
                            cnt_next            <= cnt + 1;
                        -- GapList.Bitmap
                        when 5 =>
                            -- Read Bitmap
                            if (cnt2 < bitmap_cnt) then
                                cnt2_next <= cnt2 + 1;
                                
                                bitmap_latch_next(cnt2) <= data_in;
                            else
                                stage_next  <= PROCESS_GAP_SEQUENCE_NUMBERS;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_GAP_SEQUENCE_NUMBERS =>
                -- Precondition: participant_data set (PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG)
                
                -- Wait for Sequence Number to be fetched from buffer
                if (mem_op_done = '1') then
                    -- DEFAULT
                    stage_next  <= SKIP_PACKET;
                    
                    -- Sender known
                    if (participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        assert_sn;
                        
                        -- GAP is relevant
                        if (gap_start <= mem_seq_nr and mem_seq_nr <= gap_list_end) then
                            -- Next Expected is in GAP List
                            if (gap_list_base <= mem_seq_nr) then
                                -- Begin searching next valid SN from the current expected in the bitmap list
                                next_seq_nr_next    <= mem_seq_nr;
                                bitmap_pos_next     <= to_integer(mem_seq_nr - gap_list_base);
                            else
                                -- Begin searching next valid SN from the beginning of the bitmap list
                                next_seq_nr_next    <= gap_list_base;
                                bitmap_pos_next     <= 0;
                            end if;
                            stage_next  <= FIND_NEXT_VALID_IN_BITMAP;
                        end if;
                    end if;
                end if;
            when FIND_NEXT_VALID_IN_BITMAP =>
                -- Memory Operation Guard
                if (mem_op_done = '1') then
                    assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    
                    tmp_bitmap  := to_slv_bitmap(bitmap_latch);
                    
                    -- First valid sequence number found
                    if (tmp_bitmap(bitmap_pos) = '0') then
                        -- Update next sequence number
                        mem_op_start    <= '1';
                        mem_opcode      <= UPDATE_PARTICIPANT;
                        mem_r.addr      <= participant_data.addr;
                        if (message_type = EDP and is_subscriber = '0') then
                            mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG;
                            mem_r.pub_seq_nr    <= next_seq_nr;
                        elsif (message_type = EDP and is_subscriber = '1') then
                            mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG;
                            mem_r.sub_seq_nr    <= next_seq_nr;
                        else -- message_type = MESSAGE
                            mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG;
                            mem_r.mes_seq_nr    <= next_seq_nr;
                        end if;
                        -- DONE
                        stage_next      <= SKIP_PACKET;
                    else
                        -- Continue search
                        bitmap_pos_next     <= bitmap_pos + 1;
                        next_seq_nr_next    <= next_seq_nr + 1;
                    end if;
                end if;
            when PROCESS_HEARTBEAT =>
                -- NOTE: Data is already endain swapped by rtps_handler
                
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch Sequence Numbers
                    case (cnt) is
                        when 0 =>
                            first_seq_nr_next(0)    <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        when 1 =>
                            first_seq_nr_next(1)    <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        when 2 =>
                            last_seq_nr_next(0)     <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        when 3 =>
                            last_seq_nr_next(1)     <= unsigned(data_in);
                            stage_next              <= PROCESS_HEARTBEAT_SEQUENCE_NUMBERS;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_HEARTBEAT_SEQUENCE_NUMBERS =>
                -- Precondition: participant_data set (PMF_HEARTBEAT_RES_TIME_FLAG, PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG)
                
                -- Wait for Participant Search to finish
                if (mem_op_done = '1') then
                    -- Participant in Buffer
                    if (participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, check_mask(participant_data.field_flags, PMF_HEARTBEAT_RES_TIME_FLAG)) severity FAILURE;
                        assert_sn;
                        
                        -- No scheduled Heartbeat Response
                        if (participant_data.heartbeat_res_time = TIME_INVALID) then
                            -- If current Sequence Number obsolete (removed from source history cache)
                            if (first_seq_nr > mem_seq_nr) then
                                -- Store new expected Sequence Number and set Response Dealy
                                mem_op_start    <= '1';
                                mem_opcode      <= UPDATE_PARTICIPANT;
                                mem_r.addr      <= participant_data.addr;
                                
                                if (message_type = EDP and is_subscriber = '0') then
                                    mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                                    mem_r.pub_seq_nr    <= first_seq_nr;
                                elsif (message_type = EDP and is_subscriber = '1') then
                                    mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                                    mem_r.sub_seq_nr    <= first_seq_nr;
                                else -- message_type = MESSAGE
                                    mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                                    mem_r.mes_seq_nr    <= first_seq_nr;
                                end if;
                                -- NOTE: Only response with ACKNACK if SN is available (Or no Final Flag)
                                if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE and (first_seq_nr <= last_seq_nr or final_flag = '0')) then
                                    tmp_dw              := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
                                    mem_r.heartbeat_res_time    <= tmp_dw;
                                    mem_r.acknack_res_time      <= tmp_dw;
                                    -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                    mem_r.heartbeat_res_time(1)(0)  <= '0';
                                    mem_r.acknack_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.heartbeat_res_time    <= TIME_INVALID;
                                    mem_r.acknack_res_time      <= TIME_INVALID;
                                end if;
                            -- If new Sequence Number is available or Writer expects ACKNACK
                            elsif (last_seq_nr >= mem_seq_nr or final_flag = '0') then
                                -- Set Response Delay
                                mem_op_start        <= '1';
                                mem_opcode          <= UPDATE_PARTICIPANT;
                                mem_r.addr          <= participant_data.addr;
                                mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG;
                                if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
                                    tmp_dw                      := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY;
                                    mem_r.heartbeat_res_time    <= tmp_dw;
                                    -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                    mem_r.heartbeat_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.heartbeat_res_time    <= TIME_INVALID;
                                end if;
                            end if;
                        -- Currently in Heartbeat Response Delay
                        elsif (participant_data.heartbeat_res_time(1)(0) = '0') then
                            -- If current Sequence Number obsolete (removed from source history cache)
                            if (first_seq_nr > mem_seq_nr) then
                                -- Store new expected Sequence Number
                                mem_op_start    <= '1';
                                mem_opcode      <= UPDATE_PARTICIPANT;
                                mem_r.addr      <= participant_data.addr;
                                if (message_type = EDP and is_subscriber = '0') then
                                    mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG;
                                    mem_r.pub_seq_nr    <= first_seq_nr;
                                elsif (message_type = EDP and is_subscriber = '1') then
                                    mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG;
                                    mem_r.sub_seq_nr    <= first_seq_nr;
                                else -- message_type = MESSAGE
                                    mem_r.field_flags   <= PMF_MES_SEQ_NR_FLAG;
                                    mem_r.mes_seq_nr    <= first_seq_nr;
                                end if;
                            end if;
                        end if;
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PACKET;
                end if;
            when PROCESS_ACKNACK =>
                -- NOTE: Data is already endain swapped by rtps_handler
                
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch Sequence Number
                    -- NOTE: Because we always sent the entire history cache, we only need to look at the SequenceNumberSetBase to determine if we need to sent data or not
                    case (cnt) is
                        when 0 =>
                            first_seq_nr_next(0)    <= unsigned(data_in);
                            cnt_next                <= cnt + 1;
                        when 1 =>
                            first_seq_nr_next(1)    <= unsigned(data_in);
                            
                            stage_next              <= PROCESS_ACKNACK_SEQUENCE_NUMBERS;
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_ACKNACK_SEQUENCE_NUMBERS =>
                -- Precondition: participant_data set (PMF_ACKNACK_RES_TIME_FLAG, PMF_EXTRA_FLAGS_FLAG)
                
                -- Wait for Participant Search to finish
                if (mem_op_done = '1') then
                    -- Participant in Buffer
                    if (participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, check_mask(participant_data.field_flags, PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG)) severity FAILURE;
                        
                        -- No scheduled Acknack Response
                        if (participant_data.acknack_res_time = TIME_INVALID) then
                            case (message_type) is
                                when EDP =>
                                    -- Subscriber Acknack
                                    if (is_subscriber = '1') then
                                        -- If Reader has not ACKed all Publisher History Cache
                                        if (first_seq_nr <= PUB_SEQUENCENUMBER) then
                                            -- Set Acknack Response Time and Publisher Data as Acknack Response
                                            mem_op_start        <= '1';
                                            mem_opcode          <= UPDATE_PARTICIPANT;
                                            mem_r.addr          <= participant_data.addr;
                                            mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
                                            if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
                                                tmp_dw          := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
                                                mem_r.acknack_res_time  <= tmp_dw;
                                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                                mem_r.acknack_res_time(1)(0)    <= '0';
                                                mem_r.extra_flags               <= participant_data.extra_flags or EF_PUB_DATA_FLAG;
                                                -- 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.acknack_res_time  <= TIME_INVALID;
                                                mem_r.extra_flags       <= participant_data.extra_flags;
                                            end if;
                                        end if;
                                    -- Publisher Acknack
                                    else
                                        -- If Reader has not ACKed all Subscriber History Cache
                                        if (first_seq_nr <= SUB_SEQUENCENUMBER) then
                                            -- Set Acknack Response Time and set Subscriber Data as Acknack Response
                                            mem_op_start        <= '1';
                                            mem_opcode          <= UPDATE_PARTICIPANT;
                                            mem_r.addr          <= participant_data.addr;
                                            mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
                                            if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
                                                tmp_dw          := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
                                                mem_r.acknack_res_time  <= tmp_dw;
                                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                                mem_r.acknack_res_time(1)(0)    <= '0';
                                                mem_r.extra_flags   <= participant_data.extra_flags or EF_SUB_DATA_FLAG;
                                                -- 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.acknack_res_time  <= TIME_INVALID;
                                                mem_r.extra_flags       <= participant_data.extra_flags;
                                            end if;
                                        end if;
                                    end if;
                                -- Message Acknack
                                when MESSAGE =>
                                    -- NOTE:    "auto_live_seq_nr" always has the higher sequence number by design, so we just need to check against that
                                    -- If Reader has not ACKed all Message History Cache
                                    if (first_seq_nr <= auto_live_seq_nr) then
                                        -- Set Acknack Response Time and set Message Data as Acknack Response
                                        mem_op_start        <= '1';
                                        mem_opcode          <= UPDATE_PARTICIPANT;
                                        mem_r.addr          <= participant_data.addr;
                                        mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG;
                                        if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
                                            tmp_dw          := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY;
                                            mem_r.acknack_res_time  <= tmp_dw;
                                            -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                            mem_r.acknack_res_time(1)(0)    <= '0';
                                            mem_r.extra_flags   <= participant_data.extra_flags or EF_MES_DATA_FLAG;
                                            -- 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.acknack_res_time  <= TIME_INVALID;
                                            mem_r.extra_flags       <= participant_data.extra_flags;
                                        end if;
                                    end if;
                                when others =>
                                    null;
                            end case;
                        -- Currently in Acknack Response Delay
                        elsif (participant_data.acknack_res_time(1)(0) = '0') then
                            case (message_type) is
                                when EDP =>
                                    -- Subscriber Acknack
                                    if (is_subscriber = '1') then
                                        -- Publisher Data not scheduled for response
                                        if (not check_mask(participant_data.extra_flags, EF_PUB_DATA_FLAG)) then
                                            -- If Reader has not ACKed all Publisher History Cache
                                            if (first_seq_nr <= PUB_SEQUENCENUMBER) then
                                                -- Set Publisher Data as Acknack Response
                                                mem_op_start        <= '1';
                                                mem_opcode          <= UPDATE_PARTICIPANT;
                                                mem_r.addr          <= participant_data.addr;
                                                mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG;
                                                mem_r.extra_flags   <= participant_data.extra_flags or EF_PUB_DATA_FLAG;
                                            end if;
                                        end if;
                                    -- Publisher Acknack
                                    else
                                        -- Subscriber Data not scheduled for response
                                        if (not check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG)) then
                                            -- If Reader has not ACKed all Subscriber History Cache
                                            if (first_seq_nr <= SUB_SEQUENCENUMBER) then
                                                -- Set Subscriber Data as Acknack Response
                                                mem_op_start        <= '1';
                                                mem_opcode          <= UPDATE_PARTICIPANT;
                                                mem_r.addr          <= participant_data.addr;
                                                mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG;
                                                mem_r.extra_flags   <= participant_data.extra_flags or EF_SUB_DATA_FLAG;
                                            end if;
                                        end if;
                                    end if;
                                -- Message Acknack
                                when MESSAGE =>
                                    -- Message Data not scheduled for response
                                    if (not check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then
                                        -- NOTE:    "auto_live_seq_nr" always has the higher sequence number by design, so we just need to
                                        --          check against that
                                        -- If Reader has not ACKed all Message History Cache
                                        if (first_seq_nr <= auto_live_seq_nr) then
                                            -- Set Message Data as Acknack Response
                                            mem_op_start        <= '1';
                                            mem_opcode          <= UPDATE_PARTICIPANT;
                                            mem_r.addr          <= participant_data.addr;
                                            mem_r.field_flags   <= PMF_EXTRA_FLAGS_FLAG;
                                            mem_r.extra_flags   <= participant_data.extra_flags or EF_MES_DATA_FLAG;
                                        end if;
                                    end if;
                                when others =>
                                    null;
                            end case;
                        end if;
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PACKET;
                end if;
            when FIND_PARTICIPANT_DEST =>
                -- Wait for Next Participant to be Fetched
                if (mem_op_done = '1') then
                    -- No more Participants
                    if (participant_data.addr = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        -- Reset
                        is_live_assert_next <= '0';
                        
                        -- DONE
                        stage_next      <= IDLE;
                    else
                        stage_next          <= SEND_HEADER;
                        return_stage_next   <= SEND_HEARTBEAT;
                        cnt_next            <= 0;
                    end if;
                end if;
            when PARTICIPANT_STALE_CHECK =>
                -- Precondition: participant_data set (PMF_LEASE_DEADLINE_FLAG, PMF_HEARTBEAT_RES_TIME_FLAG, PMF_ACKNACK_RES_TIME_FLAG)
                
                -- Wait for Stale Search to finish
                if (mem_op_done = '1') then
                    case (cnt) is
                        -- GET NEXT PARTICIPANT
                        when 0 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_NEXT_PARTICIPANT;
                            mem_r.addr          <= participant_data.addr;
                            mem_r.field_flags   <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                            cnt_next            <= cnt + 2;
                        -- GET PARTICIPANT
                        when 1 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= GET_PARTICIPANT;
                            mem_r.addr          <= participant_data.addr;
                            mem_r.field_flags   <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG;
                            cnt_next            <= cnt + 1;
                        -- EXIT CONDITION
                        when 2 =>
                            -- No More Participants
                            if (participant_data.addr = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                -- Reset
                                stale_check_next    <= '0';
                                -- DONE
                                stage_next          <= IDLE;
                            else
                                -- Check if STALE
                                cnt_next    <= cnt + 1;
                            end if;
                        -- LEASE DEADLINE
                        when 3 =>
                            assert stable(clk, check_mask(participant_data.field_flags, PMF_LEASE_DEADLINE_FLAG)) severity FAILURE;
                            assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            -- Lease Expiration
                            if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline <= time) then
                                mem_op_start        <= '1';
                                mem_opcode          <= GET_PARTICIPANT;
                                mem_r.addr          <= mem_addr_base;
                                mem_r.field_flags   <= PMF_GUIDPREFIX_FLAG;
                                cnt_next            <= 6; -- HELPER STAGE
                            else
                                -- Check Next Field
                                cnt_next    <= cnt + 1;
                                
                                -- Update Check Time
                                if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline < check_time) then
                                    check_time_next <= participant_data.lease_deadline;
                                end if;
                            end if;
                        -- HEARTBEAT RESPONSE TIME
                        when 4 =>
                            assert stable(clk, check_mask(participant_data.field_flags, PMF_HEARTBEAT_RES_TIME_FLAG)) severity FAILURE;
                            assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            -- HEARTBEAT Response Time Passed
                            if (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time <= time) then
                                -- Suppression Delay
                                if (participant_data.heartbeat_res_time(1)(0) = '1') then
                                    mem_op_start        <= '1';
                                    mem_opcode          <= UPDATE_PARTICIPANT;
                                    mem_r.addr          <= participant_data.addr;
                                    mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG;
                                    mem_r.heartbeat_res_time    <= TIME_INVALID;
                                -- Response Delay
                                else
                                    mem_op_start        <= '1';
                                    mem_opcode          <= GET_PARTICIPANT;
                                    mem_r.addr          <= participant_data.addr;
                                    mem_r.field_flags   <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG;
                                    
                                    -- Send ACKNACK
                                    stage_next          <= SEND_HEADER;
                                    return_stage_next   <= SEND_ACKNACK;
                                    cnt_next            <= 0;
                                    -- Increment Heartbeat/Acknack Counter
                                    count_next  <= count + 1;
                                end if;
                            else
                                -- Check Next Field
                                cnt_next    <= cnt + 1;
                                
                                -- Update Check Time
                                if (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time < check_time) then
                                    check_time_next <= participant_data.heartbeat_res_time;
                                end if;
                            end if;
                        -- ACKNACK RESPONSE TIME
                        when 5 =>
                            assert stable(clk, check_mask(participant_data.field_flags, PMF_ACKNACK_RES_TIME_FLAG)) severity FAILURE;
                            assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            -- ACKNACK Response Time Passed
                            if (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time <= time) then
                                -- Suppression Delay
                                if (participant_data.acknack_res_time(1)(0) = '1') then
                                    mem_op_start        <= '1';
                                    mem_opcode          <= UPDATE_PARTICIPANT;
                                    mem_r.addr          <= participant_data.addr;
                                    mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG;
                                    mem_r.acknack_res_time  <= TIME_INVALID;
                                -- Response Delay
                                else
                                    mem_op_start        <= '1';
                                    mem_opcode          <= GET_PARTICIPANT;
                                    mem_r.addr          <= participant_data.addr;
                                    mem_r.field_flags   <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_EXTRA_FLAGS_FLAG;
                                    
                                    -- Send Requested Data
                                    stage_next          <= SEND_HEADER;
                                    return_stage_next   <= SEND_PUB_DATA;
                                    cnt_next            <= 0;
                                end if;
                            else
                                -- Continue Search
                                cnt_next    <= 0;
                                
                                -- Update Check Time
                                if (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time < check_time) then
                                    check_time_next <= participant_data.acknack_res_time;
                                end if;
                            end if;
                        -- HELPER STAGE (Lacthes Participant GUID for participant Unmatching)
                        when 6 =>
                            assert stable(clk, check_mask(participant_data.field_flags, PMF_GUIDPREFIX_FLAG)) severity FAILURE;
                            
                            -- Latch GUID Prefix
                            guid_next(0)    <= participant_data.guid_prefix(0);
                            guid_next(1)    <= participant_data.guid_prefix(1);
                            guid_next(2)    <= participant_data.guid_prefix(2);
                            
                            -- Remove Participant
                            mem_op_start    <= '1';
                            mem_opcode      <= REMOVE_PARTICIPANT;
                            mem_r.addr      <= mem_addr_base;
                            
                            stage_next      <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH;
                            cnt_next        <= 0;
                        -- POST-ACKNACK-SENT
                        when 7 =>
                            mem_op_start        <= '1';
                            mem_opcode          <= UPDATE_PARTICIPANT;
                            mem_r.addr          <= participant_data.addr;
                            mem_r.field_flags   <= PMF_HEARTBEAT_RES_TIME_FLAG;
                            if (PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_INFINITE) then
                                -- Set Heartbeat Suppression Time
                                mem_r.heartbeat_res_time    <= time + PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY;
                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                mem_r.heartbeat_res_time(1)(0)  <= '1';
                            else
                                -- Reset
                                mem_r.heartbeat_res_time    <= TIME_INVALID;
                            end if;
                            
                            -- NOTE: The HEARTBEAT Time is re-checked in order to update the check_time
                            -- Continue
                            cnt_next    <= 4; -- CHECK HERTBEAT Response Time
                        -- POST-DATA-SENT
                        when 8 =>
                            assert stable(clk, check_mask(participant_data.field_flags, PMF_EXTRA_FLAGS_FLAG)) severity FAILURE;
                            
                            mem_op_start        <= '1';
                            mem_opcode          <= UPDATE_PARTICIPANT;
                            mem_r.addr          <= participant_data.addr;
                            mem_r.field_flags   <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG;
                            mem_r.extra_flags   <= participant_data.extra_flags and (not (EF_PUB_DATA_FLAG or EF_SUB_DATA_FLAG or EF_MES_DATA_FLAG));
                            if (PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_INFINITE) then
                                -- Set Acknack Suppression Time
                                mem_r.acknack_res_time  <= time + PARTICIPANT_ACKNACK_SUPPRESSION_DELAY;
                                -- NOTE: Last Bit denotes if this is Response or Suppression Delay
                                mem_r.acknack_res_time(1)(0)    <= '1';
                            else
                                -- Reset
                                mem_r.acknack_res_time  <= TIME_INVALID;
                            end if;
                            
                            -- NOTE: The ACKNACK Time is re-checked in order to update the check_time
                            -- Continue
                            cnt_next    <= 5; -- CHECK ACKNACK Response Time
                        when others =>
                            null;
                    end case;
                end if;
            when PROCESS_PL =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard            := '1';
                    -- Reset Word Counter
                    reset_read_cnt      <= '1';
                    -- Latch Parameter End (In order to skip parameters)
                    parameter_end_next  <= unsigned(endian_swap(endian_flag,parameter_length));
                    -- DEFAULT STAGE
                    stage_next          <= SKIP_PARAMETER;
                    
                    -- TODO: DDS-XTYPES: When reading data, implementations of this specification shall be robust to any setting of the FLAG_MUST_UNDERSTAND bit and accept the parameter nevertheless.
                    
                    -- NOTE: In-line QoS is completely ignored
                    
                    case (endian_swap(endian_flag,parameter_id)) is
                        when PID_PARTICIPANT_GUID =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next  <= MATCH_GUID;
                                cnt_next    <= 0;
                            end if;
                        when PID_DOMAIN_ID =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next <= MATCH_DOMAIN_ID;
                            end if;
                        when PID_DOMAIN_TAG =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next          <= LATCH_STRING_LENGTH;
                                -- Mark String contents (Needed for string comparison)
                                string_content_next <= DOMAIN_TAG_TYPE;
                                -- Mark reception of DOMAIN_TAG
                                rcvd_next   <= rcvd or RCVD_DOMAIN_TAG_FLAG;
                            end if;
                        when PID_PROTOCOL_VERSION =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next <= MATCH_PROTOCOL_VERSION;
                            end if;
                        when PID_DEFAULT_UNICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '0';
                                is_multicast_addr_next  <= '0';
                            end if;
                        when PID_DEFAULT_MULTICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '0';
                                is_multicast_addr_next  <= '1';
                            end if;
                        when PID_METATRAFFIC_UNICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '1';
                                is_multicast_addr_next  <= '0';
                            end if;
                        when PID_METATRAFFIC_MULTICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '1';
                                is_multicast_addr_next  <= '1';
                            end if;
                        when PID_PARTICIPANT_LEASE_DURATION =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next  <= LATCH_LEASE_DURATION;
                                cnt_next    <= 0;
                            end if;
                        when PID_BUILTIN_ENDPOINT_SET =>
                            -- Ignore in-line QoS
                            -- Only relevant for Participant Discovery Protocol
                            if(qos_flag = '0' and message_type = PDP) then
                                stage_next  <= CHECK_REMOTE_BUILTIN_ENDPOINTS;
                            end if;
                        when PID_BUILTIN_ENDPOINT_QOS =>
                            -- Only relevant for Participant Discovery Protocol
                            -- NOTE:    As of DDSI-RTPS 2.3 the PID_BUILTIN_ENDPOINT_QOS only contains the BEST_EFFORT_PARTICIPANT_MESSAGE_DATA_READER bit
                            --          Due to how the built-in Endpoint is behaving, this bit has no impact in our case and we can safely ignore it.
                            -- Ignore
                            null;
                        when PID_TOPIC_NAME =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next <= LATCH_STRING_LENGTH;
                                -- Mark String contents (Needed for string comparison)
                                string_content_next  <= TOPIC_NAME_TYPE;
                            end if;
                        when PID_TYPE_NAME =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next <= LATCH_STRING_LENGTH;
                                -- Mark String contents (Needed for string comparison)
                                string_content_next  <= TYPE_NAME_TYPE;
                            end if;
                        when PID_DURABILITY =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_DURABILITY;
                                rcvd_next   <= rcvd or RCVD_DURABILITY_QOS_FLAG;
                            end if;
                        when PID_DEADLINE =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_DEADLINE;
                                cnt_next    <= 0;
                                rcvd_next   <= rcvd or RCVD_DEADLINE_QOS_FLAG;
                            end if;
                        when PID_LIVELINESS =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_LIVELINESS;
                                rcvd_next   <= rcvd or RCVD_LIVELINESS_QOS_FLAG;
                            end if;
                        when PID_RELIABILITY =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_RELIABILITY;
                                cnt_next    <= 0;
                                rcvd_next   <= rcvd or RCVD_RELIABILITY_QOS_FLAG;
                            end if;
                        when PID_DESTINATION_ORDER =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_DESTINATION_ORDER;
                                rcvd_next   <= rcvd or RCVD_DESTINATION_ORDER_QOS_FLAG;
                            end if;
                        when PID_OWNERSHIP =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_OWNERSHIP;
                                rcvd_next   <= rcvd or RCVD_OWNERSHIP_QOS_FLAG;
                            end if;
                        when PID_PRESENTATION =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_PRESENTATION;
                                cnt_next    <= 0;
                                rcvd_next   <= rcvd or RCVD_PRESENTATION_QOS_FLAG;
                            end if;
                        when PID_PARTITION =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next <= RXO_PARTITION;
                            end if;
                        when PID_LATENCY_BUDGET =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= RXO_LATENCY_BUDGET;
                                cnt_next    <= 0;
                                rcvd_next   <= rcvd or RCVD_LATENCY_BUDGET_QOS_FLAG;
                            end if;
                        when PID_UNICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '0';
                                is_multicast_addr_next  <= '0';
                            end if;
                        when PID_MULTICAST_LOCATOR =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next              <= LATCH_LOCATOR;
                                cnt_next                <= 0;
                                
                                is_meta_addr_next       <= '0';
                                is_multicast_addr_next  <= '1';
                            end if;
                        when PID_ENDPOINT_GUID =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= MATCH_GUID;
                                cnt_next    <= 0;
                            end if;
                        when PID_DATA_MAX_SIZE_SERIALIZED =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= CHECK_MAX_SIZE_SERIALIZED;
                            end if;
                        when PID_EXPECTS_INLINE_QOS =>
                            stage_next  <= LATCH_EXPECTS_INLINE_QOS;
                        when PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT =>
                            -- Ignore
                            null;
                        when PID_CONTENT_FILTER_PROPERTY =>
                            -- Ignore
                            null;
                        when PID_GROUP_GUID =>
                            -- Ignore
                            null;
                        when PID_PROPERTY_LIST =>
                            -- Ignore
                            null;
                        when PID_ENTITY_NAME =>
                            -- Ignore
                            null;
                        when PID_TIME_BASED_FILTER =>
                            -- Ignore
                            null;
                        when PID_TRANSPORT_PRIORITY =>
                            -- Ignore
                            null;
                        when PID_VENDORID =>
                            -- Ignore
                            null;
                        when PID_OWNERSHIP_STRENGTH =>
                            -- Ignore
                            null;
                        when PID_HISTORY =>
                            -- Ignore
                            null;
                        when PID_RESOURCE_LIMITS =>
                            -- Ignore
                            null;
                        when PID_LIFESPAN =>
                            -- Ignore in-line QoS
                            -- Only relevant for Endpoint Discovery Protocol
                            if(qos_flag = '0' and message_type = EDP) then
                                stage_next  <= LATCH_LIFESPAN_DURATION;
                                cnt_next    <= 0;
                            end if;
                        when PID_DURABILITY_SERVICE =>
                            -- Ignore
                            null;
                        when PID_USER_DATA =>
                            -- Ignore
                            null;
                        when PID_GROUP_DATA =>
                            -- Ignore
                            null;
                        when PID_TOPIC_DATA =>
                            -- Ignore
                            null;
                        when PID_CONTENT_FILTER_INFO =>
                            -- Ignore
                            null;
                        when PID_COHERENT_SET =>
                            -- Ignore
                            null;
                        when PID_DIRECTED_WRITE =>
                            -- Ignore
                            null;
                        when PID_ORIGINAL_WRITER_INFO =>
                            -- Ignore
                            null;
                        when PID_GROUP_COHERENT_SET =>
                            -- Ignore
                            null;
                        when PID_GROUP_SEQ_NUM =>
                            -- Ignore
                            null;
                        when PID_WRITER_GROUP_INFO =>
                            -- Ignore
                            null;
                        when PID_SECURE_WRITER_GROUP_INFO =>
                            -- Ignore
                            null;
                        when PID_KEY_HASH =>
                            stage_next  <= MATCH_GUID;
                            cnt_next    <= 0;    
                        when PID_STATUS_INFO =>
                            stage_next  <= CHECK_STATUS_INFO;
                        when PID_PAD =>
                            -- Ignore
                            null;
                        when PID_EXTENDED =>
                            -- TODO
                            null;
                        when PID_IGNORE =>
                            -- Ignore
                            null;
                        when PID_SENTINEL =>
                            parameter_end_next  <= (others => '1');
                            
                            -- If Processing in-line QoS until now, start processing data
                            if(qos_flag = '1') then
                                -- Override QoS Flag
                                qos_flag_next   <= '0';
                                stage_next      <= PROCESS_DATA;
                            -- Else check Defaults
                            else
                                stage_next  <= CHECK_DEFAULT;
                            end if;
                        when PID_LIST_END =>
                            -- TODO
                            null;
                        when others =>
                            -- If MUST_UNDERSTAND Flag is set, we have incompatible communication. Drop Packet
                            if (endian_swap(endian_flag,parameter_id)(PID_MUST_UNDERSTAND_FLAG_POS) = '1') then
                                stage_next  <= SKIP_PACKET;
                            -- Else skip Uknown Parameter
                            else
                                stage_next  <= SKIP_PARAMETER;
                            end if;
                    end case;
                end if;
            when CHECK_DEFAULT =>
                -- DEFAULT
                stage_next      <= SELECT_LOCATOR;
                
                case (message_type) is
                    when PDP =>
                        -- Check Domain Tag against Default if necessary 
                        if (not check_mask(rcvd, RCVD_DOMAIN_TAG_FLAG) and DOMAIN_TAG /= DEFAULT_DOMAIN_TAG) then
                            participant_match_next  <= '0';
                        end if;
                    when EDP =>
                        -- Defaults
                        tmp_endpoint_mask   := (others => '1');
                        if (is_subscriber = '1') then
                            tmp_default_qos_match   := READER_DEFAULT_QOS_MATCH;
                        else
                            tmp_default_qos_match   := WRITER_DEFAULT_QOS_MATCH;
                        end if;
                        
                        if (not check_mask(rcvd, RCVD_DURABILITY_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.DURABILITY_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_PRESENTATION_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.PRESENTATION_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_DEADLINE_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.DEADLINE_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_LATENCY_BUDGET_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.LATENCY_BUDGET_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_OWNERSHIP_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.OWNERSHIP_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_LIVELINESS_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.LIVELINESS_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_RELIABILITY_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.RELIABILITY_QOS;
                        end if;
                        if (not check_mask(rcvd, RCVD_DESTINATION_ORDER_QOS_FLAG)) then
                            tmp_endpoint_mask   := tmp_endpoint_mask and tmp_default_qos_match.DESTINATION_ORDER_QOS;
                        end if;
                        
                        endpoint_mask_next  <= endpoint_mask and tmp_endpoint_mask;
                    when others =>
                        null;
                end case;
            when SELECT_LOCATOR =>
                -- NOTE: If port is set to something other than UDP_PORT_INVALID, the addr is also guarranteed to be unequal IPv4_ADDRESS_INVALID (and vice versa)
                --       We compare only the port to save on resources (If necessary we could define a bit for that).
                
                -- DEFAULT
                stage_next      <= PARTICIPANT_MATCH_STAGE;
                
                case (message_type) is
                    -- Participant Data
                    when PDP =>
                        if (PREFER_MULTICAST) then
                            --*METATRAFIC*
                            -- Multicast Locator Valid
                            if (meta_mc_port /= UDP_PORT_INVALID) then
                                meta_addr_next  <= meta_mc_addr;
                                meta_port_next  <= meta_mc_port;
                            -- Fallback to given Unicast Locator
                            elsif (meta_uc_port /= UDP_PORT_INVALID) then
                                meta_addr_next  <= meta_uc_addr;
                                meta_port_next  <= meta_uc_port;
                            -- Fallback to Protocol Locator
                            else
                                meta_addr_next  <= DEFAULT_IPv4_META_ADDRESS;
                                meta_port_next  <= META_IPv4_MULTICAST_PORT;
                            end if;
                            --*DEFAULT*
                            -- Multicast Locator Valid
                            if (def_mc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_mc_addr;
                                def_port_next   <= def_mc_port;
                            -- Fallback to given Unicast Locator
                            elsif (def_uc_port /= UDP_PORT_INVALID) then
                                def_addr_next  <= def_uc_addr;
                                def_port_next  <= def_uc_port;
                            -- Fallback to Protocol Locator
                            else
                                def_addr_next  <= DEFAULT_IPv4_META_ADDRESS;
                                def_port_next  <= USER_IPv4_MULTICAST_PORT;
                            end if;
                        else
                            --*METATRAFIC*
                            -- Unicast Locator Valid
                            if (meta_uc_port /= UDP_PORT_INVALID) then
                                meta_addr_next  <= meta_uc_addr;
                                meta_port_next  <= meta_uc_port;
                            -- Fallback to given Multicast Locator
                            elsif (meta_mc_port /= UDP_PORT_INVALID) then
                                meta_addr_next  <= meta_mc_addr;
                                meta_port_next  <= meta_mc_port;
                            -- Fallback to Protocol Locator
                            else
                                meta_addr_next  <= DEFAULT_IPv4_META_ADDRESS;
                                meta_port_next  <= META_IPv4_UNICAST_PORT;
                            end if;
                            --*DEFAULT*
                            -- Unicast Locator Valid
                            if (def_uc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_uc_addr;
                                def_port_next   <= def_uc_port;
                            -- Fallback to given Multicast Locator
                            elsif (def_mc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_mc_addr;
                                def_port_next   <= def_mc_port;
                            -- Fallback to Protocol Locator
                            else
                                def_addr_next   <= DEFAULT_IPv4_META_ADDRESS;
                                def_port_next   <= USER_IPv4_UNICAST_PORT;
                            end if;
                        end if;
                    -- Endpoint Data
                    when EDP =>
                        if (PREFER_MULTICAST) then
                            -- Multicast Locator Valid
                            if (def_mc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_mc_addr;
                                def_port_next   <= def_mc_port;
                            -- Fallback to given Unicast Locator
                            elsif (def_uc_port /= UDP_PORT_INVALID) then
                                def_addr_next  <= def_uc_addr;
                                def_port_next  <= def_uc_port;
                            else
                                -- Participant Default will be used
                                def_addr_next  <= IPv4_ADDRESS_INVALID;
                                def_port_next  <= UDP_PORT_INVALID;
                            end if;
                        else
                            -- Unicast Locator Valid
                            if (def_uc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_uc_addr;
                                def_port_next   <= def_uc_port;
                            -- Fallback to given Multicast Locator
                            elsif (def_mc_port /= UDP_PORT_INVALID) then
                                def_addr_next   <= def_mc_addr;
                                def_port_next   <= def_mc_port;
                            -- Fallback to Protocol Locator
                            else
                                -- Participant Default will be used
                                def_addr_next  <= IPv4_ADDRESS_INVALID;
                                def_port_next  <= UDP_PORT_INVALID;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when LATCH_STRING_LENGTH =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard            := '1';
                    string_length_next  <= unsigned(data_in_swapped);
                    stage_next          <= COMPARE_STRING;
                    compare_length_next <= to_unsigned(1,compare_length'length);
                    string_cnt_next     <= 0;
                end if;
            when COMPARE_STRING =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard            := '1';
                    compare_length_next <= compare_length + 1;
                    string_cnt_next     <= string_cnt + 1;
                    
                    -- NOTE: This assumes that the Parameter is padded with zeroes (Since we also compare the padding)
                    --       XTypes 7.4.1.1 requires padding bytes for "PLAIN_CDR" to be zero, but does not specify the value for "PL_CDR"
                    
                    -- Unmark matches on string comparison missmatch
                    case (string_content) is
                        when TOPIC_NAME_TYPE =>
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (data_in /= ENDPOINT_TOPIC(i)(string_cnt)) then
                                    endpoint_mask_next(i)   <= '0';
                                end if;
                            end loop;
                        when TYPE_NAME_TYPE =>
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (data_in /= ENDPOINT_TYPE(i)(string_cnt)) then
                                    endpoint_mask_next(i)   <= '0';
                                end if;
                            end loop;
                        when DOMAIN_TAG_TYPE =>
                            if (data_in /= DOMAIN_TAG(string_cnt)) then
                                    participant_match_next  <= '0';
                                end if;
                        when others =>
                            null;
                    end case;
                    
                    -- NOTE: "compare_length" counts the 4-Byte words, while "string_length" contains the total string octets/bytes
                    -- End of String (Exit Condition)
                    if ((compare_length & "00") >= string_length) then
                        -- DONE
                        stage_next  <= SKIP_PARAMETER;
                    end if;
                end if;
            when MATCH_GUID =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Check if GUID Prefix valid (Should be the same as the GUID Prefix of the Packet) and update the Entity ID
                    case (cnt) is
                        when 0 =>
                            if (data_in /= guid(0)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        when 1 =>
                            if (data_in /= guid(1)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        when 2 =>
                            if (data_in /= guid(2)) then
                                stage_next  <= SKIP_PACKET;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        when 3 =>
                            guid_next(3)    <= data_in;
                            -- DONE
                            stage_next      <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when MATCH_DOMAIN_ID =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Match Domain ID
                    if (data_in_swapped /= DOMAIN_ID) then
                        participant_match_next  <= '0';
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when MATCH_PROTOCOL_VERSION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Match major Protocol Version
                    if(data_in(31 downto 24) /= PROTOCOLVERSION_2_4(15 downto 8)) then
                        participant_match_next  <= '0';
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when LATCH_LOCATOR =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        -- Locator Kind
                        when 0 =>
                            -- Check if UDPv4 Locator
                            if (data_in_swapped /= LOCATOR_KIND_UDPv4) then
                                -- Skip
                                stage_next  <= SKIP_PARAMETER;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        -- Locator Port
                        when 1 =>
                            -- Latch Source Port
                            -- SANITY CHECK: Check if UDP Port valid
                            if (data_in_swapped(UDP_PORT_INVALID'range) /= UDP_PORT_INVALID) then
                                -- NOTE: We have to make sure that the address is also valid
                                -- Temporal Latch
                                long_latch_next <= data_in_swapped;
                                cnt_next        <= cnt + 1;
                            else
                                -- Ignore
                                stage_next      <= SKIP_PARAMETER;
                            end if;
                        -- Locator Address 1/4
                        when 2 =>
                            cnt_next    <= cnt + 1;
                        -- Locator Address 2/4
                        when 3 =>
                            cnt_next    <= cnt + 1;
                        -- Locator Address 3/4
                        when 4 =>
                            cnt_next    <= cnt + 1;
                        -- Locator Address 4/4 (IPv4)
                        when 5 =>
                            -- Latch Src Addr
                            -- SANITY CHECK: Check if IPv4 Address valid
                            if (data_in_swapped /= IPv4_ADDRESS_INVALID) then
                                if (is_meta_addr = '1') then
                                    if (is_multicast_addr = '1') then
                                        -- Metatraffic Multicast
                                        meta_mc_addr_next   <= data_in;
                                        meta_mc_port_next   <= long_latch(meta_mc_port'length-1 downto 0);
                                    else
                                        -- Metatraffic Unicast
                                        meta_uc_addr_next   <= data_in;
                                        meta_uc_port_next   <= long_latch(meta_uc_port'length-1 downto 0);
                                    end if;
                                else
                                    if (is_multicast_addr = '1') then
                                        -- Endpoint Multicast
                                        def_mc_addr_next    <= data_in;
                                        def_mc_port_next    <= long_latch(def_mc_port'length-1 downto 0);
                                    else
                                        -- Endpoint Unicast
                                        def_uc_addr_next    <= data_in;
                                        def_uc_port_next    <= long_latch(def_uc_port'length-1 downto 0);
                                    end if;
                                end if;
                            end if;
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when LATCH_EXPECTS_INLINE_QOS =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch 'expectsInlineQoS'
                    reader_flags_next(READER_EXPECTS_INLINE_QOS_FLAG)   <= data_in(24);
                    
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when LATCH_LEASE_DURATION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch Lease Duration
                    case (cnt) is
                        when 0 =>
                            lease_duration_next(0)  <= unsigned(data_in_swapped);
                            cnt_next                <= cnt + 1;
                        when 1 =>
                            lease_duration_next(1)  <= unsigned(data_in_swapped);
                            -- DONE
                            stage_next              <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when LATCH_LIFESPAN_DURATION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Latch Lease Duration
                    case (cnt) is
                        when 0 =>
                            lifespan_duration_next(0)   <= unsigned(data_in_swapped);
                            cnt_next                <= cnt + 1;
                        when 1 =>
                            lifespan_duration_next(1)   <= unsigned(data_in_swapped);
                            -- DONE
                            stage_next              <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when CHECK_REMOTE_BUILTIN_ENDPOINTS =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- SANITY CHECK (Builtin Participant and Participant Message Endpoints have to be always available)
                    if (    data_in_swapped(DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER) = '0' or
                            data_in_swapped(DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR) = '0' or
                            data_in_swapped(BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER) = '0' or
                            data_in_swapped(BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER) = '0') then
                        participant_match_next  <= '0';
                    end if;
                    -- Check for necessary Builtin Endpoints for Readers and Writers
                    if (    (NUM_READERS > 0 and (data_in_swapped(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) = '0' or data_in_swapped(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) = '0')) and
                            (NUM_WRITERS > 0 and (data_in_swapped(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER) = '0' or data_in_swapped(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) = '0'))
                    ) then
                        participant_match_next  <= '0';
                    end if;
                    
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when RXO_DURABILITY =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Check QoS Compatibility (Unmark match on incompatibility)
                    -- COMPATIBLE (DDS v1.4): offered >= requested, with VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT
                    for i in 0 to NUM_ENDPOINTS-1 loop
                        if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_CONFIG(i).DURABILITY_QOS))) then
                            endpoint_mask_next(i) <= '0';
                        end if;
                    end loop;
                    
                    -- Set Reader Flag
                    if (is_subscriber = '1') then
                        -- XXX: Quartus Limitation
                        --reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG)  <= '0' when (data_in_swapped = VOLATILE_DURABILITY_QOS) else '1';
                        if (data_in_swapped = VOLATILE_DURABILITY_QOS) then
                            reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG)  <= '0';
                        else
                            reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG)  <= '1';
                        end if;
                    end if;
                    
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when RXO_DEADLINE =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        when 0 =>
                            long_latch_next <= data_in_swapped;
                            cnt_next        <= cnt + 1;
                        when 1 =>
                            tmp_dw  := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped));
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            -- COMPATIBLE (DDS v1.4): offered <= requested
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_CONFIG(i).DEADLINE_QOS)) then
                                    endpoint_mask_next(i) <= '0';
                                end if;
                            end loop;
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when RXO_LIVELINESS =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Check QoS Compatibility (Unmark match on incompatibility)
                    -- COMPATIBLE (DDS v1.4): offered >= requested, with AUTOMATIC < MANUAL_BY_PARTICIPANT < MANUAL_BY_TOPIC
                    for i in 0 to NUM_ENDPOINTS-1 loop
                        if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_CONFIG(i).LIVELINESS_QOS))) then
                            endpoint_mask_next(i) <= '0';
                        end if;
                    end loop;
                    
                    stage_next  <= RXO_LEASE_DURATION;
                    cnt_next    <= 0;
                end if;
            when RXO_LEASE_DURATION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        when 0 =>
                            -- Temporal Latch
                            long_latch_next <= data_in_swapped;
                            cnt_next        <= cnt + 1;
                        when 1 =>
                            tmp_dw  := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped));
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            -- COMPATIBLE (DDS v1.4): offered <= requested
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_CONFIG(i).LEASE_DURATION)) then
                                    endpoint_mask_next(i) <= '0';
                                end if;
                            end loop;
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when RXO_RELIABILITY =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        when 0 =>
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            -- COMPATIBLE (DDS v1.4): offered >= requested, with BEST_EFFORT < RELIABLE
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_CONFIG(i).RELIABILITY_QOS))) then
                                    endpoint_mask_next(i) <= '0';
                                end if;
                            end loop;
                            
                            -- Set Reader Flag
                            if (is_subscriber = '1') then
                                -- XXX: Quartus Limitation
                                --reader_flags_next(READER_IS_BEST_EFFORT_FLAG)  <= '1' when (data_in_swapped = BEST_EFFORT_RELIABILITY_QOS) else '0';
                                if (data_in_swapped = BEST_EFFORT_RELIABILITY_QOS) then
                                    reader_flags_next(READER_IS_BEST_EFFORT_FLAG)  <= '1';
                                else
                                    reader_flags_next(READER_IS_BEST_EFFORT_FLAG)  <= '0';
                                end if;
                            end if;
                            cnt_next    <= cnt + 1;
                        when 1 =>
                            -- NOTE: The max_blocking_time value is ignored
                            cnt_next    <= cnt + 1;
                        when 2 =>
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when RXO_DESTINATION_ORDER =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Check QoS Compatibility (Unmark match on incompatibility)
                    -- COMPATIBLE (DDS v1.4): offered >= requested, with BY_RECEPTION_TIMESTAMP < BY_SOURCE_TIMESTAMP
                    for i in 0 to NUM_ENDPOINTS-1 loop
                        if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_CONFIG(i).DESTINATION_ORDER_QOS))) then
                            endpoint_mask_next(i) <= '0';
                        end if;
                    end loop;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when RXO_OWNERSHIP =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Check QoS Compatibility (Unmark match on incompatibility)
                    -- COMPATIBLE (DDS v1.4): offered = requested
                    for i in 0 to NUM_ENDPOINTS-1 loop
                        if (data_in_swapped /= ENDPOINT_CONFIG(i).OWNERSHIP_QOS) then
                            endpoint_mask_next(i) <= '0';
                        end if;
                    end loop;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when RXO_PRESENTATION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        when 0 =>
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            -- COMPATIBLE (DDS v1.4): offered >= requested, with INSTANCE < TOPIC < GROUP
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_CONFIG(i).PRESENTATION_QOS))) then
                                    endpoint_mask_next(i) <= '0';
                                end if;
                            end loop;
                            cnt_next    <= cnt + 1;
                        when 1 =>
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                -- data-in is Subscriber-Requested
                                -- COMPATIBLE (DDS v1.4): requested=FALSE or requested=offered=TRUE
                                if (is_subscriber = '1') then
                                    if (data_in(24) = '1' and not ENDPOINT_CONFIG(i).COHERENT_ACCESS) then
                                        endpoint_mask_next(i) <= '0';
                                    end if;
                                    if (data_in(16) = '1' and not ENDPOINT_CONFIG(i).ORDERED_ACCESS) then
                                        endpoint_mask_next(i) <= '0';
                                    end if;
                                -- data-in is Publisher-Offered
                                else
                                    if (data_in(24) = '0' and ENDPOINT_CONFIG(i).COHERENT_ACCESS) then
                                        endpoint_mask_next(i) <= '0';
                                    end if;
                                    if (data_in(16) = '0' and ENDPOINT_CONFIG(i).ORDERED_ACCESS) then
                                        endpoint_mask_next(i) <= '0';
                                    end if;
                                end if;
                            end loop;
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when RXO_PARTITION =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- NOTE: Endpoints are only matched against the default empty partition.
                    -- Match Partition Names
                    if (data_in_swapped /= (data_in_swapped'reverse_range => '0')) then
                        endpoint_mask_next <= (others => '0');
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when RXO_LATENCY_BUDGET =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    case (cnt) is
                        when 0 =>
                            long_latch_next <= data_in_swapped;
                            cnt_next        <= cnt + 1;
                        when 1 =>
                            tmp_dw  := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped));
                            -- Check QoS Compatibility (Unmark match on incompatibility)
                            -- COMPATIBLE (DDS v1.4): offered <= requested
                            for i in 0 to NUM_ENDPOINTS-1 loop
                                if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_CONFIG(i).LATENCY_BUDGET_QOS)) then
                                    endpoint_mask_next(i) <= '0';
                                end if;
                            end loop;
                            -- DONE
                            stage_next  <= SKIP_PARAMETER;
                        when others =>
                            null;
                    end case;
                end if;
            when CHECK_MAX_SIZE_SERIALIZED =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Ignore Publishers that may need Fragmentation
                    if (is_subscriber = '0' and unsigned(data_in_swapped) > to_unsigned(UDP_MAX_SIZE_SERIALIZED, CDR_LONG_WIDTH)) then
                        endpoint_mask_next  <= (others => '0');
                    end if;
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when CHECK_STATUS_INFO =>
                -- Input FIFO Guard
                if (empty = '0') then
                    rd_guard    := '1';
                    
                    -- Mark if Unregister/Disposed Status
                    if (data_in(STATUS_INFO_DISPOSED_FLAG) = '1' or data_in(STATUS_INFO_UNREGISTERED_FLAG) = '1') then
                        ud_status_next  <= '1';
                    end if;
                    
                    -- DONE
                    stage_next  <= SKIP_PARAMETER;
                end if;
            when PARTICIPANT_MATCH_STAGE =>
                -- Precondition: participant_data set (PMF_SPDP_SEQ_NR_FLAG/PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG)
                
                -- Wait for Participant Search to finish
                if (mem_op_done = '1') then
                    -- Participant not in Buffer
                    if (participant_data.addr = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                        -- Participant Match
                        if (message_type = PDP and participant_match = '1' and mem_empty_head /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                            -- Add participant in buffer
                            mem_op_start    <= '1';
                            mem_opcode      <= INSERT_PARTICIPANT;
                            mem_r.guid_prefix       <= GUIDPREFIX_TYPE(guid(0 to 2));
                            mem_r.meta_addr         <= meta_addr;
                            mem_r.def_addr          <= def_addr;
                            mem_r.meta_port         <= meta_port;
                            mem_r.def_port          <= def_port;
                            mem_r.spdp_seq_nr       <= next_seq_nr;
                            mem_r.lease_duration    <= lease_duration;
                            tmp_dw                  := time + 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;
                            
                            -- DONE
                            stage_next  <= SKIP_PACKET;
                        else
                            -- Ignore all other messages, since there is no corresponding participant in the buffer.
                            stage_next  <= SKIP_PACKET;
                        end if;
                    -- Participant in Buffer
                    else
                        assert_sn;
                        
                        -- Participant Announcement
                        if (message_type = PDP) then
                            -- Newer Sequence Number
                            if (mem_seq_nr <= seq_nr) then
                                -- Participant Unmatch
                                if (participant_match = '0') then
                                    -- Remove participant from buffer
                                    mem_op_start    <= '1';
                                    mem_opcode      <= REMOVE_PARTICIPANT;
                                    mem_r.addr      <= participant_data.addr;
                                    -- Inform ENDPOINTS
                                    stage_next      <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH;
                                    cnt_next        <= 0;
                                -- Participant remains matched
                                else
                                    -- Update Participant Data and Lease
                                    mem_op_start        <= '1';
                                    mem_opcode          <= UPDATE_PARTICIPANT;
                                    mem_r.addr          <= participant_data.addr;
                                    mem_r.field_flags   <= PMF_META_IPV4_ADDR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_SPDP_SEQ_NR_FLAG or PMF_LEASE_DURATION_FLAG or PMF_LEASE_DEADLINE_FLAG;
                                    mem_r.meta_addr         <= meta_addr;
                                    mem_r.def_addr          <= def_addr;
                                    mem_r.meta_port         <= meta_port;
                                    mem_r.def_port          <= def_port;
                                    mem_r.spdp_seq_nr       <= next_seq_nr;
                                    mem_r.lease_duration    <= lease_duration;
                                    tmp_dw                  := time + 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;
                                    -- DONE
                                    stage_next  <= SKIP_PACKET;
                                end if;
                            -- Old Sequence Number
                            else
                                -- Update Lease
                                mem_op_start            <= '1';
                                mem_opcode              <= UPDATE_PARTICIPANT;
                                mem_r.addr              <= participant_data.addr;
                                mem_r.field_flags       <= PMF_LEASE_DEADLINE_FLAG;
                                tmp_dw                  := time + 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;
                                -- DONE
                                stage_next  <= SKIP_PACKET;
                            end if;
                        -- NOTE:    We only process the Sequences in order. This may lead to more traffic being exchanged 
                        --          (since all Data messages with a higher sequence number than the next expected will be ignored), 
                        --          but keeps the logic simple.
                        -- Endpoint (Next Expected Sequence Number)
                        elsif (message_type = EDP and mem_seq_nr = seq_nr) then
                            -- Store new Sequence Number
                            mem_op_start    <= '1';
                            mem_opcode      <= UPDATE_PARTICIPANT;
                            mem_r.addr      <= participant_data.addr;
                            if (is_subscriber = '0') then
                                mem_r.field_flags   <= PMF_PUB_SEQ_NR_FLAG;
                                mem_r.pub_seq_nr    <= next_seq_nr;
                            else
                                mem_r.field_flags   <= PMF_SUB_SEQ_NR_FLAG;
                                mem_r.sub_seq_nr    <= next_seq_nr;
                            end if;
                            
                            -- At least one local Endpoint match
                            if (endpoint_mask /= (endpoint_mask'range => '0')) then
                                -- Propagate Matches to local Endpoints
                                stage_next  <= INFORM_ENDPOINTS_MATCH;
                                cnt_next    <= 0;
                            -- No local Endpoint matches
                            else
                                -- Propagate Matches to local Endpoints
                                stage_next  <= INFORM_ENDPOINTS_UNMATCH;
                                cnt_next    <= 0;
                            end if;
                        else
                            -- Ignore (Messages are handled in a dedicated stage)
                            stage_next  <= SKIP_PACKET;
                        end if;
                    end if;
                end if;
            when INFORM_ENDPOINTS_MATCH =>
                -- Precondition: participant_data set (PMF_DEFAULT_IPV4_ADDR_FLAG, PMF_UDP_PORT_FLAG)
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, check_mask(participant_data.field_flags, PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG)) severity FAILURE;
                    
                    -- Output FIFO Guard
                    if ((endpoint_mask and full_rtps) = (full_rtps'range => '0')) then
                        wr_sig      <= '1';
                        
                        case (cnt) is
                            -- Match Opcode
                            when 0 =>
                                data_out_sig    <= EMO_ENDPOINT_MATCH;
                                cnt_next        <= cnt + 1;
                            -- GUID Prefix 1/3
                            when 1 =>
                                data_out_sig    <= guid(0);
                                cnt_next        <= cnt + 1;
                            -- GUID Prefix 2/3
                            when 2 =>
                                data_out_sig    <= guid(1);
                                cnt_next        <= cnt + 1;
                            -- GUID Prefix 3/3
                            when 3 =>
                                data_out_sig    <= guid(2);
                                cnt_next        <= cnt + 1;
                            -- Entity ID
                            when 4 =>
                                data_out_sig    <= guid(3);
                                cnt_next        <= cnt + 1;
                            -- IPv4 Address
                            when 5 =>
                                -- If Endpoint did not set Address, use Participant Default
                                if (def_port /= UDP_PORT_INVALID) then -- (See SELECT_LOCATOR on why we check the port)
                                    data_out_sig    <= def_addr;
                                else
                                    data_out_sig    <= participant_data.def_addr;
                                end if;
                                cnt_next    <= cnt + 1;
                            -- UDPv4 Port and Reader Flags
                            when 6 =>
                                -- Default
                                data_out_sig        <= (others => '0');
                                
                                -- If Endpoint did not set Port, use Participant Default
                                if (def_port /= UDP_PORT_INVALID) then
                                    data_out_sig(31 downto 16)  <= def_port;
                                else
                                    data_out_sig(31 downto 16)  <= participant_data.def_port;
                                end if;
                                
                                if (is_subscriber = '1') then
                                    last_word_out_sig           <= '1';
                                    data_out_sig(15 downto 0)   <= reader_flags;
                                    
                                    -- DONE
                                    stage_next  <= INFORM_ENDPOINTS_UNMATCH;
                                    cnt_next    <= 0;
                                else
                                    cnt_next    <= cnt + 1;
                                end if;
                            -- Lifespan Duration 1/2
                            when 7 =>
                                data_out_sig    <= std_logic_vector(lifespan_duration(0));
                                cnt_next        <= cnt + 1;
                            -- Lifespan Duration 2/2
                            when 8 =>
                                last_word_out_sig   <= '1';
                                data_out_sig        <= std_logic_vector(lifespan_duration(1));
                                
                                -- DONE
                                stage_next  <= INFORM_ENDPOINTS_UNMATCH;
                                cnt_next    <= 0;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when INFORM_ENDPOINTS_UNMATCH =>
                -- Output FIFO Guard
                if (((not endpoint_mask) and full_rtps) = (full_rtps'range => '0')) then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- Match Opcode
                        when 0 =>
                            data_out_sig    <= EMO_ENDPOINT_UNMATCH;
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 1/3
                        when 1 =>
                            data_out_sig    <= guid(0);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 2 =>
                            data_out_sig    <= guid(1);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 3 =>
                            data_out_sig    <= guid(2);
                            cnt_next        <= cnt + 1;
                        -- Entity ID
                        when 4 =>
                            data_out_sig        <= guid(3);
                            last_word_out_sig   <= '1';
                            
                            -- DONE
                            stage_next  <= SKIP_PACKET;
                        when others =>
                            null;
                    end case;
                end if;
            when INFORM_ENDPOINTS_PARTICIPANT_UNMATCH =>
                -- Output FIFO Guard
                if (full_rtps = (full_rtps'range => '0')) then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- Match Opcode
                        when 0 =>
                            data_out_sig    <= EMO_PARTICIPANT_UNMATCH;
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 1/3
                        when 1 =>
                            data_out_sig    <= guid(0);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 2 =>
                            data_out_sig    <= guid(1);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 3 =>
                            data_out_sig        <= guid(2);
                            last_word_out_sig   <= '1';
                            
                            -- Currently in Stale Check
                            if (stale_check = '1') then
                                stage_next  <= PARTICIPANT_STALE_CHECK;
                                cnt_next    <= 1; -- GET PARTICIPANT
                            else
                                -- DONE
                                stage_next  <= SKIP_PACKET;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_HEADER =>
                -- Precondition: participant_data set (PMF_META_IPV4_ADDR_FLAG, PMF_UDP_PORT_FLAG) [if return_stage /= SEND_PARTICIPANT_ANNOUNCEMENT]
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    if (return_stage /= SEND_PARTICIPANT_ANNOUNCEMENT) then
                        assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                        assert stable(clk, check_mask(participant_data.field_flags, PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG)) severity FAILURE;
                    end if;
                    
                    if (full_ro = '0') then
                        wr_sig      <= '1';
                        
                        case (cnt) is
                            -- OUTPUT HEADER
                            -- Src IPv4 Address
                            when 0 =>
                                data_out_sig    <= DEFAULT_IPv4_ADDRESS;
                                cnt_next    <= cnt + 1;
                            -- Dest IPv4 Address
                            when 1 =>
                                -- Set Default Multicast Announce Address if Participant Announcement
                                if (return_stage = SEND_PARTICIPANT_ANNOUNCEMENT) then
                                    data_out_sig    <= DEFAULT_IPv4_META_ADDRESS;
                                else
                                    data_out_sig    <= participant_data.meta_addr;
                                end if;
                                cnt_next    <= cnt + 1;
                            -- Src and Dest UDPv4 Ports
                            when 2 =>
                                -- Set Default Multicast Announce Port if Participant Announcement
                                if (return_stage = SEND_PARTICIPANT_ANNOUNCEMENT) then
                                    data_out_sig    <= META_IPv4_UNICAST_PORT & META_IPv4_MULTICAST_PORT;
                                else
                                    data_out_sig    <= META_IPv4_UNICAST_PORT & participant_data.meta_port;
                                end if;
                                cnt_next    <= cnt + 1;
                            -- RTPS MESSAGE HEADER
                            when 3 =>
                                data_out_sig    <= PROTOCOL_RTPS;
                                cnt_next        <= cnt + 1;
                            when 4 =>
                                data_out_sig    <= PROTOCOLVERSION_2_4 & VENDORID;
                                cnt_next        <= cnt + 1;
                            when 5 =>
                                data_out_sig    <= GUIDPREFIX(0);
                                cnt_next        <= cnt + 1;
                            when 6 =>
                                data_out_sig    <= GUIDPREFIX(1);
                                cnt_next        <= cnt + 1;
                            when 7 =>
                                data_out_sig    <= GUIDPREFIX(2);
                                
                                -- Continue with respective RTPS Submessage
                                stage_next                  <= return_stage;
                                cnt_next                    <= 0;
                                participant_data_cnt_next   <= 0;
                                publisher_data_cnt_next     <= 0;
                                subscriber_data_cnt_next    <= 0;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when SEND_PARTICIPANT_ANNOUNCEMENT =>
                if (full_ro = '0') then
                    wr_sig                      <= '1';
                    
                    -- Send Participant Data
                    data_out_sig    <= LOCAL_PARTICIPANT_DATA.data(participant_data_cnt);
                    
                    -- Exit Condition
                    if (participant_data_cnt = (LOCAL_PARTICIPANT_DATA.length-1)) then
                        last_word_out_sig   <= '1';
                        -- DONE
                        stage_next      <= IDLE;
                    else
                        participant_data_cnt_next   <= participant_data_cnt + 1;
                    end if;
                end if;
            when SEND_ACKNACK =>
                -- Precondition: participant_data set (PMF_PUB_SEQ_NR_FLAG, PMF_SUB_SEQ_NR_FLAG, PMF_MES_SEQ_NR_FLAG)
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, check_mask(participant_data.field_flags, PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG)) severity FAILURE;
                    
                    if (full_ro = '0') then
                        wr_sig      <= '1';
                        
                        case (cnt) is
                            -- ACKNACK RTPS SUBMESSAGE (Publication)
                            -- RTPS Submessage Header
                            when 0 =>
                                data_out_sig    <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
                                cnt_next        <= cnt + 1;
                            -- Reader Entity ID
                            when 1 =>
                                data_out_sig    <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
                                cnt_next        <= cnt + 1;
                            -- Writer Entity ID
                            when 2 =>
                                data_out_sig    <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 1/2)
                            when 3 =>
                                data_out_sig    <= std_logic_vector(participant_data.pub_seq_nr(0));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 2/2)
                            when 4 =>
                                data_out_sig    <= std_logic_vector(participant_data.pub_seq_nr(1));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (NumBits)
                            when 5 =>
                                data_out_sig    <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap)
                            when 6 =>
                                -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
                                -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
                                data_out_sig    <= (others => '1');
                                cnt_next        <= cnt + 1;
                            -- Count
                            when 7 =>
                                data_out_sig    <= std_logic_vector(count);
                                cnt_next        <= cnt + 1;
                            -- ACKNACK RTPS SUBMESSAGE (Subscription)
                            -- RTPS Submessage Header
                            when 8 =>
                                data_out_sig    <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
                                cnt_next        <= cnt + 1;
                            -- Reader Entity ID
                            when 9 =>
                                data_out_sig    <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
                                cnt_next        <= cnt + 1;
                            -- Writer Entity ID
                            when 10 =>
                                data_out_sig    <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 1/2)
                            when 11 =>
                                data_out_sig    <= std_logic_vector(participant_data.sub_seq_nr(0));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 2/2)
                            when 12 =>
                                data_out_sig    <= std_logic_vector(participant_data.sub_seq_nr(1));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (NumBits)
                            when 13 =>
                                data_out_sig    <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap)
                            when 14 =>
                                -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
                                -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
                                data_out_sig    <= (others => '1');
                                cnt_next        <= cnt + 1;
                            -- Count
                            when 15 =>
                                data_out_sig    <= std_logic_vector(count);
                                cnt_next        <= cnt + 1;
                            -- ACKNACK RTPS SUBMESSAGE (Message)
                            -- RTPS Submessage Header
                            when 16 =>
                                data_out_sig    <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16));
                                cnt_next        <= cnt + 1;
                            -- Reader Entity ID
                            when 17 =>
                                data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
                                cnt_next        <= cnt + 1;
                            -- Writer Entity ID
                            when 18 =>
                                data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 1/2)
                            when 19 =>
                                data_out_sig    <= std_logic_vector(participant_data.mes_seq_nr(0));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap Base 2/2)
                            when 20 =>
                                data_out_sig    <= std_logic_vector(participant_data.mes_seq_nr(1));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (NumBits)
                            when 21 =>
                                data_out_sig    <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
                                cnt_next        <= cnt + 1;
                            -- Sequence Number Set (Bitmap)
                            when 22 =>
                                -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
                                -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
                                data_out_sig    <= (others => '1');
                                cnt_next        <= cnt + 1;
                            -- Count
                            when 23 =>
                                data_out_sig        <= std_logic_vector(count);
                                last_word_out_sig   <= '1';
                                
                                -- Continue
                                stage_next      <= PARTICIPANT_STALE_CHECK;
                                cnt_next        <= 7; -- POST-ACKNACK-SENT
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when SEND_HEARTBEAT =>
                if (full_ro = '0') then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- HEARTBEAT RTPS SUBMESSAGE (Publication)
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_sig    <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 1 =>
                            data_out_sig    <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 2 =>
                            data_out_sig    <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER;
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 3 =>
                            data_out_sig    <= std_logic_vector(FIRST_SEQUENCENUMBER(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 2/2
                        when 4 =>
                            data_out_sig    <= std_logic_vector(FIRST_SEQUENCENUMBER(1));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 5 =>
                            data_out_sig    <= std_logic_vector(PUB_SEQUENCENUMBER(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 6 =>
                            data_out_sig    <= std_logic_vector(PUB_SEQUENCENUMBER(1));
                            cnt_next        <= cnt + 1;
                        -- Count
                        when 7 =>
                            data_out_sig    <= std_logic_vector(count);
                            cnt_next        <= cnt + 1;
                        -- HEARTBEAT RTPS SUBMESSAGE (Subscription)
                        -- RTPS Submessage Header
                        when 8 =>
                            data_out_sig    <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 9 =>
                            data_out_sig    <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 10 =>
                            data_out_sig    <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER;
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 11 =>
                            data_out_sig    <= std_logic_vector(FIRST_SEQUENCENUMBER(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 2/2
                        when 12 =>
                            data_out_sig    <= std_logic_vector(FIRST_SEQUENCENUMBER(1));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 13 =>
                            data_out_sig    <= std_logic_vector(SUB_SEQUENCENUMBER(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 14 =>
                            data_out_sig    <= std_logic_vector(SUB_SEQUENCENUMBER(1));
                            cnt_next        <= cnt + 1;
                        -- Count
                        when 15 =>
                            data_out_sig    <= std_logic_vector(count);
                            cnt_next        <= cnt + 1;
                        -- HEARTBEAT RTPS SUBMESSAGE (Message)
                        -- RTPS Submessage Header
                        when 16 =>
                            data_out_sig    <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 17 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 18 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 19 =>
                            data_out_sig    <= std_logic_vector(man_live_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 2/2
                        when 20 =>
                            data_out_sig    <= std_logic_vector(man_live_seq_nr(1));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 21 =>
                            data_out_sig    <= std_logic_vector(auto_live_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 22 =>
                            data_out_sig    <= std_logic_vector(auto_live_seq_nr(1));
                            cnt_next        <= cnt + 1;
                        -- Count
                        when 23 =>
                            data_out_sig    <= std_logic_vector(count);
                            
                            -- If manual and automatic sequence numbers are not consecutive, we have only asserted the automatic liveliness
                            if (live_gap_start /= auto_live_seq_nr) then
                                stage_next  <= SEND_MES_AUTO_LIVE;
                                cnt_next    <= 0;
                            -- Else we need to send both (manual and automatic)
                            else
                                stage_next  <= SEND_MES_MAN_LIVE;
                                cnt_next    <= 0;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_PUB_DATA =>
                -- Precondition: participant_data set (PMF_EXTRA_FLAGS_FLAG)
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, check_mask(participant_data.field_flags, PMF_EXTRA_FLAGS_FLAG)) severity FAILURE;
                    
                    -- If Publisher Data not scheduled for response or no Writers available, skip
                    if (not check_mask(participant_data.extra_flags, EF_PUB_DATA_FLAG) or NUM_WRITERS = 0) then
                        stage_next  <= SEND_SUB_DATA;
                    -- Output FIFO Guard
                    elsif (full_ro = '0') then
                        wr_sig                  <= '1';
                        
                        -- Send Publisher Data
                        data_out_sig    <= WRITER_ENDPOINT_DATA.data(publisher_data_cnt);
                        
                        -- Exit Condition
                        if (publisher_data_cnt = (WRITER_ENDPOINT_DATA.length-1)) then
                            last_word_out_sig   <= '1';
                            -- If we still have Data to sent, continue
                            if (check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG) or check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then
                                stage_next          <= SEND_HEADER;
                                return_stage_next   <= SEND_SUB_DATA;
                                cnt_next            <= 0;
                            -- Currently in Stale Check
                            elsif (stale_check = '1') then
                                stage_next  <= PARTICIPANT_STALE_CHECK;
                                cnt_next    <= 8; -- POST-DATA-SENT
                            else
                                -- DONE
                                stage_next  <= IDLE;
                            end if;
                        else
                            publisher_data_cnt_next <= publisher_data_cnt + 1;
                        end if;
                    end if;
                end if;
            when SEND_SUB_DATA =>
                -- Precondition: participant_data set (PMF_EXTRA_FLAGS_FLAG)
                
                -- Wait for Participant Data
                if (mem_op_done = '1') then
                    assert stable(clk, participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, check_mask(participant_data.field_flags, PMF_EXTRA_FLAGS_FLAG)) severity FAILURE;
                    
                    -- If Subscriber Data not scheduled for response or no Readers available, skip
                    if (not check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG) or NUM_READERS = 0) then
                        stage_next  <= SEND_MES_MAN_LIVE;
                        cnt_next    <= 0;
                    -- Output FIFO Guard
                    elsif (full_ro = '0') then
                        wr_sig                      <= '1';
                        
                        -- Send Subscriber Data
                        data_out_sig    <= READER_ENDPOINT_DATA.data(subscriber_data_cnt);
                        
                        -- Exit Condition
                        if (subscriber_data_cnt = (READER_ENDPOINT_DATA.length-1)) then
                            last_word_out_sig   <= '1';
                            -- If we still have Data to sent, continue
                            if (check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then
                                stage_next          <= SEND_HEADER;
                                return_stage_next   <= SEND_MES_MAN_LIVE;
                                cnt_next            <= 0;
                            -- Currently in Stale Check
                            elsif (stale_check = '1') then
                                stage_next  <= PARTICIPANT_STALE_CHECK;
                                cnt_next    <= 8; -- POST-DATA-SENT
                            else
                                -- DONE
                                stage_next  <= IDLE;
                            end if;
                        else
                            subscriber_data_cnt_next    <= subscriber_data_cnt + 1;
                        end if;
                    end if;
                end if;
            when SEND_MES_MAN_LIVE =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- DATA RTPS SUBMESSAGE (Participant Message)
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_sig    <= SID_DATA & "00000100" & std_logic_vector(to_unsigned(44, 16));
                            cnt_next        <= cnt + 1;
                        -- ExtraFlags, octetsToInlineQoS
                        when 1 =>
                            data_out_sig    <= x"0000" & std_logic_vector(to_unsigned(16, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 2 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 3 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 4 =>
                            data_out_sig    <= std_logic_vector(man_live_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 2/2
                        when 5 =>
                            data_out_sig    <= std_logic_vector(man_live_seq_nr(1));
                            cnt_next        <= cnt + 1;
                        -- Serialized Payload Header
                        when 6 =>
                            data_out_sig    <= CDR_BE & x"0000";
                            cnt_next        <= cnt + 1;
                        -- Serialized Payload BEGIN
                        -- GUID Prefix 1/3
                        when 7 =>
                            data_out_sig    <= GUIDPREFIX(0);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 8 =>
                            data_out_sig    <= GUIDPREFIX(1);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 9 =>
                            data_out_sig    <= GUIDPREFIX(2);
                            cnt_next        <= cnt + 1;
                        -- Participant Message Kind
                        when 10 =>
                            data_out_sig    <= PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE;
                            cnt_next        <= cnt + 1;
                        -- Data Length
                        when 11 =>
                            data_out_sig    <= (others => '0');
                            -- If manual and automatic sequence numbers are not consecutive, we need to send a GAP Message
                            if (live_gap_start /= auto_live_seq_nr) then
                                stage_next  <= SEND_MES_GAP;
                                cnt_next    <= 0;
                            else
                                stage_next  <= SEND_MES_AUTO_LIVE;
                                cnt_next    <= 0;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_MES_GAP =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- DATA RTPS SUBMESSAGE (Participant Message)
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_sig    <= SID_GAP & "00000000" & std_logic_vector(to_unsigned(28, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 1 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 2 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
                            cnt_next        <= cnt + 1;
                        -- GAP Start Sequence Number 1/2
                        when 3 =>
                            data_out_sig    <= std_logic_vector(live_gap_start(0));
                            cnt_next        <= cnt + 1;
                        -- GAP Start Sequence Number 2/2
                        when 4 =>
                            data_out_sig    <= std_logic_vector(live_gap_start(1));
                            cnt_next        <= cnt + 1;
                        -- GAP End Sequence Number Set (Bitmap Base 1/2)
                        when 5 =>
                            data_out_sig    <= std_logic_vector(live_gap_end(0));
                            cnt_next        <= cnt + 1;
                        -- GAP End Sequence Number Set (Bitmap Base 2/2)
                        when 6 =>
                            data_out_sig    <= std_logic_vector(live_gap_end(1));
                            cnt_next        <= cnt + 1;
                        -- GAP End Sequence Number Set (NumBits)
                        when 7 =>
                            data_out_sig    <= (others => '0');
                            stage_next      <= SEND_MES_AUTO_LIVE;
                            cnt_next        <= 0;
                        when others =>
                            null;
                    end case;
                end if;
            when SEND_MES_AUTO_LIVE =>
                -- Output FIFO Guard
                if (full_ro = '0') then
                    wr_sig      <= '1';
                    
                    case (cnt) is
                        -- DATA RTPS SUBMESSAGE (Participant Message)
                        -- RTPS Submessage Header
                        when 0 =>
                            data_out_sig    <= SID_DATA & "00000100" & std_logic_vector(to_unsigned(44, 16));
                            cnt_next        <= cnt + 1;
                        -- ExtraFlags, octetsToInlineQoS
                        when 1 =>
                            data_out_sig    <= x"0000" & std_logic_vector(to_unsigned(16, 16));
                            cnt_next        <= cnt + 1;
                        -- Reader Entity ID
                        when 2 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER;
                            cnt_next        <= cnt + 1;
                        -- Writer Entity ID
                        when 3 =>
                            data_out_sig    <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER;
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 1/2
                        when 4 =>
                            data_out_sig    <= std_logic_vector(auto_live_seq_nr(0));
                            cnt_next        <= cnt + 1;
                        -- Sequence Number 2/2
                        when 5 =>
                            data_out_sig    <= std_logic_vector(auto_live_seq_nr(1));
                            cnt_next        <= cnt + 1;
                        -- Serialized Payload Header
                        when 6 =>
                            data_out_sig    <= CDR_BE & x"0000";
                            cnt_next        <= cnt + 1;
                        -- Serialized Payload BEGIN
                        -- GUID Prefix 1/3
                        when 7 =>
                            data_out_sig    <= GUIDPREFIX(0);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 2/3
                        when 8 =>
                            data_out_sig    <= GUIDPREFIX(1);
                            cnt_next        <= cnt + 1;
                        -- GUID Prefix 3/3
                        when 9 =>
                            data_out_sig    <= GUIDPREFIX(2);
                            cnt_next        <= cnt + 1;
                        -- Participant Message Kind
                        when 10 =>
                            data_out_sig    <= PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE;
                            cnt_next        <= cnt + 1;
                        -- Data Length
                        when 11 =>
                            data_out_sig        <= (others => '0');
                            last_word_out_sig   <= '1';
                            
                            -- If we are in the middle of a liveliness assertion, find the next Participant destination
                            if (is_live_assert = '1') then
                                assert (mem_op_done = '1') severity FAILURE;
                                assert (participant_data.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                                mem_op_start        <= '1';
                                mem_opcode          <= GET_NEXT_PARTICIPANT;
                                mem_r.addr          <= participant_data.addr;
                                mem_r.field_flags   <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG;
                                stage_next          <= FIND_PARTICIPANT_DEST;
                            -- Currently in Stale Check
                            elsif (stale_check = '1') then
                                stage_next  <= PARTICIPANT_STALE_CHECK;
                                cnt_next    <= 8; -- POST-DATA-SENT
                            else
                                -- DONE
                                stage_next      <= IDLE;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SKIP_PARAMETER =>
                -- Consumed last word of Packet
                if (last_word_in_latch = '1' and last_word_in = '0') then
                    -- Reset Last Word In Latch
                    last_word_in_latch_next <= '0';
                    -- Continue parsing next Packet
                    stage_next              <= IDLE;
                    -- Reset Parameter End
                    parameter_end_next  <= (others => '1');
                -- End of Parameter
                elsif ((read_cnt & "00" ) >= parameter_end) then
                    -- Parse Next Parameter
                    -- NOTE: data_in is already showing the next parameter
                    stage_next          <= PROCESS_PL;
                    -- Reset Parameter End
                    parameter_end_next  <= (others => '1');
                -- Input FIFO Guard
                elsif (empty = '0') then
                    -- Skip-Read
                    rd_guard    := '1';
                end if;
            when SKIP_PACKET =>
                -- NOTE: At the end of a Stale Entry Removal this stage is entered, without having started reading a Packet from input.
                -- Reset Parameter End
                parameter_end_next  <= (others => '1');
                
                -- Consumed last word of Packet
                if (last_word_in_latch = '1' and last_word_in = '0') then
                    -- Reset Last Word In Latch
                    last_word_in_latch_next <= '0';
                    -- DONE
                    stage_next              <= IDLE;
                -- Input FIFO Guard
                elsif (empty = '0') then
                    -- Skip-Read
                    rd_guard    := '1';
                end if;
        end case;
        
        -- OVERREAD GUARD
        -- Read outside of packet Length
        -- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while
        --       the Packet Length has been reached and will be caught by this clause.
        --       The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
        if ((last_word_in_latch = '1' and last_word_in = '0') and rd_guard = '1') then
            -- Force rd_sig low
            rd_sig                  <= '0';
            -- Notify Endpoints of EOP
            last_word_out_sig       <= '1'; -- TODO: Necessary? (We do not pass through input to output, so a EOP should not leave us "stranded" during a write out)
            -- Continue parsing next Packet
            stage_next              <= IDLE;
            -- Reset Last Word In Latch
            last_word_in_latch_next <= '0';
            -- Reset Parameter End
            parameter_end_next      <= (others => '1');
        -- Read outside of Parameter Length
        -- NOTE: If the Parameter Length is smaller than expected for a particular parameter, there will be a read from input FIFO while
        --       the Parameter Length has been reached and will be caught by this clause.
        --       The SKIP_PARAMETER clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
        elsif ((read_cnt & "00") >= parameter_end and rd_guard = '1') then
            -- Force rd_sig low
            rd_sig              <= '0';
            -- Notify Endpoints of EOP
            last_word_out_sig   <= '1';
            -- Invalid Parameter Length, Skip Packet
            stage_next          <= SKIP_PACKET;
            -- Reset Parameter End
            parameter_end_next  <= (others => '1');
        -- DEFAULT
        else
            rd_sig  <= rd_guard;
        end if;
    end process;
    
    empty_head_sig  <= to_integer(mem_empty_head);
    
    -- *Participant Memory Process*
    -- STATE                DESCRIPTION
    -- IDLE                 Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
    -- SEARCH_PARTICIPANT   See Memory OPCODE Description
    -- GET_NEXT_PARTICIPANT See Memory OPCODE Description
    -- GET_PARTICIPANT_DATA Latch specified Participant Data for use by main process
    -- INSERT_PARTICIPANT   See Memory OPCODE Description
    -- UPDATE_PARTICIPANT   See Memory OPCODE Description
    -- REMOVE_PARTICIPANT   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_addr_latch_next         <= mem_addr_latch;
        mem_empty_head_next         <= mem_empty_head;
        mem_occupied_head_next      <= mem_occupied_head;
        mem_cnt_next                <= mem_cnt;
        participant_data_next       <= participant_data;
        participant_latch_data_next <= participant_latch_data;
        -- DEFAULT Unregistered
        mem_abort_read  <= '0';
        mem_ready_out   <= '0';
        mem_valid_in    <= '0';
        mem_read        <= '0';
        mem_op_done     <= '0';
        mem_addr        <= (others => '0');
        mem_write_data  <= (others => '0');
        
        
        case (mem_stage) is
            when IDLE =>
                mem_op_done    <= '1';
                
                if (mem_op_start = '1') then
                    -- Latch Signals needed for Mermory Operation
                    participant_latch_data_next <= mem_r;
                    
                    case(mem_opcode) is
                        when SEARCH_PARTICIPANT =>
                            -- Reset Data
                            participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            
                            -- Memory Empty
                            if (mem_occupied_head /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next      <= mem_occupied_head;
                                mem_stage_next          <= SEARCH_PARTICIPANT;
                                mem_cnt_next            <= 0;
                            end if;
                        when INSERT_PARTICIPANT =>
                            assert (mem_empty_head /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                            -- Reset Data
                            participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            participant_data_next.addr  <= mem_empty_head;
                            
                            mem_addr_base_next      <= mem_empty_head;
                            mem_stage_next          <= INSERT_PARTICIPANT;
                            mem_cnt_next            <= 0;
                        when UPDATE_PARTICIPANT =>
                            if (mem_r.addr = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                -- Reset Data
                                participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            else
                                if (mem_r.addr /= participant_data.addr) then
                                    participant_data_next   <= ZERO_PARTICIPANT_DATA;
                                end if;
                                
                                participant_data_next.addr  <= mem_r.addr;
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= UPDATE_PARTICIPANT;
                                if check_mask(mem_r.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_r.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 1;
                                elsif check_mask(mem_r.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 2;
                                elsif check_mask(mem_r.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 3;
                                elsif check_mask(mem_r.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(mem_r.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 7;
                                elsif check_mask(mem_r.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 9;
                                elsif check_mask(mem_r.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(mem_r.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(mem_r.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 14;
                                elsif check_mask(mem_r.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 16;
                                elsif check_mask(mem_r.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 18;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        when REMOVE_PARTICIPANT =>
                            -- Reset
                            participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            
                            if (mem_r.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= REMOVE_PARTICIPANT;
                                mem_cnt_next        <= 0;
                            end if;
                        when GET_NEXT_PARTICIPANT =>
                            -- Reset
                            participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            
                            if (mem_r.addr /= PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= GET_NEXT_PARTICIPANT;
                                mem_cnt_next        <= 0;
                            end if;
                        when GET_PARTICIPANT =>
                            if (mem_r.addr = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                -- Reset Data
                                participant_data_next   <= ZERO_PARTICIPANT_DATA;
                            else
                                if (mem_r.addr /= participant_data.addr) then
                                    participant_data_next   <= ZERO_PARTICIPANT_DATA;
                                end if;
                                participant_data_next.addr  <= mem_r.addr;
                                
                                mem_addr_base_next  <= mem_r.addr;
                                mem_stage_next      <= GET_PARTICIPANT_DATA;
                                if check_mask(mem_r.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(mem_r.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 3;
                                elsif check_mask(mem_r.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(mem_r.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(mem_r.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(mem_r.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(mem_r.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(mem_r.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(mem_r.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 13;
                                elsif check_mask(mem_r.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(mem_r.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 17;
                                elsif check_mask(mem_r.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(mem_r.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 21;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEARCH_PARTICIPANT =>
                
                case (mem_cnt) is
                    -- GET GUID Prefix 1/3
                    when 0 =>
                        mem_valid_in   <= '1';
                        mem_addr       <= mem_addr_base + PMF_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 1 =>
                        mem_valid_in   <= '1';
                        mem_addr       <= mem_addr_base + PMF_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 2 =>
                        mem_valid_in   <= '1';
                        mem_addr       <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 2;
                        mem_read       <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- READ GUID Prefix 1/3
                    when 3 =>
                        mem_ready_out  <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No Match
                            if (mem_read_data /= participant_latch_data.guid_prefix(0)) then
                                mem_abort_read  <= '1';
                                mem_cnt_next    <= 6; -- GET Next Participant
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- READ GUID Prefix 2/3
                    when 4 =>
                        mem_ready_out  <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No Match
                            if (mem_read_data /= participant_latch_data.guid_prefix(1)) then
                                mem_abort_read  <= '1';
                                mem_cnt_next    <= 6; -- GET Next Participant
                            else
                                mem_cnt_next    <= mem_cnt + 1;
                            end if;
                        end if;
                    -- READ GUID Prefix 3/3
                    when 5 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No Match
                            if (mem_read_data /= participant_latch_data.guid_prefix(2)) then
                                mem_abort_read  <= '1';
                                mem_cnt_next    <= 6; -- GET Next Participant
                            else
                                participant_data_next.addr  <= mem_addr_base;
                                
                                -- Get Participant Data
                                mem_stage_next <= GET_PARTICIPANT_DATA;
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 3;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 13;
                                elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 17;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 21;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        end if;
                    -- GET Next Addr
                    when 6 =>
                        mem_addr        <= mem_addr_base + PMF_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 7 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            -- No more Endpoints
                            if (resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH) = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                participant_data_next.addr  <= PARTICIPANT_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                mem_stage_next      <= IDLE;
                            else
                                -- Continue
                                mem_addr_base_next  <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH);
                                mem_cnt_next        <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_NEXT_PARTICIPANT =>
                case (mem_cnt) is
                    -- GET Next Participant
                    when 0 =>
                        mem_valid_in   <= '1';
                        mem_addr       <= mem_addr_base + PMF_NEXT_ADDR_OFFSET;
                        mem_read       <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- READ Next Participant
                    when 1 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            if (resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH) = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                participant_data_next.addr  <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                                -- DONE
                                mem_stage_next  <= IDLE;
                            else
                                participant_data_next.addr  <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH);
                                
                                -- Get Instance Data
                                mem_addr_base_next  <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH);
                                mem_stage_next  <= GET_PARTICIPANT_DATA;
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 0;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 3;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 4;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 5;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 6;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 8;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 10;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 12;
                                elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 13;
                                elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 15;
                                elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 17;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 19;
                                elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 21;
                                else
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                end if;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_PARTICIPANT_DATA =>
                case (mem_cnt) is
                    -- GET GUID Prefix 1/3
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_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 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_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 2 =>
                        mem_valid_in   <= '1';
                        mem_addr       <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 2;
                        mem_read       <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 3;
                            elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                mem_cnt_next    <= 23;
                            end if;
                        end if;
                    -- GET Metatraffic IPv4 Address
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 4;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                else
                                    mem_cnt_next    <= 26;
                                end if;
                            end if;
                        end if;
                    -- GET Default IPv4 Address
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                else
                                    mem_cnt_next    <= 27;
                                end if;
                            end if;
                        end if;
                    -- GET UDP Ports
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_UDP_PORT_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 6;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                else
                                    mem_cnt_next    <= 28;
                                end if;
                            end if;
                        end if;
                    -- GET SPDP Sequence Number 1/2
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- GET SPDP Sequence Number 2/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 8;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                else
                                    mem_cnt_next    <= 29;
                                end if;
                            end if;
                        end if;
                    -- GET Lease Duration 1/2
                    when 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- GET Lease Duration 2/2
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                else
                                    mem_cnt_next    <= 31;
                                end if;
                            end if;
                        end if;
                    -- GET Lease Deadline 1/2
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_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 11 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                else
                                    mem_cnt_next    <= 33;
                                end if;
                            end if;
                        end if;
                    -- GET Extra Flags
                    when 12 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 13;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 33;
                                else
                                    mem_cnt_next    <= 35;
                                end if;
                            end if;
                        end if;
                    -- GET ACKNACK Response Time 1/2
                    when 13 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_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 ACKNACK Response Time 2/2
                    when 14 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 15;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 33;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 35;
                                else
                                    mem_cnt_next    <= 36;
                                end if;
                            end if;
                        end if;
                    -- GET HEARTBEAT Response Time 1/2
                    when 15 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_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 HEARTBEAT Response Time 2/2
                    when 16 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 17;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 33;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 35;
                                elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 36;
                                else
                                    mem_cnt_next    <= 38;
                                end if;
                            end if;
                        end if;
                    -- GET Publication Sequence Number 1/2
                    when 17 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- GET Publication Sequence Number 2/2
                    when 18 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 19;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 33;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 35;
                                elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 36;
                                elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 38;
                                else
                                    mem_cnt_next    <= 40;
                                end if;
                            end if;
                        end if;
                    -- GET Subscription Sequence Number 1/2
                    when 19 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- GET Subscription Sequence Number 2/2
                    when 20 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 21;
                            else
                                if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                    mem_cnt_next    <= 23;
                                elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 26;
                                elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                    mem_cnt_next    <= 27;
                                elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                    mem_cnt_next    <= 28;
                                elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 29;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                    mem_cnt_next    <= 31;
                                elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                    mem_cnt_next    <= 33;
                                elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                    mem_cnt_next    <= 35;
                                elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 36;
                                elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                    mem_cnt_next    <= 38;
                                elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                    mem_cnt_next    <= 40;
                                else
                                    mem_cnt_next    <= 42;
                                end if;
                            end if;
                        end if;
                    -- GET Message Sequence Number 1/2
                    when 21 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next   <= mem_cnt + 1;
                        end if;
                    -- GET Message Sequence Number 2/2
                    when 22 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1;
                        mem_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then
                                mem_cnt_next    <= 23;
                            elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 26;
                            elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 28;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 29;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            else
                                mem_cnt_next    <= 44;
                            end if;
                        end if;
                    -- READ GUID Prefix 1/3
                    when 23 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.guid_prefix(0)    <= mem_read_data;
                            mem_cnt_next                            <= mem_cnt + 1;
                        end if;
                    -- READ GUID Prefix 2/3
                    when 24 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.guid_prefix(1)    <= mem_read_data;
                            mem_cnt_next                            <= mem_cnt + 1;
                        end if;
                    -- READ GUID Prefix 3/3
                    when 25 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.guid_prefix(2)    <= mem_read_data;
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_GUIDPREFIX_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 26;
                            elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 28;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 29;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Metatraffic IPv4 Address
                    when 26 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.meta_addr <= mem_read_data;
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_META_IPV4_ADDR_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 27;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 28;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 29;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Default IPv4 Address
                    when 27 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.def_addr  <= mem_read_data;
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_DEFAULT_IPV4_ADDR_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 28;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 29;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ UDP Ports
                    when 28 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.meta_port <= mem_read_data(WORD_WIDTH-1 downto UDP_PORT_WIDTH);
                            participant_data_next.def_port  <= mem_read_data(UDP_PORT_WIDTH-1 downto 0);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_UDP_PORT_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 29;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ SPDP Sequence Number 1/2
                    when 29 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.spdp_seq_nr(0)    <= unsigned(mem_read_data);
                            mem_cnt_next                            <= mem_cnt + 1;
                        end if;
                    -- READ SPDP Sequence Number 2/2
                    when 30 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.spdp_seq_nr(1)    <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_SPDP_SEQ_NR_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 31;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Lease Duration 1/2
                    when 31 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.lease_duration(0) <= unsigned(mem_read_data);
                            mem_cnt_next                            <= mem_cnt + 1;
                        end if;
                    -- READ Lease Duration 2/2
                    when 32 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.lease_duration(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DURATION_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 33;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Lease Deadline 1/2
                    when 33 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.lease_deadline(0) <= unsigned(mem_read_data);
                            mem_cnt_next                            <= mem_cnt + 1;
                        end if;
                    -- READ Lease Deadline 2/2
                    when 34 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.lease_deadline(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DEADLINE_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 35;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Extra Flags
                    when 35 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.extra_flags   <= mem_read_data(EF_FLAG_WIDTH-1 downto 0);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_EXTRA_FLAGS_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 36;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ ACKNACK Response Time 1/2
                    when 36 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.acknack_res_time(0)   <= unsigned(mem_read_data);
                            mem_cnt_next                                <= mem_cnt + 1;
                        end if;
                    -- READ ACKNACK Response Time 2/2
                    when 37 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.acknack_res_time(1)   <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_ACKNACK_RES_TIME_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 38;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ HEARTBEAT Response Time 1/2
                    when 38 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.heartbeat_res_time(0) <= unsigned(mem_read_data);
                            mem_cnt_next                                <= mem_cnt + 1;
                        end if;
                    -- READ HEARTBEAT Response Time 2/2
                    when 39 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.heartbeat_res_time(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_HEARTBEAT_RES_TIME_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 40;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Publication Sequence Number 1/2
                    when 40 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.pub_seq_nr(0) <= unsigned(mem_read_data);
                            mem_cnt_next                        <= mem_cnt + 1;
                        end if;
                    -- READ Publication Sequence Number 2/2
                    when 41 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.pub_seq_nr(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_PUB_SEQ_NR_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 42;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Subscription Sequence Number 1/2
                    when 42 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.sub_seq_nr(0) <= unsigned(mem_read_data);
                            mem_cnt_next                        <= mem_cnt + 1;
                        end if;
                    -- READ Subscription Sequence Number 2/2
                    when 43 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.sub_seq_nr(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_SUB_SEQ_NR_FLAG;
                            
                            if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 44;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- READ Message Sequence Number 1/2
                    when 44 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.mes_seq_nr(0) <= unsigned(mem_read_data);
                            mem_cnt_next                        <= mem_cnt + 1;
                        end if;
                    -- READ Message Sequence Number 2/2
                    when 45 =>
                        mem_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            participant_data_next.mes_seq_nr(1) <= unsigned(mem_read_data);
                            participant_data_next.field_flags   <= participant_data.field_flags or PMF_MES_SEQ_NR_FLAG;
                            
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when INSERT_PARTICIPANT =>
                -- Precondition: mem_addr_base set
                
                case (mem_cnt) is
                    -- GET Next Addr
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_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 GUID Prefix 1/3
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_GUIDPREFIX_OFFSET;
                        mem_write_data  <= participant_latch_data.guid_prefix(0);
                        participant_data_next.guid_prefix(0)    <= participant_latch_data.guid_prefix(0);
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET GUID Prefix 2/3
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 1;
                        mem_write_data  <= participant_latch_data.guid_prefix(1);
                        participant_data_next.guid_prefix(1)    <= participant_latch_data.guid_prefix(1);
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET GUID Prefix 3/3
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 2;
                        mem_write_data  <= participant_latch_data.guid_prefix(2);
                        participant_data_next.guid_prefix(2)    <= participant_latch_data.guid_prefix(2);
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_GUIDPREFIX_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Metatraffic IPv4 Address
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET;
                        mem_write_data  <= participant_latch_data.meta_addr;
                        participant_data_next.meta_addr <= participant_latch_data.meta_addr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_META_IPV4_ADDR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Default IPv4 Address
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET;
                        mem_write_data  <= participant_latch_data.def_addr;
                        participant_data_next.def_addr  <= participant_latch_data.def_addr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_DEFAULT_IPV4_ADDR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET UDP Ports
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_UDP_PORT_OFFSET;
                        mem_write_data  <= participant_latch_data.meta_port & participant_latch_data.def_port;
                        participant_data_next.meta_port <= participant_latch_data.meta_port;
                        participant_data_next.def_port  <= participant_latch_data.def_port;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_UDP_PORT_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET SPDP Sequence Number 1/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.spdp_seq_nr(0));
                        participant_data_next.spdp_seq_nr(0)    <= participant_latch_data.spdp_seq_nr(0);
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET SPDP Sequence Number 2/2
                    when 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.spdp_seq_nr(1));
                        participant_data_next.spdp_seq_nr(1)    <= participant_latch_data.spdp_seq_nr(1);
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_SPDP_SEQ_NR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Duration 1/2
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_duration(0));
                        participant_data_next.lease_duration(0) <= participant_latch_data.lease_duration(0);
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Duration 2/2
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_duration(1));
                        participant_data_next.lease_duration(1) <= participant_latch_data.lease_duration(1);
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DURATION_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Deadline 1/2
                    when 11 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_deadline(0));
                        participant_data_next.lease_deadline(0) <= participant_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 12 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_deadline(1));
                        participant_data_next.lease_deadline(1) <= participant_latch_data.lease_deadline(1);
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DEADLINE_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Extra Flags
                    when 13 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET;
                        mem_write_data                      <= (others => '0');
                        participant_data_next.extra_flags   <= (others => '0');
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_EXTRA_FLAGS_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACKNACK Response Time 1/2
                    when 14 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(0));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACKNACK Response Time 2/2
                    when 15 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(1));
                        participant_data_next.acknack_res_time  <= TIME_INVALID;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_ACKNACK_RES_TIME_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET HEARTBEAT Response Time 1/2
                    when 16 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(0));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET HEARTBEAT Response Time 2/2
                    when 17 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(TIME_INVALID(1));
                        participant_data_next.heartbeat_res_time    <= TIME_INVALID;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_HEARTBEAT_RES_TIME_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Publication Sequence Number 1/2
                    when 18 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(0));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Publication Sequence Number 2/2
                    when 19 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(1));
                        participant_data_next.pub_seq_nr    <= FIRST_SEQUENCENUMBER;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_PUB_SEQ_NR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Subscription Sequence Number 1/2
                    when 20 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(0));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Subscription Sequence Number 2/2
                    when 21 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(1));
                        participant_data_next.sub_seq_nr    <= FIRST_SEQUENCENUMBER;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_SUB_SEQ_NR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Message Sequence Number 1/2
                    when 22 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(0));
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Message Sequence Number 2/2
                    when 23 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(FIRST_SEQUENCENUMBER(1));
                        participant_data_next.mes_seq_nr    <= FIRST_SEQUENCENUMBER;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_MES_SEQ_NR_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Next Addr
                    when 24 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_occupied_head,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Prev Addr
                    when 25 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PREV_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(PARTICIPANT_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            if (mem_occupied_head = PARTICIPANT_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 26 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_occupied_head + PMF_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 27 =>
                        mem_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (mem_valid_out = '1') then
                            
                            -- Update List Heads
                            mem_empty_head_next     <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH);
                            mem_occupied_head_next  <= mem_addr_base;
                            
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    
                    when others => 
                        null;
                end case;
            when UPDATE_PARTICIPANT =>
                case (mem_cnt) is
                    -- SET Metatraffic IPv4 Address
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET;
                        mem_write_data  <= participant_latch_data.meta_addr;
                        participant_data_next.meta_addr <= participant_latch_data.meta_addr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_META_IPV4_ADDR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then
                                mem_cnt_next    <= 1;
                            elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 2;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 3;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 7;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Default IPv4 Address
                    when 1 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET;
                        mem_write_data  <= participant_latch_data.def_addr;
                        participant_data_next.def_addr  <= participant_latch_data.def_addr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_DEFAULT_IPV4_ADDR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then
                                mem_cnt_next    <= 2;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 3;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 7;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET UDP Ports
                    when 2 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_UDP_PORT_OFFSET;
                        mem_write_data  <= participant_latch_data.meta_port & participant_latch_data.def_port;
                        participant_data_next.meta_port <= participant_latch_data.meta_port;
                        participant_data_next.def_port  <= participant_latch_data.def_port;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_UDP_PORT_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 3;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 7;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET SPDP Sequence Number 1/2
                    when 3 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.spdp_seq_nr(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET SPDP Sequence Number 2/2
                    when 4 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.spdp_seq_nr(1));
                        participant_data_next.spdp_seq_nr   <= participant_latch_data.spdp_seq_nr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_SPDP_SEQ_NR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then
                                mem_cnt_next    <= 5;
                            elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 7;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Lease Duration 1/2
                    when 5 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_duration(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Lease Duration 2/2
                    when 6 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_duration(1));
                        participant_data_next.lease_duration    <= participant_latch_data.lease_duration;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DURATION_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then
                                mem_cnt_next    <= 7;
                            elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Lease Deadline 1/2
                    when 7 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_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 8 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.lease_deadline(1));
                        participant_data_next.lease_deadline    <= participant_latch_data.lease_deadline;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_LEASE_DEADLINE_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then
                                mem_cnt_next    <= 9;
                            elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Extra Flags
                    when 9 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET;
                        mem_write_data                                  <= (others => '0');
                        mem_write_data(EF_FLAG_WIDTH-1 downto 0)    <= participant_latch_data.extra_flags;
                        participant_data_next.extra_flags   <= participant_latch_data.extra_flags;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_EXTRA_FLAGS_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then
                                mem_cnt_next    <= 10;
                            elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET ACKNACK Response Time 1/2
                    when 10 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.acknack_res_time(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET ACKNACK Response Time 2/2
                    when 11 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.acknack_res_time(1));
                        participant_data_next.acknack_res_time  <= participant_latch_data.acknack_res_time;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_ACKNACK_RES_TIME_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then
                                mem_cnt_next    <= 12;
                            elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET HEARTBEAT Response Time 1/2
                    when 12 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.heartbeat_res_time(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET HEARTBEAT Response Time 2/2
                    when 13 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.heartbeat_res_time(1));
                        participant_data_next.heartbeat_res_time    <= participant_latch_data.heartbeat_res_time;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_HEARTBEAT_RES_TIME_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 14;
                            elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Publication Sequence Number 1/2
                    when 14 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.pub_seq_nr(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Publication Sequence Number 2/2
                    when 15 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.pub_seq_nr(1));
                        participant_data_next.pub_seq_nr    <= participant_latch_data.pub_seq_nr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_PUB_SEQ_NR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 16;
                            elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Subscription Sequence Number 1/2
                    when 16 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.sub_seq_nr(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Subscription Sequence Number 2/2
                    when 17 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.sub_seq_nr(1));
                        participant_data_next.sub_seq_nr    <= participant_latch_data.sub_seq_nr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_SUB_SEQ_NR_FLAG;
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then
                                mem_cnt_next    <= 18;
                            else
                                -- DONE
                                mem_stage_next  <= IDLE;
                            end if;
                        end if;
                    -- SET Message Sequence Number 1/2
                    when 18 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET;
                        mem_write_data  <= std_logic_vector(participant_latch_data.mes_seq_nr(0));
                        -- Memory Flow Control Guard
                        if (mem_ready_in = '1') then
                            mem_cnt_next    <= mem_cnt + 1;
                        end if;
                    -- SET Message Sequence Number 2/2
                    when 19 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1;
                        mem_write_data  <= std_logic_vector(participant_latch_data.mes_seq_nr(1));
                        participant_data_next.mes_seq_nr    <= participant_latch_data.mes_seq_nr;
                        participant_data_next.field_flags   <= participant_data.field_flags or PMF_MES_SEQ_NR_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_PARTICIPANT =>
                -- Precondition: mem_addr_base set
                
                case (mem_cnt) is
                    -- GET Next Addr
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_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 + PMF_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 + PMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_empty_head,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            -- Set New Empty Head
                            mem_empty_head_next <= 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),PARTICIPANT_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 = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                if (resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH) = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                    -- RESET Occupied List Head
                                    mem_occupied_head_next  <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                                    
                                    participant_data_next.addr  <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                                    -- DONE
                                    mem_stage_next  <= IDLE;
                                else
                                    mem_addr_base_next  <= resize(unsigned(mem_read_data),PARTICIPANT_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),PARTICIPANT_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 + PMF_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 = PARTICIPANT_MEMORY_MAX_ADDRESS) then
                                -- Set New Occupied List Head
                                mem_occupied_head_next  <= mem_addr_base;
                                participant_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 + PMF_NEXT_ADDR_OFFSET;
                        mem_write_data  <= std_logic_vector(resize(mem_addr_latch,WORD_WIDTH));
                        
                        if (mem_ready_in = '1') then
                            participant_data_next.addr  <= mem_addr_latch;
                            -- DONE
                            mem_stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_MEMORY =>
                case (mem_cnt) is
                    -- SET Next Pointer
                    when 0 =>
                        mem_valid_in    <= '1';
                        mem_addr        <= mem_addr_base + PMF_NEXT_ADDR_OFFSET;
                        if (mem_addr_base = MAX_PARTICIPANT_ADDRESS) then
                            mem_write_data  <= std_logic_vector(resize(PARTICIPANT_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        else
                            mem_write_data  <= std_logic_vector(resize(mem_addr_base + PARTICIPANT_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 + PMF_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_PARTICIPANT_ADDRESS) then
                                -- Initialize Empty and Occupied Heads
                                mem_empty_head_next     <= FIRST_PARTICIPANT_ADDRESS;
                                mem_occupied_head_next  <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                                
                                -- DONE
                                mem_stage_next  <= IDLE;
                            else
                                mem_addr_latch_next <= mem_addr_base;
                                mem_addr_base_next  <= mem_addr_base + PARTICIPANT_FRAME_SIZE;
                                mem_cnt_next        <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
        end case;
    end process;
    
    -- Process responsible for counting read words
    -- This process uses the actual FIFO read signals to determine reads
    word_counter_prc : process(clk, reset)
    begin
        if rising_edge(clk) then
            -- Reset Read counter
            if (reset = '1' or reset_read_cnt = '1') then
                read_cnt    <= (others => '0');
            -- Increment read counter each time rd is high
            elsif (rd_sig = '1') then
                read_cnt    <= read_cnt + 1;
            end if;
        end if;
    end process;
    
    sync: process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage                       <= IDLE;
                return_stage                <= IDLE;
                mem_stage                   <= RESET_MEMORY;
                message_type                <= NONE;
                string_content              <= DOMAIN_TAG_TYPE;
                src_addr                    <= IPv4_ADDRESS_INVALID;
                def_mc_addr                 <= IPv4_ADDRESS_INVALID;
                def_uc_addr                 <= IPv4_ADDRESS_INVALID;
                meta_mc_addr                <= IPv4_ADDRESS_INVALID;
                meta_uc_addr                <= IPv4_ADDRESS_INVALID;
                def_mc_port                 <= UDP_PORT_INVALID;
                def_uc_port                 <= UDP_PORT_INVALID;
                meta_mc_port                <= UDP_PORT_INVALID;
                meta_uc_port                <= UDP_PORT_INVALID;
                src_port                    <= UDP_PORT_INVALID;
                guid                        <= GUID_UNKNOWN;
                src_entityid                <= ENTITYID_UNKNOWN;
                dest_entityid               <= ENTITYID_UNKNOWN;
                mem_addr_base               <= FIRST_PARTICIPANT_ADDRESS;
                mem_addr_latch              <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                mem_empty_head              <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                mem_occupied_head           <= PARTICIPANT_MEMORY_MAX_ADDRESS;
                seq_nr                      <= SEQUENCENUMBER_UNKNOWN;
                next_seq_nr                 <= SEQUENCENUMBER_UNKNOWN;
                sn_latch_1                  <= SEQUENCENUMBER_UNKNOWN;
                sn_latch_2                  <= SEQUENCENUMBER_UNKNOWN;
                sn_latch_3                  <= SEQUENCENUMBER_UNKNOWN;
                auto_live_seq_nr            <= to_double_word(to_unsigned(2, 64));
                man_live_seq_nr             <= FIRST_SEQUENCENUMBER;
                live_gap_start              <= to_double_word(to_unsigned(2, 64));
                live_gap_end                <= FIRST_SEQUENCENUMBER;
                lease_duration              <= DURATION_ZERO;
                lifespan_duration           <= DURATION_ZERO;
                check_time                  <= TIME_INVALID;
                announcement_time           <= time;
                heartbeat_time              <= time + HEARTBEAT_PERIOD;
                participant_data            <= ZERO_PARTICIPANT_DATA;
                participant_latch_data      <= ZERO_PARTICIPANT_DATA;
                cnt                         <= 0;
                cnt2                        <= 0;
                bitmap_pos                  <= 0;
                mem_cnt                     <= 0;
                participant_data_cnt        <= 0;
                publisher_data_cnt          <= 0;
                subscriber_data_cnt         <= 0;
                string_cnt                  <= 0;
                participant_match           <= '0';
                is_subscriber               <= '0';
                is_meta_addr                <= '0';
                is_multicast_addr           <= '0';
                stale_check                 <= '0';
                is_live_assert              <= '0';
                last_word_in_latch          <= '0';
                ud_status                   <= '0';
                parameter_end               <= (others => '1');
                opcode                      <= SID_PAD;
                flags                       <= (others => '0');
                string_length               <= (others => '0');
                compare_length              <= (others => '0');
                endpoint_mask               <= (others => '0');
                count                       <= (others => '0');
                long_latch                  <= (others => '0');
                rcvd                        <= (others => '0');
                reader_flags                <= (others => '0');
                bitmap_cnt                  <= (others => '0');
                bitmap_latch                <= (others => (others => '0'));
            else
                stage                       <= stage_next;
                return_stage                <= return_stage_next;
                mem_stage                   <= mem_stage_next;
                message_type                <= message_type_next;
                string_content              <= string_content_next;
                src_addr                    <= src_addr_next;
                def_mc_addr                 <= def_mc_addr_next;
                def_uc_addr                 <= def_uc_addr_next;
                meta_mc_addr                <= meta_mc_addr_next;
                meta_uc_addr                <= meta_uc_addr_next;
                def_mc_port                 <= def_mc_port_next;
                def_uc_port                 <= def_uc_port_next;
                meta_mc_port                <= meta_mc_port_next;
                meta_uc_port                <= meta_uc_port_next;
                src_port                    <= src_port_next;
                guid                        <= guid_next;
                src_entityid                <= src_entityid_next;
                dest_entityid               <= dest_entityid_next;
                mem_addr_base               <= mem_addr_base_next;
                mem_addr_latch              <= mem_addr_latch_next;
                mem_empty_head              <= mem_empty_head_next;
                mem_occupied_head           <= mem_occupied_head_next;
                seq_nr                      <= seq_nr_next;
                next_seq_nr                 <= next_seq_nr_next;
                sn_latch_1                  <= sn_latch_1_next;
                sn_latch_2                  <= sn_latch_2_next;
                sn_latch_3                  <= sn_latch_3_next;
                auto_live_seq_nr            <= auto_live_seq_nr_next;
                man_live_seq_nr             <= man_live_seq_nr_next;
                live_gap_start              <= live_gap_start_next;
                live_gap_end                <= live_gap_end_next;
                lease_duration              <= lease_duration_next;
                lifespan_duration           <= lifespan_duration_next;
                check_time                  <= check_time_next;
                announcement_time           <= announcement_time_next;
                heartbeat_time              <= heartbeat_time_next;
                participant_data            <= participant_data_next;
                participant_latch_data      <= participant_latch_data_next;
                cnt                         <= cnt_next;
                cnt2                        <= cnt2_next;
                bitmap_pos                  <= bitmap_pos_next;
                mem_cnt                     <= mem_cnt_next;
                participant_data_cnt        <= participant_data_cnt_next;
                publisher_data_cnt          <= publisher_data_cnt_next;
                subscriber_data_cnt         <= subscriber_data_cnt_next;
                string_cnt                  <= string_cnt_next;
                participant_match           <= participant_match_next;
                is_subscriber               <= is_subscriber_next;
                is_meta_addr                <= is_meta_addr_next;
                is_multicast_addr           <= is_multicast_addr_next;
                stale_check                 <= stale_check_next;
                is_live_assert              <= is_live_assert_next;
                last_word_in_latch          <= last_word_in_latch_next;
                ud_status                   <= ud_status_next;
                parameter_end               <= parameter_end_next;
                opcode                      <= opcode_next;
                flags                       <= flags_next;
                string_length               <= string_length_next;
                compare_length              <= compare_length_next;
                endpoint_mask               <= endpoint_mask_next;
                count                       <= count_next;
                long_latch                  <= long_latch_next;
                rcvd                        <= rcvd_next;
                reader_flags                <= reader_flags_next;
                bitmap_cnt                  <= bitmap_cnt_next;
                bitmap_latch                <= bitmap_latch_next;
            end if;
        end if;
    end process;
    
end architecture;
