Various fixes in RTPS Reader

Ignore unknown Metatraffic Operations.
Drop payload if not necessary (i.e. do not push payload if payload
contains serialized Key, but Key Hash is already provided).
Added Memory Reset State.
Misc fixes
This commit is contained in:
Greek 2021-02-07 17:52:34 +01:00
parent 6488918ede
commit f0cc1e5432

View File

@ -6,12 +6,7 @@ use work.rtps_package.all;
use work.user_config.all;
use work.rtps_config_package.all;
-- TODO: Use TIME_INVALID instead of zero. (Backport to builtin_endpoint) [Pay atention to (0) bit of ACKNACK and HEARTBEAT Deadlines, if compatible]
-- TODO: Check for special values of time/duration?
-- TODO: Remove last_word flag from metattraffic operations
-- TODO: Replace all ('range => 0) checks with defined constants, where possible
-- TODO: Adding LIFESPAN Duration in the stored Endpoint Metatraffic Data would allow us to not expect in-line QoS (Which could be a significant overhead)
-- TODO: Is mem_addr_base needed? Isn't it a direct mirror of addr_mem_base? mem_addr_base is only used in the same clock cycle as mem_op_done is pulled high.
entity rtps_reader is
@ -31,12 +26,13 @@ entity rtps_reader is
-- FROM RTPS_HANDLER (USER TRAFFIC)
empty_user : in std_logic;
rd_user : out std_logic;
last_word_in_user : in std_logic;
data_in_user : in std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_in_user : in std_logic;
-- FROM RTPS_BUILTIN_ENDPOINT (META TRAFFIC)
empty_meta : in std_logic;
data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0);
rd_meta : out std_logic;
data_in_meta : in std_logic_vector(WORD_WIDTH-1 downto 0);
last_word_in_meta : in std_logic;
-- RTPS OUTPUT
wr_rtps : out std_logic;
full_rtps : in std_logic;
@ -95,10 +91,10 @@ architecture arch of rtps_reader is
type STAGE_TYPE is (IDLE, LATCH_GUIDPREFIX, LATCH_ENTITYID, INITIATE_ENDPOINT_SEARCH, LATCH_ENDPOINT_DATA, METATRAFFIC_OPERATION, LATCH_SRC_ADDR,
LATCH_EXTRA_DATA, LATCH_HEARTBEAT, PROCESS_HEARTBEAT, LATCH_GAP, PROCESS_GAP, FIND_NEXT_VALID_IN_BITMAP, PROCESS_INLINE_QOS, LATCH_LIFESPAN,
LATCH_KEY_HASH, LATCH_STATUS_INFO, INITIATE_ADD_CACHE_CHANGE_REQUEST, ADD_CACHE_CHANGE, PUSH_PAYLOAD, FINALIZE_ADD_CACHE_CHANGE_REQUEST,
ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET);
ENDPOINT_STALE_CHECK, SEND_HEADER, SEND_ACKNACK, SKIP_PARAMETER, SKIP_PACKET, SKIP_META_OPERATION);
-- Memory FSM states. Explained below in detail
type MEM_STAGE_TYPE is (IDLE, SEARCH_ENDPOINT, GET_ENDPOINT_DATA, INSERT_ENDPOINT, UPDATE_ENDPOINT, REMOVE_ENDPOINT, FIND_EMPTY_SLOT,
RESET_MAX_POINTER, GET_NEXT_ENDPOINT);
RESET_MAX_POINTER, GET_NEXT_ENDPOINT, RESET_MEMORY);
-- *Memory FSM Opcodes*
-- OPCODE DESCRIPTION
-- SEARCH_ENDPOINT Find Endpoint with specified GUID in memory
@ -320,10 +316,10 @@ begin
read => mem_read,
ready_in => mem_ready_in,
valid_in => mem_valid_in,
data_in_user => mem_write_data,
data_in => mem_write_data,
ready_out => mem_ready_out,
valid_out => mem_valid_out,
data_out_rtps => mem_read_data
data_out => mem_read_data
);
-- Big Endian Representation
@ -357,6 +353,7 @@ begin
-- SEND_ACKNACK Send ACKNACK Submessage
-- SKIP_PARAMETER Skip rest of Parameter
-- SKIP_PACKET Skip rest of Packet
-- SKIP_META_OPERATION Skip Metatraffic Operation
parse_prc : process(all)
variable tmp_dw : DOUBLE_WORD_ARRAY := (others => (others => '0'));
-- NOTE: We convert the bitamp to a slv to make operations easier (The tool should handle both cases equally)
@ -364,14 +361,14 @@ begin
variable rd_guard : std_logic := '0';
variable tmp_flags : std_logic_vector(0 to EMF_FLAG_WIDTH-1) := (others => '0');
begin
-- DEFAULT Registerd
-- DEFAULT Registered
stage_next <= stage;
meta_opcode_next <= meta_opcode;
cnt_next <= cnt;
cnt2_next <= cnt2;
guid_next <= guid;
addr_next <= addr;
portn_next <= portn;
expects_inline_qos_next <= expects_inline_qos;
is_meta_next <= is_meta;
opcode_next <= opcode;
flags_next <= flags;
@ -399,9 +396,8 @@ begin
rd_user <= '0';
mem_op_start <= '0';
start_dds <= '0';
ready_out_dds <= '0';
valid_out_dds <= '0';
last_word_out_dds <= '0';
last_word_out_dds <= '0';
rd_guard := '0';
mem_field_flags <= (others => '0');
data_out_dds <= (others => '0');
@ -446,8 +442,22 @@ begin
-- Latch Endpoint Metatraffic Opcode
meta_opcode_next <= data_in_meta;
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
case (data_in_meta) is
when OPCODE_ENDPOINT_MATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_ENDPOINT_UNMATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_PARTICIPANT_UNMATCH =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when OPCODE_LIVELINESS_UPDATE =>
stage_next <= LATCH_GUIDPREFIX;
cnt_next <= 0;
when others =>
stage_next <= SKIP_META_OPERATION;
end case;
-- Input FIFO Guard
elsif (empty_user = '0') then
rd_guard := '1';
@ -499,6 +509,7 @@ begin
end if;
if (is_meta = '1' and (meta_opcode = OPCODE_PARTICIPANT_UNMATCH or meta_opcode = OPCODE_LIVELINESS_UPDATE)) then
assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE;
-- DONE Parsing
stage_next <= INITIATE_ENDPOINT_SEARCH;
else
@ -510,6 +521,7 @@ begin
-- Input FIFO Guard
if ((is_meta = '1' and empty_meta = '0') or (is_meta = '0' and empty_user = '0')) then
if (is_meta = '1') then
assert (meta_opcode /= OPCODE_ENDPOINT_UNMATCH or (meta_opcode = OPCODE_ENDPOINT_UNMATCH and last_word_in_meta = '1')) "last_word_in_meta not set" severity FAILURE;
rd_meta <= '1';
guid_next(3) <= data_in_meta;
-- Memory Operation Guard
@ -555,7 +567,6 @@ begin
stage_next <= METATRAFFIC_OPERATION;
cnt_next <= 0;
when others =>
assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE;
null;
end case;
else
@ -569,7 +580,7 @@ begin
cnt_next <= 0;
when SID_HEARTBEAT =>
stage_next <= LATCH_HEARTBEAT;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG;
mem_field_flags <= EMF_NEXT_SEQ_NR_FLAG or EMF_RES_TIME_FLAG;
cnt_next <= 0;
when SID_GAP =>
stage_next <= LATCH_GAP;
@ -594,6 +605,8 @@ begin
addr_next <= data_in_meta;
-- UDP Port
when 1 =>
assert (last_word_in_meta = '1') report "last_word_in_meta not set" severity FAILURE;
portn_next <= data_in_meta(WORD_WIDTH-1 downto WORD_WIDTH-UDP_PORT_WIDTH-1);
stage_next <= METATRAFFIC_OPERATION;
@ -724,7 +737,6 @@ begin
null;
end case;
when others =>
assert FALSE report "Uknown metatraffic endpoint frame opcode." severity FAILURE;
null;
end case;
end if;
@ -823,7 +835,7 @@ begin
end if;
-- No scheduled Heartbeat Response
if (mem_endpoint_data.res_time = 0) then
if (mem_endpoint_data.res_time = TIME_INVALID) 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
@ -894,18 +906,18 @@ begin
-- GapList.Base 2/2
when 3 =>
gap_list_base_next(1) <= unsigned(data_in_user);
-- ReaderSNState.NumBits
-- GapList.NumBits
when 4 =>
gap_list_end_next <= gap_list_base + to_integer(unsigned(data_in_user));
bitmap_cnt_next <= unsigned(round_slv(data_in_user(log2c(MAX_BITMAP_WIDTH)-1 downto 0),bitmap_cnt'length));
cnt2_next <= 0;
-- ReaderSNState.Bitmap
-- GapList.Bitmap
when 5 =>
-- Read Bitmap
if (cnt2 < bitmap_cnt) then
cnt2_next <= cnt2 + 1;
bitmap_latch_next(cnt2) <= data_in_swapped;
bitmap_latch_next(cnt2) <= data_in_user;
-- Keep Sub-State
cnt_next <= cnt;
@ -1120,12 +1132,17 @@ begin
stage_next <= SKIP_PARAMETER;
end if;
when INITIATE_ADD_CACHE_CHANGE_REQUEST =>
start_dds <= '1';
opcode_dds <= ADD_CACHE_CHANGE;
-- Wait until History Cache acknowledges request
if (res_dds = ACK) then
stage_next <= ADD_CACHE_CHANGE;
cnt_next <= 0;
-- SANITY CHECK: Skip if no Hash Key and no payload
if (WITH_KEY and key_hash_rcvd = '0' and data_flag = '0' and key_flag = '0') then
stage_next <= SKIP_PACKET;
else
start_dds <= '1';
opcode_dds <= ADD_CACHE_CHANGE;
-- Wait until History Cache acknowledges request
if (res_dds = ACK) then
stage_next <= ADD_CACHE_CHANGE;
cnt_next <= 0;
end if;
end if;
when ADD_CACHE_CHANGE =>
case (cnt) is
@ -1218,8 +1235,10 @@ begin
-- Output Guard
if (ready_out_dds = '1') then
-- NOTE: We only push the Payload if there is Data, or if the Key Hash was not received and we need to push
-- the serialized Key.
-- Payload exists
if (data_flag = '1' or (WITH_KEY and key_flag = '1')) then
if (data_flag = '1' or (WITH_KEY and key_hash_rcvd = '0')) then
stage_next <= PUSH_PAYLOAD;
else
-- DONE
@ -1331,7 +1350,7 @@ begin
end if;
else
-- Update Check Time
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 (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS and mem_endpoint_data.res_time /= TIME_INVALID and mem_endpoint_data.lease_deadline /= TIME_INVALID and mem_endpoint_data.res_time < mem_endpoint_data.lease_deadline) then
if (mem_endpoint_data.res_time < check_time) then
check_time_next <= mem_endpoint_data.res_time;
end if;
@ -1369,7 +1388,7 @@ begin
mem_field_flags <= RES_TIME_FLAG;
-- Send ACKNACK
-- Increment Heartbeat/Acknack Counter
-- Increment Acknack Counter
count_next <= count + 1;
stage_next <= SEND_HEADER;
return_stage_next <= SEND_ACKNACK;
@ -1510,6 +1529,14 @@ begin
-- Skip-Read
rd_guard := '1';
end if;
when SKIP_META_OPERATION =>
-- Skip-Read
rd_meta <= '1';
-- Exit Condition
if (last_word_in_meta = '1') then
stage_next <= IDLE;
end if;
when others =>
null;
end case;
@ -1556,6 +1583,7 @@ begin
-- FIND_EMPTY_SLOT Find first empty_user slot in memory.
-- RESET_MAX_POINTER Reset the max_endpoint_addr pointer to last occupied slot in memory.
-- GET_NEXT_ENDPOINT See Memory OPCODE Description
-- RESET_MEMORY Reset Endpoint Memory to Empty State
mem_ctrl_prc : process(all)
begin
-- DEFAULT Registered
@ -1669,8 +1697,7 @@ begin
end if;
when SEARCH_ENDPOINT =>
case (mem_cnt) is
-- *READ ADDRESS*
-- Entity ID
-- GET Entity ID
when 0 =>
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
@ -1679,7 +1706,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 1/3
-- GET GUID Prefix 1/3
when 1 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
mem_read <= '1';
@ -1688,7 +1715,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 2/3
-- GET GUID Prefix 2/3
when 2 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
mem_read <= '1';
@ -1697,7 +1724,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 3/3
-- GET GUID Prefix 3/3
when 3 =>
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
mem_read <= '1';
@ -1706,8 +1733,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- *READ DATA*
-- Entity ID
-- READ Entity ID
when 4 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -1730,7 +1756,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- GUID Prefix 1/3
-- READ GUID Prefix 1/3
when 5 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -1753,7 +1779,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- GUID Prefix 2/3
-- READ GUID Prefix 2/3
when 6 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -1776,7 +1802,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- GUID Prefix 3/3
-- READ GUID Prefix 3/3
when 7 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -1827,8 +1853,7 @@ begin
when GET_ENDPOINT_DATA =>
case (mem_cnt) is
-- *READ ADDR*
-- Entity ID
-- GET Entity ID
when 0 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
@ -1851,7 +1876,7 @@ begin
mem_cnt_next <= 12;
end if;
end if;
-- GUID Prefix 1/3
-- GET GUID Prefix 1/3
when 1 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET;
@ -1860,7 +1885,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 2/3
-- GET GUID Prefix 2/3
when 2 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 1;
@ -1869,7 +1894,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 3/3
-- GET GUID Prefix 3/3
when 3 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_GUIDPREFIX_OFFSET + 2;
@ -1894,7 +1919,7 @@ begin
end if;
end if;
end if;
-- IPv4 Address
-- GET IPv4 Address
when 4 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -1922,7 +1947,7 @@ begin
end if;
end if;
end if;
-- UDP Port/ Flags
-- GET UDP Port/ Flags
when 5 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -1950,7 +1975,7 @@ begin
end if;
end if;
end if;
-- Next Sequence Number 1/2
-- GET Next Sequence Number 1/2
when 6 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET;
@ -1959,7 +1984,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Next Sequence Number 2/2
-- GET Next Sequence Number 2/2
when 7 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_NEXT_SEQ_NR_OFFSET + 1;
@ -1984,7 +2009,7 @@ begin
end if;
end if;
end if;
-- Lease Deadline 1/2
-- GET Lease Deadline 1/2
when 8 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET;
@ -1993,7 +2018,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= mem_cnt + 1;
end if;
-- Lease Deadline 2/2
-- GET Lease Deadline 2/2
when 9 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_LEASE_DEADLINE_OFFSET + 1;
@ -2018,7 +2043,7 @@ begin
end if;
end if;
end if;
-- Response Time 1/2
-- GET Response Time 1/2
when 10 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2030,7 +2055,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- Response Time 2/2
-- GET Response Time 2/2
when 11 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2056,8 +2081,7 @@ begin
end if;
end if;
end if;
-- *READ DATA*
-- Entity ID
-- READ Entity ID
when 12 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2081,7 +2105,7 @@ begin
mem_stage_next <= IDLE;
end if;
end if;
-- GUID Prefix 1/3
-- READ GUID Prefix 1/3
when 13 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2090,7 +2114,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 2/3
-- READ GUID Prefix 2/3
when 14 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2099,7 +2123,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
-- GUID Prefix 3/3
-- READ GUID Prefix 3/3
when 15 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2121,7 +2145,7 @@ begin
mem_stage_next <= IDLE;
end if;
end if;
-- IPv4 Address
-- READ IPv4 Address
when 16 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2144,7 +2168,7 @@ begin
end if;
end if;
end if;
-- UDP Port
-- READ UDP Port
when 17 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2165,7 +2189,7 @@ begin
end if;
end if;
end if;
-- Next Sequence Number 1/2
-- READ Next Sequence Number 1/2
when 18 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2174,7 +2198,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
-- Next Sequence Number 2/2
-- READ Next Sequence Number 2/2
when 19 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2190,7 +2214,7 @@ begin
mem_stage_next <= IDLE;
end if;
end if;
-- Lease Deadline 1/2
-- READ Lease Deadline 1/2
when 20 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2199,7 +2223,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
-- Lease Deadline 2/2
-- READ Lease Deadline 2/2
when 21 =>
mem_ready_out <= '1';
-- Memory Flow Control Guard
@ -2213,7 +2237,7 @@ begin
mem_stage_next <= IDLE;
end if;
end if;
-- Response Time 1/2
-- READ Response Time 1/2
when 22 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2225,7 +2249,7 @@ begin
mem_cnt_next <= mem_cnt + 1;
end if;
end if;
-- Response Time 2/2
-- READ Response Time 2/2
when 23 =>
-- Synthesis Guard
if (RELIABILTY_QOS = RELIABLE_RELIABILITY_QOS) then
@ -2415,7 +2439,8 @@ begin
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;
mem_cnt_next <= mem_cnt + 1;
end if;
-- Next Sequence Number 2/2
when 3 =>
mem_valid_in <= '1';
@ -2561,8 +2586,7 @@ begin
end case;
when RESET_MAX_POINTER =>
case (mem_cnt) is
-- *READ ADDRESS*
-- Entity ID
-- GET Entity ID
when 0 =>
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_read <= '1';
@ -2572,8 +2596,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= 1;
end if;
-- *READ DATA*
-- Entity ID
-- READ Entity ID
when 1 =>
mem_ready_out <= '1';
@ -2618,8 +2641,7 @@ begin
end case;
when GET_NEXT_ENDPOINT =>
case (mem_cnt) is
-- *READ ADDRESS*
-- Entity ID
-- GET Entity ID
when 0 =>
mem_valid_in <= '1';
mem_read <= '1';
@ -2629,8 +2651,7 @@ begin
if (mem_ready_in = '1') then
mem_cnt_next <= 1;
end if;
-- *READ DATA*
-- Entity ID
-- READ Entity ID
when 1 =>
mem_ready_out <= '1';
@ -2677,6 +2698,32 @@ begin
when others =>
null;
end case;
when RESET_MEMORY =>
case (mem_cnt) is
-- Initiate Reset
when 0 =>
mem_addr_base_next <= FIRST_ENDPOINT_ADDRESS;
mem_cnt_next <= mem_cnt + 1;
-- Reset Memory
when 1 =>
mem_valid_in <= '1';
mem_addr <= mem_addr_base + EMF_ENTITYID_OFFSET;
mem_write_data <= ENTITYID_UNKNOWN;
-- Memory Flow Control Guard
if (mem_ready_in = '1') then
-- End of Memory
if (mem_addr_base = MAX_ENDPOINT_ADDRESS) then
-- DONE
mem_stage_next <= IDLE;
else
-- Next Endpoint Frame
mem_addr_base_next <= mem_addr_base + ENDPOINT_FRAME_SIZE;
end if;
end if;
when others =>
null;
end case;
when others =>
null;
end case;