1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-16 08:12:53 +08:00

merged changes in eth

This commit is contained in:
Alex Forencich 2023-12-02 01:30:49 -08:00
commit 1ca0151b97
95 changed files with 2416 additions and 5186 deletions

View File

@ -55,6 +55,8 @@ following boards:
* Intel Stratix 10 DX dev kit (Intel Stratix 10 DX 1SD280PT2F55E1VG)
* Intel Stratix 10 MX dev kit (Intel Stratix 10 MX 1SM21CHU1F53E1VG)
* Xilinx Alveo U50 (Xilinx Virtex UltraScale+ XCU50)
* Xilinx Alveo U55C (Xilinx Virtex UltraScale+ XCU55C)
* Xilinx Alveo U55N/Varium C1100 (Xilinx Virtex UltraScale+ XCU55N)
* Xilinx Alveo U200 (Xilinx Virtex UltraScale+ XCU200)
* Xilinx Alveo U250 (Xilinx Virtex UltraScale+ XCU250)
* Xilinx Alveo U280 (Xilinx Virtex UltraScale+ XCU280)

View File

@ -1,670 +0,0 @@
/*
Copyright (c) 2014-2021 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [3:0] sw,
output wire [2:0] led,
/*
* Ethernet: QSFP28
*/
input wire qsfp0_tx_clk_1,
input wire qsfp0_tx_rst_1,
output wire [63:0] qsfp0_txd_1,
output wire [7:0] qsfp0_txc_1,
input wire qsfp0_rx_clk_1,
input wire qsfp0_rx_rst_1,
input wire [63:0] qsfp0_rxd_1,
input wire [7:0] qsfp0_rxc_1,
input wire qsfp0_tx_clk_2,
input wire qsfp0_tx_rst_2,
output wire [63:0] qsfp0_txd_2,
output wire [7:0] qsfp0_txc_2,
input wire qsfp0_rx_clk_2,
input wire qsfp0_rx_rst_2,
input wire [63:0] qsfp0_rxd_2,
input wire [7:0] qsfp0_rxc_2,
input wire qsfp0_tx_clk_3,
input wire qsfp0_tx_rst_3,
output wire [63:0] qsfp0_txd_3,
output wire [7:0] qsfp0_txc_3,
input wire qsfp0_rx_clk_3,
input wire qsfp0_rx_rst_3,
input wire [63:0] qsfp0_rxd_3,
input wire [7:0] qsfp0_rxc_3,
input wire qsfp0_tx_clk_4,
input wire qsfp0_tx_rst_4,
output wire [63:0] qsfp0_txd_4,
output wire [7:0] qsfp0_txc_4,
input wire qsfp0_rx_clk_4,
input wire qsfp0_rx_rst_4,
input wire [63:0] qsfp0_rxd_4,
input wire [7:0] qsfp0_rxc_4,
input wire qsfp1_tx_clk_1,
input wire qsfp1_tx_rst_1,
output wire [63:0] qsfp1_txd_1,
output wire [7:0] qsfp1_txc_1,
input wire qsfp1_rx_clk_1,
input wire qsfp1_rx_rst_1,
input wire [63:0] qsfp1_rxd_1,
input wire [7:0] qsfp1_rxc_1,
input wire qsfp1_tx_clk_2,
input wire qsfp1_tx_rst_2,
output wire [63:0] qsfp1_txd_2,
output wire [7:0] qsfp1_txc_2,
input wire qsfp1_rx_clk_2,
input wire qsfp1_rx_rst_2,
input wire [63:0] qsfp1_rxd_2,
input wire [7:0] qsfp1_rxc_2,
input wire qsfp1_tx_clk_3,
input wire qsfp1_tx_rst_3,
output wire [63:0] qsfp1_txd_3,
output wire [7:0] qsfp1_txc_3,
input wire qsfp1_rx_clk_3,
input wire qsfp1_rx_rst_3,
input wire [63:0] qsfp1_rxd_3,
input wire [7:0] qsfp1_rxc_3,
input wire qsfp1_tx_clk_4,
input wire qsfp1_tx_rst_4,
output wire [63:0] qsfp1_txd_4,
output wire [7:0] qsfp1_txc_4,
input wire qsfp1_rx_clk_4,
input wire qsfp1_rx_rst_4,
input wire [63:0] qsfp1_rxd_4,
input wire [7:0] qsfp1_rxc_4,
/*
* UART: 115200 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
valid_last <= tx_udp_payload_axis_tvalid;
if (tx_udp_payload_axis_tvalid && !valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
end
end
end
//assign led = sw;
assign led = led_reg;
assign qsfp0_txd_2 = 64'h0707070707070707;
assign qsfp0_txc_2 = 8'hff;
assign qsfp0_txd_3 = 64'h0707070707070707;
assign qsfp0_txc_3 = 8'hff;
assign qsfp0_txd_4 = 64'h0707070707070707;
assign qsfp0_txc_4 = 8'hff;
assign qsfp1_txd_1 = 64'h0707070707070707;
assign qsfp1_txc_1 = 8'hff;
assign qsfp1_txd_2 = 64'h0707070707070707;
assign qsfp1_txc_2 = 8'hff;
assign qsfp1_txd_3 = 64'h0707070707070707;
assign qsfp1_txc_3 = 8'hff;
assign qsfp1_txd_4 = 64'h0707070707070707;
assign qsfp1_txc_4 = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_DEPTH(4096),
.TX_FRAME_FIFO(1),
.RX_FIFO_DEPTH(4096),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(qsfp0_rx_clk_1),
.rx_rst(qsfp0_rx_rst_1),
.tx_clk(qsfp0_tx_clk_1),
.tx_rst(qsfp0_tx_rst_1),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(qsfp0_rxd_1),
.xgmii_rxc(qsfp0_rxc_1),
.xgmii_txd(qsfp0_txd_1),
.xgmii_txc(qsfp0_txc_1),
.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(),
.cfg_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_enable(1'b1)
);
eth_axis_rx #(
.DATA_WIDTH(64)
)
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx #(
.DATA_WIDTH(64)
)
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.DEPTH(8192),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule
`resetall

View File

@ -1,229 +0,0 @@
"""
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import logging
import os
from scapy.layers.l2 import Ether, ARP
from scapy.layers.inet import IP, UDP
import cocotb_test.simulator
import cocotb
from cocotb.log import SimLog
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink
class TB:
def __init__(self, dut):
self.dut = dut
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 2.56, units="ns").start())
# Ethernet
self.qsfp_source = []
self.qsfp_sink = []
for x in range(2):
sources = []
sinks = []
for y in range(1, 5):
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_rx_clk_{y}"), 2.56, units="ns").start())
source = XgmiiSource(getattr(dut, f"qsfp{x}_rxd_{y}"), getattr(dut, f"qsfp{x}_rxc_{y}"), getattr(dut, f"qsfp{x}_rx_clk_{y}"), getattr(dut, f"qsfp{x}_rx_rst_{y}"))
sources.append(source)
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_tx_clk_{y}"), 2.56, units="ns").start())
sink = XgmiiSink(getattr(dut, f"qsfp{x}_txd_{y}"), getattr(dut, f"qsfp{x}_txc_{y}"), getattr(dut, f"qsfp{x}_tx_clk_{y}"), getattr(dut, f"qsfp{x}_tx_rst_{y}"))
sinks.append(sink)
self.qsfp_source.append(sources)
self.qsfp_sink.append(sinks)
dut.sw.setimmediatevalue(0)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").setimmediatevalue(0)
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 1
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 0
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 0
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("test UDP RX packet")
payload = bytes([x % 256 for x in range(256)])
eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
ip = IP(src='192.168.1.100', dst='192.168.1.128')
udp = UDP(sport=5678, dport=1234)
test_pkt = eth / ip / udp / payload
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_source[0][0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_sink[0][0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff'
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[ARP].hwtype == 1
assert rx_pkt[ARP].ptype == 0x0800
assert rx_pkt[ARP].hwlen == 6
assert rx_pkt[ARP].plen == 4
assert rx_pkt[ARP].op == 1
assert rx_pkt[ARP].hwsrc == test_pkt.dst
assert rx_pkt[ARP].psrc == test_pkt[IP].dst
assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00'
assert rx_pkt[ARP].pdst == test_pkt[IP].src
tb.log.info("send ARP response")
eth = Ether(src=test_pkt.src, dst=test_pkt.dst)
arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2,
hwsrc=test_pkt.src, psrc=test_pkt[IP].src,
hwdst=test_pkt.dst, pdst=test_pkt[IP].dst)
resp_pkt = eth / arp
resp_frame = XgmiiFrame.from_payload(resp_pkt.build())
await tb.qsfp_source[0][0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_sink[0][0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == test_pkt.src
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[IP].dst == test_pkt[IP].src
assert rx_pkt[IP].src == test_pkt[IP].dst
assert rx_pkt[UDP].dport == test_pkt[UDP].sport
assert rx_pkt[UDP].sport == test_pkt[UDP].dport
assert rx_pkt[UDP].payload == test_pkt[UDP].payload
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl'))
eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl'))
def test_fpga_core(request):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"),
os.path.join(eth_rtl_dir, "lfsr.v"),
os.path.join(eth_rtl_dir, "eth_axis_rx.v"),
os.path.join(eth_rtl_dir, "eth_axis_tx.v"),
os.path.join(eth_rtl_dir, "udp_complete_64.v"),
os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"),
os.path.join(eth_rtl_dir, "udp_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_complete_64.v"),
os.path.join(eth_rtl_dir, "ip_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_arb_mux.v"),
os.path.join(eth_rtl_dir, "arp.v"),
os.path.join(eth_rtl_dir, "arp_cache.v"),
os.path.join(eth_rtl_dir, "arp_eth_rx.v"),
os.path.join(eth_rtl_dir, "arp_eth_tx.v"),
os.path.join(eth_rtl_dir, "eth_arb_mux.v"),
os.path.join(axis_rtl_dir, "arbiter.v"),
os.path.join(axis_rtl_dir, "priority_encoder.v"),
os.path.join(axis_rtl_dir, "axis_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
]
parameters = {}
# parameters['A'] = val
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)

View File

@ -1,25 +0,0 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -1,30 +0,0 @@
# Verilog Ethernet Alveo U280 Example Design
## Introduction
This example design targets the Xilinx Alveo U280 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
* FPGA: xcu280-fsvh2892-2L-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the Alveo U280 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
It is also possible to use hping to test the design by running
hping 192.168.1.128 -2 -p 1234 -d 1024

View File

@ -1,137 +0,0 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: fpga vivado tmpclean clean distclean
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
FPGA_TOP ?= fpga
PROJECT ?= $(FPGA_TOP)
SYN_FILES_REL = $(foreach p,$(SYN_FILES),$(if $(filter /% ./%,$p),$p,../$p))
INC_FILES_REL = $(foreach p,$(INC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
XCI_FILES_REL = $(foreach p,$(XCI_FILES),$(if $(filter /% ./%,$p),$p,../$p))
IP_TCL_FILES_REL = $(foreach p,$(IP_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
CONFIG_TCL_FILES_REL = $(foreach p,$(CONFIG_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
ifdef XDC_FILES
XDC_FILES_REL = $(foreach p,$(XDC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
else
XDC_FILES_REL = $(PROJECT).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(PROJECT).bit
vivado: $(PROJECT).xpr
vivado $(PROJECT).xpr
tmpclean::
-rm -rf *.log *.jou *.cache *.gen *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl update_config.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean:: tmpclean
-rm -rf *.bit *.ltx program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
-rm -rf *_utilization.rpt *_utilization_hierarchical.rpt
distclean:: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
create_project.tcl: Makefile $(XCI_FILES_REL) $(IP_TCL_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $(PROJECT)" > $@
echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@
echo "set_property top $(FPGA_TOP) [current_fileset]" >> $@
echo "add_files -fileset constrs_1 $(XDC_FILES_REL)" >> $@
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> $@; done
for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> $@; done
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
update_config.tcl: $(CONFIG_TCL_FILES_REL) $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project -quiet $(PROJECT).xpr" > $@
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
$(PROJECT).xpr: create_project.tcl update_config.tcl
vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x)
# synthesis run
$(PROJECT).runs/synth_1/$(PROJECT).dcp: create_project.tcl update_config.tcl $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) | $(PROJECT).xpr
echo "open_project $(PROJECT).xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs -jobs 4 synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
$(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp: $(PROJECT).runs/synth_1/$(PROJECT).dcp
echo "open_project $(PROJECT).xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs -jobs 4 impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "open_run impl_1" >> run_impl.tcl
echo "report_utilization -file $(PROJECT)_utilization.rpt" >> run_impl.tcl
echo "report_utilization -hierarchical -file $(PROJECT)_utilization_hierarchical.rpt" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
$(PROJECT).bit $(PROJECT).ltx: $(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp
echo "open_project $(PROJECT).xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $(PROJECT).runs/impl_1/$(PROJECT).bit" >> generate_bit.tcl
echo "write_debug_probes -force $(PROJECT).runs/impl_1/$(PROJECT).ltx" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bit .
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).ltx .; fi
mkdir -p rev
COUNT=100; \
while [ -e rev/$(PROJECT)_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
cp -pv $(PROJECT).runs/impl_1/$(PROJECT).bit rev/$(PROJECT)_rev$$COUNT.bit; \
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then cp -pv $(PROJECT).runs/impl_1/$(PROJECT).ltx rev/$(PROJECT)_rev$$COUNT.ltx; fi

View File

@ -1,76 +0,0 @@
# Copyright (c) 2021 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set base_name {eth_xcvr_gt}
set preset {GTY-10GBASE-R}
set freerun_freq {125}
set line_rate {10.3125}
set refclk_freq {161.1328125}
set qpll_fracn [expr {int(fmod($line_rate*1000/2 / $refclk_freq, 1)*pow(2, 24))}]
set user_data_width {64}
set int_data_width $user_data_width
set extra_ports [list]
set extra_pll_ports [list {qpll0lock_out}]
set config [dict create]
dict set config TX_LINE_RATE $line_rate
dict set config TX_REFCLK_FREQUENCY $refclk_freq
dict set config TX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config TX_USER_DATA_WIDTH $user_data_width
dict set config TX_INT_DATA_WIDTH $int_data_width
dict set config RX_LINE_RATE $line_rate
dict set config RX_REFCLK_FREQUENCY $refclk_freq
dict set config RX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config RX_USER_DATA_WIDTH $user_data_width
dict set config RX_INT_DATA_WIDTH $int_data_width
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {CORE}
dict set config LOCATE_RESET_CONTROLLER {CORE}
dict set config LOCATE_TX_USER_CLOCKING {CORE}
dict set config LOCATE_RX_USER_CLOCKING {CORE}
dict set config LOCATE_USER_DATA_WIDTH_SIZING {CORE}
dict set config FREERUN_FREQUENCY $freerun_freq
dict set config DISABLE_LOC_XDC {1}
proc create_gtwizard_ip {name preset config} {
create_ip -name gtwizard_ultrascale -vendor xilinx.com -library ip -module_name $name
set ip [get_ips $name]
set_property CONFIG.preset $preset $ip
set config_list {}
dict for {name value} $config {
lappend config_list "CONFIG.${name}" $value
}
set_property -dict $config_list $ip
}
# variant with channel and common
dict set config ENABLE_OPTIONAL_PORTS [concat $extra_pll_ports $extra_ports]
dict set config LOCATE_COMMON {CORE}
create_gtwizard_ip "${base_name}_full" $preset $config
# variant with channel only
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {EXAMPLE_DESIGN}
create_gtwizard_ip "${base_name}_channel" $preset $config

View File

@ -1 +0,0 @@
../../../../

View File

@ -1,395 +0,0 @@
/*
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY quad wrapper
*/
module eth_xcvr_phy_quad_wrapper #
(
parameter COUNT = 4,
parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH = (DATA_WIDTH/8),
parameter HDR_WIDTH = 2,
parameter PRBS31_ENABLE = 0,
parameter TX_SERDES_PIPELINE = 0,
parameter RX_SERDES_PIPELINE = 0,
parameter BITSLIP_HIGH_CYCLES = 1,
parameter BITSLIP_LOW_CYCLES = 8,
parameter COUNT_125US = 125000/6.4
)
(
input wire xcvr_ctrl_clk,
input wire xcvr_ctrl_rst,
/*
* Common
*/
output wire xcvr_gtpowergood_out,
/*
* PLL
*/
input wire xcvr_gtrefclk00_in,
/*
* Serial data
*/
output wire [COUNT-1:0] xcvr_txp,
output wire [COUNT-1:0] xcvr_txn,
input wire [COUNT-1:0] xcvr_rxp,
input wire [COUNT-1:0] xcvr_rxn,
/*
* PHY connections
*/
output wire phy_1_tx_clk,
output wire phy_1_tx_rst,
input wire [DATA_WIDTH-1:0] phy_1_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_1_xgmii_txc,
output wire phy_1_rx_clk,
output wire phy_1_rx_rst,
output wire [DATA_WIDTH-1:0] phy_1_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_1_xgmii_rxc,
output wire phy_1_tx_bad_block,
output wire [6:0] phy_1_rx_error_count,
output wire phy_1_rx_bad_block,
output wire phy_1_rx_sequence_error,
output wire phy_1_rx_block_lock,
output wire phy_1_rx_high_ber,
output wire phy_1_rx_status,
input wire phy_1_cfg_tx_prbs31_enable,
input wire phy_1_cfg_rx_prbs31_enable,
output wire phy_2_tx_clk,
output wire phy_2_tx_rst,
input wire [DATA_WIDTH-1:0] phy_2_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_2_xgmii_txc,
output wire phy_2_rx_clk,
output wire phy_2_rx_rst,
output wire [DATA_WIDTH-1:0] phy_2_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_2_xgmii_rxc,
output wire phy_2_tx_bad_block,
output wire [6:0] phy_2_rx_error_count,
output wire phy_2_rx_bad_block,
output wire phy_2_rx_sequence_error,
output wire phy_2_rx_block_lock,
output wire phy_2_rx_high_ber,
output wire phy_2_rx_status,
input wire phy_2_cfg_tx_prbs31_enable,
input wire phy_2_cfg_rx_prbs31_enable,
output wire phy_3_tx_clk,
output wire phy_3_tx_rst,
input wire [DATA_WIDTH-1:0] phy_3_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_3_xgmii_txc,
output wire phy_3_rx_clk,
output wire phy_3_rx_rst,
output wire [DATA_WIDTH-1:0] phy_3_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_3_xgmii_rxc,
output wire phy_3_tx_bad_block,
output wire [6:0] phy_3_rx_error_count,
output wire phy_3_rx_bad_block,
output wire phy_3_rx_sequence_error,
output wire phy_3_rx_block_lock,
output wire phy_3_rx_high_ber,
output wire phy_3_rx_status,
input wire phy_3_cfg_tx_prbs31_enable,
input wire phy_3_cfg_rx_prbs31_enable,
output wire phy_4_tx_clk,
output wire phy_4_tx_rst,
input wire [DATA_WIDTH-1:0] phy_4_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_4_xgmii_txc,
output wire phy_4_rx_clk,
output wire phy_4_rx_rst,
output wire [DATA_WIDTH-1:0] phy_4_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_4_xgmii_rxc,
output wire phy_4_tx_bad_block,
output wire [6:0] phy_4_rx_error_count,
output wire phy_4_rx_bad_block,
output wire phy_4_rx_sequence_error,
output wire phy_4_rx_block_lock,
output wire phy_4_rx_high_ber,
output wire phy_4_rx_status,
input wire phy_4_cfg_tx_prbs31_enable,
input wire phy_4_cfg_rx_prbs31_enable
);
generate
wire xcvr_qpll0lock;
wire xcvr_qpll0clk;
wire xcvr_qpll0refclk;
if (COUNT > 0) begin : phy1
eth_xcvr_phy_wrapper #(
.HAS_COMMON(1),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_1 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(xcvr_gtpowergood_out),
// PLL out
.xcvr_gtrefclk00_in(xcvr_gtrefclk00_in),
.xcvr_qpll0lock_out(xcvr_qpll0lock),
.xcvr_qpll0clk_out(xcvr_qpll0clk),
.xcvr_qpll0refclk_out(xcvr_qpll0refclk),
// PLL in
.xcvr_qpll0lock_in(1'b0),
.xcvr_qpll0clk_in(1'b0),
.xcvr_qpll0refclk_in(1'b0),
// Serial data
.xcvr_txp(xcvr_txp[0]),
.xcvr_txn(xcvr_txn[0]),
.xcvr_rxp(xcvr_rxp[0]),
.xcvr_rxn(xcvr_rxn[0]),
// PHY connections
.phy_tx_clk(phy_1_tx_clk),
.phy_tx_rst(phy_1_tx_rst),
.phy_xgmii_txd(phy_1_xgmii_txd),
.phy_xgmii_txc(phy_1_xgmii_txc),
.phy_rx_clk(phy_1_rx_clk),
.phy_rx_rst(phy_1_rx_rst),
.phy_xgmii_rxd(phy_1_xgmii_rxd),
.phy_xgmii_rxc(phy_1_xgmii_rxc),
.phy_tx_bad_block(phy_1_tx_bad_block),
.phy_rx_error_count(phy_1_rx_error_count),
.phy_rx_bad_block(phy_1_rx_bad_block),
.phy_rx_sequence_error(phy_1_rx_sequence_error),
.phy_rx_block_lock(phy_1_rx_block_lock),
.phy_rx_high_ber(phy_1_rx_high_ber),
.phy_rx_status(phy_1_rx_status),
.phy_cfg_tx_prbs31_enable(phy_1_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_1_cfg_rx_prbs31_enable)
);
end
if (COUNT > 1) begin : phy2
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_2 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[1]),
.xcvr_txn(xcvr_txn[1]),
.xcvr_rxp(xcvr_rxp[1]),
.xcvr_rxn(xcvr_rxn[1]),
// PHY connections
.phy_tx_clk(phy_2_tx_clk),
.phy_tx_rst(phy_2_tx_rst),
.phy_xgmii_txd(phy_2_xgmii_txd),
.phy_xgmii_txc(phy_2_xgmii_txc),
.phy_rx_clk(phy_2_rx_clk),
.phy_rx_rst(phy_2_rx_rst),
.phy_xgmii_rxd(phy_2_xgmii_rxd),
.phy_xgmii_rxc(phy_2_xgmii_rxc),
.phy_tx_bad_block(phy_2_tx_bad_block),
.phy_rx_error_count(phy_2_rx_error_count),
.phy_rx_bad_block(phy_2_rx_bad_block),
.phy_rx_sequence_error(phy_2_rx_sequence_error),
.phy_rx_block_lock(phy_2_rx_block_lock),
.phy_rx_high_ber(phy_2_rx_high_ber),
.phy_rx_status(phy_2_rx_status),
.phy_cfg_tx_prbs31_enable(phy_2_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_2_cfg_rx_prbs31_enable)
);
end
if (COUNT > 2) begin : phy3
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_3 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[2]),
.xcvr_txn(xcvr_txn[2]),
.xcvr_rxp(xcvr_rxp[2]),
.xcvr_rxn(xcvr_rxn[2]),
// PHY connections
.phy_tx_clk(phy_3_tx_clk),
.phy_tx_rst(phy_3_tx_rst),
.phy_xgmii_txd(phy_3_xgmii_txd),
.phy_xgmii_txc(phy_3_xgmii_txc),
.phy_rx_clk(phy_3_rx_clk),
.phy_rx_rst(phy_3_rx_rst),
.phy_xgmii_rxd(phy_3_xgmii_rxd),
.phy_xgmii_rxc(phy_3_xgmii_rxc),
.phy_tx_bad_block(phy_3_tx_bad_block),
.phy_rx_error_count(phy_3_rx_error_count),
.phy_rx_bad_block(phy_3_rx_bad_block),
.phy_rx_sequence_error(phy_3_rx_sequence_error),
.phy_rx_block_lock(phy_3_rx_block_lock),
.phy_rx_high_ber(phy_3_rx_high_ber),
.phy_rx_status(phy_3_rx_status),
.phy_cfg_tx_prbs31_enable(phy_3_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_3_cfg_rx_prbs31_enable)
);
end
if (COUNT > 3) begin : phy4
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_4 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[3]),
.xcvr_txn(xcvr_txn[3]),
.xcvr_rxp(xcvr_rxp[3]),
.xcvr_rxn(xcvr_rxn[3]),
// PHY connections
.phy_tx_clk(phy_4_tx_clk),
.phy_tx_rst(phy_4_tx_rst),
.phy_xgmii_txd(phy_4_xgmii_txd),
.phy_xgmii_txc(phy_4_xgmii_txc),
.phy_rx_clk(phy_4_rx_clk),
.phy_rx_rst(phy_4_rx_rst),
.phy_xgmii_rxd(phy_4_xgmii_rxd),
.phy_xgmii_rxc(phy_4_xgmii_rxc),
.phy_tx_bad_block(phy_4_tx_bad_block),
.phy_rx_error_count(phy_4_rx_error_count),
.phy_rx_bad_block(phy_4_rx_bad_block),
.phy_rx_sequence_error(phy_4_rx_sequence_error),
.phy_rx_block_lock(phy_4_rx_block_lock),
.phy_rx_high_ber(phy_4_rx_high_ber),
.phy_rx_status(phy_4_rx_status),
.phy_cfg_tx_prbs31_enable(phy_4_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_4_cfg_rx_prbs31_enable)
);
end
endgenerate
endmodule
`resetall

View File

@ -1,307 +0,0 @@
/*
Copyright (c) 2021-2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY wrapper
*/
module eth_xcvr_phy_wrapper #
(
parameter HAS_COMMON = 1,
parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH = (DATA_WIDTH/8),
parameter HDR_WIDTH = 2,
parameter PRBS31_ENABLE = 0,
parameter TX_SERDES_PIPELINE = 0,
parameter RX_SERDES_PIPELINE = 0,
parameter BITSLIP_HIGH_CYCLES = 1,
parameter BITSLIP_LOW_CYCLES = 8,
parameter COUNT_125US = 125000/6.4
)
(
input wire xcvr_ctrl_clk,
input wire xcvr_ctrl_rst,
/*
* Common
*/
output wire xcvr_gtpowergood_out,
/*
* PLL out
*/
input wire xcvr_gtrefclk00_in,
output wire xcvr_qpll0lock_out,
output wire xcvr_qpll0clk_out,
output wire xcvr_qpll0refclk_out,
/*
* PLL in
*/
input wire xcvr_qpll0lock_in,
output wire xcvr_qpll0reset_out,
input wire xcvr_qpll0clk_in,
input wire xcvr_qpll0refclk_in,
/*
* Serial data
*/
output wire xcvr_txp,
output wire xcvr_txn,
input wire xcvr_rxp,
input wire xcvr_rxn,
/*
* PHY connections
*/
output wire phy_tx_clk,
output wire phy_tx_rst,
input wire [DATA_WIDTH-1:0] phy_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_xgmii_txc,
output wire phy_rx_clk,
output wire phy_rx_rst,
output wire [DATA_WIDTH-1:0] phy_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_xgmii_rxc,
output wire phy_tx_bad_block,
output wire [6:0] phy_rx_error_count,
output wire phy_rx_bad_block,
output wire phy_rx_sequence_error,
output wire phy_rx_block_lock,
output wire phy_rx_high_ber,
output wire phy_rx_status,
input wire phy_cfg_tx_prbs31_enable,
input wire phy_cfg_rx_prbs31_enable
);
wire phy_rx_reset_req;
wire gt_reset_tx_datapath = 1'b0;
wire gt_reset_rx_datapath = phy_rx_reset_req;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [5:0] gt_txheader;
wire [63:0] gt_txdata;
wire gt_rxgearboxslip;
wire [5:0] gt_rxheader;
wire [1:0] gt_rxheadervalid;
wire [63:0] gt_rxdata;
wire [1:0] gt_rxdatavalid;
generate
if (HAS_COMMON) begin : xcvr
eth_xcvr_gt_full
eth_xcvr_gt_full_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtrefclk00_in(xcvr_gtrefclk00_in),
.qpll0lock_out(xcvr_qpll0lock_out),
.qpll0outclk_out(xcvr_qpll0clk_out),
.qpll0outrefclk_out(xcvr_qpll0refclk_out),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
assign xcvr_qpll0reset_out = 1'b0;
end else begin : xcvr
eth_xcvr_gt_channel
eth_xcvr_gt_channel_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtwiz_reset_qpll0lock_in(xcvr_qpll0lock_in),
.gtwiz_reset_qpll0reset_out(xcvr_qpll0reset_out),
.qpll0clk_in(xcvr_qpll0clk_in),
.qpll0refclk_in(xcvr_qpll0refclk_in),
.qpll1clk_in(1'b0),
.qpll1refclk_in(1'b0),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
assign xcvr_qpll0lock_out = 1'b0;
assign xcvr_qpll0clk_out = 1'b0;
assign xcvr_qpll0refclk_out = 1'b0;
end
endgenerate
sync_reset #(
.N(4)
)
tx_reset_sync_inst (
.clk(phy_tx_clk),
.rst(!gt_reset_tx_done),
.out(phy_tx_rst)
);
sync_reset #(
.N(4)
)
rx_reset_sync_inst (
.clk(phy_rx_clk),
.rst(!gt_reset_rx_done),
.out(phy_rx_rst)
);
eth_phy_10g #(
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.BIT_REVERSE(1),
.SCRAMBLER_DISABLE(0),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
phy_inst (
.tx_clk(phy_tx_clk),
.tx_rst(phy_tx_rst),
.rx_clk(phy_rx_clk),
.rx_rst(phy_rx_rst),
.xgmii_txd(phy_xgmii_txd),
.xgmii_txc(phy_xgmii_txc),
.xgmii_rxd(phy_xgmii_rxd),
.xgmii_rxc(phy_xgmii_rxc),
.serdes_tx_data(gt_txdata),
.serdes_tx_hdr(gt_txheader),
.serdes_rx_data(gt_rxdata),
.serdes_rx_hdr(gt_rxheader),
.serdes_rx_bitslip(gt_rxgearboxslip),
.serdes_rx_reset_req(phy_rx_reset_req),
.tx_bad_block(phy_tx_bad_block),
.rx_error_count(phy_rx_error_count),
.rx_bad_block(phy_rx_bad_block),
.rx_sequence_error(phy_rx_sequence_error),
.rx_block_lock(phy_rx_block_lock),
.rx_high_ber(phy_rx_high_ber),
.rx_status(phy_rx_status),
.cfg_tx_prbs31_enable(phy_cfg_tx_prbs31_enable),
.cfg_rx_prbs31_enable(phy_cfg_rx_prbs31_enable)
);
endmodule
`resetall

View File

@ -1,655 +0,0 @@
/*
Copyright (c) 2014-2021 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA core logic
*/
module fpga_core #
(
parameter TARGET = "XILINX"
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
/*
* Ethernet: QSFP28
*/
input wire qsfp0_tx_clk_1,
input wire qsfp0_tx_rst_1,
output wire [63:0] qsfp0_txd_1,
output wire [7:0] qsfp0_txc_1,
input wire qsfp0_rx_clk_1,
input wire qsfp0_rx_rst_1,
input wire [63:0] qsfp0_rxd_1,
input wire [7:0] qsfp0_rxc_1,
input wire qsfp0_tx_clk_2,
input wire qsfp0_tx_rst_2,
output wire [63:0] qsfp0_txd_2,
output wire [7:0] qsfp0_txc_2,
input wire qsfp0_rx_clk_2,
input wire qsfp0_rx_rst_2,
input wire [63:0] qsfp0_rxd_2,
input wire [7:0] qsfp0_rxc_2,
input wire qsfp0_tx_clk_3,
input wire qsfp0_tx_rst_3,
output wire [63:0] qsfp0_txd_3,
output wire [7:0] qsfp0_txc_3,
input wire qsfp0_rx_clk_3,
input wire qsfp0_rx_rst_3,
input wire [63:0] qsfp0_rxd_3,
input wire [7:0] qsfp0_rxc_3,
input wire qsfp0_tx_clk_4,
input wire qsfp0_tx_rst_4,
output wire [63:0] qsfp0_txd_4,
output wire [7:0] qsfp0_txc_4,
input wire qsfp0_rx_clk_4,
input wire qsfp0_rx_rst_4,
input wire [63:0] qsfp0_rxd_4,
input wire [7:0] qsfp0_rxc_4,
input wire qsfp1_tx_clk_1,
input wire qsfp1_tx_rst_1,
output wire [63:0] qsfp1_txd_1,
output wire [7:0] qsfp1_txc_1,
input wire qsfp1_rx_clk_1,
input wire qsfp1_rx_rst_1,
input wire [63:0] qsfp1_rxd_1,
input wire [7:0] qsfp1_rxc_1,
input wire qsfp1_tx_clk_2,
input wire qsfp1_tx_rst_2,
output wire [63:0] qsfp1_txd_2,
output wire [7:0] qsfp1_txc_2,
input wire qsfp1_rx_clk_2,
input wire qsfp1_rx_rst_2,
input wire [63:0] qsfp1_rxd_2,
input wire [7:0] qsfp1_rxc_2,
input wire qsfp1_tx_clk_3,
input wire qsfp1_tx_rst_3,
output wire [63:0] qsfp1_txd_3,
output wire [7:0] qsfp1_txc_3,
input wire qsfp1_rx_clk_3,
input wire qsfp1_rx_rst_3,
input wire [63:0] qsfp1_rxd_3,
input wire [7:0] qsfp1_rxc_3,
input wire qsfp1_tx_clk_4,
input wire qsfp1_tx_rst_4,
output wire [63:0] qsfp1_txd_4,
output wire [7:0] qsfp1_txc_4,
input wire qsfp1_rx_clk_4,
input wire qsfp1_rx_rst_4,
input wire [63:0] qsfp1_rxd_4,
input wire [7:0] qsfp1_rxc_4
);
// AXI between MAC and Ethernet modules
wire [63:0] rx_axis_tdata;
wire [7:0] rx_axis_tkeep;
wire rx_axis_tvalid;
wire rx_axis_tready;
wire rx_axis_tlast;
wire rx_axis_tuser;
wire [63:0] tx_axis_tdata;
wire [7:0] tx_axis_tkeep;
wire tx_axis_tvalid;
wire tx_axis_tready;
wire tx_axis_tlast;
wire tx_axis_tuser;
// Ethernet frame between Ethernet modules and UDP stack
wire rx_eth_hdr_ready;
wire rx_eth_hdr_valid;
wire [47:0] rx_eth_dest_mac;
wire [47:0] rx_eth_src_mac;
wire [15:0] rx_eth_type;
wire [63:0] rx_eth_payload_axis_tdata;
wire [7:0] rx_eth_payload_axis_tkeep;
wire rx_eth_payload_axis_tvalid;
wire rx_eth_payload_axis_tready;
wire rx_eth_payload_axis_tlast;
wire rx_eth_payload_axis_tuser;
wire tx_eth_hdr_ready;
wire tx_eth_hdr_valid;
wire [47:0] tx_eth_dest_mac;
wire [47:0] tx_eth_src_mac;
wire [15:0] tx_eth_type;
wire [63:0] tx_eth_payload_axis_tdata;
wire [7:0] tx_eth_payload_axis_tkeep;
wire tx_eth_payload_axis_tvalid;
wire tx_eth_payload_axis_tready;
wire tx_eth_payload_axis_tlast;
wire tx_eth_payload_axis_tuser;
// IP frame connections
wire rx_ip_hdr_valid;
wire rx_ip_hdr_ready;
wire [47:0] rx_ip_eth_dest_mac;
wire [47:0] rx_ip_eth_src_mac;
wire [15:0] rx_ip_eth_type;
wire [3:0] rx_ip_version;
wire [3:0] rx_ip_ihl;
wire [5:0] rx_ip_dscp;
wire [1:0] rx_ip_ecn;
wire [15:0] rx_ip_length;
wire [15:0] rx_ip_identification;
wire [2:0] rx_ip_flags;
wire [12:0] rx_ip_fragment_offset;
wire [7:0] rx_ip_ttl;
wire [7:0] rx_ip_protocol;
wire [15:0] rx_ip_header_checksum;
wire [31:0] rx_ip_source_ip;
wire [31:0] rx_ip_dest_ip;
wire [63:0] rx_ip_payload_axis_tdata;
wire [7:0] rx_ip_payload_axis_tkeep;
wire rx_ip_payload_axis_tvalid;
wire rx_ip_payload_axis_tready;
wire rx_ip_payload_axis_tlast;
wire rx_ip_payload_axis_tuser;
wire tx_ip_hdr_valid;
wire tx_ip_hdr_ready;
wire [5:0] tx_ip_dscp;
wire [1:0] tx_ip_ecn;
wire [15:0] tx_ip_length;
wire [7:0] tx_ip_ttl;
wire [7:0] tx_ip_protocol;
wire [31:0] tx_ip_source_ip;
wire [31:0] tx_ip_dest_ip;
wire [63:0] tx_ip_payload_axis_tdata;
wire [7:0] tx_ip_payload_axis_tkeep;
wire tx_ip_payload_axis_tvalid;
wire tx_ip_payload_axis_tready;
wire tx_ip_payload_axis_tlast;
wire tx_ip_payload_axis_tuser;
// UDP frame connections
wire rx_udp_hdr_valid;
wire rx_udp_hdr_ready;
wire [47:0] rx_udp_eth_dest_mac;
wire [47:0] rx_udp_eth_src_mac;
wire [15:0] rx_udp_eth_type;
wire [3:0] rx_udp_ip_version;
wire [3:0] rx_udp_ip_ihl;
wire [5:0] rx_udp_ip_dscp;
wire [1:0] rx_udp_ip_ecn;
wire [15:0] rx_udp_ip_length;
wire [15:0] rx_udp_ip_identification;
wire [2:0] rx_udp_ip_flags;
wire [12:0] rx_udp_ip_fragment_offset;
wire [7:0] rx_udp_ip_ttl;
wire [7:0] rx_udp_ip_protocol;
wire [15:0] rx_udp_ip_header_checksum;
wire [31:0] rx_udp_ip_source_ip;
wire [31:0] rx_udp_ip_dest_ip;
wire [15:0] rx_udp_source_port;
wire [15:0] rx_udp_dest_port;
wire [15:0] rx_udp_length;
wire [15:0] rx_udp_checksum;
wire [63:0] rx_udp_payload_axis_tdata;
wire [7:0] rx_udp_payload_axis_tkeep;
wire rx_udp_payload_axis_tvalid;
wire rx_udp_payload_axis_tready;
wire rx_udp_payload_axis_tlast;
wire rx_udp_payload_axis_tuser;
wire tx_udp_hdr_valid;
wire tx_udp_hdr_ready;
wire [5:0] tx_udp_ip_dscp;
wire [1:0] tx_udp_ip_ecn;
wire [7:0] tx_udp_ip_ttl;
wire [31:0] tx_udp_ip_source_ip;
wire [31:0] tx_udp_ip_dest_ip;
wire [15:0] tx_udp_source_port;
wire [15:0] tx_udp_dest_port;
wire [15:0] tx_udp_length;
wire [15:0] tx_udp_checksum;
wire [63:0] tx_udp_payload_axis_tdata;
wire [7:0] tx_udp_payload_axis_tkeep;
wire tx_udp_payload_axis_tvalid;
wire tx_udp_payload_axis_tready;
wire tx_udp_payload_axis_tlast;
wire tx_udp_payload_axis_tuser;
wire [63:0] rx_fifo_udp_payload_axis_tdata;
wire [7:0] rx_fifo_udp_payload_axis_tkeep;
wire rx_fifo_udp_payload_axis_tvalid;
wire rx_fifo_udp_payload_axis_tready;
wire rx_fifo_udp_payload_axis_tlast;
wire rx_fifo_udp_payload_axis_tuser;
wire [63:0] tx_fifo_udp_payload_axis_tdata;
wire [7:0] tx_fifo_udp_payload_axis_tkeep;
wire tx_fifo_udp_payload_axis_tvalid;
wire tx_fifo_udp_payload_axis_tready;
wire tx_fifo_udp_payload_axis_tlast;
wire tx_fifo_udp_payload_axis_tuser;
// Configuration
wire [47:0] local_mac = 48'h02_00_00_00_00_00;
wire [31:0] local_ip = {8'd192, 8'd168, 8'd1, 8'd128};
wire [31:0] gateway_ip = {8'd192, 8'd168, 8'd1, 8'd1};
wire [31:0] subnet_mask = {8'd255, 8'd255, 8'd255, 8'd0};
// IP ports not used
assign rx_ip_hdr_ready = 1;
assign rx_ip_payload_axis_tready = 1;
assign tx_ip_hdr_valid = 0;
assign tx_ip_dscp = 0;
assign tx_ip_ecn = 0;
assign tx_ip_length = 0;
assign tx_ip_ttl = 0;
assign tx_ip_protocol = 0;
assign tx_ip_source_ip = 0;
assign tx_ip_dest_ip = 0;
assign tx_ip_payload_axis_tdata = 0;
assign tx_ip_payload_axis_tkeep = 0;
assign tx_ip_payload_axis_tvalid = 0;
assign tx_ip_payload_axis_tlast = 0;
assign tx_ip_payload_axis_tuser = 0;
// Loop back UDP
wire match_cond = rx_udp_dest_port == 1234;
wire no_match = !match_cond;
reg match_cond_reg = 0;
reg no_match_reg = 0;
always @(posedge clk) begin
if (rst) begin
match_cond_reg <= 0;
no_match_reg <= 0;
end else begin
if (rx_udp_payload_axis_tvalid) begin
if ((!match_cond_reg && !no_match_reg) ||
(rx_udp_payload_axis_tvalid && rx_udp_payload_axis_tready && rx_udp_payload_axis_tlast)) begin
match_cond_reg <= match_cond;
no_match_reg <= no_match;
end
end else begin
match_cond_reg <= 0;
no_match_reg <= 0;
end
end
end
assign tx_udp_hdr_valid = rx_udp_hdr_valid && match_cond;
assign rx_udp_hdr_ready = (tx_eth_hdr_ready && match_cond) || no_match;
assign tx_udp_ip_dscp = 0;
assign tx_udp_ip_ecn = 0;
assign tx_udp_ip_ttl = 64;
assign tx_udp_ip_source_ip = local_ip;
assign tx_udp_ip_dest_ip = rx_udp_ip_source_ip;
assign tx_udp_source_port = rx_udp_dest_port;
assign tx_udp_dest_port = rx_udp_source_port;
assign tx_udp_length = rx_udp_length;
assign tx_udp_checksum = 0;
assign tx_udp_payload_axis_tdata = tx_fifo_udp_payload_axis_tdata;
assign tx_udp_payload_axis_tkeep = tx_fifo_udp_payload_axis_tkeep;
assign tx_udp_payload_axis_tvalid = tx_fifo_udp_payload_axis_tvalid;
assign tx_fifo_udp_payload_axis_tready = tx_udp_payload_axis_tready;
assign tx_udp_payload_axis_tlast = tx_fifo_udp_payload_axis_tlast;
assign tx_udp_payload_axis_tuser = tx_fifo_udp_payload_axis_tuser;
assign rx_fifo_udp_payload_axis_tdata = rx_udp_payload_axis_tdata;
assign rx_fifo_udp_payload_axis_tkeep = rx_udp_payload_axis_tkeep;
assign rx_fifo_udp_payload_axis_tvalid = rx_udp_payload_axis_tvalid && match_cond_reg;
assign rx_udp_payload_axis_tready = (rx_fifo_udp_payload_axis_tready && match_cond_reg) || no_match_reg;
assign rx_fifo_udp_payload_axis_tlast = rx_udp_payload_axis_tlast;
assign rx_fifo_udp_payload_axis_tuser = rx_udp_payload_axis_tuser;
// Place first payload byte onto LEDs
reg valid_last = 0;
reg [7:0] led_reg = 0;
always @(posedge clk) begin
if (rst) begin
led_reg <= 0;
end else begin
valid_last <= tx_udp_payload_axis_tvalid;
if (tx_udp_payload_axis_tvalid && !valid_last) begin
led_reg <= tx_udp_payload_axis_tdata;
end
end
end
assign qsfp0_txd_2 = 64'h0707070707070707;
assign qsfp0_txc_2 = 8'hff;
assign qsfp0_txd_3 = 64'h0707070707070707;
assign qsfp0_txc_3 = 8'hff;
assign qsfp0_txd_4 = 64'h0707070707070707;
assign qsfp0_txc_4 = 8'hff;
assign qsfp1_txd_1 = 64'h0707070707070707;
assign qsfp1_txc_1 = 8'hff;
assign qsfp1_txd_2 = 64'h0707070707070707;
assign qsfp1_txc_2 = 8'hff;
assign qsfp1_txd_3 = 64'h0707070707070707;
assign qsfp1_txc_3 = 8'hff;
assign qsfp1_txd_4 = 64'h0707070707070707;
assign qsfp1_txc_4 = 8'hff;
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
.ENABLE_DIC(1),
.MIN_FRAME_LENGTH(64),
.TX_FIFO_DEPTH(4096),
.TX_FRAME_FIFO(1),
.RX_FIFO_DEPTH(4096),
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(qsfp0_rx_clk_1),
.rx_rst(qsfp0_rx_rst_1),
.tx_clk(qsfp0_tx_clk_1),
.tx_rst(qsfp0_tx_rst_1),
.logic_clk(clk),
.logic_rst(rst),
.tx_axis_tdata(tx_axis_tdata),
.tx_axis_tkeep(tx_axis_tkeep),
.tx_axis_tvalid(tx_axis_tvalid),
.tx_axis_tready(tx_axis_tready),
.tx_axis_tlast(tx_axis_tlast),
.tx_axis_tuser(tx_axis_tuser),
.rx_axis_tdata(rx_axis_tdata),
.rx_axis_tkeep(rx_axis_tkeep),
.rx_axis_tvalid(rx_axis_tvalid),
.rx_axis_tready(rx_axis_tready),
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(qsfp0_rxd_1),
.xgmii_rxc(qsfp0_rxc_1),
.xgmii_txd(qsfp0_txd_1),
.xgmii_txc(qsfp0_txc_1),
.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(),
.cfg_ifg(8'd12),
.cfg_tx_enable(1'b1),
.cfg_rx_enable(1'b1)
);
eth_axis_rx #(
.DATA_WIDTH(64)
)
eth_axis_rx_inst (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_axis_tdata),
.s_axis_tkeep(rx_axis_tkeep),
.s_axis_tvalid(rx_axis_tvalid),
.s_axis_tready(rx_axis_tready),
.s_axis_tlast(rx_axis_tlast),
.s_axis_tuser(rx_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(rx_eth_hdr_valid),
.m_eth_hdr_ready(rx_eth_hdr_ready),
.m_eth_dest_mac(rx_eth_dest_mac),
.m_eth_src_mac(rx_eth_src_mac),
.m_eth_type(rx_eth_type),
.m_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Status signals
.busy(),
.error_header_early_termination()
);
eth_axis_tx #(
.DATA_WIDTH(64)
)
eth_axis_tx_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(tx_eth_hdr_valid),
.s_eth_hdr_ready(tx_eth_hdr_ready),
.s_eth_dest_mac(tx_eth_dest_mac),
.s_eth_src_mac(tx_eth_src_mac),
.s_eth_type(tx_eth_type),
.s_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_axis_tdata),
.m_axis_tkeep(tx_axis_tkeep),
.m_axis_tvalid(tx_axis_tvalid),
.m_axis_tready(tx_axis_tready),
.m_axis_tlast(tx_axis_tlast),
.m_axis_tuser(tx_axis_tuser),
// Status signals
.busy()
);
udp_complete_64
udp_complete_inst (
.clk(clk),
.rst(rst),
// Ethernet frame input
.s_eth_hdr_valid(rx_eth_hdr_valid),
.s_eth_hdr_ready(rx_eth_hdr_ready),
.s_eth_dest_mac(rx_eth_dest_mac),
.s_eth_src_mac(rx_eth_src_mac),
.s_eth_type(rx_eth_type),
.s_eth_payload_axis_tdata(rx_eth_payload_axis_tdata),
.s_eth_payload_axis_tkeep(rx_eth_payload_axis_tkeep),
.s_eth_payload_axis_tvalid(rx_eth_payload_axis_tvalid),
.s_eth_payload_axis_tready(rx_eth_payload_axis_tready),
.s_eth_payload_axis_tlast(rx_eth_payload_axis_tlast),
.s_eth_payload_axis_tuser(rx_eth_payload_axis_tuser),
// Ethernet frame output
.m_eth_hdr_valid(tx_eth_hdr_valid),
.m_eth_hdr_ready(tx_eth_hdr_ready),
.m_eth_dest_mac(tx_eth_dest_mac),
.m_eth_src_mac(tx_eth_src_mac),
.m_eth_type(tx_eth_type),
.m_eth_payload_axis_tdata(tx_eth_payload_axis_tdata),
.m_eth_payload_axis_tkeep(tx_eth_payload_axis_tkeep),
.m_eth_payload_axis_tvalid(tx_eth_payload_axis_tvalid),
.m_eth_payload_axis_tready(tx_eth_payload_axis_tready),
.m_eth_payload_axis_tlast(tx_eth_payload_axis_tlast),
.m_eth_payload_axis_tuser(tx_eth_payload_axis_tuser),
// IP frame input
.s_ip_hdr_valid(tx_ip_hdr_valid),
.s_ip_hdr_ready(tx_ip_hdr_ready),
.s_ip_dscp(tx_ip_dscp),
.s_ip_ecn(tx_ip_ecn),
.s_ip_length(tx_ip_length),
.s_ip_ttl(tx_ip_ttl),
.s_ip_protocol(tx_ip_protocol),
.s_ip_source_ip(tx_ip_source_ip),
.s_ip_dest_ip(tx_ip_dest_ip),
.s_ip_payload_axis_tdata(tx_ip_payload_axis_tdata),
.s_ip_payload_axis_tkeep(tx_ip_payload_axis_tkeep),
.s_ip_payload_axis_tvalid(tx_ip_payload_axis_tvalid),
.s_ip_payload_axis_tready(tx_ip_payload_axis_tready),
.s_ip_payload_axis_tlast(tx_ip_payload_axis_tlast),
.s_ip_payload_axis_tuser(tx_ip_payload_axis_tuser),
// IP frame output
.m_ip_hdr_valid(rx_ip_hdr_valid),
.m_ip_hdr_ready(rx_ip_hdr_ready),
.m_ip_eth_dest_mac(rx_ip_eth_dest_mac),
.m_ip_eth_src_mac(rx_ip_eth_src_mac),
.m_ip_eth_type(rx_ip_eth_type),
.m_ip_version(rx_ip_version),
.m_ip_ihl(rx_ip_ihl),
.m_ip_dscp(rx_ip_dscp),
.m_ip_ecn(rx_ip_ecn),
.m_ip_length(rx_ip_length),
.m_ip_identification(rx_ip_identification),
.m_ip_flags(rx_ip_flags),
.m_ip_fragment_offset(rx_ip_fragment_offset),
.m_ip_ttl(rx_ip_ttl),
.m_ip_protocol(rx_ip_protocol),
.m_ip_header_checksum(rx_ip_header_checksum),
.m_ip_source_ip(rx_ip_source_ip),
.m_ip_dest_ip(rx_ip_dest_ip),
.m_ip_payload_axis_tdata(rx_ip_payload_axis_tdata),
.m_ip_payload_axis_tkeep(rx_ip_payload_axis_tkeep),
.m_ip_payload_axis_tvalid(rx_ip_payload_axis_tvalid),
.m_ip_payload_axis_tready(rx_ip_payload_axis_tready),
.m_ip_payload_axis_tlast(rx_ip_payload_axis_tlast),
.m_ip_payload_axis_tuser(rx_ip_payload_axis_tuser),
// UDP frame input
.s_udp_hdr_valid(tx_udp_hdr_valid),
.s_udp_hdr_ready(tx_udp_hdr_ready),
.s_udp_ip_dscp(tx_udp_ip_dscp),
.s_udp_ip_ecn(tx_udp_ip_ecn),
.s_udp_ip_ttl(tx_udp_ip_ttl),
.s_udp_ip_source_ip(tx_udp_ip_source_ip),
.s_udp_ip_dest_ip(tx_udp_ip_dest_ip),
.s_udp_source_port(tx_udp_source_port),
.s_udp_dest_port(tx_udp_dest_port),
.s_udp_length(tx_udp_length),
.s_udp_checksum(tx_udp_checksum),
.s_udp_payload_axis_tdata(tx_udp_payload_axis_tdata),
.s_udp_payload_axis_tkeep(tx_udp_payload_axis_tkeep),
.s_udp_payload_axis_tvalid(tx_udp_payload_axis_tvalid),
.s_udp_payload_axis_tready(tx_udp_payload_axis_tready),
.s_udp_payload_axis_tlast(tx_udp_payload_axis_tlast),
.s_udp_payload_axis_tuser(tx_udp_payload_axis_tuser),
// UDP frame output
.m_udp_hdr_valid(rx_udp_hdr_valid),
.m_udp_hdr_ready(rx_udp_hdr_ready),
.m_udp_eth_dest_mac(rx_udp_eth_dest_mac),
.m_udp_eth_src_mac(rx_udp_eth_src_mac),
.m_udp_eth_type(rx_udp_eth_type),
.m_udp_ip_version(rx_udp_ip_version),
.m_udp_ip_ihl(rx_udp_ip_ihl),
.m_udp_ip_dscp(rx_udp_ip_dscp),
.m_udp_ip_ecn(rx_udp_ip_ecn),
.m_udp_ip_length(rx_udp_ip_length),
.m_udp_ip_identification(rx_udp_ip_identification),
.m_udp_ip_flags(rx_udp_ip_flags),
.m_udp_ip_fragment_offset(rx_udp_ip_fragment_offset),
.m_udp_ip_ttl(rx_udp_ip_ttl),
.m_udp_ip_protocol(rx_udp_ip_protocol),
.m_udp_ip_header_checksum(rx_udp_ip_header_checksum),
.m_udp_ip_source_ip(rx_udp_ip_source_ip),
.m_udp_ip_dest_ip(rx_udp_ip_dest_ip),
.m_udp_source_port(rx_udp_source_port),
.m_udp_dest_port(rx_udp_dest_port),
.m_udp_length(rx_udp_length),
.m_udp_checksum(rx_udp_checksum),
.m_udp_payload_axis_tdata(rx_udp_payload_axis_tdata),
.m_udp_payload_axis_tkeep(rx_udp_payload_axis_tkeep),
.m_udp_payload_axis_tvalid(rx_udp_payload_axis_tvalid),
.m_udp_payload_axis_tready(rx_udp_payload_axis_tready),
.m_udp_payload_axis_tlast(rx_udp_payload_axis_tlast),
.m_udp_payload_axis_tuser(rx_udp_payload_axis_tuser),
// Status signals
.ip_rx_busy(),
.ip_tx_busy(),
.udp_rx_busy(),
.udp_tx_busy(),
.ip_rx_error_header_early_termination(),
.ip_rx_error_payload_early_termination(),
.ip_rx_error_invalid_header(),
.ip_rx_error_invalid_checksum(),
.ip_tx_error_payload_early_termination(),
.ip_tx_error_arp_failed(),
.udp_rx_error_header_early_termination(),
.udp_rx_error_payload_early_termination(),
.udp_tx_error_payload_early_termination(),
// Configuration
.local_mac(local_mac),
.local_ip(local_ip),
.gateway_ip(gateway_ip),
.subnet_mask(subnet_mask),
.clear_arp_cache(1'b0)
);
axis_fifo #(
.DEPTH(8192),
.DATA_WIDTH(64),
.KEEP_ENABLE(1),
.KEEP_WIDTH(8),
.ID_ENABLE(0),
.DEST_ENABLE(0),
.USER_ENABLE(1),
.USER_WIDTH(1),
.FRAME_FIFO(0)
)
udp_payload_fifo (
.clk(clk),
.rst(rst),
// AXI input
.s_axis_tdata(rx_fifo_udp_payload_axis_tdata),
.s_axis_tkeep(rx_fifo_udp_payload_axis_tkeep),
.s_axis_tvalid(rx_fifo_udp_payload_axis_tvalid),
.s_axis_tready(rx_fifo_udp_payload_axis_tready),
.s_axis_tlast(rx_fifo_udp_payload_axis_tlast),
.s_axis_tid(0),
.s_axis_tdest(0),
.s_axis_tuser(rx_fifo_udp_payload_axis_tuser),
// AXI output
.m_axis_tdata(tx_fifo_udp_payload_axis_tdata),
.m_axis_tkeep(tx_fifo_udp_payload_axis_tkeep),
.m_axis_tvalid(tx_fifo_udp_payload_axis_tvalid),
.m_axis_tready(tx_fifo_udp_payload_axis_tready),
.m_axis_tlast(tx_fifo_udp_payload_axis_tlast),
.m_axis_tid(),
.m_axis_tdest(),
.m_axis_tuser(tx_fifo_udp_payload_axis_tuser),
// Status
.status_overflow(),
.status_bad_frame(),
.status_good_frame()
);
endmodule
`resetall

View File

@ -1,62 +0,0 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule
`resetall

View File

@ -1,95 +0,0 @@
# Copyright (c) 2020 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst

View File

@ -1,227 +0,0 @@
"""
Copyright (c) 2020 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
import logging
import os
from scapy.layers.l2 import Ether, ARP
from scapy.layers.inet import IP, UDP
import cocotb_test.simulator
import cocotb
from cocotb.log import SimLog
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink
class TB:
def __init__(self, dut):
self.dut = dut
self.log = SimLog("cocotb.tb")
self.log.setLevel(logging.DEBUG)
cocotb.start_soon(Clock(dut.clk, 2.56, units="ns").start())
# Ethernet
self.qsfp_source = []
self.qsfp_sink = []
for x in range(2):
sources = []
sinks = []
for y in range(1, 5):
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_rx_clk_{y}"), 2.56, units="ns").start())
source = XgmiiSource(getattr(dut, f"qsfp{x}_rxd_{y}"), getattr(dut, f"qsfp{x}_rxc_{y}"), getattr(dut, f"qsfp{x}_rx_clk_{y}"), getattr(dut, f"qsfp{x}_rx_rst_{y}"))
sources.append(source)
cocotb.start_soon(Clock(getattr(dut, f"qsfp{x}_tx_clk_{y}"), 2.56, units="ns").start())
sink = XgmiiSink(getattr(dut, f"qsfp{x}_txd_{y}"), getattr(dut, f"qsfp{x}_txc_{y}"), getattr(dut, f"qsfp{x}_tx_clk_{y}"), getattr(dut, f"qsfp{x}_tx_rst_{y}"))
sinks.append(sink)
self.qsfp_source.append(sources)
self.qsfp_sink.append(sinks)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").setimmediatevalue(0)
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 1
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for x in range(2):
for y in range(1, 5):
getattr(self.dut, f"qsfp{x}_rx_rst_{y}").value = 0
getattr(self.dut, f"qsfp{x}_tx_rst_{y}").value = 0
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("test UDP RX packet")
payload = bytes([x % 256 for x in range(256)])
eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00')
ip = IP(src='192.168.1.100', dst='192.168.1.128')
udp = UDP(sport=5678, dport=1234)
test_pkt = eth / ip / udp / payload
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_source[0][0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_sink[0][0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff'
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[ARP].hwtype == 1
assert rx_pkt[ARP].ptype == 0x0800
assert rx_pkt[ARP].hwlen == 6
assert rx_pkt[ARP].plen == 4
assert rx_pkt[ARP].op == 1
assert rx_pkt[ARP].hwsrc == test_pkt.dst
assert rx_pkt[ARP].psrc == test_pkt[IP].dst
assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00'
assert rx_pkt[ARP].pdst == test_pkt[IP].src
tb.log.info("send ARP response")
eth = Ether(src=test_pkt.src, dst=test_pkt.dst)
arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2,
hwsrc=test_pkt.src, psrc=test_pkt[IP].src,
hwdst=test_pkt.dst, pdst=test_pkt[IP].dst)
resp_pkt = eth / arp
resp_frame = XgmiiFrame.from_payload(resp_pkt.build())
await tb.qsfp_source[0][0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_sink[0][0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
tb.log.info("RX packet: %s", repr(rx_pkt))
assert rx_pkt.dst == test_pkt.src
assert rx_pkt.src == test_pkt.dst
assert rx_pkt[IP].dst == test_pkt[IP].src
assert rx_pkt[IP].src == test_pkt[IP].dst
assert rx_pkt[UDP].dport == test_pkt[UDP].sport
assert rx_pkt[UDP].sport == test_pkt[UDP].dport
assert rx_pkt[UDP].payload == test_pkt[UDP].payload
await RisingEdge(dut.clk)
await RisingEdge(dut.clk)
# cocotb-test
tests_dir = os.path.abspath(os.path.dirname(__file__))
rtl_dir = os.path.abspath(os.path.join(tests_dir, '..', '..', 'rtl'))
lib_dir = os.path.abspath(os.path.join(rtl_dir, '..', 'lib'))
axis_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'lib', 'axis', 'rtl'))
eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl'))
def test_fpga_core(request):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
verilog_sources = [
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_rx_64.v"),
os.path.join(eth_rtl_dir, "axis_xgmii_tx_64.v"),
os.path.join(eth_rtl_dir, "lfsr.v"),
os.path.join(eth_rtl_dir, "eth_axis_rx.v"),
os.path.join(eth_rtl_dir, "eth_axis_tx.v"),
os.path.join(eth_rtl_dir, "udp_complete_64.v"),
os.path.join(eth_rtl_dir, "udp_checksum_gen_64.v"),
os.path.join(eth_rtl_dir, "udp_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_rx_64.v"),
os.path.join(eth_rtl_dir, "udp_ip_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_complete_64.v"),
os.path.join(eth_rtl_dir, "ip_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_rx_64.v"),
os.path.join(eth_rtl_dir, "ip_eth_tx_64.v"),
os.path.join(eth_rtl_dir, "ip_arb_mux.v"),
os.path.join(eth_rtl_dir, "arp.v"),
os.path.join(eth_rtl_dir, "arp_cache.v"),
os.path.join(eth_rtl_dir, "arp_eth_rx.v"),
os.path.join(eth_rtl_dir, "arp_eth_tx.v"),
os.path.join(eth_rtl_dir, "eth_arb_mux.v"),
os.path.join(axis_rtl_dir, "arbiter.v"),
os.path.join(axis_rtl_dir, "priority_encoder.v"),
os.path.join(axis_rtl_dir, "axis_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
]
parameters = {}
# parameters['A'] = val
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)

View File

@ -1,25 +0,0 @@
# Targets
TARGETS:=
# Subdirectories
SUBDIRS = fpga
SUBDIRS_CLEAN = $(patsubst %,%.clean,$(SUBDIRS))
# Rules
.PHONY: all
all: $(SUBDIRS) $(TARGETS)
.PHONY: $(SUBDIRS)
$(SUBDIRS):
cd $@ && $(MAKE)
.PHONY: $(SUBDIRS_CLEAN)
$(SUBDIRS_CLEAN):
cd $(@:.clean=) && $(MAKE) clean
.PHONY: clean
clean: $(SUBDIRS_CLEAN)
-rm -rf $(TARGETS)
program:
#djtgcfg prog -d Atlys --index 0 --file fpga/fpga.bit

View File

@ -1,30 +0,0 @@
# Verilog Ethernet Alveo U50 Example Design
## Introduction
This example design targets the Xilinx Alveo U50 FPGA board.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and
will echo back any packets received. The design will also respond correctly
to ARP requests.
* FPGA: xcu50-fsvh2104-2-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver
## How to build
Run make to build. Ensure that the Xilinx Vivado toolchain components are
in PATH.
## How to test
Run make program to program the Alveo U50 board with Vivado. Then run
netcat -u 192.168.1.128 1234
to open a UDP connection to port 1234. Any text entered into netcat will be
echoed back after pressing enter.
It is also possible to use hping to test the design by running
hping 192.168.1.128 -2 -p 1234 -d 1024

View File

@ -1,137 +0,0 @@
###################################################################
#
# Xilinx Vivado FPGA Makefile
#
# Copyright (c) 2016 Alex Forencich
#
###################################################################
#
# Parameters:
# FPGA_TOP - Top module name
# FPGA_FAMILY - FPGA family (e.g. VirtexUltrascale)
# FPGA_DEVICE - FPGA device (e.g. xcvu095-ffva2104-2-e)
# SYN_FILES - space-separated list of source files
# INC_FILES - space-separated list of include files
# XDC_FILES - space-separated list of timing constraint files
# XCI_FILES - space-separated list of IP XCI files
#
# Example:
#
# FPGA_TOP = fpga
# FPGA_FAMILY = VirtexUltrascale
# FPGA_DEVICE = xcvu095-ffva2104-2-e
# SYN_FILES = rtl/fpga.v
# XDC_FILES = fpga.xdc
# XCI_FILES = ip/pcspma.xci
# include ../common/vivado.mk
#
###################################################################
# phony targets
.PHONY: fpga vivado tmpclean clean distclean
# prevent make from deleting intermediate files and reports
.PRECIOUS: %.xpr %.bit %.mcs %.prm
.SECONDARY:
CONFIG ?= config.mk
-include ../$(CONFIG)
FPGA_TOP ?= fpga
PROJECT ?= $(FPGA_TOP)
SYN_FILES_REL = $(foreach p,$(SYN_FILES),$(if $(filter /% ./%,$p),$p,../$p))
INC_FILES_REL = $(foreach p,$(INC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
XCI_FILES_REL = $(foreach p,$(XCI_FILES),$(if $(filter /% ./%,$p),$p,../$p))
IP_TCL_FILES_REL = $(foreach p,$(IP_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
CONFIG_TCL_FILES_REL = $(foreach p,$(CONFIG_TCL_FILES),$(if $(filter /% ./%,$p),$p,../$p))
ifdef XDC_FILES
XDC_FILES_REL = $(foreach p,$(XDC_FILES),$(if $(filter /% ./%,$p),$p,../$p))
else
XDC_FILES_REL = $(PROJECT).xdc
endif
###################################################################
# Main Targets
#
# all: build everything
# clean: remove output files and project files
###################################################################
all: fpga
fpga: $(PROJECT).bit
vivado: $(PROJECT).xpr
vivado $(PROJECT).xpr
tmpclean::
-rm -rf *.log *.jou *.cache *.gen *.hbs *.hw *.ip_user_files *.runs *.xpr *.html *.xml *.sim *.srcs *.str .Xil defines.v
-rm -rf create_project.tcl update_config.tcl run_synth.tcl run_impl.tcl generate_bit.tcl
clean:: tmpclean
-rm -rf *.bit *.ltx program.tcl generate_mcs.tcl *.mcs *.prm flash.tcl
-rm -rf *_utilization.rpt *_utilization_hierarchical.rpt
distclean:: clean
-rm -rf rev
###################################################################
# Target implementations
###################################################################
# Vivado project file
create_project.tcl: Makefile $(XCI_FILES_REL) $(IP_TCL_FILES_REL)
rm -rf defines.v
touch defines.v
for x in $(DEFS); do echo '`define' $$x >> defines.v; done
echo "create_project -force -part $(FPGA_PART) $(PROJECT)" > $@
echo "add_files -fileset sources_1 defines.v $(SYN_FILES_REL)" >> $@
echo "set_property top $(FPGA_TOP) [current_fileset]" >> $@
echo "add_files -fileset constrs_1 $(XDC_FILES_REL)" >> $@
for x in $(XCI_FILES_REL); do echo "import_ip $$x" >> $@; done
for x in $(IP_TCL_FILES_REL); do echo "source $$x" >> $@; done
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
update_config.tcl: $(CONFIG_TCL_FILES_REL) $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL)
echo "open_project -quiet $(PROJECT).xpr" > $@
for x in $(CONFIG_TCL_FILES_REL); do echo "source $$x" >> $@; done
$(PROJECT).xpr: create_project.tcl update_config.tcl
vivado -nojournal -nolog -mode batch $(foreach x,$?,-source $x)
# synthesis run
$(PROJECT).runs/synth_1/$(PROJECT).dcp: create_project.tcl update_config.tcl $(SYN_FILES_REL) $(INC_FILES_REL) $(XDC_FILES_REL) | $(PROJECT).xpr
echo "open_project $(PROJECT).xpr" > run_synth.tcl
echo "reset_run synth_1" >> run_synth.tcl
echo "launch_runs -jobs 4 synth_1" >> run_synth.tcl
echo "wait_on_run synth_1" >> run_synth.tcl
vivado -nojournal -nolog -mode batch -source run_synth.tcl
# implementation run
$(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp: $(PROJECT).runs/synth_1/$(PROJECT).dcp
echo "open_project $(PROJECT).xpr" > run_impl.tcl
echo "reset_run impl_1" >> run_impl.tcl
echo "launch_runs -jobs 4 impl_1" >> run_impl.tcl
echo "wait_on_run impl_1" >> run_impl.tcl
echo "open_run impl_1" >> run_impl.tcl
echo "report_utilization -file $(PROJECT)_utilization.rpt" >> run_impl.tcl
echo "report_utilization -hierarchical -file $(PROJECT)_utilization_hierarchical.rpt" >> run_impl.tcl
vivado -nojournal -nolog -mode batch -source run_impl.tcl
# bit file
$(PROJECT).bit $(PROJECT).ltx: $(PROJECT).runs/impl_1/$(PROJECT)_routed.dcp
echo "open_project $(PROJECT).xpr" > generate_bit.tcl
echo "open_run impl_1" >> generate_bit.tcl
echo "write_bitstream -force $(PROJECT).runs/impl_1/$(PROJECT).bit" >> generate_bit.tcl
echo "write_debug_probes -force $(PROJECT).runs/impl_1/$(PROJECT).ltx" >> generate_bit.tcl
vivado -nojournal -nolog -mode batch -source generate_bit.tcl
ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).bit .
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then ln -f -s $(PROJECT).runs/impl_1/$(PROJECT).ltx .; fi
mkdir -p rev
COUNT=100; \
while [ -e rev/$(PROJECT)_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
cp -pv $(PROJECT).runs/impl_1/$(PROJECT).bit rev/$(PROJECT)_rev$$COUNT.bit; \
if [ -e $(PROJECT).runs/impl_1/$(PROJECT).ltx ]; then cp -pv $(PROJECT).runs/impl_1/$(PROJECT).ltx rev/$(PROJECT)_rev$$COUNT.ltx; fi

View File

@ -1,76 +0,0 @@
# Copyright (c) 2021 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
set base_name {eth_xcvr_gt}
set preset {GTY-10GBASE-R}
set freerun_freq {125}
set line_rate {10.3125}
set refclk_freq {161.1328125}
set qpll_fracn [expr {int(fmod($line_rate*1000/2 / $refclk_freq, 1)*pow(2, 24))}]
set user_data_width {64}
set int_data_width $user_data_width
set extra_ports [list]
set extra_pll_ports [list {qpll0lock_out}]
set config [dict create]
dict set config TX_LINE_RATE $line_rate
dict set config TX_REFCLK_FREQUENCY $refclk_freq
dict set config TX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config TX_USER_DATA_WIDTH $user_data_width
dict set config TX_INT_DATA_WIDTH $int_data_width
dict set config RX_LINE_RATE $line_rate
dict set config RX_REFCLK_FREQUENCY $refclk_freq
dict set config RX_QPLL_FRACN_NUMERATOR $qpll_fracn
dict set config RX_USER_DATA_WIDTH $user_data_width
dict set config RX_INT_DATA_WIDTH $int_data_width
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {CORE}
dict set config LOCATE_RESET_CONTROLLER {CORE}
dict set config LOCATE_TX_USER_CLOCKING {CORE}
dict set config LOCATE_RX_USER_CLOCKING {CORE}
dict set config LOCATE_USER_DATA_WIDTH_SIZING {CORE}
dict set config FREERUN_FREQUENCY $freerun_freq
dict set config DISABLE_LOC_XDC {1}
proc create_gtwizard_ip {name preset config} {
create_ip -name gtwizard_ultrascale -vendor xilinx.com -library ip -module_name $name
set ip [get_ips $name]
set_property CONFIG.preset $preset $ip
set config_list {}
dict for {name value} $config {
lappend config_list "CONFIG.${name}" $value
}
set_property -dict $config_list $ip
}
# variant with channel and common
dict set config ENABLE_OPTIONAL_PORTS [concat $extra_pll_ports $extra_ports]
dict set config LOCATE_COMMON {CORE}
create_gtwizard_ip "${base_name}_full" $preset $config
# variant with channel only
dict set config ENABLE_OPTIONAL_PORTS $extra_ports
dict set config LOCATE_COMMON {EXAMPLE_DESIGN}
create_gtwizard_ip "${base_name}_channel" $preset $config

View File

@ -1 +0,0 @@
../../../../

View File

@ -1,395 +0,0 @@
/*
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY quad wrapper
*/
module eth_xcvr_phy_quad_wrapper #
(
parameter COUNT = 4,
parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH = (DATA_WIDTH/8),
parameter HDR_WIDTH = 2,
parameter PRBS31_ENABLE = 0,
parameter TX_SERDES_PIPELINE = 0,
parameter RX_SERDES_PIPELINE = 0,
parameter BITSLIP_HIGH_CYCLES = 1,
parameter BITSLIP_LOW_CYCLES = 8,
parameter COUNT_125US = 125000/6.4
)
(
input wire xcvr_ctrl_clk,
input wire xcvr_ctrl_rst,
/*
* Common
*/
output wire xcvr_gtpowergood_out,
/*
* PLL
*/
input wire xcvr_gtrefclk00_in,
/*
* Serial data
*/
output wire [COUNT-1:0] xcvr_txp,
output wire [COUNT-1:0] xcvr_txn,
input wire [COUNT-1:0] xcvr_rxp,
input wire [COUNT-1:0] xcvr_rxn,
/*
* PHY connections
*/
output wire phy_1_tx_clk,
output wire phy_1_tx_rst,
input wire [DATA_WIDTH-1:0] phy_1_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_1_xgmii_txc,
output wire phy_1_rx_clk,
output wire phy_1_rx_rst,
output wire [DATA_WIDTH-1:0] phy_1_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_1_xgmii_rxc,
output wire phy_1_tx_bad_block,
output wire [6:0] phy_1_rx_error_count,
output wire phy_1_rx_bad_block,
output wire phy_1_rx_sequence_error,
output wire phy_1_rx_block_lock,
output wire phy_1_rx_high_ber,
output wire phy_1_rx_status,
input wire phy_1_cfg_tx_prbs31_enable,
input wire phy_1_cfg_rx_prbs31_enable,
output wire phy_2_tx_clk,
output wire phy_2_tx_rst,
input wire [DATA_WIDTH-1:0] phy_2_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_2_xgmii_txc,
output wire phy_2_rx_clk,
output wire phy_2_rx_rst,
output wire [DATA_WIDTH-1:0] phy_2_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_2_xgmii_rxc,
output wire phy_2_tx_bad_block,
output wire [6:0] phy_2_rx_error_count,
output wire phy_2_rx_bad_block,
output wire phy_2_rx_sequence_error,
output wire phy_2_rx_block_lock,
output wire phy_2_rx_high_ber,
output wire phy_2_rx_status,
input wire phy_2_cfg_tx_prbs31_enable,
input wire phy_2_cfg_rx_prbs31_enable,
output wire phy_3_tx_clk,
output wire phy_3_tx_rst,
input wire [DATA_WIDTH-1:0] phy_3_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_3_xgmii_txc,
output wire phy_3_rx_clk,
output wire phy_3_rx_rst,
output wire [DATA_WIDTH-1:0] phy_3_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_3_xgmii_rxc,
output wire phy_3_tx_bad_block,
output wire [6:0] phy_3_rx_error_count,
output wire phy_3_rx_bad_block,
output wire phy_3_rx_sequence_error,
output wire phy_3_rx_block_lock,
output wire phy_3_rx_high_ber,
output wire phy_3_rx_status,
input wire phy_3_cfg_tx_prbs31_enable,
input wire phy_3_cfg_rx_prbs31_enable,
output wire phy_4_tx_clk,
output wire phy_4_tx_rst,
input wire [DATA_WIDTH-1:0] phy_4_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_4_xgmii_txc,
output wire phy_4_rx_clk,
output wire phy_4_rx_rst,
output wire [DATA_WIDTH-1:0] phy_4_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_4_xgmii_rxc,
output wire phy_4_tx_bad_block,
output wire [6:0] phy_4_rx_error_count,
output wire phy_4_rx_bad_block,
output wire phy_4_rx_sequence_error,
output wire phy_4_rx_block_lock,
output wire phy_4_rx_high_ber,
output wire phy_4_rx_status,
input wire phy_4_cfg_tx_prbs31_enable,
input wire phy_4_cfg_rx_prbs31_enable
);
generate
wire xcvr_qpll0lock;
wire xcvr_qpll0clk;
wire xcvr_qpll0refclk;
if (COUNT > 0) begin : phy1
eth_xcvr_phy_wrapper #(
.HAS_COMMON(1),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_1 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(xcvr_gtpowergood_out),
// PLL out
.xcvr_gtrefclk00_in(xcvr_gtrefclk00_in),
.xcvr_qpll0lock_out(xcvr_qpll0lock),
.xcvr_qpll0clk_out(xcvr_qpll0clk),
.xcvr_qpll0refclk_out(xcvr_qpll0refclk),
// PLL in
.xcvr_qpll0lock_in(1'b0),
.xcvr_qpll0clk_in(1'b0),
.xcvr_qpll0refclk_in(1'b0),
// Serial data
.xcvr_txp(xcvr_txp[0]),
.xcvr_txn(xcvr_txn[0]),
.xcvr_rxp(xcvr_rxp[0]),
.xcvr_rxn(xcvr_rxn[0]),
// PHY connections
.phy_tx_clk(phy_1_tx_clk),
.phy_tx_rst(phy_1_tx_rst),
.phy_xgmii_txd(phy_1_xgmii_txd),
.phy_xgmii_txc(phy_1_xgmii_txc),
.phy_rx_clk(phy_1_rx_clk),
.phy_rx_rst(phy_1_rx_rst),
.phy_xgmii_rxd(phy_1_xgmii_rxd),
.phy_xgmii_rxc(phy_1_xgmii_rxc),
.phy_tx_bad_block(phy_1_tx_bad_block),
.phy_rx_error_count(phy_1_rx_error_count),
.phy_rx_bad_block(phy_1_rx_bad_block),
.phy_rx_sequence_error(phy_1_rx_sequence_error),
.phy_rx_block_lock(phy_1_rx_block_lock),
.phy_rx_high_ber(phy_1_rx_high_ber),
.phy_rx_status(phy_1_rx_status),
.phy_cfg_tx_prbs31_enable(phy_1_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_1_cfg_rx_prbs31_enable)
);
end
if (COUNT > 1) begin : phy2
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_2 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[1]),
.xcvr_txn(xcvr_txn[1]),
.xcvr_rxp(xcvr_rxp[1]),
.xcvr_rxn(xcvr_rxn[1]),
// PHY connections
.phy_tx_clk(phy_2_tx_clk),
.phy_tx_rst(phy_2_tx_rst),
.phy_xgmii_txd(phy_2_xgmii_txd),
.phy_xgmii_txc(phy_2_xgmii_txc),
.phy_rx_clk(phy_2_rx_clk),
.phy_rx_rst(phy_2_rx_rst),
.phy_xgmii_rxd(phy_2_xgmii_rxd),
.phy_xgmii_rxc(phy_2_xgmii_rxc),
.phy_tx_bad_block(phy_2_tx_bad_block),
.phy_rx_error_count(phy_2_rx_error_count),
.phy_rx_bad_block(phy_2_rx_bad_block),
.phy_rx_sequence_error(phy_2_rx_sequence_error),
.phy_rx_block_lock(phy_2_rx_block_lock),
.phy_rx_high_ber(phy_2_rx_high_ber),
.phy_rx_status(phy_2_rx_status),
.phy_cfg_tx_prbs31_enable(phy_2_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_2_cfg_rx_prbs31_enable)
);
end
if (COUNT > 2) begin : phy3
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_3 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[2]),
.xcvr_txn(xcvr_txn[2]),
.xcvr_rxp(xcvr_rxp[2]),
.xcvr_rxn(xcvr_rxn[2]),
// PHY connections
.phy_tx_clk(phy_3_tx_clk),
.phy_tx_rst(phy_3_tx_rst),
.phy_xgmii_txd(phy_3_xgmii_txd),
.phy_xgmii_txc(phy_3_xgmii_txc),
.phy_rx_clk(phy_3_rx_clk),
.phy_rx_rst(phy_3_rx_rst),
.phy_xgmii_rxd(phy_3_xgmii_rxd),
.phy_xgmii_rxc(phy_3_xgmii_rxc),
.phy_tx_bad_block(phy_3_tx_bad_block),
.phy_rx_error_count(phy_3_rx_error_count),
.phy_rx_bad_block(phy_3_rx_bad_block),
.phy_rx_sequence_error(phy_3_rx_sequence_error),
.phy_rx_block_lock(phy_3_rx_block_lock),
.phy_rx_high_ber(phy_3_rx_high_ber),
.phy_rx_status(phy_3_rx_status),
.phy_cfg_tx_prbs31_enable(phy_3_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_3_cfg_rx_prbs31_enable)
);
end
if (COUNT > 3) begin : phy4
eth_xcvr_phy_wrapper #(
.HAS_COMMON(0),
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
eth_xcvr_phy_4 (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
.xcvr_ctrl_rst(xcvr_ctrl_rst),
// Common
.xcvr_gtpowergood_out(),
// PLL out
.xcvr_gtrefclk00_in(1'b0),
.xcvr_qpll0lock_out(),
.xcvr_qpll0clk_out(),
.xcvr_qpll0refclk_out(),
// PLL in
.xcvr_qpll0lock_in(xcvr_qpll0lock),
.xcvr_qpll0clk_in(xcvr_qpll0clk),
.xcvr_qpll0refclk_in(xcvr_qpll0refclk),
// Serial data
.xcvr_txp(xcvr_txp[3]),
.xcvr_txn(xcvr_txn[3]),
.xcvr_rxp(xcvr_rxp[3]),
.xcvr_rxn(xcvr_rxn[3]),
// PHY connections
.phy_tx_clk(phy_4_tx_clk),
.phy_tx_rst(phy_4_tx_rst),
.phy_xgmii_txd(phy_4_xgmii_txd),
.phy_xgmii_txc(phy_4_xgmii_txc),
.phy_rx_clk(phy_4_rx_clk),
.phy_rx_rst(phy_4_rx_rst),
.phy_xgmii_rxd(phy_4_xgmii_rxd),
.phy_xgmii_rxc(phy_4_xgmii_rxc),
.phy_tx_bad_block(phy_4_tx_bad_block),
.phy_rx_error_count(phy_4_rx_error_count),
.phy_rx_bad_block(phy_4_rx_bad_block),
.phy_rx_sequence_error(phy_4_rx_sequence_error),
.phy_rx_block_lock(phy_4_rx_block_lock),
.phy_rx_high_ber(phy_4_rx_high_ber),
.phy_rx_status(phy_4_rx_status),
.phy_cfg_tx_prbs31_enable(phy_4_cfg_tx_prbs31_enable),
.phy_cfg_rx_prbs31_enable(phy_4_cfg_rx_prbs31_enable)
);
end
endgenerate
endmodule
`resetall

View File

@ -1,307 +0,0 @@
/*
Copyright (c) 2021-2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Transceiver and PHY wrapper
*/
module eth_xcvr_phy_wrapper #
(
parameter HAS_COMMON = 1,
parameter DATA_WIDTH = 64,
parameter CTRL_WIDTH = (DATA_WIDTH/8),
parameter HDR_WIDTH = 2,
parameter PRBS31_ENABLE = 0,
parameter TX_SERDES_PIPELINE = 0,
parameter RX_SERDES_PIPELINE = 0,
parameter BITSLIP_HIGH_CYCLES = 1,
parameter BITSLIP_LOW_CYCLES = 8,
parameter COUNT_125US = 125000/6.4
)
(
input wire xcvr_ctrl_clk,
input wire xcvr_ctrl_rst,
/*
* Common
*/
output wire xcvr_gtpowergood_out,
/*
* PLL out
*/
input wire xcvr_gtrefclk00_in,
output wire xcvr_qpll0lock_out,
output wire xcvr_qpll0clk_out,
output wire xcvr_qpll0refclk_out,
/*
* PLL in
*/
input wire xcvr_qpll0lock_in,
output wire xcvr_qpll0reset_out,
input wire xcvr_qpll0clk_in,
input wire xcvr_qpll0refclk_in,
/*
* Serial data
*/
output wire xcvr_txp,
output wire xcvr_txn,
input wire xcvr_rxp,
input wire xcvr_rxn,
/*
* PHY connections
*/
output wire phy_tx_clk,
output wire phy_tx_rst,
input wire [DATA_WIDTH-1:0] phy_xgmii_txd,
input wire [CTRL_WIDTH-1:0] phy_xgmii_txc,
output wire phy_rx_clk,
output wire phy_rx_rst,
output wire [DATA_WIDTH-1:0] phy_xgmii_rxd,
output wire [CTRL_WIDTH-1:0] phy_xgmii_rxc,
output wire phy_tx_bad_block,
output wire [6:0] phy_rx_error_count,
output wire phy_rx_bad_block,
output wire phy_rx_sequence_error,
output wire phy_rx_block_lock,
output wire phy_rx_high_ber,
output wire phy_rx_status,
input wire phy_cfg_tx_prbs31_enable,
input wire phy_cfg_rx_prbs31_enable
);
wire phy_rx_reset_req;
wire gt_reset_tx_datapath = 1'b0;
wire gt_reset_rx_datapath = phy_rx_reset_req;
wire gt_reset_tx_done;
wire gt_reset_rx_done;
wire [5:0] gt_txheader;
wire [63:0] gt_txdata;
wire gt_rxgearboxslip;
wire [5:0] gt_rxheader;
wire [1:0] gt_rxheadervalid;
wire [63:0] gt_rxdata;
wire [1:0] gt_rxdatavalid;
generate
if (HAS_COMMON) begin : xcvr
eth_xcvr_gt_full
eth_xcvr_gt_full_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtrefclk00_in(xcvr_gtrefclk00_in),
.qpll0lock_out(xcvr_qpll0lock_out),
.qpll0outclk_out(xcvr_qpll0clk_out),
.qpll0outrefclk_out(xcvr_qpll0refclk_out),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
assign xcvr_qpll0reset_out = 1'b0;
end else begin : xcvr
eth_xcvr_gt_channel
eth_xcvr_gt_channel_inst (
// Common
.gtwiz_reset_clk_freerun_in(xcvr_ctrl_clk),
.gtwiz_reset_all_in(xcvr_ctrl_rst),
.gtpowergood_out(xcvr_gtpowergood_out),
// PLL
.gtwiz_reset_qpll0lock_in(xcvr_qpll0lock_in),
.gtwiz_reset_qpll0reset_out(xcvr_qpll0reset_out),
.qpll0clk_in(xcvr_qpll0clk_in),
.qpll0refclk_in(xcvr_qpll0refclk_in),
.qpll1clk_in(1'b0),
.qpll1refclk_in(1'b0),
// Serial data
.gtytxp_out(xcvr_txp),
.gtytxn_out(xcvr_txn),
.gtyrxp_in(xcvr_rxp),
.gtyrxn_in(xcvr_rxn),
// Transmit
.gtwiz_userclk_tx_reset_in(1'b0),
.gtwiz_userclk_tx_srcclk_out(),
.gtwiz_userclk_tx_usrclk_out(),
.gtwiz_userclk_tx_usrclk2_out(phy_tx_clk),
.gtwiz_userclk_tx_active_out(),
.gtwiz_reset_tx_pll_and_datapath_in(1'b0),
.gtwiz_reset_tx_datapath_in(gt_reset_tx_datapath),
.gtwiz_reset_tx_done_out(gt_reset_tx_done),
.txpmaresetdone_out(),
.txprgdivresetdone_out(),
.gtwiz_userdata_tx_in(gt_txdata),
.txheader_in(gt_txheader),
.txsequence_in(7'b0),
// Receive
.gtwiz_userclk_rx_reset_in(1'b0),
.gtwiz_userclk_rx_srcclk_out(),
.gtwiz_userclk_rx_usrclk_out(),
.gtwiz_userclk_rx_usrclk2_out(phy_rx_clk),
.gtwiz_userclk_rx_active_out(),
.gtwiz_reset_rx_pll_and_datapath_in(1'b0),
.gtwiz_reset_rx_datapath_in(gt_reset_rx_datapath),
.gtwiz_reset_rx_cdr_stable_out(),
.gtwiz_reset_rx_done_out(gt_reset_rx_done),
.rxpmaresetdone_out(),
.rxprgdivresetdone_out(),
.rxgearboxslip_in(gt_rxgearboxslip),
.gtwiz_userdata_rx_out(gt_rxdata),
.rxdatavalid_out(gt_rxdatavalid),
.rxheader_out(gt_rxheader),
.rxheadervalid_out(gt_rxheadervalid),
.rxstartofseq_out()
);
assign xcvr_qpll0lock_out = 1'b0;
assign xcvr_qpll0clk_out = 1'b0;
assign xcvr_qpll0refclk_out = 1'b0;
end
endgenerate
sync_reset #(
.N(4)
)
tx_reset_sync_inst (
.clk(phy_tx_clk),
.rst(!gt_reset_tx_done),
.out(phy_tx_rst)
);
sync_reset #(
.N(4)
)
rx_reset_sync_inst (
.clk(phy_rx_clk),
.rst(!gt_reset_rx_done),
.out(phy_rx_rst)
);
eth_phy_10g #(
.DATA_WIDTH(DATA_WIDTH),
.CTRL_WIDTH(CTRL_WIDTH),
.HDR_WIDTH(HDR_WIDTH),
.BIT_REVERSE(1),
.SCRAMBLER_DISABLE(0),
.PRBS31_ENABLE(PRBS31_ENABLE),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
.BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES),
.BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES),
.COUNT_125US(COUNT_125US)
)
phy_inst (
.tx_clk(phy_tx_clk),
.tx_rst(phy_tx_rst),
.rx_clk(phy_rx_clk),
.rx_rst(phy_rx_rst),
.xgmii_txd(phy_xgmii_txd),
.xgmii_txc(phy_xgmii_txc),
.xgmii_rxd(phy_xgmii_rxd),
.xgmii_rxc(phy_xgmii_rxc),
.serdes_tx_data(gt_txdata),
.serdes_tx_hdr(gt_txheader),
.serdes_rx_data(gt_rxdata),
.serdes_rx_hdr(gt_rxheader),
.serdes_rx_bitslip(gt_rxgearboxslip),
.serdes_rx_reset_req(phy_rx_reset_req),
.tx_bad_block(phy_tx_bad_block),
.rx_error_count(phy_rx_error_count),
.rx_bad_block(phy_rx_bad_block),
.rx_sequence_error(phy_rx_sequence_error),
.rx_block_lock(phy_rx_block_lock),
.rx_high_ber(phy_rx_high_ber),
.rx_status(phy_rx_status),
.cfg_tx_prbs31_enable(phy_cfg_tx_prbs31_enable),
.cfg_rx_prbs31_enable(phy_cfg_rx_prbs31_enable)
);
endmodule
`resetall

View File

@ -1,62 +0,0 @@
/*
Copyright (c) 2014-2018 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog-2001
`resetall
`timescale 1 ns / 1 ps
`default_nettype none
/*
* Synchronizes an asyncronous signal to a given clock by using a pipeline of
* two registers.
*/
module sync_signal #(
parameter WIDTH=1, // width of the input and output signals
parameter N=2 // depth of synchronizer
)(
input wire clk,
input wire [WIDTH-1:0] in,
output wire [WIDTH-1:0] out
);
reg [WIDTH-1:0] sync_reg[N-1:0];
/*
* The synchronized output is the last register in the pipeline.
*/
assign out = sync_reg[N-1];
integer k;
always @(posedge clk) begin
sync_reg[0] <= in;
for (k = 1; k < N; k = k + 1) begin
sync_reg[k] <= sync_reg[k-1];
end
end
endmodule
`resetall

View File

@ -1,95 +0,0 @@
# Copyright (c) 2020 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
TOPLEVEL_LANG = verilog
SIM ?= icarus
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
TOPLEVEL = $(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/axis_xgmii_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/lfsr.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_axis_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_checksum_gen_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/udp_ip_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_complete_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_rx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_eth_tx_64.v
VERILOG_SOURCES += ../../lib/eth/rtl/ip_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_cache.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_rx.v
VERILOG_SOURCES += ../../lib/eth/rtl/arp_eth_tx.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_arb_mux.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/arbiter.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/priority_encoder.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
COMPILE_ARGS += -s iverilog_dump
endif
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim
iverilog_dump.v:
echo 'module iverilog_dump();' > $@
echo 'initial begin' >> $@
echo ' $$dumpfile("$(TOPLEVEL).fst");' >> $@
echo ' $$dumpvars(0, $(TOPLEVEL));' >> $@
echo 'end' >> $@
echo 'endmodule' >> $@
clean::
@rm -rf iverilog_dump.v
@rm -rf dump.fst $(TOPLEVEL).fst

View File

@ -1,14 +1,18 @@
# Verilog Ethernet Alveo U200/Alveo U250/VCU1525 Example Design
# Verilog Ethernet Alveo Example Design
## Introduction
This example design targets the Xilinx Alveo U200/Alveo U250/VCU1525 FPGA board.
This design targets multiple FPGA boards, including most of the Xilinx Alveo line.
The design by default listens to UDP port 1234 at IP address 192.168.1.128 and will echo back any packets received. The design will also respond correctly to ARP requests.
* FPGA
* AU50: xcu50-fsvh2104-2-e
* AU55C: xcu55c-fsvh2892-2L-e
* AU55N/C1100: xcu55n-fsvh2892-2L-e
* AU200: xcu200-fsgd2104-2-e
* AU250: xcu250-fsgd2104-2-e
* AU280: xcu280-fsvh2892-2L-e
* VCU1525: xcvu9p-fsgd2104-2L-e
* PHY: 10G BASE-R PHY IP core and internal GTY transceiver

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au280.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -51,7 +51,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au280.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au280.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -51,7 +51,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au280.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au50.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -51,7 +51,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au50.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au50.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -51,7 +51,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au50.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -0,0 +1,114 @@
# FPGA settings
FPGA_PART = xcu55c-fsvh2892-2L-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga_au55.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_register.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga_au55.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > 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 {$(FPGA_TOP).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
%.mcs %.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,114 @@
# FPGA settings
FPGA_PART = xcu55c-fsvh2892-2L-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga_au55.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_register.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga_au55.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > 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 {$(FPGA_TOP).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
%.mcs %.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,114 @@
# FPGA settings
FPGA_PART = xcu55n-fsvh2892-2L-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga_au55.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_register.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga_au55.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > 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 {$(FPGA_TOP).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
%.mcs %.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {25.78125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -0,0 +1,114 @@
# FPGA settings
FPGA_PART = xcu55n-fsvh2892-2L-e
FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga_au55.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
SYN_FILES += rtl/sync_signal.v
SYN_FILES += lib/eth/rtl/eth_mac_10g_fifo.v
SYN_FILES += lib/eth/rtl/eth_mac_10g.v
SYN_FILES += lib/eth/rtl/axis_xgmii_rx_64.v
SYN_FILES += lib/eth/rtl/axis_xgmii_tx_64.v
SYN_FILES += lib/eth/rtl/eth_phy_10g.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_if.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_frame_sync.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_ber_mon.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_rx_watchdog.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx.v
SYN_FILES += lib/eth/rtl/eth_phy_10g_tx_if.v
SYN_FILES += lib/eth/rtl/xgmii_baser_dec_64.v
SYN_FILES += lib/eth/rtl/xgmii_baser_enc_64.v
SYN_FILES += lib/eth/rtl/lfsr.v
SYN_FILES += lib/eth/rtl/eth_axis_rx.v
SYN_FILES += lib/eth/rtl/eth_axis_tx.v
SYN_FILES += lib/eth/rtl/udp_complete_64.v
SYN_FILES += lib/eth/rtl/udp_checksum_gen_64.v
SYN_FILES += lib/eth/rtl/udp_64.v
SYN_FILES += lib/eth/rtl/udp_ip_rx_64.v
SYN_FILES += lib/eth/rtl/udp_ip_tx_64.v
SYN_FILES += lib/eth/rtl/ip_complete_64.v
SYN_FILES += lib/eth/rtl/ip_64.v
SYN_FILES += lib/eth/rtl/ip_eth_rx_64.v
SYN_FILES += lib/eth/rtl/ip_eth_tx_64.v
SYN_FILES += lib/eth/rtl/ip_arb_mux.v
SYN_FILES += lib/eth/rtl/arp.v
SYN_FILES += lib/eth/rtl/arp_cache.v
SYN_FILES += lib/eth/rtl/arp_eth_rx.v
SYN_FILES += lib/eth/rtl/arp_eth_tx.v
SYN_FILES += lib/eth/rtl/eth_arb_mux.v
SYN_FILES += lib/eth/lib/axis/rtl/arbiter.v
SYN_FILES += lib/eth/lib/axis/rtl/priority_encoder.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_register.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo.v
SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga_au55.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl
# IP
IP_TCL_FILES += ip/eth_xcvr_gt.tcl
# Configuration
CONFIG_TCL_FILES = ./config.tcl
include ../common/vivado.mk
program: $(FPGA_TOP).bit
echo "open_hw" > 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 {$(FPGA_TOP).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
%.mcs %.prm: %.bit
echo "write_cfgmem -force -format mcs -size 128 -interface SPIx4 -loadbit {up 0x01002000 $*.bit} -checksum -file $*.mcs" > generate_mcs.tcl
echo "exit" >> generate_mcs.tcl
vivado -nojournal -nolog -mode batch -source generate_mcs.tcl
mkdir -p rev
COUNT=100; \
while [ -e rev/$*_rev$$COUNT.bit ]; \
do COUNT=$$((COUNT+1)); done; \
COUNT=$$((COUNT-1)); \
for x in .mcs .prm; \
do cp $*$$x rev/$*_rev$$COUNT$$x; \
echo "Output: rev/$*_rev$$COUNT$$x"; done;
flash: $(FPGA_TOP).mcs $(FPGA_TOP).prm
echo "open_hw" > flash.tcl
echo "connect_hw_server" >> flash.tcl
echo "open_hw_target" >> flash.tcl
echo "current_hw_device [lindex [get_hw_devices] 0]" >> flash.tcl
echo "refresh_hw_device -update_hw_probes false [current_hw_device]" >> flash.tcl
echo "create_hw_cfgmem -hw_device [current_hw_device] [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4}] 0]" >> flash.tcl
echo "current_hw_cfgmem -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM [current_hw_device]]" >> flash.tcl
echo "set_property PROGRAM.FILES [list \"$(FPGA_TOP).mcs\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.PRM_FILES [list \"$(FPGA_TOP).prm\"] [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ERASE 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CFG_PROGRAM 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.VERIFY 1 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.CHECKSUM 0 [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.ADDRESS_RANGE {use_file} [current_hw_cfgmem]" >> flash.tcl
echo "set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [current_hw_cfgmem]" >> flash.tcl
echo "create_hw_bitstream -hw_device [current_hw_device] [get_property PROGRAM.HW_CFGMEM_BITFILE [current_hw_device]]" >> flash.tcl
echo "program_hw_devices [current_hw_device]" >> flash.tcl
echo "refresh_hw_device [current_hw_device]" >> flash.tcl
echo "program_hw_cfgmem -hw_cfgmem [current_hw_cfgmem]" >> flash.tcl
echo "boot_hw_device [current_hw_device]" >> flash.tcl
echo "exit" >> flash.tcl
vivado -nojournal -nolog -mode batch -source flash.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {10.3125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {25.78125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -5,7 +5,7 @@ FPGA_TOP = fpga
FPGA_ARCH = virtexuplus
# Files for synthesis
SYN_FILES = rtl/fpga.v
SYN_FILES = rtl/fpga_au200.v
SYN_FILES += rtl/fpga_core.v
SYN_FILES += rtl/eth_xcvr_phy_wrapper.v
SYN_FILES += rtl/eth_xcvr_phy_quad_wrapper.v
@ -52,7 +52,7 @@ SYN_FILES += lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
SYN_FILES += lib/eth/lib/axis/rtl/sync_reset.v
# XDC files
XDC_FILES = fpga.xdc
XDC_FILES = fpga_au200.xdc
XDC_FILES += lib/eth/syn/vivado/eth_mac_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/axis_async_fifo.tcl
XDC_FILES += lib/eth/lib/axis/syn/vivado/sync_reset.tcl

View File

@ -0,0 +1,50 @@
# Copyright (c) 2023 Alex Forencich
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Transceiver configuration
set eth_xcvr_freerun_freq {125}
set eth_xcvr_line_rate {10.3125}
set eth_xcvr_sec_line_rate {0}
set eth_xcvr_refclk_freq {161.1328125}
set eth_xcvr_qpll_fracn [expr {int(fmod($eth_xcvr_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_sec_qpll_fracn [expr {int(fmod($eth_xcvr_sec_line_rate*1000/2 / $eth_xcvr_refclk_freq, 1)*pow(2, 24))}]
set eth_xcvr_rx_eq_mode {DFE}
set xcvr_config [dict create]
dict set xcvr_config CONFIG.TX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.TX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.TX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_LINE_RATE $eth_xcvr_line_rate
dict set xcvr_config CONFIG.RX_QPLL_FRACN_NUMERATOR $eth_xcvr_qpll_fracn
dict set xcvr_config CONFIG.RX_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
dict set xcvr_config CONFIG.RX_EQ_MODE $eth_xcvr_rx_eq_mode
if {$eth_xcvr_sec_line_rate != 0} {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE true
dict set xcvr_config CONFIG.SECONDARY_QPLL_FRACN_NUMERATOR $eth_xcvr_sec_qpll_fracn
dict set xcvr_config CONFIG.SECONDARY_QPLL_LINE_RATE $eth_xcvr_sec_line_rate
dict set xcvr_config CONFIG.SECONDARY_QPLL_REFCLK_FREQUENCY $eth_xcvr_refclk_freq
} else {
dict set xcvr_config CONFIG.SECONDARY_QPLL_ENABLE false
}
dict set xcvr_config CONFIG.FREERUN_FREQUENCY $eth_xcvr_freerun_freq
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_full]
set_property -dict $xcvr_config [get_ips eth_xcvr_gt_channel]

View File

@ -45,8 +45,8 @@ set_false_path -from [get_ports {reset}]
set_input_delay 0 [get_ports {reset}]
# UART
#set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart_txd]
#set_property -dict {LOC B33 IOSTANDARD LVCMOS18} [get_ports usb_uart_rxd]
set_property -dict {LOC A28 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports uart_txd]
set_property -dict {LOC B33 IOSTANDARD LVCMOS18} [get_ports uart_rxd]
#set_false_path -to [get_ports {uart_txd}]
#set_output_delay 0 [get_ports {uart_txd}]

View File

@ -37,17 +37,17 @@ set_false_path -to [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}]
set_output_delay 0 [get_ports {qsfp_led_act qsfp_led_stat_g qsfp_led_stat_y}]
# UART
#set_property -dict {LOC BE26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart0_txd]
#set_property -dict {LOC BF26 IOSTANDARD LVCMOS18} [get_ports usb_uart0_rxd]
#set_property -dict {LOC A17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart1_txd]
#set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports usb_uart1_rxd]
#set_property -dict {LOC A19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports usb_uart2_txd]
#set_property -dict {LOC A18 IOSTANDARD LVCMOS18} [get_ports usb_uart2_rxd]
set_property -dict {LOC BE26 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[0]}]
set_property -dict {LOC BF26 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[0]}]
set_property -dict {LOC A17 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[1]}]
set_property -dict {LOC B15 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[1]}]
set_property -dict {LOC A19 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[2]}]
set_property -dict {LOC A18 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[2]}]
#set_false_path -to [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}]
#set_output_delay 0 [get_ports {usb_uart0_txd usb_uart1_txd usb_uart2_txd}]
#set_false_path -from [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}]
#set_input_delay 0 [get_ports {usb_uart0_rxd usb_uart1_rxd usb_uart2_rxd}]
#set_false_path -to [get_ports {uart_txd[*]}]
#set_output_delay 0 [get_ports {uart_txd[*]}]
#set_false_path -from [get_ports {uart_rxd[*]}]
#set_input_delay 0 [get_ports {uart_rxd[*]}]
# BMC
#set_property -dict {LOC C16 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}]

View File

@ -0,0 +1,236 @@
# XDC constraints for the Xilinx Alveo U55C/Alveo U55N/Varium C1100 board
# U55C part: xcu55c-fsvh2892-2L-e
# U55N/C1100 part: xcu55n-fsvh2892-2L-e
# General configuration
set_property CFGBVS GND [current_design]
set_property CONFIG_VOLTAGE 1.8 [current_design]
set_property BITSTREAM.CONFIG.CONFIGFALLBACK ENABLE [current_design]
set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
set_property CONFIG_MODE SPIx4 [current_design]
set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]
set_property BITSTREAM.CONFIG.CONFIGRATE 85.0 [current_design]
set_property BITSTREAM.CONFIG.EXTMASTERCCLK_EN DISABLE [current_design]
set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]
set_property BITSTREAM.CONFIG.UNUSEDPIN PULLUP [current_design]
set_property BITSTREAM.CONFIG.SPI_32BIT_ADDR YES [current_design]
set_property BITSTREAM.CONFIG.OVERTEMPSHUTDOWN Enable [current_design]
#set_operating_conditions -design_power_budget 63
# System clocks
# 100 MHz
#set_property -dict {LOC BK10 IOSTANDARD LVDS} [get_ports clk_100mhz_0_p]
#set_property -dict {LOC BL10 IOSTANDARD LVDS} [get_ports clk_100mhz_0_n]
#create_clock -period 10 -name clk_100mhz_0 [get_ports clk_100mhz_0_p]
# 100 MHz
#set_property -dict {LOC BK43 IOSTANDARD LVDS} [get_ports clk_100mhz_1_p]
#set_property -dict {LOC BK44 IOSTANDARD LVDS} [get_ports clk_100mhz_1_n]
#create_clock -period 10 -name clk_100mhz_1 [get_ports clk_100mhz_1_p]
# 100 MHz
#set_property -dict {LOC F24 IOSTANDARD LVDS} [get_ports clk_100mhz_2_p]
#set_property -dict {LOC F23 IOSTANDARD LVDS} [get_ports clk_100mhz_2_n]
#create_clock -period 10 -name clk_100mhz_2 [get_ports clk_100mhz_2_p]
# Reset button
set_property -dict {LOC BG45 IOSTANDARD LVCMOS18} [get_ports reset]
set_false_path -from [get_ports {reset}]
set_input_delay 0 [get_ports {reset}]
# LEDs
set_property -dict {LOC BL13 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_act[0]}]
set_property -dict {LOC BK11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_stat_g[0]}]
set_property -dict {LOC BJ11 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_stat_y[0]}]
set_property -dict {LOC BK14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_act[1]}]
set_property -dict {LOC BK15 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_stat_g[1]}]
set_property -dict {LOC BL12 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {qsfp_led_stat_y[1]}]
set_false_path -to [get_ports {qsfp_led_act[*] qsfp_led_stat_g[*] qsfp_led_stat_y[*]}]
set_output_delay 0 [get_ports {qsfp_led_act[*] qsfp_led_stat_g[*] qsfp_led_stat_y[*]}]
# UART
set_property -dict {LOC BJ41 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[0]}]
set_property -dict {LOC BK41 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[0]}]
set_property -dict {LOC BN47 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[1]}]
set_property -dict {LOC BP47 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[1]}]
set_property -dict {LOC BL45 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports {uart_txd[2]}]
set_property -dict {LOC BL46 IOSTANDARD LVCMOS18} [get_ports {uart_rxd[2]}]
#set_false_path -to [get_ports {uart_txd[*]}]
#set_output_delay 0 [get_ports {uart_txd[*]}]
#set_false_path -from [get_ports {uart_rxd[*]}]
#set_input_delay 0 [get_ports {uart_rxd[*]}]
# BMC
#set_property -dict {LOC BE46 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[0]}]
#set_property -dict {LOC BH46 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[1]}]
#set_property -dict {LOC BF45 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[2]}]
#set_property -dict {LOC BF46 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_gpio[3]}]
#set_property -dict {LOC BH42 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 4} [get_ports {msp_uart_txd}]
#set_property -dict {LOC BJ42 IOSTANDARD LVCMOS18} [get_ports {msp_uart_rxd}]
#set_false_path -to [get_ports {msp_uart_txd}]
#set_output_delay 0 [get_ports {msp_uart_txd}]
#set_false_path -from [get_ports {msp_gpio[*] msp_uart_rxd}]
#set_input_delay 0 [get_ports {msp_gpio[*] msp_uart_rxd}]
# HBM overtemp
set_property -dict {LOC BE45 IOSTANDARD LVCMOS18} [get_ports hbm_cattrip]
set_false_path -to [get_ports {hbm_cattrip}]
set_output_delay 0 [get_ports {hbm_cattrip}]
# SI5394 (SI5394B-A10605-GM)
# I2C address 0x68
# IN0: 161.1328125 MHz from qsfp_recclk
# OUT0: 161.1328125 MHz to qsfp0_mgt_refclk
# OUT1: 161.1328125 MHz to qsfp1_mgt_refclk
# OUT3: 100 MHz to clk_100mhz_0, clk_100mhz_1, pcie_refclk_2, pcie_refclk_3
#set_property -dict {LOC BM8 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8} [get_ports si5394_rst_b]
#set_property -dict {LOC BM9 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_int_b]
#set_property -dict {LOC BN10 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_lol_b]
#set_property -dict {LOC BM10 IOSTANDARD LVCMOS18 PULLUP true} [get_ports si5394_los_b]
#set_property -dict {LOC BN14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_sda]
#set_property -dict {LOC BM14 IOSTANDARD LVCMOS18 SLEW SLOW DRIVE 8 PULLUP true} [get_ports si5394_scl]
#set_false_path -to [get_ports {si5394_rst_b}]
#set_output_delay 0 [get_ports {si5394_rst_b}]
#set_false_path -from [get_ports {si5394_int_b si5394_lol_b si5394_los_b}]
#set_input_delay 0 [get_ports {si5394_int_b si5394_lol_b si5394_los_b}]
#set_false_path -to [get_ports {si5394_i2c_sda si5394_i2c_scl}]
#set_output_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}]
#set_false_path -from [get_ports {si5394_i2c_sda si5394_i2c_scl}]
#set_input_delay 0 [get_ports {si5394_i2c_sda si5394_i2c_scl}]
# QSFP28 Interfaces
set_property -dict {LOC AD51} [get_ports {qsfp0_rx_p[0]}] ;# MGTYRXP0_130 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AD52} [get_ports {qsfp0_rx_n[0]}] ;# MGTYRXN0_130 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AD46} [get_ports {qsfp0_tx_p[0]}] ;# MGTYTXP0_130 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AD47} [get_ports {qsfp0_tx_n[0]}] ;# MGTYTXN0_130 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC53} [get_ports {qsfp0_rx_p[1]}] ;# MGTYRXP1_130 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC54} [get_ports {qsfp0_rx_n[1]}] ;# MGTYRXN1_130 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC44} [get_ports {qsfp0_tx_p[1]}] ;# MGTYTXP1_130 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC45} [get_ports {qsfp0_tx_n[1]}] ;# MGTYTXN1_130 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC49} [get_ports {qsfp0_rx_p[2]}] ;# MGTYRXP2_130 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AC50} [get_ports {qsfp0_rx_n[2]}] ;# MGTYRXN2_130 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AB46} [get_ports {qsfp0_tx_p[2]}] ;# MGTYTXP2_130 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AB47} [get_ports {qsfp0_tx_n[2]}] ;# MGTYTXN2_130 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AB51} [get_ports {qsfp0_rx_p[3]}] ;# MGTYRXP3_130 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AB52} [get_ports {qsfp0_rx_n[3]}] ;# MGTYRXN3_130 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AA48} [get_ports {qsfp0_tx_p[3]}] ;# MGTYTXP3_130 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AA49} [get_ports {qsfp0_tx_n[3]}] ;# MGTYTXN3_130 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AD42} [get_ports qsfp0_mgt_refclk_p] ;# MGTREFCLK0P_130 from SI5394 OUT0
set_property -dict {LOC AD43} [get_ports qsfp0_mgt_refclk_n] ;# MGTREFCLK0N_130 from SI5394 OUT0
# 161.1328125 MHz MGT reference clock (SI5394 OUT0)
create_clock -period 6.206 -name qsfp0_mgt_refclk [get_ports qsfp0_mgt_refclk_p]
set_property -dict {LOC AA53} [get_ports {qsfp1_rx_p[0]}] ;# MGTYRXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AA54} [get_ports {qsfp1_rx_n[0]}] ;# MGTYRXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AA44} [get_ports {qsfp1_tx_p[0]}] ;# MGTYTXP0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AA45} [get_ports {qsfp1_tx_n[0]}] ;# MGTYTXN0_131 GTYE4_CHANNEL_X0Y28 / GTYE4_COMMON_X0Y7
set_property -dict {LOC Y51 } [get_ports {qsfp1_rx_p[1]}] ;# MGTYRXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC Y52 } [get_ports {qsfp1_rx_n[1]}] ;# MGTYRXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC Y46 } [get_ports {qsfp1_tx_p[1]}] ;# MGTYTXP1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC Y47 } [get_ports {qsfp1_tx_n[1]}] ;# MGTYTXN1_131 GTYE4_CHANNEL_X0Y29 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W53 } [get_ports {qsfp1_rx_p[2]}] ;# MGTYRXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W54 } [get_ports {qsfp1_rx_n[2]}] ;# MGTYRXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W48 } [get_ports {qsfp1_tx_p[2]}] ;# MGTYTXP2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W49 } [get_ports {qsfp1_tx_n[2]}] ;# MGTYTXN2_131 GTYE4_CHANNEL_X0Y30 / GTYE4_COMMON_X0Y7
set_property -dict {LOC V51 } [get_ports {qsfp1_rx_p[3]}] ;# MGTYRXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC V52 } [get_ports {qsfp1_rx_n[3]}] ;# MGTYRXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W44 } [get_ports {qsfp1_tx_p[3]}] ;# MGTYTXP3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC W45 } [get_ports {qsfp1_tx_n[3]}] ;# MGTYTXN3_131 GTYE4_CHANNEL_X0Y31 / GTYE4_COMMON_X0Y7
set_property -dict {LOC AB42} [get_ports qsfp1_mgt_refclk_p] ;# MGTREFCLK0P_131 from SI5394 OUT1
set_property -dict {LOC AB43} [get_ports qsfp1_mgt_refclk_n] ;# MGTREFCLK0N_131 from SI5394 OUT1
# 161.1328125 MHz MGT reference clock (SI5394 OUT1)
create_clock -period 6.206 -name qsfp1_mgt_refclk [get_ports qsfp1_mgt_refclk_p]
# PCIe Interface
#set_property -dict {LOC AL2 } [get_ports {pcie_rx_p[0]}] ;# MGTYRXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AL1 } [get_ports {pcie_rx_n[0]}] ;# MGTYRXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AL11} [get_ports {pcie_tx_p[0]}] ;# MGTYTXP3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AL10} [get_ports {pcie_tx_n[0]}] ;# MGTYTXN3_227 GTYE4_CHANNEL_X1Y15 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AM4 } [get_ports {pcie_rx_p[1]}] ;# MGTYRXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AM3 } [get_ports {pcie_rx_n[1]}] ;# MGTYRXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AM9 } [get_ports {pcie_tx_p[1]}] ;# MGTYTXP2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AM8 } [get_ports {pcie_tx_n[1]}] ;# MGTYTXN2_227 GTYE4_CHANNEL_X1Y14 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN6 } [get_ports {pcie_rx_p[2]}] ;# MGTYRXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN5 } [get_ports {pcie_rx_n[2]}] ;# MGTYRXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN11} [get_ports {pcie_tx_p[2]}] ;# MGTYTXP1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN10} [get_ports {pcie_tx_n[2]}] ;# MGTYTXN1_227 GTYE4_CHANNEL_X1Y13 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN2 } [get_ports {pcie_rx_p[3]}] ;# MGTYRXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AN1 } [get_ports {pcie_rx_n[3]}] ;# MGTYRXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AP9 } [get_ports {pcie_tx_p[3]}] ;# MGTYTXP0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AP8 } [get_ports {pcie_tx_n[3]}] ;# MGTYTXN0_227 GTYE4_CHANNEL_X1Y12 / GTYE4_COMMON_X1Y3
#set_property -dict {LOC AP4 } [get_ports {pcie_rx_p[4]}] ;# MGTYRXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AP3 } [get_ports {pcie_rx_n[4]}] ;# MGTYRXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR11} [get_ports {pcie_tx_p[4]}] ;# MGTYTXP3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR10} [get_ports {pcie_tx_n[4]}] ;# MGTYTXN3_226 GTYE4_CHANNEL_X1Y11 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR2 } [get_ports {pcie_rx_p[5]}] ;# MGTYRXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR1 } [get_ports {pcie_rx_n[5]}] ;# MGTYRXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR7 } [get_ports {pcie_tx_p[5]}] ;# MGTYTXP2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AR6 } [get_ports {pcie_tx_n[5]}] ;# MGTYTXN2_226 GTYE4_CHANNEL_X1Y10 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AT4 } [get_ports {pcie_rx_p[6]}] ;# MGTYRXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AT3 } [get_ports {pcie_rx_n[6]}] ;# MGTYRXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AT9 } [get_ports {pcie_tx_p[6]}] ;# MGTYTXP1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AT8 } [get_ports {pcie_tx_n[6]}] ;# MGTYTXN1_226 GTYE4_CHANNEL_X1Y9 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AU2 } [get_ports {pcie_rx_p[7]}] ;# MGTYRXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AU1 } [get_ports {pcie_rx_n[7]}] ;# MGTYRXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AU11} [get_ports {pcie_tx_p[7]}] ;# MGTYTXP0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AU10} [get_ports {pcie_tx_n[7]}] ;# MGTYTXN0_226 GTYE4_CHANNEL_X1Y8 / GTYE4_COMMON_X1Y2
#set_property -dict {LOC AV4 } [get_ports {pcie_rx_p[8]}] ;# MGTYRXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AV3 } [get_ports {pcie_rx_n[8]}] ;# MGTYRXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AU7 } [get_ports {pcie_tx_p[8]}] ;# MGTYTXP3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AU6 } [get_ports {pcie_tx_n[8]}] ;# MGTYTXN3_225 GTYE4_CHANNEL_X1Y7 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW6 } [get_ports {pcie_rx_p[9]}] ;# MGTYRXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW5 } [get_ports {pcie_rx_n[9]}] ;# MGTYRXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AV9 } [get_ports {pcie_tx_p[9]}] ;# MGTYTXP2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AV8 } [get_ports {pcie_tx_n[9]}] ;# MGTYTXN2_225 GTYE4_CHANNEL_X1Y6 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW2 } [get_ports {pcie_rx_p[10]}] ;# MGTYRXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW1 } [get_ports {pcie_rx_n[10]}] ;# MGTYRXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW11} [get_ports {pcie_tx_p[10]}] ;# MGTYTXP1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AW10} [get_ports {pcie_tx_n[10]}] ;# MGTYTXN1_225 GTYE4_CHANNEL_X1Y5 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AY4 } [get_ports {pcie_rx_p[11]}] ;# MGTYRXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AY3 } [get_ports {pcie_rx_n[11]}] ;# MGTYRXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AY9 } [get_ports {pcie_tx_p[11]}] ;# MGTYTXP0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC AY8 } [get_ports {pcie_tx_n[11]}] ;# MGTYTXN0_225 GTYE4_CHANNEL_X1Y4 / GTYE4_COMMON_X1Y1
#set_property -dict {LOC BA6 } [get_ports {pcie_rx_p[12]}] ;# MGTYRXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BA5 } [get_ports {pcie_rx_n[12]}] ;# MGTYRXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BA11} [get_ports {pcie_tx_p[12]}] ;# MGTYTXP3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BA10} [get_ports {pcie_tx_n[12]}] ;# MGTYTXN3_224 GTYE4_CHANNEL_X1Y3 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BA2 } [get_ports {pcie_rx_p[13]}] ;# MGTYRXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BA1 } [get_ports {pcie_rx_n[13]}] ;# MGTYRXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BB9 } [get_ports {pcie_tx_p[13]}] ;# MGTYTXP2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BB8 } [get_ports {pcie_tx_n[13]}] ;# MGTYTXN2_224 GTYE4_CHANNEL_X1Y2 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BB4 } [get_ports {pcie_rx_p[14]}] ;# MGTYRXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BB3 } [get_ports {pcie_rx_n[14]}] ;# MGTYRXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC11} [get_ports {pcie_tx_p[14]}] ;# MGTYTXP1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC10} [get_ports {pcie_tx_n[14]}] ;# MGTYTXN1_224 GTYE4_CHANNEL_X1Y1 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC2 } [get_ports {pcie_rx_p[15]}] ;# MGTYRXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC1 } [get_ports {pcie_rx_n[15]}] ;# MGTYRXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC7 } [get_ports {pcie_tx_p[15]}] ;# MGTYTXP0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC BC6 } [get_ports {pcie_tx_n[15]}] ;# MGTYTXN0_224 GTYE4_CHANNEL_X1Y0 / GTYE4_COMMON_X1Y0
#set_property -dict {LOC AL15} [get_ports pcie_refclk_0_p] ;# MGTREFCLK0P_227 (for x8 bifurcated lanes 0-7)
#set_property -dict {LOC AL14} [get_ports pcie_refclk_0_n] ;# MGTREFCLK0N_227 (for x8 bifurcated lanes 0-7)
#set_property -dict {LOC AK13} [get_ports pcie_refclk_2_p] ;# MGTREFCLK1P_227 (for async x8 bifurcated lanes 0-7)
#set_property -dict {LOC AK12} [get_ports pcie_refclk_2_n] ;# MGTREFCLK1N_227 (for async x8 bifurcated lanes 0-7)
#set_property -dict {LOC AR15} [get_ports pcie_refclk_1_p] ;# MGTREFCLK0P_225 (for x16 or x8 bifurcated lanes 8-16)
#set_property -dict {LOC AR14} [get_ports pcie_refclk_1_n] ;# MGTREFCLK0N_225 (for x16 or x8 bifurcated lanes 8-16)
#set_property -dict {LOC AP13} [get_ports pcie_refclk_3_p] ;# MGTREFCLK1P_225 (for async x16 or x8 bifurcated lanes 8-16)
#set_property -dict {LOC AP12} [get_ports pcie_refclk_3_n] ;# MGTREFCLK1N_225 (for async x16 or x8 bifurcated lanes 8-16)
#set_property -dict {LOC BF41 IOSTANDARD LVCMOS18 PULLUP true} [get_ports pcie_reset_n]
# 100 MHz MGT reference clock
#create_clock -period 10 -name pcie_mgt_refclk_0 [get_ports pcie_refclk_0_p]
#create_clock -period 10 -name pcie_mgt_refclk_1 [get_ports pcie_refclk_1_p]
#create_clock -period 10 -name pcie_mgt_refclk_2 [get_ports pcie_refclk_2_p]
#create_clock -period 10 -name pcie_mgt_refclk_3 [get_ports pcie_refclk_3_p]
#set_false_path -from [get_ports {pcie_reset_n}]
#set_input_delay 0 [get_ports {pcie_reset_n}]

View File

@ -49,6 +49,12 @@ module fpga (
inout wire i2c_scl,
inout wire i2c_sda,
/*
* UART
*/
output wire uart_txd,
input wire uart_rxd,
/*
* Ethernet: QSFP28
*/
@ -82,13 +88,7 @@ module fpga (
input wire qsfp1_intl,
output wire qsfp1_lpmode,
output wire qsfp1_refclk_reset,
output wire [1:0] qsfp1_fs,
/*
* UART: 500000 bps, 8N1
*/
output wire uart_rxd,
input wire uart_txd
output wire [1:0] qsfp1_fs
);
// Clock and reset
@ -198,18 +198,6 @@ debounce_switch_inst (
.out({sw_int})
);
wire uart_txd_int;
sync_signal #(
.WIDTH(1),
.N(2)
)
sync_signal_inst (
.clk(clk_156mhz_int),
.in({uart_txd}),
.out({uart_txd_int})
);
// SI570 I2C
wire i2c_scl_i;
wire i2c_scl_o = 1'b1;
@ -282,6 +270,20 @@ always @(posedge cfgmclk_int) begin
end
// XGMII 10G PHY
localparam QSFP_CNT = 2;
localparam CH_CNT = QSFP_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
assign clk_156mhz_int = eth_tx_clk[0];
assign rst_156mhz_int = eth_tx_rst[0];
// QSFP0
assign qsfp0_modsell = 1'b0;
@ -290,42 +292,6 @@ assign qsfp0_lpmode = 1'b0;
assign qsfp0_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp0_fs = 2'b10;
wire qsfp0_tx_clk_1_int;
wire qsfp0_tx_rst_1_int;
wire [63:0] qsfp0_txd_1_int;
wire [7:0] qsfp0_txc_1_int;
wire qsfp0_rx_clk_1_int;
wire qsfp0_rx_rst_1_int;
wire [63:0] qsfp0_rxd_1_int;
wire [7:0] qsfp0_rxc_1_int;
wire qsfp0_tx_clk_2_int;
wire qsfp0_tx_rst_2_int;
wire [63:0] qsfp0_txd_2_int;
wire [7:0] qsfp0_txc_2_int;
wire qsfp0_rx_clk_2_int;
wire qsfp0_rx_rst_2_int;
wire [63:0] qsfp0_rxd_2_int;
wire [7:0] qsfp0_rxc_2_int;
wire qsfp0_tx_clk_3_int;
wire qsfp0_tx_rst_3_int;
wire [63:0] qsfp0_txd_3_int;
wire [7:0] qsfp0_txc_3_int;
wire qsfp0_rx_clk_3_int;
wire qsfp0_rx_rst_3_int;
wire [63:0] qsfp0_rxd_3_int;
wire [7:0] qsfp0_rxc_3_int;
wire qsfp0_tx_clk_4_int;
wire qsfp0_tx_rst_4_int;
wire [63:0] qsfp0_txd_4_int;
wire [7:0] qsfp0_txc_4_int;
wire qsfp0_rx_clk_4_int;
wire qsfp0_rx_rst_4_int;
wire [63:0] qsfp0_rxd_4_int;
wire [7:0] qsfp0_rxc_4_int;
assign clk_156mhz_int = qsfp0_tx_clk_1_int;
assign rst_156mhz_int = qsfp0_tx_rst_1_int;
wire qsfp0_rx_block_lock_1;
wire qsfp0_rx_block_lock_2;
wire qsfp0_rx_block_lock_3;
@ -387,14 +353,14 @@ qsfp0_phy_inst (
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp0_tx_clk_1_int),
.phy_1_tx_rst(qsfp0_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp0_txd_1_int),
.phy_1_xgmii_txc(qsfp0_txc_1_int),
.phy_1_rx_clk(qsfp0_rx_clk_1_int),
.phy_1_rx_rst(qsfp0_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp0_rxd_1_int),
.phy_1_xgmii_rxc(qsfp0_rxc_1_int),
.phy_1_tx_clk(eth_tx_clk[0*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[0*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(0*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[0*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[0*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(0*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
@ -404,14 +370,14 @@ qsfp0_phy_inst (
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp0_tx_clk_2_int),
.phy_2_tx_rst(qsfp0_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp0_txd_2_int),
.phy_2_xgmii_txc(qsfp0_txc_2_int),
.phy_2_rx_clk(qsfp0_rx_clk_2_int),
.phy_2_rx_rst(qsfp0_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp0_rxd_2_int),
.phy_2_xgmii_rxc(qsfp0_rxc_2_int),
.phy_2_tx_clk(eth_tx_clk[0*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[0*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(0*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[0*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[0*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(0*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
@ -421,14 +387,14 @@ qsfp0_phy_inst (
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp0_tx_clk_3_int),
.phy_3_tx_rst(qsfp0_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp0_txd_3_int),
.phy_3_xgmii_txc(qsfp0_txc_3_int),
.phy_3_rx_clk(qsfp0_rx_clk_3_int),
.phy_3_rx_rst(qsfp0_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp0_rxd_3_int),
.phy_3_xgmii_rxc(qsfp0_rxc_3_int),
.phy_3_tx_clk(eth_tx_clk[0*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[0*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(0*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[0*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[0*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(0*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
@ -438,14 +404,14 @@ qsfp0_phy_inst (
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp0_tx_clk_4_int),
.phy_4_tx_rst(qsfp0_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp0_txd_4_int),
.phy_4_xgmii_txc(qsfp0_txc_4_int),
.phy_4_rx_clk(qsfp0_rx_clk_4_int),
.phy_4_rx_rst(qsfp0_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp0_rxd_4_int),
.phy_4_xgmii_rxc(qsfp0_rxc_4_int),
.phy_4_tx_clk(eth_tx_clk[0*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[0*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(0*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[0*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[0*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(0*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
@ -463,39 +429,6 @@ assign qsfp1_lpmode = 1'b0;
assign qsfp1_refclk_reset = qsfp_refclk_reset_reg;
assign qsfp1_fs = 2'b10;
wire qsfp1_tx_clk_1_int;
wire qsfp1_tx_rst_1_int;
wire [63:0] qsfp1_txd_1_int;
wire [7:0] qsfp1_txc_1_int;
wire qsfp1_rx_clk_1_int;
wire qsfp1_rx_rst_1_int;
wire [63:0] qsfp1_rxd_1_int;
wire [7:0] qsfp1_rxc_1_int;
wire qsfp1_tx_clk_2_int;
wire qsfp1_tx_rst_2_int;
wire [63:0] qsfp1_txd_2_int;
wire [7:0] qsfp1_txc_2_int;
wire qsfp1_rx_clk_2_int;
wire qsfp1_rx_rst_2_int;
wire [63:0] qsfp1_rxd_2_int;
wire [7:0] qsfp1_rxc_2_int;
wire qsfp1_tx_clk_3_int;
wire qsfp1_tx_rst_3_int;
wire [63:0] qsfp1_txd_3_int;
wire [7:0] qsfp1_txc_3_int;
wire qsfp1_rx_clk_3_int;
wire qsfp1_rx_rst_3_int;
wire [63:0] qsfp1_rxd_3_int;
wire [7:0] qsfp1_rxc_3_int;
wire qsfp1_tx_clk_4_int;
wire qsfp1_tx_rst_4_int;
wire [63:0] qsfp1_txd_4_int;
wire [7:0] qsfp1_txc_4_int;
wire qsfp1_rx_clk_4_int;
wire qsfp1_rx_rst_4_int;
wire [63:0] qsfp1_rxd_4_int;
wire [7:0] qsfp1_rxc_4_int;
wire qsfp1_rx_block_lock_1;
wire qsfp1_rx_block_lock_2;
wire qsfp1_rx_block_lock_3;
@ -541,14 +474,14 @@ qsfp1_phy_inst (
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp1_tx_clk_1_int),
.phy_1_tx_rst(qsfp1_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp1_txd_1_int),
.phy_1_xgmii_txc(qsfp1_txc_1_int),
.phy_1_rx_clk(qsfp1_rx_clk_1_int),
.phy_1_rx_rst(qsfp1_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp1_rxd_1_int),
.phy_1_xgmii_rxc(qsfp1_rxc_1_int),
.phy_1_tx_clk(eth_tx_clk[1*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[1*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(1*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[1*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[1*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(1*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
@ -558,14 +491,14 @@ qsfp1_phy_inst (
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp1_tx_clk_2_int),
.phy_2_tx_rst(qsfp1_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp1_txd_2_int),
.phy_2_xgmii_txc(qsfp1_txc_2_int),
.phy_2_rx_clk(qsfp1_rx_clk_2_int),
.phy_2_rx_rst(qsfp1_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp1_rxd_2_int),
.phy_2_xgmii_rxc(qsfp1_rxc_2_int),
.phy_2_tx_clk(eth_tx_clk[1*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[1*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(1*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[1*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[1*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(1*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
@ -575,14 +508,14 @@ qsfp1_phy_inst (
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp1_tx_clk_3_int),
.phy_3_tx_rst(qsfp1_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp1_txd_3_int),
.phy_3_xgmii_txc(qsfp1_txc_3_int),
.phy_3_rx_clk(qsfp1_rx_clk_3_int),
.phy_3_rx_rst(qsfp1_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp1_rxd_3_int),
.phy_3_xgmii_rxc(qsfp1_rxc_3_int),
.phy_3_tx_clk(eth_tx_clk[1*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[1*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(1*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[1*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[1*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(1*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
@ -592,14 +525,14 @@ qsfp1_phy_inst (
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp1_tx_clk_4_int),
.phy_4_tx_rst(qsfp1_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp1_txd_4_int),
.phy_4_xgmii_txc(qsfp1_txc_4_int),
.phy_4_rx_clk(qsfp1_rx_clk_4_int),
.phy_4_rx_rst(qsfp1_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp1_rxd_4_int),
.phy_4_xgmii_rxc(qsfp1_rxc_4_int),
.phy_4_tx_clk(eth_tx_clk[1*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[1*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(1*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[1*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[1*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(1*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
@ -610,7 +543,13 @@ qsfp1_phy_inst (
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core
fpga_core #(
.SW_CNT(4),
.LED_CNT(3),
.UART_CNT(1),
.QSFP_CNT(QSFP_CNT),
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
@ -618,83 +557,33 @@ core_inst (
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(sw_int),
.led(led),
.qsfp_led_act(),
.qsfp_led_stat_g(),
.qsfp_led_stat_y(),
/*
* UART
*/
.uart_txd(uart_txd),
.uart_rxd(uart_rxd),
/*
* Ethernet: QSFP28
*/
.qsfp0_tx_clk_1(qsfp0_tx_clk_1_int),
.qsfp0_tx_rst_1(qsfp0_tx_rst_1_int),
.qsfp0_txd_1(qsfp0_txd_1_int),
.qsfp0_txc_1(qsfp0_txc_1_int),
.qsfp0_rx_clk_1(qsfp0_rx_clk_1_int),
.qsfp0_rx_rst_1(qsfp0_rx_rst_1_int),
.qsfp0_rxd_1(qsfp0_rxd_1_int),
.qsfp0_rxc_1(qsfp0_rxc_1_int),
.qsfp0_tx_clk_2(qsfp0_tx_clk_2_int),
.qsfp0_tx_rst_2(qsfp0_tx_rst_2_int),
.qsfp0_txd_2(qsfp0_txd_2_int),
.qsfp0_txc_2(qsfp0_txc_2_int),
.qsfp0_rx_clk_2(qsfp0_rx_clk_2_int),
.qsfp0_rx_rst_2(qsfp0_rx_rst_2_int),
.qsfp0_rxd_2(qsfp0_rxd_2_int),
.qsfp0_rxc_2(qsfp0_rxc_2_int),
.qsfp0_tx_clk_3(qsfp0_tx_clk_3_int),
.qsfp0_tx_rst_3(qsfp0_tx_rst_3_int),
.qsfp0_txd_3(qsfp0_txd_3_int),
.qsfp0_txc_3(qsfp0_txc_3_int),
.qsfp0_rx_clk_3(qsfp0_rx_clk_3_int),
.qsfp0_rx_rst_3(qsfp0_rx_rst_3_int),
.qsfp0_rxd_3(qsfp0_rxd_3_int),
.qsfp0_rxc_3(qsfp0_rxc_3_int),
.qsfp0_tx_clk_4(qsfp0_tx_clk_4_int),
.qsfp0_tx_rst_4(qsfp0_tx_rst_4_int),
.qsfp0_txd_4(qsfp0_txd_4_int),
.qsfp0_txc_4(qsfp0_txc_4_int),
.qsfp0_rx_clk_4(qsfp0_rx_clk_4_int),
.qsfp0_rx_rst_4(qsfp0_rx_rst_4_int),
.qsfp0_rxd_4(qsfp0_rxd_4_int),
.qsfp0_rxc_4(qsfp0_rxc_4_int),
.qsfp1_tx_clk_1(qsfp1_tx_clk_1_int),
.qsfp1_tx_rst_1(qsfp1_tx_rst_1_int),
.qsfp1_txd_1(qsfp1_txd_1_int),
.qsfp1_txc_1(qsfp1_txc_1_int),
.qsfp1_rx_clk_1(qsfp1_rx_clk_1_int),
.qsfp1_rx_rst_1(qsfp1_rx_rst_1_int),
.qsfp1_rxd_1(qsfp1_rxd_1_int),
.qsfp1_rxc_1(qsfp1_rxc_1_int),
.qsfp1_tx_clk_2(qsfp1_tx_clk_2_int),
.qsfp1_tx_rst_2(qsfp1_tx_rst_2_int),
.qsfp1_txd_2(qsfp1_txd_2_int),
.qsfp1_txc_2(qsfp1_txc_2_int),
.qsfp1_rx_clk_2(qsfp1_rx_clk_2_int),
.qsfp1_rx_rst_2(qsfp1_rx_rst_2_int),
.qsfp1_rxd_2(qsfp1_rxd_2_int),
.qsfp1_rxc_2(qsfp1_rxc_2_int),
.qsfp1_tx_clk_3(qsfp1_tx_clk_3_int),
.qsfp1_tx_rst_3(qsfp1_tx_rst_3_int),
.qsfp1_txd_3(qsfp1_txd_3_int),
.qsfp1_txc_3(qsfp1_txc_3_int),
.qsfp1_rx_clk_3(qsfp1_rx_clk_3_int),
.qsfp1_rx_rst_3(qsfp1_rx_rst_3_int),
.qsfp1_rxd_3(qsfp1_rxd_3_int),
.qsfp1_rxc_3(qsfp1_rxc_3_int),
.qsfp1_tx_clk_4(qsfp1_tx_clk_4_int),
.qsfp1_tx_rst_4(qsfp1_tx_rst_4_int),
.qsfp1_txd_4(qsfp1_txd_4_int),
.qsfp1_txc_4(qsfp1_txc_4_int),
.qsfp1_rx_clk_4(qsfp1_rx_clk_4_int),
.qsfp1_rx_rst_4(qsfp1_rx_rst_4_int),
.qsfp1_rxd_4(qsfp1_rxd_4_int),
.qsfp1_rxc_4(qsfp1_rxc_4_int),
/*
* UART: 115200 bps, 8N1
*/
.uart_rxd(uart_rxd),
.uart_txd(uart_txd_int)
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule

View File

@ -42,6 +42,12 @@ module fpga (
*/
output wire hbm_cattrip,
/*
* UART
*/
output wire uart_txd,
input wire uart_rxd,
/*
* Ethernet: QSFP28
*/
@ -162,47 +168,25 @@ sync_reset_125mhz_inst (
assign hbm_cattrip = 1'b0;
// XGMII 10G PHY
localparam QSFP_CNT = 2;
localparam CH_CNT = QSFP_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
assign clk_156mhz_int = eth_tx_clk[0];
assign rst_156mhz_int = eth_tx_rst[0];
// QSFP0
assign qsfp0_refclk_oe_b = 1'b0;
assign qsfp0_refclk_fs = 1'b1;
wire qsfp0_tx_clk_1_int;
wire qsfp0_tx_rst_1_int;
wire [63:0] qsfp0_txd_1_int;
wire [7:0] qsfp0_txc_1_int;
wire qsfp0_rx_clk_1_int;
wire qsfp0_rx_rst_1_int;
wire [63:0] qsfp0_rxd_1_int;
wire [7:0] qsfp0_rxc_1_int;
wire qsfp0_tx_clk_2_int;
wire qsfp0_tx_rst_2_int;
wire [63:0] qsfp0_txd_2_int;
wire [7:0] qsfp0_txc_2_int;
wire qsfp0_rx_clk_2_int;
wire qsfp0_rx_rst_2_int;
wire [63:0] qsfp0_rxd_2_int;
wire [7:0] qsfp0_rxc_2_int;
wire qsfp0_tx_clk_3_int;
wire qsfp0_tx_rst_3_int;
wire [63:0] qsfp0_txd_3_int;
wire [7:0] qsfp0_txc_3_int;
wire qsfp0_rx_clk_3_int;
wire qsfp0_rx_rst_3_int;
wire [63:0] qsfp0_rxd_3_int;
wire [7:0] qsfp0_rxc_3_int;
wire qsfp0_tx_clk_4_int;
wire qsfp0_tx_rst_4_int;
wire [63:0] qsfp0_txd_4_int;
wire [7:0] qsfp0_txc_4_int;
wire qsfp0_rx_clk_4_int;
wire qsfp0_rx_rst_4_int;
wire [63:0] qsfp0_rxd_4_int;
wire [7:0] qsfp0_rxc_4_int;
assign clk_156mhz_int = qsfp0_tx_clk_1_int;
assign rst_156mhz_int = qsfp0_tx_rst_1_int;
wire qsfp0_rx_block_lock_1;
wire qsfp0_rx_block_lock_2;
wire qsfp0_rx_block_lock_3;
@ -264,14 +248,14 @@ qsfp0_phy_inst (
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp0_tx_clk_1_int),
.phy_1_tx_rst(qsfp0_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp0_txd_1_int),
.phy_1_xgmii_txc(qsfp0_txc_1_int),
.phy_1_rx_clk(qsfp0_rx_clk_1_int),
.phy_1_rx_rst(qsfp0_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp0_rxd_1_int),
.phy_1_xgmii_rxc(qsfp0_rxc_1_int),
.phy_1_tx_clk(eth_tx_clk[0*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[0*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(0*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[0*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[0*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(0*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
@ -281,14 +265,14 @@ qsfp0_phy_inst (
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp0_tx_clk_2_int),
.phy_2_tx_rst(qsfp0_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp0_txd_2_int),
.phy_2_xgmii_txc(qsfp0_txc_2_int),
.phy_2_rx_clk(qsfp0_rx_clk_2_int),
.phy_2_rx_rst(qsfp0_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp0_rxd_2_int),
.phy_2_xgmii_rxc(qsfp0_rxc_2_int),
.phy_2_tx_clk(eth_tx_clk[0*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[0*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(0*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[0*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[0*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(0*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
@ -298,14 +282,14 @@ qsfp0_phy_inst (
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp0_tx_clk_3_int),
.phy_3_tx_rst(qsfp0_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp0_txd_3_int),
.phy_3_xgmii_txc(qsfp0_txc_3_int),
.phy_3_rx_clk(qsfp0_rx_clk_3_int),
.phy_3_rx_rst(qsfp0_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp0_rxd_3_int),
.phy_3_xgmii_rxc(qsfp0_rxc_3_int),
.phy_3_tx_clk(eth_tx_clk[0*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[0*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(0*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[0*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[0*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(0*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
@ -315,14 +299,14 @@ qsfp0_phy_inst (
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp0_tx_clk_4_int),
.phy_4_tx_rst(qsfp0_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp0_txd_4_int),
.phy_4_xgmii_txc(qsfp0_txc_4_int),
.phy_4_rx_clk(qsfp0_rx_clk_4_int),
.phy_4_rx_rst(qsfp0_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp0_rxd_4_int),
.phy_4_xgmii_rxc(qsfp0_rxc_4_int),
.phy_4_tx_clk(eth_tx_clk[0*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[0*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(0*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[0*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[0*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(0*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
@ -337,39 +321,6 @@ qsfp0_phy_inst (
assign qsfp1_refclk_oe_b = 1'b0;
assign qsfp1_refclk_fs = 1'b1;
wire qsfp1_tx_clk_1_int;
wire qsfp1_tx_rst_1_int;
wire [63:0] qsfp1_txd_1_int;
wire [7:0] qsfp1_txc_1_int;
wire qsfp1_rx_clk_1_int;
wire qsfp1_rx_rst_1_int;
wire [63:0] qsfp1_rxd_1_int;
wire [7:0] qsfp1_rxc_1_int;
wire qsfp1_tx_clk_2_int;
wire qsfp1_tx_rst_2_int;
wire [63:0] qsfp1_txd_2_int;
wire [7:0] qsfp1_txc_2_int;
wire qsfp1_rx_clk_2_int;
wire qsfp1_rx_rst_2_int;
wire [63:0] qsfp1_rxd_2_int;
wire [7:0] qsfp1_rxc_2_int;
wire qsfp1_tx_clk_3_int;
wire qsfp1_tx_rst_3_int;
wire [63:0] qsfp1_txd_3_int;
wire [7:0] qsfp1_txc_3_int;
wire qsfp1_rx_clk_3_int;
wire qsfp1_rx_rst_3_int;
wire [63:0] qsfp1_rxd_3_int;
wire [7:0] qsfp1_rxc_3_int;
wire qsfp1_tx_clk_4_int;
wire qsfp1_tx_rst_4_int;
wire [63:0] qsfp1_txd_4_int;
wire [7:0] qsfp1_txc_4_int;
wire qsfp1_rx_clk_4_int;
wire qsfp1_rx_rst_4_int;
wire [63:0] qsfp1_rxd_4_int;
wire [7:0] qsfp1_rxc_4_int;
wire qsfp1_rx_block_lock_1;
wire qsfp1_rx_block_lock_2;
wire qsfp1_rx_block_lock_3;
@ -415,14 +366,14 @@ qsfp1_phy_inst (
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp1_tx_clk_1_int),
.phy_1_tx_rst(qsfp1_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp1_txd_1_int),
.phy_1_xgmii_txc(qsfp1_txc_1_int),
.phy_1_rx_clk(qsfp1_rx_clk_1_int),
.phy_1_rx_rst(qsfp1_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp1_rxd_1_int),
.phy_1_xgmii_rxc(qsfp1_rxc_1_int),
.phy_1_tx_clk(eth_tx_clk[1*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[1*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(1*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[1*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[1*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(1*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
@ -432,14 +383,14 @@ qsfp1_phy_inst (
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp1_tx_clk_2_int),
.phy_2_tx_rst(qsfp1_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp1_txd_2_int),
.phy_2_xgmii_txc(qsfp1_txc_2_int),
.phy_2_rx_clk(qsfp1_rx_clk_2_int),
.phy_2_rx_rst(qsfp1_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp1_rxd_2_int),
.phy_2_xgmii_rxc(qsfp1_rxc_2_int),
.phy_2_tx_clk(eth_tx_clk[1*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[1*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(1*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[1*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[1*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(1*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
@ -449,14 +400,14 @@ qsfp1_phy_inst (
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp1_tx_clk_3_int),
.phy_3_tx_rst(qsfp1_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp1_txd_3_int),
.phy_3_xgmii_txc(qsfp1_txc_3_int),
.phy_3_rx_clk(qsfp1_rx_clk_3_int),
.phy_3_rx_rst(qsfp1_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp1_rxd_3_int),
.phy_3_xgmii_rxc(qsfp1_rxc_3_int),
.phy_3_tx_clk(eth_tx_clk[1*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[1*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(1*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[1*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[1*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(1*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
@ -466,14 +417,14 @@ qsfp1_phy_inst (
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp1_tx_clk_4_int),
.phy_4_tx_rst(qsfp1_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp1_txd_4_int),
.phy_4_xgmii_txc(qsfp1_txc_4_int),
.phy_4_rx_clk(qsfp1_rx_clk_4_int),
.phy_4_rx_rst(qsfp1_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp1_rxd_4_int),
.phy_4_xgmii_rxc(qsfp1_rxc_4_int),
.phy_4_tx_clk(eth_tx_clk[1*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[1*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(1*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[1*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[1*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(1*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
@ -484,7 +435,11 @@ qsfp1_phy_inst (
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core
fpga_core #(
.UART_CNT(1),
.QSFP_CNT(QSFP_CNT),
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
@ -492,73 +447,33 @@ core_inst (
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(0),
.led(),
.qsfp_led_act(),
.qsfp_led_stat_g(),
.qsfp_led_stat_y(),
/*
* UART
*/
.uart_txd(uart_txd),
.uart_rxd(uart_rxd),
/*
* Ethernet: QSFP28
*/
.qsfp0_tx_clk_1(qsfp0_tx_clk_1_int),
.qsfp0_tx_rst_1(qsfp0_tx_rst_1_int),
.qsfp0_txd_1(qsfp0_txd_1_int),
.qsfp0_txc_1(qsfp0_txc_1_int),
.qsfp0_rx_clk_1(qsfp0_rx_clk_1_int),
.qsfp0_rx_rst_1(qsfp0_rx_rst_1_int),
.qsfp0_rxd_1(qsfp0_rxd_1_int),
.qsfp0_rxc_1(qsfp0_rxc_1_int),
.qsfp0_tx_clk_2(qsfp0_tx_clk_2_int),
.qsfp0_tx_rst_2(qsfp0_tx_rst_2_int),
.qsfp0_txd_2(qsfp0_txd_2_int),
.qsfp0_txc_2(qsfp0_txc_2_int),
.qsfp0_rx_clk_2(qsfp0_rx_clk_2_int),
.qsfp0_rx_rst_2(qsfp0_rx_rst_2_int),
.qsfp0_rxd_2(qsfp0_rxd_2_int),
.qsfp0_rxc_2(qsfp0_rxc_2_int),
.qsfp0_tx_clk_3(qsfp0_tx_clk_3_int),
.qsfp0_tx_rst_3(qsfp0_tx_rst_3_int),
.qsfp0_txd_3(qsfp0_txd_3_int),
.qsfp0_txc_3(qsfp0_txc_3_int),
.qsfp0_rx_clk_3(qsfp0_rx_clk_3_int),
.qsfp0_rx_rst_3(qsfp0_rx_rst_3_int),
.qsfp0_rxd_3(qsfp0_rxd_3_int),
.qsfp0_rxc_3(qsfp0_rxc_3_int),
.qsfp0_tx_clk_4(qsfp0_tx_clk_4_int),
.qsfp0_tx_rst_4(qsfp0_tx_rst_4_int),
.qsfp0_txd_4(qsfp0_txd_4_int),
.qsfp0_txc_4(qsfp0_txc_4_int),
.qsfp0_rx_clk_4(qsfp0_rx_clk_4_int),
.qsfp0_rx_rst_4(qsfp0_rx_rst_4_int),
.qsfp0_rxd_4(qsfp0_rxd_4_int),
.qsfp0_rxc_4(qsfp0_rxc_4_int),
.qsfp1_tx_clk_1(qsfp1_tx_clk_1_int),
.qsfp1_tx_rst_1(qsfp1_tx_rst_1_int),
.qsfp1_txd_1(qsfp1_txd_1_int),
.qsfp1_txc_1(qsfp1_txc_1_int),
.qsfp1_rx_clk_1(qsfp1_rx_clk_1_int),
.qsfp1_rx_rst_1(qsfp1_rx_rst_1_int),
.qsfp1_rxd_1(qsfp1_rxd_1_int),
.qsfp1_rxc_1(qsfp1_rxc_1_int),
.qsfp1_tx_clk_2(qsfp1_tx_clk_2_int),
.qsfp1_tx_rst_2(qsfp1_tx_rst_2_int),
.qsfp1_txd_2(qsfp1_txd_2_int),
.qsfp1_txc_2(qsfp1_txc_2_int),
.qsfp1_rx_clk_2(qsfp1_rx_clk_2_int),
.qsfp1_rx_rst_2(qsfp1_rx_rst_2_int),
.qsfp1_rxd_2(qsfp1_rxd_2_int),
.qsfp1_rxc_2(qsfp1_rxc_2_int),
.qsfp1_tx_clk_3(qsfp1_tx_clk_3_int),
.qsfp1_tx_rst_3(qsfp1_tx_rst_3_int),
.qsfp1_txd_3(qsfp1_txd_3_int),
.qsfp1_txc_3(qsfp1_txc_3_int),
.qsfp1_rx_clk_3(qsfp1_rx_clk_3_int),
.qsfp1_rx_rst_3(qsfp1_rx_rst_3_int),
.qsfp1_rxd_3(qsfp1_rxd_3_int),
.qsfp1_rxc_3(qsfp1_rxc_3_int),
.qsfp1_tx_clk_4(qsfp1_tx_clk_4_int),
.qsfp1_tx_rst_4(qsfp1_tx_rst_4_int),
.qsfp1_txd_4(qsfp1_txd_4_int),
.qsfp1_txc_4(qsfp1_txc_4_int),
.qsfp1_rx_clk_4(qsfp1_rx_clk_4_int),
.qsfp1_rx_rst_4(qsfp1_rx_rst_4_int),
.qsfp1_rxd_4(qsfp1_rxd_4_int),
.qsfp1_rxc_4(qsfp1_rxc_4_int)
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule

View File

@ -31,26 +31,37 @@ THE SOFTWARE.
/*
* FPGA top-level module
*/
module fpga (
module fpga #
(
parameter QSFP_CNT = 1,
parameter UART_CNT = 3
)
(
/*
* GPIO
*/
output wire qsfp_led_act,
output wire qsfp_led_stat_g,
output wire qsfp_led_stat_y,
output wire hbm_cattrip,
output wire [QSFP_CNT-1:0] qsfp_led_act,
output wire [QSFP_CNT-1:0] qsfp_led_stat_g,
output wire [QSFP_CNT-1:0] qsfp_led_stat_y,
output wire hbm_cattrip,
/*
* UART
*/
output wire [UART_CNT-1:0] uart_txd,
input wire [UART_CNT-1:0] uart_rxd,
/*
* Ethernet: QSFP28
*/
output wire [3:0] qsfp_tx_p,
output wire [3:0] qsfp_tx_n,
input wire [3:0] qsfp_rx_p,
input wire [3:0] qsfp_rx_n,
input wire qsfp_mgt_refclk_0_p,
input wire qsfp_mgt_refclk_0_n
// input wire qsfp_mgt_refclk_1_p,
// input wire qsfp_mgt_refclk_1_n
output wire [3:0] qsfp_tx_p,
output wire [3:0] qsfp_tx_n,
input wire [3:0] qsfp_rx_p,
input wire [3:0] qsfp_rx_n,
input wire qsfp_mgt_refclk_0_p,
input wire qsfp_mgt_refclk_0_n
// input wire qsfp_mgt_refclk_1_p,
// input wire qsfp_mgt_refclk_1_n
);
// Clock and reset
@ -147,41 +158,19 @@ sync_reset_125mhz_inst (
assign hbm_cattrip = 1'b0;
// XGMII 10G PHY
wire qsfp_tx_clk_1_int;
wire qsfp_tx_rst_1_int;
wire [63:0] qsfp_txd_1_int;
wire [7:0] qsfp_txc_1_int;
wire qsfp_rx_clk_1_int;
wire qsfp_rx_rst_1_int;
wire [63:0] qsfp_rxd_1_int;
wire [7:0] qsfp_rxc_1_int;
wire qsfp_tx_clk_2_int;
wire qsfp_tx_rst_2_int;
wire [63:0] qsfp_txd_2_int;
wire [7:0] qsfp_txc_2_int;
wire qsfp_rx_clk_2_int;
wire qsfp_rx_rst_2_int;
wire [63:0] qsfp_rxd_2_int;
wire [7:0] qsfp_rxc_2_int;
wire qsfp_tx_clk_3_int;
wire qsfp_tx_rst_3_int;
wire [63:0] qsfp_txd_3_int;
wire [7:0] qsfp_txc_3_int;
wire qsfp_rx_clk_3_int;
wire qsfp_rx_rst_3_int;
wire [63:0] qsfp_rxd_3_int;
wire [7:0] qsfp_rxc_3_int;
wire qsfp_tx_clk_4_int;
wire qsfp_tx_rst_4_int;
wire [63:0] qsfp_txd_4_int;
wire [7:0] qsfp_txc_4_int;
wire qsfp_rx_clk_4_int;
wire qsfp_rx_rst_4_int;
wire [63:0] qsfp_rxd_4_int;
wire [7:0] qsfp_rxc_4_int;
localparam CH_CNT = QSFP_CNT*4;
assign clk_156mhz_int = qsfp_tx_clk_1_int;
assign rst_156mhz_int = qsfp_tx_rst_1_int;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
assign clk_156mhz_int = eth_tx_clk[0];
assign rst_156mhz_int = eth_tx_rst[0];
wire qsfp_rx_block_lock_1;
wire qsfp_rx_block_lock_2;
@ -244,14 +233,14 @@ qsfp_phy_inst (
/*
* PHY connections
*/
.phy_1_tx_clk(qsfp_tx_clk_1_int),
.phy_1_tx_rst(qsfp_tx_rst_1_int),
.phy_1_xgmii_txd(qsfp_txd_1_int),
.phy_1_xgmii_txc(qsfp_txc_1_int),
.phy_1_rx_clk(qsfp_rx_clk_1_int),
.phy_1_rx_rst(qsfp_rx_rst_1_int),
.phy_1_xgmii_rxd(qsfp_rxd_1_int),
.phy_1_xgmii_rxc(qsfp_rxc_1_int),
.phy_1_tx_clk(eth_tx_clk[0*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[0*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(0*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[0*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[0*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(0*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
@ -261,14 +250,14 @@ qsfp_phy_inst (
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(qsfp_tx_clk_2_int),
.phy_2_tx_rst(qsfp_tx_rst_2_int),
.phy_2_xgmii_txd(qsfp_txd_2_int),
.phy_2_xgmii_txc(qsfp_txc_2_int),
.phy_2_rx_clk(qsfp_rx_clk_2_int),
.phy_2_rx_rst(qsfp_rx_rst_2_int),
.phy_2_xgmii_rxd(qsfp_rxd_2_int),
.phy_2_xgmii_rxc(qsfp_rxc_2_int),
.phy_2_tx_clk(eth_tx_clk[0*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[0*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(0*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[0*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[0*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(0*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
@ -278,14 +267,14 @@ qsfp_phy_inst (
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(qsfp_tx_clk_3_int),
.phy_3_tx_rst(qsfp_tx_rst_3_int),
.phy_3_xgmii_txd(qsfp_txd_3_int),
.phy_3_xgmii_txc(qsfp_txc_3_int),
.phy_3_rx_clk(qsfp_rx_clk_3_int),
.phy_3_rx_rst(qsfp_rx_rst_3_int),
.phy_3_xgmii_rxd(qsfp_rxd_3_int),
.phy_3_xgmii_rxc(qsfp_rxc_3_int),
.phy_3_tx_clk(eth_tx_clk[0*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[0*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(0*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[0*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[0*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(0*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
@ -295,14 +284,14 @@ qsfp_phy_inst (
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(qsfp_tx_clk_4_int),
.phy_4_tx_rst(qsfp_tx_rst_4_int),
.phy_4_xgmii_txd(qsfp_txd_4_int),
.phy_4_xgmii_txc(qsfp_txc_4_int),
.phy_4_rx_clk(qsfp_rx_clk_4_int),
.phy_4_rx_rst(qsfp_rx_rst_4_int),
.phy_4_xgmii_rxd(qsfp_rxd_4_int),
.phy_4_xgmii_rxc(qsfp_rxc_4_int),
.phy_4_tx_clk(eth_tx_clk[0*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[0*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(0*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[0*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[0*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(0*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
@ -313,7 +302,11 @@ qsfp_phy_inst (
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core
fpga_core #(
.UART_CNT(UART_CNT),
.QSFP_CNT(QSFP_CNT),
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
@ -321,47 +314,33 @@ core_inst (
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(0),
.led(),
.qsfp_led_act(qsfp_led_act),
.qsfp_led_stat_g(qsfp_led_stat_g),
.qsfp_led_stat_y(qsfp_led_stat_y),
/*
* UART
*/
.uart_txd(uart_txd),
.uart_rxd(uart_rxd),
/*
* Ethernet: QSFP28
*/
.qsfp_tx_clk_1(qsfp_tx_clk_1_int),
.qsfp_tx_rst_1(qsfp_tx_rst_1_int),
.qsfp_txd_1(qsfp_txd_1_int),
.qsfp_txc_1(qsfp_txc_1_int),
.qsfp_rx_clk_1(qsfp_rx_clk_1_int),
.qsfp_rx_rst_1(qsfp_rx_rst_1_int),
.qsfp_rxd_1(qsfp_rxd_1_int),
.qsfp_rxc_1(qsfp_rxc_1_int),
.qsfp_tx_clk_2(qsfp_tx_clk_2_int),
.qsfp_tx_rst_2(qsfp_tx_rst_2_int),
.qsfp_txd_2(qsfp_txd_2_int),
.qsfp_txc_2(qsfp_txc_2_int),
.qsfp_rx_clk_2(qsfp_rx_clk_2_int),
.qsfp_rx_rst_2(qsfp_rx_rst_2_int),
.qsfp_rxd_2(qsfp_rxd_2_int),
.qsfp_rxc_2(qsfp_rxc_2_int),
.qsfp_tx_clk_3(qsfp_tx_clk_3_int),
.qsfp_tx_rst_3(qsfp_tx_rst_3_int),
.qsfp_txd_3(qsfp_txd_3_int),
.qsfp_txc_3(qsfp_txc_3_int),
.qsfp_rx_clk_3(qsfp_rx_clk_3_int),
.qsfp_rx_rst_3(qsfp_rx_rst_3_int),
.qsfp_rxd_3(qsfp_rxd_3_int),
.qsfp_rxc_3(qsfp_rxc_3_int),
.qsfp_tx_clk_4(qsfp_tx_clk_4_int),
.qsfp_tx_rst_4(qsfp_tx_rst_4_int),
.qsfp_txd_4(qsfp_txd_4_int),
.qsfp_txc_4(qsfp_txc_4_int),
.qsfp_rx_clk_4(qsfp_rx_clk_4_int),
.qsfp_rx_rst_4(qsfp_rx_rst_4_int),
.qsfp_rxd_4(qsfp_rxd_4_int),
.qsfp_rxc_4(qsfp_rxc_4_int)
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule

View File

@ -0,0 +1,474 @@
/*
Copyright (c) 2014-2021 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA top-level module
*/
module fpga #
(
parameter QSFP_CNT = 2,
parameter UART_CNT = 3
)
(
/*
* Reset: Push button, active low
*/
input wire reset,
/*
* GPIO
*/
output wire [QSFP_CNT-1:0] qsfp_led_act,
output wire [QSFP_CNT-1:0] qsfp_led_stat_g,
output wire [QSFP_CNT-1:0] qsfp_led_stat_y,
output wire hbm_cattrip,
/*
* UART
*/
output wire [UART_CNT-1:0] uart_txd,
input wire [UART_CNT-1:0] uart_rxd,
/*
* Ethernet: QSFP28
*/
output wire [3:0] qsfp0_tx_p,
output wire [3:0] qsfp0_tx_n,
input wire [3:0] qsfp0_rx_p,
input wire [3:0] qsfp0_rx_n,
input wire qsfp0_mgt_refclk_p,
input wire qsfp0_mgt_refclk_n,
output wire [3:0] qsfp1_tx_p,
output wire [3:0] qsfp1_tx_n,
input wire [3:0] qsfp1_rx_p,
input wire [3:0] qsfp1_rx_n,
input wire qsfp1_mgt_refclk_p,
input wire qsfp1_mgt_refclk_n
);
// Clock and reset
wire clk_161mhz_ref_int;
// Internal 125 MHz clock
wire clk_125mhz_mmcm_out;
wire clk_125mhz_int;
wire rst_125mhz_int;
// Internal 156.25 MHz clock
wire clk_156mhz_int;
wire rst_156mhz_int;
wire mmcm_rst = 1'b0;
wire mmcm_locked;
wire mmcm_clkfb;
// MMCM instance
// 161.13 MHz in, 125 MHz out
// PFD range: 10 MHz to 500 MHz
// VCO range: 800 MHz to 1600 MHz
// M = 64, D = 11 sets Fvco = 937.5 MHz (in range)
// Divide by 7.5 to get output frequency of 125 MHz
MMCME4_BASE #(
.BANDWIDTH("OPTIMIZED"),
.CLKOUT0_DIVIDE_F(7.5),
.CLKOUT0_DUTY_CYCLE(0.5),
.CLKOUT0_PHASE(0),
.CLKOUT1_DIVIDE(1),
.CLKOUT1_DUTY_CYCLE(0.5),
.CLKOUT1_PHASE(0),
.CLKOUT2_DIVIDE(1),
.CLKOUT2_DUTY_CYCLE(0.5),
.CLKOUT2_PHASE(0),
.CLKOUT3_DIVIDE(1),
.CLKOUT3_DUTY_CYCLE(0.5),
.CLKOUT3_PHASE(0),
.CLKOUT4_DIVIDE(1),
.CLKOUT4_DUTY_CYCLE(0.5),
.CLKOUT4_PHASE(0),
.CLKOUT5_DIVIDE(1),
.CLKOUT5_DUTY_CYCLE(0.5),
.CLKOUT5_PHASE(0),
.CLKOUT6_DIVIDE(1),
.CLKOUT6_DUTY_CYCLE(0.5),
.CLKOUT6_PHASE(0),
.CLKFBOUT_MULT_F(64),
.CLKFBOUT_PHASE(0),
.DIVCLK_DIVIDE(11),
.REF_JITTER1(0.010),
.CLKIN1_PERIOD(6.206),
.STARTUP_WAIT("FALSE"),
.CLKOUT4_CASCADE("FALSE")
)
clk_mmcm_inst (
.CLKIN1(clk_161mhz_ref_int),
.CLKFBIN(mmcm_clkfb),
.RST(mmcm_rst),
.PWRDWN(1'b0),
.CLKOUT0(clk_125mhz_mmcm_out),
.CLKOUT0B(),
.CLKOUT1(),
.CLKOUT1B(),
.CLKOUT2(),
.CLKOUT2B(),
.CLKOUT3(),
.CLKOUT3B(),
.CLKOUT4(),
.CLKOUT5(),
.CLKOUT6(),
.CLKFBOUT(mmcm_clkfb),
.CLKFBOUTB(),
.LOCKED(mmcm_locked)
);
BUFG
clk_125mhz_bufg_inst (
.I(clk_125mhz_mmcm_out),
.O(clk_125mhz_int)
);
sync_reset #(
.N(4)
)
sync_reset_125mhz_inst (
.clk(clk_125mhz_int),
.rst(~mmcm_locked),
.out(rst_125mhz_int)
);
// GPIO
assign hbm_cattrip = 1'b0;
// XGMII 10G PHY
localparam CH_CNT = QSFP_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
assign clk_156mhz_int = eth_tx_clk[0];
assign rst_156mhz_int = eth_tx_rst[0];
// QSFP0
wire qsfp0_rx_block_lock_1;
wire qsfp0_rx_block_lock_2;
wire qsfp0_rx_block_lock_3;
wire qsfp0_rx_block_lock_4;
wire qsfp0_gtpowergood;
wire qsfp0_mgt_refclk;
wire qsfp0_mgt_refclk_int;
wire qsfp0_mgt_refclk_bufg;
assign clk_161mhz_ref_int = qsfp0_mgt_refclk_bufg;
IBUFDS_GTE4 ibufds_gte4_qsfp0_mgt_refclk_inst (
.I (qsfp0_mgt_refclk_p),
.IB (qsfp0_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp0_mgt_refclk),
.ODIV2 (qsfp0_mgt_refclk_int)
);
BUFG_GT bufg_gt_refclk_inst (
.CE (qsfp0_gtpowergood),
.CEMASK (1'b1),
.CLR (1'b0),
.CLRMASK (1'b1),
.DIV (3'd0),
.I (qsfp0_mgt_refclk_int),
.O (qsfp0_mgt_refclk_bufg)
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp0_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(qsfp0_gtpowergood),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp0_mgt_refclk),
/*
* Serial data
*/
.xcvr_txp(qsfp0_tx_p),
.xcvr_txn(qsfp0_tx_n),
.xcvr_rxp(qsfp0_rx_p),
.xcvr_rxn(qsfp0_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(eth_tx_clk[0*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[0*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(0*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[0*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[0*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(0*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(0*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
.phy_1_rx_sequence_error(),
.phy_1_rx_block_lock(qsfp0_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(eth_tx_clk[0*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[0*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(0*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[0*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[0*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(0*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(0*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
.phy_2_rx_sequence_error(),
.phy_2_rx_block_lock(qsfp0_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(eth_tx_clk[0*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[0*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(0*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[0*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[0*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(0*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(0*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
.phy_3_rx_sequence_error(),
.phy_3_rx_block_lock(qsfp0_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(eth_tx_clk[0*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[0*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(0*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[0*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[0*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(0*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(0*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
.phy_4_rx_sequence_error(),
.phy_4_rx_block_lock(qsfp0_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
// QSFP1
wire qsfp1_rx_block_lock_1;
wire qsfp1_rx_block_lock_2;
wire qsfp1_rx_block_lock_3;
wire qsfp1_rx_block_lock_4;
wire qsfp1_mgt_refclk;
IBUFDS_GTE4 ibufds_gte4_qsfp1_mgt_refclk_inst (
.I (qsfp1_mgt_refclk_p),
.IB (qsfp1_mgt_refclk_n),
.CEB (1'b0),
.O (qsfp1_mgt_refclk),
.ODIV2 ()
);
eth_xcvr_phy_quad_wrapper #(
.TX_SERDES_PIPELINE(2),
.RX_SERDES_PIPELINE(2),
.COUNT_125US(125000/2.56)
)
qsfp1_phy_inst (
.xcvr_ctrl_clk(clk_125mhz_int),
.xcvr_ctrl_rst(rst_125mhz_int),
/*
* Common
*/
.xcvr_gtpowergood_out(),
/*
* PLL
*/
.xcvr_gtrefclk00_in(qsfp1_mgt_refclk),
/*
* Serial data
*/
.xcvr_txp(qsfp1_tx_p),
.xcvr_txn(qsfp1_tx_n),
.xcvr_rxp(qsfp1_rx_p),
.xcvr_rxn(qsfp1_rx_n),
/*
* PHY connections
*/
.phy_1_tx_clk(eth_tx_clk[1*4+0 +: 1]),
.phy_1_tx_rst(eth_tx_rst[1*4+0 +: 1]),
.phy_1_xgmii_txd(eth_txd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_txc(eth_txc[(1*4+0)*8 +: 8]),
.phy_1_rx_clk(eth_rx_clk[1*4+0 +: 1]),
.phy_1_rx_rst(eth_rx_rst[1*4+0 +: 1]),
.phy_1_xgmii_rxd(eth_rxd[(1*4+0)*64 +: 64]),
.phy_1_xgmii_rxc(eth_rxc[(1*4+0)*8 +: 8]),
.phy_1_tx_bad_block(),
.phy_1_rx_error_count(),
.phy_1_rx_bad_block(),
.phy_1_rx_sequence_error(),
.phy_1_rx_block_lock(qsfp1_rx_block_lock_1),
.phy_1_rx_status(),
.phy_1_cfg_tx_prbs31_enable(1'b0),
.phy_1_cfg_rx_prbs31_enable(1'b0),
.phy_2_tx_clk(eth_tx_clk[1*4+1 +: 1]),
.phy_2_tx_rst(eth_tx_rst[1*4+1 +: 1]),
.phy_2_xgmii_txd(eth_txd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_txc(eth_txc[(1*4+1)*8 +: 8]),
.phy_2_rx_clk(eth_rx_clk[1*4+1 +: 1]),
.phy_2_rx_rst(eth_rx_rst[1*4+1 +: 1]),
.phy_2_xgmii_rxd(eth_rxd[(1*4+1)*64 +: 64]),
.phy_2_xgmii_rxc(eth_rxc[(1*4+1)*8 +: 8]),
.phy_2_tx_bad_block(),
.phy_2_rx_error_count(),
.phy_2_rx_bad_block(),
.phy_2_rx_sequence_error(),
.phy_2_rx_block_lock(qsfp1_rx_block_lock_2),
.phy_2_rx_status(),
.phy_2_cfg_tx_prbs31_enable(1'b0),
.phy_2_cfg_rx_prbs31_enable(1'b0),
.phy_3_tx_clk(eth_tx_clk[1*4+2 +: 1]),
.phy_3_tx_rst(eth_tx_rst[1*4+2 +: 1]),
.phy_3_xgmii_txd(eth_txd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_txc(eth_txc[(1*4+2)*8 +: 8]),
.phy_3_rx_clk(eth_rx_clk[1*4+2 +: 1]),
.phy_3_rx_rst(eth_rx_rst[1*4+2 +: 1]),
.phy_3_xgmii_rxd(eth_rxd[(1*4+2)*64 +: 64]),
.phy_3_xgmii_rxc(eth_rxc[(1*4+2)*8 +: 8]),
.phy_3_tx_bad_block(),
.phy_3_rx_error_count(),
.phy_3_rx_bad_block(),
.phy_3_rx_sequence_error(),
.phy_3_rx_block_lock(qsfp1_rx_block_lock_3),
.phy_3_rx_status(),
.phy_3_cfg_tx_prbs31_enable(1'b0),
.phy_3_cfg_rx_prbs31_enable(1'b0),
.phy_4_tx_clk(eth_tx_clk[1*4+3 +: 1]),
.phy_4_tx_rst(eth_tx_rst[1*4+3 +: 1]),
.phy_4_xgmii_txd(eth_txd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_txc(eth_txc[(1*4+3)*8 +: 8]),
.phy_4_rx_clk(eth_rx_clk[1*4+3 +: 1]),
.phy_4_rx_rst(eth_rx_rst[1*4+3 +: 1]),
.phy_4_xgmii_rxd(eth_rxd[(1*4+3)*64 +: 64]),
.phy_4_xgmii_rxc(eth_rxc[(1*4+3)*8 +: 8]),
.phy_4_tx_bad_block(),
.phy_4_rx_error_count(),
.phy_4_rx_bad_block(),
.phy_4_rx_sequence_error(),
.phy_4_rx_block_lock(qsfp1_rx_block_lock_4),
.phy_4_rx_status(),
.phy_4_cfg_tx_prbs31_enable(1'b0),
.phy_4_cfg_rx_prbs31_enable(1'b0)
);
fpga_core #(
.UART_CNT(UART_CNT),
.QSFP_CNT(QSFP_CNT),
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk_156mhz_int),
.rst(rst_156mhz_int),
/*
* GPIO
*/
.sw(0),
.led(),
.qsfp_led_act(qsfp_led_act),
.qsfp_led_stat_g(qsfp_led_stat_g),
.qsfp_led_stat_y(qsfp_led_stat_y),
/*
* UART
*/
.uart_txd(uart_txd),
.uart_rxd(uart_rxd),
/*
* Ethernet: QSFP28
*/
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule
`resetall

View File

@ -33,57 +33,46 @@ THE SOFTWARE.
*/
module fpga_core #
(
parameter TARGET = "XILINX"
parameter SW_CNT = 4,
parameter LED_CNT = 3,
parameter UART_CNT = 1,
parameter QSFP_CNT = 2,
parameter CH_CNT = QSFP_CNT*4
)
(
/*
* Clock: 156.25MHz
* Synchronous reset
*/
input wire clk,
input wire rst,
input wire clk,
input wire rst,
/*
* GPIO
*/
output wire qsfp_led_act,
output wire qsfp_led_stat_g,
output wire qsfp_led_stat_y,
input wire [SW_CNT-1:0] sw,
output wire [LED_CNT-1:0] led,
output wire [QSFP_CNT-1:0] qsfp_led_act,
output wire [QSFP_CNT-1:0] qsfp_led_stat_g,
output wire [QSFP_CNT-1:0] qsfp_led_stat_y,
/*
* Ethernet: QSFP28
* UART
*/
input wire qsfp_tx_clk_1,
input wire qsfp_tx_rst_1,
output wire [63:0] qsfp_txd_1,
output wire [7:0] qsfp_txc_1,
input wire qsfp_rx_clk_1,
input wire qsfp_rx_rst_1,
input wire [63:0] qsfp_rxd_1,
input wire [7:0] qsfp_rxc_1,
input wire qsfp_tx_clk_2,
input wire qsfp_tx_rst_2,
output wire [63:0] qsfp_txd_2,
output wire [7:0] qsfp_txc_2,
input wire qsfp_rx_clk_2,
input wire qsfp_rx_rst_2,
input wire [63:0] qsfp_rxd_2,
input wire [7:0] qsfp_rxc_2,
input wire qsfp_tx_clk_3,
input wire qsfp_tx_rst_3,
output wire [63:0] qsfp_txd_3,
output wire [7:0] qsfp_txc_3,
input wire qsfp_rx_clk_3,
input wire qsfp_rx_rst_3,
input wire [63:0] qsfp_rxd_3,
input wire [7:0] qsfp_rxc_3,
input wire qsfp_tx_clk_4,
input wire qsfp_tx_rst_4,
output wire [63:0] qsfp_txd_4,
output wire [7:0] qsfp_txc_4,
input wire qsfp_rx_clk_4,
input wire qsfp_rx_rst_4,
input wire [63:0] qsfp_rxd_4,
input wire [7:0] qsfp_rxc_4
output wire [UART_CNT-1:0] uart_txd,
input wire [UART_CNT-1:0] uart_rxd,
/*
* Ethernet
*/
input wire [CH_CNT-1:0] eth_tx_clk,
input wire [CH_CNT-1:0] eth_tx_rst,
output wire [CH_CNT*64-1:0] eth_txd,
output wire [CH_CNT*8-1:0] eth_txc,
input wire [CH_CNT-1:0] eth_rx_clk,
input wire [CH_CNT-1:0] eth_rx_rst,
input wire [CH_CNT*64-1:0] eth_rxd,
input wire [CH_CNT*8-1:0] eth_rxc
);
// AXI between MAC and Ethernet modules
@ -320,14 +309,21 @@ always @(posedge clk) begin
end
end
assign qsfp_led_act = led_reg[0];
//assign led = sw;
assign led = led_reg;
assign qsfp_txd_2 = 64'h0707070707070707;
assign qsfp_txc_2 = 8'hff;
assign qsfp_txd_3 = 64'h0707070707070707;
assign qsfp_txc_3 = 8'hff;
assign qsfp_txd_4 = 64'h0707070707070707;
assign qsfp_txc_4 = 8'hff;
assign uart_txd = uart_rxd;
generate
genvar n;
for (n = 1; n < CH_CNT; n = n + 1) begin
assign eth_txd[n*64 +: 64] = 64'h0707070707070707;
assign eth_txc[n*8 +: 8] = 8'hff;
end
endgenerate
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),
@ -339,10 +335,10 @@ eth_mac_10g_fifo #(
.RX_FRAME_FIFO(1)
)
eth_mac_10g_fifo_inst (
.rx_clk(qsfp_rx_clk_1),
.rx_rst(qsfp_rx_rst_1),
.tx_clk(qsfp_tx_clk_1),
.tx_rst(qsfp_tx_rst_1),
.rx_clk(eth_rx_clk[0 +: 1]),
.rx_rst(eth_rx_rst[0 +: 1]),
.tx_clk(eth_tx_clk[0 +: 1]),
.tx_rst(eth_tx_rst[0 +: 1]),
.logic_clk(clk),
.logic_rst(rst),
@ -360,10 +356,10 @@ eth_mac_10g_fifo_inst (
.rx_axis_tlast(rx_axis_tlast),
.rx_axis_tuser(rx_axis_tuser),
.xgmii_rxd(qsfp_rxd_1),
.xgmii_rxc(qsfp_rxc_1),
.xgmii_txd(qsfp_txd_1),
.xgmii_txc(qsfp_txc_1),
.xgmii_rxd(eth_rxd[0*64 +: 64]),
.xgmii_rxc(eth_rxc[0*8 +: 8]),
.xgmii_txd(eth_txd[0*64 +: 64]),
.xgmii_txc(eth_txc[0*8 +: 8]),
.tx_fifo_overflow(),
.tx_fifo_bad_frame(),

View File

@ -27,8 +27,9 @@ COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
DUT = fpga_core
TOPLEVEL = $(DUT)
TOPLEVEL = test_$(DUT)
MODULE = test_$(DUT)
VERILOG_SOURCES += $(TOPLEVEL).v
VERILOG_SOURCES += ../../rtl/$(DUT).v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g_fifo.v
VERILOG_SOURCES += ../../lib/eth/rtl/eth_mac_10g.v
@ -59,12 +60,16 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
export PARAM_SW_CNT := 4
export PARAM_LED_CNT := 3
export PARAM_UART_CNT := 1
export PARAM_QSFP_CNT := 2
export PARAM_CH_CNT := $(shell expr $(PARAM_QSFP_CNT) \* 4)
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
@ -73,7 +78,7 @@ ifeq ($(SIM), icarus)
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst

View File

@ -48,39 +48,39 @@ class TB:
cocotb.start_soon(Clock(dut.clk, 2.56, units="ns").start())
# Ethernet
self.qsfp_source = []
self.qsfp_sink = []
self.ch_source = []
self.ch_sink = []
for y in range(1, 5):
cocotb.start_soon(Clock(getattr(dut, f"qsfp_rx_clk_{y}"), 2.56, units="ns").start())
source = XgmiiSource(getattr(dut, f"qsfp_rxd_{y}"), getattr(dut, f"qsfp_rxc_{y}"), getattr(dut, f"qsfp_rx_clk_{y}"), getattr(dut, f"qsfp_rx_rst_{y}"))
self.qsfp_source.append(source)
cocotb.start_soon(Clock(getattr(dut, f"qsfp_tx_clk_{y}"), 2.56, units="ns").start())
sink = XgmiiSink(getattr(dut, f"qsfp_txd_{y}"), getattr(dut, f"qsfp_txc_{y}"), getattr(dut, f"qsfp_tx_clk_{y}"), getattr(dut, f"qsfp_tx_rst_{y}"))
self.qsfp_sink.append(sink)
for ch in self.dut.ch:
cocotb.start_soon(Clock(ch.ch_rx_clk, 2.56, units="ns").start())
source = XgmiiSource(ch.ch_rxd, ch.ch_rxc, ch.ch_rx_clk, ch.ch_rx_rst)
self.ch_source.append(source)
cocotb.start_soon(Clock(ch.ch_tx_clk, 2.56, units="ns").start())
sink = XgmiiSink(ch.ch_txd, ch.ch_txc, ch.ch_tx_clk, ch.ch_tx_rst)
self.ch_sink.append(sink)
async def init(self):
self.dut.rst.setimmediatevalue(0)
for y in range(1, 5):
getattr(self.dut, f"qsfp_rx_rst_{y}").setimmediatevalue(0)
getattr(self.dut, f"qsfp_tx_rst_{y}").setimmediatevalue(0)
for ch in self.dut.ch:
ch.ch_rx_rst.setimmediatevalue(0)
ch.ch_tx_rst.setimmediatevalue(0)
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 1
for y in range(1, 5):
getattr(self.dut, f"qsfp_rx_rst_{y}").value = 1
getattr(self.dut, f"qsfp_tx_rst_{y}").value = 1
for ch in self.dut.ch:
ch.ch_rx_rst.value = 1
ch.ch_tx_rst.value = 1
for k in range(10):
await RisingEdge(self.dut.clk)
self.dut.rst.value = 0
for y in range(1, 5):
getattr(self.dut, f"qsfp_rx_rst_{y}").value = 0
getattr(self.dut, f"qsfp_tx_rst_{y}").value = 0
for ch in self.dut.ch:
ch.ch_rx_rst.value = 0
ch.ch_tx_rst.value = 0
@cocotb.test()
@ -100,11 +100,11 @@ async def run_test(dut):
test_frame = XgmiiFrame.from_payload(test_pkt.build())
await tb.qsfp_source[0].send(test_frame)
await tb.ch_source[0].send(test_frame)
tb.log.info("receive ARP request")
rx_frame = await tb.qsfp_sink[0].recv()
rx_frame = await tb.ch_sink[0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
@ -132,11 +132,11 @@ async def run_test(dut):
resp_frame = XgmiiFrame.from_payload(resp_pkt.build())
await tb.qsfp_source[0].send(resp_frame)
await tb.ch_source[0].send(resp_frame)
tb.log.info("receive UDP packet")
rx_frame = await tb.qsfp_sink[0].recv()
rx_frame = await tb.ch_sink[0].recv()
rx_pkt = Ether(bytes(rx_frame.get_payload()))
@ -166,9 +166,10 @@ eth_rtl_dir = os.path.abspath(os.path.join(lib_dir, 'eth', 'rtl'))
def test_fpga_core(request):
dut = "fpga_core"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = dut
toplevel = "test_fpga_core"
verilog_sources = [
os.path.join(tests_dir, f"{toplevel}.v"),
os.path.join(rtl_dir, f"{dut}.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g_fifo.v"),
os.path.join(eth_rtl_dir, "eth_mac_10g.v"),
@ -201,7 +202,11 @@ def test_fpga_core(request):
parameters = {}
# parameters['A'] = val
parameters['SW_CNT'] = 4
parameters['LED_CNT'] = 3
parameters['UART_CNT'] = 1
parameters['QSFP_CNT'] = 2
parameters['CH_CNT'] = parameters['QSFP_CNT']*4
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

View File

@ -0,0 +1,145 @@
/*
Copyright (c) 2023 Alex Forencich
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
// Language: Verilog 2001
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Testbench top-level module
*/
module test_fpga_core #
(
parameter SW_CNT = 4,
parameter LED_CNT = 3,
parameter UART_CNT = 1,
parameter QSFP_CNT = 2,
parameter CH_CNT = QSFP_CNT*4
)
(
input wire clk,
input wire rst,
/*
* GPIO
*/
input wire [SW_CNT-1:0] sw,
output wire [LED_CNT-1:0] led,
output wire [QSFP_CNT-1:0] qsfp_led_act,
output wire [QSFP_CNT-1:0] qsfp_led_stat_g,
output wire [QSFP_CNT-1:0] qsfp_led_stat_y,
/*
* UART
*/
output wire [UART_CNT-1:0] uart_txd,
input wire [UART_CNT-1:0] uart_rxd
);
genvar n;
// XGMII 10G PHY
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
wire [CH_CNT*8-1:0] eth_txc;
wire [CH_CNT-1:0] eth_rx_clk;
wire [CH_CNT-1:0] eth_rx_rst;
wire [CH_CNT*64-1:0] eth_rxd;
wire [CH_CNT*8-1:0] eth_rxc;
generate
for (n = 0; n < CH_CNT; n = n + 1) begin : ch
wire ch_tx_clk;
wire ch_tx_rst;
wire [63:0] ch_txd;
wire [7:0] ch_txc;
wire ch_rx_clk;
wire ch_rx_rst;
wire [63:0] ch_rxd;
wire [7:0] ch_rxc;
assign eth_tx_clk[n +: 1] = ch_tx_clk;
assign eth_tx_rst[n +: 1] = ch_tx_rst;
assign ch_txd = eth_txd[n*64 +: 64];
assign ch_txc = eth_txc[n*8 +: 8];
assign eth_rx_clk[n +: 1] = ch_rx_clk;
assign eth_rx_rst[n +: 1] = ch_rx_rst;
assign eth_rxd[n*64 +: 64] = ch_rxd;
assign eth_rxc[n*8 +: 8] = ch_rxc;
end
endgenerate
fpga_core #(
.SW_CNT(SW_CNT),
.LED_CNT(LED_CNT),
.UART_CNT(UART_CNT),
.QSFP_CNT(QSFP_CNT),
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz
* Synchronous reset
*/
.clk(clk),
.rst(rst),
/*
* GPIO
*/
.sw(sw),
.led(led),
.qsfp_led_act(qsfp_led_act),
.qsfp_led_stat_g(qsfp_led_stat_g),
.qsfp_led_stat_y(qsfp_led_stat_y),
/*
* UART
*/
.uart_txd(uart_txd),
.uart_rxd(uart_rxd),
/*
* Ethernet: QSFP28
*/
.eth_tx_clk(eth_tx_clk),
.eth_tx_rst(eth_tx_rst),
.eth_txd(eth_txd),
.eth_txc(eth_txc),
.eth_rx_clk(eth_rx_clk),
.eth_rx_rst(eth_rx_rst),
.eth_rxd(eth_rxd),
.eth_rxc(eth_rxc)
);
endmodule
`resetall

View File

@ -31,22 +31,27 @@ THE SOFTWARE.
/*
* FPGA top-level module
*/
module fpga (
module fpga #
(
parameter QUAD_CNT = 17,
parameter CH_CNT = QUAD_CNT*4
)
(
/*
* Clock: 156.25MHz
*/
input wire [1:0] refclk_user_p,
input wire [1:0] refclk_user_n,
input wire [1:0] refclk_user_p,
input wire [1:0] refclk_user_n,
/*
* Ethernet: QSFP28
*/
input wire [67:0] eth_gt_ch_rx_p,
input wire [67:0] eth_gt_ch_rx_n,
output wire [67:0] eth_gt_ch_tx_p,
output wire [67:0] eth_gt_ch_tx_n,
input wire [16:0] eth_gt_pri_refclk_p,
input wire [16:0] eth_gt_pri_refclk_n
input wire [CH_CNT-1:0] eth_gt_ch_rx_p,
input wire [CH_CNT-1:0] eth_gt_ch_rx_n,
output wire [CH_CNT-1:0] eth_gt_ch_tx_p,
output wire [CH_CNT-1:0] eth_gt_ch_tx_n,
input wire [QUAD_CNT-1:0] eth_gt_pri_refclk_p,
input wire [QUAD_CNT-1:0] eth_gt_pri_refclk_n
);
genvar n;
@ -161,9 +166,6 @@ sync_reset_125mhz_inst (
);
// XGMII 10G PHY
parameter QUAD_CNT = 17;
parameter CH_CNT = QUAD_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;

View File

@ -290,160 +290,16 @@ always @(posedge clk) begin
end
end
assign eth_txd[1*64 +: 64] = 64'h0707070707070707;
assign eth_txc[1*8 +: 8] = 8'hff;
assign eth_txd[2*64 +: 64] = 64'h0707070707070707;
assign eth_txc[2*8 +: 8] = 8'hff;
assign eth_txd[3*64 +: 64] = 64'h0707070707070707;
assign eth_txc[3*8 +: 8] = 8'hff;
assign eth_txd[4*64 +: 64] = 64'h0707070707070707;
assign eth_txc[4*8 +: 8] = 8'hff;
assign eth_txd[5*64 +: 64] = 64'h0707070707070707;
assign eth_txc[5*8 +: 8] = 8'hff;
assign eth_txd[6*64 +: 64] = 64'h0707070707070707;
assign eth_txc[6*8 +: 8] = 8'hff;
assign eth_txd[7*64 +: 64] = 64'h0707070707070707;
assign eth_txc[7*8 +: 8] = 8'hff;
assign eth_txd[8*64 +: 64] = 64'h0707070707070707;
assign eth_txc[8*8 +: 8] = 8'hff;
assign eth_txd[9*64 +: 64] = 64'h0707070707070707;
assign eth_txc[9*8 +: 8] = 8'hff;
assign eth_txd[10*64 +: 64] = 64'h0707070707070707;
assign eth_txc[10*8 +: 8] = 8'hff;
assign eth_txd[11*64 +: 64] = 64'h0707070707070707;
assign eth_txc[11*8 +: 8] = 8'hff;
assign eth_txd[12*64 +: 64] = 64'h0707070707070707;
assign eth_txc[12*8 +: 8] = 8'hff;
assign eth_txd[13*64 +: 64] = 64'h0707070707070707;
assign eth_txc[13*8 +: 8] = 8'hff;
assign eth_txd[14*64 +: 64] = 64'h0707070707070707;
assign eth_txc[14*8 +: 8] = 8'hff;
assign eth_txd[15*64 +: 64] = 64'h0707070707070707;
assign eth_txc[15*8 +: 8] = 8'hff;
assign eth_txd[16*64 +: 64] = 64'h0707070707070707;
assign eth_txc[16*8 +: 8] = 8'hff;
assign eth_txd[17*64 +: 64] = 64'h0707070707070707;
assign eth_txc[17*8 +: 8] = 8'hff;
assign eth_txd[18*64 +: 64] = 64'h0707070707070707;
assign eth_txc[18*8 +: 8] = 8'hff;
assign eth_txd[19*64 +: 64] = 64'h0707070707070707;
assign eth_txc[19*8 +: 8] = 8'hff;
assign eth_txd[10*64 +: 64] = 64'h0707070707070707;
assign eth_txc[10*8 +: 8] = 8'hff;
assign eth_txd[11*64 +: 64] = 64'h0707070707070707;
assign eth_txc[11*8 +: 8] = 8'hff;
assign eth_txd[12*64 +: 64] = 64'h0707070707070707;
assign eth_txc[12*8 +: 8] = 8'hff;
assign eth_txd[13*64 +: 64] = 64'h0707070707070707;
assign eth_txc[13*8 +: 8] = 8'hff;
assign eth_txd[14*64 +: 64] = 64'h0707070707070707;
assign eth_txc[14*8 +: 8] = 8'hff;
assign eth_txd[15*64 +: 64] = 64'h0707070707070707;
assign eth_txc[15*8 +: 8] = 8'hff;
assign eth_txd[16*64 +: 64] = 64'h0707070707070707;
assign eth_txc[16*8 +: 8] = 8'hff;
assign eth_txd[17*64 +: 64] = 64'h0707070707070707;
assign eth_txc[17*8 +: 8] = 8'hff;
assign eth_txd[18*64 +: 64] = 64'h0707070707070707;
assign eth_txc[18*8 +: 8] = 8'hff;
assign eth_txd[19*64 +: 64] = 64'h0707070707070707;
assign eth_txc[19*8 +: 8] = 8'hff;
assign eth_txd[20*64 +: 64] = 64'h0707070707070707;
assign eth_txc[20*8 +: 8] = 8'hff;
assign eth_txd[21*64 +: 64] = 64'h0707070707070707;
assign eth_txc[21*8 +: 8] = 8'hff;
assign eth_txd[22*64 +: 64] = 64'h0707070707070707;
assign eth_txc[22*8 +: 8] = 8'hff;
assign eth_txd[23*64 +: 64] = 64'h0707070707070707;
assign eth_txc[23*8 +: 8] = 8'hff;
assign eth_txd[24*64 +: 64] = 64'h0707070707070707;
assign eth_txc[24*8 +: 8] = 8'hff;
assign eth_txd[25*64 +: 64] = 64'h0707070707070707;
assign eth_txc[25*8 +: 8] = 8'hff;
assign eth_txd[26*64 +: 64] = 64'h0707070707070707;
assign eth_txc[26*8 +: 8] = 8'hff;
assign eth_txd[27*64 +: 64] = 64'h0707070707070707;
assign eth_txc[27*8 +: 8] = 8'hff;
assign eth_txd[28*64 +: 64] = 64'h0707070707070707;
assign eth_txc[28*8 +: 8] = 8'hff;
assign eth_txd[29*64 +: 64] = 64'h0707070707070707;
assign eth_txc[29*8 +: 8] = 8'hff;
assign eth_txd[30*64 +: 64] = 64'h0707070707070707;
assign eth_txc[30*8 +: 8] = 8'hff;
assign eth_txd[31*64 +: 64] = 64'h0707070707070707;
assign eth_txc[31*8 +: 8] = 8'hff;
assign eth_txd[32*64 +: 64] = 64'h0707070707070707;
assign eth_txc[32*8 +: 8] = 8'hff;
assign eth_txd[33*64 +: 64] = 64'h0707070707070707;
assign eth_txc[33*8 +: 8] = 8'hff;
assign eth_txd[34*64 +: 64] = 64'h0707070707070707;
assign eth_txc[34*8 +: 8] = 8'hff;
assign eth_txd[35*64 +: 64] = 64'h0707070707070707;
assign eth_txc[35*8 +: 8] = 8'hff;
assign eth_txd[36*64 +: 64] = 64'h0707070707070707;
assign eth_txc[36*8 +: 8] = 8'hff;
assign eth_txd[37*64 +: 64] = 64'h0707070707070707;
assign eth_txc[37*8 +: 8] = 8'hff;
assign eth_txd[38*64 +: 64] = 64'h0707070707070707;
assign eth_txc[38*8 +: 8] = 8'hff;
assign eth_txd[39*64 +: 64] = 64'h0707070707070707;
assign eth_txc[39*8 +: 8] = 8'hff;
assign eth_txd[40*64 +: 64] = 64'h0707070707070707;
assign eth_txc[40*8 +: 8] = 8'hff;
assign eth_txd[41*64 +: 64] = 64'h0707070707070707;
assign eth_txc[41*8 +: 8] = 8'hff;
assign eth_txd[42*64 +: 64] = 64'h0707070707070707;
assign eth_txc[42*8 +: 8] = 8'hff;
assign eth_txd[43*64 +: 64] = 64'h0707070707070707;
assign eth_txc[43*8 +: 8] = 8'hff;
assign eth_txd[44*64 +: 64] = 64'h0707070707070707;
assign eth_txc[44*8 +: 8] = 8'hff;
assign eth_txd[45*64 +: 64] = 64'h0707070707070707;
assign eth_txc[45*8 +: 8] = 8'hff;
assign eth_txd[46*64 +: 64] = 64'h0707070707070707;
assign eth_txc[46*8 +: 8] = 8'hff;
assign eth_txd[47*64 +: 64] = 64'h0707070707070707;
assign eth_txc[47*8 +: 8] = 8'hff;
assign eth_txd[48*64 +: 64] = 64'h0707070707070707;
assign eth_txc[48*8 +: 8] = 8'hff;
assign eth_txd[49*64 +: 64] = 64'h0707070707070707;
assign eth_txc[49*8 +: 8] = 8'hff;
assign eth_txd[50*64 +: 64] = 64'h0707070707070707;
assign eth_txc[50*8 +: 8] = 8'hff;
assign eth_txd[51*64 +: 64] = 64'h0707070707070707;
assign eth_txc[51*8 +: 8] = 8'hff;
assign eth_txd[52*64 +: 64] = 64'h0707070707070707;
assign eth_txc[52*8 +: 8] = 8'hff;
assign eth_txd[53*64 +: 64] = 64'h0707070707070707;
assign eth_txc[53*8 +: 8] = 8'hff;
assign eth_txd[54*64 +: 64] = 64'h0707070707070707;
assign eth_txc[54*8 +: 8] = 8'hff;
assign eth_txd[55*64 +: 64] = 64'h0707070707070707;
assign eth_txc[55*8 +: 8] = 8'hff;
assign eth_txd[56*64 +: 64] = 64'h0707070707070707;
assign eth_txc[56*8 +: 8] = 8'hff;
assign eth_txd[57*64 +: 64] = 64'h0707070707070707;
assign eth_txc[57*8 +: 8] = 8'hff;
assign eth_txd[58*64 +: 64] = 64'h0707070707070707;
assign eth_txc[58*8 +: 8] = 8'hff;
assign eth_txd[59*64 +: 64] = 64'h0707070707070707;
assign eth_txc[59*8 +: 8] = 8'hff;
assign eth_txd[60*64 +: 64] = 64'h0707070707070707;
assign eth_txc[60*8 +: 8] = 8'hff;
assign eth_txd[61*64 +: 64] = 64'h0707070707070707;
assign eth_txc[61*8 +: 8] = 8'hff;
assign eth_txd[62*64 +: 64] = 64'h0707070707070707;
assign eth_txc[62*8 +: 8] = 8'hff;
assign eth_txd[63*64 +: 64] = 64'h0707070707070707;
assign eth_txc[63*8 +: 8] = 8'hff;
assign eth_txd[64*64 +: 64] = 64'h0707070707070707;
assign eth_txc[64*8 +: 8] = 8'hff;
assign eth_txd[65*64 +: 64] = 64'h0707070707070707;
assign eth_txc[65*8 +: 8] = 8'hff;
assign eth_txd[66*64 +: 64] = 64'h0707070707070707;
assign eth_txc[66*8 +: 8] = 8'hff;
assign eth_txd[67*64 +: 64] = 64'h0707070707070707;
assign eth_txc[67*8 +: 8] = 8'hff;
generate
genvar n;
for (n = 1; n < CH_CNT; n = n + 1) begin
assign eth_txd[n*64 +: 64] = 64'h0707070707070707;
assign eth_txc[n*8 +: 8] = 8'hff;
end
endgenerate
eth_mac_10g_fifo #(
.ENABLE_PADDING(1),

View File

@ -60,12 +60,13 @@ VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo.v
VERILOG_SOURCES += ../../lib/eth/lib/axis/rtl/axis_async_fifo_adapter.v
# module parameters
#export PARAM_A := value
export PARAM_QUAD_CNT := 17
export PARAM_CH_CNT := $(shell expr $(PARAM_QUAD_CNT) \* 4)
ifeq ($(SIM), icarus)
PLUSARGS += -fst
# COMPILE_ARGS += -P $(TOPLEVEL).A=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
VERILOG_SOURCES += iverilog_dump.v
@ -74,7 +75,7 @@ ifeq ($(SIM), icarus)
else ifeq ($(SIM), verilator)
COMPILE_ARGS += -Wno-SELRANGE -Wno-WIDTH
# COMPILE_ARGS += -GA=$(PARAM_A)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst

View File

@ -202,7 +202,8 @@ def test_fpga_core(request):
parameters = {}
# parameters['A'] = val
parameters['QUAD_CNT'] = 17
parameters['CH_CNT'] = parameters['QUAD_CNT']*4
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}

View File

@ -31,17 +31,19 @@ THE SOFTWARE.
/*
* Testbench top-level module
*/
module test_fpga_core ();
module test_fpga_core #
(
parameter QUAD_CNT = 17,
parameter CH_CNT = QUAD_CNT*4
)
(
input wire clk,
input wire rst
);
genvar n;
wire clk;
wire rst;
// XGMII 10G PHY
parameter QUAD_CNT = 17;
parameter CH_CNT = QUAD_CNT*4;
wire [CH_CNT-1:0] eth_tx_clk;
wire [CH_CNT-1:0] eth_tx_rst;
wire [CH_CNT*64-1:0] eth_txd;
@ -77,7 +79,9 @@ end
endgenerate
fpga_core
fpga_core #(
.CH_CNT(CH_CNT)
)
core_inst (
/*
* Clock: 156.25 MHz

View File

@ -29,6 +29,11 @@ create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz]
#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz]
# User SMA clock J34/J35
#set_property -dict {LOC AR14 IOSTANDARD LVDS} [get_ports user_sma_clk_p]
#set_property -dict {LOC AT14 IOSTANDARD LVDS} [get_ports user_sma_clk_n]
#create_clock -period 8.000 -name user_sma_clk [get_ports user_sma_clk_p]
# LEDs
set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]

View File

@ -29,6 +29,11 @@ create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz]
#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz]
# User SMA clock J34/J35
#set_property -dict {LOC AR14 IOSTANDARD LVDS} [get_ports user_sma_clk_p]
#set_property -dict {LOC AT14 IOSTANDARD LVDS} [get_ports user_sma_clk_n]
#create_clock -period 8.000 -name user_sma_clk [get_ports user_sma_clk_p]
# LEDs
set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]

View File

@ -35,6 +35,11 @@ create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz]
#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz]
# User SMA clock J34/J35
#set_property -dict {LOC R32 IOSTANDARD LVDS} [get_ports user_sma_clk_p]
#set_property -dict {LOC P32 IOSTANDARD LVDS} [get_ports user_sma_clk_n]
#create_clock -period 8.000 -name user_sma_clk [get_ports user_sma_clk_p]
# LEDs
set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]

View File

@ -35,6 +35,11 @@ create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz]
#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz]
# User SMA clock J34/J35
#set_property -dict {LOC R32 IOSTANDARD LVDS} [get_ports user_sma_clk_p]
#set_property -dict {LOC P32 IOSTANDARD LVDS} [get_ports user_sma_clk_n]
#create_clock -period 8.000 -name user_sma_clk [get_ports user_sma_clk_p]
# LEDs
set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]

View File

@ -35,6 +35,11 @@ create_clock -period 8.000 -name clk_125mhz [get_ports clk_125mhz_p]
#set_property -dict {LOC AL20 IOSTANDARD LVCMOS18} [get_ports clk_90mhz]
#create_clock -period 11.111 -name clk_90mhz [get_ports clk_90mhz]
# User SMA clock J34/J35
#set_property -dict {LOC R32 IOSTANDARD LVDS} [get_ports user_sma_clk_p]
#set_property -dict {LOC P32 IOSTANDARD LVDS} [get_ports user_sma_clk_n]
#create_clock -period 8.000 -name user_sma_clk [get_ports user_sma_clk_p]
# LEDs
set_property -dict {LOC AT32 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[0]}]
set_property -dict {LOC AV34 IOSTANDARD LVCMOS12 SLEW SLOW DRIVE 8} [get_ports {led[1]}]

View File

@ -491,8 +491,6 @@ always @(posedge output_clk) begin
ts_capt_valid_reg <= 1'b1;
end
ts_sync_valid_reg <= 1'b0;
if (src_sync_sync2_reg ^ src_sync_sync3_reg) begin
// store captured source TS
if (TS_WIDTH == 96) begin
@ -501,7 +499,11 @@ always @(posedge output_clk) begin
src_ts_ns_sync_reg <= src_ts_ns_capt_reg;
src_ts_step_sync_reg <= src_ts_step_capt_reg;
ts_sync_valid_reg <= ts_capt_valid_reg;
ts_sync_valid_reg <= 1'b1;
end
if (ts_sync_valid_reg && ts_capt_valid_reg) begin
ts_sync_valid_reg <= 1'b0;
ts_capt_valid_reg <= 1'b0;
end
@ -595,7 +597,7 @@ always @* begin
ts_ns_next = ts_ns_reg + period_ns_reg;
end
if (ts_sync_valid_reg) begin
if (ts_sync_valid_reg && ts_capt_valid_reg) begin
// Read new value
if (TS_WIDTH == 96) begin
if (src_ts_step_sync_reg || load_ts_reg) begin
@ -672,19 +674,19 @@ always @* begin
// PI control
// gain scheduling
if (!ts_ns_diff_reg[8+CMP_FNS_WIDTH]) begin
if (ts_ns_diff_reg[4+CMP_FNS_WIDTH +: 4]) begin
gain_sel_next = 1'b1;
end else begin
gain_sel_next = 1'b0;
end
end else begin
if (~ts_ns_diff_reg[4+CMP_FNS_WIDTH +: 4]) begin
gain_sel_next = 1'b1;
end else begin
gain_sel_next = 1'b0;
end
end
casez (ts_ns_diff_reg[9+CMP_FNS_WIDTH-5 +: 5])
5'b01zzz: gain_sel_next = 1'b1;
5'b001zz: gain_sel_next = 1'b1;
5'b0001z: gain_sel_next = 1'b1;
5'b00001: gain_sel_next = 1'b1;
5'b00000: gain_sel_next = 1'b0;
5'b11111: gain_sel_next = 1'b0;
5'b11110: gain_sel_next = 1'b1;
5'b1110z: gain_sel_next = 1'b1;
5'b110zz: gain_sel_next = 1'b1;
5'b10zzz: gain_sel_next = 1'b1;
default: gain_sel_next = 1'b0;
endcase
// time integral of error
case (gain_sel_reg)

View File

@ -89,7 +89,7 @@ localparam LOG_RATE = 3;
localparam PHASE_CNT_W = LOG_RATE;
localparam PHASE_ACC_W = PHASE_CNT_W+16;
localparam LOAD_CNT_W = 8-LOG_RATE;
localparam LOAD_CNT_W = 8-LOG_RATE-1;
localparam LOG_SAMPLE_SYNC_RATE = 4;
localparam SAMPLE_ACC_W = LOG_SAMPLE_SYNC_RATE+2;
@ -225,8 +225,6 @@ reg [PERIOD_NS_W+32-1:0] src_period_shadow_reg = 0;
reg [9+SRC_FNS_W-1:0] src_ns_reg = 0;
reg [9+32-1:0] src_ns_shadow_reg = 0;
reg src_fns_shadow_valid_reg = 1'b0;
reg src_ns_shadow_valid_reg = 1'b0;
always @(posedge ptp_clk) begin
src_load_reg <= 1'b0;
@ -242,15 +240,12 @@ always @(posedge ptp_clk) begin
if (td_tvalid_reg) begin
if (td_tid_reg[3:0] == 4'd6) begin
src_ns_shadow_reg[15:0] <= td_tdata_reg;
src_fns_shadow_valid_reg <= 1'b0;
end
if (td_tid_reg[3:0] == 4'd7) begin
src_ns_shadow_reg[31:16] <= td_tdata_reg;
src_fns_shadow_valid_reg <= 1'b1;
end
if (td_tid_reg[3:0] == 4'd8) begin
src_ns_shadow_reg[40:32] <= td_tdata_reg;
src_ns_shadow_valid_reg <= 1'b1;
end
if (td_tid_reg[3:0] == 4'd11) begin
src_period_shadow_reg[15:0] <= td_tdata_reg;
@ -264,12 +259,9 @@ always @(posedge ptp_clk) begin
end
if (src_load_reg) begin
if (src_ns_shadow_valid_reg && src_fns_shadow_valid_reg) begin
src_ns_reg <= src_ns_shadow_reg >> (32-SRC_FNS_W);
end
src_fns_shadow_valid_reg <= 1'b0;
src_ns_shadow_valid_reg <= 1'b0;
src_ns_reg <= src_ns_shadow_reg >> (32-SRC_FNS_W);
src_period_reg <= src_period_shadow_reg;
src_sync_reg <= 1'b1;
src_marker_reg <= !src_marker_reg;
end
@ -435,19 +427,17 @@ always @* begin
// updated sampled dst_phase error
// gain scheduling
if (!sample_acc_sync_reg[SAMPLE_ACC_W-1]) begin
if (sample_acc_sync_reg[SAMPLE_ACC_W-4 +: 3]) begin
dst_gain_sel_next = 1'b1;
end else begin
dst_gain_sel_next = 1'b0;
end
end else begin
if (~sample_acc_sync_reg[SAMPLE_ACC_W-4 +: 3]) begin
dst_gain_sel_next = 1'b1;
end else begin
dst_gain_sel_next = 1'b0;
end
end
casez (sample_acc_sync_reg[SAMPLE_ACC_W-4 +: 4])
4'b01zz: dst_gain_sel_next = 1'b1;
4'b001z: dst_gain_sel_next = 1'b1;
4'b0001: dst_gain_sel_next = 1'b1;
4'b0000: dst_gain_sel_next = 1'b0;
4'b1111: dst_gain_sel_next = 1'b0;
4'b1110: dst_gain_sel_next = 1'b1;
4'b110z: dst_gain_sel_next = 1'b1;
4'b10zz: dst_gain_sel_next = 1'b1;
default: dst_gain_sel_next = 1'b0;
endcase
// time integral of error
case (dst_gain_sel_reg)
@ -530,17 +520,16 @@ always @(posedge clk) begin
dst_sync_reg <= !dst_sync_reg;
ts_capt_valid_reg <= 1'b1;
dst_load_cnt_reg <= dst_load_cnt_reg + 1;
if (dst_sync_reg) begin
dst_load_cnt_reg <= dst_load_cnt_reg + 1;
end
end
ts_sync_valid_reg <= 1'b0;
if (src_sync_sync2_reg ^ src_sync_sync3_reg) begin
// store captured source TS
src_ns_sync_reg <= src_ns_reg >> (SRC_FNS_W-CMP_FNS_W);
ts_sync_valid_reg <= ts_capt_valid_reg;
ts_capt_valid_reg <= 1'b0;
ts_sync_valid_reg <= 1'b1;
end
if (src_marker_sync2_reg ^ src_marker_sync3_reg) begin
@ -548,9 +537,12 @@ always @(posedge clk) begin
end
phase_err_out_valid_reg <= 1'b0;
if (ts_sync_valid_reg) begin
if (ts_sync_valid_reg && ts_capt_valid_reg) begin
// coarse phase locking
ts_sync_valid_reg <= 1'b0;
ts_capt_valid_reg <= 1'b0;
// phase and frequency detector
phase_last_src_reg <= src_ns_sync_reg[8+CMP_FNS_W];
phase_last_dst_reg <= dst_ns_capt_reg[8+CMP_FNS_W];
@ -696,6 +688,10 @@ always @* begin
// extract data
if (dst_td_tvalid_reg) begin
if (TS_TOD_EN) begin
if (dst_td_tid_reg[3:0] == 4'd1) begin
// prevent stale data from being used in time sync
dst_tod_shadow_valid_next = 1'b0;
end
if (dst_td_tid_reg == {4'd0, 4'd1}) begin
dst_tod_ns_shadow_next[15:0] = dst_td_tdata_reg;
dst_tod_shadow_valid_next = 1'b0;
@ -749,7 +745,7 @@ always @* begin
ts_rel_ns_next = ({ts_rel_ns_reg, ts_fns_reg} + period_ns_reg) >> FNS_W;
if (TS_REL_EN) begin
if (dst_update_reg && dst_rel_shadow_valid_reg && (dst_load_cnt_reg == {LOAD_CNT_W{1'b1}})) begin
if (dst_update_reg && !dst_sync_reg && dst_rel_shadow_valid_reg && (dst_load_cnt_reg == 0)) begin
// check timestamp MSBs
if (dst_rel_step_shadow_reg || ts_rel_load_ts_reg) begin
// input stepped
@ -797,7 +793,7 @@ always @* begin
end
end
if (dst_update_reg && dst_tod_shadow_valid_reg && (dst_load_cnt_reg == {LOAD_CNT_W{1'b1}})) begin
if (dst_update_reg && !dst_sync_reg && dst_tod_shadow_valid_reg && (dst_load_cnt_reg == 0)) begin
// check timestamp MSBs
if (dst_tod_step_shadow_reg || ts_tod_load_ts_reg) begin
// input stepped
@ -827,7 +823,7 @@ always @* begin
end
end
if (ts_sync_valid_reg) begin
if (ts_sync_valid_reg && ts_capt_valid_reg) begin
// compute difference
ts_ns_diff_valid_next = freq_locked_reg;
ts_ns_diff_next = src_ns_sync_reg - dst_ns_capt_reg;
@ -859,19 +855,19 @@ always @* begin
// PI control
// gain scheduling
if (!ts_ns_diff_reg[8+CMP_FNS_W]) begin
if (ts_ns_diff_reg[4+CMP_FNS_W +: 4]) begin
gain_sel_next = 1'b1;
end else begin
gain_sel_next = 1'b0;
end
end else begin
if (~ts_ns_diff_reg[4+CMP_FNS_W +: 4]) begin
gain_sel_next = 1'b1;
end else begin
gain_sel_next = 1'b0;
end
end
casez (ts_ns_diff_reg[9+CMP_FNS_W-5 +: 5])
5'b01zzz: gain_sel_next = 1'b1;
5'b001zz: gain_sel_next = 1'b1;
5'b0001z: gain_sel_next = 1'b1;
5'b00001: gain_sel_next = 1'b1;
5'b00000: gain_sel_next = 1'b0;
5'b11111: gain_sel_next = 1'b0;
5'b11110: gain_sel_next = 1'b1;
5'b1110z: gain_sel_next = 1'b1;
5'b110zz: gain_sel_next = 1'b1;
5'b10zzz: gain_sel_next = 1'b1;
default: gain_sel_next = 1'b0;
endcase
// time integral of error
case (gain_sel_reg)

View File

@ -154,10 +154,9 @@ reg [3:0] update_state_reg = 0;
reg [47:0] adder_a_reg = 0;
reg [47:0] adder_b_reg = 0;
reg adder_cin_reg = 0;
wire [47:0] adder_sum;
wire adder_cout;
assign {adder_cout, adder_sum} = adder_a_reg + adder_b_reg + adder_cin_reg;
reg [47:0] adder_sum_reg = 0;
reg adder_cout_reg = 0;
reg adder_busy_reg = 0;
assign input_ts_tod_ready = input_ts_tod_ready_reg;
assign input_ts_tod_offset_ready = input_ts_tod_offset_ready_reg;
@ -225,8 +224,7 @@ always @(posedge clk) begin
pps_gen_ns_reg <= pps_gen_ns_reg + pps_gen_ns_inc_reg;
if (!pps_gen_ns_reg[30]) begin
// pps_delay_reg <= 14*17 + 32 + 1;
pps_delay_reg <= 14*17 + 32 + 248;
pps_delay_reg <= 14*17 + 32 + 240;
pps_gen_ns_reg[30] <= 1'b1;
end
@ -245,231 +243,269 @@ always @(posedge clk) begin
end
// update state machine
case (update_state_reg)
0: begin
// idle
{adder_cout_reg, adder_sum_reg} <= adder_a_reg + adder_b_reg + adder_cin_reg;
adder_busy_reg <= 1'b0;
// set relative timestamp
if (input_ts_rel_valid) begin
ts_rel_ns_reg <= input_ts_rel_ns;
input_ts_rel_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
// computes the following:
// {ts_inc_ns_reg, ts_fns_reg} = drift_acc_reg + $signed(input_ts_offset_fns) + {period_ns_reg, period_fns_reg} * 256 + ts_fns_reg
// ts_rel_ns_reg = ts_rel_ns_reg + ts_inc_ns_reg + $signed(input_ts_rel_offset_ns);
// ts_tod_ns_reg = ts_tod_ns_reg + ts_inc_ns_reg + $signed(input_ts_tod_offset_ns);
// if that borrowed,
// ts_tod_ns_reg = ts_tod_ns_reg + NS_PER_S
// ts_tod_s_reg = ts_tod_s_reg - 1
// else
// pps_gen_ns_reg = ts_tod_ns_reg - NS_PER_S
// if that did not borrow,
// ts_tod_ns_reg = ts_tod_ns_reg - NS_PER_S
// ts_tod_s_reg = ts_tod_s_reg + 1
// ts_tod_offset_ns_reg = ts_tod_ns_reg - ts_rel_ns_reg
// if ts_tod_ns_reg[29]
// ts_tod_alt_offset_ns_reg = ts_tod_offset_ns_reg - NS_PER_S
// ts_tod_alt_s_reg = ts_tod_s_reg + 1
// else
// ts_tod_alt_offset_ns_reg = ts_tod_offset_ns_reg + NS_PER_S
// ts_tod_alt_s_reg = ts_tod_s_reg - 1
// set ToD timestamp
if (input_ts_tod_valid) begin
ts_tod_s_reg <= input_ts_tod_s;
ts_tod_ns_reg <= input_ts_tod_ns;
input_ts_tod_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
if (!adder_busy_reg) begin
case (update_state_reg)
0: begin
// idle
// compute period 1 - add drift and requested offset
if (drift_apply_reg) begin
adder_a_reg <= drift_acc_reg + drift_num_reg;
end else begin
adder_a_reg <= drift_acc_reg;
end
adder_b_reg <= input_ts_offset_valid ? $signed(input_ts_offset_fns) : 0;
adder_cin_reg <= 0;
// set relative timestamp
if (input_ts_rel_valid) begin
ts_rel_ns_reg <= input_ts_rel_ns;
input_ts_rel_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
if (td_update_reg) begin
drift_acc_reg <= 0;
input_ts_offset_ready_reg <= input_ts_offset_valid;
update_state_reg <= 1;
end else begin
update_state_reg <= 0;
end
end
1: begin
// compute period 2 - add drift and offset to period
adder_a_reg <= adder_sum;
adder_b_reg <= {period_ns_reg, period_fns_reg, 8'd0};
adder_cin_reg <= 0;
// set ToD timestamp
if (input_ts_tod_valid) begin
ts_tod_s_reg <= input_ts_tod_s;
ts_tod_ns_reg <= input_ts_tod_ns;
input_ts_tod_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
update_state_reg <= 2;
end
2: begin
// compute next fns
adder_a_reg <= adder_sum;
adder_b_reg <= ts_fns_reg;
adder_cin_reg <= 0;
update_state_reg <= 3;
end
3: begin
// store fns; compute relative timestamp 1 - add previous value and offset
{ts_inc_ns_reg, ts_fns_reg} <= {adder_cout, adder_sum};
adder_a_reg <= ts_rel_ns_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset relative timestamp if requested
if (input_ts_rel_offset_valid) begin
adder_b_reg <= $signed(input_ts_rel_offset_ns);
input_ts_rel_offset_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
update_state_reg <= 4;
end
4: begin
// compute relative timestamp 2 - add increment
adder_a_reg <= adder_sum;
adder_b_reg <= ts_inc_ns_reg;
adder_cin_reg <= 0;
update_state_reg <= 5;
end
5: begin
// store relative timestamp; compute ToD timestamp 1 - add previous value and increment
ts_rel_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ts_inc_ns_reg;
adder_cin_reg <= 0;
update_state_reg <= 6;
end
6: begin
// compute ToD timestamp 2 - add offset
adder_a_reg <= adder_sum;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset ToD timestamp if requested
if (input_ts_tod_offset_valid) begin
adder_b_reg <= $signed(input_ts_tod_offset_ns);
input_ts_tod_offset_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
update_state_reg <= 7;
end
7: begin
// compute ToD timestamp 2 - check for underflow/overflow
ts_tod_ns_reg <= adder_sum;
if (adder_b_reg[47] && !adder_cout) begin
// borrowed; add 1 billion
adder_a_reg <= adder_sum;
adder_b_reg <= NS_PER_S;
// compute period 1 - add drift and requested offset
if (drift_apply_reg) begin
adder_a_reg <= drift_acc_reg + drift_num_reg;
end else begin
adder_a_reg <= drift_acc_reg;
end
adder_b_reg <= input_ts_offset_valid ? $signed(input_ts_offset_fns) : 0;
adder_cin_reg <= 0;
update_state_reg <= 8;
end else begin
// did not borrow; subtract 1 billion to check for overflow
adder_a_reg <= adder_sum;
if (td_update_reg) begin
drift_acc_reg <= 0;
input_ts_offset_ready_reg <= input_ts_offset_valid;
update_state_reg <= 1;
adder_busy_reg <= 1'b1;
end else begin
update_state_reg <= 0;
end
end
1: begin
// compute period 2 - add drift and offset to period
adder_a_reg <= adder_sum_reg;
adder_b_reg <= {period_ns_reg, period_fns_reg, 8'd0};
adder_cin_reg <= 0;
update_state_reg <= 2;
adder_busy_reg <= 1'b1;
end
2: begin
// compute next fns
adder_a_reg <= adder_sum_reg;
adder_b_reg <= ts_fns_reg;
adder_cin_reg <= 0;
update_state_reg <= 3;
adder_busy_reg <= 1'b1;
end
3: begin
// store fns
{ts_inc_ns_reg, ts_fns_reg} <= {adder_cout_reg, adder_sum_reg};
// compute relative timestamp 1 - add previous value and increment
adder_a_reg <= ts_rel_ns_reg;
adder_b_reg <= {adder_cout_reg, adder_sum_reg} >> FNS_W; // ts_inc_ns_reg
adder_cin_reg <= 0;
update_state_reg <= 4;
adder_busy_reg <= 1'b1;
end
4: begin
// compute relative timestamp 2 - add offset
adder_a_reg <= adder_sum_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset relative timestamp if requested
if (input_ts_rel_offset_valid) begin
adder_b_reg <= $signed(input_ts_rel_offset_ns);
input_ts_rel_offset_ready_reg <= 1'b1;
ts_rel_updated_reg <= 1'b1;
end
update_state_reg <= 5;
adder_busy_reg <= 1'b1;
end
5: begin
// store relative timestamp
ts_rel_ns_reg <= adder_sum_reg;
// compute ToD timestamp 1 - add previous value and increment
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ts_inc_ns_reg;
adder_cin_reg <= 0;
update_state_reg <= 6;
adder_busy_reg <= 1'b1;
end
6: begin
// compute ToD timestamp 2 - add offset
adder_a_reg <= adder_sum_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
// offset ToD timestamp if requested
if (input_ts_tod_offset_valid) begin
adder_b_reg <= $signed(input_ts_tod_offset_ns);
input_ts_tod_offset_ready_reg <= 1'b1;
ts_tod_updated_reg <= 1'b1;
end
update_state_reg <= 7;
adder_busy_reg <= 1'b1;
end
7: begin
// compute ToD timestamp 3 - check for underflow/overflow
ts_tod_ns_reg <= adder_sum_reg;
if (adder_b_reg[47] && !adder_cout_reg) begin
// borrowed; add 1 billion
adder_a_reg <= adder_sum_reg;
adder_b_reg <= NS_PER_S;
adder_cin_reg <= 0;
update_state_reg <= 8;
adder_busy_reg <= 1'b1;
end else begin
// did not borrow; subtract 1 billion to check for overflow
adder_a_reg <= adder_sum_reg;
adder_b_reg <= -NS_PER_S;
adder_cin_reg <= 0;
update_state_reg <= 9;
adder_busy_reg <= 1'b1;
end
end
8: begin
// seconds decrement
ts_tod_ns_reg <= adder_sum_reg;
pps_gen_ns_reg[30] <= 1'b1;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 10;
adder_busy_reg <= 1'b1;
end
9: begin
// seconds increment
pps_gen_ns_reg <= adder_sum_reg;
if (!adder_cout_reg) begin
// borrowed; leave seconds alone
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
end else begin
// did not borrow; increment seconds
ts_tod_ns_reg <= adder_sum_reg;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 1;
adder_cin_reg <= 0;
end
update_state_reg <= 10;
adder_busy_reg <= 1'b1;
end
10: begin
// store seconds
ts_tod_s_reg <= adder_sum_reg;
// compute offset
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ~ts_rel_ns_reg;
adder_cin_reg <= 1;
update_state_reg <= 11;
adder_busy_reg <= 1'b1;
end
11: begin
// store offset
ts_tod_offset_ns_reg <= adder_sum_reg;
adder_a_reg <= adder_sum_reg;
adder_b_reg <= -NS_PER_S;
adder_cin_reg <= 0;
update_state_reg <= 9;
if (ts_tod_ns_reg[29]) begin
// latter half of second; compute offset for next second
adder_b_reg <= -NS_PER_S;
update_state_reg <= 12;
adder_busy_reg <= 1'b1;
end else begin
// former half of second; compute offset for previous second
adder_b_reg <= NS_PER_S;
update_state_reg <= 14;
adder_busy_reg <= 1'b1;
end
end
end
8: begin
// seconds decrement
ts_tod_ns_reg <= adder_sum;
pps_gen_ns_reg[30] <= 1'b1;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 10;
end
9: begin
// seconds increment
pps_gen_ns_reg <= adder_sum;
if (!adder_cout) begin
// borrowed; leave seconds alone
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 0;
adder_cin_reg <= 0;
end else begin
// did not borrow; decrement seconds
ts_tod_ns_reg <= adder_sum;
12: begin
// store alternate offset for next second
ts_tod_alt_offset_ns_reg <= adder_sum_reg;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 1;
adder_cin_reg <= 0;
update_state_reg <= 13;
adder_busy_reg <= 1'b1;
end
13: begin
// store alternate second for next second
ts_tod_alt_s_reg <= adder_sum_reg;
update_state_reg <= 10;
end
10: begin
// store seconds; compute offset
ts_tod_s_reg <= adder_sum;
if (adder_sum == ts_tod_alt_s_reg) begin
// store previous offset as alternate
ts_tod_alt_s_reg <= ts_tod_s_reg;
ts_tod_alt_offset_ns_reg <= ts_tod_offset_ns_reg;
update_state_reg <= 0;
end
14: begin
// store alternate offset for previous second
ts_tod_alt_offset_ns_reg <= adder_sum_reg;
adder_a_reg <= ts_tod_ns_reg;
adder_b_reg <= ~ts_rel_ns_reg;
adder_cin_reg <= 1;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 11;
end
11: begin
// store offset
ts_tod_offset_ns_reg <= adder_sum;
adder_a_reg <= adder_sum;
adder_b_reg <= -NS_PER_S;
adder_cin_reg <= 0;
if (ts_tod_ns_reg[29]) begin
// latter half of second; compute offset for next second
adder_b_reg <= -NS_PER_S;
update_state_reg <= 12;
end else begin
// former half of second; compute offset for previous second
adder_b_reg <= NS_PER_S;
update_state_reg <= 14;
update_state_reg <= 15;
adder_busy_reg <= 1'b1;
end
end
12: begin
// store alternate offset for next second
ts_tod_alt_offset_ns_reg <= adder_sum;
15: begin
// store alternate second for previous second
ts_tod_alt_s_reg <= adder_sum_reg;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= 1;
adder_cin_reg <= 0;
update_state_reg <= 13;
end
13: begin
// store alternate second for next second
ts_tod_alt_s_reg <= adder_sum;
update_state_reg <= 0;
end
14: begin
// store alternate offset for previous second
ts_tod_alt_offset_ns_reg <= adder_sum;
adder_a_reg <= ts_tod_s_reg;
adder_b_reg <= -1;
adder_cin_reg <= 0;
update_state_reg <= 15;
end
15: begin
// store alternate second for previous second
ts_tod_alt_s_reg <= adder_sum;
update_state_reg <= 0;
end
default: begin
// invalid state; return to idle
update_state_reg <= 0;
end
endcase
update_state_reg <= 0;
end
default: begin
// invalid state; return to idle
update_state_reg <= 0;
end
endcase
end
// time distribution message generation
td_shift_reg <= {1'b1, td_shift_reg} >> 1;

View File

@ -20,8 +20,8 @@
# Ethernet MAC timing constraints
foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == eth_mac_1g || REF_NAME == eth_mac_1g || \
ORIG_REF_NAME == eth_mac_10g || REF_NAME == eth_mac_10g)}] {
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "eth_mac_(1g|10g)(__\w+__\d+)?" ||
REF_NAME =~ "eth_mac_(1g|10g)(__\w+__\d+)?")}] {
puts "Inserting timing constraints for Ethernet MAC instance $inst"
set sync_ffs [get_cells -quiet -hier -regexp ".*/mac_ctrl.tx_lfc_req_sync_reg_\[1234\]_reg" -filter "PARENT == $inst"]

View File

@ -20,42 +20,43 @@
# GMII Gigabit Ethernet MAC timing constraints
foreach mac_inst [get_cells -hier -filter {(ORIG_REF_NAME == eth_mac_1g_gmii || REF_NAME == eth_mac_1g_gmii)}] {
puts "Inserting timing constraints for eth_mac_1g_gmii instance $mac_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "eth_mac_1g_gmii(__\w+__\d+)?" ||
REF_NAME =~ "eth_mac_1g_gmii(__\w+__\d+)?")}] {
puts "Inserting timing constraints for eth_mac_1g_gmii instance $inst"
set select_ffs [get_cells -hier -regexp ".*/tx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set select_ffs [get_cells -hier -regexp ".*/tx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $select_ffs]} {
set_property ASYNC_REG TRUE $select_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/mii_select_reg_reg/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/mii_select_reg_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/mii_select_reg_reg] -to [get_cells $mac_inst/tx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/mii_select_reg_reg] -to [get_cells $inst/tx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
}
set select_ffs [get_cells -hier -regexp ".*/rx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set select_ffs [get_cells -hier -regexp ".*/rx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $select_ffs]} {
set_property ASYNC_REG TRUE $select_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/mii_select_reg_reg/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/mii_select_reg_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/mii_select_reg_reg] -to [get_cells $mac_inst/rx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/mii_select_reg_reg] -to [get_cells $inst/rx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
}
set prescale_ffs [get_cells -hier -regexp ".*/rx_prescale_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set prescale_ffs [get_cells -hier -regexp ".*/rx_prescale_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $prescale_ffs]} {
set_property ASYNC_REG TRUE $prescale_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/rx_prescale_reg[2]/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/rx_prescale_reg[2]/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/rx_prescale_reg[2]] -to [get_cells $mac_inst/rx_prescale_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/rx_prescale_reg[2]] -to [get_cells $inst/rx_prescale_sync_reg[0]] -datapath_only $src_clk_period
}
}

View File

@ -20,42 +20,43 @@
# RGMII Gigabit Ethernet MAC timing constraints
foreach mac_inst [get_cells -hier -filter {(ORIG_REF_NAME == eth_mac_1g_rgmii || REF_NAME == eth_mac_1g_rgmii)}] {
puts "Inserting timing constraints for eth_mac_1g_rgmii instance $mac_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "eth_mac_1g_rgmii(__\w+__\d+)?" ||
REF_NAME =~ "eth_mac_1g_rgmii(__\w+__\d+)?")}] {
puts "Inserting timing constraints for eth_mac_1g_rgmii instance $inst"
set select_ffs [get_cells -hier -regexp ".*/tx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set select_ffs [get_cells -hier -regexp ".*/tx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $select_ffs]} {
set_property ASYNC_REG TRUE $select_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/mii_select_reg_reg/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/mii_select_reg_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/mii_select_reg_reg] -to [get_cells $mac_inst/tx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/mii_select_reg_reg] -to [get_cells $inst/tx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
}
set select_ffs [get_cells -hier -regexp ".*/rx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set select_ffs [get_cells -hier -regexp ".*/rx_mii_select_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $select_ffs]} {
set_property ASYNC_REG TRUE $select_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/mii_select_reg_reg/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/mii_select_reg_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/mii_select_reg_reg] -to [get_cells $mac_inst/rx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/mii_select_reg_reg] -to [get_cells $inst/rx_mii_select_sync_reg[0]] -datapath_only $src_clk_period
}
set prescale_ffs [get_cells -hier -regexp ".*/rx_prescale_sync_reg\\\[\\d\\\]" -filter "PARENT == $mac_inst"]
set prescale_ffs [get_cells -hier -regexp ".*/rx_prescale_sync_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
if {[llength $prescale_ffs]} {
set_property ASYNC_REG TRUE $prescale_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/rx_prescale_reg[2]/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/rx_prescale_reg[2]/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/rx_prescale_reg[2]] -to [get_cells $mac_inst/rx_prescale_sync_reg[0]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/rx_prescale_reg[2]] -to [get_cells $inst/rx_prescale_sync_reg[0]] -datapath_only $src_clk_period
}
}

View File

@ -20,34 +20,31 @@
# Ethernet MAC with FIFO timing constraints
foreach mac_inst [get_cells -hier -filter {(ORIG_REF_NAME == eth_mac_1g_fifo || REF_NAME == eth_mac_1g_fifo || \
ORIG_REF_NAME == eth_mac_10g_fifo || REF_NAME == eth_mac_10g_fifo || \
ORIG_REF_NAME == eth_mac_1g_gmii_fifo || REF_NAME == eth_mac_1g_gmii_fifo || \
ORIG_REF_NAME == eth_mac_1g_rgmii_fifo || REF_NAME == eth_mac_1g_rgmii_fifo || \
ORIG_REF_NAME == eth_mac_mii_fifo || REF_NAME == eth_mac_mii_fifo)}] {
puts "Inserting timing constraints for ethernet MAC with FIFO instance $mac_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "eth_mac_(10g|1g_(gmii|rgmii)|mii)_fifo(__\w+__\d+)?" ||
REF_NAME =~ "eth_mac_(10g|1g_(gmii|rgmii)|mii)_fifo(__\w+__\d+)?")}] {
puts "Inserting timing constraints for ethernet MAC with FIFO instance $inst"
set sync_ffs [get_cells -hier -regexp ".*/rx_sync_reg_\[1234\]_reg\\\[\\d+\\\]" -filter "PARENT == $mac_inst"]
set sync_ffs [get_cells -hier -regexp ".*/rx_sync_reg_\[1234\]_reg\\\[\\d+\\\]" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/rx_sync_reg_1_reg[*]/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/rx_sync_reg_1_reg[*]/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/rx_sync_reg_1_reg[*]] -to [get_cells $mac_inst/rx_sync_reg_2_reg[*]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/rx_sync_reg_1_reg[*]] -to [get_cells $inst/rx_sync_reg_2_reg[*]] -datapath_only $src_clk_period
}
set sync_ffs [get_cells -hier -regexp ".*/tx_sync_reg_\[1234\]_reg\\\[\\d+\\\]" -filter "PARENT == $mac_inst"]
set sync_ffs [get_cells -hier -regexp ".*/tx_sync_reg_\[1234\]_reg\\\[\\d+\\\]" -filter "PARENT == $inst"]
if {[llength $sync_ffs]} {
set_property ASYNC_REG TRUE $sync_ffs
set src_clk [get_clocks -of_objects [get_pins $mac_inst/tx_sync_reg_1_reg[*]/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/tx_sync_reg_1_reg[*]/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $mac_inst/tx_sync_reg_1_reg[*]] -to [get_cells $mac_inst/tx_sync_reg_2_reg[*]] -datapath_only $src_clk_period
set_max_delay -from [get_cells $inst/tx_sync_reg_1_reg[*]] -to [get_cells $inst/tx_sync_reg_2_reg[*]] -datapath_only $src_clk_period
}
}

View File

@ -20,11 +20,12 @@
# GMII PHY IF timing constraints
foreach if_inst [get_cells -hier -filter {(ORIG_REF_NAME == gmii_phy_if || REF_NAME == gmii_phy_if)}] {
puts "Inserting timing constraints for gmii_phy_if instance $if_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "gmii_phy_if(__\w+__\d+)?" ||
REF_NAME =~ "gmii_phy_if(__\w+__\d+)?")}] {
puts "Inserting timing constraints for gmii_phy_if instance $inst"
# reset synchronization
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $if_inst"]
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
set_property ASYNC_REG TRUE $reset_ffs
set_false_path -to [get_pins -of_objects $reset_ffs -filter {IS_PRESET || IS_RESET}]

View File

@ -20,11 +20,12 @@
# MII PHY IF timing constraints
foreach if_inst [get_cells -hier -filter {(ORIG_REF_NAME == mii_phy_if || REF_NAME == mii_phy_if)}] {
puts "Inserting timing constraints for mii_phy_if instance $if_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "mii_phy_if(__\w+__\d+)?" ||
REF_NAME =~ "mii_phy_if(__\w+__\d+)?")}] {
puts "Inserting timing constraints for mii_phy_if instance $inst"
# reset synchronization
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $if_inst"]
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
set_property ASYNC_REG TRUE $reset_ffs
set_false_path -to [get_pins -of_objects $reset_ffs -filter {IS_PRESET || IS_RESET}]

View File

@ -20,7 +20,8 @@
# PTP timestamp capture module
foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_clock_cdc || REF_NAME == ptp_clock_cdc)}] {
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "ptp_clock_cdc(__\w+__\d+)?" ||
REF_NAME =~ "ptp_clock_cdc(__\w+__\d+)?")}] {
puts "Inserting timing constraints for ptp_clock_cdc instance $inst"
# get clock periods

View File

@ -20,7 +20,8 @@
# PTP time distribution leaf module
foreach inst [get_cells -hier -filter {(ORIG_REF_NAME == ptp_td_leaf || REF_NAME == ptp_td_leaf)}] {
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "ptp_td_leaf(__\w+__\d+)?" ||
REF_NAME =~ "ptp_td_leaf(__\w+__\d+)?")}] {
puts "Inserting timing constraints for ptp_td_leaf instance $inst"
# get clock periods

View File

@ -20,22 +20,23 @@
# RGMII PHY IF timing constraints
foreach if_inst [get_cells -hier -filter {(ORIG_REF_NAME == rgmii_phy_if || REF_NAME == rgmii_phy_if)}] {
puts "Inserting timing constraints for rgmii_phy_if instance $if_inst"
foreach inst [get_cells -hier -regexp -filter {(ORIG_REF_NAME =~ "rgmii_phy_if(__\w+__\d+)?" ||
REF_NAME =~ "rgmii_phy_if(__\w+__\d+)?")}] {
puts "Inserting timing constraints for rgmii_phy_if instance $inst"
# reset synchronization
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $if_inst"]
set reset_ffs [get_cells -hier -regexp ".*/(rx|tx)_rst_reg_reg\\\[\\d\\\]" -filter "PARENT == $inst"]
set_property ASYNC_REG TRUE $reset_ffs
set_false_path -to [get_pins -of_objects $reset_ffs -filter {IS_PRESET || IS_RESET}]
# clock output
set_property ASYNC_REG TRUE [get_cells $if_inst/clk_oddr_inst/oddr[0].oddr_inst]
set_property ASYNC_REG TRUE [get_cells $inst/clk_oddr_inst/oddr[0].oddr_inst]
set src_clk [get_clocks -of_objects [get_pins $if_inst/rgmii_tx_clk_1_reg/C]]
set src_clk [get_clocks -of_objects [get_pins $inst/rgmii_tx_clk_1_reg/C]]
set src_clk_period [if {[llength $src_clk]} {get_property -min PERIOD $src_clk} {expr 8.0}]
set_max_delay -from [get_cells $if_inst/rgmii_tx_clk_1_reg] -to [get_cells $if_inst/clk_oddr_inst/oddr[0].oddr_inst] -datapath_only [expr $src_clk_period/4]
set_max_delay -from [get_cells $if_inst/rgmii_tx_clk_2_reg] -to [get_cells $if_inst/clk_oddr_inst/oddr[0].oddr_inst] -datapath_only [expr $src_clk_period/4]
set_max_delay -from [get_cells $inst/rgmii_tx_clk_1_reg] -to [get_cells $inst/clk_oddr_inst/oddr[0].oddr_inst] -datapath_only [expr $src_clk_period/4]
set_max_delay -from [get_cells $inst/rgmii_tx_clk_2_reg] -to [get_cells $inst/clk_oddr_inst/oddr[0].oddr_inst] -datapath_only [expr $src_clk_period/4]
}

View File

@ -421,6 +421,40 @@ async def run_test(dut):
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Coherent tracking (250 MHz +0/-0.5%)")
tb.set_ptp_clock_period(6.4)
tb.set_clock_period(4.0)
await RisingEdge(dut.clk)
period = 4.000
step = 0.0002
period_min = 4.0
period_max = 4.0*(1+0.005)
for i in range(5000):
period += step
if period <= period_min:
step = abs(step)
if period >= period_max:
step = -abs(step)
tb.set_clock_period(period)
for i in range(20):
await RisingEdge(dut.clk)
assert tb.dut.locked.value.integer
rel_diffs, tod_diffs = await tb.measure_ts_diff()
tb.log.info(f"Difference (rel): {mean(rel_diffs)} ns (stdev: {stdev(rel_diffs)})")
tb.log.info(f"Difference (ToD): {mean(tod_diffs)} ns (stdev: {stdev(tod_diffs)})")
assert abs(mean(rel_diffs)) < 5
assert abs(mean(tod_diffs)) < 5
await RisingEdge(dut.clk)
tb.log.info("Significantly slower (100 MHz)")