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

Merge branch 'L2SDP-23' into 'master'

Resolve L2SDP-23

Closes L2SDP-23

See merge request desp/hdl!9
parents 34e09755 3f044e04
No related branches found
No related tags found
2 merge requests!10Update branch to latest revision,!9Resolve L2SDP-23
Showing
with 2664 additions and 53 deletions
...@@ -223,6 +223,18 @@ PACKAGE common_network_total_header_pkg IS ...@@ -223,6 +223,18 @@ PACKAGE common_network_total_header_pkg IS
FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header; FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header;
FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header; FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header;
-- Combinatorial map just as above but for network packets without word align field.
FUNCTION func_network_total_header_no_align_extract_eth( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_eth_header;
FUNCTION func_network_total_header_no_align_extract_eth( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_eth_header;
FUNCTION func_network_total_header_no_align_extract_ip( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_ip_header;
FUNCTION func_network_total_header_no_align_extract_ip( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_ip_header;
FUNCTION func_network_total_header_no_align_extract_arp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_arp_packet;
FUNCTION func_network_total_header_no_align_extract_arp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_arp_packet;
FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_icmp_header;
FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_icmp_header;
FUNCTION func_network_total_header_no_align_extract_udp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header;
FUNCTION func_network_total_header_no_align_extract_udp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header;
-- Construct the total header array from the individual header records -- Construct the total header array from the individual header records
FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_32b_arr; -- sets unused words to zero FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_32b_arr; -- sets unused words to zero
FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_64b_arr; -- sets unused words to zero FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_64b_arr; -- sets unused words to zero
...@@ -251,6 +263,25 @@ PACKAGE common_network_total_header_pkg IS ...@@ -251,6 +263,25 @@ PACKAGE common_network_total_header_pkg IS
FUNCTION func_network_total_header_response_udp( udp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr; FUNCTION func_network_total_header_response_udp( udp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_response_udp( udp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr; FUNCTION func_network_total_header_response_udp( udp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
-- Construct the response total header array for a total header array without alignment bytes
FUNCTION func_network_total_header_no_align_response_eth( eth_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_no_align_response_eth( eth_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
FUNCTION func_network_total_header_no_align_response_arp( arp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0))
RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_no_align_response_arp( arp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0))
RETURN t_network_total_header_64b_arr;
FUNCTION func_network_total_header_no_align_response_ip( ip_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_no_align_response_ip( ip_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
FUNCTION func_network_total_header_no_align_response_udp( udp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
FUNCTION func_network_total_header_no_align_response_udp( udp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
END common_network_total_header_pkg; END common_network_total_header_pkg;
...@@ -397,6 +428,146 @@ PACKAGE BODY common_network_total_header_pkg IS ...@@ -397,6 +428,146 @@ PACKAGE BODY common_network_total_header_pkg IS
RETURN v_hdr; RETURN v_hdr;
END; END;
-- Assume the total header has NOT been padded with the word align field
-- Map the 11 32b words or 6 64b longwords from the total header to the header field records
FUNCTION func_network_total_header_no_align_extract_eth(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_eth_header IS
VARIABLE v_hdr : t_network_eth_header;
BEGIN
v_hdr.dst_mac(47 DOWNTO 16) := hdr_arr(0);
v_hdr.dst_mac(15 DOWNTO 0) := hdr_arr(1)(31 DOWNTO 16);
v_hdr.src_mac(47 DOWNTO 32) := hdr_arr(1)(15 DOWNTO 0);
v_hdr.src_mac(31 DOWNTO 0) := hdr_arr(2);
v_hdr.eth_type := hdr_arr(3)(31 DOWNTO 16);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_eth(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_eth_header IS
VARIABLE v_hdr : t_network_eth_header;
BEGIN
v_hdr.dst_mac := hdr_arr(0)(63 DOWNTO 16);
v_hdr.src_mac(47 DOWNTO 32) := hdr_arr(0)(15 DOWNTO 0);
v_hdr.src_mac(31 DOWNTO 0) := hdr_arr(1)(63 DOWNTO 32);
v_hdr.eth_type := hdr_arr(1)(31 DOWNTO 16);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_ip(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_ip_header IS
VARIABLE v_hdr : t_network_ip_header;
BEGIN
v_hdr.version := hdr_arr(3)(15 DOWNTO 12);
v_hdr.header_length := hdr_arr(3)(11 DOWNTO 8);
v_hdr.services := hdr_arr(3)( 7 DOWNTO 0);
v_hdr.total_length := hdr_arr(4)(31 DOWNTO 16);
v_hdr.identification := hdr_arr(4)(15 DOWNTO 0);
v_hdr.flags := hdr_arr(5)(31 DOWNTO 29);
v_hdr.fragment_offset := hdr_arr(5)(28 DOWNTO 16);
v_hdr.time_to_live := hdr_arr(5)(15 DOWNTO 8);
v_hdr.protocol := hdr_arr(5)( 7 DOWNTO 0);
v_hdr.header_checksum := hdr_arr(6)(31 DOWNTO 16);
v_hdr.src_ip_addr(31 DOWNTO 16) := hdr_arr(6)(15 DOWNTO 0);
v_hdr.src_ip_addr(15 DOWNTO 0) := hdr_arr(7)(31 DOWNTO 16);
v_hdr.dst_ip_addr(31 DOWNTO 16) := hdr_arr(7)(15 DOWNTO 0);
v_hdr.dst_ip_addr(15 DOWNTO 0) := hdr_arr(8)(31 DOWNTO 16);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_ip(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_ip_header IS
VARIABLE v_hdr : t_network_ip_header;
BEGIN
v_hdr.version := hdr_arr(1)(15 DOWNTO 12);
v_hdr.header_length := hdr_arr(1)(11 DOWNTO 8);
v_hdr.services := hdr_arr(1)( 7 DOWNTO 0);
v_hdr.total_length := hdr_arr(2)(63 DOWNTO 48);
v_hdr.identification := hdr_arr(2)(47 DOWNTO 32);
v_hdr.flags := hdr_arr(2)(31 DOWNTO 29);
v_hdr.fragment_offset := hdr_arr(2)(28 DOWNTO 16);
v_hdr.time_to_live := hdr_arr(2)(15 DOWNTO 8);
v_hdr.protocol := hdr_arr(2)( 7 DOWNTO 0);
v_hdr.header_checksum := hdr_arr(3)(63 DOWNTO 48);
v_hdr.src_ip_addr := hdr_arr(3)(47 DOWNTO 16);
v_hdr.dst_ip_addr(31 DOWNTO 16) := hdr_arr(3)(15 DOWNTO 0);
v_hdr.dst_ip_addr(15 DOWNTO 0) := hdr_arr(4)(63 DOWNTO 48);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_arp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_arp_packet IS
VARIABLE v_arp : t_network_arp_packet;
BEGIN
v_arp.htype := hdr_arr(3)(15 DOWNTO 0);
v_arp.ptype := hdr_arr(4)(31 DOWNTO 16);
v_arp.hlen := hdr_arr(4)(15 DOWNTO 8);
v_arp.plen := hdr_arr(4)( 7 DOWNTO 0);
v_arp.oper := hdr_arr(5)(31 DOWNTO 16);
v_arp.sha(47 DOWNTO 32) := hdr_arr(5)(15 DOWNTO 0);
v_arp.sha(31 DOWNTO 0) := hdr_arr(6);
v_arp.spa := hdr_arr(7);
v_arp.tha(47 DOWNTO 16) := hdr_arr(8);
v_arp.tha(15 DOWNTO 0) := hdr_arr(9)(31 DOWNTO 16);
v_arp.tpa(31 DOWNTO 16) := hdr_arr(9)(15 DOWNTO 0);
v_arp.tpa(15 DOWNTO 0) := hdr_arr(9)(31 DOWNTO 16);
RETURN v_arp;
END;
FUNCTION func_network_total_header_no_align_extract_arp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_arp_packet IS
VARIABLE v_arp : t_network_arp_packet;
BEGIN
v_arp.htype := hdr_arr(1)(15 DOWNTO 0);
v_arp.ptype := hdr_arr(2)(63 DOWNTO 48);
v_arp.hlen := hdr_arr(2)(47 DOWNTO 40);
v_arp.plen := hdr_arr(2)(39 DOWNTO 32);
v_arp.oper := hdr_arr(2)(31 DOWNTO 16);
v_arp.sha(47 DOWNTO 32) := hdr_arr(2)(15 DOWNTO 0);
v_arp.sha(31 DOWNTO 0) := hdr_arr(3)(63 DOWNTO 32);
v_arp.spa := hdr_arr(3)(31 DOWNTO 0);
v_arp.tha := hdr_arr(4)(63 DOWNTO 16);
v_arp.tpa(31 DOWNTO 16) := hdr_arr(4)(15 DOWNTO 0);
v_arp.tpa(15 DOWNTO 0) := hdr_arr(5)(63 DOWNTO 48);
RETURN v_arp;
END;
FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_icmp_header IS
VARIABLE v_hdr : t_network_icmp_header;
BEGIN
v_hdr.msg_type := hdr_arr(8)(15 DOWNTO 8);
v_hdr.code := hdr_arr(8)( 7 DOWNTO 0);
v_hdr.checksum := hdr_arr(9)(31 DOWNTO 16);
v_hdr.id := hdr_arr(9)(15 DOWNTO 0);
v_hdr.sequence := hdr_arr(10)(31 DOWNTO 16);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_icmp_header IS
VARIABLE v_hdr : t_network_icmp_header;
BEGIN
v_hdr.msg_type := hdr_arr(4)(47 DOWNTO 40);
v_hdr.code := hdr_arr(4)(39 DOWNTO 32);
v_hdr.checksum := hdr_arr(4)(31 DOWNTO 16);
v_hdr.id := hdr_arr(4)(15 DOWNTO 0);
v_hdr.sequence := hdr_arr(5)(63 DOWNTO 48);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_udp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header IS
VARIABLE v_hdr : t_network_udp_header;
BEGIN
v_hdr.src_port := hdr_arr(8)(15 DOWNTO 0);
v_hdr.dst_port := hdr_arr(9)(31 DOWNTO 16);
v_hdr.total_length := hdr_arr(9)(15 DOWNTO 0);
v_hdr.checksum := hdr_arr(10)(31 DOWNTO 16);
RETURN v_hdr;
END;
FUNCTION func_network_total_header_no_align_extract_udp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header IS
VARIABLE v_hdr : t_network_udp_header;
BEGIN
v_hdr.src_port := hdr_arr(4)(47 DOWNTO 32);
v_hdr.dst_port := hdr_arr(4)(31 DOWNTO 16);
v_hdr.total_length := hdr_arr(4)(15 DOWNTO 0);
v_hdr.checksum := hdr_arr(5)(63 DOWNTO 48);
RETURN v_hdr;
END;
-- Construct the total header array from the individual header records -- Construct the total header array from the individual header records
FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_32b_arr IS FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_32b_arr IS
VARIABLE v_total : t_network_total_header_32b_arr := (OTHERS=>(OTHERS=>'0')); VARIABLE v_total : t_network_total_header_32b_arr := (OTHERS=>(OTHERS=>'0'));
...@@ -713,4 +884,173 @@ PACKAGE BODY common_network_total_header_pkg IS ...@@ -713,4 +884,173 @@ PACKAGE BODY common_network_total_header_pkg IS
RETURN v_response; RETURN v_response;
END; END;
-- Construct the response headers for headers without word align padding
FUNCTION func_network_total_header_no_align_response_eth(eth_arr : t_network_total_header_32b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
VARIABLE v_response : t_network_total_header_32b_arr;
BEGIN
-- Default
v_response := eth_arr;
-- ETH
-- . use input src mac for dst mac
v_response(0) := eth_arr(1)(15 DOWNTO 0) & eth_arr(2)(31 DOWNTO 16);
v_response(1)(31 DOWNTO 16) := eth_arr(2)(15 DOWNTO 0);
-- . force eth src mac to this node mac address (because the input dst_mac can be via eth broadcast mac)
v_response(1)(15 DOWNTO 0) := mac_addr(47 DOWNTO 32);
v_response(2) := mac_addr(31 DOWNTO 0);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_eth(eth_arr : t_network_total_header_64b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
VARIABLE v_response : t_network_total_header_64b_arr;
BEGIN
-- Default
v_response := eth_arr;
-- ETH
-- . use input src mac for dst mac
v_response(0)(63 DOWNTO 16) := eth_arr(0)(15 DOWNTO 0) & eth_arr(1)(63 DOWNTO 32);
-- . force eth src mac to this node mac address (because the input dst_mac can be via eth broadcast mac)
v_response(0)(15 DOWNTO 0) := mac_addr(47 DOWNTO 32);
v_response(1)(63 DOWNTO 32) := mac_addr(31 DOWNTO 0);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_arp(arp_arr : t_network_total_header_32b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
VARIABLE v_response : t_network_total_header_32b_arr;
BEGIN
-- ETH
v_response := func_network_total_header_no_align_response_eth(arp_arr, mac_addr);
-- ARP
-- . force operation arp reply
v_response(5)(15 DOWNTO 0) := TO_UVEC(c_network_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_arr(6)(31 DOWNTO 16);
v_response(9) := arp_arr(6)(15 DOWNTO 0) & arp_arr(7)(31 DOWNTO 16);
-- . use input spa for tpa
v_response(10) := arp_arr(7)(15 DOWNTO 0) & arp_arr(8)(31 DOWNTO 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_arp(arp_arr : t_network_total_header_64b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
ip_addr : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
VARIABLE v_response : t_network_total_header_64b_arr;
BEGIN
-- ETH
v_response := func_network_total_header_no_align_response_eth(arp_arr, mac_addr);
-- ARP
-- . force operation arp reply
v_response(3)(47 DOWNTO 32) := TO_UVEC(c_network_arp_oper_reply, 16);
-- . force sha to this node mac address
v_response(3)(31 DOWNTO 0) := mac_addr(47 DOWNTO 16);
v_response(4)(63 DOWNTO 48) := mac_addr(15 DOWNTO 0);
-- . force spa to this node ip address
v_response(4)(47 DOWNTO 16) := ip_addr(31 DOWNTO 0);
-- . use input sha for tha
v_response(4)(15 DOWNTO 0) := arp_arr(3)(31 DOWNTO 16);
v_response(5)(63 DOWNTO 32) := arp_arr(3)(15 DOWNTO 0) & arp_arr(4)(63 DOWNTO 48);
-- . use input spa for tpa
v_response(5)(31 DOWNTO 0) := arp_arr(4)(47 DOWNTO 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_ip(ip_arr : t_network_total_header_32b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
VARIABLE v_response : t_network_total_header_32b_arr;
BEGIN
-- ETH
v_response := func_network_total_header_no_align_response_eth(ip_arr, mac_addr);
-- IP
-- . force ip header checksum to 0
v_response(6)(31 DOWNTO 16) := TO_UVEC(0, 16);
-- . swap ip dst_addr and ip src_addr
v_response(6)(15 DOWNTO 0) := ip_arr(7)(15 DOWNTO 0);
v_response(7)(31 DOWNTO 16) := ip_arr(8)(31 DOWNTO 16);
v_response(7)(15 DOWNTO 0) := ip_arr(6)(15 DOWNTO 0);
v_response(8)(31 DOWNTO 16) := ip_arr(7)(31 DOWNTO 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_ip(ip_arr : t_network_total_header_64b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
VARIABLE v_response : t_network_total_header_64b_arr;
BEGIN
-- ETH
v_response := func_network_total_header_no_align_response_eth(ip_arr, mac_addr);
-- IP
-- . force ip header checksum to 0
v_response(3)(63 DOWNTO 48) := TO_UVEC(0, 16);
-- . swap ip dst_addr and ip src_addr
v_response(3)(47 DOWNTO 16) := ip_arr(3)(15 DOWNTO 0) & ip_arr(4)(63 DOWNTO 48);
v_response(3)(15 DOWNTO 0) := ip_arr(3)(47 DOWNTO 32);
v_response(4)(63 DOWNTO 48) := ip_arr(3)(31 DOWNTO 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_32b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
VARIABLE v_response : t_network_total_header_32b_arr;
BEGIN
-- ETH, IP
v_response := func_network_total_header_no_align_response_ip(icmp_arr, mac_addr);
-- ICMP : force type to icmp reply
v_response(8)(15 DOWNTO 8) := TO_UVEC(c_network_icmp_msg_type_reply, 8);
-- ICMP : force icmp checksum to 0
v_response(9)(31 DOWNTO 16) := TO_UVEC(0, 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_64b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
VARIABLE v_response : t_network_total_header_64b_arr;
BEGIN
-- ETH, IP
v_response := func_network_total_header_no_align_response_ip(icmp_arr, mac_addr);
-- ICMP : force type to icmp reply
v_response(4)(47 DOWNTO 40) := TO_UVEC(c_network_icmp_msg_type_reply, 8);
-- ICMP : force icmp checksum to 0
v_response(4)(31 DOWNTO 16) := TO_UVEC(0, 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_udp(udp_arr : t_network_total_header_32b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
VARIABLE v_response : t_network_total_header_32b_arr;
BEGIN
-- ETH, IP
v_response := func_network_total_header_no_align_response_ip(udp_arr, mac_addr);
-- UDP : swap udp dst port and udp src port
v_response(9) := udp_arr(9)(15 DOWNTO 0) & udp_arr(9)(31 DOWNTO 16);
-- UDP : force udp checksum to 0
v_response(10)(15 DOWNTO 0) := TO_UVEC(0, 16);
RETURN v_response;
END;
FUNCTION func_network_total_header_no_align_response_udp(udp_arr : t_network_total_header_64b_arr;
mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
VARIABLE v_response : t_network_total_header_64b_arr;
BEGIN
-- ETH, IP
v_response := func_network_total_header_no_align_response_ip(udp_arr, mac_addr);
-- UDP : swap udp dst port and udp src port
v_response(5)(63 DOWNTO 32) := udp_arr(5)(47 DOWNTO 32) & udp_arr(5)(63 DOWNTO 48);
-- UDP : force udp checksum to 0
v_response(5)(15 DOWNTO 0) := TO_UVEC(0, 16);
RETURN v_response;
END;
END common_network_total_header_pkg; END common_network_total_header_pkg;
...@@ -128,6 +128,7 @@ synth_files = ...@@ -128,6 +128,7 @@ synth_files =
src/vhdl/dp_field_blk.vhd src/vhdl/dp_field_blk.vhd
src/vhdl/dp_concat_field_blk.vhd src/vhdl/dp_concat_field_blk.vhd
src/vhdl/dp_offload_tx.vhd src/vhdl/dp_offload_tx.vhd
src/vhdl/dp_offload_tx_v3.vhd
src/vhdl/dp_offload_rx_filter.vhd src/vhdl/dp_offload_rx_filter.vhd
src/vhdl/dp_offload_rx_filter_mm.vhd src/vhdl/dp_offload_rx_filter_mm.vhd
src/vhdl/dp_offload_rx.vhd src/vhdl/dp_offload_rx.vhd
...@@ -289,6 +290,7 @@ test_bench_files = ...@@ -289,6 +290,7 @@ test_bench_files =
tb/vhdl/tb_tb_dp_xonoff.vhd tb/vhdl/tb_tb_dp_xonoff.vhd
tb/vhdl/tb_tb_tb_dp_backpressure.vhd tb/vhdl/tb_tb_tb_dp_backpressure.vhd
tb/vhdl/tb_dp_offload_tx_v3.vhd
tb/vhdl/tb_dp_offload_rx_filter.vhd tb/vhdl/tb_dp_offload_rx_filter.vhd
regression_test_vhdl = regression_test_vhdl =
......
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- --
-- Copyright (C) 2019 -- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
-- --
-- This program is free software: you can redistribute it and/or modify -- Licensed under the Apache License, Version 2.0 (the "License");
-- it under the terms of the GNU General Public License as published by -- you may not use this file except in compliance with the License.
-- the Free Software Foundation, either version 3 of the License, or -- You may obtain a copy of the License at
-- (at your option) any later version.
-- --
-- This program is distributed in the hope that it will be useful, -- http://www.apache.org/licenses/LICENSE-2.0
-- 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 -- Unless required by applicable law or agreed to in writing, software
-- along with this program. If not, see <http://www.gnu.org/licenses/>. -- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: -- Purpose:
-- The FIFO starts outputting data when the output is ready and it has been -- The FIFO starts outputting data when the output is ready and it has been
-- filled with more than g_fifo_fill words or an eop signal has been received. -- filled with more than g_fifo_fill words or an eop signal has been received.
-- Given a fixed frame length, this is useful when the in_val is throttled while -- This is useful when the in_val is throttled while the out_val should not be
-- the out_val should not be inactive valid between out_sop to out_eop. -- inactive valid between out_sop to out_eop. This is necessary for frame
-- This is necessary for frame transport over a PHY link without separate data -- transport over a PHY link without separate data valid signal.
-- valid signal.
-- Description: -- Description:
-- Modified version of dp_fifo_fill_core. In addition to a frame being available -- Modified version of dp_fifo_fill_core. In addition to a frame being available
-- after the fifo has been filled sufficiently, a frame is also available when -- after the fifo has been filled sufficiently, a frame is also available when
-- the in_eop has been received earlier than the specified g_fifo_fill. For -- the in_eop has been received earlier than the specified g_fifo_fill. For
-- more details, please consult the description of dp_fill_fifo_core. -- more details, please consult the description of dp_fill_fifo_core.
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, technology_lib; LIBRARY IEEE, common_lib, technology_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
...@@ -82,7 +84,6 @@ ENTITY dp_fifo_fill_eop IS ...@@ -82,7 +84,6 @@ ENTITY dp_fifo_fill_eop IS
); );
END dp_fifo_fill_eop; END dp_fifo_fill_eop;
ARCHITECTURE rtl OF dp_fifo_fill_eop IS ARCHITECTURE rtl OF dp_fifo_fill_eop IS
CONSTANT c_fifo_rl : NATURAL := sel_a_b(g_fifo_fill=0, 1, g_fifo_rl); CONSTANT c_fifo_rl : NATURAL := sel_a_b(g_fifo_fill=0, 1, g_fifo_rl);
...@@ -100,6 +101,8 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS ...@@ -100,6 +101,8 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
CONSTANT s_output : STD_LOGIC_VECTOR(1 DOWNTO 0) := "10"; CONSTANT s_output : STD_LOGIC_VECTOR(1 DOWNTO 0) := "10";
CONSTANT s_xoff : STD_LOGIC_VECTOR(1 DOWNTO 0) := "11"; CONSTANT s_xoff : STD_LOGIC_VECTOR(1 DOWNTO 0) := "11";
CONSTANT c_nof_spulse : NATURAL := 3;
SIGNAL state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state SIGNAL state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state
SIGNAL nxt_state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state SIGNAL nxt_state : STD_LOGIC_VECTOR(1 DOWNTO 0); -- t_state
...@@ -122,6 +125,11 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS ...@@ -122,6 +125,11 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
SIGNAL received_eop : BOOLEAN := FALSE; SIGNAL received_eop : BOOLEAN := FALSE;
SIGNAL nxt_received_eop : BOOLEAN := FALSE; SIGNAL nxt_received_eop : BOOLEAN := FALSE;
SIGNAL expecting_eop : BOOLEAN := FALSE;
SIGNAL nxt_expecting_eop : BOOLEAN := FALSE;
SIGNAL common_spulse_clken : STD_LOGIC_VECTOR(c_nof_spulse DOWNTO 0) := (OTHERS => '1');
SIGNAL common_spulse_out_pulse : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0);
SIGNAL common_spulse_busy : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0);
SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0'; SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0';
BEGIN BEGIN
...@@ -136,7 +144,7 @@ BEGIN ...@@ -136,7 +144,7 @@ BEGIN
rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0); rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0);
gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
crossed_domain_snk_in_eop <= snk_in.eop; crossed_domain_snk_in_eop <= snk_in.eop; -- No need to transfer eop across clock domains
u_dp_fifo_sc : ENTITY work.dp_fifo_sc u_dp_fifo_sc : ENTITY work.dp_fifo_sc
GENERIC MAP ( GENERIC MAP (
g_technology => g_technology, g_technology => g_technology,
...@@ -175,15 +183,22 @@ BEGIN ...@@ -175,15 +183,22 @@ BEGIN
END GENERATE; END GENERATE;
gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE
-- Transfer eop across clock domain
crossed_domain_snk_in_eop <= vector_or(common_spulse_out_pulse);
gen_spulse : FOR I IN 0 TO c_nof_spulse-1 GENERATE
common_spulse_clken(I+1) <= vector_and(common_spulse_busy(I DOWNTO 0));
u_common_spulse : ENTITY common_lib.common_spulse u_common_spulse : ENTITY common_lib.common_spulse
PORT MAP ( PORT MAP (
in_rst => wr_rst, in_rst => wr_rst,
in_clk => wr_clk, in_clk => wr_clk,
in_clken => common_spulse_clken(I),
in_pulse => snk_in.eop, in_pulse => snk_in.eop,
in_busy => common_spulse_busy(I),
out_rst => rd_rst, out_rst => rd_rst,
out_clk => rd_clk, out_clk => rd_clk,
out_pulse => crossed_domain_snk_in_eop out_pulse => common_spulse_out_pulse(I)
); );
END GENERATE;
u_dp_fifo_dc : ENTITY work.dp_fifo_dc u_dp_fifo_dc : ENTITY work.dp_fifo_dc
GENERIC MAP ( GENERIC MAP (
...@@ -239,13 +254,19 @@ BEGIN ...@@ -239,13 +254,19 @@ BEGIN
state <= s_idle; state <= s_idle;
i_src_out <= c_dp_sosi_rst; i_src_out <= c_dp_sosi_rst;
received_eop <= FALSE; received_eop <= FALSE;
expecting_eop <= FALSE;
ELSIF rising_edge(rd_clk) THEN ELSIF rising_edge(rd_clk) THEN
xon_reg <= nxt_xon_reg; xon_reg <= nxt_xon_reg;
state <= nxt_state; state <= nxt_state;
i_src_out <= nxt_src_out; i_src_out <= nxt_src_out;
IF crossed_domain_snk_in_eop = '1' THEN IF crossed_domain_snk_in_eop = '1' THEN
IF expecting_eop THEN
expecting_eop <= FALSE;
ELSE
received_eop <= TRUE; received_eop <= TRUE;
END IF;
ELSE ELSE
expecting_eop <= nxt_expecting_eop;
received_eop <= nxt_received_eop; received_eop <= nxt_received_eop;
END IF; END IF;
END IF; END IF;
...@@ -254,10 +275,11 @@ BEGIN ...@@ -254,10 +275,11 @@ BEGIN
nxt_xon_reg <= src_in.xon; -- register xon to easy timing closure nxt_xon_reg <= src_in.xon; -- register xon to easy timing closure
gen_rl_0 : IF g_fifo_rl=0 GENERATE gen_rl_0 : IF g_fifo_rl=0 GENERATE
p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop) p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop)
BEGIN BEGIN
nxt_state <= state; nxt_state <= state;
nxt_received_eop <= received_eop; nxt_received_eop <= received_eop;
nxt_expecting_eop <= expecting_eop;
rd_siso <= src_in; -- default acknowledge (RL=1) this input when output is ready rd_siso <= src_in; -- default acknowledge (RL=1) this input when output is ready
-- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready -- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready
...@@ -291,8 +313,12 @@ BEGIN ...@@ -291,8 +313,12 @@ BEGIN
-- if the output is ready, then start outputting the frame -- if the output is ready, then start outputting the frame
IF src_in.ready='1' THEN IF src_in.ready='1' THEN
nxt_src_out <= rd_sosi; -- output sop that is still at FIFO output (RL=0) nxt_src_out <= rd_sosi; -- output sop that is still at FIFO output (RL=0)
nxt_received_eop <= FALSE;
nxt_state <= s_output; nxt_state <= s_output;
IF received_eop THEN
nxt_received_eop <= FALSE;
ELSE
nxt_expecting_eop <= TRUE;
END IF;
END IF; END IF;
END IF; END IF;
END IF; END IF;
...@@ -335,10 +361,11 @@ BEGIN ...@@ -335,10 +361,11 @@ BEGIN
src_out_reg => i_src_out src_out_reg => i_src_out
); );
p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop) p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop)
BEGIN BEGIN
nxt_state <= state; nxt_state <= state;
nxt_received_eop <= received_eop; nxt_received_eop <= received_eop;
nxt_expecting_eop <= expecting_eop;
hold_src_in <= src_in; -- default request (RL=1) new input when output is ready hold_src_in <= src_in; -- default request (RL=1) new input when output is ready
...@@ -373,8 +400,12 @@ BEGIN ...@@ -373,8 +400,12 @@ BEGIN
-- if the output is ready, then start outputting the input frame -- if the output is ready, then start outputting the input frame
IF src_in.ready='1' THEN IF src_in.ready='1' THEN
nxt_src_out <= pend_src_out; -- output sop that is still pending in dp_hold_input nxt_src_out <= pend_src_out; -- output sop that is still pending in dp_hold_input
nxt_received_eop <= FALSE;
nxt_state <= s_output; nxt_state <= s_output;
IF received_eop THEN
nxt_received_eop <= FALSE;
ELSE
nxt_expecting_eop <= TRUE;
END IF;
END IF; END IF;
END IF; END IF;
END IF; END IF;
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2017
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
--
-------------------------------------------------------------------------------
-- Purpose:
-- . Concatenate a user-defined header to a DP frame e.g. to create an Ethernet frame
-- Description:
-- . The header contents can be controlled dynamically by data path or MM control (selected by g_hdr_field_sel)
-- . The header and data can be concatened at symbol level. The g_symbol_w defines the
-- resolution of the empty field. The g_data_w must be an integer multiple of the
-- g_symbol_w. If the empty field is not used or if the empty field is always 0 then
-- set g_symbol_w = g_data_w.
-- . For example to concat header and data for an Ethernet frame use:
-- - g_data_w = 32 (1GbE) or 64 (10GbE)
-- - g_symbol_w = c_byte_w = 8 if either the header or the data can have an
-- non-zero empty field, so when they are not a multiple of 4 bytes
-- (= 32b) or 8 bytes (= 64b).
-- g_symbol_w = g_data_w if the empty field is always 0, so the number of bits in
-- the header and data are an integer number of g_data_w.
LIBRARY IEEE, common_lib, technology_lib, mm_lib;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE work.dp_stream_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY dp_offload_tx_v3 IS
GENERIC (
g_nof_streams : NATURAL;
g_data_w : NATURAL;
g_symbol_w : NATURAL;
g_hdr_field_arr : t_common_field_arr; -- User defined header fields
g_hdr_field_sel : STD_LOGIC_VECTOR; -- For each header field, select the source: 0=data path, 1=MM controlled
g_pipeline_ready : BOOLEAN := FALSE
);
PORT (
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
reg_hdr_dat_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_hdr_dat_miso : OUT t_mem_miso;
snk_in_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
snk_out_arr : OUT t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
src_out_arr : OUT t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
src_in_arr : IN t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
hdr_fields_in_arr : IN t_slv_1024_arr(g_nof_streams-1 DOWNTO 0); -- hdr_fields_in_arr(i) is considered valid @ snk_in_arr(i).sop
hdr_fields_out_arr : OUT t_slv_1024_arr(g_nof_streams-1 DOWNTO 0)
);
END dp_offload_tx_v3;
ARCHITECTURE str OF dp_offload_tx_v3 IS
CONSTANT c_dp_field_blk_snk_data_w : NATURAL := field_slv_out_len(field_arr_set_mode(g_hdr_field_arr , "RW"));
CONSTANT c_dp_field_blk_src_data_w : NATURAL := g_data_w;
SIGNAL dbg_c_dp_field_blk_snk_data_w : NATURAL := c_dp_field_blk_snk_data_w;
SIGNAL dbg_c_dp_field_blk_src_data_w : NATURAL := c_dp_field_blk_src_data_w;
SIGNAL dp_field_blk_snk_in_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL dp_field_blk_snk_out_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL dp_field_blk_src_out_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL dp_field_blk_src_in_arr : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL dp_concat_snk_in_2arr : t_dp_sosi_2arr_2(g_nof_streams-1 DOWNTO 0);
SIGNAL dp_concat_snk_out_2arr : t_dp_siso_2arr_2(g_nof_streams-1 DOWNTO 0);
SIGNAL reg_hdr_dat_mosi_arr : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL reg_hdr_dat_miso_arr : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL mm_fields_slv_out_arr : t_slv_1024_arr(g_nof_streams-1 DOWNTO 0);
SIGNAL field_override_arr : STD_LOGIC_VECTOR(g_hdr_field_arr'RANGE) := g_hdr_field_sel; --1 override bit per field
BEGIN
ASSERT c_dp_field_blk_snk_data_w <= c_dp_stream_data_w REPORT "Number of header bits must fit in t_dp_sosi data field." SEVERITY FAILURE;
---------------------------------------------------------------------------------------
-- Create header block & concatenate header to offload stream.
---------------------------------------------------------------------------------------
p_wire_valid : PROCESS(snk_in_arr, hdr_fields_in_arr)
BEGIN
FOR i IN 0 TO g_nof_streams-1 LOOP
-- default pass on the other snk_in_arr fields as well, especially the sync, bsn and channel can
-- be useful to preserve for the packetized output, even though only the sosi.data of the
-- packetized output will get transmitted.
dp_field_blk_snk_in_arr(i) <= snk_in_arr(i);
-- Prepare packet header as a data block with only one data word, so valid = sop = eop. If
-- c_dp_field_blk_snk_data_w > c_dp_field_blk_src_data_w then dp_repack_data in dp_field_blk will
-- repack this data word into a multi word header block, else dp_field_blk will pass on the
-- dp_field_blk_snk_in_arr as a single word header block.
dp_field_blk_snk_in_arr(i).data <= RESIZE_DP_DATA(hdr_fields_in_arr(i)(field_slv_len(g_hdr_field_arr)-1 DOWNTO 0));
dp_field_blk_snk_in_arr(i).valid <= snk_in_arr(i).sop;
dp_field_blk_snk_in_arr(i).sop <= snk_in_arr(i).sop; -- necessary for single word header block
dp_field_blk_snk_in_arr(i).eop <= snk_in_arr(i).sop; -- necessary for single word header block
END LOOP;
END PROCESS;
gen_dp_field_blk : FOR i IN 0 TO g_nof_streams-1 GENERATE
-- Both dp_concat inputs must be ready. One of the inputs toggles ready via dp_field_blk.
snk_out_arr(i).ready <= dp_field_blk_snk_out_arr(i).ready AND dp_concat_snk_out_2arr(i)(0).ready;
snk_out_arr(i).xon <= src_in_arr(i).xon;
-- Wire hdr_fields_out_arr
-- MM override bits determine source for each field
gen_field_wires: FOR j IN g_hdr_field_arr'RANGE GENERATE
hdr_fields_out_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j)) <= mm_fields_slv_out_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j))
WHEN field_override_arr(j) = '1' ELSE
hdr_fields_in_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j));
END GENERATE;
---------------------------------------------------------------------------------------
-- mm_fields for MM access to each field
---------------------------------------------------------------------------------------
u_mm_fields_slv: ENTITY mm_lib.mm_fields
GENERIC MAP(
g_field_arr => field_arr_set_mode(g_hdr_field_arr , "RW")
)
PORT MAP (
mm_clk => mm_clk,
mm_rst => mm_rst,
mm_mosi => reg_hdr_dat_mosi_arr(i),
mm_miso => OPEN, -- Not used
slv_clk => dp_clk,
slv_rst => dp_rst,
slv_out => mm_fields_slv_out_arr(i)(field_slv_len(g_hdr_field_arr)-1 DOWNTO 0)
);
-- Create multi-cycle header block from single-cycle wide header SLV
u_dp_field_blk : ENTITY work.dp_field_blk
GENERIC MAP (
g_field_arr => field_arr_set_mode(g_hdr_field_arr , "RW"),
g_field_sel => g_hdr_field_sel,
g_snk_data_w => c_dp_field_blk_snk_data_w,
g_src_data_w => c_dp_field_blk_src_data_w,
g_in_symbol_w => g_symbol_w,
g_out_symbol_w => g_symbol_w,
g_pipeline_ready => g_pipeline_ready
)
PORT MAP (
dp_clk => dp_clk,
dp_rst => dp_rst,
mm_clk => mm_clk,
mm_rst => mm_rst,
snk_in => dp_field_blk_snk_in_arr(i),
snk_out => dp_field_blk_snk_out_arr(i),
src_out => dp_field_blk_src_out_arr(i),
src_in => dp_field_blk_src_in_arr(i),
reg_slv_mosi => reg_hdr_dat_mosi_arr(i),
reg_slv_miso => reg_hdr_dat_miso_arr(i)
);
dp_field_blk_src_in_arr(i) <= dp_concat_snk_out_2arr(i)(1);
END GENERATE;
-- Prepend the header block to the input block
gen_dp_concat : FOR i IN 0 TO g_nof_streams-1 GENERATE
dp_concat_snk_in_2arr(i)(0) <= snk_in_arr(i);
dp_concat_snk_in_2arr(i)(1) <= dp_field_blk_src_out_arr(i);
u_dp_concat : ENTITY work.dp_concat
GENERIC MAP (
g_data_w => g_data_w,
g_symbol_w => g_symbol_w
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_out_arr => dp_concat_snk_out_2arr(i),
snk_in_arr => dp_concat_snk_in_2arr(i),
src_in => src_in_arr(i),
src_out => src_out_arr(i)
);
END GENERATE;
---------------------------------------------------------------------------------------
-- MM control & monitoring
---------------------------------------------------------------------------------------
u_common_mem_mux_hdr_dat : ENTITY common_lib.common_mem_mux
GENERIC MAP (
g_nof_mosi => g_nof_streams,
g_mult_addr_w => ceil_log2(field_nof_words(g_hdr_field_arr, c_word_w))
)
PORT MAP (
mosi => reg_hdr_dat_mosi,
miso => reg_hdr_dat_miso,
mosi_arr => reg_hdr_dat_mosi_arr,
miso_arr => reg_hdr_dat_miso_arr
);
END str;
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- --
-- Copyright (C) 2010 -- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- 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 -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
-- --
-- This program is free software: you can redistribute it and/or modify -- Licensed under the Apache License, Version 2.0 (the "License");
-- it under the terms of the GNU General Public License as published by -- you may not use this file except in compliance with the License.
-- the Free Software Foundation, either version 3 of the License, or -- You may obtain a copy of the License at
-- (at your option) any later version.
-- --
-- This program is distributed in the hope that it will be useful, -- http://www.apache.org/licenses/LICENSE-2.0
-- 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 -- Unless required by applicable law or agreed to in writing, software
-- along with this program. If not, see <http://www.gnu.org/licenses/>. -- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: -- Purpose:
-- Test bench for dp_fifo_fill_eop -- Test bench for dp_fifo_fill_eop
-- Description: -- Description:
...@@ -33,7 +34,8 @@ ...@@ -33,7 +34,8 @@
-- > run -all -- > run -all
-- . signal tb_end will stop the simulation by stopping the clk -- . signal tb_end will stop the simulation by stopping the clk
-- . the tb is self checking -- . the tb is self checking
-- -------------------------------------------------------------------------------
LIBRARY IEEE, common_lib; LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; USE IEEE.numeric_std.ALL;
......
This diff is collapsed.
hdl_lib_name = nw_10GbE
hdl_library_clause_name = nw_10GbE_lib
hdl_lib_uses_synth = common dp technology tech_mac_10g tr_10GbE
hdl_lib_uses_sim =
hdl_lib_technology =
synth_files =
src/vhdl/nw_arp_request.vhd
src/vhdl/nw_ping_response.vhd
src/vhdl/nw_10GbE.vhd
test_bench_files =
tb/vhdl/tb_nw_10GbE.vhd
tb/vhdl/tb_tb_nw_10GbE.vhd
tb/vhdl/tb_nw_ping_response.vhd
tb/vhdl/tb_nw_arp_request.vhd
#regression_test_vhdl =
# tb/vhdl/tb_nw_10GbE.vhd
# tb/vhdl/tb_tb_nw_10GbE.vhd
[modelsim_project_file]
[quartus_project_file]
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Adds basic networking capabilities to tr_10GbE by sending ARP request
-- packets on a predefined interval as well as respond to PING requests.
-- To avoid that the packet transmission will get a gap that will abort it.
-- The average DP data rate depends on dp_clk and on the DP data valid.
-- NOTE: When connected to a PC make sure you can handle backpressure for
-- a large amount of clock cycles (can be > 16k). This backpressure
-- is due to the possibility of receiving pause frames from the PC.
-- If your design cannot handle the backpressure from PC, you should
-- disable it on the PC side. This can be done with ethtool:
-- # ethtool -A ethX autoneg off rx off tx off
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_mac_10g_lib, tr_10GbE_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE common_lib.common_interface_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE technology_lib.technology_pkg.ALL;
USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
ENTITY nw_10GbE IS
GENERIC (
g_technology : NATURAL := c_tech_select_default;
g_sim : BOOLEAN;
g_sim_level : NATURAL := 1; -- 0 = use IP; 1 = use fast serdes model
g_nof_macs : NATURAL;
g_direction : STRING := "TX_RX"; -- "TX_RX", "TX_ONLY", "RX_ONLY"
g_use_mdio : BOOLEAN := FALSE;
g_mdio_epcs_dis : BOOLEAN := FALSE; -- TRUE disables EPCS on init; e.g. to target a 10GbE card in PC that does not support it
g_tx_fifo_fill : NATURAL := 10; -- Release tx packet only when sufficiently data is available such that no data gaps are introduced.
g_tx_fifo_size : NATURAL := 256; -- 2 * 32b * 256 = 2 M9K (DP interface has 64b data, so at least 2 M9K needed)
g_rx_fifo_size : NATURAL := 256; -- 2 * 32b * 256 = 2 M9K (DP interface has 64b data, so at least 2 M9K needed)
g_word_alignment_padding : BOOLEAN := FALSE;
g_arp_period_s : NATURAL := 30;
g_ip_hdr_field_arr : t_common_field_arr
);
PORT (
-- Transceiver PLL reference clock
tr_ref_clk_644 : IN STD_LOGIC := '0'; -- 644.531250 MHz for 10GBASE-R
tr_ref_clk_312 : IN STD_LOGIC := '0'; -- 312.5 MHz for 10GBASE-R
tr_ref_clk_156 : IN STD_LOGIC := '0'; -- 156.25 MHz for 10GBASE-R or for XAUI
tr_ref_rst_156 : IN STD_LOGIC := '0'; -- for 10GBASE-R or for XAUI
-- Calibration & reconfig clock
cal_rec_clk : IN STD_LOGIC := '0'; -- for XAUI;
-- MM interface
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
reg_mac_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_mac_miso : OUT t_mem_miso;
xaui_mosi : IN t_mem_mosi := c_mem_mosi_rst;
xaui_miso : OUT t_mem_miso;
reg_eth10g_mosi : IN t_mem_mosi := c_mem_mosi_rst; -- ETH10G (link status register)
reg_eth10g_miso : OUT t_mem_miso;
mdio_mosi_arr : IN t_mem_mosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_mem_mosi_rst);
mdio_miso_arr : OUT t_mem_miso_arr(g_nof_macs-1 DOWNTO 0);
reg_10gbase_r_24_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_10gbase_r_24_miso : OUT t_mem_miso;
-- DP interface
dp_rst : IN STD_LOGIC := '0';
dp_clk : IN STD_LOGIC := '0';
dp_pps : IN STD_LOGIC := '0';
snk_out_arr : OUT t_dp_siso_arr(g_nof_macs-1 DOWNTO 0);
snk_in_arr : IN t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
src_in_arr : IN t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
src_out_arr : OUT t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
-- Serial XAUI IO
xaui_tx_arr : OUT t_xaui_arr(g_nof_macs-1 DOWNTO 0);
xaui_rx_arr : IN t_xaui_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
-- Serial IO
serial_tx_arr : OUT STD_LOGIC_VECTOR(g_nof_macs-1 downto 0);
serial_rx_arr : IN STD_LOGIC_VECTOR(g_nof_macs-1 downto 0) := (OTHERS=>'0');
-- MDIO interface
mdio_rst : OUT STD_LOGIC;
mdio_mdc_arr : OUT STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0);
mdio_mdat_in_arr : IN STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0) := (OTHERS=>'0');
mdio_mdat_oen_arr : OUT STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0);
hdr_fields_in_arr : IN t_slv_1024_arr(g_nof_macs-1 DOWNTO 0)
);
END nw_10GbE;
ARCHITECTURE str OF nw_10GbE IS
CONSTANT c_nof_mux_streams : NATURAL := 3;
SIGNAL nw_arp_request_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
SIGNAL nw_arp_request_src_in_arr : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
SIGNAL nw_ping_response_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
SIGNAL nw_ping_response_src_in_arr : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
SIGNAL dp_mux_snk_in_2arr : t_dp_sosi_2arr_3(g_nof_macs-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_sosi_rst));
SIGNAL dp_mux_snk_out_2arr : t_dp_siso_2arr_3(g_nof_macs-1 DOWNTO 0);
SIGNAL tr_10GbE_snk_in_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
SIGNAL tr_10GbE_snk_out_arr : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
SIGNAL tr_10GbE_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
SIGNAL tr_10GbE_src_in_arr : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
SIGNAL eth_src_mac_arr : t_slv_48_arr(g_nof_macs-1 DOWNTO 0);
SIGNAL ip_src_addr_arr : t_slv_32_arr(g_nof_macs-1 DOWNTO 0);
SIGNAL ip_dst_addr_arr : t_slv_32_arr(g_nof_macs-1 DOWNTO 0);
BEGIN
src_out_arr <= tr_10GbE_src_out_arr;
tr_10GbE_src_in_arr <= src_in_arr;
gen_nof_macs : FOR I in 0 TO g_nof_macs-1 GENERATE
-- Wire hdr_fields_in_arr
eth_src_mac_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(g_ip_hdr_field_arr, "eth_src_mac"));
ip_src_addr_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(g_ip_hdr_field_arr, "ip_src_addr"));
ip_dst_addr_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(g_ip_hdr_field_arr, "ip_dst_addr"));
---------------------------------------------------------------------------------------
-- ARP request
---------------------------------------------------------------------------------------
u_nw_arp_request : ENTITY work.nw_arp_request
GENERIC MAP (
g_period_s => g_arp_period_s
)
PORT MAP (
dp_pps => dp_pps,
dp_clk => dp_clk,
dp_rst => dp_rst,
src_out => nw_arp_request_src_out_arr(I),
src_in => nw_arp_request_src_in_arr(I),
arp_sha => eth_src_mac_arr(I),
arp_spa => ip_src_addr_arr(I),
arp_tpa => ip_dst_addr_arr(I)
);
---------------------------------------------------------------------------------------
-- PING response
---------------------------------------------------------------------------------------
u_nw_ping_response : ENTITY work.nw_ping_response
GENERIC MAP (
g_technology => g_technology
)
PORT MAP (
clk => dp_clk,
rst => dp_rst,
snk_in => tr_10GbE_src_out_arr(I),
src_in => nw_ping_response_src_in_arr(I),
src_out => nw_ping_response_src_out_arr(I),
eth_src_mac => eth_src_mac_arr(I)
);
---------------------------------------------------------------------------------------
-- dp_mux to multiplex the three possible data streams
---------------------------------------------------------------------------------------
dp_mux_snk_in_2arr(I)(0) <= snk_in_arr(I);
dp_mux_snk_in_2arr(I)(1) <= nw_ping_response_src_out_arr(I);
dp_mux_snk_in_2arr(I)(2) <= nw_arp_request_src_out_arr(I);
snk_out_arr(I) <= dp_mux_snk_out_2arr(I)(0);
nw_ping_response_src_in_arr(I) <= dp_mux_snk_out_2arr(I)(1);
nw_arp_request_src_in_arr(I) <= dp_mux_snk_out_2arr(I)(2);
u_dp_mux : ENTITY dp_lib.dp_mux
GENERIC MAP (
g_nof_input => c_nof_mux_streams,
g_sel_ctrl_invert => TRUE,
g_fifo_size => array_init(0,c_nof_mux_streams), --no FIFO used but must match g_nof_input
g_fifo_fill => array_init(0,c_nof_mux_streams) --no FIFO used but must match g_nof_input
)
PORT MAP (
clk => dp_clk,
rst => dp_rst,
snk_in_arr => dp_mux_snk_in_2arr(I),
snk_out_arr => dp_mux_snk_out_2arr(I),
src_out => tr_10GbE_snk_in_arr(I),
src_in => tr_10GbE_snk_out_arr(I)
);
END GENERATE;
-------------
-- tr_10GbE
-------------
u_tr_10GbE: ENTITY tr_10GbE_lib.tr_10GbE
GENERIC MAP (
g_technology => g_technology,
g_sim => g_sim,
g_sim_level => g_sim_level,
g_nof_macs => g_nof_macs,
g_direction => g_direction,
g_use_mdio => g_use_mdio,
g_mdio_epcs_dis => g_mdio_epcs_dis,
g_tx_fifo_fill => g_tx_fifo_fill,
g_tx_fifo_size => g_tx_fifo_size,
g_rx_fifo_size => g_rx_fifo_size,
g_word_alignment_padding => g_word_alignment_padding
)
PORT MAP (
-- Transceiver PLL reference clock
tr_ref_clk_644 => tr_ref_clk_644,
tr_ref_clk_312 => tr_ref_clk_312, -- 312.5 MHz for 10GBASE-R
tr_ref_clk_156 => tr_ref_clk_156, -- 156.25 MHz for 10GBASE-R or for XAUI
tr_ref_rst_156 => tr_ref_rst_156, -- for 10GBASE-R or for XAUI
-- Calibration & reconfig clock
cal_rec_clk => cal_rec_clk, -- for XAUI;
-- MM interface
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mac_mosi => reg_mac_mosi,
reg_mac_miso => reg_mac_miso,
xaui_mosi => xaui_mosi,
xaui_miso => xaui_miso,
reg_eth10g_mosi => reg_eth10g_mosi,
reg_eth10g_miso => reg_eth10g_miso,
mdio_mosi_arr => mdio_mosi_arr,
mdio_miso_arr => mdio_miso_arr,
reg_10gbase_r_24_mosi => reg_10gbase_r_24_mosi,
reg_10gbase_r_24_miso => reg_10gbase_r_24_miso,
-- DP interface
dp_rst => dp_rst,
dp_clk => dp_clk,
src_out_arr => tr_10GbE_src_out_arr,
src_in_arr => tr_10GbE_src_in_arr,
snk_out_arr => tr_10GbE_snk_out_arr,
snk_in_arr => tr_10GbE_snk_in_arr,
-- Serial XAUI IO
xaui_tx_arr => xaui_tx_arr,
xaui_rx_arr => xaui_rx_arr,
-- Serial IO
serial_tx_arr => serial_tx_arr,
serial_rx_arr => serial_rx_arr,
-- MDIO interface
mdio_rst => mdio_rst,
mdio_mdc_arr => mdio_mdc_arr,
mdio_mdat_in_arr => mdio_mdat_in_arr,
mdio_mdat_oen_arr => mdio_mdat_oen_arr
);
END str;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Generate ARP request packets at a predefined interval.
-- Description:
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib, technology_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_network_total_header_pkg.ALL;
USE common_lib.common_interface_layers_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
ENTITY nw_arp_request IS
GENERIC (
g_period_s : NATURAL := 30
);
PORT (
dp_pps : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
dp_rst : IN STD_LOGIC;
src_in : IN t_dp_siso := c_dp_siso_rst;
src_out : OUT t_dp_sosi := c_dp_sosi_rst;
arp_sha : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
arp_spa : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
arp_tpa : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)
);
END nw_arp_request;
ARCHITECTURE rtl of nw_arp_request IS
CONSTANT c_data_w : NATURAL := c_xgmii_data_w;
CONSTANT c_nof_hdr_fields : NATURAL := 12;
CONSTANT c_hdr_field_sel : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := (OTHERS => '0');
CONSTANT c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(c_network_eth_bc_mac) ), --broadcast address
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ), --same as arp_sha
( field_name_pad("eth_type" ), "RW", 16, field_default(x"0806") ), -- ARP type
( field_name_pad("arp_htype" ), "RW", 16, field_default(1) ), -- eth type
( field_name_pad("arp_ptype" ), "RW", 16, field_default(x"0800") ), -- IP type
( field_name_pad("arp_hlen" ), "RW", 8, field_default(6) ), -- Mac length is 6 bytes
( field_name_pad("arp_plen" ), "RW", 8, field_default(4) ), -- IP length is 4 bytes
( field_name_pad("arp_operation" ), "RW", 16, field_default(1) ), -- operation is request
( field_name_pad("arp_sha" ), "RW", 48, field_default(0) ), --set later
( field_name_pad("arp_spa" ), "RW", 32, field_default(0) ), --set later
( field_name_pad("arp_tha" ), "RW", 48, field_default(0) ), --set to 0
( field_name_pad("arp_tpa" ), "RW", 32, field_default(0) )); -- set later
CONSTANT c_dp_field_blk_snk_data_w : NATURAL := field_slv_len(c_hdr_field_arr);
CONSTANT c_dp_field_blk_src_data_w : NATURAL := c_data_w;
SIGNAL pps_cnt : NATURAL := 0;
SIGNAL trigger : BOOLEAN := FALSE;
SIGNAL dp_field_blk_snk_in : t_dp_sosi := c_dp_sosi_rst;
SIGNAL nxt_dp_field_blk_snk_in : t_dp_sosi := c_dp_sosi_rst;
SIGNAL dp_field_blk_snk_out : t_dp_siso := c_dp_siso_rdy;
BEGIN
p_field_wires : PROCESS (arp_sha, arp_spa, arp_tpa)
BEGIN
-- Set defaults
loop_field_wires: FOR i IN c_hdr_field_arr'RANGE LOOP
nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, i) DOWNTO field_lo(c_hdr_field_arr, i)) <= c_hdr_field_arr(i).default(c_hdr_field_arr(i).size-1 DOWNTO 0);
END LOOP;
-- Overwrite fields comming from inputs
nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac")) <= arp_sha;
nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_sha") DOWNTO field_lo(c_hdr_field_arr, "arp_sha")) <= arp_sha;
nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_spa") DOWNTO field_lo(c_hdr_field_arr, "arp_spa")) <= arp_spa;
nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_tpa") DOWNTO field_lo(c_hdr_field_arr, "arp_tpa")) <= arp_tpa;
END PROCESS;
-- pps counter process setting sop, eop and valid
p_dp_pps : PROCESS (dp_clk, dp_rst)
BEGIN
IF dp_rst = '1' THEN
trigger <= FALSE;
pps_cnt <= 0;
dp_field_blk_snk_in <= c_dp_sosi_rst;
ELSIF RISING_EDGE(dp_clk) THEN
dp_field_blk_snk_in <= nxt_dp_field_blk_snk_in;
IF trigger AND dp_field_blk_snk_out.ready = '1' AND dp_field_blk_snk_out.xon = '1' THEN
trigger <= FALSE;
dp_field_blk_snk_in.sop <= '1';
dp_field_blk_snk_in.eop <= '1';
dp_field_blk_snk_in.valid <= '1';
END IF;
IF dp_pps = '1' THEN
IF pps_cnt < g_period_s-1 THEN
pps_cnt <= pps_cnt + 1;
ELSE
pps_cnt <= 0;
trigger <= TRUE;
END IF;
END IF;
END IF;
END PROCESS;
-- dp_field_blk to convert the ARP packet SLV to multi-cycle
u_dp_field_blk : ENTITY dp_lib.dp_field_blk
GENERIC MAP (
g_field_arr => c_hdr_field_arr,
g_field_sel => c_hdr_field_sel,
g_snk_data_w => c_dp_field_blk_snk_data_w,
g_src_data_w => c_dp_field_blk_src_data_w,
g_in_symbol_w => c_byte_w,
g_out_symbol_w => c_byte_w
)
PORT MAP (
dp_clk => dp_clk,
dp_rst => dp_rst,
mm_clk => '0',
mm_rst => '0',
snk_in => dp_field_blk_snk_in,
snk_out => dp_field_blk_snk_out,
src_out => src_out,
src_in => src_in
);
END rtl;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: generate PING response packet if a PING request is received.
-- Description: A response header is derived from the incoming request header.
-- . The payload of the response is created by pipelining the request packet.
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_mac_10g_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_network_total_header_pkg.ALL;
USE common_lib.common_interface_layers_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
ENTITY nw_ping_response IS
GENERIC (
g_technology : NATURAL := c_tech_select_default
);
PORT (
clk : IN STD_LOGIC;
rst : IN STD_LOGIC;
snk_in : IN t_dp_sosi := c_dp_sosi_rst;
src_in : IN t_dp_siso := c_dp_siso_rdy;
src_out : OUT t_dp_sosi := c_dp_sosi_rst;
eth_src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)
);
END nw_ping_response;
ARCHITECTURE rtl of nw_ping_response IS
CONSTANT c_data_w : NATURAL := c_xgmii_data_w;
CONSTANT c_dp_fifo_empty_w : NATURAL := c_tech_mac_10g_empty_w;
CONSTANT c_dp_fifo_size : NATURAL := 16;
CONSTANT c_cin_w : NATURAL := 4;
CONSTANT c_pipeline : NATURAL := c_network_total_header_64b_nof_words + 5; -- Header length and 5 more pipeline cycles to allow for the other states
TYPE t_state IS (s_idle, s_capture, s_check, s_sum, s_output, s_wait);
TYPE t_reg IS RECORD
state : t_state;
word_cnt : NATURAL RANGE 0 TO c_network_total_header_64b_nof_words;
hdr_words_arr : t_network_total_header_64b_arr;
hdr_fields : t_network_total_header;
hdr_response : t_network_total_header_64b_arr;
ip_checksum : STD_LOGIC_VECTOR(c_halfword_w -1 DOWNTO 0);
icmp_checksum : STD_LOGIC_VECTOR(c_halfword_w -1 DOWNTO 0);
ip_sum : UNSIGNED(c_halfword_w + c_cin_w -1 DOWNTO 0);
src_out : t_dp_sosi;
END RECORD;
SIGNAL r, rin : t_reg;
CONSTANT c_r_rst : t_reg := ( state => s_idle,
word_cnt => 0,
hdr_words_arr => (OTHERS=>(OTHERS=>'0')),
hdr_fields => c_network_total_header_ones,
hdr_response => (OTHERS=>(OTHERS=>'0')),
ip_checksum => (OTHERS => '0'),
icmp_checksum => (OTHERS => '0'),
ip_sum => (OTHERS => '0'),
src_out => c_dp_sosi_rst );
SIGNAL dp_pipeline_src_out : t_dp_sosi;
SIGNAL dp_fifo_sc_src_out : t_dp_sosi;
SIGNAL dp_fifo_sc_rd_emp : STD_LOGIC;
BEGIN
-- Combinational Process
p_comb : PROCESS(r, rst, snk_in, dp_pipeline_src_out, dp_fifo_sc_rd_emp)
VARIABLE v : t_reg;
BEGIN
v := r;
CASE r.state IS
WHEN s_idle => -- Wait for valid SOP
IF snk_in.sop = '1' AND snk_in.valid = '1' THEN
v.state := s_capture;
v.hdr_words_arr(r.word_cnt) := snk_in.data(c_data_w-1 DOWNTO 0);
v.word_cnt := r.word_cnt + 1;
END IF;
WHEN s_capture => -- Capture header
IF snk_in.valid = '1' AND r.word_cnt < c_network_total_header_64b_nof_words THEN
v.word_cnt := r.word_cnt + 1;
v.hdr_words_arr(r.word_cnt) := snk_in.data(c_data_w-1 DOWNTO 0);
ELSIF snk_in.eop = '1' AND snk_in.valid = '1' THEN
v := c_r_rst;
ELSIF r.word_cnt >= c_network_total_header_64b_nof_words THEN
v.word_cnt := 0;
v.state := s_check;
v.hdr_fields.eth := func_network_total_header_no_align_extract_eth( r.hdr_words_arr);
v.hdr_fields.ip := func_network_total_header_no_align_extract_ip( r.hdr_words_arr);
v.hdr_fields.icmp := func_network_total_header_no_align_extract_icmp( r.hdr_words_arr);
END IF;
WHEN s_check => -- Check if packet is ICMP echo request, create response header if it is the case.
IF TO_UINT(r.hdr_fields.eth.eth_type)=c_network_eth_type_ip AND
TO_UINT(r.hdr_fields.ip.protocol)=c_network_ip_protocol_icmp AND
TO_UINT(r.hdr_fields.icmp.msg_type)=c_network_icmp_msg_type_request THEN
v.hdr_response := func_network_total_header_no_align_response_icmp(r.hdr_words_arr, eth_src_mac);
v.state := s_sum;
ELSE
v := c_r_rst;
END IF;
WHEN s_sum => -- Sum halfwords of headers for checksum
v.state := s_output;
v.ip_sum := r.ip_sum
+ UNSIGNED(r.hdr_response(1)(c_halfword_w-1 DOWNTO 0)) -- ip_version, ip_header_length, ip_services
+ UNSIGNED(r.hdr_response(2)(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)) -- ip_total_length
+ UNSIGNED(r.hdr_response(2)(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) -- ip_identification
+ UNSIGNED(r.hdr_response(2)(c_halfword_w*2 -1 DOWNTO c_halfword_w)) -- ip_flags, ip_fragment_offset
+ UNSIGNED(r.hdr_response(2)(c_halfword_w -1 DOWNTO 0)) -- ip_time_to_live, ip_protocol
+ UNSIGNED(r.hdr_response(3)(c_halfword_w*3 -1 DOWNTO c_halfword_w *2)) -- ip_src_addr(1/2)
+ UNSIGNED(r.hdr_response(3)(c_halfword_w*2 -1 DOWNTO c_halfword_w)) -- ip_src_addr(2/2)
+ UNSIGNED(r.hdr_response(3)(c_halfword_w -1 DOWNTO 0)) -- ip_dst_addr(1/2)
+ UNSIGNED(r.hdr_response(4)(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)); -- ip_dst_addr(2/2)
WHEN s_output => -- Send out ICMP response
v.src_out := dp_pipeline_src_out;
IF dp_pipeline_src_out.valid = '1' THEN
CASE r.word_cnt IS
WHEN 0 =>
-- Also perform final checksum calculation
IF dp_pipeline_src_out.sop = '1' THEN -- Wait for SOP
v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
v.ip_checksum := NOT(STD_LOGIC_VECTOR(r.ip_sum(c_halfword_w-1 DOWNTO 0)+r.ip_sum(r.ip_sum'HIGH DOWNTO c_halfword_w))); -- checksum = inverted (sum + carry)
v.icmp_checksum := TO_UVEC((2048 + TO_UINT(r.hdr_fields.icmp.checksum)), c_halfword_w); -- checksum = original checksum + 0x0800 (incremental update)
v.word_cnt := r.word_cnt+1;
ELSE
v.src_out := c_dp_sosi_rst;
END IF;
WHEN 1 TO 2 =>
v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
v.word_cnt := r.word_cnt+1;
WHEN 3 =>
v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
v.src_out.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3) := r.ip_checksum;
v.word_cnt := r.word_cnt+1;
WHEN 4 =>
v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
v.src_out.data(c_halfword_w*2 -1 DOWNTO c_halfword_w) := r.icmp_checksum;
v.word_cnt := r.word_cnt+1;
WHEN OTHERS =>
IF dp_pipeline_src_out.eop = '1' THEN
v.state := s_wait;
END IF;
END CASE;
END IF;
WHEN s_wait =>
v.src_out := c_dp_sosi_rst;
IF dp_fifo_sc_rd_emp = '1' THEN -- Wait until ping response has left the fifo
v := c_r_rst;
END IF;
END CASE;
IF rst = '1' THEN
v := c_r_rst;
END IF;
rin <= v;
END PROCESS;
-- Sequential process
p_regs : PROCESS(clk)
BEGIN
IF RISING_EDGE(clk) THEN
r <= rin;
END IF;
END PROCESS;
-- Pipeline packet payload
u_dp_pipeline : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => c_pipeline
)
PORT MAP (
clk => clk,
rst => rst,
snk_in => snk_in,
src_out => dp_pipeline_src_out
);
-- Store response packet until ready
u_dp_fifo_sc : ENTITY dp_lib.dp_fifo_sc
GENERIC MAP (
g_technology => g_technology,
g_data_w => c_data_w,
g_empty_w => c_dp_fifo_empty_w,
g_use_empty => TRUE,
g_fifo_size => c_dp_fifo_size
)
PORT MAP (
rst => rst,
clk => clk,
rd_emp => dp_fifo_sc_rd_emp,
snk_out => OPEN,
snk_in => r.src_out,
src_in => src_in,
src_out => dp_fifo_sc_src_out
);
src_out <= dp_fifo_sc_src_out;
END rtl;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Testbench for tb_nw_10GbE.
-- Description:
-- The tb is self checking based on:
-- . proc_tech_mac_10g_rx_packet() for expected header and data type
-- . tx_pkt_cnt=rx_pkt_cnt > 0 must be true at the tb_end.
--
-- The tb finishes using severity failure because the simulation can not
-- finish by stopping the clocks and applying the resets due to that the IP
-- keeps on toggling internally.
-- Usage:
-- > as 10
-- > run -all
--
-- Remarks:
-- . c_tx_rx_loopback:
-- The tb uses a single DUT and c_tx_rx_loopback to model the link.
-- The g_direction = "TX_RX" is verified properly by c_tx_rx_loopback =
-- TRUE. Internally "RX_ONLY" is equivalent to "TX_RX" so there
-- c_tx_rx_loopback = TRUE is also suitable. For TX_ONLY the MAC Tx is
-- internally loopbacked to the MAC Rx, so there the external loopback is
-- not used and set to c_tx_rx_loopback = FALSE.
-------------------------------------------------------------------------------
LIBRARY IEEE, technology_lib, tech_pll_lib, tech_mac_10g_lib, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.common_interface_layers_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE common_lib.common_network_total_header_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE technology_lib.technology_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
USE tech_mac_10g_lib.tb_tech_mac_10g_pkg.ALL;
USE tech_pll_lib.tech_pll_component_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
ENTITY tb_nw_10GbE IS
-- Test bench control parameters
GENERIC (
g_technology : NATURAL := c_tech_select_default;
g_tb_end : BOOLEAN := TRUE; -- when TRUE then tb_end ends this simulation, else a higher multi-testbench will end the simulation
g_no_dut : BOOLEAN := FALSE; -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT
g_dp_clk_period : TIME := 5 ns; -- must be ~< 9000/(9000-c_tx_fifo_fill) * g_ref_clk_156_period
g_sim_level : NATURAL := 0; -- 0 = use IP; 1 = use fast serdes model
g_nof_channels : NATURAL := 1;
g_direction : STRING := "TX_RX"; -- "TX_RX", "TX_ONLY", "RX_ONLY"
g_ref_clk_644_period : TIME := tech_pll_clk_644_period; -- for 10GBASE-R
g_ref_clk_156_period : TIME := 6.4 ns; -- for XAUI
g_data_type : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
g_verify_link_recovery : BOOLEAN := TRUE
);
PORT (
tb_end : OUT STD_LOGIC
);
END tb_nw_10GbE;
ARCHITECTURE tb OF tb_nw_10GbE IS
CONSTANT c_sim : BOOLEAN := TRUE; -- tr_xaui_align_dly has time delay ~ 1 sec, so not suitable for simulation
CONSTANT cal_clk_period : TIME := 25 ns; -- 40 MHz
CONSTANT phy_delay : TIME := sel_a_b(g_sim_level=0, 0 ns, 0 ns);
CONSTANT c_tx_rx_loopback : BOOLEAN := g_direction/="TX_ONLY";
CONSTANT c_tx_fifo_fill : NATURAL := 100;
CONSTANT c_pkt_length_arr1 : t_nat_natural_arr := array_init(0, 50, 1) & (1472, 1473) & 9000; -- frame longer than 1518-46 = 1472 is received with rx_sosi.err = 8
-- jumbo frame is 9018-46 = 8972
CONSTANT c_pkt_length_arr2 : t_nat_natural_arr := array_init(46, 10, 139) & 1472;
CONSTANT c_pkt_length_arr : t_nat_natural_arr := c_pkt_length_arr1 & c_pkt_length_arr2;
CONSTANT c_nof_pkt1 : NATURAL := c_pkt_length_arr1'LENGTH;
CONSTANT c_nof_pkt2 : NATURAL := c_pkt_length_arr2'LENGTH;
CONSTANT c_nof_pkt : NATURAL := sel_a_b(g_verify_link_recovery, c_nof_pkt1 + c_nof_pkt2, c_nof_pkt1);
CONSTANT c_dst_mac : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"10FA01020300";
CONSTANT c_src_mac : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"123456789ABC"; -- = 12-34-56-78-9A-BC
CONSTANT c_src_mac_tx : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := c_src_mac;
--CONSTANT c_src_mac_tx : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"100056789ABC"; -- = 10-00-56-78-9A-BC
CONSTANT c_ethertype : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := X"10FA";
CONSTANT c_etherlen : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := "0000000000010000";
-- Packet headers
CONSTANT c_eth_header_ethertype : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_ethertype);
CONSTANT c_eth_header_etherlen : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_etherlen);
SIGNAL total_header : t_network_total_header := c_network_total_header_ones; -- default fill all fields with value 1
CONSTANT c_ip_hdr_field_arr : t_common_field_arr(3+12-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"ffffffffffff") ),
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(x"e840f2acff78") ),
( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ),
( field_name_pad("ip_version" ), "RW", 4, field_default(4) ),
( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ),
( field_name_pad("ip_services" ), "RW", 8, field_default(0) ),
( field_name_pad("ip_total_length" ), "RW", 16, field_default(x"54") ),
( field_name_pad("ip_identification" ), "RW", 16, field_default(x"3daf") ),
( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ),
( field_name_pad("ip_fragment_offset"), "RW", 13, field_default(0) ),
( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(x"40") ),
( field_name_pad("ip_protocol" ), "RW", 8, field_default(1) ),
( field_name_pad("ip_header_checksum"), "RW", 16, field_default(x"e580") ),
( field_name_pad("ip_src_addr" ), "RW", 32, field_default(x"0a570224") ),
( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"0a5700a8") ) );
-- Clocks and reset
SIGNAL tx_end_arr : STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0);
SIGNAL tx_end : STD_LOGIC;
SIGNAL rx_end : STD_LOGIC;
SIGNAL cal_clk : STD_LOGIC := '1'; -- calibration clock
SIGNAL mm_clk : STD_LOGIC; -- memory-mapped bus clock
SIGNAL mm_rst : STD_LOGIC; -- reset synchronous with mm_clk
SIGNAL dp_clk : STD_LOGIC := '1'; -- data path clock
SIGNAL dp_pps : STD_LOGIC := '0'; -- data path clock
SIGNAL dp_rst : STD_LOGIC; -- reset synchronous with dp_clk
-- External reference clocks
SIGNAL tr_ref_clk_644 : STD_LOGIC := '1'; -- 10GBASE-R
SIGNAL tr_ref_clk_312 : STD_LOGIC; -- 10GBASE-R
SIGNAL tr_ref_clk_156 : STD_LOGIC := '1'; -- 10GBASE-R or XAUI
SIGNAL tr_ref_rst_156 : STD_LOGIC; -- 10GBASE-R or XAUI
-- MAC 10G control interface
SIGNAL mm_init : STD_LOGIC;
SIGNAL mac_mosi_wrdata : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- for channel 0, 32 bit
SIGNAL mac_mosi : t_mem_mosi;
SIGNAL mac_miso : t_mem_miso;
SIGNAL mac_miso_rdval : STD_LOGIC; -- for channel 0
SIGNAL mac_miso_rddata : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- for channel 0, 32 bit
-- MAC 10G transmit interface
SIGNAL tx_en : STD_LOGIC := '1';
SIGNAL tx_siso_arr : t_dp_siso_arr(g_nof_channels-1 DOWNTO 0);
SIGNAL tx_sosi_arr : t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0);
SIGNAL tx_sosi_data : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0); -- for channel 0, 64 bit
-- MAC 10G receive interface
SIGNAL rx_siso_arr : t_dp_siso_arr(g_nof_channels-1 DOWNTO 0);
SIGNAL rx_sosi_arr : t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0);
SIGNAL rx_sosi_data : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0); -- for channel 0, 64 bit
-- PHY XAUI serial I/O
SIGNAL xaui_tx_arr : t_xaui_arr(g_nof_channels-1 DOWNTO 0);
SIGNAL xaui_rx_arr : t_xaui_arr(g_nof_channels-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
-- PHY 10GBASE-R serial IO
SIGNAL serial_tx_arr : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0);
SIGNAL serial_rx_arr : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0) := (OTHERS=>'0');
-- Model a serial link fault
SIGNAL link_fault_arr : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0);
-- Verification
SIGNAL tx_pkt_cnt_arr : t_natural_arr(g_nof_channels-1 downto 0) := (OTHERS=>0);
SIGNAL rx_pkt_cnt_arr : t_natural_arr(g_nof_channels-1 downto 0) := (OTHERS=>0);
SIGNAL rx_toggle_arr : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0) := (OTHERS=>'0'); -- toggle after every received packet
BEGIN
cal_clk <= NOT cal_clk AFTER cal_clk_period/2; -- Calibration clock
dp_clk <= NOT dp_clk AFTER g_dp_clk_period/2; -- DP clock
dp_rst <= '1', '0' AFTER g_dp_clk_period*10;
-- debug signals to ease monitoring in wave window
mac_mosi_wrdata <= mac_mosi.wrdata(c_word_w-1 DOWNTO 0);
mac_miso_rddata <= mac_miso.rddata(c_word_w-1 DOWNTO 0);
mac_miso_rdval <= '1' WHEN mac_mosi.rd='1' AND mac_miso.waitrequest='0' ELSE '0'; -- c_rd_latency = 1
tx_sosi_data <= tx_sosi_arr(0).data(c_tech_mac_10g_data_w-1 DOWNTO 0);
rx_sosi_data <= rx_sosi_arr(0).data(c_tech_mac_10g_data_w-1 DOWNTO 0);
-- Use signal to leave unused fields 'X'
total_header.eth <= c_eth_header_ethertype;
-- Generate reference clocks
gen_ref_clocks_xaui : IF g_technology=c_tech_stratixiv GENERATE
tr_ref_clk_644 <= 'X';
tr_ref_clk_312 <= 'X';
tr_ref_clk_156 <= NOT tr_ref_clk_156 AFTER g_ref_clk_156_period/2;
tr_ref_rst_156 <= '1', '0' AFTER g_ref_clk_156_period*5;
END GENERATE;
gen_ref_clocks_10gbase_r : IF g_technology/=c_tech_stratixiv GENERATE
tr_ref_clk_644 <= NOT tr_ref_clk_644 AFTER g_ref_clk_644_period/2;
pll : ENTITY tech_pll_lib.tech_pll_xgmii_mac_clocks
GENERIC MAP (
g_technology => g_technology
)
PORT MAP (
refclk_644 => tr_ref_clk_644,
rst_in => mm_rst,
clk_156 => tr_ref_clk_156,
clk_312 => tr_ref_clk_312,
rst_156 => tr_ref_rst_156,
rst_312 => OPEN
);
END GENERATE;
-- Setup all MACs in series
u_mm_setup : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_setup
GENERIC MAP (
g_technology => g_technology,
g_nof_macs => g_nof_channels,
g_src_mac => c_src_mac
)
PORT MAP (
tb_end => rx_end,
mm_clk => mm_clk,
mm_rst => mm_rst,
mm_init => mm_init,
mac_mosi => mac_mosi,
mac_miso => mac_miso
);
gen_transmitter : FOR I IN 0 TO g_nof_channels-1 GENERATE
-- Packet transmitter
u_transmitter : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_transmitter
GENERIC MAP (
g_data_type => g_data_type,
g_pkt_length_arr1 => c_pkt_length_arr1,
g_pkt_length_arr2 => c_pkt_length_arr2,
g_verify_link_recovery => g_verify_link_recovery
)
PORT MAP (
mm_init => mm_init,
total_header => total_header,
tx_clk => dp_clk,
tx_siso => tx_siso_arr(I),
tx_sosi => tx_sosi_arr(I),
link_fault => link_fault_arr(I),
tx_end => tx_end_arr(I)
);
END GENERATE;
no_dut : IF g_no_dut=TRUE GENERATE
rx_sosi_arr <= tx_sosi_arr;
tx_siso_arr <= rx_siso_arr;
END GENERATE;
gen_dut : IF g_no_dut=FALSE GENERATE
u_nw_10GbE : ENTITY work.nw_10GbE
GENERIC MAP (
g_technology => g_technology,
g_sim => c_sim,
g_sim_level => g_sim_level, -- 0 = use IP; 1 = use fast serdes model
g_nof_macs => g_nof_channels,
g_direction => g_direction,
g_use_mdio => TRUE,
g_mdio_epcs_dis => TRUE, -- TRUE disables Enhanced PCS on init; e.g. to target a 10GbE card in PC that does not support it
g_tx_fifo_fill => c_tx_fifo_fill,
g_tx_fifo_size => 256,
g_word_alignment_padding => TRUE,
g_ip_hdr_field_arr => c_ip_hdr_field_arr
)
PORT MAP (
-- Transceiver PLL reference clock
tr_ref_clk_644 => tr_ref_clk_644, -- 644.531250 MHz for 10GBASE-R
tr_ref_clk_312 => tr_ref_clk_312, -- 312.5 MHz for 10GBASE-R
tr_ref_clk_156 => tr_ref_clk_156, -- 156.25 MHz for 10GBASE-R or for XAUI
tr_ref_rst_156 => tr_ref_rst_156, -- for 10GBASE-R or for XAUI
-- Calibration & reconfig clock
cal_rec_clk => cal_clk,
-- MM interface
mm_rst => mm_rst,
mm_clk => mm_clk,
reg_mac_mosi => mac_mosi,
reg_mac_miso => mac_miso,
xaui_mosi => c_mem_mosi_rst,
xaui_miso => OPEN,
mdio_mosi_arr => (OTHERS=>c_mem_mosi_rst),
mdio_miso_arr => OPEN,
-- DP interface
dp_rst => dp_rst,
dp_clk => dp_clk,
dp_pps => dp_pps,
snk_out_arr => tx_siso_arr,
snk_in_arr => tx_sosi_arr,
src_in_arr => rx_siso_arr,
src_out_arr => rx_sosi_arr,
-- Serial XAUI interface
xaui_tx_arr => xaui_tx_arr,
xaui_rx_arr => xaui_rx_arr,
-- Serial IO
serial_tx_arr => serial_tx_arr,
serial_rx_arr => serial_rx_arr,
-- MDIO interface
mdio_rst => OPEN,
mdio_mdc_arr => OPEN,
mdio_mdat_in_arr => (OTHERS=>'0'),
mdio_mdat_oen_arr => OPEN,
hdr_fields_in_arr => (OTHERS => (OTHERS => '0'))
);
END GENERATE;
gen_link_connect : FOR I IN 0 TO g_nof_channels-1 GENERATE
u_link_connect : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_link_connect
GENERIC MAP (
g_loopback => c_tx_rx_loopback,
g_link_delay => phy_delay
)
PORT MAP (
link_fault => link_fault_arr(I), -- when '1' then forces rx_serial_arr(0)='0'
-- 10GBASE-R serial layer connect
serial_tx => serial_tx_arr(I),
serial_rx => serial_rx_arr(I), -- connects to delayed tx_serial when g_loopback=TRUE
-- XAUI serial layer connect
xaui_tx => xaui_tx_arr(I),
xaui_rx => xaui_rx_arr(I) -- connects to delayed xaui_tx when g_loopback=TRUE
);
END GENERATE;
gen_receiver : FOR I IN 0 TO g_nof_channels-1 GENERATE
u_receiver : ENTITY tech_mac_10g_lib.tb_tech_mac_10_receiver
GENERIC MAP (
g_data_type => g_data_type
)
PORT MAP (
mm_init => mm_init,
total_header => total_header,
rx_clk => dp_clk,
rx_sosi => rx_sosi_arr(I),
rx_siso => rx_siso_arr(I),
rx_toggle => rx_toggle_arr(I)
);
END GENERATE;
gen_verify_rx_at_eop : FOR I IN 0 TO g_nof_channels-1 GENERATE
u_verify_rx_at_eop : ENTITY tech_mac_10g_lib.tb_tech_mac_10_verify_rx_at_eop
GENERIC MAP (
g_no_padding => g_no_dut,
g_pkt_length_arr => c_pkt_length_arr
)
PORT MAP (
tx_clk => dp_clk,
tx_sosi => tx_sosi_arr(I),
rx_clk => dp_clk,
rx_sosi => rx_sosi_arr(I)
);
END GENERATE;
gen_verify_rx_pkt_cnt : FOR I IN 0 TO g_nof_channels-1 GENERATE
u_verify_rx_pkt_cnt : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_verify_rx_pkt_cnt
GENERIC MAP (
g_nof_pkt => c_nof_pkt
)
PORT MAP (
tx_clk => dp_clk,
tx_sosi => tx_sosi_arr(I),
rx_clk => dp_clk,
rx_sosi => rx_sosi_arr(I),
tx_pkt_cnt => tx_pkt_cnt_arr(I),
rx_pkt_cnt => rx_pkt_cnt_arr(I),
rx_end => rx_end
);
END GENERATE;
-- Stop the simulation
tx_end <= andv(tx_end_arr);
u_simulation_end : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_simulation_end
GENERIC MAP (
g_tb_end => g_tb_end,
g_nof_clk_to_rx_end => 1000
)
PORT MAP (
clk => dp_clk,
tx_end => tx_end,
rx_end => rx_end,
tb_end => tb_end
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Verify nw_arp_request.vhd
-- Description:
-- Usage:
-- > as 10
-- > run -all -- signal tb_end will stop the simulation by stopping the clk
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
USE common_lib.common_network_layers_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE dp_lib.tb_dp_pkg.ALL;
ENTITY tb_nw_arp_request IS
GENERIC (
g_test_backpressure : BOOLEAN := TRUE
);
END tb_nw_arp_request;
ARCHITECTURE tb OF tb_nw_arp_request IS
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '1';
SIGNAL dp_pps : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL src_in : t_dp_siso := c_dp_siso_rst;
SIGNAL src_out : t_dp_sosi := c_dp_sosi_rst;
SIGNAL arp_sha : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"AABBCCDDEEFF";
SIGNAL arp_spa : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"A1A2A3A4";
SIGNAL arp_tpa : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"B1B2B3B4";
BEGIN
clk <= (NOT clk) OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER clk_period*7;
src_in.xon <= '1';
p_stimuli : PROCESS
BEGIN
IF g_test_backpressure THEN
src_in.ready <= '0';
ELSE
src_in.ready <= '1';
END IF;
dp_pps <= '0';
proc_common_wait_some_cycles(clk, 10);
dp_pps <= '1';
proc_common_wait_some_cycles(clk, 1);
dp_pps <= '0';
proc_common_wait_some_cycles(clk, 10);
src_in.ready <= '1';
proc_common_wait_until_evt(clk, src_out.eop);
tb_end <= '1';
END PROCESS;
dut: ENTITY work.nw_arp_request
GENERIC MAP(
g_period_s => 1
)
PORT MAP(
dp_pps => dp_pps,
dp_clk => clk,
dp_rst => rst,
src_in => src_in,
src_out => src_out,
arp_sha => arp_sha,
arp_spa => arp_spa,
arp_tpa => arp_tpa
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Verify nw_ping_response.vhd
-- Description:
-- Usage:
-- > as 10
-- > run -all -- signal tb_end will stop the simulation by stopping the clk
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_lfsr_sequences_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE common_lib.common_field_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE dp_lib.tb_dp_pkg.ALL;
ENTITY tb_nw_ping_response IS
END tb_nw_ping_response;
ARCHITECTURE tb OF tb_nw_ping_response IS
CONSTANT c_data_w : NATURAL := 64;
CONSTANT c_nof_ping_packet_fields : NATURAL := 21;
CONSTANT c_nof_udp_packet_fields : NATURAL := 20;
CONSTANT c_ping_packet : t_common_field_arr(c_nof_ping_packet_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"ffffffffffff") ),
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(x"e840f2acff78") ),
( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ),
( field_name_pad("ip_version" ), "RW", 4, field_default(4) ),
( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ),
( field_name_pad("ip_services" ), "RW", 8, field_default(0) ),
( field_name_pad("ip_total_length" ), "RW", 16, field_default(x"54") ),
( field_name_pad("ip_identification" ), "RW", 16, field_default(x"3daf") ),
( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ),
( field_name_pad("ip_fragment_offset"), "RW", 13, field_default(0) ),
( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(x"40") ),
( field_name_pad("ip_protocol" ), "RW", 8, field_default(1) ),
( field_name_pad("ip_header_checksum"), "RW", 16, field_default(x"e580") ),
( field_name_pad("ip_src_addr" ), "RW", 32, field_default(x"0a570224") ),
( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"0a5700a8") ),
( field_name_pad("icmp_type" ), "RW", 8, field_default(8) ),
( field_name_pad("icmp_code" ), "RW", 8, field_default(0) ),
( field_name_pad("icmp_checksum" ), "RW", 16, field_default(x"117B") ),
( field_name_pad("icmp_identifier" ), "RW", 16, field_default(x"7052") ),
( field_name_pad("icmp_seq_number" ), "RW", 16, field_default(x"0001") ),
( field_name_pad("icmp_payload" ), "RW", 160, field_default(x"123456789ABCDEF01234123456789ABCDEF01234") ) );
CONSTANT c_udp_packet : t_common_field_arr(c_nof_udp_packet_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac" ), "RW", 48, field_default(x"00074306C700") ),
( field_name_pad("eth_src_mac" ), "RW", 48, field_default(0) ),
( field_name_pad("eth_type" ), "RW", 16, field_default(x"0800") ),
( field_name_pad("ip_version" ), "RW", 4, field_default(4) ),
( field_name_pad("ip_header_length" ), "RW", 4, field_default(5) ),
( field_name_pad("ip_services" ), "RW", 8, field_default(0) ),
( field_name_pad("ip_total_length" ), "RW", 16, field_default(810) ),
( field_name_pad("ip_identification" ), "RW", 16, field_default(0) ),
( field_name_pad("ip_flags" ), "RW", 3, field_default(2) ),
( field_name_pad("ip_fragment_offset"), "RW", 13, field_default(0) ),
( field_name_pad("ip_time_to_live" ), "RW", 8, field_default(127) ),
( field_name_pad("ip_protocol" ), "RW", 8, field_default(17) ),
( field_name_pad("ip_header_checksum"), "RW", 16, field_default(0) ),
( field_name_pad("ip_src_addr" ), "RW", 32, field_default(0) ),
( field_name_pad("ip_dst_addr" ), "RW", 32, field_default(x"C0A80001") ),
( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_total_length" ), "RW", 16, field_default(790) ),
( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_payload" ), "RW", 160, field_default(x"123456789ABCDEF01234123456789ABCDEF01234") ) );
CONSTANT c_ping_packet_len : NATURAL := field_slv_out_len(c_ping_packet);
CONSTANT c_udp_packet_len : NATURAL := field_slv_out_len(c_udp_packet);
CONSTANT c_ping_packet_slv : STD_LOGIC_VECTOR(c_ping_packet_len -1 DOWNTO 0) := field_map_defaults(c_ping_packet);
CONSTANT c_udp_packet_slv : STD_LOGIC_VECTOR(c_udp_packet_len -1 DOWNTO 0) := field_map_defaults(c_udp_packet);
CONSTANT c_ping_packet_field_sel : STD_LOGIC_VECTOR(c_nof_ping_packet_fields-1 DOWNTO 0) := (OTHERS => '0');
CONSTANT c_udp_packet_field_sel : STD_LOGIC_VECTOR(c_nof_udp_packet_fields-1 DOWNTO 0) := (OTHERS => '0');
CONSTANT c_nof_ping_responses : NATURAL := 20;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL ping_dp_field_blk_snk_in : t_dp_sosi;
SIGNAL ping_dp_field_blk_snk_out : t_dp_siso;
SIGNAL ping_dp_field_blk_src_out : t_dp_sosi;
SIGNAL ping_dp_field_blk_src_in : t_dp_siso;
SIGNAL udp_dp_field_blk_snk_in : t_dp_sosi;
SIGNAL udp_dp_field_blk_snk_out : t_dp_siso;
SIGNAL udp_dp_field_blk_src_out : t_dp_sosi;
SIGNAL udp_dp_field_blk_src_in : t_dp_siso;
SIGNAL nw_ping_response_snk_in : t_dp_sosi;
SIGNAL nw_ping_response_src_in : t_dp_siso;
SIGNAL nw_ping_response_src_out : t_dp_sosi;
SIGNAL cnt : NATURAL := 0;
BEGIN
clk <= (NOT clk) OR tb_end AFTER clk_period/2;
rst <= '1', '0' AFTER clk_period*7;
p_packets : PROCESS(clk)
BEGIN
IF RISING_EDGE(clk) THEN
ping_dp_field_blk_snk_in.data(c_ping_packet_len-1 DOWNTO 0 ) <= c_ping_packet_slv;
ping_dp_field_blk_snk_in.valid <= ping_dp_field_blk_snk_out.ready;
ping_dp_field_blk_snk_in.sop <= ping_dp_field_blk_snk_out.ready;
ping_dp_field_blk_snk_in.eop <= ping_dp_field_blk_snk_out.ready;
udp_dp_field_blk_snk_in.data(c_udp_packet_len-1 DOWNTO 0 ) <= c_udp_packet_slv;
udp_dp_field_blk_snk_in.valid <= udp_dp_field_blk_snk_out.ready;
udp_dp_field_blk_snk_in.sop <= udp_dp_field_blk_snk_out.ready;
udp_dp_field_blk_snk_in.eop <= udp_dp_field_blk_snk_out.ready;
END IF;
END PROCESS;
p_stimuli : PROCESS(clk)
VARIABLE start : BOOLEAN := FALSE;
BEGIN
IF RISING_EDGE(clk) THEN
IF cnt = 5 THEN
nw_ping_response_snk_in.valid <= '0';
nw_ping_response_snk_in.sop <= '0';
nw_ping_response_snk_in.eop <= '0';
IF ping_dp_field_blk_src_out.sop = '1' THEN
start := TRUE;
END IF;
IF start AND ping_dp_field_blk_src_out.valid = '1' THEN
nw_ping_response_snk_in <= ping_dp_field_blk_src_out;
END IF;
IF udp_dp_field_blk_src_out.eop = '1' THEN
cnt <= 0;
start := FALSE;
END IF;
ELSE
nw_ping_response_snk_in.valid <= '0';
nw_ping_response_snk_in.sop <= '0';
nw_ping_response_snk_in.eop <= '0';
IF udp_dp_field_blk_src_out.sop = '1' THEN
start := TRUE;
END IF;
IF start AND udp_dp_field_blk_src_out.valid = '1' THEN
nw_ping_response_snk_in <= udp_dp_field_blk_src_out;
END IF;
IF ping_dp_field_blk_src_out.eop = '1' THEN
cnt <= cnt +1;
start := FALSE;
END IF;
END IF;
END IF;
END PROCESS;
p_tb_end : PROCESS
BEGIN
FOR I IN 0 TO 2*c_nof_ping_responses LOOP
proc_common_wait_until_evt(clk, nw_ping_response_src_out.eop);
END LOOP;
tb_end <= '1';
END PROCESS;
nw_ping_response_src_in.xon <= '1';
nw_ping_response_src_in.ready <= '1';
dut : ENTITY work.nw_ping_response
PORT MAP (
clk => clk,
rst => rst,
snk_in => nw_ping_response_snk_in,
src_in => nw_ping_response_src_in,
src_out => nw_ping_response_src_out,
eth_src_mac => x"14dda9ec2e0f"
);
ping_dp_field_blk_src_in.ready <= '1';
ping_dp_field_blk_src_in.xon <= '1';
udp_dp_field_blk_src_in.ready <= '1';
udp_dp_field_blk_src_in.xon <= '1';
u_ping_dp_field_blk : ENTITY dp_lib.dp_field_blk
GENERIC MAP (
g_field_arr => c_ping_packet,
g_field_sel => c_ping_packet_field_sel,
g_snk_data_w => c_ping_packet_len,
g_src_data_w => c_data_w,
g_in_symbol_w => c_byte_w,
g_out_symbol_w => c_byte_w
)
PORT MAP (
dp_clk => clk,
dp_rst => rst,
mm_clk => '0',
mm_rst => '0',
snk_in => ping_dp_field_blk_snk_in,
snk_out => ping_dp_field_blk_snk_out,
src_out => ping_dp_field_blk_src_out,
src_in => ping_dp_field_blk_src_in
);
u_udp_dp_field_blk : ENTITY dp_lib.dp_field_blk
GENERIC MAP (
g_field_arr => c_udp_packet,
g_field_sel => c_udp_packet_field_sel,
g_snk_data_w => c_udp_packet_len,
g_src_data_w => c_data_w,
g_in_symbol_w => c_byte_w,
g_out_symbol_w => c_byte_w
)
PORT MAP (
dp_clk => clk,
dp_rst => rst,
mm_clk => '0',
mm_rst => '0',
snk_in => udp_dp_field_blk_snk_in,
snk_out => udp_dp_field_blk_snk_out,
src_out => udp_dp_field_blk_src_out,
src_in => udp_dp_field_blk_src_in
);
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Author: R. van der Walle
-- Purpose: Multi testbench for nw_10GbE the 10G Ethernet IO module
-- Description:
-- The multi-tb finishes when all instances have signaled tb_end.
-- Usage:
-- > as 5
-- > run -all
-------------------------------------------------------------------------------
LIBRARY IEEE, technology_lib, tech_pll_lib, tech_mac_10g_lib;
USE IEEE.std_logic_1164.ALL;
USE technology_lib.technology_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE tech_mac_10g_lib.tb_tech_mac_10g_pkg.ALL;
USE tech_pll_lib.tech_pll_component_pkg.ALL;
ENTITY tb_tb_nw_10GbE IS
END tb_tb_nw_10GbE;
ARCHITECTURE tb OF tb_tb_nw_10GbE IS
CONSTANT c_644 : TIME := tech_pll_clk_644_period;
CONSTANT c_156 : TIME := 6.4 ns;
CONSTANT c_data_type : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
CONSTANT c_tb_end_vec : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'1');
SIGNAL tb_end_vec : STD_LOGIC_VECTOR(7 DOWNTO 0) := c_tb_end_vec; -- sufficiently long to fit all tb instances
SIGNAL tb_end : STD_LOGIC := '0';
BEGIN
-- g_technology : NATURAL := c_tech_select_default;
-- g_tb_end : BOOLEAN := TRUE; -- when TRUE then tb_end ends this simulation, else a higher multi-testbench will end the simulation
-- g_no_dut : BOOLEAN := FALSE; -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT
-- g_dp_clk_period : TIME := 5 ns; -- 200 MHz
-- g_sim_level : NATURAL := 1; -- 0 = use IP; 1 = use fast serdes model
-- g_nof_channels : NATURAL := 1;
-- g_direction : STRING := "TX_RX"; -- "TX_RX", "TX_ONLY", "RX_ONLY"
-- g_ref_clk_644_period : TIME := tech_pll_clk_644_period; -- for 10GBASE-R
-- g_ref_clk_156_period : TIME := 6.4 ns; -- for XAUI
-- g_data_type : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
-- g_verify_link_recovery : BOOLEAN := TRUE;
u_no_dut : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, TRUE, 5 ns, 0, 1, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(0));
u_nw_10GbE : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 0, 1, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(1));
u_nw_10GbE_tx_only : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 0, 1, "TX_ONLY", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(2));
u_nw_10GbE_rx_only : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 0, 1, "RX_ONLY", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(3));
u_nw_10GbE_dp_clk_6_5ns : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 6.5 ns, 0, 1, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(4));
gen_2_channels : IF c_tech_select_default = c_tech_stratixiv GENERATE
u_nw_10GbE_nof_channels_is_2 : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 0, 2, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(5));
END GENERATE;
-- For arria10, nof_channels need to be 1, 4, 12, 24, 48.
gen_24_channels : IF c_tech_select_default /= c_tech_stratixiv GENERATE
u_nw_10GbE_nof_channels_is_24 : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 0, 24, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(5));
END GENERATE;
u_nw_10GbE_sim_level_is_1 : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5 ns, 1, 1, "TX_RX", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(6));
tb_end <= '1' WHEN tb_end_vec=c_tb_end_vec ELSE '0';
p_tb_end : PROCESS
BEGIN
WAIT UNTIL tb_end='1';
WAIT FOR 1 ns;
REPORT "Multi tb simulation finished." SEVERITY FAILURE;
WAIT;
END PROCESS;
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment