fpga: lib: Add support for length in tuser in eth_ipv4_add_udp
Original-commit: 672487634ef817026fad83d48d3c341f80fa4d46
This commit is contained in:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user