From 9fceda71e6329ae7b00e4cee4698fa906ba33462 Mon Sep 17 00:00:00 2001 From: Evan Sun Date: Thu, 9 Apr 2026 08:18:40 -0400 Subject: [PATCH 1/2] Set the default sim profile to use xsim to follow the makefile usage guide --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6361127..7d1314d 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ OPT_MODE?=batch OPT_PROFILE?= OPT_SIM_FILES ?= false -OPT_TOOL?= +OPT_TOOL?=xsim OPT_TOP?= OPT_TEST?= OPT_ARGS?=0 From 432a2735535bfe7c3b82bdf8751d1363d3f11739 Mon Sep 17 00:00:00 2001 From: Evan Sun Date: Mon, 11 May 2026 15:19:14 -0400 Subject: [PATCH 2/2] add ZCU111 board support --- Makefile | 1 + config.json | 29 ++++ example_designs/zcu111/src.f | 2 + .../zcu111/src/qeciphy_syn_wrapper.sv | 156 ++++++++++++++++++ example_designs/zcu111/syn/constraints.xdc | 46 ++++++ 5 files changed, 234 insertions(+) create mode 100644 example_designs/zcu111/src.f create mode 100644 example_designs/zcu111/src/qeciphy_syn_wrapper.sv create mode 100644 example_designs/zcu111/syn/constraints.xdc diff --git a/Makefile b/Makefile index 7d1314d..b9373f0 100644 --- a/Makefile +++ b/Makefile @@ -188,6 +188,7 @@ get_gt_type = $(shell \ if [ "$(OPT_PROFILE)" = "kasliSoC" ]; then echo "GTX"; \ elif [ "$(OPT_PROFILE)" = "zcu106" ]; then echo "GTH"; \ elif [ "$(OPT_PROFILE)" = "zcu216" ]; then echo "GTY"; \ + elif [ "$(OPT_PROFILE)" = "zcu111" ]; then echo "GTY"; \ else echo "GTY"; fi) # ------------------------------------------------------------- diff --git a/config.json b/config.json index 82b2768..c3c910b 100644 --- a/config.json +++ b/config.json @@ -58,6 +58,35 @@ ] } }, + "zcu111": { + "device": { + "part": "xczu28dr-ffvg1517-2-e", + "vendor": "xilinx" + }, + "board": "xilinx.com:zcu111:part0:1.4", + "variant": "GTY", + "fclk_freq": "156.25", + "rclk_freq": "156.25", + "transceiver": { + "gt_loc": "X0Y8", + "rx_rclk_src": "X0Y8 clk1+1", + "tx_rclk_src": "X0Y8 clk1+1", + "line_rate_gbps": "10.3125" + }, + "synth": { + "top": "qeciphy_syn_wrapper", + "filelists": [ + "example_designs/zcu111/src.f" + ], + "constraints": [ + "example_designs/zcu111/syn/constraints.xdc" + ], + "pre_setup_hooks": [ + "example_designs/vendors/xilinx/qeciphy_rx_ila.tcl", + "example_designs/vendors/xilinx/qeciphy_vio.tcl" + ] + } + }, "kasliSoC": { "device": { "part": "xc7z030ffg676-3", diff --git a/example_designs/zcu111/src.f b/example_designs/zcu111/src.f new file mode 100644 index 0000000..751c8b2 --- /dev/null +++ b/example_designs/zcu111/src.f @@ -0,0 +1,2 @@ +-F src.f +example_designs/zcu111/src/qeciphy_syn_wrapper.sv diff --git a/example_designs/zcu111/src/qeciphy_syn_wrapper.sv b/example_designs/zcu111/src/qeciphy_syn_wrapper.sv new file mode 100644 index 0000000..0dfdc06 --- /dev/null +++ b/example_designs/zcu111/src/qeciphy_syn_wrapper.sv @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright (c) 2025 Riverlane Ltd. +// Original authors: Aniket Datta, Gargi Sunil + +module qeciphy_syn_wrapper ( + input logic gt_refclk_in_p, + input logic gt_refclk_in_n, + input logic gt_rx_p, + input logic gt_rx_n, + output logic gt_tx_p, + output logic gt_tx_n, + output logic [3:0] SFP_tx_enable, + output logic [2:0] led +); + + // Signal declarations + logic RCLK; + logic FCLK; + logic ACLK; + logic ARSTn; + logic [63:0] TX_TDATA; + logic [63:0] TX_TDATA_nxt; + logic TX_TVALID; + logic TX_TREADY; + logic [63:0] RX_TDATA; + logic RX_TVALID; + logic RX_TREADY; + logic [ 3:0] STATUS; + logic [ 3:0] ECODE; + logic [ 4:0] rst_counter; + logic [ 4:0] rst_counter_nxt; + logic rst_n_async; + logic [ 1:0] rst_n_sf; + logic rst_n; + logic clk_freerun; + logic [ 3:0] sfp_enable; + logic [63:0] RX_TDATA_ref; + logic [63:0] RX_TDATA_ref_nxt; + logic RXDATA_error; + logic RXDATA_error_nxt; + + assign SFP_tx_enable = sfp_enable; + + // Refer: https://docs.amd.com/r/en-US/ug974-vivado-ultrascale-libraries/IBUFDS_GTE4 + IBUFDS_GTE4 #( + .REFCLK_EN_TX_PATH(1'b0), + .REFCLK_HROW_CK_SEL(2'b00), + .REFCLK_ICNTL_RX(2'b00) + ) i_buff_gtrefclk ( + .O (RCLK), + .ODIV2(clk_freerun), + .CEB (1'b0), + .I (gt_refclk_in_p), + .IB (gt_refclk_in_n) + ); + + BUFG_GT i_buff_fclk ( + .O (FCLK), + .CE (1'b1), + .CEMASK (1'b1), + .CLR (1'b0), + .CLRMASK(1'b1), + .DIV (3'b000), + .I (clk_freerun) + ); + + qeciphy_rx_ila i_rx_ila ( + .clk (ACLK), + .probe0(RX_TDATA), + .probe1(RX_TVALID), + .probe2(STATUS), + .probe3(ECODE), + .probe4(sfp_enable), + .probe5(RXDATA_error) + ); + + qeciphy_vio i_vio ( + .clk (ACLK), + .probe_out0(rst_n_async), + .probe_out1(sfp_enable) + ); + + // Generate 16 cycle reset that de-asserts synchronously + assign ARSTn = rst_counter[4]; + assign rst_counter_nxt = ARSTn ? rst_counter : rst_counter + 5'h1; + assign rst_n = rst_n_sf[1]; + + always_ff @(posedge ACLK or negedge rst_n) begin + if (!rst_n) rst_counter <= 5'h0; + else rst_counter <= rst_counter_nxt; + end + + always_ff @(posedge ACLK) begin + if (!rst_n_async) rst_n_sf <= 2'h0; + else rst_n_sf <= {rst_n_sf[0], 1'b1}; + end + + // Connect free-running clock to AXI clock for simplicity + assign ACLK = FCLK; + + // By the spec + assign RX_TREADY = 1'b1; + + // For debugging + assign led[0] = (STATUS == 4'b0100) ? 1'b1 : 1'b0; + assign led[1] = (ECODE == 4'b0000) ? 1'b1 : 1'b0; + assign led[2] = ~RXDATA_error; + + // Drive the transmitter QECI-PHY TX data pins + always_ff @(posedge FCLK or negedge ARSTn) begin + if (!ARSTn) TX_TVALID <= 1'b0; + else TX_TVALID <= 1'b1; + end + + assign TX_TDATA_nxt = TX_TREADY ? TX_TDATA + 64'h1 : TX_TDATA; + + always_ff @(posedge FCLK or negedge ARSTn) begin + if (!ARSTn) TX_TDATA <= 'h0; + else TX_TDATA <= TX_TDATA_nxt; + end + + // Verify receiver data + assign RX_TDATA_ref_nxt = RX_TVALID ? RX_TDATA_ref + 64'h1 : RX_TDATA_ref; + + always_ff @(posedge FCLK or negedge ARSTn) begin + if (!ARSTn) RX_TDATA_ref <= 'h0; + else RX_TDATA_ref <= RX_TDATA_ref_nxt; + end + + assign RXDATA_error_nxt = RX_TVALID ? (RX_TDATA_ref != RX_TDATA) : RXDATA_error; + + always_ff @(posedge FCLK or negedge ARSTn) begin + if (!ARSTn) RXDATA_error <= 'h0; + else RXDATA_error <= RXDATA_error_nxt; + end + + QECIPHY i_QECIPHY ( + .RCLK (RCLK), + .FCLK (FCLK), + .ACLK (ACLK), + .ARSTn (ARSTn), + .TX_TDATA (TX_TDATA), + .TX_TVALID(TX_TVALID), + .TX_TREADY(TX_TREADY), + .RX_TDATA (RX_TDATA), + .RX_TVALID(RX_TVALID), + .RX_TREADY(RX_TREADY), + .STATUS (STATUS), + .ECODE (ECODE), + .GT_RX_P (gt_rx_p), + .GT_RX_N (gt_rx_n), + .GT_TX_P (gt_tx_p), + .GT_TX_N (gt_tx_n) + ); + +endmodule diff --git a/example_designs/zcu111/syn/constraints.xdc b/example_designs/zcu111/syn/constraints.xdc new file mode 100644 index 0000000..49c7140 --- /dev/null +++ b/example_designs/zcu111/syn/constraints.xdc @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: BSD-2-Clause +# Copyright (c) 2025 Riverlane Ltd. +# Original authors: Dogancan Davutoglu, Aniket Datta, Gargi Sunil + +create_clock -period 6.400 -name gt_refclk [get_ports gt_refclk_in_p] +set_property PACKAGE_PIN W33 [get_ports gt_refclk_in_p] + +# ------------------------------------------------------------------------- +# QECIPHY instance 0 clocks +# ------------------------------------------------------------------------- +create_generated_clock -name rx_clk [get_pins -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/gen_GTY_transceiver.i_BUFG_rx_clk/O}] +create_generated_clock -name gt_rx_clk [get_pins -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper*channel_inst/gtye4_channel_gen.gen_gtye4_channel_inst[0].GTYE4_CHANNEL_PRIM_INST/RXOUTCLK}] +create_generated_clock -name tx_clk [get_pins -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/gen_GTY_transceiver.i_BUFG_tx_clk/O}] +create_generated_clock -name gt_tx_clk [get_pins -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper*channel_inst/gtye4_channel_gen.gen_gtye4_channel_inst[0].GTYE4_CHANNEL_PRIM_INST/TXOUTCLK}] + +set_clock_groups -asynchronous -group [get_clocks gt_refclk] -group [get_clocks {rx_clk gt_rx_clk}] -group [get_clocks {tx_clk gt_tx_clk}] +set_property CLOCK_DELAY_GROUP rx_clk_dly_grp [get_nets -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/rx_clk_o || NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/rx_clk_2x_o}] +set_property CLOCK_DELAY_GROUP tx_clk_dly_grp [get_nets -hierarchical -filter {NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/tx_clk_o || NAME =~ *i_QECIPHY/i_qeciphy_serdes/i_qeciphy_gt_wrapper/tx_clk_2x_o}] + +#Define multicycle path between sync clocks +set_multicycle_path -setup -end -from [get_clocks rx_clk] -to [get_clocks gt_rx_clk] 2 +set_multicycle_path -hold -end -from [get_clocks rx_clk] -to [get_clocks gt_rx_clk] 1 +set_multicycle_path -setup -start -from [get_clocks gt_rx_clk] -to [get_clocks rx_clk] 2 +set_multicycle_path -hold -start -from [get_clocks gt_rx_clk] -to [get_clocks rx_clk] 1 +set_multicycle_path -setup -end -from [get_clocks tx_clk] -to [get_clocks gt_tx_clk] 2 +set_multicycle_path -hold -end -from [get_clocks tx_clk] -to [get_clocks gt_tx_clk] 1 +set_multicycle_path -setup -start -from [get_clocks gt_tx_clk] -to [get_clocks tx_clk] 2 +set_multicycle_path -hold -start -from [get_clocks gt_tx_clk] -to [get_clocks tx_clk] 1 + +set_property IOSTANDARD LVCMOS18 [get_ports {led[0]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led[1]}] +set_property IOSTANDARD LVCMOS18 [get_ports {led[2]}] + +set_property PACKAGE_PIN AR13 [get_ports {led[0]}] +set_property PACKAGE_PIN AP13 [get_ports {led[1]}] +set_property PACKAGE_PIN AR16 [get_ports {led[2]}] + +set_property IOSTANDARD LVCMOS12 [get_ports {SFP_tx_enable[0]}] +set_property IOSTANDARD LVCMOS12 [get_ports {SFP_tx_enable[1]}] +set_property IOSTANDARD LVCMOS12 [get_ports {SFP_tx_enable[2]}] +set_property IOSTANDARD LVCMOS12 [get_ports {SFP_tx_enable[3]}] + +set_property PACKAGE_PIN G12 [get_ports {SFP_tx_enable[0]}] +set_property PACKAGE_PIN G10 [get_ports {SFP_tx_enable[1]}] +set_property PACKAGE_PIN K12 [get_ports {SFP_tx_enable[2]}] +set_property PACKAGE_PIN J7 [get_ports {SFP_tx_enable[3]}]