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

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

use work.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;

entity dds_writer is
    generic (
        NUM_WRITERS     : natural;
        CONFIG_ARRAY    : QUARTUS_CONFIG_ARRAY_TYPE
            -- HISTORY_QOS
            -- DEADLINE_QOS
            -- LIFESPAN_QOS
            -- LEASE_DURATION
            -- WITH_KEY
            -- MAX_SAMPLES
            -- MAX_INSTANCES
            -- MAX_SAMPLES_PER_INSTANCE
            -- MAX_PAYLOAD_SIZE
    );
    port (
        -- SYSTEM
        clk                     : in std_logic;
        reset                   : in std_logic;
        time                    : in TIME_TYPE;
        -- TO/FROM RTPS ENDPOINT
        start_rtps              : in std_logic_vector(0 to NUM_WRITERS-1);
        opcode_rtps             : in HISTORY_CACHE_OPCODE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        ack_rtps                : out std_logic_vector(0 to NUM_WRITERS-1);
        done_rtps               : out std_logic_vector(0 to NUM_WRITERS-1);
        ret_rtps                : out HISTORY_CACHE_RESPONSE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        seq_nr_rtps             : in SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1);
        get_data_rtps           : in std_logic_vector(0 to NUM_WRITERS-1);
        data_out_rtps           : out WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
        valid_out_rtps          : out std_logic_vector(0 to NUM_WRITERS-1);
        ready_out_rtps          : in std_logic_vector(0 to NUM_WRITERS-1);
        last_word_out_rtps      : out std_logic_vector(0 to NUM_WRITERS-1); 
        liveliness_assertion    : out std_logic_vector(0 to NUM_WRITERS-1);
        data_available          : out std_logic_vector(0 to NUM_WRITERS-1);
        -- Cache Change
        cc_instance_handle      : out INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_kind                 : out CACHE_CHANGE_KIND_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_source_timestamp     : out TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
        cc_seq_nr               : out SEQUENCENUMBER_ARRAY_TYPE(0 to NUM_WRITERS-1);
        -- TO/FROM USER ENTITY
        start_dds               : in std_logic_vector(0 to NUM_WRITERS-1);
        ack_dds                 : out std_logic_vector(0 to NUM_WRITERS-1);
        opcode_dds              : in DDS_WRITER_OPCODE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        instance_handle_in_dds  : in INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        source_ts_dds           : in TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
        max_wait_dds            : in DURATION_ARRAY_TYPE(0 to NUM_WRITERS-1);
        done_dds                : out std_logic_vector(0 to NUM_WRITERS-1);
        return_code_dds         : out RETURN_CODE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        instance_handle_out_dds : out INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_WRITERS-1);
        valid_in_dds            : in std_logic_vector(0 to NUM_WRITERS-1);
        ready_in_dds            : out std_logic_vector(0 to NUM_WRITERS-1);
        data_in_dds             : in WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
        last_word_in_dds        : in std_logic_vector(0 to NUM_WRITERS-1);
        valid_out_dds           : out std_logic_vector(0 to NUM_WRITERS-1);
        ready_out_dds           : in std_logic_vector(0 to NUM_WRITERS-1);
        data_out_dds            : out WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
        last_word_out_dds       : out std_logic_vector(0 to NUM_WRITERS-1);
        -- Communication Status
        status                  : out STATUS_KIND_ARRAY_TYPE(0 to NUM_WRITERS-1)
    );
end entity;

architecture arch of dds_writer is
    
    constant CONFIG_ARRAY_T : QUARTUS_CONFIG_ARRAY_TYPE(0 to NUM_WRITERS-1) := CONFIG_ARRAY;
    
    --*****COMPONENT DECLARATION*****
    component key_holder is
        port (
            -- SYSTEM
            clk             : in std_logic;
            reset           : in std_logic;
            -- CONTROL
            start           : in std_logic;
            opcode          : in KEY_HOLDER_OPCODE_TYPE;
            ack             : out std_logic;
            decode_error    : out std_logic;
            abort           : in std_logic;
            -- INPUT
            ready_in        : out std_logic;
            valid_in        : in std_logic;
            data_in         : in std_logic_vector(WORD_WIDTH-1 downto 0);
            last_word_in    : in std_logic;
            -- OUTPUT
            ready_out       : in std_logic;  
            valid_out       : out std_logic;
            data_out        : out std_logic_vector(WORD_WIDTH-1 downto 0);
            last_word_out   : out std_logic
        );
    end component;
    
    type NATURAL_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of natural;
        function get_max_samples(qos : QUARTUS_CONFIG_ARRAY_TYPE) return natural is
            variable ret : natural := 0;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            for i in 0 to NUM_WRITERS-1 loop
                if (unsigned(qos(i).MAX_SAMPLES) > ret) then
                    ret := to_integer(unsigned(qos(i).MAX_SAMPLES));
                end if;
            end loop;
            return ret;
        end function;
    type MAX_SAMPLES_NATURAL_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of natural range 0 to get_max_samples(CONFIG_ARRAY_T)+1;
        function get_max_instances(qos : QUARTUS_CONFIG_ARRAY_TYPE) return natural is
            variable ret : natural := 0;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            for i in 0 to NUM_WRITERS-1 loop
                if (unsigned(qos(i).MAX_INSTANCES) > ret) then
                    ret := to_integer(unsigned(qos(i).MAX_INSTANCES));
                end if;
            end loop;
            return ret;
        end function;
    type MAX_INSTANCES_NATURAL_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of natural range 0 to get_max_instances(CONFIG_ARRAY_T);
    
    
    --*****CONSTANT DECLARATION*****
    -- NOTE: Because we need to first determine the Instance before making the ACCEPT/REJECT/DROP decision
    --       we need to latch the cache change first, calculate the Key Hash if necessary, fetch the associated
    --       Instance, and then decide on it. This in effect means that we always need an extra slot in sample and
    --       payload memory that is only used as a latch.
    -- *SAMPLE MEMORY*
    -- 4-Byte Word Size of a Sample Info Entry in Memory
    constant SAMPLE_FRAME_SIZE          : natural := 11;
    -- Sample Info Memory Size in 4-Byte Words
        function gen_sample_memory_size(qos : QUARTUS_CONFIG_ARRAY_TYPE; size : natural) return NATURAL_ARRAY_TYPE is
            variable ret : NATURAL_ARRAY_TYPE;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := to_integer(unsigned(qos(i).MAX_SAMPLES)+1) * size;
            end loop;
            
            return ret;
        end function;
    constant SAMPLE_MEMORY_SIZE         : NATURAL_ARRAY_TYPE := gen_sample_memory_size(CONFIG_ARRAY_T,SAMPLE_FRAME_SIZE);
    -- Sample Info Memory Address Width
        function get_max_sample_memory_size(sizes : NATURAL_ARRAY_TYPE) return natural is
            variable ret : natural := 0;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                if (sizes(i) > ret) then
                    ret := sizes(i);
                end if;
            end loop;
            return ret;
        end function;
    constant SAMPLE_MEMORY_ADDR_WIDTH   : natural := log2c(get_max_sample_memory_size(SAMPLE_MEMORY_SIZE));
    type SAMPLE_MEMORY_ADDR_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Highest Sample Info Memory Address
    constant SAMPLE_MEMORY_MAX_ADDRESS  : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(get_max_sample_memory_size(SAMPLE_MEMORY_SIZE)-1, SAMPLE_MEMORY_ADDR_WIDTH);
    -- Highest Sample Info Frame Address
        function gen_max_sample_address(sizes : NATURAL_ARRAY_TYPE; size : natural) return SAMPLE_MEMORY_ADDR_ARRAY_TYPE is
            variable ret : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := to_unsigned(sizes(i) - size, SAMPLE_MEMORY_ADDR_WIDTH);
            end loop;
            return ret;
        end function;
    constant MAX_SAMPLE_ADDRESS         : SAMPLE_MEMORY_ADDR_ARRAY_TYPE := gen_max_sample_address(SAMPLE_MEMORY_SIZE, SAMPLE_FRAME_SIZE);
    -- 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*
        function gen_payload_frame_size(qos : QUARTUS_CONFIG_ARRAY_TYPE) return NATURAL_ARRAY_TYPE is
            variable ret : NATURAL_ARRAY_TYPE;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := round_div(qos(i).MAX_PAYLOAD_SIZE + 4, WORD_WIDTH/BYTE_WIDTH); -- (+ NEXT ADDR Field)
            end loop;
            
            return ret;
        end function;
    constant PAYLOAD_FRAME_SIZE : NATURAL_ARRAY_TYPE := gen_payload_frame_size(CONFIG_ARRAY_T);
    -- Payload Memory Size in 4-Byte Words
        function gen_payload_memory_size(qos : QUARTUS_CONFIG_ARRAY_TYPE; size : NATURAL_ARRAY_TYPE) return NATURAL_ARRAY_TYPE is
            variable ret : NATURAL_ARRAY_TYPE;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := to_integer(unsigned(qos(i).MAX_SAMPLES)+1) * size(i);
            end loop;
            
            return ret;
        end function;
    constant PAYLOAD_MEMORY_SIZE        : NATURAL_ARRAY_TYPE := gen_payload_memory_size(CONFIG_ARRAY_T, PAYLOAD_FRAME_SIZE);
    -- Payload Memory Address Width
        function get_max_payload_memory_size(sizes : NATURAL_ARRAY_TYPE) return natural is
            variable ret : natural := 0;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                if (sizes(i) > ret) then
                    ret := sizes(i);
                end if;
            end loop;
            return ret;
        end function;
    constant PAYLOAD_MEMORY_ADDR_WIDTH  : natural := log2c(get_max_payload_memory_size(PAYLOAD_MEMORY_SIZE));
    type PAYLOAD_MEMORY_ADDR_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Highest Payload Memory Address
    constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0)    := to_unsigned(get_max_payload_memory_size(PAYLOAD_MEMORY_SIZE)-1, PAYLOAD_MEMORY_ADDR_WIDTH);
    -- Highest Payload Frame Address
        function gen_max_payload_address(sizes : NATURAL_ARRAY_TYPE; size : NATURAL_ARRAY_TYPE) return PAYLOAD_MEMORY_ADDR_ARRAY_TYPE is
            variable ret : PAYLOAD_MEMORY_ADDR_ARRAY_TYPE;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := to_unsigned(sizes(i) - size(i), PAYLOAD_MEMORY_ADDR_WIDTH);
            end loop;
            return ret;
        end function;
    constant MAX_PAYLOAD_ADDRESS        : PAYLOAD_MEMORY_ADDR_ARRAY_TYPE := gen_max_payload_address(PAYLOAD_MEMORY_SIZE, PAYLOAD_FRAME_SIZE);
    -- 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 := 9;
    -- Instance Memory Size in 4-Byte Words
        function gen_instance_memory_size(qos : QUARTUS_CONFIG_ARRAY_TYPE; size : natural) return NATURAL_ARRAY_TYPE is
            variable ret : NATURAL_ARRAY_TYPE;
        begin
            assert (qos'length = NUM_WRITERS) severity FAILURE;
            
            for i in 0 to NUM_WRITERS-1 loop
                if (qos(i).WITH_KEY) then
                    ret(i) := to_integer(unsigned(qos(i).MAX_INSTANCES)) * size;
                else
                    ret(i)  := size;
                end if;
            end loop;
            
            return ret;
        end function;
    constant INSTANCE_MEMORY_SIZE       : NATURAL_ARRAY_TYPE := gen_instance_memory_size(CONFIG_ARRAY_T, INSTANCE_FRAME_SIZE);
    -- Instance Memory Address Width
        function get_max_instance_memory_size(sizes : NATURAL_ARRAY_TYPE) return natural is
            variable ret : natural := 0;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                if (sizes(i) > ret) then
                    ret := sizes(i);
                end if;
            end loop;
            return ret;
        end function;
    constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(get_max_instance_memory_size(INSTANCE_MEMORY_SIZE));
    type INSTANCE_MEMORY_ADDR_ARRAY_TYPE is array (0 to NUM_WRITERS-1) of unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Highest Instance Memory Address
    constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(get_max_instance_memory_size(INSTANCE_MEMORY_SIZE)-1, INSTANCE_MEMORY_ADDR_WIDTH);
    -- Highest Instance Frame Address
        function gen_max_instance_address(sizes : NATURAL_ARRAY_TYPE; size : natural) return INSTANCE_MEMORY_ADDR_ARRAY_TYPE is
            variable ret : INSTANCE_MEMORY_ADDR_ARRAY_TYPE;
        begin
            for i in 0 to NUM_WRITERS-1 loop
                ret(i) := to_unsigned(sizes(i) - size, INSTANCE_MEMORY_ADDR_WIDTH);
            end loop;
            return ret;
        end function;
    constant MAX_INSTANCE_ADDRESS       : INSTANCE_MEMORY_ADDR_ARRAY_TYPE := gen_max_instance_address(INSTANCE_MEMORY_SIZE, INSTANCE_FRAME_SIZE);
    -- 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 FIELD OFFSETS*
    -- 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;
    constant SMF_PAYLOAD_ADDR_OFFSET        : natural := 7;
    constant SMF_INSTANCE_ADDR_OFFSET       : natural := 8;
    constant SMF_PREV_ADDR_OFFSET           : natural := 9;
    constant SMF_NEXT_ADDR_OFFSET           : natural := 10;
    
    -- *PAYLOAD MEMORY FRAME FIELD OFFSETS*
    -- 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 FIELD OFFSETS*
    -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
    constant IMF_NEXT_ADDR_OFFSET           : natural := 0;
    constant IMF_PREV_ADDR_OFFSET           : natural := 1;
    constant IMF_KEY_HASH_OFFSET            : natural := 2;
    constant IMF_STATUS_INFO_OFFSET         : natural := 6;
    constant IMF_SAMPLE_CNT_OFFSET          : natural := 7;
    constant IMF_ACK_CNT_OFFSET             : natural := 8;
    
    -- *INSTANCE MEMORY FRAME FIELD 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, CHECK_ACK_WAIT,
        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,
        CHECK_LIFESPAN, GET_LIVELINESS_LOST_STATUS, GET_OFFERED_DEADLINE_MISSED_STATUS, CHECK_DEADLINE, CHECK_LIVELINESS, RESET_SAMPLE_MEMORY, RESET_PAYLOAD_MEMORY);
    -- Instance Memory FSM states. Explained below in detail
    type INST_STAGE_TYPE is (IDLE, SEARCH_INSTANCE, GET_NEXT_INSTANCE, GET_INSTANCE_DATA, INSERT_INSTANCE, UPDATE_INSTANCE, 
        REMOVE_INSTANCE, RESET_MEMORY);
    -- *Instance Memory Opcodes*
    -- OPCODE                   DESCRIPTION
    -- SEARCH_INSTANCE          Search Instance based on Key Hash pointed by "inst_r.key_hash".
    --                          Set "inst_data.addr" to Base Address of found Instance, or INSTANCE_MEMORY_MAX_ADDRESS if nothing found.
    --                          "inst_data" contains Instance Data according to "inst_r.field_flags".
    -- INSERT_INSTANCE          Insert Instance to memory.
    -- UPDATE_INSTANCE          Update Instance Data pointed by "inst_data.addr" according to "inst_r.field_flags"
    -- GET_INSTANCE             Get Data of Instance pointed by "inst_r.addr" according to "inst_r.field_flags".
    --                          Already fetched Data of the Participant is not modified.
    -- GET_NEXT_INSTANCE        Get Instance Data of next Instance (from the Instance pointed by "inst_data.addr") according to "inst_r.field_flags".
    --                          Set "inst_data.addr" to Address of Instance or INSTANCE_MEMORY_MAX_ADDRESS if no other Instance in Memory.
    -- REMOVE_INSTANCE          Remove Instance pointed by "inst_data.addr".
    --                          "inst_data.addr" is set to the next Instance (or INSTANCE_MEMORY_MAX_ADDRESS if no next Instance exists)
    type INSTANCE_OPCODE_TYPE is (NOP, SEARCH_INSTANCE, INSERT_INSTANCE, UPDATE_INSTANCE, GET_INSTANCE, GET_NEXT_INSTANCE, REMOVE_INSTANCE);
    -- Record of Instance Data
    type INSTANCE_DATA_TYPE is record
        i               : natural range 0 to NUM_WRITERS-1;
        addr            : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
        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);
    end record;
    -- Zero initialized Endpoint Data
    constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := (
        i               => 0,
        addr            => INSTANCE_MEMORY_MAX_ADDRESS,
        key_hash        => KEY_HASH_NIL,
        status_info     => (others => '0'),
        sample_cnt      => (others => '0'),
        ack_cnt         => (others => '0'),
        field_flags     => (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';
    signal sample_addr_i : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
    signal sample_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal sample_read_data_i, sample_write_data_i : WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal sample_ready_in_i, sample_valid_in_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal sample_ready_out_i, sample_valid_out_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal sample_abort_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    
    -- *PAYLOAD MEMORY CONNECTION SIGNALS*
    signal payload_addr : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0);
    signal payload_read : std_logic;
    signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0);
    signal payload_ready_in, payload_valid_in : std_logic;
    signal payload_ready_out, payload_valid_out : std_logic;
    signal payload_abort_read : std_logic;
    signal payload_addr_i : PAYLOAD_MEMORY_ADDR_ARRAY_TYPE;
    signal payload_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal payload_read_data_i, payload_write_data_i : WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal payload_ready_in_i, payload_valid_in_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal payload_ready_out_i, payload_valid_out_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal payload_abort_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    
    -- *INSTANCE MEMORY CONNECTION SIGNALS*
    signal inst_addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    signal inst_read : std_logic;
    signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0);
    signal inst_ready_in, inst_valid_in : std_logic;
    signal inst_ready_out, inst_valid_out : std_logic;
    signal inst_abort_read : std_logic;
    signal inst_addr_i : INSTANCE_MEMORY_ADDR_ARRAY_TYPE;
    signal inst_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal inst_read_data_i, inst_write_data_i : WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal inst_ready_in_i, inst_valid_in_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal inst_ready_out_i, inst_valid_out_i : std_logic_vector(0 to NUM_WRITERS-1);
    signal inst_abort_read_i : std_logic_vector(0 to NUM_WRITERS-1);
    
    -- *KEY HOLDER CONNECTION SIGNALS*
    signal start_kh, ack_kh, valid_in_kh, ready_in_kh, last_word_in_kh, valid_out_kh, ready_out_kh, last_word_out_kh, abort_kh : std_logic_vector(0 to NUM_WRITERS-1);
    signal opcode_kh : KEY_HOLDER_OPCODE_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal data_in_kh, data_out_kh : WORD_ARRAY_TYPE(0 to NUM_WRITERS-1);
    
    -- *MAIN PROCESS*
    -- FSM state
    signal stage, stage_next : STAGE_TYPE;
    -- FSM state latch. Used to transition dynamically to different states from the same state.
    signal return_stage, return_stage_next : STAGE_TYPE;
    -- General Purpose Counter
    signal cnt, cnt_next : natural range 0 to 14;
    -- Counter used to read/write Payload Fames
    signal cnt2, cnt2_next : natural range 0 to max(get_max_payload_memory_size(PAYLOAD_FRAME_SIZE), INSTANCE_HANDLE_TYPE'length-1);
    -- Counter used to read/write Payload Fames
    signal cnt3, cnt3_next : natural range 0 to get_max_payload_memory_size(PAYLOAD_FRAME_SIZE);
    -- Head of Empty Sample List
    signal empty_sample_list_head, empty_sample_list_head_next : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
    -- Tail of Empty Sample List
    signal empty_sample_list_tail, empty_sample_list_tail_next : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
    -- Head of Empty Payload List
    signal empty_payload_list_head, empty_payload_list_head_next : PAYLOAD_MEMORY_ADDR_ARRAY_TYPE;
    -- Oldest Sample (Head of Occupied Sample List)
    signal oldest_sample, oldest_sample_next : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
    -- Newest Sample (Tail of Occupied Sample List)
    signal newest_sample, newest_sample_next : SAMPLE_MEMORY_ADDR_ARRAY_TYPE;
    -- Denotes if the oldest Sample should be removed
    signal remove_oldest_sample, remove_oldest_sample_next : std_logic;
    -- 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;
    -- Denotes if the Sample tobe removed should be ACKed
    signal remove_ack_sample, remove_ack_sample_next : std_logic;
    -- Lifespan Latch
    signal lifespan, lifespan_next : TIME_TYPE;
    -- Key hash Latch
    signal key_hash, key_hash_next : KEY_HASH_TYPE;
    -- Return Code Latch
    signal return_code_latch, return_code_latch_next : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
    -- Instance Handle Latch
    signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE;
    -- Source Timestamp Latch
    signal source_ts, source_ts_next : TIME_TYPE;
    -- Sequence Number Latch
    signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE;
    -- Sample Status Info Latch
    signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    -- General Purpose Payload Pointer
    signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Payload Pointer
    signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Sample Pointer
    signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Sample Pointer
    signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Sample Pointer
    signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Sample Pointer
    signal sample_addr_latch_4, sample_addr_latch_4_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Instance Pointer
    signal inst_addr_latch_1, inst_addr_latch_1_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Instance Pointer
    signal inst_addr_latch_2, inst_addr_latch_2_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Long Latch
    signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
    -- Signals start of Instance Memory Operation
    signal inst_op_start : std_logic;
    -- Opcode of Instance Memory Operation (Valid only when inst_op_start is high)
    signal inst_opcode  : INSTANCE_OPCODE_TYPE;
    -- Signals the end of an Instance Memory Operation
    signal inst_op_done : std_logic;
    -- Signal used to pass data to instance memory process
    signal inst_r : INSTANCE_DATA_TYPE;
    -- Time of next Sample Lifespan Check
    signal lifespan_time, lifespan_time_next : TIME_TYPE;
    -- Signifies if a Lifespan Check is in progress
    signal is_lifespan_check, is_lifespan_check_next : std_logic;
    -- 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_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- Signal containing the current number of stored samples
    signal global_sample_cnt, global_sample_cnt_next : MAX_SAMPLES_NATURAL_ARRAY_TYPE;
    -- Signal containing the current number of ACKed stored samples
    signal global_ack_cnt, global_ack_cnt_next : MAX_SAMPLES_NATURAL_ARRAY_TYPE;
    -- Signal containing the number of currently stale Instances
    signal stale_inst_cnt, stale_inst_cnt_next : MAX_INSTANCES_NATURAL_ARRAY_TYPE;
    -- Signifies if a Instance Register Operation is in progress
    signal register_op, register_op_next : std_logic;
    -- Signifies if a Instance Lookup Operation is in progress
    signal lookup_op, lookup_op_next : std_logic;
    -- Signifies if a WAIT_FOR_ACKNOWLEDGEMENT Operation is in progress
    signal ack_wait, ack_wait_next : std_logic_vector(0 to NUM_WRITERS-1);
    -- Triggers an ACK Wait Check
    signal ack_wait_check, ack_wait_check_next : std_logic;
    -- Time of next Timeout Check Trigger
    signal timeout_check_time, timeout_check_time_next : TIME_TYPE;
    -- Timeout time for DDS Operation
    signal timeout_time, timeout_time_next : TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- Signal used to differentiate between ACK and NACK Operations
    signal is_ack, is_ack_next : std_logic;
    -- Signal used to differentiate between RTPS and DDS Operations
    signal is_rtps, is_rtps_next : std_logic;
    -- Signifies if new Samples are available for RTPS Writer
    signal data_available_sig, data_available_sig_next : std_logic_vector(0 to NUM_WRITERS-1);
    -- Denotes if Orphan Samples (of an removed stale instance) need to be removed
    signal orphan_samples, orphan_samples_next : std_logic;
    -- Signal used to index the writers
    signal ind, ind_next : natural range 0 to NUM_WRITERS-1;
    -- Test signals used in testbenches
    signal idle_sig : std_logic;
    signal empty_inst_head_sig : NATURAL_ARRAY_TYPE;
    signal empty_sample_head_sig : NATURAL_ARRAY_TYPE;
    signal empty_payload_head_sig : NATURAL_ARRAY_TYPE;
    
    
    -- *COMMUNICATION STATUS*
    signal status_sig, status_sig_next : STATUS_KIND_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- LIVELINESS LOST STATUS
    -- Time of next Liveliness Deadline
    signal lease_check_time, lease_check_time_next : TIME_TYPE;
    signal lease_deadline, lease_deadline_next : TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal liveliness_lost_cnt, liveliness_lost_cnt_next : LIVELINESS_LOST_STATUS_COUNT_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal liveliness_lost_cnt_change, liveliness_lost_cnt_change_next : LIVELINESS_LOST_STATUS_COUNT_ARRAY_TYPE(0 to NUM_WRITERS-1);
    -- SAMPLE REJECT STATUS
    signal sample_rej_cnt, sample_rej_cnt_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0);
    signal sample_rej_cnt_change, sample_rej_cnt_change_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0);
    signal sample_rej_last_reason, sample_rej_last_reason_next : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
    signal sample_rej_last_inst, sample_rej_last_inst_next : INSTANCE_HANDLE_TYPE;
    -- OFFERED DEADLINE MISSED STATUS
    -- Time of next Deadline Miss Check
    signal deadline_check_time , deadline_check_time_next : TIME_TYPE;
    signal deadline_time, deadline_time_next : TIME_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal deadline_miss_cnt, deadline_miss_cnt_next : OFFERED_DEADLINE_MISSED_STATUS_COUNT_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal deadline_miss_cnt_change, deadline_miss_cnt_change_next : OFFERED_DEADLINE_MISSED_STATUS_COUNT_ARRAY_TYPE(0 to NUM_WRITERS-1);
    signal deadline_miss_last_inst, deadline_miss_last_inst_next : INSTANCE_HANDLE_ARRAY_TYPE(0 to NUM_WRITERS-1);
    
    -- *CACHE CHANGE*
    signal cc_instance_handle_sig, cc_instance_handle_sig_next : INSTANCE_HANDLE_TYPE;
    signal cc_kind_sig, cc_kind_sig_next : CACHE_CHANGE_KIND_TYPE;
    signal cc_source_timestamp_sig, cc_source_timestamp_sig_next : TIME_TYPE;
    signal cc_seq_nr_sig, cc_seq_nr_sig_next : SEQUENCENUMBER_TYPE;
    
    -- *INSTANCE MEMORY PROCESS*
    -- Instance Memory FSM state
    signal inst_stage, inst_stage_next  : INST_STAGE_TYPE;
    -- Pointer to current relevant Instance Memory Frame Address
    signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- General Purpose Instance Memory Address Latch
    signal inst_addr_latch, inst_addr_latch_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    -- Head of Empty Instance List
    signal inst_empty_head, inst_empty_head_next : INSTANCE_MEMORY_ADDR_ARRAY_TYPE;
    -- Head of Occupied Instance List
    signal inst_occupied_head, inst_occupied_head_next : INSTANCE_MEMORY_ADDR_ARRAY_TYPE;
    -- Latch for Instance Data from main process
    signal inst_latch_data, inst_latch_data_next : INSTANCE_DATA_TYPE;
    -- Latch for Instance Data from memory
    signal inst_data, inst_data_next : INSTANCE_DATA_TYPE;
    -- General Purpose Counter
    signal inst_cnt, inst_cnt_next : natural range 0 to 13;
    -- General Purpose Long Latch
    signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 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;
    
    -- HACK: Due to delta cycle race condition some assertions trigger false positives,
    --       so we check the signals on the falling edge
    function stable(clk : std_logic; a : boolean) return boolean is
    begin
        if (clk = '0') then
            return a;
        else
            return TRUE;
        end if;
    end function;
    
begin
    
    --*****COMPONENT INSTANTIATION*****
    
    key_holder_gen : for i in 0 to NUM_WRITERS-1 generate
        key_holder_inst : key_holder
            port map (
                -- SYSTEM
                clk             => clk,
                reset           => reset,
                -- CONTROL
                start           => start_kh(i),
                opcode          => opcode_kh(i),
                ack             => ack_kh(i),
                decode_error    => open,
                abort           => abort_kh(i),
                -- INPUT
                ready_in        => ready_out_kh(i),
                valid_in        => valid_out_kh(i),
                data_in         => data_out_kh(i),
                last_word_in    => last_word_out_kh(i),
                -- OUTPUT
                ready_out       => ready_in_kh(i),
                valid_out       => valid_in_kh(i),
                data_out        => data_in_kh(i),
                last_word_out   => last_word_in_kh(i)
            );
    end generate;
    
    sample_mem_ctrl_gen : for i in 0 to NUM_WRITERS-1 generate
        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(i),
                MAX_BURST_LENGTH    => SAMPLE_FRAME_SIZE
            )
            port map (
                clk         => clk,
                reset       => reset or sample_abort_read_i(i),
                addr        => std_logic_vector(sample_addr_i(i)),
                read        => sample_read_i(i),
                ready_in    => sample_ready_in_i(i),
                valid_in    => sample_valid_in_i(i),
                data_in     => sample_write_data_i(i),
                ready_out   => sample_ready_out_i(i),
                valid_out   => sample_valid_out_i(i),
                data_out    => sample_read_data_i(i)
            );
    end generate;
    
    payload_mem_ctrl_gen : for i in 0 to NUM_WRITERS-1 generate
        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(i),
                MAX_BURST_LENGTH    => PAYLOAD_FRAME_SIZE(i)
            )
            port map (
                clk         => clk,
                reset       => reset or payload_abort_read_i(i),
                addr        => std_logic_vector(payload_addr_i(i)),
                read        => payload_read_i(i),
                ready_in    => payload_ready_in_i(i),
                valid_in    => payload_valid_in_i(i),
                data_in     => payload_write_data_i(i),
                ready_out   => payload_ready_out_i(i),
                valid_out   => payload_valid_out_i(i),
                data_out    => payload_read_data_i(i)
            );
    end generate;
    
    instance_mem_ctrl_gen : for i in 0 to NUM_WRITERS-1 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(i),
                MAX_BURST_LENGTH    => INSTANCE_FRAME_SIZE
            )
            port map (
                clk         => clk,
                reset       => reset or inst_abort_read_i(i),
                addr        => std_logic_vector(inst_addr_i(i)),
                read        => inst_read_i(i),
                ready_in    => inst_ready_in_i(i),
                valid_in    => inst_valid_in_i(i),
                data_in     => inst_write_data_i(i),
                ready_out   => inst_ready_out_i(i),
                valid_out   => inst_valid_out_i(i),
                data_out    => inst_read_data_i(i)
            );
    end generate;
    
    inst_memory_mux : process (all)
    begin
        inst_abort_read_i   <= (others => '0');
        inst_addr_i         <= (others => (others => '0'));
        inst_read_i         <= (others => '0');
        inst_valid_in_i     <= (others => '0');
        inst_write_data_i   <= (others => (others => '0'));
        inst_ready_out_i    <= (others => '0');
        
        inst_abort_read_i(inst_latch_data.i)    <= inst_abort_read;
        inst_addr_i(inst_latch_data.i)          <= inst_addr;
        inst_read_i(inst_latch_data.i)          <= inst_read;
        inst_valid_in_i(inst_latch_data.i)      <= inst_valid_in;
        inst_write_data_i(inst_latch_data.i)    <= inst_write_data;
        inst_ready_out_i(inst_latch_data.i)     <= inst_ready_out;
        
        inst_ready_in   <= inst_ready_in_i(inst_latch_data.i);
        inst_valid_out  <= inst_valid_out_i(inst_latch_data.i);
        inst_read_data  <= inst_read_data_i(inst_latch_data.i);
    end process;
    
    sample_memory_mux : process (all)
    begin
        sample_abort_read_i <= (others => '0');
        sample_addr_i       <= (others => (others => '0'));
        sample_read_i       <= (others => '0');
        sample_valid_in_i   <= (others => '0');
        sample_write_data_i <= (others => (others => '0'));
        sample_ready_out_i  <= (others => '0');
        
        sample_abort_read_i(ind)  <= sample_abort_read;
        sample_addr_i(ind)        <= sample_addr;
        sample_read_i(ind)        <= sample_read;
        sample_valid_in_i(ind)    <= sample_valid_in;
        sample_write_data_i(ind)  <= sample_write_data;
        sample_ready_out_i(ind)   <= sample_ready_out;
        
        sample_ready_in     <= sample_ready_in_i(ind);
        sample_valid_out    <= sample_valid_out_i(ind);
        sample_read_data    <= sample_read_data_i(ind);
    end process;
    
    payload_memory_mux : process (all)
    begin
        payload_abort_read_i    <= (others => '0');
        payload_addr_i          <= (others => (others => '0'));
        payload_read_i          <= (others => '0');
        payload_valid_in_i      <= (others => '0');
        payload_write_data_i    <= (others => (others => '0'));
        payload_ready_out_i     <= (others => '0');
        
        payload_abort_read_i(ind)   <= payload_abort_read;
        payload_addr_i(ind)         <= payload_addr;
        payload_read_i(ind)         <= payload_read;
        payload_valid_in_i(ind)     <= payload_valid_in;
        payload_write_data_i(ind)   <= payload_write_data;
        payload_ready_out_i(ind)    <= payload_ready_out;
        
        payload_ready_in    <= payload_ready_in_i(ind);
        payload_valid_out   <= payload_valid_out_i(ind);
        payload_read_data   <= payload_read_data_i(ind);
    end process;
    
    status              <= status_sig;
    data_available      <= data_available_sig;
    cc_instance_handle  <= (others => cc_instance_handle_sig);
    cc_kind             <= (others => cc_kind_sig);
    cc_source_timestamp <= (others => cc_source_timestamp_sig);
    cc_seq_nr           <= (others => 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
    -- 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
    -- CHECK_LIVELINESS                     Check liveliness status of all Writers
    -- CHECK_ACK_WAIT                       Check WAIT_FOR_ACKNOWLEDGEMENT operation exit conditions
    -- 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;
        variable tmp_bool   : boolean;
    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_check_time_next                <= deadline_check_time;
        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;
        ack_wait_check_next                     <= ack_wait_check;
        timeout_check_time_next                 <= timeout_check_time;
        timeout_time_next                       <= timeout_time;
        lease_check_time_next                   <= lease_check_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;
        return_code_latch_next                  <= return_code_latch;
        ind_next                                <= ind;
        -- DEFAULT Unregistered
        inst_opcode                             <= NOP;
        ret_rtps                                <= (others => ERROR);
        return_code_dds                         <= (others => RETCODE_UNSUPPORTED);
        opcode_kh                               <= (others => NOP);
        instance_handle_out_dds                 <= (others => HANDLE_NIL);
        ack_dds                                 <= (others => '0');
        done_dds                                <= (others => '0');
        ack_rtps                                <= (others => '0');
        done_rtps                               <= (others => '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                            <= (others => '0');
        liveliness_assertion                    <= (others => '0');
        valid_out_rtps                          <= (others => '0');
        last_word_out_rtps                      <= (others => '0');
        valid_out_dds                           <= (others => '0');
        last_word_out_dds                       <= (others => '0');
        start_kh                                <= (others => '0');
        ready_in_kh                             <= (others => '0');
        valid_out_kh                            <= (others => '0');
        last_word_out_kh                        <= (others => '0');
        abort_kh                                <= (others => '0');
        idle_sig                                <= '0';
        data_out_kh                             <= (others => (others => '0'));
        sample_addr                             <= (others => '0');
        sample_write_data                       <= (others => '0');
        payload_addr                            <= (others => '0');
        payload_write_data                      <= (others => '0');
        data_out_rtps                           <= (others => (others => '0'));
        data_out_dds                            <= (others => (others => '0'));
        inst_r                                  <= ZERO_INSTANCE_DATA;
        
        
        
        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(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                    cur_sample_next <= oldest_sample(ind);
                    stage_next      <= REMOVE_ORPHAN_SAMPLES;
                    cnt_next        <= 0;
                -- DEADLINE QoS
                elsif (deadline_check_time <= time) then
                    -- Reset
                    deadline_check_time_next    <= TIME_INFINITE;
                    
                    ind_next            <= 0;
                    stage_next          <= CHECK_DEADLINE;
                    cnt_next            <= 1; -- CHECK DEADLINE
                -- Liveliness Deadline
                elsif (lease_check_time <= time) then
                    -- Reset
                    lease_check_time_next   <= TIME_INFINITE;
                    
                    ind_next            <= 0;
                    stage_next          <= CHECK_LIVELINESS;
                    cnt_next            <= 1; -- CHECK LEASE
                -- WAIT_FOR_ACKNOWLEDGEMENT Trigger
                elsif (ack_wait /= (ack_wait'range => '0') and (ack_wait_check = '1' or timeout_check_time <= time)) then
                    ind_next    <= 0;
                    
                    -- RESET
                    timeout_check_time_next <= TIME_INFINITE;
                    
                    stage_next  <= CHECK_ACK_WAIT;
                    cnt_next    <= 1; -- CHECK ACK STATE
                -- LIFESPAN QoS
                elsif (lifespan_time <= time) then
                    -- Reset Timeout
                    lifespan_time_next  <= TIME_INFINITE;
                    is_lifespan_check_next  <= '1';
                    ind_next    <= 0;
                    
                    stage_next  <= CHECK_LIFESPAN;
                    cnt_next    <= 1; -- CHECK LIFESPAN
                -- RTPS Operation
                elsif (start_rtps /= (start_rtps'range => '0')) then
                    if (start_rtps(ind) /= '1') then
                        if (ind = NUM_WRITERS-1) then
                            ind_next    <= 0;
                        else
                            ind_next    <= ind + 1;
                        end if;
                    else
                        is_rtps_next    <= '1';
                        -- Latch Input Signal
                        seq_nr_next <= seq_nr_rtps(ind);
                        -- Reset
                        is_ack_next <= '0';
                        
                        case (opcode_rtps(ind)) is
                            when GET_MIN_SN =>
                                ack_rtps(ind)   <= '1';
                                if (oldest_sample(ind) = 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; -- Return Code
                                    cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                                else
                                    cur_sample_next     <= oldest_sample(ind);
                                    stage_next          <= GET_SEQ_NR;
                                    cnt_next            <= 0;
                                end if;
                            when GET_MAX_SN =>
                                ack_rtps(ind)   <= '1';
                                
                                -- Reset Data Availability
                                data_available_sig_next(ind)    <= '0';
                                
                                if (newest_sample(ind) = 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; -- Return Code
                                    cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                                else
                                    cur_sample_next     <= newest_sample(ind);
                                    stage_next          <= GET_SEQ_NR;
                                    cnt_next            <= 0;
                                end if;
                            when GET_CACHE_CHANGE =>
                                ack_rtps(ind)   <= '1';
                                
                                -- No Samples Available
                                if (newest_sample(ind) = 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(ind);
                                    cur_sample_next     <= newest_sample(ind);
                                    stage_next          <= FIND_SEQ_NR;
                                    cnt_next            <= 0;
                                    return_stage_next   <= GET_SAMPLE;
                                end if;
                            when ACK_CACHE_CHANGE =>
                                ack_rtps(ind)   <= '1';
                                is_ack_next <= '1';
                                
                                -- No Samples Available
                                if (newest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    stage_next          <= UNKNOWN_SEQ_NR;
                                    cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                                else
                                    cur_sample_next     <= newest_sample(ind);
                                    stage_next          <= FIND_SEQ_NR;
                                    cnt_next            <= 0;
                                    return_stage_next   <= ACKNACK_SAMPLE;
                                end if;
                            when NACK_CACHE_CHANGE =>
                                ack_rtps(ind)   <= '1';
                                
                                -- No Samples Available
                                if (newest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    stage_next          <= UNKNOWN_SEQ_NR;
                                    cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                                else
                                    cur_sample_next     <= newest_sample(ind);
                                    stage_next          <= FIND_SEQ_NR;
                                    cnt_next            <= 0;
                                    return_stage_next   <= ACKNACK_SAMPLE;
                                end if;
                            when REMOVE_CACHE_CHANGE =>
                                ack_rtps(ind)   <= '1';
                                
                                -- No Samples Available
                                if (newest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    stage_next          <= UNKNOWN_SEQ_NR;
                                    cc_seq_nr_sig_next  <= SEQUENCENUMBER_UNKNOWN;
                                else
                                    cur_sample_next     <= newest_sample(ind);
                                    stage_next          <= FIND_SEQ_NR;
                                    cnt_next            <= 0;
                                    return_stage_next   <= REMOVE_SAMPLE;
                                end if;
                            when others =>
                                ack_rtps(ind)   <= '1';
                                
                                stage_next  <= UNKNOWN_OPERATION_RTPS;
                        end case;
                    end if;
                -- DDS Operation (Stall DDS Operation if a wait Operation is in progress)
                elsif (((not ack_wait) and start_dds) /= (start_dds'range => '0')) then
                    if not (ack_wait(ind) = '0' and start_dds(ind) = '1') then
                        if (ind = NUM_WRITERS-1) then
                            ind_next    <= 0;
                        else
                            ind_next    <= ind + 1;
                        end if;
                    else
                        -- Reset
                        register_op_next        <= '0';
                        instance_handle_next    <= HANDLE_NIL;
                        source_ts_next          <= TIME_INVALID;
                        sample_status_info_next <= (others => '0');
                        key_hash_next           <= KEY_HASH_NIL;
                        new_sample_next         <= SAMPLE_MEMORY_MAX_ADDRESS;
                        return_code_latch_next  <= RETCODE_UNSUPPORTED;
                        
                        case (opcode_dds(ind)) is
                            when REGISTER_INSTANCE =>
                                -- Synthesis Guard
                                if (CONFIG_ARRAY_T(ind).WITH_KEY) then
                                    start_kh(ind)   <= '1';
                                    opcode_kh(ind)  <= PUSH_DATA;
                                    
                                    if (ack_kh(ind) = '1') then
                                        ack_dds(ind)        <= '1';
                                        register_op_next    <= '1';
                                        stage_next          <= ADD_PAYLOAD;
                                        cnt_next            <= 1;
                                    end if;
                                else
                                    ack_dds(ind)        <= '1';
                                    key_hash_next       <= KEY_HASH_NIL;
                                    stage_next          <= SKIP;
                                    return_stage_next   <= PUSH_KEY_HASH;
                                end if;
                            when WRITE =>
                                ack_dds(ind)    <= '1';
                                
                                -- Reset Liveliness
                                lease_deadline_next(ind)    <= time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                
                                -- Latch Input Signals
                                key_hash_next           <= instance_handle_in_dds(ind);
                                instance_handle_next    <= instance_handle_in_dds(ind);
                                source_ts_next          <= source_ts_dds(ind);
                                
                                -- NOTE: The ALIGNED_FLAG is set by default. If actual Payload is not aligned, need to reset.
                                sample_status_info_next <= (SSI_DATA_FLAG => '1', SSI_ALIGNED_FLAG => '1', others => '0');
                                cur_sample_next         <= empty_sample_list_head(ind);
                                
                                -- 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(ind) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    if (global_ack_cnt(ind) = 0 and CONFIG_ARRAY_T(ind).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(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                        
                                        -- Do not ACK Operation
                                        ack_dds(ind)    <= '0';
                                        
                                        
                                        if (global_ack_cnt(ind) /= 0) then
                                            -- Remove Oldest ACKed Sample
                                            remove_oldest_sample_next   <= '1';
                                            remove_ack_sample_next      <= '1';
                                            
                                            cur_sample_next <= oldest_sample(ind);
                                            stage_next      <= FIND_SAMPLE;
                                            cnt_next        <= 0;
                                        else
                                            stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                            cnt_next    <= 0;
                                        end if;
                                    end if;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            when DISPOSE =>
                                ack_dds(ind)    <= '1';
                                
                                -- Reset Liveliness
                                lease_deadline_next(ind)    <= time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                
                                -- Latch Input Signals
                                key_hash_next           <= instance_handle_in_dds(ind);
                                instance_handle_next    <= instance_handle_in_dds(ind);
                                source_ts_next          <= source_ts_dds(ind);
                                
                                -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
                                sample_status_info_next <= (SSI_DATA_FLAG => '1', SSI_ALIGNED_FLAG => '1', SSI_DISPOSED_FLAG => '1', others => '0');
                                cur_sample_next <= empty_sample_list_head(ind);
                                
                                -- 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(ind) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    if (global_ack_cnt(ind) = 0 and CONFIG_ARRAY_T(ind).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(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                        -- Do not ACK Operation
                                        ack_dds(ind)    <= '0';
                                        
                                        if (global_ack_cnt(ind) /= 0) then
                                            -- Remove Oldest ACKed Sample
                                            remove_oldest_sample_next   <= '1';
                                            remove_ack_sample_next      <= '1';
                                            
                                            cur_sample_next <= oldest_sample(ind);
                                            stage_next      <= FIND_SAMPLE;
                                            cnt_next        <= 0;
                                        else
                                            stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                            cnt_next    <= 0;
                                        end if;
                                    end if;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            when UNREGISTER_INSTANCE =>
                                ack_dds(ind)    <= '1';
                                
                                -- Reset Liveliness
                                lease_deadline_next(ind)    <= time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                
                                -- Latch Input Signals
                                key_hash_next           <= instance_handle_in_dds(ind);
                                instance_handle_next    <= instance_handle_in_dds(ind);
                                source_ts_next          <= source_ts_dds(ind);
                                
                                -- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
                                sample_status_info_next <= (SSI_DATA_FLAG => '1', SSI_ALIGNED_FLAG => '1', SSI_UNREGISTERED_FLAG => '1', others => '0');
                                cur_sample_next <= empty_sample_list_head(ind);
                                
                                -- NOTE: We always expect a Serialized Key as Input of this Operation, so we also check the Payload memory
                                -- Payload Memory Full
                                if (empty_payload_list_head(ind) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    if (global_ack_cnt(ind) = 0 and CONFIG_ARRAY_T(ind).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(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                        -- Do not ACK Operation
                                        ack_dds(ind)    <= '0';
                                        
                                        if (global_ack_cnt(ind) /= 0) then
                                            -- Remove Oldest ACKed Sample
                                            remove_oldest_sample_next   <= '1';
                                            remove_ack_sample_next      <= '1';
                                            
                                            cur_sample_next <= oldest_sample(ind);
                                            stage_next      <= FIND_SAMPLE;
                                            cnt_next        <= 0;
                                        else
                                            stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                            cnt_next    <= 0;
                                        end if;
                                    end if;
                                else
                                    stage_next  <= ADD_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                end if;
                            when LOOKUP_INSTANCE =>
                                -- Synthesis Guard
                                if (CONFIG_ARRAY_T(ind).WITH_KEY) then
                                    start_kh(ind)   <= '1';
                                    opcode_kh(ind)  <= PUSH_DATA;
                                    
                                    if (ack_kh(ind) = '1') then
                                        ack_dds(ind)    <= '1';
                                        lookup_op_next  <= '1';
                                        stage_next      <= ADD_PAYLOAD;
                                        cnt_next        <= 1;
                                    end if;
                                else
                                    ack_dds(ind)        <= '1';
                                    key_hash_next       <= KEY_HASH_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 ACK the Samples, so we do not handle this case differently here.
                                ack_dds(ind)            <= '1';
                                ack_wait_next(ind)      <= '1';
                                tmp_dw  := time + max_wait_dds(ind);
                                timeout_time_next(ind)  <= tmp_dw;
                                
                                if (tmp_dw < timeout_check_time) then
                                    timeout_check_time_next <= tmp_dw;
                                end if;
                            when GET_OFFERED_DEADLINE_MISSED_STATUS =>
                                ack_dds(ind)    <= '1';
                                stage_next      <= GET_OFFERED_DEADLINE_MISSED_STATUS;
                                cnt_next        <= 0;
                            when ASSERT_LIVELINESS =>
                                -- Reset Liveliness
                                lease_deadline_next(ind)    <= time + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                
                                ack_dds(ind)    <= '1';
                                stage_next      <= ASSERT_LIVELINESS;
                            when GET_LIVELINESS_LOST_STATUS =>
                                ack_dds(ind)    <= '1';
                                stage_next      <= GET_LIVELINESS_LOST_STATUS;
                                cnt_next        <= 0;
                            when others =>
                                ack_dds(ind)    <= '1';
                                stage_next      <= UNKNOWN_OPERATION_DDS;
                        end case;
                    end if;
                end if;
            when UNKNOWN_OPERATION_DDS =>
                done_dds(ind)           <= '1';
                return_code_dds(ind)    <= RETCODE_ILLEGAL_OPERATION;
                
                -- DONE
                stage_next  <= IDLE;
            when UNKNOWN_OPERATION_RTPS =>
                done_rtps(ind)  <= '1';
                ret_rtps(ind)   <= ERROR;
                
                -- DONE
                stage_next  <= IDLE;
            when UNKNOWN_SEQ_NR =>
                done_rtps(ind)  <= '1';
                ret_rtps(ind)   <= INVALID;
                
                -- DONE
                stage_next  <= IDLE;
            
            when ASSERT_LIVELINESS =>
                -- Propagate Liveliness Assertion
                liveliness_assertion(ind)   <= '1';
                
                done_dds(ind)           <= '1';
                return_code_dds(ind)    <= 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(ind)(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(ind)(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;
                        if (source_ts /= TIME_INVALID) then
                            sample_write_data   <= std_logic_vector(source_ts(0));
                        else
                            sample_write_data   <= std_logic_vector(time(0));
                        end if;
                        -- 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;
                        if (source_ts /= TIME_INVALID) then
                            sample_write_data   <= std_logic_vector(source_ts(1));
                        else
                            sample_write_data   <= std_logic_vector(time(1));
                        end if;
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            if (CONFIG_ARRAY_T(ind).LIFESPAN_QOS /= DURATION_INFINITE) then
                                lifespan_next   <= time + CONFIG_ARRAY_T(ind).LIFESPAN_QOS;
                            else
                                lifespan_next   <= TIME_INVALID;
                            end if;
                            cnt_next        <= cnt + 1;
                        end if;
                    -- Lifespan Deadline 1/2
                    when 5 =>
                        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;
                    -- Lifespan Deadline 2/2
                    when 6 =>
                        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;
                    -- Payload Address
                    when 7 =>
                        assert (empty_payload_list_head(ind) /= 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(ind), WORD_WIDTH));
                        cur_payload_next    <= empty_payload_list_head(ind);
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Key Hash needs to be calculated
                            if (CONFIG_ARRAY_T(ind).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 =>
                        assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                        
                        start_kh(ind)   <= '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(ind)  <= PUSH_SERIALIZED_KEY;
                        else
                            opcode_kh(ind)  <= PUSH_DATA;
                        end if;
                        
                        if (ack_kh(ind) = '1') then
                            stage_next  <= ADD_PAYLOAD;
                            cnt_next    <= 0;
                            cnt2_next   <= 1;
                        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(ind) = '1') then
                            payload_valid_in    <= '1';
                            payload_addr        <= cur_payload + cnt2;
                            payload_write_data  <= data_in_dds(ind);
                            -- Memory Control Flow Guard
                            if (payload_ready_in = '1') then
                                -- Key Hash needs to be calculated
                                if (CONFIG_ARRAY_T(ind).WITH_KEY and instance_handle = HANDLE_NIL) then
                                    cnt_next    <= cnt + 1;
                                else
                                    ready_in_dds(ind)   <= '1';
                                    -- End of Payload
                                    if (last_word_in_dds(ind) = '1') then
                                        -- End of Payload Slot
                                        if (cnt2 = PAYLOAD_FRAME_SIZE(ind)-1) then
                                            stage_next  <= INITIATE_INSTANCE_SEARCH;
                                        else
                                            stage_next  <= ALIGN_PAYLOAD;
                                            cnt_next    <= 0;
                                        end if;
                                    else
                                        -- End of Payload Slot
                                        if (cnt2 = PAYLOAD_FRAME_SIZE(ind)-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 =>
                        assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                        
                        -- Input Guard
                        if (valid_in_dds(ind) = '1') then
                        
                            valid_out_kh(ind)   <= '1';
                            data_out_kh(ind)    <= data_in_dds(ind);
                            
                            -- Output Guard
                            if (ready_out_kh(ind) = '1') then
                                ready_in_dds(ind)   <= '1';
                                -- Operation does not have Payload to store
                                if (sample_status_info(SSI_DATA_FLAG) = '0') then
                                    -- End of Payload
                                    if (last_word_in_dds(ind) = '1') then
                                        last_word_out_kh(ind)   <= '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(ind) = '1') then
                                        last_word_out_kh(ind)   <= '1';
                                        -- End of Payload Slot
                                        if (cnt2 = PAYLOAD_FRAME_SIZE(ind)-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(ind)-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;
                    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(ind)   <= '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(ind)-1;
                        payload_write_data  <= std_logic_vector(to_unsigned(cnt2, WORD_WIDTH));
                        
                        -- Memory Control Flow Guard
                        if (payload_ready_in = '1') then
                            if (CONFIG_ARRAY_T(ind).WITH_KEY and instance_handle = HANDLE_NIL) then
                                stage_next  <= GET_KEY_HASH;
                                cnt_next    <= 0;
                                cnt2_next   <= 0;
                            else
                                stage_next  <= INITIATE_INSTANCE_SEARCH;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_KEY_HASH =>
                assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                
                case (cnt) is
                    -- Initiate READ Operation
                    when 0 =>   
                        start_kh(ind)   <= '1';
                        opcode_kh(ind)  <= READ_KEY_HASH;
                        
                        if (ack_kh(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- READ Key Hash
                    when 1 =>
                        ready_in_kh(ind)    <= '1';
                
                        if (valid_in_kh(ind) = '1') then
                            cnt2_next   <= cnt2 + 1;
                            
                            -- Latch Key Hash
                            key_hash_next(cnt2)  <= data_in_kh(ind);
                            
                            -- Exit Condition
                            if (last_word_in_kh(ind) = '1') then
                                -- DONE
                                stage_next    <= INITIATE_INSTANCE_SEARCH;
                            end if;
                        end if;
                    when others => 
                        null;
                end case;
            when INITIATE_INSTANCE_SEARCH =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    inst_op_start       <= '1';
                    inst_opcode         <= SEARCH_INSTANCE;
                    inst_r.i            <= ind;
                    inst_r.key_hash     <= key_hash;
                    inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                    
                    -- Register Operation in Progress
                    if (register_op = '1') then
                        stage_next  <= REGISTER_OPERATION;
                    -- Lookup Operation in Progress
                    elsif (lookup_op = '1') then
                        stage_next  <= LOOKUP_OPERATION;
                    else
                        stage_next  <= FILTER_STAGE;
                    end if;
                end if;
            when REGISTER_OPERATION =>
                assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                
                -- Wait for Instance Search to finish
                if (inst_op_done = '1') then
                    -- Instance already in Memory
                    if (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) then
                        assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG)) severity FAILURE;
                        
                        -- Accept Registration
                        stage_next      <= PUSH_KEY_HASH;
                        
                        -- 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_r.i            <= ind;
                            inst_r.addr         <= inst_data.addr;
                            inst_r.field_flags  <= IMF_STATUS_FLAG;
                            inst_r.status_info  <= inst_data.status_info;
                            inst_r.status_info(ISI_UNREGISTERED_FLAG)   <= '0';
                            
                            -- Update Stale Instance Count
                            if (inst_data.sample_cnt = inst_data.ack_cnt) then
                                stale_inst_cnt_next(ind)    <= stale_inst_cnt(ind) - 1;
                            end if;
                        end if;
                    else
                        -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
                        if (inst_empty_head(ind) = INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- Stale Instances are available
                            if (stale_inst_cnt(ind) /= 0) then
                                
                                -- Remove Stale and insert new Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_INSTANCE;
                                inst_r.i            <= ind;
                                inst_r.addr         <= inst_occupied_head(ind);
                                inst_r.field_flags  <= 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   <= KEY_HASH_NIL;
                                stage_next      <= PUSH_KEY_HASH;
                            end if;
                        else
                            -- Accept Registration
                            stage_next      <= PUSH_KEY_HASH;
                            
                            -- Insert New Instance
                            inst_op_start   <= '1';
                            inst_opcode     <= INSERT_INSTANCE;
                            inst_r.i        <= ind;    
                            inst_r.key_hash <= key_hash;
                        end if;
                    end if;
                end if;
            when LOOKUP_OPERATION =>
                assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                
                -- Wait for Instance Search to finish
                if (inst_op_done = '1') then
                    -- Instance Found
                    if (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) then
                        stage_next  <= PUSH_KEY_HASH;
                    else
                        -- Return Special Value
                        key_hash_next   <= KEY_HASH_NIL;
                        stage_next      <= PUSH_KEY_HASH;
                    end if;
                end if;
            when PUSH_KEY_HASH =>
                done_dds(ind)                   <= '1';
                instance_handle_out_dds(ind)    <= key_hash;
                -- DONE
                stage_next  <= IDLE;
            when FILTER_STAGE =>
                -- Precondition: cur_sample set, inst_data set (IMF_SAMPLE_CNT_FLAG, IMF_ACK_CNT_FLAG)
                
                -- Wait for Instance Search to finish
                if (inst_op_done = '1') then
                    -- Instance Found
                    if (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) then
                        assert (stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG))) severity FAILURE;
                        
                        -- Latch Instance Pointer
                        cur_inst_next   <= inst_data.addr;
                        
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
                        if (CONFIG_ARRAY_T(ind).MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(CONFIG_ARRAY_T(ind).MAX_SAMPLES_PER_INSTANCE)) then
                            if (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                -- No ACKed Instance Samples exist
                                if (inst_data.ack_cnt = 0) then
                                    -- Reject Change
                                    done_dds(ind)           <= '1';
                                    return_code_dds(ind)    <= 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(ind)           <= '1';
                                    return_code_dds(ind)    <= RETCODE_OK;
                                    stage_next              <= UPDATE_INSTANCE;
                                end if;
                            else
                                assert (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_LAST_HISTORY_QOS) severity FAILURE;
                                
                                -- Accept Change (Remove Oldest (ACKed) Instance Sample)
                                remove_oldest_inst_sample_next  <= '1';
                                if (inst_data.ack_cnt /= 0) then
                                    remove_ack_sample_next          <= '1';
                                else
                                    remove_ack_sample_next          <= '0';
                                end if;
                                done_dds(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OK;
                                stage_next              <= UPDATE_INSTANCE;
                            end if;
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                        elsif (empty_sample_list_head(ind) = empty_sample_list_tail(ind)) then
                            if (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                -- No ACKed Samples exist
                                if (global_ack_cnt(ind) = 0) then
                                    -- Reject Change
                                    done_dds(ind)           <= '1';
                                    return_code_dds(ind)    <= 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(ind)           <= '1';
                                    return_code_dds(ind)    <= RETCODE_OK;
                                    stage_next              <= UPDATE_INSTANCE;
                                end if;
                            else
                                assert (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_LAST_HISTORY_QOS) severity FAILURE;
                                
                                -- Accept Change (Remove Oldest (ACKed) Sample)
                                remove_oldest_sample_next   <= '1';
                                if (global_ack_cnt(ind) /= 0) then
                                    remove_ack_sample_next      <= '1';
                                else
                                    remove_ack_sample_next      <= '0';
                                end if;
                                done_dds(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OK;
                                stage_next              <= UPDATE_INSTANCE;
                            end if;
                        else
                            -- Accept Change
                            done_dds(ind)           <= '1';
                            return_code_dds(ind)    <= RETCODE_OK;
                            stage_next              <= UPDATE_INSTANCE;
                        end if;
                    else
                        -- Latch Instance Pointer
                        cur_inst_next   <= inst_empty_head(ind);
                        
                        -- Provided Instance Handle Invalid
                        if (instance_handle /= HANDLE_NIL) then
                            -- Invalid Operation
                            done_dds(ind)           <= '1';
                            return_code_dds(ind)    <= 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(ind)           <= '1';
                            return_code_dds(ind)    <= RETCODE_OK;
                            -- DONE
                            stage_next  <= IDLE;
                        -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
                        elsif (inst_empty_head(ind) = INSTANCE_MEMORY_MAX_ADDRESS) then
                            assert (stable(clk,CONFIG_ARRAY_T(ind).WITH_KEY)) severity FAILURE;
                            
                            -- No Stale Instances available
                            if (stale_inst_cnt(ind) = 0) then
                                -- Reject Change
                                done_dds(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OUT_OF_RESOURCES;
                                stage_next              <= IDLE;
                            -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                            elsif (empty_sample_list_head(ind) = empty_sample_list_tail(ind)) then
                                if (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- No ACKed Samples exist
                                    if (global_ack_cnt(ind) = 0) then
                                        -- Reject Change
                                        done_dds(ind)           <= '1';
                                        return_code_dds(ind)    <= 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(ind)           <= '1';
                                        return_code_dds(ind)    <= RETCODE_OK;
                                        
                                        -- Remove Stale and insert new Instance
                                        inst_op_start       <= '1';
                                        inst_opcode         <= GET_INSTANCE;
                                        inst_r.i            <= ind;
                                        inst_r.addr         <= inst_occupied_head(ind);
                                        inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                        stage_next          <= REMOVE_STALE_INSTANCE;
                                        cnt_next            <= 0;
                                    end if;
                                else
                                    assert (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_LAST_HISTORY_QOS) severity FAILURE;
                                    
                                    -- Accept Change (Remove Oldest (ACKed) Sample)
                                    remove_oldest_sample_next   <= '1';
                                    if (global_ack_cnt(ind) /= 0) then
                                        remove_ack_sample_next      <= '1';
                                    else
                                        remove_ack_sample_next      <= '0';
                                    end if;
                                    done_dds(ind)           <= '1';
                                    return_code_dds(ind)    <= RETCODE_OK;
                                    
                                    -- Remove Stale and insert new Instance
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_INSTANCE;
                                    inst_r.i            <= ind;
                                    inst_r.addr         <= inst_occupied_head(ind);
                                    inst_r.field_flags  <= 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(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OK;
                                
                                -- Remove Stale and insert new Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_INSTANCE;
                                inst_r.i            <= ind;
                                inst_r.addr         <= inst_occupied_head(ind);
                                inst_r.field_flags  <= 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(ind) = empty_sample_list_tail(ind)) then
                                if (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_ALL_HISTORY_QOS) then
                                    -- No ACKed Samples exist
                                    if (global_ack_cnt(ind) = 0) then
                                        -- Reject Change
                                        done_dds(ind)           <= '1';
                                        return_code_dds(ind)    <= 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(ind)           <= '1';
                                        return_code_dds(ind)    <= RETCODE_OK;
                                        
                                        -- Insert New Instance
                                        inst_op_start       <= '1';
                                        inst_opcode         <= INSERT_INSTANCE;
                                        inst_r.i            <= ind;
                                        inst_r.key_hash     <= key_hash;
                                        inst_r.status_info  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                        inst_r.sample_cnt   <= to_unsigned(1, WORD_WIDTH);
                                        inst_r.ack_cnt      <= (others => '0');
                                        
                                        stage_next  <= FINALIZE_PAYLOAD;
                                        cnt_next    <= 0;
                                    end if;
                                else
                                    assert (CONFIG_ARRAY_T(ind).HISTORY_QOS = KEEP_LAST_HISTORY_QOS) severity FAILURE;
                                    
                                    -- Accept Change (Remove Oldest (ACKed) Sample)
                                    remove_oldest_sample_next   <= '1';
                                    if (global_ack_cnt(ind) /= 0) then
                                        remove_ack_sample_next      <= '1';
                                    else
                                        remove_ack_sample_next      <= '0';
                                    end if;
                                    done_dds(ind)           <= '1';
                                    return_code_dds(ind)    <= RETCODE_OK;
                                    
                                    -- Insert New Instance
                                    inst_op_start       <= '1';
                                    inst_opcode         <= INSERT_INSTANCE;
                                    inst_r.i            <= ind;
                                    inst_r.key_hash     <= key_hash;
                                    inst_r.status_info  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                    inst_r.sample_cnt   <= to_unsigned(1, WORD_WIDTH);
                                    inst_r.ack_cnt      <= (others => '0');
                                    
                                    stage_next  <= FINALIZE_PAYLOAD;
                                    cnt_next    <= 0;
                                end if;
                            else
                                -- Accept Change
                                done_dds(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OK;
                                
                                -- Insert New Instance
                                inst_op_start       <= '1';
                                inst_opcode         <= INSERT_INSTANCE;
                                inst_r.i            <= ind;
                                inst_r.key_hash     <= key_hash;
                                inst_r.status_info  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                inst_r.sample_cnt   <= to_unsigned(1, WORD_WIDTH);
                                inst_r.ack_cnt      <= (others => '0');
                                
                                stage_next  <= FINALIZE_PAYLOAD;
                                cnt_next    <= 0;                            
                            end if;
                        end if;
                    end if;
                end if;
            when UPDATE_INSTANCE =>
                -- Precondition: inst_data set (IMF_STATUS_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_ACK_CNT_FLAG)
                
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    assert (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG)) severity FAILURE;
                    
                    inst_op_start       <= '1';
                    inst_opcode         <= UPDATE_INSTANCE;
                    inst_r.i            <= ind;
                    inst_r.addr         <= inst_data.addr;
                    inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG;
                    inst_r.status_info  <= inst_data.status_info;
                    inst_r.status_info(ISI_LIVELINESS_FLAG) <= '1';
                    if (sample_status_info(SSI_DISPOSED_FLAG) = '0' and sample_status_info(SSI_UNREGISTERED_FLAG) = '0') then
                        inst_r.status_info(ISI_DISPOSED_FLAG)       <= '0';
                        inst_r.status_info(ISI_UNREGISTERED_FLAG)   <= '0';
                    elsif (sample_status_info(SSI_DISPOSED_FLAG) = '1') then
                        inst_r.status_info(ISI_DISPOSED_FLAG)       <= '1';
                    elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then
                        inst_r.status_info(ISI_UNREGISTERED_FLAG)   <= '1';
                    end if;
                    inst_r.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(ind) <= stale_inst_cnt(ind) - 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(ind)   <= resize(unsigned(payload_read_data), PAYLOAD_MEMORY_ADDR_WIDTH);
                            
                            stage_next          <= FINALIZE_SAMPLE;
                            cur_sample_next     <= empty_sample_list_head(ind);
                            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(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                assert (oldest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                cnt_next    <= cnt + 2; -- SET INSTANCE POINTER
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- SET Next Pointer (Previous Sample)
                    when 1 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= newest_sample(ind) + 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 Instance Pointer
                    when 2 =>
                        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;
                    -- 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(ind), 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(ind)    <= resize(unsigned(sample_read_data), SAMPLE_MEMORY_ADDR_WIDTH);
                            
                            -- Fix List Pointers
                            newest_sample_next(ind) <= cur_sample;
                            if (oldest_sample(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                oldest_sample_next(ind) <= cur_sample;
                            end if;
                            
                            -- Increment Global Sequence Number
                            global_seq_nr_next(ind) <= global_seq_nr(ind) + 1;
                            
                            -- Increment Global Sample Count
                            global_sample_cnt_next(ind) <= global_sample_cnt(ind) + 1;
                            -- Trigger ACK Wait Check
                            ack_wait_check_next     <= '1';
                            
                            -- Signal Data Available
                            data_available_sig_next(ind)    <= '1';
                            
                            -- NOTE: This is needed to prevent the new Sample from being 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 (CONFIG_ARRAY_T(ind).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(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                                cur_sample_next <= oldest_sample(ind);
                                stage_next      <= FIND_SAMPLE;
                                cnt_next        <= 0;
                            elsif (remove_oldest_sample = '1') then
                                assert (oldest_sample(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
                                
                                stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                                cnt_next    <= 0;
                            else
                                -- DONE
                                stage_next  <= IDLE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_OLDEST_SAMPLE_INSTANCE =>
                case (cnt) is
                    -- GET Instance Pointer (Oldest Sample)
                    when 0 =>
                        sample_valid_in <= '1';
                        sample_addr     <= oldest_sample(ind) + 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_r.i            <= ind;
                                inst_r.addr         <= resize(unsigned(sample_read_data), INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                
                                cur_sample_next     <= oldest_sample(ind);
                                stage_next          <= REMOVE_SAMPLE;
                                cnt_next            <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            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; -- GET INSTANCE POINTER
                            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
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Instance Pointer
                    when 2 =>
                        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;
                    -- 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;
                                
                                cnt_next    <= cnt + 2; -- READ INSTANCE POINTER
                            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
                                cnt_next    <= cnt + 1;
                            else
                                -- Continue
                                sample_abort_read   <= '1';
                                cur_sample_next     <= next_sample;
                                cnt_next            <= 0;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 5 =>
                        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_r.i            <= ind;
                                inst_r.addr         <= resize(unsigned(sample_read_data), INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                
                                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;
                    when others =>
                        null;
                end case;
            when REMOVE_ORPHAN_SAMPLES =>
                assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                    
                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;
            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(ind) = SAMPLE_MEMORY_MAX_ADDRESS) then
                                empty_sample_list_head_next(ind)    <= cur_sample;
                                empty_sample_list_tail_next(ind)    <= cur_sample;
                                cnt_next    <= cnt + 2; -- SET NEXT POINTER
                            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(ind) + 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(ind)    <= cur_sample;
                            
                            -- Current Sample is Newest (Occupied List Tail)
                            if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                assert (cur_sample = newest_sample(ind)) severity FAILURE;
                                
                                -- Fix Newest Pointer
                                newest_sample_next(ind) <= prev_sample;
                                
                                -- Current Sample is Oldest (List Head)
                                if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    assert (cur_sample = oldest_sample(ind)) severity FAILURE;
                                    assert (newest_sample(ind) = oldest_sample(ind)) severity FAILURE;
                                    -- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR)
                                    
                                    -- Fix Oldest Pointer
                                    oldest_sample_next(ind) <= SAMPLE_MEMORY_MAX_ADDRESS;
                                    
                                    cnt_next    <= cnt + 3; -- READ PAYLOAD POINTER
                                else
                                    cnt_next    <= cnt + 2; -- SET NEXT POINTER (Previous Sample)
                                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(ind)) severity FAILURE;
                                
                                -- Fix Oldest Pointer
                                oldest_sample_next(ind) <= next_sample;
                                
                                cnt_next    <= cnt + 2; -- READ PAYLOAD POINTER
                            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(ind) <= global_sample_cnt(ind) - 1;
                            -- Trigger ACK Wait Check
                            ack_wait_check_next     <= '1';
                            
                            -- Update Global ACK Count
                            -- Sample was ACKed
                            if (sample_status_info(SSI_ACK_FLAG) = '1') then
                                global_ack_cnt_next(ind)    <= global_ack_cnt(ind) - 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(ind) = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                -- Fix Empty List Head
                                empty_payload_list_head_next(ind)   <= 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            <= 12; -- GET NEXT PAYLOAD
                            end if;
                        end if;
                    -- SET Next Payload Pointer (Last Payload Slot 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(ind),WORD_WIDTH));
                        
                        -- Fix Empty List Head
                        empty_payload_list_head_next(ind)   <= 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 (IMF_STATUS_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_ACK_CNT_FLAG)
                
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    assert (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
                    assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG)) severity FAILURE;
                    
                    inst_op_start       <= '1';
                    inst_opcode         <= UPDATE_INSTANCE;
                    inst_r.i            <= ind;
                    inst_r.addr         <= inst_data.addr;
                    inst_r.field_flags  <= IMF_SAMPLE_CNT_FLAG;
                    inst_r.sample_cnt   <= inst_data.sample_cnt - 1;
                    -- Sample was ACKed
                    if (sample_status_info(SSI_ACK_FLAG) = '1') then
                        inst_r.field_flags <= IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                        inst_r.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(ind)    <= stale_inst_cnt(ind) + 1;
                        end if;
                    end if;
                    
                    if (is_rtps = '1') then
                        -- DONE
                        done_rtps(ind)  <= '1';
                        ret_rtps(ind)   <= OK;
                        stage_next      <= IDLE;
                    elsif (is_lifespan_check = '1') then
                        -- Reached End of Samples
                        if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                            -- Continue
                            stage_next          <= CHECK_LIFESPAN;
                            cnt_next            <= 0; -- GET NEXT WRITER
                        else
                            -- Continue Search
                            cur_sample_next     <= next_sample;
                            stage_next          <= CHECK_LIFESPAN;
                            cnt_next            <= 2; -- GET NEXT SAMPLE
                        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(ind)   <= '1';
                        -- Wait until last word from input
                        if (last_word_in_dds(ind)  = '1') then
                            cnt_next  <= cnt + 1;
                        end if;
                    -- Return Code
                    when 1 =>
                        done_dds(ind)           <= '1';
                        return_code_dds(ind)    <= return_code_latch;
                        
                        -- DONE
                        stage_next      <= IDLE;
                    when others =>
                        null;
                end case;
            when SKIP =>
                ready_in_dds(ind)   <= '1';
                -- Wait until last word from input
                if (last_word_in_dds(ind) = '1') then
                    stage_next  <= return_stage;
                    cnt_next    <= 0;
                end if;
            when REMOVE_STALE_INSTANCE =>
                assert (CONFIG_ARRAY_T(ind).WITH_KEY) severity FAILURE;
                
                -- 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_data.addr = 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 stable(clk,FALSE) severity FAILURE;
                                stage_next  <= IDLE;
                            else
                                assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG)) severity FAILURE;
                                
                                -- 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;
                                    inst_r.i        <= ind;
                                    inst_r.addr     <= inst_data.addr;
                                    -- Update Stale Instance Count
                                    stale_inst_cnt_next(ind)    <= stale_inst_cnt(ind) - 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_data.addr;
                                    end if;
                                    
                                    cnt_next    <= cnt + 1;
                                else
                                    -- Continue Search
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_NEXT_INSTANCE;
                                    inst_r.i            <= ind;
                                    inst_r.addr         <= inst_data.addr;
                                    inst_r.field_flags  <= 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;
                            inst_r.i        <= ind;
                            inst_r.key_hash <= key_hash;
                            inst_r.ack_cnt  <= (others => '0');
                            if (register_op = '1') then
                                inst_r.status_info  <= (others => '0');
                                inst_r.sample_cnt   <= (others => '0');
                            else
                                inst_r.status_info  <= (ISI_LIVELINESS_FLAG => '1', others => '0');
                                inst_r.sample_cnt   <= to_unsigned(1, WORD_WIDTH);
                            end if;
                            
                            -- Latch Instance Pointer
                            cur_inst_next   <= inst_empty_head(ind); 
                            
                            -- Register Operation in progress
                            if (register_op = '1') then
                                -- DONE
                                stage_next  <= PUSH_KEY_HASH;
                            else
                                stage_next  <= FINALIZE_PAYLOAD;
                                cnt_next    <= 0;
                            end if;
                        when others =>
                            null;
                    end case;
                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(ind)  <= '1';
                        ret_rtps(ind)   <= 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
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Instance Pointer
                    when 3 =>
                        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;
                    -- 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
                                cnt_next    <= cnt + 1;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 7 =>
                        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;
                    -- Check Result
                    when 8 =>
                        -- No Sample with Requested Sequence Number found
                        if (cur_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                            done_rtps(ind)  <= '1';
                            ret_rtps(ind)   <= INVALID;
                            
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Memory Operation Guard
                            if (inst_op_done = '1') then
                                -- Fetch Instance Data
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_INSTANCE;
                                inst_r.i            <= ind;
                                inst_r.addr         <= cur_inst;
                                inst_r.field_flags  <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                
                                stage_next  <= return_stage;
                                cnt_next    <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when ACKNACK_SAMPLE =>
                -- Precondition: inst_data set (IMF_ACK_CNT_FLAG, IMF_STATUS_FLAG, IMF_SAMPLE_CNT_FLAG)
                
                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(ind)  <= '1';
                                ret_rtps(ind)   <= 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;
                        if (is_ack = '1') then
                            sample_write_data(SSI_ACK_FLAG) <= '1';
                        else
                            sample_write_data(SSI_ACK_FLAG) <= '0';
                        end if;
                        -- Memory Flow Control Guard
                        if (sample_ready_in = '1') then
                            -- Trigger ACK Wait Check
                            ack_wait_check_next     <= '1';
                            if (is_ack = '1') then
                                global_ack_cnt_next(ind)    <= global_ack_cnt(ind) + 1;
                            else
                                global_ack_cnt_next(ind)    <= global_ack_cnt(ind) - 1;
                            end if;
                            cnt_next            <= cnt + 1;
                        end if;
                    -- SET Instance Data
                    when 3 =>
                        -- Wait for Instance Data
                        if (inst_op_done = '1') then
                            assert (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
                            assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG)) severity FAILURE;
                            
                            -- Update 
                            inst_op_start       <= '1';
                            inst_opcode         <= UPDATE_INSTANCE;
                            inst_r.i            <= ind;
                            inst_r.addr         <= cur_inst;
                            inst_r.field_flags  <= IMF_ACK_CNT_FLAG;
                            if (is_ack = '1') then
                                inst_r.ack_cnt  <= inst_data.ack_cnt + 1;
                            else
                                inst_r.ack_cnt  <= inst_data.ack_cnt - 1;
                            end if;
                            
                            -- 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(ind)    <= stale_inst_cnt(ind) + 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(ind)    <= stale_inst_cnt(ind) - 1;
                            end if;
                            
                            -- DONE
                            done_rtps(ind)  <= '1';
                            ret_rtps(ind)   <= OK;
                            stage_next      <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_SAMPLE =>
                -- Precondition: inst_data set (IMF_KEY_HASH_FLAG)
                
                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);
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Instance Handle
                    when 8 =>
                        -- Wait for Instance Data
                        if (inst_op_done = '1') then
                            assert (inst_data.addr /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
                            assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_KEY_HASH_FLAG)) severity FAILURE;
                            
                            cc_instance_handle_sig_next <= inst_data.key_hash;
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Present Sample
                    when 9 =>
                        done_rtps(ind)  <= '1';
                        ret_rtps(ind)   <= OK;
                        
                        -- RTPS Requestes Payload
                        if (get_data_rtps(ind) = '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(ind)-1,CDR_LONG_WIDTH));
                            end if;
                        end if;
                    -- GET Payload Offset
                    when 2 =>
                        payload_valid_in    <= '1';
                        payload_addr        <= cur_payload + PAYLOAD_FRAME_SIZE(ind)-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(ind) <= '1';
                        data_out_rtps(ind)  <= payload_read_data;
                        
                        -- End of Payload
                        if (cnt3 = 1 and cnt = 5) then
                            last_word_out_rtps(ind) <= '1';
                        end if;
                        
                        -- DDS Read
                        if (ready_out_rtps(ind) = '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 WRITER
                    when 0 =>
                        if (ind = NUM_WRITERS-1) then
                            -- Reset
                            is_lifespan_check_next  <= '0';
                            
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Next Writer
                            ind_next    <= ind + 1;
                            cnt_next    <= cnt + 1;
                        end if;
                    -- CHECK LIFESPAN
                    when 1 =>
                        -- Samples Available (And Writer has Lifespan enabled)
                        if (CONFIG_ARRAY_T(ind).LIFESPAN_QOS /= DURATION_INFINITE and oldest_sample(ind) /= SAMPLE_MEMORY_MAX_ADDRESS) then
                            cur_sample_next <= oldest_sample(ind);
                            cnt_next        <= cnt + 1;
                        else
                            -- Continue
                            cnt_next   <= 0; -- GET NEXT WRITER
                        end if;
                    -- GET NEXT Sample
                    when 2 =>
                        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 3 =>
                        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 4 =>
                        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
                            cnt_next    <= cnt + 1;
                        end if;
                    -- GET Instance Pointer
                    when 5 =>
                        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;
                    -- READ Next Sample
                    when 6 =>
                        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 7 =>
                        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 8 =>
                        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
                                cnt_next    <= cnt + 1;
                            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
                                    -- Continue
                                    cnt_next    <= 0; -- GET NEXT WRITER
                                else
                                    -- Continue Search
                                    cur_sample_next <= next_sample;
                                    cnt_next        <= 2; -- GET NEXT SAMPLE
                                end if;
                            end if;
                        end if;
                    -- READ Instance Pointer
                    when 9 =>
                        -- 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_r.i            <= ind;
                                inst_r.addr         <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_r.field_flags  <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_ACK_CNT_FLAG;
                                
                                -- Remove Sample
                                stage_next  <= REMOVE_SAMPLE;
                                cnt_next    <= 0;
                            end if;
                        end if;
                    when others => 
                        null;
                end case;
            when GET_LIVELINESS_LOST_STATUS =>
                case (cnt) is
                    -- Return Code
                    when 0  =>
                        done_dds(ind)           <= '1';
                        return_code_dds(ind)    <= RETCODE_OK;
                        cnt_next                <= cnt + 1;    
                    -- Total Count
                    when 1 =>
                        data_out_dds(ind)   <= std_logic_vector(liveliness_lost_cnt(ind));
                        valid_out_dds(ind)  <= '1';
                        
                        if (ready_out_dds(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Total Count Change
                    when 2 =>
                        data_out_dds(ind)       <= std_logic_vector(liveliness_lost_cnt_change(ind));
                        valid_out_dds(ind)      <= '1';
                        last_word_out_dds(ind)  <= '1';
                        
                        if (ready_out_dds(ind) = '1') then
                            -- Reset
                            liveliness_lost_cnt_change_next(ind)    <= (others => '0');
                            status_sig_next(ind)    <= status_sig(ind) 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(ind)           <= '1';
                        return_code_dds(ind)    <= RETCODE_OK;
                        cnt_next                <= cnt + 1;
                    -- Total Count
                    when 1 =>
                        data_out_dds(ind)   <= std_logic_vector(deadline_miss_cnt(ind));
                        valid_out_dds(ind)  <= '1';
                        
                        if (ready_out_dds(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Total Count Change
                    when 2 =>
                        data_out_dds(ind)   <= std_logic_vector(deadline_miss_cnt_change(ind));
                        valid_out_dds(ind)  <= '1';
                        
                        if (ready_out_dds(ind) = '1') then
                            -- Reset
                            deadline_miss_cnt_change_next(ind)  <= (others => '0');
                            
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 1/4
                    when 3 =>
                        data_out_dds(ind)   <= deadline_miss_last_inst(ind)(0);
                        valid_out_dds(ind)  <= '1';
                        if (ready_out_dds(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 2/4
                    when 4 =>
                        data_out_dds(ind)   <= deadline_miss_last_inst(ind)(1);
                        valid_out_dds(ind)  <= '1';
                        if (ready_out_dds(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 3/4
                    when 5 =>
                        data_out_dds(ind)   <= deadline_miss_last_inst(ind)(2);
                        valid_out_dds(ind)  <= '1';
                        if (ready_out_dds(ind) = '1') then
                            cnt_next    <= cnt + 1;
                        end if;
                    -- Last Instance Handle 4/4
                    when 6 =>
                        data_out_dds(ind)       <= deadline_miss_last_inst(ind)(3);
                        valid_out_dds(ind)      <= '1';
                        last_word_out_dds(ind)  <= '1';
                        if (ready_out_dds(ind) = '1') then
                            -- Reset
                            deadline_miss_last_inst_next(ind)   <= HANDLE_NIL;
                            status_sig_next(ind)                <= status_sig(ind) and (not OFFERED_DEADLINE_MISSED_STATUS);
                            
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when CHECK_DEADLINE =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    case (cnt) is
                        -- GET NEXT WRITER
                        when 0 =>
                            if (ind = NUM_WRITERS-1) then
                                -- DONE
                                stage_next  <= IDLE;
                            else
                                -- Next Writer
                                ind_next    <= ind + 1;
                                cnt_next    <= cnt + 1;
                            end if;
                        -- CHECK DEADLINE
                        when 1 =>
                            -- Deadline Check Trigger
                            if (CONFIG_ARRAY_T(ind).DEADLINE_QOS /= DURATION_INFINITE and deadline_time(ind) <= time) then
                                tmp_dw  := deadline_time(ind) + CONFIG_ARRAY_T(ind).DEADLINE_QOS;
                                deadline_time_next(ind) <= tmp_dw;
                                
                                -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                                -- Update Check Time
                                if (tmp_dw < deadline_check_time) then
                                    deadline_check_time_next <= tmp_dw;
                                end if;
                                
                                cnt_next    <= cnt + 1;
                            else
                                if (CONFIG_ARRAY_T(ind).DEADLINE_QOS /= DURATION_INFINITE and deadline_time(ind) <= deadline_check_time) then
                                    deadline_check_time_next    <= deadline_time(ind);
                                end if;
                                
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            end if;
                        -- GET FIRST Instance
                        when 2 =>
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_INSTANCE;
                            inst_r.i            <= ind;
                            inst_r.addr         <= inst_occupied_head(ind);
                            inst_r.field_flags  <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
                            cnt_next            <= 4; -- CHECK INSTANCE
                        -- GET NEXT Instance
                        when 3 =>
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_NEXT_INSTANCE;
                            inst_r.i            <= ind;
                            inst_r.addr         <= inst_data.addr;
                            inst_r.field_flags  <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
                            cnt_next            <= 4; -- CHECK INSTANCE
                        -- CHECK Instance
                        when 4 =>
                            -- Reached End of Instances
                            if (inst_data.addr = INSTANCE_MEMORY_MAX_ADDRESS) then
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            else
                                assert stable(clk, inst_data.i = ind and check_mask(inst_data.field_flags, IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG)) severity FAILURE;
                                
                                -- 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_r.i            <= ind;
                                    inst_r.addr         <= inst_data.addr;
                                    inst_r.field_flags  <= IMF_STATUS_FLAG;
                                    inst_r.status_info  <= inst_data.status_info;
                                    inst_r.status_info(ISI_LIVELINESS_FLAG) <= '0';
                                    cnt_next    <= 3; -- GET NEXT INSTANCE
                                else
                                    -- Update Requested Deadline Missed Status
                                    status_sig_next(ind)                <= status_sig(ind) or OFFERED_DEADLINE_MISSED_STATUS;
                                    deadline_miss_cnt_next(ind)         <= std_logic_vector(unsigned(deadline_miss_cnt(ind)) + 1);
                                    deadline_miss_cnt_change_next(ind)  <= std_logic_vector(unsigned(deadline_miss_cnt_change(ind)) + 1);
                                    deadline_miss_last_inst_next(ind)   <= inst_data.key_hash;
                                    cnt_next    <= 3; -- GET NEXT INSTANCE
                                end if;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when CHECK_LIVELINESS =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    case (cnt) is
                        -- GET NEXT WRITER
                        when 0 =>
                            if (ind = NUM_WRITERS-1) then
                                -- DONE
                                stage_next  <= IDLE;
                            else
                                -- Next Writer
                                ind_next    <= ind + 1;
                                cnt_next    <= cnt + 1;
                            end if;
                        -- CHECK LEASE
                        when 1 =>
                            -- Deadline Check Trigger
                            if (CONFIG_ARRAY_T(ind).LEASE_DURATION /= DURATION_INFINITE and lease_deadline(ind) <= time) then
                                tmp_dw  := lease_deadline(ind) + CONFIG_ARRAY_T(ind).LEASE_DURATION;
                                lease_deadline_next(ind)    <= tmp_dw;
                                
                                -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
                                -- Update Check Time
                                if (tmp_dw < lease_check_time) then
                                    lease_check_time_next   <= tmp_dw;
                                end if;
                                
                                status_sig_next(ind)                    <= status_sig(ind) or LIVELINESS_LOST_STATUS;
                                liveliness_lost_cnt_next(ind)           <= std_logic_vector(unsigned(liveliness_lost_cnt(ind)) + 1);
                                liveliness_lost_cnt_change_next(ind)    <= std_logic_vector(unsigned(liveliness_lost_cnt_change(ind)) + 1);
                                
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            else
                                if (CONFIG_ARRAY_T(ind).LEASE_DURATION /= DURATION_INFINITE and lease_deadline(ind) <= lease_check_time) then
                                    lease_check_time_next   <= lease_deadline(ind);
                                end if;
                                
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when CHECK_ACK_WAIT =>
                case (cnt) is
                    -- GET NEXT WRITER
                    when 0 =>
                        if (ind = NUM_WRITERS-1) then
                            -- Reset
                            ack_wait_check_next <= '0';
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Next Writer
                            ind_next    <= ind + 1;
                            cnt_next    <= cnt + 1;
                        end if;
                    -- CHECK ACK STATE
                    when 1 =>
                        -- Writer in WAIT_FOR_ACKNOWLEDGEMENT Operation
                        if(ack_wait(ind) = '1') then
                            -- All Writer Samples are ACKed
                            if (global_ack_cnt(ind) = global_sample_cnt(ind)) then
                                -- Reset
                                ack_wait_next(ind)  <= '0';
                                -- DONE
                                done_dds(ind)           <= '1';
                                return_code_dds(ind)    <= RETCODE_OK;
                                
                                -- Continue
                                cnt_next    <= 0; -- GET NEXT WRITER
                            else
                                cnt_next    <= cnt + 1;
                            end if;
                        else
                            -- Continue
                            cnt_next    <= 0; -- GET NEXT WRITER
                        end if;
                    -- CHECK OPERATION TIMEOUT
                    when 2 =>
                        assert (ack_wait(ind) = '1') severity FAILURE;
                        
                        -- WAIT_FOR_ACKNOWLEDGEMENT Operation Timeout
                        if (timeout_time(ind) <= time) then
                            -- Reset
                            ack_wait_next(ind)  <= '0';
                            
                            -- DONE
                            done_dds(ind)           <= '1';
                            return_code_dds(ind)    <= RETCODE_TIMEOUT;
                            
                            -- Continue
                            cnt_next    <= 0; -- GET NEXT WRITER
                        else
                            if (timeout_time(ind) <= timeout_check_time) then
                                timeout_check_time_next <= timeout_time(ind);
                            end if;
                            
                            -- Continue
                            cnt_next    <= 0; -- GET NEXT WRITER
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_SAMPLE_MEMORY =>
                case (cnt) is
                    -- SET Previous Pointer
                    when 0 =>
                        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 1 =>
                        sample_valid_in     <= '1';
                        sample_addr         <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        if (cur_sample = MAX_SAMPLE_ADDRESS(ind)) 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(ind)) then
                                empty_sample_list_head_next(ind)    <= FIRST_SAMPLE_ADDRESS;
                                empty_sample_list_tail_next(ind)    <= MAX_SAMPLE_ADDRESS(ind);
                                -- DONE
                                cur_payload_next    <= FIRST_PAYLOAD_ADDRESS;
                                stage_next          <= RESET_PAYLOAD_MEMORY;
                            else
                                -- Continue
                                cur_sample_next     <= cur_sample + SAMPLE_FRAME_SIZE;
                                prev_sample_next    <= cur_sample;
                                cnt_next            <= 0; -- SET Previous Pointer
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_PAYLOAD_MEMORY =>
                -- SET Next Pointer
                payload_valid_in    <= '1';
                payload_addr        <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                if (cur_payload = MAX_PAYLOAD_ADDRESS(ind)) 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(ind),WORD_WIDTH));
                end if;
                
                -- Memory Flow Control Guard
                if (payload_ready_in = '1') then
                    if (cur_payload = MAX_PAYLOAD_ADDRESS(ind)) then
                        empty_payload_list_head_next(ind)   <= FIRST_PAYLOAD_ADDRESS;
                        
                        if (ind = NUM_WRITERS-1) then
                            -- DONE
                            stage_next  <= IDLE;
                        else
                            -- Continue (Next Writer)
                            ind_next            <= ind + 1;
                            prev_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                            cur_sample_next     <= FIRST_SAMPLE_ADDRESS;
                            stage_next          <= RESET_SAMPLE_MEMORY;
                            cnt_next            <= 0;
                        end if;
                    else
                        cur_payload_next    <= cur_payload + PAYLOAD_FRAME_SIZE(ind);
                    end if;
                end if;
        end case;
    end process;
    
    empty_head_sig_prc : process(all)
    begin
        for i in 0 to NUM_WRITERS-1 loop
            empty_inst_head_sig(i)      <= to_integer(inst_empty_head(i));
            empty_sample_head_sig(i)    <= to_integer(empty_sample_list_head(i));
            empty_payload_head_sig(i)   <= to_integer(empty_payload_list_head(i));
        end loop;
    end process;
    
    -- *Instance Memory Process*
    -- STATE                    DESCRIPTION
    -- IDLE                     Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
    -- SEARCH_INSTANCE          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_addr_latch_next        <= inst_addr_latch;
        inst_empty_head_next        <= inst_empty_head;
        inst_occupied_head_next     <= inst_occupied_head;
        inst_latch_data_next        <= inst_latch_data;
        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
                    inst_latch_data_next    <= inst_r;
                    
                    case(inst_opcode) is
                        when SEARCH_INSTANCE =>
                            -- Reset Data
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            inst_data_next.i    <= inst_r.i;
                            
                            -- No Instances available
                            if (inst_occupied_head(inst_r.i) /= INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next <= inst_occupied_head(inst_r.i);
                                inst_stage_next     <= SEARCH_INSTANCE;
                                inst_cnt_next       <= 0;
                            end if;
                        when INSERT_INSTANCE =>
                            assert (inst_empty_head(inst_r.i) /= INSTANCE_MEMORY_MAX_ADDRESS) severity FAILURE;
                            
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            inst_data_next.i    <= inst_r.i;
                            
                            inst_data_next.addr <= inst_empty_head(inst_r.i);
                            inst_addr_base_next <= inst_empty_head(inst_r.i);
                            inst_stage_next     <= INSERT_INSTANCE;
                            inst_cnt_next       <= 0;
                        when UPDATE_INSTANCE =>
                            if (inst_r.addr = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                inst_data_next.i    <= inst_r.i;
                            else
                                if (inst_r.i /= inst_data.i or inst_r.addr /= inst_data.addr) then
                                    inst_data_next  <= ZERO_INSTANCE_DATA;
                                    inst_data_next.i    <= inst_r.i;
                                end if;
                                
                                inst_data_next.addr <= inst_r.addr;
                                inst_addr_base_next <= inst_r.addr;
                                inst_stage_next     <= UPDATE_INSTANCE;
                                if check_mask(inst_r.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 0;
                                elsif check_mask(inst_r.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 1;
                                elsif check_mask(inst_r.field_flags,IMF_ACK_CNT_FLAG) then
                                    inst_cnt_next   <= 2;
                                else
                                    -- DONE
                                    inst_stage_next <= IDLE;
                                end if;
                            end if;
                        when REMOVE_INSTANCE =>
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            inst_data_next.i    <= inst_r.i;
                            
                            if (inst_r.addr /= INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next <= inst_r.addr;
                                inst_stage_next     <= REMOVE_INSTANCE;
                                inst_cnt_next       <= 0;
                            end if;
                        when GET_NEXT_INSTANCE =>
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            inst_data_next.i    <= inst_r.i;
                            
                            -- No Instances available
                            if (inst_r.addr /= INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next <= inst_r.addr;
                                inst_stage_next     <= GET_NEXT_INSTANCE;
                                inst_cnt_next       <= 0;
                            end if;
                        when GET_INSTANCE =>
                            if (inst_r.addr = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_data_next  <= ZERO_INSTANCE_DATA;
                                inst_data_next.i    <= inst_r.i;
                            else
                                if (inst_r.i /= inst_data.i or inst_r.addr /= inst_data.addr) then
                                    inst_data_next  <= ZERO_INSTANCE_DATA;
                                    inst_data_next.i    <= inst_r.i;
                                end if;
                                
                                inst_data_next.addr <= inst_r.addr;
                                inst_addr_base_next <= inst_r.addr;
                                inst_stage_next     <= GET_INSTANCE_DATA;
                                if check_mask(inst_r.field_flags,IMF_KEY_HASH_FLAG) then
                                    inst_cnt_next   <= 0;
                                elsif check_mask(inst_r.field_flags,IMF_STATUS_FLAG) then
                                    inst_cnt_next   <= 4;
                                elsif check_mask(inst_r.field_flags,IMF_SAMPLE_CNT_FLAG) then
                                    inst_cnt_next   <= 5;
                                elsif check_mask(inst_r.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;
                end if;
            when SEARCH_INSTANCE =>
                
                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
                            inst_cnt_next   <= inst_cnt + 1;
                        end if;
                    -- READ Key Hash 1/4
                    when 4 =>
                        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';
                                inst_cnt_next   <= 8; -- GET NEXT INSTANCE
                            else
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        end if;
                    -- READ Key Hash 2/4
                    when 5 =>
                        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';
                                inst_cnt_next   <= 8; -- GET NEXT INSTANCE
                            else
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        end if;
                    -- READ Key Hash 3/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(2)) then
                                inst_abort_read <= '1';
                                inst_cnt_next   <= 8; -- GET NEXT INSTANCE
                            else
                                inst_cnt_next   <= inst_cnt + 1;
                            end if;
                        end if;
                    -- READ Key Hash 4/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(3)) then
                                inst_cnt_next   <= 8; -- GET NEXT INSTANCE
                            else
                                inst_data_next.addr <= inst_addr_base;
                                -- Get 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;
                    -- GET Next Instance
                    when 8 =>
                        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 9 =>
                        inst_ready_out  <= '1';
                        
                        -- Memory Flow Control Guard
                        if (inst_valid_out = '1') then
                            -- No more Endpoints
                            if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_data_next.addr <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next <= IDLE;
                            else
                                -- Continue
                                inst_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_cnt_next       <= 0;
                            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
                            if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_data_next.addr <= INSTANCE_MEMORY_MAX_ADDRESS;
                                -- DONE
                                inst_stage_next <= IDLE;
                            else
                                inst_data_next.addr <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                
                                -- Get Instance Data
                                inst_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                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 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;
                            inst_data_next.field_flags  <= inst_data.field_flags or IMF_KEY_HASH_FLAG;
                            
                            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;
                            inst_data_next.field_flags  <= inst_data.field_flags or IMF_STATUS_FLAG;
                            
                            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);
                            inst_data_next.field_flags  <= inst_data.field_flags or IMF_SAMPLE_CNT_FLAG;
                            
                            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);
                            inst_data_next.field_flags  <= inst_data.field_flags or IMF_ACK_CNT_FLAG;
                            
                            -- DONE
                            inst_stage_next <= IDLE;
                        end if;
                end case;
            when INSERT_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;
                    -- SET Key Hash 1/4
                    when 1 =>
                        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 2 =>
                        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 3 =>
                        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 4 =>
                        inst_valid_in   <= '1';
                        inst_addr       <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
                        inst_write_data <= inst_latch_data.key_hash(3);
                        inst_data_next.field_flags  <= inst_data.field_flags or IMF_KEY_HASH_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next   <= inst_cnt + 1;
                        end if;
                    -- SET Status Info
                    when 5 =>
                        inst_valid_in   <= '1';
                        inst_addr       <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                        inst_write_data <= inst_latch_data.status_info;
                        inst_data_next.field_flags  <= inst_data.field_flags or IMF_STATUS_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next   <= inst_cnt + 1;
                        end if;
                    -- SET Sample Count
                    when 6 =>
                        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.field_flags  <= inst_data.field_flags or IMF_SAMPLE_CNT_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next   <= inst_cnt + 1;
                        end if;
                    -- SET ACK Count
                    when 7 =>
                        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.field_flags  <= inst_data.field_flags or IMF_ACK_CNT_FLAG;
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next   <= inst_cnt + 1;
                        end if;
                    -- SET Next Addr
                    when 8 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_occupied_head(inst_latch_data.i),WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next    <= inst_cnt + 1;
                        end if;
                    -- SET Prev Addr
                    when 9 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_PREV_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(INSTANCE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            if (inst_occupied_head(inst_latch_data.i) = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_cnt_next    <= inst_cnt + 2; -- Skip Next Step
                            else
                                inst_cnt_next    <= inst_cnt + 1;
                            end if;
                        end if;
                    -- SET Prev Addr (Occupied Head)
                    when 10 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_occupied_head(inst_latch_data.i) + IMF_PREV_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_addr_base,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            inst_cnt_next    <= inst_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 11 =>
                        inst_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (inst_valid_out = '1') then
                            
                            -- Update List Heads
                            inst_empty_head_next(inst_latch_data.i)     <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                            inst_occupied_head_next(inst_latch_data.i)  <= inst_addr_base;
                            
                            -- 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;
                        inst_data_next.field_flags  <= inst_data.field_flags or IMF_STATUS_FLAG;
                        -- 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;
                        inst_data_next.field_flags  <= inst_data.field_flags or IMF_SAMPLE_CNT_FLAG;
                        -- 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;
                        inst_data_next.field_flags  <= inst_data.field_flags or IMF_ACK_CNT_FLAG;
                        -- 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 =>
                case (inst_cnt) is
                    -- GET Next Addr
                    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 Prev Addr
                    when 1 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_PREV_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 Addr
                    when 2 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_empty_head(inst_latch_data.i),WORD_WIDTH));
                        
                        if (inst_ready_in = '1') then
                            -- Set New Empty Head
                            inst_empty_head_next(inst_latch_data.i) <= inst_addr_base;
                            
                            inst_cnt_next    <= inst_cnt + 1;
                        end if;
                    -- READ Next Addr
                    when 3 =>
                        inst_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (inst_valid_out = '1') then
                            inst_addr_latch_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                            inst_cnt_next    <= inst_cnt + 1;
                        end if;
                    -- READ Prev Addr
                    when 4 =>
                        inst_ready_out   <= '1';
                        -- Memory Flow Control Guard
                        if (inst_valid_out = '1') then
                            if (inst_addr_latch = INSTANCE_MEMORY_MAX_ADDRESS) then
                                if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = INSTANCE_MEMORY_MAX_ADDRESS) then
                                    -- RESET Occupied List Head
                                    inst_occupied_head_next(inst_latch_data.i)  <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    
                                    inst_data_next.addr <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    -- DONE
                                    inst_stage_next  <= IDLE;
                                else
                                    inst_addr_base_next  <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                    inst_cnt_next        <= inst_cnt + 2; -- Skip Next Step
                                end if;
                            else
                                inst_addr_base_next  <= inst_addr_latch;
                                inst_addr_latch_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
                                inst_cnt_next        <= inst_cnt + 1;
                            end if;
                        end if;
                    -- SET Prev Addr (Next Slot)
                    when 5 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_PREV_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_addr_latch,WORD_WIDTH));
                        
                        if (inst_ready_in = '1') then
                            if (inst_addr_latch = INSTANCE_MEMORY_MAX_ADDRESS) then
                                -- Set New Occupied List Head
                                inst_occupied_head_next(inst_latch_data.i)  <= inst_addr_base;
                                
                                inst_data_next.addr <= inst_addr_base;
                                -- DONE
                                inst_stage_next  <= IDLE;
                            else
                                inst_addr_base_next  <= inst_addr_latch;
                                inst_addr_latch_next <= inst_addr_base;
                                inst_cnt_next        <= inst_cnt + 1;
                            end if;
                        end if;
                    -- SET Next Addr (Previous Slot)
                    when 6 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_addr_latch,WORD_WIDTH));
                        
                        if (inst_ready_in = '1') then
                            inst_data_next.addr <= inst_addr_latch;
                            -- DONE
                            inst_stage_next  <= IDLE;
                        end if;
                    when others =>
                        null;
                end case;
            when RESET_MEMORY =>
                case (inst_cnt) is
                    -- SET Next Pointer
                    when 0 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                        if (inst_addr_base = MAX_INSTANCE_ADDRESS(inst_latch_data.i)) 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
                            inst_cnt_next    <= inst_cnt + 1;
                        end if;
                    -- SET Previous Pointer
                    when 1 =>
                        inst_valid_in    <= '1';
                        inst_addr        <= inst_addr_base + IMF_PREV_ADDR_OFFSET;
                        inst_write_data  <= std_logic_vector(resize(inst_addr_latch,WORD_WIDTH));
                        
                        -- Memory Flow Control Guard
                        if (inst_ready_in = '1') then
                            if (inst_addr_base = MAX_INSTANCE_ADDRESS(inst_latch_data.i)) then
                                -- Initialize Empty and Occupied Heads
                                inst_empty_head_next(inst_latch_data.i)     <= FIRST_INSTANCE_ADDRESS;
                                inst_occupied_head_next(inst_latch_data.i)  <= INSTANCE_MEMORY_MAX_ADDRESS;
                                
                                if (inst_latch_data.i = NUM_WRITERS-1) then
                                    -- DONE
                                    inst_stage_next  <= IDLE;
                                else
                                    -- NEXT MEMORY
                                    inst_latch_data_next.i  <= inst_latch_data.i + 1;
                                    inst_addr_base_next     <= FIRST_INSTANCE_ADDRESS;
                                    inst_addr_latch_next    <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    inst_cnt_next           <= 0;
                                end if;
                            else
                                inst_addr_latch_next <= inst_addr_base;
                                inst_addr_base_next  <= inst_addr_base + INSTANCE_FRAME_SIZE;
                                inst_cnt_next        <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
        end case;
    end process;
    
    sync_prc : process(clk)
    begin
        if rising_edge(clk) then
            if (reset = '1') then
                stage                           <= 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         <= (others => HANDLE_NIL);
                key_hash                        <= KEY_HASH_NIL;
                deadline_check_time             <= TIME_ZERO;
                for i in 0 to NUM_WRITERS-1 loop
                    deadline_time(i)    <= time + CONFIG_ARRAY_T(i).DEADLINE_QOS;
                    lease_deadline(i)   <= time + CONFIG_ARRAY_T(i).LEASE_DURATION;
                end loop;
                lifespan_time                   <= TIME_INFINITE;
                source_ts                       <= TIME_INVALID;
                timeout_check_time              <= TIME_INVALID;
                timeout_time                    <= (others => TIME_INVALID);
                lease_check_time                <= TIME_ZERO;
                cc_source_timestamp_sig         <= TIME_INVALID;
                lifespan                        <= DURATION_INFINITE;
                global_seq_nr                   <= (others => 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_INSTANCE_DATA;
                ind                             <= 0;
                cnt                             <= 0;
                cnt2                            <= 0;
                cnt3                            <= 0;
                global_sample_cnt               <= (others => 0);
                global_ack_cnt                  <= (others => 0);
                stale_inst_cnt                  <= (others => 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                        <= (others => '0');
                ack_wait_check                  <= '0';    
                is_ack                          <= '0';
                is_rtps                         <= '0';
                data_available_sig              <= (others => '0');
                orphan_samples                  <= '0';
                newest_sample                   <= (others => SAMPLE_MEMORY_MAX_ADDRESS);
                oldest_sample                   <= (others => SAMPLE_MEMORY_MAX_ADDRESS);
                empty_payload_list_head         <= (others => PAYLOAD_MEMORY_MAX_ADDRESS);
                empty_sample_list_head          <= (others => SAMPLE_MEMORY_MAX_ADDRESS);
                empty_sample_list_tail          <= (others => SAMPLE_MEMORY_MAX_ADDRESS);
                payload_addr_latch_1            <= (others => '0');
                payload_addr_latch_2            <= (others => '0');
                long_latch                      <= (others => '0');
                sample_addr_latch_1             <= SAMPLE_MEMORY_MAX_ADDRESS;
                sample_addr_latch_2             <= (others => '0');
                sample_addr_latch_3             <= FIRST_SAMPLE_ADDRESS;
                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 => (others => '0'));
                deadline_miss_cnt_change        <= (others => (others => '0'));
                liveliness_lost_cnt             <= (others => (others => '0'));
                liveliness_lost_cnt_change      <= (others => (others => '0'));
                status_sig                      <= (others => (others => '0'));
                inst_addr_base                  <= FIRST_INSTANCE_ADDRESS;
                inst_empty_head                 <= (others => INSTANCE_MEMORY_MAX_ADDRESS);
                inst_occupied_head              <= (others => INSTANCE_MEMORY_MAX_ADDRESS);
                inst_addr_latch                 <= INSTANCE_MEMORY_MAX_ADDRESS;
                inst_long_latch                 <= (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_check_time             <= deadline_check_time_next;
                deadline_time                   <= deadline_time_next;
                lifespan_time                   <= lifespan_time_next;
                source_ts                       <= source_ts_next;
                timeout_check_time              <= timeout_check_time_next;
                timeout_time                    <= timeout_time_next;
                lease_check_time                <= lease_check_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;
                inst_latch_data                 <= inst_latch_data_next;
                ind                             <= ind_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;
                ack_wait_check                  <= ack_wait_check_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_addr_latch                 <= inst_addr_latch_next;
                inst_long_latch                 <= inst_long_latch_next;
                return_code_latch               <= return_code_latch_next;
            end if;
        end if;
    end process;
    
end architecture;
