mirror of
https://github.com/fpganinja/taxi.git
synced 2025-12-09 17:08:38 -08:00
example/KCU105: Add support for 10GBASE-R on KCU105
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -12,12 +12,14 @@ The design places looped-back MACs on the BASE-T port and SFP+ cages, as well as
|
|||||||
* Looped-back MAC via SGMII via Xilinx PCS/PMA core and LVDS IOSERDES
|
* Looped-back MAC via SGMII via Xilinx PCS/PMA core and LVDS IOSERDES
|
||||||
* SFP+ cages
|
* SFP+ cages
|
||||||
* Looped-back 1000BASE-X via Xilinx PCS/PMA core and GTH transceiver
|
* Looped-back 1000BASE-X via Xilinx PCS/PMA core and GTH transceiver
|
||||||
|
* Looped-back 10GBASE-R MAC via GTH transceiver
|
||||||
|
|
||||||
## Board details
|
## Board details
|
||||||
|
|
||||||
* FPGA: xcku040-ffva1156-2-e
|
* FPGA: xcku040-ffva1156-2-e
|
||||||
* 1000BASE-T PHY: Marvell 88E1111 via SGMII
|
* 1000BASE-T PHY: Marvell 88E1111 via SGMII
|
||||||
* 1000BASE-X PHY: Xilinx PCS/PMA core via GTH transceiver
|
* 1000BASE-X PHY: Xilinx PCS/PMA core via GTH transceiver
|
||||||
|
* 10GBASE-R PHY: Soft PCS with GTH transceiver
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
|
|||||||
@@ -155,14 +155,14 @@ set_input_delay 0 [get_ports {phy_int_n}]
|
|||||||
#set_input_delay 0 [get_ports {phy_mdio}]
|
#set_input_delay 0 [get_ports {phy_mdio}]
|
||||||
|
|
||||||
# SFP+ interface
|
# SFP+ interface
|
||||||
set_property -dict {LOC T2 } [get_ports {sfp0_rx_p}] ;# MGTYRXP2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC T2 } [get_ports {sfp_rx_p[0]}] ;# MGTYRXP2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC T1 } [get_ports {sfp0_rx_n}] ;# MGTYRXN2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC T1 } [get_ports {sfp_rx_n[0]}] ;# MGTYRXN2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC U4 } [get_ports {sfp0_tx_p}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC U4 } [get_ports {sfp_tx_p[0]}] ;# MGTYTXP2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC U3 } [get_ports {sfp0_tx_n}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC U3 } [get_ports {sfp_tx_n[0]}] ;# MGTYTXN2_226 GTYE3_CHANNEL_X0Y10 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC V2 } [get_ports {sfp1_rx_p}] ;# MGTYRXP1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC V2 } [get_ports {sfp_rx_p[1]}] ;# MGTYRXP1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC V1 } [get_ports {sfp1_rx_n}] ;# MGTYRXN1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC V1 } [get_ports {sfp_rx_n[1]}] ;# MGTYRXN1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC W4 } [get_ports {sfp1_tx_p}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC W4 } [get_ports {sfp_tx_p[1]}] ;# MGTYTXP1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC W3 } [get_ports {sfp1_tx_n}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
set_property -dict {LOC W3 } [get_ports {sfp_tx_n[1]}] ;# MGTYTXN1_226 GTYE3_CHANNEL_X0Y9 / GTYE3_COMMON_X0Y2
|
||||||
set_property -dict {LOC P6 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK0P_227 from U32 Si570 via U104 Si53340
|
set_property -dict {LOC P6 } [get_ports sfp_mgt_refclk_0_p] ;# MGTREFCLK0P_227 from U32 Si570 via U104 Si53340
|
||||||
set_property -dict {LOC P5 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK0N_227 from U32 Si570 via U104 Si53340
|
set_property -dict {LOC P5 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK0N_227 from U32 Si570 via U104 Si53340
|
||||||
#set_property -dict {LOC M6 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_227 from U57 Si5328B
|
#set_property -dict {LOC M6 } [get_ports sfp_mgt_refclk_1_p] ;# MGTREFCLK1P_227 from U57 Si5328B
|
||||||
@@ -170,8 +170,8 @@ set_property -dict {LOC P5 } [get_ports sfp_mgt_refclk_0_n] ;# MGTREFCLK0N_227
|
|||||||
#set_property -dict {LOC AG11 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to U57 CKIN1 SI5328
|
#set_property -dict {LOC AG11 IOSTANDARD LVDS} [get_ports sfp_recclk_p] ;# to U57 CKIN1 SI5328
|
||||||
#set_property -dict {LOC AH11 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to U57 CKIN1 SI5328
|
#set_property -dict {LOC AH11 IOSTANDARD LVDS} [get_ports sfp_recclk_n] ;# to U57 CKIN1 SI5328
|
||||||
|
|
||||||
set_property -dict {LOC AL8 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {sfp0_tx_disable_b}]
|
set_property -dict {LOC AL8 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {sfp_tx_disable_b[0]}]
|
||||||
set_property -dict {LOC D28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {sfp1_tx_disable_b}]
|
set_property -dict {LOC D28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {sfp_tx_disable_b[1]}]
|
||||||
|
|
||||||
# 156.25 MHz MGT reference clock
|
# 156.25 MHz MGT reference clock
|
||||||
create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p]
|
create_clock -period 6.400 -name sfp_mgt_refclk_0 [get_ports sfp_mgt_refclk_0_p]
|
||||||
|
|||||||
48
example/KCU105/fpga/fpga_10g/Makefile
Normal file
48
example/KCU105/fpga/fpga_10g/Makefile
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# Copyright (c) 2025 FPGA Ninja, LLC
|
||||||
|
#
|
||||||
|
# Authors:
|
||||||
|
# - Alex Forencich
|
||||||
|
#
|
||||||
|
|
||||||
|
# FPGA settings
|
||||||
|
FPGA_PART = xcku040-ffva1156-2-e
|
||||||
|
FPGA_TOP = fpga
|
||||||
|
FPGA_ARCH = kintexu
|
||||||
|
|
||||||
|
# Files for synthesis
|
||||||
|
SYN_FILES = ../rtl/fpga.sv
|
||||||
|
SYN_FILES += ../rtl/fpga_core.sv
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/eth/taxi_eth_mac_1g_fifo.f
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/eth/us/taxi_eth_mac_25g_us.f
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/lss/taxi_uart.f
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/sync/taxi_sync_reset.sv
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/sync/taxi_sync_signal.sv
|
||||||
|
SYN_FILES += ../lib/taxi/rtl/io/taxi_debounce_switch.sv
|
||||||
|
|
||||||
|
# XDC files
|
||||||
|
XDC_FILES = ../fpga.xdc
|
||||||
|
XDC_FILES += ../lib/taxi/syn/vivado/taxi_eth_mac_fifo.tcl
|
||||||
|
XDC_FILES += ../lib/taxi/syn/vivado/taxi_axis_async_fifo.tcl
|
||||||
|
XDC_FILES += ../lib/taxi/syn/vivado/taxi_sync_reset.tcl
|
||||||
|
|
||||||
|
# IP
|
||||||
|
IP_TCL_FILES = ../ip/sgmii_pcs_pma_0.tcl
|
||||||
|
IP_TCL_FILES += ../lib/taxi/rtl/eth/us/taxi_eth_mac_25g_us_gth_10g_156.tcl
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
CONFIG_TCL_FILES = ./config.tcl
|
||||||
|
|
||||||
|
include ../common/vivado.mk
|
||||||
|
|
||||||
|
program: $(PROJECT).bit
|
||||||
|
echo "open_hw_manager" > program.tcl
|
||||||
|
echo "connect_hw_server" >> program.tcl
|
||||||
|
echo "open_hw_target" >> program.tcl
|
||||||
|
echo "current_hw_device [lindex [get_hw_devices] 0]" >> program.tcl
|
||||||
|
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> program.tcl
|
||||||
|
echo "set_property PROGRAM.FILE {$(PROJECT).bit} [current_hw_device]" >> program.tcl
|
||||||
|
echo "program_hw_devices [current_hw_device]" >> program.tcl
|
||||||
|
echo "exit" >> program.tcl
|
||||||
|
vivado -nojournal -nolog -mode batch -source program.tcl
|
||||||
@@ -32,7 +32,7 @@ IP_TCL_FILES += ../ip/basex_pcs_pma_0.tcl
|
|||||||
IP_TCL_FILES += ../ip/basex_pcs_pma_1.tcl
|
IP_TCL_FILES += ../ip/basex_pcs_pma_1.tcl
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
# CONFIG_TCL_FILES = ./config.tcl
|
CONFIG_TCL_FILES = ./config.tcl
|
||||||
|
|
||||||
include ../common/vivado.mk
|
include ../common/vivado.mk
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,17 @@ Authors:
|
|||||||
/*
|
/*
|
||||||
* FPGA top-level module
|
* FPGA top-level module
|
||||||
*/
|
*/
|
||||||
module fpga
|
module fpga #
|
||||||
|
(
|
||||||
|
// simulation (set to avoid vendor primitives)
|
||||||
|
parameter logic SIM = 1'b0,
|
||||||
|
// vendor ("GENERIC", "XILINX", "ALTERA")
|
||||||
|
parameter string VENDOR = "XILINX",
|
||||||
|
// device family
|
||||||
|
parameter string FAMILY = "kintexu",
|
||||||
|
// SFP rate selection (0 for 1G, 1 for 10G)
|
||||||
|
parameter logic SFP_RATE = 1'b1
|
||||||
|
)
|
||||||
(
|
(
|
||||||
/*
|
/*
|
||||||
* Clock: 125MHz LVDS
|
* Clock: 125MHz LVDS
|
||||||
@@ -59,19 +69,14 @@ module fpga
|
|||||||
/*
|
/*
|
||||||
* Ethernet: SFP+
|
* Ethernet: SFP+
|
||||||
*/
|
*/
|
||||||
input wire logic sfp0_rx_p,
|
input wire logic [1:0] sfp_rx_p,
|
||||||
input wire logic sfp0_rx_n,
|
input wire logic [1:0] sfp_rx_n,
|
||||||
output wire logic sfp0_tx_p,
|
output wire logic [1:0] sfp_tx_p,
|
||||||
output wire logic sfp0_tx_n,
|
output wire logic [1:0] sfp_tx_n,
|
||||||
input wire logic sfp1_rx_p,
|
|
||||||
input wire logic sfp1_rx_n,
|
|
||||||
output wire logic sfp1_tx_p,
|
|
||||||
output wire logic sfp1_tx_n,
|
|
||||||
input wire logic sfp_mgt_refclk_0_p,
|
input wire logic sfp_mgt_refclk_0_p,
|
||||||
input wire logic sfp_mgt_refclk_0_n,
|
input wire logic sfp_mgt_refclk_0_n,
|
||||||
|
|
||||||
output wire logic sfp0_tx_disable_b,
|
output wire logic [1:0] sfp_tx_disable_b
|
||||||
output wire logic sfp1_tx_disable_b
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clock and reset
|
// Clock and reset
|
||||||
@@ -346,17 +351,37 @@ eth_pcspma (
|
|||||||
.signal_detect (1'b1)
|
.signal_detect (1'b1)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 1000BASE-X SFP
|
// SFP+
|
||||||
|
wire [1:0] sfp_tx_p_int;
|
||||||
|
wire [1:0] sfp_tx_n_int;
|
||||||
|
|
||||||
wire sfp0_gmii_clk_int;
|
wire sfp0_gmii_clk_int;
|
||||||
wire sfp0_gmii_rst_int;
|
wire sfp0_gmii_rst_int;
|
||||||
wire sfp0_gmii_clk_en_int;
|
wire sfp0_gmii_clk_en_int;
|
||||||
wire [7:0] sfp0_gmii_txd_int;
|
wire [7:0] sfp0_gmii_txd_int;
|
||||||
wire sfp0_gmii_tx_en_int;
|
wire sfp0_gmii_tx_en_int = 1'b1;
|
||||||
wire sfp0_gmii_tx_er_int;
|
wire sfp0_gmii_tx_er_int;
|
||||||
wire [7:0] sfp0_gmii_rxd_int;
|
wire [7:0] sfp0_gmii_rxd_int;
|
||||||
wire sfp0_gmii_rx_dv_int;
|
wire sfp0_gmii_rx_dv_int;
|
||||||
wire sfp0_gmii_rx_er_int;
|
wire sfp0_gmii_rx_er_int;
|
||||||
|
|
||||||
|
wire [15:0] sfp0_status_vect;
|
||||||
|
|
||||||
|
wire sfp1_gmii_clk_int;
|
||||||
|
wire sfp1_gmii_rst_int;
|
||||||
|
wire sfp1_gmii_clk_en_int;
|
||||||
|
wire [7:0] sfp1_gmii_txd_int;
|
||||||
|
wire sfp1_gmii_tx_en_int = 1'b1;
|
||||||
|
wire sfp1_gmii_tx_er_int;
|
||||||
|
wire [7:0] sfp1_gmii_rxd_int;
|
||||||
|
wire sfp1_gmii_rx_dv_int;
|
||||||
|
wire sfp1_gmii_rx_er_int;
|
||||||
|
|
||||||
|
wire [15:0] sfp1_status_vect;
|
||||||
|
|
||||||
|
if (SFP_RATE == 0) begin : sfp_phy
|
||||||
|
// 1000BASE-X
|
||||||
|
|
||||||
wire sfp0_gmii_gtrefclk;
|
wire sfp0_gmii_gtrefclk;
|
||||||
wire sfp0_gmii_txuserclk;
|
wire sfp0_gmii_txuserclk;
|
||||||
wire sfp0_gmii_txuserclk2;
|
wire sfp0_gmii_txuserclk2;
|
||||||
@@ -377,8 +402,6 @@ sync_reset_sfp0_inst (
|
|||||||
.out(sfp0_gmii_rst_int)
|
.out(sfp0_gmii_rst_int)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [15:0] sfp0_status_vect;
|
|
||||||
|
|
||||||
wire sfp0_status_link_status = sfp0_status_vect[0];
|
wire sfp0_status_link_status = sfp0_status_vect[0];
|
||||||
wire sfp0_status_link_synchronization = sfp0_status_vect[1];
|
wire sfp0_status_link_synchronization = sfp0_status_vect[1];
|
||||||
wire sfp0_status_rudi_c = sfp0_status_vect[2];
|
wire sfp0_status_rudi_c = sfp0_status_vect[2];
|
||||||
@@ -406,10 +429,10 @@ sfp0_pcspma (
|
|||||||
.gtrefclk_p(sfp_mgt_refclk_0_p),
|
.gtrefclk_p(sfp_mgt_refclk_0_p),
|
||||||
.gtrefclk_n(sfp_mgt_refclk_0_n),
|
.gtrefclk_n(sfp_mgt_refclk_0_n),
|
||||||
.gtrefclk_out(sfp0_gmii_gtrefclk),
|
.gtrefclk_out(sfp0_gmii_gtrefclk),
|
||||||
.txn(sfp0_tx_n),
|
.txn(sfp_tx_n[0]),
|
||||||
.txp(sfp0_tx_p),
|
.txp(sfp_tx_p[0]),
|
||||||
.rxn(sfp0_rx_n),
|
.rxn(sfp_rx_n[0]),
|
||||||
.rxp(sfp0_rx_p),
|
.rxp(sfp_rx_p[0]),
|
||||||
.independent_clock_bufg(clk_62mhz_int),
|
.independent_clock_bufg(clk_62mhz_int),
|
||||||
.userclk_out(sfp0_gmii_txuserclk),
|
.userclk_out(sfp0_gmii_txuserclk),
|
||||||
.userclk2_out(sfp0_gmii_txuserclk2),
|
.userclk2_out(sfp0_gmii_txuserclk2),
|
||||||
@@ -432,18 +455,6 @@ sfp0_pcspma (
|
|||||||
.signal_detect(1'b1)
|
.signal_detect(1'b1)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign sfp0_gmii_clk_en_int = 1'b1;
|
|
||||||
|
|
||||||
wire sfp1_gmii_clk_int;
|
|
||||||
wire sfp1_gmii_rst_int;
|
|
||||||
wire sfp1_gmii_clk_en_int;
|
|
||||||
wire [7:0] sfp1_gmii_txd_int;
|
|
||||||
wire sfp1_gmii_tx_en_int;
|
|
||||||
wire sfp1_gmii_tx_er_int;
|
|
||||||
wire [7:0] sfp1_gmii_rxd_int;
|
|
||||||
wire sfp1_gmii_rx_dv_int;
|
|
||||||
wire sfp1_gmii_rx_er_int;
|
|
||||||
|
|
||||||
wire sfp1_gmii_txuserclk2 = sfp0_gmii_txuserclk2;
|
wire sfp1_gmii_txuserclk2 = sfp0_gmii_txuserclk2;
|
||||||
wire sfp1_gmii_resetdone;
|
wire sfp1_gmii_resetdone;
|
||||||
|
|
||||||
@@ -458,8 +469,6 @@ sync_reset_sfp1_inst (
|
|||||||
.out(sfp1_gmii_rst_int)
|
.out(sfp1_gmii_rst_int)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [15:0] sfp1_status_vect;
|
|
||||||
|
|
||||||
wire sfp1_status_link_status = sfp1_status_vect[0];
|
wire sfp1_status_link_status = sfp1_status_vect[0];
|
||||||
wire sfp1_status_link_synchronization = sfp1_status_vect[1];
|
wire sfp1_status_link_synchronization = sfp1_status_vect[1];
|
||||||
wire sfp1_status_rudi_c = sfp1_status_vect[2];
|
wire sfp1_status_rudi_c = sfp1_status_vect[2];
|
||||||
@@ -485,10 +494,10 @@ assign sfp1_config_vect[0] = 1'b0; // unidirectional enable
|
|||||||
basex_pcs_pma_1
|
basex_pcs_pma_1
|
||||||
sfp1_pcspma (
|
sfp1_pcspma (
|
||||||
.gtrefclk(sfp0_gmii_gtrefclk),
|
.gtrefclk(sfp0_gmii_gtrefclk),
|
||||||
.txn(sfp1_tx_n),
|
.txn(sfp_tx_n[1]),
|
||||||
.txp(sfp1_tx_p),
|
.txp(sfp_tx_p[1]),
|
||||||
.rxn(sfp1_rx_n),
|
.rxn(sfp_rx_n[1]),
|
||||||
.rxp(sfp1_rx_p),
|
.rxp(sfp_rx_p[1]),
|
||||||
.independent_clock_bufg(clk_62mhz_int),
|
.independent_clock_bufg(clk_62mhz_int),
|
||||||
.txoutclk(),
|
.txoutclk(),
|
||||||
.gtpowergood(),
|
.gtpowergood(),
|
||||||
@@ -515,7 +524,13 @@ sfp1_pcspma (
|
|||||||
.signal_detect(1'b1)
|
.signal_detect(1'b1)
|
||||||
);
|
);
|
||||||
|
|
||||||
assign sfp1_gmii_clk_en_int = 1'b1;
|
end else begin
|
||||||
|
// 10GBASE-R
|
||||||
|
|
||||||
|
assign sfp_tx_p = sfp_tx_p_int;
|
||||||
|
assign sfp_tx_n = sfp_tx_n_int;
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
// SGMII interface debug:
|
// SGMII interface debug:
|
||||||
// SW12:1 (sw[3]) off for payload byte, on for status vector
|
// SW12:1 (sw[3]) off for payload byte, on for status vector
|
||||||
@@ -525,7 +540,12 @@ assign sfp1_gmii_clk_en_int = 1'b1;
|
|||||||
wire [15:0] sel_sv = sw[2] ? (sw[1] ? sfp1_status_vect : sfp0_status_vect) : sgmii_status_vect;
|
wire [15:0] sel_sv = sw[2] ? (sw[1] ? sfp1_status_vect : sfp0_status_vect) : sgmii_status_vect;
|
||||||
assign led = sw[3] ? (sw[0] ? sel_sv[15:8] : sel_sv[7:0]) : led_int;
|
assign led = sw[3] ? (sw[0] ? sel_sv[15:8] : sel_sv[7:0]) : led_int;
|
||||||
|
|
||||||
fpga_core
|
fpga_core #(
|
||||||
|
.SIM(SIM),
|
||||||
|
.VENDOR(VENDOR),
|
||||||
|
.FAMILY(FAMILY),
|
||||||
|
.SFP_RATE(SFP_RATE)
|
||||||
|
)
|
||||||
core_inst (
|
core_inst (
|
||||||
/*
|
/*
|
||||||
* Clock: 125MHz
|
* Clock: 125MHz
|
||||||
@@ -569,8 +589,15 @@ core_inst (
|
|||||||
.phy_int_n(phy_int_n),
|
.phy_int_n(phy_int_n),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ethernet: 1000BASE-X SFP
|
* Ethernet: SFP+
|
||||||
*/
|
*/
|
||||||
|
.sfp_rx_p(sfp_rx_p),
|
||||||
|
.sfp_rx_n(sfp_rx_n),
|
||||||
|
.sfp_tx_p(sfp_tx_p_int),
|
||||||
|
.sfp_tx_n(sfp_tx_n_int),
|
||||||
|
.sfp_mgt_refclk_0_p(sfp_mgt_refclk_0_p),
|
||||||
|
.sfp_mgt_refclk_0_n(sfp_mgt_refclk_0_n),
|
||||||
|
|
||||||
.sfp0_gmii_clk(sfp0_gmii_clk_int),
|
.sfp0_gmii_clk(sfp0_gmii_clk_int),
|
||||||
.sfp0_gmii_rst(sfp0_gmii_rst_int),
|
.sfp0_gmii_rst(sfp0_gmii_rst_int),
|
||||||
.sfp0_gmii_clk_en(sfp0_gmii_clk_en_int),
|
.sfp0_gmii_clk_en(sfp0_gmii_clk_en_int),
|
||||||
@@ -580,7 +607,6 @@ core_inst (
|
|||||||
.sfp0_gmii_txd(sfp0_gmii_txd_int),
|
.sfp0_gmii_txd(sfp0_gmii_txd_int),
|
||||||
.sfp0_gmii_tx_en(sfp0_gmii_tx_en_int),
|
.sfp0_gmii_tx_en(sfp0_gmii_tx_en_int),
|
||||||
.sfp0_gmii_tx_er(sfp0_gmii_tx_er_int),
|
.sfp0_gmii_tx_er(sfp0_gmii_tx_er_int),
|
||||||
.sfp0_tx_disable_b(sfp0_tx_disable_b),
|
|
||||||
|
|
||||||
.sfp1_gmii_clk(sfp1_gmii_clk_int),
|
.sfp1_gmii_clk(sfp1_gmii_clk_int),
|
||||||
.sfp1_gmii_rst(sfp1_gmii_rst_int),
|
.sfp1_gmii_rst(sfp1_gmii_rst_int),
|
||||||
@@ -591,7 +617,8 @@ core_inst (
|
|||||||
.sfp1_gmii_txd(sfp1_gmii_txd_int),
|
.sfp1_gmii_txd(sfp1_gmii_txd_int),
|
||||||
.sfp1_gmii_tx_en(sfp1_gmii_tx_en_int),
|
.sfp1_gmii_tx_en(sfp1_gmii_tx_en_int),
|
||||||
.sfp1_gmii_tx_er(sfp1_gmii_tx_er_int),
|
.sfp1_gmii_tx_er(sfp1_gmii_tx_er_int),
|
||||||
.sfp1_tx_disable_b(sfp1_tx_disable_b)
|
|
||||||
|
.sfp_tx_disable_b(sfp_tx_disable_b)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|||||||
@@ -15,7 +15,17 @@ Authors:
|
|||||||
/*
|
/*
|
||||||
* FPGA core logic
|
* FPGA core logic
|
||||||
*/
|
*/
|
||||||
module fpga_core
|
module fpga_core #
|
||||||
|
(
|
||||||
|
// simulation (set to avoid vendor primitives)
|
||||||
|
parameter logic SIM = 1'b0,
|
||||||
|
// vendor ("GENERIC", "XILINX", "ALTERA")
|
||||||
|
parameter string VENDOR = "XILINX",
|
||||||
|
// device family
|
||||||
|
parameter string FAMILY = "kintexu",
|
||||||
|
// SFP rate selection (0 for 1G, 1 for 10G)
|
||||||
|
parameter logic SFP_RATE = 1'b1
|
||||||
|
)
|
||||||
(
|
(
|
||||||
/*
|
/*
|
||||||
* Clock: 125MHz
|
* Clock: 125MHz
|
||||||
@@ -59,8 +69,16 @@ module fpga_core
|
|||||||
input wire logic phy_int_n,
|
input wire logic phy_int_n,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ethernet: 1000BASE-X SFP
|
* Ethernet: SFP+
|
||||||
*/
|
*/
|
||||||
|
input wire logic [1:0] sfp_rx_p,
|
||||||
|
input wire logic [1:0] sfp_rx_n,
|
||||||
|
output wire logic [1:0] sfp_tx_p,
|
||||||
|
output wire logic [1:0] sfp_tx_n,
|
||||||
|
input wire logic sfp_mgt_refclk_0_p,
|
||||||
|
input wire logic sfp_mgt_refclk_0_n,
|
||||||
|
|
||||||
|
|
||||||
input wire logic sfp0_gmii_clk,
|
input wire logic sfp0_gmii_clk,
|
||||||
input wire logic sfp0_gmii_rst,
|
input wire logic sfp0_gmii_rst,
|
||||||
input wire logic sfp0_gmii_clk_en,
|
input wire logic sfp0_gmii_clk_en,
|
||||||
@@ -70,7 +88,6 @@ module fpga_core
|
|||||||
output wire logic [7:0] sfp0_gmii_txd,
|
output wire logic [7:0] sfp0_gmii_txd,
|
||||||
output wire logic sfp0_gmii_tx_en,
|
output wire logic sfp0_gmii_tx_en,
|
||||||
output wire logic sfp0_gmii_tx_er,
|
output wire logic sfp0_gmii_tx_er,
|
||||||
output wire logic sfp0_tx_disable_b,
|
|
||||||
|
|
||||||
input wire logic sfp1_gmii_clk,
|
input wire logic sfp1_gmii_clk,
|
||||||
input wire logic sfp1_gmii_rst,
|
input wire logic sfp1_gmii_rst,
|
||||||
@@ -81,7 +98,8 @@ module fpga_core
|
|||||||
output wire logic [7:0] sfp1_gmii_txd,
|
output wire logic [7:0] sfp1_gmii_txd,
|
||||||
output wire logic sfp1_gmii_tx_en,
|
output wire logic sfp1_gmii_tx_en,
|
||||||
output wire logic sfp1_gmii_tx_er,
|
output wire logic sfp1_gmii_tx_er,
|
||||||
output wire logic sfp1_tx_disable_b
|
|
||||||
|
output wire logic [1:0] sfp_tx_disable_b
|
||||||
);
|
);
|
||||||
|
|
||||||
assign led = sw;
|
assign led = sw;
|
||||||
@@ -199,8 +217,9 @@ eth_mac_inst (
|
|||||||
);
|
);
|
||||||
|
|
||||||
// SFP+
|
// SFP+
|
||||||
assign sfp0_tx_disable_b = 1'b1;
|
assign sfp_tx_disable_b = '1;
|
||||||
assign sfp1_tx_disable_b = 1'b1;
|
|
||||||
|
if (SFP_RATE == 0) begin : sfp_mac
|
||||||
|
|
||||||
taxi_axis_if #(.DATA_W(8), .ID_W(8)) axis_sfp0_eth();
|
taxi_axis_if #(.DATA_W(8), .ID_W(8)) axis_sfp0_eth();
|
||||||
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp0_tx_cpl();
|
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp0_tx_cpl();
|
||||||
@@ -340,6 +359,293 @@ sfp1_eth_mac_inst (
|
|||||||
.cfg_rx_enable(1'b1)
|
.cfg_rx_enable(1'b1)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
end else begin : sfp_mac
|
||||||
|
|
||||||
|
wire [1:0] sfp_tx_clk;
|
||||||
|
wire [1:0] sfp_tx_rst;
|
||||||
|
wire [1:0] sfp_rx_clk;
|
||||||
|
wire [1:0] sfp_rx_rst;
|
||||||
|
|
||||||
|
wire [1:0] sfp_rx_status;
|
||||||
|
|
||||||
|
wire sfp_gtpowergood;
|
||||||
|
|
||||||
|
wire sfp_mgt_refclk_0;
|
||||||
|
wire sfp_mgt_refclk_0_int;
|
||||||
|
wire sfp_mgt_refclk_0_bufg;
|
||||||
|
|
||||||
|
wire sfp_rst;
|
||||||
|
|
||||||
|
taxi_axis_if #(.DATA_W(64), .ID_W(8)) axis_sfp_tx[1:0]();
|
||||||
|
taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[1:0]();
|
||||||
|
taxi_axis_if #(.DATA_W(64), .ID_W(8)) axis_sfp_rx[1:0]();
|
||||||
|
|
||||||
|
if (SIM) begin
|
||||||
|
|
||||||
|
assign sfp_gtpowergood = 1'b1;
|
||||||
|
|
||||||
|
assign sfp_mgt_refclk_0 = sfp_mgt_refclk_0_p;
|
||||||
|
assign sfp_mgt_refclk_0_int = sfp_mgt_refclk_0_p;
|
||||||
|
assign sfp_mgt_refclk_0_bufg = sfp_mgt_refclk_0_int;
|
||||||
|
|
||||||
|
end else begin
|
||||||
|
|
||||||
|
IBUFDS_GTE3 ibufds_gte3_sfp_mgt_refclk_0_inst (
|
||||||
|
.I (sfp_mgt_refclk_0_p),
|
||||||
|
.IB (sfp_mgt_refclk_0_n),
|
||||||
|
.CEB (1'b0),
|
||||||
|
.O (sfp_mgt_refclk_0),
|
||||||
|
.ODIV2 (sfp_mgt_refclk_0_int)
|
||||||
|
);
|
||||||
|
|
||||||
|
BUFG_GT bufg_gt_sfp_mgt_refclk_0_inst (
|
||||||
|
.CE (sfp_gtpowergood),
|
||||||
|
.CEMASK (1'b1),
|
||||||
|
.CLR (1'b0),
|
||||||
|
.CLRMASK (1'b1),
|
||||||
|
.DIV (3'd0),
|
||||||
|
.I (sfp_mgt_refclk_0_int),
|
||||||
|
.O (sfp_mgt_refclk_0_bufg)
|
||||||
|
);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
taxi_sync_reset #(
|
||||||
|
.N(4)
|
||||||
|
)
|
||||||
|
sfp_sync_reset_inst (
|
||||||
|
.clk(sfp_mgt_refclk_0_bufg),
|
||||||
|
.rst(rst),
|
||||||
|
.out(sfp_rst)
|
||||||
|
);
|
||||||
|
|
||||||
|
taxi_eth_mac_25g_us #(
|
||||||
|
.SIM(SIM),
|
||||||
|
.VENDOR(VENDOR),
|
||||||
|
.FAMILY(FAMILY),
|
||||||
|
|
||||||
|
.CNT(2),
|
||||||
|
|
||||||
|
// GT type
|
||||||
|
.GT_TYPE("GTH"),
|
||||||
|
|
||||||
|
// PHY parameters
|
||||||
|
.PADDING_EN(1'b1),
|
||||||
|
.DIC_EN(1'b1),
|
||||||
|
.MIN_FRAME_LEN(64),
|
||||||
|
.PTP_TS_EN(1'b0),
|
||||||
|
.PTP_TS_FMT_TOD(1'b1),
|
||||||
|
.PTP_TS_W(96),
|
||||||
|
.PRBS31_EN(1'b0),
|
||||||
|
.TX_SERDES_PIPELINE(1),
|
||||||
|
.RX_SERDES_PIPELINE(1),
|
||||||
|
.COUNT_125US(125000/6.4)
|
||||||
|
)
|
||||||
|
sfp_mac_inst (
|
||||||
|
.xcvr_ctrl_clk(clk),
|
||||||
|
.xcvr_ctrl_rst(sfp_rst),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Common
|
||||||
|
*/
|
||||||
|
.xcvr_gtpowergood_out(sfp_gtpowergood),
|
||||||
|
.xcvr_gtrefclk00_in(sfp_mgt_refclk_0),
|
||||||
|
.xcvr_qpll0lock_out(),
|
||||||
|
.xcvr_qpll0clk_out(),
|
||||||
|
.xcvr_qpll0refclk_out(),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serial data
|
||||||
|
*/
|
||||||
|
.xcvr_txp(sfp_tx_p),
|
||||||
|
.xcvr_txn(sfp_tx_n),
|
||||||
|
.xcvr_rxp(sfp_rx_p),
|
||||||
|
.xcvr_rxn(sfp_rx_n),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAC clocks
|
||||||
|
*/
|
||||||
|
.rx_clk(sfp_rx_clk),
|
||||||
|
.rx_rst_in('0),
|
||||||
|
.rx_rst_out(sfp_rx_rst),
|
||||||
|
.tx_clk(sfp_tx_clk),
|
||||||
|
.tx_rst_in('0),
|
||||||
|
.tx_rst_out(sfp_tx_rst),
|
||||||
|
.ptp_sample_clk('0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Transmit interface (AXI stream)
|
||||||
|
*/
|
||||||
|
.s_axis_tx(axis_sfp_tx),
|
||||||
|
.m_axis_tx_cpl(axis_sfp_tx_cpl),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive interface (AXI stream)
|
||||||
|
*/
|
||||||
|
.m_axis_rx(axis_sfp_rx),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PTP clock
|
||||||
|
*/
|
||||||
|
.tx_ptp_ts('0),
|
||||||
|
.tx_ptp_ts_step('0),
|
||||||
|
.rx_ptp_ts('0),
|
||||||
|
.rx_ptp_ts_step('0),
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
|
||||||
|
*/
|
||||||
|
.tx_lfc_req('0),
|
||||||
|
.tx_lfc_resend('0),
|
||||||
|
.rx_lfc_en('0),
|
||||||
|
.rx_lfc_req(),
|
||||||
|
.rx_lfc_ack('0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC)
|
||||||
|
*/
|
||||||
|
.tx_pfc_req('0),
|
||||||
|
.tx_pfc_resend('0),
|
||||||
|
.rx_pfc_en('0),
|
||||||
|
.rx_pfc_req(),
|
||||||
|
.rx_pfc_ack('0),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pause interface
|
||||||
|
*/
|
||||||
|
.tx_lfc_pause_en('0),
|
||||||
|
.tx_pause_req('0),
|
||||||
|
.tx_pause_ack(),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status
|
||||||
|
*/
|
||||||
|
.tx_start_packet(),
|
||||||
|
.tx_error_underflow(),
|
||||||
|
.rx_start_packet(),
|
||||||
|
.rx_error_count(),
|
||||||
|
.rx_error_bad_frame(),
|
||||||
|
.rx_error_bad_fcs(),
|
||||||
|
.rx_bad_block(),
|
||||||
|
.rx_sequence_error(),
|
||||||
|
.rx_block_lock(),
|
||||||
|
.rx_high_ber(),
|
||||||
|
.rx_status(sfp_rx_status),
|
||||||
|
.stat_tx_mcf(),
|
||||||
|
.stat_rx_mcf(),
|
||||||
|
.stat_tx_lfc_pkt(),
|
||||||
|
.stat_tx_lfc_xon(),
|
||||||
|
.stat_tx_lfc_xoff(),
|
||||||
|
.stat_tx_lfc_paused(),
|
||||||
|
.stat_tx_pfc_pkt(),
|
||||||
|
.stat_tx_pfc_xon(),
|
||||||
|
.stat_tx_pfc_xoff(),
|
||||||
|
.stat_tx_pfc_paused(),
|
||||||
|
.stat_rx_lfc_pkt(),
|
||||||
|
.stat_rx_lfc_xon(),
|
||||||
|
.stat_rx_lfc_xoff(),
|
||||||
|
.stat_rx_lfc_paused(),
|
||||||
|
.stat_rx_pfc_pkt(),
|
||||||
|
.stat_rx_pfc_xon(),
|
||||||
|
.stat_rx_pfc_xoff(),
|
||||||
|
.stat_rx_pfc_paused(),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Configuration
|
||||||
|
*/
|
||||||
|
.cfg_ifg('{2{8'd12}}),
|
||||||
|
.cfg_tx_enable('1),
|
||||||
|
.cfg_rx_enable('1),
|
||||||
|
.cfg_tx_prbs31_enable('0),
|
||||||
|
.cfg_rx_prbs31_enable('0),
|
||||||
|
.cfg_mcf_rx_eth_dst_mcast('{2{48'h01_80_C2_00_00_01}}),
|
||||||
|
.cfg_mcf_rx_check_eth_dst_mcast('1),
|
||||||
|
.cfg_mcf_rx_eth_dst_ucast('{2{48'd0}}),
|
||||||
|
.cfg_mcf_rx_check_eth_dst_ucast('0),
|
||||||
|
.cfg_mcf_rx_eth_src('{2{48'd0}}),
|
||||||
|
.cfg_mcf_rx_check_eth_src('0),
|
||||||
|
.cfg_mcf_rx_eth_type('{2{16'h8808}}),
|
||||||
|
.cfg_mcf_rx_opcode_lfc('{2{16'h0001}}),
|
||||||
|
.cfg_mcf_rx_check_opcode_lfc('1),
|
||||||
|
.cfg_mcf_rx_opcode_pfc('{2{16'h0101}}),
|
||||||
|
.cfg_mcf_rx_check_opcode_pfc('1),
|
||||||
|
.cfg_mcf_rx_forward('0),
|
||||||
|
.cfg_mcf_rx_enable('0),
|
||||||
|
.cfg_tx_lfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
|
||||||
|
.cfg_tx_lfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
|
||||||
|
.cfg_tx_lfc_eth_type('{2{16'h8808}}),
|
||||||
|
.cfg_tx_lfc_opcode('{2{16'h0001}}),
|
||||||
|
.cfg_tx_lfc_en('0),
|
||||||
|
.cfg_tx_lfc_quanta('{2{16'hffff}}),
|
||||||
|
.cfg_tx_lfc_refresh('{2{16'h7fff}}),
|
||||||
|
.cfg_tx_pfc_eth_dst('{2{48'h01_80_C2_00_00_01}}),
|
||||||
|
.cfg_tx_pfc_eth_src('{2{48'h80_23_31_43_54_4C}}),
|
||||||
|
.cfg_tx_pfc_eth_type('{2{16'h8808}}),
|
||||||
|
.cfg_tx_pfc_opcode('{2{16'h0101}}),
|
||||||
|
.cfg_tx_pfc_en('0),
|
||||||
|
.cfg_tx_pfc_quanta('{2{'{8{16'hffff}}}}),
|
||||||
|
.cfg_tx_pfc_refresh('{2{'{8{16'h7fff}}}}),
|
||||||
|
.cfg_rx_lfc_opcode('{2{16'h0001}}),
|
||||||
|
.cfg_rx_lfc_en('0),
|
||||||
|
.cfg_rx_pfc_opcode('{2{16'h0101}}),
|
||||||
|
.cfg_rx_pfc_en('0)
|
||||||
|
);
|
||||||
|
|
||||||
|
for (genvar n = 0; n < 2; n = n + 1) begin : sfp_ch
|
||||||
|
|
||||||
|
taxi_axis_async_fifo #(
|
||||||
|
.DEPTH(16384),
|
||||||
|
.RAM_PIPELINE(2),
|
||||||
|
.FRAME_FIFO(1),
|
||||||
|
.USER_BAD_FRAME_VALUE(1'b1),
|
||||||
|
.USER_BAD_FRAME_MASK(1'b1),
|
||||||
|
.DROP_OVERSIZE_FRAME(1),
|
||||||
|
.DROP_BAD_FRAME(1),
|
||||||
|
.DROP_WHEN_FULL(1)
|
||||||
|
)
|
||||||
|
ch_fifo (
|
||||||
|
/*
|
||||||
|
* AXI4-Stream input (sink)
|
||||||
|
*/
|
||||||
|
.s_clk(sfp_rx_clk[n]),
|
||||||
|
.s_rst(sfp_rx_rst[n]),
|
||||||
|
.s_axis(axis_sfp_rx[n]),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AXI4-Stream output (source)
|
||||||
|
*/
|
||||||
|
.m_clk(sfp_tx_clk[n]),
|
||||||
|
.m_rst(sfp_tx_rst[n]),
|
||||||
|
.m_axis(axis_sfp_tx[n]),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pause
|
||||||
|
*/
|
||||||
|
.s_pause_req(1'b0),
|
||||||
|
.s_pause_ack(),
|
||||||
|
.m_pause_req(1'b0),
|
||||||
|
.m_pause_ack(),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Status
|
||||||
|
*/
|
||||||
|
.s_status_depth(),
|
||||||
|
.s_status_depth_commit(),
|
||||||
|
.s_status_overflow(),
|
||||||
|
.s_status_bad_frame(),
|
||||||
|
.s_status_good_frame(),
|
||||||
|
.m_status_depth(),
|
||||||
|
.m_status_depth_commit(),
|
||||||
|
.m_status_overflow(),
|
||||||
|
.m_status_bad_frame(),
|
||||||
|
.m_status_good_frame()
|
||||||
|
);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
`resetall
|
`resetall
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ MODULE = $(COCOTB_TEST_MODULES)
|
|||||||
TOPLEVEL = $(COCOTB_TOPLEVEL)
|
TOPLEVEL = $(COCOTB_TOPLEVEL)
|
||||||
VERILOG_SOURCES += ../../rtl/$(DUT).sv
|
VERILOG_SOURCES += ../../rtl/$(DUT).sv
|
||||||
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/taxi_eth_mac_1g_fifo.f
|
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/taxi_eth_mac_1g_fifo.f
|
||||||
|
VERILOG_SOURCES += ../../lib/taxi/rtl/eth/us/taxi_eth_mac_25g_us.f
|
||||||
VERILOG_SOURCES += ../../lib/taxi/rtl/lss/taxi_uart.f
|
VERILOG_SOURCES += ../../lib/taxi/rtl/lss/taxi_uart.f
|
||||||
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_reset.sv
|
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_reset.sv
|
||||||
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_signal.sv
|
VERILOG_SOURCES += ../../lib/taxi/rtl/sync/taxi_sync_signal.sv
|
||||||
@@ -32,7 +33,10 @@ uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $
|
|||||||
VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
|
||||||
|
|
||||||
# module parameters
|
# module parameters
|
||||||
#export PARAM_A := value
|
export PARAM_SIM := "1'b1"
|
||||||
|
export PARAM_VENDOR := "\"XILINX\""
|
||||||
|
export PARAM_FAMILY := "\"kintexu\""
|
||||||
|
export PARAM_SFP_RATE := "1'b1"
|
||||||
|
|
||||||
ifeq ($(SIM), icarus)
|
ifeq ($(SIM), icarus)
|
||||||
PLUSARGS += -fst
|
PLUSARGS += -fst
|
||||||
|
|||||||
1
example/KCU105/fpga/tb/fpga_core/baser.py
Symbolic link
1
example/KCU105/fpga/tb/fpga_core/baser.py
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../../lib/taxi/tb/eth/baser.py
|
||||||
@@ -11,7 +11,9 @@ Authors:
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pytest
|
||||||
import cocotb_test.simulator
|
import cocotb_test.simulator
|
||||||
|
|
||||||
import cocotb
|
import cocotb
|
||||||
@@ -20,8 +22,19 @@ from cocotb.clock import Clock
|
|||||||
from cocotb.triggers import RisingEdge, Combine
|
from cocotb.triggers import RisingEdge, Combine
|
||||||
|
|
||||||
from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink
|
from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink
|
||||||
|
from cocotbext.eth import XgmiiFrame
|
||||||
from cocotbext.uart import UartSource, UartSink
|
from cocotbext.uart import UartSource, UartSink
|
||||||
|
|
||||||
|
try:
|
||||||
|
from baser import BaseRSerdesSource, BaseRSerdesSink
|
||||||
|
except ImportError:
|
||||||
|
# attempt import from current directory
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
|
||||||
|
try:
|
||||||
|
from baser import BaseRSerdesSource, BaseRSerdesSink
|
||||||
|
finally:
|
||||||
|
del sys.path[0]
|
||||||
|
|
||||||
|
|
||||||
class TB:
|
class TB:
|
||||||
def __init__(self, dut, speed=1000e6):
|
def __init__(self, dut, speed=1000e6):
|
||||||
@@ -32,23 +45,37 @@ class TB:
|
|||||||
|
|
||||||
cocotb.start_soon(Clock(dut.clk, 8, units="ns").start())
|
cocotb.start_soon(Clock(dut.clk, 8, units="ns").start())
|
||||||
cocotb.start_soon(Clock(dut.phy_gmii_clk, 8, units="ns").start())
|
cocotb.start_soon(Clock(dut.phy_gmii_clk, 8, units="ns").start())
|
||||||
cocotb.start_soon(Clock(dut.sfp0_gmii_clk, 8, units="ns").start())
|
|
||||||
cocotb.start_soon(Clock(dut.sfp1_gmii_clk, 8, units="ns").start())
|
|
||||||
|
|
||||||
self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv,
|
self.gmii_source = GmiiSource(dut.phy_gmii_rxd, dut.phy_gmii_rx_er, dut.phy_gmii_rx_dv,
|
||||||
dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en)
|
dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en)
|
||||||
self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en,
|
self.gmii_sink = GmiiSink(dut.phy_gmii_txd, dut.phy_gmii_tx_er, dut.phy_gmii_tx_en,
|
||||||
dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en)
|
dut.phy_gmii_clk, dut.phy_gmii_rst, dut.phy_gmii_clk_en)
|
||||||
|
|
||||||
self.sfp0_source = GmiiSource(dut.sfp0_gmii_rxd, dut.sfp0_gmii_rx_er, dut.sfp0_gmii_rx_dv,
|
self.sfp_sources = []
|
||||||
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en)
|
self.sfp_sinks = []
|
||||||
self.sfp0_sink = GmiiSink(dut.sfp0_gmii_txd, dut.sfp0_gmii_tx_er, dut.sfp0_gmii_tx_en,
|
|
||||||
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en)
|
|
||||||
|
|
||||||
self.sfp1_source = GmiiSource(dut.sfp1_gmii_rxd, dut.sfp1_gmii_rx_er, dut.sfp1_gmii_rx_dv,
|
if dut.SFP_RATE.value == 0:
|
||||||
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en)
|
cocotb.start_soon(Clock(dut.sfp0_gmii_clk, 8, units="ns").start())
|
||||||
self.sfp1_sink = GmiiSink(dut.sfp1_gmii_txd, dut.sfp1_gmii_tx_er, dut.sfp1_gmii_tx_en,
|
cocotb.start_soon(Clock(dut.sfp1_gmii_clk, 8, units="ns").start())
|
||||||
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en)
|
|
||||||
|
self.sfp_sources.append(GmiiSource(dut.sfp0_gmii_rxd, dut.sfp0_gmii_rx_er, dut.sfp0_gmii_rx_dv,
|
||||||
|
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en))
|
||||||
|
self.sfp_sinks.append(GmiiSink(dut.sfp0_gmii_txd, dut.sfp0_gmii_tx_er, dut.sfp0_gmii_tx_en,
|
||||||
|
dut.sfp0_gmii_clk, dut.sfp0_gmii_rst, dut.sfp0_gmii_clk_en))
|
||||||
|
|
||||||
|
self.sfp_sources.append(GmiiSource(dut.sfp1_gmii_rxd, dut.sfp1_gmii_rx_er, dut.sfp1_gmii_rx_dv,
|
||||||
|
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en))
|
||||||
|
self.sfp_sinks.append(GmiiSink(dut.sfp1_gmii_txd, dut.sfp1_gmii_tx_er, dut.sfp1_gmii_tx_en,
|
||||||
|
dut.sfp1_gmii_clk, dut.sfp1_gmii_rst, dut.sfp1_gmii_clk_en))
|
||||||
|
else:
|
||||||
|
cocotb.start_soon(Clock(dut.sfp_mgt_refclk_0_p, 6.4, units="ns").start())
|
||||||
|
|
||||||
|
for ch in dut.sfp_mac.sfp_mac_inst.ch:
|
||||||
|
cocotb.start_soon(Clock(ch.ch_inst.tx_clk, 6.4, units="ns").start())
|
||||||
|
cocotb.start_soon(Clock(ch.ch_inst.rx_clk, 6.4, units="ns").start())
|
||||||
|
|
||||||
|
self.sfp_sources.append(BaseRSerdesSource(ch.ch_inst.serdes_rx_data, ch.ch_inst.serdes_rx_hdr, ch.ch_inst.rx_clk, slip=ch.ch_inst.serdes_rx_bitslip, reverse=True))
|
||||||
|
self.sfp_sinks.append(BaseRSerdesSink(ch.ch_inst.serdes_tx_data, ch.ch_inst.serdes_tx_hdr, ch.ch_inst.tx_clk, reverse=True))
|
||||||
|
|
||||||
self.uart_source = UartSource(dut.uart_rxd, baud=115200, bits=8, stop_bits=1)
|
self.uart_source = UartSource(dut.uart_rxd, baud=115200, bits=8, stop_bits=1)
|
||||||
self.uart_sink = UartSink(dut.uart_txd, baud=115200, bits=8, stop_bits=1)
|
self.uart_sink = UartSink(dut.uart_txd, baud=115200, bits=8, stop_bits=1)
|
||||||
@@ -86,6 +113,9 @@ class TB:
|
|||||||
self.dut.sfp0_gmii_rst.value = 0
|
self.dut.sfp0_gmii_rst.value = 0
|
||||||
self.dut.sfp1_gmii_rst.value = 0
|
self.dut.sfp1_gmii_rst.value = 0
|
||||||
|
|
||||||
|
for k in range(10):
|
||||||
|
await RisingEdge(self.dut.clk)
|
||||||
|
|
||||||
|
|
||||||
async def uart_test(tb, source, sink):
|
async def uart_test(tb, source, sink):
|
||||||
tb.log.info("Test UART")
|
tb.log.info("Test UART")
|
||||||
@@ -148,6 +178,46 @@ async def mac_test(tb, source, sink):
|
|||||||
tb.log.info("MAC test done")
|
tb.log.info("MAC test done")
|
||||||
|
|
||||||
|
|
||||||
|
async def mac_test_25g(tb, source, sink):
|
||||||
|
tb.log.info("Test MAC")
|
||||||
|
|
||||||
|
tb.log.info("Multiple small packets")
|
||||||
|
|
||||||
|
count = 64
|
||||||
|
|
||||||
|
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
|
||||||
|
|
||||||
|
for p in pkts:
|
||||||
|
await source.send(XgmiiFrame.from_payload(p))
|
||||||
|
|
||||||
|
for k in range(count):
|
||||||
|
rx_frame = await sink.recv()
|
||||||
|
|
||||||
|
tb.log.info("RX frame: %s", rx_frame)
|
||||||
|
|
||||||
|
assert rx_frame.get_payload() == pkts[k]
|
||||||
|
assert rx_frame.check_fcs()
|
||||||
|
|
||||||
|
tb.log.info("Multiple large packets")
|
||||||
|
|
||||||
|
count = 32
|
||||||
|
|
||||||
|
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
|
||||||
|
|
||||||
|
for p in pkts:
|
||||||
|
await source.send(XgmiiFrame.from_payload(p))
|
||||||
|
|
||||||
|
for k in range(count):
|
||||||
|
rx_frame = await sink.recv()
|
||||||
|
|
||||||
|
tb.log.info("RX frame: %s", rx_frame)
|
||||||
|
|
||||||
|
assert rx_frame.get_payload() == pkts[k]
|
||||||
|
assert rx_frame.check_fcs()
|
||||||
|
|
||||||
|
tb.log.info("MAC test done")
|
||||||
|
|
||||||
|
|
||||||
@cocotb.test()
|
@cocotb.test()
|
||||||
async def run_test(dut):
|
async def run_test(dut):
|
||||||
|
|
||||||
@@ -155,23 +225,25 @@ async def run_test(dut):
|
|||||||
|
|
||||||
await tb.init()
|
await tb.init()
|
||||||
|
|
||||||
|
tests = []
|
||||||
|
|
||||||
tb.log.info("Start UART test")
|
tb.log.info("Start UART test")
|
||||||
|
|
||||||
uart_test_cr = cocotb.start_soon(uart_test(tb, tb.uart_source, tb.uart_sink))
|
tests.append(cocotb.start_soon(uart_test(tb, tb.uart_source, tb.uart_sink)))
|
||||||
|
|
||||||
tb.log.info("Start BASE-T MAC loopback test")
|
tb.log.info("Start BASE-T MAC loopback test")
|
||||||
|
|
||||||
baset_test_cr = cocotb.start_soon(mac_test(tb, tb.gmii_source, tb.gmii_sink))
|
tests.append(cocotb.start_soon(mac_test(tb, tb.gmii_source, tb.gmii_sink)))
|
||||||
|
|
||||||
tb.log.info("Start SFP0 MAC loopback test")
|
for k in range(len(tb.sfp_sources)):
|
||||||
|
if dut.SFP_RATE.value == 0:
|
||||||
|
tb.log.info("Start SFP %d 1G MAC loopback test", k)
|
||||||
|
tests.append(cocotb.start_soon(mac_test(tb, tb.sfp_sources[k], tb.sfp_sinks[k])))
|
||||||
|
else:
|
||||||
|
tb.log.info("Start SFP %d 10G MAC loopback test", k)
|
||||||
|
tests.append(cocotb.start_soon(mac_test_25g(tb, tb.sfp_sources[k], tb.sfp_sinks[k])))
|
||||||
|
|
||||||
sfp0_test_cr = cocotb.start_soon(mac_test(tb, tb.sfp0_source, tb.sfp0_sink))
|
await Combine(*tests)
|
||||||
|
|
||||||
tb.log.info("Start SFP1 MAC loopback test")
|
|
||||||
|
|
||||||
sfp1_test_cr = cocotb.start_soon(mac_test(tb, tb.sfp1_source, tb.sfp1_sink))
|
|
||||||
|
|
||||||
await Combine(uart_test_cr, baset_test_cr, sfp0_test_cr, sfp1_test_cr)
|
|
||||||
|
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
await RisingEdge(dut.clk)
|
await RisingEdge(dut.clk)
|
||||||
@@ -197,7 +269,8 @@ def process_f_files(files):
|
|||||||
return list(lst.values())
|
return list(lst.values())
|
||||||
|
|
||||||
|
|
||||||
def test_fpga_core(request):
|
@pytest.mark.parametrize("sfp_rate", [0, 1])
|
||||||
|
def test_fpga_core(request, sfp_rate):
|
||||||
dut = "fpga_core"
|
dut = "fpga_core"
|
||||||
module = os.path.splitext(os.path.basename(__file__))[0]
|
module = os.path.splitext(os.path.basename(__file__))[0]
|
||||||
toplevel = dut
|
toplevel = dut
|
||||||
@@ -205,6 +278,7 @@ def test_fpga_core(request):
|
|||||||
verilog_sources = [
|
verilog_sources = [
|
||||||
os.path.join(rtl_dir, f"{dut}.sv"),
|
os.path.join(rtl_dir, f"{dut}.sv"),
|
||||||
os.path.join(lib_dir, "taxi", "rtl", "eth", "taxi_eth_mac_1g_fifo.f"),
|
os.path.join(lib_dir, "taxi", "rtl", "eth", "taxi_eth_mac_1g_fifo.f"),
|
||||||
|
os.path.join(lib_dir, "taxi", "rtl", "eth", "us", "taxi_eth_mac_25g_us.f"),
|
||||||
os.path.join(lib_dir, "taxi", "rtl", "lss", "taxi_uart.f"),
|
os.path.join(lib_dir, "taxi", "rtl", "lss", "taxi_uart.f"),
|
||||||
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_reset.sv"),
|
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_reset.sv"),
|
||||||
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_signal.sv"),
|
os.path.join(lib_dir, "taxi", "rtl", "sync", "taxi_sync_signal.sv"),
|
||||||
@@ -215,7 +289,10 @@ def test_fpga_core(request):
|
|||||||
|
|
||||||
parameters = {}
|
parameters = {}
|
||||||
|
|
||||||
# parameters['A'] = val
|
parameters['SIM'] = "1'b1"
|
||||||
|
parameters['VENDOR'] = "\"XILINX\""
|
||||||
|
parameters['FAMILY'] = "\"kintexu\""
|
||||||
|
parameters['SFP_RATE'] = f"1'b{sfp_rate}"
|
||||||
|
|
||||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user