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

Merge branch 'HPR-127' into 'master'

added ip checksum inserter + added generics to eth_tester for setting

Closes HPR-127

See merge request desp/hdl!338
parents 268dff24 8a1d728d
No related branches found
No related tags found
1 merge request!338added ip checksum inserter + added generics to eth_tester for setting
Pipeline #55796 passed
Showing
with 1451 additions and 182 deletions
...@@ -7,6 +7,7 @@ hdl_lib_technology = ...@@ -7,6 +7,7 @@ hdl_lib_technology =
synth_files = synth_files =
src/vhdl/rdma_demo_pkg.vhd src/vhdl/rdma_demo_pkg.vhd
src/vhdl/rdma_demo_eth_tester_wrapper.vhd src/vhdl/rdma_demo_eth_tester_wrapper.vhd
src/vhdl/rdma_demo_roce_tester_wrapper.vhd
test_bench_files = test_bench_files =
......
...@@ -189,10 +189,11 @@ begin ...@@ -189,10 +189,11 @@ begin
generic map ( generic map (
g_nof_octet_generate => c_rdma_demo_nof_octet_generate_100gbe, g_nof_octet_generate => c_rdma_demo_nof_octet_generate_100gbe,
g_nof_octet_output => c_rdma_demo_nof_octet_output_100gbe, g_nof_octet_output => c_rdma_demo_nof_octet_output_100gbe,
g_use_network_header => false, g_use_eth_header => false,
g_use_ip_udp_header => false,
g_use_dp_header => true, g_use_dp_header => true,
g_hdr_field_arr => c_rdma_demo_hdr_field_arr, g_hdr_field_arr => c_rdma_demo_dp_hdr_field_arr,
g_hdr_field_sel => c_rdma_demo_hdr_field_sel, g_hdr_field_sel => c_rdma_demo_dp_hdr_field_sel,
g_remove_crc => false g_remove_crc => false
) )
port map ( port map (
......
...@@ -53,19 +53,70 @@ package rdma_demo_pkg is ...@@ -53,19 +53,70 @@ package rdma_demo_pkg is
-- to 0 by declaring hdr_fields_in_arr with all 0. Hence e.g. udp_checksum -- to 0 by declaring hdr_fields_in_arr with all 0. Hence e.g. udp_checksum
-- = 0 can be achieve via data path and default hdr_fields_in_arr = 0 or -- = 0 can be achieve via data path and default hdr_fields_in_arr = 0 or
-- via MM controlled and field_default(0). -- via MM controlled and field_default(0).
constant c_rdma_demo_nof_hdr_fields : natural := 4; constant c_rdma_demo_dp_nof_hdr_fields : natural := 4;
constant c_rdma_demo_hdr_field_sel : std_logic_vector(c_rdma_demo_nof_hdr_fields - 1 downto 0) := "0100"; constant c_rdma_demo_dp_hdr_field_sel : std_logic_vector(c_rdma_demo_dp_nof_hdr_fields - 1 downto 0) := "0100";
constant c_rdma_demo_hdr_field_arr : t_common_field_arr(c_rdma_demo_nof_hdr_fields - 1 downto 0) := ( constant c_rdma_demo_dp_hdr_field_arr : t_common_field_arr(c_rdma_demo_dp_nof_hdr_fields - 1 downto 0) := (
( field_name_pad("dp_length" ), "RW", 16, field_default(0) ), ( field_name_pad("dp_length" ), "RW", 16, field_default(0) ),
( field_name_pad("dp_reserved" ), "RW", 15, field_default(0) ), ( field_name_pad("dp_reserved"), "RW", 15, field_default(0) ),
( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ), ( field_name_pad("dp_sync" ), "RW", 1, field_default(0) ),
( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) ) ( field_name_pad("dp_bsn" ), "RW", 64, field_default(0) )
);
constant c_rdma_demo_dp_reg_hdr_dat_addr_w : natural := ceil_log2(field_nof_words(c_rdma_demo_dp_hdr_field_arr, c_word_w));
constant c_rdma_demo_dp_reg_hdr_dat_addr_span : natural := 2**c_rdma_demo_dp_reg_hdr_dat_addr_w;
constant c_rdma_demo_dp_app_hdr_len : natural := 12; -- octets
-- RoCEv2 header for RDMA write operation (excluding ETH, IP, UDP)
-- Base Transport Header (BTH) + RDMA Extended Transport Header (RETH) + Immediate Data
constant c_rdma_demo_roce_nof_hdr_fields : natural := 12 + 4 + 13 + 3 + 1;
constant c_rdma_demo_roce_hdr_field_sel : std_logic_vector(c_rdma_demo_roce_nof_hdr_fields - 1 downto 0) := "111011111001" & "0100" & "1111111111111" & "111" & "1";
constant c_rdma_demo_roce_hdr_field_arr : t_common_field_arr(c_rdma_demo_roce_nof_hdr_fields - 1 downto 0) := (
( 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(0) ), -- depends on BG block size, so set by data path
( 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(0) ), -- c_eth_tester_ip_dst_addr
( field_name_pad("udp_src_port" ), "RW", 16, field_default(0) ),
( field_name_pad("udp_dst_port" ), "RW", 16, field_default(0) ), -- c_eth_tester_udp_dst_port
( field_name_pad("udp_total_length" ), "RW", 16, field_default(0) ), -- depends on BG block size, so set by data path
( field_name_pad("udp_checksum" ), "RW", 16, field_default(0) ),
( field_name_pad("bth_opcode" ), "RW", 8, field_default(0) ),
( field_name_pad("bth_se" ), "RW", 1, field_default(0) ),
( field_name_pad("bth_m" ), "RW", 1, field_default(0) ),
( field_name_pad("bth_pad" ), "RW", 2, field_default(0) ),
( field_name_pad("bth_tver" ), "RW", 4, field_default(0) ),
( field_name_pad("bth_partition_key" ), "RW", 16, field_default(0) ),
( field_name_pad("bth_fres" ), "RW", 1, field_default(0) ),
( field_name_pad("bth_bres" ), "RW", 1, field_default(0) ),
( field_name_pad("bth_reserved_a" ), "RW", 6, field_default(0) ),
( field_name_pad("bth_dest_qp" ), "RW", 16, field_default(0) ),
( field_name_pad("bth_ack_req" ), "RW", 1, field_default(0) ),
( field_name_pad("bth_reserved_b" ), "RW", 7, field_default(0) ),
( field_name_pad("bth_psn" ), "RW", 32, field_default(0) ),
( field_name_pad("reth_virtual_address"), "RW", 64, field_default(0) ),
( field_name_pad("reth_r_key" ), "RW", 32, field_default(0) ),
( field_name_pad("reth_dma_length" ), "RW", 32, field_default(0) ),
( field_name_pad("immediate_data" ), "RW", 32, field_default(0) )
); );
constant c_rdma_demo_reg_hdr_dat_addr_w : natural := ceil_log2(field_nof_words(c_rdma_demo_hdr_field_arr, c_word_w)); -- = 5 constant c_rdma_demo_roce_reg_hdr_dat_addr_w : natural := ceil_log2(field_nof_words(c_rdma_demo_roce_hdr_field_arr, c_word_w));
constant c_rdma_demo_reg_hdr_dat_addr_span : natural := 2**c_rdma_demo_reg_hdr_dat_addr_w; -- = 32 constant c_rdma_demo_roce_reg_hdr_dat_addr_span : natural := 2**c_rdma_demo_roce_reg_hdr_dat_addr_w;
constant c_rdma_demo_app_hdr_len : natural := 12; -- octets constant c_rdma_demo_roce_hdr_len : natural := 32; -- octets
constant c_rdma_demo_roce_icrc_len : natural := 4; -- octets
end rdma_demo_pkg; end rdma_demo_pkg;
......
-------------------------------------------------------------------------------
--
-- Copyright 2023
-- 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: Provide AXI-4-stream interfaces + standard avalon MM interfaces for
-- eth_tester.vhd such that it can be used to create a Vivado IP block.
-- Description:
-- . The rdma_demo_roce_tester_wrapper uses axi4_stream_dp_bridge to convert the dp
-- sosi/siso interfaces of the eth_tester into AXI4-Stream interfaces.
-- . In order for this component to be suitable as a Vivado IP, the ports are
-- exclusively STD_LOGIC(_VECTOR) where the widths are hard-coded as demanded
-- by the Vivado IP creator (only supports VHDL-93).
-- . * roce = RDMA Over Converged Ethernet
-- Remark
-- . Avalon is used for all MM interfaces, which can be bridged to AXI4-Lite in
-- vivado using the AXI AMM Bridge IP.
library IEEE, common_lib, dp_lib, axi4_lib, eth_lib;
use IEEE.std_logic_1164.all;
use common_lib.common_pkg.all;
use common_lib.common_mem_pkg.all;
use common_lib.common_network_layers_pkg.all;
use dp_lib.dp_stream_pkg.all;
use dp_lib.dp_components_pkg.all;
use axi4_lib.axi4_stream_pkg.all;
use eth_lib.eth_pkg.all;
use eth_lib.eth_tester_pkg.all;
use work.rdma_demo_pkg.all;
entity rdma_demo_roce_tester_wrapper is
port (
-- Clocks and reset
mm_clk : in std_logic;
st_clk : in std_logic;
st_pps : in std_logic;
aresetn : in std_logic;
-- UDP transmit interface
eth_src_mac : in std_logic_vector(6 * 8 - 1 downto 0);
ip_src_addr : in std_logic_vector(4 * 8 - 1 downto 0);
udp_src_port : in std_logic_vector(2 * 8 - 1 downto 0);
tx_fifo_rd_emp_arr : out std_logic_vector(0 downto 0);
-- tx_udp
-- Source In and Sink Out
tx_udp_tready : in std_logic;
-- Source Out and Sink In
tx_udp_tvalid : out std_logic;
tx_udp_tdata : out std_logic_vector(512 - 1 downto 0);
tx_udp_tstrb : out std_logic_vector(512 / 8 - 1 downto 0);
tx_udp_tkeep : out std_logic_vector(512 / 8 - 1 downto 0);
tx_udp_tlast : out std_logic;
tx_udp_tid : out std_logic_vector(4 - 1 downto 0);
tx_udp_tdest : out std_logic_vector(32 - 1 downto 0);
tx_udp_tuser : out std_logic_vector(70 - 1 downto 0);
-- rx_udp
-- Source In and Sink Out
rx_udp_tready : out std_logic;
-- Source Out and Sink In
rx_udp_tvalid : in std_logic;
rx_udp_tdata : in std_logic_vector(512 - 1 downto 0);
rx_udp_tstrb : in std_logic_vector(512 / 8 - 1 downto 0);
rx_udp_tkeep : in std_logic_vector(512 / 8 - 1 downto 0);
rx_udp_tlast : in std_logic;
rx_udp_tid : in std_logic_vector(4 - 1 downto 0);
rx_udp_tdest : in std_logic_vector(32 - 1 downto 0);
rx_udp_tuser : in std_logic_vector(70 - 1 downto 0);
-- reg_bg_ctrl
reg_bg_ctrl_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_bg_ctrl_avs_read : in std_logic;
reg_bg_ctrl_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_bg_ctrl_avs_readdatavalid : out std_logic;
reg_bg_ctrl_avs_waitrequest : out std_logic;
reg_bg_ctrl_avs_write : in std_logic;
reg_bg_ctrl_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_hdr_dat
reg_hdr_dat_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_hdr_dat_avs_read : in std_logic;
reg_hdr_dat_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_hdr_dat_avs_readdatavalid : out std_logic;
reg_hdr_dat_avs_waitrequest : out std_logic;
reg_hdr_dat_avs_write : in std_logic;
reg_hdr_dat_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_bsn_monitor_v2_tx
reg_bsn_monitor_v2_tx_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_bsn_monitor_v2_tx_avs_read : in std_logic;
reg_bsn_monitor_v2_tx_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_bsn_monitor_v2_tx_avs_readdatavalid : out std_logic;
reg_bsn_monitor_v2_tx_avs_waitrequest : out std_logic;
reg_bsn_monitor_v2_tx_avs_write : in std_logic;
reg_bsn_monitor_v2_tx_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_strobe_total_count_tx
reg_strobe_total_count_tx_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_strobe_total_count_tx_avs_read : in std_logic;
reg_strobe_total_count_tx_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_strobe_total_count_tx_avs_readdatavalid : out std_logic;
reg_strobe_total_count_tx_avs_waitrequest : out std_logic;
reg_strobe_total_count_tx_avs_write : in std_logic;
reg_strobe_total_count_tx_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_dp_split
reg_dp_split_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_dp_split_avs_read : in std_logic;
reg_dp_split_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_dp_split_avs_readdatavalid : out std_logic;
reg_dp_split_avs_waitrequest : out std_logic;
reg_dp_split_avs_write : in std_logic;
reg_dp_split_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_bsn_monitor_v2_rx
reg_bsn_monitor_v2_rx_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_bsn_monitor_v2_rx_avs_read : in std_logic;
reg_bsn_monitor_v2_rx_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_bsn_monitor_v2_rx_avs_readdatavalid : out std_logic;
reg_bsn_monitor_v2_rx_avs_waitrequest : out std_logic;
reg_bsn_monitor_v2_rx_avs_write : in std_logic;
reg_bsn_monitor_v2_rx_avs_writedata : in std_logic_vector(32 - 1 downto 0);
-- reg_strobe_total_count_rx
reg_strobe_total_count_rx_avs_address : in std_logic_vector(32 - 1 downto 0);
reg_strobe_total_count_rx_avs_read : in std_logic;
reg_strobe_total_count_rx_avs_readdata : out std_logic_vector(32 - 1 downto 0);
reg_strobe_total_count_rx_avs_readdatavalid : out std_logic;
reg_strobe_total_count_rx_avs_waitrequest : out std_logic;
reg_strobe_total_count_rx_avs_write : in std_logic;
reg_strobe_total_count_rx_avs_writedata : in std_logic_vector(32 - 1 downto 0)
);
end rdma_demo_roce_tester_wrapper;
architecture str of rdma_demo_roce_tester_wrapper is
constant c_nof_byte : natural := c_rdma_demo_nof_octet_output_100gbe;
signal rx_udp_sosi_arr : t_dp_sosi_arr(0 downto 0) := (others => c_dp_sosi_rst);
signal rx_udp_siso_arr : t_dp_siso_arr(0 downto 0) := (others => c_dp_siso_rdy);
signal tx_udp_sosi_arr : t_dp_sosi_arr(0 downto 0) := (others => c_dp_sosi_rst);
signal tx_udp_siso_arr : t_dp_siso_arr(0 downto 0) := (others => c_dp_siso_rdy);
signal rx_udp_axi4_sosi : t_axi4_sosi := c_axi4_sosi_rst;
signal rx_udp_axi4_siso : t_axi4_siso := c_axi4_siso_rst;
signal tx_udp_axi4_sosi : t_axi4_sosi := c_axi4_sosi_rst;
signal tx_udp_axi4_siso : t_axi4_siso := c_axi4_siso_rst;
signal reg_bg_ctrl_copi : t_mem_copi := c_mem_copi_rst;
signal reg_bg_ctrl_cipo : t_mem_cipo;
signal reg_hdr_dat_copi : t_mem_copi := c_mem_copi_rst;
signal reg_hdr_dat_cipo : t_mem_cipo;
signal reg_bsn_monitor_v2_tx_copi : t_mem_copi := c_mem_copi_rst;
signal reg_bsn_monitor_v2_tx_cipo : t_mem_cipo;
signal reg_strobe_total_count_tx_copi : t_mem_copi := c_mem_copi_rst;
signal reg_strobe_total_count_tx_cipo : t_mem_cipo;
signal reg_dp_split_copi : t_mem_copi := c_mem_copi_rst;
signal reg_dp_split_cipo : t_mem_cipo;
signal reg_bsn_monitor_v2_rx_copi : t_mem_copi := c_mem_copi_rst;
signal reg_bsn_monitor_v2_rx_cipo : t_mem_cipo;
signal reg_strobe_total_count_rx_copi : t_mem_copi := c_mem_copi_rst;
signal reg_strobe_total_count_rx_cipo : t_mem_cipo;
signal mm_rst : std_logic := '0';
signal st_rst : std_logic := '0';
begin
u_eth_tester : entity eth_lib.eth_tester
generic map (
g_nof_octet_generate => c_rdma_demo_nof_octet_generate_100gbe,
g_nof_octet_output => c_rdma_demo_nof_octet_output_100gbe,
g_use_eth_header => false,
g_use_ip_udp_header => true,
g_use_dp_header => false,
g_hdr_calc_ip_crc => true,
g_hdr_field_arr => c_rdma_demo_roce_hdr_field_arr,
g_hdr_field_sel => c_rdma_demo_roce_hdr_field_sel,
-- Add icrc length here as g_hdr_app_len is used to calculate the total packet length.
g_hdr_app_len => c_rdma_demo_roce_hdr_len + c_rdma_demo_roce_icrc_len,
g_remove_crc => false
)
port map (
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => st_rst,
st_clk => st_clk,
st_pps => st_pps,
-- UDP transmit interface
eth_src_mac => eth_src_mac,
ip_src_addr => ip_src_addr,
udp_src_port => udp_src_port,
tx_fifo_rd_emp_arr => tx_fifo_rd_emp_arr,
tx_udp_sosi_arr => tx_udp_sosi_arr,
tx_udp_siso_arr => tx_udp_siso_arr,
-- UDP receive interface
rx_udp_sosi_arr => rx_udp_sosi_arr,
-- Memory Mapped Slaves (one per stream)
reg_bg_ctrl_copi => reg_bg_ctrl_copi,
reg_bg_ctrl_cipo => reg_bg_ctrl_cipo,
reg_hdr_dat_copi => reg_hdr_dat_copi,
reg_hdr_dat_cipo => reg_hdr_dat_cipo,
reg_bsn_monitor_v2_tx_copi => reg_bsn_monitor_v2_tx_copi,
reg_bsn_monitor_v2_tx_cipo => reg_bsn_monitor_v2_tx_cipo,
reg_strobe_total_count_tx_copi => reg_strobe_total_count_tx_copi,
reg_strobe_total_count_tx_cipo => reg_strobe_total_count_tx_cipo,
reg_dp_split_copi => reg_dp_split_copi,
reg_dp_split_cipo => reg_dp_split_cipo,
reg_bsn_monitor_v2_rx_copi => reg_bsn_monitor_v2_rx_copi,
reg_bsn_monitor_v2_rx_cipo => reg_bsn_monitor_v2_rx_cipo,
reg_strobe_total_count_rx_copi => reg_strobe_total_count_rx_copi,
reg_strobe_total_count_rx_cipo => reg_strobe_total_count_rx_cipo
);
-- DP to AXI4
u_axi4_tx_udp : entity axi4_lib.axi4_stream_dp_bridge
generic map (
g_axi4_rl => 0,
g_dp_rl => 1,
g_active_low_rst => true
)
port map (
in_clk => st_clk,
in_rst => aresetn,
dp_rst => st_rst,
dp_in_sosi => tx_udp_sosi_arr(0),
dp_in_siso => tx_udp_siso_arr(0),
axi4_out_sosi => tx_udp_axi4_sosi,
axi4_out_siso => tx_udp_axi4_siso
);
u_axi4_rx_udp : entity axi4_lib.axi4_stream_dp_bridge
generic map (
g_axi4_rl => 0,
g_dp_rl => 1,
g_active_low_rst => true
)
port map (
in_clk => st_clk,
in_rst => aresetn,
axi4_in_sosi => rx_udp_axi4_sosi,
axi4_in_siso => rx_udp_axi4_siso,
dp_out_sosi => rx_udp_sosi_arr(0),
dp_out_siso => rx_udp_siso_arr(0)
);
-- Wire Records to IN/OUT ports.
-- tx_udp
tx_udp_axi4_siso.tready <= tx_udp_tready;
tx_udp_tvalid <= tx_udp_axi4_sosi.tvalid;
tx_udp_tstrb <= tx_udp_axi4_sosi.tstrb;
tx_udp_tlast <= tx_udp_axi4_sosi.tlast;
tx_udp_tid <= tx_udp_axi4_sosi.tid;
tx_udp_tdest <= tx_udp_axi4_sosi.tdest;
tx_udp_tuser <= tx_udp_axi4_sosi.tuser;
-- reverse order of bytes
gen_tx_data : for I in 0 to c_nof_byte - 1 generate
tx_udp_tdata( (I + 1) * c_octet_w - 1 downto I * c_octet_w) <= tx_udp_axi4_sosi.tdata((c_nof_byte - I) * c_octet_w - 1 downto (c_nof_byte - 1 - I) * c_octet_w);
tx_udp_tkeep(I) <= tx_udp_axi4_sosi.tkeep(c_nof_byte - 1 - I);
end generate;
-- rx_udp
rx_udp_tready <= rx_udp_axi4_siso.tready;
rx_udp_axi4_sosi.tvalid <= rx_udp_tvalid;
rx_udp_axi4_sosi.tstrb <= rx_udp_tstrb;
rx_udp_axi4_sosi.tlast <= rx_udp_tlast;
rx_udp_axi4_sosi.tid <= rx_udp_tid;
rx_udp_axi4_sosi.tdest <= rx_udp_tdest;
rx_udp_axi4_sosi.tuser <= rx_udp_tuser;
-- reverse order of bytes
gen_rx_data : for I in 0 to c_nof_byte - 1 generate
rx_udp_axi4_sosi.tdata( (I + 1) * c_octet_w - 1 downto I * c_octet_w) <= rx_udp_tdata((c_nof_byte - I) * c_octet_w - 1 downto (c_nof_byte - 1 - I) * c_octet_w);
rx_udp_axi4_sosi.tkeep(I) <= rx_udp_tkeep(c_nof_byte - 1 - I);
end generate;
-- reg_bg_ctrl
-- copi
reg_bg_ctrl_copi.address <= reg_bg_ctrl_avs_address;
reg_bg_ctrl_copi.wrdata <= RESIZE_UVEC(reg_bg_ctrl_avs_writedata, c_mem_data_w);
reg_bg_ctrl_copi.wr <= reg_bg_ctrl_avs_write;
reg_bg_ctrl_copi.rd <= reg_bg_ctrl_avs_read;
-- cipo
reg_bg_ctrl_avs_readdata <= RESIZE_UVEC_32(reg_bg_ctrl_cipo.rddata);
reg_bg_ctrl_avs_readdatavalid <= reg_bg_ctrl_cipo.rdval;
reg_bg_ctrl_avs_waitrequest <= reg_bg_ctrl_cipo.waitrequest;
-- reg_hdr_dat
-- copi
reg_hdr_dat_copi.address <= reg_hdr_dat_avs_address;
reg_hdr_dat_copi.wrdata <= RESIZE_UVEC(reg_hdr_dat_avs_writedata, c_mem_data_w);
reg_hdr_dat_copi.wr <= reg_hdr_dat_avs_write;
reg_hdr_dat_copi.rd <= reg_hdr_dat_avs_read;
-- cipo
reg_hdr_dat_avs_readdata <= RESIZE_UVEC_32(reg_hdr_dat_cipo.rddata);
reg_hdr_dat_avs_readdatavalid <= reg_hdr_dat_cipo.rdval;
reg_hdr_dat_avs_waitrequest <= reg_hdr_dat_cipo.waitrequest;
-- reg_bsn_monitor_v2_tx
-- copi
reg_bsn_monitor_v2_tx_copi.address <= reg_bsn_monitor_v2_tx_avs_address;
reg_bsn_monitor_v2_tx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_tx_avs_writedata, c_mem_data_w);
reg_bsn_monitor_v2_tx_copi.wr <= reg_bsn_monitor_v2_tx_avs_write;
reg_bsn_monitor_v2_tx_copi.rd <= reg_bsn_monitor_v2_tx_avs_read;
-- cipo
reg_bsn_monitor_v2_tx_avs_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_tx_cipo.rddata);
reg_bsn_monitor_v2_tx_avs_readdatavalid <= reg_bsn_monitor_v2_tx_cipo.rdval;
reg_bsn_monitor_v2_tx_avs_waitrequest <= reg_bsn_monitor_v2_tx_cipo.waitrequest;
-- reg_strobe_total_count_tx
-- copi
reg_strobe_total_count_tx_copi.address <= reg_strobe_total_count_tx_avs_address;
reg_strobe_total_count_tx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_tx_avs_writedata, c_mem_data_w);
reg_strobe_total_count_tx_copi.wr <= reg_strobe_total_count_tx_avs_write;
reg_strobe_total_count_tx_copi.rd <= reg_strobe_total_count_tx_avs_read;
-- cipo
reg_strobe_total_count_tx_avs_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_tx_cipo.rddata);
reg_strobe_total_count_tx_avs_readdatavalid <= reg_strobe_total_count_tx_cipo.rdval;
reg_strobe_total_count_tx_avs_waitrequest <= reg_strobe_total_count_tx_cipo.waitrequest;
-- reg_dp_split
-- copi
reg_dp_split_copi.address <= reg_dp_split_avs_address;
reg_dp_split_copi.wrdata <= RESIZE_UVEC(reg_dp_split_avs_writedata, c_mem_data_w);
reg_dp_split_copi.wr <= reg_dp_split_avs_write;
reg_dp_split_copi.rd <= reg_dp_split_avs_read;
-- cipo
reg_dp_split_avs_readdata <= RESIZE_UVEC_32(reg_dp_split_cipo.rddata);
reg_dp_split_avs_readdatavalid <= reg_dp_split_cipo.rdval;
reg_dp_split_avs_waitrequest <= reg_dp_split_cipo.waitrequest;
-- reg_bsn_monitor_v2_rx
-- copi
reg_bsn_monitor_v2_rx_copi.address <= reg_bsn_monitor_v2_rx_avs_address;
reg_bsn_monitor_v2_rx_copi.wrdata <= RESIZE_UVEC(reg_bsn_monitor_v2_rx_avs_writedata, c_mem_data_w);
reg_bsn_monitor_v2_rx_copi.wr <= reg_bsn_monitor_v2_rx_avs_write;
reg_bsn_monitor_v2_rx_copi.rd <= reg_bsn_monitor_v2_rx_avs_read;
-- cipo
reg_bsn_monitor_v2_rx_avs_readdata <= RESIZE_UVEC_32(reg_bsn_monitor_v2_rx_cipo.rddata);
reg_bsn_monitor_v2_rx_avs_readdatavalid <= reg_bsn_monitor_v2_rx_cipo.rdval;
reg_bsn_monitor_v2_rx_avs_waitrequest <= reg_bsn_monitor_v2_rx_cipo.waitrequest;
-- reg_strobe_total_count_rx
-- copi
reg_strobe_total_count_rx_copi.address <= reg_strobe_total_count_rx_avs_address;
reg_strobe_total_count_rx_copi.wrdata <= RESIZE_UVEC(reg_strobe_total_count_rx_avs_writedata, c_mem_data_w);
reg_strobe_total_count_rx_copi.wr <= reg_strobe_total_count_rx_avs_write;
reg_strobe_total_count_rx_copi.rd <= reg_strobe_total_count_rx_avs_read;
-- cipo
reg_strobe_total_count_rx_avs_readdata <= RESIZE_UVEC_32(reg_strobe_total_count_rx_cipo.rddata);
reg_strobe_total_count_rx_avs_readdatavalid <= reg_strobe_total_count_rx_cipo.rdval;
reg_strobe_total_count_rx_avs_waitrequest <= reg_strobe_total_count_rx_cipo.waitrequest;
end str;
...@@ -26,6 +26,7 @@ library IEEE; ...@@ -26,6 +26,7 @@ library IEEE;
use IEEE.std_logic_1164.all; use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all; use IEEE.numeric_std.all;
use work.common_pkg.all; use work.common_pkg.all;
use work.common_field_pkg.all;
package common_network_layers_pkg is package common_network_layers_pkg is
...@@ -355,8 +356,36 @@ package common_network_layers_pkg is ...@@ -355,8 +356,36 @@ package common_network_layers_pkg is
constant c_network_udp_header_ones : t_network_udp_header := ("0000000000000001", "0000000000000001", constant c_network_udp_header_ones : t_network_udp_header := ("0000000000000001", "0000000000000001",
"0000000000000001", "0000000000000001"); "0000000000000001", "0000000000000001");
function func_network_ip_header_checksum(field_arr : t_common_field_arr; hdr_fields_slv : std_logic_vector) return std_logic_vector;
end common_network_layers_pkg; end common_network_layers_pkg;
package body common_network_layers_pkg is package body common_network_layers_pkg is
function func_network_ip_header_checksum(field_arr : t_common_field_arr; hdr_fields_slv : std_logic_vector) return std_logic_vector is
-- function to calculate the ip header checksum based on a header field array.
constant c_cin_w : natural := 4; -- bit width of carry
constant c_nof_halfword : natural := (c_network_ip_header_len / c_halfword_sz) - 1; -- -1 as we exclude the checksum field itself for calculation.
variable sum : unsigned(c_network_ip_header_checksum_w + c_cin_w - 1 downto 0) := (others => '0');
variable crc : std_logic_vector(c_network_ip_header_checksum_w - 1 downto 0);
variable vec : std_logic_vector(c_halfword_w * c_nof_halfword - 1 downto 0);
begin
-- vec = whole ip header excluding ip_header_checksum.
vec :=
hdr_fields_slv(field_hi(field_arr, "ip_version" ) downto field_lo(field_arr, "ip_protocol" ))
& hdr_fields_slv(field_hi(field_arr, "ip_src_addr" ) downto field_lo(field_arr, "ip_dst_addr" ));
-- sum up vec in halfwords
for i in 0 to c_nof_halfword - 1 loop
sum := sum + unsigned(vec(( i + 1 ) * c_halfword_w - 1 downto i * c_halfword_w));
end loop;
-- checksum = inverted (sum + carry)
crc := not(std_logic_vector(sum(c_halfword_w - 1 downto 0) + sum(sum'high downto c_halfword_w)));
return crc;
end func_network_ip_header_checksum;
end common_network_layers_pkg; end common_network_layers_pkg;
...@@ -7,7 +7,7 @@ hdl_lib_technology = ...@@ -7,7 +7,7 @@ hdl_lib_technology =
synth_files = synth_files =
src/vhdl/eth_pkg.vhd src/vhdl/eth_pkg.vhd
src/vhdl/eth_checksum.vhd src/vhdl/eth_checksum.vhd
src/vhdl/eth_checksum_10g.vhd src/vhdl/eth_ip_header_checksum.vhd
src/vhdl/eth_hdr_store.vhd src/vhdl/eth_hdr_store.vhd
src/vhdl/eth_hdr_status.vhd src/vhdl/eth_hdr_status.vhd
src/vhdl/eth_hdr_ctrl.vhd src/vhdl/eth_hdr_ctrl.vhd
...@@ -33,6 +33,7 @@ test_bench_files = ...@@ -33,6 +33,7 @@ test_bench_files =
src/vhdl/eth_statistics.vhd src/vhdl/eth_statistics.vhd
tb/vhdl/tb_eth_checksum.vhd tb/vhdl/tb_eth_checksum.vhd
tb/vhdl/tb_eth_crc_ctrl.vhd tb/vhdl/tb_eth_crc_ctrl.vhd
tb/vhdl/tb_eth_ip_header_checksum.vhd
tb/vhdl/tb_eth_hdr.vhd tb/vhdl/tb_eth_hdr.vhd
tb/vhdl/tb_eth.vhd tb/vhdl/tb_eth.vhd
tb/vhdl/tb_eth_tester_pkg.vhd tb/vhdl/tb_eth_tester_pkg.vhd
...@@ -46,6 +47,7 @@ test_bench_files = ...@@ -46,6 +47,7 @@ test_bench_files =
tb/vhdl/tb_eth_udp_offload.vhd tb/vhdl/tb_eth_udp_offload.vhd
tb/vhdl/tb_eth_ihl_to_20.vhd tb/vhdl/tb_eth_ihl_to_20.vhd
tb/vhdl/tb_tb_tb_eth_regression.vhd tb/vhdl/tb_tb_tb_eth_regression.vhd
tb/vhdl/tb_tb_eth_ip_header_checksum.vhd
regression_test_vhdl = regression_test_vhdl =
tb/vhdl/tb_eth_checksum.vhd tb/vhdl/tb_eth_checksum.vhd
......
-------------------------------------------------------------------------------
--
-- Copyright (C) 2010
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
library IEEE, common_lib, dp_lib;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use common_lib.common_pkg.all;
use dp_lib.dp_stream_pkg.all;
----------------------------------------------------------------------------------
-- Purpose: --
-- Can be used to calculate and insert the checksum for the IP header --
-- in a 10GbE package, if the correct longwords are provided. --
-- Description: --
-- Determine the 16 bit 1-complement checksum according IPv4 to for the valid --
-- words between snk_in.sop and the last ip header field. --
-- After calculation, the checksum is inserted in the outgoing stream --
----------------------------------------------------------------------------------
entity eth_checksum_10g is
port (
rst : in std_logic;
clk : in std_logic;
src_out : out t_dp_sosi;
snk_in : in t_dp_sosi;
src_in : in t_dp_siso;
snk_out : out t_dp_siso
);
end eth_checksum_10g;
architecture rtl of eth_checksum_10g is
constant c_cin_w : natural := 4; -- bit width of carry
constant c_pipeline_delay : natural := 2;
signal sum : unsigned(c_halfword_w + c_cin_w - 1 downto 0) := (others => '0');
signal checksum : std_logic_vector(c_halfword_w - 1 downto 0);
signal cnt_clr, cnt_p_clr : std_logic;
signal cnt_en, cnt_p_en : std_logic;
signal count, count_p : std_logic_vector(31 downto 0);
signal dp_pipeline_src_out : t_dp_sosi;
begin
-------------------------------------------------
-- process to calculate the ip_header_checksum --
-------------------------------------------------
p_calc_chksum : process(clk)
begin
if rst = '1' then
sum <= (others => '0');
elsif rising_edge(clk) then
if cnt_clr = '1' then
sum <= (others => '0');
elsif cnt_en = '1' then
case TO_UINT(count) is
when 0 => -- 0 is the cycle after the sop due to the common_counter latency
sum <= sum + unsigned(snk_in.data(c_halfword_w - 1 downto 0)); -- ip_version, ip_header_length, ip_services
when 1 =>
sum <= sum + unsigned(snk_in.data(c_halfword_w * 4 - 1 downto c_halfword_w * 3)) -- ip_total_length
+ unsigned(snk_in.data(c_halfword_w * 3 - 1 downto c_halfword_w * 2)) -- ip_identification
+ unsigned(snk_in.data(c_halfword_w * 2 - 1 downto c_halfword_w)) -- ip_flags, ip_fragment_offset
+ unsigned(snk_in.data(c_halfword_w - 1 downto 0)); -- ip_time_to_live, ip_protocol
when 2 => -- skip ip_header_checksum
sum <= sum + unsigned(snk_in.data(c_halfword_w * 3 - 1 downto c_halfword_w * 2)) -- ip_src_addr(1/2)
+ unsigned(snk_in.data(c_halfword_w * 2 - 1 downto c_halfword_w)) -- ip_src_addr(2/2)
+ unsigned(snk_in.data(c_halfword_w - 1 downto 0)); -- ip_dst_addr(1/2)
when 3 =>
sum <= sum + unsigned(snk_in.data(c_halfword_w * 4 - 1 downto c_halfword_w * 3)); -- ip_dst_addr(2/2)
when others =>
end case;
end if;
end if;
end process;
---------------------------------------------------
-- process to insert checksum in outgoing stream --
---------------------------------------------------
checksum <= not(std_logic_vector(sum(c_halfword_w - 1 downto 0) + sum(sum'high downto c_halfword_w))); -- checksum = inverted (sum + carry)
p_insert_chksum : process(dp_pipeline_src_out, checksum, count)
begin
src_out <= dp_pipeline_src_out;
if TO_UINT(count_p) = 2 then
src_out.data(c_halfword_w * 4 - 1 downto c_halfword_w * 3) <= checksum;
end if;
end process;
-------------------------------------------------------------------------------------------
-- useing common_counter to keep track of the word alignment during checksum calculation --
-------------------------------------------------------------------------------------------
cnt_en <= snk_in.valid; -- only count when valid
cnt_clr <= snk_in.sop; -- restart counter on sop
u_calc_counter : entity common_lib.common_counter
port map (
rst => rst,
clk => clk,
cnt_clr => cnt_clr,
cnt_en => cnt_en,
count => count
);
-----------------------------------------------------------------------------------------
-- useing common_counter to keep track of the word alignment during checksum insertion --
-----------------------------------------------------------------------------------------
cnt_p_en <= dp_pipeline_src_out.valid; -- only count when valid
cnt_p_clr <= dp_pipeline_src_out.sop; -- restart counter on sop
u_pipe_counter : entity common_lib.common_counter
port map (
rst => rst,
clk => clk,
cnt_clr => cnt_p_clr,
cnt_en => cnt_p_en,
count => count_p
);
--------------------------------------------------------------------------------
-- useing dp_pipeline to make room for the checksum calculation and insertion --
--------------------------------------------------------------------------------
u_dp_pipeline : entity dp_lib.dp_pipeline
generic map (
g_pipeline => c_pipeline_delay
)
port map (
rst => rst,
clk => clk,
-- ST sink
snk_out => snk_out,
snk_in => snk_in,
-- ST source
src_in => src_in,
src_out => dp_pipeline_src_out
);
end rtl;
-- --------------------------------------------------------------------------
-- Copyright 2023
-- 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:
-- Can be used to calculate and insert the checksum for the IP header
-- in a network package, if the correct hdr_fields_slv_in is provided.
-- Description:
-- Determine the 16 bit 1-complement checksum according IPv4 to for the
-- hdr_fields_slv_in.
-- After calculation, the checksum is inserted in the outgoing stream at
-- corresponding position based on g_hdr_field_arr and g_data_w.
-- Remarks:
-- The hdr_fields_slv_in should be valid on the snk_in.sop
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_field_pkg.all;
use common_lib.common_network_layers_pkg.all;
use dp_lib.dp_stream_pkg.all;
entity eth_ip_header_checksum is
generic (
g_data_w : natural := 64;
g_hdr_field_arr : t_common_field_arr
);
port (
rst : in std_logic;
clk : in std_logic;
src_out : out t_dp_sosi;
snk_in : in t_dp_sosi;
src_in : in t_dp_siso;
snk_out : out t_dp_siso;
hdr_fields_slv_in : std_logic_vector(1023 downto 0) := (others => '0')
);
end eth_ip_header_checksum;
architecture rtl of eth_ip_header_checksum is
constant c_hdr_len : natural := field_slv_len(g_hdr_field_arr);
constant c_hdr_crc_bit_hi : natural := field_hi(g_hdr_field_arr, "ip_header_checksum");
constant c_hdr_crc_bit_lo : natural := field_lo(g_hdr_field_arr, "ip_header_checksum");
-- calculate which word(s) of the incoming snk_in stream should contain the checksum.
constant c_hdr_crc_word_hi : natural := sel_a_b((c_hdr_crc_bit_hi / g_data_w) > 0, c_hdr_crc_bit_hi / g_data_w,
sel_a_b( c_hdr_crc_bit_hi > (c_hdr_len mod g_data_w), 1, 0)); --special case as the last hdr word can be < g_data_w.
constant c_hdr_crc_word_lo : natural := sel_a_b((c_hdr_crc_bit_lo / g_data_w) > 0, c_hdr_crc_bit_lo / g_data_w,
sel_a_b( c_hdr_crc_bit_lo > (c_hdr_len mod g_data_w), 1, 0)); --special case as the last hdr word can be < g_data_w.
-- calculate in which bit range of the selected word(s) the checksum should go.
constant c_crc_hi_bit_in_word : natural := g_data_w - ((c_hdr_len - c_hdr_crc_bit_hi) mod g_data_w);
constant c_crc_lo_bit_in_word : natural := (g_data_w - ((c_hdr_len - c_hdr_crc_bit_lo) mod g_data_w)) mod g_data_w;
constant c_hdr_nof_words : natural := ceil_div(c_hdr_len, g_data_w);
constant c_crc_word_span : natural := 1 + c_hdr_crc_word_hi - c_hdr_crc_word_lo;
constant c_crc_in_one_word : boolean := c_crc_word_span = 1;
signal checksum : std_logic_vector(c_network_ip_header_checksum_w - 1 downto 0) := (others => '0');
signal count : std_logic_vector(31 downto 0);
signal dp_pipeline_src_out : t_dp_sosi;
signal reg_done : std_logic := '0';
signal nxt_reg_done : std_logic := '0';
begin
-- calculate checksum
checksum <= func_network_ip_header_checksum(g_hdr_field_arr, hdr_fields_slv_in) when rising_edge(clk);
-- register to know when crc has been inserted.
reg_done <= nxt_reg_done when rising_edge(clk);
---------------------------------------------------
-- process to insert checksum in outgoing stream --
---------------------------------------------------
gen_insert_crc_one : if c_crc_in_one_word generate -- checksum is in 1 word.
p_insert_crc_one : process(dp_pipeline_src_out, checksum, count, reg_done)
variable v_count : natural := 0;
begin
v_count := TO_UINT(count);
src_out <= dp_pipeline_src_out;
nxt_reg_done <= reg_done;
if reg_done = '0' and dp_pipeline_src_out.valid = '1' and v_count = c_hdr_crc_word_hi then
src_out.data(c_crc_hi_bit_in_word downto c_crc_lo_bit_in_word) <= checksum;
nxt_reg_done <= '1';
end if;
if reg_done = '1' and dp_pipeline_src_out.eop = '1' then
nxt_reg_done <= '0';
end if;
end process;
end generate;
gen_insert_crc_multi : if not c_crc_in_one_word generate
p_insert_crc_multi : process(dp_pipeline_src_out, checksum, count, reg_done)
variable v_count : natural := 0;
variable v_hi : natural := 0;
variable v_lo : natural := 0;
begin
v_count := TO_UINT(count);
src_out <= dp_pipeline_src_out;
nxt_reg_done <= reg_done;
if reg_done = '0' and dp_pipeline_src_out.valid = '1' then
if v_count = c_hdr_crc_word_hi then
src_out.data(c_crc_hi_bit_in_word downto 0) <= checksum(c_network_ip_header_checksum_w - 1 downto c_network_ip_header_checksum_w - c_crc_hi_bit_in_word - 1);
elsif v_count = c_hdr_crc_word_lo then
src_out.data(g_data_w - 1 downto c_crc_lo_bit_in_word) <= checksum(g_data_w - c_crc_lo_bit_in_word - 1 downto 0);
nxt_reg_done <= '1';
elsif v_count < c_hdr_crc_word_hi and v_count > c_hdr_crc_word_lo then
v_hi := c_network_ip_header_checksum_w - 1 - c_crc_hi_bit_in_word - 1 - g_data_w * (c_hdr_crc_word_hi - v_count - 1);
v_lo := v_hi + 1 - g_data_w;
src_out.data(g_data_w - 1 downto 0) <= checksum(v_hi downto v_lo);
end if;
end if;
if reg_done = '1' and dp_pipeline_src_out.eop = '1' then
nxt_reg_done <= '0';
end if;
end process;
end generate;
------------------------------------------------------------------------------------------
-- using common_counter to keep track of the word alignment during checksum calculation --
------------------------------------------------------------------------------------------
u_calc_counter : entity common_lib.common_counter
generic map (
g_init => c_hdr_nof_words - 1,
g_step_size => -1
)
port map (
rst => rst,
clk => clk,
cnt_ld => snk_in.sop,
cnt_en => snk_in.valid,
count => count
);
-------------------------------------------------------------------------------
-- using dp_pipeline to make room for the checksum calculation and insertion --
-------------------------------------------------------------------------------
u_dp_pipeline : entity dp_lib.dp_pipeline
generic map (
g_pipeline => 1 -- fixed to 1 as common_counter has fixed latency of 1 (cannot be higher)
)
port map (
rst => rst,
clk => clk,
-- ST sink
snk_out => snk_out,
snk_in => snk_in,
-- ST source
src_in => src_in,
src_out => dp_pipeline_src_out
);
end rtl;
...@@ -42,10 +42,13 @@ entity eth_tester is ...@@ -42,10 +42,13 @@ entity eth_tester is
g_bg_sync_timeout : natural := c_eth_tester_sync_timeout; g_bg_sync_timeout : natural := c_eth_tester_sync_timeout;
g_nof_octet_generate : natural := 1; g_nof_octet_generate : natural := 1;
g_nof_octet_output : natural := 4; -- must be multiple of g_nof_octet_generate. g_nof_octet_output : natural := 4; -- must be multiple of g_nof_octet_generate.
g_use_network_header : boolean := true; g_use_eth_header : boolean := true;
g_use_ip_udp_header : boolean := true;
g_use_dp_header : boolean := true; g_use_dp_header : boolean := true;
g_hdr_calc_ip_crc : boolean := false;
g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr; g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr;
g_hdr_field_sel : std_logic_vector := c_eth_tester_hdr_field_sel; g_hdr_field_sel : std_logic_vector := c_eth_tester_hdr_field_sel;
g_hdr_app_len : natural := c_eth_tester_app_hdr_len;
g_remove_crc : boolean := true -- use TRUE when using sim_tse and tech_tse link interface, g_remove_crc : boolean := true -- use TRUE when using sim_tse and tech_tse link interface,
-- use FALSE when streaming link interface -- use FALSE when streaming link interface
); );
...@@ -125,10 +128,13 @@ begin ...@@ -125,10 +128,13 @@ begin
g_bg_sync_timeout => g_bg_sync_timeout, g_bg_sync_timeout => g_bg_sync_timeout,
g_nof_octet_generate => g_nof_octet_generate, g_nof_octet_generate => g_nof_octet_generate,
g_nof_octet_output => g_nof_octet_output, g_nof_octet_output => g_nof_octet_output,
g_use_network_header => g_use_network_header, g_use_eth_header => g_use_eth_header,
g_use_ip_udp_header => g_use_ip_udp_header,
g_use_dp_header => g_use_dp_header, g_use_dp_header => g_use_dp_header,
g_hdr_calc_ip_crc => g_hdr_calc_ip_crc,
g_hdr_field_arr => g_hdr_field_arr, g_hdr_field_arr => g_hdr_field_arr,
g_hdr_field_sel => g_hdr_field_sel g_hdr_field_sel => g_hdr_field_sel,
g_hdr_app_len => g_hdr_app_len
) )
port map ( port map (
-- Clocks and reset -- Clocks and reset
......
...@@ -48,11 +48,13 @@ entity eth_tester_tx is ...@@ -48,11 +48,13 @@ entity eth_tester_tx is
g_bg_sync_timeout : natural := 220 * 10**6; -- 10% margin for nominal 1 s with st_clk at 200MHz g_bg_sync_timeout : natural := 220 * 10**6; -- 10% margin for nominal 1 s with st_clk at 200MHz
g_nof_octet_generate : natural := 1; g_nof_octet_generate : natural := 1;
g_nof_octet_output : natural := 4; -- must be multiple of g_nof_octet_generate g_nof_octet_output : natural := 4; -- must be multiple of g_nof_octet_generate
g_use_network_header : boolean := true; g_use_eth_header : boolean := true;
g_use_ip_udp_header : boolean := true;
g_use_dp_header : boolean := true; g_use_dp_header : boolean := true;
g_hdr_calc_ip_crc : boolean := false;
g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr; g_hdr_field_arr : t_common_field_arr := c_eth_tester_hdr_field_arr;
g_hdr_field_sel : std_logic_vector := c_eth_tester_hdr_field_sel g_hdr_field_sel : std_logic_vector := c_eth_tester_hdr_field_sel;
g_hdr_app_len : natural := c_eth_tester_app_hdr_len
); );
port ( port (
-- Clocks and reset -- Clocks and reset
...@@ -109,6 +111,7 @@ architecture str of eth_tester_tx is ...@@ -109,6 +111,7 @@ architecture str of eth_tester_tx is
constant c_out_data_w : natural := g_nof_octet_output * c_octet_w; constant c_out_data_w : natural := g_nof_octet_output * c_octet_w;
constant c_nof_symbols_max : natural := c_network_eth_payload_jumbo_max; constant c_nof_symbols_max : natural := c_network_eth_payload_jumbo_max;
constant c_use_split : boolean := sel_a_b(g_nof_octet_generate > 1, true, false); constant c_use_split : boolean := sel_a_b(g_nof_octet_generate > 1, true, false);
constant c_hdr_calc_ip_crc : boolean := g_use_ip_udp_header and g_hdr_calc_ip_crc;
signal ip_total_length : natural; signal ip_total_length : natural;
signal udp_total_length : natural; signal udp_total_length : natural;
...@@ -134,6 +137,8 @@ architecture str of eth_tester_tx is ...@@ -134,6 +137,8 @@ architecture str of eth_tester_tx is
signal i_tx_fifo_rd_emp : std_logic; signal i_tx_fifo_rd_emp : std_logic;
signal tx_offload_siso : t_dp_siso; signal tx_offload_siso : t_dp_siso;
signal tx_offload_sosi : t_dp_sosi; signal tx_offload_sosi : t_dp_sosi;
signal tx_offload_frame_siso : t_dp_siso;
signal tx_offload_frame_sosi : t_dp_sosi;
signal i_ref_sync : std_logic := '0'; signal i_ref_sync : std_logic := '0';
signal in_strobe_arr : std_logic_vector(c_nof_total_counts - 1 downto 0); signal in_strobe_arr : std_logic_vector(c_nof_total_counts - 1 downto 0);
...@@ -334,12 +339,15 @@ begin ...@@ -334,12 +339,15 @@ begin
-- until it restarts, so no need to pass bg_block_len on via e.g. the channel -- until it restarts, so no need to pass bg_block_len on via e.g. the channel
-- field in u_fifo. -- field in u_fifo.
bg_block_len <= split_nof_symbols when c_use_split else TO_UINT(bg_ctrl_hold.samples_per_packet(15 downto 0)); -- packet lenghts fit in 16b bg_block_len <= split_nof_symbols when c_use_split else TO_UINT(bg_ctrl_hold.samples_per_packet(15 downto 0)); -- packet lenghts fit in 16b
app_total_length <= c_eth_tester_app_hdr_len + bg_block_len when rising_edge(st_clk); app_total_length <= g_hdr_app_len + bg_block_len when rising_edge(st_clk);
udp_total_length <= c_network_udp_header_len + app_total_length when rising_edge(st_clk); udp_total_length <= c_network_udp_header_len + app_total_length when rising_edge(st_clk);
ip_total_length <= c_network_ip_header_len + udp_total_length when rising_edge(st_clk); ip_total_length <= c_network_ip_header_len + udp_total_length when rising_edge(st_clk);
gen_network_header : if g_use_network_header generate gen_eth_header : if g_use_eth_header generate
hdr_fields_slv_in(field_hi(g_hdr_field_arr, "eth_src_mac" ) downto field_lo(g_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac; hdr_fields_slv_in(field_hi(g_hdr_field_arr, "eth_src_mac" ) downto field_lo(g_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac;
end generate;
gen_ip_udp_header : if g_use_ip_udp_header generate
hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_total_length" ) downto field_lo(g_hdr_field_arr, "ip_total_length" )) <= TO_UVEC(ip_total_length, 16); hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_total_length" ) downto field_lo(g_hdr_field_arr, "ip_total_length" )) <= TO_UVEC(ip_total_length, 16);
hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_src_addr" ) downto field_lo(g_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr; hdr_fields_slv_in(field_hi(g_hdr_field_arr, "ip_src_addr" ) downto field_lo(g_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr;
hdr_fields_slv_in(field_hi(g_hdr_field_arr, "udp_src_port" ) downto field_lo(g_hdr_field_arr, "udp_src_port" )) <= udp_src_port; hdr_fields_slv_in(field_hi(g_hdr_field_arr, "udp_src_port" ) downto field_lo(g_hdr_field_arr, "udp_src_port" )) <= udp_src_port;
...@@ -387,6 +395,33 @@ begin ...@@ -387,6 +395,33 @@ begin
hdr_fields_rec_in <= func_eth_tester_map_header(hdr_fields_slv_in); hdr_fields_rec_in <= func_eth_tester_map_header(hdr_fields_slv_in);
hdr_fields_rec_tx <= func_eth_tester_map_header(hdr_fields_slv_tx); hdr_fields_rec_tx <= func_eth_tester_map_header(hdr_fields_slv_tx);
-------------------------------------------------------------------------------
-- IP header checksum
-------------------------------------------------------------------------------
gen_ip_crc : if c_hdr_calc_ip_crc generate
u_eth_ip_header_checksum : entity work.eth_ip_header_checksum
generic map (
g_data_w => c_out_data_w,
g_hdr_field_arr => g_hdr_field_arr
)
port map (
rst => st_rst,
clk => st_clk,
snk_in => tx_offload_sosi,
snk_out => tx_offload_siso,
src_out => tx_offload_frame_sosi,
src_in => tx_offload_frame_siso,
hdr_fields_slv_in => hdr_fields_slv_tx
);
end generate;
gen_no_ip_crc : if not c_hdr_calc_ip_crc generate
tx_offload_frame_sosi <= tx_offload_sosi;
tx_offload_siso <= tx_offload_frame_siso;
end generate;
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
-- dp_pipeline_ready to ease timing closure -- dp_pipeline_ready to ease timing closure
...@@ -396,8 +431,8 @@ begin ...@@ -396,8 +431,8 @@ begin
rst => st_rst, rst => st_rst,
clk => st_clk, clk => st_clk,
snk_out => tx_offload_siso, snk_out => tx_offload_frame_siso,
snk_in => tx_offload_sosi, snk_in => tx_offload_frame_sosi,
src_in => tx_udp_siso, src_in => tx_udp_siso,
src_out => i_tx_udp_sosi src_out => i_tx_udp_sosi
); );
......
This diff is collapsed.
-- --------------------------------------------------------------------------
-- Copyright 2023
-- 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. vd Walle
-- Purpose: Regression multi tb for eth_ip_header_checksum
-- Description:
-- Usage:
-- > as 4
-- > run -all
library IEEE, dp_lib;
use IEEE.std_logic_1164.all;
use dp_lib.tb_dp_pkg.all; -- for t_dp_flow_control_enum
entity tb_tb_eth_ip_header_checksum is
end tb_tb_eth_ip_header_checksum;
architecture tb of tb_tb_eth_ip_header_checksum is
signal tb_end : std_logic := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
begin
-- -- general
-- g_flow_control_stimuli : t_dp_flow_control_enum := e_pulse; -- always e_active, e_random or e_pulse flow control
-- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control
-- g_print_en : BOOLEAN := TRUE;
-- -- specific
-- g_data_w : NATURAL := 64;
-- g_symbol_w : NATURAL := 16;
-- g_empty : NATURAL := 6; -- number of empty symbols in header when g_symbol_w < g_data_w, must be < c_nof_symbols_per_data
-- g_pkt_len : NATURAL := 240;
-- g_pkt_gap : NATURAL := 16
u_pls_act_data_w_256 : entity work.tb_eth_ip_header_checksum generic map (e_pulse, e_active, false, 256, 64, 0, 240, 16);
u_act_act_data_w_512_no_gap : entity work.tb_eth_ip_header_checksum generic map (e_active, e_active, false, 512, 8, 0, 240, 0);
u_pls_act_data_w_64_no_gap : entity work.tb_eth_ip_header_checksum generic map (e_pulse, e_active, false, 64, 64, 0, 240, 0);
u_rnd_act_data_w_32 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 32, 8, 0, 240, 16);
u_rnd_act_data_w_8 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 8, 8, 0, 240, 16);
--u_act_rnd_data_w : ENTITY work.tb_eth_ip_header_checksum GENERIC MAP (e_active, e_random, FALSE, 64, 64, 0, 240, 16); -- dp_offload_rx requires e_active
u_rnd_act_data_64_symbol_8_empty_1 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 64, 8, 1, 240, 16);
u_rnd_act_data_64_symbol_8_empty_6 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 64, 8, 6, 240, 16);
u_rnd_act_data_64_symbol_16 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 64, 16, 1, 240, 16);
u_rnd_act_data_64_symbol_32 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 64, 32, 1, 240, 16);
u_rnd_act_data_32_symbol_8 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 32, 8, 1, 240, 16);
u_rnd_act_data_32_symbol_16 : entity work.tb_eth_ip_header_checksum generic map (e_random, e_active, false, 32, 16, 1, 240, 16);
end tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment