fpga: lib: Add support for length in tuser in eth_ipv4_add_udp

Original-commit: 672487634ef817026fad83d48d3c341f80fa4d46
This commit is contained in:
Wade Fife
2022-08-29 17:01:45 -05:00
committed by skooNI
parent dce09f8fd7
commit cad2f7ba5c
+48 -32
View File
@@ -1,28 +1,34 @@
// //
// Copyright 2020 Ettus Research, A National Instruments Brand // Copyright 2020 Ettus Research, a National Instruments Brand
// //
// SPDX-License-Identifier: LGPL-3.0-or-later // SPDX-License-Identifier: LGPL-3.0-or-later
// //
// Module: eth_ipv4_add_udp.sv // Module: eth_ipv4_add_udp.sv
//
// Description: Add a UDP header onto an incoming CHDR stream // Description: Add a UDP header onto an incoming CHDR stream
// //
// Parameters: // Parameters:
// - PREAMBLE_BYTES: Number of bytes of Preamble expected //
// - MAX_PACKET_BYTES: Maximum expected packet size // PREAMBLE_BYTES : Number of bytes of preamble expected
// Constant fields in the added packet header // MAX_PACKET_BYTES : Maximum expected packet size
// - ETH_TYPE: EthType in Ethernet Frame header // ETH_TYPE : EthType in Ethernet frame header
// - MISC_IP: IP version / IP header Length / DSCP and ECN in IpV4 header // MISC_IP : Version, header length, DSCP, and ECN in IPv4 header
// - FLAG_FRAG: Identification in IPv4 header // FLAG_FRAG : Flags and fragment offset in IPv4 header
// - TTL_PROT: Time to Live / Protocol in IPv4 header // TTL_PROT : Time to live and protocol in IPv4 header
// LENGTH_IN_TUSER : Use length in i.TUSER when true. Otherwise, assume
// there's a CHDR header with the length.
//
module eth_ipv4_add_udp #( module eth_ipv4_add_udp #(
int PREAMBLE_BYTES = 6, int PREAMBLE_BYTES = 6,
int MAX_PACKET_BYTES = 2**16, int MAX_PACKET_BYTES = 2**16,
logic [15:0] ETH_TYPE = 16'h0800, // IPv4 logic [15:0] ETH_TYPE = 16'h0800, // IPv4
logic [15:0] MISC_IP = { 4'd4 /* IPv4 */, 4'd5 /* IP HDR Len */, 8'h00 /* DSCP and ECN */}, logic [15:0] MISC_IP = { 4'd4 /* IPv4 */, 4'd5 /* HDR Len */, 8'h00 /* DSCP and ECN */},
logic [15:0] IDENT = 16'h0, logic [15:0] IDENT = 16'h0,
logic [15:0] FLAG_FRAG = { 3'b010 /* don't fragment */, 13'h0 }, logic [15:0] FLAG_FRAG = { 3'b010 /* don't fragment */, 13'h0 },
logic [15:0] TTL_PROT = { 8'h10 /* TTL */, 8'h11 /* UDP */ } logic [15:0] TTL_PROT = { 8'h10 /* TTL */, 8'h11 /* UDP */ },
bit LENGTH_IN_TUSER = 0
)( )(
// Clock domain: i.clk (o_.clk is unused) // Clock domain: i.clk (o_.clk is unused)
@@ -36,8 +42,8 @@ module eth_ipv4_add_udp #(
input logic [15:0] udp_dst, input logic [15:0] udp_dst,
// Ethernet Stream - CHDR ONLY // Ethernet Stream - CHDR ONLY
AxiStreamIf.slave i, // tUser = {*not used*} AxiStreamIf.slave i, // tUser = {Incoming packet length if LENGTH_IN_TUSER = 1}
AxiStreamIf.master o // tUser = {1'b0,trailing bytes}; AxiStreamIf.master o // tUser = {1'b0, trailing bytes};
); );
@@ -72,6 +78,7 @@ module eth_ipv4_add_udp #(
//--------------------------------------- //---------------------------------------
// Ethernet Framer // Ethernet Framer
//--------------------------------------- //---------------------------------------
logic sop; // Start of packet
logic [15:0] chdr_len_new, chdr_len_old, chdr_len_reg; logic [15:0] chdr_len_new, chdr_len_old, chdr_len_reg;
logic [15:0] ip_len, ip_len_reg; logic [15:0] ip_len, ip_len_reg;
@@ -84,7 +91,7 @@ module eth_ipv4_add_udp #(
always_comb begin : s0_assign always_comb begin : s0_assign
`AXI4S_ASSIGN(s0,i) `AXI4S_ASSIGN(s0,i)
s0.tuser = 0; // all full words going in s0.tuser = 0; // all full words going in
end end
localparam BYTES_TO_ADD = UDP_END+1+PREAMBLE_BYTES; localparam BYTES_TO_ADD = UDP_END+1+PREAMBLE_BYTES;
@@ -93,23 +100,28 @@ module eth_ipv4_add_udp #(
.i(s0), .o(s1) .i(s0), .o(s1)
); );
// try to calculate what tuser should be on the final word
logic [15:0] total_len;
logic [15:0] rem_bytes;
always_ff @(posedge i.clk) begin : chdr_len_ff always_ff @(posedge i.clk) begin : chdr_len_ff
if (i.rst) begin if (i.rst) begin
chdr_len_old <= '0; sop <= 1;
chdr_len_old <= '0;
end else begin end else begin
if (s0.tvalid && s0.tready) begin if (i.tvalid && i.tready) begin
chdr_len_old <= chdr_len_new; chdr_len_old <= chdr_len_new;
sop <= i.tlast;
end end
end end
end end
always_comb begin : calc_length_fields always_comb begin : calc_length_fields
// exract fields if (LENGTH_IN_TUSER) begin
chdr_len_new = s0.get_packet_field16(chdr_len_old,CHDR_LENGTH_BYTE); if (i.tvalid && sop) begin
chdr_len_new = i.tuser;
end else begin
chdr_len_new = chdr_len_old;
end
end else begin
chdr_len_new = s0.get_packet_field16(chdr_len_old,CHDR_LENGTH_BYTE);
end
ip_len = (16'd28 + chdr_len_new); // 20 for IP, 8 for UDP ip_len = (16'd28 + chdr_len_new); // 20 for IP, 8 for UDP
udp_len = (16'd8 + chdr_len_new); udp_len = (16'd8 + chdr_len_new);
end end
@@ -118,7 +130,7 @@ module eth_ipv4_add_udp #(
always_comb begin : pack_unpack_header_info always_comb begin : pack_unpack_header_info
`AXI4S_ASSIGN(s2,s1) `AXI4S_ASSIGN(s2,s1)
s2.tuser = { udp_len, ip_len, chdr_len_new, udp_dst, ip_dst, mac_dst, s1.tuser}; s2.tuser = { udp_len, ip_len, chdr_len_new, udp_dst, ip_dst, mac_dst, s1.tuser};
{ udp_len_reg, ip_len_reg, chdr_len_reg, udp_dst_reg, ip_dst_reg, { udp_len_reg, ip_len_reg, chdr_len_reg, udp_dst_reg, ip_dst_reg,
mac_dst_reg,trailing_bytes} = s3.tuser; mac_dst_reg,trailing_bytes} = s3.tuser;
end end
@@ -135,12 +147,12 @@ module eth_ipv4_add_udp #(
// track when we cut off the outgoing packet // track when we cut off the outgoing packet
always_ff @(posedge i.clk) begin : chdr_end_early_ff always_ff @(posedge i.clk) begin : chdr_end_early_ff
if (i.rst) begin if (i.rst) begin
chdr_end_early <= 0; chdr_end_early <= 0;
end else begin end else begin
if (s3.tvalid && s3.tready && s3.tlast) if (s3.tvalid && s3.tready && s3.tlast)
chdr_end_early <= 0; chdr_end_early <= 0;
else if (s4.tvalid && s4.tready &&s4.tlast) else if (s4.tvalid && s4.tready &&s4.tlast)
chdr_end_early <= 1; chdr_end_early <= 1;
end end
end end
@@ -155,19 +167,23 @@ module eth_ipv4_add_udp #(
.out(iphdr_checksum) .out(iphdr_checksum)
); );
// calculate what tuser should be on the final word
logic [15:0] total_len;
logic [15:0] rem_bytes;
always_comb begin : calc_rem_bytes always_comb begin : calc_rem_bytes
total_len = (BYTES_TO_ADD + chdr_len_reg); total_len = (BYTES_TO_ADD + chdr_len_reg);
rem_bytes = total_len - s4.word_count*i.DATA_WIDTH/8; rem_bytes = total_len - s4.word_count*i.DATA_WIDTH/8;
end end
// zero value fields are commented out because the fill goes to zero // zero value fields are commented out because the fill goes to zero
// if those fields become non zero uncomment them // if those fields become non zero, uncomment them
always_comb begin : set_header_fields always_comb begin : set_header_fields
// assign bus // assign bus
s4.tvalid = s3.tvalid && !chdr_end_early; s4.tvalid = s3.tvalid && !chdr_end_early;
s3.tready = s4.tready || chdr_end_early; s3.tready = s4.tready || chdr_end_early;
if (rem_bytes > i.DATA_WIDTH/8 || chdr_end_early) begin if (rem_bytes > i.DATA_WIDTH/8 || chdr_end_early) begin
s4.tlast = s3.tvalid && s3.tlast; // s0metimes packets end early s4.tlast = s3.tvalid && s3.tlast; // sometimes packets end early
s4.tuser = 0; s4.tuser = 0;
end else if (rem_bytes == i.DATA_WIDTH/8) begin end else if (rem_bytes == i.DATA_WIDTH/8) begin
s4.tlast = s3.tvalid; s4.tlast = s3.tvalid;
@@ -199,4 +215,4 @@ module eth_ipv4_add_udp #(
`AXI4S_ASSIGN(o,s4) `AXI4S_ASSIGN(o,s4)
end end
endmodule // eth_ipv4_add_udp endmodule : eth_ipv4_add_udp