rtps-fpga/src/history_cache.vhd
Greek f2826ddd20 Change Sample Memory Format
The Sample Memory was changed to contain only the Instance Memory
Address instead of the whole Key Hash. This simplifies the B process and
reduces memory footprint.
The instance memory process was also updated to handle the conditional
fields defined in the previous commit.
2021-01-17 21:01:15 +01:00

1680 lines
90 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity history_cache is
generic (
TIME_BASED_FILTER_QOS : DURATION_TYPE := DEFAULT_TIME_BASED_FILTER_QOS;
MAX_INSTANCES : natural := DEFAULT_MAX_INSTANCES;
MAX_SAMPLES_PER_INSTANCE : natural := DEFAULT_MAX_SAMPLES_PER_INSTANCE;
HISTORY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_HISTORY_QOS;
RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS;
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;
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);
release_lock : std_logic;
end record;
constant ZERO_INST_LATCH_DATA : INST_LATCH_DATA_TYPE := (
key_hash => (others => (others => '0')),
instance_state => ALIVE,
gen_cnt => (others => '0'),
deadline => TIME_INVALID,
writer_bitmap => (others => (others => '0')),
update_flags => (others => '0'),
release_lock => '0'
);
--*****SIGNAL DECLARATION
signal sample_addr_a, sample_addr_a_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_addr_b, sample_addr_b_next : unsigned(SAMPLE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal sample_wen_a, sample_wen_b : std_logic := '0';
signal sample_ren_a, sample_ren_b : std_logic := '0';
signal sample_read_data_a, sample_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal sample_write_data_a, sample_write_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal payload_addr_a, payload_addr_a_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_addr_b, payload_addr_b_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal payload_wen_a, payload_wen_b : std_logic := '0';
signal payload_ren_a, payload_ren_b : std_logic := '0';
signal payload_read_data_a, payload_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal payload_write_data_a, payload_write_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal inst_addr_a, inst_addr_a_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_addr_b, inst_addr_b_next : unsigned(PAYLOAD_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_wen_a, inst_wen_b : std_logic := '0';
signal inst_ren_a, inst_ren_b : std_logic := '0';
signal inst_read_data_a, inst_read_data_b : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal inst_write_data_a, inst_write_data_b : 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_a, stage_a_next : STAGE_TYPE := IDLE;
signal cnt_a, cnt_a_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 empty_payload_list_tail, empty_payload_list_tail_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 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 od_instance_sample_removal : std_logic := '0';
signal od_oldest_sample_removal : std_logic := '0';
signal od_sample_removal_done : 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 release_inst_lock : std_logic := '0';
signal inst_op_start_a : std_logic := '0';
signal inst_op_done_a : std_logic := '0';
signal inst_opcode_a : INSTANCE_OPCODE_TYPE := NOP;
signal inst_stage_a, inst_stage_a_next : INST_STAGE_TYPE := IDLE;
signal inst_addr_base_a, inst_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_addr_base_a, inst_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_next_addr_base_a, inst_next_addr_base_a_next : unsigned(INSTANCE_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal inst_prev_addr_base_a, inst_prev_addr_base_a_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_a : std_logic_vector(0 to UPDATE_INSTANCE_FLAG_WIDTH-1) := (others => '0');
signal inst_cnt_a, inst_cnt_a_next : natural range TODO := 0;
signal inst_mem_full, inst_mem_full_next : std_logic := '0';
signal inst_delete_lock_a, inst_delete_lock_a_next : std_logic := '0';
signal inst_atomic_lock_a : std_logic := '0';
signal inst_long_latch_a, inst_long_latch_a_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_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.true_dual_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_a => sample_addr_a,
addr_b => sample_addr_b,
wen_a => sample_wen_a,
wen_b => sample_wen_b,
ren_a => sample_ren_a,
ren_b => sample_ren_b,
wr_data_a => sample_write_data_a,
wr_data_b => sample_write_data_b,
rd_data_a => sample_read_data_a,
rd_data_b => sample_read_data_b
);
payload_ram_inst : entity work.true_dual_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_a => payload_addr_a,
addr_b => payload_addr_b,
wen_a => payload_wen_a,
wen_b => payload_wen_b,
ren_a => payload_ren_a,
ren_b => payload_ren_b,
wr_data_a => payload_write_data_a,
wr_data_b => payload_write_data_b,
rd_data_a => payload_read_data_a,
rd_data_b => payload_read_data_b
);
instance_ram_inst : entity work.true_dual_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_a => inst_addr_a,
addr_b => inst_addr_b,
wen_a => inst_wen_a,
wen_b => inst_wen_b,
ren_a => inst_ren_a,
ren_b => inst_ren_b,
wr_data_a => inst_write_data_a,
wr_data_b => inst_write_data_b,
rd_data_a => inst_read_data_a,
rd_data_b => inst_read_data_b
);
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_a_next <= stage_a;
res_a <= UNDEFINED;
sample_addr_a_next <= sample_addr_a;
sample_write_data_a <= (others => '0');
sample_ren_a <= '0';
sample_wen_a <= '0';
payload_addr_a_next <= payload_addr_a;
payload_write_data_a <= (others => '0');
payload_ren_a <= '0';
payload_wen_a <= '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;
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_a <= NOP;
key_hash_next <= key_hash;
sample_status_info_next <= sample_status_info;
inst_op_start_a <= '0';
khg_last_word_in <= '0';
khg_data_in <= (others => '0');
khg_valid_in <= '0';
khg_ready_out <= '0';
writer_bitmap <= (others => '0');
od_instance_sample_removal <= '0';
od_oldest_sample_removal <= '0';
release_inst_lock <= '0';
-- Reset Payload Memory Fullness Indicator
if (payload_mem_full = '1' and empty_payload_list_head /= empty_payload_list_tail) then
payload_mem_full_next <= '0';
end if;
-- Reset Sample Memory Fullness Indicator
if (sample_mem_full = '1' and empty_sample_list_head /= empty_sample_list_tail) then
sample_mem_full_next <= '0';
end if;
case (stage_a) is
when IDLE =>
-- Release Instance Memory Lock
if (inst_delete_lock_a = '1' and inst_op_done_a = '1') then
inst_op_start_a <= '1';
inst_opcode_a <= RELEASE_LOCK;
end if;
if (start_a = '1') then
ready_in_a <= '1';
case (opcode_a) is
when ADD_CHANGE =>
-- This Operation does not accept input at this time
ready_in_a <= '0';
-- If memory Full
if (sample_mem_full = '1' or payload_mem_full = '1') then
stage_a_next <= WAIT_FOR_REMOVE;
res_a <= ACK;
else
stage_a_next <= ADD_SAMPLE_INFO;
sample_addr_a_next <= empty_sample_list_head;
cnt_a_next <= 0;
res_a <= ACK;
end if;
when REMOVE_WRITER =>
-- Input and Memory Gurad
if (valid_in_a = '1' and inst_op_done_a = '1') then
-- Latch Writer Pos
writer_pos_next <= to_integer(unsigned(data_in_a));
inst_op_start_a <= '1';
inst_opcode_a <= GET_FIRST_INSTANCE;
stage_a_next <= REMOVE_WRITER;
res_a <= ACK;
end if;
when others =>
null;
end case;
end if;
when ADD_SAMPLE_INFO =>
-- Precondition: sample_addr_a (empty_sample_list_head)
ready_in_a <= '1';
-- Input Guard
if (valid_in_a = '1') then
cnt_a_next <= cnt_a + 1;
sample_addr_a_next <= sample_addr_a + 1;
-- Write Through
sample_wen_a <= '1';
sample_write_data_a <= data_in_a;
case (cnt_a) is
-- Status Info
when 0 =>
-- Initialize local status bits
sample_write_data_a(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;
-- Lifespna Deadline 2/2
when 4 =>
-- Skip Key Hash, if not available
if (has_key_hash = '0') then
cnt_a_next <= 9;
end if;
-- Latch Key Hash
-- Key Hash 1/4
when 5 =>
-- Latch Input, but do not pass to Memory
sample_wen_a <= '0';
sample_addr_a_next <= sample_addr_a;
key_hash_next(0) <= data_in_a;
-- Key Hash 2/4
when 6 =>
-- Latch Input, but do not pass to Memory
sample_wen_a <= '0';
sample_addr_a_next <= sample_addr_a;
key_hash_next(1) <= data_in_a;
-- Key Hash 3/4
when 7 =>
-- Latch Input, but do not pass to Memory
sample_wen_a <= '0';
sample_addr_a_next <= sample_addr_a;
key_hash_next(2) <= data_in_a;
-- Key Hash 4/4
when 8 =>
-- Latch Input, but do not pass to Memory
sample_wen_a <= '0';
sample_addr_a_next <= sample_addr_a;
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_a <= '0';
sample_addr_a_next <= sample_addr_a;
stage_a_next <= ADD_PAYLOAD_ADDRESS;
when others =>
null;
end case;
end if;
when ADD_PAYLOAD_ADDRESS =>
-- Precondition: sample_addr_a (Payload Address)
sample_addr_a_next <= sample_addr_a + 1; -- Instance Address
if (has_data = '1') then
-- Store Payload Address
sample_wen_a <= '1';
sample_write_data_a <= empty_payload_list_head;
payload_addr_a_next <= empty_payload_list_head + PMF_NEXT_ADDR_OFFSET;
cur_payload_next <= empty_payload_list_head;
else
-- Mark Sample with no Payload
sample_wen_a <= '1';
sample_write_data_a <= PAYLOAD_MEMORY_MAX_ADDRESS;
end if;
-- If key Hash is avialable, start the Instacne Search first
if (has_key_hash = '1') then
stage_a_next <= INITIATE_INSTANCE_SEARCH;
else
stage_a_next <= ADD_PAYLOAD;
cnt_a_next <= 0;
end if;
when ADD_PAYLOAD =>
-- Precondition (if has_data = '1'): cur_payload set (Current Slot), payload_addr_a (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_a_next <= cnt_a + 1;
payload_addr_a_next <= payload_addr_a + PMF_NEXT_ADDR_OFFSET;
-- Payload Write
if (has_data = '1') then
payload_write_data_a <= data_in_a;
payload_wen_a <= '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_a_next <= GET_KEY_HASH;
cnt_a_next <= 0;
else
stage_a_next <= FILTER_STAGE;
end if;
-- End of Payload Slot
elsif (has_data = '1' and cnt_a = PAYLOAD_FRAME_SIZE-2) then
stage_a_next <= NEXT_PAYLOAD_SLOT;
payload_addr_a_next <= cur_payload;
cnt_a_next <= 0;
end if;
end if;
when NEXT_PAYLOAD_SLOT =>
-- Precondition: payload_addr_a (Beginning of current Slot)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Preload
when 0 =>
payload_ren_a <= '1';
when 1 =>
-- No Empty Payload Slots available
if (payload_read_data_a = PAYLOAD_MEMORY_MAX_ADDRESS) then
-- TODO
else
-- Latch next Payload Slot and Continue
cur_payload_next <= payload_read_data_a;
payload_addr_a_next <= payload_read_data_a + PMF_NEXT_ADDR_OFFSET;
stage_a_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_a_next <= cnt_a + 1;
-- Latch Key Hash
key_hash_next(cnt_a) <= khg_data_out;
-- Exit Condition
if (khg_last_word_out = '1') then
-- DONE
stage_a_next <= INITIATE_INSTANCE_SEARCH;
end if;
end if;
when INITIATE_INSTANCE_SEARCH =>
-- Memory Operation Guard
if (inst_op_done_a = '1') then
inst_opcode_a <= SEARCH_INSTANCE;
inst_op_start_a <= '1';
-- Payload not yet stored
if (has_data = '1') then
stage_a_next <= ADD_PAYLOAD;
cnt_a_next <= 0;
else
stage_a_next <= FILTER_STAGE;
end if;
end if;
when FILTER_STAGE =>
-- Precondition: sample_addr_a (Instance Address of New Sample)
-- Wait for Instance Search to finish
if (inst_op_done_a = '1') then
sample_addr_a_next <= sample_addr_a + 1; -- Disposed Gen Counter (Prev Address if GENERATION_COUNTERS=FALSE)
-- Instance Found
if (inst_addr_base_a /= INSTANCE_MEMORY_MAX_ADDRESS) then
-- Store Instance Address
sample_write_data_a <= inst_addr_base_a;
sample_wen_a <= '1';
-- TIME_BASED_FILTER QOS
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO and time < inst_data.ignore_deadline) then
-- Reject Change
res_a <= REJECTED;
stage_a_next <= IDLE;
-- RESOURCE_LIMITS_QOS / HISTORY_QOS
elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and inst_data.sample_cnt = MAX_SAMPLES_PER_INSTANCE) then
if (HISTORY_QOS = KEEP_LAST_HISTORY_QOS) then
-- Reject Change
res_a <= REJECTED;
stage_a_next <= IDLE;
else
od_instance_sample_removal <= '1';
-- Wait until B process completes On-Demand Sample Removal
if (od_sample_removal_done = '1') then
-- Accept Change
res_a <= ACCEPTED;
stage_a_next <= UPDATE_INSTANCE;
end if;
end if;
else
-- Accept Change
res_a <= ACCEPTED;
stage_a_next <= UPDATE_INSTANCE;
end if;
else
-- Store Instance Address
sample_write_data_a <= inst_empty_head;
sample_wen_a <= '1';
-- MAX_INSTANCES Reached (Instance Memory Full)
if (inst_mem_full = '1') then
-- Reject Change
res_a <= REJECTED;
stage_a_next <= IDLE;
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_a <= INSERT_INSTANCE;
inst_op_start_a <= '1';
release_inst_lock <= '1';
if (has_data = '1') then
payload_addr_a_next <= cur_payload;
stage_a_next <= FINALIZE_PAYLOAD;
cnt_a_next <= 0;
else
stage_a_next <= SAMPLE_PRE_FINISH;
cnt_a_next <= 0 when GENERATION_COUNTERS else 2;
end if;
else
-- Ignore
stage_a_next <= IDLE;
end if;
end if;
end if;
end if;
when UPDATE_INSTANCE =>
-- Memory Operation Guard
if (inst_op_done_a = '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;
-- INSANCE SAMPLE COUNT
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) 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_a <= UPDATE_INSTANCE;
inst_op_start_a <= '1';
release_inst_lock <= '1';
update_inst_flags_a <= tmp_update;
if (has_data = '1') then
payload_addr_a_next <= cur_payload;
stage_a_next <= FINALIZE_PAYLOAD;
cnt_a_next <= 0;
else
stage_a_next <= SAMPLE_PRE_FINISH;
cnt_a_next <= 0 when GENERATION_COUNTERS else 2;
end if;
end if;
when FINALIZE_PAYLOAD =>
-- Precondition: payload_addr_a (Beginning of Last Added Payload Slot)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Preload
when 0 =>
payload_ren_a <= '1';
when 1 =>
-- No Empty Payload Slot available
if (payload_read_data_a = PAYLOAD_MEMORY_MAX_ADDRESS) then
assert (cur_payload = empty_payload_list_tail) report "Payload List empty, but HEAD /= TAIL" severity FAILURE;
-- Signal Sample Memory Full
payload_mem_full_next <= '1';
else
empty_payload_list_head_next <= payload_read_data_a;
end if;
-- Make current Slot the Tail
payload_write_data_a <= PAYLOAD_MEMORY_MAX_ADDRESS;
payload_wen_a <= '1';
stage_a_next <= SAMPLE_PRE_FINISH;
cnt_a_next <= 0 when GENERATION_COUNTERS else 2;
when others =>
null;
end case;
when SAMPLE_PRE_FINISH =>
-- Precondition: sample_addr_a (Disposed generation Counter of New Sample)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Disposed Generation Counter
when 0 =>
if (GENERATION_COUNTERS) then
sample_addr_a_next <= sample_addr_a + 1;
sample_wen_a <= '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_a <= gen_cnt + 1;
else
sample_write_data_a <= gen_cnt;
end if;
end if;
-- No Writer Generation Counter
when 1 =>
if (GENERATION_COUNTERS) then
sample_wen_a <= '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_a <= gen_cnt + 1;
else
sample_write_data_a <= gen_cnt;
end if;
end if;
when 2 =>
-- First Sample
if (newest_sample = SAMPLE_MEMORY_MAX_ADDRESS) then
stage_a_next <= FINALIZE_SAMPLE_INFO;
sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET;
next_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
prev_sample_next <= SAMPLE_MEMORY_MAX_ADDRESS;
cnt_a_next <= 0;
else
stage_a_next <= FIND_POS;
prev_sample_next <= newest_sample;
sample_addr_a_next <= newest_sample + SMF_TIMESTAMP_OFFSET;
cnt_a_next <= 0;
end if;
when others =>
null;
end case;
when FIND_POS =>
-- Precondition: prev_sample set, sample_addr_a (Timestamp 1/2 Addr of prev_sample)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Preload
when 0 =>
sample_addr_a_next <= sample_addr_a + 1;
sample_ren_a <= '1';
-- Timestamp 1/2
when 1 =>
sample_addr_a_next <= sample_addr_a + SMF_PREV_ADDR_OFFSET-(SMF_TIMESTAMP_OFFSET+1); -- Prev Addr
sample_ren_a <= '1';
long_latch_next <= sample_read_data_a;
-- Timestamp 2/2
when 2 =>
sample_ren_a <= '1';
tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(sample_read_data_a));
sample_addr_a_next <= sample_addr_a + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET; -- Next Addr
-- Found position (After current slot)
if (ts_latch >= tmp_dw) then
stage_a_next <= FIX_POINTERS;
cnt_a_next <= 0;
end if;
-- Previous Address
when 3 =>
-- No previous Slot (Oldest Sample)
if (sample_read_data_a = 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_a_next <= FIX_POINTERS;
cnt_a_next <= 0;
else
prev_sample_next <= sample_read_data_a;
sample_addr_a_next <= sample_read_data_a + SMF_TIMESTAMP_OFFSET;
cnt_a_next <= 0;
end if;
end case;
when FIX_POINTERS =>
-- Precondition: sample_addr_a (Next Addr of prev_sample)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Preload
when 0 =>
sample_ren_a <= '1';
when 1 =>
-- Fix Next Pointer
sample_write_data_a <= empty_sample_list_head;
sample_wen_a <= '1';
-- No next Slot (Newest Sample)
if (sample_read_data_a = 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_a_next <= FINALIZE_SAMPLE_INFO;
sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample
cnt_a_next <= 0;
else
-- Latch Next Sample
next_sample_next <= sample_read_data_a;
sample_addr_a_next <= sample_read_data_a + SMF_PREV_ADDR_OFFSET; -- Prev Addr of Next Sample
end if;
when 2 =>
-- Fix Previous Pointer
sample_write_data_a <= empty_sample_list_head;
sample_wen_a <= '1';
stage_a_next <= FINALIZE_SAMPLE_INFO;
sample_addr_a_next <= empty_sample_list_head + SMF_PREV_ADDR_OFFSET; -- Prev Addr of New Sample
cnt_a_next <= 0;
when others =>
null;
end case;
when FINALIZE_SAMPLE_INFO =>
-- Precondition: prev_sample set, next_sample set, sample_addr_a (Prev Addr of new sample)
cnt_a_next <= cnt_a + 1;
case (cnt_a) is
-- Previous Address
when 0 =>
sample_addr_a_next <= sample_addr_a + SMF_NEXT_ADDR_OFFSET-SMF_PREV_ADDR_OFFSET;
-- Write Prev Addr
sample_write_data_a <= prev_sample;
sample_ren_a <= '1';
-- Preload
when 1 =>
sample_ren_a <= '1';
-- Next Address
when 2 =>
-- No empty Sample Slot Available
if (sample_read_data_a = SAMPLE_MEMORY_MAX_ADDRESS) then
-- Signal Smaple Memory Full
sample_mem_full_next <= '1';
else
empty_sample_list_head_next <= sample_read_data_a;
end if;
-- Write Next Addr
sample_write_data_a <= next_sample;
sample_ren_a <= '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;
-- DONE
stage_a_next <= IDLE;
end case;
when SKIP_ADD =>
case (cnt_a) is
-- SKIP READ
when 0 =>
ready_in_a <= '1';
-- Wait until last word from input
if (last_word_in_a = '1') then
cnt_a_next <= 1;
end if;
-- REJECT SAMPLE
when 1 =>
res_a <= REJECTED;
stage_a_next <= IDLE;
when others =>
null;
end case;
when REMOVE_WRITER =>
-- Memory Operation Guard
if (inst_op_done_a = '1') then
-- No More Instances
if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then
-- DONE
stage_a_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_a <= '1';
instance_state <= NOT_ALIVE_NO_WRITERS;
inst_opcode_a <= UPDATE_INSTANCE;
update_inst_flags_a <= STATUS_FLAG or WRITER_BITMAP_FLAG;
else
inst_op_start_a <= '1';
inst_opcode_a <= UPDATE_INSTANCE;
update_inst_flags_a <= WRITER_BITMAP_FLAG;
end if;
stage_a_next <= GET_NEXT_INSTANCE;
end if;
end if;
when GET_NEXT_INSTANCE =>
-- Wait for Operation to Complete
if (inst_op_done_a = '1') then
inst_op_start_a <= '1';
inst_opcode_a <= NEXT_INSTANCE;
stage_a_next <= REMOVE_WRITER;
end if;
when WAIT_FOR_REMOVE =>
-- Stall Input
ready_in_a <= '0';
if (HISTORY_QOS = KEEP_ALL_HISTORY_QOS and RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Reject Change
stage_a_next <= SKIP_ADD;
cnt_a_next <= 0;
else
od_oldest_sample_removal <= '1';
-- NOTE: We are ignoring the od_sample_removal_done signal of process B, because in this
-- case we can directly observe the status from the available signals. This cannot
-- be done in the MAX_SAMPLES_PER_INSTANCE removal case, since there we have to wait
-- until process B explicitly states that it has removed a sample of the offending instance.
-- In addition to that, the removal of the oldest sample is no guarantee that the payload
-- memory will also get freed (Since the oldest sample may be one without data).
-- Here we are keeping the od_oldest_sample_removal signal high (meaning process B will keep
-- removing samples) as long as it takes for both memories to get freed.
-- Memory Available
if (sample_mem_full = '0' and payload_mem_full = '0') then
stage_a_next <= ADD_SAMPLE_INFO;
sample_addr_a_next <= empty_sample_list_head;
cnt_a_next <= 0;
end if;
end if;
when others =>
null;
end case;
end process;
signal stage_b, stage_b_next : STAGE_TYPE := IDLE;
parse_b_prc : process (all)
begin
-- DEFAULT
stage_b_next <= stage_b;
case (stage_b) is
when IDLE =>
if (start_b = '1') then
case (opcode_b) is
when others =>
null;
end case;
end if;
when others =>
null;
end case;
end process;
inst_ctrl_prc : process(all)
begin
-- DEFAULT Registered
inst_stage_a_next <= inst_stage_a;
inst_addr_base_a_next <= inst_addr_base_a;
inst_addr_a_next <= inst_addr_a;
inst_empty_head_next <= inst_empty_head;
inst_occupied_tail_next <= inst_occupied_tail;
inst_latch_data_next <= inst_latch_data;
inst_next_addr_base_a_next <= inst_next_addr_base_a;
inst_prev_addr_base_a_next <= inst_prev_addr_base_a;
inst_cnt_a_next <= inst_cnt_a;
inst_mem_full_next <= inst_mem_full;
inst_delete_lock_a_next <= inst_delete_lock_a;
inst_data_next <= inst_data;
-- DEFAULT Unregistered
inst_write_data_a <= (others => '0');
inst_op_done_a <= '0';
inst_ren_a <= '0';
inst_wen_a <= '0';
inst_atomic_lock_a <= '0';
case (mem_stage) is
when IDLE =>
inst_op_done_a <= '1';
-- Lock Release
if (inst_delete_lock_a = '1' and inst_latch_data.release_lock = '1') then
inst_delete_lock_a_next <= '0';
end if;
if (inst_op_start_a = '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,
gen_cnt => gen_cnt,
deadline => deadline,
writer_bitmap => writer_bitmap,
update_flags => update_inst_flags_a,
release_lock => release_inst_lock
);
-- Reset Memory Fullness Indicator
if (inst_mem_full = '1' and inst_empty_head /= inst_empty_tail) then
inst_mem_full_next <= '0';
end if;
case(inst_opcode_a) is
when SEARCH_INSTANCE =>
-- Reset Data
inst_data_next <= ZERO_INSTANCE_DATA;
-- NOTE: This process gets the lock implicitly when the SEARCH_INSTANCE, or GET_FIRST_INSTANCE operation is called, and has to be released explicitly
-- by the main process. There are two ways to release the lock: 1) The man process explicitly calles the RELEASE_LOCK operation 2) The main
-- process pulls the release_inst_lock signal high during the issuing of the last memory operation (Lock will be release after the opration finishes)
-- Process B has lock
if (inst_delete_lock_b = '1') then
-- Wait until process B releases lock
inst_stage_a_next <= WAIT_FOR_LOCK_1;
else
-- NOTE: The case that both processes aqcuire the lock at the same time is handled by the B process in the next clock cycle.
-- Get Lock
inst_delete_lock_a_next <= '1';
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_a <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_a_next <= inst_occupied_head;
inst_addr_a_next <= inst_occupied_head;
inst_stage_a_next <= SEARCH_INSTANCE;
inst_cnt_a_next <= 0;
end if;
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_mem_full = '0') report "Instance Insertion while memory Full" severity FAILURE;
inst_prev_addr_base_a_next <= inst_occupied_tail;
inst_addr_base_a_next <= inst_occupied_tail;
inst_addr_a_next <= inst_occupied_tail;
inst_stage_a_next <= INSERT_PREPARATION;
inst_cnt_a_next <= 0;
when UPDATE_INSTANCE =>
inst_addr_base_a_next <= inst_addr_base_a;
if ((update_inst_flags_a and STATUS_FLAG) = STATUS_FLAG) then
inst_stage_a_next <= UPDATE_INSTANCE;
inst_addr_a_next <= inst_addr_base_a + IMF_STATUS_INFO_OFFSET;
inst_cnt_a_next <= 0;
elsif (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and (update_inst_flags_a and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
inst_stage_a_next <= UPDATE_INSTANCE;
inst_addr_a_next <= inst_addr_base_a + IMF_SAMPLE_CNT_OFFSET;
inst_cnt_a_next <= 3;
elsif (GENERATION_COUNTERS and (update_inst_flags_a and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_stage_a_next <= UPDATE_INSTANCE;
inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_a_next <= 6;
elsif (GENERATION_COUNTERS and (update_inst_flags_a and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_stage_a_next <= UPDATE_INSTANCE;
inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_a_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (update_inst_flags_a and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_stage_a_next <= UPDATE_INSTANCE;
inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_a_next <= 8;
elsif ((update_inst_flags_a and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_cnt_a_next <= 0;
end if;
when GET_FIRST_INSTANCE =>
-- NOTE: This process gets the lock implicitly when the SEARCH_INSTANCE, or GET_FIRST_INSTANCE operation is called, and has to be released explicitly
-- by the main process via the RELEASE_LOCK operation.
-- Process B has lock
if (inst_delete_lock_b = '1') then
-- Wait until process B releases lock
inst_stage_a_next <= WAIT_FOR_LOCK_2;
else
-- NOTE: The case that both processes aqcuire the lock at the same time is handled by the B process in the next clock cycle.
-- Get Lock
inst_delete_lock_a_next <= '1';
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_a_next <= inst_occupied_head;
inst_addr_a_next <= inst_occupied_head + 5;
inst_stage_a_next <= GET_INSTANCE_DATA;
inst_cnt_a_next <= 0;
end if;
end if;
when GET_NEXT_INSTANCE =>
inst_prev_addr_base_a_next <= inst_addr_base_a;
inst_addr_base_a_next <= inst_next_addr_base_a;
inst_addr_a_next <= inst_next_addr_base_a;
inst_stage_a_next <= GET_NEXT_INSTANCE;
inst_cnt_a_next <= 0;
when RELEASE_LOCK =>
inst_delete_lock_a_next <= '0';
when others =>
null;
end case;
end if;
when WAIT_FOR_LOCK_1 =>
-- Wait until B process releases lock
if (inst_delete_lock_b = '0') then
-- Get Lock
inst_delete_lock_a_next <= '1';
if (inst_occupied_head /= INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= inst_occupied_head;
inst_addr_a_next <= inst_occupied_head;
inst_stage_a_next <= SEARCH_INSTANCE;
inst_cnt_a_next <= 0;
else
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
end if;
end if;
when WAIT_FOR_LOCK_2 =>
-- Wait until B process releases lock
if (inst_delete_lock_b = '0') then
-- Get Lock
inst_delete_lock_a_next <= '1';
-- No Instances avialable
if (inst_occupied_head = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
else
inst_prev_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS;
inst_addr_base_a_next <= inst_occupied_head;
inst_addr_a_next <= inst_occupied_head + 5;
inst_stage_a_next <= GET_INSTANCE_DATA;
inst_cnt_a_next <= 0;
end if;
end if;
when SEARCH_INSTANCE =>
inst_ren_a <= '1';
inst_cnt_a_next <= inst_cnt_a + 1;
inst_addr_a_next <= inst_addr_a + 1;
case (inst_cnt_a) is
-- Preload
when 0 =>
null;
-- Next Instance
when 1 =>
inst_next_addr_base_a_next <= inst_read_data_a;
-- Key Hash 1/4
when 2 =>
-- No Match
if (inst_read_data_a /= inst_latch_data.key_hash(0)) then
-- Reached List Tail, No Match
if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_a_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_a_next <= inst_addr_base_a;
inst_addr_base_a_next <= inst_next_addr_base_a;
inst_addr_a_next <= inst_next_addr_base_a;
inst_cnt_a_next <= 0;
end if;
end if;
-- Key Hash 2/4
when 3 =>
-- No Match
if (inst_read_data_a /= inst_latch_data.key_hash(1)) then
-- Reached List Tail, No Match
if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_a_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_a_next <= inst_addr_base_a;
inst_addr_base_a_next <= inst_next_addr_base_a;
inst_addr_a_next <= inst_next_addr_base_a;
inst_cnt_a_next <= 0;
end if;
end if;
-- Key Hash 3/4
when 4 =>
-- No Match
if (inst_read_data_a /= inst_latch_data.key_hash(2)) then
-- Reached List Tail, No Match
if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_a_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_a_next <= inst_addr_base_a;
inst_addr_base_a_next <= inst_next_addr_base_a;
inst_addr_a_next <= inst_next_addr_base_a;
inst_cnt_a_next <= 0;
end if;
end if;
-- Key Hash 4/4
when 5 =>
-- No Match
if (inst_read_data_a /= inst_latch_data.key_hash(3)) then
-- Reached List Tail, No Match
if (inst_addr_base_a = INSTANCE_MEMORY_MAX_ADDRESS) then
inst_addr_base_a_next <= INSTANCE_MEMORY_MAX_ADDRESS; --No match
-- DONE
inst_stage_a_next <= IDLE;
else
-- Continue Search
inst_prev_addr_base_a_next <= inst_addr_base_a;
inst_addr_base_a_next <= inst_next_addr_base_a;
inst_addr_a_next <= inst_next_addr_base_a;
inst_cnt_a_next <= 0;
end if;
-- Match
else
-- Fetch Instance Data
inst_stage_a_next <= GET_INSTANCE_DATA;
inst_cnt_a_next <= 1; -- No preload needed
end if;
when others =>
null;
end case;
when GET_NEXT_INSTANCE =>
case (inst_cnt_a) is
-- Preload
when 0 =>
inst_wen_a <= '1';
-- Next Instance
when 1 =>
inst_addr_base_a_next <= inst_read_data_a;
inst_addr_a_next <= inst_read_data_a + 5;
inst_cnt_a_next <= 0;
inst_stage_a_next <= GET_INSTANCE_DATA;
end case;
when GET_INSTANCE_DATA =>
inst_ren_a <= '1';
inst_cnt_a_next <= inst_cnt_a + 1;
inst_addr_a_next <= inst_addr_a + 1;
case (inst_cnt_a) is
-- Memory Preload
when 0 =>
null;
-- Status Info
when 1 =>
inst_data_next.status_info <= inst_read_data_a;
-- Sample Count
when 2 =>
inst_data_next.sample_cnt <= inst_read_data_a;
-- Disposed Generation Count
when 3 =>
inst_data_next.disposed_gen_cnt <= inst_read_data_a;
-- No Writers Generation Count
when 4 =>
inst_data_next.no_writers_gen_cnt <= inst_read_data_a;
-- Ignore Deadline 1/2
when 5 =>
inst_data_next.ignore_deadline(0) <= unsigned(inst_read_data_a);
-- Ignore Deadline 2/2
when 5 =>
inst_data_next.ignore_deadline(1) <= unsigned(inst_read_data_a);
-- DONE
inst_stage_a_next <= GET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
when others =>
null;
end case;
when GET_WRITER_BITMAP =>
inst_cnt_a_next <= inst_cnt_a + 1;
inst_latch_data_next.writer_bitmap(inst_cnt_a) <= inst_read_data_a;
if (inst_cnt_a = writer_bitmap'length-1) then
-- DONE
inst_stage_a_next <= IDLE;
end if;
when INSERT_PREPARATION =>
inst_cnt_a_next <= inst_cnt_a + 1;
case (inst_cnt_a) is
-- Next Payload Slot (Old Occupied Tail)
when 0 =>
-- Point Old Occupied Tail to New Occupied Tail
inst_write_data_a <= inst_empty_head;
inst_wen_a <= '1';
inst_occupied_tail_next <= inst_empty_head;
inst_addr_a_next <= inst_empty_head;
inst_addr_base_a_next <= inst_empty_head;
-- Preload
when 1 =>
inst_ren_a <= '1';
-- Next Payload Slot (New Occupied Tail)
when 2 =>
-- Instance Memory Full
if (inst_read_data_a = INSTANCE_MEMORY_MAX_ADDRESS) then
assert (inst_empty_head = inst_empty_tail) report "Instance empty list empty, but HEAD /= TAIL" severity FAILURE;
inst_mem_full_next <= '1';
inst_next_addr_base_a_next <= inst_empty_head; -- Keep same tail
else
-- Latch new Empty Head
inst_next_addr_base_a_next <= inst_read_data_a;
end if;
inst_stage_a_next <= INSERT_INSTANCE;
inst_cnt_a_next <= 0;
when others =>
null;
end case;
when INSERT_INSTANCE =>
inst_wen_a <= '1';
inst_addr_a_next <= inst_addr_a + 1;
inst_cnt_a_next <= inst_cnt_a + 1;
case (inst_cnt_a) is
-- Next Instance Address
when 0 =>
-- Mark as Tail
inst_write_data_a <= INSTANCE_MEMORY_MAX_ADDRESS;
-- Set New Empty List Head
inst_empty_head_next <= inst_next_addr_base_a;
-- Key Hash 1/4
when 1 =>
inst_write_data_a <= inst_latch_data.key_hash(0);
-- Key Hash 2/4
when 2 =>
inst_write_data_a <= inst_latch_data.key_hash(1);
-- Key Hash 3/4
when 3 =>
inst_write_data_a <= inst_latch_data.key_hash(2);
-- Key Hash 4/4
when 4 =>
inst_write_data_a <= inst_latch_data.key_hash(3);
-- Status Info
when 5 =>
inst_write_data_a <= inst_latch_data.status_info;
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then
null;
elsif (GENERATION_COUNTERS) then
inst_cnt_a <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt_a <= 9;
else
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
end if;
-- Sample Count
when 6 =>
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then
inst_write_data_a <= std_logic_vector(to_unsigned(1, WORD_WIDTH));
if (GENERATION_COUNTERS) then
inst_cnt_a <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt_a <= 9;
else
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
end if;
end if;
-- Disposed Generation Count
when 7 =>
if (GENERATION_COUNTERS) then
inst_write_data_a <= (others => '0');
end if;
-- No Writers Generation Count
when 8 =>
if (GENERATION_COUNTERS) then
inst_write_data_a <= (others => '0');
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_cnt_a <= 9;
else
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
end if;
end if;
-- Ignore Deadline 1/2
when 9 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_write_data_a <= inst_latch_data.deadline(0);
end if;
-- Ignore Deadline 1/2
when 10 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_write_data_a <= inst_latch_data.deadline(1);
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
end if;
when others =>
null;
end case;
when SET_WRITER_BITMAP =>
inst_wen_a <= '1';
inst_addr_a_next <= inst_addr_a + 1;
inst_cnt_a_next <= inst_cnt_a + 1;
inst_write_data_a <= inst_latch_data.writer_bitmap(inst_cnt_a);
-- Exit Condition
if (inst_cnt_a = inst_latch_data.writer_bitmap'length-1) then
-- DONE
inst_stage_a_next <= IDLE;
end if;
when UPDATE_INSTANCE =>
inst_cnt_a_next <= inst_cnt_a + 1;
case (inst_cnt_a) is
-- *Status Info Begin*
-- Preload
when 0 =>
inst_atomic_lock_a <= '1';
inst_ren_a <= '1';
-- Read
when 1 =>
-- Latch Contents
inst_atomic_lock_a <= '1';
inst_long_latch_a_next <= inst_read_data_a;
-- Write
when 2 =>
inst_atomic_lock_a <= '1';
inst_wen_a <= '1';
inst_write_data_a <= inst_long_latch_a;
case (inst_latch_data.instance_state) is
when ALIVE =>
inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
inst_write_data_a(LIVELINESS_FLAG) <= '1';
when NOT_ALIVE_DISPOSED =>
inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '1';
inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '0';
inst_write_data_a(LIVELINESS_FLAG) <= '1';
when NOT_ALIVE_NO_WRITERS =>
inst_write_data_a(NOT_ALIVE_DISPOSED_FLAG) <= '0';
inst_write_data_a(NOT_ALIVE_NO_WRITERS_FLAG) <= '1';
inst_write_data_a(LIVELINESS_FLAG) <= '1';
end case;
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED and (inst_latch_data.update_flags and SAMPLE_CNT_FLAG) = SAMPLE_CNT_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_SAMPLE_CNT_OFFSET;
inst_cnt_a_next <= 3;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_a_next <= 6;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_a_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_a_next <= 8;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
else
-- DONE
inst_stage_a_next <= IDLE;
end if;
-- *Status Info End*
-- *Sample Count Begin*
-- Preload
when 3 =>
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then
inst_ren_a <= '1';
inst_atomic_lock_a <= '1';
end if;
-- Read
when 4 =>
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then
-- Latch Contents
inst_atomic_lock_a <= '1';
inst_long_latch_a_next <= inst_read_data_a;
end if;
when 5 =>
if (MAX_SAMPLES_PER_INSTANCE /= LENGTH_UNLIMITED) then
-- Increment Sample Count
inst_atomic_lock_a <= '1';
inst_wen_a <= '1';
inst_write_data_a <= std_logic_vector(unsigned(inst_long_latch_a) + 1);
if (GENERATION_COUNTERS and (inst_latch_data.update_flags and DISPOSED_CNT_FLAG) = DISPOSED_CNT_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_DISPOSED_GEN_CNT_OFFSET;
inst_cnt_a_next <= 6;
elsif (GENERATION_COUNTERS and (inst_latch_data.update_flags and NO_WRITERS_CNT_FLAG) = NO_WRITERS_CNT_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_a_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_a_next <= 8;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
else
-- DONE
inst_stage_a_next <= IDLE;
end if;
end if;
-- *Sample Count End*
-- Disposed Generation Count
when 6 =>
if (GENERATION_COUNTERS) then
inst_wen_a <= '1';
inst_write_data_a <= 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_a_next <= inst_addr_base_a + IMF_NO_WRITERS_GEN_CNT_OFFSET;
inst_cnt_a_next <= 7;
elsif (TIME_BASED_FILTER_QOS /= DURATION_ZERO and (inst_latch_data.update_flags and IGNORE_DEADLINE_FLAG) = IGNORE_DEADLINE_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_a_next <= 8;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
else
-- DONE
inst_stage_a_next <= IDLE;
end if;
end if;
-- No Writers Generation Count
when 7 =>
if (GENERATION_COUNTERS) then
inst_wen_a <= '1';
inst_write_data_a <= 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_a_next <= inst_addr_base_a + IMF_IGNORE_DEADLINE_OFFSET;
inst_cnt_a_next <= 8;
elsif ((inst_latch_data.update_flags and WRITER_BITMAP_FLAG) = WRITER_BITMAP_FLAG) then
inst_addr_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
else
-- DONE
inst_stage_a_next <= IDLE;
end if;
end if;
-- Ignore Deadline 1/2
when 8 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_wen_a <= '1';
inst_write_data_a <= std_logic_vector(inst_latch_data.ignore_deadline(0));
end if;
-- Ignore Deadline 2/2
when 9 =>
if (TIME_BASED_FILTER_QOS /= DURATION_ZERO) then
inst_wen_a <= '1';
inst_write_data_a <= 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_a_next <= inst_addr_base_a + IMF_WRITER_BITMAP_OFFSET;
inst_stage_a_next <= SET_WRITER_BITMAP;
inst_cnt_a_next <= 0;
else
-- DONE
inst_stage_a_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when others =>
null;
end case;
when others =>
null;
end case;
end process;
end architecture;