rtps-fpga/src/dds_reader.vhd
Greek 9cc4907a2f Add complete Level2 System Test
Using seperately compiled Libraries we interconnect two systems, and
test their communication and interaction.
A bug in rtps_builtin_endpoint was fixed (were if only the SUB data was
to be sent, it was never actually sent).
2021-11-17 14:23:53 +01:00

6728 lines
392 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
-- TODO: Check if sample_cnt is always maintained (also with MAX_SAMPLES_PER_INSTANCE = LENGTH_UNLIMITED)
entity dds_reader is
generic (
ID : ID_TYPE := 0;
TIME_BASED_FILTER_QOS : DURATION_TYPE := ENDPOINT_TIME_BASED_FILTER_QOS(ID);
DEADLINE_QOS : DURATION_TYPE := ENDPOINT_DEADLINE_QOS(ID);
MAX_INSTANCES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_INSTANCES(ID);
MAX_SAMPLES_PER_INSTANCE : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_SAMPLES_PER_INSTANCE(ID);
MAX_SAMPLES : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := ENDPOINT_MAX_SAMPLES(ID);
HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_HISTORY_QOS(ID);
RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_RELIABILITY_QOS(ID);
PRESENTATION_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_PRESENTATION_QOS(ID);
DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := ENDPOINT_DESTINATION_ORDER_QOS(ID);
COHERENT_ACCESS : boolean := ENDPOINT_COHERENT_ACCESS(ID);
ORDERED_ACCESS : boolean := ENDPOINT_ORDERED_ACCESS(ID);
WITH_KEY : boolean := ENDPOINT_WITH_KEY(ID);
PAYLOAD_FRAME_SIZE : natural;
MAX_REMOTE_ENDPOINTS : natural := 50
);
port (
-- SYSTEM
clk : in std_logic;
reset : in std_logic;
time : in TIME_TYPE;
-- FROM RTPS ENDPOINT
start_rtps : in std_logic;
opcode_rtps : in HISTORY_CACHE_OPCODE_TYPE;
ack_rtps : out std_logic;
done_rtps : out std_logic;
ret_rtps : out HISTORY_CACHE_RESPONSE_TYPE;
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;
-- TO/FROM KEY_HOLDER
start_kh : out std_logic;
opcode_kh : out KEY_HOLDER_OPCODE_TYPE;
ack_kh : in std_logic;
data_in_kh : in std_logic_vector(WORD_WIDTH-1 downto 0);
valid_in_kh : in std_logic;
ready_in_kh : out std_logic;
last_word_in_kh : in std_logic;
data_out_kh : out std_logic_vector(WORD_WIDTH-1 downto 0);
valid_out_kh : out std_logic;
ready_out_kh : in std_logic;
last_word_out_kh : out std_logic;
abort_kh : out std_logic;
-- TO USER ENTITY
start_dds : in std_logic;
ack_dds : out std_logic;
opcode_dds : in DDS_READER_OPCODE_TYPE;
instance_state_dds : in std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0);
view_state_dds : in std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0);
sample_state_dds : in std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0);
instance_handle_dds : in INSTANCE_HANDLE_TYPE;
max_samples_dds : in std_logic_vector(MAX_SAMPLES_WIDTH-1 downto 0);
get_data_dds : in std_logic;
done_dds : out std_logic;
return_code_dds : out std_logic_vector(RETURN_CODE_WIDTH-1 downto 0);
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;
-- 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_rank : out std_logic_vector(ABSOLUTE_GENERATION_COUNT_WIDTH-1 downto 0);
si_valid_data : out std_logic;
si_valid : out std_logic;
si_ack : in std_logic;
eoc : out std_logic;
-- Communication Status
status : out std_logic_vector(STATUS_KIND_WIDTH-1 downto 0)
);
end entity;
architecture arch of dds_reader is
--*****CONSTANT DECLARATION*****
-- NOTE: Because we need to first determine the Instance before making the ACCEPT/REJECT/DROP decision
-- we need to latch the cache change first, calculate the Key Hash if necessary, fetch the associated
-- Instance, and then decide on it. This in effect means that we always need an extra slot in sample and
-- payload memory that is only used as a latch.
-- *SAMPLE MEMORY*
-- 4-Byte Word Size of a Sample Info Entry in Memory
function gen_sample_frame_size(WITH_KEY : boolean) return natural is
variable ret : natural := 0;
begin
if (WITH_KEY) then
return 11;
else
return 10;
end if;
end function;
constant SAMPLE_FRAME_SIZE : natural := gen_sample_frame_size(WITH_KEY);
-- Sample Info Memory Size in 4-Byte Words
constant SAMPLE_MEMORY_SIZE : natural := to_integer(unsigned(MAX_SAMPLES)+1) * SAMPLE_FRAME_SIZE;
-- Sample Info Memory Address Width
constant SAMPLE_MEMORY_ADDR_WIDTH : natural := log2c(SAMPLE_MEMORY_SIZE);
-- Highest Sample Info Memory Address
constant SAMPLE_MEMORY_MAX_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH);
-- Highest Sample Info Frame Address
constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Sample Data Frame
constant FIRST_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *PAYLOAD MEMORY*
-- Payload Memory Size in 4-Byte Words
constant PAYLOAD_MEMORY_SIZE : natural := to_integer(unsigned(MAX_SAMPLES)+1) * PAYLOAD_FRAME_SIZE;
-- Payload Memory Address Width
constant PAYLOAD_MEMORY_ADDR_WIDTH : natural := log2c(PAYLOAD_MEMORY_SIZE);
-- Highest Payload Memory Address
constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH);
-- Highest Payload Frame Address
constant MAX_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Payload Data Frame
constant FIRST_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *INSTANCE MEMORY*
-- 4-Byte Word Size of a Instance Entry in Memory
function gen_inst_frame_size(time_based_filter : DURATION_TYPE) return natural is
variable ret : natural := 0;
begin
if (time_based_filter = DURATION_ZERO) then
return 9 + round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH);
else
return 11 + round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH);
end if;
end function;
constant INSTANCE_FRAME_SIZE : natural := gen_inst_frame_size(TIME_BASED_FILTER_QOS);
-- Instance Memory Size in 4-Byte Words
constant INSTANCE_MEMORY_SIZE : natural := to_integer(unsigned(MAX_INSTANCES)) * INSTANCE_FRAME_SIZE;
-- Instance Memory Address Width
constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE);
-- Highest Instance Memory Address
constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH);
-- Highest Instance Frame Address
constant MAX_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Instance Data Frame
constant FIRST_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *SAMPLE MEMORY FRAME FIELD OFFSETS*
-- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
constant SMF_STATUS_INFO_OFFSET : natural := 0;
constant SMF_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;
function gen_smf_disposed_gen_cnt_offset(WITH_KEY : boolean) return natural is
variable ret : natural := 0;
begin
ret := (SMF_INSTANCE_ADDR_OFFSET + 1) when WITH_KEY else SMF_INSTANCE_ADDR_OFFSET;
return ret;
end function;
constant SMF_DISPOSED_GEN_CNT_OFFSET : natural := gen_smf_disposed_gen_cnt_offset(WITH_KEY);
constant SMF_NO_WRITERS_GEN_CNT_OFFSET : natural := SMF_DISPOSED_GEN_CNT_OFFSET + 1;
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 FIELD OFFSETS*
-- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
constant PMF_NEXT_ADDR_OFFSET : natural := 0;
constant PMF_PAYLOAD_OFFSET : natural := 1;
-- *INSTANCE MEMORY FRAME FIELD OFFSETS*
-- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
constant IMF_NEXT_ADDR_OFFSET : natural := 0;
constant IMF_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 := 7;
constant IMF_NO_WRITERS_GEN_CNT_OFFSET : natural := 8;
constant IMF_IGNORE_DEADLINE_OFFSET : natural := 9;
function gen_imf_writer_bitmap_offset(time_based_filter : DURATION_TYPE) return natural is
variable ret : natural := 0;
begin
ret := IMF_IGNORE_DEADLINE_OFFSET+2 when (time_based_filter /= DURATION_ZERO) else IMF_IGNORE_DEADLINE_OFFSET;
return ret;
end function;
constant IMF_WRITER_BITMAP_OFFSET : natural := gen_imf_writer_bitmap_offset(TIME_BASED_FILTER_QOS);
-- *INSTANCE MEMORY FRAME FIELD FLAGS*
-- Flags mapping to the respective Endpoint Memory Frame Fields
constant IMF_FLAG_WIDTH : natural := 7;
constant IMF_KEY_HASH_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (0 => '1', others => '0');
constant IMF_STATUS_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (1 => '1', others => '0');
constant IMF_SAMPLE_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (2 => '1', others => '0');
constant IMF_DISPOSED_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (3 => '1', others => '0');
constant IMF_NO_WRITERS_CNT_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (4 => '1', others => '0');
constant IMF_IGNORE_DEADLINE_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (5 => '1', others => '0');
constant IMF_WRITER_BITMAP_FLAG : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (6 => '1', others => '0');
--*****TYPE DECLARATION*****
-- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, RETURN_DDS, RETURN_RTPS, ADD_SAMPLE_INFO, ADD_PAYLOAD_ADDRESS, ADD_PAYLOAD, NEXT_PAYLOAD_SLOT, ALIGN_PAYLOAD, GET_KEY_HASH, INITIATE_INSTANCE_SEARCH,
FILTER_STAGE, UPDATE_INSTANCE, FINALIZE_PAYLOAD, PRE_SAMPLE_FINALIZE, FIND_POS, FIX_POINTERS, FINALIZE_SAMPLE, GENERATE_SAMPLE, GET_OLDEST_SAMPLE_INSTANCE,
FIND_OLDEST_INST_SAMPLE, REMOVE_SAMPLE, POST_SAMPLE_REMOVE, SKIP_AND_RETURN, REMOVE_WRITER, REMOVE_STALE_INSTANCE, GET_NEXT_SAMPLE, PRE_CALCULATE, FINALIZE_SAMPLE_INFO,
GET_PAYLOAD, FIND_NEXT_INSTANCE, CHECK_INSTANCE, CHECK_LIFESPAN, PROCESS_PENDING_SAMPLE_GENERATION, GET_SAMPLE_REJECTED_STATUS, GET_REQUESTED_DEADLINE_MISSED_STATUS,
CHECK_DEADLINE, RESET_SAMPLE_MEMORY, RESET_PAYLOAD_MEMORY);
-- Instance Memory FSM states. Explained below in detail
type INST_STAGE_TYPE is (IDLE, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, GET_NEXT_INSTANCE, GET_INSTANCE_DATA, FIND_POS, INSERT_INSTANCE, UPDATE_INSTANCE,
REMOVE_INSTANCE, UNMARK_INSTANCES, RESET_MEMORY);
-- *Instance Memory Opcodes*
-- OPCODE DESCRIPTION
-- SEARCH_INSTANCE_HASH Search Instance based on Key Hash pointed by "key_hash".
-- Set "inst_addr_base" to Base Address of found Instance, of INSTANCE_MEMORY_MAX_ADDRESS if nothing found.
-- "inst_data" contains Instance Data according to "inst_mem_fields".
-- SEARCH_INSTANCE_ADDR Search Instance based on Instance Pointer pointed by "inst_addr_update".
-- Set "inst_addr_base" to "inst_addr_update"
-- "inst_data" contains Instance Data according to "inst_mem_fields".
-- INSERT_INSTANCE Insert Instance to memory. The Instance is inserted in Key Hash Numerical Order.
-- UPDATE_INSTANCE Update Instance Data pointed by "inst_addr_base" according to "inst_mem_fields"
-- GET_FIRST_INSTANCE Get Instance Data of first Instance (Instance with smallest Key Hash Numerical Order) according to "inst_mem_fields".
-- Set "inst_addr_base" to Address of Instance or INSTANCE_MEMORY_MAX_ADDRESS if no Instance in Memory.
-- GET_NEXT_INSTANCE Get Instance Data of next Instance (from the Instance pointed by "inst_addr_base") according to "inst_mem_fields".
-- Set "inst_addr_base" to Address of Instance or INSTANCE_MEMORY_MAX_ADDRESS if no other Instance in Memory.
-- REMOVE_INSTANCE Remove Instance pointed by "inst_addr_base".
-- GET_INSTANCE Get Data of Instance pointed by "inst_addr_update" according to "inst_mem_fields".
-- Already fetched Data of the Participant is not modified.
-- UNMARK_INSTANCES Reset the MARK_FLAG of all Instances in Memory.
type INSTANCE_OPCODE_TYPE is (NOP, SEARCH_INSTANCE_HASH, SEARCH_INSTANCE_ADDR, INSERT_INSTANCE, UPDATE_INSTANCE, GET_FIRST_INSTANCE, GET_NEXT_INSTANCE, REMOVE_INSTANCE,
GET_INSTANCE, UNMARK_INSTANCES);
type WRITER_BITMAP_ARRAY_TYPE is array (0 to round_div(MAX_REMOTE_ENDPOINTS, WORD_WIDTH)-1) of std_logic_vector(0 to WORD_WIDTH-1);
constant ZERO_WRITER_BITMAP_ARRAY : WRITER_BITMAP_ARRAY_TYPE := (others => (others => '0'));
constant WRITER_BITMAP_WIDTH : natural := WRITER_BITMAP_ARRAY_TYPE'length*WORD_WIDTH;
-- Record of Instance Data
type INSTANCE_DATA_TYPE is record
key_hash : KEY_HASH_TYPE;
status_info : std_logic_vector(WORD_WIDTH-1 downto 0);
sample_cnt : unsigned(WORD_WIDTH-1 downto 0);
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 : WRITER_BITMAP_ARRAY_TYPE;
end record;
-- Zero initialized Endpoint Data
constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := (
key_hash => (others => (others => '0')),
status_info => (others => '0'),
sample_cnt => (others => '0'),
disposed_gen_cnt => (others => '0'),
no_writers_gen_cnt => (others => '0'),
ignore_deadline => TIME_INVALID,
writer_bitmap => ZERO_WRITER_BITMAP_ARRAY
);
-- Instance Data Latch used as temporal cache by Instance Memory FSM
type INST_LATCH_DATA_TYPE is record
key_hash : KEY_HASH_TYPE;
status_info : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0);
gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0);
deadline : TIME_TYPE;
writer_bitmap : WRITER_BITMAP_ARRAY_TYPE;
field_flags : std_logic_vector(0 to IMF_FLAG_WIDTH-1);
addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
end record;
-- Zero initialized Instance Data Latch
constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := (
key_hash => (others => (others => '0')),
status_info => (others => '0'),
sample_cnt => (others => '0'),
gen_cnt => (others => '0'),
deadline => TIME_INVALID,
writer_bitmap => ZERO_WRITER_BITMAP_ARRAY,
field_flags => (others => '0'),
addr => (others => '0')
);
--*****SIGNAL DECLARATION
-- *SAMPLE MEMORY CONNECTION SIGNALS*
signal sample_addr : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_read : std_logic := '0';
signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal sample_ready_in, sample_valid_in : std_logic := '0';
signal sample_ready_out, sample_valid_out : std_logic := '0';
signal sample_abort_read : std_logic := '0';
-- *PAYLOAD MEMORY CONNECTION SIGNALS*
signal payload_addr : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_read : std_logic := '0';
signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal payload_ready_in, payload_valid_in : std_logic := '0';
signal payload_ready_out, payload_valid_out : std_logic := '0';
signal payload_abort_read : std_logic := '0';
-- *INSTANCE MEMORY CONNECTION SIGNALS*
signal inst_addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_read : std_logic := '0';
signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal inst_ready_in, inst_valid_in : std_logic := '0';
signal inst_ready_out, inst_valid_out : std_logic := '0';
signal inst_abort_read : std_logic := '0';
-- *MAIN PROCESS*
-- FSM state
signal stage, stage_next : STAGE_TYPE := IDLE;
-- General Purpose Counter
signal cnt, cnt_next : natural range 0 to 18 := 0;
-- Counter used to read/write Payload Fames
signal cnt2, cnt2_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0;
-- Counter used to read/write Payload Fames
signal cnt3, cnt3_next : natural range 0 to PAYLOAD_FRAME_SIZE := 0;
-- Head of Empty Sample List
signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Tail of Empty Sample List
signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Head of Empty Payload List
signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Oldest Sample (Head of Occupied Sample List)
signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Newest Sample (Tail of Occupied Sample List)
signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Highest Timestamp of all READ Samples
signal last_read_ts, last_read_ts_next : TIME_TYPE := TIME_INVALID;
-- Denotes if the oldest Sample should be removed
signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0';
-- Denotes if the oldest sample of the Instance with 'key_hash' should be removed
signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0';
-- Remote Writer ID
signal writer_id, writer_id_next : natural range 0 to MAX_REMOTE_ENDPOINTS-1 := 0;
-- Key Hash Latch
signal key_hash, key_hash_next : KEY_HASH_TYPE := HANDLE_NIL;
-- RTPS Return Code Latch
signal rtps_return_code_latch, rtps_return_code_latch_next : HISTORY_CACHE_RESPONSE_TYPE := ERROR;
-- DDS Return Code Latch
signal dds_return_code_latch, dds_return_code_latch_next : std_logic_vector(RETURN_CODE_WIDTH-1 downto 0) := RETCODE_ERROR;
-- Source Timestamp Latch
signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID;
-- Lifespan Latch
signal lifespan, lifespan_next : TIME_TYPE := TIME_INVALID;
-- Sample Status Info Latch
signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Payload Pointer
signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Payload Pointer
signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Sample Pointer
signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Sample Pointer
signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Sample Pointer
signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Sample Pointer
signal sample_addr_latch_4, sample_addr_latch_4_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Sample Pointer
signal sample_addr_latch_5, sample_addr_latch_5_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Instance Pointer
signal inst_addr_latch_1, inst_addr_latch_1_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Instance Pointer
signal inst_addr_latch_2, inst_addr_latch_2_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Long Latch
signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Signal used to pass Writer Bitmaps to Instance Memory Process
signal writer_bitmap : WRITER_BITMAP_ARRAY_TYPE := ZERO_WRITER_BITMAP_ARRAY;
-- Signal used to pass Sample Status Infos to Instance Memory Process
signal status_info_update : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Signal used to pass Generation Counters to the Instance Memory Process
signal gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Signal used to pass TIMEs to the Instance Memory Process
signal deadline : TIME_TYPE := TIME_INVALID;
-- Signal containing the relevant Instance Memory Frame Fields of the Instance Memory Operation
signal inst_mem_fields : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0');
-- Signal used to pass Instance Pointers to the Instance Memory Process
signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Signal used to pass Sample Counts to the Instance Memory Process
signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Signals start of Instance Memory Operation
signal inst_op_start : std_logic := '0';
-- Opcode of Instance Memory Operation (Valid only when inst_op_start is high)
signal inst_opcode : INSTANCE_OPCODE_TYPE := NOP;
-- Signals the end of an Instance Memory Operation
signal inst_op_done : std_logic := '0';
-- Time of next Sample Lifespan Check
signal lifespan_time, lifespan_time_next : TIME_TYPE := TIME_ZERO;
-- Signifies if a Lifespan Check is in progress
signal is_lifespan_check, is_lifespan_check_next : std_logic := '0';
-- Sample State Latch
signal sample_state, sample_state_next : std_logic_vector(SAMPLE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
-- View State Latch
signal view_state, view_state_next : std_logic_vector(VIEW_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
-- Instance State Latch
signal instance_state, instance_state_next : std_logic_vector(INSTANCE_STATE_KIND_WIDTH-1 downto 0) := (others => '0');
-- Instance Handle Latch
signal instance_handle, instance_handle_next : INSTANCE_HANDLE_TYPE := HANDLE_NIL;
-- Max Samples Latch
signal max_samples_latch, max_samples_latch_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
-- Denotes the current length of the Collection
signal collection_cnt, collection_cnt_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
-- Denotes the current pre-calculated length of the Collection
signal collection_cnt_max, collection_cnt_max_next : unsigned(MAX_SAMPLES_WIDTH-1 downto 0) := (others => '0');
-- Denotes the Generation Rank (For a collection of length collection_cnt_max)
signal collection_generation_rank, collection_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0');
-- Number of NOT_ALIVE->ALIVE Transitions during reception of selected Sample
signal cur_generation_rank, cur_generation_rank_next : unsigned(GENERATION_RANK_WIDTH-1 downto 0) := (others => '0');
-- Denotes if a TAKE operation is in progress
signal is_take, is_take_next : std_logic := '0';
-- NOTE: We use this signal to prevent the costly Instance Marking in the case that we only need to ouptput samples of one Instance.
-- Denotes if the READ/TAKE operation applies to a single Instance
signal single_instance, single_instance_next : std_logic := '0';
-- Denotes if the marks on Instances should be reset
signal unmark_instances_flag, unmark_instances_flag_next : std_logic := '0';
-- Denotes if the READ/TAKE operation does not apply to a specific Instance
signal dynamic_next_instance, dynamic_next_instance_next : std_logic := '0';
-- Signal containing the number of currently stale Instances
signal stale_inst_cnt, stale_inst_cnt_next : natural range 0 to to_integer(unsigned(MAX_INSTANCES))-1 := 0;
-- Test signal used for testbench synchronisation
signal idle_sig : std_logic := '0';
-- Signal denoting if the PRE_CALCULATE stage was run for the current instance
signal pre_calculated, pre_calculated_next : std_logic := '0';
-- Disposed Generation Count Latch
signal dis_gen_cnt_latch, dis_gen_cnt_latch_next : unsigned(WORD_WIDTH-1 downto 0) := (others => '0');
-- No Writers Generation Count Latch
signal no_w_gen_cnt_latch, no_w_gen_cnt_latch_next : unsigned(WORD_WIDTH-1 downto 0) := (others => '0');
-- Denotes if a newer sample of the same Instance exists
signal newer_inst_sample, newer_inst_sample_next : std_logic := '0';
-- Denotes if a new Instance is added
signal new_inst, new_inst_next : std_logic := '0';
-- Triggers Sample Generation
signal trigger_sample_gen, trigger_sample_gen_next : std_logic := '0';
-- Waits for Sample Removal (MAX_SAMPLES Limit lift) to trigger Sample Generation
signal wait_for_sample_removal, wait_for_sample_removal_next : std_logic := '0';
-- *COMMUNICATION STATUS*
signal status_sig, status_sig_next : std_logic_vector(STATUS_KIND_WIDTH-1 downto 0) := (others => '0');
-- SAMPLE REJECT STATUS
signal sample_rej_cnt, sample_rej_cnt_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
signal sample_rej_cnt_change, sample_rej_cnt_change_next : unsigned(SAMPLE_REJECTED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
signal sample_rej_last_reason, sample_rej_last_reason_next : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := (others =>'0');
signal sample_rej_last_inst, sample_rej_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0'));
-- REQUESTED DEADLINE MISSED STATUS
-- Time of next Deadline Miss Check
signal deadline_time, deadline_time_next : TIME_TYPE := TIME_ZERO;
signal deadline_miss_cnt, deadline_miss_cnt_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
signal deadline_miss_cnt_change, deadline_miss_cnt_change_next : unsigned(REQUESTED_DEADLINE_MISSED_STATUS_COUNT_WIDTH-1 downto 0) := (others => '0');
signal deadline_miss_last_inst, deadline_miss_last_inst_next : INSTANCE_HANDLE_TYPE := (others => (others => '0'));
-- *SAMPLE INFO*
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 := HANDLE_NIL;
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 : std_logic_vector(DISPOSED_GENERATION_COUNT_WIDTH-1 downto 0) := (others => '0');
signal si_no_writers_generation_count_sig, si_no_writers_generation_count_sig_next : std_logic_vector(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_rank_sig, si_absolute_generation_rank_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 eoc_sig, eoc_sig_next : std_logic := '0';
-- *INSTANCE MEMORY PROCESS*
-- Instance Memory FSM state
signal inst_stage, inst_stage_next : INST_STAGE_TYPE := IDLE;
-- Pointer to current relevant Instance Memory Frame Address
signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Pointer to next Instance Memory Frame Address
signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Pointer to previous Instacne Memory Address
signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Head of Empty Instance List
signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Head of Occupied Instance List
signal inst_occupied_head, inst_occupied_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Latch for Instance Data from main process
signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA;
-- NOTE: The next signal is driven by the inst_ctrl_prc. In case WITH_KEY is FALSE, no inst_ctrl_prc is generated and the inst_data is
-- set by the main process directly by drivng the next2 signal. The sync_prc is responsible for latching the corrct next signal.
-- Latch for Instance Data from memory
signal inst_data, inst_data_next, inst_data_next2 : INSTANCE_DATA_TYPE := ZERO_INSTANCE_DATA;
-- General Purpose Counter
signal inst_cnt, inst_cnt_next : natural range 0 to 21 := 0;
-- Counter used to read/write the Writer Bitmap
signal inst_cnt2, inst_cnt2_next : natural range 0 to WRITER_BITMAP_ARRAY_TYPE'length := 0;
-- General Purpose Long Latch
signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
-- Instance Memory Flag Array denoting which inst_data Fields are up-to-date with the respective fields of the Instance (Pointed by inst_addr_base)
signal current_imf, current_imf_next : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0');
--*****ALIAS DECLARATION*****
alias prev_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1;
alias prev_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next;
alias sel_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1;
alias sel_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 sample_p1 : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4;
alias sample_p1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_4_next;
alias sample_p2 : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_5;
alias sample_p2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_5_next;
alias cur_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1;
alias cur_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next;
alias next_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2;
alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next;
alias 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 first_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2;
alias first_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_2_next;
alias has_data : std_logic is sample_status_info(SSI_DATA_FLAG);
alias has_key_hash : std_logic is sample_status_info(SSI_KEY_HASH_FLAG);
-- *FUNCTION DECLARATION*
function from_writer_bitmap_array (input : WRITER_BITMAP_ARRAY_TYPE) return std_logic_vector is
variable ret : std_logic_vector(0 to WRITER_BITMAP_WIDTH-1) := (others => '0');
begin
for i in 0 to input'length-1 loop
ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i);
end loop;
return ret;
end function;
function to_writer_bitmap_array (input : std_logic_vector(0 to WRITER_BITMAP_WIDTH-1)) return WRITER_BITMAP_ARRAY_TYPE is
variable ret : WRITER_BITMAP_ARRAY_TYPE := ZERO_WRITER_BITMAP_ARRAY;
begin
for i in 0 to ret'length-1 loop
ret(i) := input(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1);
end loop;
return ret;
end function;
-- This function caps the range of a natural.
-- This is needed, because during simulation some values may be outside the range due to delta time delays.
function cap_range(input : in integer; max : in natural) return natural is
begin
if (input > max and SIMULATION_FLAG) then
return max;
elsif (input < 0 and SIMULATION_FLAG) then
return 0;
else
return input;
end if;
end function;
begin
--*****COMPONENT INSTANTIATION*****
sample_mem_ctrl_inst : entity work.mem_ctrl(arch)
generic map (
ADDR_WIDTH => SAMPLE_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => SAMPLE_MEMORY_SIZE,
MAX_BURST_LENGTH => SAMPLE_FRAME_SIZE
)
port map (
clk => clk,
reset => reset or sample_abort_read,
addr => std_logic_vector(sample_addr),
read => sample_read,
ready_in => sample_ready_in,
valid_in => sample_valid_in,
data_in => sample_write_data,
ready_out => sample_ready_out,
valid_out => sample_valid_out,
data_out => sample_read_data
);
payload_mem_ctrl_inst : entity work.mem_ctrl(arch)
generic map (
ADDR_WIDTH => PAYLOAD_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => PAYLOAD_MEMORY_SIZE,
MAX_BURST_LENGTH => PAYLOAD_FRAME_SIZE
)
port map (
clk => clk,
reset => reset or payload_abort_read,
addr => std_logic_vector(payload_addr),
read => payload_read,
ready_in => payload_ready_in,
valid_in => payload_valid_in,
data_in => payload_write_data,
ready_out => payload_ready_out,
valid_out => payload_valid_out,
data_out => payload_read_data
);
gen_instance_mem_ctrl_inst : if WITH_KEY generate
instance_mem_ctrl_inst : entity work.mem_ctrl(arch)
generic map (
ADDR_WIDTH => INSTANCE_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => INSTANCE_MEMORY_SIZE,
MAX_BURST_LENGTH => INSTANCE_FRAME_SIZE
)
port map (
clk => clk,
reset => reset or inst_abort_read,
addr => std_logic_vector(inst_addr),
read => inst_read,
ready_in => inst_ready_in,
valid_in => inst_valid_in,
data_in => inst_write_data,
ready_out => inst_ready_out,
valid_out => inst_valid_out,
data_out => inst_read_data
);
end generate;
si_sample_state <= si_sample_state_sig;
si_view_state <= si_view_state_sig;
si_instance_state <= si_instance_state_sig;
si_source_timestamp <= si_source_timestamp_sig;
si_instance_handle <= si_instance_handle_sig;
si_publication_handle <= si_publication_handle_sig;
si_disposed_generation_count <= si_disposed_generation_count_sig;
si_no_writers_generation_count <= si_no_writers_generation_count_sig;
si_sample_rank <= std_logic_vector(si_sample_rank_sig);
si_generation_rank <= std_logic_vector(si_generation_rank_sig);
si_absolute_generation_rank <= std_logic_vector(si_absolute_generation_rank_sig);
si_valid_data <= si_valid_data_sig;
si_valid <= si_valid_sig;
eoc <= eoc_sig;
status <= status_sig;
-- *Main State Machine*
-- STATE DESCRIPTION
-- IDLE Idle State. Initiates Deadline Miss Checks, Lifespan Expiry Checks, RTPS Operation handling, and DDS Operation handling, in that priority order.
-- RETURN_DDS Return latched DDS Return Code
-- RETURN_RTPS Return latched RTPS Return Code
-- ADD_SAMPLE_INFO Latch and store Cache Change (pre-payload)
-- ADD_PAYLOAD_ADDRESS Store payload pointer.
-- ADD_PAYLOAD Push payload to memory and key hash generator (as needed)
-- NEXT_PAYLOAD_SLOT Get pointer to next empty payload slot
-- ALIGN_PAYLOAD Store the offset of the actual payload in the last address of the last payload slot.
-- GET_KEY_HASH Fetch the calculated key hash from the Key Hash Generator
-- INITIATE_INSTANCE_SEARCH Initiate Instance Search Memory Operation. This state is used to start the Search operation as soon as the required data is available
-- FILTER_STAGE This state decides if the RTPS Cache Change is accepted, dropped, or rejected. It also decides what sample (if any) has to be removed.
-- UPDATE_INSTANCE Update the Data of the Instance of the received sample (Cache Change)
-- FINALIZE_PAYLOAD Finalize the payload addition (Update pointers)
-- PRE_SAMPLE_FINALIZE Store Sample Info based on Instance Data
-- FIND_POS Find Sample List position based on DESTINATION_ORDER_QOS
-- FIX_POINTERS Update the List Pointers of the inserted Sample neighbours (First Step of Sample Addition Finalization)
-- FINALIZE_SAMPLE Update inserted sample and list pointers. (Second Step of Sample Addition Finalization)
-- GENERATE_SAMPLE Generate a NOT_ALIVE_NO_WRITERS Sample
-- GET_OLDEST_SAMPLE_INSTANCE Fetch the Instance Data of the oldest sample
-- FIND_OLDEST_INST_SAMPLE Find the oldest sample of a specific Instance
-- REMOVE_SAMPLE Remove sample and linked payload
-- POST_SAMPLE_REMOVE Update Instance Data of removed sample. If Instance Memory is full, and Instance is now eligible for removal, it is removed.
-- SKIP_AND_RETURN Skip DDS Input and return latched Return Code
-- REMOVE_WRITER Unmark specified Writer Bitmap Position from all stored Instances. (Also updates Instance Data if necessary)
-- REMOVE_STALE_INSTANCE Find and remove the first eligible Instance in the memory
-- GET_NEXT_SAMPLE Find the next sample in the requested collection
-- PRE_CALCULATE Calculate ranks for the selected sample in the requested collection.
-- FINALIZE_SAMPLE_INFO Finalize the Sample Info Data, and present them.
-- GET_PAYLOAD Push linked Payload to output
-- FIND_NEXT_INSTANCE Find next Instance that passes requested masks
-- CHECK_INSTANCE Check if selected Instance passes requested masks
-- CHECK_LIFESPAN Check and remove samples with expired Lifespans
-- PROCESS_PENDING_SAMPLE_GENERATION Iterate through the Instances and Generate Samples where required
-- GET_SAMPLE_REJECTED_STATUS Return Sample Rejected Status
-- GET_REQUESTED_DEADLINE_MISSED_STATUS Return Requested Deadline Missed Status
-- CHECK_DEADLINE Check and Mark Instances with missed Deadlines
-- RESET_SAMPLE_MEMORY Reset Sample Memory to Empty State
-- RESET_PAYLOAD_MEMORY Reset Payload Memory to Empty State
parse_a_prc : process (all)
variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0'));
variable tmp_bitmap : std_logic_vector(0 to WRITER_BITMAP_WIDTH-1) := (others => '0');
variable tmp_update : std_logic_vector(0 to IMF_FLAG_WIDTH-1) := (others => '0');
variable tmp_bool : boolean := FALSE;
begin
-- DEFAULT Registered
stage_next <= stage;
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;
sample_addr_latch_3_next <= sample_addr_latch_3;
sample_addr_latch_4_next <= sample_addr_latch_4;
sample_addr_latch_5_next <= sample_addr_latch_5;
writer_id_next <= writer_id;
key_hash_next <= key_hash;
sample_status_info_next <= sample_status_info;
remove_oldest_sample_next <= remove_oldest_sample;
remove_oldest_inst_sample_next <= remove_oldest_inst_sample;
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_rank_sig_next <= si_absolute_generation_rank_sig;
si_valid_data_sig_next <= si_valid_data_sig;
si_valid_sig_next <= si_valid_sig;
eoc_sig_next <= eoc_sig;
sample_state_next <= sample_state;
view_state_next <= view_state;
instance_state_next <= instance_state;
instance_handle_next <= instance_handle;
max_samples_latch_next <= max_samples_latch;
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;
single_instance_next <= single_instance;
unmark_instances_flag_next <= unmark_instances_flag;
dynamic_next_instance_next <= dynamic_next_instance;
last_read_ts_next <= last_read_ts;
sample_rej_cnt_next <= sample_rej_cnt;
sample_rej_cnt_change_next <= sample_rej_cnt_change;
sample_rej_last_reason_next <= sample_rej_last_reason;
sample_rej_last_inst_next <= sample_rej_last_inst;
deadline_time_next <= deadline_time;
deadline_miss_cnt_next <= deadline_miss_cnt;
deadline_miss_cnt_change_next <= deadline_miss_cnt_change;
deadline_miss_last_inst_next <= deadline_miss_last_inst;
lifespan_time_next <= lifespan_time;
is_lifespan_check_next <= is_lifespan_check;
status_sig_next <= status_sig;
cnt_next <= cnt;
cnt2_next <= cnt2;
cnt3_next <= cnt3;
lifespan_next <= lifespan;
stale_inst_cnt_next <= stale_inst_cnt;
inst_data_next2 <= inst_data;
oldest_sample_next <= oldest_sample;
rtps_return_code_latch_next <= rtps_return_code_latch;
dds_return_code_latch_next <= dds_return_code_latch;
pre_calculated_next <= pre_calculated;
dis_gen_cnt_latch_next <= dis_gen_cnt_latch;
no_w_gen_cnt_latch_next <= no_w_gen_cnt_latch;
newer_inst_sample_next <= newer_inst_sample;
new_inst_next <= new_inst;
trigger_sample_gen_next <= trigger_sample_gen;
wait_for_sample_removal_next <= wait_for_sample_removal;
-- DEFAULT Unregistered
inst_opcode <= NOP;
opcode_kh <= NOP;
ret_rtps <= ERROR;
return_code_dds <= RETCODE_UNSUPPORTED;
ack_dds <= '0';
done_dds <= '0';
ack_rtps <= '0';
done_rtps <= '0';
inst_op_start <= '0';
sample_read <= '0';
sample_ready_out <= '0';
sample_valid_in <= '0';
sample_abort_read <= '0';
payload_read <= '0';
payload_ready_out <= '0';
payload_valid_in <= '0';
payload_abort_read <= '0';
ready_in_rtps <= '0';
start_kh <= '0';
abort_kh <= '0';
ready_in_kh <= '0';
valid_out_kh <= '0';
last_word_out_kh <= '0';
valid_out_dds <= '0';
last_word_out_dds <= '0';
idle_sig <= '0';
data_out_dds <= (others => '0');
data_out_kh <= (others => '0');
writer_bitmap <= ZERO_WRITER_BITMAP_ARRAY;
inst_addr_update <= (others => '0');
sample_addr <= (others => '0');
sample_write_data <= (others => '0');
payload_addr <= (others => '0');
payload_write_data <= (others => '0');
case (stage) is
when IDLE =>
idle_sig <= '1';
-- Reset
new_inst_next <= '0';
newer_inst_sample_next <= '0';
remove_oldest_inst_sample_next <= '0';
remove_oldest_sample_next <= '0';
is_take_next <= '0';
key_hash_next <= HANDLE_NIL;
-- DEADLINE QoS
if (DEADLINE_QOS /= DURATION_INFINITE and deadline_time <= time) then
-- Reset Timeout
deadline_time_next <= deadline_time + DEADLINE_QOS;
-- Synthesis Guard
if (WITH_KEY) then
stage_next <= CHECK_DEADLINE;
cnt_next <= 0;
else
if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then
-- Reset Liveliness Flag
inst_data_next2.status_info(ISI_LIVELINESS_FLAG) <= '0';
else
-- Update Requested Deadline Missed Status
status_sig_next <= status_sig or REQUESTED_DEADLINE_MISSED_STATUS;
deadline_miss_cnt_next <= deadline_miss_cnt + 1;
deadline_miss_cnt_change_next <= deadline_miss_cnt_change + 1;
end if;
end if;
-- LIFESPAN QoS
elsif (lifespan_time <= time) then
-- Reset Timeout
lifespan_time_next <= TIME_INFINITE;
-- Samples Available
if (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
cur_sample_next <= oldest_sample;
stage_next <= CHECK_LIFESPAN;
cnt_next <= 0;
end if;
-- Sample Generation
elsif (trigger_sample_gen = '1') then
-- Synthesis Guard
if (WITH_KEY) then
stage_next <= PROCESS_PENDING_SAMPLE_GENERATION;
cnt_next <= 0;
else
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
if (empty_sample_list_head = empty_sample_list_tail) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
wait_for_sample_removal_next <= '1';
-- Reset
trigger_sample_gen_next <= '0';
-- DONE
stage_next <= IDLE;
else
-- Reset
trigger_sample_gen_next <= '0';
-- Update Instance
inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '0';
inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1;
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
cur_sample_next <= empty_sample_list_head;
cur_inst_next <= inst_addr_base;
stage_next <= GENERATE_SAMPLE;
cnt_next <= 0;
end if;
else
-- Reset
trigger_sample_gen_next <= '0';
-- Update Instance
inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '0';
inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1;
cur_sample_next <= empty_sample_list_head;
cur_inst_next <= inst_addr_base;
stage_next <= GENERATE_SAMPLE;
cnt_next <= 0;
end if;
end if;
-- RTPS Operation
elsif (start_rtps = '1') then
case (opcode_rtps) is
when ADD_CACHE_CHANGE =>
-- NOTE: We have to explicitly check the Payload Memory, as it may be "unaligned" with our Sample Memory
-- (Sample Memory has available Slot, but Payload Memory not)
-- Payload Memory Full
if (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
ack_rtps <= '1';
-- Reject Change
stage_next <= SKIP_AND_RETURN;
cnt_next <= 0;
rtps_return_code_latch_next <= REJECTED;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_PAYOAD_MEMORY_LIMIT;
sample_rej_last_inst_next <= HANDLE_NIL;
else
assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
-- Do not ACK Operation
ack_dds <= '0';
remove_oldest_sample_next <= '1';
if (WITH_KEY) then
stage_next <= GET_OLDEST_SAMPLE_INSTANCE;
cnt_next <= 0;
else
cur_sample_next <= oldest_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
end if;
else
ack_rtps <= '1';
stage_next <= ADD_SAMPLE_INFO;
cur_sample_next <= empty_sample_list_head;
cnt_next <= 0;
end if;
when REMOVE_WRITER =>
ack_rtps <= '1';
-- Synthesis Guard
if (WITH_KEY) then
-- Latch Writer Pos
writer_id_next <= to_integer(unsigned(data_in_rtps));
stage_next <= REMOVE_WRITER;
cnt_next <= 2;
else
-- Convert Writer Bitmap to SLV
tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap);
-- Remove Writer
tmp_bitmap(to_integer(unsigned(data_in_rtps))) := '0';
-- Convert Back
inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
-- NOT_ALIVE_NO_WRITERS Transition
if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
trigger_sample_gen_next <= '1';
inst_data_next2.status_info(ISI_GENERATE_SAMPLE_FLAG) <= '1';
inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
end if;
stage_next <= RETURN_RTPS;
rtps_return_code_latch_next <= OK;
end if;
when others =>
null;
end case;
-- Unmark Instances
elsif (WITH_KEY and unmark_instances_flag = '1') then
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= UNMARK_INSTANCES;
unmark_instances_flag_next <= '0';
end if;
-- DDS Operation
elsif (start_dds = '1') then
-- Latch Input Signals
sample_state_next <= sample_state_dds;
view_state_next <= view_state_dds;
instance_state_next <= instance_state_dds;
max_samples_latch_next <= unsigned(max_samples_dds);
-- Reset
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
pre_calculated_next <= '0';
single_instance_next <= '0' when WITH_KEY else '1';
dynamic_next_instance_next <= '0';
collection_cnt_next <= (others => '0');
collection_cnt_max_next <= (others => '0');
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 <= HANDLE_NIL;
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';
eoc_sig_next <= '0';
si_absolute_generation_rank_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';
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
cur_sample_next <= oldest_sample;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
if (unsigned(max_samples_dds) = 1) then
single_instance_next <= '1';
end if;
end if;
when TAKE =>
ack_dds <= '1';
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
is_take_next <= '1';
cur_sample_next <= oldest_sample;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
if (unsigned(max_samples_dds) = 1) then
single_instance_next <= '1';
end if;
end if;
when READ_NEXT_SAMPLE =>
ack_dds <= '1';
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
single_instance_next <= '1';
cur_sample_next <= oldest_sample;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
sample_state_next <= NOT_READ_SAMPLE_STATE;
view_state_next <= ANY_VIEW_STATE;
instance_state_next <= ANY_INSTANCE_STATE;
max_samples_latch_next <= to_unsigned(1, max_samples_latch'length);
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
end if;
when TAKE_NEXT_SAMPLE =>
ack_dds <= '1';
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
is_take_next <= '1';
single_instance_next <= '1';
cur_sample_next <= oldest_sample;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
sample_state_next <= NOT_READ_SAMPLE_STATE;
view_state_next <= ANY_VIEW_STATE;
instance_state_next <= ANY_INSTANCE_STATE;
max_samples_latch_next <= to_unsigned(1, max_samples_latch'length);
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
end if;
when READ_INSTANCE =>
ack_dds <= '1';
-- Synthesis Guard
if (WITH_KEY) then
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
single_instance_next <= '1';
cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds;
stage_next <= CHECK_INSTANCE;
cnt_next <= 0;
end if;
else
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION;
end if;
when TAKE_INSTANCE =>
ack_dds <= '1';
-- Synthesis Guard
if (WITH_KEY) then
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
is_take_next <= '1';
single_instance_next <= '1';
cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds;
stage_next <= CHECK_INSTANCE;
cnt_next <= 0;
end if;
else
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION;
end if;
when READ_NEXT_INSTANCE =>
ack_dds <= '1';
-- Synthesis Guard
if (WITH_KEY) then
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
single_instance_next <= '1';
dynamic_next_instance_next <= '1';
cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds;
stage_next <= FIND_NEXT_INSTANCE;
cnt_next <= 0;
end if;
else
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION;
end if;
when TAKE_NEXT_INSTANCE =>
ack_dds <= '1';
-- Synthesis Guard
if (WITH_KEY) then
-- No Samples Available
if (oldest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_NO_DATA;
else
is_take_next <= '1';
single_instance_next <= '1';
dynamic_next_instance_next <= '1';
cur_sample_next <= oldest_sample;
key_hash_next <= instance_handle_dds;
stage_next <= FIND_NEXT_INSTANCE;
cnt_next <= 0;
end if;
else
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_ILLEGAL_OPERATION;
end if;
when GET_SAMPLE_REJECTED_STATUS =>
ack_dds <= '1';
stage_next <= GET_SAMPLE_REJECTED_STATUS;
cnt_next <= 0;
when GET_REQUESTED_DEADLINE_MISSED_STATUS =>
ack_dds <= '1';
stage_next <= GET_REQUESTED_DEADLINE_MISSED_STATUS;
cnt_next <= 0;
when others =>
ack_dds <= '1';
stage_next <= RETURN_DDS;
dds_return_code_latch_next <= RETCODE_UNSUPPORTED;
end case;
end if;
when RETURN_DDS =>
done_dds <= '1';
return_code_dds <= dds_return_code_latch;
-- DONE
stage_next <= IDLE;
when RETURN_RTPS =>
done_rtps <= '1';
ret_rtps <= rtps_return_code_latch;
-- DONE
stage_next <= IDLE;
when ADD_SAMPLE_INFO =>
-- Precondition: cur_sample set
case (cnt) is
-- SET Status Info
when 0 =>
-- Input Guard
if (valid_in_rtps = '1') then
-- NOTE: The PAYLOAD_FLAG and KEY_HASH_FLAG are set by the RTPS Reader
-- NOTE: The ALIGNED_FLAG is set by default. if actual Payload is not aligned, need to reset.
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_write_data <= data_in_rtps;
sample_write_data(SSI_KEY_HASH_FLAG) <= '0'; -- Key Hash Flag is not stored
sample_write_data(SSI_READ_FLAG) <= '0';
sample_write_data(SSI_ALIGNED_FLAG) <= data_in_rtps(SSI_DATA_FLAG);
-- Latch Status Info
sample_status_info_next <= data_in_rtps;
sample_status_info_next(SSI_READ_FLAG) <= '0';
sample_status_info_next(SSI_ALIGNED_FLAG) <= data_in_rtps(SSI_DATA_FLAG);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
ready_in_rtps <= '1';
cnt_next <= cnt + 1;
end if;
end if;
-- SET Timestamp 1/2
when 1 =>
-- Input Guard
if (valid_in_rtps = '1') then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET;
sample_write_data <= data_in_rtps;
-- Latch Timestamp
ts_latch_next(0) <= unsigned(data_in_rtps);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
ready_in_rtps <= '1';
cnt_next <= cnt + 1;
end if;
end if;
-- SET Timestamp 2/2
when 2 =>
-- Input Guard
if (valid_in_rtps = '1') then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
sample_write_data <= data_in_rtps;
-- Latch Timestamp
ts_latch_next(1) <= unsigned(data_in_rtps);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
ready_in_rtps <= '1';
cnt_next <= cnt + 1;
-- 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
-- last read sample.
-- Timestamp is smaller than highest last read (Or is Invalid)
if (tmp_dw = TIME_INVALID or (tmp_dw /= TIME_INVALID and tmp_dw < last_read_ts)) then
-- Drop Sample
rtps_return_code_latch_next <= OK;
stage_next <= SKIP_AND_RETURN;
cnt_next <= 0;
end if;
end if;
end if;
end if;
-- SET Lifespan Deadline 1/2
when 3 =>
-- Input Guard
if (valid_in_rtps = '1') then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET;
sample_write_data <= data_in_rtps;
-- Latch Lifespan
lifespan_next(0) <= unsigned(data_in_rtps);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
ready_in_rtps <= '1';
cnt_next <= cnt + 1;
end if;
end if;
-- SET Lifespan Deadline 2/2
when 4 =>
-- Input Guard
if (valid_in_rtps = '1') then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1;
sample_write_data <= data_in_rtps;
-- Latch Lifespan
lifespan_next(1) <= unsigned(data_in_rtps);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
ready_in_rtps <= '1';
-- Skip Key Hash, if not available
if (has_key_hash = '0') then
cnt_next <= 9;
else
cnt_next <= cnt + 1;
end if;
end if;
end if;
-- Key Hash 1/4
when 5 =>
-- Input Guard
if (valid_in_rtps = '1') then
ready_in_rtps <= '1';
-- Latch Input, but do not pass to Memory
key_hash_next(0) <= data_in_rtps;
cnt_next <= cnt + 1;
end if;
-- Key Hash 2/4
when 6 =>
-- Input Guard
if (valid_in_rtps = '1') then
ready_in_rtps <= '1';
-- Latch Input, but do not pass to Memory
key_hash_next(1) <= data_in_rtps;
cnt_next <= cnt + 1;
end if;
-- Key Hash 3/4
when 7 =>
-- Input Guard
if (valid_in_rtps = '1') then
ready_in_rtps <= '1';
-- Latch Input, but do not pass to Memory
key_hash_next(2) <= data_in_rtps;
cnt_next <= cnt + 1;
end if;
-- Key Hash 4/4
when 8 =>
-- Input Guard
if (valid_in_rtps = '1') then
ready_in_rtps <= '1';
-- Latch Input, but do not pass to Memory
key_hash_next(3) <= data_in_rtps;
cnt_next <= cnt + 1;
end if;
-- Writer Endpoint Position
when 9 =>
-- Input Guard
if (valid_in_rtps = '1') then
ready_in_rtps <= '1';
-- Latch Input, but do not pass to Memory
writer_id_next <= cap_range(to_integer(unsigned(data_in_rtps)), MAX_REMOTE_ENDPOINTS-1);
cnt_next <= cnt + 1;
end if;
-- SET Payload Address
when 10 =>
assert (empty_payload_list_head /= PAYLOAD_MEMORY_MAX_ADDRESS) severity FAILURE;
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
if (has_data = '1') then
-- Store Payload Address
sample_write_data <= std_logic_vector(resize(empty_payload_list_head, WORD_WIDTH));
cur_payload_next <= empty_payload_list_head;
else
-- Mark Sample with no Payload
sample_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS, WORD_WIDTH));
end if;
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- If Key Hash is available, start the Instance Search first
if (WITH_KEY and has_key_hash = '1') then
stage_next <= INITIATE_INSTANCE_SEARCH;
-- Key Hash Needs to be Calculated
elsif (WITH_KEY and has_key_hash = '0') then
cnt_next <= cnt + 1;
elsif (has_data = '1') then
assert (not WITH_KEY) severity FAILURE;
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
cnt2_next <= 1;
else -- has_data = '0'
assert (not WITH_KEY) severity FAILURE;
stage_next <= FILTER_STAGE;
end if;
end if;
-- Initiate KH Operation
when 11 =>
-- Synthesis Guard
if (WITH_KEY) then
start_kh <= '1';
-- Payload is Serialized Key
if (has_data = '0') then
opcode_kh <= PUSH_SERIALIZED_KEY;
else
opcode_kh <= PUSH_DATA;
end if;
if (ack_kh = '1') then
-- Payload is Serialized Key
if (has_data = '0') then
stage_next <= ADD_PAYLOAD;
cnt_next <= 1;
else
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
cnt2_next <= 1;
end if;
end if;
end if;
when others =>
null;
end case;
when ADD_PAYLOAD =>
-- Precondition (if has_data = '1'): cur_payload set (Current Slot)
-- 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 [Entered from INITIATE_INSTANCE_SEARCH]
-- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow) [Entered from ADD_PAYLOAD_ADDRESS]
-- 0 0 There is no payload to write, but the input contains the key for the KHG [Entered from ADD_PAYLOAD_ADDRESS]
case (cnt) is
-- Push to memory
when 0 =>
-- Input Guard
if (valid_in_rtps = '1') then
payload_valid_in <= '1';
payload_addr <= cur_payload + cnt2;
payload_write_data <= data_in_rtps;
-- Memory Control Flow Guard
if (payload_ready_in = '1') then
-- Key Hash needs to be calculated
if (WITH_KEY and has_key_hash = '0') then
cnt_next <= cnt + 1;
else
ready_in_rtps <= '1';
-- End of Payload
if (last_word_in_rtps = '1') then
-- End of Payload Slot
if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
stage_next <= FILTER_STAGE;
else
stage_next <= ALIGN_PAYLOAD;
cnt_next <= 0;
end if;
else
-- End of Payload Slot
if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
stage_next <= NEXT_PAYLOAD_SLOT;
cnt_next <= 0;
else
-- Next Word
cnt2_next <= cnt2 + 1;
end if;
end if;
end if;
end if;
end if;
-- Push to KHG
when 1 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Input Guard
if (valid_in_rtps = '1') then
valid_out_kh <= '1';
data_out_kh <= data_in_rtps;
-- Output Guard
if (ready_out_kh = '1') then
ready_in_rtps <= '1';
if (has_data = '1') then
-- End of Payload
if (last_word_in_rtps = '1') then
last_word_out_kh <= '1';
-- End of Payload Slot
if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
-- Fetch the Key Hash
stage_next <= GET_KEY_HASH;
cnt_next <= 0;
cnt2_next <= 0;
else
stage_next <= ALIGN_PAYLOAD;
cnt_next <= 0;
end if;
else
-- End of Payload Slot
if (cnt2 = PAYLOAD_FRAME_SIZE-1) then
stage_next <= NEXT_PAYLOAD_SLOT;
cnt_next <= 0;
else
-- Next Word
cnt_next <= 0;
cnt2_next <= cnt2 + 1;
end if;
end if;
else
-- End of Payload
if (last_word_in_rtps = '1') then
last_word_out_kh <= '1';
-- Fetch the Key Hash
stage_next <= GET_KEY_HASH;
cnt_next <= 0;
cnt2_next <= 0;
else
-- Next Word
cnt_next <= 1; -- Same Sub-state
end if;
end if;
end if;
end if;
end if;
when others =>
null;
end case;
when NEXT_PAYLOAD_SLOT =>
-- Precondition: cur_payload set
case (cnt) is
-- GET Next Pointer
when 0 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
payload_read <= '1';
-- Memory Control Flow Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next Pointer
when 1 =>
payload_ready_out <= '1';
-- Memory Control Flow Guard
if (payload_valid_out = '1') then
-- No Empty Payload Slots available
if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- Reject Change
rtps_return_code_latch_next <= REJECTED;
stage_next <= SKIP_AND_RETURN;
cnt_next <= 0;
-- Abort Key Hash Generation
abort_kh <= '1';
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_PAYOAD_MEMORY_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
-- Latch next Payload Slot and Continue
cur_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
cnt2_next <= 1;
end if;
end if;
when others =>
null;
end case;
when ALIGN_PAYLOAD =>
case (cnt) is
-- Mark Payload as unaligned
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_write_data <= sample_status_info;
sample_write_data(SSI_ALIGNED_FLAG) <= '0';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- Store Payload End Offset
when 1 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1;
payload_write_data <= std_logic_vector(to_unsigned(cnt2, WORD_WIDTH));
-- Memory Control Flow Guard
if (payload_ready_in = '1') then
if (WITH_KEY and has_key_hash = '0') then
stage_next <= GET_KEY_HASH;
cnt_next <= 0;
cnt2_next <= 0;
else
stage_next <= FILTER_STAGE;
end if;
end if;
when others =>
null;
end case;
when GET_KEY_HASH =>
-- Synthesis Guard
if (WITH_KEY) then
case (cnt) is
-- Initiate READ Operation
when 0 =>
start_kh <= '1';
opcode_kh <= READ_KEY_HASH;
if (ack_kh = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Key Hash
when 1 =>
ready_in_kh <= '1';
if (valid_in_kh = '1') then
cnt2_next <= cnt2 + 1;
-- Latch Key Hash
key_hash_next(cnt2) <= data_in_kh;
-- Exit Condition
if (last_word_in_kh = '1') then
-- DONE
stage_next <= INITIATE_INSTANCE_SEARCH;
end if;
end if;
when others =>
null;
end case;
end if;
when INITIATE_INSTANCE_SEARCH =>
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= SEARCH_INSTANCE_HASH;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG or IMF_IGNORE_DEADLINE_FLAG or IMF_WRITER_BITMAP_FLAG;
-- Payload not yet stored
if (has_data = '1' and WITH_KEY and has_key_hash = '1') then
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
cnt2_next <= 1;
else
stage_next <= FILTER_STAGE;
end if;
end if;
end if;
when FILTER_STAGE =>
-- Precondition: cur_sample set, inst_data set (IMF_STATUS_FLAG, IMF_IGNORE_DEADLINE_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG)
-- Wait for Instance Search to finish
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_IGNORE_DEADLINE_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE;
-- Instance Found
if (not WITH_KEY or inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Latch Instance Pointer
cur_inst_next <= inst_addr_base;
-- Latch Instance Generation Counters
dis_gen_cnt_latch_next <= inst_data.disposed_gen_cnt;
no_w_gen_cnt_latch_next <= inst_data.no_writers_gen_cnt;
-- TIME_BASED_FILTER QOS
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time < inst_data.ignore_deadline) then
-- Drop Change
done_rtps <= '1';
ret_rtps <= OK;
stage_next <= IDLE;
-- Pending Sample Generation
-- NOTE: If there is a Pending Sample Generation and we reach this stage, the limiting factor is still here and the Sample will be rejected.
-- In order to have a valid sample rejected status it makes sense to let the sample be rejected "naturally".
--elsif (inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then
-- -- Reject Change
-- done_rtps <= '1';
-- ret_rtps <= REJECTED;
-- stage_next <= IDLE;
-- -- Update Sample Reject Status
-- status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
-- sample_rej_cnt_next <= sample_rej_cnt + 1;
-- sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
-- sample_rej_last_reason_next <= REJECTED_BY_PENDING_SAMPLE_GENERATION;
-- sample_rej_last_inst_next <= key_hash;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
elsif (WITH_KEY and MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(MAX_SAMPLES_PER_INSTANCE)) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change
done_rtps <= '1';
ret_rtps <= REJECTED;
stage_next <= IDLE;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_PER_INSTANCE_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
-- Accept Change (Remove Oldest Instance Sample)
remove_oldest_inst_sample_next <= '1';
done_rtps <= '1';
ret_rtps <= OK;
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
stage_next <= UPDATE_INSTANCE;
end if;
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
done_rtps <= '1';
ret_rtps <= REJECTED;
stage_next <= IDLE;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
done_rtps <= '1';
ret_rtps <= OK;
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
stage_next <= UPDATE_INSTANCE;
end if;
end if;
else
-- Accept Change
done_rtps <= '1';
ret_rtps <= OK;
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
stage_next <= UPDATE_INSTANCE;
end if;
end if;
else -- (only WITH_KEY)
new_inst_next <= '1';
-- Latch Instance Pointer
cur_inst_next <= inst_empty_head;
-- Ignore UNREGISTER/FILTERED Samples on Unknown Instances
if (sample_status_info(SSI_UNREGISTERED_FLAG) = '1' or sample_status_info(SSI_FILTERED_FLAG) = '1') then
-- Drop Change
done_rtps <= '1';
ret_rtps <= OK;
-- DONE
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
done_rtps <= '1';
ret_rtps <= REJECTED;
stage_next <= IDLE;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_SAMPLES_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
-- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
-- No Stale Instances available
if (stale_inst_cnt = 0) then
-- Reject Change
done_rtps <= '1';
ret_rtps <= REJECTED;
-- DONE
stage_next <= IDLE;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_INSTANCES_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
done_rtps <= '1';
ret_rtps <= OK;
-- Remove Stale Instance and Insert Instance
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
stage_next <= REMOVE_STALE_INSTANCE;
cnt_next <= 0;
end if;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
done_rtps <= '1';
ret_rtps <= OK;
-- Insert New Instance
inst_op_start <= '1';
inst_opcode <= INSERT_INSTANCE;
status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0');
sample_cnt <= to_unsigned(1, WORD_WIDTH);
deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID;
tmp_bitmap := (others => '0');
tmp_bitmap(writer_id) := '1';
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
if (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
end if;
end if;
end if;
else
-- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
-- No Stale Instances available
if (stale_inst_cnt = 0) then
-- Reject Change
done_rtps <= '1';
ret_rtps <= REJECTED;
-- DONE
stage_next <= IDLE;
-- Update Sample Reject Status
status_sig_next <= status_sig or SAMPLE_REJECTED_STATUS;
sample_rej_cnt_next <= sample_rej_cnt + 1;
sample_rej_cnt_change_next <= sample_rej_cnt_change + 1;
sample_rej_last_reason_next <= REJECTED_BY_INSTANCES_LIMIT;
sample_rej_last_inst_next <= key_hash;
else
done_rtps <= '1';
ret_rtps <= OK;
-- Remove Stale Instance and Insert Instance
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
stage_next <= REMOVE_STALE_INSTANCE;
cnt_next <= 0;
end if;
else
-- Accept Change
done_rtps <= '1';
ret_rtps <= OK;
-- Insert New Instance
inst_op_start <= '1';
inst_opcode <= INSERT_INSTANCE;
status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0');
sample_cnt <= to_unsigned(1, WORD_WIDTH);
deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID;
tmp_bitmap := (others => '0');
tmp_bitmap(writer_id) := '1';
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
if (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
end if;
end if;
end if;
end if;
end if;
when FIND_POS =>
-- Synthesis Guard
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
-- Precondition: cur_sample set
case (cnt) is
-- GET Timestamp 1/2
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Timestamp 2/2
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Previous Sample
when 2 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Instance Pointer
when 3 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Timestamp 1/2
when 4 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
long_latch_next <= sample_read_data;
cnt_next <= cnt + 1;
end if;
-- READ Timestamp 2/2
when 5 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
-- Found position (After current slot)
if (ts_latch >= tmp_dw) then
sample_abort_read <= '1';
prev_sample_next <= cur_sample;
cur_sample_next <= empty_sample_list_head;
if (new_inst = '1') then
if (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
else
stage_next <= UPDATE_INSTANCE;
end if;
else
cnt_next <= cnt + 1;
end if;
end if;
-- READ Previous Sample Pointer
when 6 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
prev_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Instance Poiner
when 7 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Sample has Same Instance
if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = cur_inst) then
-- Newer Sample of same Instance found
newer_inst_sample_next <= '1';
-- NOT_ALIVE Sample
if (sample_status_info(SSI_DISPOSED_FLAG) = '1' or sample_status_info(SSI_UNREGISTERED_FLAG) = '1') then
-- NOTE: We drop Dispose and Unregister Samples if a newer Sample of the same Instance exists, because else
-- the Instance State and Generation Counters would have to be recalculated (by crawling through all the Instance Samples)
-- Drop Sample
stage_next <= IDLE;
else
cnt_next <= cnt + 1;
end if;
else
-- No previous Slot (Oldest Sample)
if (prev_sample = PAYLOAD_MEMORY_MAX_ADDRESS) then
assert (cur_sample = oldest_sample) severity FAILURE;
-- NOTE: Sample is added to HEAD of List
next_sample_next <= cur_sample;
cur_sample_next <= empty_sample_list_head;
if (new_inst = '1') then
if (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
else
stage_next <= UPDATE_INSTANCE;
end if;
else
-- Continue Search
cur_sample_next <= prev_sample;
next_sample_next <= cur_sample;
cnt_next <= 0;
end if;
end if;
end if;
-- GET Disposed Generation Count
when 8 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET No Writers Generation Count
when 9 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Disposed Generation Count
when 10 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Latch Generation Counter
dis_gen_cnt_latch_next <= unsigned(sample_read_data);
cnt_next <= cnt + 1;
end if;
-- READ No Writers Generation Count
when 11 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Latch Generation Counter
no_w_gen_cnt_latch_next <= unsigned(sample_read_data);
-- Continue Search
cur_sample_next <= prev_sample;
next_sample_next <= cur_sample;
cnt_next <= 0;
end if;
when others =>
null;
end case;
end if;
when UPDATE_INSTANCE =>
-- Precondition inst_data set (IMF_STATUS_FLAG, IMF_WRITER_BITMAP_FLAG, IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG, IMF_SAMPLE_CNT_FLAG, IMF_IGNORE_DEADLINE_FLAG)
-- Mark if Sample is stored in memory
tmp_bool := TRUE;
-- Memory Operation Guard
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_IGNORE_DEADLINE_FLAG) severity FAILURE;
-- DEFAULT STATUS INFO (LIVELINESS)
if (WITH_KEY) then
tmp_update := IMF_STATUS_FLAG;
status_info_update <= inst_data.status_info;
status_info_update(ISI_LIVELINESS_FLAG) <= '1';
else
inst_data_next2.status_info(ISI_LIVELINESS_FLAG) <= '1';
end if;
-- *WRITER BITMAP*
-- Convert Writer Bitmap to SLV
tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap);
-- ALIVE/FILTERED/DISPOSE Operation
if (sample_status_info(SSI_UNREGISTERED_FLAG) /= '1') then
-- Write if Writer New for Instance
if (tmp_bitmap(writer_id) /= '1') then
-- Insert Writer
tmp_bitmap(writer_id) := '1';
-- Convert Back
-- Synthesis Guard
if (WITH_KEY) then
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG;
else
inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
end if;
end if;
else
-- Write if Writer New for Instance
if (tmp_bitmap(writer_id) /= '0') then
-- Insert Writer
tmp_bitmap(writer_id) := '0';
-- Convert Back
-- Synthesis Guard
if (WITH_KEY) then
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
tmp_update := tmp_update or IMF_WRITER_BITMAP_FLAG;
else
inst_data_next2.writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
end if;
end if;
end if;
-- *GENERATION COUNTERS / VIEW STATE*
-- Only Update Instance State if Sample if newest
if (newer_inst_sample = '0') then
-- NOT_ALIVE_DISPOSED -> ALIVE Transition
if (sample_status_info(SSI_DISPOSED_FLAG) = '0' and sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then
-- Synthesis Guard
if (WITH_KEY) then
tmp_update := tmp_update or IMF_DISPOSED_CNT_FLAG;
gen_cnt <= inst_data.disposed_gen_cnt + 1;
status_info_update(ISI_VIEW_FLAG) <= '0';
else
inst_data_next2.disposed_gen_cnt <= inst_data.disposed_gen_cnt + 1;
inst_data_next2.status_info(ISI_VIEW_FLAG) <= '0';
end if;
-- NOT_ALIVE_NO_WRITERS -> ALIVE Transition OR NOT_ALIVE_NO_WRITERS -> NOT_ALIVE_DISPOSED Transition
elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
-- Synthesis Guard
if (WITH_KEY) then
tmp_update := tmp_update or IMF_NO_WRITERS_CNT_FLAG;
gen_cnt <= inst_data.no_writers_gen_cnt + 1;
status_info_update(ISI_VIEW_FLAG) <= '0';
else
inst_data_next2.no_writers_gen_cnt <= inst_data.no_writers_gen_cnt + 1;
inst_data_next2.status_info(ISI_VIEW_FLAG) <= '0';
end if;
end if;
end if;
-- *STATUS INFO*
-- * -> NOT_ALIVE_DISPOSED Transition
if (sample_status_info(SSI_DISPOSED_FLAG) = '1') then
-- NOT_ALIVE_DISPOSED -> NOT_ALIVE_DISPOSED
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then
tmp_bool := FALSE;
-- Only Update Instance State if Sample if newest
elsif (newer_inst_sample = '0') then
-- Synthesis Guard
if (WITH_KEY) then
status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1';
status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
else
inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '1';
inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
end if;
end if;
-- * -> NOT_ALIVE_NO_WRITERS Transition
elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '1' and tmp_bitmap = (tmp_bitmap'reverse_range => '0')) then
-- NOT_ALIVE -> NOT_ALIVE_NO_WRITERS
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_bool := FALSE;
-- Only Update Instance State if Sample if newest
elsif (newer_inst_sample = '0') then
-- Synthesis Guard
if (WITH_KEY) then
status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0';
status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
else
inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
end if;
end if;
-- * -> ALIVE Transition
elsif (sample_status_info(SSI_UNREGISTERED_FLAG) = '0' and sample_status_info(SSI_DISPOSED_FLAG) = '0') then
-- ALIVE -> ALIVE
if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) /= '1') then
-- Filtered Sample
if (sample_status_info(SSI_FILTERED_FLAG) = '1') then
tmp_bool := FALSE;
else
assert (has_data = '1') severity FAILURE;
end if;
-- Only Update Instance State if Sample if newest
elsif (newer_inst_sample = '0') then
-- Synthesis Guard
if (WITH_KEY) then
status_info_update(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0';
status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
else
inst_data_next2.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_data_next2.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
end if;
end if;
else
tmp_bool := FALSE;
end if;
-- *INSTANCE SAMPLE COUNT*
if (tmp_bool) then
-- Synthesis Guard
if (WITH_KEY) then
tmp_update := tmp_update or IMF_SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt + 1;
else
inst_data_next2.sample_cnt <= inst_data.sample_cnt + 1;
end if;
end if;
-- *IGNORE DEADLINE*
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
-- Synthesis Guard
if (WITH_KEY) then
tmp_update := tmp_update or IMF_IGNORE_DEADLINE_FLAG;
deadline <= time + TIME_BASED_FILTER_QOS;
else
inst_data_next2.ignore_deadline <= time + TIME_BASED_FILTER_QOS;
end if;
end if;
-- *STALE INSTANCE COUNT*
if (tmp_bool) then
-- Synthesis Guard
if (WITH_KEY) then
-- Instance was Stale
if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then
assert (stale_inst_cnt /= 0) severity FAILURE;
-- NOTE: The UPDATE_INSTANCE state is only taken if a new Sample is added to an existing Instance.
-- Since Instances with Samples are not stale, we have to unmark the Instance.
stale_inst_cnt_next <= stale_inst_cnt - 1;
end if;
end if;
else
-- Synthesis Guard
if (WITH_KEY) then
-- Stale Instance Transition
if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap /= ZERO_WRITER_BITMAP_ARRAY and tmp_bitmap = (tmp_bitmap'reverse_range => '0')) then
stale_inst_cnt_next <= stale_inst_cnt + 1;
end if;
end if;
end if;
-- Synthesis Guard
if (WITH_KEY) then
-- UPDATE Instance
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= tmp_update;
end if;
if (not tmp_bool) then
-- DONE (Drop Sample)
stage_next <= IDLE;
elsif (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
end if;
when FINALIZE_PAYLOAD =>
-- Precondition: cur_payload set
case (cnt) is
-- GET Next Pointer
when 0 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
payload_read <= '1';
-- Memory Control Flow Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- Next Pointer
when 1 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
-- Make current Slot the Tail
payload_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH));
-- Memory Control Flow Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next Pointer
when 2 =>
payload_ready_out <= '1';
-- Memory Control Flow Guard
if (payload_valid_out = '1') then
-- Fix New Empty List Head
empty_payload_list_head_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
when others =>
null;
end case;
when PRE_SAMPLE_FINALIZE =>
-- Precondition: cur_sample set, inst_data set (IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG)
-- Wait for instance Update to Complete
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE;
case (cnt) is
-- SET Disposed Generation Counter
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
if (newer_inst_sample = '1') then
sample_write_data <= std_logic_vector(dis_gen_cnt_latch);
else
sample_write_data <= std_logic_vector(inst_data.disposed_gen_cnt);
end if;
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET No Writer Generation Counter
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
if (newer_inst_sample = '1') then
sample_write_data <= std_logic_vector(no_w_gen_cnt_latch);
else
sample_write_data <= std_logic_vector(inst_data.no_writers_gen_cnt);
end if;
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- First Sample
if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FINALIZE_SAMPLE;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cnt_next <= 0;
elsif (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
stage_next <= FIX_POINTERS;
if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
cnt_next <= 1; -- Skip to Previous Pointer Fix
else
cnt_next <= 0;
end if;
else
stage_next <= FIX_POINTERS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
end if;
when FIX_POINTERS =>
-- Precondition: prev_sample set, next_sample set
case (cnt) is
-- Next Pointer (Previous Sample)
when 0 =>
-- Fix Next Pointer
sample_valid_in <= '1';
sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- No next Slot (Newest Sample)
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE;
stage_next <= FINALIZE_SAMPLE;
cur_sample_next <= empty_sample_list_head;
cnt_next <= 0;
else
cnt_next <= 1;
end if;
end if;
-- Previous Pointer (Next Sample)
when 1 =>
-- Fix Previous Pointer
sample_valid_in <= '1';
sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
stage_next <= FINALIZE_SAMPLE;
cur_sample_next <= empty_sample_list_head;
cnt_next <= 0;
end if;
when others =>
null;
end case;
when FINALIZE_SAMPLE =>
-- Precondition: prev_sample set, next_sample set, cur_sample set
case (cnt) is
-- GET Next (Empty) Sample
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- Synthesis Guard
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
cnt_next <= cnt + 2;
end if;
end if;
-- SET Instance Pointer
when 1 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Write Instance Pointer
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(cur_inst,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
end if;
-- SET Previous Pointer
when 2 =>
-- Write Previous Pointer
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Next Pointer
when 3 =>
-- Write Next Pointer
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(next_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next (Empty) Sample
when 4 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Fix new Empty List Head
empty_sample_list_head_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
-- If newest Sample is now previous, select current sample as new newest
if (newest_sample = prev_sample) then
newest_sample_next <= cur_sample;
end if;
-- If current Sample as no predecessor, it is the oldest
if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
oldest_sample_next <= cur_sample;
end if;
-- Signal Data Available
status_sig_next <= status_sig or DATA_AVAILABLE_STATUS;
-- Update Lifespan Check Time
if (lifespan /= TIME_INVALID and lifespan < lifespan_time) then
lifespan_time_next <= lifespan;
end if;
if (WITH_KEY and remove_oldest_inst_sample = '1') then
assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
cur_sample_next <= oldest_sample;
stage_next <= FIND_OLDEST_INST_SAMPLE;
cnt_next <= 0;
elsif (remove_oldest_sample = '1') then
assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
-- Synthesis Guard
if (WITH_KEY) then
stage_next <= GET_OLDEST_SAMPLE_INSTANCE;
cnt_next <= 0;
else
cur_sample_next <= oldest_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
else
-- DONE
stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when GENERATE_SAMPLE =>
-- Precondition: cur_sample set, cur_inst set, inst_data set (IMF_DISPOSED_CNT_FLAG, IMF_NO_WRITERS_CNT_FLAG)
-- Wait for Instane Data
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG) severity FAILURE;
case (cnt) is
-- GET Next Sample (Empty List)
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Sample Status Info
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_write_data <= (SSI_UNREGISTERED_FLAG => '1', others => '0');
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Timestamp 1/2
when 2 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET;
sample_write_data <= std_logic_vector(time(0));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Timestamp 2/2
when 3 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
sample_write_data <= std_logic_vector(time(1));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Lifespan 1/2
when 4 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET;
sample_write_data <= std_logic_vector(TIME_INVALID(0));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Lifespan 2/2
when 5 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1;
sample_write_data <= std_logic_vector(TIME_INVALID(1));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Payload Pointer
when 6 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Instance Pointer
when 7 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(cur_inst,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Disposed Generation Count
when 8 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
sample_write_data <= std_logic_vector(inst_data.disposed_gen_cnt);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET No Writers Generation Count
when 9 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
sample_write_data <= std_logic_vector(inst_data.no_writers_gen_cnt);
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Previous Sample Pointer
when 10 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(newest_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Next Sample Pointer
when 11 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
assert (newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
cnt_next <= cnt + 1;
end if;
-- SET Next Sample Pointer (Previous Sample)
when 12 =>
sample_valid_in <= '1';
sample_addr <= newest_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(empty_sample_list_head,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next Address (Empty List)
when 13 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Update Sample List Pointer
newest_sample_next <= cur_sample;
empty_sample_list_head_next <= resize(unsigned(sample_read_data), SAMPLE_MEMORY_ADDR_WIDTH);
-- Signal Data Available
status_sig_next <= status_sig or DATA_AVAILABLE_STATUS;
if (WITH_KEY and remove_oldest_inst_sample = '1') then
assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
cur_sample_next <= oldest_sample;
stage_next <= FIND_OLDEST_INST_SAMPLE;
cnt_next <= 0;
elsif (remove_oldest_sample = '1') then
assert (oldest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) severity FAILURE;
-- Synthesis Guard
if (WITH_KEY) then
stage_next <= GET_OLDEST_SAMPLE_INSTANCE;
cnt_next <= 0;
else
cur_sample_next <= oldest_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
elsif (trigger_sample_gen = '1') then
-- Continue
stage_next <= PROCESS_PENDING_SAMPLE_GENERATION;
cnt_next <= 1;
else
-- DONE
stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
end if;
when GET_OLDEST_SAMPLE_INSTANCE =>
-- Synthesis Guard
if (WITH_KEY) then
case (cnt) is
-- GET Instance Pointer (Oldest Sample)
when 0 =>
sample_valid_in <= '1';
sample_addr <= oldest_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Instance Pointer (Oldest Sample)
when 1 =>
-- Memory Operation Guard
if (inst_op_done = '1') then
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
cur_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
cur_sample_next <= oldest_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
end if;
when FIND_OLDEST_INST_SAMPLE =>
-- Precondition: cur_sample set
-- Synthesis Guard
if (WITH_KEY) then
case (cnt) is
-- GET Instance Pointer
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Next Sample
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Instance Pointer
when 2 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
-- Oldest Instance Sample Found
if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = cur_inst) then
sample_abort_read <= '1';
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
else
cnt_next <= cnt + 1;
end if;
end if;
-- READ Next Sample
when 3 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
cur_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= 0;
end if;
when others =>
null;
end case;
end if;
when REMOVE_SAMPLE =>
-- Precondition: cur_sample set, cur_inst set
case (cnt) is
-- GET Instance Data
when 0 =>
if (not WITH_KEY or (cur_inst = inst_addr_base and check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG))) then
cnt_next <= cnt + 1;
else
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= GET_INSTANCE;
inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG;
inst_addr_update <= cur_inst;
cnt_next <= cnt + 1;
end if;
end if;
-- GET Previous Sample
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Next Sample
when 2 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Payload Pointer
when 3 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
sample_read <= '1';
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Previous Sample
when 4 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
prev_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Next Sample
when 5 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
-- Sample Memory Full
if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
empty_sample_list_head_next <= cur_sample;
empty_sample_list_tail_next <= cur_sample;
cnt_next <= cnt + 2; --Skip Next Step
else
cnt_next <= cnt + 1;
end if;
end if;
-- SET Next Pointer (Empty List Tail)
when 6 =>
-- Add Current Sample after Empty List Tail
sample_valid_in <= '1';
sample_addr <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(cur_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- SET Next Pointer (Current Sample)
when 7 =>
-- Make Current Sample Empty List Tail
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- Fix Empty List Pointers
empty_sample_list_tail_next <= cur_sample;
-- Current Sample is Newest (Occupied List Tail)
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
assert (cur_sample = newest_sample) 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 = SAMPLE_MEMORY_MAX_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;
-- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR)
-- Fix Oldest Pointer
oldest_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cnt_next <= cnt + 3; -- Skip next 2 steps
else
cnt_next <= cnt + 2; -- Skip next step
end if;
else
cnt_next <= cnt + 1;
end if;
end if;
-- SET Previous Address (Next Sample)
when 8 =>
-- Remove link to cur_sample
sample_valid_in <= '1';
sample_addr <= next_sample + SMF_PREV_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
-- Current Sample is oldest sample (List Head)
if (prev_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
-- Fix Oldest Pointer
oldest_sample_next <= next_sample;
cnt_next <= cnt + 2; -- Skip next step
else
cnt_next <= cnt + 1;
end if;
end if;
-- SET Next Address (Previous Sample)
when 9 =>
-- Remove link to cur_sample
sample_valid_in <= '1';
sample_addr <= prev_sample + SMF_NEXT_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(next_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Payload Pointer
when 10 =>
sample_ready_out <= '1';
-- Memory Flow Control Guard
if (sample_valid_out = '1') then
cur_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
-- Sample has no Data
if (resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then
stage_next <= POST_SAMPLE_REMOVE;
-- Payload Memory Full
elsif (empty_payload_list_head = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- Fix Empty List Head
empty_payload_list_head_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
stage_next <= POST_SAMPLE_REMOVE;
else
-- Latch First Payload Slot for later use
first_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
end if;
-- GET Next Payload
when 11 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
payload_read <= '1';
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next Payload
when 12 =>
payload_ready_out <= '1';
-- Memory Flow Control Guard
if (payload_valid_out = '1') then
-- Found Empty List Tail
if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS) then
cnt_next <= cnt + 1;
else
cur_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
cnt_next <= cnt - 1;
end if;
end if;
-- SET Next Payload Pointer (Last Payload of Current Sample)
when 13 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
payload_write_data <= std_logic_vector(resize(empty_payload_list_head,WORD_WIDTH));
-- Fix Empty List Head
empty_payload_list_head_next <= first_payload;
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
stage_next <= POST_SAMPLE_REMOVE;
end if;
when others =>
null;
end case;
when POST_SAMPLE_REMOVE =>
-- Precondition: inst_data set (IMF_SAMPLE_CNT_FLAG, IMF_WRITER_BITMAP_FLAG, IMF_STATUS_FLAG)
-- Memory Operation Guard
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG) severity FAILURE;
-- Synthesis Guard
if (WITH_KEY) then
-- Stale Instance Update
if (inst_data.sample_cnt = 1 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then
stale_inst_cnt_next <= stale_inst_cnt + 1;
end if;
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt - 1;
else
inst_data_next2.sample_cnt <= inst_data.sample_cnt - 1;
end if;
if (wait_for_sample_removal = '1' or inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then
trigger_sample_gen_next <= '1';
-- Reset
wait_for_sample_removal_next <= '0';
end if;
-- Reset
remove_oldest_inst_sample_next <= '0';
remove_oldest_sample_next <= '0';
if (is_take = '1') then
-- cur_inst has no more samples in collection
if (si_sample_rank_sig = 0) then
-- Skipped Sample available
if (sample_p2 /= SAMPLE_MEMORY_MAX_ADDRESS) then
cur_sample_next <= sample_p2;
else
cur_sample_next <= sample_p1;
end if;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
pre_calculated_next <= '0';
else
cur_sample_next <= sample_p1;
end if;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
-- Continue Processing
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
elsif (is_lifespan_check = '1') then
-- Reached End of Samples
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Continue Search
cur_sample_next <= next_sample;
stage_next <= CHECK_LIFESPAN;
cnt_next <= 0;
end if;
elsif (trigger_sample_gen = '1') then
-- Continue
stage_next <= PROCESS_PENDING_SAMPLE_GENERATION;
cnt_next <= 1;
else
-- DONE
stage_next <= IDLE;
end if;
end if;
when SKIP_AND_RETURN =>
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 <= cnt + 1;
end if;
-- Return Code
when 1 =>
done_rtps <= '1';
ret_rtps <= rtps_return_code_latch;
-- DONE
stage_next <= IDLE;
when others =>
null;
end case;
when REMOVE_WRITER =>
-- Precondition: inst_data set (IMF_WRITER_BITMAP_FLAG, IMF_STATUS_FLAG, IMF_SAMPLE_CNT_FLAG)
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
case (cnt) is
when 0 =>
assert check_mask(current_imf, IMF_WRITER_BITMAP_FLAG or IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG) severity FAILURE;
-- No More Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
done_rtps <= '1';
ret_rtps <= OK;
stage_next <= IDLE;
else
-- Convert Writer Bitmap to SLV
tmp_bitmap := from_writer_bitmap_array(inst_data.writer_bitmap);
-- Remove Writer
tmp_bitmap(writer_id) := '0';
-- NOTE: writer_bitmap is not latched, since the memory process is latching it at the
-- same clock cycle.
-- Convert Back
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
-- NOT_ALIVE_NO_WRITERS Transition
if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
trigger_sample_gen_next <= '1';
status_info_update <= inst_data.status_info;
status_info_update(ISI_NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '1';
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_WRITER_BITMAP_FLAG;
else
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_WRITER_BITMAP_FLAG;
end if;
-- Update Stale Instance Count
if (tmp_bitmap = (tmp_bitmap'reverse_range => '0') and inst_data.sample_cnt = 0) then
stale_inst_cnt_next <= stale_inst_cnt + 1;
end if;
-- Continue
cnt_next <= 1;
end if;
when 1 =>
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
stage_next <= REMOVE_WRITER;
cnt_next <= 0;
when 2 =>
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
stage_next <= REMOVE_WRITER;
cnt_next <= 0;
when others =>
null;
end case;
end if;
end if;
when REMOVE_STALE_INSTANCE =>
-- Precondition: inst_data set (IMF_SAMPLE_CNT_FLAG, IMF_WRITER_BITMAP_FLAG)
-- Synthesis Guard
if (WITH_KEY) then
-- Wait for Instance Data
if (inst_op_done = '1') then
case (cnt) is
-- Find and Remove First Stale Instance
when 0 =>
assert check_mask(current_imf, IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG) severity FAILURE;
-- Iterated through all Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- NOTE: We should enter this state only if there is at least one stale Instance to be removed, so we should never enter this branch.
assert FALSE severity FAILURE;
stage_next <= IDLE;
else
-- Found Stale Instance (No Samples and No Active Writers)
if (inst_data.sample_cnt = 0 and inst_data.writer_bitmap = ZERO_WRITER_BITMAP_ARRAY) then
-- Remove Stale Instance
inst_op_start <= '1';
inst_opcode <= REMOVE_INSTANCE;
-- Update Stale Instance Count
stale_inst_cnt_next <= stale_inst_cnt - 1;
cnt_next <= cnt + 1;
else
-- Continue Search
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
end if;
end if;
-- Insert New Instance
when 1 =>
inst_op_start <= '1';
inst_opcode <= INSERT_INSTANCE;
status_info_update <= (ISI_LIVELINESS_FLAG => '1', ISI_NOT_ALIVE_DISPOSED_FLAG => sample_status_info(SSI_DISPOSED_FLAG), others => '0');
sample_cnt <= to_unsigned(1, WORD_WIDTH);
deadline <= (time + TIME_BASED_FILTER_QOS) when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else TIME_INVALID;
tmp_bitmap := (others => '0');
tmp_bitmap(writer_id) := '1';
writer_bitmap <= to_writer_bitmap_array(tmp_bitmap);
-- Latch Instance Pointer
cur_inst_next <= inst_empty_head;
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS and newest_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FIND_POS;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= newest_sample;
cur_sample_next <= newest_sample;
cnt_next <= 0;
else
if (has_data = '1') then
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
end if;
end if;
when GET_NEXT_SAMPLE =>
-- Precondition: cur_sample set, cur_inst set, si_sample_rank_sig set
case (cnt) is
-- GET Next Sample
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Status Info
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
-- Synthesis Guard
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
cnt_next <= cnt + 2; -- Skip Next Step
end if;
end if;
-- GET Instance Pointer
when 2 =>
-- Synthesis Guard
if (WITH_KEY) then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
end if;
-- READ Next Sample
when 3 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Status Info
when 4 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
tmp_bool := TRUE;
-- Check Sample State
case (sample_state) is
when READ_SAMPLE_STATE =>
if (sample_read_data(SSI_READ_FLAG) /= '1') then
tmp_bool := FALSE;
end if;
when NOT_READ_SAMPLE_STATE =>
if (sample_read_data(SSI_READ_FLAG) /= '0') then
tmp_bool := FALSE;
end if;
when ANY_SAMPLE_STATE =>
null;
-- Uknown Sample State
when others =>
tmp_bool := FALSE;
end case;
-- Latch Sample Status Info
sample_status_info_next <= sample_read_data;
if (sample_read_data(SSI_READ_FLAG) = '1') then
si_sample_state_sig_next <= READ_SAMPLE_STATE;
else
si_sample_state_sig_next <= NOT_READ_SAMPLE_STATE;
end if;
-- Sample Passes Checks
if (tmp_bool) then
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
-- First Instance Sample
-- NOTE: If sample rank is bigger than zero, we have already accepted the instance.
if (si_sample_rank_sig = 0) then
cnt_next <= cnt + 3; --Skip to Check Instance State
else
-- Select Sample
collection_cnt_next <= collection_cnt + 1;
sel_sample_next <= cur_sample;
-- Latch Next Sample (For resume purposes)
sample_p1_next <= next_sample;
si_sample_rank_sig_next <= si_sample_rank_sig - 1;
cnt_next <= cnt + 4; --Skip all Instance Related States
end if;
end if;
else
-- Sample not in collection, Skip Sample
cnt_next <= 18;
sample_abort_read <= '1';
end if;
end if;
-- READ Instance Pointer
when 5 =>
-- Synthesis Guard
if (WITH_KEY) then
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Instance pre-selected
if (cur_inst /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Sample has different Instance
if (cur_inst /= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH)) then
-- Consecutive Instance Sample Order
if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then
-- Skip Sample
cnt_next <= 18;
sample_abort_read <= '1';
-- Latch first skipped Sample
if (sample_p2 = SAMPLE_MEMORY_MAX_ADDRESS) then
sample_p2_next <= cur_sample;
end if;
else
-- Get Instance Data
next_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
else
-- Select Sample
collection_cnt_next <= collection_cnt + 1;
sel_sample_next <= cur_sample;
-- Latch Next Sample (For resume purposes)
sample_p1_next <= next_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_next <= si_sample_rank_sig - 1;
end if;
-- Skip Instance Operation
cnt_next <= cnt + 3;
end if;
else
-- Get Instance Data
next_inst_next <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
end if;
end if;
-- Get Instance Data
when 6 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= GET_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
inst_addr_update <= next_inst;
cnt_next <= cnt + 1;
end if;
end if;
-- Check Instance Data
when 7 =>
-- Wait for Instance Data
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
assert (next_inst = inst_addr_base) severity FAILURE;
-- DEFAULT
tmp_bool := TRUE;
-- Check Instance State
case (instance_state) is
when ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_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(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') 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(ISI_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_next <= (others => '0');
cur_inst_next <= next_inst;
sel_sample_next <= cur_sample;
-- Latch Next Sample (For resume purposes)
sample_p1_next <= next_sample;
cnt_next <= cnt + 1;
-- Reset
pre_calculated_next <= '0';
else
if (WITH_KEY) then
-- Skip Sample
cnt_next <= 18;
sample_abort_read <= '1';
else
-- Instance does not pass Checks
done_dds <= '1';
return_code_dds <= RETCODE_NO_DATA;
stage_next <= IDLE;
end if;
end if;
end if;
-- GET Timestamp 1/2
when 8 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Timestamp 2/2
when 9 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_TIMESTAMP_OFFSET + 1;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Payload Pointer
when 10 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Disposed Generation Count
when 11 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET No Writers Generation Count
when 12 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Timestamp 1/2
when 13 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
si_source_timestamp_sig_next(0) <= unsigned(sample_read_data);
cnt_next <= cnt + 1;
end if;
-- READ Timestamp 2/2
when 14 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
si_source_timestamp_sig_next(1) <= unsigned(sample_read_data);
cnt_next <= cnt + 1;
end if;
-- READ Payload Pointer
when 15 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Latch Payload Address
cur_payload_next <= resize(unsigned(sample_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Disposed Generation Count
when 16 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
si_disposed_generation_count_sig_next <= sample_read_data;
cnt_next <= cnt + 1;
end if;
-- READ No Writers Generation Count
when 17 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
si_no_writers_generation_count_sig_next <= sample_read_data;
cur_generation_rank_next <= unsigned(si_disposed_generation_count_sig) + unsigned(sample_read_data);
if (pre_calculated = '0') then
-- Reset
collection_generation_rank_next <= unsigned(si_disposed_generation_count_sig) + unsigned(sample_read_data);
end if;
cnt_next <= cnt + 1;
end if;
-- Exit State
when 18 =>
-- Exit Condition (Sample Selected)
if (sel_sample /= SAMPLE_MEMORY_MAX_ADDRESS) then
-- Sample not marked as Read
if (sample_status_info(SSI_READ_FLAG) /= '1') then
-- Mark Sample as Read
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_write_data <= sample_status_info;
sample_write_data(SSI_READ_FLAG) <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
-- Pre-Calculation already done for selected Instance (Or not necessary)
if (pre_calculated = '1' or collection_cnt_max = max_samples_latch or next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FINALIZE_SAMPLE_INFO;
cnt_next <= 0;
else
-- Calculate Instance Sample Ranks
cur_sample_next <= next_sample;
stage_next <= PRE_CALCULATE;
cnt_next <= 0;
end if;
end if;
else
-- Pre-Calculation already done for selected Instance (Or not necessary)
if (pre_calculated = '1' or collection_cnt_max = max_samples_latch or next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FINALIZE_SAMPLE_INFO;
cnt_next <= 0;
else
-- Calculate Instance Sample Ranks
cur_sample_next <= next_sample;
stage_next <= PRE_CALCULATE;
cnt_next <= 0;
end if;
end if;
-- First Sample Selected
if (collection_cnt = 1) then
done_dds <= '1';
return_code_dds <= RETCODE_OK;
end if;
else
-- End of Samples
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
-- Collection Empty
if (collection_cnt = 0) then
-- READ_NEXT_INSTANCE/TAKE_NEXT_INSTANCE Operation
if (WITH_KEY and 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
-- Mark End of Collection
eoc_sig_next <= '1';
stage_next <= IDLE;
-- Consecutive Instance Sample Order of multiple Instances
if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0') then
-- Unmark Instances
unmark_instances_flag_next <= '1';
end if;
end if;
else
-- Continue Searching
cur_sample_next <= next_sample;
cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
when PRE_CALCULATE =>
-- Precondition: cur_sample set, cur_inst set
case (cnt) is
-- GET Next Sample
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Status Info
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_STATUS_INFO_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
-- Synthesis Guard
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
cnt_next <= cnt + 2; --Skip Next Step
end if;
end if;
-- GET Instance Pointer
when 2 =>
-- Synthesis Guard
if (WITH_KEY) then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
end if;
-- GET Disposed Generation Count
when 3 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_DISPOSED_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET No Writers Generation Count
when 4 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NO_WRITERS_GEN_CNT_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Next Sample
when 5 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Status Info
when 6 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
tmp_bool := TRUE;
-- Check Sample State
case (sample_state) is
when READ_SAMPLE_STATE =>
if (sample_read_data(SSI_READ_FLAG) /= '1') then
tmp_bool := FALSE;
end if;
when NOT_READ_SAMPLE_STATE =>
if (sample_read_data(SSI_READ_FLAG) /= '0') then
tmp_bool := FALSE;
end if;
when ANY_SAMPLE_STATE =>
null;
-- Uknown Sample State
when others =>
tmp_bool := FALSE;
end case;
-- Sample Passes Checks
if (tmp_bool) then
-- Synthesis Guard
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
-- 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;
cnt_next <= cnt + 2; --Skip Next Step
end if;
else
-- Skip Sample
cnt_next <= 12;
sample_abort_read <= '1';
end if;
end if;
-- READ Instance Pointer
when 7 =>
-- Synthesis Guard
if (WITH_KEY) then
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Same Instance
if (resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = 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;
cnt_next <= cnt + 1;
else
-- Consecutive Instance Sample Order
if (not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS or single_instance = '1') then
-- Skip Sample
cnt_next <= 12;
sample_abort_read <= '1';
else
-- Check New Instance
cnt_next <= cnt + 3;
sample_abort_read <= '1';
end if;
end if;
end if;
end if;
-- READ Disposed Generation Count
when 8 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Calculate highest collection generation rank
collection_generation_rank_next <= unsigned(sample_read_data);
cnt_next <= cnt + 1;
end if;
-- READ No Writers Generation Count
when 9 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Calculate highest collection generation rank
collection_generation_rank_next <= collection_generation_rank + unsigned(sample_read_data);
-- Skip Instance Check
cnt_next <= cnt + 3;
end if;
-- Get Instance Data
when 10 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= GET_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
inst_addr_update <= next_inst;
cnt_next <= cnt + 1;
end if;
end if;
-- Check Instance Data
when 11 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Wait for Instance Data
if (inst_op_done = '1') then
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
assert (next_inst = inst_addr_base) severity FAILURE;
-- DEFAULT
tmp_bool := TRUE;
-- Check Instance State
case (instance_state) is
when ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_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(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') 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(ISI_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;
cnt_next <= cnt + 1;
end if;
end if;
-- Exit State
when 12 =>
-- Exit Condition (Reached End of Samples or Collection Fully Precalculated)
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS or collection_cnt_max = max_samples_latch) then
stage_next <= FINALIZE_SAMPLE_INFO;
cnt_next <= 0;
pre_calculated_next <= '1';
else
-- Continue with next Sample
cur_sample_next <= next_sample;
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 =>
-- Wait for Instance Data
if (not WITH_KEY or inst_op_done = '1') then
-- Instance Data valid
if (not WITH_KEY or (inst_addr_base = cur_inst and check_mask(current_imf,IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG))) then
-- Sample Info View State
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') 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(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1') then
si_instance_state_sig_next <= NOT_ALIVE_DISPOSED_INSTANCE_STATE;
elsif (inst_data.status_info(ISI_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_absolute_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_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG;
inst_addr_update <= cur_inst;
end if;
end if;
-- Present Data
when 1 =>
-- 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;
-- Reset Data Available Status
status_sig_next <= status_sig and (not DATA_AVAILABLE_STATUS);
-- Wait on User
if (si_ack = '1') then
-- Sample Data Request
if (get_data_dds = '1') then
stage_next <= GET_PAYLOAD;
cnt_next <= 0;
else
cnt_next <= 2;
-- Invalidate Data
si_valid_sig_next <= '0';
end if;
end if;
-- Post-Present Data
when 2 =>
-- Memory Operation Guard
if (not WITH_KEY or inst_op_done = '1') then
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
-- 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 = 0) then
-- Synthesis Guard
if (WITH_KEY) then
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_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') then
-- Mark Instance
status_info_update(ISI_MARK_FLAG) <= '1';
end if;
-- Instance is NOT_VIEWED and sample is from last generation of Instance
if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_rank_sig = 0) then
-- Mark Instance as VIEWED
status_info_update(ISI_VIEW_FLAG) <= '1';
end if;
else
-- Instance is NOT_VIEWED and sample is from last generation of Instance
if (inst_data.status_info(ISI_VIEW_FLAG) = '0' and si_absolute_generation_rank_sig = 0) then
-- Mark Instance as VIEWED
inst_data_next2.status_info(ISI_VIEW_FLAG) <= '1';
end if;
end if;
end if;
-- End of Collection
if (collection_cnt = max_samples_latch or (sample_p1 = SAMPLE_MEMORY_MAX_ADDRESS and sample_p2 = SAMPLE_MEMORY_MAX_ADDRESS) or (si_sample_rank_sig = 0 and single_instance = '1')) then
-- Mark End of Collection
eoc_sig_next <= '1';
-- Consecutive Instance Sample Order of multiple Instances
if ((not ORDERED_ACCESS or PRESENTATION_QOS = INSTANCE_PRESENTATION_QOS) and single_instance = '0') then
-- Unmark Instances
unmark_instances_flag_next <= '1';
end if;
if (is_take = '1') then
cur_sample_next <= sel_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
is_take_next <= '0'; -- Return to IDLE from REMOVE
else
-- DONE
stage_next <= IDLE;
end if;
else
if (is_take = '1') then
-- Remove Sample
cur_sample_next <= sel_sample;
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
else
-- cur_inst has no more samples in collection
if (si_sample_rank_sig = 0) then
-- Skipped Sample available
if (sample_p2 /= SAMPLE_MEMORY_MAX_ADDRESS) then
cur_sample_next <= sample_p2;
else
cur_sample_next <= sample_p1;
end if;
cur_inst_next <= INSTANCE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
pre_calculated_next <= '0';
else
cur_sample_next <= sample_p1;
end if;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
-- Continue Processing
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when GET_PAYLOAD =>
-- Precondition: cur_payload set, sample_status_info set
-- NOTE: We are using the Burst Capability of the Memory Controller as a FIFO which we
-- fill and the output is directly reading. cnt is switching the memory reading states,
-- cnt2 signals the offset of the payload read, and cnt3 signals how many Bytes have been
-- requested but not yet claimed (i.e. how many Bytes are in the FIFO).
-- DEFAULT
tmp_bool := FALSE;
case (cnt) is
-- GET Next Pointer
when 0 =>
-- NOTE: We have to make sure that no pending Reads are in the Memory Controler Buffer,
-- else the Next Payload Pointer cannot be read.
-- No Pending Reads
if (cnt3 = 0) then
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
payload_read <= '1';
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
end if;
-- READ Next Pointer
when 1 =>
payload_ready_out <= '1';
-- Memory Flow Control Guard
if (payload_valid_out = '1') then
next_payload_next <= resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH);
cnt2_next <= 1;
-- Last Payload Slot is unaligned
if (resize(unsigned(payload_read_data),PAYLOAD_MEMORY_ADDR_WIDTH) = PAYLOAD_MEMORY_MAX_ADDRESS and sample_status_info(SSI_ALIGNED_FLAG) = '0') then
cnt_next <= cnt + 1;
else
cnt_next <= cnt + 3;
long_latch_next <= std_logic_vector(to_unsigned(PAYLOAD_FRAME_SIZE-1,CDR_LONG_WIDTH));
end if;
end if;
-- GET Payload Offset
when 2 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PAYLOAD_FRAME_SIZE-1;
payload_read <= '1';
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- READ Payload Offset
when 3 =>
payload_ready_out <= '1';
-- Memory Flow Control Guard
if (payload_valid_out = '1') then
long_latch_next <= payload_read_data;
cnt_next <= cnt + 1;
end if;
-- GET PAYLOAD
when 4 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + cnt2;
payload_read <= '1';
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
cnt3_next <= cnt3 + 1;
tmp_bool := TRUE;
-- End of Payload Slot
if (cnt2 = unsigned(long_latch)) then
-- End of Payload
if (next_payload = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- DONE (Wait for Output to finidh reading)
cnt_next <= cnt + 1;
else
-- Next Payload Slot
cur_payload_next <= next_payload;
cnt_next <= 0;
end if;
else
cnt2_next <= cnt2 + 1;
end if;
end if;
when others =>
null;
end case;
-- Data available for Output
if (cnt3 /= 0) then
-- Memory Flow Control Guard
if (payload_valid_out = '1') then
valid_out_dds <= '1';
data_out_dds <= payload_read_data;
-- End of Payload
if (cnt3 = 1 and cnt = 5) then
last_word_out_dds <= '1';
end if;
-- DDS Read
if (ready_out_dds = '1') then
payload_ready_out <= '1';
-- NOTE: We are using the tmp_bool variable to signal if there is an increment
-- on the same clock cycle.
-- Increment in same clock cycle
if (tmp_bool) then
cnt3_next <= cnt3; -- Override increment
else
cnt3_next <= cnt3 - 1;
-- Exit Condition
if (cnt3 = 1 and cnt = 5) then
-- Exit
stage_next <= FINALIZE_SAMPLE_INFO;
cnt_next <= 2;
-- Invalidate Data
si_valid_sig_next <= '0';
end if;
end if;
end if;
end if;
end if;
when FIND_NEXT_INSTANCE =>
-- Synthesis Guard
if (WITH_KEY) then
-- Wait for Instance Data
if (inst_op_done = '1') then
case (cnt) is
when 0 =>
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
cnt_next <= 2;
when 1 =>
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
cnt_next <= 2;
when 2 =>
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
-- Instance Found
if (inst_addr_base /= INSTANCE_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(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_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(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') 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_next <= inst_addr_base;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
-- Reset
sel_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p1_next <= SAMPLE_MEMORY_MAX_ADDRESS;
sample_p2_next <= SAMPLE_MEMORY_MAX_ADDRESS;
else
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG;
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;
end if;
when CHECK_INSTANCE =>
-- Synthesis Guard
if (WITH_KEY) then
-- Wait for Instance Data
if (inst_op_done = '1') then
case (cnt) is
when 0 =>
-- NOTE: The Generation Counters are not used directly in this state, but will be needed by the FINALIZE_SAMPLE_INFO state.
inst_op_start <= '1';
inst_opcode <= SEARCH_INSTANCE_HASH;
inst_mem_fields <= IMF_STATUS_FLAG;
cnt_next <= cnt + 1;
when 1 =>
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
-- Instance Found
if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- DEFAULT
tmp_bool := TRUE;
-- Check Instance State
case (instance_state) is
when ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '1' or inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_DISPOSED_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_NO_WRITERS_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
tmp_bool := FALSE;
end if;
when NOT_ALIVE_INSTANCE_STATE =>
if (inst_data.status_info(ISI_NOT_ALIVE_DISPOSED_FLAG) = '0' and inst_data.status_info(ISI_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(ISI_VIEW_FLAG) = '1') then
tmp_bool := FALSE;
end if;
when NOT_NEW_VIEW_STATE =>
if (inst_data.status_info(ISI_VIEW_FLAG) = '0') 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_next <= inst_addr_base;
stage_next <= GET_NEXT_SAMPLE;
cnt_next <= 0;
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;
end if;
when CHECK_LIFESPAN =>
-- Precondition: cur_sample set,
case (cnt) is
-- GET Next Sample
when 0 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Lifespan 1/2
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- GET Lifespan 2/2
when 2 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_LIFESPAN_DEADLINE_OFFSET + 1;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
cnt_next <= cnt + 2; --Skip Next Step
end if;
end if;
-- GET Instance Pointer
when 3 =>
-- Synthesis Guard
if (WITH_KEY) then
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
sample_read <= '1';
-- Memory Control Flow Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
end if;
-- READ Next Sample
when 4 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
next_sample_next <= resize(unsigned(sample_read_data),SAMPLE_MEMORY_ADDR_WIDTH);
cnt_next <= cnt + 1;
end if;
-- READ Lifespan 1/2
when 5 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
long_latch_next <= sample_read_data;
cnt_next <= cnt + 1;
end if;
-- READ Lifespan 2/2
when 6 =>
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
-- Sample Lifespan Expired
if (tmp_dw /= TIME_INVALID and time >= tmp_dw) then
if (WITH_KEY) then
cnt_next <= cnt + 1;
else
-- Remove Sample
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
else
sample_abort_read <= '1';
-- Update Check Time
if (tmp_dw /= TIME_INVALID and tmp_dw < lifespan_time) then
lifespan_time_next <= tmp_dw;
end if;
-- Reached End of Samples
if (next_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Continue Search
cur_sample_next <= next_sample;
cnt_next <= 0;
end if;
end if;
end if;
-- READ Instance Pointer
when 7 =>
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
sample_ready_out <= '1';
-- Memory Control Flow Guard
if (sample_valid_out = '1') then
-- Fetch Instance Data
inst_op_start <= '1';
inst_opcode <= GET_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_WRITER_BITMAP_FLAG;
inst_addr_update <= resize(unsigned(sample_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
-- Remove Sample
stage_next <= REMOVE_SAMPLE;
cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when PROCESS_PENDING_SAMPLE_GENERATION =>
-- Synthesis Guard
if (WITH_KEY) then
-- 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_mem_fields <= IMF_STATUS_FLAG;
cnt_next <= cnt + 2;
when 1 =>
-- Continue
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
cnt_next <= cnt + 1;
when 2 =>
assert check_mask(current_imf, IMF_STATUS_FLAG) severity FAILURE;
-- Instance Found
if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Sample needs to be Generated
if (inst_data.status_info(ISI_GENERATE_SAMPLE_FLAG) = '1') then
-- GET Required Instance Data
inst_op_start <= '1';
inst_opcode <= GET_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG or IMF_DISPOSED_CNT_FLAG or IMF_NO_WRITERS_CNT_FLAG;
inst_addr_update <= inst_addr_base;
cnt_next <= cnt + 1;
else
-- Continue
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
end if;
else
-- Reset
trigger_sample_gen_next <= '0';
-- DONE
stage_next <= IDLE;
end if;
when 3 =>
assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG) severity FAILURE;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
if (WITH_KEY and MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = unsigned(MAX_SAMPLES_PER_INSTANCE)) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Continue
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
cnt_next <= 2;
else
-- Accept Change (Remove Oldest Instance Sample)
remove_oldest_inst_sample_next <= '1';
-- Update Instance
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt + 1;
status_info_update <= inst_data.status_info;
status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0';
cur_sample_next <= empty_sample_list_head;
cur_inst_next <= inst_addr_base;
stage_next <= GENERATE_SAMPLE;
cnt_next <= 0;
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
wait_for_sample_removal_next <= '1';
-- Reset
trigger_sample_gen_next <= '0';
-- DONE
stage_next <= IDLE;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
-- Update Instance
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt + 1;
status_info_update <= inst_data.status_info;
status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0';
cur_sample_next <= empty_sample_list_head;
cur_inst_next <= inst_addr_base;
stage_next <= GENERATE_SAMPLE;
cnt_next <= 0;
end if;
else
-- Update Instance
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG or IMF_SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt + 1;
status_info_update <= inst_data.status_info;
status_info_update(ISI_GENERATE_SAMPLE_FLAG) <= '0';
cur_sample_next <= empty_sample_list_head;
cur_inst_next <= inst_addr_base;
stage_next <= GENERATE_SAMPLE;
cnt_next <= 0;
end if;
when others =>
null;
end case;
end if;
end if;
when GET_SAMPLE_REJECTED_STATUS =>
case (cnt) is
-- Return Code
when 0 =>
done_dds <= '1';
return_code_dds <= RETCODE_OK;
cnt_next <= cnt + 1;
-- Total Count
when 1 =>
data_out_dds <= std_logic_vector(sample_rej_cnt);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Total Count Change
when 2 =>
data_out_dds <= std_logic_vector(sample_rej_cnt_change);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
-- Reset
sample_rej_cnt_change_next <= (others => '0');
cnt_next <= cnt + 1;
end if;
-- Last Reason
when 3 =>
data_out_dds <= sample_rej_last_reason;
valid_out_dds <= '1';
if (ready_out_dds = '1') then
-- Reset
sample_rej_last_reason_next <= NOT_REJECTED;
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 1/4
when 4 =>
data_out_dds <= sample_rej_last_inst(0);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 2/4
when 5 =>
data_out_dds <= sample_rej_last_inst(1);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 3/4
when 6 =>
data_out_dds <= sample_rej_last_inst(2);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 4/4
when 7 =>
data_out_dds <= sample_rej_last_inst(3);
valid_out_dds <= '1';
last_word_out_dds <= '1';
if (ready_out_dds = '1') then
-- Reset
sample_rej_last_inst_next <= HANDLE_NIL;
status_sig_next <= status_sig and (not SAMPLE_REJECTED_STATUS);
-- DONE
stage_next <= IDLE;
end if;
when others =>
null;
end case;
when GET_REQUESTED_DEADLINE_MISSED_STATUS =>
case (cnt) is
-- Return Code
when 0 =>
done_dds <= '1';
return_code_dds <= RETCODE_OK;
cnt_next <= cnt + 1;
-- Total Count
when 1 =>
data_out_dds <= std_logic_vector(deadline_miss_cnt);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Total Count Change
when 2 =>
data_out_dds <= std_logic_vector(deadline_miss_cnt_change);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
-- Reset
deadline_miss_cnt_change_next <= (others => '0');
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 1/4
when 3 =>
data_out_dds <= deadline_miss_last_inst(0);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 2/4
when 4 =>
data_out_dds <= deadline_miss_last_inst(1);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 3/4
when 5 =>
data_out_dds <= deadline_miss_last_inst(2);
valid_out_dds <= '1';
if (ready_out_dds = '1') then
cnt_next <= cnt + 1;
end if;
-- Last Instance Handle 4/4
when 6 =>
data_out_dds <= deadline_miss_last_inst(3);
valid_out_dds <= '1';
last_word_out_dds <= '1';
if (ready_out_dds = '1') then
-- Reset
deadline_miss_last_inst_next <= HANDLE_NIL;
status_sig_next <= status_sig and (not REQUESTED_DEADLINE_MISSED_STATUS);
-- DONE
stage_next <= IDLE;
end if;
when others =>
null;
end case;
when CHECK_DEADLINE =>
-- Synthesis Guard
if (WITH_KEY) then
-- Memory Operation Guard
if (inst_op_done = '1') then
case (cnt) is
-- Get First Instance
when 0 =>
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
cnt_next <= 2;
-- Get Next Instance
when 1 =>
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
inst_mem_fields <= IMF_KEY_HASH_FLAG or IMF_STATUS_FLAG;
cnt_next <= 2;
-- Check Instance
when 2 =>
assert check_mask(current_imf, IMF_STATUS_FLAG or IMF_KEY_HASH_FLAG) severity FAILURE;
-- Reached End of Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Instance received Sample
if (inst_data.status_info(ISI_LIVELINESS_FLAG) = '1') then
-- Reset Liveliness Flag
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
inst_mem_fields <= IMF_STATUS_FLAG;
status_info_update <= inst_data.status_info;
status_info_update(ISI_LIVELINESS_FLAG) <= '0';
cnt_next <= 1;
else
-- Update Requested Deadline Missed Status
status_sig_next <= status_sig or REQUESTED_DEADLINE_MISSED_STATUS;
deadline_miss_cnt_next <= deadline_miss_cnt + 1;
deadline_miss_cnt_change_next <= deadline_miss_cnt_change + 1;
deadline_miss_last_inst_next <= inst_data.key_hash;
cnt_next <= 1;
end if;
end if;
when others =>
null;
end case;
end if;
end if;
when RESET_SAMPLE_MEMORY =>
case (cnt) is
-- Initialize
when 0 =>
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cur_sample_next <= (others => '0');
cnt_next <= cnt + 1;
-- Set Previous Pointer
when 1 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_PREV_ADDR_OFFSET;
sample_write_data <= std_logic_vector(resize(prev_sample,WORD_WIDTH));
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
cnt_next <= cnt + 1;
end if;
-- Set Next Pointer
when 2 =>
sample_valid_in <= '1';
sample_addr <= cur_sample + SMF_NEXT_ADDR_OFFSET;
if (cur_sample = MAX_SAMPLE_ADDRESS) then
sample_write_data <= std_logic_vector(resize(SAMPLE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
else
sample_write_data <= std_logic_vector(resize(cur_sample + SAMPLE_FRAME_SIZE,WORD_WIDTH));
end if;
-- Memory Flow Control Guard
if (sample_ready_in = '1') then
if (cur_sample = MAX_SAMPLE_ADDRESS) then
-- DONE
stage_next <= RESET_PAYLOAD_MEMORY;
cnt_next <= 0;
empty_sample_list_head_next <= FIRST_SAMPLE_ADDRESS;
empty_sample_list_tail_next <= MAX_SAMPLE_ADDRESS;
else
-- Continue
cur_sample_next <= cur_sample + SAMPLE_FRAME_SIZE;
prev_sample_next <= cur_sample;
cnt_next <= 1;
end if;
end if;
when others =>
null;
end case;
when RESET_PAYLOAD_MEMORY =>
case (cnt) is
-- Initialize
when 0 =>
cur_payload_next <= (others => '0');
cnt_next <= cnt + 1;
-- Set Next Pointer
when 1 =>
payload_valid_in <= '1';
payload_addr <= cur_payload + PMF_NEXT_ADDR_OFFSET;
if (cur_payload = MAX_PAYLOAD_ADDRESS) then
payload_write_data <= std_logic_vector(resize(PAYLOAD_MEMORY_MAX_ADDRESS,WORD_WIDTH));
else
payload_write_data <= std_logic_vector(resize(cur_payload + PAYLOAD_FRAME_SIZE,WORD_WIDTH));
end if;
-- Memory Flow Control Guard
if (payload_ready_in = '1') then
if (cur_payload = MAX_PAYLOAD_ADDRESS) then
-- DONE
stage_next <= IDLE;
empty_payload_list_head_next <= FIRST_PAYLOAD_ADDRESS;
else
cur_payload_next <= cur_payload + PAYLOAD_FRAME_SIZE;
end if;
end if;
when others =>
null;
end case;
when others =>
null;
end case;
end process;
gen_inst_ctrl_prc : if WITH_KEY generate
-- *Instance Memory Process*
-- STATE DESCRIPTION
-- IDLE Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
-- SEARCH_INSTANCE_HASH See Memory OPCODE Description
-- SEARCH_INSTANCE_ADDR See Memory OPCODE Description
-- GET_NEXT_INSTANCE See Memory OPCODE Description
-- GET_INSTANCE_DATA Latch specified Instance Data for use by main process
-- FIND_POS Find List position of Instance to be added
-- INSERT_INSTANCE See Memory OPCODE Description
-- UPDATE_INSTANCE See Memory OPCODE Description
-- REMOVE_INSTANCE See Memory OPCODE Description
-- UNMARK_INTANCES See Memory OPCODE Description
-- RESET_MEMORY Reset Endpoint Memory to Empty State
inst_ctrl_prc : process(all)
begin
-- DEFAULT Registered
inst_stage_next <= inst_stage;
inst_addr_base_next <= inst_addr_base;
inst_empty_head_next <= inst_empty_head;
inst_occupied_head_next <= inst_occupied_head;
inst_latch_data_next <= inst_latch_data;
inst_next_addr_base_next <= inst_next_addr_base;
inst_prev_addr_base_next <= inst_prev_addr_base;
inst_cnt_next <= inst_cnt;
inst_cnt2_next <= inst_cnt2;
inst_data_next <= inst_data;
inst_long_latch_next <= inst_long_latch;
current_imf_next <= current_imf;
-- DEFAULT Unregistered
inst_abort_read <= '0';
inst_ready_out <= '0';
inst_valid_in <= '0';
inst_read <= '0';
inst_op_done <= '0';
inst_addr <= (others => '0');
inst_write_data <= (others => '0');
case (inst_stage) is
when IDLE =>
inst_op_done <= '1';
if (inst_op_start = '1') then
-- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
inst_latch_data_next <= (
key_hash => key_hash_next,
status_info => status_info_update,
sample_cnt => sample_cnt,
gen_cnt => gen_cnt,
deadline => deadline,
writer_bitmap => writer_bitmap,
field_flags => inst_mem_fields,
addr => inst_addr_update
);
case(inst_opcode) is
when SEARCH_INSTANCE_HASH =>
-- Reset Data
current_imf_next <= inst_mem_fields;
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances available
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_stage_next <= SEARCH_INSTANCE_HASH;
inst_cnt_next <= 0;
end if;
when SEARCH_INSTANCE_ADDR =>
-- Reset Data
current_imf_next <= inst_mem_fields;
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_stage_next <= SEARCH_INSTANCE_ADDR;
inst_cnt_next <= 0;
end if;
when INSERT_INSTANCE =>
-- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure
-- by the main process that the operation can succeed (Memory is available)
assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE;
-- Reset Data
current_imf_next <= (others => '1');
inst_data_next <= ZERO_INSTANCE_DATA;
-- First Instance
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 1; -- Skip first Step
inst_occupied_head_next <= inst_empty_head;
else
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_stage_next <= FIND_POS;
inst_cnt_next <= 0;
end if;
when UPDATE_INSTANCE =>
current_imf_next <= current_imf or inst_mem_fields;
inst_stage_next <= UPDATE_INSTANCE;
if check_mask(inst_mem_fields,IMF_STATUS_FLAG) then
inst_cnt_next <= 0;
elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 1;
elsif check_mask(inst_mem_fields,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 2;
elsif check_mask(inst_mem_fields,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 4;
elsif check_mask(inst_mem_fields,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
when GET_FIRST_INSTANCE =>
-- Reset
current_imf_next <= inst_mem_fields;
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances available
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_stage_next <= GET_NEXT_INSTANCE;
inst_cnt_next <= 0;
end if;
when GET_NEXT_INSTANCE =>
-- Reset
current_imf_next <= inst_mem_fields;
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances available
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_stage_next <= GET_NEXT_INSTANCE;
inst_cnt_next <= 0;
end if;
when REMOVE_INSTANCE =>
-- Reset
current_imf_next <= (others => '0');
inst_data_next <= ZERO_INSTANCE_DATA;
inst_stage_next <= REMOVE_INSTANCE;
inst_cnt_next <= 0;
when GET_INSTANCE =>
inst_addr_base_next <= inst_addr_update;
if (inst_addr_base /= inst_addr_update) then
-- Reset
current_imf_next <= inst_mem_fields;
inst_data_next <= ZERO_INSTANCE_DATA;
else
current_imf_next <= current_imf or inst_mem_fields;
end if;
-- Get Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
if check_mask(inst_mem_fields,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 0;
elsif check_mask(inst_mem_fields,IMF_STATUS_FLAG) then
inst_cnt_next <= 4;
elsif check_mask(inst_mem_fields,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_mem_fields,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_mem_fields,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_mem_fields,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_mem_fields,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
when UNMARK_INSTANCES =>
-- Empty Memory Guard
if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Reset
inst_data_next <= ZERO_INSTANCE_DATA;
current_imf_next <= (others => '0');
inst_addr_base_next <= inst_occupied_head;
inst_stage_next <= UNMARK_INSTANCES;
inst_cnt_next <= 0;
end if;
when others =>
null;
end case;
end if;
when SEARCH_INSTANCE_HASH =>
case (inst_cnt) is
-- GET Next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 1/4
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 2/4
when 2 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 3/4
when 3 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 4/4
when 4 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 5 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Key Hash 1/4
when 6 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(0)) then
inst_abort_read <= '1';
-- Reached List Tail, No Match
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
else
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- READ Key Hash 2/4
when 7 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(1)) then
inst_abort_read <= '1';
-- Reached List Tail, No Match
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
else
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- READ Key Hash 3/4
when 8 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(2)) then
inst_abort_read <= '1';
-- Reached List Tail, No Match
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
else
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- READ Key Hash 4/4
when 9 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(3)) then
-- Reached List Tail, No Match
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
else
-- Get Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 0;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
end if;
when others =>
null;
end case;
when SEARCH_INSTANCE_ADDR =>
case (inst_cnt) is
-- GET Next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 1 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
-- Match
if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = inst_latch_data.addr) then
-- Get Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 0;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
-- No Match
else
-- Reached List Tail, No Match
if (resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH) = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when GET_NEXT_INSTANCE =>
case (inst_cnt) is
-- GET next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 1 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
-- Get Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 0;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when GET_INSTANCE_DATA =>
case (inst_cnt) is
-- GET Key Hash 1/4
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 2/4
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 3/4
when 2 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 4/4
when 3 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
inst_cnt_next <= 11;
end if;
end if;
-- GET Status Info
when 4 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 5;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
else
inst_cnt_next <= 15;
end if;
end if;
end if;
-- GET Sample Count
when 5 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 6;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
else
inst_cnt_next <= 16;
end if;
end if;
end if;
-- GET Disposed Generation Count
when 6 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
else
inst_cnt_next <= 17;
end if;
end if;
end if;
-- GET No Writers Generation Count
when 7 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 8;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
else
inst_cnt_next <= 18;
end if;
end if;
end if;
-- GET Ignore Deadline 1/2
when 8 =>
-- Synthesis Guard
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- GET Ignore Deadline 2/2
when 9 =>
-- Synthesis Guard
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 10;
inst_cnt2_next <= 0;
else
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
else
inst_cnt_next <= 19;
end if;
end if;
end if;
end if;
-- GET Writer Bitmap
when 10 =>
-- XXX: Possible Worst case Path (2 Additions in same clock)
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + inst_cnt2;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
-- Exit Condition
if (inst_cnt2 = WRITER_BITMAP_ARRAY_TYPE'length-1) then
if check_mask(inst_latch_data.field_flags,IMF_KEY_HASH_FLAG) then
inst_cnt_next <= 11;
elsif check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
else
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
end if;
else
inst_cnt2_next <= inst_cnt2 + 1;
end if;
end if;
-- READ Key Hash 1/4
when 11 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.key_hash(0) <= inst_read_data;
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Key Hash 2/4
when 12 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.key_hash(1) <= inst_read_data;
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Key Hash 3/4
when 13 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.key_hash(2) <= inst_read_data;
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Key Hash 4/4
when 14 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.key_hash(3) <= inst_read_data;
if check_mask(inst_latch_data.field_flags,IMF_STATUS_FLAG) then
inst_cnt_next <= 15;
elsif check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ Status Info
when 15 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.status_info <= inst_read_data;
if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 16;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ Sample Count
when 16 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.sample_cnt <= unsigned(inst_read_data);
if check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 17;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ Disposed Generation Count
when 17 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.disposed_gen_cnt <= unsigned(inst_read_data);
if check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 18;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ No Writers Generation Count
when 18 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.no_writers_gen_cnt <= unsigned(inst_read_data);
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 19;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ Ignore Deadline 1/2
when 19 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data);
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Ignore Deadline 2/2
when 20 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data);
if check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 21;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- READ Writer Bitamp
when 21 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_data_next.writer_bitmap(inst_cnt2) <= inst_read_data;
-- Exit Condition
if (inst_cnt2 = WRITER_BITMAP_ARRAY_TYPE'length-1) then
-- DONE
inst_stage_next <= IDLE;
else
inst_cnt2_next <= inst_cnt2 + 1;
end if;
end if;
end case;
when FIND_POS =>
-- NOTE: Instances are inserted in KEY_HASH numerical order.
case (inst_cnt) is
-- GET Next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 1/4
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 2/4
when 2 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 3/4
when 3 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Key Hash 4/4
when 4 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 5 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Key Hash 1/4
when 6 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_cnt_next <= inst_cnt + 1;
-- Found Position (Before Current Instance)
if (inst_latch_data.key_hash(0) < inst_read_data) then
inst_next_addr_base_next <= inst_addr_base;
inst_abort_read <= '1';
-- Occupied List Head
if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
assert (inst_addr_base = inst_occupied_head) severity FAILURE;
inst_occupied_head_next <= inst_empty_head;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 1; -- Skip First Step
else
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
end if;
-- BIGGER-THAN
elsif (inst_latch_data.key_hash(0) /= inst_read_data) then
inst_abort_read <= '1';
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
else
-- Continue
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
end if;
-- READ Key Hash 2/4
when 7 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_cnt_next <= inst_cnt + 1;
-- Found Position (Before Current Instance)
if (inst_latch_data.key_hash(1) < inst_read_data) then
inst_next_addr_base_next <= inst_addr_base;
inst_abort_read <= '1';
-- Occupied List Head
if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
assert (inst_addr_base = inst_occupied_head) severity FAILURE;
inst_occupied_head_next <= inst_empty_head;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 1; -- Skip First Step
else
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
end if;
-- BIGGER-THAN
elsif (inst_latch_data.key_hash(1) /= inst_read_data) then
inst_abort_read <= '1';
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
else
-- Continue
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
end if;
-- READ Key Hash 3/4
when 8 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_cnt_next <= inst_cnt + 1;
-- Found Position (Before Current Instance)
if (inst_latch_data.key_hash(2) < inst_read_data) then
inst_next_addr_base_next <= inst_addr_base;
inst_abort_read <= '1';
-- Occupied List Head
if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
assert (inst_addr_base = inst_occupied_head) severity FAILURE;
inst_occupied_head_next <= inst_empty_head;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 1; -- Skip First Step
else
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
end if;
-- BIGGER-THAN
elsif (inst_latch_data.key_hash(2) /= inst_read_data) then
inst_abort_read <= '1';
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
else
-- Continue
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
end if;
-- Key Hash 4/4
when 9 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_cnt_next <= inst_cnt + 1;
-- Found Position (Before Current Instance)
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) severity FAILURE;
inst_occupied_head_next <= inst_empty_head;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 1; -- Skip First Step
else
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
end if;
else
assert (inst_latch_data.key_hash(3) /= inst_read_data) report "Duplicate Instance Detected" severity FAILURE;
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_next_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
else
-- Continue
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when INSERT_INSTANCE =>
-- Precondition: inst_addr_base set, inst_prev_addr_base set (Only if first Step executed), inst_next_addr_base set
case (inst_cnt) is
-- SET Next Pointer (Previous Instance)
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_write_data <= std_logic_vector(resize(inst_addr_base,WORD_WIDTH));
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Next Pointer
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- SET Next Pointer (New Instance)
when 2 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_write_data <= std_logic_vector(resize(inst_next_addr_base,WORD_WIDTH));
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Pointer
when 3 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- Fix Empty List Head
inst_empty_head_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
inst_cnt_next <= inst_cnt + 1;
end if;
-- Key Hash 1/4
when 4 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET;
inst_write_data <= inst_latch_data.key_hash(0);
inst_data_next.key_hash(0) <= inst_latch_data.key_hash(0);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Key Hash 2/4
when 5 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 1;
inst_write_data <= inst_latch_data.key_hash(1);
inst_data_next.key_hash(1) <= inst_latch_data.key_hash(1);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Key Hash 3/4
when 6 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 2;
inst_write_data <= inst_latch_data.key_hash(2);
inst_data_next.key_hash(2) <= inst_latch_data.key_hash(2);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Key Hash 4/4
when 7 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_KEY_HASH_OFFSET + 3;
inst_write_data <= inst_latch_data.key_hash(3);
inst_data_next.key_hash(3) <= inst_latch_data.key_hash(3);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Status Info
when 8 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_write_data <= inst_latch_data.status_info;
inst_data_next.status_info <= inst_latch_data.status_info;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Sample Count
when 9 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt);
inst_data_next.sample_cnt <= inst_latch_data.sample_cnt;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- Disposed Generation Count
when 10 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_write_data <= (others => '0');
inst_data_next.disposed_gen_cnt <= (others => '0');
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- No Writers Generation Count
when 11 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_write_data <= (others => '0');
inst_data_next.no_writers_gen_cnt <= (others => '0');
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt_next <= inst_cnt + 1;
else
inst_cnt_next <= inst_cnt + 3;
inst_cnt2_next <= 0;
end if;
end if;
-- Ignore Deadline 1/2
when 12 =>
-- Synthesis Guard
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.deadline(0));
inst_data_next.ignore_deadline(0) <= inst_latch_data.deadline(0);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- Ignore Deadline 2/2
when 13 =>
-- Synthesis Guard
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1;
inst_write_data <= std_logic_vector(inst_latch_data.deadline(1));
inst_data_next.ignore_deadline(1) <= inst_latch_data.deadline(1);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
inst_cnt2_next <= 0;
end if;
end if;
-- Writer Bitmap
when 14 =>
-- XXX: Possible Worst case Path (2 Additions in same clock)
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET + inst_cnt2;
inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt2);
inst_data_next.writer_bitmap <= inst_latch_data.writer_bitmap;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
-- Exit Condition
if (inst_cnt2 = WRITER_BITMAP_ARRAY_TYPE'length-1) then
-- DONE
inst_stage_next <= IDLE;
else
inst_cnt2_next <= inst_cnt2 + 1;
end if;
end if;
when others =>
null;
end case;
when UPDATE_INSTANCE =>
case (inst_cnt) is
-- Status Info
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_write_data <= inst_latch_data.status_info;
inst_data_next.status_info <= inst_latch_data.status_info;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_SAMPLE_CNT_FLAG) then
inst_cnt_next <= 1;
elsif check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 2;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- Sample Count
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.sample_cnt);
inst_data_next.sample_cnt <= inst_latch_data.sample_cnt;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_DISPOSED_CNT_FLAG) then
inst_cnt_next <= 2;
elsif check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- Disposed Generation Count
when 2 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.gen_cnt);
inst_data_next.disposed_gen_cnt <= inst_latch_data.gen_cnt;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_NO_WRITERS_CNT_FLAG) then
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- No Writers Generation Count
when 3 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.gen_cnt);
inst_data_next.no_writers_gen_cnt <= inst_latch_data.gen_cnt;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and check_mask(inst_latch_data.field_flags,IMF_IGNORE_DEADLINE_FLAG)) then
inst_cnt_next <= 4;
elsif check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- Ignore Deadline 1/2
when 4 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_write_data <= std_logic_vector(inst_latch_data.deadline(0));
inst_data_next.ignore_deadline(0) <= inst_latch_data.deadline(0);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- Ignore Deadline 2/2
when 5 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET + 1;
inst_write_data <= std_logic_vector(inst_latch_data.deadline(1));
inst_data_next.ignore_deadline(1) <= inst_latch_data.deadline(1);
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if check_mask(inst_latch_data.field_flags,IMF_WRITER_BITMAP_FLAG) then
inst_cnt_next <= 6;
inst_cnt2_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
end if;
-- Writer Bitmap
when 6 =>
-- XXX: Possible Worst case Path (2 Additions in same clock)
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET + inst_cnt2;
inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt2);
inst_data_next.writer_bitmap <= inst_latch_data.writer_bitmap;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
-- Exit Condition
if (inst_cnt2 = WRITER_BITMAP_ARRAY_TYPE'length-1) then
-- DONE
inst_stage_next <= IDLE;
else
inst_cnt2_next <= inst_cnt2 + 1;
end if;
end if;
when others =>
null;
end case;
when REMOVE_INSTANCE =>
-- Precondition: inst_addr_base set, inst_prev_addr_base set
case (inst_cnt) is
-- GET Next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 1 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
-- Removed Instance is List Head
if (inst_prev_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
assert (inst_addr_base = inst_occupied_head) severity FAILURE;
-- Fix Occupied Head
inst_occupied_head_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
inst_cnt_next <= inst_cnt + 2; -- Skip Next Step
else
inst_cnt_next <= inst_cnt + 1;
end if;
end if;
-- SET Next Pointer (Previous Instance)
when 2 =>
-- Point Previous instance to Next Instance (Remove current Instance from inbetween)
inst_valid_in <= '1';
inst_addr <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_write_data <= std_logic_vector(resize(inst_next_addr_base,WORD_WIDTH));
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- SET Next Pointer (Current/Removed Instance)
when 3 =>
-- Point Current Instance to Empty List Head (Make Removed Instance Head of the Empty List)
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_write_data <= std_logic_vector(resize(inst_empty_head,WORD_WIDTH));
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
-- Fix Empty List Head
inst_empty_head_next <= inst_addr_base;
-- Reset
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
-- DONE
inst_stage_next <= IDLE;
end if;
when others =>
null;
end case;
when UNMARK_INSTANCES =>
-- Precondition: inst_addr_base set
case (inst_cnt) is
-- GET Next Instance
when 0 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- GET Status Info
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_read <= '1';
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Next Instance
when 2 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
inst_next_addr_base_next <= resize(unsigned(inst_read_data),INSTANCE_MEMORY_ADDR_WIDTH);
inst_cnt_next <= inst_cnt + 1;
end if;
-- READ Status Info
when 3 =>
inst_ready_out <= '1';
-- Memory Flow Control Guard
if (inst_valid_out = '1') then
-- MARK Flag Set
if (inst_read_data(ISI_MARK_FLAG) = '1') then
-- Latch Status Info (With MARK removed)
inst_long_latch_next <= inst_read_data;
inst_long_latch_next(ISI_MARK_FLAG) <= '0';
inst_cnt_next <= inst_cnt + 1;
else
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
inst_stage_next <= IDLE;
else
-- Continue
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
end if;
-- Status Info
when 4 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_write_data <= inst_long_latch;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
-- End of Instances
if (inst_next_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
inst_stage_next <= IDLE;
else
-- Continue
inst_addr_base_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
when RESET_MEMORY =>
case (inst_cnt) is
-- Initialize
when 0 =>
inst_addr_base_next <= FIRST_INSTANCE_ADDRESS;
inst_cnt_next <= inst_cnt + 1;
-- Set Next Pointer
when 1 =>
inst_valid_in <= '1';
inst_addr <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
if (inst_addr_base = MAX_INSTANCE_ADDRESS) then
inst_write_data <= std_logic_vector(resize(INSTANCE_MEMORY_MAX_ADDRESS,WORD_WIDTH));
else
inst_write_data <= std_logic_vector(resize(inst_addr_base + INSTANCE_FRAME_SIZE,WORD_WIDTH));
end if;
-- Memory Flow Control Guard
if (inst_ready_in = '1') then
if (inst_addr_base = MAX_INSTANCE_ADDRESS) then
-- DONE
inst_stage_next <= IDLE;
inst_empty_head_next <= FIRST_INSTANCE_ADDRESS;
else
inst_addr_base_next <= inst_addr_base + INSTANCE_FRAME_SIZE;
end if;
end if;
when others =>
null;
end case;
when others =>
null;
end case;
end process;
end generate;
sync_prc : process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
stage <= RESET_SAMPLE_MEMORY;
inst_stage <= RESET_MEMORY;
newest_sample <= SAMPLE_MEMORY_MAX_ADDRESS;
oldest_sample <= SAMPLE_MEMORY_MAX_ADDRESS;
empty_sample_list_head <= SAMPLE_MEMORY_MAX_ADDRESS;
empty_sample_list_tail <= SAMPLE_MEMORY_MAX_ADDRESS;
empty_payload_list_head <= PAYLOAD_MEMORY_MAX_ADDRESS;
inst_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_occupied_head <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_next_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_empty_head <= INSTANCE_MEMORY_MAX_ADDRESS;
key_hash <= HANDLE_NIL;
si_instance_handle_sig <= HANDLE_NIL;
si_publication_handle_sig <= (others => (others => '0'));
instance_handle <= HANDLE_NIL;
sample_rej_last_inst <= HANDLE_NIL;
ts_latch <= TIME_INVALID;
lifespan_time <= TIME_INFINITE;
lifespan <= TIME_INVALID;
si_source_timestamp_sig <= TIME_INVALID;
last_read_ts <= TIME_ZERO;
deadline_time <= time + DEADLINE_QOS;
si_sample_state_sig <= ANY_SAMPLE_STATE;
sample_state <= ANY_SAMPLE_STATE;
si_view_state_sig <= ANY_VIEW_STATE;
view_state <= ANY_VIEW_STATE;
si_instance_state_sig <= ANY_INSTANCE_STATE;
instance_state <= ANY_INSTANCE_STATE;
inst_data <= ZERO_INSTANCE_DATA;
inst_latch_data <= ZERO_INST_LATCH_DATA;
sample_rej_last_reason <= NOT_REJECTED;
rtps_return_code_latch <= ERROR;
dds_return_code_latch <= RETCODE_ERROR;
writer_id <= 0;
cnt <= 0;
cnt2 <= 0;
cnt3 <= 0;
inst_cnt <= 0;
inst_cnt2 <= 0;
stale_inst_cnt <= 0;
is_lifespan_check <= '0';
remove_oldest_sample <= '0';
remove_oldest_inst_sample <= '0';
si_valid_data_sig <= '0';
si_valid_sig <= '0';
eoc_sig <= '0';
is_take <= '0';
single_instance <= '0';
unmark_instances_flag <= '0';
dynamic_next_instance <= '0';
pre_calculated <= '0';
newer_inst_sample <= '0';
new_inst <= '0';
trigger_sample_gen <= '0';
wait_for_sample_removal <= '0';
dis_gen_cnt_latch <= (others => '0');
no_w_gen_cnt_latch <= (others => '0');
current_imf <= (others => '0');
sample_addr_latch_1 <= (others => '0');
sample_addr_latch_2 <= (others => '0');
sample_addr_latch_3 <= (others => '0');
sample_addr_latch_4 <= (others => '0');
sample_addr_latch_5 <= (others => '0');
payload_addr_latch_1 <= (others => '0');
payload_addr_latch_2 <= (others => '0');
inst_addr_latch_1 <= (others => '0');
inst_addr_latch_2 <= (others => '0');
long_latch <= (others => '0');
sample_status_info <= (others => '0');
si_disposed_generation_count_sig <= (others => '0');
si_no_writers_generation_count_sig <= (others => '0');
si_sample_rank_sig <= (others => '0');
si_generation_rank_sig <= (others => '0');
si_absolute_generation_rank_sig <= (others => '0');
max_samples_latch <= (others => '0');
collection_cnt <= (others => '0');
collection_cnt_max <= (others => '0');
collection_generation_rank <= (others => '0');
cur_generation_rank <= (others => '0');
sample_rej_cnt <= (others => '0');
sample_rej_cnt_change <= (others => '0');
deadline_miss_cnt <= (others => '0');
deadline_miss_cnt_change <= (others => '0');
deadline_miss_last_inst <= HANDLE_NIL;
status_sig <= (others => '0');
inst_long_latch <= (others => '0');
else
stage <= stage_next;
inst_stage <= inst_stage_next;
newest_sample <= newest_sample_next;
oldest_sample <= oldest_sample_next;
empty_sample_list_head <= empty_sample_list_head_next;
empty_sample_list_tail <= empty_sample_list_tail_next;
empty_payload_list_head <= empty_payload_list_head_next;
inst_addr_base <= inst_addr_base_next;
inst_occupied_head <= inst_occupied_head_next;
inst_next_addr_base <= inst_next_addr_base_next;
inst_prev_addr_base <= inst_prev_addr_base_next;
inst_empty_head <= inst_empty_head_next;
key_hash <= key_hash_next;
si_instance_handle_sig <= si_instance_handle_sig_next;
si_publication_handle_sig <= si_publication_handle_sig_next;
instance_handle <= instance_handle_next;
sample_rej_last_inst <= sample_rej_last_inst_next;
ts_latch <= ts_latch_next;
lifespan_time <= lifespan_time_next;
lifespan <= lifespan_next;
si_source_timestamp_sig <= si_source_timestamp_sig_next;
last_read_ts <= last_read_ts_next;
deadline_time <= deadline_time_next;
si_sample_state_sig <= si_sample_state_sig_next;
sample_state <= sample_state_next;
si_view_state_sig <= si_view_state_sig_next;
view_state <= view_state_next;
si_instance_state_sig <= si_instance_state_sig_next;
instance_state <= instance_state_next;
inst_data <= inst_data_next when WITH_KEY else inst_data_next2;
inst_latch_data <= inst_latch_data_next;
sample_rej_last_reason <= sample_rej_last_reason_next;
rtps_return_code_latch <= rtps_return_code_latch_next;
dds_return_code_latch <= dds_return_code_latch_next;
writer_id <= writer_id_next;
cnt <= cnt_next;
cnt2 <= cnt2_next;
cnt3 <= cnt3_next;
inst_cnt <= inst_cnt_next;
inst_cnt2 <= inst_cnt2_next;
stale_inst_cnt <= stale_inst_cnt_next;
is_lifespan_check <= is_lifespan_check_next;
remove_oldest_sample <= remove_oldest_sample_next;
remove_oldest_inst_sample <= remove_oldest_inst_sample_next;
si_valid_data_sig <= si_valid_data_sig_next;
si_valid_sig <= si_valid_sig_next;
eoc_sig <= eoc_sig_next;
is_take <= is_take_next;
single_instance <= single_instance_next;
unmark_instances_flag <= unmark_instances_flag_next;
dynamic_next_instance <= dynamic_next_instance_next;
pre_calculated <= pre_calculated_next;
newer_inst_sample <= newer_inst_sample_next;
new_inst <= new_inst_next;
trigger_sample_gen <= trigger_sample_gen_next;
wait_for_sample_removal <= wait_for_sample_removal_next;
dis_gen_cnt_latch <= dis_gen_cnt_latch_next;
no_w_gen_cnt_latch <= no_w_gen_cnt_latch_next;
current_imf <= current_imf_next when WITH_KEY else (others => '1');
sample_addr_latch_1 <= sample_addr_latch_1_next;
sample_addr_latch_2 <= sample_addr_latch_2_next;
sample_addr_latch_3 <= sample_addr_latch_3_next;
sample_addr_latch_4 <= sample_addr_latch_4_next;
sample_addr_latch_5 <= sample_addr_latch_5_next;
payload_addr_latch_1 <= payload_addr_latch_1_next;
payload_addr_latch_2 <= payload_addr_latch_2_next;
inst_addr_latch_1 <= inst_addr_latch_1_next;
inst_addr_latch_2 <= inst_addr_latch_2_next;
long_latch <= long_latch_next;
sample_status_info <= sample_status_info_next;
si_disposed_generation_count_sig <= si_disposed_generation_count_sig_next;
si_no_writers_generation_count_sig <= si_no_writers_generation_count_sig_next;
si_sample_rank_sig <= si_sample_rank_sig_next;
si_generation_rank_sig <= si_generation_rank_sig_next;
si_absolute_generation_rank_sig <= si_absolute_generation_rank_sig_next;
max_samples_latch <= max_samples_latch_next;
collection_cnt <= collection_cnt_next;
collection_cnt_max <= collection_cnt_max_next;
collection_generation_rank <= collection_generation_rank_next;
cur_generation_rank <= cur_generation_rank_next;
sample_rej_cnt <= sample_rej_cnt_next;
sample_rej_cnt_change <= sample_rej_cnt_change_next;
deadline_miss_cnt <= deadline_miss_cnt_next;
deadline_miss_cnt_change <= deadline_miss_cnt_change_next;
deadline_miss_last_inst <= deadline_miss_last_inst_next;
status_sig <= status_sig_next;
inst_long_latch <= inst_long_latch_next;
end if;
end if;
end process;
end architecture;