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

entity history_cache is
    generic (
        TIME_BASED_FILTER_QOS       : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS;
        MAX_INSTANCES               : natural       := DEFAULT_MAX_INSTANCES;
        MAX_SAMPLES_PER_INSTANCE    : natural       := DEFAULT_MAX_SAMPLES_PER_INSTANCE;
        HISTORY_QOS                 : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS;
        RELIABILITY_QOS             : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS;
        PRESENTATION_QOS            : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_PRESENTATION_QOS;
        DESTINATION_ORDER_QOS       : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_DESTINATION_ORDER_QOS;
        COHERENT_ACCESS             : boolean := DEFAULT_COHERENT_ACCESS;
        ORDERED_ACCESS              : boolean := DEFAULT_ORDERED_ACCESS;
    );
    port (
        clk             : in std_logic;
        reset           : in std_logic;
        
        start_rtps          : in std_logic;
        opcode_rtps         : in HISTORY_CACHE_OPCODE_TYPE;
        res_rtps            : out HISTORY_CACHE_RESPOSNE_TYPE;
        data_in_rtps        : in std_logic_vector(WORD_WIDTH-1 downto 0);
        valid_in_rtps       : in std_logic;
        ready_in_rtps       : out std_logic;
        last_word_in_rtps   : in std_logic;
        
        --
        start_dds           : in std_logic;
        ack_dds             : out std_logic;
        opcode_dds          : in HISTORY_CACHE_OPCODE_TYPE;
        instance_state_in   : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
        view_state_in       : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
        sample_state_in     : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
        instance_handle_in  : in INSTANCE_HANDLE_TYPE;
        max_samples_in      : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
        next_sample         : in std_logic;
        get_data            : in std_logic;
        done_dds            : out std_logic;
        return_code_dds     : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
        
        -- Sample Info
        si_sample_state                 : out std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
        si_view_state                   : out std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
        si_instance_state               : out std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
        si_source_timestamp             : out TIME_TYPE;
        si_instance_handle              : out INSTANCE_HANDLE_TYPE;
        si_publication_handle           : out PUBLICATION_HANDLE_TYPE;
        si_disposed_generation_count    : out std_logic_vector(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0);
        si_no_writers_generation_count  : out std_logic_vector(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0);
        si_sample_rank                  : out std_logic_vector(SAMPLE_RANK_WIDTH-1 downto 0);
        si_generation_rank              : out std_logic_vector(GENERATION_RANK_WIDTH-1 downto 0);
        si_absolute_generation_count    : out std_logic_vector(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0);
        si_valid_data                   : out std_logic;
        si_valid                        : out std_logic;
        
        ready_out_dds       : in std_logic;
        valid_out_dds       : out std_logic;
        data_out_dds        : out std_logic_vector(WORD_WIDTH-1 downto 0);
        last_word_out_dds   : out std_logic;
        
        status  : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0);
    );
end entity;

architecture arch of history_cache is
    
    --*****CONSTANT DECLARATION*****
    -- Sample Info Memory Size in 4-Byte Words
    constant SAMPLE_MEMORY_SIZE         : natural := TODO;
    -- Sample Info Memory Address Width
    constant SAMPLE_MEMORY_ADDR_WIDTH   : natural := log2c(SAMPLE_MEMORY_SIZE);
    -- Highest Sample Info Memory Address
    constant SAMPLE_MEMORY_MAX_ADDRESS  : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH);
    -- Highest Sample Info Frame Address
    constant MAX_SAMPLE_ADDRESS         : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_INFO_FRAME_SIZE + 1;
    
    -- Payload Memory Size in 4-Byte Words
    constant PAYLOAD_MEMORY_SIZE        : natural := TODO;
    -- Payload Memory Address Width
    constant PAYLOAD_MEMORY_ADDR_WIDTH  : natural := log2c(PAYLOAD_MEMORY_SIZE);
    -- Highest Payload Memory Address
    constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH);
    -- Highest Payload Frame Address
    constant MAX_PAYLOAD_ADDRESS        : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1;
    
    -- Instance Memory Size in 4-Byte Words
    constant INSTANCE_MEMORY_SIZE       : natural := TODO;
    -- Instance Memory Address Width
    constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE);
    -- Highest Instance Memory Address
    constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH);
    -- Highest Instance Frame Address
    constant MAX_INSTANCE_ADDRESS        : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1;
    -- Address pointing to the beginning of the first Instance Data Frame
    constant FIRST_INSTANCE_ADDRESS     : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    
    -- *UPDATE INSTANCE FLAG POSITIONS*
    constant UPDATE_INSTANCE_FLAG_WIDTH : natural := 6;
    constant STATUS_FLAG                : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (0 => 1, others => '0');
    constant SAMPLE_CNT_FLAG            : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (1 => 1, others => '0');
    constant DISPOSED_CNT_FLAG          : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (2 => 1, others => '0');
    constant NO_WRITERS_CNT_FLAG        : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (3 => 1, others => '0');
    constant IGNORE_DEADLINE_FLAG       : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (4 => 1, others => '0');
    constant WRITER_BITMAP_FLAG         : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (5 => 1, others => '0');
    
    -- *SAMPLE MEMORY FRAME FORMAT*
    constant SMF_STATUS_INFO_OFFSET         : natural := 0;
    constant SMF_TIMESTAMP_OFFSET           : natural := 1;
    constant SMF_LIFESPAN_DEADLINE_OFFSET   : natural := 3;
    constant SMF_PAYLOAD_ADDR_OFFSET        : natural := 5;
    constant SMF_INSTANCE_ADDR_OFFSET       : natural := 6;
    constant SMF_DISPOSED_GEN_CNT_OFFSET    : natural := 7;
    constant SMF_NO_WRITERS_GEN_CNT_OFFSET  : natural := 8;
    constant SMF_PREV_ADDR_OFFSET           : natural := SMF_NO_WRITERS_GEN_CNT_OFFSET+1;
    constant SMF_NEXT_ADDR_OFFSET           : natural := SMF_PREV_ADDR_OFFSET+1;
    -- *PAYLOAD MEMORY FRAME FORMAT*
    constant PMF_NEXT_ADDR_OFFSET   : natural := 0;
    constant PMF_PAYLOAD_OFFSET     : natural := 1;
    -- *INSTANCE MEMORY FRAME OFFSET*
    constant IMF_NEXT_ADDR_OFFSET           : natural := 0;
    constant IMF_KEY_HASH_OFFSET            : natural := 1;
    constant IMF_STATUS_INFO_OFFSET         : natural := 5;
    constant IMF_SAMPLE_CNT_OFFSET          : natural := 6;
    constant IMF_DISPOSED_GEN_CNT_OFFSET    : natural := IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_OFFSET+1;
    constant IMF_NO_WRITERS_GEN_CNT_OFFSET  : natural := IMF_DISPOSED_GEN_CNT_OFFSET+1;
    constant IMF_IGNORE_DEADLINE_OFFSET     : natural := IMF_NO_WRITERS_GEN_CNT_OFFSET+1;
    constant IMF_WRITER_BITMAP_OFFSET       : natural := IMF_IGNORE_DEADLINE_OFFSET+2 when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else IMF_NO_WRITERS_GEN_CNT_OFFSET+1;
    
    --*****TYPE DECLARATION*****
    -- FSM states. Explained below in detail
    type STAGE_TYPE is (IDLE, TODO);
    type INST_STAGE_TYPE is (IDLE, TODO);
    type INSTANCE_OPCODE_TYPE is (NOP, TODO);
    type INSTANCE_DATA_TYPE is record
        key_hash            : KEY_HASH_TYPE;
        status_info         : std_logic_vector(WORD_WIDTH-1 downto 0);
        sample_cnt          : unsigned(WORD_WIDTH-1 downto 0);
        disposed_gen_cnt    : unsigned(WORD_WIDTH-1 downto 0);
        no_writers_gen_cnt  : unsigned(WORD_WIDTH-1 downto 0);
        ignore_deadline     : TIME_TYPE;
        writer_bitmap       : ENDPOINT_BITMAP_ARRAY_TYPE;
    end record;
    constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := (
        key_hash            => (others => (others => '0')),
        status_info         => (others => '0'),
        sample_cnt          => (others => '0'),
        disposed_gen_cnt    => (others => '0'),
        no_writers_gen_cnt  => (others => '0'),
        ignore_deadline     => TIME_INVALID,
        writer_bitmap       => (others => (others => '0'))
    );
    type INST_LATCH_DATA_TYPE is record
        variant         : std_logic;
        key_hash        : KEY_HASH_TYPE;
        status_info     : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        sample_cnt      : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        gen_cnt         : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
        deadline        : TIME_TYPE;
        writer_bitmap   : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1);
        update_flags    : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1);
        addr            : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
    end record;
    constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := (
        variant         => '1',
        key_hash        => (others => (others => '0')),
        status_info     => (others => '0'),
        sample_cnt      => (others => '0'),
        gen_cnt         => (others => '0'),
        deadline        => TIME_INVALID,
        writer_bitmap   => (others => (others => '0')),
        update_flags    => (others => '0'),
        addr            => (others => '0')
    );
    
    --*****SIGNAL DECLARATION
    signal sample_addr, sample_addr_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_wen, sample_ren : std_logic := '0';
    signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    
    signal payload_addr, payload_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal payload_wen, payload_ren : std_logic := '0';
    signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    
    signal inst_addr, inst_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_wen, inst_ren : std_logic := '0';
    signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    
    signal khg_valid_in, khg_ready_in, khg_last_word_in, khg_valid_out, khg_ready_out, khg_last_word_out : std_logic := '0';
    signal khg_data_in, khg_data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
    
    signal stage, stage_next : STAGE_TYPE := IDLE;
    signal cnt, cnt_next : natural range TODO := 0;
    signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal first_unread_sample, first_unread_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID;
    signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID;
    signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal payload_mem_full, payload_mem_full_next : std_logic := '0';
    signal sample_mem_full, sample_mem_full_next : std_logic := '0';
    signal writer_pos, writer_pos_next : natural range TODO := 0;
    signal writer_bitmap : ENDPOINT_BITMAP_ARRAY_TYPE;
    signal status_info_update : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal key_hash, key_hash_next  : KEY_HASH_TYPE := (others => (others => '0'));
    signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0';
    signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0';
    signal added_new_instance, added_new_instance_next : std_logic := '0';
    signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal gen_cnt  : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal deadline : TIME_TYPE := TIME_INVALID;
    signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    
    signal inst_op_start : std_logic := '0';
    signal inst_op_done : std_logic := '0';
    signal inst_opcode  : INSTANCE_OPCODE_TYPE := NOP;
    signal inst_stage, inst_stage_next  : INST_STAGE_TYPE := IDLE;
    signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_occupied_head, inst_occupied_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA;
    signal update_inst_flags : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0');
    signal inst_cnt, inst_cnt_next : natural range TODO := 0;
    signal inst_mem_full, inst_mem_full_next : std_logic := '0';
    signal inst_delete_lock, inst_delete_lock_next : std_logic := '0';
    signal inst_atomic_lock : std_logic := '0';
    signal inst_long_latch_1, inst_long_latch_1_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    signal inst_long_latch_2, inst_long_latch_2_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
    
    signal si_sample_state_sig, si_sample_state_sig_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal si_view_state_sig, si_view_state_sig_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal si_instance_state_sig, si_instance_state_sig_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal si_source_timestamp_sig, si_source_timestamp_sig_next : TIME_TYPE := TIME_INVALID;
    signal si_instance_handle_sig, si_instance_handle_sig_next : INSTANCE_HANDLE_TYPE := (others => (others => '0'));
    signal si_publication_handle_sig, si_publication_handle_sig_next :  PUBLICATION_HANDLE_TYPE := (others => (others => '0'));
    signal si_disposed_generation_count_sig, si_disposed_generation_count_sig_next : unsigned(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal si_no_writers_generation_count_sig, si_no_writers_generation_count_sig_next : unsigned(NO_WRITERS_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal si_sample_rank_sig, si_sample_rank_sig_next : unsigned(SAMPLE_RANK_WIDTH-1 downto 0) := (others => '0');
    signal si_generation_rank_sig, si_generation_rank_sig_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0');
    signal si_absolute_generation_count_sig, si_absolute_generation_count_sig_next : unsigned(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0');
    signal si_valid_data_sig, si_valid_data_sig_next : std_logic := '0';
    signal si_valid_sig, si_valid_sig_next : std_logic := '0';
    
    signal sample_state, sample_state_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal view_state, view_state_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal instance_state, instance_state_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
    signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE := (others => '0');
    signal max_samples, max_samples_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
    signal inst_addr_latch, inst_addr_latch_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
    signal collection_cnt, collection_cnt_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
    signal collection_cnt_max, collection_cnt_max_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
    signal collection_generation_rank, collection_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0');
    signal cur_generation_rank, cur_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0');
    signal is_take, is_take_next : std_logic := '0';
    signal has_latched,  has_lacthed_next : std_logic := '0';
    signal single_instance, single_instance_next : std_logic := '0';
    -- NOTE: We use this signal to prevent the costly Instance Marking in the case that we only need to ouptput next sample.
    --       I.e. make READ_NEXT/TAKE_NEXT the fastest commands.
    signal single_sample, single_sample_next : std_logic := '0';
    signal unmark_instances, unmark_instances_next : std_logic := '0';
    signal dynamic_next_instance, dynamic_next_instance_next : std_logic := '0';
    signal inst_data_variant : std_logic := '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 first_sample      : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1;
    alias first_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 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_1;
    alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_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 has_data          : std_logic is sample_status_info(PAYLOAD_FLAG);
    alias has_key_hash      : std_logic is sample_status_info(KEY_HASH_FLAG);
    
    -- *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) := input(i);
        end loop;
        return ret;
    end function;
    
begin
    
    sample_ram_inst : entity work.single_port_ram(arch)
        generic map (
            ADDR_WIDTH      => SAMPLE_MEMORY_ADDR_WIDTH,
            DATA_WIDTH      => WORD_WIDTH,
            MEMORY_DEPTH    => SAMPLE_MEMORY_SIZE
        )
        port map (
            clk     => clk,
            addr    => sample_addr,
            wen     => sample_wen,
            ren     => sample_ren,
            wr_data => sample_write_data,
            rd_data => sample_read_data
        );
    
    payload_ram_inst : entity work.single_port_ram(arch)
        generic map (
            ADDR_WIDTH      => PAYLOAD_MEMORY_ADDR_WIDTH,
            DATA_WIDTH      => WORD_WIDTH,
            MEMORY_DEPTH    => PAYLOAD_MEMORY_SIZE
        )
        port map (
            clk     => clk,
            addr    => payload_addr,
            wen     => payload_wen,
            ren     => payload_ren,
            wr_data => payload_write_data,
            rd_data => payload_read_data
        );
        
    instance_ram_inst : entity work.single_port_ram(arch)
        generic map (
            ADDR_WIDTH      => INSTANCE_MEMORY_ADDR_WIDTH,
            DATA_WIDTH      => WORD_WIDTH,
            MEMORY_DEPTH    => INSTANCE_MEMORY_SIZE
        )
        port map (
            clk     => clk,
            addr    => inst_addr,
            wen     => inst_wen,
            ren     => inst_ren,
            wr_data => inst_write_data,
            rd_data => inst_read_data
        );
        
    key_hash_generator_inst : entity work.key_hash_generator(arch)
        port (
            clk             => clk,
            reset           => reset,
            data_in         => khg_data_in,
            valid_in        => khg_valid_in,
            ready_in        => khg_ready_in,
            last_word_in    => khg_last_word_in,
            data_out        => khg_data_out,
            valid_out       => khg_valid_out,
            ready_out       => khg_ready_out,
            last_word_out   => khg_last_word_out
        );
    
    parse_a_prc : process (all)
        variable tmp_dw     : DOUBLE_WORD_ARRAY := (others => (others => '0'));
        variable tmp_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0');
        variable tmp_update : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0');
        variable tmp_bool   : boolean := FALSE;    
    begin
        -- Default
        stage_next                      <= stage;
        res_rtps                           <= UNDEFINED;
        sample_addr_next                <= sample_addr;
        sample_write_data               <= (others => '0');
        sample_ren                      <= '0';
        sample_wen                      <= '0';
        payload_addr_next               <= payload_addr;
        payload_write_data              <= (others => '0');
        payload_ren                     <= '0';
        payload_wen                     <= '0';
        ready_in_rtps                      <= '0';
        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;
        ts_latch_next                   <= ts_latch;
        long_latch_next                 <= long_latch;
        sample_addr_latch_1_next        <= sample_addr_latch_1;
        sample_addr_latch_2_next        <= sample_addr_latch_2;
        payload_mem_full_next           <= payload_mem_full;
        sample_mem_full_next            <= sample_mem_full;
        writer_pos_next                 <= writer_pos;
        inst_opcode                     <= NOP;
        key_hash_next                   <= key_hash;
        sample_status_info_next         <= sample_status_info;
        inst_op_start                   <= '0';
        khg_last_word_in                <= '0';
        khg_data_in                     <= (others => '0');
        khg_valid_in                    <= '0';
        khg_ready_out                   <= '0';
        writer_bitmap                   <= (others => '0');
        inst_addr_update                <= (others => '0');
        remove_oldest_sample_next       <= remove_oldest_sample;
        remove_oldest_inst_sample_next  <= remove_oldest_inst_sample;
        added_new_instance_next         <= added_new_instance;
        si_sample_state_sig_next        <= si_sample_state;
        si_view_state_sig_next          <= si_view_state_sig;
        si_instance_state_sig_next      <= si_instance_state_sig;
        si_source_timestamp_sig_next    <= si_source_timestamp_sig;    
        si_instance_handle_sig_next     <= si_instance_handle_sig;
        si_publication_handle_sig_next  <= si_publication_handle_sig;
        si_disposed_generation_count_sig_next   <= si_disposed_generation_count_sig;
        si_no_writers_generation_count_sig_next <= si_no_writers_generation_count_sig;
        si_sample_rank_sig_next         <= si_sample_rank_sig;
        si_generation_rank_sig_next     <= si_generation_rank_sig;
        si_absolute_generation_count_sig_next   <= si_absolute_generation_count_sig;
        si_valid_data_sig_next          <= si_valid_data_sig;
        si_valid_sig_next               <= si_valid_sig_next;
        sample_state_next               <= sample_state;
        view_state_next                 <= view_state;
        instance_state_next             <= instance_state;
        instance_handle_next            <= instance_handle;
        max_samples_next                <= max_samples;
        inst_addr_latch_1_next          <= inst_addr_latch_1;
        inst_addr_latch_2_next          <= inst_addr_latch_2;
        collection_cnt_next             <= collection_cnt;
        collection_cnt_max_next         <= collection_cnt_max;
        collection_generation_rank_next <= collection_generation_rank;
        cur_generation_rank_next        <= cur_generation_rank;
        is_take_next                    <= is_take;
        has_lacthed_next                <= has_latched;
        single_instance_next            <= single_instance;
        single_sample_next              <= single_sample;
        unmark_instances_next           <= unmark_instances;
        is_first_instance_sample_next   <= is_first_instance_sample;
        dynamic_next_instance_next      <= dynamic_next_instance;
        last_read_ts_next               <= last_read_ts;
        ack_dds                         <= '0';
        inst_data_variant               <= '0';
        done_dds                        <= '0';
        return_code_dds                 <= RETCODE_UNSUPPORTED;
        
        case (stage) is
            when IDLE =>
                -- DEFAULT
                ready_in_rtps                   <= '1';
                
                -- Reset
                remove_oldest_inst_sample_next  <= '0';
                remove_oldest_sample_next       <= '0';
                added_new_instance_next         <= '0';
                is_take_next                    <= '0';
                
                
                if (start_rtps = '1') then
                    case (opcode_rtps) is
                        when ADD_CHANGE =>
                            -- This Operation does not accept input at this time
                            ready_in_rtps       <= '0';
                            
                            res_rtps            <= ACK;
                            stage_next          <= ADD_SAMPLE_INFO;
                            cur_sample_next     <= empty_sample_list_head;
                            sample_addr_next    <= empty_sample_list_head;
                            cnt_next            <= 0;
                            end if;
                        when REMOVE_WRITER =>
                            -- Input and Memory Gurad
                            if (valid_in_rtps = '1' and inst_op_done = '1') then
                                -- Latch Writer Pos
                                writer_pos_next     <= to_integer(unsigned(data_in_rtps));
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_FIRST_INSTANCE;
                                inst_data_variant   <= '0';
                                stage_next          <= REMOVE_WRITER;
                                res_rtps            <= ACK;
                            end if;
                        when others =>
                            null;
                    end case;
                elsif (unmark_instances = '1') then
                    -- Memory Operation Guard
                    if (inst_op_done = '1') then
                        inst_op_start   <= '1';
                        inst_opcode     <= UNMARK_INTANCES;
                        unmark_instances_next   <= '0';
                    end if;
                elsif (start_dds = '1') then
                    -- Latch Input Signals
                    sample_state_next       <= sample_state_in;
                    view_state_next         <= view_state_in;
                    instance_state_next     <= instance_state;
                    max_samples_next        <= unsigned(max_samples_in);
                    
                    -- Reset
                    single_instance_next            <= '0';
                    single_instance_next            <= '0';
                    collection_cnt_next             <= 0;
                    collection_cnt_max_next         <= 0;
                    is_first_instance_sample_next   <= '1';
                    si_sample_state_sig_next        <= (others => '0');
                    si_view_state_sig_next          <= (others => '0');
                    si_instance_state_sig_next      <= (others => '0');
                    si_source_timestamp_sig_next    <= TIME_ZERO;
                    si_instance_handle_sig_next     <= (others => (others => '0'));
                    si_publication_handle_sig_next  <= (others => (others => '0'));
                    si_sample_rank_sig_next         <= (others => '0');
                    si_generation_rank_sig_next     <= (others => '0');
                    si_valid_data_sig_next          <= '0';
                    si_valid_sig_next               <= '0';
                    si_absolute_generation_count_sig_next   <= (others => '0');
                    si_disposed_generation_count_sig_next   <= (others => '0');
                    si_no_writers_generation_count_sig_next <= (others => '0');
                    
                    case (opcode_dds) is
                        when READ =>
                            ack_dds             <= '1';
                            cur_sample_next     <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            cur_inst_next       <= INSTANCE_MEMORY_MAX_ADDRESS;
                            stage_next          <= GET_NEXT_SAMPLE;
                            cnt_next            <= 0;
                        when TAKE =>
                            is_take_next        <= '1';
                            ack_dds             <= '1';
                            cur_sample_next     <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            cur_inst_next       <= INSTANCE_MEMORY_MAX_ADDRESS;
                            stage_next          <= GET_NEXT_SAMPLE;
                            cnt_next            <= 0;
                        when READ_NEXT_SAMPLE =>
                            ack_dds             <= '1';
                            single_sample_next  <= '1';
                            cur_sample_next     <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            cur_inst_next       <= INSTANCE_MEMORY_MAX_ADDRESS;
                            sample_state_next   <= NOT_READ_SAMPLE_STATE;
                            view_state_next     <= ANY_VIEW_STATE;
                            instance_state_next <= ALIVE_INSTANCE_STATE;
                            max_samples_next    <= to_unsigned(1, max_samples'length);
                            stage_next          <= GET_NEXT_SAMPLE;
                            cnt_next            <= 0;
                        when TAKE_NEXT_SAMPLE =>
                            ack_dds             <= '1';
                            is_take_next        <= '1';
                            single_sample_next  <= '1';
                            cur_sample_next     <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            cur_inst_next       <= INSTANCE_MEMORY_MAX_ADDRESS;
                            sample_state_next   <= NOT_READ_SAMPLE_STATE;
                            view_state_next     <= ANY_VIEW_STATE;
                            instance_state_next <= ALIVE_INSTANCE_STATE;
                            max_samples_next    <= to_unsigned(1, max_samples'length);
                            stage_next          <= GET_NEXT_SAMPLE;
                            cnt_next            <= 0;
                        when READ_INSTANCE =>
                            ack_dds                 <= '1';
                            single_instance_next    <= '1';
                            cur_sample_next         <= oldest_sample;
                            sample_addr_next        <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            key_hash_next           <= instance_handle_in;
                            stage_next              <= CHECK_INSTANCE;
                            cnt_next                <= 0;
                        when TAKE_INSTANCE =>
                            ack_dds                 <= '1';
                            is_take_next            <= '1';
                            single_instance_next    <= '1';
                            cur_sample_next         <= oldest_sample;
                            sample_addr_next        <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            key_hash_next           <= instance_handle_in;
                            stage_next              <= CHECK_INSTANCE;
                            cnt_next                <= 0;
                        when READ_NEXT_INSTANCE =>
                            ack_dds                     <= '1';
                            single_instance_next        <= '1';
                            dynamic_next_instance_next  <= '1';
                            cur_sample_next             <= oldest_sample;
                            sample_addr_next            <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            key_hash_next               <= instance_handle_in;
                            stage_next                  <= FIND_NEXT_INSTANCE;
                            cnt_next                    <= 0;
                        when TAKE_NEXT_INSTANCE =>
                            ack_dds                     <= '1';
                            is_take_next                <= '1';
                            single_instance_next        <= '1';
                            dynamic_next_instance_next  <= '1';
                            cur_sample_next             <= oldest_sample;
                            sample_addr_next            <= oldest_sample + SMF_STATUS_INFO_OFFSET;
                            key_hash_next               <= instance_handle_in;
                            stage_next                  <= FIND_NEXT_INSTANCE;
                            cnt_next                    <= 0;
                        when others =>
                            ack_dds     <= '1';
                            stage_next  <= UNKNOWN_OPERATION;
                    end case;
                end if;
            when UNKNOWN_OPERATION =>
                done_dds        <= '1';
                return_code_dds <= RETCODE_UNSUPPORTED;
                
                -- DONE
                stage_next  <= IDLE;
            when ADD_SAMPLE_INFO =>
                -- Precondition: sample_addr (empty_sample_list_head)
                
                ready_in_rtps  <= '1';
                
                -- Input Guard
                if (valid_in_rtps = '1') then
                    cnt_next          <= cnt + 1;
                    sample_addr_next  <= sample_addr + 1;
                    
                    -- Write Through
                    sample_wen        <= '1';
                    sample_write_data <= data_in_rtps;
                    
                    case (cnt) is
                        -- Status Info
                        when 0 =>
                            -- Initialize local status bits
                            sample_write_data(READ_FLAG)        <= '0';
                            -- Latch Status Info
                            sample_status_info_next             <= data_in_rtps;
                            sample_status_info_next(READ_FLAG)  <= '0';
                        -- Latch Timestamp for ordering
                        -- Timestamp 1/2
                        when 1 =>
                            ts_latch_next(0)    <= data_in_rtps;
                        -- Timestamp 2/2
                        when 2 =>
                            ts_latch_next(1)    <= data_in_rtps;
                            
                            -- Synthesis Guard
                            if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                                -- Check Timestamp
                                tmp_dw  := (0 => ts_latch(0), 1 => unsigned(data_in_rtps));
                                
                                -- NOTE: Equal timestamps are still acceptable, as they are inserted after the
                                --       highest last read sample.
                                
                                -- Timestamp is smaller than highest last read (Or is Invalid)
                                if (tmp_dw /= TIME_INVALID or tmp_dw < last_read_ts) then
                                    -- Drop Sample
                                    stage_next  <= SKIP_ADD_DROP;
                                end if;
                            end if;
                        
                        -- Lifespan Deadline 2/2
                        when 4 =>
                            -- Skip Key Hash, if not available
                            if (has_key_hash = '0') then
                                cnt_next  <= 9;
                            end if;
                        -- Latch Key Hash
                        -- Key Hash 1/4
                        when 5 =>
                            -- Latch Input, but do not pass to Memory
                            sample_wen          <= '0';
                            sample_addr_next    <= sample_addr; -- Keep Addr (Payload Addr)
                            key_hash_next(0)    <= data_in_rtps;
                        -- Key Hash 2/4
                        when 6 =>
                            -- Latch Input, but do not pass to Memory
                            sample_wen          <= '0';
                            sample_addr_next    <= sample_addr; -- Keep Addr (Payload Addr)
                            key_hash_next(1)    <= data_in_rtps;
                        -- Key Hash 3/4
                        when 7 =>
                            -- Latch Input, but do not pass to Memory
                            sample_wen          <= '0';
                            sample_addr_next    <= sample_addr; -- Keep Addr (Payload Addr)
                            key_hash_next(2)    <= data_in_rtps;
                        -- Key Hash 4/4
                        when 8 =>
                            -- Latch Input, but do not pass to Memory
                            sample_wen          <= '0';
                            sample_addr_next    <= sample_addr; -- Keep Addr (Payload Addr)
                            key_hash_next(3)    <= data_in_rtps; 
                        -- Writer Endpoint Position
                        when 9 =>
                            -- Latch Input, but do not pass to Memory
                            writer_pos_next     <= to_integer(unsigned(data_in_rtps));
                            sample_wen          <= '0';
                            sample_addr_next    <= sample_addr; -- Keep Addr (Payload Addr)
                            stage_next          <= ADD_PAYLOAD_ADDRESS;
                        when others =>
                            null;
                    end case;
                end if;
            when ADD_PAYLOAD_ADDRESS =>
                -- Precondition: sample_addr (Payload Address)
                
                sample_addr_next  <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                
                if (has_data = '1') then
                    -- Store Payload Address
                    sample_wen          <= '1';
                    sample_write_data   <= empty_payload_list_head;
                    
                    payload_addr_next   <= empty_payload_list_head + PMF_NEXT_ADDR_OFFSET;
                    cur_payload_next    <= empty_payload_list_head;
                else
                    -- Mark Sample with no Payload
                    sample_wen        <= '1';
                    sample_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS;
                end if;
                
                -- If Key Hash is available, start the Instance Search first
                if (has_key_hash = '1') then
                    stage_next    <= INITIATE_INSTANCE_SEARCH;
                else
                    stage_next    <= ADD_PAYLOAD;
                    cnt_next      <= 0;
                end if;
            when ADD_PAYLOAD =>
                -- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr (Beginning of Payload Data of cur_payload)
                
                -- NOTE: This state is responsible for reading the payload and writing it through to the local payload memory
                --       and key hash generator (KHG). This state is taken on following cases:
                -- has_data     has_key_hash
                --    1              1          The payload is written to memory
                --    1              0          The payload is written to memory and the KHG at the same time (KHG controls the flow)
                --    0              0          There is no payload to write, but the input contains the key for the KHG
                
                if (has_key_hash = '0') then
                    ready_in_rtps  <= khg_ready_in;
                else
                    ready_in_rtps  <= '1';
                end if;
                
                -- Flow Control Guard
                if ((valid_in_rtps = '1' and has_key_hash = '0') or (valid_in_rtps = '1' and has_key_hash = '0' and khg_ready_in = '1')) then
                    cnt_next          <= cnt + 1;
                    payload_addr_next <= payload_addr + PMF_NEXT_ADDR_OFFSET;
                    
                    -- Payload Write
                    if (has_data = '1') then
                        payload_write_data    <= data_in_rtps;
                        payload_wen           <= '1';
                    end if;
                    
                    -- Key Hash Generator Write
                    if (has_key_hash = '0') then
                        khg_data_in     <= data_in_rtps;
                        khg_valid_in    <= '1';
                    end if;
                    
                    -- End of Payload
                    if (last_word_in_rtps = '1') then
                        if (has_key_hash = '0') then
                            khg_last_word_in    <= '1';
                            stage_next          <= GET_KEY_HASH;
                            cnt_next            <= 0;
                        else
                            stage_next          <= FILTER_STAGE;
                        end if;
                    -- End of Payload Slot
                    elsif (has_data = '1' and cnt = PAYLOAD_FRAME_SIZE-2) then
                        stage_next        <= NEXT_PAYLOAD_SLOT;
                        payload_addr_next <= cur_payload;
                        cnt_next          <= 0;
                    end if;
                end if;
            when NEXT_PAYLOAD_SLOT =>
                -- Precondition: payload_addr (Beginning of current Slot)
                
                cnt_next  <= cnt + 1;
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        payload_ren   <= '1';
                    when 1 =>
                        -- No Empty Payload Slots available
                        if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
                            -- Reject Change
                            stage_next  <= SKIP_ADD_REJECT;
                        else
                            -- Latch next Payload Slot and Continue
                            cur_payload_next    <= payload_read_data;
                            payload_addr_next   <= payload_read_data + PMF_NEXT_ADDR_OFFSET;
                            stage_next          <= ADD_PAYLOAD;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_KEY_HASH =>
                
                khg_ready_out   <= '1';
                
                if (khg_valid_out = '1') then
                    cnt_next          <= cnt + 1;
                    
                    -- Latch Key Hash
                    key_hash_next(cnt)    <= khg_data_out;
                    
                    -- Exit Condition
                    if (khg_last_word_out = '1') then
                        -- DONE
                        stage_next    <= INITIATE_INSTANCE_SEARCH;
                    end if;
                end if;
            when INITIATE_INSTANCE_SEARCH =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    inst_opcode         <= SEARCH_INSTANCE_HASH;
                    inst_op_start       <= '1';
                    inst_data_variant   <= '0';
                    
                    -- Payload not yet stored
                    if (has_data = '1') then
                        stage_next    <= ADD_PAYLOAD;
                        cnt_next      <= 0;
                    else
                        stage_next    <= FILTER_STAGE;
                    end if;
                end if;
            when FILTER_STAGE =>
                -- Precondition: sample_addr (Instance Address of New Sample)
                
                -- Wait for Instance Search to finish
                if (inst_op_done = '1') then
                    sample_addr_next    <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
                    cur_inst_next       <= inst_addr_base;
                    
                    -- Instance Found
                    if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
                        -- Store Instance Address
                        sample_write_data <= inst_addr_base;
                        sample_wen        <= '1';
                        
                        -- TIME_BASED_FILTER QOS
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then
                            -- Drop Change
                            res_rtps    <= ACCEPTED;
                            stage_next  <= IDLE;
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
                        elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then
                            if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                               -- Reject Change
                                res_rtps    <= REJECTED;
                                stage_next  <= IDLE;
                            else
                                -- Accept Change (Remove Oldest Instance Sample)
                                remove_oldest_inst_sample_next  <= '1';
                                res_rtps    <= ACCEPTED;
                                stage_next  <= UPDATE_INSTANCE;
                            end if;
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                        elsif (empty_sample_list_head = empty_sample_list_tail) then
                            if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                               -- Reject Change
                                res_rtps    <= REJECTED;
                                stage_next  <= IDLE;
                            else
                                -- Accept Change (Remove Oldest Sample)
                                remove_oldest_sample_next   <= '1';
                                res_rtps       <= ACCEPTED;
                                stage_next  <= UPDATE_INSTANCE;
                            end if;
                        else
                            -- Accept Change
                            res_rtps       <= ACCEPTED;
                            stage_next  <= UPDATE_INSTANCE;
                        end if;
                    else
                        -- Store Instance Address
                        sample_write_data <= inst_empty_head;
                        sample_wen        <= '1';
                        
                        -- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
                        if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- Reject Change
                            res_rtps       <= REJECTED;
                            stage_next  <= IDLE;
                        -- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
                        elsif (empty_sample_list_head = empty_sample_list_tail) then
                            if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
                               -- Reject Change
                                res_rtps       <= REJECTED;
                                stage_next  <= IDLE;
                            else
                                -- Accept Change (Remove Oldest Sample)
                                remove_oldest_sample_next   <= '1';
                                res_rtps       <= ACCEPTED;
                                
                                -- Only Insert Sample/Instance if Instance is ALIVE
                                if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then
                                    -- Insert New Instance
                                    inst_opcode     <= INSERT_INSTANCE;
                                    inst_op_start   <= '1';
                                    
                                    added_new_instance_next <= '1';
                                    
                                    if (has_data = '1') then
                                        payload_addr_next   <= cur_payload;
                                        stage_next          <= FINALIZE_PAYLOAD;
                                        cnt_next            <= 0;
                                    else
                                        stage_next          <= PRE_SAMPLE_FINALIZE;
                                        cnt_next            <= 0;
                                    end if;
                                else
                                    -- Drop Change
                                    stage_next    <= IDLE;
                                end if;
                            end if;
                        else
                            -- Accept Change
                            res_rtps   <= ACCEPTED;
                            
                            -- Only Insert Sample/Instance if Instance is ALIVE
                            if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then
                                -- Insert New Instance
                                inst_opcode     <= INSERT_INSTANCE;
                                inst_op_start   <= '1';
                                
                                if (has_data = '1') then
                                    payload_addr_next <= cur_payload;
                                    stage_next        <= FINALIZE_PAYLOAD;
                                    cnt_next          <= 0;
                                else
                                    stage_next        <= PRE_SAMPLE_FINALIZE;
                                    cnt_next          <= 0;
                                end if;
                            else
                                -- Drop Change
                                stage_next    <= IDLE;
                            end if;
                        end if;
                    end if;
                end if;
            when UPDATE_INSTANCE =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    -- DEFAULT
                    tmp_update  := (others => '0');
                    
                    -- Instance DISPOSED
                    if (sample_status_info(DISPOSED_FLAG) = '1') then
                        -- ALIVE -> NOT_ALIVE_DISPOSED Transition
                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1') then
                            -- STATUS INFO
                            tmp_update      <= tmp_update or STATUS_FLAG;
                            status_info_update                               <= inst_data.status;
                            status_info_update(NOT_ALIVE_DISPOSED_FLAG)      <= '1';
                            status_info_update(NOT_ALIVE_NO_WRITERS_FLAG)    <= '0';
                            status_info_update(LIVELINESS_FLAG)              <= '1';
                        end if;
                        -- WRITER BITMAP
                        -- Convert Writer Bitmap to SLV
                        tmp_bitmap              := to_endpoint_bitmap(inst_data.writer_bitmap);
                        -- Remove Writer
                        tmp_bitmap(writer_pos)  := '0';
                        -- Convert Back
                        writer_bitmap           <= from_endpoint_bitmap(tmp_bitmap);
                        tmp_update              := tmp_update or WRITER_BITMAP_FLAG;
                    -- Instance UNREGISTERED
                    elsif (sample_status_info(UNREGISTERED_FLAG) = '1') then
                        -- WRITER BITMAP
                        -- Convert Writer Bitmap to SLV
                        tmp_bitmap              := to_endpoint_bitmap(inst_data.writer_bitmap);
                        -- Remove Writer
                        tmp_bitmap(writer_pos)  := '0';
                        -- Convert Back
                        writer_bitmap           <= from_endpoint_bitmap(tmp_bitmap);
                        tmp_update              := tmp_update or WRITER_BITMAP_FLAG;
                        
                        -- ALIVE -> NOT_ALIVE_NO_WRITERS Transition
                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and tmp_bitmap = (tmp_bitmap => '0')) then
                            -- STATUS INFO
                            tmp_update          <= tmp_update or STATUS_FLAG;
                            status_info_update                               <= inst_data.status;
                            status_info_update(NOT_ALIVE_DISPOSED_FLAG)      <= '0';
                            status_info_update(NOT_ALIVE_NO_WRITERS_FLAG)    <= '1';
                            status_info_update(LIVELINESS_FLAG)              <= '1';
                        end if;
                    -- Instance ALIVE/FILTERED
                    else
                        -- STATUS INFO
                        tmp_update      <= tmp_update or STATUS_FLAG;
                        status_info_update                               <= inst_data.status;
                        status_info_update(NOT_ALIVE_DISPOSED_FLAG)      <= '0';
                        status_info_update(NOT_ALIVE_NO_WRITERS_FLAG)    <= '0';
                        status_info_update(LIVELINESS_FLAG)              <= '1';
                        
                        
                        -- GENERATION COUNTERS
                        -- NOT_ALIVE_DISPOSED -> ALIVE Transition
                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then
                            tmp_update  := tmp_update or DISPOSED_CNT_FLAG;
                            gen_cnt     <= inst_data.disposed_gen_cnt + 1;
                        -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition
                        elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                            tmp_update := tmp_update or NO_WRITERS_CNT_FLAG;
                            gen_cnt     <= inst_data.no_writers_gen_cnt + 1;
                        end if;
                        
                        -- WRITER BITMAP
                        -- Convert Writer Bitmap to SLV
                        tmp_bitmap              := to_endpoint_bitmap(inst_data.writer_bitmap);
                        -- Write if Writer New for Instance
                        if (tmp_bitmap(writer_pos) /= '1') then
                            -- Remove Writer
                            tmp_bitmap(writer_pos)  := '0';
                            -- Convert Back
                            writer_bitmap           <= from_endpoint_bitmap(tmp_bitmap);
                            tmp_update              := tmp_update or WRITER_BITMAP_FLAG;
                        end if;
                    end if;
                    
                    -- INSTANCE SAMPLE COUNT
                    -- NOTE: Ignored when remove_oldest_inst_sample, since it will be decremented again. (Stays same)
                    if (remove_oldest_inst_sample = '0') then
                        tmp_update := tmp_update or SAMPLE_CNT_FLAG;
                    end if;
                    -- IGNORE DEADLINE
                    if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
                        tmp_update := tmp_update or IGNORE_DEADLINE_FLAG;
                        deadline    <= time + TIME_BASED_FILTER_QOS;
                    end if;
                    
                    inst_opcode         <= UPDATE_INSTANCE;
                    inst_op_start       <= '1';
                    update_inst_flags   <= tmp_update;
                    
                    if (has_data = '1') then
                        payload_addr_next   <= cur_payload;
                        stage_next          <= FINALIZE_PAYLOAD;
                        cnt_next            <= 0;
                    else
                        stage_next          <= PRE_SAMPLE_FINALIZE;
                        cnt_next            <= 0;
                    end if;
                end if;
            when FINALIZE_PAYLOAD =>
                -- Precondition: payload_addr (Beginning of Last Added Payload Slot)
            
                cnt_next  <= cnt + 1;
                
                case (cnt) is 
                    -- Preload
                    when 0 =>
                        payload_ren   <= '1';
                    when 1 =>
                        -- Fix New Empty List Head
                        empty_payload_list_head_next    <= payload_read_data;
                        
                        -- Make current Slot the Tail
                        payload_write_data  <= PAYLOAD_MEMORY_MAX_ADDRESS;
                        payload_wen         <= '1';
                        
                        stage_next        <= PRE_SAMPLE_FINALIZE;
                        cnt_next          <= 0;
                    when others =>
                        null;
                end case;
            when PRE_SAMPLE_FINALIZE =>
                -- Precondition: sample_addr (Disposed generation Counter of New Sample)
                
                cnt_next  <= cnt + 1;
                
                case (cnt) is
                    -- Disposed Generation Counter
                    when 0 =>
                        sample_addr_next  <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
                        sample_wen        <= '1';
                        
                        -- NOT_ALIVE_DISPOSED -> ALIVE Transition
                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                            sample_write_data <= gen_cnt + 1;
                        else
                            sample_write_data <= gen_cnt;
                        end if;
                    -- No Writer Generation Counter
                    when 1 =>
                        sample_wen        <= '1';
                        
                        -- NOT_ALIVE_NO_WRITERS -> ALIVE Transition
                        if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                            sample_write_data <= gen_cnt + 1;
                        else
                            sample_write_data <= gen_cnt;
                        end if;
                    when 2 =>
                        -- First Sample
                        if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                            stage_next          <= FINALIZE_SAMPLE;
                            sample_addr_next    <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
                            cur_sample_next     <= empty_sample_list_head;
                            next_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                            prev_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                            cnt_next            <= 0;
                        elsif (DESTINATION_ORDER_QOS = BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then
                            stage_next          <= FIX_POINTERS;
                            prev_sample_next    <= newest_sample;
                            sample_addr_next    <= newest_sample + SMF_NEXT_ADDR_OFFSET;
                            cur_sample_next     <= newest_sample;
                            cnt_next            <= 0;
                        else
                            stage_next          <= FIND_POS;
                            prev_sample_next    <= newest_sample;
                            sample_addr_next    <= newest_sample + SMF_TIMESTAMP_OFFSET;
                            cur_sample_next     <= newest_sample;
                            cnt_next            <= 0;
                        end if;
                    when others =>
                        null;
                end case;
            when FIND_POS =>
                -- Synthesis Guard
                if (DESTINATION_ORDER_QOS /= BY_RECEPTION_TIMESTAMP_DESTINATION_ORDER_QOS) then
                    -- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample)
                    
                    cnt_next  <= cnt + 1;
                    
                    case (cnt) is
                        -- Preload
                        when 0 =>
                            sample_addr_next    <= sample_addr + 1; -- Timestamp 2/2
                            sample_ren          <= '1';
                        -- Timestamp 1/2
                        when 1 =>
                            sample_addr_next    <= cur_sample + SMF_PREV_ADDR_OFFSET;
                            sample_ren          <= '1';
                            long_latch_next     <= sample_read_data;
                        -- Timestamp 2/2
                        when 2 =>
                            sample_ren          <= '1';
                            
                            tmp_dw  := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
                            
                            sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                            
                            -- Found position (After current slot)
                            if (ts_latch >= tmp_dw) then
                                stage_next      <= FIX_POINTERS;
                                cnt_next        <= 0;
                            end if;
                        -- Previous Pointer (Previous Sample)
                        when 3 =>
                            -- No previous Slot (Oldest Sample)
                            if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE;
                                
                                -- NOTE: Sample is added to HEAD of List
                                
                                prev_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                                next_sample_next    <= cur_sample;
                                stage_next          <= FIX_POINTERS;
                                cnt_next            <= 2; -- Skip to Previous Pointer Fix
                            else
                                -- Continue Search
                                prev_sample_next    <= sample_read_data;
                                sample_addr_next    <= sample_read_data + SMF_TIMESTAMP_OFFSET;
                                cnt_next            <= 0;
                            end if;
                    end case;
                end if;
            when FIX_POINTERS =>
                -- Precondition: sample_addr (Next Addr of prev_sample)
                
                cnt_next  <= cnt + 1;
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        sample_ren    <= '1';
                    -- Next Pointer (Previous Sample)
                    when 1 =>
                        
                        -- Fix Next Pointer
                        sample_write_data <= empty_sample_list_head;
                        sample_wen        <= '1';
                        
                        -- No next Slot (Newest Sample)
                        if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then
                            assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE;
                            
                            next_sample_next    <= SAMPLE_MEMORY_MAX_ADDRESS;
                            stage_next          <= FINALIZE_SAMPLE;
                            sample_addr_next    <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
                            cur_sample_next     <= empty_sample_list_head;
                            cnt_next            <= 0;
                        else
                            -- Latch Next Sample
                            next_sample_next    <= sample_read_data;
                            
                            sample_addr_next    <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample
                        end if;
                    -- Previous Pointer (Next Sample)
                    when 2 =>
                        -- Fix Previous Pointer
                        sample_write_data   <= empty_sample_list_head;
                        sample_wen          <= '1';
                        
                        stage_next          <= FINALIZE_SAMPLE;
                        sample_addr_next    <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
                        cur_sample_next     <= empty_sample_list_head;
                        cnt_next            <= 0;
                    when others =>
                        null;
                end case;
            when FINALIZE_SAMPLE =>
                -- Precondition: prev_sample set, next_sample set, sample_addr (Prev Addr of new sample)
                
                cnt_next  <= cnt + 1;
                
                case (cnt) is
                    -- Previous Sample Address
                    when 0 =>
                        sample_addr_next  <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        
                        -- Write Prev Addr
                        sample_write_data <= prev_sample;
                        sample_wen        <= '1';
                    -- Preload
                    when 1 =>
                        sample_ren    <= '1';
                    -- Next Sample Address
                    when 2 =>
                        empty_sample_list_head_next <= sample_read_data;
                        
                        -- Write Next Addr
                        sample_write_data <= next_sample;
                        sample_wen        <= '1';
                        
                        -- If newest Sample is now previous, select current sample as new newest
                        if (newest_sample = prev_sample) then
                            newest_sample_next  <= empty_sample_list_head;
                        end if;
                        
                        -- NOTE: added_new_instance and remove_oldest_sample are NOT mutual exclusive, but Instance Removal takes precedence.
                        
                        -- New Instance was added, and Instance Memory is Full
                        if (added_new_instance = '1' and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- Memory Operation Guard
                            if (inst_op_done = '1') then
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_FIRST_INSTANCE;
                                inst_data_variant   <= '0';
                                
                                -- NOTE: Instances are only removed in two occasions: 
                                --          * A new instance is added, and the instance memory gets full
                                --          * A Sample is removed, making an instance eligible for deletion, while the 
                                --            instance memory is full.
                                --       The combination of both cases allows to search and remove instances only when needed.
                                
                                stage_next  <= REMOVE_STALE_INSTANCE;
                            else
                                cnt_next    <= cnt; -- Keep State
                            end if;
                        elsif (remove_oldest_inst_sample = '1') then
                            cur_sample          <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET;
                            stage_next          <= FIND_OLDEST_INST_SAMPLE;
                        elsif (remove_oldest_sample = '1') then
                            stage_next  <= GET_OLDEST_SAMPLE_INSTANCE;
                        else
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                end case;
            when GET_OLDEST_SAMPLE_INSTANCE =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    cnt_next    <= cnt + 1;
                    
                    case (cnt) is
                        -- Preload
                        when 0 =>
                            sample_ren  <= '1';
                        when 1 =>
                            -- NOTE: We have to initiate an instance "search" despite having direct access to the instance
                            --       in order to set up the 'previous' instance pointer required by the removal procedure
                            --       (Since we do not store previous pointers in the memory frame format)
                            inst_op_start       <= '1';
                            inst_opcode         <= SEARCH_INSTANCE_ADDR;
                            inst_data_variant   <= '0';
                            inst_addr_update    <= sample_read_data;
                            
                            cur_sample_next     <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_PREV_ADDR_OFFSET;
                            stage_next          <= REMOVE_SAMPLE;
                        when others =>
                            null;
                    end case;
                end if;
            when FIND_OLDEST_INST_SAMPLE =>
                -- Precondition: cur_sample set, sample_addr (Instance Address of cur_sample)
                
                cnt_next <= cnt + 1;
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        sample_ren          <= '1';
                        sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                    -- Instance Address
                    when 1 =>
                        sample_ren          <= '1';
                        -- Oldest Instance Sample Found
                        if (sample_read_data = cur_inst) then
                            stage_next          <= REMOVE_SAMPLE;
                            sample_addr_next    <= cur_sample + SMF_PREV_ADDR_OFFSET;
                        end if;
                    -- Next Address
                    when 2 =>
                        cur_sample_next     <= sample_read_data;
                        sample_addr_next    <= sample_read_data + SMF_INSTANCE_ADDR_OFFSET;
                        cnt_next            <= 0;
                    when others =>
                        null;
                end case;
            when REMOVE_SAMPLE =>
                -- Precondition: cur_sample set, sample_addr (Previous Pointer of cur_sample)
                
                -- Wait for Instance Search to finish
                if (inst_op_done = '1') then
                    cnt_next    <= cnt + 1;
                    
                    case (cnt) is
                        -- Preload
                        when 0 =>
                            sample_ren          <= '1';
                            sample_addr_next    <= cur_sample + 1; -- Next Addr
                        -- Previous Pointer (Current Sample)
                        when 1 =>
                            sample_ren          <= '1';
                            prev_sample_next    <= sample_read_data;
                        -- Next Pointer (Current Sample)
                        when 2 =>
                            next_sample_next    <= sample_read_data;
                            
                            -- Make Current Sample Empty List Tail
                            sample_write_data   <= INSTANCE_MEMORY_MAX_ADDRESS;
                            sample_wen          <= '1';
                            
                            -- Current Sample is Newest (Occupied List Tail)
                            if (sample_read_data = MAX_SAMPLE_ADDRESS) then
                                assert (cur_sample = newest_sample) report "Next Sample is MAX_ADDR, but cur_sample /= newest_sample" severity FAILURE;
                                
                                -- Fix Newest Pointer
                                newest_sample_next  <= prev_sample;
                                
                                -- Current Sample is Oldest (List Head)
                                if (prev_sample = MAX_SAMPLE_ADDRESS) then
                                    assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
                                    assert (newest_sample = oldest_sample) report "Previous and Next Sample is MAX_ADDR, but cur_sample /= newest_sample /= oldest_sample" severity FAILURE;
                                    
                                    -- Fix Oldest Pointer
                                    oldest_sample_next  <= MAX_SAMPLE_ADDRESS;
                                    -- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR)
                                    
                                    -- Sample Memory Full
                                    if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
                                        empty_sample_list_head_next <= cur_sample;
                                        empty_sample_list_tail_next <= cur_sample;
                                        
                                        -- Skip to Payload Handling
                                        cnt_next            <= 6;
                                        sample_addr_next    <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                                    else
                                        -- Skip to Empty List Handling
                                        cnt_next            <= 5;
                                        sample_addr_next    <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
                                    end if;
                                else
                                    -- Skip to Previous Handling
                                    sample_addr_next    <= prev_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 4;
                                end if;
                            else
                                sample_addr_next    <= sample_read_data + SMF_PREV_ADDR_OFFSET;
                            end if;
                        -- Previous Address (Next Sample)
                        when 3 =>
                            -- Remove link to cur_sample
                            sample_write_data   <= prev_sample;
                            sample_wen          <= '1';
                            
                            -- Current Sample is oldest sample (List Head)
                            if (prev_sample = MAX_SAMPLE_ADDRESS) then
                                assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
                                
                                -- Fix Oldest Pointer
                                oldest_sample_next  <= MAX_SAMPLE_ADDRESS;
                                
                                -- Sample Memory Full
                                if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    empty_sample_list_head_next <= cur_sample;
                                    empty_sample_list_tail_next <= cur_sample;
                                    
                                    -- Skip to Payload Handling
                                    cnt_next            <= 6;
                                    sample_addr_next    <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                                else
                                    -- Skip to Empty List Handling
                                    cnt_next            <= 5;
                                    sample_addr_next    <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
                                end if;
                            end if;
                        -- Next Address (Previous Sample)
                        when 4 =>
                            -- Remove link to cur_sample
                            sample_write_data   <= next_sample;
                            sample_wen          <= '1';
                            
                            sample_addr_next    <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        -- Next Address (Empty Tail)
                        when 5 =>
                            sample_write_data   <= cur_sample;
                            sample_wen          <= '1';
                            
                            -- Fix Empty List Pointers
                            empty_sample_list_tail_next <= cur_sample;
                            
                            sample_addr_next    <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        -- Preload
                        when 6 =>
                            sample_ren  <= '1';
                        -- Payload Address
                        when 7 =>
                            cur_payload_next    <= sample_read_data;
                            -- Sample has no Data
                            if (sample_read_data = MAX_PAYLOAD_ADDRESS) then
                                stage_next  <= POST_SAMPLE_REMOVE;
                            -- Payload Memory Full
                            elsif (empty_payload_list_head = MAX_PAYLOAD_ADDRESS) then
                                -- NOTE: Make the head of the Payload, the head of the Empty List
                                empty_payload_list_head_next    <= sample_read_data;
                                
                                stage_next  <= POST_SAMPLE_REMOVE;
                            else
                                payload_addr_next   <= cur_payload + PMF_NEXT_ADDR_OFFSET;
                            end if;
                        -- Preload
                        when 8 =>
                            payload_ren <= '1';
                        -- Next Payload Addr
                        when 9 =>
                            -- Found Empty List Tail
                            if (payload_read_data = MAX_PAYLOAD_ADDRESS) then
                                empty_payload_list_head_next    <= cur_payload;
                                payload_write_data              <= empty_payload_list_head;
                                payload_wen                     <= '1';
                                
                                stage_next  <= POST_SAMPLE_REMOVE;
                            else
                                payload_addr_next   <= payload_read_data + PMF_NEXT_ADDR_OFFSET;
                                cnt_next            <= 8;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when POST_SAMPLE_REMOVE =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    -- No Instance Change on remove_oldest_inst_sample
                    if (remove_oldest_inst_sample = '0') then
                        tmp_bitmap  := to_endpoint_bitmap(inst_data.writer_bitmap);
                        -- Instance obsolete and Instance Memory Full
                        if (inst_data.sample_cnt = 1 and tmp_bitmap = (tmp_bitmap'range => '0') and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                            inst_op_start   <= '1';
                            inst_opcode     <= REMOVE_INSTANCE;
                        else
                            inst_op_start       <= '1';
                            inst_opcode         <= UPDATE_INSTANCE;
                            update_inst_flags   <= SAMPLE_CNT_FLAG;
                            sample_cnt          <= inst_data.sample_cnt - 1;
                        end if;
                    end if;
                    
                    if (is_take = '1') then
                        -- Continue Processing
                        stage_next  <= GET_NEXT_SAMPLE;
                        cnt_next    <= 0;
                    else
                        -- DONE
                        stage_next  <= IDLE;
                    end if;
                end if;
            when SKIP_ADD_REJECT =>
                case (cnt) is
                    -- SKIP READ
                    when 0 =>
                        ready_in_rtps  <= '1';
                        -- Wait until last word from input
                        if (last_word_in_rtps  = '1') then
                            cnt_next  <= 1;
                        end if;
                    -- REJECT SAMPLE
                    when 1 =>
                        res_rtps    <= REJECTED;
                        stage_next  <= IDLE;
                    when others =>
                        null;
                end case;
            when SKIP_ADD_DROP =>
                case (cnt) is
                    -- SKIP READ
                    when 0 =>
                        ready_in_rtps  <= '1';
                        -- Wait until last word from input
                        if (last_word_in_rtps  = '1') then
                            cnt_next  <= 1;
                        end if;
                    -- DROP SAMPLE
                    when 1 =>
                        res_rtps    <= ACCEPTED;
                        stage_next  <= IDLE;
                    when others =>
                        null;
                end case;
            when REMOVE_WRITER =>
                -- Memory Operation Guard
                if (inst_op_done = '1') then
                    -- No More Instances
                    if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                        -- DONE
                        stage_next    <= IDLE;
                    else
                        -- Convert Writer Bitmap to SLV
                        tmp_bitmap  := to_endpoint_bitmap(inst_data.writer_bitmap);
                        
                        -- Remove Writer
                        tmp_bitmap(writer_pos) := '0';
                        
                        -- NOTE: writer_bitmap is not latched, since the memory process is latching it at the
                        --       same clock cycle.
                        -- Convert Back
                        writer_bitmap   <= from_endpoint_bitmap(tmp_bitmap);
                        
                        -- No More Writers for Instance
                        if (tmp_bitmap = (tmp_bitmap'range => '0')) then
                            status_info_update                               <= inst_data.status;
                            status_info_update(NOT_ALIVE_DISPOSED_FLAG)      <= '0';
                            status_info_update(NOT_ALIVE_NO_WRITERS_FLAG)    <= '1';
                            status_info_update(LIVELINESS_FLAG)              <= '1';
                            inst_op_start     <= '1';
                            inst_opcode       <= UPDATE_INSTANCE;
                            update_inst_flags <= STATUS_FLAG or WRITER_BITMAP_FLAG;
                        else
                            inst_op_start     <= '1';
                            inst_opcode       <= UPDATE_INSTANCE;
                            update_inst_flags <= WRITER_BITMAP_FLAG;
                        end if;
                        
                        stage_next    <= GET_NEXT_INSTANCE;
                    end if;
                end if;
            when GET_NEXT_INSTANCE =>
                -- Wait for Operation to Complete
                if (inst_op_done = '1') then                    
                    inst_op_start       <= '1';
                    inst_opcode         <= GET_NEXT_INSTANCE;
                    inst_data_variant   <= '0';
                    stage_next          <= REMOVE_WRITER;
                end if;
            when REMOVE_STALE_INSTANCE =>
                -- Wait for Instance Data
                if (inst_op_done = '1') then
                    -- Iterated through all Instances
                    if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                        if (remove_oldest_inst_sample = '1') then
                            cur_sample          <= oldest_sample;
                            sample_addr_next    <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET;
                            stage_next          <= FIND_OLDEST_INST_SAMPLE;
                        else
                            -- DONE
                            stage_next  <= IDLE;
                        end if;
                    else
                        -- Convert Writer Bitmap to SLV
                        tmp_bitmap  := to_endpoint_bitmap(inst_data.writer_bitmap);
                        
                        -- Found Stale Instance (No Samples and No Active Writers)
                        if (inst_data.sample_cnt = 0 and tmp_bitmap = (tmp_bitmap'range => '0')) then
                            -- Remove Stale Instance
                            inst_op_start   <= '1';
                            inst_opcode     <= REMOVE_INSTANCE;
                            
                            if (remove_oldest_inst_sample = '1') then
                                cur_sample          <= oldest_sample;
                                sample_addr_next    <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET;
                                stage_next          <= FIND_OLDEST_INST_SAMPLE;
                            else
                                -- DONE
                                stage_next  <= IDLE;
                            end if;
                        else
                            -- Continue Search
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_NEXT_INSTANCE;
                            inst_data_variant   <= '0';
                        end if;
                    end if;
                end if;
            when GET_NEXT_SAMPLE =>
                -- Precondition: cur_sample set, sample_addr (Status Info of cur_sample), cur_inst set, si_sample_rank_sig set
                
                cnt_next            <= cnt + 1;
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        sample_addr_next    <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                        sample_ren          <= '1';
                    -- Status Info
                    when 1 =>
                        sample_addr_next    <= cur_sample + SMF_TIMESTAMP_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Latch Sample Status Info
                        sample_status_info_next <= sample_read_data;
                        
                        -- Check Sample State
                        case (sample_state) is
                            when READ_SAMPLE_STATE =>
                                if (sample_read_data(READ_FLAG) /= '1') then
                                    -- Sample not in collection, Skip Sample
                                    sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 13;
                                end if;
                            when NOT_READ_SAMPLE_STATE =>
                                if (sample_read_data(READ_FLAG) /= '0') then
                                    -- Sample not in collection, Skip Sample
                                    sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 13;
                                end if;
                            when ANY_SAMPLE_STATE =>
                                null;
                            -- Uknown Sample State
                            when others =>
                                -- Sample not in collection, Skip Sample
                                sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                cnt_next            <= 13;
                        end case;
                        
                        if (sample_read_data(READ_FLAG) = '1') then
                            si_sample_state_sig_next    <= READ_SAMPLE_STATE;
                        else
                            si_sample_state_sig_next    <= NOT_READ_SAMPLE_STATE;
                        end if;
                    -- Instance Pointer
                    when 2 =>
                        -- Instance pre-selected
                        if (cur_inst /= INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- Sample has different Instance
                            if (cur_inst /= sample_read_data) then
                                -- Consecutive Instance Sample Order
                                if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) then
                                    -- Skip Sample
                                    sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 13;
                                else
                                    -- Get Instance Data
                                    next_inst_next  <= sample_read_data;
                                end if;
                            else
                                -- Select Sample
                                collection_cnt_next     <= collection_cnt + 1;
                                first_sample_next       <= cur_sample;
                                
                                -- First Instance Sample
                                -- NOTE: This state only enters with a sample rank of 0 and cur_inst set, when the
                                --       first sample of the instance has not yet been selected
                                if (si_sample_rank_sig = 0) then
                                    -- Reset
                                    collection_cnt_max_next <= collection_cnt + 1;
                                else
                                    si_sample_rank_sig      <= si_sample_rank_sig - 1;
                                end if;
                                
                                sample_addr_next    <= sample_addr + 1; -- Timestamp 2/2
                                sample_ren          <= '1';
                                cnt_next            <= 5; -- Skip Instance Operation
                            end if;
                        else
                            -- Get Instance Data
                            next_inst_next  <= sample_read_data;
                        end if;
                    -- Get Instance
                    when 3 =>
                        -- Memory Operation Guard
                        if (inst_op_done = '1') then
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_INSTANCE;
                            inst_data_variant   <= '1';
                            inst_addr_update    <= next_inst;
                        else
                            cnt_next    <= cnt; -- Keep sub-state
                        end if;
                    -- Check Instance Data
                    when 4 =>
                        -- Wait for Instance Data
                        if (inst_op_done = '1') then
                            sample_addr_next    <= sample_addr + 1; -- Timestamp 2/2
                            sample_ren          <= '1';
                            -- DEFAULT
                            tmp_bool    := TRUE;
                            
                            -- Check Instance State
                            case (instance_state) is
                                when ALIVE_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when ANY_INSTANCE_STATE =>
                                    null;
                                when others =>
                                    tmp_bool    := FALSE;
                            end case;
                            
                            -- Check View State
                            case (view_state) is
                                when NEW_VIEW_STATE =>
                                    if (inst_data.status_info(VIEW_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_NEW_VIEW_STATE =>
                                    if (inst_data.status_info(VIEW_FLAG) = '1') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when ANY_VIEW_STATE =>
                                    null;
                                when others =>
                                    tmp_bool    := FALSE;
                            end case;
                            
                            -- Check Instance Mark
                            if (inst_data.status_info(MARK_FLAG) = '1') then
                                -- Skip Marked Instance
                                tmp_bool    := FALSE;
                            end if;
                            
                            -- Instance Passes Checks
                            if (tmp_bool) then
                                -- Select Sample
                                collection_cnt_next     <= collection_cnt + 1;
                                collection_cnt_max_next <= collection_cnt + 1;
                                si_sample_rank_sig      <= (others => '0');
                                cur_inst_next           <= next_inst;
                                first_sample_next       <= cur_sample;
                            else
                                -- Skip Sample
                                sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                cnt_next            <= 13;
                            end if;
                        else
                            cnt_next    <= cnt; -- Keep sub-state
                        end if;
                    -- Timestamp 1/2
                    when 5 =>
                        sample_addr_next    <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
                        sample_ren          <= '1';
                        
                        si_source_timestamp_sig_next(0) <= sample_read_data;
                    -- Timestamp 2/2
                    when 6 =>
                        sample_addr_next    <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
                        sample_ren          <= '1';
                        
                        si_source_timestamp_sig_next(1) <= sample_read_data;
                    -- Payload Pointer
                    when 10 =>
                        sample_addr_next    <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Latch Payload Address
                        cur_payload_next                <= sample_read_data;
                    -- Disposed Generation Count
                    when 11 =>
                        sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_ren          <= '1';
                        
                        si_disposed_generation_count_sig_next   <= sample_read_data;
                    -- No Writers Generation Count
                    when 12 =>
                        sample_ren          <= '1';
                        
                        si_no_writers_generation_count_sig_next <= sample_read_data;
                        cur_generation_rank_next                <= si_disposed_generation_count_sig + sample_read_data;
                        -- Calculate highest collection generation rank
                        collection_generation_rank_next         <= si_disposed_generation_count_sig + sample_read_data;
                        
                        cnt_next    <= 14; -- Skip Preload
                    -- Preload
                    when 13 =>
                        sample_ren  <= '1';
                    -- Next Pointer
                    when 14 =>
                        -- Reached End of Samples
                        if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then
                            -- Exit Condition (Sample Selected)
                            if (first_sample = cur_sample) then
                                stage_next  <= FINALIZE_SAMPLE_INFO;
                                cnt_next    <= 0;
                            else
                                -- Collection Empty
                                if (collection_cnt = 0) then
                                    -- READ_NEXT_INSTANCE/TAKE_NEXT_INSTANCE Operation
                                    if (dynamic_next_instance = '1') then
                                        -- NOTE: We selected a compatible instance, but the instance has no compatible samples.
                                        --       Find next compatible instance.
                                        stage_next  <= FIND_NEXT_INSTANCE;
                                        cnt_next    <= 1;
                                    else
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_NO_DATA;
                                        stage_next      <= IDLE;
                                    end if;
                                else
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    stage_next      <= IDLE;
                                end if;
                            end if;
                        else
                            -- Next Sample
                            cur_sample_next     <= sample_read_data;
                            sample_addr_next    <= sample_read_data + SMF_STATUS_INFO_OFFSET;
                            cnt_next            <= 0;
                            
                            -- Exit Condition (Sample Selected)
                            if (first_sample = cur_sample) then
                                -- Pre-Calculation already done for selected Instance
                                if (si_sample_rank_sig /= 0) then
                                    stage_next  <= FINALIZE_SAMPLE_INFO;
                                    cnt_next    <= 0;
                                else
                                    -- Latch Next Sample (For resume purposes)
                                    next_sample_next    <= sample_read_data;
                                    -- Calculate Instance Sample Ranks
                                    stage_next          <= PRE_CALCULATE;
                                end if;
                            end if;
                        end if;
                    when others => 
                        null;
                end case;
            when PRE_CALCULATE =>
                -- Precondition: cur_sample set, sample_addr_next (Status Info of cur_sample)
                
                cnt_next    <= cnt + 1;
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        sample_addr_next    <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Exit Condition (Reached Collection Limit)
                        if (collection_cnt_max = max_samples) then
                            stage_next  <= FINALIZE_SAMPLE_INFO;
                            cnt_next    <= 0;
                        end if;
                    -- Status Info
                    when 1 =>
                        sample_addr_next    <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Check Sample State
                        case (sample_state) is
                            when READ_SAMPLE_STATE =>
                                if (sample_read_data(READ_FLAG) /= '1') then
                                    -- Skip Sample
                                    sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 7;
                                end if;
                            when NOT_READ_SAMPLE_STATE =>
                                if (sample_read_data(READ_FLAG) /= '0') then
                                    -- Skip Sample
                                    sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                    cnt_next            <= 7;
                                end if;
                            when ANY_SAMPLE_STATE =>
                                null;
                            -- Uknown Sample State
                            when others =>
                                -- Skip Sample
                                sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                cnt_next            <= 7;
                        end case;
                    -- Instance Pointer
                    when 2 =>
                        sample_addr_next    <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Same Instance
                        if (sample_read_data = cur_inst) then
                            -- Count Sample (No need to check Instance)
                            collection_cnt_max_next <= collection_cnt_max + 1;
                            si_sample_rank_sig_next <= si_sample_rank_sig + 1;
                        else
                            -- Consecutive Instance Sample Order
                            if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then
                                -- Skip Sample
                                sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                                cnt_next            <= 7;
                            else
                                -- Check New Instance
                                next_inst_next  <= sample_read_data;
                                cnt_next        <= 5;
                            end if;
                        end if;
                    -- Disposed Generation Count
                    when 3 =>
                        sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                        sample_ren          <= '1';
                        
                        -- Calculate highest collection generation rank
                        collection_generation_rank_next <= sample_read_data;
                    -- No Writers Generation Count
                    when 4 =>
                        sample_ren          <= '1';
                        
                        -- Calculate highest collection generation rank
                        collection_generation_rank_next <= collection_generation_rank + sample_read_data;
                        
                        cnt_next    <= 8;
                    -- Initiate Get Memory Operation
                    when 5 =>
                        -- Memory Operation Guard
                        if (inst_op_done = '1') then
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_INSTANCE_DATA_2;
                            inst_data_variant   <= '1';
                            inst_addr_update    <= next_inst;
                        else
                            cnt_next    <= cnt; -- Keep State
                        end if;
                    -- State Check
                    when 6 =>
                        -- Wait for Instance Data
                        if (inst_op_done = '1') then
                            -- DEFAULT
                            tmp_bool    := TRUE;
                            
                            -- Check Instance State
                            case (instance_state) is
                                when ALIVE_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_ALIVE_INSTANCE_STATE =>
                                    if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when ANY_INSTANCE_STATE =>
                                    null;
                                when others =>
                                    tmp_bool    := FALSE;
                            end case;
                            
                            -- Check View State
                            case (view_state) is
                                when NEW_VIEW_STATE =>
                                    if (inst_data.status_info(VIEW_FLAG) = '0') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when NOT_NEW_VIEW_STATE =>
                                    if (inst_data.status_info(VIEW_FLAG) = '1') then
                                        tmp_bool    := FALSE;
                                    end if;
                                when ANY_VIEW_STATE =>
                                    null;
                                when others =>
                                    tmp_bool    := FALSE;
                            end case;
                            
                            -- Check Instance Mark
                            if (inst_data.status_info(MARK_FLAG) = '1') then
                                -- Skip Marked Instance
                                tmp_bool    := FALSE;
                            end if;
                            
                            -- Instance passes Checks
                            if (tmp_bool) then
                                -- Count Sample
                                collection_cnt_max_next <= collection_cnt_max + 1;
                            end if;
                            -- Done
                            sample_addr_next    <= cur_sample + SMF_NEXT_ADDR_OFFSET;
                            cnt_next            <= 7;
                        else
                            cnt_next    <= cnt; -- Keep sub-state
                        end if;
                    -- Preload
                    when 7 =>
                        sample_ren  <= '1';
                    -- Next Pointer
                    when 8 =>
                        -- Exit Condition (Reached End of Samples)
                        if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then
                            stage_next  <= FINALIZE_SAMPLE_INFO;
                            cnt_next    <= 0;
                        else
                            -- Continue with next Sample
                            cur_sample_next     <= sample_read_data;
                            sample_addr_next    <= sample_read_data + SMF_STATUS_INFO_OFFSET;
                            cnt_next            <= 0;
                        end if;
                    when others =>
                        null;
                end case;
            when FINALIZE_SAMPLE_INFO =>
                -- Precondition: cur_inst set 
                
                case (cnt) is
                    -- Finalize Sample Info Data
                    when 0 =>
                        sample_addr_next    <= first_sample + SMF_STATUS_INFO_OFFSET;
                        
                        -- Wait for Instance Data
                        if (inst_op_done = '1') then
                            -- Instance Data valid
                            if (inst_addr_base = cur_inst) then
                                -- Sample Info View State
                                if (inst_data.status_info(VIEW_FLAG) = '1') then
                                    si_view_state_sig_next  <= NEW_VIEW_STATE;
                                else
                                    si_view_state_sig_next  <= NOT_NEW_VIEW_STATE;
                                end if;
                                
                                -- Sample Info Instance State
                                if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then
                                    si_instance_state_sig_next  <= NOT_ALIVE_DISPOSED_INSTANCE_STATE;
                                elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                                    si_instance_state_sig_next  <= NOT_ALIVE_NO_WRITERS_INSTANCE_STATE;
                                else
                                    si_instance_state_sig_next  <= ALIVE_INSTANCE_STATE;
                                end if;
                                
                                -- Sample Info Instance Handle
                                si_instance_handle_sig_next <= inst_data.key_hash;
                                
                                -- Sample Info Generation Rank
                                si_generation_rank_sig_next <= collection_generation_rank - cur_generation_rank;
                                
                                -- Sample Info Absolut Generation Rank
                                -- XXX: Possible Worst Case Path (2 32-bit Operations in same clock)
                                si_generation_rank_sig_next <= (inst_data.disposed_gen_cnt + inst_data.no_writers_gen_cnt) - cur_generation_rank;
                                
                                -- Sample Info Valid Data
                                if (cur_payload /= PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    si_valid_data_sig_next  <= '1';
                                else
                                    si_valid_data_sig_next  <= '0';
                                end if;
                                
                                si_valid_sig_next   <= '1';
                                cnt_next            <= 1;
                            else
                                -- Get Instance Data
                                inst_op_start       <= '1';
                                inst_opcode         <= GET_INSTANCE;
                                inst_data_variant   <= '1';
                                inst_addr_update    <= cur_inst;
                            end if;
                        end if;
                    -- Present Data
                    when 1 =>
                        -- Invalidate Data
                        si_valid_sig_next   <= '0';
                        
                        -- Synthesis Guard
                        if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
                            -- Update Last Read Timestamp
                            if (si_source_timestamp_sig > last_read_ts) then
                                last_read_ts_next   <= si_source_timestamp_sig;
                            end if;
                        end if;
                        
                        -- Sample not marked as Read
                        if (sample_status_info(READ_FLAG) /= '1') then
                            -- Mark Sample as Read
                            sample_write_data               <= sample_status_info;
                            sample_write_data(READ_FLAG)    <= '1';
                            sample_wen                      <= '1';
                        end if;
                        
                        -- Sample Data Request
                        if (get_data = '1') then
                            stage_next          <= GET_PAYLOAD;
                            cnt_next            <= 0;
                            payload_addr_next   <= cur_payload;
                        else
                            cnt_next    <= 2;
                        end if;
                    -- Post-Present Data
                    when 2 =>
                        -- Memory Operation Guard
                        if (inst_op_done = '1') then
                            -- NOTE: If we have a presentation of consecutive same instance samples of multiple instances, we have to
                            --       mark the instances we have already handled, in order to prevent the GET_NEXT_SAMPLE state to
                            --       re-process them.
                            -- Last Sample of Instance in Collection
                            if (si_sample_rank_sig = 1) then
                                inst_op_start       <= '1';
                                inst_opcode         <= UPDATE_INSTANCE;
                                update_inst_flags   <= STATUS_FLAG;
                                status_info_update  <= inst_data.status_info;
                                
                                -- Consecutive Instance Sample Order of multiple Instances
                                if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0' and single_sample = '0') then
                                    -- Completed Collection
                                    if (collection_cnt = max_samples) then
                                        -- Unmark Instances
                                        unmark_instances_next   <= '1';
                                    else
                                        -- Mark Instance
                                        status_info_update(MARK_FLAG)   <= '1';
                                    end if;
                                end if;
                                
                                -- Instance is NOT_VIEWED and sample is from last generation of Instance
                                if (inst_data.status_info(VIEW_FLAG) = '0' and si_absolute_generation_count_sig = 0) then
                                    -- Mark Instance as VIEWED
                                    status_info_update(VIEW_FLAG)   <= '1';
                                end if;
                            end if;
                            
                            -- Collection Completed
                            if (collection_cnt = max_samples) then
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_OK;
                                is_take_next    <= '0'; -- Return to IDLE from REMOVE
                                
                                if (is_take = '1') then
                                    stage_next          <= REMOVE_SAMPLE;
                                    cur_sample_next     <= first_sample;
                                    sample_addr_next    <= first_sample + SMF_PREV_ADDR_OFFSET;
                                else
                                    -- DONE
                                    stage_next  <= IDLE;
                                end if;
                            else
                                cur_sample  <= next_sample;
                                cnt_next    <= 0;
                                
                                -- Reached End of Samples
                                if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
                                    -- DONE
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_OK;
                                    is_take_next    <= '0'; -- Return to IDLE from REMOVE
                                end if;
                                
                                -- cur_inst has no more samples in collection
                                if (si_sample_rank_sig = 0) then
                                    -- Present only single Instance
                                    if (single_instance = '1') then
                                        -- DONE
                                        done_dds        <= '1';
                                        return_code_dds <= RETCODE_OK;
                                        is_take_next    <= '0'; -- Return to IDLE from REMOVE
                                    else
                                        cur_inst_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                    end if;
                                end if;
                                
                                if (is_take = '1') then
                                    -- Remove Sample
                                    stage_next          <= REMOVE_SAMPLE;
                                    cur_sample_next     <= first_sample;
                                    sample_addr_next    <= first_sample + SMF_PREV_ADDR_OFFSET;
                                else
                                    -- Continue Processing
                                    stage_next  <= GET_NEXT_SAMPLE;
                                end if;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when GET_PAYLOAD =>
                -- Precondition: payload_addr (Beginning of cur_payload)
                
                case (cnt) is
                    -- Preload
                    when 0 =>
                        payload_addr_next   <= payload_addr + 1;
                        payload_ren         <= '1';
                        cnt_next            <= cnt + 1;
                    -- Next Pointer
                    when 1 =>
                        payload_addr_next   <= payload_addr + 1;
                        payload_ren         <= '1';
                        cnt_next            <= cnt + 1;
                        
                        next_payload_next   <= payload_read_data;
                    -- Payload
                    when others =>
                        if (ready_out_dds = '1') then
                            payload_addr_next   <= payload_addr + 1;
                            payload_ren         <= '1';
                            cnt_next            <= cnt + 1; 
                            
                            valid_out_dds   <= '1';
                            if (has_latched = '0') then
                                data_out_dds    <= payload_read_data;
                            else
                                -- Previously Latched
                                data_out_dds    <= long_latch;
                            end if;
                            
                            -- Reset
                            has_lacthed_next    <= '0';
                            
                            -- End of Payload Frame
                            if (cnt = PAYLOAD_FRAME_SIZE) then
                                -- Last Payload Frame
                                if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then
                                    last_word_out_dds   <= '1';
                                    
                                    stage_next  <= FINALIZE_SAMPLE_INFO;
                                    cnt_next    <= 2;
                                else
                                    -- Continue with next payload Slot
                                    payload_addr_next   <= next_payload;
                                    cnt_next            <= 0;
                                end if;
                            end if;
                        else
                            long_latch_next     <= payload_read_data;
                            has_lacthed_next    <= '1';
                        end if;
                
                end case;
            when FIND_NEXT_INSTANCE =>
                -- Wait for Instance Data
                if (inst_op_done = '1') then
                    case (cnt) is
                        when 0 =>
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_FIRST_INSTANCE;
                            inst_data_variant   <= '1';
                            cnt_next            <= 2;
                        when 1 =>
                            inst_op_start       <= '1';
                            inst_opcode         <= GET_NEXT_INSTANCE;
                            inst_data_variant   <= '1';
                            cnt_next            <= 2;
                        when 2 =>
                            -- Instance Found
                            if (inst_addr_base /= SAMPLE_MEMORY_MAX_ADDRESS) then
                                -- DEFAULT
                                tmp_bool    := TRUE;
                                
                                -- Check Instance Handle (Key Hash)
                                -- XXX: Posible Worst Case Path (128-bit Comparison)
                                if (to_unsigned(inst_data.key_hash) =< to_unsigned(key_hash)) then
                                    tmp_bool    := FALSE;
                                end if;
                                
                                -- Check Instance State
                                case (instance_state) is
                                    when ALIVE_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when ANY_INSTANCE_STATE =>
                                        null;
                                    when others =>
                                        tmp_bool    := FALSE;
                                end case;
                                
                                -- Check View State
                                case (view_state) is
                                    when NEW_VIEW_STATE =>
                                        if (inst_data.status_info(VIEW_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_NEW_VIEW_STATE =>
                                        if (inst_data.status_info(VIEW_FLAG) = '1') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when ANY_VIEW_STATE =>
                                        null;
                                    when others =>
                                        tmp_bool    := FALSE;
                                end case;
                                
                                -- Instance Passes Checks
                                if (tmp_bool) then
                                    cur_inst    <= inst_addr_base;
                                    stage_next  <= GET_NEXT_SAMPLE;
                                else
                                    inst_op_start       <= '1';
                                    inst_opcode         <= GET_NEXT_INSTANCE;
                                    inst_data_variant   <= '1';
                                end if;
                            else
                                -- DONE
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_NO_DATA;
                                stage_next      <= IDLE;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when CHECK_INSTANCE =>
                -- Wait for Instance Data
                if (inst_op_done = '1') then
                    case (cnt) is
                        when 0 =>
                            inst_op_start       <= '1';
                            inst_opcode         <= SEARCH_INSTANCE_HASH;
                            inst_data_variant   <= '1';
                            cnt_next            <= 1;
                        when 1 =>
                            -- Instance Found
                            if (inst_addr_base /= SAMPLE_MEMORY_MAX_ADDRESS) then
                                -- DEFAULT
                                tmp_bool    := TRUE;
                                
                                -- Check Instance State
                                case (instance_state) is
                                    when ALIVE_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_ALIVE_INSTANCE_STATE =>
                                        if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when ANY_INSTANCE_STATE =>
                                        null;
                                    when others =>
                                        tmp_bool    := FALSE;
                                end case;
                                
                                -- Check View State
                                case (view_state) is
                                    when NEW_VIEW_STATE =>
                                        if (inst_data.status_info(VIEW_FLAG) = '0') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when NOT_NEW_VIEW_STATE =>
                                        if (inst_data.status_info(VIEW_FLAG) = '1') then
                                            tmp_bool    := FALSE;
                                        end if;
                                    when ANY_VIEW_STATE =>
                                        null;
                                    when others =>
                                        tmp_bool    := FALSE;
                                end case;
                                
                                -- Instance Passes Checks
                                if (tmp_bool) then
                                    -- Get Instance Samples
                                    cur_inst    <= inst_addr_base;
                                    stage_next  <= GET_NEXT_SAMPLE;
                                else
                                    -- DONE
                                    done_dds        <= '1';
                                    return_code_dds <= RETCODE_NO_DATA;
                                    stage_next      <= IDLE;
                                end if;
                            else
                                -- Given Instance does not exist
                                -- DONE
                                done_dds        <= '1';
                                return_code_dds <= RETCODE_BAD_PARAMETER;
                                stage_next      <= IDLE;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when others =>
                null;
        end case;
    end process;
    
    
    inst_ctrl_prc : process(all)
    begin
        -- DEFAULT Registered
        inst_stage_next             <= inst_stage;
        inst_addr_base_next         <= inst_addr_base;
        inst_addr_next              <= inst_addr;
        inst_empty_head_next        <= inst_empty_head;
        inst_occupied_head_next     <= inst_occupied_head;
        inst_latch_data_next        <= inst_latch_data;
        inst_next_addr_base_next    <= inst_next_addr_base;
        inst_prev_addr_base_next    <= inst_prev_addr_base;
        inst_cnt_next               <= inst_cnt;
        inst_mem_full_next          <= inst_mem_full;
        inst_data_next              <= inst_data;
        -- DEFAULT Unregistered
        inst_write_data   <= (others => '0');
        inst_op_done      <= '0';
        inst_ren          <= '0';
        inst_wen          <= '0';
        
        
        case (mem_stage) is
            when IDLE =>
                inst_op_done    <= '1';
                
                if (inst_op_start = '1') then
                    -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
                    inst_latch_data_next    <= (
                        variant         => inst_data_variant,
                        key_hash        => key_hash_next,
                        status_info     => status_info_update,
                        sample_cnt      => sample_cnt,
                        gen_cnt         => gen_cnt,
                        deadline        => deadline,
                        writer_bitmap   => writer_bitmap,
                        update_flags    => update_inst_flags,
                        addr            => inst_addr_update
                    );
                    
                    case(inst_opcode) is
                        when SEARCH_INSTANCE_HASH =>
                            -- Reset Data
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            
                            -- No Instances avialable
                            if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                            else
                                inst_prev_addr_base   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                inst_addr_base_next   <= inst_occupied_head;
                                inst_addr_next        <= inst_occupied_head;
                                inst_stage_next       <= SEARCH_INSTANCE_HASH;
                                inst_cnt_next         <= 0;
                            end if;
                        when SEARCH_INSTANCE_ADDR =>
                            -- Reset Data
                            inst_data_next  <= ZERO_INSTANCE_DATA;
                            
                            -- No Instances avialable
                            if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                            else
                                inst_prev_addr_base   <= INSTANCE_MEMORY_MAX_ADDRESS;
                                inst_addr_base_next   <= inst_occupied_head;
                                inst_addr_next        <= inst_occupied_head;
                                inst_stage_next       <= SEARCH_INSTANCE_ADDR;
                                inst_cnt_next         <= 0;
                            end if;
                        when INSERT_INSTANCE =>
                            -- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure
                            --       by the main process that the operation can succeed (Memory is available)
                            assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE;
                            
                            inst_addr_next          <= inst_occupied_head;
                            inst_addr_base_next     <= inst_occupied_head;
                            inst_stage_next         <= FIND_POS;
                            inst_cnt_next           <= 0;
                        when UPDATE_INSTANCE =>
                            inst_addr_base_next   <= inst_addr_update;
                            if ((update_inst_flags and STATUS_FLAG) = STATUS_FLAG) then
                                inst_stage_next   <= UPDATE_INSTANCE;
                                inst_addr_next    <= inst_addr_update + IMF_STATUS_INFO_OFFSET;
                                inst_cnt_next     <= 0;
                            elsif ((update_inst_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
                                inst_stage_next   <= UPDATE_INSTANCE;
                                inst_addr_next    <= inst_addr_update + IMF_SAMPLE_CNT_OFFSET;
                                inst_cnt_next     <= 3;
                            elsif ((update_inst_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
                                inst_stage_next   <= UPDATE_INSTANCE;
                                inst_addr_next    <= inst_addr_update + IMF_DISPOSED_GEN_CNT_OFFSET;
                                inst_cnt_next     <= 6;
                            elsif ((update_inst_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
                                inst_stage_next   <= UPDATE_INSTANCE;
                                inst_addr_next    <= inst_addr_update + IMF_NO_WRITERS_GEN_CNT_OFFSET;
                                inst_cnt_next     <= 7;
                            elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (update_inst_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
                                inst_stage_next   <= UPDATE_INSTANCE;
                                inst_addr_next    <= inst_addr_update + IMF_IGNORE_DEADLINE_OFFSET;
                                inst_cnt_next     <= 8;
                            elsif ((update_inst_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                                inst_stage_next   <= SET_WRITER_BITMAP;
                                inst_addr_next    <= inst_addr_update + IMF_WRITER_BITMAP_OFFSET;
                                inst_cnt_next     <= 0;
                            end if;
                        when GET_FIRST_INSTANCE =>
                            -- No Instances avialable
                            if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                            else
                                inst_prev_addr_base_next  <= INSTANCE_MEMORY_MAX_ADDRESS;
                                inst_addr_base_next       <= inst_occupied_head;
                                inst_addr_next            <= inst_occupied_head + IMF_STATUS_INFO_OFFSET;
                                if (inst_data_variant = '0')  then
                                    inst_stage_next <= GET_INSTANCE_DATA_1;
                                else
                                    inst_stage_next <= GET_INSTANCE_DATA_2;
                                end if;
                                inst_cnt_next             <= 0;
                            end if;
                        when GET_NEXT_INSTANCE =>
                            -- No Instances avialable
                            if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS;
                            else
                                inst_prev_addr_base_next    <= inst_addr_base;
                                inst_addr_base_next         <= inst_next_addr_base;
                                inst_addr_next              <= inst_next_addr_base;
                                inst_stage_next             <= GET_NEXT_INSTANCE;
                                inst_cnt_next               <= 0;
                            end if;
                        when REMOVE_INSTANCE =>
                            assert (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) report "Request Removal on empty memory" severity FAILURE;
                            
                            inst_prev_addr_base_next  <= INSTANCE_MEMORY_MAX_ADDRESS;
                            inst_addr_base_next       <= inst_occupied_head;
                            inst_addr_next            <= inst_occupied_head;
                            inst_stage_next           <= REMOVE_INSTANCE;
                            inst_cnt_next             <= 0;
                        when GET_INSTANCE =>
                            inst_addr_base_next       <= inst_addr_update;
                            inst_addr_next            <= inst_addr_update + IMF_KEY_HASH_OFFSET;
                            if (inst_data_variant = '0')  then
                                inst_stage_next <= GET_INSTANCE_DATA_1;
                            else
                                inst_stage_next <= GET_INSTANCE_DATA_2;
                            end if;
                            inst_cnt_next             <= 0;
                        when UNMARK_INTANCES =>
                            -- Empty Memory Guard
                            if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next       <= inst_occupied_head;
                                inst_addr_next            <= inst_occupied_head + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next           <= UNMARK_INTANCES;
                                inst_cnt_next             <= 0;
                            end if;
                        when others =>
                            null;
                    end case;
                end if;
            when SEARCH_INSTANCE_HASH =>
                inst_ren        <= '1';
                inst_cnt_next   <= inst_cnt + 1;
                inst_addr_next  <= inst_addr + 1;
                
                case (inst_cnt) is
                    -- Preload
                    when 0 =>
                        null;
                    -- Next Instance
                    when 1 =>
                        inst_next_addr_base_next    <= inst_read_data;
                    -- Key Hash 1/4
                    when 2 =>
                        -- No Match
                        if (inst_read_data /= inst_latch_data.key_hash(0)) then
                            -- Reached List Tail, No Match
                            if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next       <= IDLE;
                            else
                                -- Continue Search
                                inst_prev_addr_base_next  <= inst_addr_base;
                                inst_addr_base_next       <= inst_next_addr_base;
                                inst_addr_next            <= inst_next_addr_base;
                                inst_cnt_next             <= 0;
                            end if;
                        end if;
                    -- Key Hash 2/4
                    when 3 =>
                        -- No Match
                        if (inst_read_data /= inst_latch_data.key_hash(1)) then
                            -- Reached List Tail, No Match
                            if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next       <= IDLE;
                            else
                                -- Continue Search
                                inst_prev_addr_base_next  <= inst_addr_base;
                                inst_addr_base_next       <= inst_next_addr_base;
                                inst_addr_next            <= inst_next_addr_base;
                                inst_cnt_next             <= 0;
                            end if;
                        end if;
                    -- Key Hash 3/4
                    when 4 =>
                        -- No Match
                        if (inst_read_data /= inst_latch_data.key_hash(2)) then
                            -- Reached List Tail, No Match
                            if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next       <= IDLE;
                            else
                                -- Continue Search
                                inst_prev_addr_base_next  <= inst_addr_base;
                                inst_addr_base_next       <= inst_next_addr_base;
                                inst_addr_next            <= inst_next_addr_base;
                                inst_cnt_next             <= 0;
                            end if;
                        end if;
                    -- Key Hash 4/4
                    when 5 =>
                        -- No Match
                        if (inst_read_data /= inst_latch_data.key_hash(3)) then
                            -- Reached List Tail, No Match
                            if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next       <= IDLE;
                            else
                                -- Continue Search
                                inst_prev_addr_base_next  <= inst_addr_base;
                                inst_addr_base_next       <= inst_next_addr_base;
                                inst_addr_next            <= inst_next_addr_base;
                                inst_cnt_next             <= 0;
                            end if;
                        -- Match
                        else
                            -- Fetch Instance Data
                            if (inst_data_variant = '0')  then
                                inst_stage_next <= GET_INSTANCE_DATA_1;
                                inst_cnt_next   <= 1; -- No preload needed
                            else
                                inst_addr_next  <= inst_addr_base + IMF_KEY_HASH_OFFSET;
                                inst_stage_next <= GET_INSTANCE_DATA_2;
                                inst_cnt_next   <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when SEARCH_INSTANCE_ADDR =>
                inst_cnt_next   <= inst_cnt + 1;
                inst_addr_next  <= inst_addr + 1;
                
                case (inst_cnt) is
                    -- Preload
                    when 0 =>
                        inst_ren        <= '1';
                    -- Next Instance
                    when 1 =>
                        inst_prev_addr_base_next  <= inst_addr_base;
                        inst_addr_base_next       <= inst_read_data;
                    
                        -- Match
                        if (inst_read_data = inst_latch_data.addr) then
                            -- Fetch Instance Data
                            if (inst_data_variant = '0')  then
                                inst_addr_next  <= inst_read_data + IMF_STATUS_INFO_OFFSET;
                                inst_stage_next <= GET_INSTANCE_DATA_1;
                                inst_cnt_next   <= 0;
                            else
                                inst_addr_next  <= inst_read_data + IMF_KEY_HASH_OFFSET;
                                inst_stage_next <= GET_INSTANCE_DATA_2;
                                -- TODO: Skip Preload?
                                inst_cnt_next   <= 0;
                            end if;
                        -- No Match
                        else
                            -- Reached List Tail, No Match
                            if (inst_read_data = INSTANCE_MEMORY_MAX_ADDRESS) then
                                inst_addr_base_next   <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
                                -- DONE
                                inst_stage_next       <= IDLE;
                            else
                                -- Continue Search
                                inst_addr_next  <= inst_read_data;
                                inst_cnt_next   <= 0;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;    
            when GET_NEXT_INSTANCE =>
                case (inst_cnt) is
                    -- Preload
                    when 0 =>
                        inst_wen  <= '1';
                    -- Next Instance
                    when 1 =>
                        -- Latch Next Instance
                        inst_next_addr_base_next    <= inst_read_data;
                        
                        
                        -- Fetch Instance Data
                        if (inst_data_variant = '0')  then
                            inst_addr_next  <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                            inst_stage_next <= GET_INSTANCE_DATA_1;
                            inst_cnt_next   <= 0;
                        else
                            inst_addr_next  <= inst_addr_base + IMF_KEY_HASH_OFFSET;
                            inst_stage_next <= GET_INSTANCE_DATA_2;
                            -- TODO: Skip Preload?
                            inst_cnt_next   <= 0;
                        end if;
                end case;
            when GET_INSTANCE_DATA_2 =>
                -- Precondition: inst_addr (Status Info)
            
                inst_ren        <= '1';
                inst_cnt_next   <= inst_cnt + 1;
                inst_addr_next  <= inst_addr + 1;
                
                case (inst_cnt) is
                    -- Memory Preload
                    when 0 =>
                        null;
                    -- Key Hash 1/4
                    when 1 =>
                        inst_data_next.key_hash(0)          <= inst_read_data;
                    -- Key Hash 2/4
                    when 2 =>
                        inst_data_next.key_hash(1)          <= inst_read_data;
                    -- Key Hash 3/4
                    when 3 =>
                        inst_data_next.key_hash(2)          <= inst_read_data;
                    -- Key Hash 4/4
                    when 4 =>
                        inst_data_next.key_hash(3)          <= inst_read_data;
                    -- Status Info
                    when 5 =>
                        inst_data_next.status_info          <= inst_read_data;
                    -- Sample Count
                    when 6 =>
                        inst_data_next.sample_cnt           <= inst_read_data;
                    -- Disposed Generation Count
                    when 7 =>
                        inst_data_next.disposed_gen_cnt     <= inst_read_data;
                    -- No Writers Generation Count
                    when 8 =>
                        inst_data_next.no_writers_gen_cnt   <= inst_read_data;
                    
                        -- DONE
                        inst_stage_next <= IDLE;
                    when others =>
                        null;
                end case;
            when GET_INSTANCE_DATA_1 =>
                -- Precondition: inst_addr (Status Info)
            
                inst_ren        <= '1';
                inst_cnt_next   <= inst_cnt + 1;
                inst_addr_next  <= inst_addr + 1;
                
                case (inst_cnt) is
                    -- Memory Preload
                    when 0 =>
                        null;
                    -- Status Info
                    when 1 =>
                        inst_data_next.status_info          <= inst_read_data;
                    -- Sample Count
                    when 2 =>
                        inst_data_next.sample_cnt           <= inst_read_data;
                    -- Disposed Generation Count
                    when 3 =>
                        inst_data_next.disposed_gen_cnt     <= inst_read_data;
                    -- No Writers Generation Count
                    when 4 =>
                        inst_data_next.no_writers_gen_cnt   <= inst_read_data;
                    -- Ignore Deadline 1/2
                    when 5 =>
                        inst_data_next.ignore_deadline(0)   <= unsigned(inst_read_data);
                    -- Ignore Deadline 2/2
                    when 5 =>
                        inst_data_next.ignore_deadline(1)   <= unsigned(inst_read_data);
                        -- DONE
                        inst_stage_next <= GET_WRITER_BITMAP;
                        inst_cnt_next <= 0;
                    when others =>
                        null;
                end case;
            when GET_WRITER_BITMAP =>
                inst_cnt_next  <= inst_cnt + 1;
                
                inst_latch_data_next.writer_bitmap(inst_cnt) <= inst_read_data;
                
                if (inst_cnt = writer_bitmap'length-1) then
                    -- DONE
                    inst_stage_next <= IDLE;
                end if;
            when FIND_POS =>
                inst_cnt_next   <= inst_cnt + 1;
                inst_addr_next  <= inst_addr + 1;
                inst_ren        <= '1';
                
                -- NOTE: Instances are inserted in KEY_HASH numerical order.
                
                case (inst_cnt) is
                    
                    -- Preload
                    when 0 =>
                        null;
                    -- Next Instance
                    when 1 =>
                        inst_next_addr_base_next    <= inst_read_data;
                    -- Key Hash 1/4
                    when 2 =>
                        -- Found Position
                        if (inst_latch_data.key_hash(0) < inst_read_data) then
                            inst_next_addr_base_next    <= inst_addr_base;
                            -- Occupied List Head
                            if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                assert (inst_addr_base = inst_occupied_head)
                                inst_occupied_head_next <= inst_empty_head;
                                
                                inst_addr_base_next     <= inst_empty_head;
                                inst_addr_next          <= inst_empty_head + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 1; -- Skip First Step 
                            else
                                inst_addr_base_next     <= inst_prev_addr_base;
                                inst_addr_next          <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 0;
                            end if;
                        -- BIGGER-THAN
                        elsif (inst_latch_data.key_hash(0) /= inst_read_data) then
                            -- Continue
                            inst_prev_addr_base_next    <= inst_addr_base;
                            inst_addr_next              <= inst_next_addr_base;
                            inst_addr_base_next         <= inst_next_addr_base;
                            cnt_next                    <= 0;
                        end if;
                    -- Key Hash 2/4
                    when 3 =>
                        -- Found Position
                        if (inst_latch_data.key_hash(1) < inst_read_data) then
                            inst_next_addr_base_next    <= inst_addr_base;
                            -- Occupied List Head
                            if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                assert (inst_addr_base = inst_occupied_head)
                                inst_occupied_head_next <= inst_empty_head;
                                
                                inst_addr_base_next     <= inst_empty_head;
                                inst_addr_next          <= inst_empty_head + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 1; -- Skip First Step 
                            else
                                inst_addr_base_next     <= inst_prev_addr_base;
                                inst_addr_next          <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 0;
                            end if;
                        -- BIGGER-THAN
                        elsif (inst_latch_data.key_hash(1) /= inst_read_data) then
                            -- Continue
                            inst_prev_addr_base_next    <= inst_addr_base;
                            inst_addr_next              <= inst_next_addr_base;
                            inst_addr_base_next         <= inst_next_addr_base;
                            cnt_next                    <= 0;
                        end if;
                    -- Key Hash 3/4
                    when 4 =>
                        -- Found Position
                        if (inst_latch_data.key_hash(2) < inst_read_data) then
                            inst_next_addr_base_next    <= inst_addr_base;
                            -- Occupied List Head
                            if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                assert (inst_addr_base = inst_occupied_head)
                                inst_occupied_head_next <= inst_empty_head;
                                
                                inst_addr_base_next     <= inst_empty_head;
                                inst_addr_next          <= inst_empty_head + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 1; -- Skip First Step 
                            else
                                inst_addr_base_next     <= inst_prev_addr_base;
                                inst_addr_next          <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 0;
                            end if;
                        -- BIGGER-THAN
                        elsif (inst_latch_data.key_hash(2) /= inst_read_data) then
                            -- Continue
                            inst_prev_addr_base_next    <= inst_addr_base;
                            inst_addr_next              <= inst_next_addr_base;
                            inst_addr_base_next         <= inst_next_addr_base;
                            cnt_next                    <= 0;
                        end if;
                    -- Key Hash 4/4
                    when 5 =>
                        -- Found Position
                        if (inst_latch_data.key_hash(3) < inst_read_data) then
                            inst_next_addr_base_next    <= inst_addr_base;
                            -- Occupied List Head
                            if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
                                assert (inst_addr_base = inst_occupied_head)
                                inst_occupied_head_next <= inst_empty_head;
                                
                                inst_addr_base_next     <= inst_empty_head;
                                inst_addr_next          <= inst_empty_head + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 1; -- Skip First Step 
                            else
                                inst_addr_base_next     <= inst_prev_addr_base;
                                inst_addr_next          <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                                inst_stage_next         <= INSERT_INSTANCE;
                                cnt_next                <= 0;
                            end if;
                        else
                            assert (inst_latch_data.key_hash(3) /= inst_read_data) report "Doublicate Instance Detected" severity FAILURE;
                            
                            -- Continue
                            inst_prev_addr_base_next    <= inst_addr_base;
                            inst_addr_next              <= inst_next_addr_base;
                            inst_addr_base_next         <= inst_next_addr_base;
                            cnt_next                    <= 0;
                        end if;
                    when others => 
                        null;
                end case;
            when INSERT_INSTANCE =>
                inst_addr_next  <= inst_addr + 1;
                inst_cnt_next   <= inst_cnt + 1;
                
                case (inst_cnt) is
                    -- Next Pointer (Previous Instance)
                    when 0 =>
                        inst_write_data     <= inst_empty_head;
                        inst_wen            <= '1';
                        inst_addr_next      <= inst_empty_head;
                        inst_addr_base_next <= inst_empty_head;    
                    -- Preload
                    when 1 =>
                        inst_ren        <= '1';
                        inst_addr_next  <= inst_addr; -- Keep Addr
                    -- Next Pointer (New Instance)
                    when 2 =>
                        -- Fix Empty List Head
                        inst_empty_head_next    <= inst_read_data;
                        
                        inst_write_data <= inst_next_addr_base;
                        inst_wen        <= '1';
                    -- Key Hash 1/4
                    when 3 =>
                        inst_write_data <= inst_latch_data.key_hash(0);
                        inst_wen        <= '1';
                    -- Key Hash 2/4
                    when 4 =>
                        inst_write_data <= inst_latch_data.key_hash(1);
                        inst_wen        <= '1';
                    -- Key Hash 3/4
                    when 5 =>
                        inst_write_data <= inst_latch_data.key_hash(2);
                        inst_wen        <= '1';
                    -- Key Hash 4/4
                    when 6 =>
                        inst_write_data <= inst_latch_data.key_hash(3);
                        inst_wen        <= '1';
                    -- Status Info
                    when 7 =>
                        inst_write_data <= inst_latch_data.status_info;
                        inst_wen        <= '1';
                    -- Sample Count
                    when 8 =>
                        inst_write_data <= std_logic_vector(to_unsigned(1, WORD_WIDTH));
                        inst_wen        <= '1';
                    -- Disposed Generation Count
                    when 9 =>
                        inst_write_data <= (others => '0');
                        inst_wen        <= '1';
                    -- No Writers Generation Count
                    when 10 =>
                        inst_write_data <= (others => '0');
                        inst_wen        <= '1';
                        
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
                            inst_cnt  <= 11;
                        else
                            inst_stage_next   <= SET_WRITER_BITMAP;
                            inst_cnt_next     <= 0;
                        end if;
                    -- Ignore Deadline 1/2
                    when 11 =>
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
                            inst_write_data <= inst_latch_data.deadline(0);
                            inst_wen        <= '1';
                        end if;
                    -- Ignore Deadline 1/2
                    when 12 =>
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
                            inst_write_data <= inst_latch_data.deadline(1);
                            inst_wen        <= '1';
                            
                            inst_stage_next <= SET_WRITER_BITMAP;
                            inst_cnt_next   <= 0;
                        end if;
                    when others => 
                        null;
                end case;
            when SET_WRITER_BITMAP =>
                inst_wen          <= '1';
                inst_addr_next    <= inst_addr + 1;
                inst_cnt_next     <= inst_cnt + 1;
                
                inst_write_data   <= inst_latch_data.writer_bitmap(inst_cnt);
                
                -- Exit Condition
                if (inst_cnt = inst_latch_data.writer_bitmap'length-1) then
                    -- DONE
                    inst_stage_next   <= IDLE;
                end if;
            when UPDATE_INSTANCE =>
                inst_cnt_next     <= inst_cnt + 1;
                
                case (inst_cnt) is
                    -- Status Info
                    when 0 =>
                        inst_wen                    <= '1';
                        inst_write_data             <= inst_latch_data.status_info;
                        inst_data_next.status_info  <= inst_latch_data.status_info;
                        
                        if ((inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
                            inst_addr_next    <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
                            inst_cnt_next     <= 1;
                        elsif ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
                            inst_addr_next    <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
                            inst_cnt_next     <= 2;
                        elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
                            inst_addr_next    <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
                            inst_cnt_next     <= 3;
                        elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
                            inst_cnt_next     <= 4;
                        elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
                            inst_stage_next   <= SET_WRITER_BITMAP;
                            inst_cnt_next     <= 0;
                        else
                            -- DONE
                            inst_stage_next   <= IDLE;
                        end if;
                    -- Sample Count
                    when 1 =>
                        inst_wen                    <= '1';
                        inst_write_data             <= inst_latch_data.sample_cnt;
                        inst_data_next.sample_cnt   <= inst_latch_data.sample_cnt;
                        
                        if ((inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
                            inst_addr_next    <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
                            inst_cnt_next     <= 2;
                        elsif ((inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
                            inst_addr_next    <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
                            inst_cnt_next     <= 3;
                        elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
                            inst_cnt_next     <= 4;
                        elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
                            inst_stage_next   <= SET_WRITER_BITMAP;
                            inst_cnt_next     <= 0;
                        else
                            -- DONE
                            inst_stage_next   <= IDLE;
                        end if;
                    -- Disposed Generation Count
                    when 2 =>
                        inst_wen                        <= '1';
                        inst_write_data                 <= inst_latch_data.gen_cnt;
                        inst_data_next.disposed_gen_cnt <= inst_latch_data.gen_cnt;
                    
                        -- NOTE: Both Generation Counters cannot be updated on the same update procedure
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
                            inst_cnt_next     <= 4;
                        elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
                            inst_stage_next   <= SET_WRITER_BITMAP;
                            inst_cnt_next     <= 0;
                        else
                            -- DONE
                            inst_stage_next   <= IDLE;
                        end if;
                    -- No Writers Generation Count
                    when 3 =>
                        inst_wen                            <= '1';
                        inst_write_data                     <= inst_latch_data.gen_cnt;
                        inst_data_next.no_writers_gen_cnt   <= inst_latch_data.gen_cnt;
                    
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
                            inst_cnt_next     <= 4;
                        elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                            inst_addr_next    <=  inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
                            inst_stage_next   <= SET_WRITER_BITMAP;
                            inst_cnt_next     <= 0;
                        else
                            -- DONE
                            inst_stage_next   <= IDLE;
                        end if;
                    -- Ignore Deadline 1/2
                    when 4 =>
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO)  then
                            inst_wen                <= '1';
                            inst_write_data         <= std_logic_vector(inst_latch_data.ignore_deadline(0));
                            inst_data_next.deadline <= inst_latch_data.ignore_deadline(0);
                        end if;
                    -- Ignore Deadline 2/2
                    when 5 =>
                        if (TIME_BASED_FILTER_QOS /= DURATION_ZERO)  then
                            inst_wen                <= '1';
                            inst_write_data         <= std_logic_vector(inst_latch_data.ignore_deadline(1));
                            inst_data_next.deadline <= inst_latch_data.ignore_deadline(1);
                            
                            if ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
                                inst_addr_next    <=  inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
                                inst_stage_next   <= SET_WRITER_BITMAP;
                                inst_cnt_next     <= 0;
                            else
                                -- DONE
                                inst_stage_next   <= IDLE;
                            end if;
                        end if;
                    when others =>
                        null;
                end case;
            when REMOVE_INSTANCE =>
                inst_cnt_next   <= inst_cnt + 1;
                
                case (inst_cnt) is
                    -- Preload
                    when 0 =>
                        inst_ren        <= '1';
                        inst_addr_next  <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
                    -- Next Pointer (Previous Occupied Instance)
                    when 1 =>
                        -- Fix Pointer
                        inst_write_data <= inst_read_data;
                        inst_wen        <= '1';
                        
                        inst_addr_next  <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
                    -- Next Pointer (Current Instance)
                    when 2 =>
                        -- Fix Pointer
                        inst_write_data         <= inst_empty_head;
                        inst_wen                <= '1';
                        -- Fix Empty List Head
                        inst_empty_head_next    <= inst_addr_base;
                        
                        -- Reset
                        inst_data_next      <= ZERO_INSTANCE_DATA;
                        inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
                        
                        -- DONE
                        inst_stage_next     <= IDLE;
                    when others =>
                        null;
                end case;
            when UNMARK_INTANCES =>
                -- Precondition: 
                
                inst_cnt_next   <= inst_cnt + 1;
                
                case (inst_cnt) is
                    -- Preload
                    when 0 =>
                        inst_addr_next  <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
                        inst_ren        <= '1';
                    -- Next Pointer
                    when 1 =>
                        inst_ren    <= '1';
                        
                        next_inst_next  <= inst_read_data;
                    -- Instance Status Info
                    when 2 =>
                        inst_write_data             <= inst_read_data;
                        inst_write_data(MARK_FLAG)  <= '0';
                        inst_wen                    <= '1';
                        
                        -- Reached End of Instances
                        if (next_inst = INSTANCE_MEMORY_MAX_ADDRESS) then
                            -- DONE
                            inst_stage_next <= IDLE;
                        else
                            inst_addr_base_next <= next_inst;
                            inst_addr_next      <= next_inst + IMF_NEXT_ADDR_OFFSET;
                            inst_cnt_next       <= 0;
                        end if;
                    when others =>
                        null;
                end case;
            when others =>
                null;
        end case;
    end process;
    
end architecture;