-- 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 : generic "" 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;