Skip to content
Snippets Groups Projects

initial commit of rdma_packetiser library

Merged Reinier van der Walle requested to merge HPR-129 into master
5 files
+ 740
0
Compare changes
  • Side-by-side
  • Inline
Files
5
-------------------------------------------------------------------------------
--
-- 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: Assembles the RDMA header at snk_in.sop
-- Description:
-- The hdr_fields_slv output is set one st_clk cycle after snk_in.sop and will
-- contain the RoCEv2 (RDMA over Converged Ethernet v2) header information for
-- the corresponding data frame.
-- Remark
-- . The incoming data frame on snk_in should consist of at least 2 clock cycles.
-- i.e. two consecutive 1 cycle frames (sop + eop on the same clock cycle)
-- without a gap inbetween is not supported.
library IEEE, common_lib, dp_lib, eth_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_layers_pkg.all;
use common_lib.common_field_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;
use work.rdma_packetiser_pkg.all;
entity rdma_packetiser_assemble_header is
generic (
g_use_immediate : boolean := true;
g_use_msg_cnt_as_immediate : boolean := true
);
port (
-- Clocks and reset
st_clk : in std_logic;
st_rst : in std_logic;
snk_in : in t_dp_sosi := c_dp_sosi_rst;
hdr_fields_slv : out std_logic_vector(1023 downto 0) := (others => '0');
immediate_data : in std_logic_vector(c_rdma_packetiser_roce_imm_len * c_octet_w - 1 downto 0) := (others => '0');
block_len : in std_logic_vector(c_halfword_w - 1 downto 0); -- in octets
nof_packets_in_msg : in std_logic_vector(c_word_w - 1 downto 0);
nof_msg : in std_logic_vector(c_word_w - 1 downto 0);
dma_len : in std_logic_vector(c_word_w - 1 downto 0); -- = block_len * nof_packets_in_msg
start_address : in std_logic_vector(c_longword_w - 1 downto 0)
);
end rdma_packetiser_assemble_header;
architecture str of rdma_packetiser_assemble_header is
constant c_hdr_field_arr : t_common_field_arr := sel_a_b(g_use_immediate, c_rdma_packetiser_roce_hdr_field_arr, c_rdma_packetiser_roce_no_imm_hdr_field_arr);
constant c_app_hdr_length : natural := sel_a_b(g_use_immediate, c_rdma_packetiser_roce_hdr_len, c_rdma_packetiser_roce_no_imm_hdr_len);
constant c_udp_app_hdr_length : natural := c_network_udp_header_len + c_app_hdr_length;
constant c_ip_udp_app_hdr_length : natural := c_network_ip_header_len + c_udp_app_hdr_length;
type t_state is (s_idle, s_first, s_middle, s_last);
type t_reg is record
state : t_state;
opcode : std_logic_vector(c_byte_w - 1 downto 0);
immediate_data : std_logic_vector(c_rdma_packetiser_roce_imm_len * c_octet_w - 1 downto 0);
psn : std_logic_vector(c_word_w - 1 downto 0);
virtual_address : unsigned(c_longword_w - 1 downto 0);
dma_len : unsigned(c_word_w - 1 downto 0);
p_cnt : natural;
msg_cnt : natural;
udp_total_length : natural;
ip_total_length : natural;
nof_packets_in_msg : natural;
end record;
constant c_reg_rst : t_reg := (s_idle, (others => '1'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0);
signal d, q : t_reg;
begin
q <= d when rising_edge(st_clk);
p_comb : process(st_rst, q, snk_in, nof_packets_in_msg, start_address, nof_msg, immediate_data, dma_len, block_len)
variable v : t_reg;
begin
v := q;
if snk_in.sop = '1' then -- set on sop
v.psn := resize_uvec(snk_in.bsn, c_word_w);
end if;
if v.msg_cnt = 0 then -- set on new message
v.virtual_address := unsigned(start_address);
v.dma_len := unsigned(dma_len);
v.udp_total_length := c_udp_app_hdr_length + to_uint(block_len) + c_rdma_packetiser_roce_icrc_len;
v.ip_total_length := c_ip_udp_app_hdr_length + to_uint(block_len) + c_rdma_packetiser_roce_icrc_len;
v.nof_packets_in_msg := to_uint(nof_packets_in_msg);
v.immediate_data := immediate_data;
end if;
case q.state is
when s_idle =>
if snk_in.sop = '1' and v.nof_packets_in_msg > 1 then
v.state := s_first;
v.opcode := c_rdma_packetiser_opcode_uc_write_first;
v.p_cnt := 1;
elsif snk_in.sop = '1' and v.nof_packets_in_msg = 1 then
v.state := s_last;
v.opcode := c_rdma_packetiser_opcode_uc_write_only;
if g_use_immediate then
v.opcode := c_rdma_packetiser_opcode_uc_write_only_im;
end if;
end if;
when s_first =>
if snk_in.sop = '1' and v.nof_packets_in_msg > 2 then
v.state := s_middle;
v.opcode := c_rdma_packetiser_opcode_uc_write_middle;
v.p_cnt := q.p_cnt + 1;
elsif snk_in.sop = '1' and v.nof_packets_in_msg = 2 then
v.state := s_last;
v.opcode := c_rdma_packetiser_opcode_uc_write_last;
v.p_cnt := q.p_cnt + 1;
if g_use_immediate then
v.opcode := c_rdma_packetiser_opcode_uc_write_last_im;
end if;
end if;
when s_middle =>
if snk_in.sop = '1' and q.p_cnt >= v.nof_packets_in_msg - 1 then
v.state := s_last;
v.opcode := c_rdma_packetiser_opcode_uc_write_last;
v.p_cnt := q.p_cnt + 1;
if g_use_immediate then
v.opcode := c_rdma_packetiser_opcode_uc_write_last_im;
end if;
elsif snk_in.sop = '1' then
v.p_cnt := q.p_cnt + 1;
end if;
when s_last =>
v.state := s_idle;
v.p_cnt := 0;
if q.msg_cnt >= to_uint(nof_msg) - 1 then
v.msg_cnt := 0;
else
v.msg_cnt := q.msg_cnt + 1;
v.virtual_address := q.virtual_address + q.dma_len;
end if;
end case;
if st_rst = '1' then
v := c_reg_rst;
end if;
d <= v;
end process;
hdr_fields_slv(field_hi(c_hdr_field_arr, "ip_total_length" ) downto field_lo(c_hdr_field_arr, "ip_total_length" )) <= TO_UVEC(q.ip_total_length, 16);
hdr_fields_slv(field_hi(c_hdr_field_arr, "udp_total_length" ) downto field_lo(c_hdr_field_arr, "udp_total_length" )) <= TO_UVEC(q.udp_total_length, 16);
hdr_fields_slv(field_hi(c_hdr_field_arr, "bth_opcode" ) downto field_lo(c_hdr_field_arr, "bth_opcode" )) <= q.opcode;
hdr_fields_slv(field_hi(c_hdr_field_arr, "bth_psn" ) downto field_lo(c_hdr_field_arr, "bth_psn" )) <= q.psn;
hdr_fields_slv(field_hi(c_hdr_field_arr, "reth_virtual_address") downto field_lo(c_hdr_field_arr, "reth_virtual_address")) <= std_logic_vector(q.virtual_address);
hdr_fields_slv(field_hi(c_hdr_field_arr, "reth_dma_length" ) downto field_lo(c_hdr_field_arr, "reth_dma_length" )) <= std_logic_vector(q.dma_len);
gen_use_immediate : if g_use_immediate generate
gen_use_msg_cnt : if g_use_msg_cnt_as_immediate generate
hdr_fields_slv(field_hi(c_hdr_field_arr, "immediate_data") downto field_lo(c_hdr_field_arr, "immediate_data")) <= TO_UVEC(q.msg_cnt, 32);
end generate;
gen_use_no_msg_cnt : if not g_use_msg_cnt_as_immediate generate
hdr_fields_slv(field_hi(c_hdr_field_arr, "immediate_data") downto field_lo(c_hdr_field_arr, "immediate_data")) <= q.immediate_data;
end generate;
end generate;
end str;
Loading