rtps-fpga/src/rtps_builtin_endpoint.vhd
2021-12-11 12:20:52 +01:00

6036 lines
349 KiB
VHDL

-- altera vhdl_input_version vhdl_2008
-- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.math_pkg.all;
use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
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);
-- 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*****
-- 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; -- EXIT CONDITION
-- 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
-- GET NEXT PARTICIPANT
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;
-- EXIT CONDITION
when 1 =>
-- No More Participants
if (mem_addr_base = PARTICIPANT_MEMORY_MAX_ADDRESS) then
-- Reset
stale_check_next <= '0';
-- DONE
stage_next <= IDLE;
else
-- Check if STALE
cnt_next <= cnt + 1;
end if;
-- LEASE DEADLINE
when 2 =>
assert check_mask(current_pmf, PMF_LEASE_DEADLINE_FLAG) severity FAILURE;
assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
-- 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 <= 5; -- HELPER STAGE
else
-- Check Next Field
cnt_next <= cnt + 1;
-- 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;
end if;
-- HEARTBEAT RESPONSE TIME
when 3 =>
assert check_mask(current_pmf, PMF_HEARTBEAT_RES_TIME_FLAG) severity FAILURE;
assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
-- HEARTBEAT Response Time Passed
if (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;
else
-- Check Next Field
cnt_next <= cnt + 1;
-- Update Check Time
if (participant_data.heartbeat_res_time /= TIME_INVALID and participant_data.heartbeat_res_time < check_time) then
check_time_next <= participant_data.heartbeat_res_time;
end if;
end if;
-- ACKNACK RESPONSE TIME
when 4 =>
assert check_mask(current_pmf, PMF_ACKNACK_RES_TIME_FLAG) severity FAILURE;
assert (mem_addr_base /= PARTICIPANT_MEMORY_MAX_ADDRESS) severity FAILURE;
-- ACKNACK Response Time Passed
if (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;
cnt_next <= 1;
-- Update Check Time
if (participant_data.acknack_res_time /= TIME_INVALID and participant_data.acknack_res_time < check_time) then
check_time_next <= participant_data.acknack_res_time;
end if;
end if;
-- HELPER STAGE (Lacthes Participant GUID for removal)
when 5 =>
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;
-- POST-ACKNACK-SENT
when 6 =>
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: The HEARTBEAT Time is re-checked in order to update the check_time
-- Continue
cnt_next <= 3;
-- POST-DATA-SENT
when 7 =>
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: The ACKNACK Time is re-checked in order to update the check_time
-- Continue
cnt_next <= 4;
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 (endian_swap(endian_flag,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 (endian_swap(endian_flag,parameter_id)(PID_MUST_UNDERSTAND_FLAG_POS) = '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; -- GET NEXT PARTICIPANT
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 <= 6; -- POST-ACKNACK-SENT
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 <= 7; -- POST-DATA-SENT
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 <= 7; -- POST-DATA-SENT
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 <= 7; -- POST-DATA-SENT
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;