fpga: x400: Add support for X410 motherboard FPGA

Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
Wade Fife
2021-06-10 11:56:58 -05:00
committed by Aaron Rossetto
co-authored by Andrew Moch Daniel Jepson Javier Valenzuela Joerg Hofrichter Kumaran Subramoniam Max Köhler Michael Auchter Paul Butler Hector Rubio
parent bfef20ea45
commit 61782b02d7
205 changed files with 299634 additions and 0 deletions
+234
View File
@@ -0,0 +1,234 @@
//
// Copyright 2021 Ettus Research, A National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: model_100gbe
//
// Description:
//
// A wrapper of the 100gbe core to axistream interface. this model can be
// used drive packets into the X400 translated to serial Ethernet. This is
// generally pretty slower than just driving things in at the output of the
// mac.
//
package Pkg100gbMac;
import PkgAxiLite::*;
import PkgAxiLiteBfm::*;
import PkgTestExec::*;
localparam DATA_WIDTH =32;
localparam ADDR_WIDTH =15;
typedef AxiLiteBfm #(DATA_WIDTH, ADDR_WIDTH) MacAxiLiteBfm_t;
// defined in https://www.xilinx.com/support/documentation/ip_documentation/cmac_usplus/v2_4/pg203-cmac-usplus.pdf
// pg 187
localparam CONFIGURATION_TX_REG1 = 32'h000C;
localparam ctl_tx_ctl_enable = 0;
localparam ctl_tx_ctl_tx_send_lfi = 3;
localparam ctl_tx_ctl_tx_send_rfi = 4;
localparam ctl_tx_ctl_tx_send_idle = 5;
localparam ctl_tx_ctl_test_pattern = 16;
localparam CONFIGURATION_RX_REG1 = 32'h0014;
localparam ctl_rx_ctl_enable = 0;
localparam ctl_rx_ctl_rx_force_resync = 7;
localparam ctl_rx_ctl_test_pattern = 8;
localparam RSFEC_CONFIG_INDICATION_CORRECTION = 32'h1000;
localparam rs_fec_in_ctl_rx_rsfec_enable_correction = 0;
localparam rs_fec_in_ctl_rx_rsfec_enable_indication = 1;
localparam rs_fec_in_ctl_rsfec_ieee_error_indication_mode = 2;
localparam RSFEC_CONFIG_ENABLE = 32'h107C;
localparam rs_fec_in_ctl_rx_rsfec_enable = 0;
localparam rs_fec_in_ctl_tx_rsfec_enable = 1;
localparam STAT_RX_STATUS_REG = 32'h0204;
localparam stat_rx_status = 0;
localparam stat_rx_aligned = 1;
localparam stat_rx_misaligned = 2;
localparam stat_rx_aligned_err = 3;
task automatic init_mac (int offset, MacAxiLiteBfm_t axi);
automatic logic [31:0] data;
automatic resp_t resp;
// start transmitting alignment pattern
data = 0;
data[ctl_tx_ctl_enable] = 0;
data[ctl_tx_ctl_tx_send_idle] = 0;
data[ctl_tx_ctl_tx_send_lfi] = 0;
data[ctl_tx_ctl_tx_send_rfi] = 1;
data[ctl_tx_ctl_test_pattern] = 0;
axi.wr(CONFIGURATION_TX_REG1+offset,data);
// configure fec
data = 0;
data[rs_fec_in_ctl_rx_rsfec_enable_correction] = 1;
data[rs_fec_in_ctl_rx_rsfec_enable_indication] = 1;
data[rs_fec_in_ctl_rsfec_ieee_error_indication_mode] = 1;
axi.wr(RSFEC_CONFIG_INDICATION_CORRECTION+offset,data);
data = 0;
data[rs_fec_in_ctl_rx_rsfec_enable] = 1;
data[rs_fec_in_ctl_tx_rsfec_enable] = 1;
axi.wr(RSFEC_CONFIG_ENABLE+offset,data);
// turn on RX interface
data = 0;
data[ctl_rx_ctl_enable] = 1;
data[ctl_rx_ctl_rx_force_resync] = 0;
data[ctl_rx_ctl_test_pattern] = 0;
axi.wr(CONFIGURATION_RX_REG1+offset,data);
do begin
axi.rd_block(STAT_RX_STATUS_REG+offset,data,resp);
assert (resp==OKAY);
end while (data[stat_rx_aligned] !== 1);
// stop transmitting alignment pattern
// and start transmitting data
data = 0;
data[ctl_tx_ctl_enable] = 1;
data[ctl_tx_ctl_tx_send_idle] = 0;
data[ctl_tx_ctl_tx_send_lfi] = 0;
data[ctl_tx_ctl_tx_send_rfi] = 0;
data[ctl_tx_ctl_test_pattern] = 0;
axi.wr(CONFIGURATION_TX_REG1+offset,data);
endtask : init_mac
endpackage : Pkg100gbMac
module model_100gbe (
input logic areset,
// 156.25 Mhz refclk
input logic ref_clk,
// QSFP high-speed IO
output logic [3:0] tx_p,
output logic [3:0] tx_n,
input logic [3:0] rx_p,
input logic [3:0] rx_n,
// CLK and RESET out
output logic mgt_clk,
output logic mgt_rst,
output logic link_up,
// Data port
AxiStreamIf.slave mgt_tx,
AxiStreamIf.master mgt_rx
);
// Include macros and time declarations for use with PkgTestExec
`define TEST_EXEC_OBJ test
`include "test_exec.svh"
import PkgAxiLiteBfm::*;
import PkgTestExec::*;
logic refclk_p;
logic refclk_n;
logic clk40,clk40_rst;
logic clk100,clk100_rst;
logic phy_reset;
assign refclk_p = ref_clk;
assign refclk_n = ~ref_clk;
//interface
AxiLiteIf #(Pkg100gbMac::DATA_WIDTH,Pkg100gbMac::ADDR_WIDTH)
mgt_axil (clk40, clk40_rst);
//bfm
Pkg100gbMac::MacAxiLiteBfm_t axi = new(.master(mgt_axil));
TestExec mac_test = new();
sim_clock_gen #(.PERIOD(25.0), .AUTOSTART(1))
clk40_gen (.clk(clk40), .rst(clk40_rst));
sim_clock_gen #(.PERIOD(100.0), .AUTOSTART(1))
clk100_gen (.clk(clk100), .rst(clk100_rst));
initial begin : init_model
clk40_gen.reset();
axi.run();
wait(!clk40_rst);
repeat (10) @(posedge clk40);
wait(!phy_reset); // both usr_clk's are ok
mac_test.start_test("model_100gbe::Wait for MAC link_up", 150us);
//Added autoconnect - uncomment to test connecting over AXI
//Pkg100gbMac::init_mac(0,axi);
mac_test.end_test();
end
AxiStreamIf #(.DATA_WIDTH(512),.USER_WIDTH(7),.TKEEP(0))
eth100g_rx(mgt_clk,mgt_rst);
always_comb begin
mgt_rx.tdata = eth100g_rx.tdata;
mgt_rx.tuser = eth100g_rx.tuser;
mgt_rx.tkeep = eth100g_rx.trailing2keep(eth100g_rx.tuser);
mgt_rx.tvalid = eth100g_rx.tvalid;
mgt_rx.tlast = eth100g_rx.tlast;
eth100g_rx.tready = mgt_rx.tready;
// The MAC ignores hold off. Data must be consumed every clock it is valid.
if (!mgt_rst) begin
if (!mgt_rx.tready && mgt_rx.tvalid) begin
$error("Model 100Gbe : can't hold off the MAC");
end
end
end
// model does not pause. Users could access this heirarchically to test it
logic mgt_pause_req;
assign mgt_pause_req = 1'b0;
// hold off link up untill the stat_auto_config writes are complete
logic link_up_model;
logic [31:0] mac_status;
always_comb begin
link_up = link_up_model && mac_status[4];
end
eth_100g #(.PAUSE_QUANTA(10),.PAUSE_REFRESH(100)) eth_100gx (
.areset(areset),
//-- Free running 100 MHz clock used for InitClk and AxiLite to mac
//-- 3.125 - 161.132812 MHz.
.clk100(clk100),
// MGT Reference Clock 100/125/156.25/161.1328125 MHz
.refclk_p(refclk_p),
.refclk_n(refclk_n),
// MGT TX/RX differential signals
.tx_p(tx_p),
.tx_n(tx_n),
.rx_p(rx_p),
.rx_n(rx_n),
// 322.26666 Mhz clock generated by 100G Phy from RefClock
.mgt_clk(mgt_clk),
.mgt_rst(mgt_rst),
// pause
.mgt_pause_req(mgt_pause_req),
//------------------------ AXI Stream TX Interface ------------------------
.mgt_tx(mgt_tx),
//---------------------- AXI Stream RX Interface ------------------------
// There is no RxTReady signal support by the Ethernet100G IP. Received data has to
// be read immediately or it is lost.
// tUser indicates an error on rcvd packet
.mgt_rx(eth100g_rx),
.mgt_axil(mgt_axil),
// LEDs of QSFP28 port
.phy_status(),
.mac_ctrl(32'h01000001), // autoconfig / pause mask set to global
.mac_status(mac_status),
.phy_reset(phy_reset),
.link_up(link_up_model)
);
endmodule