- Detect dropped words at the dispatch level. This prevents an overflow on CHDR from block CPU. - Dropped packets are recorded as CPU or CHDR drop count - Refactor to put chdr_xport_adapter.sv in different clock domain to improve timing - Unwrinkle tkeep/trailing transitions Original-commit: 7f86724ec3387f75d39d683b2ac5f5152e714c74
275 lines
8.7 KiB
Systemverilog
275 lines
8.7 KiB
Systemverilog
//
|
|
// Copyright 2020 Ettus Research, a National Instruments Brand
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// Module: eth_ipv4_interface
|
|
//
|
|
// Description:
|
|
// Adapts from internal CHDR to UDP/IPV4 Ethernet packets.
|
|
// Packets not specifically addressed to CHDR are routed
|
|
// to the CPU
|
|
//
|
|
// Parameters:
|
|
// - PROTOVER: RFNoC protocol version {8'd<major>, 8'd<minor>}
|
|
// - CPU_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CPU egress path
|
|
// - CHDR_FIFO_SIZE: Log2 of the FIFO depth (in bytes) for the CHDR egress path
|
|
// - RT_TBL_SIZE: Log2 of the depth of the return-address routing table
|
|
// - NODE_INST: The node type to return for a node-info discovery
|
|
// - DROP_UNKNOWN_MAC: Drop packets not addressed to us?
|
|
// - DROP_MIN_PACKET: Drop packets smaller than 64 bytes?
|
|
// - PREAMBLE_BYTES: Number of bytes of Preamble expected
|
|
// - ADD_SOF: Add a SOF indication into the tuser field of e2c
|
|
// - SYNC: Set if MAC is not the same as bus_clk
|
|
// - ENET_W: Width of the link to the Ethernet MAC
|
|
// - CPU_W: Width of the CPU interface
|
|
// - CHDR_W: Width of the CHDR interface
|
|
//
|
|
|
|
module eth_ipv4_interface #(
|
|
logic [15:0] PROTOVER = {8'd1, 8'd0},
|
|
int CPU_FIFO_SIZE = $clog2(8*1024),
|
|
int CHDR_FIFO_SIZE = $clog2(8*1024),
|
|
int NODE_INST = 0,
|
|
int RT_TBL_SIZE = 6,
|
|
int REG_AWIDTH = 14,
|
|
int BASE = 0,
|
|
bit DROP_UNKNOWN_MAC = 0,
|
|
bit DROP_MIN_PACKET = 0,
|
|
int PREAMBLE_BYTES = 6,
|
|
bit ADD_SOF = 1,
|
|
bit SYNC = 0,
|
|
int ENET_W = 64,
|
|
int CPU_W = 64,
|
|
int CHDR_W = 64
|
|
) (
|
|
input logic bus_clk,
|
|
input logic bus_rst,
|
|
input logic [15:0] device_id,
|
|
|
|
// Register port: Write port (domain: bus_clk)
|
|
input logic reg_wr_req,
|
|
input logic [REG_AWIDTH-1:0] reg_wr_addr,
|
|
input logic [31:0] reg_wr_data,
|
|
|
|
// Register port: Read port (domain: bus_clk)
|
|
input logic reg_rd_req,
|
|
input logic [REG_AWIDTH-1:0] reg_rd_addr,
|
|
output logic reg_rd_resp,
|
|
output logic [31:0] reg_rd_data,
|
|
|
|
// Status ports (domain: bus_clk)
|
|
output logic [47:0] my_mac,
|
|
output logic [31:0] my_ip,
|
|
output logic [15:0] my_udp_chdr_port,
|
|
|
|
// Ethernet MAC
|
|
AxiStreamIf.master eth_tx, // tUser = {1'b0,trailing bytes};
|
|
AxiStreamIf.slave eth_rx, // tUser = {error,trailing bytes};
|
|
// CHDR router interface
|
|
AxiStreamIf.master e2v, // tUser = {*not used*};
|
|
AxiStreamIf.slave v2e, // tUser = {*not used*};
|
|
// CPU DMA
|
|
AxiStreamIf.master e2c, // tUser = {sof,trailing bytes};
|
|
AxiStreamIf.slave c2e // tUser = {1'b0,trailing bytes};
|
|
|
|
);
|
|
|
|
localparam [47:0] DEFAULT_MAC_ADDR = {8'h00, 8'h80, 8'h2f, 8'h16, 8'hc5, 8'h2f};
|
|
localparam [31:0] DEFAULT_IP_ADDR = {8'd192, 8'd168, 8'd10, 8'd2};
|
|
localparam [31:0] DEFAULT_UDP_PORT = 16'd49153;
|
|
|
|
//---------------------------------------------------------
|
|
// Registers
|
|
//---------------------------------------------------------
|
|
// Include for register offsets
|
|
`include "eth_regs.vh"
|
|
// Allocate one full page for M
|
|
// mac_reg: MAC address for the dispatcher module. This value is used to
|
|
// determine if the packet is meant for this device and should be consumed.
|
|
//
|
|
// ip_reg: IP address for the dispatcher module. This value is used to
|
|
// determine if the packet is addressed to this device
|
|
//
|
|
// This module supports two destination ports.
|
|
logic [47:0] mac_reg = DEFAULT_MAC_ADDR;
|
|
logic [31:0] ip_reg = DEFAULT_IP_ADDR;
|
|
logic [15:0] udp_port = DEFAULT_UDP_PORT;
|
|
logic [47:0] bridge_mac_reg = DEFAULT_MAC_ADDR;
|
|
logic [31:0] bridge_ip_reg = DEFAULT_IP_ADDR;
|
|
logic [15:0] bridge_udp_port = DEFAULT_UDP_PORT;
|
|
logic bridge_en;
|
|
logic cpu_dropped;
|
|
logic chdr_dropped;
|
|
logic [31:0] chdr_drop_count = 0;
|
|
logic [31:0] cpu_drop_count = 0;
|
|
|
|
always_comb begin : bridge_mux
|
|
my_mac = bridge_en ? bridge_mac_reg : mac_reg;
|
|
my_ip = bridge_en ? bridge_ip_reg : ip_reg;
|
|
my_udp_chdr_port = bridge_en ? bridge_udp_port : udp_port;
|
|
end
|
|
|
|
always_ff @(posedge bus_clk) begin : reg_wr_ff
|
|
if (bus_rst) begin
|
|
mac_reg <= DEFAULT_MAC_ADDR;
|
|
ip_reg <= DEFAULT_IP_ADDR;
|
|
udp_port <= DEFAULT_UDP_PORT;
|
|
bridge_en <= 1'b0;
|
|
bridge_mac_reg <= DEFAULT_MAC_ADDR;
|
|
bridge_ip_reg <= DEFAULT_IP_ADDR;
|
|
bridge_udp_port <= DEFAULT_UDP_PORT;
|
|
end
|
|
else begin
|
|
if (reg_wr_req)
|
|
case (reg_wr_addr)
|
|
|
|
REG_MAC_LSB:
|
|
mac_reg[31:0] <= reg_wr_data;
|
|
|
|
REG_MAC_MSB:
|
|
mac_reg[47:32] <= reg_wr_data[15:0];
|
|
|
|
REG_IP:
|
|
ip_reg <= reg_wr_data;
|
|
|
|
REG_UDP:
|
|
udp_port <= reg_wr_data[15:0];
|
|
|
|
REG_BRIDGE_MAC_LSB:
|
|
bridge_mac_reg[31:0] <= reg_wr_data;
|
|
|
|
REG_BRIDGE_MAC_MSB:
|
|
bridge_mac_reg[47:32] <= reg_wr_data[15:0];
|
|
|
|
REG_BRIDGE_IP:
|
|
bridge_ip_reg <= reg_wr_data;
|
|
|
|
REG_BRIDGE_UDP:
|
|
bridge_udp_port <= reg_wr_data[15:0];
|
|
|
|
REG_BRIDGE_ENABLE:
|
|
bridge_en <= reg_wr_data[0];
|
|
endcase
|
|
end
|
|
end
|
|
|
|
always_ff @ (posedge bus_clk) begin : reg_rd_ff
|
|
if (bus_rst) begin
|
|
reg_rd_resp <= 1'b0;
|
|
reg_rd_data <= 32'd0;
|
|
chdr_drop_count <= 32'd0;
|
|
cpu_drop_count <= 32'd0;
|
|
end
|
|
else begin
|
|
if (chdr_dropped) begin
|
|
chdr_drop_count <= chdr_drop_count+1;
|
|
end
|
|
if (cpu_dropped) begin
|
|
cpu_drop_count <= cpu_drop_count+1;
|
|
end
|
|
if (reg_rd_req) begin
|
|
// Assert read response one cycle after read request
|
|
reg_rd_resp <= 1'b1;
|
|
case (reg_rd_addr)
|
|
REG_MAC_LSB:
|
|
reg_rd_data <= mac_reg[31:0];
|
|
|
|
REG_MAC_MSB:
|
|
reg_rd_data <= {16'b0,mac_reg[47:32]};
|
|
|
|
REG_IP:
|
|
reg_rd_data <= ip_reg;
|
|
|
|
REG_UDP:
|
|
reg_rd_data <= {16'b0, udp_port};
|
|
|
|
REG_BRIDGE_MAC_LSB:
|
|
reg_rd_data <= bridge_mac_reg[31:0];
|
|
|
|
REG_BRIDGE_MAC_MSB:
|
|
reg_rd_data <= {16'b0,bridge_mac_reg[47:32]};
|
|
|
|
REG_BRIDGE_IP:
|
|
reg_rd_data <= bridge_ip_reg;
|
|
|
|
REG_BRIDGE_UDP:
|
|
reg_rd_data <= {16'b0, bridge_udp_port};
|
|
|
|
REG_BRIDGE_ENABLE:
|
|
reg_rd_data <= {31'b0,bridge_en};
|
|
// Drop counts are used to debug situations
|
|
// Where the incoming data goes faster than
|
|
// chdr can consume it
|
|
REG_CHDR_DROPPED:
|
|
begin
|
|
reg_rd_data <= chdr_drop_count;
|
|
chdr_drop_count <= 0; // clear when read
|
|
end
|
|
REG_CPU_DROPPED:
|
|
begin
|
|
reg_rd_data <= cpu_drop_count;
|
|
cpu_drop_count <= 0; // clear when read
|
|
end
|
|
default:
|
|
reg_rd_resp <= 1'b0;
|
|
endcase
|
|
end
|
|
// Deassert read response after one clock cycle
|
|
if (reg_rd_resp) begin
|
|
reg_rd_resp <= 1'b0;
|
|
end
|
|
end
|
|
end
|
|
|
|
logic b_dropped_valid;
|
|
logic e_cpu_dropped, b_cpu_dropped;
|
|
logic e_chdr_dropped, b_chdr_dropped;
|
|
// push over the clock domain
|
|
// Sized to fit into 2 SRL's
|
|
axi_fifo_2clk #(.WIDTH(2), .SIZE(4)) fifo_i (
|
|
.reset(eth_rx.rst),
|
|
.i_aclk(eth_rx.clk),
|
|
.i_tdata({e_cpu_dropped, e_chdr_dropped}),
|
|
.i_tvalid(e_cpu_dropped || e_chdr_dropped), .i_tready(/*not used*/),
|
|
.o_aclk(bus_clk),
|
|
.o_tdata({b_cpu_dropped, b_chdr_dropped}),
|
|
.o_tvalid(b_dropped_valid), .o_tready(1'b1)
|
|
);
|
|
|
|
always_comb begin
|
|
cpu_dropped = b_cpu_dropped && b_dropped_valid;
|
|
chdr_dropped = b_chdr_dropped && b_dropped_valid;
|
|
end
|
|
|
|
eth_ipv4_chdr_adapter #(
|
|
.PROTOVER (PROTOVER),
|
|
.CPU_FIFO_SIZE (CPU_FIFO_SIZE),
|
|
.CHDR_FIFO_SIZE (CHDR_FIFO_SIZE),
|
|
.RT_TBL_SIZE (RT_TBL_SIZE),
|
|
.NODE_INST (NODE_INST),
|
|
.DROP_UNKNOWN_MAC(DROP_UNKNOWN_MAC),
|
|
.DROP_MIN_PACKET (DROP_MIN_PACKET),
|
|
.PREAMBLE_BYTES (PREAMBLE_BYTES),
|
|
.ADD_SOF (ADD_SOF),
|
|
.SYNC (SYNC),
|
|
.ENET_W (ENET_W),
|
|
.CPU_W (CPU_W),
|
|
.CHDR_W (CHDR_W)
|
|
) eth_adapter_i (
|
|
.eth_rx (eth_rx ),
|
|
.eth_tx (eth_tx ),
|
|
.v2e (v2e ),
|
|
.e2v (e2v ),
|
|
.c2e (c2e ),
|
|
.e2c (e2c ),
|
|
.device_id (device_id),
|
|
.my_mac (my_mac ),
|
|
.my_ip (my_ip ),
|
|
.my_udp_chdr_port(my_udp_chdr_port),
|
|
.chdr_dropped (e_chdr_dropped),
|
|
.cpu_dropped (e_cpu_dropped)
|
|
);
|
|
|
|
|
|
endmodule : eth_ipv4_interface
|