diff --git a/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg b/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg index c449e83d95a91ecdf4244a1e792bbbc7ca5316ae..70a9f1437ef434bb1c44fe5f959ffb0cf9e57f7f 100644 --- a/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg +++ b/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg @@ -1,12 +1,13 @@ hdl_lib_name = rdma_packetiser hdl_library_clause_name = rdma_packetiser_lib -hdl_lib_uses_synth = common dp eth +hdl_lib_uses_synth = common dp eth rdma_icrc_external hdl_lib_uses_sim = diag technology hdl_lib_technology = synth_files = src/vhdl/rdma_packetiser_pkg.vhd src/vhdl/rdma_packetiser_assemble_header.vhd + src/vhdl/rdma_packetiser.vhd test_bench_files = tb/vhdl/tb_rdma_packetiser_assemble_header.vhd diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd new file mode 100644 index 0000000000000000000000000000000000000000..462ff07b7e61f46855866a901d076d990c9c527d --- /dev/null +++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd @@ -0,0 +1,200 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2024 +-- 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: Packetizes an incoming data stream as RDMA "WRITE" packets. +-- Description: see https://support.astron.nl/confluence/x/urT-Bg +-- +library IEEE, common_lib, dp_lib, eth_lib, rdma_icrc_external_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 eth_lib.eth_pkg.all; +use eth_lib.eth_tester_pkg.all; + +entity rdma_packetiser is + generic ( + g_cross_clock_domain : boolean := false; + g_sync_timeout : natural := c_dp_sync_timeout + ); + port ( + -- Clocks and reset + dp_clk : in std_logic; + dp_rst : in std_logic; + + mm_clk : in std_logic; + mm_rst : in std_logic; + + reg_hdr_dat_copi : in t_mem_copi := c_mem_copi_rst; + reg_hdr_dat_cipo : out t_mem_cipo; + + reg_bsn_monitor_v2_rdma_packetiser_input_copi : in t_mem_copi := c_mem_copi_rst; + reg_bsn_monitor_v2_rdma_packetiser_input_cipo : out t_mem_cipo; + reg_bsn_monitor_v2_rdma_packetiser_output_copi : in t_mem_copi := c_mem_copi_rst; + reg_bsn_monitor_v2_rdma_packetiser_output_cipo : out t_mem_cipo; + + snk_in : in t_dp_sosi := c_dp_sosi_rst; + snk_out : out t_dp_siso := c_dp_siso_rdy; + + src_out : out t_dp_sosi := c_dp_sosi_rst; + src_in : in t_dp_siso := c_dp_siso_rdy; + + block_len : in std_logic_vector(c_halfword_w - 1 downto 0) -- in octets + ); +end rdma_packetiser; + +architecture str of rdma_packetiser is + constant c_nof_byte : natural := 64; + constant c_data_w : natural := c_nof_byte * c_byte_w; + constant c_max_packet_size : natural := ceil_div(9000, c_nof_byte); + + signal dp_xonoff_sosi : t_dp_sosi := c_dp_sosi_rst; + signal dp_xonoff_siso : t_dp_siso := c_dp_siso_rdy; + signal dp_fifo_data_sosi : t_dp_sosi := c_dp_sosi_rst; + signal dp_fifo_data_siso : t_dp_siso := c_dp_siso_rdy; + signal assemble_header_sosi : t_dp_sosi := c_dp_sosi_rst; + signal assemble_header_siso : t_dp_siso := c_dp_siso_rdy; + signal icrc_sosi : t_dp_sosi := c_dp_sosi_rst; + signal icrc_siso : t_dp_siso := c_dp_siso_rdy; + +begin + -- dp_xonoff to prevent fifo overflow + u_dp_xonoff : entity dp_lib.dp_xonoff + port map ( + rst => dp_rst, + clk => dp_clk, + + in_siso => snk_out, + in_sosi => snk_in, + out_siso => dp_xonoff_siso, + out_sosi => dp_xonoff_sosi + ); + + -- dp_fifo_fill_eop + u_dp_fifo_data : entity dp_lib.dp_fifo_fill_eop_sc + generic map ( + g_data_w => c_data_w, + g_empty_w => c_byte_w, + g_bsn_w => 64, + g_use_empty => true, + g_use_bsn => true, + g_use_sync => true, + g_fifo_size => c_max_packet_size * 2, + g_fifo_fill => c_max_packet_size, + g_fifo_rl => 1, + g_fifo_af_margin => 0, + g_fifo_af_xon => 0 + ) + port map ( + clk => dp_clk, + rst => dp_rst, + snk_in => dp_xonoff_sosi, + snk_out => dp_xonoff_siso, + src_out => dp_fifo_data_sosi, + src_in => dp_fifo_data_siso + ); + + -- mms_dp_bsn_monitor_v2 + u_bsn_mon_input : entity dp_lib.mms_dp_bsn_monitor_v2 + generic map ( + g_nof_streams => 1, + g_cross_clock_domain => g_cross_clock_domain, + g_sync_timeout => g_sync_timeout + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + reg_mosi => reg_bsn_monitor_v2_rdma_packetiser_input_copi, + reg_miso => reg_bsn_monitor_v2_rdma_packetiser_input_cipo, + + -- Streaming clock domain + dp_rst => dp_rst, + dp_clk => dp_clk, + ref_sync => snk_in.sync, + + in_sosi_arr(0) => dp_fifo_data_sosi + ); + + u_rdma_assemble_header : entity work.rdma_packetiser_assemble_header + generic map ( + g_data_w => c_data_w + ) + port map ( + -- Clocks and reset + mm_rst => mm_rst, + mm_clk => mm_clk, + st_rst => dp_rst, + st_clk => dp_clk, + + -- Streaming interfaces + snk_in => dp_fifo_data_sosi, + snk_out => dp_fifo_data_siso, + src_out => assemble_header_sosi, + src_in => assemble_header_siso, + + -- Memory Mapped Peripherals + reg_hdr_dat_copi => reg_hdr_dat_copi, + reg_hdr_dat_cipo => reg_hdr_dat_cipo, + + -- block length in nof octets + block_len => block_len + ); + + u_icrc_append : entity rdma_icrc_external_lib.append_crc_dp_wrapper + port map ( + dp_clk => dp_clk, + dp_rst => dp_rst, + + in_dp_sosi => assemble_header_sosi, + in_dp_siso => assemble_header_siso, + + out_dp_sosi => icrc_sosi, + out_dp_siso => icrc_siso + ); + + -- mms_dp_bsn_monitor_v2 + u_bsn_mon_output : entity dp_lib.mms_dp_bsn_monitor_v2 + generic map ( + g_nof_streams => 1, + g_cross_clock_domain => g_cross_clock_domain, + g_sync_timeout => g_sync_timeout + ) + port map ( + -- Memory-mapped clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + reg_mosi => reg_bsn_monitor_v2_rdma_packetiser_output_copi, + reg_miso => reg_bsn_monitor_v2_rdma_packetiser_output_cipo, + + -- Streaming clock domain + dp_rst => dp_rst, + dp_clk => dp_clk, + ref_sync => snk_in.sync, + + in_sosi_arr(0) => icrc_sosi + ); + + src_out <= icrc_sosi; + icrc_siso <= src_in; + +end str; diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd index a71c4922a3629945ec991744097b1c3c73546024..9ab165aaf994a8e9caed130beacc04ccc208eec4 100644 --- a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd +++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd @@ -120,9 +120,10 @@ architecture str of rdma_packetiser_assemble_header is ip_total_length : natural; nof_packets_in_msg : natural; sel_ctrl : natural range 0 to c_nof_offload - 1; + sel_ctrl_delayed : natural range 0 to c_nof_offload - 1; end record; - constant c_reg_rst : t_reg := (s_first, (others => '1'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0, 0); + constant c_reg_rst : t_reg := (s_first, (others => '1'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0, 0, 0); signal d, q : t_reg; signal use_immediate : std_logic; @@ -144,22 +145,22 @@ architecture str of rdma_packetiser_assemble_header is signal dp_demux_src_in_arr : t_dp_siso_arr(c_nof_offload - 1 downto 0) := (others => c_dp_siso_rdy); signal dp_mux_snk_in_arr : t_dp_sosi_arr(c_nof_offload - 1 downto 0) := (others => c_dp_sosi_rst); signal dp_mux_snk_out_arr : t_dp_siso_arr(c_nof_offload - 1 downto 0) := (others => c_dp_siso_rdy); - signal dp_offload_first_snk_in : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_first_snk_out : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_first_src_out : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_first_src_in : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_mid_snk_in : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_mid_snk_out : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_mid_src_out : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_mid_src_in : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_last_snk_in : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_last_snk_out : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_last_src_out : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_last_src_in : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_wo_snk_in : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_wo_snk_out : t_dp_siso := c_dp_siso_rdy; - signal dp_offload_wo_src_out : t_dp_sosi := c_dp_sosi_rst; - signal dp_offload_wo_src_in : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_first_snk_in : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_first_snk_out : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_first_src_out : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_first_src_in : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_mid_snk_in : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_mid_snk_out : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_mid_src_out : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_mid_src_in : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_last_snk_in : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_last_snk_out : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_last_src_out : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_last_src_in : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_wo_snk_in : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_wo_snk_out : t_dp_siso := c_dp_siso_rdy; + signal eth_ip_offload_wo_src_out : t_dp_sosi := c_dp_sosi_rst; + signal eth_ip_offload_wo_src_in : t_dp_siso := c_dp_siso_rdy; signal dp_pipeline_src_out : t_dp_sosi := c_dp_sosi_rst; begin @@ -177,6 +178,7 @@ begin variable v : t_reg; begin v := q; + v.sel_ctrl_delayed := q.sel_ctrl; if snk_in.sop = '1' then v.psn := resize_uvec(snk_in.bsn, c_word_w); v.p_cnt := q.p_cnt + 1; @@ -265,7 +267,7 @@ begin hdr_fields_slv_in(field_hi(c_rdma_packetiser_mm_field_arr, "reth_dma_length" ) downto field_lo(c_rdma_packetiser_mm_field_arr, "reth_dma_length" )) <= std_logic_vector(q.dma_len); ------------------------------------------------------------------------------- - -- demux to guide the incoming stream to the correct dp_offload_tx_v3 + -- demux to guide the incoming stream to the correct eth_ip_offload_tx ------------------------------------------------------------------------------- u_dp_demux : entity dp_lib.dp_demux generic map ( @@ -289,16 +291,16 @@ begin ); -- Wire demux outputs to dp_offload inputs. - dp_offload_first_snk_in <= dp_demux_src_out_arr(0); - dp_offload_mid_snk_in <= dp_demux_src_out_arr(1); - dp_offload_last_snk_in <= dp_demux_src_out_arr(2); - dp_offload_wo_snk_in <= dp_demux_src_out_arr(3); - dp_demux_src_in_arr(0) <= dp_offload_first_snk_out; - dp_demux_src_in_arr(1) <= dp_offload_mid_snk_out; - dp_demux_src_in_arr(2) <= dp_offload_last_snk_out; - dp_demux_src_in_arr(3) <= dp_offload_wo_snk_out; - - -- Wire header fields for every do_offload + eth_ip_offload_first_snk_in <= dp_demux_src_out_arr(0); + eth_ip_offload_mid_snk_in <= dp_demux_src_out_arr(1); + eth_ip_offload_last_snk_in <= dp_demux_src_out_arr(2); + eth_ip_offload_wo_snk_in <= dp_demux_src_out_arr(3); + dp_demux_src_in_arr(0) <= eth_ip_offload_first_snk_out; + dp_demux_src_in_arr(1) <= eth_ip_offload_mid_snk_out; + dp_demux_src_in_arr(2) <= eth_ip_offload_last_snk_out; + dp_demux_src_in_arr(3) <= eth_ip_offload_wo_snk_out; + + -- Wire header fields for every eth_ip_offload_tx p_wire_headers : process(hdr_fields_slv_out_mm, use_msg_cnt_as_immediate, q) begin -- set headers. @@ -322,11 +324,10 @@ begin field_lo(c_rdma_packetiser_wo_hdr_field_arr, "immediate_data")) <= TO_UVEC(q.msg_cnt, 32); end if; end process; - ------------------------------------------------------------------------------- -- Header for first packets or write only without immediate data ------------------------------------------------------------------------------- - u_dp_offload_first : entity dp_lib.dp_offload_tx_v3 + u_eth_ip_offload_first : entity eth_lib.eth_ip_offload_tx generic map ( g_nof_streams => 1, g_data_w => g_data_w, @@ -338,17 +339,17 @@ begin port map ( dp_rst => st_rst, dp_clk => st_clk, - snk_in_arr(0) => dp_offload_first_snk_in, - snk_out_arr(0) => dp_offload_first_snk_out, - src_out_arr(0) => dp_offload_first_src_out, - src_in_arr(0) => dp_offload_first_src_in, + snk_in_arr(0) => eth_ip_offload_first_snk_in, + snk_out_arr(0) => eth_ip_offload_first_snk_out, + src_out_arr(0) => eth_ip_offload_first_src_out, + src_in_arr(0) => eth_ip_offload_first_src_in, hdr_fields_in_arr(0) => hdr_fields_slv_in_first ); ------------------------------------------------------------------------------- -- Header for middle or last without immediate data (no RETH, no immediate data) ------------------------------------------------------------------------------- - u_dp_offload_mid : entity dp_lib.dp_offload_tx_v3 + u_eth_ip_offload_mid : entity eth_lib.eth_ip_offload_tx generic map ( g_nof_streams => 1, g_data_w => g_data_w, @@ -360,17 +361,17 @@ begin port map ( dp_rst => st_rst, dp_clk => st_clk, - snk_in_arr(0) => dp_offload_mid_snk_in, - snk_out_arr(0) => dp_offload_mid_snk_out, - src_out_arr(0) => dp_offload_mid_src_out, - src_in_arr(0) => dp_offload_mid_src_in, + snk_in_arr(0) => eth_ip_offload_mid_snk_in, + snk_out_arr(0) => eth_ip_offload_mid_snk_out, + src_out_arr(0) => eth_ip_offload_mid_src_out, + src_in_arr(0) => eth_ip_offload_mid_src_in, hdr_fields_in_arr(0) => hdr_fields_slv_in_mid ); ------------------------------------------------------------------------------- -- Header for last packets with immediate data ------------------------------------------------------------------------------- - u_dp_offload_last : entity dp_lib.dp_offload_tx_v3 + u_eth_ip_offload_last : entity eth_lib.eth_ip_offload_tx generic map ( g_nof_streams => 1, g_data_w => g_data_w, @@ -382,17 +383,17 @@ begin port map ( dp_rst => st_rst, dp_clk => st_clk, - snk_in_arr(0) => dp_offload_last_snk_in, - snk_out_arr(0) => dp_offload_last_snk_out, - src_out_arr(0) => dp_offload_last_src_out, - src_in_arr(0) => dp_offload_last_src_in, + snk_in_arr(0) => eth_ip_offload_last_snk_in, + snk_out_arr(0) => eth_ip_offload_last_snk_out, + src_out_arr(0) => eth_ip_offload_last_src_out, + src_in_arr(0) => eth_ip_offload_last_src_in, hdr_fields_in_arr(0) => hdr_fields_slv_in_last ); ------------------------------------------------------------------------------- -- Header for write only packets with immediate data ------------------------------------------------------------------------------- - u_dp_offload_wo : entity dp_lib.dp_offload_tx_v3 + u_eth_ip_offload_wo : entity eth_lib.eth_ip_offload_tx generic map ( g_nof_streams => 1, g_data_w => g_data_w, @@ -404,10 +405,10 @@ begin port map ( dp_rst => st_rst, dp_clk => st_clk, - snk_in_arr(0) => dp_offload_wo_snk_in, - snk_out_arr(0) => dp_offload_wo_snk_out, - src_out_arr(0) => dp_offload_wo_src_out, - src_in_arr(0) => dp_offload_wo_src_in, + snk_in_arr(0) => eth_ip_offload_wo_snk_in, + snk_out_arr(0) => eth_ip_offload_wo_snk_out, + src_out_arr(0) => eth_ip_offload_wo_src_out, + src_in_arr(0) => eth_ip_offload_wo_src_in, hdr_fields_in_arr(0) => hdr_fields_slv_in_wo ); @@ -419,7 +420,6 @@ begin port map ( rst => st_rst, clk => st_clk, - snk_out => open, snk_in => snk_in, src_out => dp_pipeline_src_out ); @@ -447,17 +447,17 @@ begin ); ------------------------------------------------------------------------------- - -- Mux to merge the packets from the different dp_offload_tx_v3 + -- Mux to merge the packets from the different eth_ip_offload_tx ------------------------------------------------------------------------------- -- Wire demux outputs to dp_offload inputs. - dp_mux_snk_in_arr(0) <= dp_offload_first_src_out; - dp_mux_snk_in_arr(1) <= dp_offload_mid_src_out; - dp_mux_snk_in_arr(2) <= dp_offload_last_src_out; - dp_mux_snk_in_arr(3) <= dp_offload_wo_src_out; - dp_offload_first_src_in <= dp_mux_snk_out_arr(0); - dp_offload_mid_src_in <= dp_mux_snk_out_arr(1); - dp_offload_last_src_in <= dp_mux_snk_out_arr(2); - dp_offload_wo_src_in <= dp_mux_snk_out_arr(3); + dp_mux_snk_in_arr(0) <= eth_ip_offload_first_src_out; + dp_mux_snk_in_arr(1) <= eth_ip_offload_mid_src_out; + dp_mux_snk_in_arr(2) <= eth_ip_offload_last_src_out; + dp_mux_snk_in_arr(3) <= eth_ip_offload_wo_src_out; + eth_ip_offload_first_src_in <= dp_mux_snk_out_arr(0); + eth_ip_offload_mid_src_in <= dp_mux_snk_out_arr(1); + eth_ip_offload_last_src_in <= dp_mux_snk_out_arr(2); + eth_ip_offload_wo_src_in <= dp_mux_snk_out_arr(3); u_dp_mux : entity dp_lib.dp_mux generic map ( @@ -472,7 +472,7 @@ begin port map ( rst => st_rst, clk => st_clk, - sel_ctrl => q.sel_ctrl, + sel_ctrl => q.sel_ctrl_delayed, snk_in_arr => dp_mux_snk_in_arr, snk_out_arr => dp_mux_snk_out_arr, src_out => src_out, diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd index b66da5f7dc56ef1eb9d137d0c2bca9c350c5bc0f..6909c4c228cfe15996c18f19c6b0b00fe404710b 100644 --- a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd +++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd @@ -356,6 +356,7 @@ package rdma_packetiser_pkg is constant c_rdma_packetiser_opcode_uc_write_only_imm : std_logic_vector(7 downto 0) := "001" & "01011"; -- with immediate function func_rdma_packetiser_map_header(hdr_fields_raw : std_logic_vector; field_arr : t_common_field_arr) return t_rdma_packetiser_roce_header; + function func_rdma_packetiser_unmap_header(hdr_fields : t_rdma_packetiser_roce_header; field_arr : t_common_field_arr) return std_logic_vector; end rdma_packetiser_pkg; package body rdma_packetiser_pkg is @@ -420,4 +421,60 @@ package body rdma_packetiser_pkg is return v; end func_rdma_packetiser_map_header; + function func_rdma_packetiser_unmap_header(hdr_fields : t_rdma_packetiser_roce_header; field_arr : t_common_field_arr) return std_logic_vector is + constant c_field_len : natural := field_slv_len(field_arr); + variable v : std_logic_vector(c_field_len-1 downto 0) := (others => '0'); + constant c_hdr_field_arr : t_common_field_arr := field_arr; + begin + -- eth header + v(field_hi(c_hdr_field_arr, "eth_dst_mac") downto field_lo(c_hdr_field_arr, "eth_dst_mac")) := hdr_fields.eth.dst_mac; + v(field_hi(c_hdr_field_arr, "eth_src_mac") downto field_lo(c_hdr_field_arr, "eth_src_mac")) := hdr_fields.eth.src_mac; + v(field_hi(c_hdr_field_arr, "eth_type") downto field_lo(c_hdr_field_arr, "eth_type")) := hdr_fields.eth.eth_type; + + -- ip header + v(field_hi(c_hdr_field_arr, "ip_version") downto field_lo(c_hdr_field_arr, "ip_version")) := hdr_fields.ip.version; + v(field_hi(c_hdr_field_arr, "ip_header_length") downto field_lo(c_hdr_field_arr, "ip_header_length")) := hdr_fields.ip.header_length; + v(field_hi(c_hdr_field_arr, "ip_services") downto field_lo(c_hdr_field_arr, "ip_services")) := hdr_fields.ip.services; + v(field_hi(c_hdr_field_arr, "ip_total_length") downto field_lo(c_hdr_field_arr, "ip_total_length")) := hdr_fields.ip.total_length; + v(field_hi(c_hdr_field_arr, "ip_identification") downto field_lo(c_hdr_field_arr, "ip_identification")) := hdr_fields.ip.identification; + v(field_hi(c_hdr_field_arr, "ip_flags") downto field_lo(c_hdr_field_arr, "ip_flags")) := hdr_fields.ip.flags; + v(field_hi(c_hdr_field_arr, "ip_fragment_offset") downto field_lo(c_hdr_field_arr, "ip_fragment_offset")) := hdr_fields.ip.fragment_offset; + v(field_hi(c_hdr_field_arr, "ip_time_to_live") downto field_lo(c_hdr_field_arr, "ip_time_to_live")) := hdr_fields.ip.time_to_live; + v(field_hi(c_hdr_field_arr, "ip_protocol") downto field_lo(c_hdr_field_arr, "ip_protocol")) := hdr_fields.ip.protocol; + v(field_hi(c_hdr_field_arr, "ip_header_checksum") downto field_lo(c_hdr_field_arr, "ip_header_checksum")) := hdr_fields.ip.header_checksum; + v(field_hi(c_hdr_field_arr, "ip_src_addr") downto field_lo(c_hdr_field_arr, "ip_src_addr")) := hdr_fields.ip.src_ip_addr; + v(field_hi(c_hdr_field_arr, "ip_dst_addr") downto field_lo(c_hdr_field_arr, "ip_dst_addr")) := hdr_fields.ip.dst_ip_addr; + + -- udp header + v(field_hi(c_hdr_field_arr, "udp_src_port") downto field_lo(c_hdr_field_arr, "udp_src_port")) := hdr_fields.udp.src_port; + v(field_hi(c_hdr_field_arr, "udp_dst_port") downto field_lo(c_hdr_field_arr, "udp_dst_port")) := hdr_fields.udp.dst_port; + v(field_hi(c_hdr_field_arr, "udp_total_length") downto field_lo(c_hdr_field_arr, "udp_total_length")) := hdr_fields.udp.total_length; + v(field_hi(c_hdr_field_arr, "udp_checksum") downto field_lo(c_hdr_field_arr, "udp_checksum")) := hdr_fields.udp.checksum; + + -- bth header + v(field_hi(c_hdr_field_arr, "bth_opcode") downto field_lo(c_hdr_field_arr, "bth_opcode")) := hdr_fields.bth.opcode; + v(field_hi(c_hdr_field_arr, "bth_se") downto field_lo(c_hdr_field_arr, "bth_se")) := hdr_fields.bth.se; + v(field_hi(c_hdr_field_arr, "bth_m") downto field_lo(c_hdr_field_arr, "bth_m")) := hdr_fields.bth.m; + v(field_hi(c_hdr_field_arr, "bth_pad") downto field_lo(c_hdr_field_arr, "bth_pad")) := hdr_fields.bth.pad; + v(field_hi(c_hdr_field_arr, "bth_tver") downto field_lo(c_hdr_field_arr, "bth_tver")) := hdr_fields.bth.tver; + v(field_hi(c_hdr_field_arr, "bth_partition_key") downto field_lo(c_hdr_field_arr, "bth_partition_key")) := hdr_fields.bth.partition_key; + v(field_hi(c_hdr_field_arr, "bth_fres") downto field_lo(c_hdr_field_arr, "bth_fres")) := hdr_fields.bth.fres; + v(field_hi(c_hdr_field_arr, "bth_bres") downto field_lo(c_hdr_field_arr, "bth_bres")) := hdr_fields.bth.bres; + v(field_hi(c_hdr_field_arr, "bth_reserved_a") downto field_lo(c_hdr_field_arr, "bth_reserved_a")) := hdr_fields.bth.reserved_a; + v(field_hi(c_hdr_field_arr, "bth_dest_qp") downto field_lo(c_hdr_field_arr, "bth_dest_qp")) := hdr_fields.bth.dest_qp; + v(field_hi(c_hdr_field_arr, "bth_ack_req") downto field_lo(c_hdr_field_arr, "bth_ack_req")) := hdr_fields.bth.ack_req; + v(field_hi(c_hdr_field_arr, "bth_reserved_b") downto field_lo(c_hdr_field_arr, "bth_reserved_b")) := hdr_fields.bth.reserved_b; + v(field_hi(c_hdr_field_arr, "bth_psn") downto field_lo(c_hdr_field_arr, "bth_psn")) := hdr_fields.bth.psn; + + -- reth header + v(field_hi(c_hdr_field_arr, "reth_virtual_address") downto field_lo(c_hdr_field_arr, "reth_virtual_address")) := hdr_fields.reth.virtual_address; + v(field_hi(c_hdr_field_arr, "reth_r_key") downto field_lo(c_hdr_field_arr, "reth_r_key")) := hdr_fields.reth.r_key; + v(field_hi(c_hdr_field_arr, "reth_dma_length") downto field_lo(c_hdr_field_arr, "reth_dma_length")) := hdr_fields.reth.dma_length; + + --immediate data + v(field_hi(c_hdr_field_arr, "immediate_data") downto field_lo(c_hdr_field_arr, "immediate_data")) := hdr_fields.immediate_data; + + return v; + end func_rdma_packetiser_unmap_header; + end rdma_packetiser_pkg; diff --git a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd index 66b41e714ef9bdf1ecf9cdc54577d267667194cc..d4d6c6b101d2bc99249e51cb1e504a552a06eabf 100644 --- a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd +++ b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd @@ -17,9 +17,6 @@ -- limitations under the License. -- ------------------------------------------------------------------------------- --- NOTE Work in progress, will be finished in HPR-131 -------------------------------------------------------------------------------- --- -- Author: R. vd Walle -- Purpose: -- . test bench for rdma_packetiser_assemble_header @@ -47,6 +44,7 @@ library IEEE, common_lib, dp_lib; use common_lib.common_pkg.all; use common_lib.common_mem_pkg.all; use common_lib.common_network_layers_pkg.all; + use common_lib.common_field_pkg.all; use common_lib.tb_common_pkg.all; use common_lib.tb_common_mem_pkg.all; use dp_lib.tb_dp_pkg.all; @@ -164,6 +162,8 @@ begin variable v_exp_reth_dma_length : natural; variable v_exp_immediate_data : std_logic_vector(c_word_w - 1 downto 0); variable v_p, v_m : natural := 0; + variable v_exp_hdr_raw : std_logic_vector(field_slv_len(c_rdma_packetiser_wo_hdr_field_arr) - 1 downto 0); + variable v_exp_rdma_header : t_rdma_packetiser_roce_header := func_rdma_packetiser_map_header(c_hdr_fields_slv_rst, c_rdma_packetiser_wo_hdr_field_arr); begin proc_common_wait_until_high(dp_clk, mm_done); -- wait mm setup @@ -229,28 +229,33 @@ begin -- assign expected values to signal to view in wave window. -- defaults - exp_rdma_header.eth.eth_type <= x"0800"; - exp_rdma_header.ip.version <= to_uvec(4, 4); - exp_rdma_header.ip.header_length <= to_uvec(5, 4); - exp_rdma_header.ip.flags <= to_uvec(2, 3); - exp_rdma_header.ip.time_to_live <= to_uvec(127, 8); - exp_rdma_header.ip.protocol <= to_uvec(17, 8); - exp_rdma_header.bth.partition_key <= to_uvec(65535, 16); + v_exp_rdma_header.eth.eth_type := x"0800"; + v_exp_rdma_header.ip.version := to_uvec(4, 4); + v_exp_rdma_header.ip.header_length := to_uvec(5, 4); + v_exp_rdma_header.ip.flags := to_uvec(2, 3); + v_exp_rdma_header.ip.time_to_live := to_uvec(127, 8); + v_exp_rdma_header.ip.protocol := to_uvec(17, 8); + v_exp_rdma_header.bth.partition_key := to_uvec(65535, 16); -- changed by DUT - exp_rdma_header.ip.total_length <= to_uvec(v_exp_ip_total_length, c_halfword_w); - exp_rdma_header.udp.total_length <= to_uvec(v_exp_udp_total_length, c_halfword_w ); - exp_rdma_header.bth.opcode <= v_exp_bth_opcode; - exp_rdma_header.bth.psn <= to_uvec(v_exp_bth_psn, c_word_w); - exp_rdma_header.reth.virtual_address <= std_logic_vector(v_exp_reth_virtual_address); - exp_rdma_header.reth.dma_length <= to_uvec(v_exp_reth_dma_length, c_word_w); - exp_rdma_header.immediate_data <= v_exp_immediate_data; + v_exp_rdma_header.ip.total_length := to_uvec(v_exp_ip_total_length, c_halfword_w); + v_exp_rdma_header.udp.total_length := to_uvec(v_exp_udp_total_length, c_halfword_w ); + v_exp_rdma_header.bth.opcode := v_exp_bth_opcode; + v_exp_rdma_header.bth.psn := to_uvec(v_exp_bth_psn, c_word_w); + v_exp_rdma_header.reth.virtual_address := std_logic_vector(v_exp_reth_virtual_address); + v_exp_rdma_header.reth.dma_length := to_uvec(v_exp_reth_dma_length, c_word_w); + v_exp_rdma_header.immediate_data := v_exp_immediate_data; + -- determine expected ip header checksum + v_exp_hdr_raw := func_rdma_packetiser_unmap_header(v_exp_rdma_header, c_rdma_packetiser_wo_hdr_field_arr); + v_exp_rdma_header.ip.header_checksum := func_network_ip_header_checksum(c_rdma_packetiser_wo_hdr_field_arr, v_exp_hdr_raw); + + exp_rdma_header <= v_exp_rdma_header; -- for view in wave window -- increase counters v_p := v_p + 1; v_m := v_p / g_nof_packets_in_msg; proc_common_wait_some_cycles(dp_clk, 1); - + -- assert when header is not as expected. assert rx_rdma_header = exp_rdma_header report "Wrong rx_rdma_header" severity error; assert rx_rdma_header.ip.total_length = exp_rdma_header.ip.total_length report "Wrong rx_rdma_header.ip.total_length value" severity error; diff --git a/libraries/io/eth/hdllib.cfg b/libraries/io/eth/hdllib.cfg index 86eb82159e6c2e1299e59bb71258a3df01426a58..2c904dd81bf8f9f2cfaf363282742d11261a5b2a 100644 --- a/libraries/io/eth/hdllib.cfg +++ b/libraries/io/eth/hdllib.cfg @@ -8,6 +8,7 @@ synth_files = src/vhdl/eth_pkg.vhd src/vhdl/eth_checksum.vhd src/vhdl/eth_ip_header_checksum.vhd + src/vhdl/eth_ip_offload_tx.vhd src/vhdl/eth_hdr_store.vhd src/vhdl/eth_hdr_status.vhd src/vhdl/eth_hdr_ctrl.vhd diff --git a/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd b/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f4e4c935f61481f4a2e827155375f20ff7647093 --- /dev/null +++ b/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd @@ -0,0 +1,120 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2024 +-- 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: +-- . concatenate header from hdr_fields_in_arr to incoming sosi stream and +-- calculate + insert ip header checksum (crc). +-- Description: +-- . dp_offload_tx_v3 is used to concatenate the header to the dp sosi stream. +-- . eth_ip_header_checksum is used to calculate and insert the ip header +-- checksum. +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_mem_pkg.all; +use dp_lib.dp_stream_pkg.all; +use common_lib.common_field_pkg.all; + +entity eth_ip_offload_tx 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 := '0'; + mm_clk : in std_logic := '0'; + + dp_rst : in std_logic; + dp_clk : in std_logic; + + reg_hdr_dat_copi : in t_mem_copi := c_mem_copi_rst; + reg_hdr_dat_cipo : out t_mem_cipo; + + 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 eth_ip_offload_tx; + +architecture str of eth_ip_offload_tx is + + signal dp_offload_tx_src_out_arr : t_dp_sosi_arr(g_nof_streams-1 downto 0) := (others => c_dp_sosi_rst); + signal dp_offload_tx_src_in_arr : t_dp_siso_arr(g_nof_streams-1 downto 0) := (others => c_dp_siso_rdy); + signal dp_offload_tx_hdr_fields_out_arr : t_slv_1024_arr(g_nof_streams - 1 downto 0); + +begin + + u_dp_offload_tx_v3 : entity dp_lib.dp_offload_tx_v3 + generic map ( + g_nof_streams => g_nof_streams, + g_data_w => g_data_w, + g_symbol_w => g_symbol_w, + g_hdr_field_arr => g_hdr_field_arr, + g_hdr_field_sel => g_hdr_field_sel, + g_pipeline_ready => g_pipeline_ready + ) + port map ( + mm_rst => mm_rst, + mm_clk => mm_clk, + dp_rst => dp_rst, + dp_clk => dp_clk, + reg_hdr_dat_mosi => reg_hdr_dat_copi, + reg_hdr_dat_miso => reg_hdr_dat_cipo, + snk_in_arr => snk_in_arr, + snk_out_arr => snk_out_arr, + src_out_arr => dp_offload_tx_src_out_arr, + src_in_arr => dp_offload_tx_src_in_arr, + hdr_fields_in_arr => hdr_fields_in_arr, + hdr_fields_out_arr => dp_offload_tx_hdr_fields_out_arr + ); + + hdr_fields_out_arr <= dp_offload_tx_hdr_fields_out_arr; + + gen_crc : for i in 0 to g_nof_streams - 1 generate + u_eth_ip_header_checksum : entity work.eth_ip_header_checksum + generic map ( + g_data_w => g_data_w, + g_hdr_field_arr => g_hdr_field_arr + ) + port map ( + rst => dp_rst, + clk => dp_clk, + + snk_in => dp_offload_tx_src_out_arr(i), + snk_out => dp_offload_tx_src_in_arr(i), + + src_out => src_out_arr(i), + src_in => src_in_arr(i), + + hdr_fields_slv_in => dp_offload_tx_hdr_fields_out_arr(i) + ); + end generate; + + end str;