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;

-- TODO: Check if sample_cnt is always maintained (also with MAX_SAMPLES_PER_INSTANCE = LENGTH_UNLIMITED)

entity dds_writer is
    generic (
        HISTORY_QOS                 : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
        DEADLINE_QOS                : DURATION_TYPE;
        LIFESPAN_QOS                : DURATION_TYPE;
        LEASE_DURATION              : DURATION_TYPE;
        WITH_KEY                    : boolean;
        MAX_SAMPLES                 : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        MAX_INSTANCES               : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        MAX_SAMPLES_PER_INSTANCE    : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        PAYLOAD_FRAME_SIZE          : natural
    );
    port (
        -- SYSTEM
        clk                     : in std_logic;
        reset                   : in std_logic;
        time                    : in TIME_TYPE;
        -- TO/FROM RTPS ENDPOINT
        start_rtps              : in std_logic;
        opcode_rtps             : in HISTORY_CACHE_OPCODE_TYPE;
        ack_rtps                : out std_logic;
        done_rtps               : out std_logic;
        ret_rtps                : out HISTORY_CACHE_RESPONSE_TYPE;
        seq_nr_rtps             : in SEQUENCENUMBER_TYPE;
        get_data_rtps           : in std_logic;
        data_out_rtps           : out std_logic_vector(WORD_WIDTH-1 downto 0);
        valid_out_rtps          : out std_logic;
        ready_out_rtps          : in std_logic;
        last_word_out_rtps      : out std_logic; 
        liveliness_assertion    : out std_logic;
        data_available          : out std_logic;
        -- Cache Change
        cc_instance_handle      : out INSTANCE_HANDLE_TYPE;
        cc_kind                 : out CACHE_CHANGE_KIND_TYPE;
        cc_source_timestamp     : out TIME_TYPE;
        cc_seq_nr               : out SEQUENCENUMBER_TYPE;
        -- TO/FROM KEY_HOLDER
        start_kh                : out std_logic;
        opcode_kh               : out KEY_HOLDER_OPCODE_TYPE;
        ack_kh                  : in std_logic;
        data_in_kh              : in std_logic_vector(WORD_WIDTH-1 downto 0);
        valid_in_kh             : in std_logic;
        ready_in_kh             : out std_logic;
        last_word_in_kh         : in std_logic;
        data_out_kh             : out std_logic_vector(WORD_WIDTH-1 downto 0);
        valid_out_kh            : out std_logic;
        ready_out_kh            : in std_logic;
        last_word_out_kh        : out std_logic;
        abort_kh                : out std_logic;
        -- TO/FROM USER ENTITY
        start_dds               : in std_logic;
        ack_dds                 : out std_logic;
        opcode_dds              : in DDS_WRITER_OPCODE_TYPE;
        instance_handle_dds     : in INSTANCE_HANDLE_TYPE;
        source_ts_dds           : in TIME_TYPE;
        max_wait_dds            : in DURATION_TYPE;
        done_dds                : out std_logic;
        return_code_dds         : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        ready_in_dds            : out std_logic;
        valid_in_dds            : in std_logic;
        data_in_dds             : in std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_in_dds        : in std_logic;
        ready_out_dds           : in std_logic;
        valid_out_dds           : out std_logic;
        data_out_dds            : out std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_out_dds       : out std_logic;
        -- Communication Status
        status                  : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0)
    );
end entity;

architecture arch of dds_writer is
    
    --*****CONSTANT DECLARATION*****
    -- *SAMPLE MEMORY*
    -- 4-Byte Word Size of a Sample Info Entry in Memory
    function gen_frame_size(lifespan : DURATION_TYPE; WITH_KEY : boolean) return natural is
        variable ret : natural := 0;
    begin
        if (lifespan /= DURATION_INFINITE and WITH_KEY) then
            return 11;
        elsif (lifespan /= DURATION_INFINITE and (not WITH_KEY)) then
            return 10;
        elsif (lifespan = DURATION_INFINITE and WITH_KEY) then
            return 9;
        else --lifespan = DURATION_INFINITE and (not WITH_KEY)
            return 8;
        end if;
    end function;
    constant SAMPLE_FRAME_SIZE          : natural := gen_frame_size(LIFESPAN_QOS,WITH_KEY);
    -- Sample Info Memory Size in 4-Byte Words
    constant SAMPLE_MEMORY_SIZE         : natural := to_integer(unsigned(MAX_SAMPLES)+1) * SAMPLE_FRAME_SIZE;
    -- Sample Info Memory Address Width
    constant SAMPLE_MEMORY_ADDR_WIDTH   : natural := log2c(SAMPLE_MEMORY_SIZE);
    -- Highest Sample Info Memory Address
    constant SAMPLE_MEMORY_MAX_ADDRESS  : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH);
    -- Highest Sample Info Frame Address
    constant MAX_SAMPLE_ADDRESS         : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Sample Data Frame
    constant FIRST_SAMPLE_ADDRESS       : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *PAYLOAD MEMORY*
    -- Payload Memory Size in 4-Byte Words
    constant PAYLOAD_MEMORY_SIZE        : natural := to_integer(unsigned(MAX_SAMPLES)+1) * PAYLOAD_FRAME_SIZE;
    -- Payload Memory Address Width
    constant PAYLOAD_MEMORY_ADDR_WIDTH  : natural := log2c(PAYLOAD_MEMORY_SIZE);
    -- Highest Payload Memory Address
    constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH);
    -- Highest Payload Frame Address
    constant MAX_PAYLOAD_ADDRESS        : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Payload Data Frame
    constant FIRST_PAYLOAD_ADDRESS      : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *INSTANCE MEMORY*
    -- 4-Byte Word Size of a Instance Entry in Memory
    constant INSTANCE_FRAME_SIZE        : natural := 8;
    -- Instance Memory Size in 4-Byte Words
    constant INSTANCE_MEMORY_SIZE       : natural := to_integer(unsigned(MAX_INSTANCES)) * INSTANCE_FRAME_SIZE;
    -- Instance Memory Address Width
    constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE);
    -- Highest Instance Memory Address
    constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH);
    -- Highest Instance Frame Address
    constant MAX_INSTANCE_ADDRESS       : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Instance Data Frame
    constant FIRST_INSTANCE_ADDRESS     : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *SAMPLE MEMORY FRAME FORMAT*
    -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
    constant SMF_STATUS_INFO_OFFSET         : natural := 0;
    constant SMF_SEQ_NR_OFFSET              : natural := 1;
    constant SMF_TIMESTAMP_OFFSET           : natural := 3;
    constant SMF_LIFESPAN_DEADLINE_OFFSET   : natural := 5;
    function gen_smf_payload_addr_offset(lifespan : DURATION_TYPE) return natural is
        variable ret : natural := 0;
    begin
        ret := (SMF_LIFESPAN_DEADLINE_OFFSET + 2) when (lifespan /= DURATION_INFINITE) else SMF_LIFESPAN_DEADLINE_OFFSET;
        return ret;
    end function;
    constant SMF_PAYLOAD_ADDR_OFFSET        : natural := gen_smf_payload_addr_offset(LIFESPAN_QOS);
    constant SMF_INSTANCE_ADDR_OFFSET       : natural := SMF_PAYLOAD_ADDR_OFFSET + 1;
    function gen_smf_prev_addr_offset(WITH_KEY : boolean) return natural is
        variable ret : natural := 0;
    begin
        ret := (SMF_INSTANCE_ADDR_OFFSET + 1) when WITH_KEY else SMF_INSTANCE_ADDR_OFFSET;
        return ret;
    end function;
    constant SMF_PREV_ADDR_OFFSET           : natural := gen_smf_prev_addr_offset(WITH_KEY);
    constant SMF_NEXT_ADDR_OFFSET           : natural := SMF_PREV_ADDR_OFFSET + 1;
    
    -- *PAYLOAD MEMORY FRAME FORMAT*
    -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
    constant PMF_NEXT_ADDR_OFFSET   : natural := 0;
    constant PMF_PAYLOAD_OFFSET     : natural := 1;
    
    -- *INSTANCE MEMORY FRAME OFFSET*
    -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
    constant IMF_NEXT_ADDR_OFFSET           : natural := 0;
    constant IMF_KEY_HASH_OFFSET            : natural := 1;
    constant IMF_STATUS_INFO_OFFSET         : natural := 5;
    constant IMF_SAMPLE_CNT_OFFSET          : natural := 6;
    constant IMF_ACK_CNT_OFFSET             : natural := 7;
    
    -- *INSTANCE MEMORY FRAME FORMAT FLAGS*
    -- Flags mapping to the respective Endpoint Memory Frame Fields
    constant IMF_FLAG_WIDTH : natural := 4;
    constant IMF_KEY_HASH_FLAG          : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (0 => '1', others => '0');
    constant IMF_STATUS_FLAG            : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (1 => '1', others => '0');
    constant IMF_SAMPLE_CNT_FLAG        : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (2 => '1', others => '0');
    constant IMF_ACK_CNT_FLAG           : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (3 => '1', others => '0');
    
    --*****TYPE DECLARATION*****
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE, UNKNOWN_OPERATION_DDS, UNKNOWN_OPERATION_RTPS, UNKNOWN_SEQ_NR, ASSERT_LIVELINESS, ADD_SAMPLE_INFO, ADD_PAYLOAD, NEXT_PAYLOAD_SLOT, 
        ALIGN_PAYLOAD, GET_KEY_HASH, INITIATE_INSTANCE_SEARCH, REGISTER_OPERATION, LOOKUP_OPERATION, PUSH_KEY_HASH, FILTER_STAGE, UPDATE_INSTANCE, 
        FINALIZE_PAYLOAD, FINALIZE_SAMPLE, GET_OLDEST_SAMPLE_INSTANCE, FIND_SAMPLE, REMOVE_ORPHAN_SAMPLES, REMOVE_SAMPLE, 
        POST_SAMPLE_REMOVE, SKIP_AND_RETURN, SKIP, REMOVE_STALE_INSTANCE, GET_SEQ_NR, FIND_SEQ_NR, ACKNACK_SAMPLE, GET_SAMPLE, GET_PAYLOAD, GET_SERIALIZED_KEY,
        CHECK_LIFESPAN, GET_LIVELINESS_LOST_STATUS, GET_OFFERED_DEADLINE_MISSED_STATUS, CHECK_DEADLINE, RESET_SAMPLE_MEMORY, RESET_PAYLOAD_MEMORY);
    -- Instance Memory FSM states. Explained below in detail
    type INST_STAGE_TYPE is (IDLE, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, GET_NEXT_INSTANCE, GET_INSTANCE_DATA, INSERT_INSTANCE, UPDATE_INSTANCE, 
        REMOVE_INSTANCE, RESET_MEMORY);
    -- *Instance Memory Opcodes*
    -- OPCODE                   DESCRIPTION
    -- SEARCH_INSTANCE_HASH     Search Instance based on Key Hash pointed by key_hash.
    -- SEARCH_INSTANCE_ADDR     Search Instance based on Instance Pointer pointed by inst_addr_update. [This is needed to mark the previous Instance for Instance Removal]
    -- INSERT_INSTANCE          Insert Instance to memory. The Instance is inserted in Key Hash Numerical Order.
    -- UPDATE_INSTANCE          Update Instance Data pointed by inst_addr_base. (inst_mem_fields specifies which Fields to update)
    -- GET_FIRST_INSTANCE       Get Instance Data of first Instance (Instance with smallest Key Hash Numerical Order). (inst_mem_fields specifies which Fields to get)
    -- GET_NEXT_INSTANCE        Get Instance Data of next Instance (from the Instance pointed by inst_addr_base) (inst_mem_fields specifies which Fields to get)
    -- REMOVE_INSTANCE          Remove Instance pointed by inst_addr_base
    -- GET_INSTANCE             Get Data of Instance pointed by inst_addr_update. (inst_mem_fields specifies which Fields to get)
    type INSTANCE_OPCODE_TYPE is (NOP, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, INSERT_INSTANCE, UPDATE_INSTANCE, GET_FIRST_INSTANCE, GET_NEXT_INSTANCE, REMOVE_INSTANCE, 
        GET_INSTANCE);
    -- Record of Instance Data
    type INSTANCE_DATA_TYPE is record
        key_hash            : KEY_HASH_TYPE;
        status_info         : std_logic_vector(WORD_WIDTH-1 downto 0);
        sample_cnt          : unsigned(WORD_WIDTH-1 downto 0);
        ack_cnt             : unsigned(WORD_WIDTH-1 downto 0);
    end record;
    -- Zero initialized Endpoint Data
    constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := (
        key_hash            => (others => (others => '0')),
        status_info         => (others => '0'),
        sample_cnt          => (others => '0'),
        ack_cnt             => (others => '0')
    );
    -- Instance Data Latch used as temporal cache by Instance Memory FSM
    type INST_LATCH_DATA_TYPE is record
        key_hash        : KEY_HASH_TYPE;
        status_info     : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        sample_cnt      : unsigned(CDR_LONG_WIDTH-1 downto 0);
        ack_cnt         : unsigned(CDR_LONG_WIDTH-1 downto 0);
        field_flags     : std_logic_vector(0 to IMF_FLAG_WIDTH-1);
        addr            : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    end record;
    -- Zero initialized Instance Data Latch
    constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := (
        key_hash        => (others => (others => '0')),
        status_info     => (others => '0'),
        sample_cnt      => (others => '0'),
        ack_cnt         => (others => '0'),
        field_flags     => (others => '0'),
        addr            => (others => '0')
    );
    
    --*****SIGNAL DECLARATION
    -- *SAMPLE MEMORY CONNECTION SIGNALS*
    signal sample_addr : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_read : std_logic := '0';
    signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    signal sample_ready_in, sample_valid_in : std_logic := '0';
    signal sample_ready_out, sample_valid_out : std_logic := '0';
    signal sample_abort_read : std_logic := '0';
    
    -- *PAYLOAD MEMORY CONNECTION SIGNALS*
    signal payload_addr : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal payload_read : std_logic := '0';
    signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    signal payload_ready_in, payload_valid_in : std_logic := '0';
    signal payload_ready_out, payload_valid_out : std_logic := '0';
    signal payload_abort_read : std_logic := '0';
    
    -- *INSTANCE MEMORY CONNECTION SIGNALS*
    signal inst_addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_read : std_logic := '0';
    signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    signal inst_ready_in, inst_valid_in : std_logic := '0';
    signal inst_ready_out, inst_valid_out : std_logic := '0';
    signal inst_abort_read : std_logic := '0';
    
    -- *MAIN PROCESS*
    -- FSM state
    signal stage, stage_next : STAGE_TYPE := IDLE;
    -- FSM state latch. Used to transition dynamically to different states from the same state.
    signal return_stage, return_stage_next : STAGE_TYPE := IDLE;
    -- General Purpose Counter
    signal cnt, cnt_next : natural range 0 to 14 := 0;
    -- Counter used to read/write Payload Fames
    signal cnt2, cnt2_next : natural range 0 to max(PAYLOAD_FRAME_SIZE, INSTANCE_HANDLE_TYPE'length-1) := 0;
    -- Counter used to read/write Payload Fames
    signal cnt3, cnt3_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0;
    -- Head of Empty Sample List
    signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Tail of Empty Sample List
    signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Head of Empty Payload List
    signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Oldest Sample (Head of Occupied Sample List)
    signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Newest Sample (Tail of Occupied Sample List)
    signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Denotes if the oldest Sample should be removed
    signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0';
    -- Denotes if the oldest sample of the Instance with 'key_hash' should be removed
    signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0';
    -- Denotes if the Sample tobe removed should be ACKed
    signal remove_ack_sample, remove_ack_sample_next : std_logic := '0';
    -- Lifespan Latch
    signal lifespan, lifespan_next : TIME_TYPE := TIME_INVALID;
    -- Key hash Latch
    signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0'));
    -- Return Code Latch
    signal return_code_latch, return_code_latch_next : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0) := (others => '0');
    -- Instance Handle Latch
    signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE := HANDLE_NIL;
    -- Source Timestamp Latch
    signal source_ts, source_ts_next : TIME_TYPE := TIME_INVALID;
    -- Sequence Number Latch
    signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
    -- Sample Status Info Latch
    signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Payload Pointer
    signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Payload Pointer
    signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Sample Pointer
    signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Sample Pointer
    signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Sample Pointer
    signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Sample Pointer
    signal sample_addr_latch_4, sample_addr_latch_4_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Instance Pointer
    signal inst_addr_latch_1, inst_addr_latch_1_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Instance Pointer
    signal inst_addr_latch_2, inst_addr_latch_2_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- General Purpose Long Latch
    signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    -- Signal used to pass Sample Status Infos to Instance Memory Process
    signal status_info_update : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    -- Signal used to pass TIMEs to the Instance Memory Process
    signal deadline : TIME_TYPE := TIME_INVALID;
    -- Signal containing the relevant Instance Memory Frame Fields of the Instance Memory Operation
    signal inst_mem_fields : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0');
    -- Signal used to pass Instance Pointers to the Instance Memory Process
    signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Signal used to pass Sample Counts to the Instance Memory Process
    signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    -- Signal used to pass ACK Counts to the Instance Memory Process
    signal ack_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    -- Signals start of Instance Memory Operation
    signal inst_op_start : std_logic := '0';
    -- Opcode of Instance Memory Operation (Valid only when inst_op_start is high)
    signal inst_opcode  : INSTANCE_OPCODE_TYPE := NOP;
    -- Signals the end of an Instance Memory Operation
    signal inst_op_done : std_logic := '0';
    -- Time of next Sample Lifespan Check
    signal lifespan_time, lifespan_time_next : TIME_TYPE := TIME_ZERO;
    -- Signifies if a Lifespan Check is in progress
    signal is_lifespan_check, is_lifespan_check_next : std_logic := '0';
    -- Signal used to generate the monotonically rising Sequence Numbers
    -- It contains the next applicable Sequence Number
    signal global_seq_nr, global_seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
    -- Signal containing the current number of stored samples
    signal global_sample_cnt, global_sample_cnt_next : natural range 0 to to_integer(unsigned(MAX_SAMPLES)+1) := 0;
    -- Signal containing the current number of ACKed stored samples
    signal global_ack_cnt, global_ack_cnt_next : natural range 0 to to_integer(unsigned(MAX_SAMPLES)+1) := 0;
    -- Signal containing the number of currently stale Instances
    signal stale_inst_cnt, stale_inst_cnt_next : natural range 0 to to_integer(unsigned(MAX_INSTANCES)) := 0;
    -- Signifies if a Instance Register Operation is in progress
    signal register_op, register_op_next : std_logic := '0';
    -- Signifies if a Instance Lookup Operation is in progress
    signal lookup_op, lookup_op_next : std_logic := '0';
    -- Signifies if a WAIT_FOR_ACKNOWLEDGEMENT Operation is in progress
    signal ack_wait, ack_wait_next : std_logic := '0';
    -- Timout time for DDS Operation
    signal timeout_time, timeout_time_next : TIME_TYPE := TIME_INVALID;
    -- Signal used to differentiate between ACK and NACK Operations
    signal is_ack, is_ack_next : std_logic := '0';
    -- Signal used to differentiate between RTPS and DDS Operations
    signal is_rtps, is_rtps_next : std_logic := '0';
    -- Signifies if new Samples are available for RTPS Writer
    signal data_available_sig, data_available_sig_next : std_logic := '0';
    -- Denotes if Orphan Samples (of an removed stale instance) need to be removed
    signal orphan_samples, orphan_samples_next : std_logic := '0';
    -- Test signal used for testbench synchronisation
    signal idle_sig : std_logic := '0';
    
    
    -- *COMMUNICATION STATUS*
    signal status_sig, status_sig_next : std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) := (others => '0');
    -- LIVELINESS LOST STATUS
    -- Time of next Liveliness Deadline
    signal lease_deadline, lease_deadline_next : TIME_TYPE := TIME_INVALID;
    signal liveliness_lost_cnt, liveliness_lost_cnt_next : unsigned(LIVELINESS_LOST_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal liveliness_lost_cnt_change, liveliness_lost_cnt_change_next : unsigned(LIVELINESS_LOST_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    -- SAMPLE REJECT STATUS
    signal sample_rej_cnt, sample_rej_cnt_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal sample_rej_cnt_change, sample_rej_cnt_change_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal sample_rej_last_reason, sample_rej_last_reason_next : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := (others =>'0');
    signal sample_rej_last_inst, sample_rej_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0'));
    -- OFFERED DEADLINE MISSED STATUS
    -- Time of next Deadline Miss Check
    signal deadline_time, deadline_time_next : TIME_TYPE := TIME_ZERO;
    signal deadline_miss_cnt, deadline_miss_cnt_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal deadline_miss_cnt_change, deadline_miss_cnt_change_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal deadline_miss_last_inst, deadline_miss_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0'));
    
    -- *CACHE CHANGE*
    signal cc_instance_handle_sig, cc_instance_handle_sig_next : INSTANCE_HANDLE_TYPE := HANDLE_NIL;
    signal cc_kind_sig, cc_kind_sig_next : CACHE_CHANGE_KIND_TYPE := ALIVE;
    signal cc_source_timestamp_sig, cc_source_timestamp_sig_next : TIME_TYPE := TIME_INVALID;
    signal cc_seq_nr_sig, cc_seq_nr_sig_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
    
    -- *INSTANCE MEMORY PROCESS*
    -- Instance Memory FSM state
    signal inst_stage, inst_stage_next  : INST_STAGE_TYPE := IDLE;
    -- Pointer to current relevant Instance Memory Frame Address
    signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Pointer to next Instance Memory Frame Address
    signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Pointer to previous Instacne Memory Address
    signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Head of Empty Instance List
    signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Head of Occupied Instance List
    signal inst_occupied_head, inst_occupied_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    -- Latch for Instance Data from main process
    signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA;
    -- NOTE: The next signal is driven by the inst_ctrl_prc. In case WITH_KEY is FALSE, no inst_ctrl_prc is generated and the inst_data is
    --       set by the main process directly by drivng the next2 signal. The sync_prc is responsible for latching the corrct next signal.
    -- Latch for Instance Data from memory
    signal inst_data, inst_data_next, inst_data_next2 : INSTANCE_DATA_TYPE := ZERO_INSTANCE_DATA;
    -- General Purpose Counter
    signal inst_cnt, inst_cnt_next : natural range 0 to 13 := 0;
    -- General Purpose Long Latch
    signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    
    --*****ALIAS DECLARATION*****
    alias prev_sample           : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1;
    alias prev_sample_next      : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next;
    alias next_sample           : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2;
    alias next_sample_next      : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2_next;
    alias cur_sample            : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3;
    alias cur_sample_next       : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3_next;
    alias new_sample            : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4;
    alias new_sample_next       : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4_next;
    alias cur_payload           : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1;
    alias cur_payload_next      : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next;
    alias next_payload          : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2;
    alias next_payload_next     : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next;
    alias first_payload         : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2;
    alias first_payload_next    : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next;
    alias cur_inst              : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1;
    alias cur_inst_next         : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_1_next;
    alias next_inst             : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2;
    alias next_inst_next        : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2_next;
    alias dead_inst             : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2;
    alias dead_inst_next        : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) is inst_addr_latch_2_next;
    
    -- *FUNCTION DECLARATION*
    function to_unsigned(input : KEY_HASH_TYPE) return unsigned is
        variable ret : unsigned((KEY_HASH_WIDTH*WORD_WIDTH)-1 downto 0) := (others => '0');
    begin
        for i in 0 to KEY_HASH_WIDTH-1 loop
            ret(((KEY_HASH_WIDTH-i)*WORD_WIDTH)-1 downto (KEY_HASH_WIDTH-1-i)*WORD_WIDTH) := unsigned(input(i));
        end loop;
        return ret;
    end function;
    
begin
    
    --*****COMPONENT INSTANTIATION*****
    
    sample_mem_ctrl_inst : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => SAMPLE_MEMORY_ADDR_WIDTH,
            DATA_WIDTH          => WORD_WIDTH,
            MEMORY_DEPTH        => SAMPLE_MEMORY_SIZE,
            MAX_BURST_LENGTH    => SAMPLE_FRAME_SIZE
        )
        port map (
            clk         => clk,
            reset       => reset or sample_abort_read,
            addr        => std_logic_vector(sample_addr),
            read        => sample_read,
            ready_in    => sample_ready_in,
            valid_in    => sample_valid_in,
            data_in     => sample_write_data,
            ready_out   => sample_ready_out,
            valid_out   => sample_valid_out,
            data_out    => sample_read_data
        );
    
    payload_mem_ctrl_inst : entity work.mem_ctrl(arch)
        generic map (
            ADDR_WIDTH          => PAYLOAD_MEMORY_ADDR_WIDTH,
            DATA_WIDTH          => WORD_WIDTH,
            MEMORY_DEPTH        => PAYLOAD_MEMORY_SIZE,
            MAX_BURST_LENGTH    => PAYLOAD_FRAME_SIZE
        )
        port map (
            clk         => clk,
            reset       => reset or payload_abort_read,
            addr        => std_logic_vector(payload_addr),
            read        => payload_read,
            ready_in    => payload_ready_in,
            valid_in    => payload_valid_in,
            data_in     => payload_write_data,
            ready_out   => payload_ready_out,
            valid_out   => payload_valid_out,
            data_out    => payload_read_data
        );
    
    gen_instance_mem_ctrl_inst : if WITH_KEY generate
        instance_mem_ctrl_inst : entity work.mem_ctrl(arch)
            generic map (
                ADDR_WIDTH          => INSTANCE_MEMORY_ADDR_WIDTH,
                DATA_WIDTH          => WORD_WIDTH,
                MEMORY_DEPTH        => INSTANCE_MEMORY_SIZE,
                MAX_BURST_LENGTH    => INSTANCE_FRAME_SIZE
            )
            port map (
                clk         => clk,
                reset       => reset or inst_abort_read,
                addr        => std_logic_vector(inst_addr),
                read        => inst_read,
                ready_in    => inst_ready_in,
                valid_in    => inst_valid_in,
                data_in     => inst_write_data,
                ready_out   => inst_ready_out,
                valid_out   => inst_valid_out,
                data_out    => inst_read_data
            );
        
    end generate;
    
    status              <= status_sig;
    data_available      <= data_available_sig;
    cc_instance_handle  <= cc_instance_handle_sig;
    cc_kind             <= cc_kind_sig;
    cc_source_timestamp <= cc_source_timestamp_sig;
    cc_seq_nr           <= cc_seq_nr_sig;
    
    -- *Main State Machine*
    -- STATE                                DESCRIPTION
    -- IDLE                                 Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order.
    -- UNKNOWN_OPERATION_DDS                Dummy State for not supported/unknown DDS Operations
    -- UNKNOWN_OPERATION_RTPS               Dummy State for not supported/unknown RTPS Operations
    -- UNKNOWN_SEQ_NR                       Dummy State for RTPS Operation with unknown Sequence Number
    -- ASSERT_LIVELINESS                    Propagate Liveliness Assertion to RTPS
    -- ADD_SAMPLE_INFO                      Latch and store Cache Change (pre-payload)
    -- ADD_PAYLOAD                          Push payload to memory and key hash generator (as needed)
    -- NEXT_PAYLOAD_SLOT                    Get pointer to next empty payload slot
    -- ALIGN_PAYLOAD                        Store the offset of the actual payload in the last address of the last payload slot.
    -- GET_KEY_HASH                         Fetch the calculated key hash from the Key Hash Generator
    -- INITIATE_INSTANCE_SEARCH             Initiate Instance Search Memory Operation. This state is used to start the Search operation as soon as the required data is available
    -- REGISTER_OPERATION                   Insert new Instance into Memory, or Re-register an existing Unregistered Instance
    -- LOOKUP_OPERATION                     Check Instance lookup results and return special value in case Instance was not found.
    -- PUSH_KEY_HASH                        Push stored Instance Handle/Key hash to DDS output
    -- FILTER_STAGE                         This state decides if the Cache Change is accepted, or rejected. It also decides what sample (if any) has to be removed.
    -- UPDATE_INSTANCE                      Update the Data of the Instance of the received saample (Cache Change)
    -- FINALIZE_PAYLOAD                     Finalize the payload addition (Update pointers).
    -- FINALIZE_SAMPLE                      Update inserted sample and list pointers. (Second Step of Sample Addition Finalization)
    -- GET_OLDEST_SAMPLE_INSTANCE           Fetch the Instance Data of the oldest sample
    -- FIND_SAMPLE                          Find the specified Sample (Oldest ACKed Sample, Oldest Sample of specific Instance, Oldest ACKed Sample of specific Instance)
    -- REMOVE_ORPHAN_SAMPLES                Remove all Samples of the removed Instance (dead_inst)
    -- REMOVE_SAMPLE                        Remove sample and linked payload
    -- POST_SAMPLE_REMOVE                   Update Instance Data of removed sample. If Instance Memory is full, and Instance is now eligible for removal, it is removed.
    -- SKIP_AND_RETURN                      Skip DDS Input and return latched Return Code
    -- SKIP                                 Skip DDS Input and return to latched stage.
    -- REMOVE_STALE_INSTANCE                Find and remove the first eligible Instance in the memory
    -- GET_SEQ_NR                           Push Sequence Number of specified Sample to RTPS output.
    -- FIND_SEQ_NR                          Find Sample with specified Sequence Number.
    -- ACKNACK_SAMPLE                       Acknowledge/Unacknowledge specied Sample
    -- GET_SAMPLE                           Push Sample Data to RTPS output
    -- GET_PAYLOAD                          Push linked Payload to output, or to the serialized key generator
    -- GET_SERIALIZED_KEY                   Push serialized key to output
    -- CHECK_LIFESPAN                       Check and remove samples with expired Lifespans
    -- GET_LIVELINESS_LOST_STATUS           Return Liveliness Loss Status
    -- GET_OFFERED_DEADLINE_MISSED_STATUS   Return Offered Deadline Missed Status
    -- CHECK_DEADLINE                       Check and Mark Instances with missed Deadlines
    -- RESET_SAMPLE_MEMORY                  Reset Sample Memory to Empty State
    -- RESET_PAYLOAD_MEMORY                 Reset Payload Memory to Empty State
    parse_a_prc : process (all)
        variable tmp_dw     : DOUBLE_WORD_ARRAY := (others => (others => '0'));
        variable tmp_bool   : boolean := FALSE;
    begin
        -- DEFAULT Registered
        stage_next                              <= stage;
        oldest_sample_next                      <= oldest_sample;
        newest_sample_next                      <= newest_sample;
        empty_payload_list_head_next            <= empty_payload_list_head;
        empty_sample_list_head_next             <= empty_sample_list_head;
        empty_sample_list_tail_next             <= empty_sample_list_tail;
        payload_addr_latch_1_next               <= payload_addr_latch_1;
        payload_addr_latch_2_next               <= payload_addr_latch_2;
        long_latch_next                         <= long_latch;
        sample_addr_latch_1_next                <= sample_addr_latch_1;
        sample_addr_latch_2_next                <= sample_addr_latch_2;
        sample_addr_latch_3_next                <= sample_addr_latch_3;
        sample_addr_latch_4_next                <= sample_addr_latch_4;
        inst_addr_latch_1_next                  <= inst_addr_latch_1;
        inst_addr_latch_2_next                  <= inst_addr_latch_2;
        sample_status_info_next                 <= sample_status_info;
        remove_oldest_sample_next               <= remove_oldest_sample;
        remove_oldest_inst_sample_next          <= remove_oldest_inst_sample;
        remove_ack_sample_next                  <= remove_ack_sample;
        instance_handle_next                    <= instance_handle;
        sample_rej_cnt_next                     <= sample_rej_cnt;
        sample_rej_cnt_change_next              <= sample_rej_cnt_change;
        sample_rej_last_reason_next             <= sample_rej_last_reason;
        sample_rej_last_inst_next               <= sample_rej_last_inst;
        deadline_time_next                      <= deadline_time;
        deadline_miss_cnt_next                  <= deadline_miss_cnt;
        deadline_miss_cnt_change_next           <= deadline_miss_cnt_change;
        deadline_miss_last_inst_next            <= deadline_miss_last_inst;
        liveliness_lost_cnt_next                <= liveliness_lost_cnt;
        liveliness_lost_cnt_change_next         <= liveliness_lost_cnt_change;
        lifespan_time_next                      <= lifespan_time;
        is_lifespan_check_next                  <= is_lifespan_check;
        status_sig_next                         <= status_sig;
        cnt_next                                <= cnt;
        cnt2_next                               <= cnt2;
        cnt3_next                               <= cnt3;
        source_ts_next                          <= source_ts;
        global_seq_nr_next                      <= global_seq_nr;
        global_sample_cnt_next                  <= global_sample_cnt;
        global_ack_cnt_next                     <= global_ack_cnt;
        stale_inst_cnt_next                     <= stale_inst_cnt;
        lifespan_next                           <= lifespan;
        register_op_next                        <= register_op;
        lookup_op_next                          <= lookup_op;
        ack_wait_next                           <= ack_wait;
        timeout_time_next                       <= timeout_time;
        lease_deadline_next                     <= lease_deadline;
        seq_nr_next                             <= seq_nr;
        return_stage_next                       <= return_stage;
        cc_instance_handle_sig_next             <= cc_instance_handle_sig;
        cc_kind_sig_next                        <= cc_kind_sig;
        cc_source_timestamp_sig_next            <= cc_source_timestamp_sig;
        cc_seq_nr_sig_next                      <= cc_seq_nr_sig;
        is_ack_next                             <= is_ack;
        is_rtps_next                            <= is_rtps;
        data_available_sig_next                 <= data_available_sig;
        orphan_samples_next                     <= orphan_samples;
        key_hash_next                           <= key_hash;
        inst_data_next2                         <= inst_data;
        return_code_latch_next                  <= return_code_latch;
        -- DEFAULT Unregistered
        inst_opcode                             <= NOP;
        ret_rtps                                <= ERROR;
        return_code_dds                         <= RETCODE_UNSUPPORTED;
        opcode_kh                               <= NOP;
        ack_dds                                 <= '0';
        done_dds                                <= '0';
        ack_rtps                                <= '0';
        done_rtps                               <= '0';
        inst_op_start                           <= '0';
        sample_read                             <= '0';
        sample_ready_out                        <= '0';
        sample_valid_in                         <= '0';
        sample_abort_read                       <= '0';
        payload_read                            <= '0';
        payload_ready_out                       <= '0';
        payload_valid_in                        <= '0';
        payload_abort_read                      <= '0';
        ready_in_dds                            <= '0';
        liveliness_assertion                    <= '0';
        valid_out_rtps                          <= '0';
        last_word_out_rtps                      <= '0';
        valid_out_dds                           <= '0';
        last_word_out_dds                       <= '0';
        start_kh                                <= '0';
        ready_in_kh                             <= '0';
        valid_out_kh                            <= '0';
        last_word_out_kh                        <= '0';
        abort_kh                                <= '0';
        idle_sig                                <= '0';
        data_out_kh                             <= (others => '0');
        inst_addr_update                        <= (others => '0');
        sample_addr                             <= (others => '0');
        sample_write_data                       <= (others => '0');
        payload_addr                            <= (others => '0');
        payload_write_data                      <= (others => '0');
        data_out_rtps                           <= (others => '0');
        data_out_dds                            <= (others => '0');
        
        
        case (stage) is
            when IDLE =>
                idle_sig    <= '1';
                -- Reset
                remove_oldest_sample_next       <= '0';
                remove_oldest_inst_sample_next  <= '0';
                remove_ack_sample_next          <= '0';
                lookup_op_next                  <= '0';
                register_op_next                <= '0';
                is_rtps_next                    <= '0';
                
                -- Orphan Samples Available
                if (orphan_samples = '1') then
                    assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                    cur_sample_next <= oldest_sample;
                    stage_next      <= REMOVE_ORPHAN_SAMPLES;
                    cnt_next        <= 0;
                -- DEADLINE QoS
                elsif (DEADLINE_QOS /= DURATION_INFINITE and deadline_time <= time) then
                    -- Reset Timeout
                    deadline_time_next  <= deadline_time + DEADLINE_QOS;
                    
                    -- Synthesis Guard
                    if (WITH_KEY) then
                        stage_next          <= CHECK_DEADLINE;
                        cnt_next            <= 0;
                    else
                        if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then
                            -- Reset Liveliness Flag
                            inst_data_next2.status_info(ISI_LIVELINESS_FLAG) <= '0';
                        else
                            -- Update Requested Deadline Missed Status
                            status_sig_next <= status_sig or OFFERED_DEADLINE_MISSED_STATUS;
                            deadline_miss_cnt_next          <= deadline_miss_cnt + 1;
                            deadline_miss_cnt_change_next   <= deadline_miss_cnt_change + 1;
                        end if;
                    end if;
                -- Liveliness Deadline
                elsif (LEASE_DURATION /= DURATION_INFINITE and lease_deadline <= time) then
                    liveliness_lost_cnt_next        <= liveliness_lost_cnt + 1;
                    liveliness_lost_cnt_change_next <= liveliness_lost_cnt_change + 1;
                    status_sig_next <= status_sig or LIVELINESS_LOST_STATUS;
                    
                    -- Reset
                    lease_deadline_next <= time + LEASE_DURATION;
                -- WAIT_FOR_ACKNOWLEDGEMENT Done
                elsif (ack_wait = '1' and global_ack_cnt = global_sample_cnt) then
                    -- Reset
                    ack_wait_next   <= '0';
                    
                    -- DONE
                    done_dds        <= '1';
                    return_code_dds <= RETCODE_OK;
                -- WAIT_FOR_ACKNOWLEDGEMENT Timeout
                elsif (ack_wait = '1' and timeout_time <= time) then
                    -- Reset
                    ack_wait_next   <= '0';
                    
                    -- DONE
                    done_dds        <= '1';
                    return_code_dds <= RETCODE_TIMEOUT;
                -- LIFESPAN QoS
                elsif (lifespan_time <= time) then
                    -- Reset Timeout
                    lifespan_time_next  <= TIME_INFINITE;
                    
                    -- Samples Available
                    if (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
                        is_lifespan_check_next  <= '1';
                        cur_sample_next         <= oldest_sample;
                        stage_next              <= CHECK_LIFESPAN;
                        cnt_next                <= 0;
                    end if;
                -- RTPS Operation
                elsif (start_rtps = '1') then
                    is_rtps_next    <= '1';
                    -- Latch Input Signal
                    seq_nr_next <= seq_nr_rtps;
                    -- Reset
                    is_ack_next <= '0';
                    
                    case (opcode_rtps) is
                        when GET_MIN_SN =>
                            ack_rtps    <= '1';
                            if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                -- NOTE: If the HC is empty we return the Special value SEQUENCENUMBER_UNKNOWN
                                stage_next          <= GET_SEQ_NR;
                                cnt_next            <= 4;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cur_sample_next     <= oldest_sample;
                                stage_next          <= GET_SEQ_NR;
                                cnt_next            <= 0;
                            end if;
                        when GET_MAX_SN =>
                            ack_rtps    <= '1';
                            
                            -- Reset Data Availability
                            data_available_sig_next <= '0';
                            
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                -- NOTE: If the HC is empty we return the Special value SEQUENCENUMBER_UNKNOWN
                                stage_next          <= GET_SEQ_NR;
                                cnt_next            <= 4;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cur_sample_next     <= newest_sample;
                                stage_next          <= GET_SEQ_NR;
                                cnt_next            <= 0;
                            end if;
                        when GET_CACHE_CHANGE =>
                            ack_rtps    <= '1';
                            
                            -- No Samples Available
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                stage_next          <= UNKNOWN_SEQ_NR;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cc_seq_nr_sig_next  <= seq_nr_rtps;
                                cur_sample_next     <= newest_sample;
                                stage_next          <= FIND_SEQ_NR;
                                cnt_next            <= 0;
                                return_stage_next   <= GET_SAMPLE;
                            end if;
                        when ACK_CACHE_CHANGE =>
                            ack_rtps    <= '1';
                            is_ack_next <= '1';
                            
                            -- No Samples Available
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                stage_next          <= UNKNOWN_SEQ_NR;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cur_sample_next     <= newest_sample;
                                stage_next          <= FIND_SEQ_NR;
                                cnt_next            <= 0;
                                return_stage_next   <= ACKNACK_SAMPLE;
                            end if;
                        when NACK_CACHE_CHANGE =>
                            ack_rtps    <= '1';
                            
                            -- No Samples Available
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                stage_next          <= UNKNOWN_SEQ_NR;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cur_sample_next     <= newest_sample;
                                stage_next          <= FIND_SEQ_NR;
                                cnt_next            <= 0;
                                return_stage_next   <= ACKNACK_SAMPLE;
                            end if;
                        when REMOVE_CACHE_CHANGE =>
                            ack_rtps    <= '1';
                            
                            -- No Samples Available
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                stage_next          <= UNKNOWN_SEQ_NR;
                                cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                            else
                                cur_sample_next     <= newest_sample;
                                stage_next          <= FIND_SEQ_NR;
                                cnt_next            <= 0;
                                return_stage_next   <= REMOVE_SAMPLE;
                            end if;
                        when others =>
                            ack_rtps    <= '1';
                            
                            stage_next  <= UNKNOWN_OPERATION_RTPS;
                    end case;
                -- DDS Operation (Stall DDS Operation if a wait Operation is in progress)
                elsif (ack_wait = '0' and start_dds = '1') then
                    -- Reset
                    register_op_next        <= '0';
                    instance_handle_next    <= HANDLE_NIL;
                    source_ts_next          <= TIME_INVALID;
                    sample_status_info_next <= (others => '0');
                    key_hash_next           <= HANDLE_NIL;
                    new_sample_next         <= SAMPLE_MEMORY_MAX_ADDRESS;
                    return_code_latch_next  <= RETCODE_UNSUPPORTED;
                    
                    case (opcode_dds) is
                        when REGISTER_INSTANCE =>
                            -- Synthesis Guard
                            if (WITH_KEY) then
                                start_kh    <= '1';
                                opcode_kh   <= PUSH_DATA;
                                
                                if (ack_kh = '1') then
                                    ack_dds             <= '1';
                                    register_op_next    <= '1';
                                    stage_next          <= ADD_PAYLOAD;
                                    cnt_next            <= 1;
                                end if;
                            else
                                ack_dds             <= '1';
                                key_hash_next       <= HANDLE_NIL;
                                stage_next          <= SKIP;
                                return_stage_next   <= PUSH_KEY_HASH;
                            end if;
                        when WRITE =>
                            ack_dds <= '1';
                            
                            -- Reset Liveliness
                            lease_deadline_next <= time + LEASE_DURATION;
                            
                            -- Latch Input Signals
                            instance_handle_next    <= instance_handle_dds;
                            source_ts_next          <= source_ts_dds;
                            
                            -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
                            sample_status_info_next <= (SSI_PAYLOAD_FLAG => '1', SSI_ALIGNED_FLAG => '1', others => '0');
                            cur_sample_next         <= empty_sample_list_head;
                            
                            -- NOTE: We have to explicitly check the Payload Memory, as it may be "unaligned" with our Sample Memory 
                            --       (Sample Memory has available Slot, but Payload Memory not)
                            -- Payload Memory Full
                            if (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                if (global_ack_cnt = 0 and HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- Reject Change
                                    stage_next              <= SKIP_AND_RETURN;
                                    cnt_next                <= 0;
                                    return_code_latch_next  <= RETCODE_OUT_OF_RESOURCES;
                                else
                                    assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                    -- Do not ACK Operation
                                    ack_dds <= '0';
                                    
                                    
                                    if (global_ack_cnt /= 0) then
                                        -- Remove Oldest ACKed Sample
                                        remove_oldest_sample_next   <= '1';
                                        remove_ack_sample_next      <= '1';
                                        
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= FIND_SAMPLE;
                                        cnt_next        <= 0;
                                    elsif (WITH_KEY) then
                                        stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                        cnt_next    <= 0;
                                    else
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= REMOVE_SAMPLE;
                                        cnt_next        <= 0;
                                    end if;
                                end if;
                            else
                                -- Instance Handle provided
                                if (WITH_KEY and instance_handle_dds /= HANDLE_NIL) then
                                    key_hash_next   <= instance_handle_dds;
                                    stage_next      <= INITIATE_INSTANCE_SEARCH;
                                    cnt_next        <= 0;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            end if;
                        when DISPOSE =>
                            ack_dds <= '1';
                            
                            -- Reset Liveliness
                            lease_deadline_next <= time + LEASE_DURATION;
                            
                            -- Latch Input Signals
                            instance_handle_next    <= instance_handle_dds;
                            source_ts_next          <= source_ts_dds;
                            
                            -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
                            sample_status_info_next <= (SSI_PAYLOAD_FLAG => '1', SSI_ALIGNED_FLAG => '1', SSI_DISPOSED_FLAG => '1', others => '0');
                            cur_sample_next <= empty_sample_list_head;
                            
                            -- NOTE: We always expect a Serialized Key as Input of this Opration, so we also check the Payload memory
                            -- Payload Memory Full
                            if (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                if (global_ack_cnt = 0 and HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- Reject Change
                                    stage_next              <= SKIP_AND_RETURN;
                                    cnt_next                <= 0;
                                    return_code_latch_next  <= RETCODE_OUT_OF_RESOURCES;
                                else
                                    assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                    -- Do not ACK Operation
                                    ack_dds <= '0';
                                    
                                    if (global_ack_cnt /= 0) then
                                        -- Remove Oldest ACKed Sample
                                        remove_oldest_sample_next   <= '1';
                                        remove_ack_sample_next      <= '1';
                                        
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= FIND_SAMPLE;
                                        cnt_next        <= 0;
                                    elsif (WITH_KEY) then
                                        stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                        cnt_next    <= 0;
                                    else
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= REMOVE_SAMPLE;
                                        cnt_next        <= 0;
                                    end if;
                                end if;
                            else
                                -- Instance Handle provided
                                if (WITH_KEY and instance_handle_dds /= HANDLE_NIL) then
                                    key_hash_next   <= instance_handle_dds;
                                    stage_next      <= INITIATE_INSTANCE_SEARCH;
                                    cnt_next        <= 0;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            end if;
                        when UNREGISTER_INSTANCE =>
                            ack_dds <= '1';
                            
                            -- Reset Liveliness
                            lease_deadline_next <= time + LEASE_DURATION;
                            
                            -- Latch Input Signals
                            instance_handle_next    <= instance_handle_dds;
                            source_ts_next          <= source_ts_dds;
                            
                            -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
                            sample_status_info_next <= (SSI_PAYLOAD_FLAG => '1', SSI_ALIGNED_FLAG => '1', SSI_UNREGISTERED_FLAG => '1', others => '0');
                            cur_sample_next <= empty_sample_list_head;
                            
                            -- NOTE: We always expect a Serialized Key as Input of this Opration, so we also check the Payload memory
                            -- Payload Memory Full
                            if (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                if (global_ack_cnt = 0 and HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- Reject Change
                                    stage_next              <= SKIP_AND_RETURN;
                                    cnt_next                <= 0;
                                    return_code_latch_next  <= RETCODE_OUT_OF_RESOURCES;
                                else
                                    assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                    -- Do not ACK Operation
                                    ack_dds <= '0';
                                    
                                    if (global_ack_cnt /= 0) then
                                        -- Remove Oldest ACKed Sample
                                        remove_oldest_sample_next   <= '1';
                                        remove_ack_sample_next      <= '1';
                                        
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= FIND_SAMPLE;
                                        cnt_next        <= 0;
                                    elsif (WITH_KEY) then
                                        stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                        cnt_next    <= 0;
                                    else
                                        cur_sample_next <= oldest_sample;
                                        stage_next      <= REMOVE_SAMPLE;
                                        cnt_next        <= 0;
                                    end if;
                                end if;
                            else
                                -- Instance Handle provided
                                if (WITH_KEY and instance_handle_dds /= HANDLE_NIL) then
                                    key_hash_next   <= instance_handle_dds;
                                    stage_next      <= INITIATE_INSTANCE_SEARCH;
                                    cnt_next        <= 0;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            end if;
                        when LOOKUP_INSTANCE =>
                            -- Synthesis Guard
                            if (WITH_KEY) then
                                start_kh    <= '1';
                                opcode_kh   <= PUSH_DATA;
                                
                                if (ack_kh = '1') then
                                    ack_dds         <= '1';
                                    lookup_op_next  <= '1';
                                    stage_next      <= ADD_PAYLOAD;
                                    cnt_next        <= 1;
                                end if;
                            else
                                ack_dds             <= '1';
                                key_hash_next       <= HANDLE_NIL;
                                stage_next          <= SKIP;
                                return_stage_next   <= PUSH_KEY_HASH;
                            end if;
                        when WAIT_FOR_ACKNOWLEDGEMENTS =>
                            -- NOTE: In case of BEST_EFFORT the RTPS Writer still manually ACKs the Samples, so we do not handle this case differently here.
                            ack_dds             <= '1';
                            ack_wait_next       <= '1';
                            timeout_time_next   <= time + max_wait_dds;
                        when GET_OFFERED_DEADLINE_MISSED_STATUS =>
                            ack_dds     <= '1';
                            stage_next  <= GET_OFFERED_DEADLINE_MISSED_STATUS;
                            cnt_next    <= 0;
                        when ASSERT_LIVELINESS =>
                            -- Reset Liveliness
                            lease_deadline_next <= time + LEASE_DURATION;
                            
                            ack_dds     <= '1';
                            stage_next  <= ASSERT_LIVELINESS;
                        when GET_LIVELINESS_LOST_STATUS =>
                            ack_dds     <= '1';
                            stage_next  <= GET_LIVELINESS_LOST_STATUS;
                            cnt_next    <= 0;
                        when others =>
                            ack_dds     <= '1';
                            stage_next  <= UNKNOWN_OPERATION_DDS;
                    end case;
                end if;
            when UNKNOWN_OPERATION_DDS =>
                done_dds        <= '1';
                return_code_dds <= RETCODE_ILLEGAL_OPERATION;
                
                -- DONE
                stage_next  <= IDLE;
            when UNKNOWN_OPERATION_RTPS =>
                done_rtps   <= '1';
                ret_rtps    <= ERROR;
                
                -- DONE
                stage_next  <= IDLE;
            when UNKNOWN_SEQ_NR =>
                done_rtps           <= '1';
                ret_rtps            <= INVALID;
                
                -- DONE
                stage_next  <= IDLE;
            
            when ASSERT_LIVELINESS =>
                -- Propagate Liveliness Assertion
                liveliness_assertion    <= '1';
                
                done_dds        <= '1';
                return_code_dds <= RETCODE_OK;
                
                -- DONE
                stage_next  <= IDLE;
            when ADD_SAMPLE_INFO =>
                -- Precondition: cur_sample set
                
                case (cnt) is
                    -- Status Info
                    when 0 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_write_data   <= sample_status_info;
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next        <= cnt + 1;
                        end if;
                    -- Sequence Number 1/2
                    when 1 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_SEQ_NR_OFFSET;
                        sample_write_data   <= std_logic_vector(global_seq_nr(0));
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next        <= cnt + 1;
                        end if;
                    -- Sequence Number 2/2
                    when 2 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_SEQ_NR_OFFSET + 1;
                        sample_write_data   <= std_logic_vector(global_seq_nr(1));
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next        <= cnt + 1;
                        end if;
                    -- Timestamp 1/2
                    when 3 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_TIMESTAMP_OFFSET;
                        sample_write_data   <= std_logic_vector(source_ts(0)) when source_ts /= TIME_INVALID else std_logic_vector(time(0));
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next        <= cnt + 1;
                        end if;
                    -- Timestamp 2/2
                    when 4 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
                        sample_write_data   <= std_logic_vector(source_ts(1)) when source_ts /= TIME_INVALID else std_logic_vector(time(1));
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Synthesis Guard
                            if (LIFESPAN_QOS /= DURATION_INFINITE) then
                                cnt_next        <= cnt + 1;
                                lifespan_next   <= time + LIFESPAN_QOS;
                            else
                                cnt_next    <= cnt + 3; -- Skip
                            end if;
                        end if;
                    -- Lifespan Deadline 1/2
                    when 5 =>
                        -- Synthesis Guard
                        if (LIFESPAN_QOS /= DURATION_INFINITE) then
                            sample_valid_in     <= '1';
                            sample_addr         <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET;
                            sample_write_data   <= std_logic_vector(lifespan(0));
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next        <= cnt + 1;
                            end if;
                        end if;
                    -- Lifespan Deadline 2/2
                    when 6 =>
                        -- Synthesis Guard
                        if (LIFESPAN_QOS /= DURATION_INFINITE) then
                            sample_valid_in     <= '1';
                            sample_addr         <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1;
                            sample_write_data   <= std_logic_vector(lifespan(1));
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- Payload Address
                    when 7 =>
                        assert (empty_payload_list_head /= PAYLOAD_MEMORY_MAX_ADDRESS) severity FAILURE;
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(empty_payload_list_head, WORD_WIDTH));
                        cur_payload_next    <= empty_payload_list_head;
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Key Hash needs to be calculated
                            if (WITH_KEY and instance_handle = HANDLE_NIL) then
                                cnt_next    <= cnt + 1;
                            else
                                stage_next  <= ADD_PAYLOAD;
                                cnt_next    <= 0;
                                cnt2_next   <= 1;
                            end if;
                        end if;
                    -- Initiate KH Operation
                    when 8 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            start_kh    <= '1';
                            -- Payload is Serialized Key
                            if (sample_status_info(SSI_DISPOSED_FLAG) = '1' or sample_status_info(SSI_UNREGISTERED_FLAG) = '1' or sample_status_info(SSI_FILTERED_FLAG) = '1') then
                                opcode_kh   <= PUSH_SERIALIZED_KEY;
                            else
                                opcode_kh   <= PUSH_DATA;
                            end if;
                            
                            if (ack_kh = '1') then
                                stage_next  <= ADD_PAYLOAD;
                                cnt_next    <= 0;
                                cnt2_next   <= 1;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when ADD_PAYLOAD =>
                -- Precondition: cur_payload set
                
                case (cnt) is
                    -- Push to memory
                    when 0 =>
                        -- Input Guard
                        if (valid_in_dds = '1') then
                            payload_valid_in    <= '1';
                            payload_addr        <= cur_payload + cnt2;
                            payload_write_data  <= data_in_dds;
                            -- Memory Control Flow Guard
                            if (payload_ready_in = '1') then
                                -- Key Hash needs to be calculated
                                if (WITH_KEY and instance_handle = HANDLE_NIL) then
                                    cnt_next    <= cnt + 1;
                                else
                                    ready_in_dds   <= '1';
                                    -- End of Payload
                                    if (last_word_in_dds = '1') then
                                        -- End of Payload Slot
                                        if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
                                            stage_next  <= FILTER_STAGE;
                                        else
                                            stage_next  <= ALIGN_PAYLOAD;
                                            cnt_next    <= 0;
                                        end if;
                                    else
                                        -- End of Payload Slot
                                        if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
                                            stage_next  <= NEXT_PAYLOAD_SLOT;
                                            cnt_next    <= 0;    
                                        else
                                            -- Next Word
                                            cnt2_next   <= cnt2 + 1;
                                        end if;
                                    end if;
                                end if;
                            end if;
                        end if;
                    -- Push to KH
                    when 1 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            -- Input Guard
                            if (valid_in_dds = '1') then
                            
                                valid_out_kh    <= '1';
                                data_out_kh     <= data_in_dds;
                                
                                -- Output Guard
                                if (ready_out_kh = '1') then
                                    ready_in_dds   <= '1';
                                    -- Operation does not have Payload to store
                                    if (sample_status_info(SSI_PAYLOAD_FLAG) = '0') then
                                        -- End of Payload
                                        if (last_word_in_dds = '1') then
                                            last_word_out_kh    <= '1';
                                            -- Fetch the Key Hash
                                            stage_next  <= GET_KEY_HASH;
                                            cnt_next    <= 0;
                                            cnt2_next   <= 0;
                                        else
                                            -- Next Word
                                            cnt_next    <= 1; -- Same Sub-state
                                        end if;
                                    else
                                        -- End of Payload
                                        if (last_word_in_dds = '1') then
                                            last_word_out_kh    <= '1';
                                            -- End of Payload Slot
                                            if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
                                                -- Fetch the Key Hash
                                                stage_next  <= GET_KEY_HASH;
                                                cnt_next    <= 0;
                                                cnt2_next   <= 0;
                                            else
                                                stage_next  <= ALIGN_PAYLOAD;
                                                cnt_next    <= 0;
                                            end if;
                                        else
                                            -- End of Payload Slot
                                            if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
                                                stage_next  <= NEXT_PAYLOAD_SLOT;
                                                cnt_next    <= 0;
                                            else
                                                -- Next Word
                                                cnt_next    <= 0;
                                                cnt2_next   <= cnt2 + 1;
                                            end if;
                                        end if;
                                    end if;
                                end if;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when NEXT_PAYLOAD_SLOT =>
                -- Precondition: cur_payload set
                
                case (cnt) is
                    -- GET Next Pointer
                    when 0 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        payload_read        <= '1';
                        
                        -- Memory Control Flow Guard
                        if (payload_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Next Pointer
                    when 1 =>
                        payload_ready_out   <= '1';
                        
                        -- Memory Control Flow Guard
                        if (payload_valid_out = '1') then
                            -- No Empty Payload Slots available
                            if (unsigned(payload_read_data) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                -- Reject Change
                                stage_next              <= SKIP_AND_RETURN;
                                cnt_next                <= 0;
                                return_code_latch_next  <= RETCODE_OUT_OF_RESOURCES;
                                -- Abort Key Hash Generation
                                abort_kh    <= '1';
                            else
                                -- Latch next Payload Slot and Continue
                                cur_payload_next    <= resize(unsigned(payload_read_data), PAYLOAD_MEMORY_ADDR_WIDTH);
                                stage_next          <= ADD_PAYLOAD;
                                cnt_next            <= 0;
                                cnt2_next           <= 1;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when ALIGN_PAYLOAD =>
                case (cnt) is
                    -- Mark Payload as unaligned
                    when 0 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_write_data   <= sample_status_info;
                        sample_write_data(SSI_ALIGNED_FLAG) <= '0';
                        
                        -- Memory Control Flow Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Store Payload End Offset
                    when 1 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PAYLOAD_FRAME_SIZE-1;
                        payload_write_data  <= std_logic_vector(to_unsigned(cnt2, WORD_WIDTH));
                        
                        -- Memory Control Flow Guard
                        if (payload_ready_in = '1') then
                            if (WITH_KEY and instance_handle = HANDLE_NIL) then
                                stage_next  <= GET_KEY_HASH;
                                cnt_next    <= 0;
                                cnt2_next   <= 0;
                            else
                                stage_next  <= FILTER_STAGE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_KEY_HASH =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    case (cnt) is
                        -- Initiate READ Operation
                        when 0 =>   
                            start_kh    <= '1';
                            opcode_kh   <= READ_KEY_HASH;
                            
                            if (ack_kh = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        -- READ Key Hash
                        when 1 =>
                            ready_in_kh <= '1';
                    
                            if (valid_in_kh = '1') then
                                cnt2_next   <= cnt2 + 1;
                                
                                -- Latch Key Hash
                                key_hash_next(cnt2)  <= data_in_kh;
                                
                                -- Exit Condition
                                if (last_word_in_kh = '1') then
                                    -- DONE
                                    stage_next    <= INITIATE_INSTANCE_SEARCH;
                                end if;
                            end if;
                        when others => 
                            null;
                    end case;
                end if;
            when INITIATE_INSTANCE_SEARCH =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    -- Memory Operation Guard
                    if (inst_op_done = '1') then
                        inst_op_start       <= '1';
                        inst_opcode         <= SEARCH_INSTANCE_HASH;
                        inst_mem_fields     <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                        
                        -- Register Operation in Progress
                        if (WITH_KEY and register_op = '1') then
                            stage_next  <= REGISTER_OPERATION;
                        -- Lookup Operation in Progress
                        elsif (WITH_KEY and lookup_op = '1') then
                            stage_next  <= LOOKUP_OPERATION;
                        -- Cache Change not yet Stored
                        elsif (instance_handle /= HANDLE_NIL) then
                            stage_next  <= ADD_SAMPLE_INFO;
                            cnt_next    <= 0;
                        else
                            stage_next  <= FILTER_STAGE;
                        end if;
                    end if;
                end if;
            when REGISTER_OPERATION =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    -- Wait for Instance Search to finish
                    if (inst_op_done = '1') then
                        -- Instance already in Memory
                        if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- Accept Registration
                            stage_next      <= PUSH_KEY_HASH;
                            cnt_next        <= 0;
                            
                            -- Instance is Unregistered
                            if (inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1') then
                                -- Re-register Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= UPDATE_INSTANCE;
                                inst_mem_fields     <= IMF_STATUS_FLAG;
                                status_info_update  <= inst_data.status_info;
                                status_info_update(ISI_UNREGISTERED_FLAG)   <= '0';
                                
                                -- Update Stale Instance Count
                                if (inst_data.sample_cnt = inst_data.ack_cnt) then
                                    stale_inst_cnt_next <= stale_inst_cnt - 1;
                                end if;
                            end if;
                        else
                            -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
                            if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                -- Stale Instances are available
                                if (stale_inst_cnt /= 0) then
                                    -- Remove Stale and insert new Instance
                                    inst_op_start   <= '1';
                                    inst_opcode     <= GET_FIRST_INSTANCE;
                                    inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    stage_next      <= REMOVE_STALE_INSTANCE;
                                    cnt_next        <= 0;
                                else
                                    -- Reject Registration
                                    key_hash_next   <= HANDLE_NIL;
                                    stage_next      <= PUSH_KEY_HASH;
                                    cnt_next        <= 0;
                                end if;
                            else
                                -- Accept Registration
                                stage_next      <= PUSH_KEY_HASH;
                                cnt_next        <= 0;
                                
                                -- Insert New Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= INSERT_INSTANCE;
                                status_info_update  <= (others => '0');
                                sample_cnt          <= (others => '0');
                                ack_cnt             <= (others => '0');
                            end if;
                        end if;
                    end if;
                end if;
            when LOOKUP_OPERATION =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    -- Wait for Instance Search to finish
                    if (inst_op_done = '1') then
                        -- Instance Found
                        if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
                            stage_next  <= PUSH_KEY_HASH;
                            cnt_next    <= 0;
                        else
                            -- Return Special Value
                            key_hash_next   <= HANDLE_NIL;
                            stage_next      <= PUSH_KEY_HASH;
                            cnt_next        <= 0;
                        end if;
                    end if;
                end if;
            when PUSH_KEY_HASH =>
                case (cnt) is
                    -- Key Hash 1/4
                    when 0 =>
                        valid_out_dds   <= '1';
                        data_out_dds    <= key_hash(0);
                        
                        -- Output Guard
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Key Hash 2/4
                    when 1 =>
                        valid_out_dds   <= '1';
                        data_out_dds    <= key_hash(1);
                        
                        -- Output Guard
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Key Hash 3/4
                    when 2 =>
                        valid_out_dds   <= '1';
                        data_out_dds    <= key_hash(2);
                        
                        -- Output Guard
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Key Hash 4/4
                    when 3 =>
                        valid_out_dds       <= '1';
                        data_out_dds        <= key_hash(3);
                        last_word_out_dds   <= '1';
                        
                        -- Output Guard
                        if (ready_out_dds = '1') then
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when FILTER_STAGE =>
                -- Precondition: cur_sample set
                
                -- Wait for Instance Search to finish
                if (not WITH_KEY or inst_op_done = '1') then
                    
                    -- Instance Found
                    if (not WITH_KEY or inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
                        -- Latch Instance Pointer
                        cur_inst_next   <= inst_addr_base;
                        
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
                        if (WITH_KEY and MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(MAX_SAMPLES_PER_INSTANCE)) then
                            -- Synthesis Guard
                            if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                -- No ACKed Instance Samples exist
                                if (inst_data.ack_cnt = 0) then
                                    -- Reject Change
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OUT_OF_RESOURCES;
                                    stage_next      <= IDLE;
                                else
                                    -- Accept Change (Remove Oldest ACKed Instance Sample)
                                    remove_oldest_inst_sample_next  <= '1';
                                    remove_ack_sample_next          <= '1';
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    stage_next      <= UPDATE_INSTANCE;
                                end if;
                            else -- HISTORY_QOS = KEEP_LAST_HISTORY_QOS
                                -- Accept Change (Remove Oldest (ACKed) Instance Sample)
                                remove_oldest_inst_sample_next  <= '1';
                                remove_ack_sample_next          <= '1' when (inst_data.ack_cnt /= 0) else '0';
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OK;
                                stage_next      <= UPDATE_INSTANCE;
                            end if;
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                        elsif (empty_sample_list_head = empty_sample_list_tail) then
                            -- Synthesis Guard
                            if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                -- No ACKed Samples exist
                                if (global_ack_cnt = 0) then
                                    -- Reject Change
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OUT_OF_RESOURCES;
                                    stage_next      <= IDLE;
                                else
                                    -- Accept Change (Remove Oldest ACKed Sample)
                                    remove_oldest_sample_next   <= '1';
                                    remove_ack_sample_next      <= '1';
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    stage_next      <= UPDATE_INSTANCE;
                                end if;
                            else -- HISTORY_QOS = KEEP_LAST_HISTORY_QOS
                                -- Accept Change (Remove Oldest (ACKed) Sample)
                                remove_oldest_sample_next   <= '1';
                                remove_ack_sample_next      <= '1' when (global_ack_cnt /= 0) else '0';
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OK;
                                stage_next      <= UPDATE_INSTANCE;
                            end if;
                        else
                            -- Accept Change
                            done_dds        <= '1';
                            return_code_dds <= RETCODE_OK;
                            stage_next      <= UPDATE_INSTANCE;
                        end if;
                    else -- (WITH_KEY)
                        -- Latch Instance Pointer
                        cur_inst_next   <= inst_empty_head;
                        
                        -- Provided Instance Handle Invalid
                        if (instance_handle /= HANDLE_NIL) then
                            -- Invalid Operation
                            done_dds        <= '1';
                            return_code_dds <= RETCODE_BAD_PARAMETER;
                            -- DONE
                            stage_next  <= IDLE;
                        -- Ignore Unregister Operation on Unknown Instance
                        elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then
                            -- Drop Change
                            done_dds        <= '1';
                            return_code_dds <= RETCODE_OK;
                            -- DONE
                            stage_next  <= IDLE;
                        -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
                        elsif (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- No Stale Instances available
                            if (stale_inst_cnt = 0) then
                                -- Reject Change
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OUT_OF_RESOURCES;
                                stage_next      <= IDLE;
                            -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                            elsif (empty_sample_list_head = empty_sample_list_tail) then
                                -- Synthesis Guard
                                if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- No ACKed Samples exist
                                    if (global_ack_cnt = 0) then
                                        -- Reject Change
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_OUT_OF_RESOURCES;
                                        stage_next      <= IDLE;
                                    else
                                        -- Accept Change (Remove Oldest ACKed Sample)
                                        remove_oldest_sample_next   <= '1';
                                        remove_ack_sample_next      <= '1';
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_OK;
                                        
                                        -- Remove Stale and insert new Instance
                                        inst_op_start   <= '1';
                                        inst_opcode     <= GET_FIRST_INSTANCE;
                                        inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                        stage_next      <= REMOVE_STALE_INSTANCE;
                                        cnt_next        <= 0;
                                    end if;
                                else -- HISTORY_QOS = KEEP_LAST_HISTORY_QOS
                                    -- Accept Change (Remove Oldest (ACKed) Sample)
                                    remove_oldest_sample_next   <= '1';
                                    remove_ack_sample_next      <= '1' when (global_ack_cnt /= 0) else '0';
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    
                                    -- Remove Stale and insert new Instance
                                    inst_op_start   <= '1';
                                    inst_opcode     <= GET_FIRST_INSTANCE;
                                    inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    stage_next      <= REMOVE_STALE_INSTANCE;
                                    cnt_next        <= 0;
                                end if;
                            else
                                -- Accept Change
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OK;
                                
                                -- Remove Stale and insert new Instance
                                inst_op_start   <= '1';
                                inst_opcode     <= GET_FIRST_INSTANCE;
                                inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                stage_next      <= REMOVE_STALE_INSTANCE;
                                cnt_next        <= 0;
                            end if;
                        else
                            -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                            if (empty_sample_list_head = empty_sample_list_tail) then
                                -- Synthesis Guard
                                if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- No ACKed Samples exist
                                    if (global_ack_cnt = 0) then
                                        -- Reject Change
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_OUT_OF_RESOURCES;
                                        stage_next      <= IDLE;
                                    else
                                        -- Accept Change (Remove Oldest ACKed Sample)
                                        remove_oldest_sample_next   <= '1';
                                        remove_ack_sample_next      <= '1';
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_OK;
                                        
                                        -- Insert New Instance
                                        inst_op_start       <= '1';
                                        inst_opcode         <= INSERT_INSTANCE;
                                        status_info_update  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                        sample_cnt          <= to_unsigned(1, WORD_WIDTH);
                                        ack_cnt             <= (others => '0');
                                        
                                        stage_next  <= FINALIZE_PAYLOAD;
                                        cnt_next    <= 0;
                                    end if;
                                else -- HISTORY_QOS = KEEP_LAST_HISTORY_QOS
                                    -- Accept Change (Remove Oldest (ACKed) Sample)
                                    remove_oldest_sample_next   <= '1';
                                    remove_ack_sample_next      <= '1' when (global_ack_cnt /= 0) else '0';
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    
                                    -- Insert New Instance
                                    inst_op_start       <= '1';
                                    inst_opcode         <= INSERT_INSTANCE;
                                    status_info_update  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                    sample_cnt          <= to_unsigned(1, WORD_WIDTH);
                                    ack_cnt             <= (others => '0');
                                    
                                    stage_next  <= FINALIZE_PAYLOAD;
                                    cnt_next    <= 0;
                                end if;
                            else
                                -- Accept Change
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OK;
                                
                                -- Insert New Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= INSERT_INSTANCE;
                                status_info_update  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                sample_cnt          <= to_unsigned(1, WORD_WIDTH);
                                ack_cnt             <= (others => '0');
                                
                                stage_next  <= FINALIZE_PAYLOAD;
                                cnt_next    <= 0;                            
                            end if;
                        end if;
                    end if;
                end if;
            when UPDATE_INSTANCE =>
                -- Memory Operation Guard
                if (not WITH_KEY or inst_op_done = '1') then
                    -- Synthesis Guard
                    if (WITH_KEY) then
                        inst_op_start       <= '1';
                        inst_opcode         <= UPDATE_INSTANCE;
                        inst_mem_fields     <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG;
                        status_info_update  <= inst_data.status_info;
                        status_info_update(ISI_LIVELINESS_FLAG)     <= '1';
                        if (sample_status_info(SSI_DISPOSED_FLAG) = '0' and sample_status_info(SSI_UNREGISTERED_FLAG) = '0') then
                            status_info_update(ISI_DISPOSED_FLAG)       <= '0';
                            status_info_update(ISI_UNREGISTERED_FLAG)   <= '0';
                        elsif (sample_status_info(SSI_DISPOSED_FLAG) = '1') then
                            status_info_update(ISI_DISPOSED_FLAG)       <= '1';
                        elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then
                            status_info_update(ISI_UNREGISTERED_FLAG)   <= '1';
                        end if;
                        sample_cnt          <= inst_data.sample_cnt + 1;
                        
                        -- Update Stale Instance Count
                        -- NOTE: We enter this state only when we have a new sample, so an instance cannot turn stale, but only 
                        --       become relevant again.
                        if (inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1' and inst_data.sample_cnt = inst_data.ack_cnt) then
                            stale_inst_cnt_next <= stale_inst_cnt - 1;
                        end if;
                    else
                        if (sample_status_info(SSI_DISPOSED_FLAG) = '0' and sample_status_info(SSI_UNREGISTERED_FLAG) = '0') then
                            inst_data_next2.status_info(ISI_DISPOSED_FLAG)      <= '0';
                            inst_data_next2.status_info(ISI_UNREGISTERED_FLAG)  <= '0';
                        elsif (sample_status_info(SSI_DISPOSED_FLAG) = '1') then
                            inst_data_next2.status_info(ISI_DISPOSED_FLAG)      <= '1';
                        elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then
                            inst_data_next2.status_info(ISI_UNREGISTERED_FLAG)  <= '1';
                        end if;
                        inst_data_next2.status_info(ISI_LIVELINESS_FLAG)     <= '1';
                        inst_data_next2.sample_cnt   <= inst_data.sample_cnt + 1;
                    end if;
                    
                    stage_next  <= FINALIZE_PAYLOAD;
                    cnt_next    <= 0;
                end if;
            when FINALIZE_PAYLOAD =>
                -- Precondition: cur_payload set
                
                case (cnt) is 
                    -- GET Next Pointer
                    when 0 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        payload_read        <= '1';
                        
                        -- Memory Control Flow Guard
                        if (payload_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Next Pointer
                    when 1 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        -- Make current Slot the Tail
                        payload_write_data  <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS, WORD_WIDTH));
                        
                        -- Memory Control Flow Guard
                        if (payload_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Next Pointer
                    when 2 =>
                        payload_ready_out   <= '1';
                        
                        -- Memory Control Flow Guard
                        if (payload_valid_out = '1') then
                            -- Fix New Empty List Head
                            empty_payload_list_head_next    <= resize(unsigned(payload_read_data), PAYLOAD_MEMORY_ADDR_WIDTH);
                            
                            stage_next          <= FINALIZE_SAMPLE;
                            cur_sample_next     <= empty_sample_list_head;
                            cnt_next            <= 0;
                        end if;
                    when others =>
                        null;
                end case;
            when FINALIZE_SAMPLE =>
                -- Precondition: cur_sample set, cur_inst set
                
                case (cnt) is
                    -- GET Next Pointer
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_read     <= '1';
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Sample Memory Empty (No previous Sample)
                            if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                assert (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                if (WITH_KEY) then
                                    cnt_next    <= cnt + 2; -- Skip Next Step
                                else
                                    cnt_next    <= cnt + 3; -- Skip Next 2 Steps
                                end if;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Next Pointer (Previous Sample)
                    when 1 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= newest_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(cur_sample, WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            if (WITH_KEY) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= cnt + 2; --Skip Next Step
                            end if;
                        end if;
                    -- SET Instance Pointer
                    when 2 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_valid_in     <= '1';
                            sample_addr         <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_write_data   <= std_logic_vector(resize(cur_inst, WORD_WIDTH));
                            
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Previous Pointer
                    when 3 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_PREV_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(newest_sample, WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- SET Next Pointer
                    when 4 =>
                        -- Write Next Pointer
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS, WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                        
                    -- READ Next Pointer
                    when 5 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            
                            -- Fix new Empty List Head
                            empty_sample_list_head_next <= resize(unsigned(sample_read_data), SAMPLE_MEMORY_ADDR_WIDTH);
                            
                            -- Fix List Pointers
                            newest_sample_next  <= cur_sample;
                            if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                oldest_sample_next  <= cur_sample;
                            end if;
                            
                            -- Increment Global Sequence Number
                            global_seq_nr_next  <= global_seq_nr + 1;
                            
                            -- Increment Global Sample Count
                            global_sample_cnt_next  <= global_sample_cnt + 1;
                            
                            -- Signal Data Available
                            data_available_sig_next <= '1';
                            
                            -- NOTE: This is needed to prevent the new Sample to be selected during an Orphan Sample
                            --       Search, since the Dead Instance Address is the same as the new Sample Instance Address.
                            -- Latch Sample Address
                            new_sample_next <= cur_sample;
                            
                            -- Update Lifespan Check Time
                            if (LIFESPAN_QOS /= DURATION_INFINITE and lifespan < lifespan_time) then
                                lifespan_time_next  <= lifespan;
                            end if;
                            
                            if (remove_oldest_inst_sample = '1' or (remove_oldest_sample = '1' and remove_ack_sample = '1')) then
                                assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                                cur_sample_next <= oldest_sample;
                                stage_next      <= FIND_SAMPLE;
                                cnt_next        <= 0;
                            elsif (remove_oldest_sample = '1') then
                                assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                                -- Synthesis Guard
                                if (WITH_KEY) then
                                    stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                    cnt_next    <= 0;
                                else
                                    cur_sample_next <= oldest_sample;
                                    stage_next      <= REMOVE_SAMPLE;
                                    cnt_next        <= 0;
                                end if;
                            else
                                -- DONE
                                stage_next  <= IDLE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_OLDEST_SAMPLE_INSTANCE =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    case (cnt) is
                        -- GET Instance Pointer (Oldest Sample)
                        when 0 =>
                            sample_valid_in <= '1';
                            sample_addr     <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_read     <= '1';
                            
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        -- READ Instance Pointer (Oldest Sample)
                        when 1 =>
                            -- Memory Operation Guard
                            if (inst_op_done = '1') then
                                sample_ready_out    <= '1';
                                
                                -- Memory Flow Control Guard
                                if (sample_valid_out = '1') then
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_INSTANCE;
                                    inst_mem_fields     <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    inst_addr_update    <= resize(unsigned(sample_read_data), INSTANCE_MEMORY_ADDR_WIDTH);
                                    
                                    cur_sample_next     <= oldest_sample;
                                    stage_next          <= REMOVE_SAMPLE;
                                    cnt_next            <= 0;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when FIND_SAMPLE =>
                -- Precondition: cur_sample set
                
                case (cnt) is
                    -- GET Next Sample
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            if (remove_ack_sample = '1') then
                                cnt_next    <= cnt + 1;
                            else
                                assert(remove_oldest_inst_sample = '1') severity FAILURE;
                                
                                cnt_next    <= cnt + 2; -- Skip Next Step
                            end if;
                        end if;
                    -- GET Status Info
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Synthesis Guard
                            if (WITH_KEY) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= cnt + 2; -- Skip Next Step
                            end if;
                        end if;
                    -- GET Instance Pointer
                    when 2 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_valid_in <= '1';
                            sample_addr     <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_read     <= '1';
                            
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Next Sample
                    when 3 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            next_sample_next    <= resize(unsigned(sample_read_data), SAMPLE_MEMORY_ADDR_WIDTH);
                            
                            if (remove_ack_sample = '1') then
                                cnt_next    <= cnt + 1;
                            else
                                assert(remove_oldest_inst_sample = '1') severity FAILURE;
                                assert(WITH_KEY) severity FAILURE;
                                
                                cnt_next    <= cnt + 2; -- Skip Next Step
                            end if;
                        end if;
                    -- READ Status Info
                    when 4 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- Sample is ACKed
                            if (sample_read_data(SSI_ACK_FLAG) = '1') then
                                if (WITH_KEY) then
                                    cnt_next    <= cnt + 1;
                                else
                                    stage_next  <= REMOVE_SAMPLE;
                                    cnt_next    <= 0;
                                end if;
                            else
                                -- Continue
                                sample_abort_read   <= '1';
                                cur_sample_next     <= next_sample;
                                cnt_next            <= 0;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 5 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_ready_out    <= '1';
                            
                            -- Memory Flow Control Guard
                            if (sample_valid_out = '1') then
                                if (remove_oldest_sample = '1') then
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_INSTANCE;
                                    inst_mem_fields     <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    inst_addr_update    <= resize(unsigned(sample_read_data), INSTANCE_MEMORY_ADDR_WIDTH);
                                    
                                    stage_next  <= REMOVE_SAMPLE;
                                    cnt_next    <= 0;
                                -- Oldest Instance Sample Found
                                elsif (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = cur_inst) then
                                    -- NOTE: Instance Data already valid
                                    stage_next  <= REMOVE_SAMPLE;
                                    cnt_next    <= 0;
                                else
                                    -- Continue
                                    cur_sample_next <= next_sample;
                                    cnt_next        <= 0;
                                end if;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when REMOVE_ORPHAN_SAMPLES =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    case (cnt) is
                        -- GET Instance Pointer
                        when 0 =>
                            sample_valid_in <= '1';
                            sample_addr     <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_read     <= '1';
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        -- GET Next Sample
                        when 1 =>
                            sample_valid_in <= '1';
                            sample_addr     <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                            sample_read     <= '1';
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        -- READ Instance Pointer
                        when 2 =>
                            sample_ready_out    <= '1';
                            -- Memory Flow Control Guard
                            if (sample_valid_out = '1') then
                                -- Sample is Orphan (And not newly added sample of new instance)
                                if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = dead_inst and cur_sample /= new_sample) then
                                    -- Remove Orphan Sample
                                    stage_next          <= REMOVE_SAMPLE;
                                    cnt_next            <= 0;
                                    sample_abort_read   <= '1';
                                else
                                    cnt_next    <= cnt + 1;
                                end if;
                            end if;
                        -- READ Next Sample
                        when 3 =>
                            sample_ready_out    <= '1';
                            -- Memory Flow Control Guard
                            if (sample_valid_out = '1') then
                                -- End of Samples
                                if (resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- DONE
                                    orphan_samples_next <= '0';
                                    stage_next          <= IDLE;
                                else
                                    -- Continue
                                    cur_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
                                    cnt_next        <= 0;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when REMOVE_SAMPLE =>
                -- Precondition: cur_sample set
                
                case (cnt) is
                    -- GET Status Info
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Previous Pointer
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_PREV_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Next Pointer
                    when 2 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Payload Pointer
                    when 3 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Status Info
                    when 4 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- Latch Sample Status Info (For POST_SAMPLE_REMOVE State)
                            sample_status_info_next <= sample_read_data;
                            cnt_next                <= cnt + 1;
                        end if;
                    -- READ Previous Pointer
                    when 5 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            prev_sample_next    <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
                            cnt_next            <= cnt + 1;
                        end if;
                    -- READ Next Pointer
                    when 6 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            next_sample_next    <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
                            
                            -- Sample Memory Full
                            if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
                                empty_sample_list_head_next <= cur_sample;
                                empty_sample_list_tail_next <= cur_sample;
                                cnt_next    <= cnt + 2; --Skip Next Step
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Next Pointer (Empty List Tail)
                    when 7 =>
                        -- Add Current Sample after Empty List Tail
                        sample_valid_in     <= '1';
                        sample_addr         <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(cur_sample,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- SET Next Pointer
                    when 8 =>
                        -- Make Current Sample Empty List Tail
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Fix Empty List Pointers
                            empty_sample_list_tail_next <= cur_sample;
                            
                            -- Current Sample is Newest (Occupied List Tail)
                            if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                assert (cur_sample = newest_sample) severity FAILURE;
                                
                                -- Fix Newest Pointer
                                newest_sample_next  <= prev_sample;
                                
                                -- Current Sample is Oldest (List Head)
                                if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    assert (cur_sample = oldest_sample) severity FAILURE;
                                    assert (newest_sample = oldest_sample) severity FAILURE;
                                    -- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR)
                                    
                                    -- Fix Oldest Pointer
                                    oldest_sample_next  <= SAMPLE_MEMORY_MAX_ADDRESS;
                                    
                                    cnt_next    <= cnt + 3; -- Skip next 2 steps
                                else
                                    cnt_next    <= cnt + 2; -- Skip next step
                                end if;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Previous Pointer (Next Sample)
                    when 9 =>
                        -- Remove link to cur_sample
                        sample_valid_in     <= '1';
                        sample_addr         <= next_sample + SMF_PREV_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(prev_sample,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Current Sample is oldest sample (List Head)
                            if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
                                
                                -- Fix Oldest Pointer
                                oldest_sample_next  <= next_sample;
                                
                                cnt_next    <= cnt + 2; -- Skip next step
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Next Pointer (Previous Sample)
                    when 10 =>
                        -- Remove link to cur_sample
                        sample_valid_in     <= '1';
                        sample_addr         <= prev_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(next_sample,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Payload Pointer
                    when 11 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- Update Global Sample Count
                            global_sample_cnt_next  <= global_sample_cnt - 1;
                            
                            -- Update Global ACK Count
                            -- Sample was ACKed
                            if (sample_status_info(SSI_ACK_FLAG) = '1') then
                                global_ack_cnt_next <= global_ack_cnt - 1;
                            end if;
                            
                            cur_payload_next    <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                            -- Sample has no Data
                            if (resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                -- Orphan Sample Removal in progress
                                if (orphan_samples = '1') then
                                    -- End of Samples
                                    if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                        -- DONE
                                        orphan_samples_next <= '0';
                                        stage_next          <= IDLE;
                                    else
                                        -- Continue
                                        stage_next      <= REMOVE_ORPHAN_SAMPLES;
                                        cur_sample_next <= next_sample;
                                        cnt_next        <= 0;
                                    end if;
                                else
                                    stage_next  <= POST_SAMPLE_REMOVE;
                                end if;
                            -- Payload Memory Full
                            elsif (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                -- Fix Empty List Head
                                empty_payload_list_head_next    <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                                
                                -- Orphan Sample Removal in progress
                                if (orphan_samples = '1') then
                                    -- End of Samples
                                    if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                        -- DONE
                                        orphan_samples_next <= '0';
                                        stage_next          <= IDLE;
                                    else
                                        -- Continue
                                        stage_next      <= REMOVE_ORPHAN_SAMPLES;
                                        cur_sample_next <= next_sample;
                                        cnt_next        <= 0;
                                    end if;
                                else
                                    stage_next  <= POST_SAMPLE_REMOVE;
                                end if;
                            else
                                -- Latch First Payload Slot for later use
                                first_payload_next  <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- GET Next Payload
                    when 12 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        payload_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Next Payload
                    when 13 =>
                        payload_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_valid_out = '1') then
                            -- Found Empty List Tail
                            if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                cnt_next    <= cnt + 1;
                            else
                                cur_payload_next    <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                                cnt_next            <= cnt - 1;
                            end if;
                        end if;
                    -- SET Next Payload Pointer (Last Payload of Current Sample)
                    when 14 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        payload_write_data  <= std_logic_vector(resize(empty_payload_list_head,WORD_WIDTH));
                        
                        -- Fix Empty List Head
                        empty_payload_list_head_next    <= first_payload;
                        
                        -- Memory Flow Control Guard
                        if (payload_ready_in = '1') then
                            -- Orphan Sample Removal in progress
                            if (orphan_samples = '1') then
                                -- End of Samples
                                if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- DONE
                                    orphan_samples_next <= '0';
                                    stage_next          <= IDLE;
                                else
                                    -- Continue
                                    stage_next      <= REMOVE_ORPHAN_SAMPLES;
                                    cur_sample_next <= next_sample;
                                    cnt_next        <= 0;
                                end if;
                            else
                                stage_next  <= POST_SAMPLE_REMOVE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when POST_SAMPLE_REMOVE =>
                -- Precondition: inst_data set (Status Info, Sample Count, ACK Count)
                
                -- Memory Operation Guard
                if (not WITH_KEY or inst_op_done = '1') then
                    -- Synthesis Guard
                    if (WITH_KEY) then
                        inst_op_start   <= '1';
                        inst_opcode     <= UPDATE_INSTANCE;
                        inst_mem_fields <= IMF_SAMPLE_CNT_FLAG;
                        sample_cnt      <= inst_data.sample_cnt - 1;
                        -- Sample was ACKed
                        if (sample_status_info(SSI_ACK_FLAG) = '1') then
                            inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                            ack_cnt         <= inst_data.ack_cnt - 1;
                        else
                            -- Update Stale Instance Count
                            -- Instance is Unregistered and last NACKed sample is removed
                            if (inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1' and inst_data.sample_cnt = 1) then
                                stale_inst_cnt_next <= stale_inst_cnt + 1;
                            end if;
                        end if;
                    else
                        inst_data_next2.sample_cnt   <= inst_data.sample_cnt - 1;
                        -- Sample was ACKed
                        if (sample_status_info(SSI_ACK_FLAG) = '1') then
                            inst_data_next2.ack_cnt  <= inst_data.ack_cnt - 1;
                        end if;
                    end if;
                    
                    if (is_rtps = '1') then
                        -- DONE
                        done_rtps   <= '1';
                        ret_rtps    <= OK;
                        stage_next  <= IDLE;
                    elsif (is_lifespan_check = '1') then
                        -- Reached End of Samples
                        if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Continue Search
                            cur_sample_next     <= next_sample;
                            stage_next          <= CHECK_LIFESPAN;
                            cnt_next            <= 0;
                        end if;
                    else
                        -- DONE
                        stage_next  <= IDLE;
                    end if;
                end if;
            when SKIP_AND_RETURN =>
                case (cnt) is
                    -- SKIP READ
                    when 0 =>
                        ready_in_dds  <= '1';
                        -- Wait until last word from input
                        if (last_word_in_dds  = '1') then
                            cnt_next  <= cnt + 1;
                        end if;
                    -- Return Code
                    when 1 =>
                        done_dds        <= '1';
                        return_code_dds <= return_code_latch;
                        
                        -- DONE
                        stage_next      <= IDLE;
                    when others =>
                        null;
                end case;
            when SKIP =>
                ready_in_dds  <= '1';
                -- Wait until last word from input
                if (last_word_in_dds  = '1') then
                    stage_next  <= return_stage;
                    cnt_next    <= 0;
                end if;
            when REMOVE_STALE_INSTANCE =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    -- Wait for Instance Data
                    if (inst_op_done = '1') then
                        case (cnt) is
                            -- Find and Remove First Stale Instance
                            when 0 =>
                                -- Iterated through all Instances
                                if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    -- NOTE: We should enter this state only if there is at least one stale Instance to be removed, so we should never enter this branch.
                                    assert FALSE severity FAILURE;
                                    stage_next  <= IDLE;
                                else
                                    -- Found Stale Instance (Unregistered and all Samples ACKed)
                                    if (inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1' and inst_data.sample_cnt = inst_data.ack_cnt) then
                                        -- Remove Stale Instance
                                        inst_op_start   <= '1';
                                        inst_opcode     <= REMOVE_INSTANCE;
                                        -- Update Stale Instance Count
                                        stale_inst_cnt_next <= stale_inst_cnt - 1;
                                        
                                        -- Instance has Samples
                                        if (inst_data.sample_cnt /= 0) then
                                            -- NOTE: The Stale Instance has Samples that need to be removed, but we cannot do that now, 
                                            --       because that would mess with our current Sample that is currently in "limbo" until
                                            --       finalized. So we postpone the Sample removal until after the finalization of the 
                                            --       current sample.
                                            orphan_samples_next <= '1';
                                            dead_inst_next      <= inst_addr_base;
                                        end if;
                                        
                                        cnt_next    <= cnt + 1;
                                    else
                                        -- Continue Search
                                        inst_op_start   <= '1';
                                        inst_opcode     <= GET_NEXT_INSTANCE;
                                        inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    end if;
                                end if;
                            -- Insert New Instance
                            when 1 =>
                                inst_op_start       <= '1';
                                inst_opcode         <= INSERT_INSTANCE;
                                ack_cnt             <= (others => '0');
                                if (register_op = '1') then
                                    status_info_update  <= (others => '0');
                                    sample_cnt          <= (others => '0');
                                else
                                    status_info_update  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                    sample_cnt          <= to_unsigned(1, WORD_WIDTH);
                                end if;
                                
                                -- Latch Instance Pointer
                                cur_inst_next   <= inst_empty_head; 
                                
                                -- Register Operation in progress
                                if (register_op = '1') then
                                    -- DONE
                                    stage_next  <= PUSH_KEY_HASH;
                                    cnt_next    <= 0;
                                else
                                    stage_next  <= FINALIZE_PAYLOAD;
                                    cnt_next    <= 0;
                                end if;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when GET_SEQ_NR =>
                -- Precondition: cur_sample set
                
                case (cnt) is
                    -- GET Sequence Number 1/2
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_SEQ_NR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Sequence Number 2/2
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_SEQ_NR_OFFSET + 1;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Sequence Number 1/2
                    when 2 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            cc_seq_nr_sig_next(0)   <= unsigned(sample_read_data);
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Sequence Number 2/2
                    when 3 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            cc_seq_nr_sig_next(1)   <= unsigned(sample_read_data);
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Return Code
                    when 4 =>
                        done_rtps   <= '1';
                        ret_rtps    <= OK;
                        
                        -- DONE
                        stage_next  <= IDLE;
                    when others =>
                        null;
                end case;
            when FIND_SEQ_NR =>
                -- NOTE: We are searching in backwards order, since it is more likely that newer Sequence Numbers are polled
                case (cnt) is
                    -- GET Previous Sample
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_PREV_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Sequence Number 1/2
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_SEQ_NR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Sequence Number 2/2
                    when 2 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_SEQ_NR_OFFSET + 1;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            if (WITH_KEY) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= cnt + 2; -- Skip Next Step
                            end if;
                        end if;
                    -- GET Instance Pointer
                    when 3 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_valid_in <= '1';
                            sample_addr     <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_read     <= '1';
                            
                            -- Memory Flow Control Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Previous Sample
                    when 4 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            prev_sample_next    <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
                            cnt_next            <= cnt + 1;
                        end if;
                    -- READ Sequence Number 1/2
                    when 5 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- No Match
                            if (unsigned(sample_read_data) /= seq_nr(0)) then
                                sample_abort_read   <= '1';
                                -- End of Samples
                                if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- No Sample with SN found
                                    cur_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
                                    cnt_next        <= 8;
                                else
                                    -- Continue
                                    cur_sample_next <= prev_sample;
                                    cnt_next        <= 0;
                                end if;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Sequence Number 2/2
                    when 6 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- No Match
                            if (unsigned(sample_read_data) /= seq_nr(1)) then
                                sample_abort_read   <= '1';
                                -- End of Samples
                                if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- No Sample with SN found
                                    cur_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
                                    cnt_next        <= 8;
                                else
                                    -- Continue
                                    cur_sample_next <= prev_sample;
                                    cnt_next        <= 0;
                                end if;
                            else
                                if (WITH_KEY) then
                                    cnt_next    <= cnt + 1;
                                else
                                    cnt_next    <= cnt + 2; -- Skip Next Step
                                end if;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 7 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_ready_out    <= '1';
                            
                            -- Memory Flow Control Guard
                            if (sample_valid_out = '1') then
                                cur_inst_next   <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                cnt_next        <= cnt + 1;
                            end if;
                        end if;
                    -- Check Result
                    when 8 =>
                        -- No Sample with Requested Sequence Number found
                        if (cur_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                            done_rtps   <= '1';
                            ret_rtps    <= INVALID;
                            
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Synthesis Guard
                            if (WITH_KEY) then
                                -- Memory Operation Guard
                                if (inst_op_done = '1') then
                                    -- Fetch Instance Data
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_INSTANCE;
                                    inst_mem_fields     <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    inst_addr_update    <= cur_inst;
                                    
                                    stage_next  <= return_stage;
                                    cnt_next    <= 0;
                                end if;
                            else
                                stage_next  <= return_stage;
                                cnt_next    <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when ACKNACK_SAMPLE =>
                case (cnt) is
                    -- GET Status Info
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_read     <= '1';
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Status Info
                    when 1 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            sample_status_info_next <= sample_read_data;
                            
                            -- Sample Already ACKed/NACKed
                            if ((is_ack = '1' and sample_read_data(SSI_ACK_FLAG) = '1') or (is_ack = '0' and sample_read_data(SSI_ACK_FLAG) = '0')) then
                                done_rtps   <= '1';
                                ret_rtps    <= OK;
                                -- DONE
                                stage_next  <= IDLE;
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Status Info
                    when 2 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_write_data   <= sample_status_info;
                        sample_write_data(SSI_ACK_FLAG) <= '1' when (is_ack = '1') else '0';
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            global_ack_cnt_next <= (global_ack_cnt + 1) when (is_ack = '1') else (global_ack_cnt - 1);
                            cnt_next            <= cnt + 1;
                        end if;
                    -- SET Instance Data
                    when 3 =>
                        if (WITH_KEY) then
                            -- Wait for Instance Data
                            if (inst_op_done = '1') then
                                -- Update 
                                inst_op_start       <= '1';
                                inst_opcode         <= UPDATE_INSTANCE;
                                inst_mem_fields     <= IMF_ACK_CNT_FLAG;
                                inst_addr_update    <= cur_inst;
                                ack_cnt             <= (inst_data.ack_cnt + 1) when (is_ack = '1') else (inst_data.ack_cnt - 1);
                                
                                -- Update Stale Instance Count
                                -- XXX: Possible Worst Case Path (Addition and Comparison in same clock)
                                if (is_ack = '1' and inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1' and (inst_data.ack_cnt+1) = inst_data.sample_cnt) then
                                    stale_inst_cnt_next <= stale_inst_cnt + 1;
                                elsif (is_ack = '0' and inst_data.status_info(ISI_UNREGISTERED_FLAG) = '1' and inst_data.ack_cnt = inst_data.sample_cnt) then
                                    stale_inst_cnt_next <= stale_inst_cnt - 1;
                                end if;
                                
                                -- DONE
                                done_rtps   <= '1';
                                ret_rtps    <= OK;
                                stage_next  <= IDLE;
                            end if;
                        else
                            inst_data_next2.ack_cnt <= (inst_data.ack_cnt + 1) when (is_ack = '1') else (inst_data.ack_cnt - 1);
                            
                            -- DONE
                            done_rtps   <= '1';
                            ret_rtps    <= OK;
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_SAMPLE =>
                case (cnt) is
                    -- GET Status Info
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_STATUS_INFO_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Timestamp 1/2
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_TIMESTAMP_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Timestamp 2/2
                    when 2 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Payload Pointer
                    when 3 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Status Info
                    when 4 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            -- NOTE: SSI_UNREGISTERED_FLAG takes precedence over SSI_DISPOSED_FLAG, because a Disposed Instance
                            --       can still be Unregistered, but not the other way around.
                            if (sample_read_data(SSI_UNREGISTERED_FLAG) = '1') then
                                cc_kind_sig_next    <= NOT_ALIVE_UNREGISTERED;
                            elsif (sample_read_data(SSI_DISPOSED_FLAG) = '1') then
                                cc_kind_sig_next    <= NOT_ALIVE_DISPOSED;
                            else
                                cc_kind_sig_next    <= ALIVE;
                            end if;
                            -- Latch Status Info (For GET_PAYLOAD State)
                            sample_status_info_next <= sample_read_data;
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Timestamp 1/2
                    when 5 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            cc_source_timestamp_sig_next(0) <= unsigned(sample_read_data);
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Timestamp 2/2
                    when 6 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            cc_source_timestamp_sig_next(1) <= unsigned(sample_read_data);
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Payload Pointer
                    when 7 =>
                        sample_ready_out    <= '1';
                        -- Memory Flow Control Guard
                        if (sample_valid_out = '1') then
                            cur_payload_next    <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                            
                            if (WITH_KEY) then
                                cnt_next    <= cnt + 1;
                            else    
                                cnt_next    <= cnt + 2; -- Skip Next Step
                            end if;
                        end if;
                    -- Instance Handle
                    when 8 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            -- Wait for Instance Data
                            if (inst_op_done = '1') then
                                cc_instance_handle_sig_next <= inst_data.key_hash;
                                
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- Present Sample
                    when 9 =>
                        done_rtps   <= '1';
                        ret_rtps    <= OK;
                        
                        -- RTPS Requestes Payload
                        if (get_data_rtps = '1') then
                            if (cur_payload /= PAYLOAD_MEMORY_MAX_ADDRESS) then
                                -- Get Payload
                                stage_next  <= GET_PAYLOAD;
                                cnt_next    <= 0;
                                cnt2_next   <= 0;
                                cnt3_next   <= 0;
                            else
                                assert FALSE report "Payload Requested, while no Payload available" severity FAILURE;
                                stage_next  <= IDLE;
                            end if;
                        else
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_PAYLOAD =>
                -- Precondition: cur_payload set, sample_status_info set
                
                -- NOTE: We are using the Burst Capability of the Memory Controller as a FIFO which we
                --       fill and the output is directly reading. cnt is switching the memory reading states,
                --       cnt2 signals the offset of the payload read, and cnt3 signals how many Bytes have been
                --       requested but not yet claimed (i.e. how many Bytes are in the FIFO).
                
                -- DEFAULT
                tmp_bool    := FALSE;
                
                case (cnt) is
                    -- GET Next Pointer
                    when 0 =>
                        -- NOTE: We have to make sure that no pending Reads are in the Memory Controler Buffer,
                        --       else the Next Payload Pointer cannot be read.
                        -- No Pending Reads
                        if (cnt3 = 0) then
                            payload_valid_in    <= '1';
                            payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                            payload_read        <= '1';
                            
                            -- Memory Flow Control Guard
                            if (payload_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Next Pointer
                    when 1 =>
                        payload_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_valid_out = '1') then
                            next_payload_next   <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
                            cnt2_next           <= 1;
                            
                            -- Last Payload Slot is unaligned
                            if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS and sample_status_info(SSI_ALIGNED_FLAG) = '0') then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next        <= cnt + 3;
                                long_latch_next <= std_logic_vector(to_unsigned(PAYLOAD_FRAME_SIZE-1,CDR_LONG_WIDTH));
                            end if;
                        end if;
                    -- GET Payload Offset
                    when 2 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PAYLOAD_FRAME_SIZE-1;
                        payload_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Payload Offset
                    when 3 =>
                        payload_ready_out   <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_valid_out = '1') then
                            long_latch_next <= payload_read_data;
                            cnt_next        <= cnt + 1;
                        end if;
                    -- GET PAYLOAD
                    when 4 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + cnt2;
                        payload_read        <= '1';
                        
                        -- Memory Flow Control Guard
                        if (payload_ready_in = '1') then
                            cnt3_next   <= cnt3 + 1;
                            tmp_bool    := TRUE;
                            -- End of Payload Slot
                            if (cnt2 = unsigned(long_latch)) then
                                -- End of Payload
                                if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    -- DONE (Wait for Output to finidh reading)
                                    cnt_next    <= cnt + 1;
                                else
                                    -- Next Payload Slot
                                    cur_payload_next    <= next_payload;
                                    cnt_next            <= 0;
                                end if;
                            else
                                cnt2_next   <= cnt2 + 1;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
                
                -- Data available for Output
                if (cnt3 /= 0) then
                    -- Memory Flow Control Guard
                    if (payload_valid_out = '1') then
                        valid_out_rtps  <= '1';
                        data_out_rtps   <= payload_read_data;
                        
                        -- End of Payload
                        if (cnt3 = 1 and cnt = 5) then
                            last_word_out_rtps  <= '1';
                        end if;
                        
                        -- DDS Read
                        if (ready_out_rtps = '1') then
                            payload_ready_out   <= '1';
                            -- NOTE: We are using the tmp_bool variable to signal if there is an increment
                            --       on the same clock cycle.
                            -- Increment in same clock cycle
                            if (tmp_bool) then
                                cnt3_next   <= cnt3; -- Override increment
                            else                            
                                cnt3_next   <= cnt3 - 1;
                            end if;
                        end if;
                    end if;
                -- Finished Reading
                elsif (cnt = 5) then
                    assert (cnt3 = 0) severity FAILURE;
                    -- DONE
                    stage_next  <= IDLE;
                end if;
            when CHECK_LIFESPAN =>
                -- Precondition: cur_sample set, 
                
                case (cnt) is
                    -- GET Next Sample
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Lifespan 1/2
                    when 1 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET;
                        sample_read     <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Lifespan 2/2
                    when 2 =>
                        sample_valid_in <= '1';
                        sample_addr     <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1;
                        sample_read     <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_ready_in = '1') then
                            if (WITH_KEY) then
                                cnt_next    <= cnt + 1;
                            else
                                cnt_next    <= cnt + 2; --Skip Next Step
                            end if;
                        end if;
                    -- GET Instance Pointer
                    when 3 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            sample_valid_in <= '1';
                            sample_addr     <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                            sample_read     <= '1';
                            
                            -- Memory Control Flow Guard
                            if (sample_ready_in = '1') then
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Next Sample
                    when 4 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_valid_out = '1') then
                            next_sample_next    <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
                            cnt_next            <= cnt + 1;
                        end if;
                    -- READ Lifespan 1/2
                    when 5 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_valid_out = '1') then
                            long_latch_next <= sample_read_data;
                            cnt_next        <= cnt + 1;
                        end if;
                    -- READ Lifespan 2/2
                    when 6 =>
                        sample_ready_out    <= '1';
                        
                        -- Memory Control Flow Guard
                        if (sample_valid_out = '1') then
                            tmp_dw  := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
                        
                            -- Sample Lifespan Expired
                            if (tmp_dw /= TIME_INVALID and time >= tmp_dw) then
                                if (WITH_KEY) then
                                    cnt_next    <= cnt + 1;
                                else
                                    -- Remove Sample
                                    stage_next  <= REMOVE_SAMPLE;
                                    cnt_next    <= 0;
                                end if;
                            else
                                sample_abort_read   <= '1';
                                
                                -- Update Check Time
                                if (tmp_dw /= TIME_INVALID and tmp_dw < lifespan_time) then
                                    lifespan_time_next  <= tmp_dw;
                                end if;
                                
                                -- Reached End of Samples
                                if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- DONE
                                    stage_next  <= IDLE;
                                else
                                    -- Continue Search
                                    cur_sample_next <= next_sample;
                                    cnt_next        <= 0;
                                end if;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 7 =>
                        -- Synthesis Guard
                        if (WITH_KEY) then
                            -- Memory Operation Guard
                            if (inst_op_done = '1') then
                                sample_ready_out    <= '1';
                                
                                -- Memory Control Flow Guard
                                if (sample_valid_out = '1') then
                                    -- Fetch Instance Data
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_INSTANCE;
                                    inst_mem_fields     <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                    inst_addr_update    <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                    
                                    -- Remove Sample
                                    stage_next  <= REMOVE_SAMPLE;
                                    cnt_next    <= 0;
                                end if;
                            end if;
                        end if;
                    when others => 
                        null;
                end case;
            when GET_LIVELINESS_LOST_STATUS =>
                case (cnt) is
                    -- Return Code
                    when 0  =>
                        done_dds        <= '1';
                        return_code_dds <= RETCODE_OK;
                        cnt_next        <= cnt + 1;    
                    -- Total Count
                    when 1 =>
                        data_out_dds    <= std_logic_vector(liveliness_lost_cnt);
                        valid_out_dds   <= '1';
                        
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Total Count Change
                    when 2 =>
                        data_out_dds        <= std_logic_vector(liveliness_lost_cnt_change);
                        valid_out_dds       <= '1';
                        last_word_out_dds   <= '1';
                        
                        if (ready_out_dds = '1') then
                            -- Reset
                            liveliness_lost_cnt_change_next <= (others => '0');
                            status_sig_next <= status_sig and (not LIVELINESS_LOST_STATUS);
                            
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_OFFERED_DEADLINE_MISSED_STATUS =>
                case (cnt) is
                    -- Return Code
                    when 0 =>
                        done_dds        <= '1';
                        return_code_dds <= RETCODE_OK;
                        cnt_next        <= cnt + 1;
                    -- Total Count
                    when 1 =>
                        data_out_dds    <= std_logic_vector(deadline_miss_cnt);
                        valid_out_dds   <= '1';
                        
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Total Count Change
                    when 2 =>
                        data_out_dds    <= std_logic_vector(deadline_miss_cnt_change);
                        valid_out_dds   <= '1';
                        
                        if (ready_out_dds = '1') then
                            -- Reset
                            deadline_miss_cnt_change_next   <= (others => '0');
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 1/4
                    when 3 =>
                        data_out_dds    <= deadline_miss_last_inst(0);
                        valid_out_dds   <= '1';
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 2/4
                    when 4 =>
                        data_out_dds    <= deadline_miss_last_inst(1);
                        valid_out_dds   <= '1';
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 3/4
                    when 5 =>
                        data_out_dds    <= deadline_miss_last_inst(2);
                        valid_out_dds   <= '1';
                        if (ready_out_dds = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 4/4
                    when 6 =>
                        data_out_dds        <= deadline_miss_last_inst(3);
                        valid_out_dds       <= '1';
                        last_word_out_dds   <= '1';
                        if (ready_out_dds = '1') then
                            -- Reset
                            status_sig_next <= status_sig and (not OFFERED_DEADLINE_MISSED_STATUS);
                            
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when CHECK_DEADLINE =>
                -- Synthesis Guard
                if (WITH_KEY) then
                    -- Memory Operation Guard
                    if (inst_op_done = '1') then
                        case (cnt) is
                            -- Get First Instance
                            when 0 =>
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_FIRST_INSTANCE;
                                inst_mem_fields     <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
                                cnt_next    <= 2;
                            -- Get Next Instance
                            when 1 =>
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_NEXT_INSTANCE;
                                inst_mem_fields     <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
                                cnt_next    <= 2;
                            -- Check Instance
                            when 2 =>
                                -- Reached End of Instances
                                if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    -- DONE
                                    stage_next  <= IDLE;
                                else
                                    -- Instance received Sample
                                    if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then
                                        -- Reset Liveliness Flag
                                        inst_op_start       <= '1';
                                        inst_opcode         <= UPDATE_INSTANCE;
                                        inst_mem_fields     <= IMF_STATUS_FLAG;
                                        status_info_update  <= inst_data.status_info;
                                        status_info_update(ISI_LIVELINESS_FLAG) <= '0';
                                        cnt_next    <= 1;
                                    else
                                        -- Update Requested Deadline Missed Status
                                        status_sig_next <= status_sig or OFFERED_DEADLINE_MISSED_STATUS;
                                        deadline_miss_cnt_next          <= deadline_miss_cnt + 1;
                                        deadline_miss_cnt_change_next   <= deadline_miss_cnt_change + 1;
                                        deadline_miss_last_inst_next    <= inst_data.key_hash;
                                        cnt_next    <= 1;
                                    end if;
                                end if;
                            when others =>
                                null;
                        end case;
                    end if;
                end if;
            when RESET_SAMPLE_MEMORY =>
                case (cnt) is
                    -- Initialize
                    when 0 =>
                        prev_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                        cur_sample_next     <= (others => '0');
                        cnt_next            <= cnt + 1;
                    -- SET Previous Pointer
                    when 1 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_PREV_ADDR_OFFSET;
                        sample_write_data   <= std_logic_vector(resize(prev_sample,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- SET Next Pointer
                    when 2 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        if (cur_sample = MAX_SAMPLE_ADDRESS) then
                            sample_write_data   <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        else
                            sample_write_data   <= std_logic_vector(resize(cur_sample + SAMPLE_FRAME_SIZE,WORD_WIDTH));
                        end if;
                        
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            if (cur_sample = MAX_SAMPLE_ADDRESS) then
                                -- DONE
                                stage_next  <= RESET_PAYLOAD_MEMORY;
                                cnt_next    <= 0;
                            else
                                -- Continue
                                cur_sample_next     <= cur_sample + SAMPLE_FRAME_SIZE;
                                prev_sample_next    <= cur_sample;
                                cnt_next            <= 1;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_PAYLOAD_MEMORY =>
                case (cnt) is
                    -- Initialize
                    when 0 =>
                        cur_payload_next    <= (others => '0');
                        cnt_next            <= cnt + 1;
                    -- SET Next Pointer
                    when 1 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                        if (cur_payload = MAX_PAYLOAD_ADDRESS) then
                            payload_write_data  <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        else
                            payload_write_data  <= std_logic_vector(resize(cur_payload + PAYLOAD_FRAME_SIZE,WORD_WIDTH));
                        end if;
                        
                        -- Memory Flow Control Guard
                        if (payload_ready_in = '1') then
                            if (cur_payload = MAX_PAYLOAD_ADDRESS) then
                                -- DONE
                                stage_next  <= IDLE;
                            else
                                cur_payload_next    <= cur_payload + PAYLOAD_FRAME_SIZE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when others =>
                null;
        end case;
    end process;
    
    gen_inst_ctrl_prc : if WITH_KEY generate
    
        -- *Instance Memory Process*
        -- STATE                    DESCRIPTION
        -- IDLE                     Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
        -- SEARCH_INSTANCE_HASH     See Memory OPCODE Description
        -- SEARCH_INSTANCE_ADDR     See Memory OPCODE Description
        -- GET_NEXT_INSTANCE        See Memory OPCODE Description
        -- GET_INSTANCE_DATA        Latch specified Instance Data for use by main process
        -- INSERT_INSTANCE          See Memory OPCODE Description
        -- UPDATE_INSTANCE          See Memory OPCODE Description
        -- REMOVE_INSTANCE          See Memory OPCODE Description
        -- RESET_MEMORY             Reset Endpoint Memory to Empty State
        inst_ctrl_prc : process(all)
        begin
            -- DEFAULT Registered
            inst_stage_next             <= inst_stage;
            inst_addr_base_next         <= inst_addr_base;
            inst_empty_head_next        <= inst_empty_head;
            inst_occupied_head_next     <= inst_occupied_head;
            inst_latch_data_next        <= inst_latch_data;
            inst_next_addr_base_next    <= inst_next_addr_base;
            inst_prev_addr_base_next    <= inst_prev_addr_base;
            inst_cnt_next               <= inst_cnt;
            inst_data_next              <= inst_data;
            inst_long_latch_next        <= inst_long_latch;
            -- DEFAULT Unregistered
            inst_ready_out      <= '0';
            inst_valid_in       <= '0';
            inst_read           <= '0';
            inst_op_done        <= '0';
            inst_abort_read     <= '0';
            inst_addr           <= (others => '0');
            inst_write_data     <= (others => '0');
            
            
            case (inst_stage) is
                when IDLE =>
                    inst_op_done    <= '1';
                    
                    if (inst_op_start = '1') then
                        -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
                        inst_latch_data_next    <= (
                            key_hash        => key_hash_next,
                            status_info     => status_info_update,
                            sample_cnt      => sample_cnt,
                            ack_cnt         => ack_cnt,
                            field_flags     => inst_mem_fields,
                            addr            => inst_addr_update
                        );
                        
                        case(inst_opcode) is
                            when SEARCH_INSTANCE_HASH =>
                                -- Reset Data
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                
                                -- No Instances available
                                if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                else
                                    inst_prev_addr_base_next    <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    inst_addr_base_next         <= inst_occupied_head;
                                    inst_stage_next             <= SEARCH_INSTANCE_HASH;
                                    inst_cnt_next               <= 0;
                                end if;
                            when SEARCH_INSTANCE_ADDR =>
                                -- Reset Data
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                
                                -- No Instances avialable
                                if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                else
                                    inst_prev_addr_base_next    <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    inst_addr_base_next         <= inst_occupied_head;
                                    inst_stage_next             <= SEARCH_INSTANCE_ADDR;
                                    inst_cnt_next               <= 0;
                                end if;
                            when INSERT_INSTANCE =>
                                -- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure
                                --       by the main process that the operation can succeed (Memory is available)
                                assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE;
                                
                                inst_addr_base_next         <= inst_empty_head;
                                inst_stage_next             <= INSERT_INSTANCE;
                                inst_cnt_next               <= 0;
                                
                                -- SET Instance Data
                                inst_data_next.key_hash     <= key_hash_next;
                                inst_data_next.status_info  <= status_info_update;
                                inst_data_next.sample_cnt   <= sample_cnt;
                                inst_data_next.ack_cnt      <= ack_cnt;
                            when UPDATE_INSTANCE =>
                                inst_stage_next     <= UPDATE_INSTANCE;
                                if check_mask(inst_mem_fields,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 0;
                                elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 1;
                                elsif check_mask(inst_mem_fields,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 2;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            when GET_FIRST_INSTANCE =>
                                -- No Instances avialable
                                if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                else
                                    inst_prev_addr_base_next    <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    inst_addr_base_next         <= inst_occupied_head;
                                    inst_stage_next             <= GET_NEXT_INSTANCE;
                                    inst_cnt_next               <= 0;
                                end if;
                            when GET_NEXT_INSTANCE =>
                                -- No Instances avialable
                                if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                else
                                    inst_prev_addr_base_next    <= inst_addr_base;
                                    inst_addr_base_next         <= inst_next_addr_base;
                                    inst_stage_next             <= GET_NEXT_INSTANCE;
                                    inst_cnt_next               <= 0;
                                end if;
                            when REMOVE_INSTANCE =>
                                inst_stage_next <= REMOVE_INSTANCE;
                                inst_cnt_next   <= 0;
                            when GET_INSTANCE =>
                                inst_addr_base_next <= inst_addr_update;
                                -- Get Instance Data
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                inst_stage_next <= GET_INSTANCE_DATA;
                                if check_mask(inst_mem_fields,IMF_KEY_HASH_FLAG) then
                                    inst_cnt_next   <= 0;
                                elsif check_mask(inst_mem_fields,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 4;
                                elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 5;
                                elsif check_mask(inst_mem_fields,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 6;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            when others =>
                                null;
                        end case;
                    end if;
                when SEARCH_INSTANCE_HASH =>
                    
                    case (inst_cnt) is
                        -- GET Next Instance
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 1/4
                        when 1 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 2/4
                        when 2 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 3/4
                        when 3 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 4/4
                        when 4 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Next Instance
                        when 5 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_next_addr_base_next    <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Key Hash 1/4
                        when 6 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                -- No Match
                                if (inst_read_data /= inst_latch_data.key_hash(0)) then
                                    inst_abort_read <= '1';
                                    -- Reached List Tail, No Match
                                    if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                        inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                        -- DONE
                                        inst_stage_next       <= IDLE;
                                    else
                                        -- Continue Search
                                        inst_prev_addr_base_next    <= inst_addr_base;
                                        inst_addr_base_next         <= inst_next_addr_base;
                                        inst_cnt_next               <= 0;
                                    end if;
                                else
                                    inst_cnt_next   <= inst_cnt + 1;
                                end if;
                            end if;
                        -- READ Key Hash 2/4
                        when 7 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                -- No Match
                                if (inst_read_data /= inst_latch_data.key_hash(1)) then
                                    inst_abort_read <= '1';
                                    -- Reached List Tail, No Match
                                    if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                        inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                        -- DONE
                                        inst_stage_next       <= IDLE;
                                    else
                                        -- Continue Search
                                        inst_prev_addr_base_next    <= inst_addr_base;
                                        inst_addr_base_next         <= inst_next_addr_base;
                                        inst_cnt_next               <= 0;
                                    end if;
                                else
                                    inst_cnt_next   <= inst_cnt + 1;
                                end if;
                            end if;
                        -- READ Key Hash 3/4
                        when 8 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                -- No Match
                                if (inst_read_data /= inst_latch_data.key_hash(2)) then
                                    inst_abort_read <= '1';
                                    -- Reached List Tail, No Match
                                    if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                        inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                        -- DONE
                                        inst_stage_next       <= IDLE;
                                    else
                                        -- Continue Search
                                        inst_prev_addr_base_next    <= inst_addr_base;
                                        inst_addr_base_next         <= inst_next_addr_base;
                                        inst_cnt_next               <= 0;
                                    end if;
                                else
                                    inst_cnt_next   <= inst_cnt + 1;
                                end if;
                            end if;
                        -- READ Key Hash 4/4
                        when 9 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                -- No Match
                                if (inst_read_data /= inst_latch_data.key_hash(3)) then
                                    -- Reached List Tail, No Match
                                    if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                        inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                        -- DONE
                                        inst_stage_next       <= IDLE;
                                    else
                                        -- Continue Search
                                        inst_prev_addr_base_next    <= inst_addr_base;
                                        inst_addr_base_next         <= inst_next_addr_base;
                                        inst_cnt_next               <= 0;
                                    end if;
                                else
                                    -- Get Instance Data
                                    inst_data_next  <= ZERO_INSTANCE_DATA;
                                    inst_stage_next <= GET_INSTANCE_DATA;
                                    if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                        inst_cnt_next   <= 0;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                        inst_cnt_next   <= 4;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                        inst_cnt_next   <= 5;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                        inst_cnt_next   <= 6;
                                    else
                                        -- DONE
                                        inst_stage_next <= IDLE;
                                    end if;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                when SEARCH_INSTANCE_ADDR =>
                    
                    case (inst_cnt) is
                        -- GET Next Instance
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Next Instance
                        when 1 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_prev_addr_base_next  <= inst_addr_base;
                                inst_addr_base_next       <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                            
                                -- Match
                                if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = inst_latch_data.addr) then
                                    -- Get Instance Data
                                    inst_stage_next <= GET_INSTANCE_DATA;
                                    inst_data_next  <= ZERO_INSTANCE_DATA;
                                    if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                        inst_cnt_next   <= 0;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                        inst_cnt_next   <= 4;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                        inst_cnt_next   <= 5;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                        inst_cnt_next   <= 6;
                                    else
                                        -- DONE
                                        inst_stage_next <= IDLE;
                                    end if;
                                -- No Match
                                else
                                    -- Reached List Tail, No Match
                                    if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = INSTANCE_MEMORY_MAX_ADDRESS) then
                                        inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                        -- DONE
                                        inst_stage_next       <= IDLE;
                                    else
                                        -- Continue Search
                                        inst_cnt_next   <= 0;
                                    end if;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                when GET_NEXT_INSTANCE =>
                    case (inst_cnt) is
                        -- GET next Instance
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Next Instance
                        when 1 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_next_addr_base_next    <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                -- Get Instance Data
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                inst_stage_next <= GET_INSTANCE_DATA;
                                if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                    inst_cnt_next   <= 0;
                                elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 4;
                                elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 5;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 6;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                when GET_INSTANCE_DATA =>
                    case (inst_cnt) is
                        -- GET Key Hash 1/4
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 2/4
                        when 1 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 3/4
                        when 2 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- GET Key Hash 4/4
                        when 3 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 4;
                                elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 5;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 6;
                                else
                                    inst_cnt_next   <= 7;
                                end if;
                            end if;
                        -- GET Status Info
                        when 4 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 5;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 6;
                                else
                                    if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                        inst_cnt_next   <= 7;
                                    else
                                        inst_cnt_next   <= 11;
                                    end if;
                                end if;
                            end if;
                        -- GET Sample Count
                        when 5 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 6;
                                else
                                    if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                        inst_cnt_next   <= 7;
                                    elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                        inst_cnt_next   <= 11;
                                    else
                                        inst_cnt_next   <= 12;
                                    end if;
                                end if;
                            end if;
                        -- GET ACK Count
                        when 6 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_ACK_CNT_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
                                    inst_cnt_next   <= 7;
                                elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 11;
                                elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 12;
                                else
                                    inst_cnt_next   <= 13;
                                end if;
                            end if;
                        -- READ Key Hash 1/4
                        when 7 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.key_hash(0)  <= inst_read_data;
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Key Hash 2/4
                        when 8 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.key_hash(1)  <= inst_read_data;
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Key Hash 3/4
                        when 9 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.key_hash(2)  <= inst_read_data;
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Key Hash 4/4
                        when 10 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.key_hash(3)  <= inst_read_data;
                                
                                if check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 11;
                                elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 12;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 13;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        -- READ Status Info
                        when 11 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.status_info  <= inst_read_data;
                                
                                if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 12;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 13;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        -- READ Sample Count
                        when 12 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.sample_cnt   <= unsigned(inst_read_data);
                                
                                if check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 13;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        -- READ ACK Count
                        when 13 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_data_next.ack_cnt  <= unsigned(inst_read_data);
                                
                                -- DONE
                                inst_stage_next <= IDLE;
                            end if;
                    end case;
                when INSERT_INSTANCE =>
                    -- Precondition: inst_addr_base set
                    
                    case (inst_cnt) is
                        -- GET Next Instance Pointer
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Next Instance Pointer
                        when 1 =>
                            inst_valid_in           <= '1';
                            inst_addr               <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_write_data         <= std_logic_vector(resize(inst_occupied_head,WORD_WIDTH));
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                -- Fix Occupied List Head
                                inst_occupied_head_next <= inst_addr_base;
                                
                                inst_cnt_next           <= inst_cnt + 1;
                            end if;
                        -- READ Next Instance Pointer
                        when 2 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                -- Fix Empty List Head
                                inst_empty_head_next    <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Key Hash 1/4
                        when 3 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET;
                            inst_write_data <= inst_latch_data.key_hash(0);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Key Hash 2/4
                        when 4 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
                            inst_write_data <= inst_latch_data.key_hash(1);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Key Hash 3/4
                        when 5 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
                            inst_write_data <= inst_latch_data.key_hash(2);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Key Hash 4/4
                        when 6 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
                            inst_write_data <= inst_latch_data.key_hash(3);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Status Info
                        when 7 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                            inst_write_data <= inst_latch_data.status_info;
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Sample Count
                        when 8 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
                            inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET ACK Count
                        when 9 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_ACK_CNT_OFFSET;
                            inst_write_data <= std_logic_vector(inst_latch_data.ack_cnt);
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                -- DONE
                                inst_stage_next <= IDLE;
                            end if;
                        when others => 
                            null;
                    end case;
                when UPDATE_INSTANCE =>
                    case (inst_cnt) is
                        -- Status Info
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                            inst_write_data <= inst_latch_data.status_info;
                            inst_data_next.status_info  <= inst_latch_data.status_info;
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 1;
                                elsif check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 2;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        -- Sample Count
                        when 1 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
                            inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt);
                            inst_data_next.sample_cnt   <= inst_latch_data.sample_cnt;
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if check_mask(inst_latch_data.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 2;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        -- ACK Count
                        when 2 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_ACK_CNT_OFFSET;
                            inst_write_data <= std_logic_vector(inst_latch_data.ack_cnt);
                            inst_data_next.ack_cnt  <= inst_latch_data.ack_cnt;
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                -- DONE
                                inst_stage_next <= IDLE;
                            end if;
                        when others =>
                            null;
                    end case;
                when REMOVE_INSTANCE =>
                    -- Precondition: inst_addr_base set, inst_prev_addr_base set
                    
                    case (inst_cnt) is
                        -- GET Next Instance
                        when 0 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_read       <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- READ Next Instance
                        when 1 =>
                            inst_ready_out  <= '1';
                            
                            -- Memory Flow Control Guard
                            if (inst_valid_out = '1') then
                                inst_next_addr_base_next    <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                
                                -- Removed Instance is List Head
                                if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    assert (inst_addr_base = inst_occupied_head) severity FAILURE;
                                    
                                    -- Fix Occupied Head
                                    inst_occupied_head_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                    
                                    inst_cnt_next   <= inst_cnt + 2; -- Skip Next Step
                                else
                                    inst_cnt_next   <= inst_cnt + 1;
                                end if;
                            end if;
                        -- SET Next Pointer (Previous Instance)
                        when 2 =>
                            -- Point Previous instance to Next Instance (Remove current Instance from inbetween)
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_write_data <= std_logic_vector(resize(inst_next_addr_base,WORD_WIDTH));
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        -- SET Next Pointer (Current/Removed Instance)
                        when 3 =>
                            -- Point Current Instance to Empty List Head (Make Removed Instance Head of the Empty List)
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            inst_write_data <= std_logic_vector(resize(inst_empty_head,WORD_WIDTH));
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                -- Fix Empty List Head
                                inst_empty_head_next    <= inst_addr_base;
                                
                                -- Reset
                                inst_data_next      <= ZERO_INSTANCE_DATA;
                                inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
                                
                                -- DONE
                                inst_stage_next     <= IDLE;
                            end if;
                        when others =>
                            null;
                    end case;
                when RESET_MEMORY =>
                    case (inst_cnt) is
                        -- Initialize
                        when 0 =>
                            inst_addr_base_next <= FIRST_INSTANCE_ADDRESS;
                            inst_cnt_next       <= inst_cnt + 1;
                        -- SET Next Pointer
                        when 1 =>
                            inst_valid_in   <= '1';
                            inst_addr       <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                            if (inst_addr_base = MAX_INSTANCE_ADDRESS) then
                                inst_write_data <= std_logic_vector(resize(INSTANCE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                            else
                                inst_write_data <= std_logic_vector(resize(inst_addr_base + INSTANCE_FRAME_SIZE,WORD_WIDTH));
                            end if;
                            
                            -- Memory Flow Control Guard
                            if (inst_ready_in = '1') then
                                if (inst_addr_base = MAX_INSTANCE_ADDRESS) then
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                else
                                    inst_addr_base_next <= inst_addr_base + INSTANCE_FRAME_SIZE;
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                when others =>
                    null;
            end case;
        end process;
    end generate;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage                           <= RESET_SAMPLE_MEMORY;
                return_stage                    <= IDLE;
                inst_stage                      <= RESET_MEMORY;
                instance_handle                 <= HANDLE_NIL;
                cc_instance_handle_sig          <= HANDLE_NIL;
                sample_rej_last_inst            <= HANDLE_NIL;
                deadline_miss_last_inst         <= HANDLE_NIL;
                key_hash                        <= HANDLE_NIL;
                deadline_time                   <= time + DEADLINE_QOS;
                lifespan_time                   <= TIME_INFINITE;
                source_ts                       <= TIME_INVALID;
                timeout_time                    <= TIME_INVALID;
                lease_deadline                  <= time + LEASE_DURATION;
                cc_source_timestamp_sig         <= TIME_INVALID;
                lifespan                        <= DURATION_INFINITE;
                global_seq_nr                   <= FIRST_SEQUENCENUMBER;
                seq_nr                          <= SEQUENCENUMBER_UNKNOWN;
                cc_seq_nr_sig                   <= SEQUENCENUMBER_UNKNOWN;
                cc_kind_sig                     <= ALIVE;
                inst_data                       <= ZERO_INSTANCE_DATA;
                inst_latch_data                 <= ZERO_INST_LATCH_DATA;
                cnt                             <= 0;
                cnt2                            <= 0;
                cnt3                            <= 0;
                global_sample_cnt               <= 0;
                global_ack_cnt                  <= 0;
                stale_inst_cnt                  <= 0;
                inst_cnt                        <= 0;
                remove_oldest_sample            <= '0';
                remove_oldest_inst_sample       <= '0';
                remove_ack_sample               <= '0';
                is_lifespan_check               <= '0';
                register_op                     <= '0';
                lookup_op                       <= '0';
                ack_wait                        <= '0';
                is_ack                          <= '0';
                is_rtps                         <= '0';
                data_available_sig              <= '0';
                orphan_samples                  <= '0';
                newest_sample                   <= SAMPLE_MEMORY_MAX_ADDRESS;
                oldest_sample                   <= SAMPLE_MEMORY_MAX_ADDRESS;
                empty_payload_list_head         <= FIRST_PAYLOAD_ADDRESS;
                empty_sample_list_head          <= FIRST_SAMPLE_ADDRESS;
                empty_sample_list_tail          <= MAX_SAMPLE_ADDRESS;
                payload_addr_latch_1            <= (others => '0');
                payload_addr_latch_2            <= (others => '0');
                long_latch                      <= (others => '0');
                sample_addr_latch_1             <= (others => '0');
                sample_addr_latch_2             <= (others => '0');
                sample_addr_latch_3             <= (others => '0');
                sample_addr_latch_4             <= (others => '0');
                inst_addr_latch_1               <= (others => '0');
                inst_addr_latch_2               <= (others => '0');
                sample_status_info              <= (others => '0');
                sample_rej_cnt                  <= (others => '0');
                sample_rej_cnt_change           <= (others => '0');
                sample_rej_last_reason          <= (others => '0');
                deadline_miss_cnt               <= (others => '0');
                deadline_miss_cnt_change        <= (others => '0');
                liveliness_lost_cnt             <= (others => '0');
                liveliness_lost_cnt_change      <= (others => '0');
                status_sig                      <= (others => '0');
                inst_addr_base                  <= (others => '0');
                inst_empty_head                 <= FIRST_INSTANCE_ADDRESS;
                inst_occupied_head              <= INSTANCE_MEMORY_MAX_ADDRESS;
                inst_long_latch                 <= (others => '0');
                inst_next_addr_base             <= (others => '0');
                inst_prev_addr_base             <= (others => '0');
                return_code_latch               <= RETCODE_UNSUPPORTED;
            else
                stage                           <= stage_next;
                return_stage                    <= return_stage_next;
                inst_stage                      <= inst_stage_next;
                instance_handle                 <= instance_handle_next;
                cc_instance_handle_sig          <= cc_instance_handle_sig_next;
                sample_rej_last_inst            <= sample_rej_last_inst_next;
                deadline_miss_last_inst         <= deadline_miss_last_inst_next;
                key_hash                        <= key_hash_next;
                deadline_time                   <= deadline_time_next;
                lifespan_time                   <= lifespan_time_next;
                source_ts                       <= source_ts_next;
                timeout_time                    <= timeout_time_next;
                lease_deadline                  <= lease_deadline_next;
                cc_source_timestamp_sig         <= cc_source_timestamp_sig_next;
                lifespan                        <= lifespan_next;
                global_seq_nr                   <= global_seq_nr_next;
                seq_nr                          <= seq_nr_next;
                cc_seq_nr_sig                   <= cc_seq_nr_sig_next;
                cc_kind_sig                     <= cc_kind_sig_next;
                inst_data                       <= inst_data_next when WITH_KEY else inst_data_next2;
                inst_latch_data                 <= inst_latch_data_next;
                cnt                             <= cnt_next;
                cnt2                            <= cnt2_next;
                cnt3                            <= cnt3_next;
                global_sample_cnt               <= global_sample_cnt_next;
                global_ack_cnt                  <= global_ack_cnt_next;
                stale_inst_cnt                  <= stale_inst_cnt_next;
                inst_cnt                        <= inst_cnt_next;
                remove_oldest_sample            <= remove_oldest_sample_next;
                remove_oldest_inst_sample       <= remove_oldest_inst_sample_next;
                remove_ack_sample               <= remove_ack_sample_next;
                is_lifespan_check               <= is_lifespan_check_next;
                register_op                     <= register_op_next;
                lookup_op                       <= lookup_op_next;
                ack_wait                        <= ack_wait_next;
                is_ack                          <= is_ack_next;
                is_rtps                         <= is_rtps_next;
                data_available_sig              <= data_available_sig_next;
                orphan_samples                  <= orphan_samples_next;
                newest_sample                   <= newest_sample_next;
                oldest_sample                   <= oldest_sample_next;
                empty_payload_list_head         <= empty_payload_list_head_next;
                empty_sample_list_head          <= empty_sample_list_head_next;
                empty_sample_list_tail          <= empty_sample_list_tail_next;
                payload_addr_latch_1            <= payload_addr_latch_1_next;
                payload_addr_latch_2            <= payload_addr_latch_2_next;
                long_latch                      <= long_latch_next;
                sample_addr_latch_1             <= sample_addr_latch_1_next;
                sample_addr_latch_2             <= sample_addr_latch_2_next;
                sample_addr_latch_3             <= sample_addr_latch_3_next;
                sample_addr_latch_4             <= sample_addr_latch_4_next;
                inst_addr_latch_1               <= inst_addr_latch_1_next;
                inst_addr_latch_2               <= inst_addr_latch_2_next;
                sample_status_info              <= sample_status_info_next;
                sample_rej_cnt                  <= sample_rej_cnt_next;
                sample_rej_cnt_change           <= sample_rej_cnt_change_next;
                sample_rej_last_reason          <= sample_rej_last_reason_next;
                deadline_miss_cnt               <= deadline_miss_cnt_next;
                deadline_miss_cnt_change        <= deadline_miss_cnt_change_next;
                liveliness_lost_cnt             <= liveliness_lost_cnt_next;
                liveliness_lost_cnt_change      <= liveliness_lost_cnt_change_next;
                status_sig                      <= status_sig_next;
                inst_addr_base                  <= inst_addr_base_next;
                inst_empty_head                 <= inst_empty_head_next;
                inst_occupied_head              <= inst_occupied_head_next;
                inst_long_latch                 <= inst_long_latch_next;
                inst_next_addr_base             <= inst_next_addr_base_next;
                inst_prev_addr_base             <= inst_prev_addr_base_next;
                return_code_latch               <= return_code_latch_next;
            end if;
        end if;
    end process;
    
end architecture;