diff --git a/src/eth/example/ZCU102/fpga/fpga_10g/config.tcl b/src/eth/example/ZCU102/fpga/fpga_10g/config.tcl index fe5171b..51c34b1 100644 --- a/src/eth/example/ZCU102/fpga/fpga_10g/config.tcl +++ b/src/eth/example/ZCU102/fpga/fpga_10g/config.tcl @@ -12,6 +12,11 @@ set params [dict create] # 0 for 1G, 1 for 10G dict set params SFP_RATE "1" +# 10G MAC configuration +dict set params CFG_LOW_LATENCY "1" +dict set params COMBINED_MAC_PCS "1" +dict set params MAC_DATA_W "32" + # apply parameters to top-level set param_list {} dict for {name value} $params { diff --git a/src/eth/example/ZCU102/fpga/fpga_1g/Makefile b/src/eth/example/ZCU102/fpga/fpga_1g/Makefile index ce4c839..cdde828 100644 --- a/src/eth/example/ZCU102/fpga/fpga_1g/Makefile +++ b/src/eth/example/ZCU102/fpga/fpga_1g/Makefile @@ -18,9 +18,10 @@ TAXI_SRC_DIR = $(LIB_DIR)/taxi/src # Files for synthesis SYN_FILES = $(RTL_DIR)/fpga.sv SYN_FILES += $(RTL_DIR)/fpga_core.sv -SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/taxi_eth_mac_1g_fifo.f +SYN_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_1g_basex_us.f SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv +SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f SYN_FILES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_stats.f SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_reset.sv SYN_FILES += $(TAXI_SRC_DIR)/sync/rtl/taxi_sync_signal.sv @@ -37,8 +38,7 @@ XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_reset.tcl XDC_FILES += $(TAXI_SRC_DIR)/sync/syn/vivado/taxi_sync_signal.tcl # IP -IP_TCL_FILES = ../ip/basex_pcs_pma_0.tcl -IP_TCL_FILES += ../ip/basex_pcs_pma_1.tcl +IP_TCL_FILES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_phy_1g_basex_us_gth_156.tcl # Configuration CONFIG_TCL_FILES = ./config.tcl diff --git a/src/eth/example/ZCU102/fpga/fpga_1g/config.tcl b/src/eth/example/ZCU102/fpga/fpga_1g/config.tcl index 168762b..a95092e 100644 --- a/src/eth/example/ZCU102/fpga/fpga_1g/config.tcl +++ b/src/eth/example/ZCU102/fpga/fpga_1g/config.tcl @@ -12,6 +12,11 @@ set params [dict create] # 0 for 1G, 1 for 10G dict set params SFP_RATE "0" +# 10G MAC configuration +dict set params CFG_LOW_LATENCY "1" +dict set params COMBINED_MAC_PCS "1" +dict set params MAC_DATA_W "16" + # apply parameters to top-level set param_list {} dict for {name value} $params { diff --git a/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_0.tcl b/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_0.tcl deleted file mode 100644 index 43a289a..0000000 --- a/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_0.tcl +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# Copyright (c) 2025 FPGA Ninja, LLC -# -# Authors: -# - Alex Forencich -# - -create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name basex_pcs_pma_0 - -set_property -dict [list \ - CONFIG.Standard {1000BASEX} \ - CONFIG.Physical_Interface {Transceiver} \ - CONFIG.Management_Interface {false} \ - CONFIG.Auto_Negotiation {false} \ - CONFIG.TransceiverControl {false} \ - CONFIG.RefClkRate {156.25} \ - CONFIG.DrpClkRate {62.5} \ - CONFIG.SupportLevel {Include_Shared_Logic_in_Core} \ - CONFIG.GT_Location {X0Y10} \ -] [get_ips basex_pcs_pma_0] diff --git a/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_1.tcl b/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_1.tcl deleted file mode 100644 index bca6438..0000000 --- a/src/eth/example/ZCU102/fpga/ip/basex_pcs_pma_1.tcl +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: MIT -# -# Copyright (c) 2025 FPGA Ninja, LLC -# -# Authors: -# - Alex Forencich -# - -create_ip -name gig_ethernet_pcs_pma -vendor xilinx.com -library ip -module_name basex_pcs_pma_1 - -set_property -dict [list \ - CONFIG.Standard {1000BASEX} \ - CONFIG.Physical_Interface {Transceiver} \ - CONFIG.Management_Interface {false} \ - CONFIG.Auto_Negotiation {false} \ - CONFIG.TransceiverControl {false} \ - CONFIG.RefClkRate {156.25} \ - CONFIG.DrpClkRate {62.5} \ - CONFIG.SupportLevel {Include_Shared_Logic_in_Example_Design} \ - CONFIG.GT_Location {X0Y9} \ -] [get_ips basex_pcs_pma_1] diff --git a/src/eth/example/ZCU102/fpga/rtl/fpga.sv b/src/eth/example/ZCU102/fpga/rtl/fpga.sv index b84a799..40a9eb2 100644 --- a/src/eth/example/ZCU102/fpga/rtl/fpga.sv +++ b/src/eth/example/ZCU102/fpga/rtl/fpga.sv @@ -24,7 +24,11 @@ module fpga # // device family parameter string FAMILY = "zynquplus", // SFP rate selection (0 for 1G, 1 for 10G) - parameter logic SFP_RATE = 1'b1 + parameter logic SFP_RATE = 1'b1, + // 10G MAC configuration + parameter logic CFG_LOW_LATENCY = 1'b1, + parameter logic COMBINED_MAC_PCS = 1'b1, + parameter MAC_DATA_W = 32 ) ( /* @@ -83,13 +87,13 @@ wire mmcm_locked; wire mmcm_clkfb; IBUFGDS #( - .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE") + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE") ) clk_125mhz_ibufg_inst ( - .O (clk_125mhz_ibufg), - .I (clk_125mhz_p), - .IB (clk_125mhz_n) + .O (clk_125mhz_ibufg), + .I (clk_125mhz_p), + .IB (clk_125mhz_n) ); BUFG @@ -240,361 +244,14 @@ sync_signal_inst ( .out({uart_rxd_int, uart_rts_int}) ); -wire [7:0] led_int; - -// SFP+ -wire sfp_tx_p_int[4]; -wire sfp_tx_n_int[4]; - -wire sfp0_gmii_clk_int; -wire sfp0_gmii_rst_int; -wire sfp0_gmii_clk_en_int = 1'b1; -wire [7:0] sfp0_gmii_txd_int; -wire sfp0_gmii_tx_en_int; -wire sfp0_gmii_tx_er_int; -wire [7:0] sfp0_gmii_rxd_int; -wire sfp0_gmii_rx_dv_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 = 1'b1; -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 [15:0] sfp1_status_vect; - -wire sfp2_gmii_clk_int; -wire sfp2_gmii_rst_int; -wire sfp2_gmii_clk_en_int = 1'b1; -wire [7:0] sfp2_gmii_txd_int; -wire sfp2_gmii_tx_en_int; -wire sfp2_gmii_tx_er_int; -wire [7:0] sfp2_gmii_rxd_int; -wire sfp2_gmii_rx_dv_int; -wire sfp2_gmii_rx_er_int; - -wire [15:0] sfp2_status_vect; - -wire sfp3_gmii_clk_int; -wire sfp3_gmii_rst_int; -wire sfp3_gmii_clk_en_int = 1'b1; -wire [7:0] sfp3_gmii_txd_int; -wire sfp3_gmii_tx_en_int; -wire sfp3_gmii_tx_er_int; -wire [7:0] sfp3_gmii_rxd_int; -wire sfp3_gmii_rx_dv_int; -wire sfp3_gmii_rx_er_int; - -wire [15:0] sfp3_status_vect; - -if (SFP_RATE == 0) begin : sfp_phy - // 1000BASE-X - - wire sfp0_gmii_gtrefclk; - wire sfp0_gmii_txuserclk; - wire sfp0_gmii_txuserclk2; - wire sfp0_gmii_resetdone; - wire sfp0_gmii_pmareset; - wire sfp0_gmii_mmcm_locked; - - assign sfp0_gmii_clk_int = sfp0_gmii_txuserclk2; - - taxi_sync_reset #( - .N(4) - ) - sync_reset_sfp0_inst ( - .clk(sfp0_gmii_clk_int), - .rst(rst_125mhz_int || !sfp0_gmii_resetdone), - .out(sfp0_gmii_rst_int) - ); - - wire sfp0_status_link_status = sfp0_status_vect[0]; - wire sfp0_status_link_synchronization = sfp0_status_vect[1]; - wire sfp0_status_rudi_c = sfp0_status_vect[2]; - wire sfp0_status_rudi_i = sfp0_status_vect[3]; - wire sfp0_status_rudi_invalid = sfp0_status_vect[4]; - wire sfp0_status_rxdisperr = sfp0_status_vect[5]; - wire sfp0_status_rxnotintable = sfp0_status_vect[6]; - wire sfp0_status_phy_link_status = sfp0_status_vect[7]; - wire [1:0] sfp0_status_remote_fault_encdg = sfp0_status_vect[9:8]; - wire [1:0] sfp0_status_speed = sfp0_status_vect[11:10]; - wire sfp0_status_duplex = sfp0_status_vect[12]; - wire sfp0_status_remote_fault = sfp0_status_vect[13]; - wire [1:0] sfp0_status_pause = sfp0_status_vect[15:14]; - - wire [4:0] sfp0_config_vect; - - assign sfp0_config_vect[4] = 1'b0; // autonegotiation enable - assign sfp0_config_vect[3] = 1'b0; // isolate - assign sfp0_config_vect[2] = 1'b0; // power down - assign sfp0_config_vect[1] = 1'b0; // loopback enable - assign sfp0_config_vect[0] = 1'b0; // unidirectional enable - - basex_pcs_pma_0 - sfp0_pcspma ( - .gtrefclk_p(sfp_mgt_refclk_0_p), - .gtrefclk_n(sfp_mgt_refclk_0_n), - .gtrefclk_out(sfp0_gmii_gtrefclk), - .txn(sfp_tx_n[0]), - .txp(sfp_tx_p[0]), - .rxn(sfp_rx_n[0]), - .rxp(sfp_rx_p[0]), - .independent_clock_bufg(clk_62mhz_int), - .userclk_out(sfp0_gmii_txuserclk), - .userclk2_out(sfp0_gmii_txuserclk2), - .rxuserclk_out(), - .rxuserclk2_out(), - .gtpowergood(), - .resetdone(sfp0_gmii_resetdone), - .pma_reset_out(sfp0_gmii_pmareset), - .mmcm_locked_out(sfp0_gmii_mmcm_locked), - .gmii_txd(sfp0_gmii_txd_int), - .gmii_tx_en(sfp0_gmii_tx_en_int), - .gmii_tx_er(sfp0_gmii_tx_er_int), - .gmii_rxd(sfp0_gmii_rxd_int), - .gmii_rx_dv(sfp0_gmii_rx_dv_int), - .gmii_rx_er(sfp0_gmii_rx_er_int), - .gmii_isolate(), - .configuration_vector(sfp0_config_vect), - .status_vector(sfp0_status_vect), - .reset(rst_125mhz_int), - .signal_detect(1'b1) - ); - - wire sfp1_gmii_txuserclk2 = sfp0_gmii_txuserclk2; - wire sfp1_gmii_resetdone; - - assign sfp1_gmii_clk_int = sfp1_gmii_txuserclk2; - - taxi_sync_reset #( - .N(4) - ) - sync_reset_sfp1_inst ( - .clk(sfp1_gmii_clk_int), - .rst(rst_125mhz_int || !sfp1_gmii_resetdone), - .out(sfp1_gmii_rst_int) - ); - - wire sfp1_status_link_status = sfp1_status_vect[0]; - wire sfp1_status_link_synchronization = sfp1_status_vect[1]; - wire sfp1_status_rudi_c = sfp1_status_vect[2]; - wire sfp1_status_rudi_i = sfp1_status_vect[3]; - wire sfp1_status_rudi_invalid = sfp1_status_vect[4]; - wire sfp1_status_rxdisperr = sfp1_status_vect[5]; - wire sfp1_status_rxnotintable = sfp1_status_vect[6]; - wire sfp1_status_phy_link_status = sfp1_status_vect[7]; - wire [1:0] sfp1_status_remote_fault_encdg = sfp1_status_vect[9:8]; - wire [1:0] sfp1_status_speed = sfp1_status_vect[11:10]; - wire sfp1_status_duplex = sfp1_status_vect[12]; - wire sfp1_status_remote_fault = sfp1_status_vect[13]; - wire [1:0] sfp1_status_pause = sfp1_status_vect[15:14]; - - wire [4:0] sfp1_config_vect; - - assign sfp1_config_vect[4] = 1'b0; // autonegotiation enable - assign sfp1_config_vect[3] = 1'b0; // isolate - assign sfp1_config_vect[2] = 1'b0; // power down - assign sfp1_config_vect[1] = 1'b0; // loopback enable - assign sfp1_config_vect[0] = 1'b0; // unidirectional enable - - basex_pcs_pma_1 - sfp1_pcspma ( - .gtrefclk(sfp0_gmii_gtrefclk), - .txn(sfp_tx_n[1]), - .txp(sfp_tx_p[1]), - .rxn(sfp_rx_n[1]), - .rxp(sfp_rx_p[1]), - .independent_clock_bufg(clk_62mhz_int), - .txoutclk(), - .gtpowergood(), - .rxoutclk(), - .resetdone(sfp1_gmii_resetdone), - .cplllock(), - .mmcm_reset(), - .userclk(sfp0_gmii_txuserclk), - .userclk2(sfp0_gmii_txuserclk2), - .pma_reset(sfp0_gmii_pmareset), - .mmcm_locked(sfp0_gmii_mmcm_locked), - .rxuserclk(1'b0), - .rxuserclk2(1'b0), - .gmii_txd(sfp1_gmii_txd_int), - .gmii_tx_en(sfp1_gmii_tx_en_int), - .gmii_tx_er(sfp1_gmii_tx_er_int), - .gmii_rxd(sfp1_gmii_rxd_int), - .gmii_rx_dv(sfp1_gmii_rx_dv_int), - .gmii_rx_er(sfp1_gmii_rx_er_int), - .gmii_isolate(), - .configuration_vector(sfp1_config_vect), - .status_vector(sfp1_status_vect), - .reset(rst_125mhz_int), - .signal_detect(1'b1) - ); - - wire sfp2_gmii_txuserclk2 = sfp0_gmii_txuserclk2; - wire sfp2_gmii_resetdone; - - assign sfp2_gmii_clk_int = sfp2_gmii_txuserclk2; - - taxi_sync_reset #( - .N(4) - ) - sync_reset_sfp2_inst ( - .clk(sfp2_gmii_clk_int), - .rst(rst_125mhz_int || !sfp2_gmii_resetdone), - .out(sfp2_gmii_rst_int) - ); - - wire sfp2_status_link_status = sfp2_status_vect[0]; - wire sfp2_status_link_synchronization = sfp2_status_vect[1]; - wire sfp2_status_rudi_c = sfp2_status_vect[2]; - wire sfp2_status_rudi_i = sfp2_status_vect[3]; - wire sfp2_status_rudi_invalid = sfp2_status_vect[4]; - wire sfp2_status_rxdisperr = sfp2_status_vect[5]; - wire sfp2_status_rxnotintable = sfp2_status_vect[6]; - wire sfp2_status_phy_link_status = sfp2_status_vect[7]; - wire [1:0] sfp2_status_remote_fault_encdg = sfp2_status_vect[9:8]; - wire [1:0] sfp2_status_speed = sfp2_status_vect[11:10]; - wire sfp2_status_duplex = sfp2_status_vect[12]; - wire sfp2_status_remote_fault = sfp2_status_vect[13]; - wire [1:0] sfp2_status_pause = sfp2_status_vect[15:14]; - - wire [4:0] sfp2_config_vect; - - assign sfp2_config_vect[4] = 1'b0; // autonegotiation enable - assign sfp2_config_vect[3] = 1'b0; // isolate - assign sfp2_config_vect[2] = 1'b0; // power down - assign sfp2_config_vect[1] = 1'b0; // loopback enable - assign sfp2_config_vect[0] = 1'b0; // unidirectional enable - - basex_pcs_pma_1 - sfp2_pcspma ( - .gtrefclk(sfp0_gmii_gtrefclk), - .txn(sfp_tx_n[2]), - .txp(sfp_tx_p[2]), - .rxn(sfp_rx_n[2]), - .rxp(sfp_rx_p[2]), - .independent_clock_bufg(clk_62mhz_int), - .txoutclk(), - .gtpowergood(), - .rxoutclk(), - .resetdone(sfp2_gmii_resetdone), - .cplllock(), - .mmcm_reset(), - .userclk(sfp0_gmii_txuserclk), - .userclk2(sfp0_gmii_txuserclk2), - .pma_reset(sfp0_gmii_pmareset), - .mmcm_locked(sfp0_gmii_mmcm_locked), - .rxuserclk(1'b0), - .rxuserclk2(1'b0), - .gmii_txd(sfp2_gmii_txd_int), - .gmii_tx_en(sfp2_gmii_tx_en_int), - .gmii_tx_er(sfp2_gmii_tx_er_int), - .gmii_rxd(sfp2_gmii_rxd_int), - .gmii_rx_dv(sfp2_gmii_rx_dv_int), - .gmii_rx_er(sfp2_gmii_rx_er_int), - .gmii_isolate(), - .configuration_vector(sfp2_config_vect), - .status_vector(sfp2_status_vect), - .reset(rst_125mhz_int), - .signal_detect(1'b1) - ); - - wire sfp3_gmii_txuserclk2 = sfp0_gmii_txuserclk2; - wire sfp3_gmii_resetdone; - - assign sfp3_gmii_clk_int = sfp3_gmii_txuserclk2; - - taxi_sync_reset #( - .N(4) - ) - sync_reset_sfp3_inst ( - .clk(sfp3_gmii_clk_int), - .rst(rst_125mhz_int || !sfp3_gmii_resetdone), - .out(sfp3_gmii_rst_int) - ); - - wire sfp3_status_link_status = sfp3_status_vect[0]; - wire sfp3_status_link_synchronization = sfp3_status_vect[1]; - wire sfp3_status_rudi_c = sfp3_status_vect[2]; - wire sfp3_status_rudi_i = sfp3_status_vect[3]; - wire sfp3_status_rudi_invalid = sfp3_status_vect[4]; - wire sfp3_status_rxdisperr = sfp3_status_vect[5]; - wire sfp3_status_rxnotintable = sfp3_status_vect[6]; - wire sfp3_status_phy_link_status = sfp3_status_vect[7]; - wire [1:0] sfp3_status_remote_fault_encdg = sfp3_status_vect[9:8]; - wire [1:0] sfp3_status_speed = sfp3_status_vect[11:10]; - wire sfp3_status_duplex = sfp3_status_vect[12]; - wire sfp3_status_remote_fault = sfp3_status_vect[13]; - wire [1:0] sfp3_status_pause = sfp3_status_vect[15:14]; - - wire [4:0] sfp3_config_vect; - - assign sfp3_config_vect[4] = 1'b0; // autonegotiation enable - assign sfp3_config_vect[3] = 1'b0; // isolate - assign sfp3_config_vect[2] = 1'b0; // power down - assign sfp3_config_vect[1] = 1'b0; // loopback enable - assign sfp3_config_vect[0] = 1'b0; // unidirectional enable - - basex_pcs_pma_1 - sfp3_pcspma ( - .gtrefclk(sfp0_gmii_gtrefclk), - .txn(sfp_tx_n[3]), - .txp(sfp_tx_p[3]), - .rxn(sfp_rx_n[3]), - .rxp(sfp_rx_p[3]), - .independent_clock_bufg(clk_62mhz_int), - .txoutclk(), - .gtpowergood(), - .rxoutclk(), - .resetdone(sfp3_gmii_resetdone), - .cplllock(), - .mmcm_reset(), - .userclk(sfp0_gmii_txuserclk), - .userclk2(sfp0_gmii_txuserclk2), - .pma_reset(sfp0_gmii_pmareset), - .mmcm_locked(sfp0_gmii_mmcm_locked), - .rxuserclk(1'b0), - .rxuserclk2(1'b0), - .gmii_txd(sfp3_gmii_txd_int), - .gmii_tx_en(sfp3_gmii_tx_en_int), - .gmii_tx_er(sfp3_gmii_tx_er_int), - .gmii_rxd(sfp3_gmii_rxd_int), - .gmii_rx_dv(sfp3_gmii_rx_dv_int), - .gmii_rx_er(sfp3_gmii_rx_er_int), - .gmii_isolate(), - .configuration_vector(sfp3_config_vect), - .status_vector(sfp3_status_vect), - .reset(rst_125mhz_int), - .signal_detect(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: -// SW12:1 (sw[3]) off for payload byte, on for status vector -// SW12:2 (sw[2]) off for SFP0, on for SFP1 -// SW12:4 (sw[0]) off for LSB of status vector, on for MSB -wire [15:0] sel_sv = sw[2] ? sfp1_status_vect : sfp0_status_vect; -assign led = sw[3] ? (sw[0] ? sel_sv[15:8] : sel_sv[7:0]) : led_int; - fpga_core #( .SIM(SIM), .VENDOR(VENDOR), .FAMILY(FAMILY), - .SFP_RATE(SFP_RATE) + .SFP_RATE(SFP_RATE), + .CFG_LOW_LATENCY(CFG_LOW_LATENCY), + .COMBINED_MAC_PCS(COMBINED_MAC_PCS), + .MAC_DATA_W(MAC_DATA_W) ) core_inst ( /* @@ -613,7 +270,7 @@ core_inst ( .btnr(btnr_int), .btnc(btnc_int), .sw(sw_int), - .led(led_int), + .led(led), /* * UART: 115200 bps, 8N1 @@ -628,51 +285,11 @@ core_inst ( */ .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_tx_p(sfp_tx_p), + .sfp_tx_n(sfp_tx_n), .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_rst(sfp0_gmii_rst_int), - .sfp0_gmii_clk_en(sfp0_gmii_clk_en_int), - .sfp0_gmii_rxd(sfp0_gmii_rxd_int), - .sfp0_gmii_rx_dv(sfp0_gmii_rx_dv_int), - .sfp0_gmii_rx_er(sfp0_gmii_rx_er_int), - .sfp0_gmii_txd(sfp0_gmii_txd_int), - .sfp0_gmii_tx_en(sfp0_gmii_tx_en_int), - .sfp0_gmii_tx_er(sfp0_gmii_tx_er_int), - - .sfp1_gmii_clk(sfp1_gmii_clk_int), - .sfp1_gmii_rst(sfp1_gmii_rst_int), - .sfp1_gmii_clk_en(sfp1_gmii_clk_en_int), - .sfp1_gmii_rxd(sfp1_gmii_rxd_int), - .sfp1_gmii_rx_dv(sfp1_gmii_rx_dv_int), - .sfp1_gmii_rx_er(sfp1_gmii_rx_er_int), - .sfp1_gmii_txd(sfp1_gmii_txd_int), - .sfp1_gmii_tx_en(sfp1_gmii_tx_en_int), - .sfp1_gmii_tx_er(sfp1_gmii_tx_er_int), - - .sfp2_gmii_clk(sfp2_gmii_clk_int), - .sfp2_gmii_rst(sfp2_gmii_rst_int), - .sfp2_gmii_clk_en(sfp2_gmii_clk_en_int), - .sfp2_gmii_rxd(sfp2_gmii_rxd_int), - .sfp2_gmii_rx_dv(sfp2_gmii_rx_dv_int), - .sfp2_gmii_rx_er(sfp2_gmii_rx_er_int), - .sfp2_gmii_txd(sfp2_gmii_txd_int), - .sfp2_gmii_tx_en(sfp2_gmii_tx_en_int), - .sfp2_gmii_tx_er(sfp2_gmii_tx_er_int), - - .sfp3_gmii_clk(sfp3_gmii_clk_int), - .sfp3_gmii_rst(sfp3_gmii_rst_int), - .sfp3_gmii_clk_en(sfp3_gmii_clk_en_int), - .sfp3_gmii_rxd(sfp3_gmii_rxd_int), - .sfp3_gmii_rx_dv(sfp3_gmii_rx_dv_int), - .sfp3_gmii_rx_er(sfp3_gmii_rx_er_int), - .sfp3_gmii_txd(sfp3_gmii_txd_int), - .sfp3_gmii_tx_en(sfp3_gmii_tx_en_int), - .sfp3_gmii_tx_er(sfp3_gmii_tx_er_int), - .sfp_tx_disable_b(sfp_tx_disable_b) ); diff --git a/src/eth/example/ZCU102/fpga/rtl/fpga_core.sv b/src/eth/example/ZCU102/fpga/rtl/fpga_core.sv index dd7b8c7..e1d67b1 100644 --- a/src/eth/example/ZCU102/fpga/rtl/fpga_core.sv +++ b/src/eth/example/ZCU102/fpga/rtl/fpga_core.sv @@ -24,7 +24,11 @@ module fpga_core # // device family parameter string FAMILY = "zynquplus", // SFP rate selection (0 for 1G, 1 for 10G) - parameter logic SFP_RATE = 1'b1 + parameter logic SFP_RATE = 1'b1, + // 10G MAC configuration + parameter logic CFG_LOW_LATENCY = 1'b1, + parameter logic COMBINED_MAC_PCS = 1'b1, + parameter MAC_DATA_W = 32 ) ( /* @@ -63,46 +67,6 @@ module fpga_core # 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_rst, - input wire logic sfp0_gmii_clk_en, - input wire logic [7:0] sfp0_gmii_rxd, - input wire logic sfp0_gmii_rx_dv, - input wire logic sfp0_gmii_rx_er, - output wire logic [7:0] sfp0_gmii_txd, - output wire logic sfp0_gmii_tx_en, - output wire logic sfp0_gmii_tx_er, - - input wire logic sfp1_gmii_clk, - input wire logic sfp1_gmii_rst, - input wire logic sfp1_gmii_clk_en, - input wire logic [7:0] sfp1_gmii_rxd, - input wire logic sfp1_gmii_rx_dv, - input wire logic sfp1_gmii_rx_er, - output wire logic [7:0] sfp1_gmii_txd, - output wire logic sfp1_gmii_tx_en, - output wire logic sfp1_gmii_tx_er, - - input wire logic sfp2_gmii_clk, - input wire logic sfp2_gmii_rst, - input wire logic sfp2_gmii_clk_en, - input wire logic [7:0] sfp2_gmii_rxd, - input wire logic sfp2_gmii_rx_dv, - input wire logic sfp2_gmii_rx_er, - output wire logic [7:0] sfp2_gmii_txd, - output wire logic sfp2_gmii_tx_en, - output wire logic sfp2_gmii_tx_er, - - input wire logic sfp3_gmii_clk, - input wire logic sfp3_gmii_rst, - input wire logic sfp3_gmii_clk_en, - input wire logic [7:0] sfp3_gmii_rxd, - input wire logic sfp3_gmii_rx_dv, - input wire logic sfp3_gmii_rx_er, - output wire logic [7:0] sfp3_gmii_txd, - output wire logic sfp3_gmii_tx_en, - output wire logic sfp3_gmii_tx_er, - output wire logic [3:0] sfp_tx_disable_b ); @@ -139,7 +103,7 @@ xfcp_if_uart_inst ( .prescale(16'(125000000/2000000)) ); -localparam XFCP_PORTS = SFP_RATE ? 2 : 1; +localparam XFCP_PORTS = 2; taxi_axis_if #(.DATA_W(8), .USER_EN(1), .USER_W(1)) xfcp_sw_ds[XFCP_PORTS](), xfcp_sw_us[XFCP_PORTS](); @@ -191,7 +155,7 @@ xfcp_stats_inst ( .s_axis_stat(axis_stat) ); -taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(10)) axis_eth_stat[SFP_RATE ? 1 : 4](); +taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(10)) axis_eth_stat[2](); taxi_axis_arb_mux #( .S_COUNT($size(axis_eth_stat)), @@ -217,69 +181,219 @@ stat_mux_inst ( // SFP+ assign sfp_tx_disable_b = '1; +wire sfp_tx_clk[4]; +wire sfp_tx_rst[4]; +wire sfp_rx_clk[4]; +wire sfp_rx_rst[4]; + +wire sfp_rx_status[4]; + +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(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_tx[4](); +taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[4](); +taxi_axis_if #(.DATA_W(MAC_DATA_W), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_rx[4](); + +if (SIM) begin + + 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_GTE4 ibufds_gte4_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_125mhz), + .out(sfp_rst) +); + +taxi_apb_if #( + .ADDR_W(18), + .DATA_W(16) +) +gt_apb_ctrl(); + +taxi_xfcp_mod_apb #( + .XFCP_EXT_ID_STR("GTH CTRL") +) +xfcp_mod_apb_inst ( + .clk(clk_125mhz), + .rst(rst_125mhz), + + /* + * XFCP upstream port + */ + .xfcp_usp_ds(xfcp_sw_ds[1]), + .xfcp_usp_us(xfcp_sw_us[1]), + + /* + * APB master interface + */ + .m_apb(gt_apb_ctrl) +); + if (SFP_RATE == 0) begin : sfp_mac - taxi_axis_if #(.DATA_W(8), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp0_eth(); - taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp0_tx_cpl(); + taxi_eth_mac_1g_basex_us #( + .SIM(SIM), + .VENDOR(VENDOR), + .FAMILY(FAMILY), - taxi_axis_if #(.DATA_W(8), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp1_eth(); - taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp1_tx_cpl(); + .CNT(4), - taxi_axis_if #(.DATA_W(8), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp2_eth(); - taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp2_tx_cpl(); + // GT config + .CFG_LOW_LATENCY(CFG_LOW_LATENCY), - taxi_axis_if #(.DATA_W(8), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp3_eth(); - taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp3_tx_cpl(); + // GT type + .GT_TYPE("GTH"), - taxi_eth_mac_1g_fifo #( + // PHY parameters + .COMBINED_MAC_PCS(COMBINED_MAC_PCS), + .DIC_EN(1'b1), + .PTP_TS_EN(1'b0), + .PTP_TD_EN(1'b0), + .PTP_TS_FMT_TOD(1'b1), + .PTP_TS_W(96), + .PTP_TD_SDI_PIPELINE(2), + .PRBS31_EN(1'b0), + .TX_SERDES_PIPELINE(1), + .RX_SERDES_PIPELINE(1), + .COUNT_125US(125000/6.4), .STAT_EN(1), .STAT_TX_LEVEL(1), .STAT_RX_LEVEL(1), - .STAT_ID_BASE((16+16)*0), + .STAT_ID_BASE(0), .STAT_UPDATE_PERIOD(1024), .STAT_STR_EN(1), - .STAT_PREFIX_STR("SFP0"), - .TX_FIFO_DEPTH(16384), - .TX_FRAME_FIFO(1), - .RX_FIFO_DEPTH(16384), - .RX_FRAME_FIFO(1) + .STAT_PREFIX_STR('{"SFP0", "SFP1", "SFP2", "SFP3"}) ) - sfp0_eth_mac_inst ( - .rx_clk(sfp0_gmii_clk), - .rx_rst(sfp0_gmii_rst), - .tx_clk(sfp0_gmii_clk), - .tx_rst(sfp0_gmii_rst), - .logic_clk(clk_125mhz), - .logic_rst(rst_125mhz), + sfp_mac_inst ( + .xcvr_ctrl_clk(clk_125mhz), + .xcvr_ctrl_rst(sfp_rst), + + /* + * Transceiver control + */ + .s_apb_ctrl(gt_apb_ctrl), + + /* + * Common + */ + .xcvr_gtpowergood_out(sfp_gtpowergood), + .xcvr_gtrefclk00_in(sfp_mgt_refclk_0), + .xcvr_qpll0pd_in(1'b0), + .xcvr_qpll0reset_in(1'b0), + .xcvr_qpll0pcierate_in(3'd0), + .xcvr_qpll0lock_out(), + .xcvr_qpll0clk_out(), + .xcvr_qpll0refclk_out(), + .xcvr_gtrefclk01_in(sfp_mgt_refclk_0), + .xcvr_qpll1pd_in(1'b0), + .xcvr_qpll1reset_in(1'b0), + .xcvr_qpll1pcierate_in(3'd0), + .xcvr_qpll1lock_out(), + .xcvr_qpll1clk_out(), + .xcvr_qpll1refclk_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('{4{1'b0}}), + .rx_rst_out(sfp_rx_rst), + .tx_clk(sfp_tx_clk), + .tx_rst_in('{4{1'b0}}), + .tx_rst_out(sfp_tx_rst), /* * Transmit interface (AXI stream) */ - .s_axis_tx(axis_sfp0_eth), - .m_axis_tx_cpl(axis_sfp0_tx_cpl), + .s_axis_tx(axis_sfp_tx), + .m_axis_tx_cpl(axis_sfp_tx_cpl), /* * Receive interface (AXI stream) */ - .m_axis_rx(axis_sfp0_eth), + .m_axis_rx(axis_sfp_rx), /* - * GMII interface + * PTP clock */ - .gmii_rxd(sfp0_gmii_rxd), - .gmii_rx_dv(sfp0_gmii_rx_dv), - .gmii_rx_er(sfp0_gmii_rx_er), - .gmii_txd(sfp0_gmii_txd), - .gmii_tx_en(sfp0_gmii_tx_en), - .gmii_tx_er(sfp0_gmii_tx_er), + .ptp_clk(1'b0), + .ptp_rst(1'b0), + .ptp_sample_clk(1'b0), + .ptp_td_sdi(1'b0), + .tx_ptp_ts_in('{4{'0}}), + .tx_ptp_ts_out(), + .tx_ptp_ts_step_out(), + .tx_ptp_locked(), + .rx_ptp_ts_in('{4{'0}}), + .rx_ptp_ts_out(), + .rx_ptp_ts_step_out(), + .rx_ptp_locked(), /* - * Control + * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) */ - .rx_clk_enable(sfp0_gmii_clk_en), - .tx_clk_enable(sfp0_gmii_clk_en), - .rx_mii_select(1'b0), - .tx_mii_select(1'b0), + .tx_lfc_req('{4{1'b0}}), + .tx_lfc_resend('{4{1'b0}}), + .rx_lfc_en('{4{1'b0}}), + .rx_lfc_req(), + .rx_lfc_ack('{4{1'b0}}), + + /* + * Priority Flow Control (PFC) (IEEE 802.3 annex 31D PFC) + */ + .tx_pfc_req('{4{'0}}), + .tx_pfc_resend('{4{1'b0}}), + .rx_pfc_en('{4{'0}}), + .rx_pfc_req(), + .rx_pfc_ack('{4{'0}}), + + /* + * Pause interface + */ + .tx_lfc_pause_en('{4{1'b0}}), + .tx_pause_req('{4{1'b0}}), + .tx_pause_ack(), /* * Statistics @@ -291,357 +405,106 @@ if (SFP_RATE == 0) begin : sfp_mac /* * Status */ - .tx_error_underflow(), - .tx_fifo_overflow(), - .tx_fifo_bad_frame(), - .tx_fifo_good_frame(), - .rx_error_bad_frame(), - .rx_error_bad_fcs(), - .rx_fifo_overflow(), - .rx_fifo_bad_frame(), - .rx_fifo_good_frame(), + .tx_start_packet(), + .stat_tx_byte(), + .stat_tx_pkt_len(), + .stat_tx_pkt_ucast(), + .stat_tx_pkt_mcast(), + .stat_tx_pkt_bcast(), + .stat_tx_pkt_vlan(), + .stat_tx_pkt_good(), + .stat_tx_pkt_bad(), + .stat_tx_pad_frame(), + .stat_tx_err_oversize(), + .stat_tx_err_user(), + .stat_tx_err_underflow(), + .rx_start_packet(), + .rx_error_count(), + .rx_block_lock(), + .rx_high_ber(), + .rx_status(sfp_rx_status), + .stat_rx_byte(), + .stat_rx_pkt_len(), + .stat_rx_pkt_fragment(), + .stat_rx_pkt_jabber(), + .stat_rx_pkt_ucast(), + .stat_rx_pkt_mcast(), + .stat_rx_pkt_bcast(), + .stat_rx_pkt_vlan(), + .stat_rx_pkt_good(), + .stat_rx_pkt_bad(), + .stat_rx_err_oversize(), + .stat_rx_err_bad_fcs(), + .stat_rx_err_bad_block(), + .stat_rx_err_framing(), + .stat_rx_err_preamble(), + .stat_rx_fifo_drop('{4{1'b0}}), + .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_tx_pad_en(1'b1), - .cfg_tx_min_pkt_len(8'd60-1), - .cfg_tx_max_pkt_len(16'd9218-1), - .cfg_tx_ifg(8'd12), - .cfg_tx_enable(1'b1), - .cfg_rx_max_pkt_len(16'd9218-1), - .cfg_rx_enable(1'b1) - ); - - taxi_eth_mac_1g_fifo #( - .STAT_EN(1), - .STAT_TX_LEVEL(1), - .STAT_RX_LEVEL(1), - .STAT_ID_BASE((16+16)*1), - .STAT_UPDATE_PERIOD(1024), - .STAT_STR_EN(1), - .STAT_PREFIX_STR("SFP1"), - .TX_FIFO_DEPTH(16384), - .TX_FRAME_FIFO(1), - .RX_FIFO_DEPTH(16384), - .RX_FRAME_FIFO(1) - ) - sfp1_eth_mac_inst ( - .rx_clk(sfp1_gmii_clk), - .rx_rst(sfp1_gmii_rst), - .tx_clk(sfp1_gmii_clk), - .tx_rst(sfp1_gmii_rst), - .logic_clk(clk_125mhz), - .logic_rst(rst_125mhz), - - /* - * Transmit interface (AXI stream) - */ - .s_axis_tx(axis_sfp1_eth), - .m_axis_tx_cpl(axis_sfp1_tx_cpl), - - /* - * Receive interface (AXI stream) - */ - .m_axis_rx(axis_sfp1_eth), - - /* - * GMII interface - */ - .gmii_rxd(sfp1_gmii_rxd), - .gmii_rx_dv(sfp1_gmii_rx_dv), - .gmii_rx_er(sfp1_gmii_rx_er), - .gmii_txd(sfp1_gmii_txd), - .gmii_tx_en(sfp1_gmii_tx_en), - .gmii_tx_er(sfp1_gmii_tx_er), - - /* - * Control - */ - .rx_clk_enable(sfp1_gmii_clk_en), - .tx_clk_enable(sfp1_gmii_clk_en), - .rx_mii_select(1'b0), - .tx_mii_select(1'b0), - - /* - * Statistics - */ - .stat_clk(clk_125mhz), - .stat_rst(rst_125mhz), - .m_axis_stat(axis_eth_stat[1]), - - /* - * Status - */ - .tx_error_underflow(), - .tx_fifo_overflow(), - .tx_fifo_bad_frame(), - .tx_fifo_good_frame(), - .rx_error_bad_frame(), - .rx_error_bad_fcs(), - .rx_fifo_overflow(), - .rx_fifo_bad_frame(), - .rx_fifo_good_frame(), - - /* - * Configuration - */ - .cfg_tx_pad_en(1'b1), - .cfg_tx_min_pkt_len(8'd60-1), - .cfg_tx_max_pkt_len(16'd9218-1), - .cfg_tx_ifg(8'd12), - .cfg_tx_enable(1'b1), - .cfg_rx_max_pkt_len(16'd9218-1), - .cfg_rx_enable(1'b1) - ); - - taxi_eth_mac_1g_fifo #( - .STAT_EN(1), - .STAT_TX_LEVEL(1), - .STAT_RX_LEVEL(1), - .STAT_ID_BASE((16+16)*2), - .STAT_UPDATE_PERIOD(1024), - .STAT_STR_EN(1), - .STAT_PREFIX_STR("SFP2"), - .TX_FIFO_DEPTH(16384), - .TX_FRAME_FIFO(1), - .RX_FIFO_DEPTH(16384), - .RX_FRAME_FIFO(1) - ) - sfp2_eth_mac_inst ( - .rx_clk(sfp2_gmii_clk), - .rx_rst(sfp2_gmii_rst), - .tx_clk(sfp2_gmii_clk), - .tx_rst(sfp2_gmii_rst), - .logic_clk(clk_125mhz), - .logic_rst(rst_125mhz), - - /* - * Transmit interface (AXI stream) - */ - .s_axis_tx(axis_sfp2_eth), - .m_axis_tx_cpl(axis_sfp2_tx_cpl), - - /* - * Receive interface (AXI stream) - */ - .m_axis_rx(axis_sfp2_eth), - - /* - * GMII interface - */ - .gmii_rxd(sfp2_gmii_rxd), - .gmii_rx_dv(sfp2_gmii_rx_dv), - .gmii_rx_er(sfp2_gmii_rx_er), - .gmii_txd(sfp2_gmii_txd), - .gmii_tx_en(sfp2_gmii_tx_en), - .gmii_tx_er(sfp2_gmii_tx_er), - - /* - * Control - */ - .rx_clk_enable(sfp2_gmii_clk_en), - .tx_clk_enable(sfp2_gmii_clk_en), - .rx_mii_select(1'b0), - .tx_mii_select(1'b0), - - /* - * Statistics - */ - .stat_clk(clk_125mhz), - .stat_rst(rst_125mhz), - .m_axis_stat(axis_eth_stat[2]), - - /* - * Status - */ - .tx_error_underflow(), - .tx_fifo_overflow(), - .tx_fifo_bad_frame(), - .tx_fifo_good_frame(), - .rx_error_bad_frame(), - .rx_error_bad_fcs(), - .rx_fifo_overflow(), - .rx_fifo_bad_frame(), - .rx_fifo_good_frame(), - - /* - * Configuration - */ - .cfg_tx_pad_en(1'b1), - .cfg_tx_min_pkt_len(8'd60-1), - .cfg_tx_max_pkt_len(16'd9218-1), - .cfg_tx_ifg(8'd12), - .cfg_tx_enable(1'b1), - .cfg_rx_max_pkt_len(16'd9218-1), - .cfg_rx_enable(1'b1) - ); - - taxi_eth_mac_1g_fifo #( - .STAT_EN(1), - .STAT_TX_LEVEL(1), - .STAT_RX_LEVEL(1), - .STAT_ID_BASE((16+16)*3), - .STAT_UPDATE_PERIOD(1024), - .STAT_STR_EN(1), - .STAT_PREFIX_STR("SFP3"), - .TX_FIFO_DEPTH(16384), - .TX_FRAME_FIFO(1), - .RX_FIFO_DEPTH(16384), - .RX_FRAME_FIFO(1) - ) - sfp3_eth_mac_inst ( - .rx_clk(sfp3_gmii_clk), - .rx_rst(sfp3_gmii_rst), - .tx_clk(sfp3_gmii_clk), - .tx_rst(sfp3_gmii_rst), - .logic_clk(clk_125mhz), - .logic_rst(rst_125mhz), - - /* - * Transmit interface (AXI stream) - */ - .s_axis_tx(axis_sfp3_eth), - .m_axis_tx_cpl(axis_sfp3_tx_cpl), - - /* - * Receive interface (AXI stream) - */ - .m_axis_rx(axis_sfp3_eth), - - /* - * GMII interface - */ - .gmii_rxd(sfp3_gmii_rxd), - .gmii_rx_dv(sfp3_gmii_rx_dv), - .gmii_rx_er(sfp3_gmii_rx_er), - .gmii_txd(sfp3_gmii_txd), - .gmii_tx_en(sfp3_gmii_tx_en), - .gmii_tx_er(sfp3_gmii_tx_er), - - /* - * Control - */ - .rx_clk_enable(sfp3_gmii_clk_en), - .tx_clk_enable(sfp3_gmii_clk_en), - .rx_mii_select(1'b0), - .tx_mii_select(1'b0), - - /* - * Statistics - */ - .stat_clk(clk_125mhz), - .stat_rst(rst_125mhz), - .m_axis_stat(axis_eth_stat[3]), - - /* - * Status - */ - .tx_error_underflow(), - .tx_fifo_overflow(), - .tx_fifo_bad_frame(), - .tx_fifo_good_frame(), - .rx_error_bad_frame(), - .rx_error_bad_fcs(), - .rx_fifo_overflow(), - .rx_fifo_bad_frame(), - .rx_fifo_good_frame(), - - /* - * Configuration - */ - .cfg_tx_pad_en(1'b1), - .cfg_tx_min_pkt_len(8'd60-1), - .cfg_tx_max_pkt_len(16'd9218-1), - .cfg_tx_ifg(8'd12), - .cfg_tx_enable(1'b1), - .cfg_rx_max_pkt_len(16'd9218-1), - .cfg_rx_enable(1'b1) + .cfg_tx_pad_en('{4{1'b1}}), + .cfg_tx_min_pkt_len('{4{8'd60-1}}), + .cfg_tx_max_pkt_len('{4{16'd9218-1}}), + .cfg_tx_ifg('{4{8'd12}}), + .cfg_tx_enable('{4{1'b1}}), + .cfg_rx_max_pkt_len('{4{16'd9218-1}}), + .cfg_rx_enable('{4{1'b1}}), + .cfg_tx_prbs31_enable('{4{1'b0}}), + .cfg_rx_prbs31_enable('{4{1'b0}}), + .cfg_mcf_rx_eth_dst_mcast('{4{48'h01_80_C2_00_00_01}}), + .cfg_mcf_rx_check_eth_dst_mcast('{4{1'b1}}), + .cfg_mcf_rx_eth_dst_ucast('{4{48'd0}}), + .cfg_mcf_rx_check_eth_dst_ucast('{4{1'b0}}), + .cfg_mcf_rx_eth_src('{4{48'd0}}), + .cfg_mcf_rx_check_eth_src('{4{1'b0}}), + .cfg_mcf_rx_eth_type('{4{16'h8808}}), + .cfg_mcf_rx_opcode_lfc('{4{16'h0001}}), + .cfg_mcf_rx_check_opcode_lfc('{4{1'b1}}), + .cfg_mcf_rx_opcode_pfc('{4{16'h0101}}), + .cfg_mcf_rx_check_opcode_pfc('{4{1'b1}}), + .cfg_mcf_rx_forward('{4{1'b0}}), + .cfg_mcf_rx_enable('{4{1'b0}}), + .cfg_tx_lfc_eth_dst('{4{48'h01_80_C2_00_00_01}}), + .cfg_tx_lfc_eth_src('{4{48'h80_23_31_43_54_4C}}), + .cfg_tx_lfc_eth_type('{4{16'h8808}}), + .cfg_tx_lfc_opcode('{4{16'h0001}}), + .cfg_tx_lfc_en('{4{1'b0}}), + .cfg_tx_lfc_quanta('{4{16'hffff}}), + .cfg_tx_lfc_refresh('{4{16'h7fff}}), + .cfg_tx_pfc_eth_dst('{4{48'h01_80_C2_00_00_01}}), + .cfg_tx_pfc_eth_src('{4{48'h80_23_31_43_54_4C}}), + .cfg_tx_pfc_eth_type('{4{16'h8808}}), + .cfg_tx_pfc_opcode('{4{16'h0101}}), + .cfg_tx_pfc_en('{4{1'b0}}), + .cfg_tx_pfc_quanta('{4{'{8{16'hffff}}}}), + .cfg_tx_pfc_refresh('{4{'{8{16'h7fff}}}}), + .cfg_rx_lfc_opcode('{4{16'h0001}}), + .cfg_rx_lfc_en('{4{1'b0}}), + .cfg_rx_pfc_opcode('{4{16'h0101}}), + .cfg_rx_pfc_en('{4{1'b0}}) ); end else begin : sfp_mac - wire sfp_tx_clk[4]; - wire sfp_tx_rst[4]; - wire sfp_rx_clk[4]; - wire sfp_rx_rst[4]; - - wire sfp_rx_status[4]; - - 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(32), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_tx[4](); - taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_W(8)) axis_sfp_tx_cpl[4](); - taxi_axis_if #(.DATA_W(32), .ID_W(8), .USER_EN(1), .USER_W(1)) axis_sfp_rx[4](); - - if (SIM) begin - - 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_GTE4 ibufds_gte4_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_125mhz), - .out(sfp_rst) - ); - - taxi_apb_if #( - .ADDR_W(18), - .DATA_W(16) - ) - gt_apb_ctrl(); - - taxi_xfcp_mod_apb #( - .XFCP_EXT_ID_STR("GTH CTRL") - ) - xfcp_mod_apb_inst ( - .clk(clk_125mhz), - .rst(rst_125mhz), - - /* - * XFCP upstream port - */ - .xfcp_usp_ds(xfcp_sw_ds[1]), - .xfcp_usp_us(xfcp_sw_us[1]), - - /* - * APB master interface - */ - .m_apb(gt_apb_ctrl) - ); - taxi_eth_mac_25g_us #( .SIM(SIM), .VENDOR(VENDOR), @@ -650,12 +513,13 @@ end else begin : sfp_mac .CNT(4), // GT config - .CFG_LOW_LATENCY(1), + .CFG_LOW_LATENCY(CFG_LOW_LATENCY), // GT type .GT_TYPE("GTH"), // PHY parameters + .COMBINED_MAC_PCS(COMBINED_MAC_PCS), .DATA_W(axis_sfp_tx[0].DATA_W), .DIC_EN(1'b1), .PTP_TS_EN(1'b0), @@ -881,57 +745,57 @@ end else begin : sfp_mac .cfg_rx_pfc_en('{4{1'b0}}) ); - for (genvar n = 0; n < 4; n = n + 1) begin : sfp_ch +end - 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]), +for (genvar n = 0; n < $size(axis_sfp_tx); n = n + 1) begin : sfp_ch - /* - * AXI4-Stream output (source) - */ - .m_clk(sfp_tx_clk[n]), - .m_rst(sfp_tx_rst[n]), - .m_axis(axis_sfp_tx[n]), + 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]), - /* - * Pause - */ - .s_pause_req(1'b0), - .s_pause_ack(), - .m_pause_req(1'b0), - .m_pause_ack(), + /* + * AXI4-Stream output (source) + */ + .m_clk(sfp_tx_clk[n]), + .m_rst(sfp_tx_rst[n]), + .m_axis(axis_sfp_tx[n]), - /* - * 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() - ); + /* + * Pause + */ + .s_pause_req(1'b0), + .s_pause_ack(), + .m_pause_req(1'b0), + .m_pause_ack(), - end + /* + * 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 diff --git a/src/eth/example/ZCU102/fpga/tb/fpga_core/Makefile b/src/eth/example/ZCU102/fpga/tb/fpga_core/Makefile index f51c242..34d9959 100644 --- a/src/eth/example/ZCU102/fpga/tb/fpga_core/Makefile +++ b/src/eth/example/ZCU102/fpga/tb/fpga_core/Makefile @@ -25,6 +25,7 @@ TOPLEVEL = $(COCOTB_TOPLEVEL) VERILOG_SOURCES += $(RTL_DIR)/$(DUT).sv VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/taxi_eth_mac_1g_fifo.f VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_25g_us.f +VERILOG_SOURCES += $(TAXI_SRC_DIR)/eth/rtl/us/taxi_eth_mac_1g_basex_us.f VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_if_uart.f VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_switch.sv VERILOG_SOURCES += $(TAXI_SRC_DIR)/xfcp/rtl/taxi_xfcp_mod_apb.f @@ -44,6 +45,9 @@ export PARAM_SIM := "1'b1" export PARAM_VENDOR := "\"XILINX\"" export PARAM_FAMILY := "\"zynquplus\"" export PARAM_SFP_RATE := "1'b1" +export PARAM_CFG_LOW_LATENCY := "1'b1" +export PARAM_COMBINED_MAC_PCS := "1'b1" +export PARAM_MAC_DATA_W := "32" ifeq ($(SIM), icarus) PLUSARGS += -fst diff --git a/src/eth/example/ZCU102/fpga/tb/fpga_core/basex.py b/src/eth/example/ZCU102/fpga/tb/fpga_core/basex.py new file mode 120000 index 0000000..b976cc4 --- /dev/null +++ b/src/eth/example/ZCU102/fpga/tb/fpga_core/basex.py @@ -0,0 +1 @@ +../../lib/taxi/src/eth/tb/basex.py \ No newline at end of file diff --git a/src/eth/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py b/src/eth/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py index aea0b23..10c8361 100644 --- a/src/eth/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py +++ b/src/eth/example/ZCU102/fpga/tb/fpga_core/test_fpga_core.py @@ -20,17 +20,19 @@ import cocotb from cocotb.clock import Clock from cocotb.triggers import RisingEdge, Combine -from cocotbext.eth import GmiiFrame, GmiiSource, GmiiSink +from cocotbext.eth import GmiiSource, GmiiSink from cocotbext.eth import XgmiiFrame from cocotbext.uart import UartSource, UartSink try: from baser import BaseRSerdesSource, BaseRSerdesSink + from basex import BaseXSerdesSource, BaseXSerdesSink except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: from baser import BaseRSerdesSource, BaseRSerdesSink + from basex import BaseXSerdesSource, BaseXSerdesSink finally: del sys.path[0] @@ -47,43 +49,55 @@ class TB: self.sfp_sources = [] self.sfp_sinks = [] - if dut.SFP_RATE.value == 0: - cocotb.start_soon(Clock(dut.sfp0_gmii_clk, 8, units="ns").start()) - cocotb.start_soon(Clock(dut.sfp1_gmii_clk, 8, units="ns").start()) - cocotb.start_soon(Clock(dut.sfp2_gmii_clk, 8, units="ns").start()) - cocotb.start_soon(Clock(dut.sfp3_gmii_clk, 8, units="ns").start()) + cocotb.start_soon(Clock(dut.sfp_mgt_refclk_0_p, 6.4, units="ns").start()) - 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)) - - self.sfp_sources.append(GmiiSource(dut.sfp2_gmii_rxd, dut.sfp2_gmii_rx_er, dut.sfp2_gmii_rx_dv, - dut.sfp2_gmii_clk, dut.sfp2_gmii_rst, dut.sfp2_gmii_clk_en)) - self.sfp_sinks.append(GmiiSink(dut.sfp2_gmii_txd, dut.sfp2_gmii_tx_er, dut.sfp2_gmii_tx_en, - dut.sfp2_gmii_clk, dut.sfp2_gmii_rst, dut.sfp2_gmii_clk_en)) - - self.sfp_sources.append(GmiiSource(dut.sfp3_gmii_rxd, dut.sfp3_gmii_rx_er, dut.sfp3_gmii_rx_dv, - dut.sfp3_gmii_clk, dut.sfp3_gmii_rst, dut.sfp3_gmii_clk_en)) - self.sfp_sinks.append(GmiiSink(dut.sfp3_gmii_txd, dut.sfp3_gmii_tx_er, dut.sfp3_gmii_tx_en, - dut.sfp3_gmii_clk, dut.sfp3_gmii_rst, dut.sfp3_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: - gt_inst = ch.ch_inst.gt.gt_inst + for ch in dut.sfp_mac.sfp_mac_inst.ch: + gt_inst = ch.ch_inst.gt.gt_inst + if dut.SFP_RATE.value == 0: if ch.ch_inst.CFG_LOW_LATENCY.value: - clk = 3.102 - gbx_cfg = (66, [64, 65]) - else: - clk = 3.2 + clk = 16 gbx_cfg = None + else: + clk = 16 + gbx_cfg = None + + cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start()) + cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start()) + + self.sfp_sources.append(BaseXSerdesSource( + data=gt_inst.serdes_rx_data, + data_k=gt_inst.serdes_rx_data_k, + data_valid=gt_inst.serdes_rx_data_valid, + clock=gt_inst.rx_clk, + enc_8b10b=False, + gbx_cfg=gbx_cfg + )) + self.sfp_sinks.append(BaseXSerdesSink( + data=gt_inst.serdes_tx_data, + data_k=gt_inst.serdes_tx_data_k, + data_valid=gt_inst.serdes_tx_data_valid, + gbx_sync=gt_inst.serdes_tx_gbx_sync, + clock=gt_inst.tx_clk, + dec_8b10b=False, + gbx_cfg=gbx_cfg + )) + + else: + if ch.ch_inst.DATA_W.value == 64: + if ch.ch_inst.CFG_LOW_LATENCY.value: + clk = 6.206 + gbx_cfg = (66, [64, 65]) + else: + clk = 6.4 + gbx_cfg = None + else: + if ch.ch_inst.CFG_LOW_LATENCY.value: + clk = 3.102 + gbx_cfg = (66, [64, 65]) + else: + clk = 3.2 + gbx_cfg = None cocotb.start_soon(Clock(gt_inst.tx_clk, clk, units="ns").start()) cocotb.start_soon(Clock(gt_inst.rx_clk, clk, units="ns").start()) @@ -123,28 +137,16 @@ class TB: async def init(self): self.dut.rst_125mhz.setimmediatevalue(0) - self.dut.sfp0_gmii_rst.setimmediatevalue(0) - self.dut.sfp1_gmii_rst.setimmediatevalue(0) - self.dut.sfp2_gmii_rst.setimmediatevalue(0) - self.dut.sfp3_gmii_rst.setimmediatevalue(0) for k in range(10): await RisingEdge(self.dut.clk_125mhz) self.dut.rst_125mhz.value = 1 - self.dut.sfp0_gmii_rst.value = 1 - self.dut.sfp1_gmii_rst.value = 1 - self.dut.sfp2_gmii_rst.value = 1 - self.dut.sfp3_gmii_rst.value = 1 for k in range(10): await RisingEdge(self.dut.clk_125mhz) self.dut.rst_125mhz.value = 0 - self.dut.sfp0_gmii_rst.value = 0 - self.dut.sfp1_gmii_rst.value = 0 - self.dut.sfp2_gmii_rst.value = 0 - self.dut.sfp3_gmii_rst.value = 0 for k in range(10): await RisingEdge(self.dut.clk_125mhz) @@ -153,51 +155,7 @@ class TB: async def mac_test(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(GmiiFrame.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() - assert rx_frame.error is None - - 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(GmiiFrame.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() - assert rx_frame.error is None - - tb.log.info("MAC test done") - - -async def mac_test_10g(tb, source, sink): - tb.log.info("Test MAC") - - tb.log.info("Wait for block lock") - for k in range(1200): - await RisingEdge(tb.dut.clk_125mhz) + sink.clear() tb.log.info("Multiple small packets") @@ -245,13 +203,13 @@ async def run_test(dut): tests = [] + tb.log.info("Wait for block lock") + for k in range(1200): + await RisingEdge(dut.clk_125mhz) + 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_10g(tb, tb.sfp_sources[k], tb.sfp_sinks[k]))) + tb.log.info("Start SFP %d MAC loopback test", k) + tests.append(cocotb.start_soon(mac_test(tb, tb.sfp_sources[k], tb.sfp_sinks[k]))) await Combine(*tests) @@ -280,8 +238,8 @@ def process_f_files(files): return list(lst.values()) -@pytest.mark.parametrize("sfp_rate", [0, 1]) -def test_fpga_core(request, sfp_rate): +@pytest.mark.parametrize(("sfp_rate", "mac_data_w"), [(0, 16), (1, 32), (1, 64)]) +def test_fpga_core(request, sfp_rate, mac_data_w): dut = "fpga_core" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = dut @@ -290,6 +248,7 @@ def test_fpga_core(request, sfp_rate): os.path.join(rtl_dir, f"{dut}.sv"), os.path.join(taxi_src_dir, "eth", "rtl", "taxi_eth_mac_1g_fifo.f"), os.path.join(taxi_src_dir, "eth", "rtl", "us", "taxi_eth_mac_25g_us.f"), + os.path.join(taxi_src_dir, "eth", "rtl", "us", "taxi_eth_mac_1g_basex_us.f"), os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_if_uart.f"), os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_switch.sv"), os.path.join(taxi_src_dir, "xfcp", "rtl", "taxi_xfcp_mod_apb.f"), @@ -307,6 +266,9 @@ def test_fpga_core(request, sfp_rate): parameters['VENDOR'] = "\"XILINX\"" parameters['FAMILY'] = "\"zynquplus\"" parameters['SFP_RATE'] = f"1'b{sfp_rate}" + parameters['CFG_LOW_LATENCY'] = "1'b1" + parameters['COMBINED_MAC_PCS'] = "1'b1" + parameters['MAC_DATA_W'] = mac_data_w extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}