diff --git a/src/REF.txt b/src/REF.txt index 3407e34..4ad2f1d 100644 --- a/src/REF.txt +++ b/src/REF.txt @@ -303,6 +303,9 @@ ENDPOINT LIVELINESS UPDATE LOCAL ENDPOINT BUFFER ===================== + +READER +------ 31............24..............16..............8...............0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-------------------------------------------------------------+ @@ -315,21 +318,55 @@ LOCAL ENDPOINT BUFFER 03| | +-------------------------------------------------------------+ 04| IPv4_ADDRESS | [Reliable Only] - +-----------------------------+-----------------------------+-+ -05| UDP_PORT | UNUSED |Q| [Reliable Only] - +-----------------------------+-----------------------------+-+ + +-----------------------------+-------------------------------+ +05| UDP_PORT | UNUSED | [Reliable Only] + +-----------------------------+-------------------------------+ +06| | + + NEXT_SEQ_NR + +07| | + +-------------------------------------------------------------+ +08| | + + LEASE_DEADLINE + +09| | + +-------------------------------------------------------------+ +10| | + + RES_TIME + [Reliable Only] +11| | + +-------------------------------------------------------------+ + +WRITER +------ + 31............24..............16..............8...............0 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +-------------------------------------------------------------+ +00| ENTITYID | + +-------------------------------------------------------------+ +01| | + + + +02| GUIDPREFIX | + + + +03| | + +-------------------------------------------------------------+ +04| IPv4_ADDRESS | [Reliable Only] + +-----------------------------+---------------------------+-+-+ +05| UDP_PORT | UNUSED |P|Q| [Reliable Only] + +-----------------------------+---------------------------+-+-+ 06| | + LEASE_DEADLINE + 07| | +-------------------------------------------------------------+ -08| | - + RES_TIME + [Reliable Only] +08| | + + GAP_LOW_SEQ_NR + [Reliable Only] 09| | +-------------------------------------------------------------+ 10| | - + NEXT_SEQ_NR + + + GAP_HIGH_SEQ_NR + [Reliable Only] 11| | +-------------------------------------------------------------+ +12| | + + RES_TIME + [Reliable Only] +13| | + +-------------------------------------------------------------+ HISTORY CACHE diff --git a/src/mem_ctrl.vhd b/src/mem_ctrl.vhd new file mode 100644 index 0000000..190ceba --- /dev/null +++ b/src/mem_ctrl.vhd @@ -0,0 +1,98 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity mem_ctrl is + generic ( + ADDR_WIDTH : natural; + DATA_WIDTH : natural; + MEMORY_DEPTH : natural; + MAX_BURST_LENGTH : natural + ); + port ( + clk : in std_logic; + reset : in std_logic; + addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); + read : in std_logic; + ready_in : out std_logic; + valid_in : in std_logic; + data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); + ready_out : in std_logic; + valid_out : out std_logic; + data_out : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of mem_ctrl is + + -- *CONSTANT DECLARATION* + constant READ_LATENCY : natural := 1; + + -- *TYPE DECLARATION* + + -- *SIGNAL DECLARATION* + signal mem_read_data : std_logic_vector(DATA_WIDTH-1 downto 0); + signal delay_line : std_logic_vector(READ_LATENCY downto 0) := (others => '0'); + signal fifo_empty : std_logic := '0'; + signal fifo_cnt : natural 0 to MAX_BURST_LENGTH := 0; + signal delay_cnt : natural 0 to READ_LATENCY := 0; + +begin + + --*****COMPONENT INSTANTIATION***** + ram_inst : entity work.single_port_ram(arch) + generic map ( + ADDR_WIDTH => ADDR_WIDTH, + DATA_WIDTH => DATA_WIDTH, + MEMORY_DEPTH => MEMORY_DEPTH + ) + port map ( + clk => clk, + addr => addr, + wen => not read, + ren => read, + wr_data => data_in, + rd_data => mem_read_data + ); + + delay_line_prc : process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + delay_line <= (others => '0'); + delay_cnt <= 0; + else + -- Shift Right + delay_line(READ_LATENCY-1 downto 0) <= delay_line(READ_LATENCY downto 1); + delay_line(READ_LATENCY) <= read; + + if (read = '1' and delay_line(1) = '0') then + delay_cnt <= delay_cnt + 1; + elsif (read = '0' and delay_line(1) = '1') then + delay_cnt <= delay_cnt - 1; + end if; + end if; + end if; + end process; + + burst_fifo_inst : entity work.FWFT_FIFO(arch) + generic map ( + FIFO_DEPTH => MAX_BURST_LENGTH, + DATA_WIDTH => DATA_WIDTH + ) + port map ( + clk => clk, + reset => reset, + data_in => mem_read_data, + write => delay_line(0), + read => ready_out, + data_out => data_out, + empty => fifo_empty, + full => open, + free => fifo_cnt, + ); + + ready_in <= '0' when (fifo_cnt + delay_cnt = MAX_BURST_LENGTH) else '1'; + valid_out <= not fifo_empty; + +end architecture; \ No newline at end of file diff --git a/src/rtps_config_package.vhd b/src/rtps_config_package.vhd index 81c8c35..de2de23 100644 --- a/src/rtps_config_package.vhd +++ b/src/rtps_config_package.vhd @@ -136,6 +136,8 @@ package rtps_config_package is function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : unsigned(WORD_WIDTH-1 downto 0); local : unsigned(WORD_WIDTH-1 downto 0)) return boolean; function check_qos_compatibility(src_is_reader : std_logic; direction : std_logic; remote : DOUBLE_WORD_ARRAY; local : DOUBLE_WORD_ARRAY) return boolean; + function check_mask(flags : std_logic_vector, mask : std_logic_vector) return boolean; + end package; package body rtps_config_package is @@ -1087,4 +1089,14 @@ package body rtps_config_package is return ret; end function; + function check_mask(flags : std_logic_vector, mask : std_logic_vector) return boolean is + begin + assert (flags'length = mask'length) report "Flag and mask Signal have unequal length" severity FAILURE; + if ((flags and mask) = mask) then + return TRUE; + else + return FALSE; + end if; + end function; + end package body; diff --git a/src/rtps_endpoint.vhd b/src/rtps_endpoint.vhd index 9853268..440fc68 100644 --- a/src/rtps_endpoint.vhd +++ b/src/rtps_endpoint.vhd @@ -16,68 +16,77 @@ use work.rtps_config_package.all; entity rtps_endpoint is generic ( - ID : natural; + HEARTBEAT_RESPONSE_DELAY : DURATION_TYPE := TODO; + HEARTBEAT_SUPPRESSION_DELAY : DURATION_TYPE := TODO; + LEASE_DURATION : DURATION_TYPE := DEFAULT_LEASE_DURATION; + ENTITYID : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := ENTITYID_UNKNOWN; ); port ( + -- SYSTEM clk : in std_logic; reset : in std_logic; time : in TIME_TYPE; - alive : out std_logic; - + -- FROM RTPS_HANDLER empty : in std_logic; rd : out std_logic; last_word_in : in std_logic; data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); - + -- FROM RTPS_BUILTIN_ENDPOINT meta_empty : in std_logic; meta_data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); meta_rd : out std_logic; - + -- RTPS OUTPUT rtps_wr : out std_logic; rtps_full : in std_logic; last_word_out : out std_logic; data_out : out std_logic_vector(WORD_WIDTH-1 downto 0); - - hc_start : out std_logic; - hc_opcode : out HISTORY_CACHE_OPCODE_TYPE; - hc_res : in HISTORY_CACHE_RESPOSNE_TYPE; - - hc_data_out : in std_logic_vector(WORD_WIDTH-1 downto 0); - hc_valid_out : in std_logic; - hc_ready_out : out std_logic; - hc_last_word_out: in std_logic; - - hc_data_in : out std_logic_vector(WORD_WIDTH-1 downto 0); - hc_valid_in : out std_logic; - hc_ready_in : in std_logic; - hc_last_word_in : out std_logic + -- TO DDS READER + dds_start : out std_logic; + dds_opcode : out HISTORY_CACHE_OPCODE_TYPE; + dds_res : in HISTORY_CACHE_RESPOSNE_TYPE; + dds_data_out : in std_logic_vector(WORD_WIDTH-1 downto 0); + dds_valid_out : in std_logic; + dds_ready_out : out std_logic; + dds_last_word_out: in std_logic ); end entity; architecture arch of rtps_endpoint is --*****CONSTANT DECLARATION***** + -- *ENDPOINT MEMORY* -- Endpoint Memory Size in 4-Byte Words - constant ENDPOINT_MEMORY_SIZE : natural := TODO; + constant ENDPOINT_MEMORY_SIZE : natural := TODO; -- Endpoint Memory Address Width - constant ENDPOINT_MEMORY_ADDR_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE); - -- Highest Memory Address - constant MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH); + constant ENDPOINT_MEMORY_ADDR_WIDTH : natural := log2c(ENDPOINT_MEMORY_SIZE); + -- Highest Endpoint Memory Address + constant ENDPOINT_MEMORY_MAX_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := to_unsigned(ENDPOINT_MEMORY_SIZE-1, ENDPOINT_MEMORY_ADDR_WIDTH); -- Highest Endpoint Frame Address - constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1; + constant MAX_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := ENDPOINT_MEMORY_MAX_ADDRESS - ENDPOINT_FRAME_SIZE + 1; -- Address pointing to the beginning of the first Endpoint Data Frame - constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + constant FIRST_ENDPOINT_ADDRESS : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + + -- *ENDPOINT MEMORY FORMAT FIELD FLAGS* + -- Flags mapping to the respective Endpoint Memory Frame Fields + constant EMF_FLAG_WIDTH : natural := 7; + constant EMF_ENTITYID_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (0 => 1, others => '0'); + constant EMF_GUIDPREFIX_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (1 => 1, others => '0'); + constant EMF_IPV4_ADDR_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (2 => 1, others => '0'); + constant EMF_UDP_PORT_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (3 => 1, others => '0'); + constant EMF_NEXT_SEQ_NR_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (4 => 1, others => '0'); + constant EMF_LEASE_DEADLINE_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (5 => 1, others => '0'); + constant EMF_RES_TIME_FLAG : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (6 => 1, others => '0'); + + -- *ENDPOINT MEMORY FRAME FORMAT* + -- 4-Byte Word Offsets to Beginning of Respective Fields in the Endpoint Memory Frame + constant EMF_ENTITYID_OFFSET : natural := 0; + constant EMF_GUIDPREFIX_OFFSET : natural := 1; + constant EMF_IPV4_ADDR_OFFSET : natural := 4; + constant EMF_UDP_PORT_OFFSET : natural := 5; + constant EMF_NEXT_SEQ_NR_OFFSET : natural := 6; + constant EMF_LEASE_DEADLINE_OFFSET : natural := 8; + constant EMF_RES_TIME_OFFSET : natural := 10; - -- *UPDATE PARTICIPANT FLAG POSITIONS* - constant UPDATE_ENDPOINT_FLAG_WIDTH : natural := 4; - -- Signifies that the main Endpoint Data are updated - constant ENDPOINT_DATA_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (0 => 1, others => '0'); - -- Signifies that the Lease Deadline of the Endpoint Data is updated - constant LEASE_DEADLINE_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (1 => 1, others => '0'); - -- Signifies that the last Sequence Number of the Endpoint Data is updated - constant NEXT_SEQ_NR_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (2 => 1, others => '0'); - -- Signifies that the HEARTBEAT/ACKNACK Timeout Time of the Endpoint Data is updated - constant RES_TIME_FLAG : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (3 => 1, others => '0'); --*****TYPE DECLARATION***** -- FSM states. Explained below in detail @@ -87,38 +96,36 @@ architecture arch of rtps_endpoint is type MEM_STAGE_TYPE is (IDLE, TODO); -- Record of all Participant Data stored in memory type ENDPOINT_DATA_TYPE is record - addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); - portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); - expects_inline_qos : std_logic; - lease_deadline : TIME_TYPE; - res_time : TIME_TYPE; - next_seq_nr : SEQUENCENUMBER_TYPE; - end record; - constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( - addr => IPv4_ADDRESS_INVALID, - portn => UDP_PORT_INVALID, - expects_inline_qos => '0', - lease_deadline => TIME_INVALID, - res_time => TIME_INVALID, - next_seq_nr => SEQUENCENUMBER_UNKNOWN - ); - type MEM_CTRL_DATA_TYPE is record guid : GUID_TYPE; addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); - expects_inline_qos : std_logic; + next_seq_nr : SEQUENCENUMBER_TYPE; + lease_deadline : TIME_TYPE; + res_time : TIME_TYPE; + end record; + constant ZERO_ENDPOINT_DATA : ENDPOINT_DATA_TYPE := ( + guid => GUID_UNKNOWN, + addr => IPv4_ADDRESS_INVALID, + portn => UDP_PORT_INVALID, + next_seq_nr => SEQUENCENUMBER_UNKNOWN, + lease_deadline => TIME_INVALID, + res_time => TIME_INVALID + ); + type ENDPOINT_LATCH_DATA_TYPE is record + guid : GUID_TYPE; + addr : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0); + portn : std_logic_vector(UDP_PORT_WIDTH-1 downto 0); deadline : TIME_TYPE; next_seq_nr : SEQUENCENUMBER_TYPE; - update_flags : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1); + field_flag : std_logic_vector(0 to EMF_FLAG_WIDTH-1); end record; - constant ZERO_MEM_CTRL_DATA : MEM_CTRL_DATA_TYPE := ( - guid => (others => (others => '0')), - addr => (others => '0'), - portn => (others => '0'), - expects_inline_qos => '0', + constant ZERO_ENDPOINT_LATCH_DATA : ENDPOINT_LATCH_DATA_TYPE := ( + guid => GUID_UNKNOWN, + addr => IPv4_ADDRESS_INVALID, + portn => UDP_PORT_INVALID, deadline => TIME_INVALID, next_seq_nr => SEQUENCENUMBER_UNKNOWN, - update_flags => (others => '0'), + field_flag => (others => '0') ); @@ -135,13 +142,13 @@ architecture arch of rtps_endpoint is signal portn, portn_next : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); signal expects_inline_qos, expects_inline_qos_next : std_logic := '0'; signal is_meta, is_meta_next : std_logic := '0'; - signal update_endpoint_flags : std_logic_vector(0 to UPDATE_ENDPOINT_FLAG_WIDTH-1) := (others => '0'); + signal mem_field_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0'); signal opcode, opcode_next : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := (others => '0'); signal flags, flags_next : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0) := (others => '0'); signal seq_nr, seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; signal next_seq_nr, next_seq_nr_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; signal ts, ts_next : TIME_TYPE := TIME_INVALID; - signal deadline, deadline_next : DURATION_TYPE := DURATION_ZERO; + signal deadline : TIME_TYPE := TIME_INVALID; signal sn_latch_1, sn_latch_1_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; signal sn_latch_2, sn_latch_2_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; signal sn_latch_3, sn_latch_3_next : SEQUENCENUMBER_TYPE := SEQUENCENUMBER_UNKNOWN; @@ -164,25 +171,29 @@ architecture arch of rtps_endpoint is signal data_in_swapped : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); signal mem_stage, mem_stage_next : MEM_STAGE_TYPE := IDLE; - signal mem_wr, mem_rd : std_logic := '0'; - signal mem_wr_data, mem_rd_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); - signal mem_addr, mem_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); - signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal mem_addr_base, mem_addr_base_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal last_addr, last_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal mem_addr_latch, mem_addr_latch_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal max_endpoint_addr, max_endpoint_addr_next : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); signal mem_cnt, mem_cnt_next : natural range TODO := 0; signal mem_endpoint_data, mem_endpoint_data_next : ENDPOINT_DATA_TYPE := ZERO_ENDPOINT_DATA; - signal reset_max_pointer, reset_max_pointer_next : std_logic := '0'; - signal mem_long_latch, mem_long_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); - signal mem_ctrl_data, mem_ctrl_data_next : MEM_CTRL_DATA_TYPE := ZERO_MEM_CTRL_DATA; + signal mem_endpoint_latch_data, mem_endpoint_latch_data_next : ENDPOINT_LATCH_DATA_TYPE := ZERO_ENDPOINT_LATCH_DATA; signal mem_pos, mem_pos_next : natural range TODO := 0; - signal is_psearch, is_psearch_next : std_logic := '0'; + signal abort_read : std_logic := '0'; + + signal mem_addr : unsigned(ENDPOINT_MEMORY_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal mem_read_data, mem_write_data : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal mem_ready_in, mem_valid_in : std_logic := '0'; + signal mem_ready_out, mem_valid_out : std_logic := '0'; + signal mem_read : std_logic := '0'; signal stale_check, stale_check_next : std_logic := '0'; signal count, count_next : unsigned(COUNT_WIDTH-1 downto 0) := (others => '0'); signal return_stage, return_stage_next : STAGE_TYPE := IDLE; + signal check_time, check_time_next : TIME_TYPE := TIME_INVALID; + signal lifespan, lifespan_next : TIME_TYPE := TIME_INVALID; + --*****ALIAS DECLARATION***** -- ENDPOINT FRAME HEADER alias header_opcode : std_logic_vector(7 downto 0) is data_in(31 downto 24); @@ -228,19 +239,24 @@ architecture arch of rtps_endpoint is begin --*****COMPONENT INSTANTIATION***** - ram_inst : single_port_ram + mem_ctrl_inst : entity work.mem_ctrl(arch) generic map ( - ADDR_WIDTH => ENDPOINT_MEMORY_ADDR_WIDTH, - DATA_WIDTH => WORD_WIDTH, - MEMORY_DEPTH => ENDPOINT_MEMORY_SIZE + ADDR_WIDTH => ENDPOINT_MEMORY_ADDR_WIDTH, + DATA_WIDTH => WORD_WIDTH, + MEMORY_DEPTH => ENDPOINT_MEMORY_SIZE, + MAX_BURST_LENGTH => ENDPOINT_FRAME_SIZE ) port map ( clk => clk, - addr => std_logic_vector(end_mem_addr), - wen => mem_wr, - ren => mem_rd, - wr_data => mem_wr_data, - rd_data => mem_rd_data + reset => reset or abort_read, + addr => std_logic_vector(mem_addr), + read => mem_read, + ready_in => mem_ready_in, + valid_in => mem_valid_in, + data_in => mem_write_data, + ready_out => mem_ready_out, + valid_out => mem_valid_out, + data_out => mem_read_data ); -- Big Endian Representation @@ -265,7 +281,6 @@ begin flags_next <= flags; seq_nr_next <= seq_nr; ts_next <= ts; - deadline_next <= deadline; sn_latch_1_next <= sn_latch_1; sn_latch_2_next <= sn_latch_2; sn_latch_3_next <= sn_latch_3; @@ -277,18 +292,21 @@ begin stale_check_next <= stale_check; count_next <= count; return_stage_next <= return_stage; + check_time_next <= check_time; + lifespan_next <= lifespan; meta_rd <= '0'; rd <= '0'; mem_opcode <= NOP; mem_op_start <= '0'; rd_guard := '0'; - update_endpoint_flags <= (others => '0'); - hc_start <= '0'; - hc_opcode <= ADD_CACHE_CHANGE; - hc_data_in <= (others => '0'); - hc_ready_out <= '0'; - hc_valid_in <= '0'; - hc_last_word_in <= '0'; + mem_field_flags <= (others => '0'); + dds_start <= '0'; + dds_opcode <= ADD_CACHE_CHANGE; + dds_data_in <= (others => '0'); + dds_ready_out <= '0'; + dds_valid_in <= '0'; + dds_last_word_in <= '0'; + deadline <= TIME_INVALID; -- Last Word Latch Setter @@ -300,31 +318,28 @@ begin -- OPCODE when IDLE => -- RESET - deadline_next <= TIME_INVALID; + lifespan_next <= TIME_INVALID; addr_next <= (others => '0'); portn_next <= (others => '0'); status_info_next <= (others => '0'); key_hash_rcvd_next <= '0'; - expects_inline_qos_next <= '0'; is_meta_next <= '0'; - -- Stale Entry search is initiated between every packet processing and when there is no packet to process - if (stale_check = '0' or (empty = '1' and meta_empty = '1')) then + if (time >= check_time) then + -- Memory Operation Guard if (mem_op_done = '1') then - mem_opcode <= FIND_STALE_ENDPOINT; - mem_op_start <= '1'; - - -- Stale Check Toggle (Setter) stale_check_next <= '1'; - stage_next <= ENDPOINT_STALE_CHECK; + cnt_next <= 1; + mem_op_start <= '1'; + mem_opcode <= GET_FIRST_ENDPOINT; + mem_field_flags <= EMF_LEASE_DEADLINE_FLAG or EMF_RES_TIME_FLAG; + -- Reset Timeout + check_time_next <= TIME_INFINITE; end if; -- Input FIFO Guard elsif (meta_empty = '0') then - meta_rd <= '1'; - - -- Stale Check Toggle (Resetter) - stale_check_next <= '0'; + meta_rd <= '1'; -- Mark as METATRAFFIC is_meta_next <= '1'; @@ -338,9 +353,6 @@ begin elsif (empty = '0') then rd_guard := '1'; - -- Stale Check Toggle (Resetter) - stale_check_next <= '0'; - -- Latch Opcode opcode_next <= header_opcode; -- Latch Flags @@ -418,19 +430,25 @@ begin when OPCODE_ENDPOINT_MATCH => mem_op_start <= '1'; mem_opcode <= SEARCH_ENDPOINT; + mem_field_flags <= (others => '0'); stage_next <= LATCH_ENDPOINT_DATA; when OPCODE_ENDPOINT_UNMATCH => mem_op_start <= '1'; mem_opcode <= SEARCH_ENDPOINT; + mem_field_flags <= (others => '0'); stage_next <= METATRAFFIC_OPERATION; when OPCODE_PARTICIPANT_UNMATCH => mem_op_start <= '1'; - mem_opcode <= FIND_FIRST_PARTICIPANT_ENDPOINT; + mem_opcode <= GET_FIRST_ENDPOINT; + mem_field_flags <= EMF_GUIDPREFIX_FLAG; stage_next <= METATRAFFIC_OPERATION; + cnt_next <= 0; when OPCODE_LIVELINESS_UPDATE => mem_op_start <= '1'; - mem_opcode <= FIND_FIRST_PARTICIPANT_ENDPOINT; + mem_opcode <= GET_FIRST_ENDPOINT; + mem_field_flags <= (others => '0'); stage_next <= METATRAFFIC_OPERATION; + cnt_next <= 0; when others => assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; @@ -441,14 +459,17 @@ begin case (opcode) is when SID_DATA => - stage_next <= LATCH_EXTRA_DATA; - cnt_next <= 0; + stage_next <= LATCH_EXTRA_DATA; + mem_field_flags <= (others => '0'); + cnt_next <= 0; when SID_HEARTBEAT => - stage_next <= LATCH_HEARTBEAT; - cnt_next <= 0; + stage_next <= LATCH_HEARTBEAT; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; + cnt_next <= 0; when SID_GAP => - stage_next <= LATCH_GAP; - cnt_next <= 0; + stage_next <= LATCH_GAP; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; + cnt_next <= 0; when others => stage_next <= SKIP_PACKET; end case; @@ -464,14 +485,11 @@ begin -- IPv4 Address when 0 => addr_next <= meta_data_in; - -- UDP Port & EXTRA Flags (Expects InLine QoS) + -- UDP Port when 1 => - portn_next <= meta_data_in(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1); - expects_inline_qos_next <= meta_data_in(0); - -- Calculate Lease Deadline - deadline_next <= time + ENDPOINT_LEASE_DURATION(ID); + portn_next <= meta_data_in(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1); - stage_next <= METATRAFFIC_OPERATION; + stage_next <= METATRAFFIC_OPERATION; when others => null; end case; @@ -479,92 +497,113 @@ begin when METATRAFFIC_OPERATION => -- Memory Operation Guard if (mem_op_done = '1') then - case (meta_opcode) is when OPCODE_ENDPOINT_MATCH => -- Endpoint already in Memory - if (mem_addr_base /= MAX_ADDRESS) then + if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then -- Update the Endpoint Data -- NOTE: The Lease Duration is NOT updated in case of an update. That is the responsibility of the Liveliness Update - update_endpoint_flags <= ENDPOINT_DATA_FLAG; - mem_opcode <= UDPATE_ENDPOINT; mem_op_start <= '1'; + mem_opcode <= UDPATE_ENDPOINT; + mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG; + -- DONE stage_next <= IDLE; else -- Insert Matched Remote Endpoint - mem_opcode <= INSERT_ENDPOINT; mem_op_start <= '1'; + mem_opcode <= INSERT_ENDPOINT; + deadline <= (time + LEASE_DURATION) when (LEASE_DURATION /= DURATION_INFINITE) else TIME_INVALID; + -- DONE stage_next <= IDLE; end if; when OPCODE_ENDPOINT_UNMATCH => -- Endpoint not in Memory - if (mem_addr_base = MAX_ADDRESS) then + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then -- Ignore stage_next <= IDLE; else -- Output Guard - if (hc_ready_in = '1') then + if (dds_ready_in = '1') then -- Propagate Removal - hc_start <= '1'; - hc_opcode <= REMOVE_WRITER; - hc_valid_in <= '1'; - hc_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); - -- Wait until HC Acknowledgement - if (hc_res = ACK) then + dds_start <= '1'; + dds_opcode <= REMOVE_WRITER; + dds_valid_in <= '1'; + dds_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); + -- Wait for Operation Acknowledgement + if (dds_res = ACK) then -- Remove Unmatched Remote Endpoint - mem_opcode <= REMOVE_ENDPOINT; mem_op_start <= '1'; + mem_opcode <= REMOVE_ENDPOINT; + -- DONE stage_next <= IDLE; end if; end if; end if; when OPCODE_PARTICIPANT_UNMATCH => - -- No matches in memory - if (mem_addr_base = MAX_ADDRESS) then - -- DONE - stage_next <= IDLE; - else - -- Output Guard - if (hc_ready_in = '1') then - -- Propagate Removal - hc_start <= '1'; - hc_opcode <= REMOVE_WRITER; - hc_valid_in <= '1'; - hc_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); - -- Wait until HC Acknowledgement - if (hc_res = ACK) then - -- Remove Unmatched Remote Endpoint - mem_opcode <= REMOVE_ENDPOINT; - mem_op_start <= '1'; - stage_next <= INITIATE_NEXT_ENDPOINT_SEARCH; + case (cnt) is + when 0 => + -- Reached End of Endpoints + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- DONE + stage_next <= IDLE; + else + -- Participant Match + if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then + -- Output Guard + if (dds_ready_in = '1') then + -- Propagate Removal + dds_start <= '1'; + dds_opcode <= REMOVE_WRITER; + dds_valid_in <= '1'; + dds_data_in <= std_logic_vector(to_unsigned(mem_pos, WORD_WIDTH)); + -- Wait for Operation Acknowledgement + if (dds_res = ACK) then + -- Remove Unmatched Remote Endpoint + mem_op_start <= '1'; + mem_opcode <= REMOVE_ENDPOINT; + end if; + end if; + end if; + cnt_next <= 1; end if; - end if; - end if; + when 1 => + -- Continue Search + mem_op_start <= '1'; + mem_opcode <= GET_NEXT_ENDPOINT; + cnt_next <= 0; + when others => + null; + end case; when OPCODE_LIVELINESS_UPDATE => - -- No matches in memory - if (mem_addr_base = MAX_ADDRESS) then - -- DONE - stage_next <= IDLE; - else - -- Renew Lease of Remote Endpoint - update_endpoint_flags <= LEASE_DEADLINE_FLAG; - mem_opcode <= UDPATE_ENDPOINT; - mem_op_start <= '1'; - stage_next <= INITIATE_NEXT_ENDPOINT_SEARCH; - end if; + case (cnt) is + when 0 => + -- No matches in memory + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- DONE + stage_next <= IDLE; + else + -- Participant Match + if (guid(0) = mem_endpoint_data.guid(0) and guid(1) = mem_endpoint_data.guid(1) and guid(2) = mem_endpoint_data.guid(2)) then + -- Renew Lease of Remote Endpoint + mem_op_start <= '1'; + mem_opcode <= UDPATE_ENDPOINT; + mem_field_flags <= EMF_LEASE_DEADLINE_FLAG; + deadline <= (time + LEASE_DURATION) when (LEASE_DURATION /= DURATION_INFINITE) else TIME_INVALID; + end if; + cnt_next <= 1; + end if; + when 1 => + -- Continue Search + mem_op_start <= '1'; + mem_opcode <= GET_NEXT_ENDPOINT; + cnt_next <= 0; + when others => + null; + end case; when others => assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE; null; end case; - -- DONE - stage_next <= SKIP_PACKET; - end if; - when INITIATE_NEXT_ENDPOINT_SEARCH => - -- Memory Operation Guard - if (mem_op_done = '1') then - mem_opcode <= FIND_NEXT_PARTICIPANT_ENDPOINT; - mem_op_start <= '1'; - stage_next <= METATRAFFIC_OPERATION; end if; when LATCH_SRC_ADDR => -- Input FIFO Guard @@ -603,7 +642,7 @@ begin if (qos_flag = '1') then stage_next <= PROCESS_INLINE_QOS; else - stage_next <= INITIATE_HISTORY_CACHE_REQUEST; + stage_next <= INITIATE_ADD_CACHE_CHANGE_REQUEST; end if; when others => null; @@ -641,39 +680,46 @@ begin stage_next <= SKIP_PACKET; -- Endpoint in Buffer - if (mem_addr_base /= MAX_ADDRESS) then + if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then -- No scheduled Heartbeat Response if (mem_endpoint_data.res_time = 0) then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then -- Store new expected Sequence Number and set Response Dealy - next_seq_nr_next <= first_seq_nr; - mem_op_start <= '1'; - mem_opcode <= UPDATE_ENDPOINT; - -- XXX: Assumes lease deadline will not be updated concurrently (Since they use the same latch) - deadline_next <= time + ENDPOINT_HEARTBEAT_RESPONSE_DELAY(ID); - -- NOTE: Last Bit denotes if this is Response or Suppression Delay - deadline_next(1)(0) <= '0'; - update_endpoint_flags <= NEXT_SEQ_NR_FLAG or RES_TIME_FLAG; + next_seq_nr_next <= first_seq_nr; + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG; + if (HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then + deadline <= time + HEARTBEAT_RESPONSE_DELAY; + -- NOTE: Last Bit denotes if this is Response or Suppression Delay + deadline(1)(0) <= '0'; + else + deadline <= TIME_INVALID; + end if; -- If new Sequence Number is available or Writer expects ACKNACK elsif (last_seq_nr >= mem_endpoint_data.next_seq_nr or final_flag = '0') then -- Set Response Delay - mem_opcode <= UPDATE_ENDPOINT; - mem_op_start <= '1'; - deadline_next <= time + ENDPOINT_HEARTBEAT_RESPONSE_DELAY(ID); - -- NOTE: Last Bit denotes if this is Response or Suppression Delay - deadline_next(1)(0) <= '0'; - update_endpoint_flags <= RES_TIME_FLAG; + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_RES_TIME_FLAG; + if (HEARTBEAT_RESPONSE_DELAY /= DURATION_INFINITE) then + deadline <= time + HEARTBEAT_RESPONSE_DELAY; + -- NOTE: Last Bit denotes if this is Response or Suppression Delay + deadline(1)(0) <= '0'; + else + deadline <= TIME_INVALID; + end if; end if; -- Currently in Heartbeat Response Delay - elsif (mem_participant_data.res_time(1)(0) = '0') then + elsif (mem_endpoint_data.res_time(1)(0) = '0') then -- If current Sequence Number obsolete (removed from source history cache) if (first_seq_nr > mem_endpoint_data.next_seq_nr and first_seq_nr <= last_seq_nr) then -- Store new expected Sequence Number next_seq_nr_next <= first_seq_nr; mem_op_start <= '1'; mem_opcode <= UPDATE_ENDPOINT; - update_endpoint_flags <= NEXT_SEQ_NR_FLAG; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; end if; end if; end if; @@ -727,7 +773,7 @@ begin stage_next <= SKIP_PACKET; -- Known Remote Endpoint - if (mem_addr_base /= MAX_ADDRESS) then + if (mem_addr_base /= ENDPOINT_MEMORY_MAX_ADDRESS) then -- GAP is relevant if (gap_start <= mem_endpoint_data.next_seq_nr and mem_endpoint_data.next_seq_nr <= gap_list_end) then -- Next Expected is in GAP List @@ -753,11 +799,11 @@ begin -- First valid sequence number found if (tmp_bitmap(bitmap_pos) = '0') then -- Update next sequence number - mem_op_start <= '1'; - mem_opcode <= UPDATE_ENDPOINT; - update_endpoint_flags <= NEXT_SEQ_NR_FLAG; + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG; -- DONE - stage_next <= SKIP_PACKET; + stage_next <= SKIP_PACKET; else -- Continue search bitmap_pos_next <= bitmap_pos + 1; @@ -850,7 +896,7 @@ begin null; when PID_SENTINEL => -- QOS DONE - stage_next <= INITIATE_HISTORY_CACHE_REQUEST; + stage_next <= INITIATE_ADD_CACHE_CHANGE_REQUEST; when others => -- If MUST_UNDERSTAND Flag is set, we have incompatible communication. Drop Packet if (must_understand = '1') then @@ -878,7 +924,7 @@ begin -- TODO: Use source timestamp if clocks with remote synchronized -- Calculate Sample Lifespan Deadline - deadline_next <= time + tmp_dw; + deadline <= (time + tmp_dw) when (tmp_dw /= DURATION_INFINITE) else TIME_INVALID; -- DONE stage_next <= SKIP_PARAMETER; @@ -922,72 +968,72 @@ begin -- DONE stage_next <= SKIP_PARAMETER; end if; - when INITIATE_HISTORY_CACHE_REQUEST => - hc_start <= '1'; - hc_opcode <= ADD_CACHE_CHANGE; + when INITIATE_ADD_CACHE_CHANGE_REQUEST => + dds_start <= '1'; + dds_opcode <= ADD_CACHE_CHANGE; -- Wait until History Cache acknowledges request - if (hc_res = ACK) then + if (dds_res = ACK) then stage_next <= ADD_CACHE_CHANGE; cnt_next <= 0; end if; when ADD_CACHE_CHANGE => - if (hc_ready_in = '1') then - hc_valid_in <= '1'; + if (dds_ready_in = '1') then + dds_valid_in <= '1'; cnt_next <= cnt + 1; case (cnt) is -- Status Info when 0 => - hc_data_in <= status_info; - hc_data_in(KEY_HASH_FLAG) <= key_hash_rcvd; - hc_data_in(PAYLOAD_FLAG) <= data_flag; + dds_data_in <= status_info; + dds_data_in(KEY_HASH_FLAG) <= key_hash_rcvd; + dds_data_in(PAYLOAD_FLAG) <= data_flag; -- Timestamp 1/2 when 1 => - hc_data_in <= ts(0); + dds_data_in <= ts(0); -- Timestamp 2/2 when 2 => - hc_data_in <= ts(1); + dds_data_in <= ts(1); -- Lifespan Deadline 1/2 when 3 => - hc_data_in <= deadline(0); + dds_data_in <= lifespan(0); -- Lifespan Deadline 2/2 when 4 => - hc_data_in <= deadline(1); + dds_data_in <= lifespan(1); -- Skip Key Hash, if not received if (key_hash_rcvd = '0') then cnt_next <= 9; end if; -- Key hash 1/4 when 5 => - hc_data_in <= key_hash(0); + dds_data_in <= key_hash(0); -- Key Hash 2/4 when 6 => - hc_data_in <= key_hash(1); + dds_data_in <= key_hash(1); -- Key Hash 3/4 when 7 => - hc_data_in <= key_hash(2); + dds_data_in <= key_hash(2); -- Key hash 4/4 when 8 => - hc_data_in <= key_hash(3); + dds_data_in <= key_hash(3); -- Endpoint Memory Position when 9 => -- Wait for Endpoint Search if (mem_op_done = '1') then -- TODO: Assert mem_pos range fits in CDR_LONG - hc_data_in <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH)); + dds_data_in <= std_logic_vector(to_unsigned(mem_pos, CDR_LONG_WIDTH)); -- Payload exists if (data_flag = '1' or key_flag = '1') then stage_next <= PUSH_PAYLOAD; else -- DONE - hc_last_word_in <= '1'; + dds_last_word_in <= '1'; stage_next <= FINALIZE_HISTORY_CACHE_REQUEST; end if; else -- Keep State - hc_valid_in <= '0'; + dds_valid_in <= '0'; cnt_next <= cnt; end if; when others => @@ -996,16 +1042,16 @@ begin end if; when PUSH_PAYLOAD => -- Input/Output Guard - if (empty = '0' and hc_ready_in = '1') then + if (empty = '0' and dds_ready_in = '1') then rd_guard := '1'; - hc_valid_in <= '1'; + dds_valid_in <= '1'; -- Push Payload to History Cache - hc_data_in <= data_in; + dds_data_in <= data_in; -- Exit Condition if (last_word_in = '1') then - hc_last_word_in <= '1'; + dds_last_word_in <= '1'; stage_next <= FINALIZE_HISTORY_CACHE_REQUEST; end if; end if; @@ -1013,14 +1059,14 @@ begin -- NOTE: Memory is already in done state from previous state (ADD_CACHE_CHANGE) assert (mem_op_done = '1') report "FINALIZE_HISTORY_CACHE_REQUEST precondition not met. mem_op_done /= '1'" severity FAILURE; -- Wai for History Cache Response - if (hc_res /= UNDEFINED) then + if (dds_res /= UNDEFINED) then -- Operation was Accepted - if (hc_res = ACCEPTED) then + if (dds_res = ACCEPTED) then -- Update next sequence number and renew Lease - mem_op_start <= '1'; - mem_opcode <= UPDATE_ENDPOINT; - deadline_next <= time + ENDPOINT_LEASE_DURATION(ID); - update_endpoint_flags <= NEXT_SEQ_NR_FLAG or LEASE_DEADLINE_FLAG; + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + deadline <= (time + LEASE_DURATION) when (LEASE_DURATION /= DURATION_INFINITE) else TIME_INVALID; + mem_field_flags <= NEXT_SEQ_NR_FLAG or LEASE_DEADLINE_FLAG; end if; -- NOTE: In case the operation was unsucessfull (e.g. reached Resource Limits), the endpoint is not updated and the -- Sequence Number is thus not "acknowledged". @@ -1028,56 +1074,85 @@ begin stage_next <= SKIP_PACKET; end if; when ENDPOINT_STALE_CHECK => - -- Wait for Stale Search to finish + -- Memory Operation Guard if (mem_op_done = '1') then - -- Found Stale Entry - if (mem_addr_base /= MAX_ADDRESS) then - -- Endpoint Lease Expired - -- NOTE: The mem_endpoint_data is zero initialized on lease expiration, so we check if the address is set - if (mem_endpoint_data.addr = IPv4_ADDRESS_INVALID) then - -- Remove Participant - mem_opcode <= REMOVE_ENDPOINT; + case (cnt) is + -- Get Next Endpoint + when 0 => mem_op_start <= '1'; - stage_next <= IDLE; - -- Response Time Reached - else - -- If Suppression Delay passed, zero the time - if(mem_endpoint_data.res_time(1)(0) = '1') then - -- Zero Response Time - mem_opcode <= UPDATE_ENDPOINT; - deadline_next <= TIME_ZERO; - update_participant_flags <= RES_TIME_FLAG; - mem_op_start <= '1'; + mem_opcode <= GET_NEXT_ENDPOINT; + cnt_next <= 1; + -- Check Endpoint + when 1 => + -- End of Endpoints + if (mem_addr_base = ENDPOINT_MEMORY_MAX_ADDRESS) then + -- Reset + stale_check_next <= '0'; -- DONE - stage_next <= IDLE; - -- If Response Delay Passed + stage_next <= IDLE; else - -- Set Heartbeat Suppression Time - if (ENDPOINT_HEARTBEAT_SUPPRESSION_DELAY(ID) /= 0) then - -- Set Heartbeat Suppression Time - deadline_next <= time + ENDPOINT_HEARTBEAT_SUPPRESSION_DELAY(ID); - -- NOTE: Last Bit denotes if this is Response or Suppression Delay - deadline_next(1)(0) <= '1'; - else - -- Zero Heartbeat Response Time - deadline_next <= TIME_ZERO; + -- Endpoint Lease Expired + if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline <= time) then + -- Remove Participant + mem_op_start <= '1'; + mem_opcode <= REMOVE_ENDPOINT; + -- Continue Search + cnt_next <= 0; + -- Response Time Reached + elsif (mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.res_time <= time) then + -- If Suppression Delay passed, zero the time + if(mem_endpoint_data.res_time(1)(0) = '1') then + -- Disable Suppression + mem_op_start <= '1'; + mem_opcode <= UPDATE_ENDPOINT; + deadline <= TIME_INVALID; + mem_field_flags <= RES_TIME_FLAG; + -- Continue Search + cnt_next <= 0; + -- If Response Delay Passed + else + -- Get Additional Data + mem_op_start <= '1'; + mem_opcode <= GET_ENDPOINT; + mem_field_flags <= EMF_IPV4_ADDR_FLAG or EMF_UDP_PORT_FLAG or EMF_NEXT_SEQ_NR_FLAG; + cnt_next <= 2; + end if; + end if; + -- Set New Timeout (Select the closest next timeout) + if (mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then + if (mem_endpoint_data.res_time < check_time) then + check_time_next <= mem_endpoint_data.res_time; + end if; + else + if (mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.lease_deadline < check_time) then + check_time_next <= mem_endpoint_data.lease_deadline; + end if; end if; - mem_opcode <= UPDATE_PARTICIPANT; - update_participant_flags_next <= RES_TIME_FLAG; - mem_op_start <= '1'; - -- Send ACKNACK - -- Increment Heartbeat/Acknack Counter - count_next <= count + 1; - stage_next <= SEND_HEADER; - return_stage_next <= SEND_ACKNACK; - cnt_next <= 0; end if; - end if; - -- No Stale Entry Found - else - -- DONE - stage_next <= IDLE; - end if; + when 2 => + -- Set Heartbeat Suppression Time + if (HEARTBEAT_SUPPRESSION_DELAY /= DURATION_INFINITE and HEARTBEAT_SUPPRESSION_DELAY /= DURATION_ZERO) then + -- Set Heartbeat Suppression Time + deadline <= time + HEARTBEAT_SUPPRESSION_DELAY; + -- NOTE: Last Bit denotes if this is Response or Suppression Delay + deadline(1)(0) <= '1'; + else + -- Disable Suppression + deadline <= TIME_INVALID; + end if; + mem_op_start <= '1'; + mem_opcode <= UPDATE_PARTICIPANT; + mem_field_flags <= RES_TIME_FLAG; + + -- Send ACKNACK + -- Increment Heartbeat/Acknack Counter + count_next <= count + 1; + stage_next <= SEND_HEADER; + return_stage_next <= SEND_ACKNACK; + cnt_next <= 0; + when others => + null; + end case; end if; when SEND_HEADER => if (rtps_full = '0') then @@ -1094,7 +1169,7 @@ begin data_out <= mem_endpoint_data.addr; -- Src and Dest UDPv4 Ports when 2 => - data_out <= USER_IPv4_UNICAST_PORT & mem_participant_data.meta_port; + data_out <= USER_IPv4_UNICAST_PORT & mem_endpoint_data.portn; -- RTPS MESSAGE HEADER when 3 => data_out <= PROTOCOL_RTPS; @@ -1125,7 +1200,7 @@ begin data_out <= SID_ACKNACK & "00000010" & std_logic_vector(to_unsigned(28, SUBMESSAGE_LENGTH_WIDTH)); -- Reader Entity ID when 1 => - data_out <= ENTITYID(ID); + data_out <= ENTITYID; -- Writer Entity ID when 2 => data_out <= ENTITYID_UNKNOWN; @@ -1145,11 +1220,18 @@ begin data_out <= (others => '1'); -- Count when 7 => - data_out <= std_logic_vector(count); + data_out <= std_logic_vector(count); last_word_out <= '1'; - -- DONE - stage_next <= IDLE; + -- Stale Check in Progress + if (stale_check = '1') then + -- Continue Search + stage_next <= ENDPOINT_STALE_CHECK; + cnt_next <= 0; + else + -- DONE + stage_next <= IDLE; + end if; when others => null; end case; @@ -1231,93 +1313,75 @@ begin end process; mem_ctrl_prc : process(all) - variable tmp : unsigned(mem_addr_base'range) := (others => '0'); - variable tmp2 : unsigned(mem_addr_base'range) := (others => '0'); - variable tmp3 : unsigned(mem_addr_base'range) := (others => '0'); - variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0')); begin -- DEFAULT Registered mem_stage_next <= mem_stage; mem_addr_base_next <= mem_addr_base; - mem_addr_next <= mem_addr; mem_cnt_next <= mem_cnt; last_addr_next <= last_addr; + mem_addr_latch_next <= mem_addr_latch; mem_endpoint_data_next <= mem_endpoint_data; mem_guidprefix_next <= mem_guidprefix; max_endpoint_addr_next <= max_endpoint_addr; - reset_max_pointer_next <= reset_max_pointer; - mem_long_latch_next <= mem_long_latch; - mem_ctrl_data_next <= mem_ctrl_data; + mem_endpoint_latch_data_next <= mem_endpoint_latch_data; mem_pos_next <= mem_pos; -- DEFAULT Unregistered + mem_addr <= (others => '0'); mem_write_data <= (others => '0'); + mem_read <= '0'; + mem_valid_in <= '0'; + mem_ready_out <= '0'; mem_op_done <= '0'; - mem_rd <= '0'; - mem_wr <= '0'; + abort_read <= '0'; case (mem_stage) is when IDLE => mem_op_done <= '1'; - reset_max_pointer_next <= '0'; - is_psearch_next <= '0'; if (mem_op_start = '1') then -- Latch Signals needed for Mermory Operation (Use _next signals, because some signals are set in same clk) - mem_ctrl_data_next <= ( + mem_endpoint_latch_data_next <= ( guid => guid_next, addr => addr_next, portn => portn_next, - expects_inline_qos => expects_inline_qos_next, - deadline => deadline_next, + deadline => deadline, next_seq_nr => next_seq_nr_next, - update_flags => update_endpoint_flags_next + field_flag => mem_field_flags ); case(mem_opcode) is when SEARCH_ENDPOINT => mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_pos_next <= 0; mem_stage_next <= SEARCH_ENDPOINT; mem_cnt_next <= 0; when INSERT_ENDPOINT => mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_pos_next <= 0; - mem_stage_next <= FIND_ENDPOINT_SLOT; + mem_stage_next <= FIND_EMPTY_SLOT; mem_cnt_next <= 0; when UPDATE_ENDPOINT => - if ((update_endpoint_flags and ENDPOINT_DATA_FLAG) = ENDPOINT_DATA_FLAG) then - mem_stage_next <= UPDATE_ENDPOINT; - mem_addr_next <= mem_addr_base + 4; + mem_stage_next <= UPDATE_ENDPOINT; + if check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then mem_cnt_next <= 0; - elsif ((update_endpoint_flags and LEASE_DEADLINE_FLAG) = LEASE_DEADLINE_FLAG) then - mem_stage_next <= UPDATE_ENDPPOINT; - mem_addr_next <= mem_addr_base + 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then mem_cnt_next <= 2; - elsif ((update_endpoint_flags and RES_TIME_FLAG) = RES_TIME_FLAG) then - mem_stage_next <= UPDATE_ENDPOINT; - mem_addr_next <= mem_addr_base + 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then mem_cnt_next <= 4; - elsif ((update_endpoint_flags and NEXT_SEQ_NR_FLAG) = NEXT_SEQ_NR_FLAG) then - mem_stage_next <= UPDATE_ENDPOINT; - mem_addr_next <= mem_addr_base + 10; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then mem_cnt_next <= 6; + else + -- DONE + mem_stage_next <= IDLE; end if; when REMOVE_ENDPOINT => - mem_addr_next <= mem_addr_base; mem_stage_next <= REMOVE_ENDPOINT; mem_cnt_next <= 0; - when FIND_STALE_ENDPOINT => - mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; - mem_pos_next <= 0; - mem_stage_next <= FIND_STALE_ENDPOINT; - mem_cnt_next <= 0; when GET_FIRST_ENDPOINT => mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; mem_pos_next <= 0; mem_stage_next <= GET_NEXT_ENDPOINT; mem_cnt_next <= 0; @@ -1325,496 +1389,992 @@ begin -- Memory Bound Guard if (mem_addr_base /= max_endpoint_addr) then -- Reached End of Memory, No match - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - mem_addr_base_next <= tmp; - mem_addr_next <= tmp; + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; mem_pos_next <= mem_pos + 1; mem_stage_next <= GET_NEXT_ENDPOINT; mem_cnt_next <= 0; else - mem_addr_base_next <= MAX_ADDRESS; + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; end if; - when FIND_FIRST_PARTICIPANT_ENDPOINT => - mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; - mem_pos_next <= 0; - mem_stage_next <= SEARCH_ENDPOINT; - mem_cnt_next <= 0; - is_psearch_next <= '1'; - when FIND_NEXT_PARTICIPANT_ENDPOINT => - -- Memory Bound Guard - if (mem_addr_base /= max_endpoint_addr) then - -- Reached End of Memory, No match - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - mem_addr_base_next <= tmp; - mem_addr_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_stage_next <= SEARCH_ENDPOINT; - mem_cnt_next <= 0; - is_psearch_next <= '1'; + when GET_ENDPOINT => + -- Fetch Endpoint Data + mem_stage_next <= GET_ENDPOINT_DATA; + mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 0; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; else - mem_addr_base_next <= MAX_ADDRESS; + -- DONE + mem_stage_next <= IDLE; end if; when others => null; end case; end if; when SEARCH_ENDPOINT => - mem_rd <= '1'; - mem_cnt_next <= mem_cnt + 1; - mem_addr_next <= mem_addr + 1; - - -- Next Endpoint Frame Address - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - case (mem_cnt) is - -- Preload - when 0 => - null; + -- *READ ADDRESS* -- Entity ID + when 0 => + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_read <= '1'; + mem_valid_in <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 1/3 when 1 => - -- No Match (Ignore Entity ID match on Participant Endpoint Search, but skip empty Slot) - if ((mem_read_data /= mem_ctrl_data.guid(3) and is_psearch = '0') or (mem_read_data = ENTITYID_UNKNOWN)) then - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; + mem_read <= '1'; + mem_valid_in <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 2/3 + when 2 => + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; + mem_read <= '1'; + mem_valid_in <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 3/3 + when 3 => + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; + mem_read <= '1'; + mem_valid_in <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- *READ DATA* + -- Entity ID + when 4 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + -- No Match + if (mem_read_data /= mem_endpoint_latch_data.guid(3)) then + -- Reached End of Memory, No Match + if (mem_addr_base = max_endpoint_addr) then + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match + -- DONE + mem_stage_next <= IDLE; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + abort_read <= '1'; + end if; else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; + mem_cnt_next <= mem_cnt + 1; end if; end if; -- GUID Prefix 1/3 - when 2 => - -- No Match - if (mem_read_data /= mem_ctrl_data.guid(0)) then - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; + when 5 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + -- No Match + if (mem_read_data /= mem_endpoint_latch_data.guid(0)) then + -- Reached End of Memory, No Match + if (mem_addr_base = max_endpoint_addr) then + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match + -- DONE + mem_stage_next <= IDLE; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + abort_read <= '1'; + end if; else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; + mem_cnt_next <= mem_cnt + 1; end if; end if; -- GUID Prefix 2/3 - when 3 => - -- No Match - if (mem_read_data /= mem_ctrl_data.guid(1)) then - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; + when 6 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + -- No Match + if (mem_read_data /= mem_endpoint_latch_data.guid(1)) then + -- Reached End of Memory, No Match + if (mem_addr_base = max_endpoint_addr) then + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match + -- DONE + mem_stage_next <= IDLE; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + abort_read <= '1'; + end if; else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; + mem_cnt_next <= mem_cnt + 1; end if; end if; -- GUID Prefix 3/3 - when 4 => - -- No Match - if (mem_read_data /= mem_ctrl_data.guid(2)) then - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; + when 7 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + -- No Match + if (mem_read_data /= mem_endpoint_latch_data.guid(2)) then + -- Reached End of Memory, No Match + if (mem_addr_base = max_endpoint_addr) then + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match + -- DONE + mem_stage_next <= IDLE; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + abort_read <= '1'; + end if; + -- Match else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; + mem_addr_base_next <= mem_addr_base; + -- Fetch Endpoint Data + mem_stage_next <= GET_ENDPOINT_DATA; + mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 0; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + -- DONE + mem_stage_next <= IDLE; + end if; end if; - -- Match - else - mem_addr_base_next <= mem_addr_base; - -- Fetch Endpoint Data - mem_stage_next <= GET_ENDPOINT_DATA; - mem_cnt_next <= 1; -- No preload needed end if; when others => null; end case; when GET_ENDPOINT_DATA => - mem_rd <= '1'; - mem_cnt_next <= mem_cnt + 1; - mem_addr_next <= mem_addr + 1; case (mem_cnt) is - -- Memory Preload + -- *READ ADDR* + -- Entity ID when 0 => - null; - -- IPv4 Address + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + mem_cnt_next <= 12; + end if; + end if; + -- GUID Prefix 1/3 when 1 => - mem_endpoint_data_next.addr <= mem_read_data; - -- UDPv4 Ports + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 2/3 when 2 => - mem_endpoint_data_next.portn <= mem_read_data(31 downto 16); - mem_endpoint_data_next.expects_inline_qos <= mem_read_data(0); - -- Lease Deadline 1/2 + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 3/3 when 3 => - mem_endpoint_data_next.lease_deadline(0) <= unsigned(mem_read_data); - -- Lease Deadline 2/2 + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + else + mem_cnt_next <= 13; + end if; + end if; + end if; + -- IPv4 Address when 4 => - mem_endpoint_data_next.lease_deadline(1) <= unsigned(mem_read_data); - -- Response/Suppression Time 1/2 + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + else + mem_cnt_next <= 16; + end if; + end if; + end if; + -- UDP Port/ Flags when 5 => - mem_endpoint_data_next.res_time(0) <= unsigned(mem_read_data); - -- Response/Suppression Time 2/2 - when 6 => - mem_endpoint_data_next.res_time(1) <= unsigned(mem_read_data); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + else + mem_cnt_next <= 17; + end if; + end if; + end if; -- Next Sequence Number 1/2 - when 7 => - mem_endpoint_data_next.next_seq_nr(0) <= unsigned(mem_read_data); + when 6 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- Next Sequence Number 2/2 + when 7 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + else + mem_cnt_next <= 18; + end if; + end if; + end if; + -- Lease Deadline 1/2 when 8 => - mem_endpoint_data_next.next_seq_nr(1) <= unsigned(mem_read_data); - -- DONE - mem_stage_next <= IDLE; + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Lease Deadline 2/2 + when 9 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + else + mem_cnt_next <= 20; + end if; + end if; + end if; + -- Response Time 1/2 + when 10 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Response Time 2/2 + when 11 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_read <= '1'; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 12; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + else + mem_cnt_next <= 22; + end if; + end if; + -- *READ DATA* + -- Entity ID + when 12 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.guid(3) <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 13; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- GUID Prefix 1/3 + when 13 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.guid(0) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 2/3 + when 14 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.guid(1) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + -- GUID Prefix 3/3 + when 15 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.guid(2) <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 16; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- IPv4 Address + when 16 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.addr <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 17; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- UDP Port + when 17 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.portn <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 18; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- Next Sequence Number 1/2 + when 18 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.next_seq_nr(0) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + -- Next Sequence Number 2/2 + when 19 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.next_seq_nr(1) <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 20; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- Lease Deadline 1/2 + when 20 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.lease_deadline(0) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + -- Lease Deadline 2/2 + when 21 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.addr <= mem_read_data; + + if check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 22; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- Response Time 1/2 + when 22 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.res_time(0) <= mem_read_data; + + mem_cnt_next <= mem_cnt + 1; + end if; + -- Response Time 2/2 + when 23 => + mem_ready_out <= '1'; + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + mem_endpoint_data_next.res_time(1) <= mem_read_data; + + -- DONE + mem_stage_next <= IDLE; + end if; when others => null; end case; when INSERT_ENDPOINT => - mem_wr <= '1'; - mem_addr_next <= mem_addr + 1; - mem_cnt_next <= mem_cnt + 1; - case (mem_cnt) is -- Entity ID when 0 => - mem_write_data <= mem_ctrl_data.guid(3); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_write_data <= mem_endpoint_latch_data.guid(3); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- GUID Prefix 1/3 when 1 => - mem_write_data <= mem_ctrl_data.guid(0); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET; + mem_write_data <= mem_endpoint_latch_data.guid(0); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- GUID Prefix 2/3 when 2 => - mem_write_data <= mem_ctrl_data.guid(1); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1; + mem_write_data <= mem_endpoint_latch_data.guid(1); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- GUID Prefix 3/3 when 3 => - mem_write_data <= mem_ctrl_data.guid(2); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2; + mem_write_data <= mem_endpoint_latch_data.guid(2); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- IPv4 Address when 4 => - mem_write_data <= mem_ctrl_data.addr; + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET; + mem_write_data <= mem_endpoint_latch_data.addr; + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- UDPv4 Ports when 5 => - mem_write_data <= mem_ctrl_data.portn & (0 => mem_ctrl_data.expects_inline_qos, 16 downto 1 => '0'); - -- Lease Deadline 1/2 - when 6 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(0)); - -- Lease Deadline 2/2 - when 7 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(1)); - -- Response/Suppression Time 1/2 - when 8 => - mem_write_data <= (others => '0'); - -- Response/Suppression Time 2/2 - when 9 => - mem_write_data <= (others => '0'); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; + mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0'); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- Next Sequence Number 1/2 - when 10 => + when 6 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET; mem_write_data <= (others => '0'); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; -- Next Sequence Number 2/2 - when 11 => + when 7 => + mem_write_data <= (others => '0'); + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; mem_write_data <= to_unsigned(1,CDR_LONG_WIDTH); - -- DONE - mem_stage_next <= IDLE; + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Lease Deadline 1/2 + when 8 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(0)); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Lease Deadline 2/2 + when 9 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(1)); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Response/Suppression Time 1/2 + when 10 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_write_data <= (others => '0'); + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Response/Suppression Time 2/2 + when 11 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_write_data <= (others => '0'); + if (mem_ready_in = '1') then + -- DONE + mem_stage_next <= IDLE; + end if; when others => null; end case; when UPDATE_ENDPOINT => - mem_cnt_next <= mem_cnt + 1; - mem_addr_next <= mem_addr + 1; - case (mem_cnt) is -- IPv4 Address when 0 => - mem_write_data <= mem_ctrl_data.addr; - if ((mem_ctrl_data.update_flags and ENDPOINT_DATA_FLAG) = ENDPOINT_DATA_FLAG) then - mem_wr <= '1'; + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_IPV4_ADDR_OFFSET; + mem_write_data <= mem_endpoint_latch_data.addr; + mem_endpoint_data.addr <= mem_endpoint_latch_data.addr; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 2; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 6; + else + -- DONE + mem_stage_next <= IDLE; + end if; end if; -- UDPv4 Ports when 1 => - mem_write_data <= mem_ctrl_data.portn & (0 => mem_ctrl_data.expects_inline_qos, 16 downto 1 => '0'); - if ((mem_ctrl_data.update_flags and ENDPOINT_DATA_FLAG) = ENDPOINT_DATA_FLAG) then - mem_wr <= '1'; - end if; - -- If nothing else to update - if ((mem_ctrl_data.update_flags and (LEASE_DEADLINE_FLAG or NEXT_SEQ_NR_FLAG or RES_TIME_FLAG)) = (mem_ctrl_data.update_flags'range => '0')) then - -- DONE - mem_stage_next <= IDLE; - end if; - -- Lease Deadline 1/2 - when 2 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(0)); - if ((mem_ctrl_data.update_flags and LEASE_DEADLINE_FLAG) = LEASE_DEADLINE_FLAG) then - mem_wr <= '1'; - end if; - -- Lease Deadline 2/2 - when 3 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(1)); - if ((mem_ctrl_data.update_flags and LEASE_DEADLINE_FLAG) = LEASE_DEADLINE_FLAG) then - mem_wr <= '1'; - end if; - -- If nothing else to update - if ((mem_ctrl_data.update_flags and (NEXT_SEQ_NR_FLAG or RES_TIME_FLAG)) = (mem_ctrl_data.update_flags'range => '0')) then - -- DONE - mem_stage_next <= IDLE; - end if; - -- Response/Suppression Time 1/2 - when 4 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(0)); - if ((mem_ctrl_data.update_flags and RES_TIME_FLAG) = RES_TIME_FLAG) then - mem_wr <= '1'; - end if; - -- Response/Suppression Time 2/2 - when 5 => - mem_write_data <= std_logic_vector(mem_ctrl_data.deadline(1)); - if ((mem_ctrl_data.update_flags and RES_TIME_FLAG) = RES_TIME_FLAG) then - mem_wr <= '1'; - end if; - -- If nothing else to update - if ((mem_ctrl_data.update_flags and (NEXT_SEQ_NR_FLAG)) = (mem_ctrl_data.update_flags'range => '0')) then - -- DONE - mem_stage_next <= IDLE; + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_UDP_PORT_OFFSET; + mem_write_data <= mem_endpoint_latch_data.portn & ((mem_write_data'length-mem_endpoint_latch_data.portn'length-1) downto 0 => '0'); + mem_endpoint_data.portn <= mem_endpoint_latch_data.portn; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 2; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 6; + else + -- DONE + mem_stage_next <= IDLE; + end if; end if; -- Next Sequence Number 1/2 - when 6 => - mem_write_data <= std_logic_vector(mem_ctrl_data.next_seq_nr(0)); - if ((mem_ctrl_data.update_flags and NEXT_SEQ_NR_FLAG) = NEXT_SEQ_NR_FLAG) then - mem_wr <= '1'; - end if; + when 2 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(0)); + -- Memory Flow Control Guard + if (mem_ready_in = '1') + mem_cnt_next <= mem_cnt + 1; -- Next Sequence Number 2/2 - when 7 => - mem_write_data <= std_logic_vector(mem_ctrl_data.next_seq_nr(1)); - if ((mem_ctrl_data.update_flags and NEXT_SEQ_NR_FLAG) = NEXT_SEQ_NR_FLAG) then - mem_wr <= '1'; + when 3 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.next_seq_nr(1)); + mem_endpoint_data.next_seq_nr <= mem_endpoint_latch_data.next_seq_nr; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 6; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- Lease Deadline 1/2 + when 4 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(0)); + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Lease Deadline 2/2 + when 5 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(1)); + mem_endpoint_data.lease_deadline <= mem_endpoint_latch_data.deadline; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + if check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 6; + else + -- DONE + mem_stage_next <= IDLE; + end if; + end if; + -- Response/Suppression Time 1/2 + when 6 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(0)); + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= mem_cnt + 1; + end if; + -- Response/Suppression Time 2/2 + when 7 => + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_RES_TIME_OFFSET + 1; + mem_write_data <= std_logic_vector(mem_endpoint_latch_data.deadline(1)); + mem_endpoint_data.res_time <= mem_endpoint_latch_data.deadline; + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + -- DONE + mem_stage_next <= IDLE; end if; - -- DONE - mem_stage_next <= IDLE; when others => null; end case; when REMOVE_ENDPOINT => -- Mark with ENTITYID_UNKNOWN to mark slot empty - mem_wr <= '1'; + mem_valid_in <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; mem_write_data <= ENTITYID_UNKNOWN; - -- Reset MAX Endpoint Pointer - mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; - mem_addr_next <= FIRST_ENDPOINT_ADDRESS; - mem_pos_next <= 0; - reset_max_pointer_next <= '1'; - last_addr_next <= (others => '0'); - mem_stage_next <= FIND_ENDPOINT_SLOT; - mem_cnt_next <= 0; - when FIND_ENDPOINT_SLOT => - mem_rd <= '1'; - mem_addr_next <= mem_addr + 1; - mem_cnt_next <= mem_cnt + 1; - - -- Next Endpoint Frame Address - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + -- Reset MAX Endpoint Pointer + mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS; + mem_pos_next <= 0; + last_addr_next <= (others => '0'); + mem_stage_next <= RESET_MAX_POINTER; + mem_cnt_next <= 0; + -- Save Current Memory Position + mem_addr_latch_next <= mem_addr_base; + end if; + when FIND_EMPTY_SLOT => case (mem_cnt) is - -- Preload + -- *READ ADDRESS* + -- Entity ID when 0 => - null; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_read <= '1'; + mem_valid_in <= '1'; + + -- Memory Control Flow Guard + if (mem_ready_in = '1') then + mem_cnt_next <= 1; + end if; + -- *READ DATA* -- Entity ID when 1 => - -- Slot Occupied - if (mem_read_data /= ENTITYID_UNKNOWN) then - -- Reached end of Endpoint Memory Area - if (mem_addr_base = max_endpoint_addr) then - -- We are in the middle of resetting the MAX Endpoint Pointer - if (reset_max_pointer = '1') then - -- No Change - mem_stage_next <= IDLE; - -- MEMORY FULL - elsif (max_endpoint_addr = MAX_ENDPOINT_ADDRESS) then - report "Memory Full, Ignoring Endpoint Data" severity NOTE; - -- Ignore Insertion - mem_stage_next <= IDLE; - mem_addr_base_next <= MAX_ADDRESS; - else - -- Extend Endpoint Memory Area - -- NOTE: "max_endpoint_addr" points to the first address of last Endpoint Frame - max_endpoint_addr_next <= tmp; - -- Populate Endpoint Slot - mem_stage_next <= INSERT_ENDPOINT; - mem_addr_base_next <= tmp; - mem_addr_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_addr_base_next <= tmp; - mem_cnt_next <= 0; - end if; - else - -- Latch last occupied Endpoint Slot - last_addr_next <= mem_addr_base; - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; - end if; - -- Slot Empty - else - -- We are in the middle of resetting the MAX Endpoint Pointer - if (reset_max_pointer = '1') then - -- Make sure to iterate through complete Endpoint Area + mem_ready_out <= '1'; + + -- Memory Control Flow Guard + if (mem_valid_out = '1') then + -- Slot Occupied + if (mem_read_data /= ENTITYID_UNKNOWN) then + -- Reached end of Endpoint Memory Area if (mem_addr_base = max_endpoint_addr) then - -- Reset Pointer to last occupied Endpoint Slot - max_endpoint_addr_next <= last_addr; - -- DONE - mem_stage_next <= IDLE; + -- MEMORY FULL + if (max_endpoint_addr = MAX_ENDPOINT_ADDRESS) then + report "Memory Full, Ignoring Endpoint Data" severity NOTE; + -- Ignore Insertion + mem_stage_next <= IDLE; + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; + else + -- Extend Endpoint Memory Area + -- NOTE: "max_endpoint_addr" points to the first address of last Endpoint Frame + max_endpoint_addr_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + -- Populate Endpoint Slot + mem_stage_next <= INSERT_ENDPOINT; + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + end if; else -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; mem_pos_next <= mem_pos + 1; mem_cnt_next <= 0; - end if; + end if; + -- Slot Empty else -- Populate Endpoint Slot mem_stage_next <= INSERT_ENDPOINT; - mem_addr_next <= mem_addr_base; mem_cnt_next <= 0; end if; end if; when others => null; end case; + when RESET_MAX_POINTER => + case (mem_cnt) is + -- *READ ADDRESS* + -- Entity ID + when 0 => + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + mem_read <= '1'; + mem_valid_in <= '1'; + + -- Memory Control Flow Guard + if (mem_ready_in = '1') then + mem_cnt_next <= 1; + end if; + -- *READ DATA* + -- Entity ID + when 1 => + mem_ready_out <= '1'; + + -- Memory Control Flow Guard + if (mem_valid_out = '1') then + -- Slot Occupied + if (mem_read_data /= ENTITYID_UNKNOWN) then + -- Reached end of Endpoint Memory Area + if (mem_addr_base = max_endpoint_addr) then + -- No Change + mem_stage_next <= IDLE; + -- Restore Memory Position + mem_addr_base_next <= mem_addr_latch; + else + -- Latch last occupied Endpoint Slot + last_addr_next <= mem_addr_base; + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + end if; + -- Slot Empty + else + -- Make sure to iterate through complete Endpoint Area + if (mem_addr_base = max_endpoint_addr) then + -- Reset Pointer to last occupied Endpoint Slot + max_endpoint_addr_next <= last_addr; + -- DONE + mem_stage_next <= IDLE; + -- Restore Memory Position + mem_addr_base_next <= mem_addr_latch; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + end if; + end if; + end if; + when others => + null; + end case; when GET_NEXT_ENDPOINT => - mem_rd <= '1'; - mem_cnt_next <= mem_cnt + 1; - mem_addr_next <= mem_addr + 1; - - -- Next Endpoint Frame Address - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - -- Beginning of Endpoint Data - tmp2 := mem_addr_base + 4; - case (mem_cnt) is - -- Preload + -- *READ ADDRESS* + -- Entity ID when 0 => - null; + mem_valid_in <= '1'; + mem_read <= '1'; + mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET; + + -- Memory Flow Control Guard + if (mem_ready_in = '1') then + mem_cnt_next <= 1; + end if; + -- *READ DATA* -- Entity ID when 1 => - -- Slot Occupied - if (mem_read_data /= ENTITYID_UNKNOWN) then - -- Get Endpoint Data - mem_addr_next <= tmp2; - mem_stage_next <= GET_ENDPOINT_DATA; - mem_cnt_next <= 0; - -- Slot Empty - else - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; + mem_ready_out <= '1'; + + -- Memory Flow Control Guard + if (mem_valid_out = '1') then + -- Slot Occupied + if (mem_read_data /= ENTITYID_UNKNOWN) then + -- Fetch Endpoint Data + mem_stage_next <= GET_ENDPOINT_DATA; + mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; + if check_mask(mem_endpoint_latch_data.field_flag,EMF_ENTITYID_FLAG) then + mem_cnt_next <= 0; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_GUIDPREFIX_FLAG) then + mem_cnt_next <= 1; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_IPV4_ADDR_FLAG) then + mem_cnt_next <= 4; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_UDP_PORT_FLAG) then + mem_cnt_next <= 5; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_NEXT_SEQ_NR_FLAG) then + mem_cnt_next <= 6; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_LEASE_DEADLINE_FLAG) then + mem_cnt_next <= 8; + elsif check_mask(mem_endpoint_latch_data.field_flag,EMF_RES_TIME_FLAG) then + mem_cnt_next <= 10; + else + -- DONE + mem_stage_next <= IDLE; + end if; + -- Slot Empty else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; - end if; - end if; - when others => - null; - end case; - when FIND_STALE_ENDPOINT => - mem_rd <= '1'; - mem_cnt_next <= mem_cnt + 1; - mem_addr_next <= mem_addr + 1; - - -- Next Endpoint Frame Address - tmp := mem_addr_base + ENDPOINT_FRAME_SIZE; - -- Beginning of Endpoint Data - tmp2 := mem_addr_base + 4; - -- Beginning of Lease Deadline - tmp3 := mem_addr_base + 6; - - case (mem_cnt) is - -- Preload - when 0 => - null; - -- Entity ID - when 1 => - -- Slot Occupied - if (mem_read_data /= ENTITYID_UNKNOWN) then - -- Jump to Stale Check - mem_addr_next <= tmp3; - mem_cnt_next <= 2; - -- Slot Empty - else - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; - else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; - end if; - end if; - -- Preload - when 2 => - null; - -- Lease Deadline 1/2 - when 3 => - mem_long_latch_next <= mem_read_data; - -- Lease Deadline 2/2 - when 4 => - tmp_dw := (0 => unsigned(mem_long_latch), 1 => unsigned(mem_read_data)); - -- Lease Deadline passed - if (tmp_dw < time) then - -- Mark Endpoint as stale - mem_endpoint_data_next <= ZERO_ENDPOINT_DATA; - -- DONE - mem_stage_next <= IDLE; - end if; - -- Response/Suppression Time 1/2 - when 5 => - mem_long_latch_next <= mem_read_data; - -- Response/Suppression Time 2/2 - when 6 => - tmp_dw := (0 => unsigned(mem_long_latch), 1 => unsigned(mem_read_data)); - -- Response/Suppression Time passed - if (tmp_dw /= 0 and tmp_dw < time) then - -- Mark Endpoint and get Endpoint Data - mem_addr_next <= tmp2; - mem_stage_next <= GET_ENDPOINT_DATA; - mem_cnt_next <= 0; - -- Endpoint not Stale - else - -- Reached End of Memory, No Match - if (mem_addr_base = max_endpoint_addr) then - mem_addr_base_next <= MAX_ADDRESS; --No match - -- DONE - mem_stage_next <= IDLE; - else - -- Continue Search - mem_addr_next <= tmp; - mem_addr_base_next <= tmp; - mem_pos_next <= mem_pos + 1; - mem_cnt_next <= 0; + -- Reached End of Memory, No Match + if (mem_addr_base = max_endpoint_addr) then + mem_addr_base_next <= ENDPOINT_MEMORY_MAX_ADDRESS; --No match + -- DONE + mem_stage_next <= IDLE; + else + -- Continue Search + mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE; + mem_pos_next <= mem_pos + 1; + mem_cnt_next <= 0; + end if; end if; end if; when others => diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index 35a3043..d9b5da5 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -115,6 +115,7 @@ package rtps_package is constant PROTOCOLVERSION_2_4 : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0) := x"0204"; constant VENDORID_UNKNOWN : std_logic_vector(VENDORID_WIDTH-1 downto 0) := (others => '0'); constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0')); + constant GUID_UNKNOWN : GUID_TYPE := (others => (others => '0')); constant UDP_PORT_INVALID : std_logic_vector(UDP_PORT_WIDTH-1 downto 0) := (others => '0'); constant IPv4_ADDRESS_INVALID : std_logic_vector(IPv4_ADDRESS_WIDTH-1 downto 0) := (others => '0'); constant LENGTH_UNLIMITED : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := std_logic_vector(to_signed(-1,CDR_LONG_WIDTH));