rtps-fpga/src/rtps_reader.vhd
Greek 260acba5b6 Add test 3 of RTPS Reader
Test Liveliness Handling of RTPS Reader.
Test 2 expanded with extra case for Little Endian Handling.
Compiling and Passing
2021-02-22 12:16:47 +01:00

2923 lines
160 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
-- TODO: Adding LIFESPAN Duration in the stored Endpoint Metatraffic Data would allow us to not expect in-line QoS (Which could be a significant overhead)
entity rtps_reader is
generic (
ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0);
RELIABILTY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);
HEARTBEAT_RESPONSE_DELAY : DURATION_TYPE;
HEARTBEAT_SUPPRESSION_DELAY : DURATION_TYPE;
LEASE_DURATION : DURATION_TYPE;
WITH_KEY : boolean;
MAX_REMOTE_ENDPOINTS : natural := 50
);
port (
-- SYSTEM
clk : in std_logic;
reset : in std_logic;
time : in TIME_TYPE;
-- FROM RTPS_HANDLER (USER TRAFFIC)
empty_user : in std_logic;
rd_user : out std_logic;
data_in_user : in std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_in_user : in std_logic;
-- FROM RTPS_BUILTIN_ENDPOINT (META TRAFFIC)
empty_meta : in std_logic;
rd_meta : out std_logic;
data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_in_meta : in std_logic;
-- RTPS OUTPUT
wr_rtps : out std_logic;
full_rtps : in std_logic;
last_word_out_rtps : out std_logic;
data_out_rtps : out std_logic_vector(WORD_WIDTH-1 downto 0);
-- TO HISTORY CACHE
start_hc : out std_logic;
opcode_hc : out HISTORY_CACHE_OPCODE_TYPE;
ack_hc : in std_logic;
done_hc : in std_logic;
ret_hc : in HISTORY_CACHE_RESPONSE_TYPE;
data_out_hc : out std_logic_vector(WORD_WIDTH-1 downto 0);
valid_out_hc : out std_logic;
ready_out_hc : in std_logic;
last_word_out_hc : out std_logic
);
end entity;
architecture arch of rtps_reader is
--*****CONSTANT DECLARATION*****
-- *ENDPOINT MEMORY*
-- 4-Byte Word Size of a Participant Entry in Memory
function gen_frame_size(qos : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0)) return natural is
variable ret : natural := 0;
begin
ret := 12 when (qos = RELIABLE_RELIABILITY_QOS) else 8;
return ret;
end function;
constant ENDPOINT_FRAME_SIZE : natural := gen_frame_size(RELIABILTY_QOS);
-- Endpoint Memory Size in 4-Byte Words
constant ENDPOINT_MEMORY_SIZE : natural := MAX_REMOTE_ENDPOINTS * ENDPOINT_FRAME_SIZE;
-- Endpoint Memory Address Width
constant ENDPOINT_MEMORY_ADDR_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE);
-- Highest Endpoint Memory Address
constant ENDPOINT_MEMORY_MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH);
-- Highest Endpoint Frame Address
constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := ENDPOINT_MEMORY_MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1;
-- Address pointing to the beginning of the first Endpoint Data Frame
constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- *ENDPOINT MEMORY FORMAT FORMAT FLAGS*
-- Flags mapping to the respective Endpoint Memory Frame Fields
constant EMF_FLAG_WIDTH : natural := 7;
constant EMF_ENTITYID_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (0 => '1', others => '0');
constant EMF_GUIDPREFIX_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (1 => '1', others => '0');
constant EMF_IPV4_ADDR_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (2 => '1', others => '0');
constant EMF_UDP_PORT_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (3 => '1', others => '0');
constant EMF_NEXT_SEQ_NR_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (4 => '1', others => '0');
constant EMF_LEASE_DEADLINE_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (5 => '1', others => '0');
constant EMF_RES_TIME_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (6 => '1', others => '0');
-- *ENDPOINT MEMORY FRAME FORMAT*
-- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame
constant EMF_ENTITYID_OFFSET : natural := 0;
constant EMF_GUIDPREFIX_OFFSET : natural := 1;
constant EMF_IPV4_ADDR_OFFSET : natural := 4;
constant EMF_UDP_PORT_OFFSET : natural := 5;
function gen_emf_udp_port_offset(qos : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0)) return natural is
variable ret : natural := 0;
begin
ret := 6 when (qos = RELIABLE_RELIABILITY_QOS) else EMF_GUIDPREFIX_OFFSET + 3;
return ret;
end function;
constant EMF_NEXT_SEQ_NR_OFFSET : natural := gen_emf_udp_port_offset(RELIABILTY_QOS);
constant EMF_LEASE_DEADLINE_OFFSET : natural := EMF_NEXT_SEQ_NR_OFFSET + 2;
constant EMF_RES_TIME_OFFSET : natural := EMF_LEASE_DEADLINE_OFFSET + 2;
--*****TYPE DECLARATION*****
-- FSM states. Explained below in detail
type STAGE_TYPE is (IDLE, LATCH_GUIDPREFIX, LATCH_ENTITYID, INITIATE_ENDPOINT_SEARCH, LATCH_ENDPOINT_DATA, METATRAFFIC_OPERATION, LATCH_SRC_ADDR,
LATCH_EXTRA_DATA, LATCH_HEARTBEAT, PROCESS_HEARTBEAT, LATCH_GAP, PROCESS_GAP, FIND_NEXT_VALID_IN_BITMAP, PROCESS_INLINE_QOS, LATCH_LIFESPAN,
LATCH_KEY_HASH, LATCH_STATUS_INFO, INITIATE_ADD_CACHE_CHANGE_REQUEST, ADD_CACHE_CHANGE, PUSH_PAYLOAD, FINALIZE_ADD_CACHE_CHANGE_REQUEST,
ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET, SKIP_META_OPERATION);
-- Memory FSM states. Explained below in detail
type MEM_STAGE_TYPE is (IDLE, SEARCH_ENDPOINT, GET_ENDPOINT_DATA, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, FIND_EMPTY_SLOT,
RESET_MAX_POINTER, GET_NEXT_ENDPOINT, RESET_MEMORY);
-- *Memory FSM Opcodes*
-- OPCODE DESCRIPTION
-- SEARCH_ENDPOINT Find Endpoint with specified GUID in memory
-- INSERT_ENDPOINT Insert Endpoint to first available empty_user slot in memory
-- UPDATE_ENDPOINT Update Endpoint pointed by mem_addr_base. (mem_field_flags specifies which Fields to update)
-- REMOVE_ENDPOINT Remove Endpoint pointed by mem_addr_base
-- GET_FIRST_ENDPOINT Get Endpoint Data of first Endpoint stored in Memory. (mem_field_flags specifies which Fields to get)
-- GET_NEXT_ENDPOINT Get Endpoint Data of next Endpoint (from the Endpoint pointed by mem_addr_base) stored in Memory. (mem_field_flags specifies which Fields to get)
-- GET_ENDPOINT Get Endpoint Data from Endpoint currently pointed by mem_addr_base. (mem_field_flags specifies which Fields to get)
type MEM_OPCODE_TYPE is (NOP, SEARCH_ENDPOINT, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, GET_FIRST_ENDPOINT, GET_NEXT_ENDPOINT,
GET_ENDPOINT);
-- Record of Endpoint Data
type ENDPOINT_DATA_TYPE is record
guid : GUID_TYPE;
addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
next_seq_nr : SEQUENCENUMBER_TYPE;
lease_deadline : TIME_TYPE;
res_time : TIME_TYPE;
end record;
-- Zero initialized Endpoint Data
constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := (
guid => GUID_UNKNOWN,
addr => IPv4_ADDRESS_INVALID,
portn => UDP_PORT_INVALID,
next_seq_nr => SEQUENCENUMBER_UNKNOWN,
lease_deadline => TIME_INVALID,
res_time => TIME_INVALID
);
-- Endpoint Data Latch used as temporal cache by Memory Process
type ENDPOINT_LATCH_DATA_TYPE is record
guid : GUID_TYPE;
addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
lease_deadline : TIME_TYPE;
res_time : TIME_TYPE;
next_seq_nr : SEQUENCENUMBER_TYPE;
field_flag : std_logic_vector(0 to EMF_FLAG_WIDTH-1);
end record;
-- Zero initialized Endpoint Data Latch
constant ZERO_ENDPOINT_LATCH_DATA : ENDPOINT_LATCH_DATA_TYPE := (
guid => GUID_UNKNOWN,
addr => IPv4_ADDRESS_INVALID,
portn => UDP_PORT_INVALID,
lease_deadline => TIME_INVALID,
res_time => TIME_INVALID,
next_seq_nr => SEQUENCENUMBER_UNKNOWN,
field_flag => (others => '0')
);
--*****SIGNAL DECLARATION*****
-- *MAIN PROCESS*
-- FSM state
signal stage, stage_next : STAGE_TYPE := IDLE;
-- FSM state latch. Used to transition dynamically to different states from the same state.
signal return_stage, return_stage_next : STAGE_TYPE := IDLE;
-- Intermediate input read signal. (Read from output port not allowed)
signal rd_sig : std_logic := '0';
-- Signal used to reset the word counter
signal reset_read_cnt : std_logic;
-- Word (4-Byte) counter (Counts words read from input fifo)
signal read_cnt : unsigned(SUBMESSAGE_LENGTH_WIDTH-3 downto 0) := (others => '0');
-- Word aligned End of Parameter
signal parameter_end, parameter_end_next : unsigned(PARAMETER_LENGTH_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Counter
signal cnt, cnt_next : natural range 0 to 9 := 0;
-- Packet Opcode Latch (RTPS Message ID)
signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0');
-- Metatraffic Opcode Latch
signal meta_opcode, meta_opcode_next : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
-- Signifies if the received packet is a metatraffic operation
signal is_meta, is_meta_next : std_logic := '0';
-- Source GUID Latch
signal guid, guid_next : GUID_TYPE := (others => (others => '0'));
-- Source IPv4 Address Latch
signal addr, addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0');
-- UDP Port Latch
signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0');
-- RTPS Header Flags Latch
signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0');
-- Source Timestamp Latch
signal ts, ts_next : TIME_TYPE := TIME_INVALID;
-- Key Hash Latch
signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0'));
-- Signifies if a Key Hash was received
signal key_hash_rcvd, key_hash_rcvd_next : std_logic := '0';
-- Status Info Latch
signal status_info, status_info_next : std_logic_vector(STATUS_INFO_WIDTH-1 downto 0) := (others => '0');
-- Lifespan Latch
signal lifespan, lifespan_next : TIME_TYPE := TIME_INVALID;
-- RTPS Sequence Number Latch
signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Signifies the next expected Sequence Number
signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Generic Sequence Number Latch
signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Generic Sequence Number Latch
signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Generic Sequence Number Latch
signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN;
-- Toggle latching the "last_word_in_user" signal until reset
signal last_word_in_latch, last_word_in_latch_next : std_logic := '0';
-- Time of next Stale Endpoint Check
signal check_time, check_time_next : TIME_TYPE := TIME_INVALID;
-- Signifies if a Stale Endpoint Check is in progress
signal stale_check, stale_check_next : std_logic := '0';
-- Signal containing the RTPS ACKNACK Count Field
signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0');
-- Data in represented in Big Endian
signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
-- Denotes the number of valid Bitmap longs (4-Byte words)
signal bitmap_cnt, bitmap_cnt_next : unsigned(log2c(MAX_BITMAP_WIDTH/CDR_LONG_WIDTH)-1 downto 0) := (others => '0');
-- NumberSet Bitmap Latch
signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE := (others => (others => '0'));
-- Counter used to read out Bitmaps
signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length := 0;
-- Signal used to iterate through Bitmaps
signal bitmap_pos, bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1 := 0;
-- Signals the start of a Memory Operation
signal mem_op_start : std_logic := '0';
-- Opcode of the Memory Operation (Valid only when mem_op_start is high)
signal mem_opcode : MEM_OPCODE_TYPE := NOP;
-- Signals the end of a Memory Operation
signal mem_op_done : std_logic := '0';
-- Signal containing the relevant Endpoint Memory Format Fields of the Memory Operation
signal mem_field_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0');
-- Signal used to pass Lease Deadlines from main to memory process
signal lease_deadline : TIME_TYPE := TIME_INVALID;
-- Signal used to pass Response Deadlines from main to memory process
signal res_time : TIME_TYPE := TIME_INVALID;
-- Test signal used for testbench synchronisation
signal idle_sig : std_logic := '0';
-- *MEMORY PROCESS*
-- Memory FSM state
signal mem_stage, mem_stage_next : MEM_STAGE_TYPE := IDLE;
-- Pointer to current relevant Endpoint Address
signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Help signal used to reset the MAX Endpoint Memory Pointer
signal last_addr, last_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Memory Address Latch
signal mem_addr_latch, mem_addr_latch_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- Highest Endpoint Memory Address (Points to first Address of last occupied Endpoint Frame)
signal max_endpoint_addr, max_endpoint_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
-- General Purpose Couter
signal mem_cnt, mem_cnt_next : natural range 0 to 23 := 0;
-- Latch for Endpoint Data from Memory
signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE := ZERO_ENDPOINT_DATA;
-- Latch for Endpoint Data from main process
signal mem_endpoint_latch_data, mem_endpoint_latch_data_next : ENDPOINT_LATCH_DATA_TYPE := ZERO_ENDPOINT_LATCH_DATA;
-- Position (In Endpoint Memory Frame Granularity) of current relevant Endpoint
signal mem_pos, mem_pos_next : natural range 0 to MAX_REMOTE_ENDPOINTS-1 := 0;
-- Signifies an abort of the currently initiated read transaction
signal abort_read : std_logic := '0';
-- *MEMORY CONTROL CONNECTION SIGNALS*
signal mem_addr : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0');
signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0');
signal mem_ready_in, mem_valid_in : std_logic := '0';
signal mem_ready_out, mem_valid_out : std_logic := '0';
signal mem_read : std_logic := '0';
--*****ALIAS DECLARATION*****
-- ENDPOINT FRAME HEADER
alias header_opcode : std_logic_vector(7 downto 0) is data_in_user(31 downto 24);
alias header_flags : std_logic_vector(7 downto 0) is data_in_user(23 downto 16);
alias header_udp_port : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
-- RTPS PARAMETER LIST HEADER
alias parameter_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16);
alias parameter_length : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
alias must_understand : std_logic is parameter_id(14);
-- RTPS DATA PAYLOAD HEADER
alias representation_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16);
alias representation_options : std_logic_vector(15 downto 0) is data_in_user(15 downto 0);
-- RTPS SUBMESSAGE FLAGS
alias endian_flag : std_logic is flags(0);
alias qos_flag : std_logic is flags(1);
alias data_flag : std_logic is flags(2);
alias key_flag : std_logic is flags(3);
alias final_flag : std_logic is flags(1);
alias payload_flag : std_logic is flags(4);
alias liveliness_flag : std_logic is flags(2);
-- HEARTBEAT
alias first_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_1;
alias first_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
alias last_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_2;
alias last_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
-- GAP
alias gap_start : SEQUENCENUMBER_TYPE is sn_latch_1;
alias gap_start_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
alias gap_list_base : SEQUENCENUMBER_TYPE is sn_latch_2;
alias gap_list_base_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
alias gap_list_end : SEQUENCENUMBER_TYPE is sn_latch_3;
alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next;
--*****FUNCTION DECLARATION*****
-- Helper function to convert BITMAP_TYPE to std_logic_vector
function to_slv_bitmap (input : BITMAP_TYPE) return std_logic_vector is
variable ret : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0');
begin
for i in 0 to BITMAP_TYPE'length-1 loop
ret(i*WORD_WIDTH to ((i+1)*WORD_WIDTH)-1) := input(i);
end loop;
return ret;
end function;
begin
--*****COMPONENT INSTANTIATION*****
mem_ctrl_inst : entity work.mem_ctrl(arch)
generic map (
ADDR_WIDTH => ENDPOINT_MEMORY_ADDR_WIDTH,
DATA_WIDTH => WORD_WIDTH,
MEMORY_DEPTH => ENDPOINT_MEMORY_SIZE,
MAX_BURST_LENGTH => ENDPOINT_FRAME_SIZE
)
port map (
clk => clk,
reset => reset or abort_read,
addr => std_logic_vector(mem_addr),
read => mem_read,
ready_in => mem_ready_in,
valid_in => mem_valid_in,
data_in => mem_write_data,
ready_out => mem_ready_out,
valid_out => mem_valid_out,
data_out => mem_read_data
);
-- Big Endian Representation
data_in_swapped <= endian_swap(endian_flag, data_in_user);
rd_user <= rd_sig;
-- *Main State Machine*
-- STATE DESCRIPTION
-- IDLE Idle State. Initiates Stale Endpoint Checks, Metatraffic Packet Processing, and User Packet Processing, in that priority order.
-- LATCH_GUIDPREFIX Store source GUID Prefix
-- LATCH_ENTITYID Store source Entity ID
-- INITIATE_ENDPOINT_SEARCH Initiate Endpoint Search Memory Operation. This state is used to start the Search operation as soon as the required data is available
-- LATCH_ENDPOINT_DATA Store Remote Endpoint Data
-- METATRAFFIC_OPERATION State handling the Metatraffic Operations
-- LATCH_SRC_ADDR Store source IPv4 Address
-- LATCH_EXTRA_DATA Store source Timestamp, and source Sequence Number
-- LATCH_HEARTBEAT Store RTPS HEARTBEAT Sequence Numbers
-- PROCESS_HEARTBEAT Parse RTPS HEARTBEAT Message. Update stored Sequence Number if necessary. Set HEARTBEAT response time accordingly.
-- LATCH_GAP Store RTPS GAP Sequence Numbers
-- PROCESS_GAP Parse RTPS GAP Submsessage. Initiates search for next valid Sequence Number if currently expected Sequence Number is in GAP
-- FIND_NEXT_VALID_IN_BITMAP Iterate through Bitmap and find the next valid Sequence Number.
-- PROCESS_INLINE_QOS Parse in-line Parameter List QoS
-- LATCH_LIFESPAN Store LIFESPAN_QOS
-- LATCH_KEY_HASH Store KEY_HASH
-- LATCH_STATUS_INFO Store STATUS_INFO
-- INITIATE_ADD_CACHE_CHANGE_REQUEST Initiate an ADD_CACHE_CHANGE Operation
-- ADD_CACHE_CHANGE Send CACHE_CHANGE Data
-- PUSH_PAYLOAD Send CACHE_CHANGE Data (Direct Input Passthrough)
-- FINALIZE_ADD_CACHE_CHANGE_REQUEST Wait for ADD_CACHE_CHANGE Operation Results. Update Endpoint Data if successfull.
-- ENDPOINT_STALE_CHECK Check remote Endpoint Entries for Liveliness Lease Expiration, and Response Timeouts.
-- SEND_HEADER Send Output Data Header and RTPS Message Header
-- SEND_ACKNACK Send ACKNACK Submessage
-- SKIP_PARAMETER Skip rest of Parameter
-- SKIP_PACKET Skip rest of Packet
-- SKIP_META_OPERATION Skip Metatraffic Operation
parse_prc : process(all)
variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0'));
-- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally)
variable tmp_bitmap : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0');
variable rd_guard : std_logic := '0';
variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0');
begin
-- DEFAULT Registered
stage_next <= stage;
meta_opcode_next <= meta_opcode;
cnt_next <= cnt;
cnt2_next <= cnt2;
guid_next <= guid;
addr_next <= addr;
portn_next <= portn;
is_meta_next <= is_meta;
opcode_next <= opcode;
flags_next <= flags;
seq_nr_next <= seq_nr;
ts_next <= ts;
sn_latch_1_next <= sn_latch_1;
sn_latch_2_next <= sn_latch_2;
sn_latch_3_next <= sn_latch_3;
bitmap_latch <= bitmap_latch_next;
bitmap_cnt <= bitmap_cnt_next;
bitmap_pos_next <= bitmap_pos;
key_hash_rcvd_next <= key_hash_rcvd;
key_hash_next <= key_hash;
status_info_next <= status_info;
last_word_in_latch_next <= last_word_in_latch;
stale_check_next <= stale_check;
count_next <= count;
return_stage_next <= return_stage;
check_time_next <= check_time;
lifespan_next <= lifespan;
parameter_end_next <= parameter_end;
next_seq_nr_next <= next_seq_nr;
-- DEFAULT Unregistered
mem_opcode <= NOP;
opcode_hc <= NOP;
lease_deadline <= TIME_INVALID;
res_time <= TIME_INVALID;
reset_read_cnt <= '0';
rd_meta <= '0';
mem_op_start <= '0';
start_hc <= '0';
valid_out_hc <= '0';
last_word_out_hc <= '0';
wr_rtps <= '0';
last_word_out_rtps <= '0';
idle_sig <= '0';
rd_guard := '0';
mem_field_flags <= (others => '0');
data_out_hc <= (others => '0');
data_out_rtps <= (others => '0');
-- Last Word Latch Setter
if (last_word_in_user = '1') then
last_word_in_latch_next <= '1';
end if;
case (stage) is
when IDLE =>
idle_sig <= '1';
-- RESET
lifespan_next <= TIME_INVALID;
addr_next <= (others => '0');
portn_next <= (others => '0');
status_info_next <= (others => '0');
key_hash_rcvd_next <= '0';
is_meta_next <= '0';
-- Stale Check Timeout
if (time >= check_time) then
-- Memory Operation Guard
if (mem_op_done = '1') then
stale_check_next <= '1';
stage_next <= ENDPOINT_STALE_CHECK;
cnt_next <= 1;
mem_op_start <= '1';
mem_opcode <= GET_FIRST_ENDPOINT;
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG;
-- Reset Timeout
check_time_next <= TIME_INFINITE;
end if;
-- Input FIFO Guard
elsif (empty_meta = '0') then
rd_meta <= '1';
-- Mark as METATRAFFIC
is_meta_next <= '1';
-- Latch Endpoint Metatraffic Opcode
meta_opcode_next <= data_in_meta;
case (data_in_meta) is
when OPCODE_ENDPOINT_MATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_ENDPOINT_UNMATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_PARTICIPANT_UNMATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
else
stage_next <= SKIP_META_OPERATION;
end if;
when others =>
stage_next <= SKIP_META_OPERATION;
end case;
-- Input FIFO Guard
elsif (empty_user = '0') then
rd_guard := '1';
-- Latch Opcode
opcode_next <= header_opcode;
-- Latch Flags
flags_next <= header_flags;
-- Latch Source UDP Port
portn_next <= header_udp_port;
stage_next <= LATCH_SRC_ADDR;
-- SANITY CHECK: Skip Packet if non-standard Payload
if(header_opcode = SID_DATA and header_flags(SUBMESSAGE_NON_STANDARD_PAYLOAD_FLAG_POS) = '1') then
stage_next <= SKIP_PACKET;
end if;
end if;
when LATCH_GUIDPREFIX =>
-- Input FIFO Guard
if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then
if (is_meta = '1') then
rd_meta <= '1';
else
rd_guard := '1';
end if;
cnt_next <= cnt + 1;
case (cnt) is
-- GUID Prefix 1/3
when 0 =>
if (is_meta = '1') then
guid_next(0) <= data_in_meta;
else
guid_next(0) <= data_in_user;
end if;
-- GUID Prefix 2/3
when 1 =>
if (is_meta = '1') then
guid_next(1) <= data_in_meta;
else
guid_next(1) <= data_in_user;
end if;
-- GUID Prefix 3/3
when 2 =>
if (is_meta = '1') then
guid_next(2) <= data_in_meta;
else
guid_next(2) <= data_in_user;
end if;
if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS and meta_opcode = OPCODE_LIVELINESS_UPDATE))) then
--assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE;
-- DONE Parsing
stage_next <= INITIATE_ENDPOINT_SEARCH;
else
stage_next <= LATCH_ENTITYID;
end if;
when others =>
null;
end case;
end if;
when LATCH_ENTITYID =>
-- Input FIFO Guard
if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then
if (is_meta = '1') then
--assert (meta_opcode /= OPCODE_ENDPOINT_UNMATCH or (meta_opcode = OPCODE_ENDPOINT_UNMATCH and last_word_in_meta = '1')) report "last_word_in_meta not set" severity FAILURE;
rd_meta <= '1';
guid_next(3) <= data_in_meta;
-- Memory Operation Guard
else
rd_guard := '1';
guid_next(3) <= data_in_user;
end if;
stage_next <= INITIATE_ENDPOINT_SEARCH;
end if;
when INITIATE_ENDPOINT_SEARCH =>
-- Memory Operation Guard
if (mem_op_done = '1') then
if (is_meta = '1') then
case (meta_opcode) is
when OPCODE_ENDPOINT_MATCH =>
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
mem_field_flags <= (others => '0');
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
stage_next <= LATCH_ENDPOINT_DATA;
cnt_next <= 0;
else
stage_next <= METATRAFFIC_OPERATION;
end if;
when OPCODE_ENDPOINT_UNMATCH =>
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
mem_field_flags <= (others => '0');
stage_next <= METATRAFFIC_OPERATION;
when OPCODE_PARTICIPANT_UNMATCH =>
mem_op_start <= '1';
mem_opcode <= GET_FIRST_ENDPOINT;
mem_field_flags <= EMF_GUIDPREFIX_FLAG;
stage_next <= METATRAFFIC_OPERATION;
cnt_next <= 0;
when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
mem_op_start <= '1';
mem_opcode <= GET_FIRST_ENDPOINT;
mem_field_flags <= EMF_GUIDPREFIX_FLAG;
stage_next <= METATRAFFIC_OPERATION;
cnt_next <= 0;
end if;
when others =>
null;
end case;
else
mem_op_start <= '1';
mem_opcode <= SEARCH_ENDPOINT;
case (opcode) is
when SID_DATA =>
stage_next <= LATCH_EXTRA_DATA;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG;
cnt_next <= 0;
when SID_HEARTBEAT =>
stage_next <= LATCH_HEARTBEAT;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG;
cnt_next <= 0;
when SID_GAP =>
stage_next <= LATCH_GAP;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG;
cnt_next <= 0;
when others =>
stage_next <= SKIP_PACKET;
end case;
end if;
end if;
when LATCH_ENDPOINT_DATA =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Input FIFO Guard
if (empty_meta = '0') then
rd_meta <= '1';
cnt_next <= cnt + 1;
case (cnt) is
-- IPv4 Address
when 0 =>
addr_next <= data_in_meta;
-- UDP Port
when 1 =>
--assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE;
portn_next <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH);
stage_next <= METATRAFFIC_OPERATION;
when others =>
null;
end case;
end if;
end if;
when METATRAFFIC_OPERATION =>
-- Memory Operation Guard
if (mem_op_done = '1') then
case (meta_opcode) is
when OPCODE_ENDPOINT_MATCH =>
-- Endpoint already in Memory
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Update the Endpoint Data
-- NOTE: The Lease Duration is NOT updated in case of an update. That is the responsibility of the Liveliness Update
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
end if;
-- DONE
stage_next <= IDLE;
else
-- Insert Matched Remote Endpoint
mem_op_start <= '1';
mem_opcode <= INSERT_ENDPOINT;
if (LEASE_DURATION /= DURATION_INFINITE) then
lease_deadline <= time + LEASE_DURATION;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if ((time + LEASE_DURATION) < check_time) then
check_time_next <= time + LEASE_DURATION;
end if;
else
lease_deadline <= TIME_INVALID;
end if;
-- DONE
stage_next <= IDLE;
end if;
when OPCODE_ENDPOINT_UNMATCH =>
-- Endpoint not in Memory
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Ignore
stage_next <= IDLE;
else
-- Propagate Removal
start_hc <= '1';
opcode_hc <= REMOVE_WRITER;
data_out_hc <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement
if (ack_hc = '1') then
start_hc <= '0';
-- Remove Unmatched Remote Endpoint
mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT;
-- DONE
stage_next <= IDLE;
end if;
end if;
when OPCODE_PARTICIPANT_UNMATCH =>
case (cnt) is
when 0 =>
-- Reached End of Endpoints
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Participant Match
if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then
-- Propagate Removal
start_hc <= '1';
opcode_hc <= REMOVE_WRITER;
data_out_hc <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement
if (ack_hc = '1') then
start_hc <= '0';
-- Remove Unmatched Remote Endpoint
mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT;
cnt_next <= cnt + 1;
end if;
else
cnt_next <= cnt + 1;
end if;
end if;
when 1 =>
-- Continue Search
mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_GUIDPREFIX_FLAG;
cnt_next <= 0;
when others =>
null;
end case;
when OPCODE_LIVELINESS_UPDATE =>
-- Synthesis Guard
if (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) then
case (cnt) is
when 0 =>
-- No matches in memory
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- DONE
stage_next <= IDLE;
else
-- Participant Match
if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then
-- Renew Lease of Remote Endpoint
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG;
if (LEASE_DURATION /= DURATION_INFINITE) then
lease_deadline <= time + LEASE_DURATION;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if ((time + LEASE_DURATION) < check_time) then
check_time_next <= time + LEASE_DURATION;
end if;
else
lease_deadline <= TIME_INVALID;
end if;
end if;
cnt_next <= 1;
end if;
when 1 =>
-- Continue Search
mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_GUIDPREFIX_FLAG;
cnt_next <= 0;
when others =>
null;
end case;
end if;
when others =>
null;
end case;
end if;
when LATCH_SRC_ADDR =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
-- Latch Source IP Address
addr_next <= data_in_user;
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
end if;
when LATCH_EXTRA_DATA =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
-- Sequence Number 1/2
when 0 =>
seq_nr_next(0) <= unsigned(data_in_user);
-- Sequence Number 2/2
when 1 =>
seq_nr_next(1) <= unsigned(data_in_user);
-- Store Next Sequence Number
tmp_dw := (0 => seq_nr(0), 1 => unsigned(data_in_user));
next_seq_nr_next <= tmp_dw + 1;
-- Timestamp 1/2
when 2 =>
ts_next(0) <= unsigned(data_in_user);
-- Timestamp 2/2
when 3 =>
ts_next(1) <= unsigned(data_in_user);
if (qos_flag = '1') then
stage_next <= PROCESS_INLINE_QOS;
else
stage_next <= INITIATE_ADD_CACHE_CHANGE_REQUEST;
end if;
when others =>
null;
end case;
end if;
when LATCH_HEARTBEAT =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
-- First Sequence Number 1/2
when 0 =>
first_seq_nr_next(0) <= unsigned(data_in_user);
-- First Sequence Number 2/2
when 1 =>
first_seq_nr_next(1) <= unsigned(data_in_user);
-- Last Sequence Number 1/2
when 2 =>
last_seq_nr_next(0) <= unsigned(data_in_user);
-- Last Sequence Number 2/2
when 3 =>
last_seq_nr_next(1) <= unsigned(data_in_user);
stage_next <= PROCESS_HEARTBEAT;
when others =>
null;
end case;
end if;
when PROCESS_HEARTBEAT =>
-- Wait for Endpoint Search to finish
if (mem_op_done = '1') then
-- DEFAULT
stage_next <= SKIP_PACKET;
-- Endpoint in Buffer
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Default
tmp_flags := (others => '0');
tmp_dw := TIME_INFINITE;
-- Liveliness Assertion
if (liveliness_flag = '1') then
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
tmp_flags := tmp_flags or EMF_LEASE_DEADLINE_FLAG;
if (LEASE_DURATION /= DURATION_INFINITE) then
lease_deadline <= time + LEASE_DURATION;
tmp_dw := time + LEASE_DURATION;
else
lease_deadline <= TIME_INVALID;
end if;
end if;
-- No scheduled Heartbeat Response
if (mem_endpoint_data.res_time = TIME_INVALID) then
-- If Reader is Volatile and we have not received anything from the writer yet
if (DURABILITY_QOS = VOLATILE_DURABILITY_QOS and mem_endpoint_data.next_seq_nr = SEQUENCENUMBER_UNKNOWN) then
-- Mark last available SN as next expected (Ignore historical data)
next_seq_nr_next <= last_seq_nr;
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
tmp_flags := tmp_flags or EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG;
if (HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
res_time <= time + HEARTBEAT_RESPONSE_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
tmp_dw := (time + HEARTBEAT_RESPONSE_DELAY) when ((time + HEARTBEAT_RESPONSE_DELAY) < tmp_dw);
else
res_time <= TIME_INVALID;
end if;
-- If current Sequence Number obsolete (removed from source history cache)
elsif (first_seq_nr > mem_endpoint_data.next_seq_nr) then
-- Store new expected Sequence Number and set Response Dealy
next_seq_nr_next <= first_seq_nr;
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
tmp_flags := tmp_flags or EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG;
if (HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
res_time <= time + HEARTBEAT_RESPONSE_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
tmp_dw := (time + HEARTBEAT_RESPONSE_DELAY) when ((time + HEARTBEAT_RESPONSE_DELAY) < tmp_dw);
else
res_time <= TIME_INVALID;
end if;
-- If new Sequence Number is available or Writer expects ACKNACK
elsif (last_seq_nr >= mem_endpoint_data.next_seq_nr or final_flag = '0') then
-- Set Response Delay
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
tmp_flags := tmp_flags or EMF_RES_TIME_FLAG;
if (HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then
res_time <= time + HEARTBEAT_RESPONSE_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '0';
tmp_dw := (time + HEARTBEAT_RESPONSE_DELAY) when ((time + HEARTBEAT_RESPONSE_DELAY) < tmp_dw);
else
res_time <= TIME_INVALID;
end if;
end if;
-- Currently in Heartbeat Response Delay
elsif (mem_endpoint_data.res_time(1)(0) = '0') then
-- If current Sequence Number obsolete (removed from source history cache)
if (first_seq_nr > mem_endpoint_data.next_seq_nr) then
-- Store new expected Sequence Number
next_seq_nr_next <= first_seq_nr;
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
tmp_flags := tmp_flags or EMF_NEXT_SEQ_NR_FLAG;
end if;
end if;
mem_field_flags <= tmp_flags;
-- XXX: Possible Worst Case Path (MULTIPLE 64-bit addition and comparison in same clock)
-- Update Check Time
if (tmp_dw < check_time) then
check_time_next <= tmp_dw;
end if;
end if;
end if;
when LATCH_GAP =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
-- GapStart Sequence Number 1/2
when 0 =>
gap_start_next(0) <= unsigned(data_in_user);
-- GapStart Sequence Number 2/2
when 1 =>
gap_start_next(1) <= unsigned(data_in_user);
-- GapList.Base 1/2
when 2 =>
gap_list_base_next(0) <= unsigned(data_in_user);
-- GapList.Base 2/2
when 3 =>
gap_list_base_next(1) <= unsigned(data_in_user);
-- GapList.NumBits
when 4 =>
gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_user));
bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
cnt2_next <= 0;
-- GapList.Bitmap
when 5 =>
-- Read Bitmap
if (cnt2 < bitmap_cnt) then
cnt2_next <= cnt2 + 1;
bitmap_latch_next(cnt2) <= data_in_user;
-- Keep Sub-State
cnt_next <= cnt;
else
stage_next <= PROCESS_GAP;
end if;
when others =>
null;
end case;
end if;
when PROCESS_GAP =>
-- Wait for Endpoint Search
if (mem_op_done = '1') then
-- DEFAULT
stage_next <= SKIP_PACKET;
-- Known Remote Endpoint
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then
-- GAP is relevant
if (gap_start <= mem_endpoint_data.next_seq_nr and mem_endpoint_data.next_seq_nr <= gap_list_end) then
-- Next Expected is in GAP List
if (gap_list_base <= mem_endpoint_data.next_seq_nr) then
-- Begin searching next valid SN from the current expected in the bitmap list
bitmap_pos_next <= to_integer(next_seq_nr - gap_list_base);
else
-- Begin searching next valid SN from the beginning of the bitmap list
next_seq_nr_next <= gap_list_base;
bitmap_pos_next <= 0;
end if;
stage_next <= FIND_NEXT_VALID_IN_BITMAP;
end if;
end if;
end if;
when FIND_NEXT_VALID_IN_BITMAP =>
-- Memory Operation Guard
if (mem_op_done = '1') then
tmp_bitmap := to_slv_bitmap(bitmap_latch);
-- TODO: Test GAP that has next expected not marked in GAP
-- First valid sequence number found
if (tmp_bitmap(bitmap_pos) = '0') then
-- Update next sequence number
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG;
-- DONE
stage_next <= SKIP_PACKET;
else
-- Continue search
bitmap_pos_next <= bitmap_pos + 1;
next_seq_nr_next <= next_seq_nr + 1;
end if;
end if;
when PROCESS_INLINE_QOS =>
-- input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
-- Reset Word Counter
reset_read_cnt <= '1';
-- Latch Parameter End (In order to skip parameters)
parameter_end_next <= unsigned(endian_swap(endian_flag,parameter_length));
-- DEFAULT STAGE
stage_next <= SKIP_PARAMETER;
case (parameter_id) is
when PID_TOPIC_NAME =>
-- Ignore
null;
when PID_DURABILITY =>
-- Ignore
null;
when PID_PRESENTATION =>
-- Ignore
null;
when PID_DEADLINE =>
-- Ignore
null;
when PID_LATENCY_BUDGET =>
-- Ignore
null;
when PID_OWNERSHIP =>
-- Ignore
null;
when PID_OWNERSHIP_STRENGTH =>
-- Ignore
null;
when PID_LIVELINESS =>
-- Ignore
null;
when PID_PARTITION =>
-- Ignore
null;
when PID_RELIABILITY =>
-- Ignore
null;
when PID_DESTINATION_ORDER =>
-- Ignore
null;
when PID_TRANSPORT_PRIORITY =>
-- Ignore
null;
when PID_LIFESPAN =>
stage_next <= LATCH_LIFESPAN;
cnt_next <= 0;
when PID_CONTENT_FILTER_INFO =>
-- Ignore
null;
when PID_COHERENT_SET =>
-- Ignore
null;
when PID_DIRECTED_WRITE =>
-- Ignore
null;
when PID_ORIGINAL_WRITER_INFO =>
-- Ignore
null;
when PID_GROUP_COHERENT_SET =>
-- Ignore
null;
when PID_GROUP_SEQ_NUM =>
-- Ignore
null;
when PID_WRITER_GROUP_INFO =>
-- Ignore
null;
when PID_SECURE_WRITER_GROUP_INFO =>
-- Ignore
null;
when PID_KEY_HASH =>
key_hash_rcvd_next <= '1';
stage_next <= LATCH_KEY_HASH;
cnt_next <= 0;
when PID_STATUS_INFO =>
stage_next <= LATCH_STATUS_INFO;
when PID_PAD =>
-- Ignore
null;
when PID_SENTINEL =>
-- Reset
parameter_end_next <= (others => '1');
-- QOS DONE
stage_next <= INITIATE_ADD_CACHE_CHANGE_REQUEST;
when others =>
-- If MUST_UNDERSTAND Flag is set, we have incompatible communication. Drop Packet
if (must_understand = '1') then
stage_next <= SKIP_PACKET;
-- Else skip Unknown Parameter
else
stage_next <= SKIP_PARAMETER;
end if;
end case;
end if;
when LATCH_LIFESPAN =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
-- Lifespan 1/2
when 0 =>
-- NOTE: We are misusing the sn_latch_1 as temporal CDR_LONG storage
sn_latch_1_next(0) <= unsigned(data_in_swapped);
-- Lifespan 2/2
when 1 =>
tmp_dw := (0 => sn_latch_1(0), 1 => unsigned(data_in_swapped));
-- TODO: Use source timestamp if clocks with remote synchronized
-- Calculate Sample Lifespan Deadline
lifespan_next <= (time + tmp_dw) when (tmp_dw /= DURATION_INFINITE) else TIME_INVALID;
-- DONE
stage_next <= SKIP_PARAMETER;
when others =>
null;
end case;
end if;
when LATCH_KEY_HASH =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
cnt_next <= cnt + 1;
case (cnt) is
-- Key Hash 1/4
when 0 =>
key_hash_next(0) <= data_in_user;
-- Key Hash 2/4
when 1 =>
key_hash_next(1) <= data_in_user;
-- Key Hash 3/4
when 2 =>
key_hash_next(2) <= data_in_user;
-- Key Hash 4/4
when 3 =>
key_hash_next(3) <= data_in_user;
-- DONE
stage_next <= SKIP_PARAMETER;
when others =>
null;
end case;
end if;
when LATCH_STATUS_INFO =>
-- Input FIFO Guard
if (empty_user = '0') then
rd_guard := '1';
status_info_next <= data_in_user;
-- DONE
stage_next <= SKIP_PARAMETER;
end if;
when INITIATE_ADD_CACHE_CHANGE_REQUEST =>
-- Wait for Endpoint Data
if (mem_op_done = '1') then
-- Unknown Endpoint
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Ignore
stage_next <= SKIP_PACKET;
else
-- Data is Next expected Sequence Number
if ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and seq_nr = mem_endpoint_data.next_seq_nr) or (RELIABILTY_QOS = BEST_EFFORT_RELIABILITY_QOS and seq_nr >= mem_endpoint_data.next_seq_nr) or (DURABILITY_QOS = VOLATILE_DURABILITY_QOS and mem_endpoint_data.next_seq_nr = SEQUENCENUMBER_UNKNOWN)) then
-- SANITY CHECK: Skip if no Hash Key and no Payload
if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then
-- Ignore
stage_next <= SKIP_PACKET;
else
start_hc <= '1';
opcode_hc <= ADD_CACHE_CHANGE;
-- Wait until History Cache acknowledges request
if (ack_hc = '1') then
start_hc <= '0';
stage_next <= ADD_CACHE_CHANGE;
cnt_next <= 0;
end if;
end if;
else
-- Ignore
stage_next <= SKIP_PACKET;
end if;
end if;
end if;
when ADD_CACHE_CHANGE =>
case (cnt) is
-- Status Info
when 0 =>
valid_out_hc <= '1';
data_out_hc <= status_info;
data_out_hc(SSI_KEY_HASH_FLAG) <= key_hash_rcvd when WITH_KEY;
data_out_hc(SSI_PAYLOAD_FLAG) <= data_flag;
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Timestamp 1/2
when 1 =>
valid_out_hc <= '1';
data_out_hc <= std_logic_vector(ts(0));
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Timestamp 2/2
when 2 =>
valid_out_hc <= '1';
data_out_hc <= std_logic_vector(ts(1));
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Lifespan Deadline 1/2
when 3 =>
valid_out_hc <= '1';
data_out_hc <= std_logic_vector(lifespan(0));
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Lifespan Deadline 2/2
when 4 =>
valid_out_hc <= '1';
data_out_hc <= std_logic_vector(lifespan(1));
-- Output Guard
if (ready_out_hc = '1') then
-- Skip Key Hash, if not received
if (not WITH_KEY or key_hash_rcvd = '0') then
cnt_next <= cnt + 5;
else
cnt_next <= cnt + 1;
end if;
end if;
-- Key hash 1/4
when 5 =>
valid_out_hc <= '1';
data_out_hc <= key_hash(0);
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Key Hash 2/4
when 6 =>
valid_out_hc <= '1';
data_out_hc <= key_hash(1);
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Key Hash 3/4
when 7 =>
valid_out_hc <= '1';
data_out_hc <= key_hash(2);
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Key hash 4/4
when 8 =>
valid_out_hc <= '1';
data_out_hc <= key_hash(3);
-- Output Guard
if (ready_out_hc = '1') then
cnt_next <= cnt + 1;
end if;
-- Endpoint Memory Position
when 9 =>
-- Wait for Endpoint Search
if (mem_op_done = '1') then
valid_out_hc <= '1';
-- TODO: Assert mem_pos range fits in CDR_LONG
data_out_hc <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH));
-- Output Guard
if (ready_out_hc = '1') then
-- NOTE: We only push the Payload if there is Data, or if the Key Hash was not received and we need to push
-- the serialized Key.
-- Payload exists
if (data_flag = '1' or (WITH_KEY and key_hash_rcvd = '0')) then
stage_next <= PUSH_PAYLOAD;
else
-- DONE
last_word_out_hc <= '1';
stage_next <= FINALIZE_ADD_CACHE_CHANGE_REQUEST;
end if;
end if;
end if;
when others =>
null;
end case;
when PUSH_PAYLOAD =>
-- Input Guard
if (empty_user = '0') then
valid_out_hc <= '1';
-- Push Payload to History Cache
data_out_hc <= data_in_user;
last_word_out_hc <= last_word_in_user;
-- Output Guard
if (ready_out_hc = '1') then
rd_guard := '1';
-- Exit Condition
if (last_word_in_user = '1') then
stage_next <= FINALIZE_ADD_CACHE_CHANGE_REQUEST;
end if;
end if;
end if;
when FINALIZE_ADD_CACHE_CHANGE_REQUEST =>
-- NOTE: Memory is already in done state from previous state (ADD_CACHE_CHANGE)
assert (mem_op_done = '1') report "FINALIZE_ADD_CACHE_CHANGE_REQUEST precondition not met. mem_op_done /= '1'" severity FAILURE;
-- Wait for History Cache Response
if (done_hc = '1') then
-- NOTE: The Lease Duration is also updated if the Cache Change is not accepted. This in effect "skews" the
-- "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer.
-- Update Endpoint
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG;
if (LEASE_DURATION /= DURATION_INFINITE) then
lease_deadline <= time + LEASE_DURATION;
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if ((time + LEASE_DURATION) < check_time) then
check_time_next <= time + LEASE_DURATION;
end if;
else
lease_deadline <= TIME_INVALID;
end if;
-- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the Sequence Number is not updated
-- and thus not "acknowledged".
-- Operation was Accepted
if (ret_hc = OK) then
-- Update also next sequence number
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_LEASE_DEADLINE_FLAG;
end if;
-- DONE
stage_next <= SKIP_PACKET;
end if;
when ENDPOINT_STALE_CHECK =>
-- Memory Operation Guard
if (mem_op_done = '1') then
case (cnt) is
-- Get Next Endpoint
when 0 =>
mem_op_start <= '1';
mem_opcode <= GET_NEXT_ENDPOINT;
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG;
cnt_next <= 1;
-- Check Endpoint
when 1 =>
-- End of Endpoints
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
-- Reset
stale_check_next <= '0';
-- DONE
stage_next <= IDLE;
else
-- Endpoint Lease Expired
if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline <= time) then
-- Propagate Removal
start_hc <= '1';
opcode_hc <= REMOVE_WRITER;
data_out_hc <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH));
-- Wait for Operation Acknowledgement
if (ack_hc = '1') then
start_hc <= '0';
-- Remove Endpoint
mem_op_start <= '1';
mem_opcode <= REMOVE_ENDPOINT;
-- Continue Search
cnt_next <= 0;
end if;
-- Synthesis Guard/Response Time Reached
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.res_time <= time) then
-- If Suppression Delay passed, zero the time
if(mem_endpoint_data.res_time(1)(0) = '1') then
-- Disable Suppression
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
res_time <= TIME_INVALID;
mem_field_flags <= EMF_RES_TIME_FLAG;
-- Continue Search
cnt_next <= 0;
-- If Response Delay Passed
else
-- Get Additional Data
mem_op_start <= '1';
mem_opcode <= GET_ENDPOINT;
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG or EMF_NEXT_SEQ_NR_FLAG;
cnt_next <= 2;
end if;
else
-- Update Check Time
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then
if (mem_endpoint_data.res_time < check_time) then
check_time_next <= mem_endpoint_data.res_time;
end if;
else
if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline < check_time) then
check_time_next <= mem_endpoint_data.lease_deadline;
end if;
end if;
-- Continue Search
cnt_next <= 0;
end if;
end if;
when 2 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Set Heartbeat Suppression Time
if (HEARTBEAT_SUPPRESSION_DELAY /= DURATION_INFINITE and HEARTBEAT_SUPPRESSION_DELAY /= DURATION_ZERO) then
-- Set Heartbeat Suppression Time
res_time <= time + HEARTBEAT_SUPPRESSION_DELAY;
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
res_time(1)(0) <= '1';
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
-- Update Check Time
if ((time + HEARTBEAT_SUPPRESSION_DELAY) < check_time) then
check_time_next <= time + HEARTBEAT_SUPPRESSION_DELAY;
end if;
else
-- Disable Suppression
res_time <= TIME_INVALID;
end if;
mem_op_start <= '1';
mem_opcode <= UPDATE_ENDPOINT;
mem_field_flags <= EMF_RES_TIME_FLAG;
-- Send ACKNACK
-- Increment Acknack Counter
count_next <= count + 1;
stage_next <= SEND_HEADER;
return_stage_next <= SEND_ACKNACK;
cnt_next <= 0;
end if;
when others =>
null;
end case;
end if;
when SEND_HEADER =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Output FIFO Guard
if (full_rtps = '0') then
wr_rtps <= '1';
cnt_next <= cnt + 1;
case (cnt) is
-- OUTPUT HEADER
-- Src IPv4 Address
when 0 =>
data_out_rtps <= DEFAULT_IPv4_ADDRESS;
-- Dest IPv4 Address
when 1 =>
data_out_rtps <= mem_endpoint_data.addr;
-- Src and Dest UDPv4 Ports
when 2 =>
data_out_rtps <= USER_IPv4_UNICAST_PORT & mem_endpoint_data.portn;
-- RTPS MESSAGE HEADER
when 3 =>
data_out_rtps <= PROTOCOL_RTPS;
when 4 =>
data_out_rtps <= PROTOCOLVERSION_2_4 & VENDORID;
when 5 =>
data_out_rtps <= GUIDPREFIX(0);
when 6 =>
data_out_rtps <= GUIDPREFIX(1);
when 7 =>
data_out_rtps <= GUIDPREFIX(2);
-- Continue with respective RTPS Submessage
stage_next <= return_stage;
cnt_next <= 0;
when others =>
null;
end case;
end if;
end if;
when SEND_ACKNACK =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
-- Output FIFO Guard
if (full_rtps = '0') then
wr_rtps <= '1';
cnt_next <= cnt + 1;
case (cnt) is
-- ACKNACK RTPS SUBMESSAGE
-- RTPS Submessage Header
when 0 =>
data_out_rtps <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, SUBMESSAGE_LENGTH_WIDTH));
-- Reader Entity ID
when 1 =>
data_out_rtps <= ENTITYID;
-- Writer Entity ID
when 2 =>
data_out_rtps <= ENTITYID_UNKNOWN;
-- Sequence Number Set (Bitmap Base 1/2)
when 3 =>
data_out_rtps <= std_logic_vector(mem_endpoint_data.next_seq_nr(0));
-- Sequence Number Set (Bitmap Base 2/2)
when 4 =>
data_out_rtps <= std_logic_vector(mem_endpoint_data.next_seq_nr(1));
-- Sequence Number Set (NumBits)
when 5 =>
data_out_rtps <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH));
-- Sequence Number Set (Bitmap)
when 6 =>
-- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet)
-- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist)
data_out_rtps <= (others => '1');
-- Count
when 7 =>
data_out_rtps <= std_logic_vector(count);
last_word_out_rtps <= '1';
-- Stale Check in Progress
if (stale_check = '1') then
-- Continue Search
stage_next <= ENDPOINT_STALE_CHECK;
cnt_next <= 0;
else
-- DONE
stage_next <= IDLE;
end if;
when others =>
null;
end case;
end if;
end if;
when SKIP_PARAMETER =>
-- Consumed last word of Packet
if (last_word_in_latch = '1' and last_word_in_user = '0') then
-- Reset Last Word In Latch
last_word_in_latch_next <= '0';
-- Continue parsing next Packet
stage_next <= IDLE;
-- Reset Parameter End
parameter_end_next <= (others => '1');
-- End of Parameter
elsif ((read_cnt & "00" ) >= parameter_end) then
-- Parse Next Parameter
-- NOTE: data_in_user is already showing the next parameter
stage_next <= PROCESS_INLINE_QOS;
-- Reset Parameter End
parameter_end_next <= (others => '1');
-- Input FIFO Guard
elsif (empty_user = '0') then
-- Skip-Read
rd_guard := '1';
end if;
when SKIP_PACKET =>
-- NOTE: At the end of a Stale Entry Removal this stage is entered, without having started reading a Packet from input.
-- Reset Parameter End
parameter_end_next <= (others => '1');
-- Consumed last word of Packet
if (last_word_in_latch = '1' and last_word_in_user = '0') then
-- Reset Last Word In Latch
last_word_in_latch_next <= '0';
-- DONE
stage_next <= IDLE;
-- Input FIFO Guard
elsif (empty_user = '0') then
-- Skip-Read
rd_guard := '1';
end if;
when SKIP_META_OPERATION =>
-- Input Guard
if (empty_meta = '0') then
-- Skip-Read
rd_meta <= '1';
-- Exit Condition
if (last_word_in_meta = '1') then
stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
-- OVERREAD GUARD
-- Read outside of packet Length
-- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while
-- the Packet Length has been reached and will be caught by this clause.
-- The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
if ((last_word_in_latch = '1' and last_word_in_user = '0') and rd_guard = '1') then
-- Force rd_sig low
rd_sig <= '0';
-- Continue parsing next Packet
stage_next <= IDLE;
-- Reset Last Word In Latch
last_word_in_latch_next <= '0';
-- Reset Parameter End
parameter_end_next <= (others => '1');
-- Read outside of Parameter Length
-- NOTE: If the Parameter Length is smaller than expected for a particular parameter, there will be a read from input FIFO while
-- the Parameter Length has been reached and will be caught by this clause.
-- The SKIP_PARAMETER clause prevents a read signal from occuring in this situation, and thus prevents from entering this state.
elsif ((read_cnt & "00") >= parameter_end and rd_guard = '1') then
-- Force rd_sig low
rd_sig <= '0';
-- Invalid Parameter Length, Skip Packet
stage_next <= SKIP_PACKET;
-- Reset Parameter End
parameter_end_next <= (others => '1');
-- DEFAULT
else
rd_sig <= rd_guard;
end if;
end process;
-- *Memory State Machine*
-- STATE DESCRIPTION
-- IDLE Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations
-- SEARCH_ENDPOINT See Memory OPCODE Description
-- GET_ENDPOINT_DATA Latch specified Endpoint Data for use by main FSM
-- INSERT_ENDPOINT See Memory OPCODE Description
-- UPDATE_ENDPOINT See Memory OPCODE Description
-- REMOVE_ENDPOINT See Memory OPCODE Description
-- FIND_EMPTY_SLOT Find first empty_user slot in memory.
-- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory.
-- GET_NEXT_ENDPOINT See Memory OPCODE Description
-- RESET_MEMORY Reset Endpoint Memory to Empty State
mem_ctrl_prc : process(all)
begin
-- DEFAULT Registered
mem_stage_next <= mem_stage;
mem_addr_base_next <= mem_addr_base;
mem_cnt_next <= mem_cnt;
last_addr_next <= last_addr;
mem_addr_latch_next <= mem_addr_latch;
mem_endpoint_data_next <= mem_endpoint_data;
max_endpoint_addr_next <= max_endpoint_addr;
mem_endpoint_latch_data_next <= mem_endpoint_latch_data;
mem_pos_next <= mem_pos;
-- DEFAULT Unregistered
mem_addr <= (others => '0');
mem_write_data <= (others => '0');
mem_read <= '0';
mem_valid_in <= '0';
mem_ready_out <= '0';
mem_op_done <= '0';
abort_read <= '0';
case (mem_stage) is
when IDLE =>
mem_op_done <= '1';
if (mem_op_start = '1') then
-- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk)
mem_endpoint_latch_data_next <= (
guid => guid_next,
addr => addr_next,
portn => portn_next,
lease_deadline => lease_deadline,
res_time => res_time,
next_seq_nr => next_seq_nr_next,
field_flag => mem_field_flags
);
case(mem_opcode) is
when SEARCH_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= SEARCH_ENDPOINT;
mem_cnt_next <= 0;
when INSERT_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= FIND_EMPTY_SLOT;
mem_cnt_next <= 0;
when UPDATE_ENDPOINT =>
mem_stage_next <= UPDATE_ENDPOINT;
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 0;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 1;
elsif check_mask(mem_field_flags,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 2;
elsif check_mask(mem_field_flags,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 6;
else
-- DONE
mem_stage_next <= IDLE;
end if;
when REMOVE_ENDPOINT =>
mem_stage_next <= REMOVE_ENDPOINT;
mem_cnt_next <= 0;
when GET_FIRST_ENDPOINT =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
mem_stage_next <= GET_NEXT_ENDPOINT;
mem_cnt_next <= 0;
when GET_NEXT_ENDPOINT =>
-- Memory Bound Guard
if (mem_addr_base >= max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS;
else
-- Reached End of Memory, No match
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_stage_next <= GET_NEXT_ENDPOINT;
mem_cnt_next <= 0;
end if;
when GET_ENDPOINT =>
-- Fetch Endpoint Data
mem_stage_next <= GET_ENDPOINT_DATA;
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
if check_mask(mem_field_flags,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 0;
elsif check_mask(mem_field_flags,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 1;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_field_flags,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_field_flags,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
-- DONE
mem_stage_next <= IDLE;
end if;
when others =>
null;
end case;
end if;
when SEARCH_ENDPOINT =>
case (mem_cnt) is
-- GET Entity ID
when 0 =>
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET GUID Prefix 1/3
when 1 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET GUID Prefix 2/3
when 2 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET GUID Prefix 3/3
when 3 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- READ Entity ID
when 4 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
-- No Match
if (mem_read_data /= mem_endpoint_latch_data.guid(3)) then
abort_read <= '1';
-- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
else
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- READ GUID Prefix 1/3
when 5 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
-- No Match
if (mem_read_data /= mem_endpoint_latch_data.guid(0)) then
abort_read <= '1';
-- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
else
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- READ GUID Prefix 2/3
when 6 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
-- No Match
if (mem_read_data /= mem_endpoint_latch_data.guid(1)) then
abort_read <= '1';
-- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
else
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- READ GUID Prefix 3/3
when 7 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
-- No Match
if (mem_read_data /= mem_endpoint_latch_data.guid(2)) then
abort_read <= '1';
-- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
-- Match
else
-- Fetch Endpoint Data
mem_stage_next <= GET_ENDPOINT_DATA;
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 0;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 1;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
end if;
when others =>
null;
end case;
when GET_ENDPOINT_DATA =>
case (mem_cnt) is
-- GET Entity ID
when 0 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 1;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
mem_cnt_next <= 12;
end if;
end if;
-- GET GUID Prefix 1/3
when 1 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET GUID Prefix 2/3
when 2 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET GUID Prefix 3/3
when 3 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
else
mem_cnt_next <= 13;
end if;
end if;
end if;
-- GET IPv4 Address
when 4 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
else
mem_cnt_next <= 16;
end if;
end if;
end if;
end if;
-- GET UDP Port/ Flags
when 5 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
else
mem_cnt_next <= 17;
end if;
end if;
end if;
end if;
-- GET Next Sequence Number 1/2
when 6 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET Next Sequence Number 2/2
when 7 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
else
mem_cnt_next <= 18;
end if;
end if;
end if;
-- GET Lease Deadline 1/2
when 8 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GET Lease Deadline 2/2
when 9 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
else
mem_cnt_next <= 20;
end if;
end if;
end if;
-- GET Response Time 1/2
when 10 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- GET Response Time 2/2
when 11 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
mem_read <= '1';
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 12;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
else
mem_cnt_next <= 22;
end if;
end if;
end if;
-- READ Entity ID
when 12 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.guid(3) <= mem_read_data;
if check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 13;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- READ GUID Prefix 1/3
when 13 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.guid(0) <= mem_read_data;
mem_cnt_next <= mem_cnt + 1;
end if;
-- READ GUID Prefix 2/3
when 14 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.guid(1) <= mem_read_data;
mem_cnt_next <= mem_cnt + 1;
end if;
-- READ GUID Prefix 3/3
when 15 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.guid(2) <= mem_read_data;
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 16;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- READ IPv4 Address
when 16 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.addr <= mem_read_data;
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 17;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
end if;
-- READ UDP Port
when 17 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.portn <= mem_read_data(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH);
if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 18;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
end if;
-- READ Next Sequence Number 1/2
when 18 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.next_seq_nr(0) <= unsigned(mem_read_data);
mem_cnt_next <= mem_cnt + 1;
end if;
-- READ Next Sequence Number 2/2
when 19 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.next_seq_nr(1) <= unsigned(mem_read_data);
if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 20;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- READ Lease Deadline 1/2
when 20 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.lease_deadline(0) <= unsigned(mem_read_data);
mem_cnt_next <= mem_cnt + 1;
end if;
-- READ Lease Deadline 2/2
when 21 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.lease_deadline(1) <= unsigned(mem_read_data);
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 22;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- READ Response Time 1/2
when 22 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.res_time(0) <= unsigned(mem_read_data);
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- READ Response Time 2/2
when 23 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
mem_endpoint_data_next.res_time(1) <= unsigned(mem_read_data);
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when INSERT_ENDPOINT =>
case (mem_cnt) is
-- Entity ID
when 0 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_write_data <= mem_endpoint_latch_data.guid(3);
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 1/3
when 1 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
mem_write_data <= mem_endpoint_latch_data.guid(0);
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 2/3
when 2 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
mem_write_data <= mem_endpoint_latch_data.guid(1);
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 3/3
when 3 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
mem_write_data <= mem_endpoint_latch_data.guid(2);
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1 when (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) else 6;
end if;
-- IPv4 Address
when 4 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
mem_write_data <= mem_endpoint_latch_data.addr;
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- UDPv4 Ports
when 5 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET;
mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0');
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- Next Sequence Number 1/2
when 6 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET;
mem_write_data <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(0)) when (DURABILITY_QOS = VOLATILE_DURABILITY_QOS) else std_logic_vector(FIRST_SEQUENCENUMBER(0));
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Next Sequence Number 2/2
when 7 =>
mem_write_data <= (others => '0');
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1;
mem_write_data <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(1)) when (DURABILITY_QOS = VOLATILE_DURABILITY_QOS) else std_logic_vector(FIRST_SEQUENCENUMBER(1));
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Lease Deadline 1/2
when 8 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(0));
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Lease Deadline 2/2
when 9 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(1));
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_cnt_next <= mem_cnt + 1;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- Response Time 1/2
when 10 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET;
mem_write_data <= std_logic_vector(TIME_INVALID(0));
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- Response Time 2/2
when 11 =>
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
mem_write_data <= std_logic_vector(TIME_INVALID(1));
if (mem_ready_in = '1') then
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when UPDATE_ENDPOINT =>
case (mem_cnt) is
-- IPv4 Address
when 0 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET;
mem_write_data <= mem_endpoint_latch_data.addr;
mem_endpoint_data_next.addr <= mem_endpoint_latch_data.addr;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 1;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 2;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 6;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
end if;
-- UDPv4 Ports
when 1 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET;
mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0');
mem_endpoint_data_next.portn <= mem_endpoint_latch_data.portn;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 2;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 6;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
end if;
-- Next Sequence Number 1/2
when 2 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(0));
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Next Sequence Number 2/2
when 3 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(1));
mem_endpoint_data_next.next_seq_nr <= mem_endpoint_latch_data.next_seq_nr;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 6;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- Lease Deadline 1/2
when 4 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(0));
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Lease Deadline 2/2
when 5 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.lease_deadline(1));
mem_endpoint_data_next.lease_deadline <= mem_endpoint_latch_data.lease_deadline;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 6;
else
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
-- Response Time 1/2
when 6 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.res_time(0));
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- Response Time 2/2
when 7 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1;
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.res_time(1));
mem_endpoint_data_next.res_time <= mem_endpoint_latch_data.res_time;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
-- DONE
mem_stage_next <= IDLE;
end if;
end if;
when others =>
null;
end case;
when REMOVE_ENDPOINT =>
-- Mark with ENTITYID_UNKNOWN to mark slot empty_user
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_write_data <= ENTITYID_UNKNOWN;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
-- Reset MAX Endpoint Pointer
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_pos_next <= 0;
last_addr_next <= (others => '0');
mem_stage_next <= RESET_MAX_POINTER;
mem_cnt_next <= 0;
-- Save Current Memory Position
mem_addr_latch_next <= mem_addr_base;
end if;
when FIND_EMPTY_SLOT =>
case (mem_cnt) is
-- *READ ADDRESS*
-- Entity ID
when 0 =>
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Control Flow Guard
if (mem_ready_in = '1') then
mem_cnt_next <= 1;
end if;
-- *READ DATA*
-- Entity ID
when 1 =>
mem_ready_out <= '1';
-- Memory Control Flow Guard
if (mem_valid_out = '1') then
-- Slot Occupied
if (mem_read_data /= ENTITYID_UNKNOWN) then
-- Reached end of Endpoint Memory Area
if (mem_addr_base = max_endpoint_addr) then
-- MEMORY FULL
if (max_endpoint_addr = MAX_ENDPOINT_ADDRESS) then
report "Memory Full, Ignoring Endpoint Data" severity NOTE;
-- Ignore Insertion
mem_stage_next <= IDLE;
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS;
else
-- Extend Endpoint Memory Area
-- NOTE: "max_endpoint_addr" points to the first address of last Endpoint Frame
max_endpoint_addr_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
-- Populate Endpoint Slot
mem_stage_next <= INSERT_ENDPOINT;
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
-- Slot Empty
else
-- Populate Endpoint Slot
mem_stage_next <= INSERT_ENDPOINT;
mem_cnt_next <= 0;
end if;
end if;
when others =>
null;
end case;
when RESET_MAX_POINTER =>
case (mem_cnt) is
-- GET Entity ID
when 0 =>
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
mem_valid_in <= '1';
-- Memory Control Flow Guard
if (mem_ready_in = '1') then
mem_cnt_next <= 1;
end if;
-- READ Entity ID
when 1 =>
mem_ready_out <= '1';
-- Memory Control Flow Guard
if (mem_valid_out = '1') then
-- Slot Occupied
if (mem_read_data /= ENTITYID_UNKNOWN) then
-- Reached end of Endpoint Memory Area
if (mem_addr_base = max_endpoint_addr) then
-- No Change
mem_stage_next <= IDLE;
-- Restore Memory Position
mem_addr_base_next <= mem_addr_latch;
else
-- Latch last occupied Endpoint Slot
last_addr_next <= mem_addr_base;
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_cnt_next <= 0;
end if;
-- Slot Empty
else
-- Make sure to iterate through complete Endpoint Area
if (mem_addr_base = max_endpoint_addr) then
-- Reset Pointer to last occupied Endpoint Slot
max_endpoint_addr_next <= last_addr;
-- DONE
mem_stage_next <= IDLE;
-- Restore Memory Position
mem_addr_base_next <= mem_addr_latch;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when GET_NEXT_ENDPOINT =>
case (mem_cnt) is
-- GET Entity ID
when 0 =>
mem_valid_in <= '1';
mem_read <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
mem_cnt_next <= 1;
end if;
-- READ Entity ID
when 1 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
if (mem_valid_out = '1') then
-- Slot Occupied
if (mem_read_data /= ENTITYID_UNKNOWN) then
-- Fetch Endpoint Data
mem_stage_next <= GET_ENDPOINT_DATA;
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
mem_cnt_next <= 0;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
mem_cnt_next <= 1;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG)) then
mem_cnt_next <= 4;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG)) then
mem_cnt_next <= 5;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then
mem_cnt_next <= 6;
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then
mem_cnt_next <= 8;
elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
mem_cnt_next <= 10;
else
-- DONE
mem_stage_next <= IDLE;
end if;
-- Slot Empty
else
-- Reached End of Memory, No Match
if (mem_addr_base = max_endpoint_addr) then
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match
-- DONE
mem_stage_next <= IDLE;
else
-- Continue Search
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
mem_pos_next <= mem_pos + 1;
mem_cnt_next <= 0;
end if;
end if;
end if;
when others =>
null;
end case;
when RESET_MEMORY =>
case (mem_cnt) is
-- Initiate Reset
when 0 =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_cnt_next <= mem_cnt + 1;
-- Reset Memory
when 1 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_write_data <= ENTITYID_UNKNOWN;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
-- End of Memory
if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then
-- DONE
mem_stage_next <= IDLE;
else
-- Next Endpoint Frame
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
end if;
end if;
when others =>
null;
end case;
when others =>
null;
end case;
end process;
-- Process responsible for counting read words
-- This process uses the actual FIFO read signals to determine reads
word_counter_prc : process(clk, reset)
begin
if rising_edge(clk) then
-- Reset Read counter
if (reset = '1' or reset_read_cnt = '1') then
read_cnt <= (others => '0');
-- Increment read counter each time rd_sig is high
elsif (rd_sig = '1') then
read_cnt <= read_cnt + 1;
end if;
end if;
end process;
sync_prc : process(clk)
begin
if rising_edge(clk) then
if (reset = '1') then
stage <= IDLE;
return_stage <= IDLE;
mem_stage <= RESET_MEMORY;
seq_nr <= SEQUENCENUMBER_UNKNOWN;
next_seq_nr <= SEQUENCENUMBER_UNKNOWN;
sn_latch_1 <= SEQUENCENUMBER_UNKNOWN;
sn_latch_2 <= SEQUENCENUMBER_UNKNOWN;
sn_latch_3 <= SEQUENCENUMBER_UNKNOWN;
ts <= TIME_INVALID;
check_time <= TIME_INVALID;
lifespan <= TIME_INVALID;
guid <= GUID_UNKNOWN;
addr <= IPv4_ADDRESS_INVALID;
portn <= UDP_PORT_INVALID;
mem_endpoint_data <= ZERO_ENDPOINT_DATA;
mem_endpoint_latch_data <= ZERO_ENDPOINT_LATCH_DATA;
cnt <= 0;
cnt2 <= 0;
bitmap_pos <= 0;
mem_cnt <= 0;
mem_pos <= 0;
is_meta <= '0';
key_hash_rcvd <= '0';
last_word_in_latch <= '0';
stale_check <= '0';
parameter_end <= (others => '1');
bitmap_cnt <= (others => '0');
meta_opcode <= (others => '0');
status_info <= (others => '0');
mem_addr_base <= (others => '0');
last_addr <= (others => '0');
mem_addr_latch <= (others => '0');
max_endpoint_addr <= (others => '0');
flags <= (others => '0');
opcode <= (others => '0');
count <= (others => '0');
key_hash <= (others => (others => '0'));
bitmap_latch <= (others => (others => '0'));
else
stage <= stage_next;
return_stage <= return_stage_next;
mem_stage <= mem_stage_next;
seq_nr <= seq_nr_next;
next_seq_nr <= next_seq_nr_next;
sn_latch_1 <= sn_latch_1_next;
sn_latch_2 <= sn_latch_2_next;
sn_latch_3 <= sn_latch_3_next;
ts <= ts_next;
check_time <= check_time_next;
lifespan <= lifespan_next;
guid <= guid_next;
addr <= addr_next;
portn <= portn_next;
mem_endpoint_data <= mem_endpoint_data_next;
mem_endpoint_latch_data <= mem_endpoint_latch_data_next;
cnt <= cnt_next;
cnt2 <= cnt2_next;
bitmap_pos <= bitmap_pos_next;
mem_cnt <= mem_cnt_next;
mem_pos <= mem_pos_next;
is_meta <= is_meta_next;
key_hash_rcvd <= key_hash_rcvd_next;
last_word_in_latch <= last_word_in_latch_next;
parameter_end <= parameter_end_next;
bitmap_cnt <= bitmap_cnt_next;
stale_check <= stale_check_next;
meta_opcode <= meta_opcode_next;
status_info <= status_info_next;
mem_addr_base <= mem_addr_base_next;
last_addr <= last_addr_next;
mem_addr_latch <= mem_addr_latch_next;
max_endpoint_addr <= max_endpoint_addr_next;
flags <= flags_next;
opcode <= opcode_next;
count <= count_next;
key_hash <= key_hash_next;
bitmap_latch <= bitmap_latch_next;
end if;
end if;
end process;
end architecture;