* Added Documentation
- UDP Protocol * Added Synthesis Report for IPv4 Parser with different buffer sizes * Small fixes in IPv4 Handler * Added addsub Entity * Added Checksum entity * Implemented RTPS Parser - Compiles in Modelsim * Backup Version of RTPS Parser to extract and implement UDP Checksuming * Updated RTPS Package * Added VHDL comilation test file
This commit is contained in:
parent
10cda546bf
commit
9ab7d79d87
127
Report.txt
Normal file
127
Report.txt
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Start RTL Component Statistics (1 Buffer)
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Detailed RTL Component Info :
|
||||||
|
+---Adders :
|
||||||
|
3 Input 14 Bit Adders := 1
|
||||||
|
2 Input 14 Bit Adders := 3
|
||||||
|
2 Input 9 Bit Adders := 1
|
||||||
|
+---Registers :
|
||||||
|
400 Bit Registers := 1
|
||||||
|
88 Bit Registers := 1
|
||||||
|
32 Bit Registers := 1
|
||||||
|
14 Bit Registers := 5
|
||||||
|
9 Bit Registers := 1
|
||||||
|
4 Bit Registers := 1
|
||||||
|
1 Bit Registers := 3
|
||||||
|
+---RAMs :
|
||||||
|
512K Bit RAMs := 1
|
||||||
|
+---Muxes :
|
||||||
|
2 Input 400 Bit Muxes := 2
|
||||||
|
18 Input 400 Bit Muxes := 1
|
||||||
|
2 Input 32 Bit Muxes := 10
|
||||||
|
18 Input 32 Bit Muxes := 2
|
||||||
|
2 Input 14 Bit Muxes := 1
|
||||||
|
18 Input 14 Bit Muxes := 4
|
||||||
|
18 Input 9 Bit Muxes := 1
|
||||||
|
17 Input 5 Bit Muxes := 1
|
||||||
|
2 Input 5 Bit Muxes := 10
|
||||||
|
2 Input 2 Bit Muxes := 2
|
||||||
|
2 Input 1 Bit Muxes := 7
|
||||||
|
18 Input 1 Bit Muxes := 16
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
State | New Encoding | Previous Encoding
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
ipv4_init | 00000 | 00000
|
||||||
|
ipv4_header_1 | 00001 | 00001
|
||||||
|
ipv4_header_2 | 00010 | 00010
|
||||||
|
ipv4_header_3 | 00011 | 00011
|
||||||
|
ipv4_header_4 | 00100 | 00100
|
||||||
|
ipv4_header_5 | 00101 | 00101
|
||||||
|
skip_header | 00110 | 01111
|
||||||
|
ipv4_fragment_pre | 00111 | 01000
|
||||||
|
ipv4_fragment | 01000 | 01001
|
||||||
|
ipv4_fragment_post | 01001 | 01010
|
||||||
|
ipv4_buffer_src | 01010 | 01011
|
||||||
|
ipv4_buffer_dest | 01011 | 01100
|
||||||
|
ipv4_buffer_length | 01100 | 01101
|
||||||
|
ipv4_buffer_payload | 01101 | 01110
|
||||||
|
skip_packet | 01110 | 10000
|
||||||
|
iSTATE | 01111 | 11111
|
||||||
|
ipv4_payload_length | 10000 | 00110
|
||||||
|
ipv4_payload | 10001 | 00111
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Start RTL Component Statistics (0 Buffer)
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Detailed RTL Component Info :
|
||||||
|
+---Adders :
|
||||||
|
2 Input 14 Bit Adders := 3
|
||||||
|
3 Input 14 Bit Adders := 1
|
||||||
|
2 Input 9 Bit Adders := 1
|
||||||
|
+---Registers :
|
||||||
|
400 Bit Registers := 1
|
||||||
|
88 Bit Registers := 1
|
||||||
|
14 Bit Registers := 5
|
||||||
|
9 Bit Registers := 1
|
||||||
|
4 Bit Registers := 1
|
||||||
|
1 Bit Registers := 2
|
||||||
|
+---Muxes :
|
||||||
|
2 Input 400 Bit Muxes := 2
|
||||||
|
2 Input 32 Bit Muxes := 7
|
||||||
|
12 Input 32 Bit Muxes := 1
|
||||||
|
2 Input 14 Bit Muxes := 1
|
||||||
|
11 Input 4 Bit Muxes := 1
|
||||||
|
2 Input 4 Bit Muxes := 7
|
||||||
|
2 Input 1 Bit Muxes := 4
|
||||||
|
12 Input 1 Bit Muxes := 7
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
State | New Encoding | Previous Encoding
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
ipv4_init | 0000 | 00000
|
||||||
|
ipv4_header_1 | 0001 | 00001
|
||||||
|
ipv4_header_2 | 0010 | 00010
|
||||||
|
ipv4_header_3 | 0011 | 00011
|
||||||
|
ipv4_header_4 | 0100 | 00100
|
||||||
|
ipv4_header_5 | 0101 | 00101
|
||||||
|
skip_header | 0110 | 01111
|
||||||
|
ipv4_fragment_pre | 0111 | 01000
|
||||||
|
ipv4_payload_length | 1000 | 00110
|
||||||
|
ipv4_payload | 1001 | 00111
|
||||||
|
skip_packet | 1010 | 10000
|
||||||
|
iSTATE | 1011 | 11111
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Start RTL Component Statistics (No Frag)
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
Detailed RTL Component Info :
|
||||||
|
+---Adders :
|
||||||
|
2 Input 14 Bit Adders := 1
|
||||||
|
3 Input 14 Bit Adders := 1
|
||||||
|
+---Registers :
|
||||||
|
14 Bit Registers := 1
|
||||||
|
4 Bit Registers := 1
|
||||||
|
+---Muxes :
|
||||||
|
2 Input 32 Bit Muxes := 3
|
||||||
|
11 Input 32 Bit Muxes := 1
|
||||||
|
10 Input 4 Bit Muxes := 1
|
||||||
|
2 Input 4 Bit Muxes := 5
|
||||||
|
2 Input 1 Bit Muxes := 1
|
||||||
|
11 Input 1 Bit Muxes := 6
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
State | New Encoding | Previous Encoding
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
|
ipv4_init | 0000 | 0000
|
||||||
|
ipv4_header_1 | 0001 | 0001
|
||||||
|
ipv4_header_2 | 0010 | 0010
|
||||||
|
ipv4_header_3 | 0011 | 0011
|
||||||
|
ipv4_header_4 | 0100 | 0100
|
||||||
|
ipv4_header_5 | 0101 | 0101
|
||||||
|
skip_header | 0110 | 1000
|
||||||
|
ipv4_payload_length | 0111 | 0110
|
||||||
|
ipv4_payload | 1000 | 0111
|
||||||
|
skip_packet | 1001 | 1001
|
||||||
|
iSTATE | 1010 | 1111
|
||||||
|
---------------------------------------------------------------------------------------------------
|
||||||
BIN
doc/rfc768.pdf
(Stored with Git LFS)
Normal file
BIN
doc/rfc768.pdf
(Stored with Git LFS)
Normal file
Binary file not shown.
87
src/TODO.txt
Normal file
87
src/TODO.txt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
RULES 8.4.2
|
||||||
|
===========
|
||||||
|
|
||||||
|
GENERAL
|
||||||
|
-------
|
||||||
|
* All communications must take place using RTPS Messages
|
||||||
|
* All implementations must implement the RTPS Message Receiver
|
||||||
|
* The timing characteristics of all implementations must be tunable
|
||||||
|
* Implementations must implement the Simple Participant and Endpoint Discovery Protocols
|
||||||
|
|
||||||
|
WRITER
|
||||||
|
------
|
||||||
|
* Writers must not send data out-of-order
|
||||||
|
* Writers must include in-line QoS values if requested by a Reader
|
||||||
|
* Writers must send periodic HEARTBEAT Messages (reliable only)
|
||||||
|
* Writers must eventually respond to a negative acknowledgment (reliable only)
|
||||||
|
* Sending Heartbeats and Gaps with Writer Group Information (Writer belonging to a Group)
|
||||||
|
|
||||||
|
READER
|
||||||
|
------
|
||||||
|
A best-effort Reader is completely passive as it only receives data and does not send messages itself.
|
||||||
|
Therefore, the requirements below only apply to reliable Readers.
|
||||||
|
* Readers must respond eventually after receiving a HEARTBEAT with final flag not set
|
||||||
|
* Readers must respond eventually after receiving a HEARTBEAT that indicates a sample is missing
|
||||||
|
* Once acknowledged, always acknowledged
|
||||||
|
* Readers can only send an ACKNACK Message in response to a HEARTBEAT Message
|
||||||
|
|
||||||
|
RELIABILITY
|
||||||
|
===========
|
||||||
|
* Best Effort Writer can only be matched with Best Effort Reader
|
||||||
|
* Stateless Reader can only be Best Effort (maintains absolutely no state, does not handle duplicate and out-of-order changes)
|
||||||
|
|
||||||
|
STATELESS WRITER
|
||||||
|
================
|
||||||
|
Note that the processing of this message uses the reply locators in the RTPS Receiver.
|
||||||
|
This is the only source of information for the StatelessWriter to determine where to send the reply to.
|
||||||
|
Proper functioning of the protocol requires that the RTPS Reader inserts an InfoReply Submessage ahead of the AckNack such that these fields are properly set.
|
||||||
|
|
||||||
|
Writer Liveness Protocol
|
||||||
|
========================
|
||||||
|
ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER
|
||||||
|
ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER
|
||||||
|
|
||||||
|
OPTIONAL 8.4.14
|
||||||
|
===============
|
||||||
|
Optional features may not be supported by all RTPS implementations.
|
||||||
|
|
||||||
|
* LARGE DATA (Fragmented Data)
|
||||||
|
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
ENTITYID_UKNOWN also for Built-In?
|
||||||
|
Ignore Participant/Topic/Publication/Subscription (handle argument of Sampleinfo)
|
||||||
|
|
||||||
|
ENDIANNESS
|
||||||
|
==========
|
||||||
|
You have to see what datatypes PSM maps to each element.
|
||||||
|
If the datatype is bigger than a byte, byte swaping has to occur.
|
||||||
|
The elements of an array are in order (but the elements themselves may need to be swapped if bigger than a Byte)
|
||||||
|
|
||||||
|
ENDPOINT FIFO PACKET FORMAT
|
||||||
|
===========================
|
||||||
|
|
||||||
|
0...2...........8...............16..............24..............32
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| LENTGH |
|
||||||
|
+---------------+---------------+---------------+---------------+
|
||||||
|
| OPCODE | FLAGS | UDP_PORT |
|
||||||
|
+---------------+---------------+---------------+---------------+
|
||||||
|
| IPv4_ADDR |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| ENTITYID |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
+ Sequence Number [only for DATA Submessage] +
|
||||||
|
| |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
~ PAYLOAD (SUBMESSAGE CONTENT) ~
|
||||||
|
| |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
|
||||||
|
ENDPOINT_ID
|
||||||
|
===========
|
||||||
|
|
||||||
|
MSB...........LSB
|
||||||
|
READERS...WRITERS
|
||||||
76
src/addsub.vhd
Normal file
76
src/addsub.vhd
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
Library UNISIM;
|
||||||
|
use UNISIM.vcomponents.all;
|
||||||
|
|
||||||
|
Library UNIMACRO;
|
||||||
|
use UNIMACRO.vcomponents.all;
|
||||||
|
|
||||||
|
-- Add/Sub
|
||||||
|
-- This entity adds or subtracts inputs 'A' and 'B', depending on 'mode' (1 = add, 0 = sub).
|
||||||
|
-- If 'cap' is high, on Overfolw/Underflow conditions the result is capped at max/min value.
|
||||||
|
|
||||||
|
entity addsub is
|
||||||
|
generic (
|
||||||
|
PIPELINE_STAGES : integer := 1;
|
||||||
|
DATA_WIDTH : integer := 16
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
reset : in std_logic;
|
||||||
|
mode : in std_logic;
|
||||||
|
cap : in std_logic;
|
||||||
|
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
RES : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture arch of addsub is
|
||||||
|
|
||||||
|
--*****SIGNAl DECLARATION
|
||||||
|
signal result : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal carry : std_logic := '0';
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
ADDSUB_MACRO_inst : ADDSUB_MACRO
|
||||||
|
generic map (
|
||||||
|
DEVICE => "7SERIES", -- Target Device: "VIRTEX5", "7SERIES", "SPARTAN6"
|
||||||
|
LATENCY => PIPELINE_STAGES, -- Desired clock cycle latency, 0-2
|
||||||
|
WIDTH => DATA_WIDTH -- Input / Output bus width, 1-48
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
CARRYOUT => open, -- 1-bit carry-out output signal
|
||||||
|
RESULT => result, -- Add/sub result output, width defined by WIDTH generic
|
||||||
|
A => A, -- Input A bus, width defined by WIDTH generic
|
||||||
|
ADD_SUB => mode, -- 1-bit add/sub input, high selects add, low selects subtract
|
||||||
|
B => B, -- Input B bus, width defined by WIDTH generic
|
||||||
|
CARRYIN => '0', -- 1-bit carry-in input
|
||||||
|
CE => '1', -- 1-bit clock enable input
|
||||||
|
CLK => clk, -- 1-bit clock input
|
||||||
|
RST => reset -- 1-bit active high synchronous reset
|
||||||
|
);
|
||||||
|
|
||||||
|
clamp : process(all)
|
||||||
|
begin
|
||||||
|
--DEFAULT VALUE
|
||||||
|
RES <= result;
|
||||||
|
|
||||||
|
--Overflow/Underflow
|
||||||
|
if(carry = '1' and cap = '1') then
|
||||||
|
--ADD
|
||||||
|
if(mode = '1') then
|
||||||
|
--CAP AT MAX VALUE
|
||||||
|
RES <= (others => '1');
|
||||||
|
--SUB
|
||||||
|
else
|
||||||
|
--CAP AT ZERO
|
||||||
|
RES <= (others => '0');
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
47
src/checksum.vhd
Normal file
47
src/checksum.vhd
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
|
||||||
|
entity addsub is
|
||||||
|
generic (
|
||||||
|
INPUT_WIDTH : integer := 32;
|
||||||
|
OUTPUT_WIDTH : integer := 16
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
reset : in std_logic;
|
||||||
|
op : in std_logic_vector(1 downto 0);
|
||||||
|
input : in std_logic_vector(INPUT_WIDTH-1 downto 0);
|
||||||
|
output : out std_logic_vector(OUTPUT_WIDTH-1 downto 0);
|
||||||
|
done : out std_logic
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture arch of addsub is
|
||||||
|
|
||||||
|
--*****COMPONENT DECLARATION*****
|
||||||
|
entity addsub is
|
||||||
|
generic (
|
||||||
|
PIPELINE_STAGES : integer := 1;
|
||||||
|
DATA_WIDTH : integer := 32
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
reset : in std_logic;
|
||||||
|
cin : in std_logic;
|
||||||
|
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
RES : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
cout : out std_logic
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
--*****SIGNAl DECLARATION
|
||||||
|
signal result : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal carry : std_logic := '0';
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
|
||||||
|
end architecture;
|
||||||
@ -5,26 +5,76 @@ use ieee.numeric_std.all;
|
|||||||
use work.ip_package.all;
|
use work.ip_package.all;
|
||||||
use work.math_pkg.all;
|
use work.math_pkg.all;
|
||||||
|
|
||||||
entity ipv4_in is
|
-- IPv4 Handler
|
||||||
|
-- This entity parses IPv4 packets read from the input FIFO, and extracts the underlying Protocol (Payload)
|
||||||
|
-- to the respective output FIFO together with the Src and Dest Addresses.
|
||||||
|
|
||||||
|
-- The input FIFO has to be a 32-bit wide FWFT (First Word Fall Through) FIFO. The IPv4 packet has to be
|
||||||
|
-- 32-bit word aligned (padded with zeroes in the end to the closest 32-bit boundary), and the first word
|
||||||
|
-- before the actual packet has to be the length of the following IPv4 packet (in 32-bit words + padding).
|
||||||
|
-- This is necessary to recover from spurious packets.
|
||||||
|
-- ex.
|
||||||
|
-- 31 0
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | LENGTH=4 |
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | IPv4 Packet |
|
||||||
|
-- + +
|
||||||
|
-- | |
|
||||||
|
-- + +
|
||||||
|
-- | |
|
||||||
|
-- + +--------------+
|
||||||
|
-- | | PADDING |
|
||||||
|
-- +---------------+--------------+
|
||||||
|
|
||||||
|
-- The output FIFO distribution is controlled by the 'LAYER3_PROTOCOLS' constant in the 'ip_package' package.
|
||||||
|
-- The array position of the protocol version number is also the id of the output FIFO where this protocol
|
||||||
|
-- is sent to. First word on the output FIFO is the Source address, second the Destination Address, third
|
||||||
|
-- the payload length (in 32-bit words + padding), followed by the actual packet.
|
||||||
|
-- ex.
|
||||||
|
-- 31 0
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | Source Address |
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | Destination Address |
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | LENGTH=4 |
|
||||||
|
-- +------------------------------+
|
||||||
|
-- | UDP Packet |
|
||||||
|
-- + +
|
||||||
|
-- | |
|
||||||
|
-- | +
|
||||||
|
-- | |
|
||||||
|
-- + +--------------+
|
||||||
|
-- | | PADDING |
|
||||||
|
-- +---------------+--------------+
|
||||||
|
|
||||||
|
-- This Entity features 2 architecture implementations.
|
||||||
|
-- The 'no_frag' implementation does not support fragmentation and just drops fragmented packets. This needs the least amount of resources
|
||||||
|
-- The 'with_frag' implementation supports fragmentation as stated in RFC 791 (fragments of any size received in any order with auto adjusted
|
||||||
|
-- timeout according to transmitted TTL). The re-assembly needs considerable more resources for packet buffering and state holding.
|
||||||
|
-- The generics allow tuning of the supported packet sizes and used resources.
|
||||||
|
|
||||||
|
entity ipv4_in_handler is
|
||||||
generic(
|
generic(
|
||||||
CLK_FREQ : integer := 20000000;
|
CLK_FREQ : integer := 20000000; -- Frequency of input clock in Hz
|
||||||
MAX_FRAG_SIZE : integer := 1600;
|
MAX_FRAG_SIZE : integer := 1600; -- Maximum re-assembled IP packet size. If a re-assembled packet exceeds this threshold it is dropped. (Does not limit the size of received non-fragmented packets)
|
||||||
MAX_PARALLEL_FRAG : integer := 1;
|
MAX_PARALLEL_FRAG : integer := 1; -- Maximum number of parallel running re-assemble procedures. If a fragment of a new Ip packet is received, while 'MAX_PARALLEL_FRAG' packets are already in the re-assembly procedure, it is dropped.
|
||||||
DEFAULT_FRAG_TIMEOUT: integer := 5
|
DEFAULT_FRAG_TIMEOUT: integer := 5 -- Default timeout in seconds until which the re-assembly procedure of an IP packet has to be completed before being dropped to fre up resources.
|
||||||
);
|
);
|
||||||
port (
|
port (
|
||||||
clk : in std_logic;
|
clk : in std_logic; -- Input Clock
|
||||||
reset : in std_logic;
|
reset : in std_logic; -- Synchronous Reset
|
||||||
empty : in std_logic;
|
empty : in std_logic; -- Input FIFO empty flag
|
||||||
data_in : in std_logic_vector(31 downto 0);
|
rd : out std_logic; -- Input FIFO read signal
|
||||||
rd : out std_logic;
|
data_in : in std_logic_vector(31 downto 0); -- Input FIFO data signal
|
||||||
wr : out std_logic_vector(LAYER3_PROTOCOL_NUM-1 downto 0);
|
full : in std_logic_vector(LAYER3_PROTOCOL_NUM-1 downto 0); -- Output FIFO full flag
|
||||||
full : in std_logic_vector(LAYER3_PROTOCOL_NUM-1 downto 0);
|
wr : out std_logic_vector(LAYER3_PROTOCOL_NUM-1 downto 0); -- Output FIFO write signal
|
||||||
data_out: out IP_OUTPUT_TYPE
|
data_out: out IP_OUTPUT_TYPE -- Output FIFO data signal
|
||||||
);
|
);
|
||||||
end entity;
|
end entity;
|
||||||
|
|
||||||
architecture arch of ipv4_in is
|
architecture with_frag of ipv4_in_handler is
|
||||||
|
|
||||||
--*****COMPONENT DECLARATION*****
|
--*****COMPONENT DECLARATION*****
|
||||||
-- The RAM is used for reassembly of ip fragments.
|
-- The RAM is used for reassembly of ip fragments.
|
||||||
@ -60,15 +110,15 @@ architecture arch of ipv4_in is
|
|||||||
-- NOTE: The MAX_PARALLEL_FRAG array position is not mapped to a buffer, but is used for comparison purposes
|
-- NOTE: The MAX_PARALLEL_FRAG array position is not mapped to a buffer, but is used for comparison purposes
|
||||||
type BUFFER_ID_ARRAY is array (MAX_PARALLEL_FRAG downto 0) of std_logic_vector(87 downto 0);
|
type BUFFER_ID_ARRAY is array (MAX_PARALLEL_FRAG downto 0) of std_logic_vector(87 downto 0);
|
||||||
-- Array of bitmaps used to identify received fragment words.
|
-- Array of bitmaps used to identify received fragment words.
|
||||||
type BUFFER_BITMAP_ARRAY is array (max(MAX_PARALLEL_FRAG-1,0) downto 0) of std_logic_vector((MAX_FRAG_SIZE/4)-1 downto 0);
|
type BUFFER_BITMAP_ARRAY is array (MAX_PARALLEL_FRAG-1 downto 0) of std_logic_vector((MAX_FRAG_SIZE/4)-1 downto 0);
|
||||||
-- Array of buffer timers used for timeout checking
|
-- Array of buffer timers used for timeout checking
|
||||||
type BUFFER_TIMER_ARRAY is array (max(MAX_PARALLEL_FRAG-1,0) downto 0) of unsigned(7 downto 0);
|
type BUFFER_TIMER_ARRAY is array (MAX_PARALLEL_FRAG-1 downto 0) of unsigned(7 downto 0);
|
||||||
-- Array of address offsets for the RAM. Used as constant
|
-- Array of address offsets for the RAM. Used as constant
|
||||||
type BUFFER_ADDR_OFFSET_TYPE is array (max(MAX_PARALLEL_FRAG-1,0) downto 0) of unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
type BUFFER_ADDR_OFFSET_TYPE is array (MAX_PARALLEL_FRAG-1 downto 0) of unsigned(RAM_ADDR_WIDTH-1 downto 0);
|
||||||
-- Array of packet sizes in buffers
|
-- Array of packet sizes in buffers
|
||||||
type FRAG_SIZE_ARRAY is array (max(MAX_PARALLEL_FRAG-1,0) downto 0) of std_logic_vector(13 downto 0);
|
type FRAG_SIZE_ARRAY is array (MAX_PARALLEL_FRAG-1 downto 0) of std_logic_vector(13 downto 0);
|
||||||
-- Array of 32-bit buffer word counters. Used for counting new received fragments and determining if the packet is completely re-assebled
|
-- Array of 32-bit buffer word counters. Used for counting new received fragments and determining if the packet is completely re-assebled
|
||||||
type BUFFER_WORD_COUNTER_ARRAY is array (max(MAX_PARALLEL_FRAG-1,0) downto 0) of integer range 0 to (MAX_FRAG_SIZE/4);
|
type BUFFER_WORD_COUNTER_ARRAY is array (MAX_PARALLEL_FRAG-1 downto 0) of integer range 0 to (MAX_FRAG_SIZE/4);
|
||||||
|
|
||||||
|
|
||||||
--*****SIGNAL DECLARATION*****
|
--*****SIGNAL DECLARATION*****
|
||||||
@ -113,9 +163,9 @@ architecture arch of ipv4_in is
|
|||||||
-- Signal used to reset buffer timers
|
-- Signal used to reset buffer timers
|
||||||
signal reset_buffer_timer : std_logic := '0';
|
signal reset_buffer_timer : std_logic := '0';
|
||||||
-- ID of buffer timer to be reset
|
-- ID of buffer timer to be reset
|
||||||
signal reset_buffer_timer_id : integer range 0 to max(MAX_PARALLEL_FRAG-1,0) := 0;
|
signal reset_buffer_timer_id : integer range 0 to MAX_PARALLEL_FRAG-1 := 0;
|
||||||
-- ID of current buffer
|
-- ID of current buffer
|
||||||
signal cur_buffer_id, cur_buffer_id_next : integer range 0 to max(MAX_PARALLEL_FRAG-1,0) := 0;
|
signal cur_buffer_id, cur_buffer_id_next : integer range 0 to MAX_PARALLEL_FRAG-1 := 0;
|
||||||
-- Signal used to reset the word counter
|
-- Signal used to reset the word counter
|
||||||
signal reset_read_cnt : std_logic;
|
signal reset_read_cnt : std_logic;
|
||||||
-- Intermediate output signal
|
-- Intermediate output signal
|
||||||
@ -191,19 +241,19 @@ architecture arch of ipv4_in is
|
|||||||
begin
|
begin
|
||||||
|
|
||||||
-- Generic Assertions
|
-- Generic Assertions
|
||||||
assert (MAX_PARALLEL_FRAG >= 0) report "MAX_PARALLEL_FRAG has to be positive" severity failure;
|
assert (MAX_PARALLEL_FRAG > 0) report "MAX_PARALLEL_FRAG has to be greater than 0" severity failure;
|
||||||
assert (MAX_FRAG_SIZE mod 4 = 0) report "MAX_FRAG_SIZE has to be multiple of 4" severity failure;
|
assert (MAX_FRAG_SIZE mod 4 = 0) report "MAX_FRAG_SIZE has to be multiple of 4" severity failure;
|
||||||
assert (MAX_FRAG_SIZE <= 65516) report "MAX_FRAG_SIZE has to be smaller or equal to 65516" severity error;
|
assert (MAX_FRAG_SIZE <= 65516) report "MAX_FRAG_SIZE has to be smaller or equal to 65516" severity error;
|
||||||
assert (DEFAULT_FRAG_TIMEOUT <= 255) report "DEFAULT_FRAG_TIMEOUT has to be smaller or equal to 255" severity error;
|
assert (DEFAULT_FRAG_TIMEOUT <= 255) report "DEFAULT_FRAG_TIMEOUT has to be smaller or equal to 255" severity error;
|
||||||
|
|
||||||
-- Generic Dependant Constant
|
-- Generic Dependant Constant
|
||||||
-- Does not change its value after generation
|
-- Does not change its value after generation
|
||||||
|
-- TODO: Change to constant with function initialization
|
||||||
const_gen : for i in 0 to buffer_addr_offset'length-1 generate
|
const_gen : for i in 0 to buffer_addr_offset'length-1 generate
|
||||||
buffer_addr_offset(i) <= to_unsigned(MAX_FRAG_SIZE*i,buffer_addr_offset(i)'length);
|
buffer_addr_offset(i) <= to_unsigned(MAX_FRAG_SIZE*i,buffer_addr_offset(i)'length);
|
||||||
end generate;
|
end generate;
|
||||||
|
|
||||||
--*****COMPONENT INSTANTIATION*****
|
--*****COMPONENT INSTANTIATION*****
|
||||||
buffer_gen : if (MAX_PARALLEL_FRAG /= 0) generate
|
|
||||||
ram_inst : single_port_ram
|
ram_inst : single_port_ram
|
||||||
generic map (
|
generic map (
|
||||||
ADDR_WIDTH => RAM_ADDR_WIDTH,
|
ADDR_WIDTH => RAM_ADDR_WIDTH,
|
||||||
@ -218,10 +268,10 @@ begin
|
|||||||
wr_data => buffer_wr_data,
|
wr_data => buffer_wr_data,
|
||||||
rd_data => buffer_rd_data
|
rd_data => buffer_rd_data
|
||||||
);
|
);
|
||||||
end generate;
|
|
||||||
|
|
||||||
rd <= rd_sig;
|
rd <= rd_sig;
|
||||||
|
|
||||||
|
-- TODO: Make only wr signal conditional and connect ALL output FIFOs to the Signal
|
||||||
-- This process is responsible for MUXing the correct signal to the correct output FIFO
|
-- This process is responsible for MUXing the correct signal to the correct output FIFO
|
||||||
output_prc : process(all)
|
output_prc : process(all)
|
||||||
begin
|
begin
|
||||||
@ -294,7 +344,7 @@ begin
|
|||||||
-- Reset packet Byte Counter
|
-- Reset packet Byte Counter
|
||||||
reset_read_cnt <= '1';
|
reset_read_cnt <= '1';
|
||||||
-- Check Buffer timers for timeouts
|
-- Check Buffer timers for timeouts
|
||||||
for i in 0 to max(MAX_PARALLEL_FRAG-1,0) loop
|
for i in 0 to MAX_PARALLEL_FRAG-1 loop
|
||||||
-- If timeout reached
|
-- If timeout reached
|
||||||
if(buffer_timer(i) >= max_buffer_timer(i)) then
|
if(buffer_timer(i) >= max_buffer_timer(i)) then
|
||||||
-- Free Buffer ID
|
-- Free Buffer ID
|
||||||
@ -333,11 +383,6 @@ begin
|
|||||||
if (ip_MF_flag = '0' and ip_frag_offset = (ip_frag_offset'reverse_range => '0')) then
|
if (ip_MF_flag = '0' and ip_frag_offset = (ip_frag_offset'reverse_range => '0')) then
|
||||||
stage_next <= IPv4_HEADER_3;
|
stage_next <= IPv4_HEADER_3;
|
||||||
-- IP Fragmentation
|
-- IP Fragmentation
|
||||||
else
|
|
||||||
-- Fragmentation Reassembly disabled, skip packet
|
|
||||||
if (MAX_PARALLEL_FRAG = 0) then
|
|
||||||
stage_next <= SKIP_PACKET;
|
|
||||||
-- Store Fragment relevant data
|
|
||||||
else
|
else
|
||||||
is_fragment_next <= '1';
|
is_fragment_next <= '1';
|
||||||
frag_offset_next <= unsigned(std_logic_vector'(ip_frag_offset & "0")); --'std_logic_vector needed to avoid "Ambiguous type in infix expression"
|
frag_offset_next <= unsigned(std_logic_vector'(ip_frag_offset & "0")); --'std_logic_vector needed to avoid "Ambiguous type in infix expression"
|
||||||
@ -351,7 +396,6 @@ begin
|
|||||||
stage_next <= IPv4_HEADER_3;
|
stage_next <= IPv4_HEADER_3;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
|
||||||
-- Third IPv4 Header word (Fields: TTL, Protocol, Checksum)
|
-- Third IPv4 Header word (Fields: TTL, Protocol, Checksum)
|
||||||
when IPv4_HEADER_3 =>
|
when IPv4_HEADER_3 =>
|
||||||
if (empty = '0') then
|
if (empty = '0') then
|
||||||
@ -642,7 +686,7 @@ begin
|
|||||||
buffer_timer(reset_buffer_timer_id) <= (others => '0');
|
buffer_timer(reset_buffer_timer_id) <= (others => '0');
|
||||||
else
|
else
|
||||||
-- Increment Timers
|
-- Increment Timers
|
||||||
for i in 0 to max(MAX_PARALLEL_FRAG-1,0) loop
|
for i in 0 to MAX_PARALLEL_FRAG-1 loop
|
||||||
-- Timers stay at highest value until reset
|
-- Timers stay at highest value until reset
|
||||||
if(buffer_timer(i) /= (buffer_timer(i)'reverse_range => '1')) then
|
if(buffer_timer(i) /= (buffer_timer(i)'reverse_range => '1')) then
|
||||||
buffer_timer(i) <= buffer_timer(i) + 1;
|
buffer_timer(i) <= buffer_timer(i) + 1;
|
||||||
@ -727,3 +771,266 @@ begin
|
|||||||
end process;
|
end process;
|
||||||
|
|
||||||
end architecture;
|
end architecture;
|
||||||
|
|
||||||
|
architecture no_frag of ipv4_in_handler is
|
||||||
|
|
||||||
|
|
||||||
|
--*****TYPE DECLARATION*****
|
||||||
|
-- FSM states. Explained delow in detail
|
||||||
|
type PARSER_STAGE_TYPE is (IPv4_INIT, IPv4_HEADER_1, IPv4_HEADER_2, IPv4_HEADER_3, IPv4_HEADER_4,
|
||||||
|
IPv4_HEADER_5, IPv4_PAYLOAD_LENGTH, IPv4_PAYLOAD, SKIP_HEADER, SKIP_PACKET);
|
||||||
|
|
||||||
|
--*****SIGNAL DECLARATION*****
|
||||||
|
-- FSM state
|
||||||
|
signal stage, stage_next : PARSER_STAGE_TYPE := IPv4_INIT;
|
||||||
|
-- 32-bit aligned total packet length
|
||||||
|
signal packet_length, packet_length_next : unsigned(13 downto 0) := (others => '0');
|
||||||
|
-- 32-bit aligned header length
|
||||||
|
signal header_length, header_length_next : unsigned(3 downto 0) := (others => '0');
|
||||||
|
-- 32-bit word counter (Counts words read from input fifo)
|
||||||
|
signal read_cnt : unsigned(13 downto 0) := (others => '0');
|
||||||
|
-- Intermediate input read signal. (Read from output port not allowed)
|
||||||
|
signal rd_sig : std_logic := '0';
|
||||||
|
-- ID of current output fifo (Used to MUX output FIFOs)
|
||||||
|
signal output_id, output_id_next : integer range 0 to LAYER3_PROTOCOL_NUM-1 := 0;
|
||||||
|
-- Signal used to reset the word counter
|
||||||
|
signal reset_read_cnt : std_logic;
|
||||||
|
-- Intermediate output signal
|
||||||
|
signal data_out_sig : std_logic_vector(31 downto 0);
|
||||||
|
-- Intermediate output signal, and its 1 clk cycle delayed variant
|
||||||
|
signal wr_sig : std_logic;
|
||||||
|
|
||||||
|
--*****ALIAS DEFINATION*****
|
||||||
|
--IPv4 HEADER
|
||||||
|
alias ip_version : std_logic_vector(3 downto 0) is data_in(31 downto 28);
|
||||||
|
alias ip_ihl : std_logic_vector(3 downto 0) is data_in(27 downto 24);
|
||||||
|
alias ip_dscp : std_logic_vector(5 downto 0) is data_in(23 downto 18);
|
||||||
|
alias ip_ecn : std_logic_vector(1 downto 0) is data_in(17 downto 16);
|
||||||
|
alias ip_length : std_logic_vector(15 downto 0) is data_in(15 downto 0);
|
||||||
|
alias ip_id : std_logic_vector(15 downto 0) is data_in(31 downto 16);
|
||||||
|
alias ip_DF_flag : std_logic is data_in(14);
|
||||||
|
alias ip_MF_flag : std_logic is data_in(13);
|
||||||
|
alias ip_frag_offset: std_logic_vector(12 downto 0) is data_in(12 downto 0);
|
||||||
|
alias ip_ttl : std_logic_vector(7 downto 0) is data_in(31 downto 24);
|
||||||
|
alias ip_protocol : std_logic_vector(7 downto 0) is data_in(23 downto 16);
|
||||||
|
alias ip_checksum : std_logic_vector(15 downto 0) is data_in(15 downto 0);
|
||||||
|
|
||||||
|
--*****FUNCTION DECLARATION*****
|
||||||
|
|
||||||
|
-- Truncates the lower 2 bits of the input, and if they are not equal zero, adds one to the result.
|
||||||
|
-- This is used to round the byte length to 32-bit word length.
|
||||||
|
function normalize_length (len : std_logic_vector(15 downto 0)) return std_logic_vector is
|
||||||
|
variable tmp : std_logic_vector(13 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
tmp := len(15 downto 2);
|
||||||
|
if(len(1 downto 0) /= "00") then
|
||||||
|
tmp := std_logic_vector(unsigned(tmp) + to_unsigned(1, tmp'length));
|
||||||
|
end if;
|
||||||
|
return tmp;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
rd <= rd_sig;
|
||||||
|
|
||||||
|
-- This process is responsible for MUXing the correct signal to the correct output FIFO
|
||||||
|
output_prc : process(all)
|
||||||
|
begin
|
||||||
|
data_out(output_id) <= data_out_sig;
|
||||||
|
wr(output_id) <= wr_sig;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Main State Machine
|
||||||
|
-- STATE DESCRIPSION
|
||||||
|
-- IPv4_INIT Initial and idle state. Responsible for checking the buffer timers, and reading the packet length from the input FIFO
|
||||||
|
-- IPv4_HEADER_1 Parsing first word of IPv4 HEADER
|
||||||
|
-- IPv4_HEADER_2 Parsing second word of IPv4 HEADER
|
||||||
|
-- IPv4_HEADER_3 Parsing third word of IPv4 HEADER
|
||||||
|
-- IPv4_HEADER_4 Parsing fourth word of IPv4 HEADER and writing SRC Addr to output FIFO (if not a fragment)
|
||||||
|
-- IPv4_HEADER_5 Parsing fifth word of IPv4 HEADER and writing DEST Addr to output FIFO (if not a fragment)
|
||||||
|
-- IPv4_PAYLOAD_LENGTH Writing packet(payload) length to output FIFO
|
||||||
|
-- IPv4_PAYLOAD Writing of packet(payload) from input FIFO to output FIFO
|
||||||
|
-- SKIP_HEADER Skip to beginning of Payload in input FIFO
|
||||||
|
-- SKIP_PACKET Skip to end of packet in input FIFO
|
||||||
|
parser_prc : process(all)
|
||||||
|
variable tmp : integer range 0 to max(MAX_PARALLEL_FRAG,LAYER3_PROTOCOL_NUM) := 0;
|
||||||
|
begin
|
||||||
|
--DEFAULT Registered
|
||||||
|
stage_next <= stage;
|
||||||
|
packet_length_next <= packet_length;
|
||||||
|
header_length_next <= header_length;
|
||||||
|
output_id_next <= output_id;
|
||||||
|
-- DEFAULT Unregistered
|
||||||
|
rd_sig <= '0';
|
||||||
|
wr_sig <= '0';
|
||||||
|
data_out_sig <= (others => '0');
|
||||||
|
reset_read_cnt <= '0';
|
||||||
|
|
||||||
|
case(stage) is
|
||||||
|
-- Initial/Idle State
|
||||||
|
when IPv4_INIT =>
|
||||||
|
-- Reset packet Byte Counter
|
||||||
|
reset_read_cnt <= '1';
|
||||||
|
-- Read Packet Length from input
|
||||||
|
if (empty = '0') then
|
||||||
|
packet_length_next <= unsigned(data_in(13 downto 0));
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Begin Processing
|
||||||
|
stage_next <= IPv4_HEADER_1;
|
||||||
|
end if;
|
||||||
|
-- First IPv4 Header word (Fields: Version, IHL, DSCP, ECN, Total Length)
|
||||||
|
when IPv4_HEADER_1 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Wrong IP Version or Packet Length missmatch, skip packet
|
||||||
|
if (ip_version /= "0100" or normalize_length(ip_length) /= std_logic_vector(packet_length)) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
-- Store data and continue Parsing
|
||||||
|
else
|
||||||
|
header_length_next <= unsigned(ip_ihl);
|
||||||
|
stage_next <= IPv4_HEADER_2;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Second IPv4 Header word (Fields: Identification, Flags, Fragment Offset)
|
||||||
|
when IPv4_HEADER_2 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- No fragmentation, continue parsing normaly
|
||||||
|
if (ip_MF_flag = '0' and ip_frag_offset = (ip_frag_offset'reverse_range => '0')) then
|
||||||
|
stage_next <= IPv4_HEADER_3;
|
||||||
|
-- IP Fragmentation
|
||||||
|
else
|
||||||
|
-- Fragmentation Reassembly disabled, skip packet
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Third IPv4 Header word (Fields: TTL, Protocol, Checksum)
|
||||||
|
when IPv4_HEADER_3 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Select Output according to Layer 3 Protocol
|
||||||
|
tmp := LAYER3_PROTOCOL_NUM;
|
||||||
|
for i in 0 to LAYER3_PROTOCOL_NUM-1 loop
|
||||||
|
if(ip_protocol = LAYER3_PROTOCOLS(i)) then
|
||||||
|
tmp := i;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
-- No Protocol match, skip packet
|
||||||
|
if (tmp = LAYER3_PROTOCOL_NUM) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
-- Protocol Match, continue parsing
|
||||||
|
else
|
||||||
|
output_id_next <= tmp;
|
||||||
|
stage_next <= IPv4_HEADER_4;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Fourth IPv4 Header word (Fields: Src Address)
|
||||||
|
when IPv4_HEADER_4 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
-- Write Src Address to Output FIFO
|
||||||
|
if (full(output_id) = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
wr_sig <= '1';
|
||||||
|
data_out_sig <= data_in;
|
||||||
|
-- Continue parsing
|
||||||
|
stage_next <= IPv4_HEADER_5;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Fourth IPv4 Header word (Fields: Dest Address)
|
||||||
|
when IPv4_HEADER_5 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
-- Write Dst Address to Output FIFO
|
||||||
|
if (full(output_id) = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
wr_sig <= '1';
|
||||||
|
data_out_sig <= data_in;
|
||||||
|
-- Check Header Size
|
||||||
|
if (read_cnt /= ("0000000000" & header_length)) then
|
||||||
|
-- If Header has "Options", skip to Payload
|
||||||
|
stage_next <= SKIP_HEADER;
|
||||||
|
else
|
||||||
|
-- Payload Processing
|
||||||
|
stage_next <= IPv4_PAYLOAD_LENGTH;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Push Payload Length
|
||||||
|
when IPv4_PAYLOAD_LENGTH =>
|
||||||
|
-- Write Payload Length to Output FIFO
|
||||||
|
if (full(output_id) = '0') then
|
||||||
|
wr_sig <= '1';
|
||||||
|
data_out_sig(13 downto 0) <= std_logic_vector(packet_length - ("0000000000" & header_length));
|
||||||
|
stage_next <= IPv4_PAYLOAD;
|
||||||
|
end if;
|
||||||
|
-- Push Payload
|
||||||
|
when IPv4_PAYLOAD =>
|
||||||
|
-- Write to Output FIFO
|
||||||
|
if (empty = '0' and full(output_id) = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
wr_sig <= '1';
|
||||||
|
data_out_sig <= data_in;
|
||||||
|
-- End Of Packet
|
||||||
|
if (read_cnt = packet_length) then
|
||||||
|
-- Done, process next packet
|
||||||
|
stage_next <= IPv4_INIT;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Skip until beginning of payload
|
||||||
|
when SKIP_HEADER =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- End of Header
|
||||||
|
if(read_cnt = header_length) then
|
||||||
|
-- Payload Processing
|
||||||
|
stage_next <= IPv4_PAYLOAD;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- Skip entire packet
|
||||||
|
when SKIP_PACKET =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- End of Packet
|
||||||
|
if(read_cnt = packet_length) then
|
||||||
|
-- Continue parsing next packet
|
||||||
|
stage_next <= IPv4_INIT;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when others =>
|
||||||
|
null;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Process responsible for counting read words
|
||||||
|
-- This process uses the actual RAM and FIFO read signals to determine reads
|
||||||
|
word_counter_prc : process(clk, reset)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
-- Reset Read counter
|
||||||
|
if (reset = '1' or reset_read_cnt = '1') then
|
||||||
|
read_cnt <= to_unsigned(1, read_cnt'length);
|
||||||
|
-- Increment read counter each time rd is high
|
||||||
|
elsif (rd_sig = '1') then
|
||||||
|
read_cnt <= read_cnt + to_unsigned(1, read_cnt'length);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- State Machine Sync Process (Registers)
|
||||||
|
sync : process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if (reset = '1') then
|
||||||
|
stage <= IPv4_INIT;
|
||||||
|
packet_length <= (others => '0');
|
||||||
|
header_length <= (others => '0');
|
||||||
|
output_id <= 0;
|
||||||
|
else
|
||||||
|
stage <= stage_next;
|
||||||
|
packet_length <= packet_length_next;
|
||||||
|
header_length <= header_length_next;
|
||||||
|
output_id <= output_id_next;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
1030
src/rtps_handler.vhd
Normal file
1030
src/rtps_handler.vhd
Normal file
File diff suppressed because it is too large
Load Diff
516
src/rtps_handler.vhd.BAK
Normal file
516
src/rtps_handler.vhd.BAK
Normal file
@ -0,0 +1,516 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
use work.math_pkg.all;
|
||||||
|
|
||||||
|
entity rtps_handler is
|
||||||
|
generic(
|
||||||
|
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic; -- Input Clock
|
||||||
|
reset : in std_logic; -- Synchronous Reset
|
||||||
|
empty : in std_logic; -- Input FIFO empty flag
|
||||||
|
rd : out std_logic; -- Input FIFO read signal
|
||||||
|
data_in : in std_logic_vector(31 downto 0); -- Input FIFO data signal
|
||||||
|
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture arch of rtps_handler is
|
||||||
|
|
||||||
|
--*****COMPOENENT DECLARATION******
|
||||||
|
entity adder is
|
||||||
|
generic (
|
||||||
|
PIPELINE_STAGES : integer := 1;
|
||||||
|
DATA_WIDTH : integer := 32
|
||||||
|
);
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
reset : in std_logic;
|
||||||
|
cin : in std_logic;
|
||||||
|
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
RES : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||||
|
cout : out std_logic
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
--*****CONSTANT DECLARATION*****
|
||||||
|
-- Minimum Packet Length to consider valid
|
||||||
|
-- 2 UDP Header 32-bit Words, 5 RTPS Header 32-bit Words
|
||||||
|
constant MIN_PACKET_LENGTH : integer := 7;
|
||||||
|
constant MAX_ENDPOINTS : integer := NUM_READERS+NUM_WRITERS;
|
||||||
|
|
||||||
|
|
||||||
|
--GUIDPREFIX(1 downto 0) <= VENDORID;
|
||||||
|
|
||||||
|
--*****TYPE DECLARATION*****
|
||||||
|
type STAGE_TYPE is (INIT, SRC_ADDR, DEST_ADDR, UDP_HEADER_1, UDP_HEADER_2, RTPS_HEADER_1,
|
||||||
|
RTPS_HEADER_2, RTPS_HEADER_3, RTPS_HEADER_4, SKIP_PACKET);
|
||||||
|
|
||||||
|
|
||||||
|
--*****SIGNAL DECLARATION*****
|
||||||
|
-- FSM state
|
||||||
|
signal stage, stage_next : PARSER_STAGE_TYPE := INIT;
|
||||||
|
-- Intermediate input read signal. (Read from output port not allowed)
|
||||||
|
signal rd_sig : std_logic := '0';
|
||||||
|
-- Signal used to reset the word counter
|
||||||
|
signal reset_read_cnt : std_logic;
|
||||||
|
-- 32-bit word counter (Counts words read from input fifo)
|
||||||
|
signal read_cnt : unsigned(13 downto 0) := (others => '0');
|
||||||
|
-- 32-bit aligned total packet length
|
||||||
|
signal packet_length, packet_length_next : unsigned(13 downto 0) := (others => '0');
|
||||||
|
signal sub_length, sub_length_next : unsigned(13 downto 0) := (others => '0');
|
||||||
|
signal align_sig, align_sig_next : std_logic_vector(23 downto 0) := (others => '0');
|
||||||
|
signal aligned_data_in : std_logic_vector(31 downto 0);
|
||||||
|
signal align_offset, align_offset_next : std_logic_vector(1 downto 0) := (others => '0');
|
||||||
|
signal offset_latch, offset_latch_next : std_logic_vector(1 downto 0) := (others => '0');
|
||||||
|
signal src_addr, src_addr_next : std_logic_vector(31 downto 0) := (others => '0');
|
||||||
|
signal src_port, src_port_next : std_logic_vector(15 downto 0) := (others => '0');
|
||||||
|
signal is_multicast, is_multicast_next : std_logic := '0';
|
||||||
|
signal is_metatraffic, is_metatraffic_next : std_logic := '0';
|
||||||
|
signal participant_id, participant_id_next : integer range 0 to NUM_DOMAIN-1 := 0;
|
||||||
|
signal flags, flags_next : std_logic_vector(7 downto 0) := (others => '0');
|
||||||
|
-- General purpose counter
|
||||||
|
signal cnt, cnt_next : integer := 0; --TODO: Range
|
||||||
|
-- Adder Signals
|
||||||
|
signal add_res, add_a, add_b : std_logic_vector(31 downto 0) := (others => '0');
|
||||||
|
signal add_cin, add_cout : std_logic := '0';
|
||||||
|
|
||||||
|
--*****ALIAS DEFINATION*****
|
||||||
|
-- UDP HEADER
|
||||||
|
alias udp_src_port : std_logic_vector(15 downto 0) is data_in(31 downto 16);
|
||||||
|
alias udp_dest_port : std_logic_vector(15 downto 0) is data_in(15 downto 0);
|
||||||
|
alias udp_length : std_logic_vector(15 downto 0) is data_in(31 downto 16);
|
||||||
|
alias udp_checksum : std_logic_vector(15 downto 0) is data_in(15 downto 0);
|
||||||
|
-- RTPS HEADER
|
||||||
|
alias rtps_version : std_logic_vector(15 downto 0) is data_in(31 downto 16);
|
||||||
|
alias rtps_vendorid : std_logic_vector(15 downto 0) is data_in(15 downto 0);
|
||||||
|
-- RTPS SUBMESSAGE HEADER
|
||||||
|
alias rtps_sub_id : std_logic_vector(7 downto 0) is aligned_data_in(31 downto 24);
|
||||||
|
alias rtps_sub_flags : std_logic_vector(7 downto 0) is aligned_data_in(23 downto 16);
|
||||||
|
alias rtps_sub_length : std_logic_vector(7 downto 0) is aligned_data_in(15 downto 0);
|
||||||
|
-- ACKNACK
|
||||||
|
alias rtps_acknack_final : std_logic is rtps_sub_flags(1);
|
||||||
|
-- MISC
|
||||||
|
|
||||||
|
--*****FUNCTION DECLARATION*****
|
||||||
|
|
||||||
|
-- Truncates the lower 2 bits of the input, and if they are not equal zero, adds one to the result.
|
||||||
|
-- This is used to round the byte length to 32-bit word length.
|
||||||
|
function normalize_length (len : std_logic_vector(15 downto 0)) return std_logic_vector is
|
||||||
|
variable tmp : std_logic_vector(13 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
tmp := len(15 downto 2);
|
||||||
|
if(len(1 downto 0) /= "00") then
|
||||||
|
tmp := std_logic_vector(unsigned(tmp) + to_unsigned(1, tmp'length));
|
||||||
|
end if;
|
||||||
|
return tmp;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Depending on the offset argument "off" returns a 32-bit slice from the 56-bit input signal
|
||||||
|
-- This is used to extract 32-bit aligned words from the input signal
|
||||||
|
function align_word ( off : std_logic_vector(1 downto 0),
|
||||||
|
input : std_logic_vector(56 downto 0)) return std_logic_vector is
|
||||||
|
variable ret : std_logic_vector(31 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
case(off) is
|
||||||
|
when "00" =>
|
||||||
|
ret := input(31 downto 0);
|
||||||
|
when "01" =>
|
||||||
|
ret := input(39 downto 8);
|
||||||
|
when "10" =>
|
||||||
|
ret := input(47 downto 16);
|
||||||
|
when "11" =>
|
||||||
|
ret := input(55 downto 24);
|
||||||
|
end case;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Compares argument 'ref' with every elemant of 'ar', and returns the index of the last match.
|
||||||
|
-- If no match is found, array length is returned.
|
||||||
|
function match_domain_id ( ref : std_logic_vector(UDP_PORT_WIDTH-1 downto 0),
|
||||||
|
ar : IPv4_PORT_TYPE) return integer is
|
||||||
|
variable id : integer := 0;
|
||||||
|
begin
|
||||||
|
id := ar'length(1);
|
||||||
|
for i in 0 to ar'length-1 loop
|
||||||
|
if(ref = ar(i)) then
|
||||||
|
id := i;
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
return id;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
-- Returns the 'data' argument either as is, or with reversed Byte order, depending on the
|
||||||
|
-- 'endianness' argument.
|
||||||
|
function endian_swap( endianness : std_logic,
|
||||||
|
data :std_logic_vector(31 downto 0)) return std_logic_vector is
|
||||||
|
variable ret : std_logic_vector(31 downto 0);
|
||||||
|
begin
|
||||||
|
-- Little Endian
|
||||||
|
if (endianness = '1') then
|
||||||
|
-- Reverse byte Order
|
||||||
|
for i in 0 to 3 loop
|
||||||
|
ret(i*8+8-1 downto i*8) := data((3-i)*8+8-1 downto (3-i)*8);
|
||||||
|
end loop;
|
||||||
|
-- Big Endian
|
||||||
|
else
|
||||||
|
ret := data;
|
||||||
|
end if;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
begin
|
||||||
|
|
||||||
|
rd <= rd_sig;
|
||||||
|
|
||||||
|
align_prc : process(all)
|
||||||
|
variable input : std_logic_vector(55 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
input := align_sig & data_in;
|
||||||
|
case(align_offset) is
|
||||||
|
when "00" =>
|
||||||
|
aligned_data_in <= input(31 downto 0);
|
||||||
|
when "01" =>
|
||||||
|
aligned_data_in <= input(39 downto 8);
|
||||||
|
when "10" =>
|
||||||
|
aligned_data_in <= input(47 downto 16);
|
||||||
|
when "11" =>
|
||||||
|
aligned_data_in <= input(55 downto 24);
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
checksum_adder : adder
|
||||||
|
generic map (
|
||||||
|
PIPELINE_STAGES => 1,
|
||||||
|
DATA_WIDTH => 32
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
reset => reset,
|
||||||
|
cin => add_cin,
|
||||||
|
A => add_a,
|
||||||
|
B => add_b,
|
||||||
|
RES => add_res,
|
||||||
|
cout => add_cout
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
parse_prc: process(all)
|
||||||
|
variable tmp : integer range 0 to MAX_ENDPOINTS := 0;
|
||||||
|
begin
|
||||||
|
--DEFAULT
|
||||||
|
stage_next <= stage;
|
||||||
|
reset_read_cnt <= '0';
|
||||||
|
add_a <= (others => '0');
|
||||||
|
add_b <= (others => '0');
|
||||||
|
add_cin <= '0';
|
||||||
|
cnt_next <= count;
|
||||||
|
align_offset_next <= align_offset;
|
||||||
|
align_sig_next <= align_sig;
|
||||||
|
packet_length_next <= packet_length;
|
||||||
|
sub_length_next <= sub_length;
|
||||||
|
offset_latch_next <= offset_latch;
|
||||||
|
src_addr_next <= src_addr;
|
||||||
|
is_multicast_next <= is_multicast;
|
||||||
|
src_port_next <= src_port;
|
||||||
|
is_metatraffic_next <= is_metatraffic;
|
||||||
|
participant_id_next <= participant_id;
|
||||||
|
flags_next <= flags;
|
||||||
|
|
||||||
|
case(stage) is
|
||||||
|
-- Initial/Idle State
|
||||||
|
-- Src Addr
|
||||||
|
when SRC_ADDR =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Latch Src Address
|
||||||
|
src_addr_next <= data_in;
|
||||||
|
-- Initiate Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
-- TODO: Reset Flags
|
||||||
|
is_multicast_next <= '0';
|
||||||
|
is_metatraffic_next <= '0';
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= DEST_ADDR;
|
||||||
|
end if;
|
||||||
|
-- Dest Addr
|
||||||
|
when DEST_ADDR =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Check Destination Address
|
||||||
|
if (data_in = IPv4_UNICAST_ADDRESS or data_in = DEFAULT_IPv4_MULTICAST_ADDRESS) then
|
||||||
|
-- Latch if Addr is Multicast
|
||||||
|
if (data_in = DEFAULT_IPv4_MULTICAST_ADDRESS) then
|
||||||
|
is_multicast_next <= '1';
|
||||||
|
end if;
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= UDP_HEADER_1;
|
||||||
|
-- packet not for us, skip
|
||||||
|
else
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
when LEN =>
|
||||||
|
-- Reset packet Byte Counter
|
||||||
|
reset_read_cnt <= '1';
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Read Packet Length from input
|
||||||
|
packet_length_next <= unsigned(data_in(13 downto 0));
|
||||||
|
-- Check Packet Length
|
||||||
|
if(to_integer(unsigned(data_in(13 downto 0))) < MIN_PACKET_LENGTH) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
else
|
||||||
|
-- Begin Processing
|
||||||
|
stage_next <= UDP_HEADER_1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- First UDP Header word (Fields: Src Port, Dest Port)
|
||||||
|
when UDP_HEADER_1 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Latch Src Port
|
||||||
|
src_port_next <= udp_src_port;
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Default Next Stage
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
-- Check if Dest Port is valid, if not Skip Packet
|
||||||
|
if (is_multicast = '1') then
|
||||||
|
-- Check if Metatraffic (via Mutlicast)
|
||||||
|
tmp := match_domain_id(udp_dest_port, META_IPv4_MULTICAST_PORT);
|
||||||
|
if (tmp != MAX_ENDPOINTS) then
|
||||||
|
is_metatraffic_next <= '1';
|
||||||
|
participant_id_next <= tmp;
|
||||||
|
stage_next <= UDP_HEADER_2;
|
||||||
|
-- Check if User Traffic (via Multicast)
|
||||||
|
else
|
||||||
|
tmp := match_domain_id(udp_dest_port, USER_IPv4_MULTICAST_PORT);
|
||||||
|
if (tmp != MAX_ENDPOINTS) then
|
||||||
|
stage_next <= UDP_HEADER_2;
|
||||||
|
participant_id_next <= tmp;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Check if Metatraffic (via Unicast)
|
||||||
|
tmp := match_domain_id(udp_dest_port, META_IPv4_UNICAST_PORT);
|
||||||
|
if (tmp != MAX_ENDPOINTS) then
|
||||||
|
is_metatraffic_next <= '1';
|
||||||
|
participant_id_next <= tmp;
|
||||||
|
stage_next <= UDP_HEADER_2;
|
||||||
|
-- Check if User Traffic (via Unicast)
|
||||||
|
else
|
||||||
|
tmp := match_domain_id(udp_dest_port, USER_IPv4_UNICAST_PORT);
|
||||||
|
if (tmp != MAX_ENDPOINTS) then
|
||||||
|
stage_next <= UDP_HEADER_2;
|
||||||
|
participant_id_next <= tmp;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
-- Second UDP Header Word (Fields: Length, Checksum)
|
||||||
|
when UDP_HEADER_2 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- If UPD header length does not match actual packet length, skip packet
|
||||||
|
if (normalize_length(udp_length) /= std_logic_vector(packet_length)) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
else
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= (udp_length & x"0000");
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= RTPS_HEADER_1;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
-- First RTPS Header word (Fields: Protocolld)
|
||||||
|
when RTPS_HEADER_1 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- If underlying Protocol is not RTPS, skip packet
|
||||||
|
if(data_in /= PROTOCOLLD_RTPS) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
-- Continue Parsing
|
||||||
|
else
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= RTPS_HEADER_2;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
-- Second RTPS Header word (Fields: Protocol Version, Vendor ID)
|
||||||
|
when RTPS_HEADER_2 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- If RTPS Protocol Major Version is not 2, skip packet
|
||||||
|
if(rtps_version(15 downto 8) /= PROTOCOLVERSION_2_4(15 downto 8)) then
|
||||||
|
stage_next <= SKIP_PACKET;
|
||||||
|
-- Continue Parsing
|
||||||
|
else
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Reset GP Counter
|
||||||
|
cnt_next <= 1;
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= RTPS_HEADER_3;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
-- Rest of RTPS Header (Fields: GUID Prefix)
|
||||||
|
when RTPS_HEADER_3 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- Sender GUID_Prefix
|
||||||
|
TODO <= data_in;
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
if (cnt = GUIDPREFIX_WIDTH/32) then
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= RTPS_SUB_HEADER;
|
||||||
|
else
|
||||||
|
cnt_next <= cnt + 1;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
-- NOTE: From here on, due to the nature of the RTPS Protocol, 32-bit word alignement
|
||||||
|
-- is not guaranteed, and has to be handled.
|
||||||
|
-- RTPS Submessage Header (Fields: Submessage ID, Flags, Submessage Length)
|
||||||
|
when RTPS_SUB_HEADER =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
|
||||||
|
case (rtps_sub_id) is
|
||||||
|
when SID_ACKNACK =>
|
||||||
|
-- Ignore Submessage if Final Flag not set
|
||||||
|
if (rtps_acknack_final = '1') then
|
||||||
|
-- Next Stage
|
||||||
|
stage_next <= ACKNACK_1;
|
||||||
|
else
|
||||||
|
-- Skip Submessage
|
||||||
|
stage_next <= SKIP_SUB;
|
||||||
|
end if;
|
||||||
|
when SID_PAD =>
|
||||||
|
when SID_HEARTBEAT =>
|
||||||
|
when SID_GAP =>
|
||||||
|
when SID_INFO_TS => --state
|
||||||
|
when SID_INFO_SRC => --state
|
||||||
|
when SID_INFO_REPLY_IP4 =>
|
||||||
|
when SID_INFO_DST => --state
|
||||||
|
when SID_INFO_REPLY => --state
|
||||||
|
when SID_NACK_FRAG =>
|
||||||
|
when SID_HEARTBEAT_FRAG =>
|
||||||
|
when SID_DATA =>
|
||||||
|
when SID_DATA_FRAG =>
|
||||||
|
-- Unknown ID, skip submessage
|
||||||
|
when others =>
|
||||||
|
stage_next <= SKIP_SUB;
|
||||||
|
end case;
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Store Submessage Length
|
||||||
|
-- TODO: The below conditional +1 adder should be solved with a carry-in
|
||||||
|
sub_length_next <= packet_length + unsigned(normalize_length(rtps_sub_length));
|
||||||
|
-- Store Byte offset of next Header
|
||||||
|
offset_latch_next <= unsigned(align_offset) + unsigned(rtps_sub_length(1 downto 0));
|
||||||
|
-- Next Stage
|
||||||
|
align_sig_next <= data_in(23 downto 0);
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
when ACKNACK_1 =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
--TODO
|
||||||
|
-- Checksum Calculation
|
||||||
|
add_a <= data_in;
|
||||||
|
add_b <= add_res;
|
||||||
|
add_cin <= add_cout;
|
||||||
|
-- Next Stage
|
||||||
|
align_sig_next <= data_in(23 downto 0);
|
||||||
|
else
|
||||||
|
-- Hold Checksum Value
|
||||||
|
add_a <= add_res;
|
||||||
|
end if;
|
||||||
|
when SKIP_PACKET =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- End of Packet
|
||||||
|
if (read_cnt = packet_length) then
|
||||||
|
-- Continue parsing next packet
|
||||||
|
stage_next <= SRC_ADDR;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when SKIP_SUB =>
|
||||||
|
if (empty = '0') then
|
||||||
|
rd_sig <= '1';
|
||||||
|
-- End of Packet (No further Submessages)
|
||||||
|
if (read_cnt = packet_length) then
|
||||||
|
-- Continue parsing next packet
|
||||||
|
stage_next <= SRC_ADDR;
|
||||||
|
-- End of Submessage
|
||||||
|
elsif (read_cnt = sub_length) then
|
||||||
|
-- Begin parsing of next submessage
|
||||||
|
stage_next <= RTPS_SUB_HEADER;
|
||||||
|
-- Fix alignement
|
||||||
|
align_offset <= offset_latch;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when others =>
|
||||||
|
null;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Process responsible for counting read words
|
||||||
|
-- This process uses the actual FIFO read signals to determine reads
|
||||||
|
word_counter_prc : process(clk, reset)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
-- Reset Read counter
|
||||||
|
if (reset = '1' or reset_read_cnt = '1') then
|
||||||
|
read_cnt <= to_unsigned(1, read_cnt'length);
|
||||||
|
-- Increment read counter each time rd is high
|
||||||
|
elsif (rd_sig = '1' or buffer_ren = '1') then
|
||||||
|
read_cnt <= read_cnt + to_unsigned(1, read_cnt'length);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
@ -4,144 +4,291 @@ use ieee.numeric_std.all;
|
|||||||
|
|
||||||
package rtps_package is
|
package rtps_package is
|
||||||
|
|
||||||
|
--*****USER CONFIG*****
|
||||||
|
-- Unicast IPv4 Address used by all RTPS Entities [Default 192.168.0.80]
|
||||||
|
constant IPv4_UNICAST_ADDRESS : std_logic_vector(31 downto 0) := x"C0A80080";
|
||||||
|
-- Number of RTPS Writer Endpoints
|
||||||
|
constant NUM_WRITERS : integer := 0;
|
||||||
|
-- Number of RTPS Reader Endpoints
|
||||||
|
constant NUM_READERS : integer := 1;
|
||||||
|
-- PB Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_PB : integer := 7400;
|
||||||
|
-- DG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_DG : integer := 250;
|
||||||
|
-- PG Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_PG : integer := 2;
|
||||||
|
-- D0 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_D0 : integer := 0;
|
||||||
|
-- D1 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_D1 : integer := 10;
|
||||||
|
-- D2 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_D2 : integer := 1;
|
||||||
|
-- D3 Value of Default Port Generation (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
constant PORT_CONFIG_D3 : integer := 11;
|
||||||
|
-- Number of Domains
|
||||||
|
constant NUM_DOMAIN : integer := 1;
|
||||||
|
-- MAC Address of underlying network stack (Used to generate GUIDs)
|
||||||
|
constant MAC_ADDRESS : std_logic_vector(47 downto 0) := x"97917E0BA8CF";
|
||||||
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
-- *DO NOT MODIFY BEGIN*
|
||||||
|
type USER_DOMAIN_ID_TYPE is array (NUM_DOMAIN-1 downto 0) of integer;
|
||||||
|
-- *DO NOT MODIFY END*
|
||||||
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
-- Array of Domain IDs
|
||||||
|
constant USER_DOMAIN_ID : USER_DOMAIN_ID_TYPE := (0 => 1);
|
||||||
|
|
||||||
subtype BYTE is std_logic_vector(7 downto 0);
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
-- *DO NOT MODIFY BEGIN*
|
||||||
|
type ENDPOINT_DOMAIN_MAP_TYPE is array (NUM_READERS+NUM_WRITERS-1 downto 0) of integer;
|
||||||
|
type ENDPOINT_WITH_KEY_TYPE is array (NUM_READERS+NUM_WRITERS-1 downto 0) of boolean;
|
||||||
|
-- *DO NOT MODIFY END*
|
||||||
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
type GUIDPREFIX_TYPE is array (11 downto 0) of BYTE;
|
--***RTPS ENDPOINTS***
|
||||||
constant GUIDPREFIX_UNKNOWN : GUIDPREFIX_TYPE := (others => (others => '0'));
|
-- Array mapping the RTPS Endpoints to their respective Domain IDs
|
||||||
|
-- The index of this array denotes the Endpoint, and the element value the index of the Domain in the 'USER_DOMAIN_ID'.
|
||||||
type ENTITYID_TYPE is array (3 downto 0) of BYTE;
|
constant ENDPOINT_DOMAIN_MAP: ENDPOINT_DOMAIN_MAP_TYPE := (0 => 0);
|
||||||
constant ENTITYID_UNKNOWN : ENTITYID_TYPE := (others => (others => '0'));
|
-- Array denoting if Endpoints use Keyed Topics
|
||||||
--alias ENTITYKIND : BYTE is ENTITYID(0);
|
constant ENDPOINT_WITH_KEY : ENDPOINT_WITH_KEY_TYPE := (0 => FALSE);
|
||||||
--alias ENTITYKIND_UPPER : std_logic_vector(1 downto 0) is ENTITYKIND(7 downto 6);
|
|
||||||
--FOLLOWING MAP TO ENTITYKIND_UPPER
|
|
||||||
constant USER_DEFINED_ENTITY_KIND : std_logic_vector(1 downto 0) := "00";
|
|
||||||
constant BUILT_IN_ENTITY_KIND : std_logic_vector(1 downto 0) := "11";
|
|
||||||
constant VENDOR_SPECIFIC_ENTITY_KIND: std_logic_vector(1 downto 0) := "01";
|
|
||||||
--alias ENTITYKIND_LOWER : std_logic_vector(1 downto 0) is ENTITYKIND(5 downto 0);
|
|
||||||
--FOLLOWING MAP TO ENTITYKIND_LOWER
|
|
||||||
constant WRITER_WITH_KEY : std_logic_vector(5 downto 0) := "000010";
|
|
||||||
constant WRITER_NO_KEY : std_logic_vector(5 downto 0) := "000011";
|
|
||||||
constant READER_NO_KEY : std_logic_vector(5 downto 0) := "000100";
|
|
||||||
constant READER_WITH_KEY : std_logic_vector(5 downto 0) := "000111";
|
|
||||||
constant WRITER_GROUP : std_logic_vector(5 downto 0) := "001000";
|
|
||||||
constant READER_GROUP : std_logic_vector(5 downto 0) := "001001";
|
|
||||||
--
|
|
||||||
constant ENTITYID_PARTICIPANT : ENTITYID_TYPE := (x"00", x"00", x"01", x"c1");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_TOPICS_ANNOUNCER : ENTITYID_TYPE := (x"00", x"00", x"02", x"c2");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_TOPICS_DETECTOR : ENTITYID_TYPE := (x"00", x"00", x"02", x"c7");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER : ENTITYID_TYPE := (x"00", x"00", x"03", x"c2");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR : ENTITYID_TYPE := (x"00", x"00", x"03", x"c7");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER : ENTITYID_TYPE := (x"00", x"00", x"04", x"c2");
|
|
||||||
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR : ENTITYID_TYPE := (x"00", x"00", x"04", x"c7");
|
|
||||||
constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER : ENTITYID_TYPE := (x"00", x"01", x"00", x"c2");
|
|
||||||
constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR : ENTITYID_TYPE := (x"00", x"01", x"00", x"c7");
|
|
||||||
constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: ENTITYID_TYPE := (x"00", x"02", x"00", x"c2");
|
|
||||||
constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: ENTITYID_TYPE := (x"00", x"02", x"00", x"c7");
|
|
||||||
|
|
||||||
type VENDORID_TYPE is array (1 downto 0) of BYTE;
|
|
||||||
--GUIDPREFIX(1 downto 0) <= VENDORID;
|
|
||||||
constant VENDORID_UNKNOWN : VENDORID_TYPE := (others => (others => '0'));
|
|
||||||
|
|
||||||
type PROTOCOLVERSION_TYPE is array (1 downto 0) of BYTE;
|
|
||||||
constant PROTOCOLVERSION_2_4 : PROTOCOLVERSION_TYPE := (x"02", x"04");
|
|
||||||
|
|
||||||
--General BITMAP SET Constants
|
|
||||||
constant NUMBITS_WIDTH : integer := 32;
|
|
||||||
constant BITMAP_WIDTH : integer := 32;
|
|
||||||
|
|
||||||
constant SEQUENCENUMBER_WIDTH : integer := 64;
|
|
||||||
type SEQUENCENUMBERSET_HEADER_TYPE is record {
|
|
||||||
bitmapBase : std_logic_vector(SEQUENCENUMBER_WIDTH-1 downto 0);
|
|
||||||
numBits : std_logic_vector(NUMBITS_WIDTH-1 downto 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
subtype FRAGMENTNUMBER_WIDTH : integer := 32;;
|
|
||||||
type FRAGMENTNUMBERSET_HEADER_TYPE is record{
|
|
||||||
bitmapBase : std_logic_vector(FRAGMENTNUMBER_WIDTH-1 downto 0);
|
|
||||||
numBits : std_logic_vector(NUMBITS_WIDTH-1 downto 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
--Fixed Point Q32.32
|
|
||||||
constant TIMESTAMP_WIDTH : integer := 64;
|
|
||||||
|
|
||||||
constant LOCATOR_KIND : integer := 32;
|
|
||||||
constant LOCATOR_PORT : integer := 32;
|
|
||||||
constant LOCATOR_ADDR : integer := 128;
|
|
||||||
type LOCATOR_TYPE is record{
|
|
||||||
kind : std_logic_vector(LOCATOR_KIND-1 downto 0);
|
|
||||||
port : std_logic_vector(LOCATOR_PORT-1 downto 0);
|
|
||||||
addr : std_logic_vector(LOCATOR_ADDR-1 downto 0);
|
|
||||||
};
|
|
||||||
constant NUMLOCATOR_WIDTH : integer := 32;
|
|
||||||
|
|
||||||
constant LOCATORUDPv4_PORT : integer := 32;
|
|
||||||
constant LOCATORUDPv4_ADDR : integer := 32;
|
|
||||||
type LOCATORUDPv4_TYPE is record{
|
|
||||||
addr : std_logic_vector(LOCATORUDPv4_ADDR-1 downto 0);
|
|
||||||
port : std_logic_vector(LOCATORUDPv4_PORT-1 downto 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
constant PARAMETERID_WIDTH : integer := 16;
|
--*****DDSI-RTPS 2.3*****
|
||||||
constant PARAMETERLENGTH_WIDTH : integer := 16;
|
|
||||||
type PARAMETER_HEADER_TYPE is record{
|
|
||||||
pid : std_logic_vector(PARAMETERID_WIDTH-1 downto 0);
|
|
||||||
length : std_logic_vector(PARAMETERLENGTH_WIDTH-1 downto 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
constant PID_PAD : std_logic_vector(PARAMETERID_WIDTH-1 downto 0) := (others => '0');
|
-- Default Multicast Ipv4 Address (239.255.0.1)
|
||||||
constant PID_SENTINEL : std_logic_vector(PARAMETERID_WIDTH-1 downto 0) := std_logic_vector(unsigned(1,PARAMETERID_WIDTH));
|
constant DEFAULT_IPv4_MULTICAST_ADDRESS : std_logic_vector(31 downto 0) := x"EFFF0001";
|
||||||
|
|
||||||
constant COUNT_WIDTH : integer := 32;
|
constant GUIDPREFIX_WIDTH : integer := 96;
|
||||||
|
constant PROTOCOLVERSION_WIDTH : integer := 16;
|
||||||
|
constant VENDORID_WIDTH : integer := 16;
|
||||||
|
constant SUBMESSAGE_ID_WIDTH : integer := 8;
|
||||||
|
constant DOMAIN_ID_WIDTH : integer := 32;
|
||||||
|
constant UDP_PORT_WIDTH : integer := 16;
|
||||||
|
constant ENTITYID_WIDTH : integer := 32;
|
||||||
|
constant PROTOCOL_WIDTH : integer := 32;
|
||||||
|
|
||||||
--TODO: GroupDigest?
|
-- 'RTPS' in Ascii code
|
||||||
|
constant PROTOCOL_RTPS : std_logic_vector(PROTOCOL_WIDTH-1 downto 0) := x"52545053";
|
||||||
constant PROTOCOLLD_WIDTH : integer := 32;
|
constant PROTOCOLVERSION_2_4 : std_logic_vector(PROTOCOLVERSION_WIDTH-1 downto 0) := x"0204";
|
||||||
type RTPS_HEADER_TYPE is record{
|
constant VENDORID_UNKNOWN : std_logic_vector(VENDORID_WIDTH-1 downto 0) := (others => '0');
|
||||||
protocol : std_logic_vector(PROTOCOLLD_WIDTH-1 downto 0);
|
constant VENDORID : std_logic_vector(VENDORID_WIDTH-1 downto 0) := VENDORID_UNKNOWN;
|
||||||
version : PROTOCOLVERSION_TYPE;
|
-- Submessage IDs
|
||||||
vendorid : VENDORID_TYPE;
|
constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01";
|
||||||
guidprefix : GUIDPREFIX_TYPE;
|
constant SID_ACKNACK : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"06";
|
||||||
};
|
constant SID_HEARTBEAT : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"07";
|
||||||
constant PROTOCOLLD_RTPS : std_logic_vector(PROTOCOLLD_WIDTH-1 downto 0) := x"52545053";
|
constant SID_GAP : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"08";
|
||||||
|
constant SID_INFO_TS : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"09";
|
||||||
constant SUBMESSAGE_ID_WIDTH : integer := 8;
|
constant SID_INFO_SRC : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0c";
|
||||||
constant SUBMESSAGE_FLAGS_WIDTH : integer := 8;
|
constant SID_INFO_REPLY_IP4 : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0d";
|
||||||
constant SUBMESSAGE_LENGTH_WIDTH : integer := 16;
|
constant SID_INFO_DST : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0e";
|
||||||
type RTPS_SUBMESSAGE_HEADER_TYPE is record{
|
constant SID_INFO_REPLY : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0f";
|
||||||
id : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0);
|
constant SID_NACK_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"12";
|
||||||
flags : std_logic_vector(SUBMESSAGE_FLAGS_WIDTH-1 downto 0);
|
constant SID_HEARTBEAT_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"13";
|
||||||
length : std_logic_vector(SUBMESSAGE_LENGTH_WIDTH-1 downto 0);
|
constant SID_DATA : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"15";
|
||||||
};
|
constant SID_DATA_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"16";
|
||||||
|
|
||||||
constant SID_PAD : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"01";
|
|
||||||
constant SID_ACKNACK : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"06";
|
|
||||||
constant SID_HEARTBEAT : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"07";
|
|
||||||
constant SID_GAP : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"08";
|
|
||||||
constant SID_INFO_TS : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"09";
|
|
||||||
constant SID_INFO_SRC : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0c";
|
|
||||||
constant SID_INFO_REPLY_IP4 : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0d";
|
|
||||||
constant SID_INFO_DST : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0e";
|
|
||||||
constant SID_INFO_REPLY : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"0f";
|
|
||||||
constant SID_NACK_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"12";
|
|
||||||
constant SID_HEARTBEAT_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"13";
|
|
||||||
constant SID_DATA : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"15";
|
|
||||||
constant SID_DATA_FRAG : std_logic_vector(SUBMESSAGE_ID_WIDTH-1 downto 0) := x"16";
|
|
||||||
--TODO: Enum it?
|
|
||||||
|
|
||||||
constant ENDIANNESS_FLAG_POS : integer := 0;
|
|
||||||
--ACKNACK
|
|
||||||
constant FINAL_FLAG_POS : integer := 1;
|
|
||||||
--DATA
|
|
||||||
constant INLINEQOS_FLAG_POS : integer := 1;
|
|
||||||
constant DATA_FLAG_POS : integer := 2;
|
|
||||||
constant KEY_FLAG_POS : integer := 3;
|
|
||||||
constant NONSTANDARDPAYLOAD_FLAG_POS: integer := 4;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type DOMAIN_ID_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0);
|
||||||
|
constant DOMAIN_ID : DOMAIN_ID_TYPE; -- Deferred to Package Body
|
||||||
|
|
||||||
|
type DOMAIN_ENDPOINT_MAP_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(NUM_READERS+NUM_WRITERS-1 downto 0);
|
||||||
|
constant DOMAIN_ENDPOINT_MAP : DOMAIN_ENDPOINT_MAP_TYPE; -- Deferred to Package Body
|
||||||
|
|
||||||
|
-- Since this implementation runs on the same network stack and the RTPS Endpoints (Readers & Writers)
|
||||||
|
-- can be differentiated based on their Entity ID, it makes no sense to have multiple IP Addresses
|
||||||
|
-- (and hence multiple Participants).
|
||||||
|
-- We generate just single participant for every Domain, and later match the Endpoints to their respective
|
||||||
|
-- Domain (and thus also to their respective RTPS Participant).
|
||||||
|
|
||||||
|
type IPv4_PORT_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(UDP_PORT_WIDTH-1 downto 0);
|
||||||
|
constant META_IPv4_MULTICAST_PORT: IPv4_PORT_TYPE; -- Deferred to Package Body
|
||||||
|
constant META_IPv4_UNICAST_PORT : IPv4_PORT_TYPE; -- Deferred to Package Body
|
||||||
|
constant USER_IPv4_MULTICAST_PORT: IPv4_PORT_TYPE; -- Deferred to Package Body
|
||||||
|
constant USER_IPv4_UNICAST_PORT : IPv4_PORT_TYPE; -- Deferred to Package Body
|
||||||
|
|
||||||
|
type GUIDPREFIX_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(GUIDPREFIX_WIDTH-1 downto 0);
|
||||||
|
constant GUIDPREFIX : GUIDPREFIX_TYPE; -- Deferred to Package Body
|
||||||
|
constant GUIDPREFIX_UNKNOWN : std_logic_vector(GUIDPREFIX_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
|
||||||
|
subtype ENTITY_KIND_H is std_logic_vector(1 downto 0);
|
||||||
|
subtype ENTITY_KIND_L is std_logic_vector(5 downto 0);
|
||||||
|
--FOLLOWING MAP TO ENTITY_KIND_H
|
||||||
|
constant USER_DEFINED_ENTITY : ENTITY_KIND_H := "00";
|
||||||
|
constant BUILT_IN_ENTITY : ENTITY_KIND_H := "11";
|
||||||
|
constant VENDOR_SPECIFIC_ENTITY : ENTITY_KIND_H := "01";
|
||||||
|
--FOLLOWING MAP TO ENTITY_KIND_L
|
||||||
|
constant WRITER_WITH_KEY : ENTITY_KIND_L := "000010";
|
||||||
|
constant WRITER_NO_KEY : ENTITY_KIND_L := "000011";
|
||||||
|
constant READER_NO_KEY : ENTITY_KIND_L := "000100";
|
||||||
|
constant READER_WITH_KEY : ENTITY_KIND_L := "000111";
|
||||||
|
constant WRITER_GROUP : ENTITY_KIND_L := "001000";
|
||||||
|
constant READER_GROUP : ENTITY_KIND_L := "001001";
|
||||||
|
|
||||||
|
-- DDSI-RTPS 2.3 states that Entity IDs have to be unique within each Participant.
|
||||||
|
-- For simplicity and ease of mapping we make the Entity IDs unique across all Participant and Domains on this node.
|
||||||
|
type ENTITYID_TYPE is array (NUM_READERS+NUM_WRITERS-1 downto 0) of std_logic_vector(ENTITYID_WIDTH-1 downto 0);
|
||||||
|
constant ENTITYID : ENTITYID_TYPE; -- Deferred to Package Body
|
||||||
|
constant ENTITYID_UNKNOWN : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
constant ENTITYID_PARTICIPANT : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000001c1");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_TOPICS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000002c2");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_TOPICS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000002c7");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000003c2");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_PUBLICATIONS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000003c7");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000004c2");
|
||||||
|
constant ENTITYID_SEDP_BUILTIN_SUBSCRIPTIONS_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000004c7");
|
||||||
|
constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_ANNOUNCER : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000100c2");
|
||||||
|
constant ENTITYID_SPDP_BUILTIN_PARTICIPANT_DETECTOR : std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000100c7");
|
||||||
|
constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_WRITER: std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000200c2");
|
||||||
|
constant ENTITYID_P2P_BUILTIN_PARTICIPANT_MESSAGE_READER: std_logic_vector(ENTITYID_WIDTH-1 downto 0) := (x"000200c7");
|
||||||
|
|
||||||
|
constant LOCATOR_KIND_WIDTH : integer := 32;
|
||||||
|
constant LOCATOR_KIND_INVALID : std_logic_vector := std_logic_vector(to_signed(-1,LOCATOR_KIND_WIDTH));
|
||||||
|
constant LOCATOR_KIND_RESERVERD : std_logic_vector := std_logic_vector(to_signed(0,LOCATOR_KIND_WIDTH));
|
||||||
|
constant LOCATOR_KIND_UDPv4 : std_logic_vector := std_logic_vector(to_signed(1,LOCATOR_KIND_WIDTH));
|
||||||
|
constant LOCATOR_KIND_UDPv6 : std_logic_vector := std_logic_vector(to_signed(2,LOCATOR_KIND_WIDTH));
|
||||||
|
|
||||||
|
--*****CUSTOM*****
|
||||||
|
|
||||||
|
--****************
|
||||||
|
|
||||||
|
type USER_ENDPOINT_OUTPUT is array (NUM_READERS+NUM_WRITERS-1 downto 0) of std_logic_vector(31 downto 0);
|
||||||
|
type BUILTIN_ENDPOINT_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(31 downto 0);
|
||||||
|
|
||||||
end package;
|
end package;
|
||||||
|
|
||||||
package body rtps_package is
|
package body rtps_package is
|
||||||
|
|
||||||
|
function gen_domain_ids (user_id : USER_DOMAIN_ID_TYPE) return DOMAIN_ID_TYPE is
|
||||||
|
variable ret : DOMAIN_ID_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to user_id'length-1 loop
|
||||||
|
-- Check if User provided Domain ID fits
|
||||||
|
-- NOTE: Cannot assert due to vhdl integer overflow.
|
||||||
|
--assert (user_id(i) < (2**DOMAIN_ID_WIDTH-1 - PORT_CONFIG_PB) / PORT_CONFIG_DG) report "Domain ID range exceeded" severity failure;
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(user_id(i), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant DOMAIN_ID : DOMAIN_ID_TYPE := gen_domain_ids(USER_DOMAIN_ID);
|
||||||
|
|
||||||
|
function gen_domain_endpoint_map (end_id : ENDPOINT_DOMAIN_MAP_TYPE) return DOMAIN_ENDPOINT_MAP_TYPE is
|
||||||
|
variable ret : DOMAIN_ENDPOINT_MAP_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to NUM_DOMAIN-1 loop
|
||||||
|
for j in 0 to NUM_READERS+NUM_WRITERS-1 loop
|
||||||
|
if (i = end_id(j)) then
|
||||||
|
ret(i)(j) := '1';
|
||||||
|
end if;
|
||||||
|
end loop;
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant DOMAIN_ENDPOINT_MAP : DOMAIN_ENDPOINT_MAP_TYPE := gen_domain_endpoint_map(ENDPOINT_DOMAIN_MAP);
|
||||||
|
|
||||||
|
function gen_meta_multicast_ports (domain_id : DOMAIN_ID_TYPE) return IPv4_PORT_TYPE is
|
||||||
|
variable ret : IPv4_PORT_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to domain_id'length-1 loop
|
||||||
|
-- (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
-- PB + DG * domain_id + d0
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D0 + PORT_CONFIG_DG*to_integer(unsigned(domain_id(i))), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function gen_meta_unicast_ports (domain_id : DOMAIN_ID_TYPE) return IPv4_PORT_TYPE is
|
||||||
|
variable ret : IPv4_PORT_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to domain_id'length-1 loop
|
||||||
|
-- (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
-- PB + DG * domainId + d1 + PG * participant_id
|
||||||
|
-- participant_id=0
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D1 + PORT_CONFIG_DG*to_integer(unsigned(domain_id(i))), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function gen_user_multicast_ports (domain_id : DOMAIN_ID_TYPE) return IPv4_PORT_TYPE is
|
||||||
|
variable ret : IPv4_PORT_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to domain_id'length-1 loop
|
||||||
|
-- (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
-- PB + DG * domainId + d2
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D2 + PORT_CONFIG_DG*to_integer(unsigned(domain_id(i))), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
function gen_user_unicast_ports (domain_id : DOMAIN_ID_TYPE) return IPv4_PORT_TYPE is
|
||||||
|
variable ret : IPv4_PORT_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to domain_id'length-1 loop
|
||||||
|
-- (see DDSI-RTPS 2.3 Section 9.6.1)
|
||||||
|
-- PB + DG * domainId + d3 + PG * participant_id
|
||||||
|
-- participant_id=0
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(PORT_CONFIG_PB + PORT_CONFIG_D3 + PORT_CONFIG_DG*to_integer(unsigned(domain_id(i))), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant META_IPv4_MULTICAST_PORT: IPv4_PORT_TYPE := gen_meta_multicast_ports(DOMAIN_ID);
|
||||||
|
constant META_IPv4_UNICAST_PORT : IPv4_PORT_TYPE := gen_meta_unicast_ports(DOMAIN_ID);
|
||||||
|
constant USER_IPv4_MULTICAST_PORT: IPv4_PORT_TYPE := gen_user_multicast_ports(DOMAIN_ID);
|
||||||
|
constant USER_IPv4_UNICAST_PORT : IPv4_PORT_TYPE := gen_user_unicast_ports(DOMAIN_ID);
|
||||||
|
|
||||||
|
function gen_guid_prefix (domain_id : DOMAIN_ID_TYPE) return GUIDPREFIX_TYPE is
|
||||||
|
variable ret : GUIDPREFIX_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to ret'length-1 loop
|
||||||
|
-- First to bytes have to be Vendor ID (see DDSI-RTPS 2.3 Section 9.3.1.5)
|
||||||
|
ret(i)(ret(i)'length-1 downto ret(i)'length-VENDORID_WIDTH) := VENDORID;
|
||||||
|
-- Next we insert the MAC address for uniqueness
|
||||||
|
ret(i)(ret(i)'length-VENDORID_WIDTH-1 downto ret(i)'length-VENDORID_WIDTH-48) := MAC_ADDRESS;
|
||||||
|
-- Next we insert the Domain ID
|
||||||
|
-- NOTE: If the widths of signals change in the future, this will overwrite part of the MAC Address.
|
||||||
|
ret(i)(DOMAIN_ID_WIDTH-1 downto 0) := domain_id(i);
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant GUIDPREFIX : GUIDPREFIX_TYPE := gen_guid_prefix(DOMAIN_ID);
|
||||||
|
|
||||||
|
function gen_entyid return ENTITYID_TYPE is
|
||||||
|
variable ret : ENTITYID_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to ret'length-1 loop
|
||||||
|
-- (see DDSI-RTPS 2.3 Section 9.3.1.2)
|
||||||
|
-- Entity Kind Mapping
|
||||||
|
ret(i)(7 downto 6) := USER_DEFINED_ENTITY;
|
||||||
|
if (i <= NUM_READERS-1) then
|
||||||
|
if (ENDPOINT_WITH_KEY(i)) then
|
||||||
|
ret(i)(5 downto 0) := READER_WITH_KEY;
|
||||||
|
else
|
||||||
|
ret(i)(5 downto 0) := READER_NO_KEY;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
if (ENDPOINT_WITH_KEY(i)) then
|
||||||
|
ret(i)(5 downto 0) := WRITER_WITH_KEY;
|
||||||
|
else
|
||||||
|
ret(i)(5 downto 0) := WRITER_NO_KEY;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
-- ID Mapping
|
||||||
|
ret(i)(ENTITYID_WIDTH-1 downto 8) := std_logic_vector(to_unsigned(i,ENTITYID_WIDTH-8));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant ENTITYID : ENTITYID_TYPE := gen_entyid;
|
||||||
|
|
||||||
end package body;
|
end package body;
|
||||||
|
|||||||
46
src/test.vhd
Normal file
46
src/test.vhd
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package rtps_package is
|
||||||
|
|
||||||
|
-- Number of Domains
|
||||||
|
constant NUM_DOMAIN : integer := 1;
|
||||||
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
-- *DO NOT MODIFY BEGIN*
|
||||||
|
type USER_DOMAIN_ID_TYPE is array (NUM_DOMAIN-1 downto 0) of integer;
|
||||||
|
-- *DO NOT MODIFY END*
|
||||||
|
-----------------------------------------------------------------------------------------------------
|
||||||
|
-- Array of Domain IDs
|
||||||
|
constant USER_DOMAIN_ID : USER_DOMAIN_ID_TYPE := (0 => 1);
|
||||||
|
|
||||||
|
constant DOMAIN_ID_WIDTH : integer := 32;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
type DOMAIN_ID_TYPE is array (NUM_DOMAIN-1 downto 0) of std_logic_vector(DOMAIN_ID_WIDTH-1 downto 0);
|
||||||
|
|
||||||
|
function gen_domain_ids (user_id : USER_DOMAIN_ID_TYPE) return DOMAIN_ID_TYPE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end package;
|
||||||
|
|
||||||
|
package body rtps_package is
|
||||||
|
|
||||||
|
function gen_domain_ids (user_id : USER_DOMAIN_ID_TYPE) return DOMAIN_ID_TYPE is
|
||||||
|
variable ret : DOMAIN_ID_TYPE;
|
||||||
|
begin
|
||||||
|
ret := (others => (others => '0'));
|
||||||
|
for i in 0 to user_id'length-1 loop
|
||||||
|
-- Check if User provided Domain ID fits
|
||||||
|
-- NOTE: Cannot assert due to vhdl integer overflow.
|
||||||
|
--assert (user_id(i) < (2**DOMAIN_ID_WIDTH-1 - PORT_CONFIG_PB) / PORT_CONFIG_DG) report "Domain ID range exceeded" severity failure;
|
||||||
|
ret(i) := std_logic_vector(to_unsigned(user_id(i), ret(i)'length));
|
||||||
|
end loop;
|
||||||
|
return ret;
|
||||||
|
end function;
|
||||||
|
|
||||||
|
constant DOMAIN_ID : DOMAIN_ID_TYPE := gen_domain_ids(USER_DOMAIN_ID);
|
||||||
|
|
||||||
|
end package body;
|
||||||
@ -86,7 +86,9 @@
|
|||||||
</File>
|
</File>
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="DesignMode" Val="RTL"/>
|
<Option Name="DesignMode" Val="RTL"/>
|
||||||
<Option Name="TopModule" Val="ipv4_in"/>
|
<Option Name="TopModule" Val="ipv4_in_handler"/>
|
||||||
|
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||||
|
<Option Name="TopArchitecture" Val="with_frag"/>
|
||||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
@ -106,8 +108,9 @@
|
|||||||
<Filter Type="Srcs"/>
|
<Filter Type="Srcs"/>
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="DesignMode" Val="RTL"/>
|
<Option Name="DesignMode" Val="RTL"/>
|
||||||
<Option Name="TopModule" Val="ipv4_in"/>
|
<Option Name="TopModule" Val="ipv4_in_handler"/>
|
||||||
<Option Name="TopLib" Val="xil_defaultlib"/>
|
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||||
|
<Option Name="TopArchitecture" Val="with_frag"/>
|
||||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||||
<Option Name="TransportPathDelay" Val="0"/>
|
<Option Name="TransportPathDelay" Val="0"/>
|
||||||
<Option Name="TransportIntDelay" Val="0"/>
|
<Option Name="TransportIntDelay" Val="0"/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user