From e8670aaf595babcd63cbab9976e6cf9e4e609026 Mon Sep 17 00:00:00 2001 From: Greek Date: Sun, 7 Feb 2021 17:59:33 +0100 Subject: [PATCH] Blind implementation of RTPS Writer --- src/REF.txt | 114 +- src/TODO.txt | 9 + src/rtps_config_package.vhd | 141 +- src/rtps_package.vhd | 6 + src/rtps_writer.vhd | 3423 +++++++++++++++++++++++++++++++++++ 5 files changed, 3653 insertions(+), 40 deletions(-) create mode 100644 src/rtps_writer.vhd diff --git a/src/REF.txt b/src/REF.txt index 4ad2f1d..cd5799f 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -253,9 +253,9 @@ ENDPOINT MATCH FRAME 04| ENTITYID | +-------------------------------------------------------------+ 05| IPv4_ADDRESS | - +-----------------------------+-----------------------------+-+ -06| UDP_PORT | UNUSED |Q| - +-----------------------------+-----------------------------+-+ + +-----------------------------+---------------------------+-+-+ +06| UDP_PORT | UNUSED |D|Q| + +-----------------------------+---------------------------+-+-+ ENDPOINT UNMATCH FRAME ====================== @@ -347,26 +347,28 @@ WRITER + + 03| | +-------------------------------------------------------------+ -04| IPv4_ADDRESS | [Reliable Only] - +-----------------------------+---------------------------+-+-+ -05| UDP_PORT | UNUSED |P|Q| [Reliable Only] - +-----------------------------+---------------------------+-+-+ +04| IPv4_ADDRESS | + +-----------------------------+-------------------------+-+-+-+ +05| UDP_PORT | UNUSED |B|H|Q| + +-----------------------------+-------------------------+-+-+-+ 06| | - + LEASE_DEADLINE + + + LEASE_DEADLINE + [Reliable Only] 07| | +-------------------------------------------------------------+ -08| | - + GAP_LOW_SEQ_NR + [Reliable Only] +08| | + + RES_TIME + [Reliable Only] 09| | +-------------------------------------------------------------+ 10| | - + GAP_HIGH_SEQ_NR + [Reliable Only] + + ACK_SEQ_NR_BASE + [Reliable Only] 11| | +-------------------------------------------------------------+ -12| | - + RES_TIME + [Reliable Only] +12| | + + REQ_SEQ_NR_BASE + [Reliable Only] 13| | +-------------------------------------------------------------+ +14| REQ_BITMAP | [Reliable Only] + +-------------------------------------------------------------+ HISTORY CACHE @@ -377,29 +379,56 @@ READER 31............24..............16..............8...............0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-------------------------------------------------------------+ -00| STATUS_INFO | {A/B} +00| STATUS_INFO | +-------------------------------------------------------------+ 01| | - + TIMESTAMP + {A} + + TIMESTAMP + 02| | +-------------------------------------------------------------+ 03| | - + LIFESPAN_DEADLINE + {A} + + LIFESPAN_DEADLINE + 04| | +-------------------------------------------------------------+ -05| PAYLOAD_ADDRESS | {A} +05| PAYLOAD_ADDRESS | +-------------------------------------------------------------+ -06| INSTANCE_ADDRESS | {A} +06| INSTANCE_ADDRESS | +-------------------------------------------------------------+ -07| DISPOSED_GENERATION_COUNT | {A} +07| DISPOSED_GENERATION_COUNT | +-------------------------------------------------------------+ -08| NO_WRITERS_GENERATION_COUNT | {A} +08| NO_WRITERS_GENERATION_COUNT | +-------------------------------------------------------------+ -09| PREV_ADDRESS | {A} +09| PREV_ADDRESS | +-------------------------------------------------------------+ -10| NEXT_ADDRESS | {A/B} +10| NEXT_ADDRESS | +-------------------------------------------------------------+ +WRITER +------ + 31............24..............16..............8...............0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-------------------------------------------------------------+ +00| STATUS_INFO | + +-------------------------------------------------------------+ +01| | + + TIMESTAMP + +02| | + +-------------------------------------------------------------+ +03| | + + LIFESPAN_DEADLINE + +04| | + +-------------------------------------------------------------+ +05| PAYLOAD_ADDRESS | + +-------------------------------------------------------------+ +06| INSTANCE_ADDRESS | + +-------------------------------------------------------------+ +07| | + ~ ACK_BITMAP ~ +**| | + +-------------------------------------------------------------+ +**| PREV_ADDRESS | + +-------------------------------------------------------------+ +**| NEXT_ADDRESS | + +-------------------------------------------------------------+ STATUS INFO ----------- @@ -461,35 +490,60 @@ HISTORY CACHE INPUT INSTANCE MEMORY =============== + +READER +------ 31............24..............16..............8...............0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-------------------------------------------------------------+ -00| NEXT_ADDRESS | {A/B} +00| NEXT_ADDRESS | +-------------------------------------------------------------+ 01| | + + 02| | - + KEY_HASH + {A} + + KEY_HASH + 03| | + + 04| | +-------------------------------------------------------------+ -05| STATUS_INFO | {A/B} +05| STATUS_INFO | +-------------------------------------------------------------+ -06| SAMPLE_COUNT | {A/B} +06| SAMPLE_COUNT | +-------------------------------------------------------------+ -07| DISPOSED_GENERATION_COUNT | {A} +07| DISPOSED_GENERATION_COUNT | +-------------------------------------------------------------+ -08| NO_WRITERS_GENERATION_COUNT | {A} +08| NO_WRITERS_GENERATION_COUNT | +-------------------------------------------------------------+ 09| | - + IGNORE_DEADLINE + {A} [only TIME_BASED_FILTER] + + IGNORE_DEADLINE + [only TIME_BASED_FILTER] 10| | +-------------------------------------------------------------+ 11| | - ~ WRITER_BITMAP ~ {A} + ~ WRITER_BITMAP ~ **| | +-------------------------------------------------------------+ + +WRITER +------ + 31............24..............16..............8...............0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-------------------------------------------------------------+ +00| NEXT_ADDRESS | + +-------------------------------------------------------------+ +01| | + + + +02| | + + KEY_HASH + +03| | + + + +04| | + +-------------------------------------------------------------+ +05| STATUS_INFO | + +-------------------------------------------------------------+ +06| SAMPLE_COUNT | + +-------------------------------------------------------------+ +07| ACK_COUNT | + +-------------------------------------------------------------+ STATUS INFO diff --git a/src/TODO.txt b/src/TODO.txt index 05b9e4f..509e62a 100644 --- a/src/TODO.txt +++ b/src/TODO.txt @@ -68,6 +68,10 @@ * Currently a RTPS Writer with DURABILITY TARNSIENT_LOCAL does send historical data to all matched readers, not depending if they are VOLATILE or TRANSIENT_LOCAL. * Assert Heartbeat period > Heartbeat Suppression Period * Can I request (NACK) SNs that were NOT announced by the writer (> last_sn in Heartbeat)? +* Does AUTOMATIC Liveliness QoS also update the lease on write/assert_liveliness operations? +* The Lease Duration is also updated if the Cache Change is not accepted by the DDS/HC. This in effect "skews" the "correctness" of the Writer Liveliness Protocol until the reader has no pending request from the Writer. +* If an Instance is DISPOSED, but later has no active writers, the Instance STAYS in the NOT_ALIVE_DISPOSED state. +* Is a Writer that is Disposing a Instance also Unregistering that instance? (Currently only Unregistering removes the remote Writer) * Fast-RTPS doen not follow DDSI-RTPS Specification - Open Github Issue @@ -85,6 +89,8 @@ Isn't Reader -> Writer also valid? Does it have a specific direction? - 9.4.5.3 Data Submessage writerSN is incorrectly shown as only 32 bits in width + - 8.2.3 The RTPS CacheChange + Add IDL Specification for CacheChange_t - 8.3.4 The RTPS Message Receiver, Table 8.16 - Initial State of the Receiver Port of UnicastReplyLocatorList should be initialized to Source Port. - 8.3.7.4.3 Validity @@ -93,6 +99,9 @@ 'This Submessage is invalid when the following is true: submessageLength in the Submessage header is too small' But if InvalidateFlag is set, Length can be Zero. Since the length is unsigned, there cannot be an invalid length. + - 8.7.2.2.1 DURABILITY + 'While volatile and transient-local durability do not affect the RTPS protocol' + But in case of Durability TRANSIENT_LOCAL the writer has to send historical Data. - 8.7.3.2 Indicating to a Reader that a Sample has been filtered Text refs 8.3.7.2.2 for DataFlag, but shoudl also ref 8.7.4 for FilteredFlag - 9.4.5.1.2 Flags diff --git a/src/rtps_config_package.vhd b/src/rtps_config_package.vhd index de2de23..920e8af 100644 --- a/src/rtps_config_package.vhd +++ b/src/rtps_config_package.vhd @@ -49,27 +49,31 @@ package rtps_config_package is constant OPCODE_PARTICIPANT_UNMATCH : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000002"; constant OPCODE_LIVELINESS_UPDATE : std_logic_vector(ENDPOINT_MATCH_OPCODE_WIDTH-1 downto 0) := x"55000003"; - type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE); + type HISTORY_CACHE_OPCODE_TYPE is (NOP, ADD_CACHE_CHANGE, GET_CACHE_CHANGE, ACK_CACHE_CHANGE, NACK_CACHE_CHANGE); type KEY_GENERATOR_OPCODE_TYPE is (NOP, WRITE_PAYLOAD, READ_KEY, READ_SIZE); - type HISTORY_CACHE_RESPOSNE_TYPE is (UNDEFINED, ACK, ACCEPTED, REJECTED); - type INSTANCE_STATE_TYPE is (ALIVE, NOT_ALIVE_DISPOSED, NOT_ALIVE_NO_WRITERS); - type VIEW_STATE_TYPE is (NEW_INSTANCE, NOT_NEW_INSTANCE); - type SAMPLE_STATE is (READ, NOT_READ); + type HISTORY_CACHE_RESPONSE_TYPE is (UNDEFINED, ACK, ACCEPTED, REJECTED, INVALID); + -- TODO: Prefix the Flags with something that differntiates between them -- Sample Status Info Flags - constant DISPOSED_FLAG : natural := 0; - constant UNREGISTERED_FLAG : natural := 1; - constant FILTERED_FLAG : natural := 2; + constant DISPOSED_FLAG : natural := STATUS_INFO_DISPOSED_FLAG; + constant UNREGISTERED_FLAG : natural := STATUS_INFO_UNREGISTERED_FLAG; + constant FILTERED_FLAG : natural := STATUS_INFO_FILTERED_FLAG; constant KEY_HASH_FLAG : natural := 29; constant PAYLOAD_FLAG : natural := 30; constant READ_FLAG : natural := 31; + -- Instance Status Info Flags constant NOT_ALIVE_DISPOSED_FLAG : natural := 0; constant NOT_ALIVE_NO_WRITERS_FLAG : natural := 1; constant LIVELINESS_FLAG : natural := 2; constant VIEW_FLAG : natural := 3; constant MARK_FLAG : natural := 4; + -- Remote Endpoint Flags + constant EXPECTS_INLINE_QOS_FLAG : natural := 0; + constant SEND_HISTORICAL_DATA_FLAG : natural := 1; + constant BEST_EFFORT_FLAG : natural := 2; + -- Marks the Reader Endpoint in the Endpoint Array constant ENDPOINT_READERS : std_logic_vector(0 to NUM_ENDPOINTS-1) := (0 to NUM_READERS-1 => '1', others => '0'); @@ -136,7 +140,9 @@ package rtps_config_package is function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : unsigned(WORD_WIDTH-1 downto 0); local : unsigned(WORD_WIDTH-1 downto 0)) return boolean; function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : DOUBLE_WORD_ARRAY; local : DOUBLE_WORD_ARRAY) return boolean; - function check_mask(flags : std_logic_vector, mask : std_logic_vector) return boolean; + function check_mask(flags : std_logic_vector; mask : std_logic_vector) return boolean; + + function gen_inline_qos (id : natural) return OUTPUT_DATA_TYPE; end package; @@ -723,6 +729,121 @@ package body rtps_config_package is constant WRITER_ENDPOINT_DATA : OUTPUT_DATA_TYPE := gen_writer_endpoint_data; + function gen_inline_qos (id : natural) return OUTPUT_DATA_TYPE is + variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); + variable ind : natural := 0; + variable tmp : natural := 0; + begin + assert (id >= NUM_READERS) report "Inline Qos can only be generated for Writer Endpoints" severity FAILURE; + + -- TOPIC NAME + tmp := string_len(ENDPOINT_TOPIC(id)); + ret.data(ret.length) := PID_TOPIC_NAME & std_logic_vector(to_unsigned((round_div(tmp,4)+1)*4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(to_unsigned(tmp, 32)); + for j in 0 to round_div(tmp,4)-1 loop + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_TOPIC(id)(j); + end loop; + -- DURABILITY + if (ENDPOINT_DURABILITY_QOS(id) /= DEFAULT_DURABILITY_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_DURABILITY & std_logic_vector(to_unsigned(4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_DURABILITY_QOS(id); + end if; + -- PRESENTATION + if (ENDPOINT_PRESENTATION_QOS(id) /= DEFAULT_PRESENTATION_QOS or ENDPOINT_COHERENT_ACCESS(id) /= DEFAULT_COHERENT_ACCESS or ENDPOINT_ORDERED_ACCESS(id) /= DEFAULT_ORDERED_ACCESS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_PRESENTATION & std_logic_vector(to_unsigned(8, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_PRESENTATION_QOS(id); + ret.length := ret.length + 1; + ret.data(ret.length) := (24 => boolean_to_std_logic(ENDPOINT_COHERENT_ACCESS(id)), 16 => boolean_to_std_logic(ENDPOINT_ORDERED_ACCESS(id)), others => '0'); + end if; + -- DEADLINE + if (ENDPOINT_DEADLINE_QOS(id) /= DEFAULT_DEADLINE_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_DEADLINE & std_logic_vector(to_unsigned(8, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_DEADLINE_QOS(id)(0)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_DEADLINE_QOS(id)(1)); + end if; + -- LATENCY_BUDGET + if (ENDPOINT_LATENCY_BUDGET_QOS(id) /= DEFAULT_LATENCY_BUDGET_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_LATENCY_BUDGET & std_logic_vector(to_unsigned(8, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LATENCY_BUDGET_QOS(id)(0)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LATENCY_BUDGET_QOS(id)(1)); + end if; + -- OWNERSHIP + if (ENDPOINT_OWNERSHIP_QOS(id) /= DEFAULT_OWNERSHIP_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_OWNERSHIP & std_logic_vector(to_unsigned(4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_OWNERSHIP_QOS(id); + end if; + -- OWNERSHIP STRENGTH + if (ENDPOINT_OWNERSHIP_STRENGTH_QOS(id) /= DEFAULT_OWNERSHIP_STRENGTH_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_OWNERSHIP_STRENGTH & std_logic_vector(to_unsigned(4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_OWNERSHIP_STRENGTH_QOS(id); + end if; + -- LIVELINESS + if (ENDPOINT_LIVELINESS_QOS(id) /= DEFAULT_LIVELINESS_QOS or ENDPOINT_LEASE_DURATION(id) /= DEFAULT_LEASE_DURATION) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_LIVELINESS & std_logic_vector(to_unsigned(12, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_LIVELINESS_QOS(id); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LEASE_DURATION(id)(0)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LEASE_DURATION(id)(1)); + end if; + -- RELIABILITY + if (ENDPOINT_RELIABILITY_QOS(id) /= DEFAULT_RELIABILTY_QOS or ENDPOINT_MAX_BLOCKING_TIME(id) /= DEFAULT_MAX_BLOCKING_TIME) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_RELIABILITY & std_logic_vector(to_unsigned(12, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_RELIABILITY_QOS(id); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(id)(0)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_MAX_BLOCKING_TIME(id)(1)); + end if; + -- TRANSPORT PRIORITY + if (ENDPOINT_TRANSPORT_PRIORITY_QOS(id) /= DEFAULT_TRANSPORT_PRIORITY_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_TRANSPORT_PRIORITY & std_logic_vector(to_unsigned(4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_TRANSPORT_PRIORITY_QOS(id); + end if; + -- LIFESPAN + if (ENDPOINT_LIFESPAN_QOS(id) /= DEFAULT_LIFESPAN_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_LIFESPAN & std_logic_vector(to_unsigned(8, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LIFESPAN_QOS(id)(0)); + ret.length := ret.length + 1; + ret.data(ret.length) := std_logic_vector(ENDPOINT_LIFESPAN_QOS(id)(1)); + end if; + -- DESTINATION ORDER + if (ENDPOINT_DESTINATION_ORDER_QOS(id) /= DEFAULT_DESTINATION_ORDER_QOS) then + ret.length := ret.length + 1; + ret.data(ret.length) := PID_DESTINATION_ORDER & std_logic_vector(to_unsigned(4, 16)); + ret.length := ret.length + 1; + ret.data(ret.length) := ENDPOINT_DESTINATION_ORDER_QOS(id); + end if; + -- SENTINEL + ret.length := ret.length + 1; + ret.data(ret.length) := PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); + return ret; + end function; + function gen_participant_data return OUTPUT_DATA_TYPE is variable ret : OUTPUT_DATA_TYPE := (data => (others => (others => '0')), length => 0); variable len : natural := 0; @@ -1089,7 +1210,7 @@ package body rtps_config_package is return ret; end function; - function check_mask(flags : std_logic_vector, mask : std_logic_vector) return boolean is + function check_mask(flags : std_logic_vector; mask : std_logic_vector) return boolean is begin assert (flags'length = mask'length) report "Flag and mask Signal have unequal length" severity FAILURE; if ((flags and mask) = mask) then diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index d9b5da5..a5d8c58 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -200,6 +200,11 @@ package rtps_package is constant LIFESPAN_QOS_POLICY_ID : std_logic_vector(QOS_POLICY_ID_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(21,QOS_POLICY_ID_WIDTH)); constant DURABILITYSERVICE_QOS_POLICY_ID : std_logic_vector(QOS_POLICY_ID_WIDTH-1 downto 0) := std_logic_vector(to_unsigned(22,QOS_POLICY_ID_WIDTH)); + -- *STATUS INFO* + constant STATUS_INFO_DISPOSED_FLAG : natural := 0; + constant STATUS_INFO_UNREGISTERED_FLAG : natural := 1; + constant STATUS_INFO_FILTERED_FLAG : natural := 2; + -- *SUBMESSAGE IDs* constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01"; constant SID_ACKNACK : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"06"; @@ -440,6 +445,7 @@ package rtps_package is constant PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE : std_logic_vector(PARTICIPANT_MESSAGE_KIND_WIDTH-1 downto 0) := x"00000002"; --*CUSTOM TYPES* + type CACHE_CHANGE_KIND_TYPE is (ALIVE, ALIVE_FILTERED, NOT_ALIVE_DISPOSED, NOT_ALIVE_UNREGISTERED); type USER_BOOLEAN_ARRAY_TYPE is array (natural range <>) of boolean; subtype USER_STRING_TYPE is string(1 to 256); type USER_STRING_ARRAY_TYPE is array (natural range <>) of USER_STRING_TYPE; diff --git a/src/rtps_writer.vhd b/src/rtps_writer.vhd new file mode 100644 index 0000000..f9602ac --- /dev/null +++ b/src/rtps_writer.vhd @@ -0,0 +1,3423 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.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 ( + RELIABILTY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_RELIABILTY_QOS; + LIVELINESS_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_LIVELINESS_QOS; + DURABILITY_QOS : std_logic_vector(CDR_ENUMERATION_WIDTH-1 downto 0) := DEFAULT_DURABILITY_QOS; + ACKNACK_RESPONSE_DELAY : DURATION_TYPE := TODO; + ACKNACK_SUPPRESSION_DELAY : DURATION_TYPE := TODO; + LEASE_DURATION : DURATION_TYPE := DEFAULT_LEASE_DURATION; + HEARTBEAT_PERIOD : DURATION_TYPE := TODO; + ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := ENTITYID_UNKNOWN; + WITH_KEY : boolean := FALSE; -- TODO: Default + INLINE_QOS : OUTPUT_DATA_TYPE; + PUSH_MODE : boolean := TRUE; + ); + port ( + -- SYSTEM + clk : in std_logic; + reset : in std_logic; + time : in TIME_TYPE; + -- FROM RTPS_HANDLER (USER TRAFFIC) + empty_user : in std_logic; + rd_user : out std_logic; + data_in_user : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_user : in std_logic; + -- FROM RTPS_BUILTIN_ENDPOINT (META TRAFFIC) + empty_meta : in std_logic; + rd_meta : out std_logic; + data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0); + last_word_in_meta : in std_logic; + -- TO RTPS_BUILTIN_ENDPOINT (META TRAFFIC) + alive : out std_logic; + -- RTPS OUTPUT + wr_rtps : out std_logic; + full_rtps : in std_logic; + last_word_out_rtps : out std_logic; + data_out_rtps : out std_logic_vector(WORD_WIDTH-1 downto 0); + -- FROM HC + assert_liveliness : 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; + data_in_hc : in std_logic_vector(WORD_WIDTH-1 downto 0); + valid_in_hc : in std_logic; + ready_in_hc : out std_logic; + 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; + + ); +end entity; + +architecture arch of rtps_writer is + + --*****CONSTANT DECLARATION***** + -- *ENDPOINT MEMORY* + -- Endpoint Memory Size in 4-Byte Words + constant ENDPOINT_MEMORY_SIZE : natural := TODO; + -- Endpoint Memory Address Width + constant ENDPOINT_MEMORY_ADDR_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE); + -- Highest Endpoint Memory Address + constant ENDPOINT_MEMORY_MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH); + -- Highest Endpoint Frame Address + constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := ENDPOINT_MEMORY_MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1; + -- Address pointing to the beginning of the first Endpoint Data Frame + constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + + -- *ENDPOINT MEMORY FORMAT FORMAT FLAGS* + -- Flags mapping to the respective Endpoint Memory Frame Fields + constant EMF_FLAG_WIDTH : natural := 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 FORMAT* + -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame + constant EMF_ENTITYID_OFFSET : natural := 0; + constant EMF_GUIDPREFIX_OFFSET : natural := 1; + constant EMF_IPV4_ADDR_OFFSET : natural := 4; + constant EMF_UDP_PORT_OFFSET : natural := 5; + 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); + -- *Memory FSM Opcodes* + -- OPCODE DESCRIPTION + -- SEARCH_ENDPOINT Find Endpoint with specified GUID in memory + -- INSERT_ENDPOINT Insert Endpoint to first available empty_user slot in memory + -- UPDATE_ENDPOINT Update Endpoint pointed by mem_addr_base. (mem_field_flags specifies which Fields to update) + -- REMOVE_ENDPOINT Remove Endpoint pointed by mem_addr_base + -- GET_FIRST_ENDPOINT Get Endpoint Data of first Endpoint stored in Memory. (mem_field_flags specifies which Fields to get) + -- GET_NEXT_ENDPOINT Get Endpoint Data of next Endpoint (from the Endpoint pointed by mem_addr_base) stored in Memory. (mem_field_flags specifies which Fields to get) + -- GET_ENDPOINT Get Endpoint Data from Endpoint currently pointed by mem_addr_base. (mem_field_flags specifies which Fields to get) + type MEM_OPCODE_TYPE is (NOP, SEARCH_ENDPOINT, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, GET_FIRST_ENDPOINT, GET_NEXT_ENDPOINT, + GET_ENDPOINT); + -- Record of Endpoint Data + type ENDPOINT_DATA_TYPE is record + guid : GUID_TYPE; + addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); + 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(WORD_WIDTH-1 downto 0); + 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(WORD_WIDTH-1 downto 0); + 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 := IDLE; + -- FSM state latch. Used to transition dynamically to different states from the same state. + signal return_stage, return_stage_next : STAGE_TYPE := IDLE; + -- General Purpose Counter + signal cnt, cnt_next : natural range TODO := 0; + -- Packet Opcode Latch (RTPS Message ID) + signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0'); + -- Metatraffic Opcode Latch + signal meta_opcode, meta_opcode_next : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + -- Signifies if the received packet is a metatraffic operation + signal is_meta, is_meta_next : std_logic := '0'; + -- Source GUID Latch + signal guid, guid_next : GUID_TYPE := (others => (others => '0')); + -- Source IPv4 Address Latch + signal addr, addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); + -- UDP Port Latch + signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); + -- RTPS Header Flags Latch + signal rtps_flags, rtps_flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0'); + -- Remote Endpoint Reader Flags Latch + signal reader_flags, reader_flags_next : std_logic_vector(CDR_SHORT_WIDTH-1 downto 0) := (others => '0'); + -- Generic Sequence Number Latch + signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + -- Generic Sequence Number Latch + signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + -- Generic Sequence Number Latch + signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + -- General Purpose Long Latch + signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); + -- Toggle latching the "last_word_in_user" signal until reset + signal last_word_in_latch, last_word_in_latch_next : std_logic := '0'; + -- Toggle latch for Liveliness Assertion + signal assert_liveliness_latch, assert_liveliness_latch_next : std_logic := '0'; + -- Time of next Stale Endpoint Check + signal check_time, check_time_next : TIME_TYPE := TIME_INVALID; + -- Time of next Heartbeat sending + signal heartbeat_time, heartbeat_time_next : TIME_TYPE := TIME_INVALID; + -- Signifies if a Stale Endpoint Check is in progress + signal stale_check, stale_check_next : std_logic := '0'; + -- Signifies the new Cache Changes are currently being send out + signal new_push, new_push_next : std_logic := '0'; + -- Signifies that Historical Cache Changes are currently being sent out + signal historical_push, historical_push_next : std_logic := '0'; + -- 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 := '0'; + -- Signal containing the RTPS Heartbeat Count Field + signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '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 := SEQUENCENUMBER_UNKNOWN; + -- Signal containing the highest Sequence Number sent out by the writer + signal last_seq_nr, last_seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + -- Denotes the number of valid Bitmap longs (4-Byte words) + signal bitmap_cnt, bitmap_cnt_next : unsigned(log2c(MAX_BITMAP_WIDTH/CDR_LONG_WIDTH)-1 downto 0) := (others => '0'); + -- NumberSet Bitmap Latch + signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE := (others => (others => '0')); + -- Counter used to read out Bitmaps + signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length := 0; + -- Counter used to read out the In-Line QoS + signal cnt3, cnt3_next : natural range 0 to INLINE_QOS.length-1 := 0; + -- Signal used to iterate through NACK Bitmaps + signal nack_bitmap_pos, nack_bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1 := 0; + -- 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 := 0; + -- Signals the start of a Memory Operation + signal mem_op_start : std_logic := '0'; + -- Opcode of the Memory Operation (Valid only when mem_op_start is high) + signal mem_opcode : MEM_OPCODE_TYPE := NOP; + -- Signals the end of a Memory Operation + signal mem_op_done : std_logic := '0'; + -- Signal containing the relevant Endpoint Memory Format Fields of the Memory Operation + signal mem_field_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0'); + -- Signal used to pass Lease Deadlines from main to memory process + signal lease_deadline : TIME_TYPE := TIME_INVALID; + -- Signal used to pass Response Deadlines from main to memory process + signal res_time : TIME_TYPE := TIME_INVALID; + -- Signal used to pass Sequence Numbers from main to memory process + signal seq_nr : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; + -- 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(WORD_WIDTH-1 downto 0) := (others => '0'); + + -- *MEMORY PROCESS* + -- Memory FSM state + signal mem_stage, mem_stage_next : MEM_STAGE_TYPE := IDLE; + -- Pointer to current relevant Endpoint Address + signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + -- Help signal used to reset the MAX Endpoint Memory Pointer + signal last_addr, last_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + -- General Memory Address Latch + signal mem_addr_latch, mem_addr_latch_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + -- Highest Endpoint Memory Address (Points to first Address of last occupied Endpoint Frame) + signal max_endpoint_addr, max_endpoint_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + -- General Purpose Couter + signal mem_cnt, mem_cnt_next : natural range TODO := 0; + -- Latch for Endpoint Data from Memory + signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE := ZERO_ENDPOINT_DATA; + -- Latch for Endpoint Data from main process + signal mem_endpoint_latch_data, mem_endpoint_latch_data_next : ENDPOINT_LATCH_DATA_TYPE := ZERO_ENDPOINT_LATCH_DATA; + -- Position (In Endpoint Memory Frame Granularity) of current relevant Endpoint + signal mem_pos, mem_pos_next : natural range TODO := 0; + -- Signifies an abort of the currently initiated read transaction + signal abort_read : std_logic := '0'; + + -- *MEMORY CONTROL CONNECTION SIGNALS* + signal mem_addr : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal mem_ready_in, mem_valid_in : std_logic := '0'; + signal mem_ready_out, mem_valid_out : std_logic := '0'; + signal mem_read : std_logic := '0'; + + + --*****ALIAS DECLARATION***** + -- ENDPOINT FRAME HEADER + alias header_opcode : std_logic_vector(7 downto 0) is data_in_user(31 downto 24); + alias header_flags : std_logic_vector(7 downto 0) is data_in_user(23 downto 16); + alias header_udp_port : std_logic_vector(15 downto 0) is data_in_user(15 downto 0); + -- RTPS PARAMETER LIST HEADER + alias parameter_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16); + alias parameter_length : std_logic_vector(15 downto 0) is data_in_user(15 downto 0); + alias must_understand : std_logic is parameter_id(14); + -- RTPS DATA PAYLOAD HEADER + alias representation_id : std_logic_vector(15 downto 0) is data_in_user(31 downto 16); + alias representation_options : std_logic_vector(15 downto 0) is data_in_user(15 downto 0); + -- RTPS SUBMESSAGE FLAGS + alias endian_flag : std_logic is rtps_flags(0); + alias qos_flag : std_logic is rtps_flags(1); + alias data_flag : std_logic is rtps_flags(2); + alias key_flag : std_logic is rtps_flags(3); + alias final_flag : std_logic is rtps_flags(1); + alias payload_flag : std_logic is rtps_flags(4); + alias liveliness_flag : std_logic is rtps_flags(2); + -- 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 + ); + + -- Propagate Liveliness Assertion + alive <= assert_liveliness when (LIVELINESS_QOS /= MANUAL_BY_TOPIC_LIVELINESS_QOS) else '0'; + + -- *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 + -- 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 + -- PROCESS_NACK Process Requested (Negatively Acknowledged) Sequence Numbers + -- PARSE_NACK_BITMAP Parse the bitmap containing the requested Sequence Numbers + -- 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 := (others => (others => '0')); + -- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally) + variable tmp_bitmap : std_logic_vector(0 to MAX_BITMAP_WIDTH-1) := (others => '0'); + variable rd_guard : std_logic := '0'; + variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0'); + begin + -- DEFAULT Registered + stage_next <= stage; + meta_opcode_next <= meta_opcode; + cnt_next <= cnt; + cnt2_next <= cnt2; + 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; + seq_nr_next <= seq_nr; + 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; + -- DEFAULT Unregistered + mem_opcode <= NOP; + opcode_hc <= ADD_CACHE_CHANGE; + lease_deadline <= TIME_INVALID; + res_time <= TIME_INVALID; + rd_meta <= '0'; + rd_user <= '0'; + mem_op_start <= '0'; + start_hc <= '0'; + ready_in_dds <= '0'; + get_data_hc <= '0'; + wr_rtps <= '1'; + rd_guard := '0'; + mem_field_flags <= (others => '0'); + data_out_dds <= (others => '0'); + + -- Assert Liveliness Latch Setter + if (assert_liveliness = '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 (meta_stage) is + when IDLE => + -- RESET + addr_next <= (others => '0'); + portn_next <= (others => '0'); + is_meta_next <= '0'; + + -- New Cache Change in HC + if (data_available = '1') then + new_push_next <= '1'; + + stage_next <= GET_MAX_SN; + cnt_next <= 0; + -- Heartbeat Timeout + elsif ((RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and time >= heartbeat_time) or (LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS and assert_liveliness_latch = '1')) then + -- Reset + heartbeat_time_next <= time + HEARTBEAT_PERIOD; + + -- Increment Heartbeat Count + count_next <= count + 1; + + stage_next <= GET_MIN_SN; + cnt_next <= 0; + -- Stale Check Timeout + elsif (RELIABILTY_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 OPCODE_ENDPOINT_MATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_ENDPOINT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when OPCODE_PARTICIPANT_UNMATCH => + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + when others => + stage_next <= SKIP_META_OPERATION; + end case; + -- Input FIFO Guard + elsif (empty_user = '0') then + rd_guard := '1'; + + -- Latch Opcode + opcode_next <= header_opcode; + -- Latch Flags + rtps_flags_next <= header_flags; + -- Latch Source UDP Port + portn_next <= header_udp_port; + + + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + stage_next <= LATCH_SRC_ADDR; + -- SANITY CHECK: Skip Packet if non-standard Payload + if(header_opcode = SID_DATA and payload_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_guard := '1'; + end if; + cnt_next <= cnt + 1; + + case (cnt) is + -- GUID Prefix 1/3 + when 0 => + if (is_meta = '1') then + guid_next(0) <= data_in_meta; + else + guid_next(0) <= data_in_user; + end if; + -- GUID Prefix 2/3 + when 1 => + if (is_meta = '1') then + guid_next(1) <= data_in_meta; + else + guid_next(1) <= data_in_user; + end if; + -- GUID Prefix 3/3 + when 2 => + if (is_meta = '1') then + guid_next(2) <= data_in_meta; + else + guid_next(2) <= data_in_user; + end if; + + if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; + -- DONE Parsing + stage_next <= INITIATE_ENDPOINT_SEARCH; + else + stage_next <= LATCH_ENTITYID; + end if; + end case; + end if; + when LATCH_ENTITYID => + -- Input FIFO Guard + if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then + if (is_meta = '1') then + assert (meta_opcode /= OPCODE_ENDPOINT_UNMATCH or (meta_opcode = OPCODE_ENDPOINT_UNMATCH and last_word_in_meta = '1')) "last_word_in_meta not set" severity FAILURE; + rd_meta <= '1'; + guid_next(3) <= data_in_meta; + -- Memory Operation Guard + else + rd_guard := '1'; + guid_next(3) <= data_in_user; + end if; + stage_next <= INITIATE_ENDPOINT_SEARCH; + end if; + when INITIATE_ENDPOINT_SEARCH => + -- Memory Operation Guard + if (mem_op_done = '1') then + + if (is_meta = '1') then + + case (meta_opcode) is + when OPCODE_ENDPOINT_MATCH => + mem_op_start <= '1'; + mem_opcode <= SEARCH_ENDPOINT; + mem_field_flags <= (others => '0'); + stage_next <= LATCH_ENDPOINT_DATA; + cnt_next <= 0; + when OPCODE_ENDPOINT_UNMATCH => + mem_op_start <= '1'; + mem_opcode <= SEARCH_ENDPOINT; + mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG; + stage_next <= METATRAFFIC_OPERATION; + when OPCODE_PARTICIPANT_UNMATCH => + mem_op_start <= '1'; + mem_opcode <= GET_FIRST_ENDPOINT; + mem_field_flags <= EMF_GUIDPREFIX_FLAG; + stage_next <= METATRAFFIC_OPERATION; + cnt_next <= 0; + when others => + null; + end case; + else + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + case (opcode) is + when SID_ACKNACK => + stage_next <= LATCH_ACKNACK; + mem_op_start <= '1'; + mem_opcode <= SEARCH_ENDPOINT; + mem_field_flags <= EMF_ACK_SEQ_NR_BASE_FLAG or EMF_RES_TIME_FLAG or EMF_REQ_SEQ_NR_BASE_FLAG or EMF_REQ_SEQ_NR_BITMAP_FLAG; + cnt_next <= 0; + 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'; + cnt_next <= cnt + 1; + + case (cnt) is + -- IPv4 Address + when 0 => + addr_next <= data_in_meta; + -- UDP Port + when 1 => + assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE; + + portn_next <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1); + 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 OPCODE_ENDPOINT_MATCH => + -- Endpoint already in Memory + if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Update the Endpoint Data + -- NOTE: The Lease Duration is NOT updated in case of an update. That is the responsibility of the Liveliness Update + mem_op_start <= '1'; + mem_opcode <= UDPATE_ENDPOINT; + mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG; + end if; + -- DONE + stage_next <= IDLE; + else + -- Insert Matched Remote Endpoint + mem_op_start <= '1'; + mem_opcode <= INSERT_ENDPOINT; + + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and LEASE_DURATION /= DURATION_INFINITE and reader_flags(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 + seq_nr <= SEQUENCENUMBER_UNKNOWN when (reader_flags(BEST_EFFORT_FLAG) = '1') else (others => (others => '0')); + + -- Reader needs Historical Data + if (reader_flags(SEND_HISTORICAL_DATA_FLAG) = '1') then + -- Send Historical Data + historical_push_next <= '1'; + + stage_next <= GET_MIN_SN; + cnt_next <= 0; + else + -- DONE + stage_next <= IDLE; + end if; + end if; + when OPCODE_ENDPOINT_UNMATCH => + -- Endpoint not in Memory + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- Ignore + stage_next <= IDLE; + else + -- Propagate Removal + start_hc <= '1'; + opcode_hc <= REMOVE_WRITER; + data_out_dds <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); + -- Wait for Operation Acknowledgement + if (res_hc = ACK) then + -- Remove Unmatched Remote Endpoint + mem_op_start <= '1'; + mem_opcode <= REMOVE_ENDPOINT; + + -- Global ACK SN possibly changed + if (RELIABILTY_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; + end if; + when OPCODE_PARTICIPANT_UNMATCH => + case (cnt) is + when 0 => + -- Reached End of Endpoints + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- Global ACK SN possibly changed + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and global_ack_seq_nr_base /= SEQUENCENUMBER_UNKNOWN) then + -- 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; + cnt_next <= 0; + when others => + null; + end case; + when others => + null; + end case; + end if; + when LATCH_SRC_ADDR => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Input FIFO Guard + if (empty_user = '0') then + rd_guard := '1'; + + -- Latch Source IP Address + addr_next <= data_in_user; + + stage_next <= LATCH_GUIDPREFIX; + cnt_next <= 0; + end if; + end if; + when LATCH_ACKNACK => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Input FIFO Guard + if (empty_user = '0') then + rd_guard := '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- ReaderSNState.Base 1/2 + when 1 => + nack_base_next(0) <= unsigned(data_in_user); + -- ReaderSNState.Base 2/2 + when 2 => + nack_base_next(1) <= unsigned(data_in_user); + -- ReaderSNState.NumBits + when 3 => + 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)); + cnt2_next <= 0; + -- ReaderSNState.Bitmap + when 4 => + -- Read Bitmap + if (cnt2 < bitmap_cnt) then + cnt2_next <= cnt2 + 1; + + bitmap_latch_next(cnt2) <= data_in_user; + + -- Keep Sub-State + cnt_next <= cnt; + else + stage_next <= PROCESS_ACK; + end if; + when others => + null; + end case; + end if; + end if; + when PROCESS_ACK => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Wait for Endpoint Search + if (mem_op_done = '1') then + -- 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; + + -- New Sequence Numbers are ACKed + if (ack_base > mem_endpoint_data.ack_seq_nr_base) then + -- Update ACK Sequence Number Base + mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or 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 be updated, 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; + else + -- NACK Bitmap is not Empty + if (long_latch /= (long_latch'range => '0')) then + stage_next <= PROCESS_NACK; + cnt_next <= 0; + else + -- DONE + stage_next <= SKIP_PACKET; + end if; + end if; + else + -- Skip + stage_next <= SKIP_PACKET; + end if; + end if; + end if; + when UPDATE_GLOBAL_ACK => + -- Synthesis Guard + if (RELIABILTY_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 => + -- 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 <= 2; + else + -- NACK Bitmap is not Empty + if (long_latch /= (long_latch'range => '0')) then + stage_next <= PROCESS_NACK; + cnt_next <= 0; + else + -- DONE + stage_next <= SKIP_PACKET; + 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 (res_hc = ACK) then + -- Exit Condition + if (global_ack_seq_nr_base = new_global_ack) then + -- NACK Bitmap is not Empty + if (long_latch /= (long_latch'range => '0')) then + stage_next <= PROCESS_NACK; + cnt_next <= 0; + else + -- DONE + stage_next <= SKIP_PACKET; + 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 PROCESS_NACK => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Memory Operation Guard + if (mem_op_done = '1') then + + case (cnt) is + -- Initiate Bitmap Parsing + when 0 => + -- No scheduled Acknack Response + if (mem_endpoint_data.res_time = TIME_INVALID) then + req_seq_nr_bitmap_next <= (others => '0'); + + stage_next <= PARSE_NACK_BITMAP; + cnt_next <= 0; + -- Currently in Acknack Response Delay + elsif (mem_endpoint_data.res_time(1)(0) = '0') then + req_seq_nr_bitmap_next <= mem_endpoint_data.req_seq_nr_bitmap; + + -- NOTE: If we already received a ACKNACK with requests, then we only add the requested SN that fit in the existing + -- "Request SN window" (i.e. the req_seq_nr_bitmap). We need to "align" the Bitmaps for that purpose. + if (nack_base > mem_endpoint_data.req_seq_nr_base) then + stage_next <= PARSE_NACK_BITMAP; + cnt_next <= 2; + elsif (nack_base = mem_endpoint_data.req_seq_nr_base) then + stage_next <= PARSE_NACK_BITMAP; + cnt_next <= 3; + else + stage_next <= PARSE_NACK_BITMAP; + cnt_next <= 1; + end if; + end if; + -- Check Requested Sequence Numbers + when 1 => + if (mem_endpoint_data.res_time = TIME_INVALID) 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; + 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 + -- New Sequence Numbers Requested + if ((req_bitmap_pos or mem_endpoint_data.req_seq_nr_bitmap) /= mem_endpoint_data.req_seq_nr_bitmap) then + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_REQ_SEQ_NR_BITMAP_FLAG; + end if; + end if; + + -- DONE + stage_next <= SKIP_PACKET; + when others => + null; + end case; + end if; + end if; + when PARSE_NACK_BITMAP => + -- Synthesis Guard + if (RELIABILTY_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 + cnt_next <= 3; + else + nack_bitmap_pos_next <= nack_bitmap_pos + 1; + nack_base_next <= nack_base + 1; + end if; + -- Adjust NACK Bitmap (REQ Base > NACK Base) + when 1 => + -- Bitmaps Adjusted + if (nack_base = mem_endpoint_data.req_seq_nr_base) then + cnt_next <= 3; + else + -- Reached End of Bitmap (NACK Bitmap out of window) + if (nack_bitmap_pos = unsigned(long_latch)) then + -- DONE (Nothing to update) + stage_next <= SKIP_PACKET; + else + nack_bitmap_pos_next <= nack_bitmap_pos + 1; + nack_base_next <= nack_base + 1; + end if; + end if; + -- Abjust REQ Bitmap (REQ Base < NACK Base) + when 2 => + -- Bitmaps Adjusted + if (nack_base = mem_endpoint_data.req_seq_nr_base) then + cnt_next <= 3; + else + -- Reached End of Bitmap (NACK Bitmap out of window) + if (req_bitmap_pos = req_seq_nr_base'length-1) then + -- DONE (Nothing to update) + stage_next <= SKIP_PACKET; + else + -- NOTE: Instead of incrementing the req_seq_nr_base, we decrement the nack_base + req_bitmap_pos_next <= req_bitmap_pos + 1; + nack_base_next <= nack_base - 1; + end if; + end if; + -- Parse Rest + when 3 => + nack_bitmap_pos_next <= nack_bitmap_pos + 1; + -- Next Requested Sequence Number + if (tmp_bitmap(nack_bitmap_pos) = '1') then + req_bitmap_pos_next <= req_bitmap_pos + 1; + req_seq_nr_bitmap_next(req_bitmap_pos) <= '1'; + end if; + + -- End of Bitmap + if (nack_bitmap_pos = long_latch or req_bitmap_pos = req_seq_nr_base'length-1) then + stage_next <= PROCESS_NACK; + cnt_next <= 1; + end if; + -- Find Requested + when others => + null; + end case; + end if; + when ENDPOINT_STALE_CHECK => + -- Synthesis Guard + if (RELIABILTY_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; + cnt_next <= 1; + -- Check Endpoint + when 1 => + -- End of Endpoints + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- Reset + stale_check_next <= '0'; + -- DONE + stage_next <= IDLE; + else + -- Endpoint Lease Expired + if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline <= time) then + -- Remove Participant + mem_op_start <= '1'; + mem_opcode <= REMOVE_ENDPOINT; + -- Continue Search + cnt_next <= 0; + -- Synthesis Guard/Response Time Reached + elsif (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.res_time <= time) then + -- If Suppression Delay passed, zero the time + if(mem_endpoint_data.res_time(1)(0) = '1') then + -- Disable Suppression + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + res_time <= TIME_INVALID; + mem_field_flags <= 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; + + -- Send Requests + stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; + next_seq_nr_next <= mem_endpoint_data.req_seq_nr_base; + req_bitmap_pos_next <= 0; + end if; + else + -- Update Check Time + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then + if (mem_endpoint_data.res_time < check_time) then + check_time_next <= mem_endpoint_data.res_time; + end if; + else + if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline < check_time) then + check_time_next <= mem_endpoint_data.lease_deadline; + end if; + end if; + + -- Continue Search + cnt_next <= 0; + end if; + end if; + when 2 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + 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 + -- Set Acknack Suppression Time + res_time <= time + ACKNACK_SUPPRESSION_DELAY; + -- NOTE: Last Bit denotes if this is Response or Suppression Delay + res_time(1)(0) <= '1'; + + -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) + -- Update Check Time + if ((time + ACKNACK_SUPPRESSION_DELAY) < check_time) then + check_time_next <= time + ACKNACK_SUPPRESSION_DELAY; + 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 => + case (cnt) is + -- GET MIN Sequence Number + when 0 => + start_hc <= '1'; + opcode_hc <= GET_MIN_SN; + + if (ack_hc = '1') then + cnt_next <= cnt + 1; + end if; + -- READ MIN Sequence Number 1/2 + when 1 => + ready_in_hc <= '1'; + -- Input Guard + if (valid_in_hc = '1') then + min_sn_next(0) <= data_in_hc; + cnt_next <= cnt + 1; + end if; + -- READ MIN Sequence Number 2/2 + when 2 => + ready_in_hc <= '1'; + -- Input Guard + if (valid_in_hc = '1') then + min_sn_next(1) <= data_in_hc; + assert (last_word_in_hc = '1') severity FAILURE; + + if (historical_push = '1') then + stage_next <= HANDLE_HISTORICAL; + cnt_next <= 4; -- Pre-Check Sub-state + elsif (RELIABILTY_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 others => + null; + end case; + when GET_MAX_SN => + case (cnt) is + -- GET MAX Sequence Number + when 0 => + start_hc <= '1'; + opcode_hc <= GET_MAX_SN; + + if (ack_hc = '1') then + cnt_next <= cnt + 1; + end if; + -- READ MAX Sequence Number 1/2 + when 1 => + ready_in_hc <= '1'; + -- Input Guard + if (valid_in_hc = '1') then + max_sn_next(0) <= data_in_hc; + cnt_next <= cnt + 1; + end if; + -- READ MAX Sequence Number 2/2 + when 2 => + ready_in_hc <= '1'; + -- Input Guard + if (valid_in_hc = '1') then + max_sn_next(1) <= data_in_hc; + assert (last_word_in_hc = '1') severity FAILURE; + + -- EXIT + if (new_push = '1') then + + -- NOTE: If PUSH_MODE = FALSE, we manually update the last_seq_nr signal, since thsi is + -- not done anymore. + + -- Synthesis Guard + if (PUSH_MODE) then + stage_next <= HANDLE_NEW; + cnt_next <= 0; + else + tmp_dw := (0 => max_sn(0), 1 => unsigned(data_in_hc)); + + -- New higher Sequence Number Available + if (tmp_dw /= SEQUENCENUMBER_UNKNOWN and tmp_dw > last_seq_nr) then + last_seq_nr_next <= tmp_dw; + end if; + -- DONE + stage_next <= IDLE; + end if; + else + assert FALSE severity FAILURE; + end if; + end if; + when others => + null; + end case; + when HANDLE_REQUESTS => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + case (cnt) is + -- Find SN + when 0 => + -- End of Bitmap + if (req_bitmap_pos = req_seq_nr_bitmap'length) 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; + return_stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; + else + -- DONE + stage_next <= ENDPOINT_STALE_CHECK; + cnt_next <= cnt + 2; + end if; + -- Next Requested SN found + elsif (mem_endpoint_data.req_seq_nr_bitmap(req_bitmap_pos) = '1') then + cnt_next <= cnt + 1; + else + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + end if; + -- Get SN + when 1 => + 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 2 => + -- Wait until Operation Response + if (done_hc = '1') then + -- Wait for Operation Response + if (ret_hc = ACK) then + get_data_hc <= '1'; + if (gap_in_progress = '1') then + -- Close GAP and send DATA + gap_in_progress_next <= '0'; + stage_next <= SEND_GAP_B; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + else + -- Send DATA + stage_next <= SEND_HEADER; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + 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; + return_stage_next <= SEND_GAP_A; + cnt_next <= 0; + end if; + end if; + end if; + when others => + null; + end case; + end case; + when HANDLE_HEARTBEATS => + -- Synthesis Guard + if (RELIABILTY_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 Hertbeat 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; + return_stage_next <= SEND_HEARTBEAT; + 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; + cnt_next <= cnt + 1; + end if; + -- GET SN + when 1 => + 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; + -- READ SN + when 2 => + -- Wait until Operation Response + if (done_hc = '1') then + -- Cache Change Available + if (ret_hc = ACK) then + cnt_next <= cnt + 1; + -- Cache Change Unavailable + else + report "New Cache Change unavailable" severity ERROR; + cnt_next <= 0; + end if; + end if; + -- Get First Reader + when 3 => + -- 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 + 2; + 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; + cnt_next <= cnt + 1; + end if; + -- Initiate Send + when 5 => + -- 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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS or global_ack_seq_nr_base = SEQUENCENUMBER_UNKNOWN) then + start_hc <= '1'; + opcode_hc <= ACK_CACHE_CHANGE; + 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 + stage_next <= SEND_HEADER; + return_stage_next <= SEND_DATA_A; + cnt_next <= 0; + end if; + end if; + when others => + null; + end case; + end if; + when HANDLE_HISTORICAL => + 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; + return_stage_next <= HANDLE_HISTORICAL; + cnt_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 + cnt_next <= (cnt + 1) when (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(BEST_EFFORT_FLAG) = '0') else (cnt + 2); + end if; + -- NACK SN + when 1 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + start_hc <= '1'; + opcode_hc <= NACK_CACHE_CHANGE; + seq_nr_hc <= next_seq_nr; + + -- NOTE: Ignore Return Code + + -- 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 = ACK) then + get_data_hc <= '1'; + if (gap_in_progress = '1') then + -- Close GAP and send DATA + gap_in_progress_next <= '0'; + stage_next <= SEND_GAP_B; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + else + -- Send DATA + stage_next <= SEND_HEADER; + return_stage_next <= SEND_INFO_TS when (DESTINATION_ORDER_QOS = BY_SOURCE_TIMESTAMP_DESTINATION_ORDER_QOS) else SEND_DATA_A; + 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; + return_stage_next <= SEND_GAP_A; + 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 + cnt_next <= 1 when (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and reader_flags(BEST_EFFORT_FLAG) = '0') else 2; + end if; + when others => + null; + end case; + when SEND_HEADER => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + -- Output FIFO Guard + if (full_rtps = '0') then + wr_sig <= '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- OUTPUT HEADER + -- Src IPv4 Address + when 0 => + data_out_rtps <= DEFAULT_IPv4_ADDRESS; + -- Dest IPv4 Address + when 1 => + data_out_rtps <= mem_endpoint_data.addr; + -- Src and Dest UDPv4 Ports + when 2 => + data_out_rtps <= USER_IPv4_UNICAST_PORT & mem_endpoint_data.portn; + -- RTPS MESSAGE HEADER + when 3 => + data_out_rtps <= PROTOCOL_RTPS; + when 4 => + data_out_rtps <= PROTOCOLVERSION_2_4 & VENDORID; + when 5 => + data_out_rtps <= GUIDPREFIX(0); + when 6 => + data_out_rtps <= GUIDPREFIX(1); + when 7 => + data_out_rtps <= GUIDPREFIX(2); + -- Continue with respective RTPS Submessage + stage_next <= return_stage; + cnt_next <= 0; + when others => + null; + end case; + end if; + end if; + when SEND_INFO_TS => + -- Output FIFO Guard + if (full_rtps = '0') then + wr_rtps <= '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- INFO_TS RTPS SUBMESSAGE + -- RTPS Submessage Header + when 0 => + data_out_rtps <= SID_INFO_TS & "00000000" & std_logic_vector(to_unsigned(8, SUBMESSAGE_LENGTH_WIDTH)); + -- Source Timestamp 1/2 + when 1 => + data_out_rtps <= cc_source_timestamp(0); + -- Writer Entity ID + when 2 => + data_out_rtps <= cc_source_timestamp(1); + + stage_next <= SEND_DATA_A; + cnt_next <= 0; + when others => + null; + end case; + end if; + when SEND_DATA_A => + -- Output FIFO Guard + if (full_rtps = '0') then + case (cnt) is + -- DATA RTPS SUBMESSAGE + -- RTPS Submessage Header + when 0 => + -- Operation has no Data + if (cc_kind /= ALIVE) then + -- Set KEY Flag + data_out_rtps <= SID_DATA & "00001010" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH)); + wr_sig <= '1'; + else + -- Set DATA Flag + data_out_rtps <= SID_DATA & "00000110" & std_logic_vector(to_unsigned(0, SUBMESSAGE_LENGTH_WIDTH)); + wr_sig <= '1'; + end if; + cnt_next <= cnt + 1; + -- extraFlags, octetsToInlineQoS + when 1 => + data_out_rtps <= x"0000" & std_logic_vector(to_unsigned(16, 16)); + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Reader Entity ID + when 2 => + data_out_rtps <= ENTITYID_UNKNOWN; + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Writer Entity ID + when 3 => + data_out_rtps <= ENTITYID; + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Sequence Number 1/2 + when 4 => + data_out_rtps <= std_logic_vector(next_seq_nr(0)); + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Sequence Number 2/2 + when 5 => + data_out_rtps <= std_logic_vector(next_seq_nr(1)); + wr_sig <= '1'; + if (cc_kind /= ALIVE) then + cnt_next <= cnt + 1; + else + cnt_next <= cnt + 2; + end if; + -- Status Info + when 6 => + data_out_rtps <= (others => '0'); + wr_sig <= '1'; + case (cc_kind) is + when ALIVE_FILTERED => + data_out_rtps(STATUS_INFO_FILTERED_FLAG) <= '1'; + when NOT_ALIVE_DISPOSED => + data_out_rtps(STATUS_INFO_DISPOSED_FLAG) <= '1'; + when NOT_ALIVE_UNREGISTERED => + data_out_rtps(STATUS_INFO_UNREGISTERED_FLAG) <= '1'; + when others => + null; + end case; + cnt_next <= cnt + 1; + -- Key Hash 1/4 + when 7 => + data_out_rtps <= std_logic_vector(cc_instance_handle(0)); + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Key Hash 2/4 + when 8 => + data_out_rtps <= std_logic_vector(cc_instance_handle(1)); + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Key Hash 3/4 + when 9 => + data_out_rtps <= std_logic_vector(cc_instance_handle(2)); + wr_sig <= '1'; + cnt_next <= cnt + 1; + -- Key Hash 4/4 + when 10 => + data_out_rtps <= std_logic_vector(cc_instance_handle(3)); + wr_sig <= '1'; + if (mem_endpoint_data.flags(EXPECTS_INLINE_QOS_FLAG) = '1') then + stage_next <= SEND_INLINE_QOS; + cnt3_next <= 0; + else + cnt_next <= cnt + 1; + end if; + -- Sentinel + when 11 => + data_out_rtps <= PID_SENTINEL & std_logic_vector(to_unsigned(0, 16)); + wr_sig <= '1'; + stage_next <= SEND_DATA_B; + when others => + null; + end case; + end if; + when SEND_INLINE_QOS => + -- Output FIFO Guard + if (full_rtps = '0') then + data_out_rtps <= INLINE_QOS.data(cnt3); + wr_sig <= '1'; + cnt3_next <= cnt3 + 1; + + -- Exit Condition + if (cnt3 = INLINE_QOS.length-1) then + stage_next <= SEND_DATA_B; + end if; + end if; + when SEND_DATA_B => + -- Output FIFO Guard + if (full_rtps = '0') then + ready_in_hc <= '1'; + + if (valid_in_hc = '1') then + data_out_rtps <= data_in_hc; + wr_sig <= '1'; + + if (last_word_in_hc = '1') then + last_word_out_rtps = '1'; + + -- Continue + if (stale_check = '1') then + stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + elsif (new_push = '1') then + stage_next <= HANDLE_NEW; + cnt_next <= 4; + elsif (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_rtps = '0') then + wr_sig <= '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- DATA RTPS SUBMESSAGE (Participant Message) + -- RTPS Submessage Header + when 0 => + data_out <= SID_GAP & "00000000" & std_logic_vector(to_unsigned(28, 16)); + -- Reader Entity ID + when 1 => + data_out <= ENTITYID_UNKNOWN; + -- Writer Entity ID + when 2 => + data_out <= ENTITYID; + -- GAP Start Sequence Number 1/2 + when 3 => + data_out <= std_logic_vector(next_seq_nr(0)); + -- GAP Start Sequence Number 2/2 + when 4 => + data_out <= std_logic_vector(next_seq_nr(1)); + + -- Continue + if (stale_check = '1') then + stage_next <= HANDLE_REQUESTS; + cnt_next <= 0; + req_bitmap_pos_next <= req_bitmap_pos + 1; + next_seq_nr_next <= next_seq_nr + 1; + elsif (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_rtps = '0') then + wr_sig <= '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- GAP List Sequence Number Set (Bitmap Base 1/2) + when 0 => + data_out <= std_logic_vector(next_seq_nr(0)); + -- GAP List Sequence Number Set (Bitmap Base 2/2) + when 1 => + data_out <= std_logic_vector(next_seq_nr(1)); + -- GAP List Sequence Number Set (NumBits) + when 2 => + data_out <= (others => '0'); + + -- Continue + stage_next <= return_stage; + cnt_next <= 0; + when others => + null; + end case; + end if; + when SEND_HEARTBEAT => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS or LIVELINESS_QOS = MANUAL_BY_TOPIC_LIVELINESS_QOS) then + -- Output FIFO Guard + if (full_rtps = '0') then + wr_sig <= '1'; + cnt_next <= cnt + 1; + + case (cnt) is + -- HEARTBEAT RTPS SUBMESSAGE + -- RTPS Submessage Header + when 0 => + if (assert_liveliness_latch = '1') then + data_out <= SID_HEARTBEAT & "00000100" & std_logic_vector(to_unsigned(28, 16)); + else + data_out <= SID_HEARTBEAT & "00000000" & std_logic_vector(to_unsigned(28, 16)); + end if; + -- Reader Entity ID + when 1 => + data_out <= ENTITYID_UNKNOWN; + -- Writer Entity ID + when 2 => + data_out <= ENTITYID; + -- First Sequence Number 1/2 + when 3 => + data_out <= std_logic_vector(min_sn(0)); + -- First Sequence Number 2/2 + when 4 => + data_out <= std_logic_vector(min_sn(1)); + -- Last Sequence Number 1/2 + when 5 => + data_out <= std_logic_vector(last_seq_nr(0)); + -- Last Sequence Number 2/2 + when 6 => + data_out <= std_logic_vector(last_seq_nr(1)); + -- Count + when 7 => + data_out <= std_logic_vector(count); + + stage_next <= HANDLE_HEARTBEATS; + cnt_next <= 1; + when others => + null; + end case; + end if; + end if; + when SKIP_PACKET => + -- NOTE: At the end of a Stale Entry Removal this stage is entered, without having started reading a Packet from input. + -- Reset Parameter End + parameter_end_next <= (others => '1'); + + -- Stale Check Exit + if (stale_check = '1') then + -- DONE + stage_next <= IDLE; + -- Consumed last word of Packet + elsif (last_word_in_latch = '1' and last_word_in_user = '0') then + -- Reset Last Word In Latch + last_word_in_latch_next <= '0'; + -- DONE + stage_next <= IDLE; + -- Input FIFO Guard + elsif (empty_user = '0') then + -- Skip-Read + rd_guard := '1'; + end if; + when SKIP_META_OPERATION => + -- Skip-Read + rd_meta <= '1'; + + -- Exit Condition + if (last_word_in_meta = '1') then + stage_next <= IDLE; + end if; + when others => + null; + end case; + + -- OVERREAD GUARD + -- Read outside of packet Length + -- NOTE: If the Packet Length is smaller than expected there will be a read from input FIFO while + -- the Packet Length has been reached and will be caught by this clause. + -- The SKIP_PACKET clause prevents a read signal from occuring in this situation, and thus prevents from entering this state. + if ((last_word_in_latch = '1' and last_word_in_user = '0') and rd_guard = '1') then + -- Force rd_sig low + rd_sig <= '0'; + -- Continue parsing next Packet + stage_next <= IDLE; + -- Reset Last Word In Latch + last_word_in_latch_next <= '0'; + -- DEFAULT + else + rd_sig <= rd_guard; + end if; + end process; + + -- *Memory State Machine* + -- STATE DESCRIPTION + -- IDLE Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations + -- SEARCH_ENDPOINT See Memory OPCODE Description + -- GET_ENDPOINT_DATA Latch specified Endpoint Data for use by main FSM + -- INSERT_ENDPOINT See Memory OPCODE Description + -- UPDATE_ENDPOINT See Memory OPCODE Description + -- REMOVE_ENDPOINT See Memory OPCODE Description + -- FIND_EMPTY_SLOT Find first empty_user slot in memory. + -- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory. + -- GET_NEXT_ENDPOINT See Memory OPCODE Description + 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; + mem_guidprefix_next <= mem_guidprefix; + max_endpoint_addr_next <= max_endpoint_addr; + mem_endpoint_latch_data_next <= mem_endpoint_latch_data; + mem_pos_next <= mem_pos; + -- DEFAULT Unregistered + mem_addr <= (others => '0'); + mem_write_data <= (others => '0'); + mem_read <= '0'; + mem_valid_in <= '0'; + mem_ready_out <= '0'; + mem_op_done <= '0'; + abort_read <= '0'; + + + case (mem_stage) is + when IDLE => + mem_op_done <= '1'; + + if (mem_op_start = '1') then + -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) + mem_endpoint_latch_data_next <= ( + guid => guid_next, + addr => addr_next, + portn => portn_next, + 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 => + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_pos_next <= 0; + mem_stage_next <= SEARCH_ENDPOINT; + mem_cnt_next <= 0; + when INSERT_ENDPOINT => + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_pos_next <= 0; + mem_stage_next <= FIND_EMPTY_SLOT; + mem_cnt_next <= 0; + when UPDATE_ENDPOINT => + mem_stage_next <= UPDATE_ENDPOINT; + if check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 0; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 1; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 2; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 4; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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; + when REMOVE_ENDPOINT => + mem_stage_next <= REMOVE_ENDPOINT; + mem_cnt_next <= 0; + when GET_FIRST_ENDPOINT => + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_pos_next <= 0; + mem_stage_next <= GET_NEXT_ENDPOINT; + mem_cnt_next <= 0; + when GET_NEXT_ENDPOINT => + -- Memory Bound Guard + if (mem_addr_base /= max_endpoint_addr) then + -- Reached End of Memory, No match + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_stage_next <= GET_NEXT_ENDPOINT; + mem_cnt_next <= 0; + else + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; + end if; + when GET_ENDPOINT => + -- Fetch Endpoint Data + mem_stage_next <= GET_ENDPOINT_DATA; + mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; + if check_mask(mem_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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; + 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 + -- 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; + abort_read <= '1'; + 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 + -- 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; + abort_read <= '1'; + 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 + -- 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; + abort_read <= '1'; + 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 + -- 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; + abort_read <= '1'; + 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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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/ 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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- GET Response Time 2/2 + when 9 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 + when 20 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.portn <= mem_read_data; + + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 21; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- READ Lease Deadline 2/2 + when 22 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.addr <= mem_read_data; + + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 23; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.res_time(0) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- READ Response Time 2/2 + when 24 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.res_time(1) <= mem_read_data; + + if (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- READ ACK Sequence Number 2/2 + when 26 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.ack_seq_nr_base(1) <= mem_read_data; + + if (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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) <= 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 (RELIABILTY_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) <= mem_read_data; + + if (RELIABILTY_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 (RELIABILTY_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 + when 5 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; + mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0'); + if (mem_ready_in = '1') then + if (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_write_data <= (others => '0'); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- Response Time 2/2 + when 9 => + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_write_data <= (others => '0'); + 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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET; + mem_write_data <= seq_nr(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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_write_data <= (others => '0'); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ACK_SEQ_NR_BASE_OFFSET + 1; + mem_write_data <= seq_nr(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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_REQ_SEQ_NR_BASE_OFFSET; + mem_write_data <= 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 (RELIABILTY_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 <= 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 (RELIABILTY_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.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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 2; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 4; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 + when 1 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; + mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0'); + mem_endpoint_data.portn <= mem_endpoint_latch_data.portn; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 2; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 4; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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.lease_deadline <= mem_endpoint_latch_data.lease_deadline; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 4; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.res_time(0)); + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- Response Time 2/2 + when 5 => + -- Synthesis Guard + if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.res_time(1)); + mem_endpoint_data.res_time <= mem_endpoint_latch_data.res_time; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_ACK_SEQ_NR_BASE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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') + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- ACK Sequence Number 2/2 + when 7 => + -- Synthesis Guard + if (RELIABILTY_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.ack_seq_nr_base <= mem_endpoint_latch_data.ack_seq_nr_base; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_REQ_SEQ_NR_BASE_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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') + mem_cnt_next <= mem_cnt + 1; + end if; + end if; + -- Request Sequence Number Base 2/2 + when 9 => + -- Synthesis Guard + if (RELIABILTY_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.req_seq_nr_base <= mem_endpoint_latch_data.req_seq_nr_base; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_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 (RELIABILTY_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.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_pos_next <= mem_pos + 1; + 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_pos_next <= mem_pos + 1; + 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 (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG)) then + mem_cnt_next <= 6; + elsif (RELIABILTY_QOS /= RELIABLE_RELIABILITY_QOS and check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG)) then + mem_cnt_next <= 8; + elsif (RELIABILTY_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 (RELIABILTY_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 (RELIABILTY_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; + +end architecture; \ No newline at end of file