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