-- altera vhdl_input_version vhdl_2008 -- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.math_pkg.all; use work.rtps_package.all; use work.user_config.all; use work.rtps_config_package.all; entity rtps_builtin_endpoint is generic ( MAX_REMOTE_PARTICIPANTS : natural := 50 ); port ( -- SYSTEM clk : in std_logic; reset : in std_logic; time : in TIME_TYPE; -- FROM RTPS HANDLER empty : in std_logic; rd : out std_logic; data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); last_word_in : in std_logic; -- FROM USER ENDPOINTS alive : in std_logic_vector(0 to NUM_ENDPOINTS-1); -- TO USER ENDPOINTS full_ue : in std_logic_vector(0 to NUM_ENDPOINTS-1); wr_ue : out std_logic_vector(0 to NUM_ENDPOINTS-1); data_out_ue : out std_logic_vector(WORD_WIDTH-1 downto 0); -- one-to-many (Multicast) Connection last_word_out_ue : out std_logic; -- one-to-many (Multicast) Connection -- RTPS OUTPUT full_ro : in std_logic; wr_ro : out std_logic; data_out_ro : out std_logic_vector(WORD_WIDTH-1 downto 0); last_word_out_ro : out std_logic ); end entity; architecture arch of rtps_builtin_endpoint is --*****CONSTANT DECLARATION***** -- Max Serialized Payload Size in a UDP Stream (Bytes) [MAX_PAYLOAD(65536) - IPv4_HEADER(20) - UDP_HEADER(8) - RTPS_HEADER(20) - DATA_HEADER(24)] constant UDP_MAX_SIZE_SERIALIZED : natural := 65464; -- Highest Sequence Number of Publisher Data constant PUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := to_double_word(to_unsigned(NUM_WRITERS, 64)); -- Highest Sequence Number of Subscriber Data constant SUB_SEQUENCENUMBER : SEQUENCENUMBER_TYPE := to_double_word(to_unsigned(NUM_READERS, 64)); -- Heartbeat/Liveliness Assertion Period constant HEARTBEAT_PERIOD : DURATION_TYPE := work.rtps_package.min(MIN_ENDPOINT_LEASE_DURATION, PARTICIPANT_HEARTBEAT_PERIOD) - DURATION_DELTA; -- *PARTICIPANT MEMORY* -- 4-Byte Word Size of a Participant Entry in Memory constant PARTICIPANT_FRAME_SIZE : natural := 24; -- Memory Size in 4-Byte Words constant PARTICIPANT_MEMORY_SIZE : natural := MAX_REMOTE_PARTICIPANTS * PARTICIPANT_FRAME_SIZE; -- Memory Address Width constant PARTICIPANT_MEMORY_ADDR_WIDTH : natural := log2c(PARTICIPANT_MEMORY_SIZE); -- Highest Memory Address constant PARTICIPANT_MEMORY_MAX_ADDRESS : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(PARTICIPANT_MEMORY_SIZE-1, PARTICIPANT_MEMORY_ADDR_WIDTH); -- Highest participant Frame Address constant MAX_PARTICIPANT_ADDRESS : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := PARTICIPANT_MEMORY_MAX_ADDRESS - PARTICIPANT_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Participant Data Frame constant FIRST_PARTICIPANT_ADDRESS : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); -- *PARTICIPANT MEMORY FRAME FIELD FLAGS* -- Flags mapping to the respective Participant Memory Frame Fields constant PMF_FLAG_WIDTH : natural := 14; constant PMF_NEXT_ADDR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (0 => '1', others => '0'); constant PMF_GUIDPREFIX_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (1 => '1', others => '0'); constant PMF_META_IPV4_ADDR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (2 => '1', others => '0'); constant PMF_DEFAULT_IPV4_ADDR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (3 => '1', others => '0'); constant PMF_UDP_PORT_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (4 => '1', others => '0'); constant PMF_SPDP_SEQ_NR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (5 => '1', others => '0'); constant PMF_LEASE_DURATION_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (6 => '1', others => '0'); constant PMF_LEASE_DEADLINE_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (7 => '1', others => '0'); constant PMF_EXTRA_FLAGS_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (8 => '1', others => '0'); constant PMF_ACKNACK_RES_TIME_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (9 => '1', others => '0'); constant PMF_HEARTBEAT_RES_TIME_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (10 => '1', others => '0'); constant PMF_PUB_SEQ_NR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (11 => '1', others => '0'); constant PMF_SUB_SEQ_NR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (12 => '1', others => '0'); constant PMF_MES_SEQ_NR_FLAG : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (13 => '1', others => '0'); -- *PARTICIPANT MEMORY FRAME FIELD OFFSETS* constant PMF_NEXT_ADDR_OFFSET : natural := 0; constant PMF_GUIDPREFIX_OFFSET : natural := 1; constant PMF_META_IPV4_ADDR_OFFSET : natural := 4; constant PMF_DEFAULT_IPV4_ADDR_OFFSET : natural := 5; constant PMF_UDP_PORT_OFFSET : natural := 6; constant PMF_SPDP_SEQ_NR_OFFSET : natural := 7; constant PMF_LEASE_DURATION_OFFSET : natural := 9; constant PMF_LEASE_DEADLINE_OFFSET : natural := 11; constant PMF_EXTRA_FLAGS_OFFSET : natural := 13; constant PMF_ACKNACK_RES_TIME_OFFSET : natural := 14; constant PMF_HEARTBEAT_RES_TIME_OFFSET : natural := 16; constant PMF_PUB_SEQ_NR_OFFSET : natural := 18; constant PMF_SUB_SEQ_NR_OFFSET : natural := 20; constant PMF_MES_SEQ_NR_OFFSET : natural := 22; -- *EXTRA FLAGS* -- Width of extra_flags signal constant EF_FLAG_WIDTH : natural := 3; -- Signifies that the Message Data (Liveliness) should be sent constant EF_MES_DATA_FLAG : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (0 => '1', others => '0'); -- Signifies that the Subscriber Data should be sent constant EF_SUB_DATA_FLAG : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (1 => '1', others => '0'); -- Signifies that the Publisher Data should be sent constant EF_PUB_DATA_FLAG : std_logic_vector(0 to EF_FLAG_WIDTH-1) := (2 => '1', others => '0'); -- *RECV FLAGS* -- Width of the received array constant RCVD_FLAG_WIDTH : natural := 9; -- Signifies that the DOMAIN_TAG was received constant RCVD_DOMAIN_TAG_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (0 => '1', others => '0'); -- Signifies that the DURABILITY QoS was received constant RCVD_DURABILITY_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (1 => '1', others => '0'); -- Signifies that the PRESENTATION QoS was received constant RCVD_PRESENTATION_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (2 => '1', others => '0'); -- Signifies that the DEADLINE QoS was received constant RCVD_DEADLINE_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (3 => '1', others => '0'); -- Signifies that the LATENCY_BUDGET QoS was received constant RCVD_LATENCY_BUDGET_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (4 => '1', others => '0'); -- Signifies that the OWNERSHIP QoS was received constant RCVD_OWNERSHIP_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (5 => '1', others => '0'); -- Signifies that the LIVELINESS QoS was received constant RCVD_LIVELINESS_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (6 => '1', others => '0'); -- Signifies that the RELIABILITY QoS was received constant RCVD_RELIABILITY_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (7 => '1', others => '0'); -- Signifies that the DESTINATION_ORDER QoS was received constant RCVD_DESTINATION_ORDER_QOS_FLAG : std_logic_vector(0 to RCVD_FLAG_WIDTH-1) := (8 => '1', others => '0'); --*****TYPE DECLARATION***** -- FSM states. Explained below in detail type STAGE_TYPE is (IDLE, PACKET_HEADER, PACKET_SRC_ADDR, PACKET_SRC_ENTITYID, PACKET_SRC_GUIDPREFIX, PACKET_DEST_ENTITYID, CHECK_SRC_ENTITYID, LATCH_SEQ_NR, PROCESS_DATA, PROCESS_MESSAGE_SEQUENCE_NUMBERS, PROCESS_MESSAGE, PROCESS_GAP, PROCESS_GAP_SEQUENCE_NUMBERS, FIND_NEXT_VALID_IN_BITMAP, PROCESS_PL, CHECK_DEFAULT, LATCH_STRING_LENGTH, COMPARE_STRING, RXO_DURABILITY, RXO_DEADLINE, RXO_LIVELINESS, RXO_LEASE_DURATION, LATCH_LEASE_DURATION, RXO_RELIABILITY, RXO_DESTINATION_ORDER, RXO_OWNERSHIP, RXO_PRESENTATION, RXO_PARTITION, RXO_LATENCY_BUDGET, CHECK_MAX_SIZE_SERIALIZED, MATCH_DOMAIN_ID, MATCH_PROTOCOL_VERSION, LATCH_LOCATOR, LATCH_EXPECTS_INLINE_QOS, MATCH_GUID, CHECK_REMOTE_BUILTIN_ENDPOINTS, CHECK_STATUS_INFO, PARTICIPANT_MATCH_STAGE, INFORM_ENDPOINTS_MATCH, INFORM_ENDPOINTS_UNMATCH, INFORM_ENDPOINTS_PARTICIPANT_UNMATCH, PARTICIPANT_STALE_CHECK, LATCH_REMOVED_GUIDPREFIX, PROCESS_HEARTBEAT, PROCESS_HEARTBEAT_SEQUENCE_NUMBERS, SEND_ACKNACK, SEND_HEARTBEAT, PROCESS_ACKNACK, PROCESS_ACKNACK_SEQUENCE_NUMBERS, FIND_PARTICIPANT_DEST, SEND_HEADER, SEND_PARTICIPANT_ANNOUNCEMENT, SEND_PUB_DATA, SEND_SUB_DATA, SEND_MES_MAN_LIVE, SEND_MES_GAP, SEND_MES_AUTO_LIVE, LIVELINESS_UPDATE, SKIP_PARAMETER, SKIP_PACKET); -- Memory FSM states. Explained below in detail type MEM_STAGE_TYPE is (IDLE, SEARCH_PARTICIPANT, GET_NEXT_PARTICIPANT, GET_PARTICIPANT_DATA, INSERT_PARTICIPANT, UPDATE_PARTICIPANT, REMOVE_PARTICIPANT, RESET_MEMORY); -- Memory FSM Opcodes -- OPCODE DESCRIPTION -- SEARCH_PARTICIPANT Search memory for Participant Entry with GUID Prefix equal to "guid" signal. -- Set "mem_addr_base" to Base Address of found Participant Entry or PARTICIPANT_MEMORY_MAX_ADDRESS if nothing found. -- "participant_data" contains memory Participant Data according to "mem_field_flags". -- INSERT_PARTICIPANT Write Participant Data to next avialable empty slot. -- UPDATE_PARTICIPANT Update the Participant Data of the Participant Entry pointed by "mem_addr_base" according to the "mem_field_flags" flags. -- REMOVE_PARTICIPANT Remove the Participant Entry pointed by "mem_addr_base". -- GET_FIRST_PATICIPANT Get Participant Data of first participant according to "mem_field_flags". -- "mem_addr_base" is set to the Address of the Participant, or PARTICIPANT_MEMORY_MAX_ADDRESS if no Participant in Memory -- GET_NEXT_PARTICIPANT Get Participant Data of next participant (from the one pointed by "mem_addr_base") according to "mem_field_flags". -- "mem_addr_base" is set to the Address of the Participant, or PARTICIPANT_MEMORY_MAX_ADDRESS if no Participant in Memory -- GET_PATICIPANT Get Participant Data of participant pointed by "mem_addr_update" according to "mem_field_flags". -- Already fetched Data of the same Participant is not modified type MEM_OPCODE_TYPE is (NOP, SEARCH_PARTICIPANT, INSERT_PARTICIPANT, UPDATE_PARTICIPANT, GET_FIRST_PARTICIPANT, GET_NEXT_PARTICIPANT, REMOVE_PARTICIPANT, GET_PARTICIPANT); -- RTPS Data Submessage Content: -- * PDP Simple Participant Discovery Protocol Data -- * EDP Simple Endpoint Discovery Protocol Data -- * MESSAGE Participant Message Data type MESSAGE_TYPE_TYPE is (NONE, PDP, EDP, MESSAGE); -- String Content type STRING_CONTENT_TYPE is (TOPIC_NAME_TYPE, TYPE_NAME_TYPE, DOMAIN_TAG_TYPE); -- Record of all Participant Data stored in memory type PARTICIPANT_DATA_TYPE is record guid_prefix : GUIDPREFIX_TYPE; meta_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); def_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); meta_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); def_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); extra_flags : std_logic_vector(EF_FLAG_WIDTH-1 downto 0); lease_duration : DURATION_TYPE; lease_deadline : TIME_TYPE; heartbeat_res_time : TIME_TYPE; acknack_res_time : TIME_TYPE; spdp_seq_nr : SEQUENCENUMBER_TYPE; pub_seq_nr : SEQUENCENUMBER_TYPE; sub_seq_nr : SEQUENCENUMBER_TYPE; mes_seq_nr : SEQUENCENUMBER_TYPE; end record; -- Zero initialized Participant Data constant ZERO_PARTICIPANT_DATA : PARTICIPANT_DATA_TYPE := ( guid_prefix => GUIDPREFIX_UNKNOWN, meta_addr => IPv4_ADDRESS_INVALID, def_addr => IPv4_ADDRESS_INVALID, meta_port => UDP_PORT_INVALID, def_port => UDP_PORT_INVALID, extra_flags => (others => '0'), lease_duration => DURATION_ZERO, lease_deadline => TIME_INVALID, heartbeat_res_time => TIME_INVALID, acknack_res_time => TIME_INVALID, spdp_seq_nr => SEQUENCENUMBER_UNKNOWN, pub_seq_nr => SEQUENCENUMBER_UNKNOWN, sub_seq_nr => SEQUENCENUMBER_UNKNOWN, mes_seq_nr => SEQUENCENUMBER_UNKNOWN ); type PARTICIPANT_LATCH_DATA_TYPE is record guid_prefix : GUIDPREFIX_TYPE; meta_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); def_addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); meta_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); def_port : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); extra_flags : std_logic_vector(EF_FLAG_WIDTH-1 downto 0); lease_duration : DURATION_TYPE; lease_deadline : TIME_TYPE; res_time : TIME_TYPE; seq_nr : SEQUENCENUMBER_TYPE; field_flags : std_logic_vector(0 to PMF_FLAG_WIDTH-1); end record; -- Zero initialized Participant Data constant ZERO_PARTICIPANT_LATCH_DATA : PARTICIPANT_LATCH_DATA_TYPE := ( guid_prefix => GUIDPREFIX_UNKNOWN, meta_addr => IPv4_ADDRESS_INVALID, def_addr => IPv4_ADDRESS_INVALID, meta_port => UDP_PORT_INVALID, def_port => UDP_PORT_INVALID, extra_flags => (others => '0'), lease_duration => DURATION_ZERO, lease_deadline => TIME_INVALID, res_time => TIME_INVALID, seq_nr => SEQUENCENUMBER_UNKNOWN, field_flags => (others => '0') ); --*****SIGNAL DECLARATION***** -- FSM state signal stage, stage_next : STAGE_TYPE; -- FSM state latch. Used to transition dynamically to different states from the same state. signal return_stage, return_stage_next : STAGE_TYPE; -- Intermediate input read signal. (Read from output port not allowed) signal rd_sig : std_logic; -- Signal used to reset the word counter signal reset_read_cnt : std_logic; -- Word (4-Byte) counter (Counts words read from input fifo) signal read_cnt : unsigned(SUBMESSAGE_LENGTH_WIDTH-3 downto 0); -- RTPS Submessage ID Latch signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0); -- RTPS Submessage Flags Latch signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0); -- UDPv4 Source Port Latch signal src_port, src_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); -- IPv4 Source Address Latch signal src_addr, src_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); -- Source Entity ID Latch signal src_entityid, src_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0); -- Destination Entity ID Latch signal dest_entityid, dest_entityid_next : std_logic_vector(ENTITYID_WIDTH-1 downto 0); -- Source GUID Latch signal guid, guid_next : GUID_TYPE; -- RTPS DATA Submessage Sequence Number Latch signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE; -- Word aligned End of Parameter signal parameter_end, parameter_end_next : unsigned(PARAMETER_LENGTH_WIDTH-1 downto 0); -- RTPS DATA Submessage Content Type signal message_type, message_type_next : MESSAGE_TYPE_TYPE; -- Data in represented in Big Endian signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0); -- Byte Length of string signal string_length, string_length_next : unsigned(WORD_WIDTH-1 downto 0); -- Counter of compared string words (4-Byte) signal compare_length, compare_length_next : unsigned(WORD_WIDTH-3 downto 0); -- Bitmask of local Endpoint Matches signal endpoint_mask, endpoint_mask_next : std_logic_vector(0 to NUM_ENDPOINTS-1); -- Signifies if the source of the Participant Data is compatible with our Participant signal participant_match, participant_match_next : std_logic; -- Signifies if the Packet is comming from a Subscriber Endpoint signal is_subscriber, is_subscriber_next : std_logic; -- Signifies that the read Locator is a Metatraffic Locator signal is_meta_addr, is_meta_addr_next : std_logic; -- General Purpose counter signal cnt, cnt_next : natural range 0 to max(23, STRING_WORD_ARRAY_TYPE'length); -- NOTE: In order to avoid synthesizing indexing for the full range of the OUTPUT_DATA_TYPE, we explicitly use counters constrained to the actual size -- Counter used to index the Participant Data signal participant_data_cnt, participant_data_cnt_next : natural range 0 to LOCAL_PARTICIPANT_DATA.length-1; -- Counter used to index the Publisher Data signal publisher_data_cnt, publisher_data_cnt_next : natural range 0 to work.math_pkg.max(WRITER_ENDPOINT_DATA.length-1, 0); -- Counter used to index the Subscriber Data signal subscriber_data_cnt, subscriber_data_cnt_next : natural range 0 to work.math_pkg.max(READER_ENDPOINT_DATA.length-1, 0); -- Signifies the next expected Sequence Number of the current relevant Message Type (Participant/Publisher/Subscriber/Message Data) signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE; -- Generic Sequence Number Latch signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE; -- Generic Sequence Number Latch signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE; -- Generic Sequence Number Latch signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE; -- Intermediate write enable signal. signal wr_sig : std_logic; -- Signifies if a Stale Endpoint Check is in progress signal stale_check, stale_check_next : std_logic; -- Time of next Stale Endpoint Check signal check_time, check_time_next : TIME_TYPE; -- Toggle latching the "last_word_in" signal until reset signal last_word_in_latch, last_word_in_latch_next : std_logic; -- Signal containing the HEARTBEAT/ACKNACK count of all built-in Endpoints signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0); -- Toggle set when at least one Endpoint has asserted the "alive" signal, until reset signal endpoint_alive : std_logic; -- Resets the "endpoint_alive" signal signal reset_endpoint_alive : std_logic; -- NOTE: The "auto_live_seq_nr" is always higher than "man_live_seq_nr" -- Contains the highest Sequence Number for automatic liveliness updates signal auto_live_seq_nr, auto_live_seq_nr_next : SEQUENCENUMBER_TYPE; -- Contains the highest Sequence Number for manual by participant liveliness updates signal man_live_seq_nr, man_live_seq_nr_next : SEQUENCENUMBER_TYPE; -- Points to the first Sequence Number after "man_live_seq_nr" (Signifies the start of the GAP between "man_live_seq_nr" and "auto_live_seq_nr") signal live_gap_start, live_gap_start_next : SEQUENCENUMBER_TYPE; -- Points to the first Sequence Number before "auto_live_seq_nr" (Signifies the end of the GAP between "man_live_seq_nr" and "auto_live_seq_nr") signal live_gap_end, live_gap_end_next : SEQUENCENUMBER_TYPE; -- Denotes the number of valid Bitmap longs (4-Byte words) signal bitmap_cnt, bitmap_cnt_next : unsigned(log2c(MAX_BITMAP_WIDTH/CDR_LONG_WIDTH)-1 downto 0); -- NumberSet Bitmap Latch signal bitmap_latch, bitmap_latch_next : BITMAP_TYPE; -- Counter used to read out Bitmaps signal cnt2, cnt2_next : natural range 0 to BITMAP_TYPE'length; -- Signal used to iterate through Bitmaps signal bitmap_pos, bitmap_pos_next : natural range 0 to MAX_BITMAP_WIDTH-1; -- Participant Announcement Timeout Time signal announcement_time, announcement_time_next : TIME_TYPE; -- Heartbeat/Liveliness Assertion Timeout Time signal heartbeat_time, heartbeat_time_next : TIME_TYPE; -- Signifies if we are currently in a Liveliness Assertion signal is_live_assert, is_live_assert_next : std_logic; -- Signifies the content of the string read from input signal string_content, string_content_next : STRING_CONTENT_TYPE; -- Reader Flags of remote Reader signal reader_flags, reader_flags_next : std_logic_vector(READER_FLAGS_WIDTH-1 downto 0); -- Endpoint Locator IPv4 Address Latch signal def_addr, def_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); -- Metatraffic Locator IPv4 Address Latch signal meta_addr, meta_addr_next : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); -- Endpoint UDPv4 Port Latch signal def_port, def_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); -- Metatraffic UDPv4 Port Latch signal meta_port, meta_port_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); -- Participant Lease Duration Latch signal lease_duration, lease_duration_next : DURATION_TYPE; -- General Purpose Long latch signal long_latch, long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0); -- Contains flags that signify which PIDs where received. This is done in order to use the default value for -- not received elements. signal rcvd, rcvd_next : std_logic_vector(RCVD_FLAG_WIDTH-1 downto 0); -- Signal containing the relevant Participant Memory Frame Fields of the Memory Operation signal mem_field_flags : std_logic_vector(0 to PMF_FLAG_WIDTH-1) := (others => '0'); -- Signal used to pass deadlines to the Memory FSM signal deadline : TIME_TYPE; -- Signal used to pass extra flags to the Memory FSM signal extra_flags : std_logic_vector(0 to EF_FLAG_WIDTH-1); -- Signal used to pass Participant Pointers to the Memory Process signal mem_addr_update : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Signal used to be pass Response Times to the Memory FSM signal res_time : TIME_TYPE; -- Test signal used for testbench synchronisation signal idle_sig : std_logic; -- Signifies that we received an Unregister/Dispose Status Info signal ud_status, ud_status_next : std_logic; -- Internal Signal for data_out signal data_out_sig : std_logic_vector(WORD_WIDTH-1 downto 0); -- Internal Signal for last_word_out signal last_word_out_sig : std_logic; -- *MEMORY PROCESS* -- Memory FSM State signal mem_stage, mem_stage_next : MEM_STAGE_TYPE; -- General Purpose Counter (Memory FSM) signal mem_cnt, mem_cnt_next : natural range 0 to 46; -- Signals the start of a Memory Operation (Should be pulled high only when mem_op_done is high) signal mem_op_start : std_logic; -- Signals the end of a Memory Operation signal mem_op_done : std_logic; -- Opcode of the Memory Operation (Valid only when mem_op_start is high) signal mem_opcode : MEM_OPCODE_TYPE; -- Base Memory Address of current Participant Frame signal mem_addr_base, mem_addr_base_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Pointer to previous Participant Memory Frame Address signal mem_prev_addr_base, mem_prev_addr_base_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Pointer to next Participant Memory Frame Address signal mem_next_addr_base, mem_next_addr_base_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Head of Empty Participant List signal mem_empty_head, mem_empty_head_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Head of Occupied Participant List signal mem_occupied_head, mem_occupied_head_next : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); -- Latch for the Participant Data stored in memory signal participant_data, participant_data_next : PARTICIPANT_DATA_TYPE; -- Latch for Participant Data from main FSM signal participant_latch_data, participant_latch_data_next : PARTICIPANT_LATCH_DATA_TYPE; -- Participant Memory Flag Array denoting which participant_data Fields are up-to-date with the respective fields of the Participant (Pointed by mem_addr_base) signal current_pmf, current_pmf_next : std_logic_vector(0 to PMF_FLAG_WIDTH-1); -- *MEMORY CONTROL CONNECTION SIGNALS* signal mem_addr : unsigned(PARTICIPANT_MEMORY_ADDR_WIDTH-1 downto 0); signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0); signal mem_ready_in, mem_valid_in : std_logic; signal mem_ready_out, mem_valid_out : std_logic; signal mem_read : std_logic; signal mem_abort_read : std_logic; --*****ALIAS DEFINATION***** -- ENDPOINT FRAME HEADER alias header_opcode : std_logic_vector(7 downto 0) is data_in(31 downto 24); alias header_flags : std_logic_vector(7 downto 0) is data_in(23 downto 16); alias header_udp_port : std_logic_vector(15 downto 0) is data_in(15 downto 0); -- RTPS PARAMETER LIST HEADER alias parameter_id : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) is data_in(WORD_WIDTH-1 downto WORD_WIDTH-PARAMETER_ID_WIDTH); alias parameter_length : std_logic_vector(PARAMETER_LENGTH_WIDTH-1 downto 0) is data_in(PARAMETER_LENGTH_WIDTH-1 downto 0); alias must_understand : std_logic is parameter_id(PARAMETER_ID_WIDTH-1); -- RTPS DATA PAYLOAD HEADER alias representation_id : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(WORD_WIDTH-1 downto WORD_WIDTH-PAYLOAD_REPRESENTATION_ID_WIDTH); alias representation_options : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(PAYLOAD_REPRESENTATION_OPTIONS_WIDTH-1 downto 0); -- RTPS SUBMESSAGE FLAGS alias endian_flag : std_logic is flags(0); alias endian_flag_next : std_logic is flags_next(0); alias qos_flag : std_logic is flags(1); alias qos_flag_next : std_logic is flags_next(1); alias data_flag : std_logic is flags(2); alias key_flag : std_logic is flags(3); alias final_flag : std_logic is flags(1); alias non_std_flag : std_logic is flags(4); -- HEARTBEAT alias first_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_1; alias first_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_1_next; alias last_seq_nr : SEQUENCENUMBER_TYPE is sn_latch_2; alias last_seq_nr_next : SEQUENCENUMBER_TYPE is sn_latch_2_next; -- GAP alias gap_start : SEQUENCENUMBER_TYPE is sn_latch_1; alias gap_start_next : SEQUENCENUMBER_TYPE is sn_latch_1_next; alias gap_list_base : SEQUENCENUMBER_TYPE is sn_latch_2; alias gap_list_base_next : SEQUENCENUMBER_TYPE is sn_latch_2_next; alias gap_list_end : SEQUENCENUMBER_TYPE is sn_latch_3; alias gap_list_end_next : SEQUENCENUMBER_TYPE is sn_latch_3_next; --*****FUNCTION DECLARATION***** -- Return minimum of t1,t2,t3 or TIME_INVALID if t1,t2,t3 < t. function min_time(t1, t2, t3, t : TIME_TYPE) return TIME_TYPE is variable ret : TIME_TYPE := TIME_INVALID; begin if (not (t1 <= t)) then ret := t1; end if; if (not (t2 <= t) and t2 < ret) then ret := t2; end if; if (not (t3 <= t) and t3 < ret) then ret := t3; end if; return ret; end function; -- 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; procedure assert_sn is begin if (message_type = EDP and is_subscriber = '0') then assert check_mask(current_pmf, PMF_PUB_SEQ_NR_FLAG) severity FAILURE; elsif (message_type = EDP and is_subscriber = '1') then assert check_mask(current_pmf, PMF_SUB_SEQ_NR_FLAG) severity FAILURE; elsif (message_type = MESSAGE) then assert check_mask(current_pmf, PMF_MES_SEQ_NR_FLAG) severity FAILURE; elsif (message_type = PDP) then assert check_mask(current_pmf, PMF_SPDP_SEQ_NR_FLAG) severity FAILURE; else assert FALSE report "assert_sn: Unknown Message Type" severity FAILURE; end if; end procedure; begin --*****COMPONENT INSTANTIATION***** mem_ctrl_inst : entity work.mem_ctrl(arch) generic map ( ADDR_WIDTH => PARTICIPANT_MEMORY_ADDR_WIDTH, DATA_WIDTH => WORD_WIDTH, MEMORY_DEPTH => PARTICIPANT_MEMORY_SIZE, MAX_BURST_LENGTH => PARTICIPANT_FRAME_SIZE ) port map ( clk => clk, reset => reset or mem_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 ); rd <= rd_sig; -- Big Endian Representation data_in_swapped <= endian_swap(endian_flag, data_in); -- This process is responsible for toggling the "endpoint_alive" signal -- The signal is set high when at least one bit of the "alive" signal is high for at least one clock cycle, -- and is set low when "reset_endpoint_alive" signal is high for at least one clock cycle. endpoint_alive_prc: process(all) begin if rising_edge(clk) then -- Reset Endpoint Alive Signal if (reset = '1' or reset_endpoint_alive = '1') then endpoint_alive <= '0'; -- Set Endpoint Alive Signal, if at least one endpoint asserts liveliness elsif (alive /= (alive'range => '0')) then endpoint_alive <= '1'; end if; end if; end process; -- This process connects the Intermediate Output Signals to the actual output FIFOs output_prc : process(all) begin wr_ue <= (others => '0'); wr_ro <= '0'; case (stage) is when INFORM_ENDPOINTS_MATCH => if (wr_sig = '1') then wr_ue <= endpoint_mask; end if; when INFORM_ENDPOINTS_UNMATCH => if (wr_sig = '1') then wr_ue <= not endpoint_mask; end if; when INFORM_ENDPOINTS_PARTICIPANT_UNMATCH => if (wr_sig = '1') then wr_ue <= (others => '1'); end if; when LIVELINESS_UPDATE => if (wr_sig = '1') then wr_ue <= endpoint_mask; end if; when others => wr_ro <= wr_sig; end case; end process; data_out_ue <= data_out_sig; data_out_ro <= data_out_sig; last_word_out_ue <= last_word_out_sig; last_word_out_ro <= last_word_out_sig; -- Main State Machine -- STATE DESCRIPTION -- IDLE Idle state. Initiates Participant Announcements, Heartbeat/Liveliness Assertions, Stale Participant Entry Checks ,and Packet Processing, in that priority order. -- PACKET_HEADER Read the Endpoint FIFO Packet Format Header (RTPS Submessage ID/Opcode, Submessage Flags, Source UDPv4 Port) -- PACKET_SRC_ADDR Read Source IPv4 Address -- PACKET_SRC_GUIDPREFIX Read Source GUID Prefix -- PACKET_SRC_ENTITYID Read Source Entity ID -- PACKET_DEST_ENTITYID Read Destination Entity ID. Determine content of Packet (Participant Data, Publisher/Subscriber/Message Data/GAP/HEARTBEAT/ACKNACK) and initiate processing. -- CHECK_SRC_ENTITYID Read Source Entity ID. Determine content of Packet (Participant Data, Publisher/Subscriber/Message Data/GAP/HEARTBEAT/ACKNACK) and initiate processing. -- This state is taken if the Packet content could not be determined in the PACKET_DEST_ENTITYID state. -- LATCH_SEQ_NR Store RTPS Data Submessage Sequence Number -- PROCESS_DATA Parse RTPS Data Submessage Payload Header. Determine content of Data (Parameter List, Participant Message CDR Data) or if Data Message contains in-line QoS and initiate respective handling. -- PROCESS_MESSAGE_SEQUENCE_NUMBERS Process ParticipantMessageData Sequence Numbers. Update Sequence Numbers if necessary and initiate Message processing -- PROCESS_MESSAGE Parse Participant Data Message and extract liveliness assertion of remote Participant -- LIVELINESS_UPDATE Propagate Liveliness Assertion of remote Participant to respective local Reader Endpoints -- PROCESS_GAP Parse RTPS GAP Submessage -- PROCESS_GAP_SEQUENCE_NUMBERS Process GAP Sequence Numbers. Update stored Sequence Numbers if necessary -- FIND_NEXT_VALID_IN_BITMAP Iterate through Bitmap and find the next valid Sequence Number. -- PROCESS_HEARTBEAT Parse RTPS HEARTBEAT Submessage -- PROCESS_HEARTBEAT_SEQUENCE_NUMBERS Process HEARTBEAT Sequence Numbers. Update stored Sequence Numbers if necessary. Set HEARTBEAT response timeout accordingly. -- PROCESS_ACKNACK Parse RTPS ACKNACK Submessage -- PROCESS_ACKNACK_SEQUENCE_NUMBERS Process ACKNACK Sequence Numbers. Update stored Sequence Numbers if necessary. Set ACKNACK response timeout accordingly. -- FIND_PARTICIPANT_DEST Find next stored Participant to send Participant Announcement and Liveliness Assertion to. -- PARTICIPANT_STALE_CHECK Check memory for remote stale Participant Entries (Lease Duration Exceeded, HEARTBEAT/ACKNACK timeout passed) and take appropriate action. -- PROCESS_PL Parse RTPS Parameter List -- CHECK_DEFAULT Match local endpoints against non-received QoS (default values) of remote -- LATCH_STRING_LENGTH Store String Length -- COMPARE_STRING Compare string to constants depending on string contents. -- MATCH_GUID Compare GUID Prefix to source GUID Prefix of Packet -- MATCH_DOMAIN_ID Compare Domain ID -- MATCH_PROTOCOL_VERSION Compare RTPS Protocol Version -- LATCH_LOCATOR Store Locator. NOTE: Only Metatraffic and User Locators are differentiated. Unicast and Multicast are overwriting each other and the last parsed is the one to be used. -- LATCH_EXPECTS_INLINE_QOS Store 'expectsInlineQoS' Flag -- LATCH_LEASE_DURATION Store remote Participant Lease Duration -- CHECK_REMOTE_BUILTIN_ENDPOINTS Check if the remote Participant has the required built-in Endpoints -- RXO_DURABILITY Check Compatibility of Durability QoS -- RXO_DEADLINE Check Compatibility of Deadline QoS -- RXO_LIVELINESS Check Compatibility of Liveliness QoS -- RXO_LEASE_DURATION Check Compatibility of Liveliness QoS -- RXO_RELIABILITY Check Compatibility of Reliability QoS -- RXO_DESTINATION_ORDER Check Compatibility of Destination Order QoS -- RXO_OWNERSHIP Check Compatibility of Ownership QoS -- RXO_PRESENTATION Check Compatibility of Presentation QoS -- RXO_PARTITION Check Compatibility of Partition QoS -- RXO_LATENCY_BUDGET Check Compatibility of Latency Budget QoS -- CHECK_MAX_SIZE_SERIALIZED Check if Publishers Max sent Payload Size is Compatible -- CHECK_STATUS_INFO Check inline QoS Status Info for Unregister/Dispose Status -- PARTICIPANT_MATCH_STAGE Add compatible remote and remove incompatible remote Participants to and from memory. Update stored Sequence Numbers respectively (also for EDP) -- INFORM_ENDPOINTS_MATCH Propagate local Endpoint matches -- INFORM_ENDPOINTS_UNMATCH Propagate local Endpoint unmatches -- INFORM_ENDPOINTS_PARTICIPANT_UNMATCH Propagate remote Participant unmatch -- SEND_HEADER Send Output Data Header and RTPS Message Header -- SEND_PARTICIPANT_ANNOUNCEMENT Send Participant Announcement Data Submessage -- SEND_ACKNACK Send ACKNACK Submessages -- SEND_HEARTBEAT Send HEARTBEAT Submessages -- SEND_PUB_DATA Send Endpoint Discovery Publication Data Submessage -- SEND_SUB_DATA Send Endpoint Discovery Subscriber Data Submessage -- SEND_MES_MAN_LIVE Send Participant Message Automatic Liveliness Assertion Data Submessage -- SEND_MES_GAP Send Participant Message GAP Submessages -- SEND_MES_AUTO_LIVE Send Participant Message Manual-by-Participant Liveliness Assertion Data Submessage -- SKIP_PARAMETER Skip rest of Parameter -- SKIP_PACKET Skip rest of Packet parse_prc: process(all) variable tmp_endpoint_mask : std_logic_vector(0 to NUM_ENDPOINTS-1); variable rd_guard : std_logic; variable tmp_default_qos_match : DEFAULT_QOS_MATCH_TYPE; variable tmp_dw : DOUBLE_WORD_ARRAY; variable mem_seq_nr : SEQUENCENUMBER_TYPE; -- 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); begin --DEFAULT Registered stage_next <= stage; return_stage_next <= return_stage; opcode_next <= opcode; flags_next <= flags; src_port_next <= src_port; src_addr_next <= src_addr; guid_next <= guid; src_entityid_next <= src_entityid; dest_entityid_next <= dest_entityid; parameter_end_next <= parameter_end; message_type_next <= message_type; string_length_next <= string_length; compare_length_next <= compare_length; endpoint_mask_next <= endpoint_mask; participant_match_next <= participant_match; is_subscriber_next <= is_subscriber; lease_duration_next <= lease_duration; def_addr_next <= def_addr; meta_addr_next <= meta_addr; def_port_next <= def_port; meta_port_next <= meta_port; is_meta_addr_next <= is_meta_addr; cnt_next <= cnt; reader_flags_next <= reader_flags; stale_check_next <= stale_check; sn_latch_1_next <= sn_latch_1; sn_latch_2_next <= sn_latch_2; sn_latch_3_next <= sn_latch_3; auto_live_seq_nr_next <= auto_live_seq_nr; man_live_seq_nr_next <= man_live_seq_nr; live_gap_start_next <= live_gap_start; live_gap_end_next <= live_gap_end; announcement_time_next <= announcement_time; heartbeat_time_next <= heartbeat_time; is_live_assert_next <= is_live_assert; string_content_next <= string_content; participant_data_cnt_next <= participant_data_cnt; publisher_data_cnt_next <= publisher_data_cnt; subscriber_data_cnt_next <= subscriber_data_cnt; seq_nr_next <= seq_nr; next_seq_nr_next <= next_seq_nr; last_word_in_latch_next <= last_word_in_latch; count_next <= count; long_latch_next <= long_latch; rcvd_next <= rcvd; check_time_next <= check_time; cnt2_next <= cnt2; bitmap_cnt_next <= bitmap_cnt; bitmap_latch_next <= bitmap_latch; bitmap_pos_next <= bitmap_pos; ud_status_next <= ud_status; -- DEFAULT Unregistered rd_sig <= '0'; rd_guard := '0'; reset_read_cnt <= '0'; wr_sig <= '0'; mem_opcode <= NOP; mem_op_start <= '0'; last_word_out_sig <= '0'; reset_endpoint_alive <= '0'; idle_sig <= '0'; data_out_sig <= (others => '0'); mem_field_flags <= (others => '0'); extra_flags <= (others => '0'); mem_addr_update <= PARTICIPANT_MEMORY_MAX_ADDRESS; deadline <= TIME_INVALID; res_time <= TIME_INVALID; -- Last Word Latch Setter if (last_word_in = '1') then last_word_in_latch_next <= '1'; end if; -- Set mem_seq_nr to correct sequence number -- NOTE: The stored Sequence Numbers are the next expected case (message_type) is -- Participant Data Sequence Number when PDP => mem_seq_nr := participant_data.spdp_seq_nr; when EDP => -- Subscriber Data Sequence Number if (is_subscriber = '1') then mem_seq_nr := participant_data.sub_seq_nr; -- Publisher Data Sequence Number else mem_seq_nr := participant_data.pub_seq_nr; end if; -- Participant Message Data Sequence Number when MESSAGE => mem_seq_nr := participant_data.mes_seq_nr; when others => mem_seq_nr := SEQUENCENUMBER_UNKNOWN; end case; case(stage) is -- Initial/Idle State when IDLE => idle_sig <= '1'; -- Participant Announcement Time Trigger if (time > announcement_time) then announcement_time_next <= time + PARTICIPANT_ANNOUNCEMENT_PERIOD; stage_next <= SEND_HEADER; return_stage_next <= SEND_PARTICIPANT_ANNOUNCEMENT; cnt_next <= 0; -- Heartbeat Time Trigger -- NOTE: Liveliness assertion and Heartbeat sending is done together elsif (time > heartbeat_time) then -- Memory Operation Guard if (mem_op_done = '1') then -- NOTE: The sequence number of the automatic liveliness is always higher than that of the manual liveliness -- If Manual By Participant Liveliness asserted, send both manual and automatic liveliness if (endpoint_alive = '1') then -- Reset the endpoint alive toggle signal reset_endpoint_alive <= '1'; man_live_seq_nr_next <= auto_live_seq_nr + 1; auto_live_seq_nr_next <= auto_live_seq_nr + 2; -- GAP Start is always man_live_seq_nr+1 live_gap_start_next <= auto_live_seq_nr + 2; -- GAP End is always auto_live_seq_nr-1 live_gap_end_next <= auto_live_seq_nr + 1; -- Else send only automatic liveliness else auto_live_seq_nr_next <= auto_live_seq_nr + 1; live_gap_end_next <= live_gap_end + 1; end if; heartbeat_time_next <= time + HEARTBEAT_PERIOD; -- Send Heartbeat and Liveliness Assertions to all stored Participants mem_op_start <= '1'; mem_opcode <= GET_FIRST_PARTICIPANT; mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; stage_next <= FIND_PARTICIPANT_DEST; -- Increment the counter for the new Heartbeat Messages count_next <= count + 1; -- Mark this as liveliness assertion (Allows the "SEND_MES_AUTO_LIVE" stage to decide on return stage) is_live_assert_next <= '1'; end if; -- Stale Check Timeout elsif (check_time <= time) then -- Memory Operation Guard if (mem_op_done = '1') then mem_op_start <= '1'; mem_opcode <= GET_FIRST_PARTICIPANT; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; stale_check_next <= '1'; stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 1; -- Reset Timeout check_time_next <= TIME_INFINITE; end if; -- Process Packet elsif (empty = '0') then stage_next <= PACKET_HEADER; -- Reset Latches def_addr_next <= (others => '0'); meta_addr_next <= DEFAULT_IPv4_META_ADDRESS; def_port_next <= (others => '0'); meta_port_next <= META_IPv4_MULTICAST_PORT; lease_duration_next <= DEFAULT_PARTICIPANT_LEASE_DURATION; reader_flags_next <= (READER_EXPECTS_INLINE_QOS_FLAG => DEFAULT_EXPECTS_INLINE_QOS, READER_EXPECTS_HISTORICAL_DATA_FLAG => DEFAULT_EXPECTS_HISTORICAL_DATA_FLAG, READER_IS_BEST_EFFORT_FLAG => DEFAULT_IS_BEST_EFFORT_FLAG, others => '0'); rcvd_next <= (others => '0'); ud_status_next <= '0'; -- NOTE: We work with a "mark by default, and unmark on first missmatch" System. -- This assumes that each RxO QoS parameter occur only once in the list, else the behavior is undefined. participant_match_next <= '1'; endpoint_mask_next <= (others => '1'); end if; when PACKET_HEADER => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Opcode opcode_next <= header_opcode; -- Latch Flags flags_next <= header_flags; -- Latch Source UDP Port src_port_next <= header_udp_port; stage_next <= PACKET_SRC_ADDR; -- SANITY CHECK: Skip Packet if non-standard Payload if(header_opcode = SID_DATA and non_std_flag = '1') then stage_next <= SKIP_PACKET; end if; end if; when PACKET_SRC_ADDR => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Source IP Address src_addr_next <= data_in; stage_next <= PACKET_SRC_GUIDPREFIX; cnt_next <= 0; end if; when PACKET_SRC_GUIDPREFIX => -- Input FIFO Guard and Memory Operation Guard if (empty = '0' and mem_op_done = '1') then rd_guard := '1'; -- Latch Src GUIDPrefix case (cnt) is when 0 => guid_next(0) <= data_in; cnt_next <= cnt + 1; when 1 => guid_next(1) <= data_in; cnt_next <= cnt + 1; when 2 => guid_next(2) <= data_in; guid_next(3) <= ENTITYID_PARTICIPANT; stage_next <= PACKET_SRC_ENTITYID; when others => null; end case; end if; when PACKET_SRC_ENTITYID => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Source Entity ID src_entityid_next <= data_in; stage_next <= PACKET_DEST_ENTITYID; end if; when PACKET_DEST_ENTITYID => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- DEFAULT stage_next <= SKIP_PACKET; is_subscriber_next <= '0'; -- *Check Destination Entity ID* case (data_in) is when ENTITYID_UNKNOWN => -- Wildcard Destination -- Content has to be determined through Source Entity ID stage_next <= CHECK_SRC_ENTITYID; when ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR => -- Only DATA relevant if (opcode = SID_DATA) then -- Packet Contains Participant Data message_type_next <= PDP; stage_next <= LATCH_SEQ_NR; cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SPDP_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; end if; when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER => -- SANITY CHECK: Ignore if no Writers -- Only ACKNACKs are relevant if (NUM_WRITERS /= 0 and opcode = SID_ACKNACK) then message_type_next <= EDP; is_subscriber_next <= '1'; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR => -- SANITY CHECK: Ignore if no Readers if (NUM_READERS /= 0) then message_type_next <= EDP; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_PUB_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Writers endpoint_mask_next <= ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER => -- SANITY CHECK: Ignore if no Readers -- Only ACKNACKs are relevant if (NUM_READERS /= 0 and opcode = SID_ACKNACK) then message_type_next <= EDP; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR => -- SANITY CHECK: Ignore if no Writers if (NUM_WRITERS /= 0) then message_type_next <= EDP; is_subscriber_next <= '1'; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_SUB_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SUB_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Readers endpoint_mask_next <= not ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER => -- SANITY CHECK: Ignore if no Writers if (NUM_WRITERS /= 0) then -- Only ACKNACKs are relevant if (opcode = SID_ACKNACK) then message_type_next <= MESSAGE; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; end if; when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER => -- SANITY CHECK: Ignore if no Readers if (NUM_READERS /= 0) then message_type_next <= MESSAGE; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_MES_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_MES_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Writers endpoint_mask_next <= ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when others => -- Skip Packet null; end case; end if; when CHECK_SRC_ENTITYID => -- DEFAULT stage_next <= SKIP_PACKET; is_subscriber_next <= '0'; -- *Check Dest Entity ID* case (src_entityid) is when ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER => -- Only DATA relevant if (opcode = SID_DATA) then -- Packet Contains Participant Data message_type_next <= PDP; stage_next <= LATCH_SEQ_NR; cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SPDP_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; end if; when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR => -- SANITY CHECK: Ignore if no Writers -- Only ACKNACKs are relevant if (NUM_WRITERS /= 0 and opcode = SID_ACKNACK) then message_type_next <= EDP; is_subscriber_next <= '1'; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; when ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER => -- SANITY CHECK: Ignore if no Readers if (NUM_READERS /= 0) then message_type_next <= EDP; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_PUB_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Writers endpoint_mask_next <= ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_PUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR => -- SANITY CHECK: Ignore if no Readers -- Only ACKNACKs are relevant if (NUM_READERS /= 0 and opcode = SID_ACKNACK) then message_type_next <= EDP; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; when ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER => -- SANITY CHECK: Ignore if no Writers if (NUM_WRITERS /= 0) then message_type_next <= EDP; is_subscriber_next <= '1'; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_SUB_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SUB_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Readers endpoint_mask_next <= not ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_SUB_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER => -- SANITY CHECK: Ignore if no Writers if (NUM_WRITERS /= 0) then -- Only ACKNACKs are relevant if (opcode = SID_ACKNACK) then message_type_next <= MESSAGE; stage_next <= PROCESS_ACKNACK; --ACKNACK Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; end if; end if; when ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER => -- SANITY CHECK: Ignore if no Readers if (NUM_READERS /= 0) then message_type_next <= MESSAGE; -- Only HEARTBEATs, GAPs and DATA are relevant case (opcode) is when SID_HEARTBEAT => stage_next <= PROCESS_HEARTBEAT; -- HEARTBEAT Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG or PMF_MES_SEQ_NR_FLAG; when SID_GAP => stage_next <= PROCESS_GAP; -- GAP Processing cnt_next <= 0; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_MES_SEQ_NR_FLAG; when SID_DATA => stage_next <= LATCH_SEQ_NR; -- DATA Processing cnt_next <= 0; -- Unmark all Writers endpoint_mask_next <= ENDPOINT_READERS; -- Start Participant Search mem_op_start <= '1'; mem_opcode <= SEARCH_PARTICIPANT; mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; when others => null; end case; end if; when others => null; end case; when LATCH_SEQ_NR => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Sequence Number case (cnt) is when 0 => seq_nr_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 1 => seq_nr_next(1) <= unsigned(data_in_swapped); -- Store Next Sequence Number tmp_dw := (0 => seq_nr(0), 1 => unsigned(data_in_swapped)); next_seq_nr_next <= tmp_dw + 1; stage_next <= PROCESS_DATA; when others => null; end case; end if; when PROCESS_DATA => -- Data Message contains inline QoS if (qos_flag = '1') then stage_next <= PROCESS_PL; -- Data Message contains Data Payload elsif (data_flag = '1') then -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- DEFAULT STAGE stage_next <= SKIP_PACKET; -- Process Payload Header case(representation_id) is when PL_CDR_BE => -- Override Endian Flag endian_flag_next <= '0'; stage_next <= PROCESS_PL; when PL_CDR_LE => -- Override Endian Flag endian_flag_next <= '1'; stage_next <= PROCESS_PL; when CDR_BE => -- Accept CDR Representation only for Participant Messages if (message_type = MESSAGE) then -- Override Endian Flag endian_flag_next <= '0'; stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS; end if; when CDR_LE => -- Accept CDR Representation only for Participant Messages if (message_type = MESSAGE) then -- Override Endian Flag endian_flag_next <= '1'; stage_next <= PROCESS_MESSAGE_SEQUENCE_NUMBERS; end if; when others => -- Skip Packet null; end case; end if; elsif (ud_status = '1') then -- NOTE: If the DATA message has a paylaod with DATA, the parsed in-line QoS (i.e. PID_STATUS_INFO) is ignored -- NOTE: A Sanity check is made on the GUID. It is expected that the GUID is correctly configured by parsing of an PID_KEY_HASH. -- According to the specification the PID_KEY_HASH is not a requirement, and the Key should be sent as serialized key in the DATA -- message payload. We do not parse the serialized key (because, quite frankly, we can't since we do not have a definition of it...) -- This means that if the sender does not send a PID_KEY_HASH and the sanity check here fails, the Packet will be skipped, and thus -- processing from the sender will effectively stall, since the SN will never be acknowledged. -- Participant Unamtch if (message_type = PDP and guid(3) = ENTITYID_PARTICIPANT) then participant_match_next <= '0'; stage_next <= PARTICIPANT_MATCH_STAGE; -- Endpoint Unmatch elsif (message_type = EDP and guid(3)(ENTITY_KIND_H_RANGE) /= BUILT_IN_ENTITY) then endpoint_mask_next <= (others => '0'); stage_next <= PARTICIPANT_MATCH_STAGE; else -- Skip stage_next <= SKIP_PACKET; end if; else -- Skip stage_next <= SKIP_PACKET; end if; when PROCESS_MESSAGE_SEQUENCE_NUMBERS => -- Precondition: participant_data set (PMF_MES_SEQ_NR_FLAG) -- Wait for Participant Data if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_MES_SEQ_NR_FLAG) severity FAILURE; -- Participant in Buffer if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then -- NOTE: Since the BuiltinParticipantMessageWriter has a History Depth of 1 (see DDSI-RTPS 2.3 8.4.13.3), we accept all newer SNs, since -- if the Writer has sent a newer SN he doesn't have the previous one anymore. -- Next Valid Sequence Number if (seq_nr >= mem_seq_nr) then mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_MES_SEQ_NR_FLAG; -- Process Message Data stage_next <= PROCESS_MESSAGE; cnt_next <= 0; else -- DONE stage_next <= SKIP_PACKET; end if; else -- DONE stage_next <= SKIP_PACKET; end if; end if; when PROCESS_MESSAGE => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is -- Check if GUID Prefix valid (Should be the same as the GUID Prefix of the Packet) -- GUID Prefix 1/3 when 0 => if (data_in /= guid(0)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; -- GUID Prefix 2/3 when 1 => if (data_in /= guid(1)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; -- GUID Prefix 3/3 when 2 => if (data_in /= guid(2)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; -- Participant Mesasge Kind when 3 => -- NOTE: Rest of Participant Message is ignored -- XXX: The Participant Message Data may contain additional data, and according to DDSI-RTPS 2.3 -- implementations must be able to support up to 128 Bytes of additional data. Due to the unnecessary -- high complexity this would add, this is currently not supported. case (data_in) is -- Automatic Liveliness Assertion when PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE => -- Mark all readers with automatic liveliness QoS endpoint_mask_next <= AUTOMATIC_LIVELINESS_READERS; stage_next <= LIVELINESS_UPDATE; cnt_next <= 0; -- Manual by Participant Liveliness Assertion when PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE => -- Mark all readers with manual by participant liveliness QoS endpoint_mask_next <= MANUAL_BY_PARTICIPANT_LIVELINESS_READERS; stage_next <= LIVELINESS_UPDATE; cnt_next <= 0; -- No Liveliness Update, skip packet when others => stage_next <= SKIP_PACKET; end case; when others => null; end case; end if; when LIVELINESS_UPDATE => -- If no Endpoint interested for Liveliness Assertion, skip if (endpoint_mask = (endpoint_mask'range => '0')) then -- DONE stage_next <= SKIP_PACKET; -- Output FIFO Guard elsif ((endpoint_mask and full_ue) = (full_ue'range => '0')) then wr_sig <= '1'; case (cnt) is -- Liveliness Assertion Opcode when 0 => data_out_sig <= EMO_LIVELINESS_UPDATE; cnt_next <= cnt + 1; -- GUID Prefix 1/3 when 1 => data_out_sig <= guid(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 2 => data_out_sig <= guid(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 3 => data_out_sig <= guid(2); last_word_out_sig <= '1'; -- DONE stage_next <= SKIP_PACKET; when others => null; end case; end if; when PROCESS_GAP => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is -- GapStart Sequence Number 1/2 when 0 => gap_start_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; -- GapStart Sequence Number 2/2 when 1 => gap_start_next(1) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; -- GapList.Base 1/2 when 2 => gap_list_base_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; -- GapList.Base 2/2 when 3 => gap_list_base_next(1) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; -- GapList.NumBits when 4 => gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_swapped)); bitmap_cnt_next <= unsigned(round_slv(data_in_swapped(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length)); cnt2_next <= 0; cnt_next <= cnt + 1; -- GapList.Bitmap when 5 => -- Read Bitmap if (cnt2 < bitmap_cnt) then cnt2_next <= cnt2 + 1; bitmap_latch_next(cnt2) <= data_in_swapped; else stage_next <= PROCESS_GAP_SEQUENCE_NUMBERS; end if; when others => null; end case; end if; when PROCESS_GAP_SEQUENCE_NUMBERS => -- Precondition: participant_data set (PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG) -- Wait for Sequence Number to be fetched from buffer if (mem_op_done = '1') then assert_sn; -- DEFAULT stage_next <= SKIP_PACKET; -- Sender known if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then -- GAP is relevant if (gap_start <= mem_seq_nr and mem_seq_nr <= gap_list_end) then -- Next Expected is in GAP List if (gap_list_base <= mem_seq_nr) then -- Begin searching next valid SN from the current expected in the bitmap list bitmap_pos_next <= to_integer(next_seq_nr - gap_list_base); else -- Begin searching next valid SN from the beginning of the bitmap list next_seq_nr_next <= gap_list_base; bitmap_pos_next <= 0; end if; stage_next <= FIND_NEXT_VALID_IN_BITMAP; end if; end if; end if; when FIND_NEXT_VALID_IN_BITMAP => -- Memory Operation Guard if (mem_op_done = '1') then tmp_bitmap := to_slv_bitmap(bitmap_latch); -- First valid sequence number found if (tmp_bitmap(bitmap_pos) = '0') then -- Update next sequence number mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; if (message_type = EDP and is_subscriber = '0') then mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; elsif (message_type = EDP and is_subscriber = '1') then mem_field_flags <= PMF_SUB_SEQ_NR_FLAG; else -- message_type = MESSAGE mem_field_flags <= PMF_MES_SEQ_NR_FLAG; end if; -- DONE stage_next <= SKIP_PACKET; else -- Continue search bitmap_pos_next <= bitmap_pos + 1; next_seq_nr_next <= next_seq_nr + 1; end if; end if; when PROCESS_HEARTBEAT => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Sequence Numbers case (cnt) is when 0 => first_seq_nr_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 1 => first_seq_nr_next(1) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 2 => last_seq_nr_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 3 => last_seq_nr_next(1) <= unsigned(data_in_swapped); stage_next <= PROCESS_HEARTBEAT_SEQUENCE_NUMBERS; when others => null; end case; end if; when PROCESS_HEARTBEAT_SEQUENCE_NUMBERS => -- Precondition: participant_data set (PMF_HEARTBEAT_RES_TIME_FLAG, PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG) -- Wait for Participant Search to finish if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_HEARTBEAT_RES_TIME_FLAG) severity FAILURE; assert_sn; -- Participant in Buffer if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then -- No scheduled Heartbeat Response if (participant_data.heartbeat_res_time = TIME_INVALID) then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_seq_nr) then -- Store new expected Sequence Number and set Response Dealy mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; next_seq_nr_next <= first_seq_nr; if (message_type = EDP and is_subscriber = '0') then mem_field_flags <= PMF_PUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; elsif (message_type = EDP and is_subscriber = '1') then mem_field_flags <= PMF_SUB_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; else -- message_type = MESSAGE mem_field_flags <= PMF_MES_SEQ_NR_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; end if; -- NOTE: Only response with ACKNACK if SN is available (Or no Final Flag) if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE and (first_seq_nr <= last_seq_nr or final_flag = '0')) then tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY; res_time <= tmp_dw; -- 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 (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else res_time <= TIME_INVALID; end if; -- If new Sequence Number is available or Writer expects ACKNACK elsif (last_seq_nr >= mem_seq_nr or final_flag = '0') then -- Set Response Delay mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; if (PARTICIPANT_HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then tmp_dw := time + PARTICIPANT_HEARTBEAT_RESPONSE_DELAY; res_time <= tmp_dw; -- 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 (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else res_time <= TIME_INVALID; end if; end if; -- Currently in Heartbeat Response Delay elsif (participant_data.heartbeat_res_time(1)(0) = '0') then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_seq_nr) then -- Store new expected Sequence Number mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; next_seq_nr_next <= first_seq_nr; if (message_type = EDP and is_subscriber = '0') then mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; elsif (message_type = EDP and is_subscriber = '1') then mem_field_flags <= PMF_SUB_SEQ_NR_FLAG; else -- message_type = MESSAGE mem_field_flags <= PMF_MES_SEQ_NR_FLAG; end if; end if; end if; end if; -- DONE stage_next <= SKIP_PACKET; end if; when PROCESS_ACKNACK => if (empty = '0') then rd_guard := '1'; -- Latch Sequence Number -- NOTE: Because we always sent the entire history cache, we only need to look at the SequenceNumberSetBase to determine if we need to sent data or not case (cnt) is when 0 => first_seq_nr_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 1 => first_seq_nr_next(1) <= unsigned(data_in_swapped); stage_next <= PROCESS_ACKNACK_SEQUENCE_NUMBERS; when others => null; end case; end if; when PROCESS_ACKNACK_SEQUENCE_NUMBERS => -- Precondition: participant_data set (PMF_ACKNACK_RES_TIME_FLAG, PMF_EXTRA_FLAGS_FLAG) -- Wait for Participant Search to finish if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG) severity FAILURE; -- Participant in Buffer if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then -- No scheduled Acknack Response if (participant_data.acknack_res_time = TIME_INVALID) then case (message_type) is when EDP => -- Subscriber Acknack if (is_subscriber = '1') then -- If Reader has not ACKed all Publisher History Cache if (first_seq_nr <= PUB_SEQUENCENUMBER) then -- Set Acknack Response Time and Publisher Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; res_time <= tmp_dw; -- NOTE: Last Bit denotes if this is Response or Suppression Delay res_time(1)(0) <= '0'; extra_flags <= participant_data.extra_flags or EF_PUB_DATA_FLAG; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else res_time <= TIME_INVALID; end if; end if; -- Publisher Acknack else -- If Reader has not ACKed all Subscriber History Cache if (first_seq_nr <= SUB_SEQUENCENUMBER) then -- Set Acknack Response Time and set Subscriber Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; res_time <= tmp_dw; -- NOTE: Last Bit denotes if this is Response or Suppression Delay res_time(1)(0) <= '0'; extra_flags <= participant_data.extra_flags or EF_SUB_DATA_FLAG; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else res_time <= TIME_INVALID; end if; end if; end if; -- Message Acknack when MESSAGE => -- NOTE: "auto_live_seq_nr" always has the higher sequence number by design, so we just need to check against that -- If Reader has not ACKed all Message History Cache if (first_seq_nr <= auto_live_seq_nr) then -- Set Acknack Response Time and set Message Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG or PMF_ACKNACK_RES_TIME_FLAG; if (PARTICIPANT_ACKNACK_RESPONSE_DELAY /= DURATION_INFINITE) then tmp_dw := time + PARTICIPANT_ACKNACK_RESPONSE_DELAY; res_time <= tmp_dw; -- NOTE: Last Bit denotes if this is Response or Suppression Delay res_time(1)(0) <= '0'; extra_flags <= participant_data.extra_flags or EF_MES_DATA_FLAG; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else res_time <= TIME_INVALID; end if; end if; when others => null; end case; -- Currently in Acknack Response Delay elsif (participant_data.acknack_res_time(1)(0) = '0') then case (message_type) is when EDP => -- Subscriber Acknack if (is_subscriber = '1') then -- Publisher Data not scheduled for response if (not check_mask(participant_data.extra_flags, EF_PUB_DATA_FLAG)) then -- If Reader has not ACKed all Publisher History Cache if (first_seq_nr <= PUB_SEQUENCENUMBER) then -- Set Publisher Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG; extra_flags <= participant_data.extra_flags or EF_PUB_DATA_FLAG; end if; end if; -- Publisher Acknack else -- Subscriber Data not scheduled for response if (not check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG)) then -- If Reader has not ACKed all Subscriber History Cache if (first_seq_nr <= SUB_SEQUENCENUMBER) then -- Set Subscriber Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG; extra_flags <= participant_data.extra_flags or EF_SUB_DATA_FLAG; end if; end if; end if; -- Message Acknack when MESSAGE => -- Message Data not scheduled for response if (not check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then -- NOTE: "auto_live_seq_nr" always has the higher sequence number by design, so we just need to -- check against that -- If Reader has not ACKed all Message History Cache if (first_seq_nr <= auto_live_seq_nr) then -- Set Message Data as Acknack Response mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_EXTRA_FLAGS_FLAG; extra_flags <= participant_data.extra_flags or EF_MES_DATA_FLAG; end if; end if; when others => null; end case; end if; end if; -- DONE stage_next <= SKIP_PACKET; end if; when FIND_PARTICIPANT_DEST => -- Wait for Next Participant to be Fetched if (mem_op_done = '1') then -- No more Participants if (mem_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then -- DONE stage_next <= IDLE; else stage_next <= SEND_HEADER; return_stage_next <= SEND_HEARTBEAT; cnt_next <= 0; end if; end if; when PARTICIPANT_STALE_CHECK => -- Precondition: participant_data set (PMF_LEASE_DEADLINE_FLAG, PMF_HEARTBEAT_RES_TIME_FLAG, PMF_ACKNACK_RES_TIME_FLAG) -- Wait for Stale Search to finish if (mem_op_done = '1') then case (cnt) is when 0 => mem_op_start <= '1'; mem_opcode <= GET_NEXT_PARTICIPANT; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; cnt_next <= cnt + 1; when 1 => assert check_mask(current_pmf, PMF_LEASE_DEADLINE_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG or PMF_ACKNACK_RES_TIME_FLAG) severity FAILURE; -- Found Stale Entry if (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) then -- Lease Expiration if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline <= time) then mem_op_start <= '1'; mem_opcode <= GET_PARTICIPANT; mem_field_flags <= PMF_GUIDPREFIX_FLAG; mem_addr_update <= mem_addr_base; cnt_next <= cnt + 1; -- HEARTBEAT Response Time elsif (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time <= time) then -- Suppression Delay if (participant_data.heartbeat_res_time(1)(0) = '1') then mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; res_time <= TIME_INVALID; -- Response Delay else mem_op_start <= '1'; mem_opcode <= GET_PARTICIPANT; mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG; mem_addr_update <= mem_addr_base; -- Send ACKNACK stage_next <= SEND_HEADER; return_stage_next <= SEND_ACKNACK; cnt_next <= 0; -- Increment Heartbeat/Acknack Counter count_next <= count + 1; end if; -- Update Check Time if (participant_data.lease_deadline /= TIME_INVALID and participant_data.lease_deadline < check_time) then check_time_next <= participant_data.lease_deadline; end if; -- ACKNACK Response Time elsif (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time <= time) then -- Suppression Delay if (participant_data.acknack_res_time(1)(0) = '1') then mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG; res_time <= TIME_INVALID; -- Response Delay else mem_op_start <= '1'; mem_opcode <= GET_PARTICIPANT; mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_EXTRA_FLAGS_FLAG; mem_addr_update <= mem_addr_base; -- Send Requested Data stage_next <= SEND_HEADER; return_stage_next <= SEND_PUB_DATA; cnt_next <= 0; end if; else -- Continue Search mem_op_start <= '1'; mem_opcode <= GET_NEXT_PARTICIPANT; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG or PMF_ACKNACK_RES_TIME_FLAG or PMF_HEARTBEAT_RES_TIME_FLAG; end if; -- NOTE: If the Lease Time expired, but one of the response times is less the check_time, the check_time will be updated -- Update Check Time -- XXX: Possible Worst Case Path (4 consecutive 64-bit comparisons in same clock) tmp_dw := min_time(participant_data.lease_deadline, participant_data.heartbeat_res_time, participant_data.acknack_res_time, time); if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; else -- Reset stale_check_next <= '0'; -- DONE stage_next <= IDLE; end if; when 2 => assert check_mask(current_pmf, PMF_GUIDPREFIX_FLAG) severity FAILURE; -- Latch GUID Prefix guid_next(0) <= participant_data.guid_prefix(0); guid_next(1) <= participant_data.guid_prefix(1); guid_next(2) <= participant_data.guid_prefix(2); -- Remove Participant mem_op_start <= '1'; mem_opcode <= REMOVE_PARTICIPANT; stage_next <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH; cnt_next <= 0; when 3 => mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_HEARTBEAT_RES_TIME_FLAG; if (PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY /= DURATION_INFINITE) then -- Set Heartbeat Suppression Time res_time <= time + PARTICIPANT_HEARTBEAT_SUPPRESSION_DELAY; -- NOTE: Last Bit denotes if this is Response or Suppression Delay res_time(1)(0) <= '1'; else -- Reset res_time <= TIME_INVALID; end if; -- NOTE: We go back to the Comparison Sub-state to check for further deadlines. -- The check_time is updated in that sub-state. -- Continue cnt_next <= 1; when 4 => assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE; mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_ACKNACK_RES_TIME_FLAG or PMF_EXTRA_FLAGS_FLAG; extra_flags <= participant_data.extra_flags and (not (EF_PUB_DATA_FLAG or EF_SUB_DATA_FLAG or EF_MES_DATA_FLAG)); if (PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_ZERO and PARTICIPANT_ACKNACK_SUPPRESSION_DELAY /= DURATION_INFINITE) then -- Set Acknack Suppression Time res_time <= time + PARTICIPANT_ACKNACK_SUPPRESSION_DELAY; -- NOTE: Last Bit denotes if this is Response or Suppression Delay res_time(1)(0) <= '1'; else -- Reset res_time <= TIME_INVALID; end if; -- NOTE: We go back to the Comparison Sub-state to check for further deadlines. -- The check_time is updated in that sub-state. -- Continue cnt_next <= 1; when others => null; end case; end if; when PROCESS_PL => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Reset Word Counter reset_read_cnt <= '1'; -- Latch Parameter End (In order to skip parameters) parameter_end_next <= unsigned(endian_swap(endian_flag,parameter_length)); -- DEFAULT STAGE stage_next <= SKIP_PARAMETER; -- TODO: DDS-XTYPES: When reading data, implementations of this specification shall be robust to any setting of the FLAG_MUST_UNDERSTAND bit and accept the parameter nevertheless. -- NOTE: In-line QoS is completely ignored case (parameter_id) is when PID_PARTICIPANT_GUID => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= MATCH_GUID; cnt_next <= 0; end if; when PID_DOMAIN_ID => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= MATCH_DOMAIN_ID; end if; when PID_DOMAIN_TAG => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) string_content_next <= DOMAIN_TAG_TYPE; -- Mark reception of DOMAIN_TAG rcvd_next <= rcvd or RCVD_DOMAIN_TAG_FLAG; end if; when PID_PROTOCOL_VERSION => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= MATCH_PROTOCOL_VERSION; end if; when PID_DEFAULT_UNICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; is_meta_addr_next <= '0'; end if; when PID_DEFAULT_MULTICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; is_meta_addr_next <= '0'; end if; when PID_METATRAFFIC_UNICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; is_meta_addr_next <= '1'; end if; when PID_METATRAFFIC_MULTICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; is_meta_addr_next <= '1'; end if; when PID_PARTICIPANT_LEASE_DURATION => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= LATCH_LEASE_DURATION; cnt_next <= 0; end if; when PID_BUILTIN_ENDPOINT_SET => -- Ignore in-line QoS -- Only relevant for Participant Discovery Protocol if(qos_flag = '0' and message_type = PDP) then stage_next <= CHECK_REMOTE_BUILTIN_ENDPOINTS; end if; when PID_BUILTIN_ENDPOINT_QOS => -- Only relevant for Participant Discovery Protocol -- NOTE: As of DDSI-RTPS 2.3 the PID_BUILTIN_ENDPOINT_QOS only contains the BEST_EFFORT_PARTICIPANT_MESSAGE_DATA_READER bit -- Due to how the built-in Endpoint is behaving, this bit as no impact in our case and we can safely ignore it. -- Ignore null; when PID_TOPIC_NAME => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) string_content_next <= TOPIC_NAME_TYPE; end if; when PID_TYPE_NAME => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_STRING_LENGTH; -- Mark String contents (Needed for string comparison) string_content_next <= TYPE_NAME_TYPE; end if; when PID_DURABILITY => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_DURABILITY; rcvd_next <= rcvd or RCVD_DURABILITY_QOS_FLAG; end if; when PID_DEADLINE => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_DEADLINE; cnt_next <= 0; rcvd_next <= rcvd or RCVD_DEADLINE_QOS_FLAG; end if; when PID_LIVELINESS => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_LIVELINESS; rcvd_next <= rcvd or RCVD_LIVELINESS_QOS_FLAG; end if; when PID_RELIABILITY => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_RELIABILITY; cnt_next <= 0; rcvd_next <= rcvd or RCVD_RELIABILITY_QOS_FLAG; end if; when PID_DESTINATION_ORDER => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_DESTINATION_ORDER; rcvd_next <= rcvd or RCVD_DESTINATION_ORDER_QOS_FLAG; end if; when PID_OWNERSHIP => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_OWNERSHIP; rcvd_next <= rcvd or RCVD_OWNERSHIP_QOS_FLAG; end if; when PID_PRESENTATION => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_PRESENTATION; cnt_next <= 0; rcvd_next <= rcvd or RCVD_PRESENTATION_QOS_FLAG; end if; when PID_PARTITION => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_PARTITION; end if; when PID_LATENCY_BUDGET => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= RXO_LATENCY_BUDGET; cnt_next <= 0; rcvd_next <= rcvd or RCVD_LATENCY_BUDGET_QOS_FLAG; end if; when PID_UNICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; -- Mark Latch 1 for storing is_meta_addr_next <= '0'; end if; when PID_MULTICAST_LOCATOR => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= LATCH_LOCATOR; cnt_next <= 0; -- Mark Latch 1 for storing is_meta_addr_next <= '0'; end if; when PID_ENDPOINT_GUID => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= MATCH_GUID; cnt_next <= 0; end if; when PID_DATA_MAX_SIZE_SERIALIZED => -- Ignore in-line QoS -- Only relevant for Endpoint Discovery Protocol if(qos_flag = '0' and message_type = EDP) then stage_next <= CHECK_MAX_SIZE_SERIALIZED; end if; when PID_EXPECTS_INLINE_QOS => stage_next <= LATCH_EXPECTS_INLINE_QOS; when PID_PARTICIPANT_MANUAL_LIVELINESS_COUNT => -- Ignore null; when PID_CONTENT_FILTER_PROPERTY => -- Ignore null; when PID_GROUP_GUID => -- Ignore null; when PID_PROPERTY_LIST => -- Ignore null; when PID_ENTITY_NAME => -- Ignore null; when PID_TIME_BASED_FILTER => -- Ignore null; when PID_TRANSPORT_PRIORITY => -- Ignore null; when PID_VENDORID => -- Ignore null; when PID_OWNERSHIP_STRENGTH => -- Ignore null; when PID_HISTORY => -- Ignore null; when PID_RESOURCE_LIMITS => -- Ignore null; when PID_LIFESPAN => -- Ignore -- NOTE: Lifespan is requested via in-line QoS and handled directly by the endpoint null; when PID_DURABILITY_SERVICE => -- Ignore null; when PID_USER_DATA => -- Ignore null; when PID_GROUP_DATA => -- Ignore null; when PID_TOPIC_DATA => -- Ignore null; when PID_CONTENT_FILTER_INFO => -- Ignore null; when PID_COHERENT_SET => -- Ignore null; when PID_DIRECTED_WRITE => -- Ignore null; when PID_ORIGINAL_WRITER_INFO => -- Ignore null; when PID_GROUP_COHERENT_SET => -- Ignore null; when PID_GROUP_SEQ_NUM => -- Ignore null; when PID_WRITER_GROUP_INFO => -- Ignore null; when PID_SECURE_WRITER_GROUP_INFO => -- Ignore null; when PID_KEY_HASH => stage_next <= MATCH_GUID; cnt_next <= 0; when PID_STATUS_INFO => stage_next <= CHECK_STATUS_INFO; when PID_PAD => -- Ignore null; when PID_EXTENDED => -- TODO null; when PID_IGNORE => -- Ignore null; when PID_SENTINEL => parameter_end_next <= (others => '1'); -- If Processing in-line QoS until now, start processing data if(qos_flag = '1') then -- Override QoS Flag qos_flag_next <= '0'; stage_next <= PROCESS_DATA; -- Else check Defaults else stage_next <= CHECK_DEFAULT; end if; when PID_LIST_END => -- TODO null; when others => -- If MUST_UNDERSTAND Flag is set, we have incompatible communication. Drop Packet if (must_understand = '1') then stage_next <= SKIP_PACKET; -- Else skip Uknown Parameter else stage_next <= SKIP_PARAMETER; end if; end case; end if; when CHECK_DEFAULT => -- DEFAULT stage_next <= PARTICIPANT_MATCH_STAGE; case (message_type) is when PDP => -- Check Domain Tag against Default if necessary if (not check_mask(rcvd, RCVD_DOMAIN_TAG_FLAG) and DOMAIN_TAG /= DEFAULT_DOMAIN_TAG) then participant_match_next <= '0'; end if; when EDP => -- Defaults tmp_endpoint_mask := (others => '1'); if (is_subscriber = '1') then tmp_default_qos_match := READER_DEFAULT_QOS_MATCH; else tmp_default_qos_match := WRITER_DEFAULT_QOS_MATCH; end if; if (not check_mask(rcvd, RCVD_DURABILITY_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DURABILITY_QOS; end if; if (not check_mask(rcvd, RCVD_PRESENTATION_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.PRESENTATION_QOS; end if; if (not check_mask(rcvd, RCVD_DEADLINE_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DEADLINE_QOS; end if; if (not check_mask(rcvd, RCVD_LATENCY_BUDGET_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.LATENCY_BUDGET_QOS; end if; if (not check_mask(rcvd, RCVD_OWNERSHIP_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.OWNERSHIP_QOS; end if; if (not check_mask(rcvd, RCVD_LIVELINESS_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.LIVELINESS_QOS; end if; if (not check_mask(rcvd, RCVD_RELIABILITY_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.RELIABILITY_QOS; end if; if (not check_mask(rcvd, RCVD_DESTINATION_ORDER_QOS_FLAG)) then tmp_endpoint_mask := tmp_endpoint_mask and tmp_default_qos_match.DESTINATION_ORDER_QOS; end if; endpoint_mask_next <= endpoint_mask and tmp_endpoint_mask; when others => null; end case; when LATCH_STRING_LENGTH => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; string_length_next <= unsigned(data_in_swapped); stage_next <= COMPARE_STRING; compare_length_next <= to_unsigned(1,compare_length'length); cnt_next <= 0; end if; when COMPARE_STRING => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; compare_length_next <= compare_length + 1; cnt_next <= cnt + 1; -- NOTE: This assumes that the Parameter is padded with zeroes (Since we also compare the padding) -- XTypes 7.4.1.1 requires padding bytes for "PLAIN_CDR" to be zero, but does not specify the value for "PL_CDR" -- Unmark matches on string comparison missmatch case (string_content) is when TOPIC_NAME_TYPE => for i in 0 to NUM_ENDPOINTS-1 loop if (data_in /= ENDPOINT_TOPIC(i)(cnt)) then endpoint_mask_next(i) <= '0'; end if; end loop; when TYPE_NAME_TYPE => for i in 0 to NUM_ENDPOINTS-1 loop if (data_in /= ENDPOINT_TYPE(i)(cnt)) then endpoint_mask_next(i) <= '0'; end if; end loop; when DOMAIN_TAG_TYPE => if (data_in /= DOMAIN_TAG(cnt)) then participant_match_next <= '0'; end if; when others => null; end case; -- NOTE: "compare_length" counts the 4-Byte words, while "string_length" contains the total string octets/bytes -- End of String (Exit Condition) if ((compare_length & "00") >= string_length) then -- DONE stage_next <= SKIP_PARAMETER; end if; end if; when MATCH_GUID => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Check if GUID Prefix valid (Should be the same as the GUID Prefix of the Packet) and update the Entity ID case (cnt) is when 0 => if (data_in /= guid(0)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; when 1 => if (data_in /= guid(1)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; when 2 => if (data_in /= guid(2)) then stage_next <= SKIP_PACKET; else cnt_next <= cnt + 1; end if; when 3 => guid_next(3) <= data_in; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when MATCH_DOMAIN_ID => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Match Domain ID if (data_in_swapped /= DOMAIN_ID) then participant_match_next <= '0'; end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when MATCH_PROTOCOL_VERSION => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Match major Protocol Version if(data_in(31 downto 24) /= PROTOCOLVERSION_2_4(15 downto 8)) then participant_match_next <= '0'; end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when LATCH_LOCATOR => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is -- Locator Kind when 0 => -- Check if UDPv4 Locator if (data_in_swapped /= LOCATOR_KIND_UDPv4) then -- Skip stage_next <= SKIP_PARAMETER; else cnt_next <= cnt + 1; end if; -- Locator Port when 1 => -- Latch Source Port -- SANITY CHECK: Check if UDP Port valid if (data_in_swapped(UDP_PORT_INVALID'range) /= UDP_PORT_INVALID) then -- NOTE: We have to make sure that the address is also valid -- Temporal Latch long_latch_next <= data_in_swapped; cnt_next <= cnt + 1; else -- Ignore stage_next <= SKIP_PARAMETER; end if; -- Locator Address 1/4 when 2 => cnt_next <= cnt + 1; -- Locator Address 2/4 when 3 => cnt_next <= cnt + 1; -- Locator Address 3/4 when 4 => cnt_next <= cnt + 1; -- Locator Address 4/4 (IPv4) when 5 => -- Latch Src Addr -- SANITY CHECK: Check if IPv4 Address valid if (data_in_swapped /= IPv4_ADDRESS_INVALID) then if (is_meta_addr = '0') then def_addr_next <= data_in; def_port_next <= long_latch(def_port'length-1 downto 0); else meta_addr_next <= data_in; meta_port_next <= long_latch(meta_port'length-1 downto 0); end if; end if; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when LATCH_EXPECTS_INLINE_QOS => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch 'expectsInlineQoS' reader_flags_next(READER_EXPECTS_INLINE_QOS_FLAG) <= data_in(24); -- DONE stage_next <= SKIP_PARAMETER; end if; when LATCH_LEASE_DURATION => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Latch Lease Duration case (cnt) is when 0 => lease_duration_next(0) <= unsigned(data_in_swapped); cnt_next <= cnt + 1; when 1 => lease_duration_next(1) <= unsigned(data_in_swapped); -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when CHECK_REMOTE_BUILTIN_ENDPOINTS => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- SANITY CHECK (Builtin Participant and Participant Message Endpoints have to be always available) if ( data_in_swapped(DISC_BUILTIN_ENDPOINT_PARTICIPANT_ANNOUNCER) = '0' or data_in_swapped(DISC_BUILTIN_ENDPOINT_PARTICIPANT_DETECTOR) = '0' or data_in_swapped(BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_WRITER) = '0' or data_in_swapped(BUILTIN_ENDPOINT_PARTICIPANT_MESSAGE_DATA_READER) = '0') then participant_match_next <= '0'; end if; -- Check for necessary Builtin Endpoints for Readers and Writers if ( (NUM_READERS > 0 and (data_in_swapped(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_ANNOUNCER) = '0' or data_in_swapped(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_DETECTOR) = '0')) and (NUM_WRITERS > 0 and (data_in_swapped(DISC_BUILTIN_ENDPOINT_SUBSCRIPTIONS_ANNOUNCER) = '0' or data_in_swapped(DISC_BUILTIN_ENDPOINT_PUBLICATIONS_DETECTOR) = '0')) ) then participant_match_next <= '0'; end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when RXO_DURABILITY => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_DURABILITY_QOS(i)))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- Set Reader Flag if (is_subscriber = '1') then -- XXX: Quartus Limitation --reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG) <= '0' when (data_in_swapped = VOLATILE_DURABILITY_QOS) else '1'; if (data_in_swapped = VOLATILE_DURABILITY_QOS) then reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG) <= '0'; else reader_flags_next(READER_EXPECTS_HISTORICAL_DATA_FLAG) <= '1'; end if; end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when RXO_DEADLINE => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is when 0 => long_latch_next <= data_in_swapped; cnt_next <= cnt + 1; when 1 => tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped)); -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_DEADLINE_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when RXO_LIVELINESS => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with AUTOMATIC < MANUAL_BY_PARTICIPANT < MANUAL_BY_TOPIC for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_LIVELINESS_QOS(i)))) then endpoint_mask_next(i) <= '0'; end if; end loop; stage_next <= RXO_LEASE_DURATION; cnt_next <= 0; end if; when RXO_LEASE_DURATION => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is when 0 => -- Temporal Latch long_latch_next <= data_in_swapped; cnt_next <= cnt + 1; when 1 => tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped)); -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_LEASE_DURATION(i))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when RXO_RELIABILITY => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is when 0 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with BEST_EFFORT < RELIABLE for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_RELIABILITY_QOS(i)))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- Set Reader Flag if (is_subscriber = '1') then -- XXX: Quartus Limitation --reader_flags_next(READER_IS_BEST_EFFORT_FLAG) <= '1' when (data_in_swapped = BEST_EFFORT_RELIABILITY_QOS) else '0'; if (data_in_swapped = BEST_EFFORT_RELIABILITY_QOS) then reader_flags_next(READER_IS_BEST_EFFORT_FLAG) <= '1'; else reader_flags_next(READER_IS_BEST_EFFORT_FLAG) <= '0'; end if; end if; cnt_next <= cnt + 1; when 1 => -- NOTE: The max_blocking_time value is ignored cnt_next <= cnt + 1; when 2 => -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when RXO_DESTINATION_ORDER => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with BY_RECEPTION_TIMESTAMP < BY_SOURCE_TIMESTAMP for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_DESTINATION_ORDER_QOS(i)))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; end if; when RXO_OWNERSHIP => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered = requested for i in 0 to NUM_ENDPOINTS-1 loop if (data_in_swapped /= ENDPOINT_OWNERSHIP_QOS(i)) then endpoint_mask_next(i) <= '0'; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; end if; when RXO_PRESENTATION => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is when 0 => -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered >= requested, with INSTANCE < TOPIC < GROUP for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '1', unsigned(data_in_swapped), unsigned(ENDPOINT_PRESENTATION_QOS(i)))) then endpoint_mask_next(i) <= '0'; end if; end loop; cnt_next <= cnt + 1; when 1 => -- Check QoS Compatibility (Unmark match on incompatibility) for i in 0 to NUM_ENDPOINTS-1 loop -- data-in is Subscriber-Requested -- COMPATIBLE (DDS v1.4): requested=FALSE or requested=offered=TRUE if (is_subscriber = '1') then if (data_in(24) = '1' and not ENDPOINT_COHERENT_ACCESS(i)) then endpoint_mask_next(i) <= '0'; end if; if (data_in(16) = '1' and not ENDPOINT_ORDERED_ACCESS(i)) then endpoint_mask_next(i) <= '0'; end if; -- data-in is Publisher-Offered else if (data_in(24) = '0' and ENDPOINT_COHERENT_ACCESS(i)) then endpoint_mask_next(i) <= '0'; end if; if (data_in(16) = '0' and ENDPOINT_ORDERED_ACCESS(i)) then endpoint_mask_next(i) <= '0'; end if; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when RXO_PARTITION => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- NOTE: Endpoints are only matched against the default empty partition. -- Match Partition Names if (data_in_swapped /= (data_in_swapped'reverse_range => '0')) then endpoint_mask_next <= (others => '0'); end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when RXO_LATENCY_BUDGET => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; case (cnt) is when 0 => long_latch_next <= data_in_swapped; cnt_next <= cnt + 1; when 1 => tmp_dw := (0 => unsigned(long_latch), 1 => unsigned(data_in_swapped)); -- Check QoS Compatibility (Unmark match on incompatibility) -- COMPATIBLE (DDS v1.4): offered <= requested for i in 0 to NUM_ENDPOINTS-1 loop if (not check_qos_compatibility(is_subscriber, '0', tmp_dw, ENDPOINT_LATENCY_BUDGET_QOS(i))) then endpoint_mask_next(i) <= '0'; end if; end loop; -- DONE stage_next <= SKIP_PARAMETER; when others => null; end case; end if; when CHECK_MAX_SIZE_SERIALIZED => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Ignore Publishers that may need Fragmentation if (is_subscriber = '0' and unsigned(data_in_swapped) > to_unsigned(UDP_MAX_SIZE_SERIALIZED, CDR_LONG_WIDTH)) then endpoint_mask_next <= (others => '0'); end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when CHECK_STATUS_INFO => -- Input FIFO Guard if (empty = '0') then rd_guard := '1'; -- Mark if Unregister/Disposed Status if (data_in(STATUS_INFO_DISPOSED_FLAG) = '1' or data_in(STATUS_INFO_UNREGISTERED_FLAG) = '1') then ud_status_next <= '1'; end if; -- DONE stage_next <= SKIP_PARAMETER; end if; when PARTICIPANT_MATCH_STAGE => -- Precondition: participant_data set (PMF_SPDP_SEQ_NR_FLAG/PMF_PUB_SEQ_NR_FLAG/PMF_SUB_SEQ_NR_FLAG/PMF_MES_SEQ_NR_FLAG) -- Wait for Participant Search to finish if (mem_op_done = '1') then assert_sn; -- Participant not in Buffer if (mem_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then -- Participant Match if (message_type = PDP and participant_match = '1') then -- Add participant in buffer mem_op_start <= '1'; mem_opcode <= INSERT_PARTICIPANT; tmp_dw := time + lease_duration; deadline <= tmp_dw; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; -- DONE stage_next <= SKIP_PACKET; else -- Ignore all other messages, since there is no corresponding participant in the buffer. stage_next <= SKIP_PACKET; end if; -- Participant in Buffer else -- Participant Announcement if (message_type = PDP) then -- Newer Sequence Number if (mem_seq_nr <= seq_nr) then -- Participant Unmatch if (participant_match = '0') then -- Remove participant from buffer mem_op_start <= '1'; mem_opcode <= REMOVE_PARTICIPANT; -- Inform ENDPOINTS stage_next <= INFORM_ENDPOINTS_PARTICIPANT_UNMATCH; cnt_next <= 0; -- Participant remains matched else -- Update Participant Data and Lease mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG or PMF_SPDP_SEQ_NR_FLAG or PMF_LEASE_DURATION_FLAG or PMF_LEASE_DEADLINE_FLAG; tmp_dw := time + lease_duration; deadline <= tmp_dw; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; -- DONE stage_next <= SKIP_PACKET; end if; -- Old Sequence Number else -- Update Lease mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; mem_field_flags <= PMF_LEASE_DEADLINE_FLAG; tmp_dw := time + lease_duration; deadline <= tmp_dw; -- XXX: Possible Worst Case Path (64-bit addition and comparison in same clock) -- Update Check Time if (tmp_dw < check_time) then check_time_next <= tmp_dw; end if; -- DONE stage_next <= SKIP_PACKET; end if; -- NOTE: We only process the Sequences in order. This may lead to more traffic being exchanged -- (since all Data messages with a higher sequence number than the next expected will be ignored), -- but keeps the logic simple. -- Endpoint (Next Expected Sequence Number) elsif (message_type = EDP and mem_seq_nr = seq_nr) then -- Store new Sequence Number mem_op_start <= '1'; mem_opcode <= UPDATE_PARTICIPANT; if (is_subscriber = '0') then mem_field_flags <= PMF_PUB_SEQ_NR_FLAG; else mem_field_flags <= PMF_SUB_SEQ_NR_FLAG; end if; -- At least one local Endpoint match if (endpoint_mask /= (endpoint_mask'range => '0')) then -- Propagate Matches to local Endpoints stage_next <= INFORM_ENDPOINTS_MATCH; cnt_next <= 0; -- No local Endpoint matches else -- Propagate Matches to local Endpoints stage_next <= INFORM_ENDPOINTS_UNMATCH; cnt_next <= 0; end if; else -- Ignore (Messages are handled in a dedicated stage) stage_next <= SKIP_PACKET; end if; end if; end if; when INFORM_ENDPOINTS_MATCH => -- Precondition: participant_data set (PMF_DEFAULT_IPV4_ADDR_FLAG, PMF_UDP_PORT_FLAG) -- Wait for Participant Data if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_DEFAULT_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG) severity FAILURE; -- Output FIFO Guard if ((endpoint_mask and full_ue) = (full_ue'range => '0')) then wr_sig <= '1'; case (cnt) is -- Match Opcode when 0 => data_out_sig <= EMO_ENDPOINT_MATCH; cnt_next <= cnt + 1; -- GUID Prefix 1/3 when 1 => data_out_sig <= guid(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 2 => data_out_sig <= guid(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 3 => data_out_sig <= guid(2); cnt_next <= cnt + 1; -- Entity ID when 4 => data_out_sig <= guid(3); cnt_next <= cnt + 1; -- IPv4 Address when 5 => -- If Endpoint did not set Address, use Participant Default if (def_addr /= (def_addr'reverse_range => '0')) then data_out_sig <= def_addr; else data_out_sig <= participant_data.def_addr; end if; cnt_next <= cnt + 1; -- UDPv4 Port and Reader Flags when 6 => -- Default data_out_sig <= (others => '0'); last_word_out_sig <= '1'; -- If Endpoint did not set Port, use Participant Default if (def_port /= (def_port'reverse_range => '0')) then data_out_sig(31 downto 16) <= def_port; else data_out_sig(31 downto 16) <= participant_data.def_port; end if; if (is_subscriber = '1') then data_out_sig(15 downto 0) <= reader_flags; end if; -- DONE stage_next <= INFORM_ENDPOINTS_UNMATCH; cnt_next <= 0; when others => null; end case; end if; end if; when INFORM_ENDPOINTS_UNMATCH => -- Output FIFO Guard if (((not endpoint_mask) and full_ue) = (full_ue'range => '0')) then wr_sig <= '1'; case (cnt) is -- Match Opcode when 0 => data_out_sig <= EMO_ENDPOINT_UNMATCH; cnt_next <= cnt + 1; -- GUID Prefix 1/3 when 1 => data_out_sig <= guid(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 2 => data_out_sig <= guid(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 3 => data_out_sig <= guid(2); cnt_next <= cnt + 1; -- Entity ID when 4 => data_out_sig <= guid(3); last_word_out_sig <= '1'; -- DONE stage_next <= SKIP_PACKET; when others => null; end case; end if; when INFORM_ENDPOINTS_PARTICIPANT_UNMATCH => -- Output FIFO Guard if (full_ue = (full_ue'range => '0')) then wr_sig <= '1'; case (cnt) is -- Match Opcode when 0 => data_out_sig <= EMO_PARTICIPANT_UNMATCH; cnt_next <= cnt + 1; -- GUID Prefix 1/3 when 1 => data_out_sig <= guid(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 2 => data_out_sig <= guid(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 3 => data_out_sig <= guid(2); last_word_out_sig <= '1'; -- Currently in Stale Check if (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 0; else -- DONE stage_next <= SKIP_PACKET; end if; when others => null; end case; end if; when SEND_HEADER => -- Precondition: participant_data set (PMF_META_IPV4_ADDR_FLAG, PMF_UDP_PORT_FLAG) [if return_stage /= SEND_PARTICIPANT_ANNOUNCEMENT] -- Wait for Participant Data if (mem_op_done = '1') then if (return_stage /= SEND_PARTICIPANT_ANNOUNCEMENT) then assert check_mask(current_pmf, PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG) severity FAILURE; end if; if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- OUTPUT HEADER -- Src IPv4 Address when 0 => data_out_sig <= DEFAULT_IPv4_ADDRESS; cnt_next <= cnt + 1; -- Dest IPv4 Address when 1 => -- Set Default Multicast Announce Address if Participant Announcement if (return_stage = SEND_PARTICIPANT_ANNOUNCEMENT) then data_out_sig <= DEFAULT_IPv4_META_ADDRESS; else data_out_sig <= participant_data.meta_addr; end if; cnt_next <= cnt + 1; -- Src and Dest UDPv4 Ports when 2 => -- Set Default Multicast Announce Port if Participant Announcement if (return_stage = SEND_PARTICIPANT_ANNOUNCEMENT) then data_out_sig <= META_IPv4_UNICAST_PORT & META_IPv4_MULTICAST_PORT; else data_out_sig <= META_IPv4_UNICAST_PORT & participant_data.meta_port; end if; cnt_next <= cnt + 1; -- RTPS MESSAGE HEADER when 3 => data_out_sig <= PROTOCOL_RTPS; cnt_next <= cnt + 1; when 4 => data_out_sig <= PROTOCOLVERSION_2_4 & VENDORID; cnt_next <= cnt + 1; when 5 => data_out_sig <= GUIDPREFIX(0); cnt_next <= cnt + 1; when 6 => data_out_sig <= GUIDPREFIX(1); cnt_next <= cnt + 1; when 7 => data_out_sig <= GUIDPREFIX(2); -- Continue with respective RTPS Submessage stage_next <= return_stage; cnt_next <= 0; participant_data_cnt_next <= 0; publisher_data_cnt_next <= 0; subscriber_data_cnt_next <= 0; when others => null; end case; end if; end if; when SEND_PARTICIPANT_ANNOUNCEMENT => if (full_ro = '0') then wr_sig <= '1'; -- Send Participant Data data_out_sig <= LOCAL_PARTICIPANT_DATA.data(participant_data_cnt); -- Exit Condition if (participant_data_cnt = (LOCAL_PARTICIPANT_DATA.length-1)) then last_word_out_sig <= '1'; -- DONE stage_next <= IDLE; else participant_data_cnt_next <= participant_data_cnt + 1; end if; end if; when SEND_ACKNACK => -- Precondition: participant_data set (PMF_PUB_SEQ_NR_FLAG, PMF_SUB_SEQ_NR_FLAG, PMF_MES_SEQ_NR_FLAG) -- Wait for Participant Data if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_PUB_SEQ_NR_FLAG or PMF_SUB_SEQ_NR_FLAG or PMF_MES_SEQ_NR_FLAG) severity FAILURE; if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- ACKNACK RTPS SUBMESSAGE (Publication) -- RTPS Submessage Header when 0 => data_out_sig <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 1 => data_out_sig <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; cnt_next <= cnt + 1; -- Writer Entity ID when 2 => data_out_sig <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER; cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 1/2) when 3 => data_out_sig <= std_logic_vector(participant_data.pub_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 2/2) when 4 => data_out_sig <= std_logic_vector(participant_data.pub_seq_nr(1)); cnt_next <= cnt + 1; -- Sequence Number Set (NumBits) when 5 => data_out_sig <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap) when 6 => -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet) -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist) data_out_sig <= (others => '1'); cnt_next <= cnt + 1; -- Count when 7 => data_out_sig <= std_logic_vector(count); cnt_next <= cnt + 1; -- ACKNACK RTPS SUBMESSAGE (Subscription) -- RTPS Submessage Header when 8 => data_out_sig <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 9 => data_out_sig <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; cnt_next <= cnt + 1; -- Writer Entity ID when 10 => data_out_sig <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 1/2) when 11 => data_out_sig <= std_logic_vector(participant_data.sub_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 2/2) when 12 => data_out_sig <= std_logic_vector(participant_data.sub_seq_nr(1)); cnt_next <= cnt + 1; -- Sequence Number Set (NumBits) when 13 => data_out_sig <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap) when 14 => -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet) -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist) data_out_sig <= (others => '1'); cnt_next <= cnt + 1; -- Count when 15 => data_out_sig <= std_logic_vector(count); cnt_next <= cnt + 1; -- ACKNACK RTPS SUBMESSAGE (Message) -- RTPS Submessage Header when 16 => data_out_sig <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 17 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; cnt_next <= cnt + 1; -- Writer Entity ID when 18 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 1/2) when 19 => data_out_sig <= std_logic_vector(participant_data.mes_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap Base 2/2) when 20 => data_out_sig <= std_logic_vector(participant_data.mes_seq_nr(1)); cnt_next <= cnt + 1; -- Sequence Number Set (NumBits) when 21 => data_out_sig <= std_logic_vector(to_unsigned(CDR_LONG_WIDTH, CDR_LONG_WIDTH)); cnt_next <= cnt + 1; -- Sequence Number Set (Bitmap) when 22 => -- NOTE: In order to avoid having to generate a variable sized bitmap, we always request the next 32 sequence numbers, even if they do not exist (yet) -- XXX: Assumes correct implementation of the RTPS Protocol (i.e. Writer ignores requested SNs that do not exist) data_out_sig <= (others => '1'); cnt_next <= cnt + 1; -- Count when 23 => data_out_sig <= std_logic_vector(count); last_word_out_sig <= '1'; -- Continue stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 3; when others => null; end case; end if; end if; when SEND_HEARTBEAT => if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- HEARTBEAT RTPS SUBMESSAGE (Publication) -- RTPS Submessage Header when 0 => data_out_sig <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 1 => data_out_sig <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR; cnt_next <= cnt + 1; -- Writer Entity ID when 2 => data_out_sig <= ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER; cnt_next <= cnt + 1; -- Sequence Number 1/2 when 3 => data_out_sig <= std_logic_vector(FIRST_SEQUENCENUMBER(0)); cnt_next <= cnt + 1; -- Sequence Number 2/2 when 4 => data_out_sig <= std_logic_vector(FIRST_SEQUENCENUMBER(1)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 5 => data_out_sig <= std_logic_vector(PUB_SEQUENCENUMBER(0)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 6 => data_out_sig <= std_logic_vector(PUB_SEQUENCENUMBER(1)); cnt_next <= cnt + 1; -- Count when 7 => data_out_sig <= std_logic_vector(count); cnt_next <= cnt + 1; -- HEARTBEAT RTPS SUBMESSAGE (Subscription) -- RTPS Submessage Header when 8 => data_out_sig <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 9 => data_out_sig <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR; cnt_next <= cnt + 1; -- Writer Entity ID when 10 => data_out_sig <= ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER; cnt_next <= cnt + 1; -- Sequence Number 1/2 when 11 => data_out_sig <= std_logic_vector(FIRST_SEQUENCENUMBER(0)); cnt_next <= cnt + 1; -- Sequence Number 2/2 when 12 => data_out_sig <= std_logic_vector(FIRST_SEQUENCENUMBER(1)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 13 => data_out_sig <= std_logic_vector(SUB_SEQUENCENUMBER(0)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 14 => data_out_sig <= std_logic_vector(SUB_SEQUENCENUMBER(1)); cnt_next <= cnt + 1; -- Count when 15 => data_out_sig <= std_logic_vector(count); cnt_next <= cnt + 1; -- HEARTBEAT RTPS SUBMESSAGE (Message) -- RTPS Submessage Header when 16 => data_out_sig <= SID_HEARTBEAT & "00000010" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 17 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; cnt_next <= cnt + 1; -- Writer Entity ID when 18 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; cnt_next <= cnt + 1; -- Sequence Number 1/2 when 19 => data_out_sig <= std_logic_vector(man_live_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number 2/2 when 20 => data_out_sig <= std_logic_vector(man_live_seq_nr(1)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 21 => data_out_sig <= std_logic_vector(auto_live_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number 1/2 when 22 => data_out_sig <= std_logic_vector(auto_live_seq_nr(1)); cnt_next <= cnt + 1; -- Count when 23 => data_out_sig <= std_logic_vector(count); -- If manual and automatic sequence numbers are not consecutive, we have only asserted the automatic liveliness if (live_gap_start /= auto_live_seq_nr) then stage_next <= SEND_MES_AUTO_LIVE; cnt_next <= 0; -- Else we need to send both (manual and automatic) else stage_next <= SEND_MES_MAN_LIVE; cnt_next <= 0; end if; when others => null; end case; end if; when SEND_PUB_DATA => -- Precondition: participant_data set (PMF_EXTRA_FLAGS_FLAG) -- Wait for Participant Data if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE; -- If Publisher Data not scheduled for response or no Writers available, skip if (not check_mask(participant_data.extra_flags, EF_PUB_DATA_FLAG) or NUM_WRITERS = 0) then stage_next <= SEND_SUB_DATA; -- Output FIFO Guard elsif (full_ro = '0') then wr_sig <= '1'; -- Send Publisher Data data_out_sig <= WRITER_ENDPOINT_DATA.data(publisher_data_cnt); -- Exit Condition if (publisher_data_cnt = (WRITER_ENDPOINT_DATA.length-1)) then last_word_out_sig <= '1'; -- If we still have Data to sent, continue if (check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG) or check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then stage_next <= SEND_HEADER; return_stage_next <= SEND_SUB_DATA; cnt_next <= 0; -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 4; else -- DONE stage_next <= IDLE; end if; else publisher_data_cnt_next <= publisher_data_cnt + 1; end if; end if; end if; when SEND_SUB_DATA => -- Precondition: participant_data set (PMF_EXTRA_FLAGS_FLAG) -- Wait for Participant Data if (mem_op_done = '1') then assert check_mask(current_pmf, PMF_EXTRA_FLAGS_FLAG) severity FAILURE; -- If Subscriber Data not scheduled for response or no Readers available, skip if (not check_mask(participant_data.extra_flags, EF_SUB_DATA_FLAG) or NUM_READERS = 0) then stage_next <= SEND_MES_MAN_LIVE; cnt_next <= 0; -- Output FIFO Guard elsif (full_ro = '0') then wr_sig <= '1'; -- Send Subscriber Data data_out_sig <= READER_ENDPOINT_DATA.data(subscriber_data_cnt); -- Exit Condition if (subscriber_data_cnt = (READER_ENDPOINT_DATA.length-1)) then last_word_out_sig <= '1'; -- If we still have Data to sent, continue if (check_mask(participant_data.extra_flags, EF_MES_DATA_FLAG)) then stage_next <= SEND_HEADER; return_stage_next <= SEND_MES_MAN_LIVE; cnt_next <= 0; -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 4; else -- DONE stage_next <= IDLE; end if; else subscriber_data_cnt_next <= subscriber_data_cnt + 1; end if; end if; end if; when SEND_MES_MAN_LIVE => -- Output FIFO Guard if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- DATA RTPS SUBMESSAGE (Participant Message) -- RTPS Submessage Header when 0 => data_out_sig <= SID_DATA & "00000100" & std_logic_vector(to_unsigned(44, 16)); cnt_next <= cnt + 1; -- ExtraFlags, octetsToInlineQoS when 1 => data_out_sig <= x"0000" & std_logic_vector(to_unsigned(16, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 2 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; cnt_next <= cnt + 1; -- Writer Entity ID when 3 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; cnt_next <= cnt + 1; -- Sequence Number 1/2 when 4 => data_out_sig <= std_logic_vector(man_live_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number 2/2 when 5 => data_out_sig <= std_logic_vector(man_live_seq_nr(1)); cnt_next <= cnt + 1; -- Serialized Payload Header when 6 => data_out_sig <= CDR_BE & x"0000"; cnt_next <= cnt + 1; -- Serialized Payload BEGIN -- GUID Prefix 1/3 when 7 => data_out_sig <= GUIDPREFIX(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 8 => data_out_sig <= GUIDPREFIX(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 9 => data_out_sig <= GUIDPREFIX(2); cnt_next <= cnt + 1; -- Participant Message Kind when 10 => data_out_sig <= PARTICIPANT_MESSAGE_DATA_KIND_MANUAL_LIVELINESS_UPDATE; cnt_next <= cnt + 1; -- Data Length when 11 => data_out_sig <= (others => '0'); -- If manual and automatic sequence numbers are not consecutive, we need to send a GAP Message if (live_gap_start /= auto_live_seq_nr) then stage_next <= SEND_MES_GAP; cnt_next <= 0; else stage_next <= SEND_MES_AUTO_LIVE; cnt_next <= 0; end if; when others => null; end case; end if; when SEND_MES_GAP => -- Output FIFO Guard if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- DATA RTPS SUBMESSAGE (Participant Message) -- RTPS Submessage Header when 0 => data_out_sig <= SID_GAP & "00000000" & std_logic_vector(to_unsigned(28, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 1 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; cnt_next <= cnt + 1; -- Writer Entity ID when 2 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; cnt_next <= cnt + 1; -- GAP Start Sequence Number 1/2 when 3 => data_out_sig <= std_logic_vector(live_gap_start(0)); cnt_next <= cnt + 1; -- GAP Start Sequence Number 2/2 when 4 => data_out_sig <= std_logic_vector(live_gap_start(1)); cnt_next <= cnt + 1; -- GAP End Sequence Number Set (Bitmap Base 1/2) when 5 => data_out_sig <= std_logic_vector(live_gap_end(0)); cnt_next <= cnt + 1; -- GAP End Sequence Number Set (Bitmap Base 2/2) when 6 => data_out_sig <= std_logic_vector(live_gap_end(1)); cnt_next <= cnt + 1; -- GAP End Sequence Number Set (NumBits) when 7 => data_out_sig <= (others => '0'); stage_next <= SEND_MES_AUTO_LIVE; cnt_next <= 0; when others => null; end case; end if; when SEND_MES_AUTO_LIVE => -- Output FIFO Guard if (full_ro = '0') then wr_sig <= '1'; case (cnt) is -- DATA RTPS SUBMESSAGE (Participant Message) -- RTPS Submessage Header when 0 => data_out_sig <= SID_DATA & "00000100" & std_logic_vector(to_unsigned(44, 16)); cnt_next <= cnt + 1; -- ExtraFlags, octetsToInlineQoS when 1 => data_out_sig <= x"0000" & std_logic_vector(to_unsigned(16, 16)); cnt_next <= cnt + 1; -- Reader Entity ID when 2 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER; cnt_next <= cnt + 1; -- Writer Entity ID when 3 => data_out_sig <= ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER; cnt_next <= cnt + 1; -- Sequence Number 1/2 when 4 => data_out_sig <= std_logic_vector(auto_live_seq_nr(0)); cnt_next <= cnt + 1; -- Sequence Number 2/2 when 5 => data_out_sig <= std_logic_vector(auto_live_seq_nr(1)); cnt_next <= cnt + 1; -- Serialized Payload Header when 6 => data_out_sig <= CDR_BE & x"0000"; cnt_next <= cnt + 1; -- Serialized Payload BEGIN -- GUID Prefix 1/3 when 7 => data_out_sig <= GUIDPREFIX(0); cnt_next <= cnt + 1; -- GUID Prefix 2/3 when 8 => data_out_sig <= GUIDPREFIX(1); cnt_next <= cnt + 1; -- GUID Prefix 3/3 when 9 => data_out_sig <= GUIDPREFIX(2); cnt_next <= cnt + 1; -- Participant Message Kind when 10 => data_out_sig <= PARTICIPANT_MESSAGE_DATA_KIND_AUTOMATIC_LIVELINESS_UPDATE; cnt_next <= cnt + 1; -- Data Length when 11 => data_out_sig <= (others => '0'); last_word_out_sig <= '1'; -- If we are in the middle of a liveliness assertion, find the next Participant destination if (is_live_assert = '1') then mem_op_start <= '1'; mem_opcode <= GET_NEXT_PARTICIPANT; mem_field_flags <= PMF_META_IPV4_ADDR_FLAG or PMF_UDP_PORT_FLAG; stage_next <= FIND_PARTICIPANT_DEST; -- Currently in Stale Check elsif (stale_check = '1') then stage_next <= PARTICIPANT_STALE_CHECK; cnt_next <= 4; else -- DONE stage_next <= IDLE; end if; when others => null; end case; end if; when SKIP_PARAMETER => -- Consumed last word of Packet if (last_word_in_latch = '1' and last_word_in = '0') then -- Reset Last Word In Latch last_word_in_latch_next <= '0'; -- Continue parsing next Packet stage_next <= IDLE; -- Reset Parameter End parameter_end_next <= (others => '1'); -- End of Parameter elsif ((read_cnt & "00" ) >= parameter_end) then -- Parse Next Parameter -- NOTE: data_in is already showing the next parameter stage_next <= PROCESS_PL; -- Reset Parameter End parameter_end_next <= (others => '1'); -- Input FIFO Guard elsif (empty = '0') then -- Skip-Read rd_guard := '1'; end if; when SKIP_PACKET => -- NOTE: At the end of a Stale Entry Removal this stage is entered, without having started reading a Packet from input. -- Reset Parameter End parameter_end_next <= (others => '1'); -- Consumed last word of Packet if (last_word_in_latch = '1' and last_word_in = '0') then -- Reset Last Word In Latch last_word_in_latch_next <= '0'; -- DONE stage_next <= IDLE; -- Input FIFO Guard elsif (empty = '0') then -- Skip-Read rd_guard := '1'; 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 = '0') and rd_guard = '1') then -- Force rd_sig low rd_sig <= '0'; -- Notify Endpoints of EOP last_word_out_sig <= '1'; -- TODO: Necessary? (We do not pass through input to output, so a EOP should not leave us "stranded" during a write out) -- Continue parsing next Packet stage_next <= IDLE; -- Reset Last Word In Latch last_word_in_latch_next <= '0'; -- Reset Parameter End parameter_end_next <= (others => '1'); -- Read outside of Parameter Length -- NOTE: If the Parameter Length is smaller than expected for a particular parameter, there will be a read from input FIFO while -- the Parameter Length has been reached and will be caught by this clause. -- The SKIP_PARAMETER clause prevents a read signal from occuring in this situation, and thus prevents from entering this state. elsif ((read_cnt & "00") >= parameter_end and rd_guard = '1') then -- Force rd_sig low rd_sig <= '0'; -- Notify Endpoints of EOP last_word_out_sig <= '1'; -- Invalid Parameter Length, Skip Packet stage_next <= SKIP_PACKET; -- Reset Parameter End parameter_end_next <= (others => '1'); -- DEFAULT else rd_sig <= rd_guard; end if; end process; -- *Participant Memory Process* -- STATE DESCRIPTION -- IDLE Idle State. Done Signal is pulled high and Memory FSM accepts new memory operations -- SEARCH_PARTICIPANT See Memory OPCODE Description -- GET_NEXT_PARTICIPANT See Memory OPCODE Description -- GET_PARTICIPANT_DATA Latch specified Participant Data for use by main process -- INSERT_PARTICIPANT See Memory OPCODE Description -- UPDATE_PARTICIPANT See Memory OPCODE Description -- REMOVE_PARTICIPANT See Memory OPCODE Description -- RESET_MEMORY Reset Endpoint Memory to Empty State mem_ctrl_prc : process(all) begin -- DEFAULT Registered mem_stage_next <= mem_stage; mem_addr_base_next <= mem_addr_base; mem_empty_head_next <= mem_empty_head; mem_occupied_head_next <= mem_occupied_head; mem_next_addr_base_next <= mem_next_addr_base; mem_prev_addr_base_next <= mem_prev_addr_base; mem_cnt_next <= mem_cnt; participant_data_next <= participant_data; participant_latch_data_next <= participant_latch_data; current_pmf_next <= current_pmf; -- DEFAULT Unregistered mem_abort_read <= '0'; mem_ready_out <= '0'; mem_valid_in <= '0'; mem_read <= '0'; mem_op_done <= '0'; mem_addr <= (others => '0'); mem_write_data <= (others => '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) participant_latch_data_next <= ( guid_prefix => (guid_next(0), guid_next(1), guid_next(2)), meta_addr => meta_addr, def_addr => def_addr, meta_port => meta_port, def_port => def_port, extra_flags => extra_flags, lease_duration => lease_duration, lease_deadline => deadline, res_time => res_time, seq_nr => next_seq_nr_next, field_flags => mem_field_flags ); case(mem_opcode) is when SEARCH_PARTICIPANT => -- Reset Data current_pmf_next <= mem_field_flags; participant_data_next <= ZERO_PARTICIPANT_DATA; -- Memory Empty if (mem_occupied_head = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; else mem_prev_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_addr_base_next <= mem_occupied_head; mem_stage_next <= SEARCH_PARTICIPANT; mem_cnt_next <= 0; end if; when INSERT_PARTICIPANT => -- Memory Full if (mem_empty_head = PARTICIPANT_MEMORY_MAX_ADDRESS) then report "Memory Full, Ignoring Participant Data" severity NOTE; else -- Reset Data current_pmf_next <= (others => '1'); participant_data_next <= ZERO_PARTICIPANT_DATA; mem_prev_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_next_addr_base_next <= mem_occupied_head; mem_addr_base_next <= mem_empty_head; mem_stage_next <= INSERT_PARTICIPANT; mem_cnt_next <= 0; end if; when UPDATE_PARTICIPANT => mem_stage_next <= UPDATE_PARTICIPANT; current_pmf_next <= current_pmf or mem_field_flags; if check_mask(mem_field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 0; elsif check_mask(mem_field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 1; elsif check_mask(mem_field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 2; elsif check_mask(mem_field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 3; elsif check_mask(mem_field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 5; elsif check_mask(mem_field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(mem_field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(mem_field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(mem_field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(mem_field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(mem_field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(mem_field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; when GET_FIRST_PARTICIPANT => -- Reset current_pmf_next <= mem_field_flags; participant_data_next <= ZERO_PARTICIPANT_DATA; -- No Instances available if (mem_occupied_head = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; else mem_prev_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_addr_base_next <= mem_occupied_head; mem_stage_next <= GET_NEXT_PARTICIPANT; mem_cnt_next <= 0; end if; when GET_NEXT_PARTICIPANT => -- Reset current_pmf_next <= mem_field_flags; participant_data_next <= ZERO_PARTICIPANT_DATA; -- No Instances available if (mem_next_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; else mem_prev_addr_base_next <= mem_addr_base; mem_addr_base_next <= mem_next_addr_base; mem_stage_next <= GET_NEXT_PARTICIPANT; mem_cnt_next <= 0; end if; when REMOVE_PARTICIPANT => -- Reset current_pmf_next <= (others => '0'); participant_data_next <= ZERO_PARTICIPANT_DATA; mem_stage_next <= REMOVE_PARTICIPANT; mem_cnt_next <= 0; when GET_PARTICIPANT => mem_addr_base_next <= mem_addr_update; if (mem_addr_base /= mem_addr_update) then -- Reset current_pmf_next <= mem_field_flags; participant_data_next <= ZERO_PARTICIPANT_DATA; else current_pmf_next <= current_pmf or mem_field_flags; end if; -- Get Instance Data mem_stage_next <= GET_PARTICIPANT_DATA; if check_mask(mem_field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 0; elsif check_mask(mem_field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 3; elsif check_mask(mem_field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 4; elsif check_mask(mem_field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(mem_field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(mem_field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(mem_field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(mem_field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(mem_field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(mem_field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(mem_field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(mem_field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(mem_field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else -- DONE mem_stage_next <= IDLE; end if; when others => null; end case; end if; when SEARCH_PARTICIPANT => case (mem_cnt) is -- GET Next Participant when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_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 1/3 when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_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 + PMF_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 + PMF_GUIDPREFIX_OFFSET + 2; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- READ Next Participant when 4 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then mem_next_addr_base_next <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH); mem_cnt_next <= mem_cnt + 1; 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 /= participant_latch_data.guid_prefix(0)) then mem_abort_read <= '1'; -- Reached List Tail, No Match if (mem_next_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; --No match -- DONE mem_stage_next <= IDLE; else -- Continue Search mem_prev_addr_base_next <= mem_addr_base; mem_addr_base_next <= mem_next_addr_base; mem_cnt_next <= 0; end if; else mem_cnt_next <= mem_cnt + 1; end if; end if; -- READ GUID Prefix 2/3 when 6 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then -- No Match if (mem_read_data /= participant_latch_data.guid_prefix(1)) then mem_abort_read <= '1'; -- Reached List Tail, No Match if (mem_next_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; --No match -- DONE mem_stage_next <= IDLE; else -- Continue Search mem_prev_addr_base_next <= mem_addr_base; mem_addr_base_next <= mem_next_addr_base; mem_cnt_next <= 0; end if; else mem_cnt_next <= mem_cnt + 1; end if; end if; -- READ GUID Prefix 3/3 when 7 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then -- No Match if (mem_read_data /= participant_latch_data.guid_prefix(2)) then -- Reached List Tail, No Match if (mem_next_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; --No match -- DONE mem_stage_next <= IDLE; else -- Continue Search mem_prev_addr_base_next <= mem_addr_base; mem_addr_base_next <= mem_next_addr_base; mem_cnt_next <= 0; end if; else -- Get Participant Data mem_stage_next <= GET_PARTICIPANT_DATA; if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 0; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 4; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else -- DONE mem_stage_next <= IDLE; end if; end if; end if; when others => null; end case; when GET_NEXT_PARTICIPANT => case (mem_cnt) is -- GET Next Participant when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- READ Next Participant when 1 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then mem_next_addr_base_next <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH); -- Get Instance Data mem_stage_next <= GET_PARTICIPANT_DATA; if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 0; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 4; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else -- DONE mem_stage_next <= IDLE; end if; end if; when others => null; end case; when GET_PARTICIPANT_DATA => case (mem_cnt) is -- GET GUID Prefix 1/3 when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_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 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_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 2 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 2; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 4; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else mem_cnt_next <= 23; end if; end if; -- GET Metatraffic IPv4 Address when 3 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 4; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; else mem_cnt_next <= 26; end if; end if; end if; -- GET Default IPv4 Address when 4 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; else mem_cnt_next <= 27; end if; end if; end if; -- GET UDP Ports when 5 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_UDP_PORT_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 6; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; else mem_cnt_next <= 28; end if; end if; end if; -- GET SPDP Sequence Number 1/2 when 6 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET SPDP Sequence Number 2/2 when 7 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 8; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; else mem_cnt_next <= 29; end if; end if; end if; -- GET Lease Duration 1/2 when 8 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET Lease Duration 2/2 when 9 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; else mem_cnt_next <= 31; end if; end if; end if; -- GET Lease Deadline 1/2 when 10 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET Lease Deadline 2/2 when 11 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; else mem_cnt_next <= 33; end if; end if; end if; -- GET Extra Flags when 12 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 13; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; else mem_cnt_next <= 35; end if; end if; end if; -- GET ACKNACK Response Time 1/2 when 13 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET ACKNACK Response Time 2/2 when 14 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 15; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; else mem_cnt_next <= 36; end if; end if; end if; -- GET HEARTBEAT Response Time 1/2 when 15 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET HEARTBEAT Response Time 2/2 when 16 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 17; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; else mem_cnt_next <= 38; end if; end if; end if; -- GET Publication Sequence Number 1/2 when 17 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET Publication Sequence Number 2/2 when 18 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 19; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; else mem_cnt_next <= 40; end if; end if; end if; -- GET Subscription Sequence Number 1/2 when 19 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET Subscription Sequence Number 2/2 when 20 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 21; else if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; else mem_cnt_next <= 42; end if; end if; end if; -- GET Message Sequence Number 1/2 when 21 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- GET Message Sequence Number 2/2 when 22 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_GUIDPREFIX_FLAG) then mem_cnt_next <= 23; elsif check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; else mem_cnt_next <= 44; end if; end if; -- READ GUID Prefix 1/3 when 23 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.guid_prefix(0) <= mem_read_data; mem_cnt_next <= mem_cnt + 1; end if; -- READ GUID Prefix 2/3 when 24 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.guid_prefix(1) <= mem_read_data; mem_cnt_next <= mem_cnt + 1; end if; -- READ GUID Prefix 3/3 when 25 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.guid_prefix(2) <= mem_read_data; if check_mask(participant_latch_data.field_flags,PMF_META_IPV4_ADDR_FLAG) then mem_cnt_next <= 26; elsif check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Metatraffic IPv4 Address when 26 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.meta_addr <= mem_read_data; if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 27; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Default IPv4 Address when 27 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.def_addr <= mem_read_data; if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 28; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ UDP Ports when 28 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.meta_port <= mem_read_data(WORD_WIDTH-1 downto UDP_PORT_WIDTH); participant_data_next.def_port <= mem_read_data(UDP_PORT_WIDTH-1 downto 0); if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 29; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ SPDP Sequence Number 1/2 when 29 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.spdp_seq_nr(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ SPDP Sequence Number 2/2 when 30 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.spdp_seq_nr(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 31; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Lease Duration 1/2 when 31 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.lease_duration(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ Lease Duration 2/2 when 32 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.lease_duration(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 33; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Lease Deadline 1/2 when 33 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.lease_deadline(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ Lease Deadline 2/2 when 34 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.lease_deadline(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 35; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Extra Flags when 35 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.extra_flags <= mem_read_data(EF_FLAG_WIDTH-1 downto 0); if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 36; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ ACKNACK Response Time 1/2 when 36 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.acknack_res_time(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ ACKNACK Response Time 2/2 when 37 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.acknack_res_time(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 38; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ HEARTBEAT Response Time 1/2 when 38 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.heartbeat_res_time(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ HEARTBEAT Response Time 2/2 when 39 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.heartbeat_res_time(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 40; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Publication Sequence Number 1/2 when 40 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.pub_seq_nr(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ Publication Sequence Number 2/2 when 41 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.pub_seq_nr(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 42; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Subscription Sequence Number 1/2 when 42 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.sub_seq_nr(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ Subscription Sequence Number 2/2 when 43 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.sub_seq_nr(1) <= unsigned(mem_read_data); if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 44; else -- DONE mem_stage_next <= IDLE; end if; end if; -- READ Message Sequence Number 1/2 when 44 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.mes_seq_nr(0) <= unsigned(mem_read_data); mem_cnt_next <= mem_cnt + 1; end if; -- READ Message Sequence Number 2/2 when 45 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then participant_data_next.mes_seq_nr(1) <= unsigned(mem_read_data); -- DONE mem_stage_next <= IDLE; end if; when others => null; end case; when INSERT_PARTICIPANT => -- Precondition: mem_addr_base set case (mem_cnt) is -- GET Next Pointer when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Next Pointer when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; mem_write_data <= std_logic_vector(resize(mem_occupied_head,WORD_WIDTH)); -- Memory Flow Control Guard if (mem_ready_in = '1') then -- Fix Occupied Head mem_occupied_head_next <= mem_addr_base; mem_cnt_next <= mem_cnt + 1; end if; -- READ Next Pointer when 2 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then -- Fix Empty List Head mem_empty_head_next <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH); mem_cnt_next <= mem_cnt + 1; end if; -- SET GUID Prefix 1/3 when 3 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_GUIDPREFIX_OFFSET; mem_write_data <= participant_latch_data.guid_prefix(0); participant_data_next.guid_prefix(0) <= participant_latch_data.guid_prefix(0); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET GUID Prefix 2/3 when 4 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 1; mem_write_data <= participant_latch_data.guid_prefix(1); participant_data_next.guid_prefix(1) <= participant_latch_data.guid_prefix(1); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET GUID Prefix 3/3 when 5 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_GUIDPREFIX_OFFSET + 2; mem_write_data <= participant_latch_data.guid_prefix(2); participant_data_next.guid_prefix(2) <= participant_latch_data.guid_prefix(2); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Metatraffic IPv4 Address when 6 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET; mem_write_data <= participant_latch_data.meta_addr; participant_data_next.meta_addr <= participant_latch_data.meta_addr; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Default IPv4 Address when 7 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET; mem_write_data <= participant_latch_data.def_addr; participant_data_next.def_addr <= participant_latch_data.def_addr; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET UDP Ports when 8 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_UDP_PORT_OFFSET; mem_write_data <= participant_latch_data.meta_port & participant_latch_data.def_port; participant_data_next.meta_port <= participant_latch_data.meta_port; participant_data_next.def_port <= participant_latch_data.def_port; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET SPDP Sequence Number 1/2 when 9 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(0)); participant_data_next.spdp_seq_nr(0) <= participant_latch_data.seq_nr(0); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET SPDP Sequence Number 2/2 when 10 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(1)); participant_data_next.spdp_seq_nr(1) <= participant_latch_data.seq_nr(1); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Duration 1/2 when 11 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.lease_duration(0)); participant_data_next.lease_duration(0) <= participant_latch_data.lease_duration(0); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Duration 2/2 when 12 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.lease_duration(1)); participant_data_next.lease_duration(1) <= participant_latch_data.lease_duration(1); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Deadline 1/2 when 13 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.lease_deadline(0)); participant_data_next.lease_deadline(0) <= participant_latch_data.lease_deadline(0); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Deadline 2/2 when 14 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.lease_deadline(1)); participant_data_next.lease_deadline(1) <= participant_latch_data.lease_deadline(1); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Extra Flags when 15 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET; mem_write_data <= (others => '0'); mem_write_data(EF_FLAG_WIDTH-1 downto 0) <= participant_latch_data.extra_flags; participant_data_next.extra_flags <= participant_latch_data.extra_flags; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET ACKNACK Response Time 1/2 when 16 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET; mem_write_data <= std_logic_vector(TIME_INVALID(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET ACKNACK Response Time 2/2 when 17 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1; mem_write_data <= std_logic_vector(TIME_INVALID(1)); participant_data_next.acknack_res_time <= TIME_INVALID; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET HEARTBEAT Response Time 1/2 when 18 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET; mem_write_data <= std_logic_vector(TIME_INVALID(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET HEARTBEAT Response Time 2/2 when 19 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1; mem_write_data <= std_logic_vector(TIME_INVALID(1)); participant_data_next.heartbeat_res_time <= TIME_INVALID; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Publication Sequence Number 1/2 when 20 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Publication Sequence Number 2/2 when 21 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(1)); participant_data_next.pub_seq_nr <= FIRST_SEQUENCENUMBER; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Subscription Sequence Number 1/2 when 22 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Subscription Sequence Number 2/2 when 23 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(1)); participant_data_next.sub_seq_nr <= FIRST_SEQUENCENUMBER; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Message Sequence Number 1/2 when 24 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Message Sequence Number 2/2 when 25 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(FIRST_SEQUENCENUMBER(1)); participant_data_next.mes_seq_nr <= FIRST_SEQUENCENUMBER; -- Memory Flow Control Guard if (mem_ready_in = '1') then -- DONE mem_stage_next <= IDLE; end if; when others => null; end case; when UPDATE_PARTICIPANT => case (mem_cnt) is -- SET Metatraffic IPv4 Address when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_META_IPV4_ADDR_OFFSET; mem_write_data <= participant_latch_data.meta_addr; participant_data_next.meta_addr <= participant_latch_data.meta_addr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_DEFAULT_IPV4_ADDR_FLAG) then mem_cnt_next <= 1; elsif check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 2; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Default IPv4 Address when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_DEFAULT_IPV4_ADDR_OFFSET; mem_write_data <= participant_latch_data.def_addr; participant_data_next.def_addr <= participant_latch_data.def_addr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_UDP_PORT_FLAG) then mem_cnt_next <= 2; elsif check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET UDP Ports when 2 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_UDP_PORT_OFFSET; mem_write_data <= participant_latch_data.meta_port & participant_latch_data.def_port; participant_data_next.meta_port <= participant_latch_data.meta_port; participant_data_next.def_port <= participant_latch_data.def_port; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_SPDP_SEQ_NR_FLAG) then mem_cnt_next <= 3; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET SPDP Sequence Number 1/2 when 3 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET SPDP Sequence Number 2/2 when 4 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SPDP_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(1)); participant_data_next.spdp_seq_nr <= participant_latch_data.seq_nr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_LEASE_DURATION_FLAG) then mem_cnt_next <= 5; elsif check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Lease Duration 1/2 when 5 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.lease_duration(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Duration 2/2 when 6 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DURATION_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.lease_duration(1)); participant_data_next.lease_duration <= participant_latch_data.lease_duration; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 7; elsif check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Lease Deadline 1/2 when 7 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.lease_deadline(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Lease Deadline 2/2 when 8 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_LEASE_DEADLINE_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.lease_deadline(1)); participant_data_next.lease_deadline <= participant_latch_data.lease_deadline; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_EXTRA_FLAGS_FLAG) then mem_cnt_next <= 9; elsif check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Extra Flags when 9 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_EXTRA_FLAGS_OFFSET; mem_write_data <= (others => '0'); mem_write_data(EF_FLAG_WIDTH-1 downto 0) <= participant_latch_data.extra_flags; participant_data_next.extra_flags <= participant_latch_data.extra_flags; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_ACKNACK_RES_TIME_FLAG) then mem_cnt_next <= 10; elsif check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET ACKNACK Response Time 1/2 when 10 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.res_time(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET ACKNACK Response Time 2/2 when 11 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_ACKNACK_RES_TIME_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.res_time(1)); participant_data_next.acknack_res_time <= participant_latch_data.res_time; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_HEARTBEAT_RES_TIME_FLAG) then mem_cnt_next <= 12; elsif check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET HEARTBEAT Response Time 1/2 when 12 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.res_time(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET HEARTBEAT Response Time 2/2 when 13 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_HEARTBEAT_RES_TIME_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.res_time(1)); participant_data_next.heartbeat_res_time <= participant_latch_data.res_time; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_PUB_SEQ_NR_FLAG) then mem_cnt_next <= 14; elsif check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Publication Sequence Number 1/2 when 14 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Publication Sequence Number 2/2 when 15 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_PUB_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(1)); participant_data_next.pub_seq_nr <= participant_latch_data.seq_nr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_SUB_SEQ_NR_FLAG) then mem_cnt_next <= 16; elsif check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Subscription Sequence Number 1/2 when 16 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Subscription Sequence Number 2/2 when 17 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_SUB_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(1)); participant_data_next.sub_seq_nr <= participant_latch_data.seq_nr; -- Memory Flow Control Guard if (mem_ready_in = '1') then if check_mask(participant_latch_data.field_flags,PMF_MES_SEQ_NR_FLAG) then mem_cnt_next <= 18; else -- DONE mem_stage_next <= IDLE; end if; end if; -- SET Message Sequence Number 1/2 when 18 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(0)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Message Sequence Number 2/2 when 19 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_MES_SEQ_NR_OFFSET + 1; mem_write_data <= std_logic_vector(participant_latch_data.seq_nr(1)); participant_data_next.mes_seq_nr <= participant_latch_data.seq_nr; -- Memory Flow Control Guard if (mem_ready_in = '1') then -- DONE mem_stage_next <= IDLE; end if; when others => null; end case; when REMOVE_PARTICIPANT => -- Precondition: mem_addr_base set, mem_prev_addr_base set case (mem_cnt) is -- GET Next Participant when 0 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; mem_read <= '1'; -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- READ Next Participant when 1 => mem_ready_out <= '1'; -- Memory Flow Control Guard if (mem_valid_out = '1') then mem_next_addr_base_next <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH); -- Removed Participant is List Head if (mem_prev_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then assert (mem_addr_base = mem_occupied_head) severity FAILURE; -- Fix Occupied Head mem_occupied_head_next <= resize(unsigned(mem_read_data),PARTICIPANT_MEMORY_ADDR_WIDTH); mem_cnt_next <= mem_cnt + 2; -- Skip Next Step else mem_cnt_next <= mem_cnt + 1; end if; end if; -- SET Next Pointer (Previous Participant) when 2 => -- Point Previous Participant to Next Participant (Remove current Participant from inbetween) mem_valid_in <= '1'; mem_addr <= mem_prev_addr_base + PMF_NEXT_ADDR_OFFSET; mem_write_data <= std_logic_vector(resize(mem_next_addr_base,WORD_WIDTH)); -- Memory Flow Control Guard if (mem_ready_in = '1') then mem_cnt_next <= mem_cnt + 1; end if; -- SET Next Pointer (Current/Removed Instance) when 3 => -- Point Current Instance to Empty List Head (Make Removed Instance Head of the Empty List) mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; mem_write_data <= std_logic_vector(resize(mem_empty_head,WORD_WIDTH)); -- Memory Flow Control Guard if (mem_ready_in = '1') then -- Fix Empty List Head mem_empty_head_next <= mem_addr_base; -- Reset mem_addr_base_next <= PARTICIPANT_MEMORY_MAX_ADDRESS; -- DONE mem_stage_next <= IDLE; end if; when others => null; end case; when RESET_MEMORY => case (mem_cnt) is -- Initialize when 0 => mem_addr_base_next <= FIRST_PARTICIPANT_ADDRESS; mem_cnt_next <= mem_cnt + 1; -- Set Next Pointer when 1 => mem_valid_in <= '1'; mem_addr <= mem_addr_base + PMF_NEXT_ADDR_OFFSET; if (mem_addr_base = MAX_PARTICIPANT_ADDRESS) then mem_write_data <= std_logic_vector(resize(PARTICIPANT_MEMORY_MAX_ADDRESS,WORD_WIDTH)); else mem_write_data <= std_logic_vector(resize(mem_addr_base + PARTICIPANT_FRAME_SIZE,WORD_WIDTH)); end if; -- Memory Flow Control Guard if (mem_ready_in = '1') then if (mem_addr_base = MAX_PARTICIPANT_ADDRESS) then -- DONE mem_stage_next <= IDLE; mem_empty_head_next <= FIRST_PARTICIPANT_ADDRESS; else mem_addr_base_next <= mem_addr_base + PARTICIPANT_FRAME_SIZE; end if; end if; when others => null; end case; when others => null; end case; end process; -- Process responsible for counting read words -- This process uses the actual FIFO read signals to determine reads word_counter_prc : process(clk, reset) begin if rising_edge(clk) then -- Reset Read counter if (reset = '1' or reset_read_cnt = '1') then read_cnt <= (others => '0'); -- Increment read counter each time rd is high elsif (rd_sig = '1') then read_cnt <= read_cnt + 1; end if; end if; end process; sync: process(clk) begin if rising_edge(clk) then if (reset = '1') then stage <= IDLE; return_stage <= IDLE; mem_stage <= RESET_MEMORY; message_type <= NONE; string_content <= DOMAIN_TAG_TYPE; src_addr <= IPv4_ADDRESS_INVALID; def_addr <= IPv4_ADDRESS_INVALID; meta_addr <= IPv4_ADDRESS_INVALID; src_port <= UDP_PORT_INVALID; def_port <= UDP_PORT_INVALID; meta_port <= UDP_PORT_INVALID; guid <= GUID_UNKNOWN; src_entityid <= ENTITYID_UNKNOWN; dest_entityid <= ENTITYID_UNKNOWN; mem_addr_base <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_empty_head <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_occupied_head <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_next_addr_base <= PARTICIPANT_MEMORY_MAX_ADDRESS; mem_prev_addr_base <= PARTICIPANT_MEMORY_MAX_ADDRESS; seq_nr <= SEQUENCENUMBER_UNKNOWN; next_seq_nr <= SEQUENCENUMBER_UNKNOWN; sn_latch_1 <= SEQUENCENUMBER_UNKNOWN; sn_latch_2 <= SEQUENCENUMBER_UNKNOWN; sn_latch_3 <= SEQUENCENUMBER_UNKNOWN; auto_live_seq_nr <= to_double_word(to_unsigned(2, 64)); man_live_seq_nr <= FIRST_SEQUENCENUMBER; live_gap_start <= to_double_word(to_unsigned(2, 64)); live_gap_end <= FIRST_SEQUENCENUMBER; lease_duration <= DURATION_ZERO; check_time <= TIME_INVALID; announcement_time <= time + PARTICIPANT_ANNOUNCEMENT_PERIOD; heartbeat_time <= time + HEARTBEAT_PERIOD; participant_data <= ZERO_PARTICIPANT_DATA; participant_latch_data <= ZERO_PARTICIPANT_LATCH_DATA; cnt <= 0; cnt2 <= 0; bitmap_pos <= 0; mem_cnt <= 0; participant_data_cnt <= 0; publisher_data_cnt <= 0; subscriber_data_cnt <= 0; participant_match <= '0'; is_subscriber <= '0'; is_meta_addr <= '0'; stale_check <= '0'; is_live_assert <= '0'; last_word_in_latch <= '0'; ud_status <= '0'; parameter_end <= (others => '1'); opcode <= SID_PAD; flags <= (others => '0'); string_length <= (others => '0'); compare_length <= (others => '0'); endpoint_mask <= (others => '0'); count <= (others => '0'); long_latch <= (others => '0'); rcvd <= (others => '0'); reader_flags <= (others => '0'); current_pmf <= (others => '0'); bitmap_cnt <= (others => '0'); bitmap_latch <= (others => (others => '0')); else stage <= stage_next; return_stage <= return_stage_next; mem_stage <= mem_stage_next; message_type <= message_type_next; string_content <= string_content_next; src_addr <= src_addr_next; def_addr <= def_addr_next; meta_addr <= meta_addr_next; src_port <= src_port_next; def_port <= def_port_next; meta_port <= meta_port_next; guid <= guid_next; src_entityid <= src_entityid_next; dest_entityid <= dest_entityid_next; mem_addr_base <= mem_addr_base_next; mem_empty_head <= mem_empty_head_next; mem_occupied_head <= mem_occupied_head_next; mem_next_addr_base <= mem_next_addr_base_next; mem_prev_addr_base <= mem_prev_addr_base_next; seq_nr <= seq_nr_next; next_seq_nr <= next_seq_nr_next; sn_latch_1 <= sn_latch_1_next; sn_latch_2 <= sn_latch_2_next; sn_latch_3 <= sn_latch_3_next; auto_live_seq_nr <= auto_live_seq_nr_next; man_live_seq_nr <= man_live_seq_nr_next; live_gap_start <= live_gap_start_next; live_gap_end <= live_gap_end_next; lease_duration <= lease_duration_next; check_time <= check_time_next; announcement_time <= announcement_time_next; heartbeat_time <= heartbeat_time_next; participant_data <= participant_data_next; participant_latch_data <= participant_latch_data_next; cnt <= cnt_next; cnt2 <= cnt2_next; bitmap_pos <= bitmap_pos_next; mem_cnt <= mem_cnt_next; participant_data_cnt <= participant_data_cnt_next; publisher_data_cnt <= publisher_data_cnt_next; subscriber_data_cnt <= subscriber_data_cnt_next; participant_match <= participant_match_next; is_subscriber <= is_subscriber_next; is_meta_addr <= is_meta_addr_next; stale_check <= stale_check_next; is_live_assert <= is_live_assert_next; last_word_in_latch <= last_word_in_latch_next; ud_status <= ud_status_next; parameter_end <= parameter_end_next; opcode <= opcode_next; flags <= flags_next; string_length <= string_length_next; compare_length <= compare_length_next; endpoint_mask <= endpoint_mask_next; count <= count_next; long_latch <= long_latch_next; rcvd <= rcvd_next; reader_flags <= reader_flags_next; current_pmf <= current_pmf_next; bitmap_cnt <= bitmap_cnt_next; bitmap_latch <= bitmap_latch_next; end if; end if; end process; end architecture;