Files
b210-k7-fpga/top/x300/x300_eth_interface.v
Wade Fife fb4542e9ef fpga: x300: Support advanced transport adapter
Original-commit: adc938c0b6c9b045ad60c8f5297303495a96f0ca
2023-01-10 14:19:00 -08:00

332 lines
12 KiB
Verilog

//
// Copyright 2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
// Copyright 2022 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Adapts from internal CHDR to Ethernet packets. Also handles ZPU and Ethernet
// crossover interfaces.
//
`default_nettype none
module x300_eth_interface #(
parameter [15:0] PROTOVER = {8'd1, 8'd0},
parameter MTU = 10,
parameter NODE_INST = 0,
parameter RT_TBL_SIZE = 6,
parameter ETH_BASE = 0,
parameter TA_BASE = 16,
parameter [ 0:0] EN_RX_RAW_PYLD = 1,
parameter [ 0:0] EN_RX_KV_MAP_CFG = 1
) (
input wire clk,
input wire reset,
// RFNoC Device ID
input wire [15:0] device_id,
// Settings bus
input wire set_stb,
input wire [ 7:0] set_addr,
input wire [31:0] set_data,
input wire [ 7:0] rb_addr,
output reg [31:0] rb_data,
// Eth ports
output wire [63:0] eth_tx_tdata,
output wire [ 3:0] eth_tx_tuser,
output wire eth_tx_tlast,
output wire eth_tx_tvalid,
input wire eth_tx_tready,
input wire [63:0] eth_rx_tdata,
input wire [ 3:0] eth_rx_tuser,
input wire eth_rx_tlast,
input wire eth_rx_tvalid,
output wire eth_rx_tready,
// CHDR Interface
output wire [63:0] e2v_tdata,
output wire e2v_tlast,
output wire e2v_tvalid,
input wire e2v_tready,
input wire [63:0] v2e_tdata,
input wire v2e_tlast,
input wire v2e_tvalid,
output wire v2e_tready,
// ZPU
output wire [63:0] e2z_tdata,
output wire [ 3:0] e2z_tuser,
output wire e2z_tlast,
output wire e2z_tvalid,
input wire e2z_tready,
input wire [63:0] z2e_tdata,
input wire [ 3:0] z2e_tuser,
input wire z2e_tlast,
input wire z2e_tvalid,
output wire z2e_tready
);
//---------------------------------------------------------------------------
// Ethernet Registers
//---------------------------------------------------------------------------
// UNUSED: ETH_BASE to ETH_BASE+7
localparam MY_ETH_ADDR_LO_REG = ETH_BASE + 8;
localparam MY_ETH_ADDR_HI_REG = ETH_BASE + 9;
localparam MY_IP_ADDR_REG = ETH_BASE + 10;
localparam MY_UDP_PORT_REG = ETH_BASE + 11;
// UNUSED: ETH_BASE+12 to ETH_BASE+15
wire [47:0] my_eth_addr;
wire [31:0] my_ipv4_addr;
wire [15:0] my_udp_chdr_port;
// MAC address for the dispatcher module.
// This value is used to determine if the packet is meant for this device.
setting_reg #(.my_addr(MY_ETH_ADDR_LO_REG), .awidth(8), .width(32)) sr_my_mac_lsb
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(my_eth_addr[31:0]),.changed());
setting_reg #(.my_addr(MY_ETH_ADDR_HI_REG), .awidth(8), .width(16)) sr_my_mac_msb
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(my_eth_addr[47:32]),.changed());
// IP address for the dispatcher module.
// This value is used to determine if the packet is addressed
// to this device.
setting_reg #(.my_addr(MY_IP_ADDR_REG), .awidth(8), .width(32)) sr_my_ip
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out(my_ipv4_addr[31:0]),.changed());
// This module supports one destination port
setting_reg #(.my_addr(MY_UDP_PORT_REG), .awidth(8), .width(16)) sr_udp_port
(.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
.in(set_data),.out({my_udp_chdr_port[15:0]}),.changed());
//---------------------------------------------------------------------------
// Transport Adapter Registers
//---------------------------------------------------------------------------
// See eth_regs for a description of the bit fields.
localparam [7:0] REG_XPORT_COMPAT = TA_BASE + 0;
localparam [7:0] REG_XPORT_INFO = TA_BASE + 1;
localparam [7:0] REG_XPORT_NODE_INST = TA_BASE + 2;
localparam [7:0] REG_XPORT_KV_MAC_LO = TA_BASE + 3;
localparam [7:0] REG_XPORT_KV_MAC_HI = TA_BASE + 4;
localparam [7:0] REG_XPORT_KV_IP = TA_BASE + 5;
localparam [7:0] REG_XPORT_KV_UDP = TA_BASE + 6;
localparam [7:0] REG_XPORT_KV_CFG = TA_BASE + 7;
// Note: TA_BASE + 8 is a virtual register used for ARP (see x300 firmware)
localparam [7:0] REG_IPV4_ARP = TA_BASE + 8;
localparam [7:0] COMPAT_MAJOR = 8'd1;
localparam [7:0] COMPAT_MINOR = 8'd0;
// KV map configuration registers. Make them default to 0 so that the extra
// logic for this configuration interface gets optimized out when not used.
reg kv_stb = 0;
reg [47:0] kv_mac_addr = 0;
reg [31:0] kv_ip_addr = 0;
reg [15:0] kv_udp_port = 0;
reg [15:0] kv_dst_epid = 0;
reg kv_raw_udp = 0;
wire kv_busy;
if (EN_RX_KV_MAP_CFG) begin : gen_write_regs
// Implement register writes (settings regs)
always @(posedge clk) begin : ta_reg_write
if (reset) begin
kv_stb <= 0;
end else begin
kv_stb <= 0;
if (set_stb) begin
case (set_addr)
REG_XPORT_KV_MAC_LO:
kv_mac_addr[31:0] <= set_data;
REG_XPORT_KV_MAC_HI:
kv_mac_addr[47:32] <= set_data[15:0];
REG_XPORT_KV_IP:
kv_ip_addr <= set_data[31:0];
REG_XPORT_KV_UDP:
kv_udp_port <= set_data[15:0];
REG_XPORT_KV_CFG: begin
kv_dst_epid <= set_data[15:0];
kv_raw_udp <= set_data[16];
kv_stb <= 1;
end
endcase
end
end
end // ta_reg_write
end // gen_write_regs
// Implement register reads (readback regs)
always @(*) begin : ta_reg_read
rb_data = 32'd0;
case (rb_addr)
REG_XPORT_COMPAT:
rb_data[15:0] = { COMPAT_MAJOR, COMPAT_MINOR };
REG_XPORT_INFO:
rb_data[1:0] = { EN_RX_RAW_PYLD, EN_RX_KV_MAP_CFG };
REG_XPORT_NODE_INST:
rb_data = NODE_INST;
REG_XPORT_KV_CFG:
if (EN_RX_KV_MAP_CFG) begin
rb_data[31] = kv_busy;
end
default:
rb_data = 32'd0;
endcase
end
//---------------------------------------------------------------------------
// Transport Adapter
//---------------------------------------------------------------------------
if (EN_RX_KV_MAP_CFG || EN_RX_RAW_PYLD) begin : gen_adv_ta
// Incoming MTU parameter is in CHDR_W words but eht_ipv4_chdr_adapter
// expects it in bytes.
localparam CPU_FIFO_SIZE = $clog2(8*(2**MTU));
localparam CHDR_FIFO_SIZE = $clog2(8*(2**MTU));
eth_ipv4_chdr_adapter_wrapper #(
.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(1 ),
.PREAMBLE_BYTES (6 ),
.CPU_PREAMBLE (1 ),
.SYNC (1 ),
.EN_RX_RAW_PYLD (EN_RX_RAW_PYLD)
) eth_ipv4_chdr_adapter_wrapper_i (
.bus_clk (clk ),
.bus_rst (reset ),
.device_id (device_id ),
.my_mac (my_eth_addr ),
.my_ip (my_ipv4_addr ),
.my_udp_chdr_port(my_udp_chdr_port ),
.my_pause_set (16'd0 ),
.my_pause_clear (16'd0 ),
.kv_stb (kv_stb ),
.kv_busy (kv_busy ),
.kv_mac_addr (kv_mac_addr ),
.kv_ip_addr (kv_ip_addr ),
.kv_udp_port (kv_udp_port ),
.kv_dst_epid (kv_dst_epid ),
.kv_raw_udp (kv_raw_udp ),
.eth_clk (clk ),
.eth_rst (reset ),
.eth_pause_req ( ),
.eth_tx_tdata (eth_tx_tdata ),
.eth_tx_tuser (eth_tx_tuser ),
.eth_tx_tkeep ( ),
.eth_tx_tlast (eth_tx_tlast ),
.eth_tx_tvalid (eth_tx_tvalid ),
.eth_tx_tready (eth_tx_tready ),
.eth_rx_tdata (eth_rx_tdata ),
.eth_rx_tuser (eth_rx_tuser ),
.eth_rx_tlast (eth_rx_tlast ),
.eth_rx_tvalid (eth_rx_tvalid ),
.eth_rx_tready (eth_rx_tready ),
.e2v_tdata (e2v_tdata ),
.e2v_tlast (e2v_tlast ),
.e2v_tvalid (e2v_tvalid ),
.e2v_tready (e2v_tready ),
.v2e_tdata (v2e_tdata ),
.v2e_tlast (v2e_tlast ),
.v2e_tvalid (v2e_tvalid ),
.v2e_tready (v2e_tready ),
.cpu_clk (clk ),
.cpu_rst (reset ),
.e2c_tdata ({e2z_tdata[ 7: 0],
e2z_tdata[15: 8],
e2z_tdata[23:16],
e2z_tdata[31:24],
e2z_tdata[39:32],
e2z_tdata[47:40],
e2z_tdata[55:48],
e2z_tdata[63:56]}),
.e2c_tuser (e2z_tuser ),
.e2c_tlast (e2z_tlast ),
.e2c_tvalid (e2z_tvalid ),
.e2c_tready (e2z_tready ),
.c2e_tdata ({z2e_tdata[ 7: 0],
z2e_tdata[15: 8],
z2e_tdata[23:16],
z2e_tdata[31:24],
z2e_tdata[39:32],
z2e_tdata[47:40],
z2e_tdata[55:48],
z2e_tdata[63:56]}),
.c2e_tuser (z2e_tuser ),
.c2e_tlast (z2e_tlast ),
.c2e_tvalid (z2e_tvalid ),
.c2e_tready (z2e_tready )
);
end else begin : gen_basic_ta
eth_ipv4_chdr64_adapter #(
.PROTOVER (PROTOVER),
.MTU (MTU),
.CPU_FIFO_SIZE (MTU),
.RT_TBL_SIZE (RT_TBL_SIZE),
.NODE_INST (NODE_INST),
.DROP_UNKNOWN_MAC(1)
) eth_ipv4_chdr64_adapter_i (
.clk (clk ),
.rst (reset ),
.device_id (device_id ),
.s_mac_tdata (eth_rx_tdata ),
.s_mac_tuser (eth_rx_tuser ),
.s_mac_tlast (eth_rx_tlast ),
.s_mac_tvalid (eth_rx_tvalid ),
.s_mac_tready (eth_rx_tready ),
.m_mac_tdata (eth_tx_tdata ),
.m_mac_tuser (eth_tx_tuser ),
.m_mac_tlast (eth_tx_tlast ),
.m_mac_tvalid (eth_tx_tvalid ),
.m_mac_tready (eth_tx_tready ),
.s_chdr_tdata (v2e_tdata ),
.s_chdr_tlast (v2e_tlast ),
.s_chdr_tvalid (v2e_tvalid ),
.s_chdr_tready (v2e_tready ),
.m_chdr_tdata (e2v_tdata ),
.m_chdr_tlast (e2v_tlast ),
.m_chdr_tvalid (e2v_tvalid ),
.m_chdr_tready (e2v_tready ),
.s_cpu_tdata ({z2e_tdata[7:0], z2e_tdata[15:8],
z2e_tdata[23:16], z2e_tdata[31:24],
z2e_tdata[39:32], z2e_tdata[47:40],
z2e_tdata[55:48], z2e_tdata[63:56]}),
.s_cpu_tuser (z2e_tuser ),
.s_cpu_tlast (z2e_tlast ),
.s_cpu_tvalid (z2e_tvalid ),
.s_cpu_tready (z2e_tready ),
.m_cpu_tdata ({e2z_tdata[7:0], e2z_tdata[15:8],
e2z_tdata[23:16], e2z_tdata[31:24],
e2z_tdata[39:32], e2z_tdata[47:40],
e2z_tdata[55:48], e2z_tdata[63:56]}),
.m_cpu_tuser (e2z_tuser ),
.m_cpu_tlast (e2z_tlast ),
.m_cpu_tvalid (e2z_tvalid ),
.m_cpu_tready (e2z_tready ),
.my_eth_addr (my_eth_addr ),
.my_ipv4_addr (my_ipv4_addr ),
.my_udp_chdr_port(my_udp_chdr_port)
);
end
endmodule // x300_eth_interface
`default_nettype wire