3764 lines
217 KiB
VHDL
3764 lines
217 KiB
VHDL
-- altera vhdl_input_version vhdl_2008
|
|
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)
|
|
|
|
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: Rewrite all DONE to EXIT if no return to IDLE. (DONE should only signify return to IDLE)
|
|
|
|
entity rtps_writer is
|
|
generic (
|
|
-- XXX: Quartus Limitation [VHDL error at <location>: generic "<name>" cannot be used in its own interface list (ID: 10556)]
|
|
--ID : ID_TYPE := 0;
|
|
RELIABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);-- := ENDPOINT_RELIABILITY_QOS(ID);
|
|
LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);-- := ENDPOINT_LIVELINESS_QOS(ID);
|
|
DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);-- := ENDPOINT_DURABILITY_QOS(ID);
|
|
DESTINATION_ORDER_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0);-- := ENDPOINT_DESTINATION_ORDER_QOS(ID);
|
|
ACKNACK_RESPONSE_DELAY : DURATION_TYPE;-- := ENDPOINT_ACKNACK_RESPONSE_DELAY(ID);
|
|
ACKNACK_SUPPRESSION_DELAY : DURATION_TYPE;-- := ENDPOINT_ACKNACK_SUPPRESSION_DELAY(ID);
|
|
LEASE_DURATION : DURATION_TYPE;-- := ENDPOINT_LEASE_DURATION(ID);
|
|
HEARTBEAT_PERIOD : DURATION_TYPE;-- := ENDPOINT_HEARTBEAT_PERIOD(ID);
|
|
ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0);-- := ENTITYID(ID);
|
|
WITH_KEY : boolean;-- := ENDPOINT_WITH_KEY(ID);
|
|
PUSH_MODE : boolean;-- := ENDPOINT_PUSH_MODE(ID);
|
|
INLINE_QOS : OUTPUT_DATA_TYPE;-- := gen_inline_qos(ID);
|
|
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;
|
|
-- TO/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;
|
|
-- TO RTPS BUILTIN ENDPOINT (META TRAFFIC)
|
|
alive_sig : out std_logic;
|
|
-- RTPS OUTPUT
|
|
full_ro : in std_logic;
|
|
wr_ro : out std_logic;
|
|
data_out_ro : out std_logic_vector(WORD_WIDTH-1 downto 0);
|
|
last_word_out_ro : out std_logic;
|
|
-- FROM HISTORY CACHE
|
|
liveliness_assertion : in std_logic;
|
|
data_available : in std_logic;
|
|
start_hc : out std_logic;
|
|
opcode_hc : out HISTORY_CACHE_OPCODE_TYPE;
|
|
ack_hc : in std_logic;
|
|
seq_nr_hc : out SEQUENCENUMBER_TYPE;
|
|
done_hc : in std_logic;
|
|
ret_hc : in HISTORY_CACHE_RESPONSE_TYPE;
|
|
get_data_hc : out std_logic;
|
|
valid_in_hc : in std_logic;
|
|
ready_in_hc : out std_logic;
|
|
data_in_hc : in std_logic_vector(WORD_WIDTH-1 downto 0);
|
|
last_word_in_hc : in std_logic;
|
|
cc_instance_handle : in INSTANCE_HANDLE_TYPE;
|
|
cc_kind : in CACHE_CHANGE_KIND_TYPE;
|
|
cc_source_timestamp : in TIME_TYPE;
|
|
cc_seq_nr : in SEQUENCENUMBER_TYPE
|
|
);
|
|
end entity;
|
|
|
|
architecture arch of rtps_writer is
|
|
|
|
--*****CONSTANT DECLARATION*****
|
|
-- *ENDPOINT MEMORY*
|
|
-- 4-Byte Word Size of a Remote Endpoint 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
|
|
if (qos = RELIABLE_RELIABILITY_QOS) then
|
|
ret := 15;
|
|
else
|
|
ret := 6;
|
|
end if;
|
|
return ret;
|
|
end function;
|
|
constant ENDPOINT_FRAME_SIZE : natural := gen_frame_size(RELIABILITY_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 FRAME FIELD FLAGS*
|
|
-- Flags mapping to the respective Endpoint Memory Frame Fields
|
|
constant EMF_FLAG_WIDTH : natural := 9;
|
|
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_LEASE_DEADLINE_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (4 => '1', others => '0');
|
|
constant EMF_RES_TIME_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (5 => '1', others => '0');
|
|
constant EMF_ACK_SEQ_NR_BASE_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (6 => '1', others => '0');
|
|
constant EMF_REQ_SEQ_NR_BASE_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (7 => '1', others => '0');
|
|
constant EMF_REQ_SEQ_NR_BITMAP_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (8 => '1', others => '0');
|
|
|
|
|
|
-- *ENDPOINT MEMORY FRAME FIELD OFFSETS*
|
|
-- 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;
|
|
constant EMF_LEASE_DEADLINE_OFFSET : natural := 6;
|
|
constant EMF_RES_TIME_OFFSET : natural := 8;
|
|
constant EMF_ACK_SEQ_NR_BASE_OFFSET : natural := 10;
|
|
constant EMF_REQ_SEQ_NR_BASE_OFFSET : natural := 12;
|
|
constant EMF_REQ_SEQ_NR_BITMAP_OFFSET : natural := 14;
|
|
|
|
|
|
--*****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_ACKNACK, PROCESS_ACK, UPDATE_GLOBAL_ACK, PROCESS_NACK, PARSE_NACK_BITMAP, ENDPOINT_STALE_CHECK,
|
|
GET_MIN_SN, GET_MAX_SN, HANDLE_REQUESTS, HANDLE_HEARTBEATS, HANDLE_NEW, HANDLE_HISTORICAL, SEND_HEADER, SEND_INFO_TS,
|
|
SEND_DATA_A, SEND_INLINE_QOS, SEND_DATA_B, SEND_GAP_A, SEND_GAP_B, SEND_HEARTBEAT, 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 Search memory for Endpoint with GUID equal to "guid" signal.
|
|
-- Set "mem_addr_base" to base Address of found Endpoint, or ENDPOINT_MEMORY_MAX_ADDRESS if nothing found.
|
|
-- "mem_endpoint_data" contains Endpoint Data according to "mem_field_flags".
|
|
-- INSERT_ENDPOINT Insert Endpoint to first available empty slot in memory
|
|
-- UPDATE_ENDPOINT Update Endpoint pointed by "mem_addr_base" according to "mem_field_flags".
|
|
-- REMOVE_ENDPOINT Remove Endpoint pointed by "mem_addr_base"
|
|
-- GET_FIRST_ENDPOINT Get Endpoint Data of first Endpoint stored in Memory according to "mem_field_flags".
|
|
-- Set "mem_addr_base" to Address of Endpoint, or ENDPOINT_MEMORY_MAX_ADDRESS if no Endpoint in Memory.
|
|
-- GET_NEXT_ENDPOINT Get Endpoint Data of next Endpoint (from the Endpoint pointed by "mem_addr_base") according to "mem_field_flags".
|
|
-- Set "mem_addr_base" to Address of Endpoint, or ENDPOINT_MEMORY_MAX_ADDRESS if no other Endpoint in Memory.
|
|
-- GET_ENDPOINT Get Endpoint Data from Endpoint pointed by "mem_addr_update" according to "mem_field_flags".
|
|
-- Already fetched data of the same Endpoint is not modified.
|
|
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);
|
|
flags : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
|
|
lease_deadline : TIME_TYPE;
|
|
res_time : TIME_TYPE;
|
|
ack_seq_nr_base : SEQUENCENUMBER_TYPE;
|
|
req_seq_nr_base : SEQUENCENUMBER_TYPE;
|
|
req_seq_nr_bitmap : std_logic_vector(0 to WORD_WIDTH-1);
|
|
end record;
|
|
-- Zero initialized Endpoint Data
|
|
constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := (
|
|
guid => GUID_UNKNOWN,
|
|
addr => IPv4_ADDRESS_INVALID,
|
|
portn => UDP_PORT_INVALID,
|
|
flags => (others => '0'),
|
|
lease_deadline => TIME_INVALID,
|
|
res_time => TIME_INVALID,
|
|
ack_seq_nr_base => SEQUENCENUMBER_UNKNOWN,
|
|
req_seq_nr_base => SEQUENCENUMBER_UNKNOWN,
|
|
req_seq_nr_bitmap => (others => '0')
|
|
);
|
|
-- 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);
|
|
flags : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
|
|
lease_deadline : TIME_TYPE;
|
|
res_time : TIME_TYPE;
|
|
ack_seq_nr_base : SEQUENCENUMBER_TYPE;
|
|
req_seq_nr_base : SEQUENCENUMBER_TYPE;
|
|
req_seq_nr_bitmap : std_logic_vector(0 to WORD_WIDTH-1);
|
|
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,
|
|
flags => (others => '0'),
|
|
lease_deadline => TIME_INVALID,
|
|
res_time => TIME_INVALID,
|
|
ack_seq_nr_base => SEQUENCENUMBER_UNKNOWN,
|
|
req_seq_nr_base => SEQUENCENUMBER_UNKNOWN,
|
|
req_seq_nr_bitmap => (others => '0'),
|
|
field_flag => (others => '0')
|
|
);
|
|
|
|
|
|
--*****SIGNAL DECLARATION*****
|
|
-- *MAIN PROCESS*
|
|
-- FSM state
|
|
signal stage, stage_next : STAGE_TYPE;
|
|
-- FSM state latch. Used to transition dynamically to different states from the same state.
|
|
signal return_stage, return_stage_next : STAGE_TYPE;
|
|
-- General Purpose Counter
|
|
signal cnt, cnt_next : natural range 0 to 13;
|
|
-- Counter Latch. Used to transition dynamically to different sub-states from the same state.
|
|
signal return_cnt, return_cnt_next : natural range 0 to 13;
|
|
-- Packet Opcode Latch (RTPS Message ID)
|
|
signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0);
|
|
-- Metatraffic Opcode Latch
|
|
signal meta_opcode, meta_opcode_next : std_logic_vector(EMO_WIDTH-1 downto 0);
|
|
-- Signifies if the received packet is a metatraffic operation
|
|
signal is_meta, is_meta_next : std_logic;
|
|
-- Source GUID Latch
|
|
signal guid, guid_next : GUID_TYPE;
|
|
-- Source IPv4 Address Latch
|
|
signal addr, addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0);
|
|
-- UDP Port Latch
|
|
signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
|
|
-- RTPS Header Flags Latch
|
|
signal rtps_flags, rtps_flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0);
|
|
-- Remote Endpoint Reader Flags Latch
|
|
signal reader_flags, reader_flags_next : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0);
|
|
-- Generic Sequence Number Latch
|
|
signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE;
|
|
-- Generic Sequence Number Latch
|
|
signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE;
|
|
-- Generic Sequence Number Latch
|
|
signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE;
|
|
-- General Purpose Long Latch
|
|
signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0);
|
|
-- Toggle latching the "last_word_in_user" signal until reset
|
|
signal last_word_in_latch, last_word_in_latch_next : std_logic;
|
|
-- Toggle latch for Liveliness Assertion
|
|
signal assert_liveliness_latch, assert_liveliness_latch_next : std_logic;
|
|
-- Time of next Stale Endpoint Check
|
|
signal check_time, check_time_next : TIME_TYPE;
|
|
-- Time of next Heartbeat sending
|
|
signal heartbeat_time, heartbeat_time_next : TIME_TYPE;
|
|
-- Signifies if a Stale Endpoint Check is in progress
|
|
signal stale_check, stale_check_next : std_logic;
|
|
-- Signifies the new Cache Changes are currently being send out
|
|
signal new_push, new_push_next : std_logic;
|
|
-- Signifies that Historical Cache Changes are currently being sent out
|
|
signal historical_push, historical_push_next : std_logic;
|
|
-- Signifies that the first half of a GAP Message has been written, and needs to be "closed"
|
|
signal gap_in_progress, gap_in_progress_next : std_logic;
|
|
-- Signifies that the GAP is the Last Submessage
|
|
signal gap_is_last, gap_is_last_next : std_logic;
|
|
-- Signal containing the RTPS Heartbeat Count Field
|
|
signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0);
|
|
-- Signal containing the lowest common Sequence Number ACKed by ALL remote Readers
|
|
signal global_ack_seq_nr_base, global_ack_seq_nr_base_next : SEQUENCENUMBER_TYPE;
|
|
-- Signal containing the highest Sequence Number sent out by the writer
|
|
signal last_seq_nr, last_seq_nr_next : SEQUENCENUMBER_TYPE;
|
|
-- 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);
|
|
-- NumberSet Bitmap Latch
|
|
signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE;
|
|
-- Counter used to read out Bitmaps
|
|
signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length;
|
|
-- Counter used to read out the In-Line QoS
|
|
signal cnt3, cnt3_next : natural range 0 to INLINE_QOS.length-1;
|
|
-- Signal used to iterate through NACK Bitmaps
|
|
signal nack_bitmap_pos, nack_bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1;
|
|
-- Signals the start of a Memory Operation
|
|
signal mem_op_start : std_logic;
|
|
-- Opcode of the Memory Operation (Valid only when mem_op_start is high)
|
|
signal mem_opcode : MEM_OPCODE_TYPE;
|
|
-- Signals the end of a Memory Operation
|
|
signal mem_op_done : std_logic;
|
|
-- 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);
|
|
-- Signal used to pass Lease Deadlines from main to memory process
|
|
signal lease_deadline : TIME_TYPE;
|
|
-- Signal used to pass Response Deadlines from main to memory process
|
|
signal res_time : TIME_TYPE;
|
|
-- Signal used to pass Sequence Numbers from main to memory process
|
|
signal seq_nr : SEQUENCENUMBER_TYPE;
|
|
-- Signal used to pass the Request Sequence Number Bitmap from main to memory process
|
|
signal req_seq_nr_bitmap, req_seq_nr_bitmap_next : std_logic_vector(0 to WORD_WIDTH-1);
|
|
-- Signal used to iterate through Request Bitmaps
|
|
signal req_bitmap_pos, req_bitmap_pos_next : natural range 0 to req_seq_nr_bitmap'length-1;
|
|
-- Test signal used for testbench synchronisation
|
|
signal idle_sig : std_logic;
|
|
-- Signal used to pass Endpoint Pointers to the Endpoint Memory Process
|
|
signal mem_addr_update : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
|
|
|
|
-- *MEMORY PROCESS*
|
|
-- Memory FSM state
|
|
signal mem_stage, mem_stage_next : MEM_STAGE_TYPE;
|
|
-- Pointer to current relevant Endpoint Address
|
|
signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 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);
|
|
-- General Memory Address Latch
|
|
signal mem_addr_latch, mem_addr_latch_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 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);
|
|
-- General Purpose Couter
|
|
signal mem_cnt, mem_cnt_next : natural range 0 to 29;
|
|
-- Latch for Endpoint Data from Memory
|
|
signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE;
|
|
-- Latch for Endpoint Data from main process
|
|
signal mem_endpoint_latch_data, mem_endpoint_latch_data_next : ENDPOINT_LATCH_DATA_TYPE;
|
|
-- Position (In Endpoint Memory Frame Granularity) of current relevant Endpoint
|
|
signal mem_pos, mem_pos_next : natural range 0 to MAX_REMOTE_ENDPOINTS-1;
|
|
-- Endpoint Memory Flag Array denoting which mem_endpoint_data Fields are up-to-date with the respective fields of the Endpoint (Pointed by mem_addr_base)
|
|
signal current_emf, current_emf_next : std_logic_vector(0 to EMF_FLAG_WIDTH-1);
|
|
|
|
-- *MEMORY CONTROL CONNECTION SIGNALS*
|
|
signal mem_addr : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0);
|
|
signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0);
|
|
signal mem_ready_in, mem_valid_in : std_logic;
|
|
signal mem_ready_out, mem_valid_out : std_logic;
|
|
signal mem_read : std_logic;
|
|
signal abort_read : std_logic;
|
|
|
|
|
|
--*****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 SUBMESSAGE FLAGS
|
|
alias endian_flag : std_logic is rtps_flags(0);
|
|
alias final_flag : std_logic is rtps_flags(1);
|
|
alias liveliness_flag : std_logic is rtps_flags(2);
|
|
-- RTPS OUT DATA SUBMESSAGE FLAGS
|
|
alias qos_flag : std_logic is data_out_ro(17);
|
|
alias data_flag : std_logic is data_out_ro(18);
|
|
alias key_flag : std_logic is data_out_ro(19);
|
|
alias non_std_flag : std_logic is data_out_ro(20);
|
|
-- ACKNACK
|
|
alias nack_base : SEQUENCENUMBER_TYPE is sn_latch_1;
|
|
alias nack_base_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
|
|
alias new_global_ack : SEQUENCENUMBER_TYPE is sn_latch_2;
|
|
alias new_global_ack_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
|
|
alias ack_base : SEQUENCENUMBER_TYPE is sn_latch_3;
|
|
alias ack_base_next : SEQUENCENUMBER_TYPE is sn_latch_3_next;
|
|
-- MISC
|
|
alias next_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_1;
|
|
alias next_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_1_next;
|
|
alias min_sn : SEQUENCENUMBER_TYPE is sn_latch_2;
|
|
alias min_sn_next : SEQUENCENUMBER_TYPE is sn_latch_2_next;
|
|
alias max_sn : SEQUENCENUMBER_TYPE is sn_latch_3;
|
|
alias max_sn_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
|
|
);
|
|
|
|
-- *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_ACKNACK Store ACKNACK Heartbeat Sequence Numbers
|
|
-- PARSE_NACK_BITMAP Parse the bitmap containing the requested Sequence Numbers
|
|
-- PROCESS_NACK Process Requested (Negatively Acknowledged) Sequence Numbers
|
|
-- PROCESS_ACK Process Acknowledged Sequence Numbers. Assert Liveliness of remore Reader.
|
|
-- UPDATE_GLOBAL_ACK Iterate over all remote Readers and update the global_ack_seq_nr_base to the lowest common ACKed Sequence Number
|
|
-- ENDPOINT_STALE_CHECK Check remote Endpoint Entries for Liveliness Lease Expiration, and Response Timeouts.
|
|
-- GET_MIN_SN Get the lowest available Sequence Number from the History Cache
|
|
-- GET_MAX_SN Get the highest available Sequence Number from the History Cache
|
|
-- HANDLE_REQUESTS Send requested Cache Changes to remote Reader
|
|
-- HANDLE_HEARTBEATS Send Heartbeat to all remote Readers
|
|
-- HANDLE_NEW Send new Cache Change to all remote Readers
|
|
-- HANDLE_HISTORICAL Send all available Cache Changes to remote Endpoint
|
|
-- SEND_HEADER Send Output Data Header and RTPS Message Header
|
|
-- SEND_INFO_TS Send INFO_TS Submessage
|
|
-- SEND_DATA_A Send DATA Submessage Part 1
|
|
-- SEND_INLINE_QOS Send DATA Submessage in-line QoS
|
|
-- SEND_DATA_B Send DATA Submessage Part 2
|
|
-- SEND_GAP_A Send GAP Submessage Part 1
|
|
-- SEND_GAP_B Send GAP Submessage Part 2
|
|
-- SEND_HEARTBEAT Send HEARTBEAT Submessage
|
|
-- SKIP_PACKET Skip rest of Packet
|
|
-- SKIP_META_OPERATION Skip Metatraffic Operation
|
|
parse_prc : process(all)
|
|
variable tmp_dw : DOUBLE_WORD_ARRAY;
|
|
-- 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);
|
|
variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1);
|
|
begin
|
|
-- DEFAULT Registered
|
|
stage_next <= stage;
|
|
meta_opcode_next <= meta_opcode;
|
|
cnt_next <= cnt;
|
|
cnt2_next <= cnt2;
|
|
cnt3_next <= cnt3;
|
|
guid_next <= guid;
|
|
addr_next <= addr;
|
|
portn_next <= portn;
|
|
is_meta_next <= is_meta;
|
|
opcode_next <= opcode;
|
|
rtps_flags_next <= rtps_flags;
|
|
reader_flags_next <= reader_flags;
|
|
sn_latch_1_next <= sn_latch_1;
|
|
sn_latch_2_next <= sn_latch_2;
|
|
sn_latch_3_next <= sn_latch_3;
|
|
nack_bitmap_pos_next <= nack_bitmap_pos;
|
|
req_bitmap_pos_next <= req_bitmap_pos;
|
|
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;
|
|
long_latch_next <= long_latch;
|
|
global_ack_seq_nr_base_next <= global_ack_seq_nr_base;
|
|
req_seq_nr_bitmap_next <= req_seq_nr_bitmap;
|
|
gap_in_progress_next <= gap_in_progress;
|
|
heartbeat_time_next <= heartbeat_time;
|
|
last_seq_nr_next <= last_seq_nr;
|
|
new_push_next <= new_push;
|
|
historical_push_next <= historical_push;
|
|
assert_liveliness_latch_next<= assert_liveliness_latch;
|
|
bitmap_cnt_next <= bitmap_cnt;
|
|
bitmap_latch_next <= bitmap_latch;
|
|
gap_is_last_next <= gap_is_last;
|
|
return_cnt_next <= return_cnt;
|
|
-- DEFAULT Unregistered
|
|
mem_opcode <= NOP;
|
|
opcode_hc <= NOP;
|
|
lease_deadline <= TIME_INVALID;
|
|
res_time <= TIME_INVALID;
|
|
alive_sig <= '0';
|
|
rd_meta <= '0';
|
|
rd_user <= '0';
|
|
wr_ro <= '0';
|
|
last_word_out_ro <= '0';
|
|
mem_op_start <= '0';
|
|
start_hc <= '0';
|
|
ready_in_hc <= '0';
|
|
get_data_hc <= '0';
|
|
idle_sig <= '0';
|
|
seq_nr <= SEQUENCENUMBER_UNKNOWN;
|
|
seq_nr_hc <= SEQUENCENUMBER_UNKNOWN;
|
|
mem_field_flags <= (others => '0');
|
|
data_out_ro <= (others => '0');
|
|
mem_addr_update <= (others => '0');
|
|
|
|
-- Assert Liveliness Latch Setter
|
|
if (liveliness_assertion = '1') then
|
|
assert_liveliness_latch_next <= '1';
|
|
end if;
|
|
|
|
-- 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
|
|
addr_next <= (others => '0');
|
|
portn_next <= (others => '0');
|
|
is_meta_next <= '0';
|
|
|
|
-- New Cache Change in HC
|
|
if (data_available = '1') then
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_MAX_SN;
|
|
|
|
if (ack_hc = '1') then
|
|
-- Propagate Liveliness
|
|
alive_sig <= '1';
|
|
|
|
new_push_next <= '1';
|
|
|
|
stage_next <= GET_MAX_SN;
|
|
cnt_next <= 0;
|
|
end if;
|
|
-- Manual Liveliness Assertion
|
|
elsif (LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS and assert_liveliness_latch = '1') then
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_MIN_SN;
|
|
|
|
if (ack_hc = '1') then
|
|
-- Propagate Liveliness
|
|
alive_sig <= '1';
|
|
|
|
-- Reset
|
|
heartbeat_time_next <= time + HEARTBEAT_PERIOD;
|
|
|
|
-- Increment Heartbeat Count
|
|
count_next <= count + 1;
|
|
|
|
stage_next <= GET_MIN_SN;
|
|
cnt_next <= 0;
|
|
end if;
|
|
-- Heartbeat Timeout
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and time >= heartbeat_time) then
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_MIN_SN;
|
|
|
|
if (ack_hc = '1') then
|
|
-- Reset
|
|
heartbeat_time_next <= time + HEARTBEAT_PERIOD;
|
|
|
|
-- Increment Heartbeat Count
|
|
count_next <= count + 1;
|
|
|
|
stage_next <= GET_MIN_SN;
|
|
cnt_next <= 0;
|
|
end if;
|
|
-- Stale Check Timeout
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and 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 EMO_ENDPOINT_MATCH =>
|
|
stage_next <= LATCH_GUIDPREFIX;
|
|
cnt_next <= 0;
|
|
when EMO_ENDPOINT_UNMATCH =>
|
|
stage_next <= LATCH_GUIDPREFIX;
|
|
cnt_next <= 0;
|
|
when EMO_PARTICIPANT_UNMATCH =>
|
|
stage_next <= LATCH_GUIDPREFIX;
|
|
cnt_next <= 0;
|
|
when others =>
|
|
stage_next <= SKIP_META_OPERATION;
|
|
end case;
|
|
-- Input FIFO Guard
|
|
elsif (empty_user = '0') then
|
|
rd_user <= '1';
|
|
|
|
-- Latch Opcode
|
|
opcode_next <= header_opcode;
|
|
-- Latch Flags
|
|
rtps_flags_next <= header_flags;
|
|
-- Latch Source UDP Port
|
|
portn_next <= header_udp_port;
|
|
|
|
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
stage_next <= LATCH_SRC_ADDR;
|
|
-- SANITY CHECK: Skip Packet if non-standard Payload
|
|
if(header_opcode = SID_DATA and non_std_flag = '1') then
|
|
stage_next <= SKIP_PACKET;
|
|
end if;
|
|
else
|
|
-- NOTE: We receive only User Traffic when RELIABLE
|
|
-- Ignore
|
|
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_user <= '1';
|
|
end if;
|
|
|
|
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;
|
|
cnt_next <= cnt + 1;
|
|
-- 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;
|
|
cnt_next <= cnt + 1;
|
|
-- 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 = EMO_PARTICIPANT_UNMATCH or meta_opcode = EMO_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 /= EMO_ENDPOINT_UNMATCH or (meta_opcode = EMO_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_user <= '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 EMO_ENDPOINT_MATCH =>
|
|
mem_op_start <= '1';
|
|
mem_opcode <= SEARCH_ENDPOINT;
|
|
mem_field_flags <= (others => '0');
|
|
stage_next <= LATCH_ENDPOINT_DATA;
|
|
cnt_next <= 0;
|
|
when EMO_ENDPOINT_UNMATCH =>
|
|
mem_op_start <= '1';
|
|
mem_opcode <= SEARCH_ENDPOINT;
|
|
mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG;
|
|
stage_next <= METATRAFFIC_OPERATION;
|
|
when EMO_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 others =>
|
|
null;
|
|
end case;
|
|
else
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
case (opcode) is
|
|
when SID_ACKNACK =>
|
|
stage_next <= LATCH_ACKNACK;
|
|
cnt_next <= 0;
|
|
mem_op_start <= '1';
|
|
mem_opcode <= SEARCH_ENDPOINT;
|
|
mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG or EMF_RES_TIME_FLAG;
|
|
when others =>
|
|
stage_next <= SKIP_PACKET;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
when LATCH_ENDPOINT_DATA =>
|
|
-- Input FIFO Guard
|
|
if (empty_meta = '0') then
|
|
rd_meta <= '1';
|
|
|
|
case (cnt) is
|
|
-- IPv4 Address
|
|
when 0 =>
|
|
addr_next <= data_in_meta;
|
|
cnt_next <= cnt + 1;
|
|
-- 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);
|
|
reader_flags_next <= data_in_meta(reader_flags'length-1 downto 0);
|
|
|
|
stage_next <= METATRAFFIC_OPERATION;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when METATRAFFIC_OPERATION =>
|
|
-- Memory Operation Guard
|
|
if (mem_op_done = '1') then
|
|
case (meta_opcode) is
|
|
when EMO_ENDPOINT_MATCH =>
|
|
-- Endpoint already in Memory
|
|
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) 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;
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
else
|
|
-- Insert Matched Remote Endpoint
|
|
mem_op_start <= '1';
|
|
mem_opcode <= INSERT_ENDPOINT;
|
|
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and LEASE_DURATION /= DURATION_INFINITE and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') 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;
|
|
-- Initialize ACK Sequence Number
|
|
if (reader_flags(READER_IS_BEST_EFFORT_FLAG) = '1') then
|
|
seq_nr <= SEQUENCENUMBER_UNKNOWN;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then
|
|
seq_nr <= (others => (others => '0'));
|
|
else
|
|
seq_nr <= global_ack_seq_nr_base;
|
|
end if;
|
|
|
|
-- Reader needs Historical Data
|
|
if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and reader_flags(READER_EXPECTS_HISTORICAL_DATA_FLAG) = '1') then
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_MIN_SN;
|
|
|
|
if (ack_hc = '1') then
|
|
-- Send Historical Data
|
|
historical_push_next <= '1';
|
|
|
|
stage_next <= GET_MIN_SN;
|
|
cnt_next <= 0;
|
|
end if;
|
|
else
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
when EMO_ENDPOINT_UNMATCH =>
|
|
assert check_mask(current_emf, EMF_ACK_SEQ_NR_BASE_FLAG) severity FAILURE;
|
|
|
|
-- Endpoint not in Memory
|
|
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
-- Ignore
|
|
stage_next <= IDLE;
|
|
else
|
|
-- Remove Unmatched Remote Endpoint
|
|
mem_op_start <= '1';
|
|
mem_opcode <= REMOVE_ENDPOINT;
|
|
|
|
-- Global ACK SN possibly changed
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN and global_ack_seq_nr_base = mem_endpoint_data.ack_seq_nr_base) then
|
|
-- Update Global ACK
|
|
stage_next <= UPDATE_GLOBAL_ACK;
|
|
cnt_next <= 0;
|
|
else
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
when EMO_PARTICIPANT_UNMATCH =>
|
|
case (cnt) is
|
|
when 0 =>
|
|
assert check_mask(current_emf, EMF_GUIDPREFIX_FLAG) severity FAILURE;
|
|
|
|
-- Reached End of Endpoints
|
|
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
-- Global ACK SN possibly changed
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN) then
|
|
-- NOTE: We are triggering a Global ACK SN Update on each Participant Removal. This should not happen as often, and is therefore acceptable.
|
|
-- Otherwise we need to check the ack_seq_nr_base in the other substate and mark when equal to current Global ACK SN.
|
|
-- Update Global ACK
|
|
stage_next <= UPDATE_GLOBAL_ACK;
|
|
cnt_next <= 0;
|
|
else
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
end if;
|
|
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
|
|
-- Remove Unmatched Remote Endpoint
|
|
mem_op_start <= '1';
|
|
mem_opcode <= REMOVE_ENDPOINT;
|
|
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;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when LATCH_SRC_ADDR =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Input FIFO Guard
|
|
if (empty_user = '0') then
|
|
rd_user <= '1';
|
|
|
|
-- Latch Source IP Address
|
|
addr_next <= data_in_user;
|
|
|
|
stage_next <= LATCH_GUIDPREFIX;
|
|
cnt_next <= 0;
|
|
end if;
|
|
end if;
|
|
when LATCH_ACKNACK =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Input FIFO Guard
|
|
if (empty_user = '0') then
|
|
case (cnt) is
|
|
-- ReaderSNState.Base 1/2
|
|
when 0 =>
|
|
nack_base_next(0) <= unsigned(data_in_user);
|
|
rd_user <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- ReaderSNState.Base 2/2
|
|
when 1 =>
|
|
nack_base_next(1) <= unsigned(data_in_user);
|
|
rd_user <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- ReaderSNState.NumBits
|
|
when 2 =>
|
|
ack_base_next <= nack_base - 1;
|
|
long_latch_next <= data_in_user;
|
|
bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
|
|
rd_user <= '1';
|
|
cnt_next <= cnt + 1;
|
|
cnt2_next <= 0;
|
|
-- ReaderSNState.Bitmap
|
|
when 3 =>
|
|
-- Read Bitmap
|
|
if (cnt2 < bitmap_cnt) then
|
|
cnt2_next <= cnt2 + 1;
|
|
|
|
bitmap_latch_next(cnt2) <= data_in_user;
|
|
rd_user <= '1';
|
|
|
|
else
|
|
-- NACK Bitmap is not Empty
|
|
if (long_latch /= (long_latch'reverse_range => '0')) then
|
|
nack_bitmap_pos_next <= 0;
|
|
stage_next <= PARSE_NACK_BITMAP;
|
|
cnt_next <= 0;
|
|
else
|
|
stage_next <= PROCESS_ACK;
|
|
end if;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when PARSE_NACK_BITMAP =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
tmp_bitmap := to_slv_bitmap(bitmap_latch);
|
|
|
|
-- NOTE: nack_bitmap_pos is used for the NACK Bitmap, and cnt is used for the Request Bitmap.
|
|
|
|
case (cnt) is
|
|
-- Find Beginning
|
|
when 0 =>
|
|
-- First Requested Sequence Number
|
|
if (tmp_bitmap(nack_bitmap_pos) = '1') then
|
|
req_seq_nr_bitmap_next <= (others => '0');
|
|
req_bitmap_pos_next <= 0;
|
|
cnt_next <= cnt + 1;
|
|
else
|
|
nack_bitmap_pos_next <= nack_bitmap_pos + 1;
|
|
nack_base_next <= nack_base + 1;
|
|
end if;
|
|
-- Parse Rest
|
|
when 1 =>
|
|
-- Next Requested Sequence Number
|
|
if (tmp_bitmap(nack_bitmap_pos) = '1') then
|
|
req_seq_nr_bitmap_next(req_bitmap_pos) <= '1';
|
|
end if;
|
|
|
|
-- End of Bitmap
|
|
if (nack_bitmap_pos = unsigned(long_latch) or req_bitmap_pos = req_seq_nr_bitmap'length-1) then
|
|
stage_next <= PROCESS_NACK;
|
|
else
|
|
nack_bitmap_pos_next <= nack_bitmap_pos + 1;
|
|
req_bitmap_pos_next <= req_bitmap_pos + 1;
|
|
end if;
|
|
-- Find Requested
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when PROCESS_NACK =>
|
|
-- Precondition: mem_endpoint_data set (EMF_RES_TIME_FLAG)
|
|
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Wait for Endpoint Data
|
|
if (mem_op_done = '1') then
|
|
assert check_mask(current_emf, EMF_RES_TIME_FLAG) severity FAILURE;
|
|
|
|
-- Known Remote Endpoint
|
|
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
|
|
-- Liveliness Assertion
|
|
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;
|
|
|
|
-- No Pending Response
|
|
if (mem_endpoint_data.res_time = TIME_INVALID) then
|
|
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG;
|
|
seq_nr <= nack_base;
|
|
if (ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then
|
|
res_time <= time + ACKNACK_RESPONSE_DELAY;
|
|
-- NOTE: Last Bit denotes if this is Response or Suppression Delay
|
|
res_time(1)(0) <= '0';
|
|
|
|
-- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock)
|
|
-- Update Check Time
|
|
if ((time + ACKNACK_RESPONSE_DELAY) < check_time) then
|
|
check_time_next <= time + ACKNACK_RESPONSE_DELAY;
|
|
end if;
|
|
else
|
|
res_time <= TIME_INVALID;
|
|
end if;
|
|
-- Currently in Acknack Response Delay
|
|
elsif (mem_endpoint_data.res_time(1)(0) = '0') then
|
|
mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG;
|
|
seq_nr <= nack_base;
|
|
end if;
|
|
|
|
stage_next <= PROCESS_ACK;
|
|
else
|
|
-- Skip
|
|
stage_next <= SKIP_PACKET;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
when PROCESS_ACK =>
|
|
-- Precondition: mem_endpoint_data set (EMF_ACK_SEQ_NR_BASE_FLAG)
|
|
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Wait for Endpoint Search
|
|
if (mem_op_done = '1') then
|
|
assert check_mask(current_emf, EMF_ACK_SEQ_NR_BASE_FLAG) severity FAILURE;
|
|
|
|
-- DEFAULT
|
|
stage_next <= SKIP_PACKET;
|
|
|
|
-- Known Remote Endpoint
|
|
if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
-- New Sequence Numbers are ACKed
|
|
if (ack_base > mem_endpoint_data.ack_seq_nr_base) then
|
|
-- Update ACK Sequence Number Base
|
|
mem_op_start <= '1';
|
|
mem_opcode <= UPDATE_ENDPOINT;
|
|
mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG;
|
|
seq_nr <= ack_base;
|
|
-- NOTE: The global_ack_seq_nr_base contains the lowest SN of all remote Endpoints.
|
|
-- It only needs to be updated, if the remote Endpoint with the lowest ACKed SN is updated.
|
|
-- This does not necesserily mean, that the Global ACK SN will change, as there can
|
|
-- be multiple remote Endpoints with the same lowest ACK SN.
|
|
-- Global ACK SN needs updating
|
|
if (mem_endpoint_data.ack_seq_nr_base = global_ack_seq_nr_base) then
|
|
stage_next <= UPDATE_GLOBAL_ACK;
|
|
cnt_next <= 0;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
when UPDATE_GLOBAL_ACK =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Memory Operation Guard
|
|
if (mem_op_done = '1') then
|
|
case (cnt) is
|
|
-- Initiate Search
|
|
when 0 =>
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_FIRST_ENDPOINT;
|
|
mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG;
|
|
cnt_next <= 1;
|
|
new_global_ack_next <= SEQUENCENUMBER_UNKNOWN;
|
|
-- Find new global_ack_seq_nr_base
|
|
when 1 =>
|
|
assert check_mask(current_emf, EMF_ACK_SEQ_NR_BASE_FLAG) severity FAILURE;
|
|
|
|
-- End of Endpoints
|
|
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
-- New SNs have been ACKed by ALL remote Endpoints
|
|
if (new_global_ack /= global_ack_seq_nr_base) then
|
|
-- Mark common ACKed SNs
|
|
global_ack_seq_nr_base_next <= global_ack_seq_nr_base + 1;
|
|
cnt_next <= cnt + 1;
|
|
else
|
|
-- DONE
|
|
if (is_meta = '0') then
|
|
stage_next <= SKIP_PACKET;
|
|
else
|
|
stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
else
|
|
-- NOTE: Remote Endpoints with RELIABILITY BEST_EFFORT have a ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN, since
|
|
-- they cannot send ACKNACKs.
|
|
-- XXX: Assumes SEQUENCENUMBER_UNKNOWN is higher than all valid Sequence Numbers.
|
|
-- Mark lowest common ACKed SN
|
|
if (mem_endpoint_data.ack_seq_nr_base < new_global_ack) then
|
|
new_global_ack_next <= mem_endpoint_data.ack_seq_nr_base;
|
|
end if;
|
|
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_NEXT_ENDPOINT;
|
|
mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG;
|
|
end if;
|
|
-- ACK Sequence Numbers
|
|
when 2 =>
|
|
if (DURABILITY_QOS = VOLATILE_DURABILITY_QOS) then
|
|
start_hc <= '1';
|
|
opcode_hc <= REMOVE_CACHE_CHANGE;
|
|
seq_nr_hc <= global_ack_seq_nr_base;
|
|
else
|
|
start_hc <= '1';
|
|
opcode_hc <= ACK_CACHE_CHANGE;
|
|
seq_nr_hc <= global_ack_seq_nr_base;
|
|
end if;
|
|
|
|
-- Wait for Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
-- Exit Condition
|
|
if (global_ack_seq_nr_base = new_global_ack) then
|
|
-- DONE
|
|
if (is_meta = '0') then
|
|
stage_next <= SKIP_PACKET;
|
|
else
|
|
stage_next <= IDLE;
|
|
end if;
|
|
else
|
|
global_ack_seq_nr_base_next <= global_ack_seq_nr_base + 1;
|
|
end if;
|
|
end if;
|
|
when others =>
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when ENDPOINT_STALE_CHECK =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- 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 =>
|
|
assert check_mask(current_emf, EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG) severity FAILURE;
|
|
|
|
-- 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
|
|
-- Remove Participant
|
|
mem_op_start <= '1';
|
|
mem_opcode <= REMOVE_ENDPOINT;
|
|
-- Continue Search
|
|
cnt_next <= 0;
|
|
-- Synthesis Guard/Response Time Reached
|
|
elsif (RELIABILITY_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_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG;
|
|
mem_addr_update <= mem_addr_base;
|
|
|
|
-- Send Requests
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 4;
|
|
end if;
|
|
|
|
-- Update Check Time
|
|
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;
|
|
else
|
|
-- Update Check Time
|
|
if (RELIABILITY_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;
|
|
elsif (mem_endpoint_data.lease_deadline /= TIME_INVALID) then
|
|
if (mem_endpoint_data.lease_deadline < check_time) then
|
|
check_time_next <= mem_endpoint_data.lease_deadline;
|
|
end if;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID) then
|
|
if (mem_endpoint_data.res_time < check_time) then
|
|
check_time_next <= mem_endpoint_data.res_time;
|
|
end if;
|
|
end if;
|
|
|
|
-- Continue Search
|
|
cnt_next <= 0;
|
|
end if;
|
|
end if;
|
|
when 2 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_op_start <= '1';
|
|
mem_opcode <= UPDATE_ENDPOINT;
|
|
mem_field_flags <= EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG or EMF_RES_TIME_FLAG;
|
|
|
|
-- Reset Requests
|
|
req_seq_nr_bitmap_next <= (others => '0');
|
|
seq_nr <= SEQUENCENUMBER_UNKNOWN;
|
|
-- Set Acknack Suppression Time
|
|
if (ACKNACK_SUPPRESSION_DELAY /= DURATION_INFINITE and ACKNACK_SUPPRESSION_DELAY /= DURATION_ZERO) then
|
|
tmp_dw := time + ACKNACK_SUPPRESSION_DELAY;
|
|
-- Set Acknack Suppression Time
|
|
res_time <= tmp_dw;
|
|
-- 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 (tmp_dw < check_time) then
|
|
check_time_next <= tmp_dw;
|
|
end if;
|
|
else
|
|
-- Disable Suppression
|
|
res_time <= TIME_INVALID;
|
|
end if;
|
|
|
|
cnt_next <= 0;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when GET_MIN_SN =>
|
|
-- Wait for HC
|
|
if (done_hc = '1') then
|
|
assert (ret_hc = OK) severity FAILURE;
|
|
|
|
min_sn_next <= cc_seq_nr;
|
|
|
|
if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 4; -- Pre-Check Sub-state
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then
|
|
stage_next <= HANDLE_HEARTBEATS;
|
|
cnt_next <= 0;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
when GET_MAX_SN =>
|
|
-- Wait for HC
|
|
if (done_hc = '1') then
|
|
assert (ret_hc = OK) severity FAILURE;
|
|
|
|
max_sn_next <= cc_seq_nr;
|
|
|
|
-- EXIT
|
|
if (new_push = '1') then
|
|
-- NOTE: If PUSH_MODE = FALSE, we manually update the last_seq_nr signal, since this is
|
|
-- not done anymore.
|
|
|
|
-- Synthesis Guard
|
|
if (PUSH_MODE) then
|
|
stage_next <= HANDLE_NEW;
|
|
cnt_next <= 0;
|
|
else
|
|
-- New higher Sequence Number Available
|
|
if (cc_seq_nr /= SEQUENCENUMBER_UNKNOWN and cc_seq_nr > last_seq_nr) then
|
|
last_seq_nr_next <= cc_seq_nr;
|
|
end if;
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
end if;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
when HANDLE_REQUESTS =>
|
|
-- Precondition: mem_endpoint_data set (EMF_REQ_SEQ_NR_BASE_FLAG, EMF_REQ_SEQ_NR_BITMAP_FLAG)
|
|
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
-- Wait for Endpoint Data
|
|
if (mem_op_done = '1') then
|
|
assert check_mask(current_emf, EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG) severity FAILURE;
|
|
|
|
case (cnt) is
|
|
-- Next Bitmap Pos
|
|
when 0 =>
|
|
req_bitmap_pos_next <= req_bitmap_pos + 1;
|
|
next_seq_nr_next <= next_seq_nr + 1;
|
|
cnt_next <= cnt + 1;
|
|
-- Find SN
|
|
when 1 =>
|
|
-- End of Bitmap or Requested SN is above last Written
|
|
if (req_bitmap_pos = req_seq_nr_bitmap'length-1 or next_seq_nr > last_seq_nr) then
|
|
if (gap_in_progress = '1') then
|
|
-- NOTE: We close the GAP, than come back here, and exit through the else branch.
|
|
-- Close GAP Message
|
|
gap_in_progress_next <= '0';
|
|
stage_next <= SEND_GAP_B;
|
|
cnt_next <= 0;
|
|
-- DONE
|
|
return_stage_next <= ENDPOINT_STALE_CHECK;
|
|
return_cnt_next <= 2;
|
|
gap_is_last_next <= '1';
|
|
else
|
|
-- DONE
|
|
stage_next <= ENDPOINT_STALE_CHECK;
|
|
cnt_next <= 2;
|
|
end if;
|
|
-- Next Requested SN found
|
|
elsif (mem_endpoint_data.req_seq_nr_bitmap(req_bitmap_pos) = '1') then
|
|
cnt_next <= cnt + 1;
|
|
elsif (gap_in_progress = '1') then
|
|
-- Close GAP Message
|
|
gap_in_progress_next <= '0';
|
|
stage_next <= SEND_GAP_B;
|
|
cnt_next <= 0;
|
|
-- Continue
|
|
return_stage_next <= HANDLE_REQUESTS;
|
|
return_cnt_next <= 0;
|
|
gap_is_last_next <= '1';
|
|
else
|
|
req_bitmap_pos_next <= req_bitmap_pos + 1;
|
|
next_seq_nr_next <= next_seq_nr + 1;
|
|
end if;
|
|
-- Get SN
|
|
when 2 =>
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_CACHE_CHANGE;
|
|
seq_nr_hc <= next_seq_nr;
|
|
|
|
-- Wait until Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Handle Request
|
|
when 3 =>
|
|
-- Wait until Operation Response
|
|
if (done_hc = '1') then
|
|
-- Wait for Operation Response
|
|
if (ret_hc = OK) then
|
|
-- Only request Payload if necessary (Contains DATA or Serialized Key)
|
|
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
get_data_hc <= '1';
|
|
end if;
|
|
|
|
if (gap_in_progress = '1') then
|
|
-- Close GAP and send DATA
|
|
gap_in_progress_next <= '0';
|
|
stage_next <= SEND_GAP_B;
|
|
cnt_next <= 0;
|
|
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
|
|
return_stage_next <= SEND_INFO_TS;
|
|
else
|
|
return_stage_next <= SEND_DATA_A;
|
|
end if;
|
|
return_cnt_next <= 0;
|
|
else
|
|
-- Send DATA
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
|
|
return_stage_next <= SEND_INFO_TS;
|
|
else
|
|
return_stage_next <= SEND_DATA_A;
|
|
end if;
|
|
return_cnt_next <= 0;
|
|
end if;
|
|
elsif (ret_hc = INVALID) then
|
|
if (gap_in_progress = '0') then
|
|
-- Open new GAP
|
|
gap_in_progress_next <= '1';
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
return_stage_next <= SEND_GAP_A;
|
|
return_cnt_next <= 0;
|
|
else
|
|
-- Continue
|
|
req_bitmap_pos_next <= req_bitmap_pos + 1;
|
|
next_seq_nr_next <= next_seq_nr + 1;
|
|
cnt_next <= 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- Initialize
|
|
when 4 =>
|
|
next_seq_nr_next <= mem_endpoint_data.req_seq_nr_base;
|
|
req_bitmap_pos_next <= 0;
|
|
cnt_next <= 1;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when HANDLE_HEARTBEATS =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then
|
|
-- Memory Operation Guard
|
|
if (mem_op_done = '1') then
|
|
case (cnt) is
|
|
-- Get FIRST Destination
|
|
when 0 =>
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_FIRST_ENDPOINT;
|
|
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
|
|
cnt_next <= cnt + 2;
|
|
|
|
-- HC Empty (No cache Changes Available)
|
|
if (min_sn = SEQUENCENUMBER_UNKNOWN) then
|
|
-- NOTE: Identifies the lowest SN that is yet to be written by the writter.
|
|
min_sn_next <= last_seq_nr + 1;
|
|
end if;
|
|
-- Get NEXT Destination
|
|
when 1 =>
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_NEXT_ENDPOINT;
|
|
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
|
|
cnt_next <= cnt + 1;
|
|
-- Initiate Heartbeat Sending
|
|
when 2 =>
|
|
-- End of Endpoint
|
|
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
-- Assert Liveliness Resetter
|
|
assert_liveliness_latch_next <= '0';
|
|
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
else
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
return_stage_next <= SEND_HEARTBEAT;
|
|
return_cnt_next <= 0;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when HANDLE_NEW =>
|
|
-- Synthesis Guard
|
|
if (PUSH_MODE) then
|
|
case (cnt) is
|
|
-- Next SN
|
|
when 0 =>
|
|
-- No New Cache Changes
|
|
if (max_sn = last_seq_nr) then
|
|
-- DONE
|
|
new_push_next <= '0';
|
|
stage_next <= IDLE;
|
|
else
|
|
last_seq_nr_next <= last_seq_nr + 1;
|
|
next_seq_nr_next <= last_seq_nr + 1;
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Get First Reader
|
|
when 1 =>
|
|
-- Memory Operation Guard
|
|
if (mem_op_done = '1') then
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_FIRST_ENDPOINT;
|
|
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- GET SN
|
|
when 2 =>
|
|
-- Wait for Endpoint Data
|
|
if (mem_op_done = '1') then
|
|
-- End of Endpoints
|
|
if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then
|
|
|
|
-- ACK newly sent Cache Changes if Writer is BEST_EFFORT, or if all remore Readers are BEST_EFFORT
|
|
if (RELIABILITY_QOS /= RELIABLE_RELIABILITY_QOS or global_ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN) then
|
|
start_hc <= '1';
|
|
if (DURABILITY_QOS = VOLATILE_DURABILITY_QOS) then
|
|
opcode_hc <= REMOVE_CACHE_CHANGE;
|
|
else
|
|
opcode_hc <= ACK_CACHE_CHANGE;
|
|
end if;
|
|
seq_nr_hc <= last_seq_nr;
|
|
|
|
-- NOTE: Ignore return Code
|
|
|
|
-- Wait until Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
-- EXIT
|
|
cnt_next <= 0;
|
|
end if;
|
|
else
|
|
-- EXIT
|
|
cnt_next <= 0;
|
|
end if;
|
|
else
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_CACHE_CHANGE;
|
|
seq_nr_hc <= last_seq_nr;
|
|
|
|
-- Wait until Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ SN
|
|
when 3 =>
|
|
-- Wait until Operation Response
|
|
if (done_hc = '1') then
|
|
-- Cache Change Available
|
|
if (ret_hc = OK) then
|
|
-- Only request Payload if necessary (Contains DATA or Serialized Key)
|
|
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
get_data_hc <= '1';
|
|
end if;
|
|
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
|
|
return_stage_next <= SEND_INFO_TS;
|
|
else
|
|
return_stage_next <= SEND_DATA_A;
|
|
end if;
|
|
return_cnt_next <= 0;
|
|
-- Cache Change Unavailable
|
|
else
|
|
report "New Cache Change unavailable" severity WARNING;
|
|
cnt_next <= 0;
|
|
end if;
|
|
end if;
|
|
-- Get Next Reader
|
|
when 4 =>
|
|
-- Memory Operation Guard
|
|
if (mem_op_done = '1') then
|
|
mem_op_start <= '1';
|
|
mem_opcode <= GET_NEXT_ENDPOINT;
|
|
mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG;
|
|
-- Loop
|
|
cnt_next <= 2;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when HANDLE_HISTORICAL =>
|
|
-- Synthesis Guard
|
|
if (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS) then
|
|
case (cnt) is
|
|
-- Next SN
|
|
when 0 =>
|
|
-- End of Historical Data
|
|
if (next_seq_nr = last_seq_nr) then
|
|
if (gap_in_progress) then
|
|
-- NOTE: We close the GAP, than come back here, and exit through the else branch.
|
|
-- Close GAP Message
|
|
gap_in_progress_next <= '0';
|
|
stage_next <= SEND_GAP_B;
|
|
cnt_next <= 0;
|
|
gap_is_last_next <= '1';
|
|
-- DONE
|
|
return_stage_next <= IDLE;
|
|
return_cnt_next <= 0;
|
|
|
|
-- Reset
|
|
historical_push_next <= '0';
|
|
else
|
|
-- Reset
|
|
historical_push_next <= '0';
|
|
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
end if;
|
|
else
|
|
next_seq_nr_next <= next_seq_nr + 1;
|
|
-- If remote Reader is RELIABLE, NACK the SN
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') then
|
|
cnt_next <= cnt + 1;
|
|
else
|
|
cnt_next <= cnt + 2;
|
|
end if;
|
|
end if;
|
|
-- NACK SN
|
|
when 1 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
start_hc <= '1';
|
|
opcode_hc <= NACK_CACHE_CHANGE;
|
|
seq_nr_hc <= next_seq_nr;
|
|
-- NOTE: Ignore Return Code
|
|
|
|
-- Update Global ACK
|
|
if (next_seq_nr <= global_ack_seq_nr_base) then
|
|
global_ack_seq_nr_base_next <= next_seq_nr - 1;
|
|
end if;
|
|
|
|
-- Wait until Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Get SN
|
|
when 2 =>
|
|
start_hc <= '1';
|
|
opcode_hc <= GET_CACHE_CHANGE;
|
|
seq_nr_hc <= next_seq_nr;
|
|
|
|
-- Wait until Operation Acknowledgement
|
|
if (ack_hc = '1') then
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Handle Request
|
|
when 3 =>
|
|
-- Wait until Operation Response
|
|
if (done_hc = '1') then
|
|
-- Wait for Operation Response
|
|
if (ret_hc = OK) then
|
|
-- Only request Payload if necessary (Contains DATA or Serialized Key)
|
|
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
get_data_hc <= '1';
|
|
end if;
|
|
|
|
if (gap_in_progress = '1') then
|
|
-- Close GAP and send DATA
|
|
gap_in_progress_next <= '0';
|
|
stage_next <= SEND_GAP_B;
|
|
cnt_next <= 0;
|
|
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
|
|
return_stage_next <= SEND_INFO_TS;
|
|
else
|
|
return_stage_next <= SEND_DATA_A;
|
|
end if;
|
|
return_cnt_next <= 0;
|
|
else
|
|
-- Send DATA
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
if (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) then
|
|
return_stage_next <= SEND_INFO_TS;
|
|
else
|
|
return_stage_next <= SEND_DATA_A;
|
|
end if;
|
|
return_cnt_next <= 0;
|
|
end if;
|
|
elsif (ret_hc = INVALID) then
|
|
if (gap_in_progress = '0') then
|
|
-- Open new GAP
|
|
gap_in_progress_next <= '1';
|
|
stage_next <= SEND_HEADER;
|
|
cnt_next <= 0;
|
|
return_stage_next <= SEND_GAP_A;
|
|
return_cnt_next <= 0;
|
|
else
|
|
-- Continue
|
|
cnt_next <= 0;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- Pre-Check
|
|
when 4 =>
|
|
-- No Cache Changes Available
|
|
if (min_sn = SEQUENCENUMBER_UNKNOWN) then
|
|
-- Reset
|
|
historical_push_next <= '0';
|
|
|
|
-- DONE
|
|
stage_next <= IDLE;
|
|
else
|
|
next_seq_nr_next <= min_sn;
|
|
cnt_next <= cnt + 2; -- Skip Increment
|
|
-- If remote Reader is RELIABLE, NACK the SN
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(READER_IS_BEST_EFFORT_FLAG) = '0') then
|
|
cnt_next <= 1;
|
|
else
|
|
cnt_next <= 2;
|
|
end if;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when SEND_HEADER =>
|
|
-- Precondition: mem_endpoint_data set (EMF_IPV4_ADDR_FLAG, EMF_UDP_PORT_FLAG)
|
|
|
|
-- Wait for Endpoint Data
|
|
if (mem_op_done = '1') then
|
|
assert check_mask(current_emf, EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG) severity FAILURE;
|
|
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
wr_ro <= '1';
|
|
|
|
case (cnt) is
|
|
-- OUTPUT HEADER
|
|
-- Src IPv4 Address
|
|
when 0 =>
|
|
data_out_ro <= DEFAULT_IPv4_ADDRESS;
|
|
cnt_next <= cnt + 1;
|
|
-- Dest IPv4 Address
|
|
when 1 =>
|
|
data_out_ro <= mem_endpoint_data.addr;
|
|
cnt_next <= cnt + 1;
|
|
-- Src and Dest UDPv4 Ports
|
|
when 2 =>
|
|
data_out_ro <= USER_IPv4_UNICAST_PORT & mem_endpoint_data.portn;
|
|
cnt_next <= cnt + 1;
|
|
-- RTPS MESSAGE HEADER
|
|
when 3 =>
|
|
data_out_ro <= PROTOCOL_RTPS;
|
|
cnt_next <= cnt + 1;
|
|
when 4 =>
|
|
data_out_ro <= PROTOCOLVERSION_2_4 & VENDORID;
|
|
cnt_next <= cnt + 1;
|
|
when 5 =>
|
|
data_out_ro <= GUIDPREFIX(0);
|
|
cnt_next <= cnt + 1;
|
|
when 6 =>
|
|
data_out_ro <= GUIDPREFIX(1);
|
|
cnt_next <= cnt + 1;
|
|
when 7 =>
|
|
data_out_ro <= GUIDPREFIX(2);
|
|
|
|
-- Continue with respective RTPS Submessage
|
|
stage_next <= return_stage;
|
|
cnt_next <= return_cnt;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when SEND_INFO_TS =>
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
wr_ro <= '1';
|
|
|
|
case (cnt) is
|
|
-- INFO_TS RTPS SUBMESSAGE
|
|
-- RTPS Submessage Header
|
|
when 0 =>
|
|
data_out_ro <= SID_INFO_TS & "00000000" & std_logic_vector(to_unsigned(8, SUBMESSAGE_LENGTH_WIDTH));
|
|
cnt_next <= cnt + 1;
|
|
-- Source Timestamp 1/2
|
|
when 1 =>
|
|
data_out_ro <= std_logic_vector(cc_source_timestamp(0));
|
|
cnt_next <= cnt + 1;
|
|
-- Writer Entity ID
|
|
when 2 =>
|
|
data_out_ro <= std_logic_vector(cc_source_timestamp(1));
|
|
|
|
stage_next <= SEND_DATA_A;
|
|
cnt_next <= 0;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when SEND_DATA_A =>
|
|
-- Precondition: mem_endpoint_data set (EMF_UDP_PORT_FLAG)
|
|
|
|
-- Wait for Endpoint Data
|
|
if (mem_op_done = '1') then
|
|
assert check_mask(current_emf, EMF_UDP_PORT_FLAG) severity FAILURE;
|
|
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
case (cnt) is
|
|
-- DATA RTPS SUBMESSAGE
|
|
-- RTPS Submessage Header
|
|
when 0 =>
|
|
data_out_ro <= SID_DATA & "00000000" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH));
|
|
if (cc_kind = ALIVE) then
|
|
data_flag <= '1';
|
|
else
|
|
data_flag <= '0';
|
|
end if;
|
|
if (WITH_KEY and cc_kind /= ALIVE) then
|
|
key_flag <= '1';
|
|
else
|
|
key_flag <= '0';
|
|
end if;
|
|
if (cc_kind /= ALIVE or WITH_KEY or mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
|
|
qos_flag <= '1';
|
|
else
|
|
qos_flag <= '0';
|
|
end if;
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- extraFlags, octetsToInlineQoS
|
|
when 1 =>
|
|
data_out_ro <= x"0000" & std_logic_vector(to_unsigned(16, 16));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- Reader Entity ID
|
|
when 2 =>
|
|
data_out_ro <= ENTITYID_UNKNOWN;
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- Writer Entity ID
|
|
when 3 =>
|
|
data_out_ro <= ENTITYID;
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- Sequence Number 1/2
|
|
when 4 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(0));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- Sequence Number 2/2
|
|
when 5 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(1));
|
|
wr_ro <= '1';
|
|
|
|
-- Need to send Key Hash
|
|
if (WITH_KEY) then
|
|
cnt_next <= cnt + 1;
|
|
-- Need to send Status Info
|
|
elsif (cc_kind /= ALIVE) then
|
|
cnt_next <= cnt + 6;
|
|
-- Reader expect in-line QoS
|
|
elsif(mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
|
|
stage_next <= SEND_INLINE_QOS;
|
|
cnt3_next <= 0;
|
|
-- Payload Available (DATA or Serialized Key)
|
|
elsif (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
stage_next <= SEND_DATA_B;
|
|
cnt_next <= 0;
|
|
else
|
|
last_word_out_ro <= '1';
|
|
-- Continue
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 0;
|
|
elsif (PUSH_MODE and new_push = '1') then
|
|
stage_next <= HANDLE_NEW;
|
|
cnt_next <= 4;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 0;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
-- Key Hash PID
|
|
when 6 =>
|
|
-- Synthesis Guard
|
|
if (WITH_KEY) then
|
|
data_out_ro <= PID_KEY_HASH & std_logic_vector(to_unsigned(16, SUBMESSAGE_LENGTH_WIDTH));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Key Hash 1/4
|
|
when 7 =>
|
|
-- Synthesis Guard
|
|
if (WITH_KEY) then
|
|
data_out_ro <= std_logic_vector(cc_instance_handle(0));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Key Hash 2/4
|
|
when 8 =>
|
|
-- Synthesis Guard
|
|
if (WITH_KEY) then
|
|
data_out_ro <= std_logic_vector(cc_instance_handle(1));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Key Hash 3/4
|
|
when 9 =>
|
|
-- Synthesis Guard
|
|
if (WITH_KEY) then
|
|
data_out_ro <= std_logic_vector(cc_instance_handle(2));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Key Hash 4/4
|
|
when 10 =>
|
|
-- Synthesis Guard
|
|
if (WITH_KEY) then
|
|
data_out_ro <= std_logic_vector(cc_instance_handle(3));
|
|
wr_ro <= '1';
|
|
|
|
-- Need to send Status Info
|
|
if (cc_kind /= ALIVE) then
|
|
cnt_next <= cnt + 1;
|
|
-- Reader expects in-line QoS
|
|
elsif (mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
|
|
stage_next <= SEND_INLINE_QOS;
|
|
cnt3_next <= 0;
|
|
else
|
|
cnt_next <= cnt + 3;
|
|
end if;
|
|
end if;
|
|
-- Status Info PID
|
|
when 11 =>
|
|
data_out_ro <= PID_STATUS_INFO & std_logic_vector(to_unsigned(4, SUBMESSAGE_LENGTH_WIDTH));
|
|
wr_ro <= '1';
|
|
cnt_next <= cnt + 1;
|
|
-- Status Info
|
|
when 12 =>
|
|
data_out_ro <= (others => '0');
|
|
wr_ro <= '1';
|
|
case (cc_kind) is
|
|
when ALIVE_FILTERED =>
|
|
data_out_ro(STATUS_INFO_FILTERED_FLAG) <= '1';
|
|
when NOT_ALIVE_DISPOSED =>
|
|
data_out_ro(STATUS_INFO_DISPOSED_FLAG) <= '1';
|
|
when NOT_ALIVE_UNREGISTERED =>
|
|
data_out_ro(STATUS_INFO_UNREGISTERED_FLAG) <= '1';
|
|
when others =>
|
|
null;
|
|
end case;
|
|
|
|
-- Reader expects in-line QoS
|
|
if (mem_endpoint_data.flags(READER_EXPECTS_INLINE_QOS_FLAG) = '1') then
|
|
stage_next <= SEND_INLINE_QOS;
|
|
cnt3_next <= 0;
|
|
else
|
|
cnt_next <= cnt + 1;
|
|
end if;
|
|
-- Sentinel
|
|
when 13 =>
|
|
data_out_ro <= PID_SENTINEL & std_logic_vector(to_unsigned(0, PARAMETER_LENGTH_WIDTH));
|
|
wr_ro <= '1';
|
|
|
|
-- Payload Available (DATA or Serialized Key)
|
|
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
stage_next <= SEND_DATA_B;
|
|
else
|
|
last_word_out_ro <= '1';
|
|
-- Continue
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 0;
|
|
elsif (PUSH_MODE and new_push = '1') then
|
|
stage_next <= HANDLE_NEW;
|
|
cnt_next <= 4;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 0;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when SEND_INLINE_QOS =>
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
data_out_ro <= INLINE_QOS.data(cnt3);
|
|
wr_ro <= '1';
|
|
|
|
-- Exit Condition
|
|
if (cnt3 = INLINE_QOS.length-1) then
|
|
-- Payload Available (DATA or Serialized Key)
|
|
if (cc_kind = ALIVE or (WITH_KEY and cc_kind /= ALIVE)) then
|
|
stage_next <= SEND_DATA_B;
|
|
else
|
|
last_word_out_ro <= '1';
|
|
-- Continue
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 0;
|
|
elsif (PUSH_MODE and new_push = '1') then
|
|
stage_next <= HANDLE_NEW;
|
|
cnt_next <= 4;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 0;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
else
|
|
cnt3_next <= cnt3 + 1;
|
|
end if;
|
|
end if;
|
|
when SEND_DATA_B =>
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
ready_in_hc <= '1';
|
|
|
|
if (valid_in_hc = '1') then
|
|
data_out_ro <= data_in_hc;
|
|
wr_ro <= '1';
|
|
|
|
if (last_word_in_hc = '1') then
|
|
last_word_out_ro <= '1';
|
|
|
|
-- Continue
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 0;
|
|
elsif (PUSH_MODE and new_push = '1') then
|
|
stage_next <= HANDLE_NEW;
|
|
cnt_next <= 4;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 0;
|
|
else
|
|
assert FALSE severity FAILURE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
when SEND_GAP_A =>
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
wr_ro <= '1';
|
|
|
|
case (cnt) is
|
|
-- DATA RTPS SUBMESSAGE (Participant Message)
|
|
-- RTPS Submessage Header
|
|
when 0 =>
|
|
data_out_ro <= SID_GAP & "00000000" & std_logic_vector(to_unsigned(28, 16));
|
|
cnt_next <= cnt + 1;
|
|
-- Reader Entity ID
|
|
when 1 =>
|
|
data_out_ro <= ENTITYID_UNKNOWN;
|
|
cnt_next <= cnt + 1;
|
|
-- Writer Entity ID
|
|
when 2 =>
|
|
data_out_ro <= ENTITYID;
|
|
cnt_next <= cnt + 1;
|
|
-- GAP Start Sequence Number 1/2
|
|
when 3 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(0));
|
|
cnt_next <= cnt + 1;
|
|
-- GAP Start Sequence Number 2/2
|
|
when 4 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(1));
|
|
|
|
-- Continue
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and stale_check = '1') then
|
|
stage_next <= HANDLE_REQUESTS;
|
|
cnt_next <= 0;
|
|
elsif (DURABILITY_QOS /= VOLATILE_DURABILITY_QOS and historical_push = '1') then
|
|
stage_next <= HANDLE_HISTORICAL;
|
|
cnt_next <= 0;
|
|
end if;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when SEND_GAP_B =>
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
wr_ro <= '1';
|
|
|
|
case (cnt) is
|
|
-- GAP List Sequence Number Set (Bitmap Base 1/2)
|
|
when 0 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(0));
|
|
cnt_next <= cnt + 1;
|
|
-- GAP List Sequence Number Set (Bitmap Base 2/2)
|
|
when 1 =>
|
|
data_out_ro <= std_logic_vector(next_seq_nr(1));
|
|
cnt_next <= cnt + 1;
|
|
-- GAP List Sequence Number Set (NumBits)
|
|
when 2 =>
|
|
data_out_ro <= (others => '0');
|
|
|
|
if (gap_is_last = '1') then
|
|
last_word_out_ro <= '1';
|
|
-- Reset
|
|
gap_is_last_next <= '0';
|
|
end if;
|
|
|
|
-- Continue
|
|
stage_next <= return_stage;
|
|
cnt_next <= return_cnt;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
when SEND_HEARTBEAT =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then
|
|
-- Output FIFO Guard
|
|
if (full_ro = '0') then
|
|
wr_ro <= '1';
|
|
|
|
case (cnt) is
|
|
-- HEARTBEAT RTPS SUBMESSAGE
|
|
-- RTPS Submessage Header
|
|
when 0 =>
|
|
if (assert_liveliness_latch = '1') then
|
|
data_out_ro <= SID_HEARTBEAT & "00000100" & std_logic_vector(to_unsigned(28, 16));
|
|
else
|
|
data_out_ro <= SID_HEARTBEAT & "00000000" & std_logic_vector(to_unsigned(28, 16));
|
|
end if;
|
|
cnt_next <= cnt + 1;
|
|
-- Reader Entity ID
|
|
when 1 =>
|
|
data_out_ro <= ENTITYID_UNKNOWN;
|
|
cnt_next <= cnt + 1;
|
|
-- Writer Entity ID
|
|
when 2 =>
|
|
data_out_ro <= ENTITYID;
|
|
cnt_next <= cnt + 1;
|
|
-- First Sequence Number 1/2
|
|
when 3 =>
|
|
data_out_ro <= std_logic_vector(min_sn(0));
|
|
cnt_next <= cnt + 1;
|
|
-- First Sequence Number 2/2
|
|
when 4 =>
|
|
data_out_ro <= std_logic_vector(min_sn(1));
|
|
cnt_next <= cnt + 1;
|
|
-- Last Sequence Number 1/2
|
|
when 5 =>
|
|
data_out_ro <= std_logic_vector(last_seq_nr(0));
|
|
cnt_next <= cnt + 1;
|
|
-- Last Sequence Number 2/2
|
|
when 6 =>
|
|
data_out_ro <= std_logic_vector(last_seq_nr(1));
|
|
cnt_next <= cnt + 1;
|
|
-- Count
|
|
when 7 =>
|
|
data_out_ro <= std_logic_vector(count);
|
|
last_word_out_ro <= '1';
|
|
|
|
stage_next <= HANDLE_HEARTBEATS;
|
|
cnt_next <= 1;
|
|
when others =>
|
|
null;
|
|
end case;
|
|
end if;
|
|
end if;
|
|
when SKIP_PACKET =>
|
|
-- 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_user <= '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;
|
|
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;
|
|
current_emf_next <= current_emf;
|
|
-- 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,
|
|
flags => reader_flags_next,
|
|
lease_deadline => lease_deadline,
|
|
res_time => res_time,
|
|
ack_seq_nr_base => seq_nr,
|
|
req_seq_nr_base => seq_nr,
|
|
req_seq_nr_bitmap => req_seq_nr_bitmap,
|
|
field_flag => mem_field_flags
|
|
);
|
|
|
|
case(mem_opcode) is
|
|
when SEARCH_ENDPOINT =>
|
|
current_emf_next <= mem_field_flags;
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
|
|
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
|
|
mem_pos_next <= 0;
|
|
mem_stage_next <= SEARCH_ENDPOINT;
|
|
mem_cnt_next <= 0;
|
|
when INSERT_ENDPOINT =>
|
|
current_emf_next <= (others => '1');
|
|
-- Set Endpoint Data
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
mem_endpoint_data_next.guid <= guid_next;
|
|
mem_endpoint_data_next.addr <= addr_next;
|
|
mem_endpoint_data_next.portn <= portn_next;
|
|
mem_endpoint_data_next.flags <= reader_flags_next;
|
|
mem_endpoint_data_next.lease_deadline <= lease_deadline;
|
|
mem_endpoint_data_next.res_time <= TIME_INVALID;
|
|
mem_endpoint_data_next.ack_seq_nr_base <= seq_nr;
|
|
mem_endpoint_data_next.req_seq_nr_base <= SEQUENCENUMBER_UNKNOWN;
|
|
mem_endpoint_data_next.req_seq_nr_bitmap <= (others => '0');
|
|
|
|
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
|
|
mem_pos_next <= 0;
|
|
mem_stage_next <= FIND_EMPTY_SLOT;
|
|
mem_cnt_next <= 0;
|
|
when UPDATE_ENDPOINT =>
|
|
current_emf_next <= current_emf or mem_field_flags;
|
|
mem_stage_next <= UPDATE_ENDPOINT;
|
|
|
|
if check_mask(mem_field_flags,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 0;
|
|
elsif check_mask(mem_field_flags,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 1;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 2;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 4;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
when REMOVE_ENDPOINT =>
|
|
current_emf_next <= (others => '0');
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
|
|
mem_stage_next <= REMOVE_ENDPOINT;
|
|
mem_cnt_next <= 0;
|
|
when GET_FIRST_ENDPOINT =>
|
|
current_emf_next <= mem_field_flags;
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
|
|
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 =>
|
|
current_emf_next <= mem_field_flags;
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
|
|
-- Memory Bound Guard
|
|
if (mem_addr_base >= max_endpoint_addr) then
|
|
mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS;
|
|
else
|
|
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 =>
|
|
if (mem_addr_base /= mem_addr_update) then
|
|
mem_endpoint_data_next <= ZERO_ENDPOINT_DATA;
|
|
current_emf_next <= mem_field_flags;
|
|
else
|
|
current_emf_next <= current_emf or mem_field_flags;
|
|
end if;
|
|
|
|
-- Fetch Endpoint Data
|
|
mem_stage_next <= GET_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 check_mask(mem_field_flags,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 4;
|
|
elsif check_mask(mem_field_flags,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_field_flags,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
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
|
|
mem_addr_base_next <= mem_addr_base;
|
|
-- 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 check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 4;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
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 check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 4;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
mem_cnt_next <= 15;
|
|
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 check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 4;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
else
|
|
mem_cnt_next <= 16;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET IPv4 Address
|
|
when 4 =>
|
|
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 check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
else
|
|
mem_cnt_next <= 19;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET UDP Port & Reader Flags
|
|
when 5 =>
|
|
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 (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
else
|
|
mem_cnt_next <= 20;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET Lease Deadline 1/2
|
|
when 6 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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;
|
|
end if;
|
|
-- GET Lease Deadline 2/2
|
|
when 7 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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 (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
else
|
|
mem_cnt_next <= 21;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET Response Time 1/2
|
|
when 8 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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 9 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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 (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
else
|
|
mem_cnt_next <= 23;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET ACK Sequence Number 1/2
|
|
when 10 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_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 ACK Sequence Number 2/2
|
|
when 11 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_read <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
else
|
|
mem_cnt_next <= 25;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET Request Sequence Number Base 1/2
|
|
when 12 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_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 Request Sequence Number Base 2/2
|
|
when 13 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_read <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
else
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then
|
|
mem_cnt_next <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
else
|
|
mem_cnt_next <= 27;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- GET Request Bitmap
|
|
when 14 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
|
|
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 <= 15;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then
|
|
mem_cnt_next <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
else
|
|
mem_cnt_next <= 29;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ Entity ID
|
|
when 15 =>
|
|
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 <= 16;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- READ GUID Prefix 1/3
|
|
when 16 =>
|
|
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 17 =>
|
|
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 18 =>
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.guid(2) <= mem_read_data;
|
|
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 19;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- READ IPv4 Address
|
|
when 19 =>
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.addr <= mem_read_data;
|
|
|
|
if check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 20;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- READ UDP Port & Reader Flags
|
|
when 20 =>
|
|
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);
|
|
mem_endpoint_data_next.flags <= mem_read_data(CDR_SHORT_WIDTH-1 downto 0);
|
|
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 21;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- READ Lease Deadline 1/2
|
|
when 21 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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;
|
|
end if;
|
|
-- READ Lease Deadline 2/2
|
|
when 22 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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 (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 23;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ Response Time 1/2
|
|
when 23 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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 24 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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);
|
|
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 25;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ ACK Sequence Number 1/2
|
|
when 25 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.ack_seq_nr_base(0) <= unsigned(mem_read_data);
|
|
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- READ ACK Sequence Number 2/2
|
|
when 26 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.ack_seq_nr_base(1) <= unsigned(mem_read_data);
|
|
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 27;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ Request Sequence Number Base 1/2
|
|
when 27 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.req_seq_nr_base(0) <= unsigned(mem_read_data);
|
|
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- READ Request Sequence Number Base 2/2
|
|
when 28 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.req_seq_nr_base(1) <= unsigned(mem_read_data);
|
|
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 29;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- READ Request Bitmap
|
|
when 29 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_ready_out <= '1';
|
|
-- Memory Flow Control Guard
|
|
if (mem_valid_out = '1') then
|
|
mem_endpoint_data_next.req_seq_nr_bitmap <= 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;
|
|
end if;
|
|
-- IPv4 Address
|
|
when 4 =>
|
|
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;
|
|
-- UDPv4 Ports and Reader Flags
|
|
when 5 =>
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET;
|
|
mem_write_data <= mem_endpoint_latch_data.portn & mem_endpoint_latch_data.flags;
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- Lease Deadline 1/2
|
|
when 6 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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;
|
|
end if;
|
|
-- Lease Deadline 2/2
|
|
when 7 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Response Time 1/2
|
|
when 8 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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 9 =>
|
|
if (RELIABILITY_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
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- ACK Sequence Number 1/2
|
|
when 10 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(0));
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- ACK Sequence Number 2/2
|
|
when 11 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(1));
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Request Sequence Number Base 1/2
|
|
when 12 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET;
|
|
mem_write_data <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(0));
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Request Sequence Number Base 2/2
|
|
when 13 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_write_data <= (others => '0');
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_write_data <= std_logic_vector(SEQUENCENUMBER_UNKNOWN(1));
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Request Bitmap
|
|
when 14 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
|
|
mem_write_data <= (others => '0');
|
|
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 =>
|
|
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 check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 1;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 2;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 4;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- UDPv4 Ports & Reader Flags
|
|
when 1 =>
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET;
|
|
mem_write_data <= mem_endpoint_latch_data.portn & mem_endpoint_latch_data.flags;
|
|
mem_endpoint_data_next.portn <= mem_endpoint_latch_data.portn;
|
|
mem_endpoint_data_next.flags <= mem_endpoint_latch_data.flags;
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 2;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 4;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
-- Lease Deadline 1/2
|
|
when 2 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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;
|
|
end if;
|
|
-- Lease Deadline 2/2
|
|
when 3 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
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 (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 4;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- Response Time 1/2
|
|
when 4 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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 5 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_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
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- ACK Sequence Number 1/2
|
|
when 6 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(0));
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- ACK Sequence Number 2/2
|
|
when 7 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.ack_seq_nr_base(1));
|
|
mem_endpoint_data_next.ack_seq_nr_base <= mem_endpoint_latch_data.ack_seq_nr_base;
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- Request Sequence Number Base 1/2
|
|
when 8 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.req_seq_nr_base(0));
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
mem_cnt_next <= mem_cnt + 1;
|
|
end if;
|
|
end if;
|
|
-- Request Sequence Number Base 2/2
|
|
when 9 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET + 1;
|
|
mem_write_data <= std_logic_vector(mem_endpoint_latch_data.req_seq_nr_base(1));
|
|
mem_endpoint_data_next.req_seq_nr_base <= mem_endpoint_latch_data.req_seq_nr_base;
|
|
-- Memory Flow Control Guard
|
|
if (mem_ready_in = '1') then
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
else
|
|
-- DONE
|
|
mem_stage_next <= IDLE;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
-- Request Bitmap
|
|
when 10 =>
|
|
-- Synthesis Guard
|
|
if (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS) then
|
|
mem_valid_in <= '1';
|
|
mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BITMAP_OFFSET;
|
|
mem_write_data <= mem_endpoint_latch_data.req_seq_nr_bitmap;
|
|
mem_endpoint_data_next.req_seq_nr_bitmap <= mem_endpoint_latch_data.req_seq_nr_bitmap;
|
|
-- 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
|
|
-- 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
|
|
-- 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 check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then
|
|
mem_cnt_next <= 4;
|
|
elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then
|
|
mem_cnt_next <= 5;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then
|
|
mem_cnt_next <= 6;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then
|
|
mem_cnt_next <= 8;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 10;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then
|
|
mem_cnt_next <= 12;
|
|
elsif (RELIABILITY_QOS = RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BITMAP_FLAG)) then
|
|
mem_cnt_next <= 14;
|
|
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;
|
|
|
|
sync_prc : process(clk)
|
|
begin
|
|
if rising_edge(clk) then
|
|
if (reset = '1') then
|
|
stage <= IDLE;
|
|
return_stage <= IDLE;
|
|
mem_stage <= RESET_MEMORY;
|
|
sn_latch_1 <= SEQUENCENUMBER_UNKNOWN;
|
|
sn_latch_2 <= SEQUENCENUMBER_UNKNOWN;
|
|
sn_latch_3 <= SEQUENCENUMBER_UNKNOWN;
|
|
check_time <= TIME_INVALID;
|
|
heartbeat_time <= time + HEARTBEAT_PERIOD;
|
|
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;
|
|
cnt3 <= 0;
|
|
nack_bitmap_pos <= 0;
|
|
req_bitmap_pos <= 0;
|
|
mem_cnt <= 0;
|
|
mem_pos <= 0;
|
|
return_cnt <= 0;
|
|
gap_is_last <= '0';
|
|
is_meta <= '0';
|
|
last_word_in_latch <= '0';
|
|
stale_check <= '0';
|
|
gap_in_progress <= '0';
|
|
new_push <= '0';
|
|
historical_push <= '0';
|
|
assert_liveliness_latch <= '0';
|
|
bitmap_cnt <= (others => '0');
|
|
meta_opcode <= EMO_NOP;
|
|
opcode <= SID_PAD;
|
|
rtps_flags <= (others => '0');
|
|
reader_flags <= (others => '0');
|
|
count <= (others => '0');
|
|
long_latch <= (others => '0');
|
|
req_seq_nr_bitmap <= (others => '0');
|
|
mem_addr_base <= (others => '0');
|
|
last_addr <= (others => '0');
|
|
mem_addr_latch <= (others => '0');
|
|
max_endpoint_addr <= (others => '0');
|
|
current_emf <= (others => '0');
|
|
global_ack_seq_nr_base <= (others => (others => '0'));
|
|
last_seq_nr <= (others => (others => '0'));
|
|
bitmap_latch <= (others => (others => '0'));
|
|
else
|
|
stage <= stage_next;
|
|
return_stage <= return_stage_next;
|
|
mem_stage <= mem_stage_next;
|
|
sn_latch_1 <= sn_latch_1_next;
|
|
sn_latch_2 <= sn_latch_2_next;
|
|
sn_latch_3 <= sn_latch_3_next;
|
|
check_time <= check_time_next;
|
|
heartbeat_time <= heartbeat_time_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;
|
|
cnt3 <= cnt3_next;
|
|
nack_bitmap_pos <= nack_bitmap_pos_next;
|
|
req_bitmap_pos <= req_bitmap_pos_next;
|
|
mem_cnt <= mem_cnt_next;
|
|
mem_pos <= mem_pos_next;
|
|
return_cnt <= return_cnt_next;
|
|
gap_is_last <= gap_is_last_next;
|
|
is_meta <= is_meta_next;
|
|
last_word_in_latch <= last_word_in_latch_next;
|
|
stale_check <= stale_check_next;
|
|
gap_in_progress <= gap_in_progress_next;
|
|
new_push <= new_push_next;
|
|
historical_push <= historical_push_next;
|
|
bitmap_cnt <= bitmap_cnt_next;
|
|
assert_liveliness_latch <= assert_liveliness_latch_next;
|
|
meta_opcode <= meta_opcode_next;
|
|
opcode <= opcode_next;
|
|
rtps_flags <= rtps_flags_next;
|
|
reader_flags <= reader_flags_next;
|
|
count <= count_next;
|
|
long_latch <= long_latch_next;
|
|
req_seq_nr_bitmap <= req_seq_nr_bitmap_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;
|
|
current_emf <= current_emf_next;
|
|
global_ack_seq_nr_base <= global_ack_seq_nr_base_next;
|
|
last_seq_nr <= last_seq_nr_next;
|
|
bitmap_latch <= bitmap_latch_next;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
end architecture;
|