Skip to content
Snippets Groups Projects
Commit f318c9aa authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Ported eth_layers.vhd from tse/ in $UNB to common_network_layers_pkg.vhd in common/ in $RADIOHDL.

Only file name change, definition names need to be changed later to have prefix network_*.
parent 11cab834
No related branches found
No related tags found
No related merge requests found
...@@ -11,6 +11,7 @@ synth_files = ...@@ -11,6 +11,7 @@ synth_files =
$UNB/Firmware/modules/common/src/vhdl/common_mem_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_mem_pkg.vhd
$UNB/Firmware/modules/common/src/vhdl/common_field_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_field_pkg.vhd
$UNB/Firmware/modules/common/src/vhdl/common_lfsr_sequences_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_lfsr_sequences_pkg.vhd
$UNB/Firmware/modules/common/src/vhdl/common_network_layers_pkg.vhd
$UNB/Firmware/modules/common/src/vhdl/common_components_pkg.vhd $UNB/Firmware/modules/common/src/vhdl/common_components_pkg.vhd
$UNB/Firmware/modules/MegaWizard/arith/lut_add_sub.vhd $UNB/Firmware/modules/MegaWizard/arith/lut_add_sub.vhd
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2010
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
PACKAGE eth_layers_pkg IS
-- All *_len constants are in nof octets = nof bytes
CONSTANT c_8 : NATURAL := c_octet_w; -- = 8
-- The Ethernet packet is interpreted as words and word aligned
CONSTANT c_32 : NATURAL := c_word_w; -- = 32
------------------------------------------------------------------------------
-- Ethernet Packet (with payload word alignment!)
--
-- 0 15 16 31 wi
-- |----------------------------------------------------------------------|
-- | Word Align | Destination MAC Address | 0
-- |----------------------------------- |
-- | | 1
-- |----------------------------------------------------------------------|
-- | Source MAC Address | 2
-- | ------------------------------------|
-- | | EtherType | 3
-- |----------------------------------|-----------------------------------|
-- | |
-- | Ethernet Payload |
-- | |
-- |------------------------------------------------------------ // ------|
-- | Frame Check Sequence |
-- |------------------------------------------------------------ // ------|
--
-- field widths in bits '_w' or in bytes '_len', '_min', '_max', '_sz'
CONSTANT c_eth_preamble_len : NATURAL := 8;
CONSTANT c_eth_mac_addr_len : NATURAL := 6;
CONSTANT c_eth_mac_addr_w : NATURAL := c_eth_mac_addr_len*c_8;
CONSTANT c_eth_type_len : NATURAL := 2;
CONSTANT c_eth_type_w : NATURAL := c_eth_type_len*c_8;
CONSTANT c_eth_header_len : NATURAL := 2*c_eth_mac_addr_len+c_eth_type_len; -- = 14
CONSTANT c_eth_payload_min : NATURAL := 46;
CONSTANT c_eth_payload_max : NATURAL := 1500;
CONSTANT c_eth_payload_jumbo_max : NATURAL := 9000;
CONSTANT c_eth_crc_len : NATURAL := 4;
CONSTANT c_eth_crc_w : NATURAL := c_eth_crc_len*c_8;
CONSTANT c_eth_gap_len : NATURAL := 12;
CONSTANT c_eth_word_align_len : NATURAL := 2; -- c_eth_header_len + 2 = 16, align payload to 32 bit boundaries
CONSTANT c_eth_word_align_w : NATURAL := c_eth_word_align_len*c_8;
CONSTANT c_eth_frame_max : NATURAL := c_eth_header_len + c_eth_payload_max + c_eth_crc_len; -- = 1518
CONSTANT c_eth_frame_jumbo_max : NATURAL := c_eth_header_len + c_eth_payload_jumbo_max + c_eth_crc_len; -- = 9018
-- default field values
CONSTANT c_eth_preamble : NATURAL := 5; -- nibble "0101"
CONSTANT c_eth_frame_delimiter : NATURAL := 13; -- nibble "1101"
CONSTANT c_eth_word_align : NATURAL := 0;
-- useful field values
CONSTANT c_eth_mac_slv : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0) := (OTHERS=>'X'); -- Ethernet MAC slv RANGE
CONSTANT c_eth_bc_mac : STD_LOGIC_VECTOR(c_eth_mac_slv'RANGE) := (OTHERS=>'1'); -- Broadcast destination MAC
CONSTANT c_eth_type_slv : STD_LOGIC_VECTOR(c_eth_type_w-1 DOWNTO 0) := (OTHERS=>'X'); -- Ethernet TYPE slv RANGE
CONSTANT c_eth_type_arp : NATURAL := 16#0806#; -- ARP = Address Resolution Prorotol
CONSTANT c_eth_type_ip : NATURAL := 16#0800#; -- IPv4 = Internet Protocol, Version 4
TYPE t_eth_header IS RECORD
word_align : STD_LOGIC_VECTOR(c_eth_word_align_w-1 DOWNTO 0);
dst_mac : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0);
src_mac : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0);
eth_type : STD_LOGIC_VECTOR(c_eth_type_w-1 DOWNTO 0);
END RECORD;
-- field valid word indices
CONSTANT c_eth_lo_wi : NATURAL := 0; -- first word index
CONSTANT c_eth_dst_mac_wi : NATURAL := 1;
CONSTANT c_eth_src_mac_wi : NATURAL := 3;
CONSTANT c_eth_type_wi : NATURAL := 3;
CONSTANT c_eth_hi_wi : NATURAL := 3; -- last word index
CONSTANT c_eth_nof_words : NATURAL := c_eth_hi_wi - c_eth_lo_wi + 1; -- = (c_eth_word_align_len + c_eth_word_align_len) / c_word_sz
------------------------------------------------------------------------------
-- IPv4 Packet
--
-- 0 3 4 7 8 15 16 18 19 31 wi
-- |----------------------------------------------------------------------|
-- | Version | HLEN | Services | Total Length | 4
-- |----------------------------------------------------------------------|
-- | Identification | Flags | Fragment Offset | 5
-- |----------------------------------------------------------------------|
-- | TTL | Protocol | Header Checksum | 6
-- |----------------------------------------------------------------------|
-- | Source IP Address | 7
-- |----------------------------------------------------------------------|
-- | Destination IP Address | 8
-- |----------------------------------------------------------------------|
-- | |
-- | IP Payload |
-- | |
-- |------------------------------------------------------------ // ------|
--
-- field widths in bits '_w' or in bytes '_len'
CONSTANT c_ip_version_w : NATURAL := 4; -- 4-bit field
CONSTANT c_ip_header_length_w : NATURAL := 4; -- 4-bit field
CONSTANT c_ip_version_header_len : NATURAL := 1;
CONSTANT c_ip_version_header_w : NATURAL := c_ip_version_header_len*c_8;
CONSTANT c_ip_services_len : NATURAL := 1;
CONSTANT c_ip_services_w : NATURAL := c_ip_services_len*c_8;
CONSTANT c_ip_total_length_len : NATURAL := 2;
CONSTANT c_ip_total_length_w : NATURAL := c_ip_total_length_len*c_8;
CONSTANT c_ip_identification_len : NATURAL := 2;
CONSTANT c_ip_identification_w : NATURAL := c_ip_identification_len*c_8;
CONSTANT c_ip_flags_w : NATURAL := 3; -- 3-bit field
CONSTANT c_ip_fragment_offset_w : NATURAL := 13; -- 13-bit field
CONSTANT c_ip_flags_fragment_len : NATURAL := 2;
CONSTANT c_ip_flags_fragment_w : NATURAL := c_ip_flags_fragment_len*c_8;
CONSTANT c_ip_time_to_live_len : NATURAL := 1;
CONSTANT c_ip_time_to_live_w : NATURAL := c_ip_time_to_live_len*c_8;
CONSTANT c_ip_protocol_len : NATURAL := 1;
CONSTANT c_ip_protocol_w : NATURAL := c_ip_protocol_len*c_8;
CONSTANT c_ip_header_checksum_len : NATURAL := 2;
CONSTANT c_ip_header_checksum_w : NATURAL := c_ip_header_checksum_len*c_8;
CONSTANT c_ip_addr_len : NATURAL := 4;
CONSTANT c_ip_addr_w : NATURAL := c_ip_addr_len*c_8;
-- [0:7] [8:15] [16:31]
CONSTANT c_ip_header_len : NATURAL := c_ip_version_header_len + c_ip_services_len + c_ip_total_length_len +
c_ip_identification_len + c_ip_flags_fragment_len +
c_ip_time_to_live_len + c_ip_protocol_len + c_ip_header_checksum_len +
c_ip_addr_len +
c_ip_addr_len;
-- = c_ip_header_length * c_word_sz = 20
-- default field values
CONSTANT c_ip_version : NATURAL := 4; -- 4 = IPv4,
CONSTANT c_ip_header_length : NATURAL := 5; -- 5 = nof words in the header, no options field support
CONSTANT c_ip_services : NATURAL := 0; -- 0 = default, use default on transmit, ignore on receive, copy on reply
CONSTANT c_ip_total_length : NATURAL := 20; -- >= 20, nof bytes in entire datagram including header and data
CONSTANT c_ip_identification : NATURAL := 0; -- identification number, copy on reply
CONSTANT c_ip_flags : NATURAL := 2; -- 2 = don't fragment and this is the last fragment
CONSTANT c_ip_fragment_offset : NATURAL := 0; -- 0 = first fragment
CONSTANT c_ip_time_to_live : NATURAL := 127; -- number of hops until the packet will be discarded
CONSTANT c_ip_header_checksum : NATURAL := 0; -- init value
-- useful field values
CONSTANT c_ip_protocol_slv : STD_LOGIC_VECTOR(c_ip_protocol_w-1 DOWNTO 0) := (OTHERS=>'X'); -- IP protocol slv RANGE
CONSTANT c_ip_protocol_udp : NATURAL := 17; -- UDP = User Datagram Protocol (for board control and streaming data)
CONSTANT c_ip_protocol_icmp : NATURAL := 1; -- ICMP = Internet Control Message Protocol (for ping)
CONSTANT c_ip_addr_slv : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0) := (OTHERS=>'X'); -- IP address slv RANGE
TYPE t_ip_header IS RECORD
version : STD_LOGIC_VECTOR(c_ip_version_w-1 DOWNTO 0); -- 4 bit
header_length : STD_LOGIC_VECTOR(c_ip_header_length_w-1 DOWNTO 0); -- 4 bit
services : STD_LOGIC_VECTOR(c_ip_services_w-1 DOWNTO 0); -- 1 octet
total_length : STD_LOGIC_VECTOR(c_ip_total_length_w-1 DOWNTO 0); -- 2 octet
identification : STD_LOGIC_VECTOR(c_ip_identification_w-1 DOWNTO 0); -- 2 octet
flags : STD_LOGIC_VECTOR(c_ip_flags_w-1 DOWNTO 0); -- 3 bit
fragment_offset : STD_LOGIC_VECTOR(c_ip_fragment_offset_w-1 DOWNTO 0); -- 13 bit
time_to_live : STD_LOGIC_VECTOR(c_ip_time_to_live_w-1 DOWNTO 0); -- 1 octet
protocol : STD_LOGIC_VECTOR(c_ip_protocol_w-1 DOWNTO 0); -- 1 octet
header_checksum : STD_LOGIC_VECTOR(c_ip_header_checksum_w-1 DOWNTO 0); -- 2 octet
src_ip_addr : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0); -- 4 octet
dst_ip_addr : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0); -- 4 octet
END RECORD;
-- field valid word indices
CONSTANT c_ip_lo_wi : NATURAL := 4; -- first word index
CONSTANT c_ip_version_wi : NATURAL := 4;
CONSTANT c_ip_header_length_wi : NATURAL := 4;
CONSTANT c_ip_services_wi : NATURAL := 4;
CONSTANT c_ip_total_length_wi : NATURAL := 4;
CONSTANT c_ip_identification_wi : NATURAL := 5;
CONSTANT c_ip_flags_wi : NATURAL := 5;
CONSTANT c_ip_fragment_offset_wi : NATURAL := 5;
CONSTANT c_ip_time_to_live_wi : NATURAL := 6;
CONSTANT c_ip_protocol_wi : NATURAL := 6;
CONSTANT c_ip_header_checksum_wi : NATURAL := 6;
CONSTANT c_ip_src_ip_addr_wi : NATURAL := 7;
CONSTANT c_ip_dst_ip_addr_wi : NATURAL := 8;
CONSTANT c_ip_hi_wi : NATURAL := 8; -- last word index
CONSTANT c_ip_nof_words : NATURAL := c_ip_hi_wi - c_ip_lo_wi + 1; -- = c_ip_header_len / c_word_sz
------------------------------------------------------------------------------
-- ARP Packet
--
-- 0 7 8 15 16 31 wi
-- |----------------------------------------------------------------------|
-- | Hardware Type | Protocol Type | 4
-- |----------------------------------------------------------------------|
-- | HW Addr Len | Prot Addr Len | Operation | 5
-- |----------------------------------------------------------------------|
-- | Sender Hardware Address | 6
-- | ------------------------------------|
-- | | | 7
-- |---------------------------------/ /----------------------------------|
-- | Sender Protocol Address | | 8
-- |----------------------------------- |
-- | Target Hardware Address | 9
-- |----------------------------------------------------------------------|
-- | Target Protocol Address | 10
-- |----------------------------------------------------------------------|
--
-- field widths in bits '_w' or in bytes '_len'
CONSTANT c_arp_htype_len : NATURAL := 2;
CONSTANT c_arp_htype_w : NATURAL := c_arp_htype_len*c_8;
CONSTANT c_arp_ptype_len : NATURAL := 2;
CONSTANT c_arp_ptype_w : NATURAL := c_arp_ptype_len*c_8;
CONSTANT c_arp_hlen_len : NATURAL := 1;
CONSTANT c_arp_hlen_w : NATURAL := c_arp_hlen_len*c_8;
CONSTANT c_arp_plen_len : NATURAL := 1;
CONSTANT c_arp_plen_w : NATURAL := c_arp_plen_len*c_8;
CONSTANT c_arp_oper_len : NATURAL := 2;
CONSTANT c_arp_oper_w : NATURAL := c_arp_oper_len*c_8;
-- [0:15] [16:31]
CONSTANT c_arp_data_len : NATURAL := c_arp_htype_len + c_arp_ptype_len +
c_arp_hlen_len + c_arp_plen_len + c_arp_oper_len +
c_eth_mac_addr_len + c_ip_addr_len +
c_eth_mac_addr_len + c_ip_addr_len;
-- [0:47] [0:31] = 8 + 2*(6+4) = 28
-- default field values
CONSTANT c_arp_htype : NATURAL := 1; -- Hardware type, 1=ethernet
CONSTANT c_arp_ptype : NATURAL := c_eth_type_ip; -- Protocol type, do ARP for IPv4
CONSTANT c_arp_hlen : NATURAL := c_eth_mac_addr_len; -- Hardware length = 6
CONSTANT c_arp_plen : NATURAL := c_ip_addr_len; -- Protocol length = 4
CONSTANT c_arp_oper_request : NATURAL := 1; -- Operator, 1=request
CONSTANT c_arp_oper_reply : NATURAL := 2; -- Operator, 2=reply
-- useful field values
CONSTANT c_arp_dst_mac : STD_LOGIC_VECTOR(c_eth_mac_slv'RANGE) := c_eth_bc_mac; -- Broadcast destination MAC
CONSTANT c_arp_tha : STD_LOGIC_VECTOR(c_eth_mac_slv'RANGE) := c_eth_bc_mac; -- Broadcast target hardware address
TYPE t_arp_packet IS RECORD
htype : STD_LOGIC_VECTOR(c_arp_htype_w-1 DOWNTO 0); -- 2 octet
ptype : STD_LOGIC_VECTOR(c_arp_ptype_w-1 DOWNTO 0); -- 2 octet
hlen : STD_LOGIC_VECTOR(c_arp_hlen_w-1 DOWNTO 0); -- 1 octet
plen : STD_LOGIC_VECTOR(c_arp_plen_w-1 DOWNTO 0); -- 1 octet
oper : STD_LOGIC_VECTOR(c_arp_oper_w-1 DOWNTO 0); -- 2 octet
sha : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0); -- 6 octet, Sender Hardware Address
spa : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0); -- 4 octet, Sender Protocol Address
tha : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0); -- 6 octet, Target Hardware Address
tpa : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0); -- 4 octet, Target Protocol Address
END RECORD;
-- field valid word indices
CONSTANT c_arp_lo_wi : NATURAL := 4; -- first word index
CONSTANT c_arp_htype_wi : NATURAL := 4;
CONSTANT c_arp_ptype_wi : NATURAL := 4;
CONSTANT c_arp_hlen_wi : NATURAL := 5;
CONSTANT c_arp_plen_wi : NATURAL := 5;
CONSTANT c_arp_oper_wi : NATURAL := 5;
CONSTANT c_arp_sha_wi : NATURAL := 7;
CONSTANT c_arp_spa_wi : NATURAL := 8;
CONSTANT c_arp_tha_wi : NATURAL := 9;
CONSTANT c_arp_tpa_wi : NATURAL := 10;
CONSTANT c_arp_hi_wi : NATURAL := 10; -- last word index
CONSTANT c_arp_nof_words : NATURAL := c_arp_hi_wi - c_arp_lo_wi + 1; -- = c_arp_data_len / c_word_sz
------------------------------------------------------------------------------
-- ICMP (for ping)
--
-- 0 7 8 15 16 31 wi
-- |----------------------------------------------------------------------|
-- | Type | Code | Checksum | 9
-- |----------------------------------------------------------------------|
-- | ID | Sequence | 10
-- |----------------------------------------------------------------------|
-- | |
-- | ICMP Payload (padding data) |
-- | |
-- |------------------------------------------------------------ // ------|
--
-- field widths in bits '_w' or in bytes '_len'
CONSTANT c_icmp_msg_type_len : NATURAL := 1;
CONSTANT c_icmp_msg_type_w : NATURAL := c_icmp_msg_type_len*c_8;
CONSTANT c_icmp_code_len : NATURAL := 1;
CONSTANT c_icmp_code_w : NATURAL := c_icmp_code_len*c_8;
CONSTANT c_icmp_checksum_len : NATURAL := 2;
CONSTANT c_icmp_checksum_w : NATURAL := c_icmp_checksum_len*c_8;
CONSTANT c_icmp_id_len : NATURAL := 2;
CONSTANT c_icmp_id_w : NATURAL := c_icmp_id_len*c_8;
CONSTANT c_icmp_sequence_len : NATURAL := 2;
CONSTANT c_icmp_sequence_w : NATURAL := c_icmp_sequence_len*c_8;
CONSTANT c_icmp_header_len : NATURAL := c_icmp_msg_type_len + c_icmp_code_len + c_icmp_checksum_len +
c_icmp_id_len + c_icmp_sequence_len;
-- default field values
CONSTANT c_icmp_msg_type_request : NATURAL := 8; -- 8 = echo request
CONSTANT c_icmp_msg_type_reply : NATURAL := 0; -- 8 = echo reply (ping)
CONSTANT c_icmp_checksum : NATURAL := 0; -- init value
-- useful field values
CONSTANT c_icmp_code : NATURAL := 0; -- default
CONSTANT c_icmp_id : NATURAL := 3; -- arbitrary value
CONSTANT c_icmp_sequence : NATURAL := 4; -- arbitrary value
TYPE t_icmp_header IS RECORD
msg_type : STD_LOGIC_VECTOR(c_icmp_msg_type_w-1 DOWNTO 0); -- 1 octet
code : STD_LOGIC_VECTOR(c_icmp_code_w-1 DOWNTO 0); -- 1 octet
checksum : STD_LOGIC_VECTOR(c_icmp_checksum_w-1 DOWNTO 0); -- 2 octet
id : STD_LOGIC_VECTOR(c_icmp_id_w-1 DOWNTO 0); -- 2 octet
sequence : STD_LOGIC_VECTOR(c_icmp_sequence_w-1 DOWNTO 0); -- 2 octet
END RECORD;
-- field valid word indices
CONSTANT c_icmp_lo_wi : NATURAL := 9; -- first word index
CONSTANT c_icmp_msg_type_wi : NATURAL := 9;
CONSTANT c_icmp_code_wi : NATURAL := 9;
CONSTANT c_icmp_checksum_wi : NATURAL := 9;
CONSTANT c_icmp_id_wi : NATURAL := 10;
CONSTANT c_icmp_sequence_wi : NATURAL := 10;
CONSTANT c_icmp_hi_wi : NATURAL := 10; -- last word index
CONSTANT c_icmp_nof_words : NATURAL := c_icmp_hi_wi - c_icmp_lo_wi + 1; -- = c_icmp_header_len / c_word_sz
------------------------------------------------------------------------------
-- UDP Packet
--
-- 0 15 16 31 wi
-- |----------------------------------------------------------------------|
-- | Source Port | Destination Port | 9
-- |----------------------------------------------------------------------|
-- | Total Length | Checksum | 10
-- |----------------------------------------------------------------------|
-- | |
-- | UDP Payload |
-- | |
-- |----------------------------------------------------------- // -------|
--
-- field widths in bits '_w' or in bytes '_len'
CONSTANT c_udp_port_len : NATURAL := 2;
CONSTANT c_udp_port_w : NATURAL := c_udp_port_len*c_8;
CONSTANT c_udp_total_length_len : NATURAL := 2;
CONSTANT c_udp_total_length_w : NATURAL := c_udp_total_length_len*c_8;
CONSTANT c_udp_checksum_len : NATURAL := 2;
CONSTANT c_udp_checksum_w : NATURAL := c_udp_checksum_len*c_8;
-- [0:15] [16:31]
CONSTANT c_udp_header_len : NATURAL := c_udp_port_len + c_udp_port_len +
c_udp_total_length_len + c_udp_checksum_len; -- 8
-- default field values
CONSTANT c_udp_total_length : NATURAL := 8; -- >= 8, nof bytes in entire datagram including header and data
CONSTANT c_udp_checksum : NATURAL := 0; -- init value
-- useful field values
CONSTANT c_udp_port_dhcp_in : NATURAL := 68; -- DHCP to client = Dynamic Host Configuration Protocol (for IP address assignment)
CONSTANT c_udp_port_dhcp_out : NATURAL := 67; -- DHCP to server
CONSTANT c_udp_port_slv : STD_LOGIC_VECTOR(c_udp_port_w-1 DOWNTO 0) := (OTHERS=>'X'); -- UDP port slv RANGE
TYPE t_udp_header IS RECORD
src_port : STD_LOGIC_VECTOR(c_udp_port_w-1 DOWNTO 0); -- 2 octet
dst_port : STD_LOGIC_VECTOR(c_udp_port_w-1 DOWNTO 0); -- 2 octet
total_length : STD_LOGIC_VECTOR(c_udp_total_length_w-1 DOWNTO 0); -- 2 octet
checksum : STD_LOGIC_VECTOR(c_udp_checksum_w-1 DOWNTO 0); -- 2 octet
END RECORD;
-- field valid word indices
CONSTANT c_udp_lo_wi : NATURAL := 9; -- first word index
CONSTANT c_udp_src_port_wi : NATURAL := 9;
CONSTANT c_udp_dst_port_wi : NATURAL := 9;
CONSTANT c_udp_total_length_wi : NATURAL := 10;
CONSTANT c_udp_checksum_wi : NATURAL := 10;
CONSTANT c_udp_hi_wi : NATURAL := 10; -- last word index
CONSTANT c_udp_nof_words : NATURAL := c_udp_hi_wi - c_udp_lo_wi + 1; -- = c_udp_header_len / c_word_sz
------------------------------------------------------------------------------
-- Total Ethernet Header
------------------------------------------------------------------------------
CONSTANT c_eth_total_arp_len : NATURAL := c_eth_header_len + c_arp_data_len; -- = 14 + 28 = 42
CONSTANT c_eth_total_icmp_len : NATURAL := c_eth_header_len + c_ip_header_len + c_icmp_header_len; -- = 14 + 20 + 8 = 42
CONSTANT c_eth_total_udp_len : NATURAL := c_eth_header_len + c_ip_header_len + c_udp_header_len; -- = 14 + 20 + 8 = 42
-- Hence it appears that all relevant packets have the same total header length
CONSTANT c_eth_total_header_len : NATURAL := 42;
CONSTANT c_eth_total_header_nof_words : NATURAL := (c_eth_word_align_len + c_eth_total_header_len)/4; -- = 44 / c_word_sz = 11
-- Aggregate all supported Ethernet headers into one record
TYPE t_eth_total_header IS RECORD
eth : t_eth_header;
arp : t_arp_packet;
ip : t_ip_header;
icmp : t_icmp_header;
udp : t_udp_header;
END RECORD;
-- Ethernet frame word indices
TYPE t_eth_total_header_arr IS ARRAY(0 TO c_eth_total_header_nof_words-1) OF STD_LOGIC_VECTOR(c_32-1 DOWNTO 0);
-- Combinatorial map of the total header on to the Ethernet header records
-- Type casting an array to a record is not possible, so therefore we need these functions
-- Define also the inverse mapping functions as overloaded functions
FUNCTION func_eth_map_eth_header( total_header : t_eth_total_header_arr) RETURN t_eth_header;
FUNCTION func_eth_map_eth_header( header : t_eth_header) RETURN t_eth_total_header_arr;
FUNCTION func_eth_map_ip_header( total_header : t_eth_total_header_arr) RETURN t_ip_header;
FUNCTION func_eth_map_ip_header( header : t_ip_header) RETURN t_eth_total_header_arr;
FUNCTION func_eth_map_arp_packet( total_header : t_eth_total_header_arr) RETURN t_arp_packet;
FUNCTION func_eth_map_arp_packet( header : t_arp_packet) RETURN t_eth_total_header_arr;
FUNCTION func_eth_map_icmp_header(total_header : t_eth_total_header_arr) RETURN t_icmp_header;
FUNCTION func_eth_map_icmp_header(header : t_icmp_header) RETURN t_eth_total_header_arr;
FUNCTION func_eth_map_udp_header( total_header : t_eth_total_header_arr) RETURN t_udp_header;
FUNCTION func_eth_map_udp_header( header : t_udp_header) RETURN t_eth_total_header_arr;
-- Construct the total header array from the individual header records
FUNCTION func_eth_arp_total_header( eth : t_eth_header; arp : t_arp_packet) RETURN t_eth_total_header_arr;
FUNCTION func_eth_icmp_total_header(eth : t_eth_header; ip : t_ip_header; icmp : t_icmp_header) RETURN t_eth_total_header_arr;
FUNCTION func_eth_udp_total_header( eth : t_eth_header; ip : t_ip_header; udp : t_udp_header) RETURN t_eth_total_header_arr;
-- Construct the response headers
FUNCTION func_eth_response_header( eth : t_eth_total_header_arr; mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr;
FUNCTION func_eth_arp_response_header( arp : t_eth_total_header_arr; mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0))
RETURN t_eth_total_header_arr;
FUNCTION func_eth_ip_response_header( ip : t_eth_total_header_arr; mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr;
FUNCTION func_eth_icmp_response_header(icmp : t_eth_total_header_arr; mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr;
FUNCTION func_eth_udp_response_header( udp : t_eth_total_header_arr; mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr;
END eth_layers_pkg;
PACKAGE BODY eth_layers_pkg IS
------------------------------------------------------------------------------
-- Total Ethernet Header
------------------------------------------------------------------------------
-- * Map the 11 words from the Ethernet header to the Ethernet field records
-- * Define also the inverse mapping functions, leave unused v_total words 'X'
-- * Outside this package use the c_*_lo_wi and c_*_hi_wi constants to select
-- the used words from the total header word array.
FUNCTION func_eth_map_eth_header(total_header : t_eth_total_header_arr) RETURN t_eth_header IS
VARIABLE v_hdr : t_eth_header;
BEGIN
v_hdr.word_align := total_header(0)(31 DOWNTO 16);
v_hdr.dst_mac(47 DOWNTO 32) := total_header(0)(15 DOWNTO 0);
v_hdr.dst_mac(31 DOWNTO 0) := total_header(1);
v_hdr.src_mac(47 DOWNTO 16) := total_header(2);
v_hdr.src_mac(15 DOWNTO 0) := total_header(3)(31 DOWNTO 16);
v_hdr.eth_type := total_header(3)(15 DOWNTO 0);
RETURN v_hdr;
END;
FUNCTION func_eth_map_eth_header(header : t_eth_header) RETURN t_eth_total_header_arr IS
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
v_total(0)(31 DOWNTO 16) := header.word_align;
v_total(0)(15 DOWNTO 0) := header.dst_mac(47 DOWNTO 32);
v_total(1) := header.dst_mac(31 DOWNTO 0);
v_total(2) := header.src_mac(47 DOWNTO 16);
v_total(3)(31 DOWNTO 16) := header.src_mac(15 DOWNTO 0);
v_total(3)(15 DOWNTO 0) := header.eth_type;
RETURN v_total;
END;
FUNCTION func_eth_map_ip_header(total_header : t_eth_total_header_arr) RETURN t_ip_header IS
VARIABLE v_hdr : t_ip_header;
BEGIN
v_hdr.version := total_header(4)(31 DOWNTO 28);
v_hdr.header_length := total_header(4)(27 DOWNTO 24);
v_hdr.services := total_header(4)(23 DOWNTO 16);
v_hdr.total_length := total_header(4)(15 DOWNTO 0);
v_hdr.identification := total_header(5)(31 DOWNTO 16);
v_hdr.flags := total_header(5)(15 DOWNTO 13);
v_hdr.fragment_offset := total_header(5)(12 DOWNTO 0);
v_hdr.time_to_live := total_header(6)(31 DOWNTO 24);
v_hdr.protocol := total_header(6)(23 DOWNTO 16);
v_hdr.header_checksum := total_header(6)(15 DOWNTO 0);
v_hdr.src_ip_addr := total_header(7);
v_hdr.dst_ip_addr := total_header(8);
RETURN v_hdr;
END;
FUNCTION func_eth_map_ip_header(header : t_ip_header) RETURN t_eth_total_header_arr IS
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
v_total(4)(31 DOWNTO 28) := header.version;
v_total(4)(27 DOWNTO 24) := header.header_length;
v_total(4)(23 DOWNTO 16) := header.services;
v_total(4)(15 DOWNTO 0) := header.total_length;
v_total(5)(31 DOWNTO 16) := header.identification;
v_total(5)(15 DOWNTO 13) := header.flags;
v_total(5)(12 DOWNTO 0) := header.fragment_offset;
v_total(6)(31 DOWNTO 24) := header.time_to_live;
v_total(6)(23 DOWNTO 16) := header.protocol;
v_total(6)(15 DOWNTO 0) := header.header_checksum;
v_total(7) := header.src_ip_addr;
v_total(8) := header.dst_ip_addr;
RETURN v_total;
END;
FUNCTION func_eth_map_arp_packet(total_header : t_eth_total_header_arr) RETURN t_arp_packet IS
VARIABLE v_arp : t_arp_packet;
BEGIN
v_arp.htype := total_header(4)(31 DOWNTO 16);
v_arp.ptype := total_header(4)(15 DOWNTO 0);
v_arp.hlen := total_header(5)(31 DOWNTO 24);
v_arp.plen := total_header(5)(23 DOWNTO 16);
v_arp.oper := total_header(5)(15 DOWNTO 0);
v_arp.sha(47 DOWNTO 16) := total_header(6);
v_arp.sha(15 DOWNTO 0) := total_header(7)(31 DOWNTO 16);
v_arp.spa(31 DOWNTO 16) := total_header(7)(15 DOWNTO 0);
v_arp.spa(15 DOWNTO 0) := total_header(8)(31 DOWNTO 16);
v_arp.tha(47 DOWNTO 32) := total_header(8)(15 DOWNTO 0);
v_arp.tha(31 DOWNTO 0) := total_header(9);
v_arp.tpa := total_header(10);
RETURN v_arp;
END;
FUNCTION func_eth_map_arp_packet(header : t_arp_packet) RETURN t_eth_total_header_arr IS
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
v_total(4)(31 DOWNTO 16) := header.htype;
v_total(4)(15 DOWNTO 0) := header.ptype;
v_total(5)(31 DOWNTO 24) := header.hlen;
v_total(5)(23 DOWNTO 16) := header.plen;
v_total(5)(15 DOWNTO 0) := header.oper;
v_total(6) := header.sha(47 DOWNTO 16);
v_total(7)(31 DOWNTO 16) := header.sha(15 DOWNTO 0);
v_total(7)(15 DOWNTO 0) := header.spa(31 DOWNTO 16);
v_total(8)(31 DOWNTO 16) := header.spa(15 DOWNTO 0);
v_total(8)(15 DOWNTO 0) := header.tha(47 DOWNTO 32);
v_total(9) := header.tha(31 DOWNTO 0);
v_total(10) := header.tpa;
RETURN v_total;
END;
FUNCTION func_eth_map_icmp_header(total_header : t_eth_total_header_arr) RETURN t_icmp_header IS
VARIABLE v_hdr : t_icmp_header;
BEGIN
v_hdr.msg_type := total_header(9)(31 DOWNTO 24);
v_hdr.code := total_header(9)(23 DOWNTO 16);
v_hdr.checksum := total_header(9)(15 DOWNTO 0);
v_hdr.id := total_header(10)(31 DOWNTO 16);
v_hdr.sequence := total_header(10)(15 DOWNTO 0);
RETURN v_hdr;
END;
FUNCTION func_eth_map_icmp_header(header : t_icmp_header) RETURN t_eth_total_header_arr IS
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
v_total(9)(31 DOWNTO 24) := header.msg_type;
v_total(9)(23 DOWNTO 16) := header.code;
v_total(9)(15 DOWNTO 0) := header.checksum;
v_total(10)(31 DOWNTO 16) := header.id;
v_total(10)(15 DOWNTO 0) := header.sequence;
RETURN v_total;
END;
FUNCTION func_eth_map_udp_header(total_header : t_eth_total_header_arr) RETURN t_udp_header IS
VARIABLE v_hdr : t_udp_header;
BEGIN
v_hdr.src_port := total_header(9)(31 DOWNTO 16);
v_hdr.dst_port := total_header(9)(15 DOWNTO 0);
v_hdr.total_length := total_header(10)(31 DOWNTO 16);
v_hdr.checksum := total_header(10)(15 DOWNTO 0);
RETURN v_hdr;
END;
FUNCTION func_eth_map_udp_header(header : t_udp_header) RETURN t_eth_total_header_arr IS
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
v_total(9)(31 DOWNTO 16) := header.src_port;
v_total(9)(15 DOWNTO 0) := header.dst_port;
v_total(10)(31 DOWNTO 16) := header.total_length;
v_total(10)(15 DOWNTO 0) := header.checksum;
RETURN v_total;
END;
-- Construct the total header array from the individual header records
FUNCTION func_eth_arp_total_header(eth : t_eth_header; arp : t_arp_packet) RETURN t_eth_total_header_arr IS
CONSTANT c_eth : t_eth_total_header_arr := func_eth_map_eth_header(eth);
CONSTANT c_arp : t_eth_total_header_arr := func_eth_map_arp_packet(arp);
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
FOR I IN c_eth_lo_wi TO c_eth_hi_wi LOOP
v_total(I) := c_eth(I);
END LOOP;
FOR I IN c_arp_lo_wi TO c_arp_hi_wi LOOP
v_total(I) := c_arp(I);
END LOOP;
RETURN v_total;
END;
FUNCTION func_eth_icmp_total_header(eth : t_eth_header; ip : t_ip_header; icmp : t_icmp_header) RETURN t_eth_total_header_arr IS
CONSTANT c_eth : t_eth_total_header_arr := func_eth_map_eth_header(eth);
CONSTANT c_ip : t_eth_total_header_arr := func_eth_map_ip_header(ip);
CONSTANT c_icmp : t_eth_total_header_arr := func_eth_map_icmp_header(icmp);
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
FOR I IN c_eth_lo_wi TO c_eth_hi_wi LOOP
v_total(I) := c_eth(I);
END LOOP;
FOR I IN c_ip_lo_wi TO c_ip_hi_wi LOOP
v_total(I) := c_ip(I);
END LOOP;
FOR I IN c_icmp_lo_wi TO c_icmp_hi_wi LOOP
v_total(I) := c_icmp(I);
END LOOP;
RETURN v_total;
END;
FUNCTION func_eth_udp_total_header( eth : t_eth_header; ip : t_ip_header; udp : t_udp_header) RETURN t_eth_total_header_arr IS
CONSTANT c_eth : t_eth_total_header_arr := func_eth_map_eth_header(eth);
CONSTANT c_ip : t_eth_total_header_arr := func_eth_map_ip_header(ip);
CONSTANT c_udp : t_eth_total_header_arr := func_eth_map_udp_header(udp);
VARIABLE v_total : t_eth_total_header_arr;
BEGIN
FOR I IN c_eth_lo_wi TO c_eth_hi_wi LOOP
v_total(I) := c_eth(I);
END LOOP;
FOR I IN c_ip_lo_wi TO c_ip_hi_wi LOOP
v_total(I) := c_ip(I);
END LOOP;
FOR I IN c_udp_lo_wi TO c_udp_hi_wi LOOP
v_total(I) := c_udp(I);
END LOOP;
RETURN v_total;
END;
-- Construct the response headers
FUNCTION func_eth_response_header(eth : t_eth_total_header_arr;
mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr IS
VARIABLE v_response : t_eth_total_header_arr;
BEGIN
-- Default
v_response := eth;
-- ETH
-- . use input src mac for dst mac
v_response(0)(15 DOWNTO 0) := eth(2)(31 DOWNTO 16);
v_response(1) := eth(2)(15 DOWNTO 0) & eth(3)(31 DOWNTO 16);
-- . force eth src mac to this node mac address (because the input dst_mac can be via eth broadcast mac)
v_response(2) := mac_addr(47 DOWNTO 16);
v_response(3)(31 DOWNTO 16) := mac_addr(15 DOWNTO 0);
RETURN v_response;
END;
FUNCTION func_eth_arp_response_header(arp : t_eth_total_header_arr;
mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_ip_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr IS
VARIABLE v_response : t_eth_total_header_arr;
BEGIN
-- ETH
v_response := func_eth_response_header(arp, mac_addr);
-- ARP
-- . force operation arp reply
v_response(5)(15 DOWNTO 0) := TO_UVEC(c_arp_oper_reply, 16);
-- . force sha to this node mac address
v_response(6) := mac_addr(47 DOWNTO 16);
v_response(7)(31 DOWNTO 16) := mac_addr(15 DOWNTO 0);
-- . force spa to this node ip address
v_response(7)(15 DOWNTO 0) := ip_addr(31 DOWNTO 16);
v_response(8)(31 DOWNTO 16) := ip_addr(15 DOWNTO 0);
-- . use input sha for tha
v_response(8)(15 DOWNTO 0) := arp(6)(31 DOWNTO 16);
v_response(9) := arp(6)(15 DOWNTO 0) & arp(7)(31 DOWNTO 16);
-- . use input spa for tpa
v_response(10) := arp(7)(15 DOWNTO 0) & arp(8)(31 DOWNTO 16);
RETURN v_response;
END;
FUNCTION func_eth_ip_response_header(ip : t_eth_total_header_arr;
mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr IS
VARIABLE v_response : t_eth_total_header_arr;
BEGIN
-- ETH
v_response := func_eth_response_header(ip, mac_addr);
-- IP
-- . force ip header checksum to 0
v_response(6)(15 DOWNTO 0) := TO_UVEC(0, 16);
-- . swap ip dst_addr and ip src_addr
v_response(7) := ip(8);
v_response(8) := ip(7);
RETURN v_response;
END;
FUNCTION func_eth_icmp_response_header(icmp : t_eth_total_header_arr;
mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr IS
VARIABLE v_response : t_eth_total_header_arr;
BEGIN
-- ETH, IP
v_response := func_eth_ip_response_header(icmp, mac_addr);
-- ICMP : force type to icmp reply
v_response(9)(31 DOWNTO 24) := TO_UVEC(c_icmp_msg_type_reply, 8);
-- ICMP : force icmp checksum to 0
v_response(9)(15 DOWNTO 0) := TO_UVEC(0, 16);
RETURN v_response;
END;
FUNCTION func_eth_udp_response_header(udp : t_eth_total_header_arr;
mac_addr : STD_LOGIC_VECTOR(c_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_eth_total_header_arr IS
VARIABLE v_response : t_eth_total_header_arr;
BEGIN
-- ETH, IP
v_response := func_eth_ip_response_header(udp, mac_addr);
-- UDP : swap udp dst port and udp src port
v_response(9) := udp(9)(15 DOWNTO 0) & udp(9)(31 DOWNTO 16);
-- UDP : force udp checksum to 0
v_response(10)(15 DOWNTO 0) := TO_UVEC(0, 16);
RETURN v_response;
END;
END eth_layers_pkg;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment