rtps-fpga/src/dds_endpoint.vhd
Greek bdb397ae7d Major History Cache/DDS Endpoint Redesign
It was decided to connect the DDS Endpoint directly to the RTPS
Endpoint. The history_cache Entity will be converted to a generic
History Cache acording to the RTPS Specification.
Because of consistency requirements the implementation was changed to a
single process/single port RAM design.
This should fully (blindly) implement the RTPS Reader side of the DDS
Entity.
2021-01-21 12:51:39 +01:00

1837 lines
98 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- TODO: Cancel KHG operation on incomplete payload parsing
entity history_cache is
generic (
TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS;
MAX_INSTANCES : natural := DEFAULT_MAX_INSTANCES;
MAX_SAMPLES_PER_INSTANCE : natural := DEFAULT_MAX_SAMPLES_PER_INSTANCE;
HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS;
RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS;
GENERATION_COUNTERS : boolean := TRUE;
);
port (
clk : in std_logic;
reset : in std_logic;
start_a : in std_logic;
opcode_a : in HISTORY_CACHE_OPCODE_TYPE;
res_a : out HISTORY_CACHE_RESPOSNE_TYPE;
data_in_a : in std_logic_vector(WORD_WIDTH-1 downto 0);
valid_in_a : in std_logic;
ready_in_a : out std_logic;
last_word_in_a : in std_logic;
start_b : in std_logic;
opcode_b : in HISTORY_CACHE_OPCODE_TYPE;
res_b : out HISTORY_CACHE_RESPOSNE_TYPE;
data_out_b : out std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_out_b : in std_logic;
);
end entity;
architecture arch of history_cache is
--*****CONSTANT DECLARATION*****
-- Sample Info Memory Size in 4-Byte Words
constant SAMPLE_MEMORY_SIZE : natural := TODO;
-- Sample Info Memory Address Width
constant SAMPLE_MEMORY_ADDR_WIDTH : natural := log2c(SAMPLE_MEMORY_SIZE);
-- Highest Sample Info Memory Address
constant SAMPLE_MEMORY_MAX_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(SAMPLE_MEMORY_SIZE-1, SAMPLE_MEMORY_ADDR_WIDTH);
-- Highest Sample Info Frame Address
constant MAX_SAMPLE_ADDRESS : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := SAMPLE_MEMORY_MAX_ADDRESS - SAMPLE_INFO_FRAME_SIZE + 1;
-- Payload Memory Size in 4-Byte Words
constant PAYLOAD_MEMORY_SIZE : natural := TODO;
-- Payload Memory Address Width
constant PAYLOAD_MEMORY_ADDR_WIDTH : natural := log2c(PAYLOAD_MEMORY_SIZE);
-- Highest Payload Memory Address
constant PAYLOAD_MEMORY_MAX_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PAYLOAD_MEMORY_SIZE-1, PAYLOAD_MEMORY_ADDR_WIDTH);
-- Highest Payload Frame Address
constant MAX_PAYLOAD_ADDRESS : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := PAYLOAD_MEMORY_MAX_ADDRESS - PAYLOAD_FRAME_SIZE + 1;
-- Instance Memory Size in 4-Byte Words
constant INSTANCE_MEMORY_SIZE : natural := TODO;
-- Instance Memory Address Width
constant INSTANCE_MEMORY_ADDR_WIDTH : natural := log2c(INSTANCE_MEMORY_SIZE);
-- Highest Instance Memory Address
constant INSTANCE_MEMORY_MAX_ADDRESS: unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(INSTANCE_MEMORY_SIZE-1, INSTANCE_MEMORY_ADDR_WIDTH);
-- Highest Instance Frame Address
constant MAX_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := INSTANCE_MEMORY_MAX_ADDRESS - INSTANCE_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Instance Data Frame
constant FIRST_INSTANCE_ADDRESS : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *UPDATE INSTANCE FLAG POSITIONS*
constant UPDATE_INSTANCE_FLAG_WIDTH : natural := 6;
constant STATUS_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (0 => 1, others => '0');
constant SAMPLE_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (1 => 1, others => '0');
constant DISPOSED_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (2 => 1, others => '0');
constant NO_WRITERS_CNT_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (3 => 1, others => '0');
constant IGNORE_DEADLINE_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (4 => 1, others => '0');
constant WRITER_BITMAP_FLAG : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (5 => 1, others => '0');
-- *SAMPLE MEMORY FRAME FORMAT*
constant SMF_STATUS_INFO_OFFSET : natural := 0;
constant SMF_TIMESTAMP_OFFSET : natural := 1;
constant SMF_LIFESPAN_DEADLINE_OFFSET : natural := 3;
constant SMF_PAYLOAD_ADDR_OFFSET : natural := 5;
constant SMF_INSTANCE_ADDR_OFFSET : natural := 6;
constant SMF_DISPOSED_GEN_CNT_OFFSET : natural := 7;
constant SMF_NO_WRITERS_GEN_CNT_OFFSET : natural := 8;
constant SMF_PREV_ADDR_OFFSET : natural := SMF_NO_WRITERS_GEN_CNT_OFFSET+1 when GENERATION_COUNTERS else SMF_INSTANCE_ADDR_OFFSET+1;
constant SMF_NEXT_ADDR_OFFSET : natural := SMF_PREV_ADDR_OFFSET+1;
-- *PAYLOAD MEMORY FRAME FORMAT*
constant PMF_NEXT_ADDR_OFFSET : natural := 0;
constant PMF_PAYLOAD_OFFSET : natural := 1;
-- *INSTANCE MEMORY FRAME OFFSET*
constant IMF_NEXT_ADDR_OFFSET : natural := 0;
constant IMF_KEY_HASH_OFFSET : natural := 1;
constant IMF_STATUS_INFO_OFFSET : natural := 5;
constant IMF_SAMPLE_CNT_OFFSET : natural := 6;
constant IMF_DISPOSED_GEN_CNT_OFFSET : natural := IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_OFFSET+1;
constant IMF_NO_WRITERS_GEN_CNT_OFFSET : natural := IMF_DISPOSED_GEN_CNT_OFFSET+1;
constant IMF_IGNORE_DEADLINE_OFFSET : natural := IMF_NO_WRITERS_GEN_CNT_OFFSET+1 when (GENERATION_COUNTERS) else
IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_OFFSET+1;
constant IMF_WRITER_BITMAP_OFFSET : natural := IMF_IGNORE_DEADLINE_OFFSET+2 when (TIME_BASED_FILTER_QOS /= DURATION_ZERO) else
IMF_NO_WRITERS_GEN_CNT_OFFSET+1 when (GENERATION_COUNTERS) else
IMF_SAMPLE_CNT_OFFSET+1 when (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) else IMF_STATUS_INFO_OFFSET+1;
--*****TYPE DECLARATION*****
-- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, TODO);
type INST_STAGE_TYPE is (IDLE, TODO);
type INSTANCE_OPCODE_TYPE is (NOP, TODO);
type INSTANCE_DATA_TYPE is record
status_info : std_logic_vector(WORD_WIDTH-1 downto 0);
sample_cnt : unsigned(WORD_WIDTH-1 downto 0);
disposed_gen_cnt : unsigned(WORD_WIDTH-1 downto 0);
no_writers_gen_cnt : unsigned(WORD_WIDTH-1 downto 0);
ignore_deadline : TIME_TYPE;
writer_bitmap : ENDPOINT_BITMAP_ARRAY_TYPE;
end record;
constant ZERO_INSTANCE_DATA : INSTANCE_DATA_TYPE := (
status_info => (others => '0'),
sample_cnt => (others => '0'),
disposed_gen_cnt => (others => '0'),
no_writers_gen_cnt => (others => '0'),
ignore_deadline => TIME_INVALID,
writer_bitmap => (others => (others => '0'))
);
type INST_LATCH_DATA_TYPE is record
key_hash : KEY_HASH_TYPE;
instance_state : INSTANCE_STATE_TYPE;
sample_cnt : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
gen_cnt : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
deadline : TIME_TYPE;
writer_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1);
update_flags : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1);
addr : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0);
end record;
constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := (
key_hash => (others => (others => '0')),
instance_state => ALIVE,
sample_cnt => (others => '0'),
gen_cnt => (others => '0'),
deadline => TIME_INVALID,
writer_bitmap => (others => (others => '0')),
update_flags => (others => '0'),
addr => (others => '0')
);
--*****SIGNAL DECLARATION
signal sample_addr, sample_addr_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_wen, sample_ren : std_logic := '0';
signal sample_read_data, sample_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal payload_addr, payload_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_wen, payload_ren : std_logic := '0';
signal payload_read_data, payload_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal inst_addr, inst_addr_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_wen, inst_ren : std_logic := '0';
signal inst_read_data, inst_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal khg_valid_in, khg_ready_in, khg_last_word_in, khg_valid_out, khg_ready_out, khg_last_word_out : std_logic := '0';
signal khg_data_in, khg_data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal stage, stage_next : STAGE_TYPE := IDLE;
signal cnt, cnt_next : natural range TODO := 0;
signal empty_sample_list_head, empty_sample_list_head_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal empty_sample_list_tail, empty_sample_list_tail_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal empty_payload_list_head, empty_payload_list_head_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal oldest_sample, oldest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal newest_sample, newest_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal first_unread_sample, first_unread_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_addr_latch_1, payload_addr_latch_1_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_addr_latch_2, payload_addr_latch_2_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_addr_latch_1, sample_addr_latch_1_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_addr_latch_2, sample_addr_latch_2_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_addr_latch_3, sample_addr_latch_3_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal ts_latch, ts_latch_next : TIME_TYPE := TIME_INVALID;
signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal payload_mem_full, payload_mem_full_next : std_logic := '0';
signal sample_mem_full, sample_mem_full_next : std_logic := '0';
signal writer_pos, writer_pos_next : natural range TODO := 0;
signal writer_bitmap : ENDPOINT_BITMAP_ARRAY_TYPE;
signal instance_state : INSTANCE_STATE_TYPE := ALIVE;
signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0'));
signal remove_oldest_sample, remove_oldest_sample_next : std_logic := '0';
signal remove_oldest_inst_sample, remove_oldest_inst_sample_next : std_logic := '0';
signal added_new_instance, added_new_instance_next : std_logic := '0';
signal sample_status_info, sample_status_info_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal gen_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal deadline : TIME_TYPE := TIME_INVALID;
signal inst_addr_update : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_cnt : unsigned(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
signal inst_op_start : std_logic := '0';
signal inst_op_done : std_logic := '0';
signal inst_opcode : INSTANCE_OPCODE_TYPE := NOP;
signal inst_stage, inst_stage_next : INST_STAGE_TYPE := IDLE;
signal inst_addr_base, inst_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_next_addr_base, inst_next_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_prev_addr_base, inst_prev_addr_base_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_empty_head, inst_empty_head_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_occupied_tail, inst_occupied_tail_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_latch_data, inst_latch_data_next : INST_LATCH_DATA_TYPE := ZERO_INST_LATCH_DATA;
signal update_inst_flags : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0');
signal inst_cnt, inst_cnt_next : natural range TODO := 0;
signal inst_mem_full, inst_mem_full_next : std_logic := '0';
signal inst_delete_lock, inst_delete_lock_next : std_logic := '0';
signal inst_atomic_lock : std_logic := '0';
signal inst_long_latch, inst_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0');
--*****ALIAS DECLARATION*****
alias prev_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1;
alias prev_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_1_next;
alias next_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2;
alias next_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_2_next;
alias cur_sample : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3;
alias cur_sample_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) is sample_addr_latch_3_next;
alias cur_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1;
alias cur_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next;
alias next_payload : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1;
alias next_payload_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) is payload_addr_latch_1_next;
alias has_data : std_logic is sample_status_info(PAYLOAD_FLAG);
alias has_key_hash : std_logic is sample_status_info(KEY_HASH_FLAG);
begin
sample_ram_inst : entity work.single_port_ram(arch)
generic map (
ADDR_WIDTH => SAMPLE_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => SAMPLE_MEMORY_SIZE
)
port map (
clk => clk,
addr => sample_addr,
wen => sample_wen,
ren => sample_ren,
wr_data => sample_write_data,
rd_data => sample_read_data
);
payload_ram_inst : entity work.single_port_ram(arch)
generic map (
ADDR_WIDTH => PAYLOAD_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => PAYLOAD_MEMORY_SIZE
)
port map (
clk => clk,
addr => payload_addr,
wen => payload_wen,
ren => payload_ren,
wr_data => payload_write_data,
rd_data => payload_read_data
);
instance_ram_inst : entity work.single_port_ram(arch)
generic map (
ADDR_WIDTH => INSTANCE_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => INSTANCE_MEMORY_SIZE
)
port map (
clk => clk,
addr => inst_addr,
wen => inst_wen,
ren => inst_ren,
wr_data => inst_write_data,
rd_data => inst_read_data
);
key_hash_generator_inst : entity work.key_hash_generator(arch)
port (
clk => clk,
reset => reset,
data_in => khg_data_in,
valid_in => khg_valid_in,
ready_in => khg_ready_in,
last_word_in => khg_last_word_in,
data_out => khg_data_out,
valid_out => khg_valid_out,
ready_out => khg_ready_out,
last_word_out => khg_last_word_out
);
parse_a_prc : process (all)
variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0'));
variable tmp_bitmap : std_logic_vector(0 to ENDPOINT_BITMAP_WIDTH-1) := (others => '0');
variable tmp_update : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0');
begin
-- Default
stage_next <= stage;
res_a <= UNDEFINED;
sample_addr_next <= sample_addr;
sample_write_data <= (others => '0');
sample_ren <= '0';
sample_wen <= '0';
payload_addr_next <= payload_addr;
payload_write_data <= (others => '0');
payload_ren <= '0';
payload_wen <= '0';
ready_in_a <= '0';
newest_sample_next <= newest_sample;
empty_payload_list_head_next <= empty_payload_list_head;
empty_sample_list_head_next <= empty_sample_list_head;
empty_sample_list_tail_next <= empty_sample_list_tail;
payload_addr_latch_1_next <= payload_addr_latch_1;
payload_addr_latch_2_next <= payload_addr_latch_2;
ts_latch_next <= ts_latch;
long_latch_next <= long_latch;
sample_addr_latch_1_next <= sample_addr_latch_1;
sample_addr_latch_2_next <= sample_addr_latch_2;
payload_mem_full_next <= payload_mem_full;
sample_mem_full_next <= sample_mem_full;
writer_pos_next <= writer_pos;
inst_opcode <= NOP;
key_hash_next <= key_hash;
sample_status_info_next <= sample_status_info;
inst_op_start <= '0';
khg_last_word_in <= '0';
khg_data_in <= (others => '0');
khg_valid_in <= '0';
khg_ready_out <= '0';
writer_bitmap <= (others => '0');
inst_addr_update <= (others => '0');
remove_oldest_sample_next <= remove_oldest_sample;
remove_oldest_inst_sample_next <= remove_oldest_inst_sample;
added_new_instance_next <= added_new_instance;
case (stage) is
when IDLE =>
-- DEFAULT
ready_in_a <= '1';
remove_oldest_inst_sample_next <= '0';
remove_oldest_sample_next <= '0';
added_new_instance_next <= '0';
if (start_a = '1') then
case (opcode_a) is
when ADD_CHANGE =>
-- This Operation does not accept input at this time
ready_in_a <= '0';
res_a <= ACK;
stage_next <= ADD_SAMPLE_INFO;
cur_sample_next <= empty_sample_list_head;
sample_addr_next <= empty_sample_list_head;
cnt_next <= 0;
end if;
when REMOVE_WRITER =>
-- Input and Memory Gurad
if (valid_in_a = '1' and inst_op_done = '1') then
-- Latch Writer Pos
writer_pos_next <= to_integer(unsigned(data_in_a));
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
stage_next <= REMOVE_WRITER;
res_a <= ACK;
end if;
when others =>
null;
end case;
elsif (start_b = '1') then
-- TODO
end if;
when ADD_SAMPLE_INFO =>
-- Precondition: sample_addr (empty_sample_list_head)
ready_in_a <= '1';
-- Input Guard
if (valid_in_a = '1') then
cnt_next <= cnt + 1;
sample_addr_next <= sample_addr + 1;
-- Write Through
sample_wen <= '1';
sample_write_data <= data_in_a;
case (cnt) is
-- Status Info
when 0 =>
-- Initialize local status bits
sample_write_data(READ_FLAG) <= '0';
-- Latch Status Info
sample_status_info_next <= data_in_a;
sample_status_info_next(READ_FLAG) <= '0';
-- Latch Timestamp for ordering
-- Timestamp 1/2
when 1 =>
ts_latch_next(0) <= data_in_a;
-- Timestamp 2/2
when 2 =>
ts_latch_next(1) <= data_in_a;
-- Lifespan Deadline 2/2
when 4 =>
-- Skip Key Hash, if not available
if (has_key_hash = '0') then
cnt_next <= 9;
end if;
-- Latch Key Hash
-- Key Hash 1/4
when 5 =>
-- Latch Input, but do not pass to Memory
sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
key_hash_next(0) <= data_in_a;
-- Key Hash 2/4
when 6 =>
-- Latch Input, but do not pass to Memory
sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
key_hash_next(1) <= data_in_a;
-- Key Hash 3/4
when 7 =>
-- Latch Input, but do not pass to Memory
sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
key_hash_next(2) <= data_in_a;
-- Key Hash 4/4
when 8 =>
-- Latch Input, but do not pass to Memory
sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
key_hash_next(3) <= data_in_a;
when 9 =>
-- Latch Input, but do not pass to Memory
writer_pos_next <= to_integer(unsigned(data_in_a));
sample_wen <= '0';
sample_addr_next <= sample_addr; -- Keep Addr (Payload Addr)
stage_next <= ADD_PAYLOAD_ADDRESS;
when others =>
null;
end case;
end if;
when ADD_PAYLOAD_ADDRESS =>
-- Precondition: sample_addr (Payload Address)
sample_addr_next <= sample_addr + 1; -- Instance Address
if (has_data = '1') then
-- Store Payload Address
sample_wen <= '1';
sample_write_data <= empty_payload_list_head;
payload_addr_next <= empty_payload_list_head + PMF_NEXT_ADDR_OFFSET;
cur_payload_next <= empty_payload_list_head;
else
-- Mark Sample with no Payload
sample_wen <= '1';
sample_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS;
end if;
-- If Key Hash is available, start the Instance Search first
if (has_key_hash = '1') then
stage_next <= INITIATE_INSTANCE_SEARCH;
else
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
end if;
when ADD_PAYLOAD =>
-- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr (Beginning of Payload Data of cur_payload)
-- NOTE: This state is responsible for reading the payload and writing it through to the local payload memory
-- and key hash generator (KHG). This state is taken on following cases:
-- has_data has_key_hash
-- 1 1 The payload is written to memory
-- 1 0 The payload is written to memory and the KHG at the same time (KHG controls the flow)
-- 0 0 There is no payload to write, but the input contains the key for the KHG
if (has_key_hash = '0') then
ready_in_a <= khg_ready_in;
else
ready_in_a <= '1';
end if;
-- Flow Control Guard
if ((valid_in_a = '1' and has_key_hash = '0') or (valid_in_a = '1' and has_key_hash = '0' and khg_ready_in = '1')) then
cnt_next <= cnt + 1;
payload_addr_next <= payload_addr + PMF_NEXT_ADDR_OFFSET;
-- Payload Write
if (has_data = '1') then
payload_write_data <= data_in_a;
payload_wen <= '1';
end if;
-- Key Hash Generator Write
if (has_key_hash = '0') then
khg_data_in <= data_in_a;
khg_valid_in <= '1';
end if;
-- End of Payload
if (last_word_in_a = '1') then
if (has_key_hash = '0') then
khg_last_word_in <= '1';
stage_next <= GET_KEY_HASH;
cnt_next <= 0;
else
stage_next <= FILTER_STAGE;
end if;
-- End of Payload Slot
elsif (has_data = '1' and cnt = PAYLOAD_FRAME_SIZE-2) then
stage_next <= NEXT_PAYLOAD_SLOT;
payload_addr_next <= cur_payload;
cnt_next <= 0;
end if;
end if;
when NEXT_PAYLOAD_SLOT =>
-- Precondition: payload_addr (Beginning of current Slot)
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
payload_ren <= '1';
when 1 =>
-- No Empty Payload Slots available
if (payload_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- Reject Change
stage_next <= SKIP_ADD;
else
-- Latch next Payload Slot and Continue
cur_payload_next <= payload_read_data;
payload_addr_next <= payload_read_data + PMF_NEXT_ADDR_OFFSET;
stage_next <= ADD_PAYLOAD;
end if;
when others =>
null;
end case;
when GET_KEY_HASH =>
khg_ready_out <= '1';
if (khg_valid_out = '1') then
cnt_next <= cnt + 1;
-- Latch Key Hash
key_hash_next(cnt) <= khg_data_out;
-- Exit Condition
if (khg_last_word_out = '1') then
-- DONE
stage_next <= INITIATE_INSTANCE_SEARCH;
end if;
end if;
when INITIATE_INSTANCE_SEARCH =>
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_opcode <= SEARCH_INSTANCE_HASH;
inst_op_start <= '1';
-- Payload not yet stored
if (has_data = '1') then
stage_next <= ADD_PAYLOAD;
cnt_next <= 0;
else
stage_next <= FILTER_STAGE;
end if;
end if;
when FILTER_STAGE =>
-- Precondition: sample_addr (Instance Address of New Sample)
-- Wait for Instance Search to finish
if (inst_op_done = '1') then
sample_addr_next <= sample_addr + 1; -- Disposed Gen Counter (Prev Address if GENERATION_COUNTERS=FALSE)
-- Instance Found
if (inst_addr_base /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Store Instance Address
sample_write_data <= inst_addr_base;
sample_wen <= '1';
-- TIME_BASED_FILTER QOS
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time <= inst_data.ignore_deadline) then
-- Drop Change
res_a <= ACCEPTED;
stage_next <= IDLE;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES_PER_INSTANCE)
elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then
if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change
res_a <= REJECTED;
stage_next <= IDLE;
else
-- Accept Change (Remove Oldest Instance Sample)
remove_oldest_inst_sample_next <= '1';
res_a <= ACCEPTED;
stage_next <= UPDATE_INSTANCE;
end if;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
elsif (empty_sample_list_head = empty_sample_list_tail) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change
res_a <= REJECTED;
stage_next <= IDLE;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
res_a <= ACCEPTED;
stage_next <= UPDATE_INSTANCE;
end if;
else
-- Accept Change
res_a <= ACCEPTED;
stage_next <= UPDATE_INSTANCE;
end if;
else
-- Store Instance Address
sample_write_data <= inst_empty_head;
sample_wen <= '1';
-- RESOURCE_LIMITS_QOS (MAX_INSTANCES) (Instance Memory Full)
if (inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
-- Reject Change
res_a <= REJECTED;
stage_next <= IDLE;
-- RESOURCE_LIMITS_QOS (MAX_SAMPLES)
elsif (empty_sample_list_head = empty_sample_list_tail) then
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change
res_a <= REJECTED;
stage_next <= IDLE;
else
-- Accept Change (Remove Oldest Sample)
remove_oldest_sample_next <= '1';
res_a <= ACCEPTED;
-- Only Insert Sample/Instance if Instance is ALIVE
if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then
-- Insert New Instance
inst_opcode <= INSERT_INSTANCE;
inst_op_start <= '1';
added_new_instance_next <= '1';
if (has_data = '1') then
payload_addr_next <= cur_payload;
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0 when GENERATION_COUNTERS else 2;
end if;
else
-- Drop Change
stage_next <= IDLE;
end if;
end if;
else
-- Accept Change
res_a <= ACCEPTED;
-- Only Insert Sample/Instance if Instance is ALIVE
if (sample_status_info(DISPOSED_FLAG) /= '1' and sample_status_info(UNREGISTERED_FLAG) /= '1' and sample_status_info(FILTERED_FLAG) /= '1') then
-- Insert New Instance
inst_opcode <= INSERT_INSTANCE;
inst_op_start <= '1';
if (has_data = '1') then
payload_addr_next <= cur_payload;
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0 when GENERATION_COUNTERS else 2;
end if;
else
-- Drop Change
stage_next <= IDLE;
end if;
end if;
end if;
end if;
when UPDATE_INSTANCE =>
-- Memory Operation Guard
if (inst_op_done = '1') then
-- DEFAULT
tmp_update := (others => '0');
-- Instance DISPOSED
if (sample_status_info(DISPOSED_FLAG) = '1') then
-- ALIVE -> NOT_ALIVE_DISPOSED Transition
if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1') then
-- STATUS INFO
tmp_update <= tmp_update or STATUS_FLAG;
instance_state <= NOT_ALIVE_DISPOSED;
end if;
-- WRITER BITMAP
-- Convert Writer Bitmap to SLV
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Remove Writer
tmp_bitmap(writer_pos) := '0';
-- Convert Back
writer_bitmap <= from_endpoint_bitmap(tmp_bitmap);
tmp_update := tmp_update or WRITER_BITMAP_FLAG;
-- Instance UNREGISTERED
elsif (sample_status_info(UNREGISTERED_FLAG) = '1') then
-- WRITER BITMAP
-- Convert Writer Bitmap to SLV
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Remove Writer
tmp_bitmap(writer_pos) := '0';
-- Convert Back
writer_bitmap <= from_endpoint_bitmap(tmp_bitmap);
tmp_update := tmp_update or WRITER_BITMAP_FLAG;
-- ALIVE -> NOT_ALIVE_NO_WRITERS Transition
if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) /= '1' and inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) /= '1' and tmp_bitmap = (tmp_bitmap => '0')) then
-- STATUS INFO
tmp_update <= tmp_update or STATUS_FLAG;
instance_state <= NOT_ALIVE_NO_WRITERS;
end if;
-- Instance ALIVE/FILTERED
else
-- STATUS INFO
tmp_update <= tmp_update or STATUS_FLAG;
instance_state <= ALIVE;
-- GENERATION COUNTERS
if (GENERATION_COUNTERS) then
-- NOT_ALIVE_DISPOSED -> ALIVE Transition
if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1') then
tmp_update := tmp_update or DISPOSED_CNT_FLAG;
gen_cnt <= inst_data.disposed_gen_cnt + 1;
-- NOT_ALIVE_NO_WRITERS -> ALIVE Transition
elsif (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1') then
tmp_update := tmp_update or NO_WRITERS_CNT_FLAG;
gen_cnt <= inst_data.no_writers_gen_cnt + 1;
end if;
end if;
-- WRITER BITMAP
-- Convert Writer Bitmap to SLV
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Write if Writer New for Instance
if (tmp_bitmap(writer_pos) /= '1') then
-- Remove Writer
tmp_bitmap(writer_pos) := '0';
-- Convert Back
writer_bitmap <= from_endpoint_bitmap(tmp_bitmap);
tmp_update := tmp_update or WRITER_BITMAP_FLAG;
end if;
end if;
-- INSTANCE SAMPLE COUNT
-- NOTE: Ignored when remove_oldest_inst_sample, since it will be decremented again. (Stays same)
if (remove_oldest_inst_sample = '0') then
tmp_update := tmp_update or SAMPLE_CNT_FLAG;
end if;
-- IGNORE DEADLINE
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
tmp_update := tmp_update or IGNORE_DEADLINE_FLAG;
deadline <= time + TIME_BASED_FILTER_QOS;
end if;
inst_opcode <= UPDATE_INSTANCE;
inst_op_start <= '1';
update_inst_flags <= tmp_update;
if (has_data = '1') then
payload_addr_next <= cur_payload;
stage_next <= FINALIZE_PAYLOAD;
cnt_next <= 0;
else
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0 when GENERATION_COUNTERS else 2;
end if;
end if;
when FINALIZE_PAYLOAD =>
-- Precondition: payload_addr (Beginning of Last Added Payload Slot)
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
payload_ren <= '1';
when 1 =>
-- Fix New Empty List Head
empty_payload_list_head_next <= payload_read_data;
-- Make current Slot the Tail
payload_write_data <= PAYLOAD_MEMORY_MAX_ADDRESS;
payload_wen <= '1';
stage_next <= PRE_SAMPLE_FINALIZE;
cnt_next <= 0 when GENERATION_COUNTERS else 2;
when others =>
null;
end case;
when PRE_SAMPLE_FINALIZE =>
-- Precondition: sample_addr (Disposed generation Counter of New Sample)
cnt_next <= cnt + 1;
case (cnt) is
-- Disposed Generation Counter
when 0 =>
if (GENERATION_COUNTERS) then
sample_addr_next <= sample_addr + 1;
sample_wen <= '1';
-- NOT_ALIVE_DISPOSED -> ALIVE Transition
if (inst_data.status_info(NOT_ALIVE_DISPOSED_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
sample_write_data <= gen_cnt + 1;
else
sample_write_data <= gen_cnt;
end if;
end if;
-- No Writer Generation Counter
when 1 =>
if (GENERATION_COUNTERS) then
sample_wen <= '1';
-- NOT_ALIVE_NO_WRITERS -> ALIVE Transition
if (inst_data.status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '1' and sample_status_info(NOT_ALIVE_DISPOSED_FLAG) = '0' and sample_status_info(NOT_ALIVE_NO_WRITERS_FLAG) = '0') then
sample_write_data <= gen_cnt + 1;
else
sample_write_data <= gen_cnt;
end if;
end if;
when 2 =>
-- First Sample
if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_next <= FINALIZE_SAMPLE_INFO;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cnt_next <= 0;
else
stage_next <= FIND_POS;
prev_sample_next <= newest_sample;
sample_addr_next <= newest_sample + SMF_TIMESTAMP_OFFSET;
cnt_next <= 0;
end if;
when others =>
null;
end case;
when FIND_POS =>
-- Precondition: prev_sample set, sample_addr (Timestamp 1/2 Addr of prev_sample)
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
sample_addr_next <= sample_addr + 1;
sample_ren <= '1';
-- Timestamp 1/2
when 1 =>
sample_addr_next <= sample_addr + SMF_PREV_ADDR_OFFSET-(SMF_TIMESTAMP_OFFSET+1); -- Prev Addr
sample_ren <= '1';
long_latch_next <= sample_read_data;
-- Timestamp 2/2
when 2 =>
sample_ren <= '1';
tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data));
sample_addr_next <= sample_addr + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Next Addr
-- Found position (After current slot)
if (ts_latch >= tmp_dw) then
stage_next <= FIX_POINTERS;
cnt_next <= 0;
end if;
-- Previous Address
when 3 =>
-- No previous Slot (Oldest Sample)
if (sample_read_data = PAYLOAD_MEMORY_MAX_ADDRESS) then
assert (prev_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but sample is not OLDEST (HEAD)" severity FAILURE;
stage_next <= FIX_POINTERS;
cnt_next <= 0;
else
prev_sample_next <= sample_read_data;
sample_addr_next <= sample_read_data + SMF_TIMESTAMP_OFFSET;
cnt_next <= 0;
end if;
end case;
when FIX_POINTERS =>
-- Precondition: sample_addr (Next Addr of prev_sample)
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
sample_ren <= '1';
when 1 =>
-- Fix Next Pointer
sample_write_data <= empty_sample_list_head;
sample_wen <= '1';
-- No next Slot (Newest Sample)
if (sample_read_data = SAMPLE_MEMORY_MAX_ADDRESS) then
assert (prev_sample = newest_sample) report "Next Sample is MAX_ADDRESS, but sample is not NEWEST (TAIL)" severity FAILURE;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
stage_next <= FINALIZE_SAMPLE_INFO;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample
cnt_next <= 0;
else
-- Latch Next Sample
next_sample_next <= sample_read_data;
sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample
end if;
when 2 =>
-- Fix Previous Pointer
sample_write_data <= empty_sample_list_head;
sample_wen <= '1';
stage_next <= FINALIZE_SAMPLE_INFO;
sample_addr_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample
cnt_next <= 0;
when others =>
null;
end case;
when FINALIZE_SAMPLE_INFO =>
-- Precondition: prev_sample set, next_sample set, sample_addr (Prev Addr of new sample)
cnt_next <= cnt + 1;
case (cnt) is
-- Previous Sample Address
when 0 =>
sample_addr_next <= sample_addr + 1; -- Next Sample
-- Write Prev Addr
sample_write_data <= prev_sample;
sample_wen <= '1';
-- Preload
when 1 =>
sample_ren <= '1';
-- Next Sample Address
when 2 =>
empty_sample_list_head_next <= sample_read_data;
-- Write Next Addr
sample_write_data <= next_sample;
sample_wen <= '1';
-- If newest Sample is now previous, select current sample as new newest
if (newest_sample = prev_sample) then
newest_sample_next <= empty_sample_list_head;
end if;
-- New Instance was added, and Instance Memory is Full
if (added_new_instance = '1' and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
-- Memory Operation Guard
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= GET_FIRST_INSTANCE;
stage_next <= REMOVE_STALE_INSTANCE;
else
cnt_next <= cnt; -- Keep State
end if;
elsif (remove_oldest_inst_sample = '1') then
sample_addr_next <= cur_sample + SMF_INSTANCE_ADDR_OFFSET;
stage_next <= FIND_OLDEST_INST_SAMPLE;
elsif (remove_oldest_sample = '1') then
stage_next <= GET_OLDEST_SAMPLE_INSTANCE;
else
-- DONE
stage_next <= IDLE;
end if;
end case;
when GET_OLDEST_SAMPLE_INSTANCE =>
-- Memory Operation Guard
if (inst_op_done = '1') then
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
sample_ren <= '1';
when 1 =>
inst_op_start <= '1';
inst_opcode <= SEARCH_INSTANCE_ADDR;
inst_addr_update <= sample_read_data;
cur_sample_next <= oldest_sample;
sample_addr_next <= oldest_sample + SMF_PREV_ADDR_OFFSET;
stage_next <= REMOVE_SAMPLE;
when others =>
null;
end case;
end if;
when FIND_OLDEST_INST_SAMPLE =>
-- Precondition: cur_sample set, sample_addr (Instance Address of cur_sample)
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
sample_ren <= '1';
sample_addr_next <= cur_sample + SMF_NEXT_ADDR_OFFSET; -- Next Addr
-- Instance Address
when 1 =>
sample_ren <= '1';
-- Oldest Instance Sample Found
if (sample_read_data = inst_addr_base) then
stage_next <= REMOVE_SAMPLE;
sample_addr_next <= cur_sample + SMF_PREV_ADDR_OFFSET;
end if;
-- Next Address
when 2 =>
cur_sample_next <= sample_read_data;
sample_addr_next <= sample_read_data + SMF_INSTANCE_ADDR_OFFSET; -- Instance Addr
cnt_next <= 0;
when others =>
null;
end case;
when REMOVE_SAMPLE =>
-- Precondition: cur_sample set, sample_addr (Previous Address of cur_sample)
-- Wait for Instance Search to finish
if (inst_op_done = '1') then
cnt_next <= cnt + 1;
case (cnt) is
-- Preload
when 0 =>
sample_ren <= '1';
sample_addr_next <= cur_sample + 1; -- Next Addr
-- Previous Addr (Current Sample)
when 1 =>
sample_ren <= '1';
prev_sample_next <= sample_read_data;
-- Next Addr (Current Sample)
when 2 =>
next_sample_next <= sample_read_data;
-- Make Current Sample Empty List Tail
sample_write_data <= INSTANCE_MEMORY_MAX_ADDRESS;
sample_wen <= '1';
-- Current Sample is Newest (Occupied List Tail)
if (sample_read_data = MAX_SAMPLE_ADDRESS) then
assert (cur_sample = newest_sample) report "Next Sample is MAX_ADDR, but cur_sample /= newest_sample" severity FAILURE;
-- Fix Newest Pointer
newest_sample_next <= prev_sample;
-- Current Sample is Oldest (List Head)
if (prev_sample = MAX_SAMPLE_ADDRESS) then
assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
assert (newest_sample = oldest_sample) report "Previous and Next Sample is MAX_ADDR, but cur_sample /= newest_sample /= oldest_sample" severity FAILURE;
-- Fix Oldest Pointer
oldest_sample_next <= MAX_SAMPLE_ADDRESS;
-- NOTE: Sample Memory Empty (newest_sample also set to MAX_ADDR)
-- Sample Memory Full
if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
empty_sample_list_head_next <= cur_sample;
empty_sample_list_tail_next <= cur_sample;
-- Skip to Payload Handling
cnt_next <= 6;
sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
else
-- Skip to Empty List Handling
cnt_next <= 5;
sample_addr_next <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
end if;
else
-- Skip to Previous Handling
sample_addr_next <= prev_sample + SMF_NEXT_ADDR_OFFSET;
cnt_next <= 4;
end if;
else
sample_addr_next <= sample_read_data + SMF_PREV_ADDR_OFFSET;
end if;
-- Previous Address (Next Sample)
when 3 =>
-- Remove link to cur_sample
sample_write_data <= prev_sample;
sample_wen <= '1';
-- Current Sample is oldest sample (List Head)
if (prev_sample = MAX_SAMPLE_ADDRESS) then
assert (cur_sample = oldest_sample) report "Previous Sample is MAX_ADDR, but cur_sample /= oldest_sample" severity FAILURE;
-- Fix Oldest Pointer
oldest_sample_next <= MAX_SAMPLE_ADDRESS;
-- Sample Memory Full
if (empty_sample_list_head = SAMPLE_MEMORY_MAX_ADDRESS) then
empty_sample_list_head_next <= cur_sample;
empty_sample_list_tail_next <= cur_sample;
-- Skip to Payload Handling
cnt_next <= 6;
sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
else
-- Skip to Empty List Handling
cnt_next <= 5;
sample_addr_next <= empty_sample_list_tail + SMF_NEXT_ADDR_OFFSET;
end if;
end if;
-- Next Address (Previous Sample)
when 4 =>
-- Remove link to cur_sample
sample_write_data <= next_sample;
sample_wen <= '1';
sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
-- Next Address (Empty Tail)
when 5 =>
sample_write_data <= cur_sample;
sample_wen <= '1';
-- Fix Empty List Pointers
empty_sample_list_tail_next <= cur_sample;
sample_addr_next <= cur_sample + SMF_PAYLOAD_ADDR_OFFSET;
-- Preload
when 6 =>
sample_ren <= '1';
-- Payload Address
when 7 =>
cur_payload_next <= sample_read_data;
-- Sample has no Data
if (sample_read_data = MAX_PAYLOAD_ADDRESS) then
stage_next <= POST_SAMPLE_REMOVE;
-- Payload Memory Full
elsif (empty_payload_list_head = MAX_PAYLOAD_ADDRESS) then
-- NOTE: Make the head of the Payload, the head of the Empty List
empty_payload_list_head_next <= sample_read_data;
stage_next <= POST_SAMPLE_REMOVE;
else
payload_addr_next <= cur_payload + PMF_NEXT_ADDR_OFFSET;
end if;
-- Preload
when 8 =>
payload_ren <= '1';
-- Next Payload Addr
when 9 =>
-- Found Empty List Tail
if (payload_read_data = MAX_PAYLOAD_ADDRESS) then
empty_payload_list_head_next <= cur_payload;
payload_write_data <= empty_payload_list_head;
payload_wen <= '1';
stage_next <= POST_SAMPLE_REMOVE;
else
payload_addr_next <= payload_read_data + PMF_NEXT_ADDR_OFFSET;
cnt_next <= 8;
end if;
when others =>
null;
end case;
end if;
when POST_SAMPLE_REMOVE =>
-- Memory Operation Guard
if (inst_op_done = '1') then
-- No Instance Change on remove_oldest_inst_sample
if (remove_oldest_inst_sample = '0') then
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Instance obsolete and Instance Memory Full
if (inst_data.sample_cnt = 1 and tmp_bitmap = (tmp_bitmap'range => '0') and inst_empty_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_op_start <= '1';
inst_opcode <= REMOVE_INSTANCE;
-- DONE
stage_next <= IDLE;
else
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
update_inst_flags <= SAMPLE_CNT_FLAG;
sample_cnt <= inst_data.sample_cnt - 1;
-- DONE
stage_next <= IDLE;
end if;
end if;
end if;
when SKIP_ADD =>
case (cnt) is
-- SKIP READ
when 0 =>
ready_in_a <= '1';
-- Wait until last word from input
if (last_word_in_a = '1') then
cnt_next <= 1;
end if;
-- REJECT SAMPLE
when 1 =>
res_a <= REJECTED;
stage_next <= IDLE;
when others =>
null;
end case;
when REMOVE_WRITER =>
-- Memory Operation Guard
if (inst_op_done = '1') then
-- No More Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Convert Writer Bitmap to SLV
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Remove Writer
tmp_bitmap(writer_pos) := '0';
-- NOTE: writer_bitmap is not latched, since the memory process is latching it at the
-- same clock cycle.
-- Convert Back
writer_bitmap <= from_endpoint_bitmap(tmp_bitmap);
-- No More Writers for Instance
if (tmp_bitmap = (tmp_bitmap'range => '0')) then
inst_op_start <= '1';
instance_state <= NOT_ALIVE_NO_WRITERS;
inst_opcode <= UPDATE_INSTANCE;
update_inst_flags <= STATUS_FLAG or WRITER_BITMAP_FLAG;
else
inst_op_start <= '1';
inst_opcode <= UPDATE_INSTANCE;
update_inst_flags <= WRITER_BITMAP_FLAG;
end if;
stage_next <= GET_NEXT_INSTANCE;
end if;
end if;
when GET_NEXT_INSTANCE =>
-- Wait for Operation to Complete
if (inst_op_done = '1') then
inst_op_start <= '1';
inst_opcode <= NEXT_INSTANCE;
stage_next <= REMOVE_WRITER;
end if;
when REMOVE_STALE_INSTANCE =>
-- Wait for Instance Data
if (inst_op_done = '1') then
-- Iterated through all Instances
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Convert Writer Bitmap to SLV
tmp_bitmap := to_endpoint_bitmap(inst_data.writer_bitmap);
-- Found Stale Instance (No Samples and No Active Writers)
if (inst_data.sample_cnt = 0 and tmp_bitmap = (tmp_bitmap'range => '0')) then
-- Remove Stale Instance
inst_op_start <= '1';
inst_opcode <= REMOVE_INSTANCE;
-- DONE
stage_next <= IDLE;
else
-- Continue Search
inst_op_start <= '1';
inst_opcode <= GET_NEXT_INSTANCE;
end if;
end if;
end if;
when others =>
null;
end case;
end process;
inst_ctrl_prc : process(all)
begin
-- DEFAULT Registered
inst_stage_next <= inst_stage;
inst_addr_base_next <= inst_addr_base;
inst_addr_next <= inst_addr;
inst_empty_head_next <= inst_empty_head;
inst_occupied_head_next <= inst_occupied_head;
inst_latch_data_next <= inst_latch_data;
inst_next_addr_base_next <= inst_next_addr_base;
inst_prev_addr_base_next <= inst_prev_addr_base;
inst_cnt_next <= inst_cnt;
inst_mem_full_next <= inst_mem_full;
inst_data_next <= inst_data;
-- DEFAULT Unregistered
inst_write_data <= (others => '0');
inst_op_done <= '0';
inst_ren <= '0';
inst_wen <= '0';
case (mem_stage) is
when IDLE =>
inst_op_done <= '1';
if (inst_op_start = '1') then
-- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
inst_latch_data_next <= (
key_hash => key_hash_next,
instance_state => instance_state,
sample_cnt => sample_cnt,
gen_cnt => gen_cnt,
deadline => deadline,
writer_bitmap => writer_bitmap,
update_flags => update_inst_flags,
addr => inst_addr_update
);
case(inst_opcode) is
when SEARCH_INSTANCE_HASH =>
-- Reset Data
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_addr_next <= inst_occupied_head;
inst_stage_next <= SEARCH_INSTANCE_HASH;
inst_cnt_next <= 0;
end if;
when SEARCH_INSTANCE_ADDR =>
-- Reset Data
inst_data_next <= ZERO_INSTANCE_DATA;
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_addr_next <= inst_occupied_head;
inst_stage_next <= SEARCH_INSTANCE_ADDR;
inst_cnt_next <= 0;
end if;
when INSERT_INSTANCE =>
-- NOTE: Since this process has no way to communicate a failed insert to the main process, it has to be made sure
-- by the main process that the operation can succeed (Memory is available)
assert (inst_empty_head /= INSTANCE_MEMORY_MAX_ADDRESS) report "Instance Insertion while memory Full" severity FAILURE;
inst_addr_next <= inst_empty_head;
inst_addr_base_next <= inst_empty_head;
inst_stage_next <= INSERT_INSTANCE;
inst_cnt_next <= 0;
when UPDATE_INSTANCE =>
inst_addr_base_next <= inst_addr_update;
if ((update_inst_flags and STATUS_FLAG) = STATUS_FLAG) then
inst_stage_next <= UPDATE_INSTANCE;
inst_addr_next <= inst_addr_update + IMF_STATUS_INFO_OFFSET;
inst_cnt_next <= 0;
elsif ((update_inst_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
inst_stage_next <= UPDATE_INSTANCE;
inst_addr_next <= inst_addr_update + IMF_SAMPLE_CNT_OFFSET;
inst_cnt_next <= 3;
elsif (GENERATION_COUNTERS and (update_inst_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_stage_next <= UPDATE_INSTANCE;
inst_addr_next <= inst_addr_update + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_next <= 6;
elsif (GENERATION_COUNTERS and (update_inst_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_stage_next <= UPDATE_INSTANCE;
inst_addr_next <= inst_addr_update + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (update_inst_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_stage_next <= UPDATE_INSTANCE;
inst_addr_next <= inst_addr_update + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_next <= 8;
elsif ((update_inst_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_stage_next <= SET_WRITER_BITMAP;
inst_addr_next <= inst_addr_update + IMF_WRITER_BITMAP_OFFSET;
inst_cnt_next <= 0;
end if;
when GET_FIRST_INSTANCE =>
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_addr_next <= inst_occupied_head + IMF_STATUS_INFO_OFFSET;
inst_stage_next <= GET_INSTANCE_DATA;
inst_cnt_next <= 0;
end if;
when GET_NEXT_INSTANCE =>
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_addr_next <= inst_next_addr_base;
inst_stage_next <= GET_NEXT_INSTANCE;
inst_cnt_next <= 0;
when REMOVE_INSTANCE =>
assert (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) report "Request Removal on empty memory" severity FAILURE;
inst_prev_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_next <= inst_occupied_head;
inst_addr_next <= inst_occupied_head;
inst_stage_next <= REMOVE_INSTANCE;
inst_cnt_next <= 0;
when others =>
null;
end case;
end if;
when SEARCH_INSTANCE_HASH =>
inst_ren <= '1';
inst_cnt_next <= inst_cnt + 1;
inst_addr_next <= inst_addr + 1;
case (inst_cnt) is
-- Preload
when 0 =>
null;
-- Next Instance
when 1 =>
inst_next_addr_base_next <= inst_read_data;
-- Key Hash 1/4
when 2 =>
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(0)) then
-- Reached List Tail, No Match
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_addr_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
-- Key Hash 2/4
when 3 =>
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(1)) then
-- Reached List Tail, No Match
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_addr_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
-- Key Hash 3/4
when 4 =>
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(2)) then
-- Reached List Tail, No Match
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_addr_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
end if;
-- Key Hash 4/4
when 5 =>
-- No Match
if (inst_read_data /= inst_latch_data.key_hash(3)) then
-- Reached List Tail, No Match
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_next_addr_base;
inst_addr_next <= inst_next_addr_base;
inst_cnt_next <= 0;
end if;
-- Match
else
-- Fetch Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
inst_cnt_next <= 1; -- No preload needed
end if;
when others =>
null;
end case;
when SEARCH_INSTANCE_ADDR =>
inst_cnt_next <= inst_cnt + 1;
inst_addr_next <= inst_addr + 1;
case (inst_cnt) is
-- Preload
when 0 =>
inst_ren <= '1';
-- Next Instance
when 1 =>
inst_prev_addr_base_next <= inst_addr_base;
inst_addr_base_next <= inst_read_data;
-- No Match
if (inst_read_data /= inst_latch_data.addr) then
-- Fetch Instance Data
inst_stage_next <= GET_INSTANCE_DATA;
inst_addr_next <= inst_read_data + IMF_STATUS_INFO_OFFSET;
inst_cnt_next <= 0;
-- Match
else
-- Reached List Tail, No Match
if (inst_addr_base = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_next <= IDLE;
else
-- Continue Search
inst_addr_next <= inst_read_data;
inst_cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
when GET_NEXT_INSTANCE =>
case (inst_cnt) is
-- Preload
when 0 =>
inst_wen <= '1';
-- Next Instance
when 1 =>
-- Latch Next Instance
inst_next_addr_base_next <= inst_read_data;
inst_addr_next <= inst_addr_base + IMF_STATUS_INFO_OFFSET;
inst_cnt_next <= 0;
inst_stage_next <= GET_INSTANCE_DATA;
end case;
when GET_INSTANCE_DATA =>
-- Precondition: inst_addr (Status Info)
inst_ren <= '1';
inst_cnt_next <= inst_cnt + 1;
inst_addr_next <= inst_addr + 1;
case (inst_cnt) is
-- Memory Preload
when 0 =>
null;
-- Status Info
when 1 =>
inst_data_next.status_info <= inst_read_data;
-- Sample Count
when 2 =>
inst_data_next.sample_cnt <= inst_read_data;
-- Disposed Generation Count
when 3 =>
inst_data_next.disposed_gen_cnt <= inst_read_data;
-- No Writers Generation Count
when 4 =>
inst_data_next.no_writers_gen_cnt <= inst_read_data;
-- Ignore Deadline 1/2
when 5 =>
inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data);
-- Ignore Deadline 2/2
when 5 =>
inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data);
-- DONE
inst_stage_next <= GET_WRITER_BITMAP;
inst_cnt_next <= 0;
when others =>
null;
end case;
when GET_WRITER_BITMAP =>
inst_cnt_next <= inst_cnt + 1;
inst_latch_data_next.writer_bitmap(inst_cnt) <= inst_read_data;
if (inst_cnt = writer_bitmap'length-1) then
-- DONE
inst_stage_next <= IDLE;
end if;
when INSERT_INSTANCE =>
inst_wen <= '1';
inst_addr_next <= inst_addr + 1;
inst_cnt_next <= inst_cnt + 1;
case (inst_cnt) is
-- Preload
when 0 =>
inst_ren <= '1';
-- Next Instance Address
when 1 =>
inst_empty_head_next <= inst_read_data;
-- Make New Occupied Head
inst_write_data <= inst_occupied_head;
inst_occupied_head_next <= inst_empty_head;
-- Key Hash 1/4
when 2 =>
inst_write_data <= inst_latch_data.key_hash(0);
-- Key Hash 2/4
when 3 =>
inst_write_data <= inst_latch_data.key_hash(1);
-- Key Hash 3/4
when 4 =>
inst_write_data <= inst_latch_data.key_hash(2);
-- Key Hash 4/4
when 5 =>
inst_write_data <= inst_latch_data.key_hash(3);
-- Status Info
when 6 =>
inst_write_data <= inst_latch_data.status_info;
-- Sample Count
when 7 =>
inst_write_data <= std_logic_vector(to_unsigned(1, WORD_WIDTH));
if (GENERATION_COUNTERS) then
inst_cnt <= 8;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt <= 10;
else
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
end if;
-- Disposed Generation Count
when 8 =>
if (GENERATION_COUNTERS) then
inst_write_data <= (others => '0');
end if;
-- No Writers Generation Count
when 9 =>
if (GENERATION_COUNTERS) then
inst_write_data <= (others => '0');
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt <= 10;
else
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
end if;
end if;
-- Ignore Deadline 1/2
when 10 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_write_data <= inst_latch_data.deadline(0);
end if;
-- Ignore Deadline 1/2
when 11 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_write_data <= inst_latch_data.deadline(1);
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
end if;
when others =>
null;
end case;
when SET_WRITER_BITMAP =>
inst_wen <= '1';
inst_addr_next <= inst_addr + 1;
inst_cnt_next <= inst_cnt + 1;
inst_write_data <= inst_latch_data.writer_bitmap(inst_cnt);
-- Exit Condition
if (inst_cnt = inst_latch_data.writer_bitmap'length-1) then
-- DONE
inst_stage_next <= IDLE;
end if;
when UPDATE_INSTANCE =>
inst_cnt_next <= inst_cnt + 1;
case (inst_cnt) is
-- Status Info
when 0 =>
inst_wen <= '1';
inst_write_data <= inst_long_latch;
case (inst_latch_data.instance_state) is
when ALIVE =>
inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
inst_write_data(LIVELINESS_FLAG) <= '1';
when NOT_ALIVE_DISPOSED =>
inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '1';
inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
inst_write_data(LIVELINESS_FLAG) <= '1';
when NOT_ALIVE_NO_WRITERS =>
inst_write_data(NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_write_data(NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
inst_write_data(LIVELINESS_FLAG) <= '1';
end case;
if ((inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_SAMPLE_CNT_OFFSET;
inst_cnt_next <= 1;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_next <= 2;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_next <= 4;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
-- Sample Count
when 1 =>
inst_wen <= '1';
inst_write_data <= inst_latch_data.sample_cnt;
if (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_next <= 2;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_next <= 4;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
-- Disposed Generation Count
when 2 =>
if (GENERATION_COUNTERS) then
inst_wen <= '1';
inst_write_data <= inst_latch_data.gen_cnt;
if (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_addr_next <= inst_addr_base + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_next <= 3;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_next <= 4;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- No Writers Generation Count
when 3 =>
if (GENERATION_COUNTERS) then
inst_wen <= '1';
inst_write_data <= inst_latch_data.gen_cnt;
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_next <= inst_addr_base + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_next <= 4;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
-- Ignore Deadline 1/2
when 4 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_wen <= '1';
inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(0));
end if;
-- Ignore Deadline 2/2
when 5 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_wen <= '1';
inst_write_data <= std_logic_vector(inst_latch_data.ignore_deadline(1));
if ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_next <= inst_addr_base + IMF_WRITER_BITMAP_OFFSET;
inst_stage_next <= SET_WRITER_BITMAP;
inst_cnt_next <= 0;
else
-- DONE
inst_stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when REMOVE_INSTANCE =>
inst_cnt_next <= inst_cnt + 1;
case (inst_cnt) is
-- Preload
when 0 =>
inst_ren <= '1';
inst_addr_next <= inst_prev_addr_base + IMF_NEXT_ADDR_OFFSET;
-- Next Instance (Previous Occupied Instance)
when 1 =>
-- Fix Pointer
inst_write_data <= inst_read_data;
inst_wen <= '1';
inst_addr_next <= inst_addr_base + IMF_NEXT_ADDR_OFFSET;
-- Next Instance (Current Instance)
when 2 =>
-- Fix Pointer
inst_write_data <= inst_empty_head;
inst_wen <= '1';
-- Fix Empty List Head
inst_empty_head_next <= inst_addr_base;
-- DONE
inst_stage_next <= IDLE;
when others =>
null;
end case;
when others =>
null;
end case;
end process;
end architecture;