fpga: x4xx: Replace Ethernet transport adapter
Original-commit: 34cee97e6206151e80d33e0e5367dcac62038a67
This commit is contained in:
committed by
Joerg Hofrichter
parent
8669c68048
commit
872de917bf
@@ -0,0 +1,11 @@
|
||||
#
|
||||
# Copyright 2023 Ettus Research, a National Instruments Brand
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
|
||||
RFNOC_TA_X4XX_ETH_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/rfnoc/transport_adapters/rfnoc_ta_x4xx_eth/, \
|
||||
rfnoc_ta_x4xx_eth.sv \
|
||||
x4xx_mgt_io_core.sv \
|
||||
x4xx_qsfp_wrapper.sv \
|
||||
))
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
# Description:
|
||||
# 10 GbE Timing Constraints.
|
||||
#
|
||||
|
||||
# Specify which clock is used for dclk in the 10 GbE IP.
|
||||
set DCLK_NAME clk100
|
||||
|
||||
# Constraints taken from xge_pcs_pma_exceptions.xdc in the example design.
|
||||
set_max_delay -from [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/RXOUTCLK}]] -to [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/TXOUTCLK}]] -datapath_only 6.40
|
||||
set_max_delay -from [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/TXOUTCLK}]] -to [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/RXOUTCLK}]] -datapath_only 6.40
|
||||
set_max_delay -from [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/RXOUTCLK}]] -to [get_clocks $DCLK_NAME] -datapath_only 6.40
|
||||
set_max_delay -from [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/TXOUTCLK}]] -to [get_clocks $DCLK_NAME] -datapath_only 6.40
|
||||
set_max_delay -from [get_clocks $DCLK_NAME] -to [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/TXOUTCLK}]] -datapath_only 10.000
|
||||
set_max_delay -from [get_clocks $DCLK_NAME] -to [get_clocks -of_objects [get_pins -hierarchical -filter {NAME =~ */channel_inst/*_CHANNEL_PRIM_INST/RXOUTCLK}]] -datapath_only 10.000
|
||||
@@ -0,0 +1,352 @@
|
||||
//
|
||||
// Copyright 2024 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rfnoc_ta_x4xx_eth
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Top-level file for the X4xx Ethernet transport adapter.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// PROTOCOL : Indicates the port type to use for each of the 4 QSFP lanes.
|
||||
// See x4xx_mgt_types.vh for possible values.
|
||||
// CHDR_W : CHDR width used by RFNoC on the FPGA
|
||||
// BYTE_MTU : Transport MTU in bytes
|
||||
// QSFP_NUM : Port number to distinguish multiple QSFP ports
|
||||
// NODE_INST : Node instance, must be unique among transport adapters.
|
||||
// Also, for now, must match the crossbar port number it is
|
||||
// connected to (for multi-lane transports, it must match the
|
||||
// first crossbar port number)
|
||||
// PROTOVER : RFNoC protocol version for IPv4 interface
|
||||
//
|
||||
`default_nettype none
|
||||
|
||||
|
||||
`include "./x4xx_mgt_types.vh"
|
||||
|
||||
|
||||
module rfnoc_ta_x4xx_eth #(
|
||||
parameter integer PROTOCOL [3:0] = {`MGT_Disabled,
|
||||
`MGT_Disabled,
|
||||
`MGT_Disabled,
|
||||
`MGT_Disabled},
|
||||
parameter CHDR_W = 64,
|
||||
parameter BYTE_MTU = $clog2(8*1024),
|
||||
parameter [ 7:0] QSFP_NUM = 8'd0,
|
||||
parameter NODE_INST = 0,
|
||||
parameter [15:0] PROTOVER = {8'd1, 8'd0}
|
||||
) (
|
||||
// Standard Clocks and Resets
|
||||
input wire core_arst,
|
||||
input wire rfnoc_ctrl_clk,
|
||||
input wire rfnoc_ctrl_rst,
|
||||
input wire rfnoc_chdr_clk,
|
||||
input wire rfnoc_chdr_rst,
|
||||
|
||||
// QSFP Clocks
|
||||
input wire refclk_p,
|
||||
input wire refclk_n,
|
||||
input wire dclk,
|
||||
|
||||
// MGT Pins
|
||||
output logic [3:0] tx_p,
|
||||
output logic [3:0] tx_n,
|
||||
input wire [3:0] rx_p,
|
||||
input wire [3:0] rx_n,
|
||||
|
||||
// Transport Adapter Status
|
||||
output logic recovered_clk,
|
||||
input wire [ 15:0] device_id,
|
||||
output logic [ 3:0] rx_irq,
|
||||
output logic [ 3:0] tx_irq,
|
||||
output logic [127:0] port_info,
|
||||
output logic [ 3:0] link_up,
|
||||
output logic [ 3:0] activity,
|
||||
|
||||
// AXI-Lite Register Interface
|
||||
input wire axil_rst,
|
||||
input wire axil_clk,
|
||||
input wire [39:0] axil_awaddr,
|
||||
input wire axil_awvalid,
|
||||
output logic axil_awready,
|
||||
input wire [31:0] axil_wdata,
|
||||
input wire [ 3:0] axil_wstrb,
|
||||
input wire axil_wvalid,
|
||||
output logic axil_wready,
|
||||
output logic [ 1:0] axil_bresp,
|
||||
output logic axil_bvalid,
|
||||
input wire axil_bready,
|
||||
input wire [39:0] axil_araddr,
|
||||
input wire axil_arvalid,
|
||||
output logic axil_arready,
|
||||
output logic [31:0] axil_rdata,
|
||||
output logic [ 1:0] axil_rresp,
|
||||
output logic axil_rvalid,
|
||||
input wire axil_rready,
|
||||
|
||||
// Ethernet DMA AXI to CPU memory
|
||||
input wire axi_rst,
|
||||
input wire axi_clk,
|
||||
output logic [ 48:0] axi_araddr,
|
||||
output logic [ 1:0] axi_arburst,
|
||||
output logic [ 3:0] axi_arcache,
|
||||
output logic [ 7:0] axi_arlen,
|
||||
output logic [ 0:0] axi_arlock,
|
||||
output logic [ 2:0] axi_arprot,
|
||||
output logic [ 3:0] axi_arqos,
|
||||
input wire axi_arready,
|
||||
output logic [ 2:0] axi_arsize,
|
||||
output logic axi_arvalid,
|
||||
output logic [ 48:0] axi_awaddr,
|
||||
output logic [ 1:0] axi_awburst,
|
||||
output logic [ 3:0] axi_awcache,
|
||||
output logic [ 7:0] axi_awlen,
|
||||
output logic [ 0:0] axi_awlock,
|
||||
output logic [ 2:0] axi_awprot,
|
||||
output logic [ 3:0] axi_awqos,
|
||||
input wire axi_awready,
|
||||
output logic [ 2:0] axi_awsize,
|
||||
output logic axi_awvalid,
|
||||
output logic axi_bready,
|
||||
input wire [ 1:0] axi_bresp,
|
||||
input wire axi_bvalid,
|
||||
input wire [127:0] axi_rdata,
|
||||
input wire axi_rlast,
|
||||
output logic axi_rready,
|
||||
input wire [ 1:0] axi_rresp,
|
||||
input wire axi_rvalid,
|
||||
output logic [127:0] axi_wdata,
|
||||
output logic axi_wlast,
|
||||
input wire axi_wready,
|
||||
output logic [ 15:0] axi_wstrb,
|
||||
output logic axi_wvalid,
|
||||
|
||||
// CHDR Buses
|
||||
output logic [4*CHDR_W-1:0] s_rfnoc_chdr_tdata,
|
||||
output logic [ 3:0] s_rfnoc_chdr_tlast,
|
||||
output logic [ 3:0] s_rfnoc_chdr_tvalid,
|
||||
input wire [ 3:0] s_rfnoc_chdr_tready,
|
||||
|
||||
input wire [4*CHDR_W-1:0] m_rfnoc_chdr_tdata,
|
||||
input wire [ 3:0] m_rfnoc_chdr_tlast,
|
||||
input wire [ 3:0] m_rfnoc_chdr_tvalid,
|
||||
output logic [ 3:0] m_rfnoc_chdr_tready
|
||||
);
|
||||
import PkgAxiLite::*;
|
||||
|
||||
`include "../../lib/axi4lite_sv/axi_lite.vh"
|
||||
`include "../../lib/axi4s_sv/axi4s.vh"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// AXI Interfaces
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
localparam CHDR_USER_W = $clog2(CHDR_W/8);
|
||||
|
||||
// AXI-Stream for RFNoC CHDR
|
||||
AxiStreamIf #(
|
||||
.DATA_WIDTH(CHDR_W ),
|
||||
.USER_WIDTH(CHDR_USER_W),
|
||||
.TKEEP (0 ),
|
||||
.TUSER (0)
|
||||
) v2e[4] (
|
||||
.clk(rfnoc_chdr_clk),
|
||||
.rst(rfnoc_chdr_rst)
|
||||
);
|
||||
|
||||
AxiStreamIf #(
|
||||
.DATA_WIDTH(CHDR_W ),
|
||||
.USER_WIDTH(CHDR_USER_W),
|
||||
.TKEEP (0 ),
|
||||
.TUSER (0 )
|
||||
) e2v[4] (
|
||||
.clk(rfnoc_chdr_clk),
|
||||
.rst(rfnoc_chdr_rst)
|
||||
);
|
||||
|
||||
// AXI-Lite register interface
|
||||
AxiLiteIf #(
|
||||
.DATA_WIDTH(32),
|
||||
.ADDR_WIDTH(40)
|
||||
) s_axi (
|
||||
.clk(axil_clk),
|
||||
.rst(axil_rst)
|
||||
);
|
||||
|
||||
// AXI (Full) for DMA back to CPU memory
|
||||
AxiIf #(
|
||||
.DATA_WIDTH(128),
|
||||
.ADDR_WIDTH(49 )
|
||||
) axi_hp (
|
||||
.clk(axi_clk),
|
||||
.rst(axi_rst)
|
||||
);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Translate Signals to Interfaces
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
logic [3:0][31:0] port_info_arr;
|
||||
|
||||
always_comb begin
|
||||
port_info = { port_info_arr[3], port_info_arr[2], port_info_arr[1], port_info_arr[0] };
|
||||
|
||||
//---------------------------------
|
||||
// AXI-Lite
|
||||
//---------------------------------
|
||||
|
||||
// Write channel
|
||||
s_axi.awaddr[39:18] = 0;
|
||||
s_axi.awaddr[17:0] = axil_awaddr[17:0]; // 256 KiB window
|
||||
s_axi.awvalid = axil_awvalid;
|
||||
axil_awready = s_axi.awready;
|
||||
|
||||
s_axi.wdata = axil_wdata[31:0];
|
||||
s_axi.wstrb = axil_wstrb;
|
||||
s_axi.wvalid = axil_wvalid;
|
||||
axil_wready = s_axi.wready;
|
||||
|
||||
axil_bresp = s_axi.bresp[1:0];
|
||||
axil_bvalid = s_axi.bvalid;
|
||||
s_axi.bready = axil_bready;
|
||||
|
||||
// Read channel
|
||||
s_axi.araddr[39:18] = 0;
|
||||
s_axi.araddr[17:0] = axil_araddr[17:0]; // 256 KiB window
|
||||
s_axi.arvalid = axil_arvalid;
|
||||
axil_arready = s_axi.arready;
|
||||
|
||||
axil_rdata[31:0] = s_axi.rdata;
|
||||
axil_rresp = s_axi.rresp[1:0];
|
||||
axil_rvalid = s_axi.rvalid;
|
||||
s_axi.rready = axil_rready;
|
||||
|
||||
//---------------------------------
|
||||
// AXI
|
||||
//---------------------------------
|
||||
|
||||
// Write channel
|
||||
axi_awaddr = axi_hp.awaddr;
|
||||
axi_awburst = axi_hp.awburst;
|
||||
axi_awcache = axi_hp.awcache;
|
||||
axi_awlen = axi_hp.awlen;
|
||||
axi_awsize = axi_hp.awsize;
|
||||
axi_awlock = axi_hp.awlock;
|
||||
axi_awprot = axi_hp.awprot;
|
||||
axi_awqos = axi_hp.awqos;
|
||||
axi_awvalid = axi_hp.awvalid;
|
||||
axi_hp.awready = axi_awready;
|
||||
|
||||
axi_wdata = axi_hp.wdata;
|
||||
axi_wstrb = axi_hp.wstrb;
|
||||
axi_wlast = axi_hp.wlast;
|
||||
axi_wvalid = axi_hp.wvalid;
|
||||
axi_hp.wready = axi_wready;
|
||||
|
||||
axi_hp.bresp[1:0] = axi_bresp;
|
||||
axi_hp.bvalid = axi_bvalid;
|
||||
axi_bready = axi_hp.bready;
|
||||
|
||||
// Read channel
|
||||
axi_araddr = axi_hp.araddr;
|
||||
axi_arburst = axi_hp.arburst;
|
||||
axi_arcache = axi_hp.arcache;
|
||||
axi_arlen = axi_hp.arlen;
|
||||
axi_arsize = axi_hp.arsize;
|
||||
axi_arlock = axi_hp.arlock;
|
||||
axi_arprot = axi_hp.arprot;
|
||||
axi_arqos = axi_hp.arqos;
|
||||
axi_arvalid = axi_hp.arvalid;
|
||||
axi_hp.arready = axi_arready;
|
||||
|
||||
axi_hp.rdata = axi_rdata;
|
||||
axi_hp.rresp[1:0] = axi_rresp;
|
||||
axi_hp.rlast = axi_rlast;
|
||||
axi_hp.rvalid = axi_rvalid;
|
||||
axi_rready = axi_hp.rready;
|
||||
|
||||
//---------------------------------
|
||||
// CHDR Links
|
||||
//---------------------------------
|
||||
|
||||
s_rfnoc_chdr_tdata[1*CHDR_W-1:0*CHDR_W] = e2v[0].tdata;
|
||||
s_rfnoc_chdr_tlast[0] = e2v[0].tlast;
|
||||
s_rfnoc_chdr_tvalid[0] = e2v[0].tvalid;
|
||||
e2v[0].tready = s_rfnoc_chdr_tready[0];
|
||||
|
||||
s_rfnoc_chdr_tdata[2*CHDR_W-1:1*CHDR_W] = e2v[1].tdata;
|
||||
s_rfnoc_chdr_tlast[1] = e2v[1].tlast;
|
||||
s_rfnoc_chdr_tvalid[1] = e2v[1].tvalid;
|
||||
e2v[1].tready = s_rfnoc_chdr_tready[1];
|
||||
|
||||
s_rfnoc_chdr_tdata[3*CHDR_W-1:2*CHDR_W] = e2v[2].tdata;
|
||||
s_rfnoc_chdr_tlast[2] = e2v[2].tlast;
|
||||
s_rfnoc_chdr_tvalid[2] = e2v[2].tvalid;
|
||||
e2v[2].tready = s_rfnoc_chdr_tready[2];
|
||||
|
||||
s_rfnoc_chdr_tdata[4*CHDR_W-1:3*CHDR_W] = e2v[3].tdata;
|
||||
s_rfnoc_chdr_tlast[3] = e2v[3].tlast;
|
||||
s_rfnoc_chdr_tvalid[3] = e2v[3].tvalid;
|
||||
e2v[3].tready = s_rfnoc_chdr_tready[3];
|
||||
|
||||
v2e[0].tdata = m_rfnoc_chdr_tdata[1*CHDR_W-1:0*CHDR_W];
|
||||
v2e[0].tlast = m_rfnoc_chdr_tlast[0];
|
||||
v2e[0].tvalid = m_rfnoc_chdr_tvalid[0];
|
||||
m_rfnoc_chdr_tready[0] = v2e[0].tready;
|
||||
|
||||
v2e[1].tdata = m_rfnoc_chdr_tdata[2*CHDR_W-1:1*CHDR_W];
|
||||
v2e[1].tlast = m_rfnoc_chdr_tlast[1];
|
||||
v2e[1].tvalid = m_rfnoc_chdr_tvalid[1];
|
||||
m_rfnoc_chdr_tready[1] = v2e[1].tready;
|
||||
|
||||
v2e[2].tdata = m_rfnoc_chdr_tdata[3*CHDR_W-1:2*CHDR_W];
|
||||
v2e[2].tlast = m_rfnoc_chdr_tlast[2];
|
||||
v2e[2].tvalid = m_rfnoc_chdr_tvalid[2];
|
||||
m_rfnoc_chdr_tready[2] = v2e[2].tready;
|
||||
|
||||
v2e[3].tdata = m_rfnoc_chdr_tdata[4*CHDR_W-1:3*CHDR_W];
|
||||
v2e[3].tlast = m_rfnoc_chdr_tlast[3];
|
||||
v2e[3].tvalid = m_rfnoc_chdr_tvalid[3];
|
||||
m_rfnoc_chdr_tready[3] = v2e[3].tready;
|
||||
end
|
||||
|
||||
x4xx_qsfp_wrapper #(
|
||||
.PROTOCOL (PROTOCOL),
|
||||
.CHDR_W (CHDR_W),
|
||||
.NET_CHDR_W (CHDR_W),
|
||||
.BYTE_MTU (BYTE_MTU),
|
||||
.PORTNUM (QSFP_NUM),
|
||||
.NODE_INST (NODE_INST),
|
||||
.RFNOC_PROTOVER (PROTOVER)
|
||||
) x4xx_qsfp_wrapper_i (
|
||||
.areset (core_arst),
|
||||
.refclk_p (refclk_p),
|
||||
.refclk_n (refclk_n),
|
||||
.bus_rst (rfnoc_chdr_rst),
|
||||
.clk100 (dclk),
|
||||
.bus_clk (rfnoc_chdr_clk),
|
||||
.s_axi (s_axi),
|
||||
.tx_p (tx_p),
|
||||
.tx_n (tx_n),
|
||||
.rx_p (rx_p),
|
||||
.rx_n (rx_n),
|
||||
.e2v (e2v),
|
||||
.v2e (v2e),
|
||||
.axi_hp (axi_hp),
|
||||
.eth_tx_irq (tx_irq),
|
||||
.eth_rx_irq (rx_irq),
|
||||
.device_id (device_id),
|
||||
.rx_rec_clk_out (recovered_clk),
|
||||
.port_info (port_info_arr),
|
||||
.link_up (link_up),
|
||||
.activity (activity)
|
||||
);
|
||||
|
||||
endmodule : rfnoc_ta_x4xx_eth
|
||||
|
||||
`default_nettype wire
|
||||
@@ -0,0 +1,150 @@
|
||||
#
|
||||
# Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
#
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
#
|
||||
|
||||
#-------------------------------------------------
|
||||
# Top-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Define BASE_DIR to point to the "top" dir
|
||||
BASE_DIR = $(abspath ../../../../../top)
|
||||
|
||||
# Include viv_sim_preamble after defining BASE_DIR
|
||||
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
|
||||
|
||||
#-------------------------------------------------
|
||||
# Design Specific
|
||||
#-------------------------------------------------
|
||||
# Define part using PART_ID (<device>/<package>/<speedgrade>)
|
||||
ARCH = zynquplusRFSOC
|
||||
PART_ID = xczu28dr/ffvg1517/-1/e
|
||||
|
||||
# Include makefiles and sources for the DUT and its dependencies
|
||||
include $(BASE_DIR)/../lib/axi4_sv/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/axi4s_sv/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/xge/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/xge_interface/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/rfnoc/xport_sv/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/rfnoc/crossbar/Makefile.srcs
|
||||
include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
$(AXI4_SV_SRCS) \
|
||||
$(AXI4S_SV_SRCS) \
|
||||
$(XGE_SRCS) \
|
||||
$(XGE_INTERFACE_SRCS) \
|
||||
$(RFNOC_UTIL_SRCS) \
|
||||
$(RFNOC_XPORT_SV_SRCS) \
|
||||
$(RFNOC_XBAR_SRCS) \
|
||||
$(RFNOC_CORE_SRCS) \
|
||||
)
|
||||
|
||||
# Add files for the DUT
|
||||
DESIGN_SRCS += $(abspath \
|
||||
../x4xx_mgt_io_core.sv \
|
||||
../x4xx_qsfp_wrapper.sv \
|
||||
../rfnoc_ta_x4xx_eth.sv \
|
||||
)
|
||||
|
||||
#-------------------------------------------------
|
||||
# IP Specific
|
||||
#-------------------------------------------------
|
||||
# If simulation contains IP, define the IP_DIR and point
|
||||
# it to the base level IP directory
|
||||
IP_DIR = $(BASE_DIR)/x400/ip
|
||||
|
||||
# Include makefiles and sources for all IP components
|
||||
# *after* defining the IP_DIR
|
||||
include $(IP_DIR)/axi_interconnect_eth_bd/Makefile.inc
|
||||
include $(IP_DIR)/axi_interconnect_dma_bd/Makefile.inc
|
||||
include $(IP_DIR)/axi_eth_dma_bd/Makefile.inc
|
||||
include $(IP_DIR)/xge_pcs_pma/Makefile.inc
|
||||
include $(IP_DIR)/eth_100g_bd/Makefile.inc
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
$(IP_AXI_INTERCONNECT_ETH_HDL_SRCS) \
|
||||
$(IP_AXI_INTERCONNECT_ETH_BD_SRCS) \
|
||||
$(IP_AXI_INTERCONNECT_DMA_HDL_SRCS) \
|
||||
$(IP_AXI_INTERCONNECT_DMA_BD_SRCS) \
|
||||
$(IP_AXI_ETH_DMA_BD_HDL_SRCS) \
|
||||
$(IP_AXI_ETH_DMA_BD_SRCS) \
|
||||
$(XGE_PCS_PMA_SRCS) \
|
||||
$(IP_100G_HDL_SRCS) \
|
||||
$(IP_100G_BD_SRCS) \
|
||||
)
|
||||
|
||||
#-------------------------------------------------
|
||||
# ModelSim Specific
|
||||
#-------------------------------------------------
|
||||
|
||||
# Note: ipshared/*/hdl/sc_util_*_rfs.sv needs to be compiled before the rest of
|
||||
# the ipshared files.
|
||||
IP_AXI_ETH_DMA_BD_HDL_SIM_SRCS = $(wildcard $(addprefix $(IP_BUILD_DIR)/axi_eth_dma_bd/axi_eth_dma_bd/, \
|
||||
sim/axi_eth_dma_bd.v \
|
||||
ip/*/sim/*.h \
|
||||
ip/*/sim/*.v \
|
||||
ip/*/sim/*.vhd \
|
||||
ip/*/bd_0/hdl/*.v \
|
||||
ip/*/bd_0/sim/*.v \
|
||||
ip/*/bd_0/ip/ip_*/sim/*.v \
|
||||
ip/*/bd_0/ip/ip_*/sim/*.sv \
|
||||
ip/*/bd_0/ip/ip_*/sim/*.vhd \
|
||||
ipshared/*/hdl/sc_util_*_rfs.sv \
|
||||
ipshared/*/hdl/*.sv \
|
||||
ipshared/*/hdl/*.v \
|
||||
ipshared/*/simulation/*.v \
|
||||
ipshared/*/hdl/verilog/*.v \
|
||||
ipshared/*/hdl/verilog/*.svh \
|
||||
ipshared/*/hdl/verilog/*.vh \
|
||||
))
|
||||
|
||||
IP_AXI_INTERCONNECT_DMA_BD_HDL_SIM_SRCS = $(wildcard $(addprefix $(IP_BUILD_DIR)/axi_interconnect_dma_bd/axi_interconnect_dma_bd/, \
|
||||
sim/*.v \
|
||||
ip/*/sim/*.v \
|
||||
))
|
||||
|
||||
MISC_IP_SIM_SRCS += \
|
||||
$(VIVADO_PATH)/data/verilog/src/glbl.v \
|
||||
$(abspath $(IP_BUILD_DIR)/xge_pcs_pma/model_10gbe.sv) \
|
||||
|
||||
DESIGN_SRCS += $(abspath \
|
||||
$(IP_AXI_ETH_DMA_BD_HDL_SIM_SRCS) \
|
||||
$(IP_AXI_INTERCONNECT_DMA_BD_HDL_SIM_SRCS) \
|
||||
$(IP_AXI_INTERCONNECT_ETH_HDL_SIM_SRCS) \
|
||||
$(IP_100G_HDL_SIM_SRCS) \
|
||||
$(IP_XGE_PCS_PMA_HDL_SIM_SRCS) \
|
||||
$(MISC_IP_SIM_SRCS) \
|
||||
)
|
||||
|
||||
# Xilinx IP wants lots of libraries
|
||||
MODELSIM_LIBS += secureip unimacro_ver unisims_ver xilinx_vip xpm
|
||||
MODELSIM_ARGS += glbl -t 1fs
|
||||
# Needed for the HACK_SRC, speeds up the alignment phase (still long!)
|
||||
VLOG_ARGS += +define+SIM_SPEED_UP
|
||||
|
||||
# Suppressing the following worthless reminder.
|
||||
#* Warning: M:/usrp4-hw/oss-repo/fpga/usrp3/lib/axi4s_sv/axi4s_remove_bytes.sv(228): (vlog-2583) [SVCHK] -
|
||||
# Extra checking for conflicts with always_comb and always_latch variables is done at vopt time
|
||||
SVLOG_ARGS += -suppress 2583
|
||||
|
||||
#-------------------------------------------------
|
||||
# Testbench Specific
|
||||
#-------------------------------------------------
|
||||
# Define only one top-level module
|
||||
TB_TOP_MODULE ?= rfnoc_ta_x4xx_eth_all_tb
|
||||
|
||||
SIM_TOP = $(TB_TOP_MODULE)
|
||||
|
||||
SIM_SRCS = \
|
||||
$(abspath rfnoc_ta_x4xx_eth_tb.sv) \
|
||||
$(abspath $(TB_TOP_MODULE).sv) \
|
||||
|
||||
#-------------------------------------------------
|
||||
# Bottom-of-Makefile
|
||||
#-------------------------------------------------
|
||||
# Include all simulator specific makefiles here
|
||||
# Each should define a unique target to simulate
|
||||
# e.g. xsim, vsim, etc and a common "clean" target
|
||||
include $(BASE_DIR)/../tools/make/viv_simulator.mak
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: rfnoc_ta_x4xx_eth_all_tb
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Testbench for the QSFP wrapper to allow testing all protocols.
|
||||
//
|
||||
|
||||
`include "./x4xx_mgt_types.vh"
|
||||
|
||||
module rfnoc_ta_x4xx_eth_all_tb;
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("100GbE_F"),
|
||||
.PROTOCOL0 (`MGT_100GbE),
|
||||
.CHDR_W (512),
|
||||
.USE_MAC (0)
|
||||
) ETH_100Gb_fast ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("10GbE_F"),
|
||||
.PROTOCOL0 (`MGT_10GbE),
|
||||
.CHDR_W (64),
|
||||
.USE_MAC (0)
|
||||
) ETH_10Gb_fast ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("10GbE_F_512"),
|
||||
.PROTOCOL0 (`MGT_10GbE),
|
||||
.CHDR_W (512),
|
||||
.USE_MAC (0)
|
||||
) ETH_10Gb_fast_512 ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("10GbE_x4_F"),
|
||||
.PROTOCOL0 (`MGT_10GbE),
|
||||
.PROTOCOL1 (`MGT_10GbE),
|
||||
.PROTOCOL2 (`MGT_10GbE),
|
||||
.PROTOCOL3 (`MGT_10GbE),
|
||||
.CHDR_W (64),
|
||||
.USE_MAC (0)
|
||||
) ETH_10Gb_x4_fast ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("100GbE_512S"),
|
||||
.PROTOCOL0 (`MGT_100GbE),
|
||||
.CHDR_W (512),
|
||||
.USE_MAC (1)
|
||||
) ETH_100Gb_512serial ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("100GbE_128S"),
|
||||
.PROTOCOL0 (`MGT_100GbE),
|
||||
.CHDR_W (128),
|
||||
.USE_MAC (1)
|
||||
) ETH_100Gb_128serial ();
|
||||
|
||||
rfnoc_ta_x4xx_eth_tb #(
|
||||
.TEST_NAME ("10GbE_S"),
|
||||
.PROTOCOL0 (`MGT_10GbE),
|
||||
.CHDR_W (64),
|
||||
.USE_MAC (1)
|
||||
) ETH_10Gb_serial ();
|
||||
|
||||
bit clk,rst;
|
||||
|
||||
sim_clock_gen #(100.0) clk_gen (clk, rst);
|
||||
|
||||
// Wait for all done
|
||||
always_ff@(posedge clk) begin
|
||||
if (ETH_100Gb_fast.test.done &&
|
||||
ETH_10Gb_fast.test.done &&
|
||||
ETH_10Gb_fast_512.test.done &&
|
||||
ETH_10Gb_x4_fast.test.done &&
|
||||
ETH_100Gb_512serial.test.done &&
|
||||
ETH_100Gb_128serial.test.done &&
|
||||
ETH_10Gb_serial.test.done
|
||||
) $finish(1);
|
||||
end
|
||||
|
||||
endmodule
|
||||
+1633
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,426 @@
|
||||
//
|
||||
// Copyright 2021 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: x4xx_mgt_io_core
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Encapsulates the PCS/PMA, the MAC layer and the control interface
|
||||
// for 10GbE, and 100Gbe.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// PROTOCOL : Indicates the protocol to use for each of the 4 QSFP lanes.
|
||||
// See x4xx_mgt_types.vh for possible values.
|
||||
// REG_BASE : Base address for internal registers
|
||||
// REG_DWIDTH : Register data width
|
||||
// REG_AWIDTH : Register address width
|
||||
// PORTNUM : Port number, to distinguish between multiple QSFP ports
|
||||
// LANENUM : Lane number
|
||||
//
|
||||
|
||||
`include "./x4xx_mgt_types.vh"
|
||||
|
||||
|
||||
module x4xx_mgt_io_core #(
|
||||
parameter PROTOCOL = `MGT_100GbE,
|
||||
parameter [13:0] REG_BASE = 14'h0,
|
||||
parameter REG_DWIDTH = 32,
|
||||
parameter REG_AWIDTH = 14,
|
||||
parameter [ 7:0] PORTNUM = 8'd0,
|
||||
parameter LANENUM = 0
|
||||
) (
|
||||
// Resets
|
||||
input logic areset,
|
||||
input logic bus_rst,
|
||||
|
||||
output logic mgt_rst,
|
||||
|
||||
// Clocks
|
||||
input logic clk100,
|
||||
input logic bus_clk,
|
||||
input logic refclk_p,
|
||||
input logic refclk_n,
|
||||
|
||||
output logic mgt_clk,
|
||||
|
||||
// QSFP high-speed IO
|
||||
output logic [3:0] tx_p,
|
||||
output logic [3:0] tx_n,
|
||||
input logic [3:0] rx_p,
|
||||
input logic [3:0] rx_n,
|
||||
|
||||
// Common signals for single lane 10 GbE
|
||||
output logic [0:0] qpll0_reset,
|
||||
input logic [0:0] qpll0_lock,
|
||||
input logic [0:0] qpll0_clk,
|
||||
input logic [0:0] qpll0_refclk,
|
||||
output logic [0:0] qpll1_reset,
|
||||
input logic [0:0] qpll1_lock,
|
||||
input logic [0:0] qpll1_clk,
|
||||
input logic [0:0] qpll1_refclk,
|
||||
|
||||
// AXI-Lite
|
||||
AxiLiteIf.slave m_axi_mac,
|
||||
|
||||
// Data port
|
||||
// Interface clocks on mgt_tx and mgt_rx are NOT used (logic uses mgt_clk).
|
||||
AxiStreamIf.slave mgt_tx,
|
||||
AxiStreamIf.master mgt_rx,
|
||||
input logic mgt_pause_req,
|
||||
|
||||
// Register port
|
||||
input logic reg_wr_req,
|
||||
input logic [REG_AWIDTH-1:0] reg_wr_addr,
|
||||
input logic [REG_DWIDTH-1:0] reg_wr_data,
|
||||
input logic reg_rd_req,
|
||||
input logic [REG_AWIDTH-1:0] reg_rd_addr,
|
||||
output logic reg_rd_resp,
|
||||
output logic [REG_DWIDTH-1:0] reg_rd_data,
|
||||
|
||||
// Misc.
|
||||
output logic rx_rec_clk_out,
|
||||
output logic [31:0] port_info,
|
||||
output logic link_up,
|
||||
output logic activity
|
||||
);
|
||||
|
||||
import PkgAxiLite::*;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Registers
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
localparam [7:0] COMPAT_NUM = 8'd2;
|
||||
|
||||
// Common registers
|
||||
localparam REG_PORT_INFO = REG_BASE + 'h0;
|
||||
localparam REG_MAC_CTRL_STATUS = REG_BASE + 'h4;
|
||||
localparam REG_PHY_CTRL_STATUS = REG_BASE + 'h8;
|
||||
localparam REG_MAC_LED_CTL = REG_BASE + 'hC;
|
||||
|
||||
// Ethernet specific
|
||||
localparam REG_ETH_MDIO_BASE = REG_BASE + 'h10;
|
||||
|
||||
// Aurora specific
|
||||
localparam REG_AURORA_OVERRUNS = REG_BASE + 'h20;
|
||||
localparam REG_CHECKSUM_ERRORS = REG_BASE + 'h24;
|
||||
localparam REG_BIST_CHECKER_SAMPS = REG_BASE + 'h28;
|
||||
localparam REG_BIST_CHECKER_ERRORS = REG_BASE + 'h2C;
|
||||
|
||||
localparam [ 1:0] MAC_LED_CTRL_RST_VAL = 2'h0;
|
||||
localparam [ 7:0] MGT_PROTOCOL = PROTOCOL;
|
||||
localparam [31:0] MAC_CTRL_RST_VAL =
|
||||
PROTOCOL == `MGT_100GbE ? {31'h0, 1'b1} : // Auto-connect enabled by default
|
||||
PROTOCOL == `MGT_WhiteRabbit ? 32'h0 :
|
||||
PROTOCOL == `MGT_Aurora ? 32'h0 :
|
||||
PROTOCOL == `MGT_10GbE ? {31'h0, 1'b1} : // Tx enabled by default
|
||||
PROTOCOL == `MGT_1GbE ? {31'h0, 1'b1} : // Tx enabled by default
|
||||
32'h0;
|
||||
localparam [31:0] PHY_CTRL_RST_VAL =
|
||||
PROTOCOL == `MGT_100GbE ? 32'h0 : // Unused
|
||||
PROTOCOL == `MGT_WhiteRabbit ? 32'h0 : // Unused
|
||||
PROTOCOL == `MGT_Aurora ? 32'h0 :
|
||||
PROTOCOL == `MGT_10GbE ? 32'h0 : // Unused
|
||||
PROTOCOL == `MGT_1GbE ? 32'h0 :
|
||||
32'h0;
|
||||
// Writable registers
|
||||
logic [31:0] mac_ctrl = MAC_CTRL_RST_VAL;
|
||||
logic [31:0] phy_ctrl = PHY_CTRL_RST_VAL;
|
||||
logic [ 1:0] mac_led_ctl = MAC_LED_CTRL_RST_VAL;
|
||||
|
||||
always @(posedge bus_clk) begin
|
||||
if (bus_rst) begin
|
||||
mac_ctrl <= MAC_CTRL_RST_VAL;
|
||||
phy_ctrl <= PHY_CTRL_RST_VAL;
|
||||
mac_led_ctl <= MAC_LED_CTRL_RST_VAL;
|
||||
end else if (reg_wr_req) begin
|
||||
case(reg_wr_addr)
|
||||
REG_MAC_CTRL_STATUS:
|
||||
mac_ctrl <= reg_wr_data;
|
||||
REG_PHY_CTRL_STATUS:
|
||||
phy_ctrl <= reg_wr_data;
|
||||
REG_MAC_LED_CTL:
|
||||
mac_led_ctl <= reg_wr_data[1:0];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// Readable registers
|
||||
logic [31:0] overruns;
|
||||
logic [31:0] checksum_errors;
|
||||
logic [47:0] bist_checker_samps;
|
||||
logic [47:0] bist_checker_errors;
|
||||
logic [31:0] mac_status, phy_status;
|
||||
logic [31:0] mac_status_bclk, phy_status_bclk;
|
||||
logic activity_bclk, link_up_bclk;
|
||||
logic [31:0] port_info_bclk;
|
||||
|
||||
// readback on m_axi.clk outside this core
|
||||
assign port_info = {COMPAT_NUM, 6'h0, activity, link_up, MGT_PROTOCOL, PORTNUM};
|
||||
assign port_info_bclk = {COMPAT_NUM, 6'h0, activity_bclk, link_up_bclk, MGT_PROTOCOL, PORTNUM};
|
||||
|
||||
always @(posedge bus_clk) begin
|
||||
// No reset handling needed for readback
|
||||
if (reg_rd_req) begin
|
||||
reg_rd_resp <= 1'b1;
|
||||
case(reg_rd_addr)
|
||||
REG_PORT_INFO:
|
||||
reg_rd_data <= port_info_bclk;
|
||||
REG_MAC_CTRL_STATUS:
|
||||
reg_rd_data <= mac_status_bclk;
|
||||
REG_PHY_CTRL_STATUS:
|
||||
reg_rd_data <= phy_status_bclk;
|
||||
REG_MAC_LED_CTL:
|
||||
reg_rd_data <= {30'd0, mac_led_ctl};
|
||||
REG_AURORA_OVERRUNS:
|
||||
reg_rd_data <= overruns;
|
||||
REG_CHECKSUM_ERRORS:
|
||||
reg_rd_data <= checksum_errors;
|
||||
REG_BIST_CHECKER_SAMPS:
|
||||
reg_rd_data <= bist_checker_samps[47:16]; // Scale num samples by 2^16
|
||||
REG_BIST_CHECKER_ERRORS:
|
||||
reg_rd_data <= bist_checker_errors[31:0]; // Don't scale errors
|
||||
default:
|
||||
begin
|
||||
reg_rd_data <= 32'd0;
|
||||
reg_rd_resp <= 1'b0;
|
||||
end
|
||||
endcase
|
||||
end if (reg_rd_resp) begin
|
||||
reg_rd_resp <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
synchronizer #(
|
||||
.STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0)
|
||||
) synchronizer_mac_status (
|
||||
.clk(bus_clk), .rst(1'b0), .in(mac_status), .out(mac_status_bclk)
|
||||
);
|
||||
|
||||
synchronizer #(
|
||||
.STAGES(2), .WIDTH(32), .INITIAL_VAL(32'h0)
|
||||
) synchronizer_phy_status (
|
||||
.clk(bus_clk), .rst(1'b0), .in(phy_status), .out(phy_status_bclk)
|
||||
);
|
||||
|
||||
logic link_up_mgtclk;
|
||||
logic wr_activity = 0;
|
||||
|
||||
if (PROTOCOL == `MGT_10GbE) begin : core_10g
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 10 GbE Interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
eth_10g eth_10g_i (
|
||||
.areset (areset),
|
||||
// Free-running 100 MHz clock used for InitClk and AxiLite to MAC
|
||||
.clk100 (clk100),
|
||||
// Quad Info
|
||||
.qpll0_refclk (qpll0_refclk),
|
||||
.qpll0_clk (qpll0_clk),
|
||||
.qpll0_lock (qpll0_lock),
|
||||
.qpll0_reset (qpll0_reset),
|
||||
.qpll1_refclk (qpll1_refclk),
|
||||
.qpll1_clk (qpll1_clk),
|
||||
.qpll1_lock (qpll1_lock),
|
||||
.qpll1_reset (qpll1_reset),
|
||||
// Recovered clock for export
|
||||
.rx_rec_clk_out (rx_rec_clk_out),
|
||||
// MGT TX/RX differential signals
|
||||
.tx_p (tx_p[LANENUM]),
|
||||
.tx_n (tx_n[LANENUM]),
|
||||
.rx_p (rx_p[LANENUM]),
|
||||
.rx_n (rx_n[LANENUM]),
|
||||
// 156.25 MHz clock
|
||||
.mgt_clk (mgt_clk),
|
||||
.mgt_rst (mgt_rst),
|
||||
// AXI Stream TX Interface
|
||||
.mgt_tx (mgt_tx),
|
||||
// AXI Stream RX Interface
|
||||
// There is no RX TREADY signal support in the IP. Received data has to
|
||||
// be read immediately or it is lost. TUSER indicates an error on
|
||||
// received packet.
|
||||
.mgt_rx (mgt_rx),
|
||||
// AXI-Lite bus for tie off
|
||||
.mgt_axil (m_axi_mac),
|
||||
// LEDs of QSFP28 port
|
||||
.phy_status (phy_status),
|
||||
.mac_ctrl (mac_ctrl),
|
||||
.mac_status (mac_status),
|
||||
.phy_reset (),
|
||||
.link_up (link_up_mgtclk)
|
||||
);
|
||||
|
||||
always_comb begin : eth_10g_tieoff
|
||||
overruns = 0;
|
||||
checksum_errors = 0;
|
||||
bist_checker_samps = 0;
|
||||
bist_checker_errors = 0;
|
||||
end : eth_10g_tieoff
|
||||
|
||||
end else if (PROTOCOL == `MGT_100GbE) begin : core_100g
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// 100 GbE Interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
eth_100g eth_100g_i (
|
||||
.areset (areset),
|
||||
// Free-running 100 MHz clock used for InitClk and AxiLite to MAC
|
||||
.clk100 (clk100),
|
||||
// MGT Reference Clock 100/125/156.25/161.1328125 MHz
|
||||
.refclk_p (refclk_p),
|
||||
.refclk_n (refclk_n),
|
||||
// Recovered clock for export
|
||||
.rx_rec_clk_out (rx_rec_clk_out),
|
||||
// MGT TX/RX differential signals
|
||||
.tx_p (tx_p),
|
||||
.tx_n (tx_n),
|
||||
.rx_p (rx_p),
|
||||
.rx_n (rx_n),
|
||||
// 322.26666 MHz clock generated by 100G PHY from RefClock
|
||||
.mgt_clk (mgt_clk),
|
||||
.mgt_rst (mgt_rst),
|
||||
.mgt_pause_req (mgt_pause_req),
|
||||
// AXI Stream TX Interface
|
||||
.mgt_tx (mgt_tx),
|
||||
// AXI Stream RX Interface
|
||||
// There is no RX TREADY signal support in the IP. Received data has to
|
||||
// be read immediately or it is lost. TUSER indicates an error on
|
||||
// received packet.
|
||||
.mgt_rx (mgt_rx),
|
||||
.mgt_axil (m_axi_mac),
|
||||
// LEDs of QSFP28 port
|
||||
.phy_status (phy_status),
|
||||
.mac_status (mac_status),
|
||||
.mac_ctrl (mac_ctrl),
|
||||
.phy_reset (),
|
||||
.link_up (link_up_mgtclk)
|
||||
);
|
||||
|
||||
always_comb begin : eth_100g_tieoff
|
||||
overruns = 0;
|
||||
checksum_errors = 0;
|
||||
bist_checker_samps = 0;
|
||||
bist_checker_errors = 0;
|
||||
|
||||
qpll0_reset = 0;
|
||||
qpll1_reset = 0;
|
||||
end : eth_100g_tieoff
|
||||
|
||||
end else if (PROTOCOL == `MGT_Aurora) begin : core_aurora
|
||||
|
||||
Aurora_not_yet_supported();
|
||||
|
||||
always_comb begin : aurrora_tieoff
|
||||
m_axi_mac.drive_read_resp(.resp(SLVERR),.data(0));
|
||||
m_axi_mac.drive_write_resp(.resp(SLVERR));
|
||||
m_axi_mac.arready = 1'b1;
|
||||
m_axi_mac.awready = 1'b1;
|
||||
m_axi_mac.wready = 1'b1;
|
||||
|
||||
phy_status = 'h0;
|
||||
mac_status = 'h0;
|
||||
link_up_mgtclk = 1'b0;
|
||||
|
||||
overruns = 0;
|
||||
checksum_errors = 0;
|
||||
bist_checker_samps = 0;
|
||||
bist_checker_errors = 0;
|
||||
rx_rec_clk_out = 0;
|
||||
|
||||
qpll0_reset = 0;
|
||||
qpll1_reset = 0;
|
||||
end : aurrora_tieoff
|
||||
|
||||
end else begin : core_disabled
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Port Disabled
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
assign mgt_clk = bus_clk;
|
||||
assign mgt_rst = bus_rst;
|
||||
|
||||
always_comb begin : disabled_tieoff
|
||||
m_axi_mac.drive_read_resp(.resp(SLVERR),.data(0));
|
||||
m_axi_mac.drive_write_resp(.resp(SLVERR));
|
||||
m_axi_mac.arready = 1'b1;
|
||||
m_axi_mac.awready = 1'b1;
|
||||
m_axi_mac.wready = 1'b1;
|
||||
|
||||
phy_status = 'h0;
|
||||
mac_status = 'h0;
|
||||
link_up_mgtclk = 1'b0;
|
||||
|
||||
mgt_tx.tready = 1'b1;
|
||||
mgt_rx.tdata = 64'h0;
|
||||
mgt_rx.tuser = 4'h0;
|
||||
mgt_rx.tlast = 1'b0;
|
||||
mgt_rx.tvalid = 1'b0;
|
||||
mgt_rx.tkeep = 'b0;
|
||||
|
||||
overruns = 0;
|
||||
checksum_errors = 0;
|
||||
bist_checker_samps = 0;
|
||||
bist_checker_errors = 0;
|
||||
rx_rec_clk_out = 0;
|
||||
|
||||
tx_p = 0;
|
||||
tx_n = 0;
|
||||
|
||||
qpll0_reset = 0;
|
||||
qpll1_reset = 0;
|
||||
end : disabled_tieoff
|
||||
|
||||
end
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Activity Detector
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
logic identify_enable,identify_value;
|
||||
logic activity_mgtclk, activity_int;
|
||||
always_comb begin
|
||||
identify_enable = mac_led_ctl[0];
|
||||
identify_value = mac_led_ctl[1];
|
||||
end
|
||||
|
||||
pulse_stretch pulse_stretch_activity_i (
|
||||
.clk (mgt_clk),
|
||||
.rst (mgt_rst | ~link_up_mgtclk),
|
||||
.pulse ((mgt_tx.tvalid & mgt_tx.tready) | (mgt_rx.tvalid & mgt_rx.tready)),
|
||||
.pulse_stretched (activity_mgtclk)
|
||||
);
|
||||
|
||||
synchronizer #(
|
||||
.WIDTH (2),
|
||||
.STAGES (1)
|
||||
) synchronizer_lnk_act_bclk (
|
||||
.clk (bus_clk),
|
||||
.rst (bus_rst),
|
||||
.in ({link_up_mgtclk, activity_mgtclk}),
|
||||
.out ({link_up_bclk, activity_int})
|
||||
);
|
||||
|
||||
always @ (posedge bus_clk) begin
|
||||
activity_bclk <= identify_enable ? identify_value : activity_int;
|
||||
end
|
||||
|
||||
synchronizer #(
|
||||
.WIDTH (2),
|
||||
.STAGES (1)
|
||||
) synchronizer_lnk_act_aclk (
|
||||
.clk (m_axi_mac.clk),
|
||||
.rst (m_axi_mac.rst),
|
||||
.in ({link_up_bclk, activity_bclk}),
|
||||
.out ({link_up, activity})
|
||||
);
|
||||
|
||||
endmodule
|
||||
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// Copyright 2021 Ettus Research, a National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: x4xx_mgt_type.vh
|
||||
// Description: Enumerations for types of MGT to be used with the X4XX
|
||||
//
|
||||
|
||||
`define MGT_100GbE 5
|
||||
`define MGT_WhiteRabbit 4
|
||||
`define MGT_Aurora 3
|
||||
`define MGT_10GbE 2
|
||||
`define MGT_1GbE 1
|
||||
`define MGT_Disabled 0
|
||||
@@ -0,0 +1,569 @@
|
||||
//
|
||||
// Copyright 2021 Ettus Research, A National Instruments Brand
|
||||
//
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
//
|
||||
// Module: x4xx_qsfp_wrapper
|
||||
//
|
||||
// Description:
|
||||
//
|
||||
// Consolidates the logic necessary for a QSFP port, depending on the
|
||||
// requested protocol.
|
||||
//
|
||||
// Parameters:
|
||||
//
|
||||
// PROTOCOL : Indicates the protocol to use for each of the 4 QSFP
|
||||
// lanes. See x4xx_mgt_types.vh for possible values.
|
||||
// CHDR_W : CHDR bus width
|
||||
// NET_CHDR_W : CHDR width used over the network connection
|
||||
// BYTE_MTU : Transport MTU in bytes
|
||||
// PORTNUM : Port number to distinguish multiple QSFP ports
|
||||
// NODE_INST : RFNoC transport adapter node instance for the first port
|
||||
// RFNOC_PROTOVER : RFNoC protocol version for IPv4 interface
|
||||
//
|
||||
|
||||
`include "./x4xx_mgt_types.vh"
|
||||
|
||||
|
||||
module x4xx_qsfp_wrapper #(
|
||||
// Must be a value defined in x4xx_mgt_types.vh
|
||||
parameter integer PROTOCOL [3:0] = {`MGT_Disabled,
|
||||
`MGT_Disabled,
|
||||
`MGT_Disabled,
|
||||
`MGT_Disabled},
|
||||
parameter CHDR_W = 64,
|
||||
parameter NET_CHDR_W = CHDR_W,
|
||||
parameter BYTE_MTU = $clog2(8*1024),
|
||||
parameter [ 7:0] PORTNUM = 8'd0,
|
||||
parameter NODE_INST = 0,
|
||||
parameter [15:0] RFNOC_PROTOVER = {8'd1, 8'd0}
|
||||
)(
|
||||
// Resets
|
||||
input logic areset,
|
||||
input logic bus_rst,
|
||||
|
||||
// Clocks
|
||||
input logic refclk_p,
|
||||
input logic refclk_n,
|
||||
input logic clk100,
|
||||
input logic bus_clk,
|
||||
|
||||
// AXI-Lite register access
|
||||
AxiLiteIf.slave s_axi,
|
||||
|
||||
// Ethernet DMA AXI to PS memory
|
||||
AxiIf.master axi_hp,
|
||||
|
||||
// MGT high-speed IO
|
||||
output logic [3:0] tx_p,
|
||||
output logic [3:0] tx_n,
|
||||
input logic [3:0] rx_p,
|
||||
input logic [3:0] rx_n,
|
||||
|
||||
// CHDR router interface
|
||||
AxiStreamIf.master e2v [4],
|
||||
AxiStreamIf.slave v2e [4],
|
||||
|
||||
// ETH DMA IRQs
|
||||
output logic [3:0] eth_rx_irq,
|
||||
output logic [3:0] eth_tx_irq,
|
||||
|
||||
// Misc.
|
||||
output logic rx_rec_clk_out,
|
||||
input logic [15:0] device_id,
|
||||
|
||||
output logic [3:0][31:0] port_info,
|
||||
|
||||
output logic [3:0] link_up,
|
||||
output logic [3:0] activity
|
||||
);
|
||||
|
||||
import PkgAxiLite::*;
|
||||
|
||||
localparam REG_BASE_SFP_IO = 14'h0;
|
||||
localparam REG_BASE_ETH_SWITCH = 14'h1000;
|
||||
localparam CPU_W = 64; // Must match axi_eth_dma IP
|
||||
localparam CPU_USER_W = $clog2(CPU_W/8)+1;
|
||||
localparam CHDR_USER_W = $clog2(CHDR_W/8);
|
||||
localparam REG_DWIDTH = 32;
|
||||
localparam REG_AWIDTH_MISC = 14;
|
||||
localparam logic [3:0] DISABLED = { PROTOCOL[3] == `MGT_Disabled,
|
||||
PROTOCOL[2] == `MGT_Disabled,
|
||||
PROTOCOL[1] == `MGT_Disabled,
|
||||
PROTOCOL[0] == `MGT_Disabled };
|
||||
localparam logic [3:0] IS10GBE = { PROTOCOL[3] == `MGT_10GbE,
|
||||
PROTOCOL[2] == `MGT_10GbE,
|
||||
PROTOCOL[1] == `MGT_10GbE,
|
||||
PROTOCOL[0] == `MGT_10GbE };
|
||||
localparam logic [3:0] IS100GBE = { 3'b0,PROTOCOL[0] == `MGT_100GbE };
|
||||
localparam logic [3:0] ISAURORA = { 3'b0,PROTOCOL[0] == `MGT_Aurora };
|
||||
|
||||
|
||||
`include "../../lib/axi4_sv/axi.vh"
|
||||
`include "../../lib/axi4lite_sv/axi_lite.vh"
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Interfaces
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// AXI-Lite interface
|
||||
AxiLiteIf #(REG_DWIDTH,40)
|
||||
m_axi_dma[3:0] (s_axi.clk, s_axi.rst);
|
||||
|
||||
// 0x0000-0x3FFF - Bottom goes to XGE top goes to UIO
|
||||
AxiLiteIf #(REG_DWIDTH,40)
|
||||
m_axi_misc[3:0] (s_axi.clk, s_axi.rst);
|
||||
AxiLiteIf_v #(REG_DWIDTH,REG_AWIDTH_MISC)
|
||||
m_axi_misc_v[3:0] (s_axi.clk, s_axi.rst);
|
||||
|
||||
// 0x4000-0x5FFF - Goes to 100G Mac
|
||||
AxiLiteIf #(REG_DWIDTH,40)
|
||||
m_axi_mac[3:0] (s_axi.clk, s_axi.rst);
|
||||
|
||||
// AXI (Full) for DMA back to CPU memory
|
||||
AxiIf #(128,49)
|
||||
axi_hp_dma[3:0] (s_axi.clk, s_axi.rst);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// AXI Interconnect
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Break the incoming register request into 12 different spaces:
|
||||
//
|
||||
// 0x0_0000 - dma0
|
||||
// 0x0_8000 - misc0 - +0x0000 NIXGE
|
||||
// +0x2000 UIO
|
||||
// 0x0_C000 - mac0
|
||||
//
|
||||
// 0x1_0000 - dma1
|
||||
// 0x1_8000 - misc1 - +0x0000 NIXGE
|
||||
// +0x2000 UIO
|
||||
// 0x1_C000 - mac1
|
||||
//
|
||||
// 0x2_0000 - dma2
|
||||
// 0x2_8000 - misc2 - +0x0000 NIXGE
|
||||
// +0x2000 UIO
|
||||
// 0x2_C000 - mac2
|
||||
//
|
||||
// 0x3_0000 - dma3
|
||||
// 0x3_8000 - misc3 - +0x0000 NIXGE
|
||||
// +0x2000 UIO
|
||||
// 0x3_C000 - mac3
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
axi_interconnect_eth axi_interconnect_eth_i (
|
||||
.s_axi_eth (s_axi),
|
||||
.m_axi_dma (m_axi_dma),
|
||||
.m_axi_misc (m_axi_misc),
|
||||
.m_axi_mac (m_axi_mac)
|
||||
);
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Map DMA Engine Masters to CPU Memory Port
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Everything Disabled
|
||||
if (DISABLED == 4'b1111) begin : axi_hp_noconnect
|
||||
always_comb begin
|
||||
axi_hp.drive_read_idle();
|
||||
axi_hp.drive_aw_idle();
|
||||
axi_hp.drive_w_idle();
|
||||
axi_hp.bready = 1'b0;
|
||||
axi_hp.rready = 1'b0;
|
||||
end
|
||||
end : axi_hp_noconnect else
|
||||
// Only port0 Enabled
|
||||
if (DISABLED == 4'b1110) begin : axi_hp_directconnect
|
||||
always_comb begin
|
||||
`AXI4_ASSIGN(axi_hp,axi_hp_dma[0])
|
||||
axi_hp_dma[1].wready = 1'b0;
|
||||
axi_hp_dma[2].wready = 1'b0;
|
||||
axi_hp_dma[3].wready = 1'b0;
|
||||
axi_hp_dma[1].awready = 1'b0;
|
||||
axi_hp_dma[2].awready = 1'b0;
|
||||
axi_hp_dma[3].awready = 1'b0;
|
||||
axi_hp_dma[1].arready = 1'b0;
|
||||
axi_hp_dma[2].arready = 1'b0;
|
||||
axi_hp_dma[3].arready = 1'b0;
|
||||
axi_hp_dma[1].bvalid = 1'b0;
|
||||
axi_hp_dma[2].bvalid = 1'b0;
|
||||
axi_hp_dma[3].bvalid = 1'b0;
|
||||
axi_hp_dma[1].rvalid = 1'b0;
|
||||
axi_hp_dma[2].rvalid = 1'b0;
|
||||
axi_hp_dma[3].rvalid = 1'b0;
|
||||
end
|
||||
// All other cases
|
||||
end : axi_hp_directconnect else begin : axi_hp_interconnect
|
||||
axi_interconnect_dma axi_interconnect_dma_i (
|
||||
.m_axi_hp (axi_hp),
|
||||
.s_axi_hp_dma (axi_hp_dma)
|
||||
);
|
||||
end : axi_hp_interconnect
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// 10 Gigabit Ethernet
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
logic refclk; // 156 Mhz Ref 10 GbE
|
||||
logic [0:0] qpll0_reset;
|
||||
logic [3:0] qpll0_reset_i;
|
||||
logic [0:0] qpll0_lock;
|
||||
logic [0:0] qpll0_clk;
|
||||
logic [0:0] qpll0_refclk;
|
||||
logic [0:0] qpll1_reset;
|
||||
logic [3:0] qpll1_reset_i;
|
||||
logic [0:0] qpll1_lock;
|
||||
logic [0:0] qpll1_clk;
|
||||
logic [0:0] qpll1_refclk;
|
||||
|
||||
assign qpll0_reset[0] = qpll0_reset_i[0] || qpll0_reset_i[1] ||
|
||||
qpll0_reset_i[2] || qpll0_reset_i[3];
|
||||
assign qpll1_reset[0] = qpll1_reset_i[0] || qpll1_reset_i[1] ||
|
||||
qpll1_reset_i[2] || qpll1_reset_i[3];
|
||||
|
||||
// The following logic is shared amongst potentially 4X10GBE interfaces
|
||||
if (IS10GBE != 0) begin : xge_common
|
||||
|
||||
// Clocking signals for MGTs
|
||||
IBUFDS_GTE4 ibufds_gte4_refclk (
|
||||
.I (refclk_p),
|
||||
.IB (refclk_n),
|
||||
.CEB (1'b0),
|
||||
.O (refclk),
|
||||
.ODIV2 ()
|
||||
);
|
||||
|
||||
xge_pcs_pma_common_wrapper xge_pcs_pma_common_wrapper_i (
|
||||
.refclk (refclk),
|
||||
.qpll0reset (qpll0_reset),
|
||||
.qpll0lock (qpll0_lock),
|
||||
.qpll0outclk (qpll0_clk),
|
||||
.qpll0outrefclk (qpll0_refclk),
|
||||
.qpll1reset (qpll1_reset),
|
||||
.qpll1lock (qpll1_lock),
|
||||
.qpll1outclk (qpll1_clk),
|
||||
.qpll1outrefclk (qpll1_refclk)
|
||||
);
|
||||
|
||||
end : xge_common
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Generate QSFP Lanes
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
logic [3:0] rx_rec_clk_out_i;
|
||||
assign rx_rec_clk_out = rx_rec_clk_out_i[0];
|
||||
|
||||
generate
|
||||
genvar lane;
|
||||
begin : mgt_lanes
|
||||
// Repeat logic for up to 4 QSFP lanes
|
||||
for(lane = 0; lane < 4; lane++) begin : lane_loop
|
||||
|
||||
//---------------------------------------
|
||||
// AXI-Lite to RegPort Bridge
|
||||
//---------------------------------------
|
||||
|
||||
// Map to 0x4000 space
|
||||
always_comb begin
|
||||
`AXI4LITE_ASSIGN(m_axi_misc_v[lane],m_axi_misc[lane])
|
||||
m_axi_misc_v[lane].araddr = 0;
|
||||
m_axi_misc_v[lane].araddr[13:0] = m_axi_misc[lane].araddr[13:0];
|
||||
m_axi_misc_v[lane].awaddr = 0;
|
||||
m_axi_misc_v[lane].awaddr[13:0] = m_axi_misc[lane].awaddr[13:0];
|
||||
end
|
||||
|
||||
// AXI4-Lite to RegPort (PS to PL Register Access)
|
||||
// NOTE: We always have a register interface even if the block is
|
||||
// unused, so that the driver can query the status.
|
||||
typedef logic [REG_AWIDTH_MISC-1:0] reg_addr_t;
|
||||
typedef logic [REG_DWIDTH-1:0] reg_data_t;
|
||||
|
||||
logic reg_wr_req;
|
||||
reg_addr_t reg_wr_addr;
|
||||
reg_data_t reg_wr_data;
|
||||
logic reg_rd_req;
|
||||
reg_addr_t reg_rd_addr;
|
||||
logic reg_rd_resp, reg_rd_resp_io, reg_rd_resp_eth_if;
|
||||
reg_data_t reg_rd_data, reg_rd_data_io, reg_rd_data_eth_if;
|
||||
|
||||
axil_regport_master #(
|
||||
.DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64)
|
||||
.AWIDTH (REG_AWIDTH_MISC), // Width of the address bus
|
||||
.WRBASE (0), // Write address base
|
||||
.RDBASE (0), // Read address base
|
||||
.TIMEOUT (10) // log2(timeout). Read will timeout after (2^TIMEOUT - 1) cycles
|
||||
) axil_regport_master_i (
|
||||
// Clock and reset
|
||||
.s_axi_aclk (m_axi_misc_v[lane].clk),
|
||||
.s_axi_aresetn (!m_axi_misc_v[lane].rst),
|
||||
`AXI4LITE_PORT_ASSIGN_NR(s_axi,m_axi_misc_v[lane])
|
||||
// Register port: Write port (domain: reg_clk)
|
||||
.reg_clk (bus_clk),
|
||||
.reg_wr_req (reg_wr_req),
|
||||
.reg_wr_addr (reg_wr_addr),
|
||||
.reg_wr_data (reg_wr_data),
|
||||
.reg_wr_keep (/*unused*/),
|
||||
// Register port: Read port (domain: reg_clk)
|
||||
.reg_rd_req (reg_rd_req),
|
||||
.reg_rd_addr (reg_rd_addr),
|
||||
.reg_rd_resp (reg_rd_resp),
|
||||
.reg_rd_data (reg_rd_data)
|
||||
);
|
||||
|
||||
// Regport Mux for response
|
||||
regport_resp_mux #(
|
||||
.WIDTH (REG_DWIDTH),
|
||||
.NUM_SLAVES (2)
|
||||
) regport_resp_mux_i (
|
||||
.clk(bus_clk), .reset(bus_rst),
|
||||
.sla_rd_resp({reg_rd_resp_eth_if, reg_rd_resp_io}),
|
||||
.sla_rd_data({reg_rd_data_eth_if, reg_rd_data_io}),
|
||||
.mst_rd_resp(reg_rd_resp), .mst_rd_data(reg_rd_data)
|
||||
);
|
||||
|
||||
|
||||
//---------------------------------------
|
||||
// MGT IO Core
|
||||
//---------------------------------------
|
||||
|
||||
localparam MGT_W = (IS100GBE) ? 512 : 64;
|
||||
localparam MGT_USER_W = $clog2(MGT_W/8)+1;
|
||||
|
||||
// The Clocking for the MGT interfaces comes from the MGT Wrapper
|
||||
// depending on the bus it may change.
|
||||
logic mgt_rst, mgt_clk;
|
||||
AxiStreamIf #(.DATA_WIDTH(MGT_W),.USER_WIDTH(MGT_USER_W))
|
||||
mgt_tx(mgt_clk, mgt_rst);
|
||||
AxiStreamIf #(.DATA_WIDTH(MGT_W),.USER_WIDTH(MGT_USER_W),.TKEEP(0))
|
||||
mgt_rx(mgt_clk, mgt_rst);
|
||||
|
||||
logic mgt_pause_req;
|
||||
logic [3:0] tx_p_lane;
|
||||
logic [3:0] tx_n_lane;
|
||||
|
||||
if (IS10GBE[lane]) begin
|
||||
// Single lane case:
|
||||
assign tx_p[lane] = tx_p_lane[lane];
|
||||
assign tx_n[lane] = tx_n_lane[lane];
|
||||
end else if (IS100GBE[lane] || ISAURORA[lane]) begin
|
||||
// Multi lane case:
|
||||
assign tx_p = tx_p_lane;
|
||||
assign tx_n = tx_n_lane;
|
||||
end
|
||||
|
||||
x4xx_mgt_io_core #(
|
||||
.PROTOCOL (PROTOCOL[lane]),
|
||||
.REG_BASE (REG_BASE_SFP_IO),
|
||||
.REG_DWIDTH (REG_DWIDTH), // Width of the AXI4-Lite data bus (must be 32 or 64)
|
||||
.REG_AWIDTH (REG_AWIDTH_MISC), // Width of the address bus
|
||||
.PORTNUM (PORTNUM),
|
||||
.LANENUM (lane)
|
||||
) x4xx_mgt_io_core_i (
|
||||
// Must reset all channels on quad when QSFP GTX core is reset
|
||||
.areset (areset),
|
||||
|
||||
.mgt_rst (mgt_rst),
|
||||
.mgt_clk (mgt_clk),
|
||||
|
||||
.clk100 (clk100),
|
||||
|
||||
.bus_rst (bus_rst),
|
||||
.bus_clk (bus_clk),
|
||||
|
||||
.refclk_p (refclk_p),
|
||||
.refclk_n (refclk_n),
|
||||
.tx_p (tx_p_lane),
|
||||
.tx_n (tx_n_lane),
|
||||
.rx_p (rx_p),
|
||||
.rx_n (rx_n),
|
||||
|
||||
// Common signals (for single lane instances)
|
||||
.qpll0_reset (qpll0_reset_i[lane]),
|
||||
.qpll0_lock (qpll0_lock),
|
||||
.qpll0_clk (qpll0_clk),
|
||||
.qpll0_refclk (qpll0_refclk),
|
||||
.qpll1_reset (qpll1_reset_i[lane]),
|
||||
.qpll1_lock (qpll1_lock),
|
||||
.qpll1_clk (qpll1_clk),
|
||||
.qpll1_refclk (qpll1_refclk),
|
||||
|
||||
// RegPort
|
||||
.reg_wr_req (reg_wr_req),
|
||||
.reg_wr_addr (reg_wr_addr),
|
||||
.reg_wr_data (reg_wr_data),
|
||||
.reg_rd_req (reg_rd_req),
|
||||
.reg_rd_addr (reg_rd_addr),
|
||||
.reg_rd_resp (reg_rd_resp_io),
|
||||
.reg_rd_data (reg_rd_data_io),
|
||||
// AxiLite
|
||||
.m_axi_mac (m_axi_mac[lane]),
|
||||
// Pause
|
||||
.mgt_pause_req (mgt_pause_req),
|
||||
// Data
|
||||
.mgt_tx (mgt_tx),
|
||||
.mgt_rx (mgt_rx),
|
||||
|
||||
// Misc.
|
||||
.rx_rec_clk_out (rx_rec_clk_out_i[lane]),
|
||||
.port_info (port_info[lane]),
|
||||
.link_up (link_up[lane]),
|
||||
.activity (activity[lane])
|
||||
);
|
||||
|
||||
|
||||
if (IS100GBE[lane] || IS10GBE[lane]) begin : eth_port
|
||||
|
||||
//---------------------------------------
|
||||
// Ethernet IPv4 Interface for CHDR
|
||||
//---------------------------------------
|
||||
|
||||
// Option to use a bigger FIFO for 100GBe.
|
||||
// This is address width so +1 doubles the size +2 quadruples it.
|
||||
localparam CHDR_FIFO_SIZE = (IS100GBE[lane]) ? BYTE_MTU+2 : BYTE_MTU;
|
||||
|
||||
AxiStreamIf #(.DATA_WIDTH(CPU_W), .USER_WIDTH(CPU_USER_W), .TUSER(0))
|
||||
c2e (s_axi.clk, s_axi.rst);
|
||||
AxiStreamIf #(.DATA_WIDTH(CPU_W), .USER_WIDTH(CPU_USER_W), .TUSER(0))
|
||||
e2c (s_axi.clk, s_axi.rst);
|
||||
|
||||
localparam PAUSE_EN = (IS100GBE[lane]) ? 1 : 0;
|
||||
|
||||
// Ethernet interface
|
||||
// (1) routes the packet to CHDR/CPU
|
||||
// (2) implements a wrap back (eth_tx/eth_rx)
|
||||
eth_ipv4_interface #(
|
||||
.PROTOVER (RFNOC_PROTOVER),
|
||||
.CPU_FIFO_SIZE (BYTE_MTU),
|
||||
.CHDR_FIFO_SIZE (CHDR_FIFO_SIZE),
|
||||
.NODE_INST (NODE_INST+lane),
|
||||
.BASE (REG_BASE_ETH_SWITCH),
|
||||
.PREAMBLE_BYTES (0),
|
||||
.ADD_SOF (0),
|
||||
.SYNC (0), // c2e/e2c don't use the same clock as eth_tx/eth_rx
|
||||
.PAUSE_EN (PAUSE_EN),
|
||||
.ENET_W (MGT_W),
|
||||
.CPU_W (CPU_W),
|
||||
.CHDR_W (CHDR_W),
|
||||
.NET_CHDR_W (NET_CHDR_W)
|
||||
) eth_ipv4_interface_i (
|
||||
.bus_clk (bus_clk),
|
||||
.bus_rst (bus_rst),
|
||||
.device_id (device_id),
|
||||
.reg_wr_req (reg_wr_req),
|
||||
.reg_wr_addr (reg_wr_addr),
|
||||
.reg_wr_data (reg_wr_data),
|
||||
.reg_rd_req (reg_rd_req),
|
||||
.reg_rd_addr (reg_rd_addr),
|
||||
.reg_rd_resp (reg_rd_resp_eth_if),
|
||||
.reg_rd_data (reg_rd_data_eth_if),
|
||||
.eth_pause_req (mgt_pause_req),
|
||||
.eth_tx (mgt_tx),
|
||||
.eth_rx (mgt_rx),
|
||||
.e2v (e2v[lane]),
|
||||
.v2e (v2e[lane]),
|
||||
.e2c (e2c),
|
||||
.c2e (c2e),
|
||||
.my_udp_chdr_port (/* unused */),
|
||||
.my_ip (/* unused */),
|
||||
.my_mac (/* unused */)
|
||||
);
|
||||
|
||||
axi_eth_dma axi_eth_dma_i (
|
||||
.c2e (c2e),
|
||||
.e2c (e2c),
|
||||
.s_axi_eth_dma (m_axi_dma[lane]),
|
||||
.axi_hp (axi_hp_dma[lane]),
|
||||
.eth_tx_irq (eth_tx_irq[lane]),
|
||||
.eth_rx_irq (eth_rx_irq[lane])
|
||||
);
|
||||
|
||||
end : eth_port else begin : not_eth
|
||||
|
||||
//---------------------------------------
|
||||
// Terminate DMA for Unused Ethernet
|
||||
//---------------------------------------
|
||||
|
||||
// Set unused ETH_DMA ports to default value
|
||||
always_comb begin
|
||||
m_axi_dma[lane].drive_read_resp(.resp(SLVERR),.data(0));
|
||||
m_axi_dma[lane].drive_write_resp(.resp(SLVERR));
|
||||
m_axi_dma[lane].arready = 1'b1;
|
||||
m_axi_dma[lane].awready = 1'b1;
|
||||
m_axi_dma[lane].wready = 1'b1;
|
||||
|
||||
axi_hp_dma[lane].drive_read_idle();
|
||||
axi_hp_dma[lane].drive_aw_idle();
|
||||
axi_hp_dma[lane].drive_w_idle();
|
||||
axi_hp_dma[lane].bready = 1'b0;
|
||||
axi_hp_dma[lane].rready = 1'b0;
|
||||
|
||||
mgt_pause_req = 0'b0;
|
||||
|
||||
eth_rx_irq[lane] = 1'b0;
|
||||
eth_tx_irq[lane] = 1'b0;
|
||||
|
||||
reg_rd_resp_eth_if = 1'b0;
|
||||
reg_rd_data_eth_if = 'h0;
|
||||
end
|
||||
|
||||
if (ISAURORA[lane]) begin : aurora_port
|
||||
|
||||
//---------------------------------------
|
||||
// Aurora
|
||||
//---------------------------------------
|
||||
|
||||
Aurora_not_yet_supported();
|
||||
|
||||
// if MGT_W and CHDR_W mismatch figure out what to do
|
||||
always_comb begin
|
||||
e2v[lane].tdata = mgt_rx.tdata;
|
||||
e2v[lane].tuser = 'b0;
|
||||
e2v[lane].tkeep = 'b1;
|
||||
e2v[lane].tlast = mgt_rx.tlast;
|
||||
e2v[lane].tvalid = mgt_rx.tvalid;
|
||||
mgt_rx.tready = e2v[lane].tready;
|
||||
|
||||
mgt_tx.tdata = v2e[lane].tdata;
|
||||
mgt_tx.tuser = 'b0;
|
||||
mgt_tx.tkeep = 'b1;
|
||||
mgt_tx.tlast = v2e[lane].tlast;
|
||||
mgt_tx.tvalid = v2e[lane].tvalid;
|
||||
v2e[lane].tready = mgt_tx.tready;
|
||||
end
|
||||
|
||||
end else begin : inactive_port
|
||||
|
||||
//---------------------------------------
|
||||
// Disabled Port
|
||||
//---------------------------------------
|
||||
|
||||
always_comb begin
|
||||
e2v[lane].tdata = 'b0;
|
||||
e2v[lane].tuser = 'b0;
|
||||
e2v[lane].tkeep = 'b1;
|
||||
e2v[lane].tlast = 1'b0;
|
||||
e2v[lane].tvalid = 1'b0;
|
||||
mgt_rx.tready = 1'b1;
|
||||
|
||||
mgt_tx.tdata = 'b0;
|
||||
mgt_tx.tuser = 'b0;
|
||||
mgt_tx.tkeep = 'b1;
|
||||
mgt_tx.tlast = 1'b0;
|
||||
mgt_tx.tvalid = 1'b0;
|
||||
v2e[lane].tready = 1'b1;
|
||||
end
|
||||
|
||||
end : inactive_port
|
||||
end : not_eth
|
||||
end : lane_loop
|
||||
end : mgt_lanes
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
@@ -17,7 +17,7 @@
|
||||
// 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
|
||||
// NODE_INST : The node instance number 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 on Ethernet interface
|
||||
|
||||
Reference in New Issue
Block a user