cndm: Copy cndm-micro core logic as cndm-lite

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-03-06 21:07:25 -08:00
parent 4a2b9dd10c
commit 2e8f9f8731
8 changed files with 2068 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
cndm_lite_core.sv
cndm_micro_cmd_mbox.sv
cndm_micro_dp_mgr.sv
cndm_micro_port.sv
cndm_micro_rx.sv
cndm_micro_tx.sv
cndm_micro_queue_state.sv
cndm_micro_desc_rd.sv
cndm_micro_cpl_wr.sv
../lib/taxi/src/prim/rtl/taxi_ram_2rw_1c.sv
../lib/taxi/src/dma/rtl/taxi_dma_client_axis_source.sv
../lib/taxi/src/dma/rtl/taxi_dma_client_axis_sink.sv
../lib/taxi/src/dma/rtl/taxi_dma_if_mux.f
../lib/taxi/src/dma/rtl/taxi_dma_psdpram.sv
../lib/taxi/src/apb/rtl/taxi_apb_if.sv
../lib/taxi/src/apb/rtl/taxi_apb_interconnect.sv
../lib/taxi/src/axi/rtl/taxi_axil_interconnect_1s.f
../lib/taxi/src/axis/rtl/taxi_axis_async_fifo_adapter.f
../lib/taxi/src/axis/rtl/taxi_axis_arb_mux.f
../lib/taxi/src/axis/rtl/taxi_axis_demux.sv
../lib/taxi/src/ptp/rtl/taxi_ptp_td_phc_apb.f
../lib/taxi/src/ptp/rtl/taxi_ptp_td_rel2tod.sv

View File

@@ -0,0 +1,563 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2025-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Corundum-lite core logic
*/
module cndm_lite_core #(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtexuplus",
// FW ID
parameter FPGA_ID = 32'hDEADBEEF,
parameter FW_ID = 32'h0000C002,
parameter FW_VER = 32'h000_01_000,
parameter BOARD_ID = 32'h1234_0000,
parameter BOARD_VER = 32'h001_00_000,
parameter BUILD_DATE = 32'd602976000,
parameter GIT_HASH = 32'h5f87c2e8,
parameter RELEASE_INFO = 32'h00000000,
// Structural configuration
parameter PORTS = 2,
// Queue configuration
parameter WQN_W = 5,
parameter CQN_W = WQN_W,
// PTP configuration
parameter logic PTP_TS_EN = 1'b1,
parameter logic PTP_TS_FMT_TOD = 1'b0,
parameter PTP_CLK_PER_NS_NUM = 512,
parameter PTP_CLK_PER_NS_DENOM = 165
)
(
input wire logic clk,
input wire logic rst,
/*
* Control register interface
*/
taxi_axil_if.wr_slv s_axil_ctrl_wr,
taxi_axil_if.rd_slv s_axil_ctrl_rd,
/*
* DMA
*/
taxi_dma_desc_if.req_src dma_rd_desc_req,
taxi_dma_desc_if.sts_snk dma_rd_desc_sts,
taxi_dma_desc_if.req_src dma_wr_desc_req,
taxi_dma_desc_if.sts_snk dma_wr_desc_sts,
taxi_dma_ram_if.wr_slv dma_ram_wr,
taxi_dma_ram_if.rd_slv dma_ram_rd,
output wire logic [PORTS-1:0] irq,
/*
* PTP
*/
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_sample_clk = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
output wire logic ptp_td_sdo,
output wire logic ptp_pps,
output wire logic ptp_pps_str,
output wire logic ptp_sync_locked,
output wire logic [63:0] ptp_sync_ts_rel,
output wire logic ptp_sync_ts_rel_step,
output wire logic [95:0] ptp_sync_ts_tod,
output wire logic ptp_sync_ts_tod_step,
output wire logic ptp_sync_pps,
output wire logic ptp_sync_pps_str,
/*
* Ethernet
*/
input wire logic mac_tx_clk[PORTS],
input wire logic mac_tx_rst[PORTS],
taxi_axis_if.src mac_axis_tx[PORTS],
taxi_axis_if.snk mac_axis_tx_cpl[PORTS],
input wire logic mac_rx_clk[PORTS],
input wire logic mac_rx_rst[PORTS],
taxi_axis_if.snk mac_axis_rx[PORTS]
);
localparam CL_PORTS = $clog2(PORTS);
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
localparam RAM_SEGS = dma_ram_wr.SEGS;
localparam RAM_SEG_ADDR_W = dma_ram_wr.SEG_ADDR_W;
localparam RAM_SEG_DATA_W = dma_ram_wr.SEG_DATA_W;
localparam RAM_SEG_BE_W = dma_ram_wr.SEG_BE_W;
localparam RAM_SEL_W = dma_ram_wr.SEL_W;
localparam PORT_OFFSET_DP = PTP_TS_EN ? 1 : 0;
localparam PORT_OFFSET_HOST = 2;
localparam PORT_BASE_ADDR_DP = PTP_TS_EN ? 32'h00010000 : 32'h00000000;
localparam PORT_BASE_ADDR_HOST = 32'h00020000;
taxi_axil_if #(
.DATA_W(s_axil_ctrl_wr.DATA_W),
.ADDR_W(16),
.STRB_W(s_axil_ctrl_wr.STRB_W),
.AWUSER_EN(s_axil_ctrl_wr.AWUSER_EN),
.AWUSER_W(s_axil_ctrl_wr.AWUSER_W),
.WUSER_EN(s_axil_ctrl_wr.WUSER_EN),
.WUSER_W(s_axil_ctrl_wr.WUSER_W),
.BUSER_EN(s_axil_ctrl_wr.BUSER_EN),
.BUSER_W(s_axil_ctrl_wr.BUSER_W),
.ARUSER_EN(s_axil_ctrl_wr.ARUSER_EN),
.ARUSER_W(s_axil_ctrl_wr.ARUSER_W),
.RUSER_EN(s_axil_ctrl_wr.RUSER_EN),
.RUSER_W(s_axil_ctrl_wr.RUSER_W)
)
axil_ctrl[PORTS+PORT_OFFSET_HOST]();
taxi_axil_interconnect_1s #(
.M_COUNT($size(axil_ctrl)),
.ADDR_W(s_axil_ctrl_wr.ADDR_W),
.M_REGIONS(1),
.M_BASE_ADDR('0),
.M_ADDR_W({$size(axil_ctrl){{1{32'd16}}}}),
.M_SECURE({$size(axil_ctrl){1'b0}})
)
port_intercon_inst (
.clk(clk),
.rst(rst),
/*
* AXI4-lite slave interface
*/
.s_axil_wr(s_axil_ctrl_wr),
.s_axil_rd(s_axil_ctrl_rd),
/*
* AXI4-lite master interfaces
*/
.m_axil_wr(axil_ctrl),
.m_axil_rd(axil_ctrl)
);
logic s_axil_awready_reg = 1'b0;
logic s_axil_wready_reg = 1'b0;
logic s_axil_bvalid_reg = 1'b0;
logic s_axil_arready_reg = 1'b0;
logic [AXIL_DATA_W-1:0] s_axil_rdata_reg = '0;
logic s_axil_rvalid_reg = 1'b0;
assign axil_ctrl[0].awready = s_axil_awready_reg;
assign axil_ctrl[0].wready = s_axil_wready_reg;
assign axil_ctrl[0].bresp = '0;
assign axil_ctrl[0].buser = '0;
assign axil_ctrl[0].bvalid = s_axil_bvalid_reg;
assign axil_ctrl[0].arready = s_axil_arready_reg;
assign axil_ctrl[0].rdata = s_axil_rdata_reg;
assign axil_ctrl[0].rresp = '0;
assign axil_ctrl[0].ruser = '0;
assign axil_ctrl[0].rvalid = s_axil_rvalid_reg;
logic cmd_mbox_start_reg = 1'b0;
wire cmd_mbox_busy;
logic [95:0] get_ptp_ts_tod_reg = '0;
logic [63:0] get_ptp_ts_rel_reg = '0;
always_ff @(posedge clk) begin
s_axil_awready_reg <= 1'b0;
s_axil_wready_reg <= 1'b0;
s_axil_bvalid_reg <= s_axil_bvalid_reg && !axil_ctrl[0].bready;
s_axil_arready_reg <= 1'b0;
s_axil_rvalid_reg <= s_axil_rvalid_reg && !axil_ctrl[0].rready;
cmd_mbox_start_reg <= 1'b0;
if (axil_ctrl[0].awvalid && axil_ctrl[0].wvalid && !s_axil_bvalid_reg) begin
s_axil_awready_reg <= 1'b1;
s_axil_wready_reg <= 1'b1;
s_axil_bvalid_reg <= 1'b1;
case ({axil_ctrl[0].awaddr[15:2], 2'b00})
// 16'h0100: begin
// txq_en_reg <= axil_ctrl[0].wdata[0];
// txq_size_reg <= axil_ctrl[0].wdata[19:16];
// end
// 16'h0104: txq_prod_reg <= axil_ctrl[0].wdata[15:0];
// 16'h0108: txq_base_addr_reg[31:0] <= axil_ctrl[0].wdata;
// 16'h010c: txq_base_addr_reg[63:32] <= axil_ctrl[0].wdata;
16'h0200: begin
cmd_mbox_start_reg <= axil_ctrl[0].wdata[0];
end
default: begin end
endcase
end
if (axil_ctrl[0].arvalid && !s_axil_rvalid_reg) begin
s_axil_rdata_reg <= '0;
s_axil_arready_reg <= 1'b1;
s_axil_rvalid_reg <= 1'b1;
case ({axil_ctrl[0].araddr[15:2], 2'b00})
16'h0100: s_axil_rdata_reg <= PORTS; // port count
16'h0200: begin
s_axil_rdata_reg[0] <= cmd_mbox_busy;
end
16'h0300: s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0}; // PTP cur fns
16'h0304: s_axil_rdata_reg <= ptp_sync_ts_tod[47:16]; // PTP cur ToD ns
16'h0308: s_axil_rdata_reg <= ptp_sync_ts_tod[79:48]; // PTP cur ToD sec l
16'h030C: s_axil_rdata_reg <= 32'(ptp_sync_ts_tod[95:80]); // PTP cur ToD sec h
16'h0310: s_axil_rdata_reg <= ptp_sync_ts_rel[47:16]; // PTP cur rel ns l
16'h0314: s_axil_rdata_reg <= 32'(ptp_sync_ts_rel[63:48]); // PTP cur rel ns h
16'h0318: s_axil_rdata_reg <= '0; // PTP cur PTM l
16'h031C: s_axil_rdata_reg <= '0; // PTP cur PTM h
16'h0320: begin
// PTP snapshot fns
get_ptp_ts_tod_reg <= ptp_sync_ts_tod;
get_ptp_ts_rel_reg <= ptp_sync_ts_rel;
s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0};
end
16'h0324: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[45:16]); // PTP snapshot ToD ns
16'h0328: s_axil_rdata_reg <= get_ptp_ts_tod_reg[79:48]; // PTP snapshot ToD sec l
16'h032C: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[95:80]); // PTP snapshot ToD sec h
16'h0330: s_axil_rdata_reg <= get_ptp_ts_rel_reg[47:16]; // PTP snapshot rel ns l
16'h0334: s_axil_rdata_reg <= 32'(get_ptp_ts_rel_reg[63:48]); // PTP snapshot rel ns h
16'h0338: s_axil_rdata_reg <= '0; // PTP snapshot PTM l
16'h033C: s_axil_rdata_reg <= '0; // PTP snapshot PTM h
default: begin end
endcase
end
if (rst) begin
s_axil_awready_reg <= 1'b0;
s_axil_wready_reg <= 1'b0;
s_axil_bvalid_reg <= 1'b0;
s_axil_arready_reg <= 1'b0;
s_axil_rvalid_reg <= 1'b0;
end
end
// command mailbox
taxi_axis_if #(
.DATA_W(32),
.KEEP_EN(1),
.LAST_EN(1),
.ID_EN(0),
.DEST_EN(0),
.USER_EN(0)
) axis_cmd();
taxi_axis_if #(
.DATA_W(32),
.KEEP_EN(1),
.LAST_EN(1),
.ID_EN(0),
.DEST_EN(0),
.USER_EN(0)
) axis_rsp();
cndm_micro_cmd_mbox
cmd_mbox_inst (
.clk(clk),
.rst(rst),
/*
* AXI lite interface
*/
.s_axil_wr(axil_ctrl[1]),
.s_axil_rd(axil_ctrl[1]),
/*
* Control
*/
.start(cmd_mbox_start_reg),
.busy(cmd_mbox_busy),
/*
* Command interface
*/
.m_axis_cmd(axis_cmd),
.s_axis_rsp(axis_rsp)
);
// datapath manager
localparam APB_DP_ADDR_W = 16+$clog2(PORTS+PORT_OFFSET_DP);
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(APB_DP_ADDR_W)
)
apb_dp_ctrl();
cndm_micro_dp_mgr #(
.PORTS(PORTS),
.WQN_W(WQN_W),
.CQN_W(CQN_W),
.PTP_EN(PTP_TS_EN),
.PTP_BASE_ADDR_DP(0),
.PORT_BASE_ADDR_DP(PORT_BASE_ADDR_DP),
.PORT_BASE_ADDR_HOST(PORT_BASE_ADDR_HOST)
)
dp_mgr_inst (
.clk(clk),
.rst(rst),
/*
* Command interface
*/
.s_axis_cmd(axis_cmd),
.m_axis_rsp(axis_rsp),
/*
* APB master interface (datapath control)
*/
.m_apb_dp_ctrl(apb_dp_ctrl)
);
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(16)
)
apb_port_dp_ctrl[PORT_OFFSET_DP+PORTS]();
taxi_apb_interconnect #(
.M_CNT($size(apb_port_dp_ctrl)),
.ADDR_W(APB_DP_ADDR_W),
.M_REGIONS(1),
.M_BASE_ADDR('0),
.M_ADDR_W({$size(apb_port_dp_ctrl){{1{32'd16}}}}),
.M_SECURE({$size(apb_port_dp_ctrl){1'b0}})
)
port_dp_intercon_inst (
.clk(clk),
.rst(rst),
/*
* APB slave interface
*/
.s_apb(apb_dp_ctrl),
/*
* APB master interfaces
*/
.m_apb(apb_port_dp_ctrl)
);
if (PTP_TS_EN) begin : ptp
taxi_ptp_td_phc_apb #(
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
)
ptp_inst (
.clk(clk),
.rst(rst),
/*
* Control register interface
*/
.s_apb(apb_port_dp_ctrl[0]),
/*
* PTP
*/
.ptp_clk(ptp_clk),
.ptp_rst(ptp_rst),
.ptp_sample_clk(ptp_sample_clk),
.ptp_td_sdo(ptp_td_sdo),
.ptp_pps(ptp_pps),
.ptp_pps_str(ptp_pps_str),
.ptp_sync_locked(ptp_sync_locked),
.ptp_sync_ts_rel(ptp_sync_ts_rel),
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
.ptp_sync_ts_tod(ptp_sync_ts_tod),
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
.ptp_sync_pps(ptp_sync_pps),
.ptp_sync_pps_str(ptp_sync_pps_str)
);
end else begin : ptp
assign ptp_td_sdo = 1'b0;
assign ptp_pps = 1'b0;
assign ptp_pps_str = 1'b0;
assign ptp_sync_locked = 1'b0;
assign ptp_sync_ts_rel = '0;
assign ptp_sync_ts_rel_step = 1'b0;
assign ptp_sync_ts_tod = '0;
assign ptp_sync_ts_tod_step = 1'b0;
assign ptp_sync_pps = 1'b0;
assign ptp_sync_pps_str = 1'b0;
end
taxi_dma_desc_if #(
.SRC_ADDR_W(dma_rd_desc_req.SRC_ADDR_W),
.SRC_SEL_EN(dma_rd_desc_req.SRC_SEL_EN),
.SRC_SEL_W(dma_rd_desc_req.SRC_SEL_W),
.SRC_ASID_EN(dma_rd_desc_req.SRC_ASID_EN),
.DST_ADDR_W(dma_rd_desc_req.DST_ADDR_W),
.DST_SEL_EN(dma_rd_desc_req.DST_SEL_EN),
.DST_SEL_W(dma_rd_desc_req.DST_SEL_W-CL_PORTS),
.DST_ASID_EN(dma_rd_desc_req.DST_ASID_EN),
.IMM_EN(dma_rd_desc_req.IMM_EN),
.LEN_W(dma_rd_desc_req.LEN_W),
.TAG_W(dma_rd_desc_req.TAG_W-CL_PORTS),
.ID_EN(dma_rd_desc_req.ID_EN),
.DEST_EN(dma_rd_desc_req.DEST_EN),
.USER_EN(dma_rd_desc_req.USER_EN)
) dma_rd_desc_int[PORTS]();
taxi_dma_desc_if #(
.SRC_ADDR_W(dma_wr_desc_req.SRC_ADDR_W),
.SRC_SEL_EN(dma_wr_desc_req.SRC_SEL_EN),
.SRC_SEL_W(dma_wr_desc_req.SRC_SEL_W-CL_PORTS),
.SRC_ASID_EN(dma_wr_desc_req.SRC_ASID_EN),
.DST_ADDR_W(dma_wr_desc_req.DST_ADDR_W),
.DST_SEL_EN(dma_wr_desc_req.DST_SEL_EN),
.DST_SEL_W(dma_wr_desc_req.DST_SEL_W),
.DST_ASID_EN(dma_wr_desc_req.DST_ASID_EN),
.IMM_EN(dma_wr_desc_req.IMM_EN),
.IMM_W(dma_wr_desc_req.IMM_W),
.LEN_W(dma_wr_desc_req.LEN_W),
.TAG_W(dma_wr_desc_req.TAG_W-CL_PORTS),
.ID_EN(dma_wr_desc_req.ID_EN),
.DEST_EN(dma_wr_desc_req.DEST_EN),
.USER_EN(dma_wr_desc_req.USER_EN)
) dma_wr_desc_int[PORTS]();
taxi_dma_ram_if #(
.SEGS(RAM_SEGS),
.SEG_ADDR_W(RAM_SEG_ADDR_W),
.SEG_DATA_W(RAM_SEG_DATA_W),
.SEG_BE_W(RAM_SEG_BE_W),
.SEL_W(RAM_SEL_W-CL_PORTS)
) dma_ram_int[PORTS]();
taxi_dma_if_mux #(
.PORTS(PORTS),
.ARB_ROUND_ROBIN(1),
.ARB_LSB_HIGH_PRIO(1)
)
dma_mux_inst (
.clk(clk),
.rst(rst),
/*
* DMA descriptors from clients
*/
.client_rd_req(dma_rd_desc_int),
.client_rd_sts(dma_rd_desc_int),
.client_wr_req(dma_wr_desc_int),
.client_wr_sts(dma_wr_desc_int),
/*
* DMA descriptors to DMA engines
*/
.dma_rd_req(dma_rd_desc_req),
.dma_rd_sts(dma_rd_desc_sts),
.dma_wr_req(dma_wr_desc_req),
.dma_wr_sts(dma_wr_desc_sts),
/*
* RAM interface (from DMA interface)
*/
.dma_ram_wr(dma_ram_wr),
.dma_ram_rd(dma_ram_rd),
/*
* RAM interface (towards RAM)
*/
.client_ram_wr(dma_ram_int),
.client_ram_rd(dma_ram_int)
);
for (genvar p = 0; p < PORTS; p = p + 1) begin : port
cndm_micro_port #(
// Queue configuration
.WQN_W(WQN_W),
.CQN_W(CQN_W),
// PTP configuration
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
)
port_inst (
.clk(clk),
.rst(rst),
/*
* Control register interface
*/
.s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET_HOST+p]),
.s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET_HOST+p]),
/*
* Datapath control register interface
*/
.s_apb_dp_ctrl(apb_port_dp_ctrl[PORT_OFFSET_DP+p]),
/*
* DMA
*/
.dma_rd_desc_req(dma_rd_desc_int[p]),
.dma_rd_desc_sts(dma_rd_desc_int[p]),
.dma_wr_desc_req(dma_wr_desc_int[p]),
.dma_wr_desc_sts(dma_wr_desc_int[p]),
.dma_ram_wr(dma_ram_int[p]),
.dma_ram_rd(dma_ram_int[p]),
.irq(irq[p]),
/*
* PTP
*/
.ptp_clk(ptp_clk),
.ptp_rst(ptp_rst),
.ptp_td_sdi(ptp_td_sdo),
/*
* Ethernet
*/
.mac_tx_clk(mac_tx_clk[p]),
.mac_tx_rst(mac_tx_rst[p]),
.mac_axis_tx(mac_axis_tx[p]),
.mac_axis_tx_cpl(mac_axis_tx_cpl[p]),
.mac_rx_clk(mac_rx_clk[p]),
.mac_rx_rst(mac_rx_rst[p]),
.mac_axis_rx(mac_axis_rx[p])
);
end
endmodule
`resetall

View File

@@ -0,0 +1,6 @@
cndm_lite_pcie_us.sv
cndm_lite_core.f
../lib/taxi/src/pcie/rtl/taxi_pcie_us_axil_master.sv
../lib/taxi/src/pcie/rtl/taxi_pcie_us_msi.sv
../lib/taxi/src/pcie/rtl/taxi_pcie_us_cfg.sv
../lib/taxi/src/dma/rtl/taxi_dma_if_pcie_us.f

View File

@@ -0,0 +1,580 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2025-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Corundum-lite core logic for UltraScale PCIe
*/
module cndm_lite_pcie_us #(
// simulation (set to avoid vendor primitives)
parameter logic SIM = 1'b0,
// vendor ("GENERIC", "XILINX", "ALTERA")
parameter string VENDOR = "XILINX",
// device family
parameter string FAMILY = "virtexuplus",
// FW ID
parameter FPGA_ID = 32'hDEADBEEF,
parameter FW_ID = 32'h0000C002,
parameter FW_VER = 32'h000_01_000,
parameter BOARD_ID = 32'h1234_0000,
parameter BOARD_VER = 32'h001_00_000,
parameter BUILD_DATE = 32'd602976000,
parameter GIT_HASH = 32'h5f87c2e8,
parameter RELEASE_INFO = 32'h00000000,
// Structural configuration
parameter PORTS = 2,
// Queue configuration
parameter CQN_W = 5,
// PTP configuration
parameter logic PTP_TS_EN = 1'b1,
parameter logic PTP_TS_FMT_TOD = 1'b0,
parameter PTP_CLK_PER_NS_NUM = 512,
parameter PTP_CLK_PER_NS_DENOM = 165,
// PCIe interface configuration
parameter RQ_SEQ_NUM_W = 6,
// AXI lite interface configuration (control)
parameter AXIL_CTRL_DATA_W = 32,
parameter AXIL_CTRL_ADDR_W = 24
)
(
/*
* PCIe
*/
input wire logic pcie_clk,
input wire logic pcie_rst,
taxi_axis_if.snk s_axis_pcie_cq,
taxi_axis_if.src m_axis_pcie_cc,
taxi_axis_if.src m_axis_pcie_rq,
taxi_axis_if.snk s_axis_pcie_rc,
input wire logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num0,
input wire logic pcie_rq_seq_num_vld0,
input wire logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num1,
input wire logic pcie_rq_seq_num_vld1,
input wire logic [2:0] cfg_max_payload,
input wire logic [2:0] cfg_max_read_req,
input wire logic [3:0] cfg_rcb_status,
output wire logic [9:0] cfg_mgmt_addr,
output wire logic [7:0] cfg_mgmt_function_number,
output wire logic cfg_mgmt_write,
output wire logic [31:0] cfg_mgmt_write_data,
output wire logic [3:0] cfg_mgmt_byte_enable,
output wire logic cfg_mgmt_read,
input wire logic [31:0] cfg_mgmt_read_data,
input wire logic cfg_mgmt_read_write_done,
input wire logic [7:0] cfg_fc_ph,
input wire logic [11:0] cfg_fc_pd,
input wire logic [7:0] cfg_fc_nph,
input wire logic [11:0] cfg_fc_npd,
input wire logic [7:0] cfg_fc_cplh,
input wire logic [11:0] cfg_fc_cpld,
output wire logic [2:0] cfg_fc_sel,
input wire logic [3:0] cfg_interrupt_msi_enable,
input wire logic [11:0] cfg_interrupt_msi_mmenable,
input wire logic cfg_interrupt_msi_mask_update,
input wire logic [31:0] cfg_interrupt_msi_data,
output wire logic [1:0] cfg_interrupt_msi_select,
output wire logic [31:0] cfg_interrupt_msi_int,
output wire logic [31:0] cfg_interrupt_msi_pending_status,
output wire logic cfg_interrupt_msi_pending_status_data_enable,
output wire logic [1:0] cfg_interrupt_msi_pending_status_function_num,
input wire logic cfg_interrupt_msi_sent,
input wire logic cfg_interrupt_msi_fail,
output wire logic [2:0] cfg_interrupt_msi_attr,
output wire logic cfg_interrupt_msi_tph_present,
output wire logic [1:0] cfg_interrupt_msi_tph_type,
output wire logic [7:0] cfg_interrupt_msi_tph_st_tag,
output wire logic [7:0] cfg_interrupt_msi_function_number,
/*
* PTP
*/
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_sample_clk = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
output wire logic ptp_td_sdo,
output wire logic ptp_pps,
output wire logic ptp_pps_str,
output wire logic ptp_sync_locked,
output wire logic [63:0] ptp_sync_ts_rel,
output wire logic ptp_sync_ts_rel_step,
output wire logic [95:0] ptp_sync_ts_tod,
output wire logic ptp_sync_ts_tod_step,
output wire logic ptp_sync_pps,
output wire logic ptp_sync_pps_str,
/*
* Ethernet
*/
input wire logic mac_tx_clk[PORTS],
input wire logic mac_tx_rst[PORTS],
taxi_axis_if.src mac_axis_tx[PORTS],
taxi_axis_if.snk mac_axis_tx_cpl[PORTS],
input wire logic mac_rx_clk[PORTS],
input wire logic mac_rx_rst[PORTS],
taxi_axis_if.snk mac_axis_rx[PORTS]
);
localparam CL_PORTS = $clog2(PORTS);
taxi_axil_if #(
.DATA_W(AXIL_CTRL_DATA_W),
.ADDR_W(AXIL_CTRL_ADDR_W),
.AWUSER_EN(1'b0),
.WUSER_EN(1'b0),
.BUSER_EN(1'b0),
.ARUSER_EN(1'b0),
.RUSER_EN(1'b0)
) axil_ctrl_bar();
taxi_pcie_us_axil_master
pcie_axil_master_inst (
.clk(pcie_clk),
.rst(pcie_rst),
/*
* UltraScale PCIe interface
*/
.s_axis_cq(s_axis_pcie_cq),
.m_axis_cc(m_axis_pcie_cc),
/*
* AXI Lite Master output
*/
.m_axil_wr(axil_ctrl_bar),
.m_axil_rd(axil_ctrl_bar),
/*
* Configuration
*/
.completer_id('0),
.completer_id_en(1'b0),
/*
* Status
*/
.stat_err_cor(),
.stat_err_uncor()
);
localparam AXIS_PCIE_DATA_W = m_axis_pcie_rq.DATA_W;
localparam PCIE_ADDR_W = 64;
// TODO
localparam logic RQ_SEQ_NUM_EN = 1'b1;
localparam RAM_SEL_W = 2+CL_PORTS;
localparam RAM_ADDR_W = 16;
localparam RAM_SEGS = 2;//AXIS_PCIE_DATA_W > 256 ? AXIS_PCIE_DATA_W / 128 : 2;
localparam PCIE_TAG_CNT = 64;//AXIS_PCIE_RQ_USER_W == 60 ? 64 : 256,
localparam logic IMM_EN = 1'b0;
localparam IMM_W = 32;
localparam LEN_W = 20;
localparam TAG_W = 8;
localparam RD_OP_TBL_SIZE = PCIE_TAG_CNT;
localparam RD_TX_LIMIT = 2**(RQ_SEQ_NUM_W-1);
localparam logic RD_TX_FC_EN = 1'b1;
localparam RD_CPLH_FC_LIMIT = 512;
localparam RD_CPLD_FC_LIMIT = RD_CPLH_FC_LIMIT*4;
localparam WR_OP_TBL_SIZE = 2**(RQ_SEQ_NUM_W-1);
localparam WR_TX_LIMIT = 2**(RQ_SEQ_NUM_W-1);
localparam logic WR_TX_FC_EN = 1'b1;
localparam RAM_DATA_W = AXIS_PCIE_DATA_W*2;
localparam RAM_SEG_DATA_W = RAM_DATA_W / RAM_SEGS;
localparam RAM_SEG_BE_W = RAM_SEG_DATA_W / 8;
localparam RAM_SEG_ADDR_W = RAM_ADDR_W - $clog2(RAM_SEGS*RAM_SEG_BE_W);
logic [RQ_SEQ_NUM_W-1:0] s_axis_rq_seq_num_0;
logic s_axis_rq_seq_num_valid_0;
logic [RQ_SEQ_NUM_W-1:0] s_axis_rq_seq_num_1;
logic s_axis_rq_seq_num_valid_1;
logic [7:0] pcie_tx_fc_nph_av;
logic [7:0] pcie_tx_fc_ph_av;
logic [11:0] pcie_tx_fc_pd_av;
logic ext_tag_en;
assign cfg_fc_sel = 3'b100;
taxi_dma_desc_if #(
.SRC_ADDR_W(PCIE_ADDR_W),
.SRC_SEL_EN(1'b0),
.SRC_ASID_EN(1'b0),
.DST_ADDR_W(RAM_ADDR_W),
.DST_SEL_EN(1'b1),
.DST_SEL_W(RAM_SEL_W),
.DST_ASID_EN(1'b0),
.IMM_EN(1'b0),
.LEN_W(LEN_W),
.TAG_W(TAG_W),
.ID_EN(1'b0),
.DEST_EN(1'b0),
.USER_EN(1'b0)
) dma_rd_desc();
taxi_dma_desc_if #(
.SRC_ADDR_W(RAM_ADDR_W),
.SRC_SEL_EN(1'b1),
.SRC_SEL_W(RAM_SEL_W),
.SRC_ASID_EN(1'b0),
.DST_ADDR_W(PCIE_ADDR_W),
.DST_SEL_EN(1'b0),
.DST_ASID_EN(1'b0),
.IMM_EN(IMM_EN),
.IMM_W(IMM_W),
.LEN_W(LEN_W),
.TAG_W(TAG_W),
.ID_EN(1'b0),
.DEST_EN(1'b0),
.USER_EN(1'b0)
) dma_wr_desc();
taxi_dma_ram_if #(
.SEGS(RAM_SEGS),
.SEG_ADDR_W(RAM_SEG_ADDR_W),
.SEG_DATA_W(RAM_SEG_DATA_W),
.SEG_BE_W(RAM_SEG_BE_W),
.SEL_W(RAM_SEL_W)
) dma_ram();
logic stat_rd_busy;
logic stat_wr_busy;
logic stat_err_cor;
logic stat_err_uncor;
logic [$clog2(RD_OP_TBL_SIZE)-1:0] stat_rd_op_start_tag;
logic stat_rd_op_start_valid;
logic [$clog2(RD_OP_TBL_SIZE)-1:0] stat_rd_op_finish_tag;
logic [3:0] stat_rd_op_finish_status;
logic stat_rd_op_finish_valid;
logic [$clog2(PCIE_TAG_CNT)-1:0] stat_rd_req_start_tag;
logic [12:0] stat_rd_req_start_len;
logic stat_rd_req_start_valid;
logic [$clog2(PCIE_TAG_CNT)-1:0] stat_rd_req_finish_tag;
logic [3:0] stat_rd_req_finish_status;
logic stat_rd_req_finish_valid;
logic stat_rd_req_timeout;
logic stat_rd_op_tbl_full;
logic stat_rd_no_tags;
logic stat_rd_tx_limit;
logic stat_rd_tx_stall;
logic [$clog2(WR_OP_TBL_SIZE)-1:0] stat_wr_op_start_tag;
logic stat_wr_op_start_valid;
logic [$clog2(WR_OP_TBL_SIZE)-1:0] stat_wr_op_finish_tag;
logic [3:0] stat_wr_op_finish_status;
logic stat_wr_op_finish_valid;
logic [$clog2(WR_OP_TBL_SIZE)-1:0] stat_wr_req_start_tag;
logic [12:0] stat_wr_req_start_len;
logic stat_wr_req_start_valid;
logic [$clog2(WR_OP_TBL_SIZE)-1:0] stat_wr_req_finish_tag;
logic [3:0] stat_wr_req_finish_status;
logic stat_wr_req_finish_valid;
logic stat_wr_op_tbl_full;
logic stat_wr_tx_limit;
logic stat_wr_tx_stall;
// register to break timing path from PCIe HIP 500 MHz clock domain
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num0_reg = '0;
logic pcie_rq_seq_num_vld0_reg = 1'b0;
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num1_reg = '0;
logic pcie_rq_seq_num_vld1_reg = 1'b0;
always_ff @(posedge pcie_clk) begin
pcie_rq_seq_num0_reg <= pcie_rq_seq_num0;
pcie_rq_seq_num_vld0_reg <= pcie_rq_seq_num_vld0;
pcie_rq_seq_num1_reg <= pcie_rq_seq_num1;
pcie_rq_seq_num_vld1_reg <= pcie_rq_seq_num_vld1;
if (pcie_rst) begin
pcie_rq_seq_num_vld0_reg <= 1'b0;
pcie_rq_seq_num_vld1_reg <= 1'b0;
end
end
taxi_dma_if_pcie_us #(
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
.RQ_SEQ_NUM_EN(RQ_SEQ_NUM_EN),
.PCIE_TAG_CNT(PCIE_TAG_CNT),
.RD_OP_TBL_SIZE(RD_OP_TBL_SIZE),
.RD_TX_LIMIT(RD_TX_LIMIT),
.RD_TX_FC_EN(RD_TX_FC_EN),
.RD_CPLH_FC_LIMIT(RD_CPLH_FC_LIMIT),
.RD_CPLD_FC_LIMIT(RD_CPLD_FC_LIMIT),
.WR_OP_TBL_SIZE(WR_OP_TBL_SIZE),
.WR_TX_LIMIT(WR_TX_LIMIT),
.WR_TX_FC_EN(WR_TX_FC_EN)
)
dma_if_inst (
.clk(pcie_clk),
.rst(pcie_rst),
/*
* UltraScale PCIe interface
*/
.m_axis_rq(m_axis_pcie_rq),
.s_axis_rc(s_axis_pcie_rc),
/*
* Transmit sequence number input
*/
.s_axis_rq_seq_num_0(pcie_rq_seq_num0_reg),
.s_axis_rq_seq_num_valid_0(pcie_rq_seq_num_vld0_reg),
.s_axis_rq_seq_num_1(pcie_rq_seq_num1_reg),
.s_axis_rq_seq_num_valid_1(pcie_rq_seq_num_vld1_reg),
/*
* Transmit flow control
*/
.pcie_tx_fc_nph_av(cfg_fc_nph),
.pcie_tx_fc_ph_av(cfg_fc_ph),
.pcie_tx_fc_pd_av(cfg_fc_pd),
/*
* Read descriptor
*/
.rd_desc_req(dma_rd_desc),
.rd_desc_sts(dma_rd_desc),
/*
* Write descriptor
*/
.wr_desc_req(dma_wr_desc),
.wr_desc_sts(dma_wr_desc),
/*
* RAM interface
*/
.dma_ram_wr(dma_ram),
.dma_ram_rd(dma_ram),
/*
* Configuration
*/
.read_enable(1'b1),
.write_enable(1'b1),
.ext_tag_en(ext_tag_en),
.rcb_128b(cfg_rcb_status[0]),
.requester_id('0),
.requester_id_en(1'b0),
.max_rd_req_size(cfg_max_read_req),
.max_payload_size(cfg_max_payload),
/*
* Status
*/
.stat_rd_busy(stat_rd_busy),
.stat_wr_busy(stat_wr_busy),
.stat_err_cor(stat_err_cor),
.stat_err_uncor(stat_err_uncor),
/*
* Statistics
*/
.stat_rd_op_start_tag(stat_rd_op_start_tag),
.stat_rd_op_start_valid(stat_rd_op_start_valid),
.stat_rd_op_finish_tag(stat_rd_op_finish_tag),
.stat_rd_op_finish_status(stat_rd_op_finish_status),
.stat_rd_op_finish_valid(stat_rd_op_finish_valid),
.stat_rd_req_start_tag(stat_rd_req_start_tag),
.stat_rd_req_start_len(stat_rd_req_start_len),
.stat_rd_req_start_valid(stat_rd_req_start_valid),
.stat_rd_req_finish_tag(stat_rd_req_finish_tag),
.stat_rd_req_finish_status(stat_rd_req_finish_status),
.stat_rd_req_finish_valid(stat_rd_req_finish_valid),
.stat_rd_req_timeout(stat_rd_req_timeout),
.stat_rd_op_tbl_full(stat_rd_op_tbl_full),
.stat_rd_no_tags(stat_rd_no_tags),
.stat_rd_tx_limit(stat_rd_tx_limit),
.stat_rd_tx_stall(stat_rd_tx_stall),
.stat_wr_op_start_tag(stat_wr_op_start_tag),
.stat_wr_op_start_valid(stat_wr_op_start_valid),
.stat_wr_op_finish_tag(stat_wr_op_finish_tag),
.stat_wr_op_finish_status(stat_wr_op_finish_status),
.stat_wr_op_finish_valid(stat_wr_op_finish_valid),
.stat_wr_req_start_tag(stat_wr_req_start_tag),
.stat_wr_req_start_len(stat_wr_req_start_len),
.stat_wr_req_start_valid(stat_wr_req_start_valid),
.stat_wr_req_finish_tag(stat_wr_req_finish_tag),
.stat_wr_req_finish_status(stat_wr_req_finish_status),
.stat_wr_req_finish_valid(stat_wr_req_finish_valid),
.stat_wr_op_tbl_full(stat_wr_op_tbl_full),
.stat_wr_tx_limit(stat_wr_tx_limit),
.stat_wr_tx_stall(stat_wr_tx_stall)
);
taxi_pcie_us_cfg #(
.PF_COUNT(1),
.VF_COUNT(0),
.VF_OFFSET(m_axis_pcie_rq.USER_W == 60 ? 64 : 4),
.PCIE_CAP_OFFSET(m_axis_pcie_rq.USER_W == 60 ? 12'h0C0 : 12'h070)
)
cfg_inst (
.clk(pcie_clk),
.rst(pcie_rst),
/*
* Configuration outputs
*/
.ext_tag_en(ext_tag_en),
.max_read_req_size(),
.max_payload_size(),
/*
* Interface to Ultrascale PCIe IP core
*/
.cfg_mgmt_addr(cfg_mgmt_addr),
.cfg_mgmt_function_number(cfg_mgmt_function_number),
.cfg_mgmt_write(cfg_mgmt_write),
.cfg_mgmt_write_data(cfg_mgmt_write_data),
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
.cfg_mgmt_read(cfg_mgmt_read),
.cfg_mgmt_read_data(cfg_mgmt_read_data),
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done)
);
wire [PORTS-1:0] irq;
wire [31:0] msi_irq = 32'(irq);
taxi_pcie_us_msi #(
.MSI_CNT(32)
)
msi_inst (
.clk(pcie_clk),
.rst(pcie_rst),
/*
* Interrupt request inputs
*/
.msi_irq(msi_irq),
/*
* Interface to UltraScale PCIe IP core
*/
/* verilator lint_off WIDTHEXPAND */
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
.cfg_interrupt_msi_vf_enable(),
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number)
/* verilator lint_on WIDTHEXPAND */
);
cndm_lite_core #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
// FW ID
.FPGA_ID(FPGA_ID),
.FW_ID(FW_ID),
.FW_VER(FW_VER),
.BOARD_ID(BOARD_ID),
.BOARD_VER(BOARD_VER),
.BUILD_DATE(BUILD_DATE),
.GIT_HASH(GIT_HASH),
.RELEASE_INFO(RELEASE_INFO),
// Structural configuration
.PORTS(PORTS),
// Queue configuration
.CQN_W(CQN_W),
// PTP configuration
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
)
core_inst (
.clk(pcie_clk),
.rst(pcie_rst),
/*
* Control register interface
*/
.s_axil_ctrl_wr(axil_ctrl_bar),
.s_axil_ctrl_rd(axil_ctrl_bar),
/*
* DMA
*/
.dma_rd_desc_req(dma_rd_desc),
.dma_rd_desc_sts(dma_rd_desc),
.dma_wr_desc_req(dma_wr_desc),
.dma_wr_desc_sts(dma_wr_desc),
.dma_ram_wr(dma_ram),
.dma_ram_rd(dma_ram),
.irq(irq),
/*
* PTP
*/
.ptp_clk(ptp_clk),
.ptp_rst(ptp_rst),
.ptp_sample_clk(ptp_sample_clk),
.ptp_td_sdi(ptp_td_sdi),
.ptp_td_sdo(ptp_td_sdo),
.ptp_pps(ptp_pps),
.ptp_pps_str(ptp_pps_str),
.ptp_sync_locked(ptp_sync_locked),
.ptp_sync_ts_rel(ptp_sync_ts_rel),
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
.ptp_sync_ts_tod(ptp_sync_ts_tod),
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
.ptp_sync_pps(ptp_sync_pps),
.ptp_sync_pps_str(ptp_sync_pps_str),
/*
* Ethernet
*/
.mac_tx_clk(mac_tx_clk),
.mac_tx_rst(mac_tx_rst),
.mac_axis_tx(mac_axis_tx),
.mac_axis_tx_cpl(mac_axis_tx_cpl),
.mac_rx_clk(mac_rx_clk),
.mac_rx_rst(mac_rx_rst),
.mac_axis_rx(mac_axis_rx)
);
endmodule
`resetall

View File

@@ -0,0 +1,71 @@
# SPDX-License-Identifier: CERN-OHL-S-2.0
#
# Copyright (c) 2020-2026 FPGA Ninja, LLC
#
# Authors:
# - Alex Forencich
TOPLEVEL_LANG = verilog
SIM ?= verilator
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
RTL_DIR = ../../rtl
LIB_DIR = ../../lib
TAXI_SRC_DIR = $(LIB_DIR)/taxi/src
DUT = cndm_lite_pcie_us
COCOTB_TEST_MODULES = test_$(DUT)
COCOTB_TOPLEVEL = test_$(DUT)
MODULE = $(COCOTB_TEST_MODULES)
TOPLEVEL = $(COCOTB_TOPLEVEL)
VERILOG_SOURCES += $(COCOTB_TOPLEVEL).sv
VERILOG_SOURCES += $(RTL_DIR)/$(DUT).f
# handle file list files
process_f_file = $(call process_f_files,$(addprefix $(dir $1),$(shell cat $1)))
process_f_files = $(foreach f,$1,$(if $(filter %.f,$f),$(call process_f_file,$f),$f))
uniq_base = $(if $1,$(call uniq_base,$(foreach f,$1,$(if $(filter-out $(notdir $(lastword $1)),$(notdir $f)),$f,))) $(lastword $1))
VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
# module parameters
export PARAM_SIM := "1'b1"
export PARAM_VENDOR := "\"XILINX\""
export PARAM_FAMILY := "\"virtexuplus\""
# Structural configuration
export PARAM_PORTS := 2
# PTP configuration
export PARAM_PTP_TS_EN := 1
export PARAM_PTP_TS_FMT_TOD := 0
export PARAM_PTP_CLK_PER_NS_NUM := 512
export PARAM_PTP_CLK_PER_NS_DENOM := 165
# PCIe interface configuration
export PARAM_AXIS_PCIE_DATA_W := 512
# AXI lite interface configuration (control)
export PARAM_AXIL_CTRL_DATA_W := 32
export PARAM_AXIL_CTRL_ADDR_W := 24
# MAC configuration
export PARAM_MAC_DATA_W := 512
ifeq ($(SIM), icarus)
PLUSARGS += -fst
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-P $(COCOTB_TOPLEVEL).$(subst PARAM_,,$(v))=$($(v)))
else ifeq ($(SIM), verilator)
COMPILE_ARGS += $(foreach v,$(filter PARAM_%,$(.VARIABLES)),-G$(subst PARAM_,,$(v))=$($(v)))
ifeq ($(WAVES), 1)
COMPILE_ARGS += --trace-fst
VERILATOR_TRACE = 1
endif
endif
include $(shell cocotb-config --makefiles)/Makefile.sim

View File

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

View File

@@ -0,0 +1,516 @@
#!/usr/bin/env python
# SPDX-License-Identifier: CERN-OHL-S-2.0
"""
Copyright (c) 2020-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
"""
import logging
import os
import sys
import pytest
import cocotb_test.simulator
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge, FallingEdge, Timer
from cocotbext.axi import AxiStreamBus
from cocotbext.eth import EthMac
from cocotbext.pcie.core import RootComplex
from cocotbext.pcie.xilinx.us import UltraScalePlusPcieDevice
try:
import cndm
except ImportError:
# attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try:
import cndm
finally:
del sys.path[0]
class TB:
def __init__(self, dut):
self.dut = dut
self.log = logging.getLogger("cocotb.tb")
self.log.setLevel(logging.DEBUG)
# PCIe
self.rc = RootComplex()
self.rc.max_payload_size = 0x1 # 256 bytes
self.rc.max_read_request_size = 0x2 # 512 bytes
self.dev = UltraScalePlusPcieDevice(
# configuration options
pcie_generation=3,
#pcie_link_width=16,
user_clk_frequency=250e6,
alignment="dword",
cq_straddle=False,
cc_straddle=False,
rq_straddle=False,
rc_straddle=False,
rc_4tlp_straddle=False,
pf_count=1,
max_payload_size=1024,
enable_client_tag=True,
enable_extended_tag=True,
enable_parity=False,
enable_rx_msg_interface=False,
enable_sriov=False,
enable_extended_configuration=False,
pf0_msi_enable=True,
pf0_msi_count=32,
pf1_msi_enable=False,
pf1_msi_count=1,
pf2_msi_enable=False,
pf2_msi_count=1,
pf3_msi_enable=False,
pf3_msi_count=1,
pf0_msix_enable=False,
pf0_msix_table_size=31,
pf0_msix_table_bir=4,
pf0_msix_table_offset=0x00000000,
pf0_msix_pba_bir=4,
pf0_msix_pba_offset=0x00008000,
pf1_msix_enable=False,
pf1_msix_table_size=0,
pf1_msix_table_bir=0,
pf1_msix_table_offset=0x00000000,
pf1_msix_pba_bir=0,
pf1_msix_pba_offset=0x00000000,
pf2_msix_enable=False,
pf2_msix_table_size=0,
pf2_msix_table_bir=0,
pf2_msix_table_offset=0x00000000,
pf2_msix_pba_bir=0,
pf2_msix_pba_offset=0x00000000,
pf3_msix_enable=False,
pf3_msix_table_size=0,
pf3_msix_table_bir=0,
pf3_msix_table_offset=0x00000000,
pf3_msix_pba_bir=0,
pf3_msix_pba_offset=0x00000000,
# signals
# Clock and Reset Interface
user_clk=dut.pcie_clk,
user_reset=dut.pcie_rst,
# user_lnk_up
# sys_clk
# sys_clk_gt
# sys_reset
# phy_rdy_out
# Requester reQuest Interface
rq_bus=AxiStreamBus.from_entity(dut.m_axis_pcie_rq),
pcie_rq_seq_num0=dut.pcie_rq_seq_num0,
pcie_rq_seq_num_vld0=dut.pcie_rq_seq_num_vld0,
pcie_rq_seq_num1=dut.pcie_rq_seq_num1,
pcie_rq_seq_num_vld1=dut.pcie_rq_seq_num_vld1,
# pcie_rq_tag0
# pcie_rq_tag1
# pcie_rq_tag_av
# pcie_rq_tag_vld0
# pcie_rq_tag_vld1
# Requester Completion Interface
rc_bus=AxiStreamBus.from_entity(dut.s_axis_pcie_rc),
# Completer reQuest Interface
cq_bus=AxiStreamBus.from_entity(dut.s_axis_pcie_cq),
# pcie_cq_np_req
# pcie_cq_np_req_count
# Completer Completion Interface
cc_bus=AxiStreamBus.from_entity(dut.m_axis_pcie_cc),
# Transmit Flow Control Interface
# pcie_tfc_nph_av=dut.pcie_tfc_nph_av,
# pcie_tfc_npd_av=dut.pcie_tfc_npd_av,
# Configuration Management Interface
cfg_mgmt_addr=dut.cfg_mgmt_addr,
cfg_mgmt_function_number=dut.cfg_mgmt_function_number,
cfg_mgmt_write=dut.cfg_mgmt_write,
cfg_mgmt_write_data=dut.cfg_mgmt_write_data,
cfg_mgmt_byte_enable=dut.cfg_mgmt_byte_enable,
cfg_mgmt_read=dut.cfg_mgmt_read,
cfg_mgmt_read_data=dut.cfg_mgmt_read_data,
cfg_mgmt_read_write_done=dut.cfg_mgmt_read_write_done,
# cfg_mgmt_debug_access
# Configuration Status Interface
# cfg_phy_link_down
# cfg_phy_link_status
# cfg_negotiated_width
# cfg_current_speed
# cfg_max_payload=dut.cfg_max_payload,
# cfg_max_read_req=dut.cfg_max_read_req,
# cfg_function_status
# cfg_vf_status
# cfg_function_power_state
# cfg_vf_power_state
# cfg_link_power_state
# cfg_err_cor_out
# cfg_err_nonfatal_out
# cfg_err_fatal_out
# cfg_local_error_out
# cfg_local_error_valid
# cfg_rx_pm_state
# cfg_tx_pm_state
# cfg_ltssm_state
# cfg_rcb_status=dut.cfg_rcb_status,
# cfg_obff_enable
# cfg_pl_status_change
# cfg_tph_requester_enable
# cfg_tph_st_mode
# cfg_vf_tph_requester_enable
# cfg_vf_tph_st_mode
# Configuration Received Message Interface
# cfg_msg_received
# cfg_msg_received_data
# cfg_msg_received_type
# Configuration Transmit Message Interface
# cfg_msg_transmit
# cfg_msg_transmit_type
# cfg_msg_transmit_data
# cfg_msg_transmit_done
# Configuration Flow Control Interface
cfg_fc_ph=dut.cfg_fc_ph,
cfg_fc_pd=dut.cfg_fc_pd,
cfg_fc_nph=dut.cfg_fc_nph,
cfg_fc_npd=dut.cfg_fc_npd,
cfg_fc_cplh=dut.cfg_fc_cplh,
cfg_fc_cpld=dut.cfg_fc_cpld,
cfg_fc_sel=dut.cfg_fc_sel,
# Configuration Control Interface
# cfg_hot_reset_in
# cfg_hot_reset_out
# cfg_config_space_enable
# cfg_dsn
# cfg_bus_number
# cfg_ds_port_number
# cfg_ds_bus_number
# cfg_ds_device_number
# cfg_ds_function_number
# cfg_power_state_change_ack
# cfg_power_state_change_interrupt
# cfg_err_cor_in=dut.status_error_cor,
# cfg_err_uncor_in=dut.status_error_uncor,
# cfg_flr_in_process
# cfg_flr_done
# cfg_vf_flr_in_process
# cfg_vf_flr_func_num
# cfg_vf_flr_done
# cfg_pm_aspm_l1_entry_reject
# cfg_pm_aspm_tx_l0s_entry_disable
# cfg_req_pm_transition_l23_ready
# cfg_link_training_enable
# Configuration Interrupt Controller Interface
# cfg_interrupt_int
# cfg_interrupt_sent
# cfg_interrupt_pending
cfg_interrupt_msi_enable=dut.cfg_interrupt_msi_enable,
cfg_interrupt_msi_mmenable=dut.cfg_interrupt_msi_mmenable,
cfg_interrupt_msi_mask_update=dut.cfg_interrupt_msi_mask_update,
cfg_interrupt_msi_data=dut.cfg_interrupt_msi_data,
cfg_interrupt_msi_select=dut.cfg_interrupt_msi_select,
cfg_interrupt_msi_int=dut.cfg_interrupt_msi_int,
cfg_interrupt_msi_pending_status=dut.cfg_interrupt_msi_pending_status,
cfg_interrupt_msi_pending_status_data_enable=dut.cfg_interrupt_msi_pending_status_data_enable,
cfg_interrupt_msi_pending_status_function_num=dut.cfg_interrupt_msi_pending_status_function_num,
cfg_interrupt_msi_sent=dut.cfg_interrupt_msi_sent,
cfg_interrupt_msi_fail=dut.cfg_interrupt_msi_fail,
# cfg_interrupt_msix_enable=dut.cfg_interrupt_msix_enable,
# cfg_interrupt_msix_mask=dut.cfg_interrupt_msix_mask,
# cfg_interrupt_msix_vf_enable=dut.cfg_interrupt_msix_vf_enable,
# cfg_interrupt_msix_vf_mask=dut.cfg_interrupt_msix_vf_mask,
# cfg_interrupt_msix_address=dut.cfg_interrupt_msix_address,
# cfg_interrupt_msix_data=dut.cfg_interrupt_msix_data,
# cfg_interrupt_msix_int=dut.cfg_interrupt_msix_int,
# cfg_interrupt_msix_vec_pending=dut.cfg_interrupt_msix_vec_pending,
# cfg_interrupt_msix_vec_pending_status=dut.cfg_interrupt_msix_vec_pending_status,
# cfg_interrupt_msix_sent=dut.cfg_interrupt_msix_sent,
# cfg_interrupt_msix_fail=dut.cfg_interrupt_msix_fail,
cfg_interrupt_msi_attr=dut.cfg_interrupt_msi_attr,
cfg_interrupt_msi_tph_present=dut.cfg_interrupt_msi_tph_present,
cfg_interrupt_msi_tph_type=dut.cfg_interrupt_msi_tph_type,
cfg_interrupt_msi_tph_st_tag=dut.cfg_interrupt_msi_tph_st_tag,
cfg_interrupt_msi_function_number=dut.cfg_interrupt_msi_function_number,
# Configuration Extend Interface
# cfg_ext_read_received
# cfg_ext_write_received
# cfg_ext_register_number
# cfg_ext_function_number
# cfg_ext_write_data
# cfg_ext_write_byte_enable
# cfg_ext_read_data
# cfg_ext_read_data_valid
)
# self.dev.log.setLevel(logging.DEBUG)
self.rc.make_port().connect(self.dev)
self.dev.functions[0].configure_bar(0, 2**int(dut.uut.axil_ctrl_bar.ADDR_W))
# PTP
cocotb.start_soon(Clock(dut.ptp_clk, 3.102, units="ns").start())
cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start())
# Ethernet
self.port_mac = []
if len(dut.mac_axis_tx[0].tdata) == 512:
# assuming US+ 100G CMAC, 512 bits at 322.265625 MHz
eth_clock_period = 3.102
eth_speed = 100e9
elif len(dut.mac_axis_tx[0].tdata) == 64:
# assuming 25G MAC in low-latency mode, 64 bits at 402.83203125 MHz
eth_clock_period = 2.482
eth_speed = 25e9
else:
# assuming 25G MAC in low-latency mode, 512 bits at 322.265625 MHz
eth_clock_period = 3.102
eth_speed = 10e9
for k in range(len(dut.mac_axis_tx)):
cocotb.start_soon(Clock(dut.mac_tx_clk[k], eth_clock_period, units="ns").start())
cocotb.start_soon(Clock(dut.mac_rx_clk[k], eth_clock_period, units="ns").start())
dut.mac_tx_rst[k].setimmediatevalue(0)
dut.mac_rx_rst[k].setimmediatevalue(0)
mac = EthMac(
tx_clk=dut.mac_tx_clk[k],
tx_rst=dut.mac_tx_rst[k],
tx_bus=AxiStreamBus.from_entity(dut.mac_axis_tx[k]),
rx_clk=dut.mac_rx_clk[k],
rx_rst=dut.mac_rx_rst[k],
rx_bus=AxiStreamBus.from_entity(dut.mac_axis_rx[k]),
tx_ptp_time=dut.mac_axis_tx[k].tid, # TODO
tx_ptp_ts=dut.mac_axis_tx_cpl[k].tdata, # TODO
tx_ptp_ts_valid=dut.mac_axis_tx_cpl[k].tvalid, # TODO
ifg=12, speed=eth_speed
)
self.port_mac.append(mac)
self.loopback_enable = False
cocotb.start_soon(self._run_loopback())
async def init(self):
self.dut.ptp_rst.setimmediatevalue(0)
for mac in self.port_mac:
mac.rx.reset.setimmediatevalue(0)
mac.tx.reset.setimmediatevalue(0)
await FallingEdge(self.dut.pcie_rst)
await Timer(100, 'ns')
for k in range(10):
await RisingEdge(self.dut.pcie_clk)
self.dut.ptp_rst.value = 1
for mac in self.port_mac:
mac.rx.reset.value = 1
mac.tx.reset.value = 1
for k in range(10):
await RisingEdge(self.dut.pcie_clk)
self.dut.ptp_rst.value = 0
for mac in self.port_mac:
mac.rx.reset.value = 0
mac.tx.reset.value = 0
for k in range(10):
await RisingEdge(self.dut.pcie_clk)
await self.rc.enumerate()
async def _run_loopback(self):
while True:
await RisingEdge(self.dut.pcie_clk)
if self.loopback_enable:
for mac in self.port_mac:
while not mac.tx.empty():
await mac.rx.send(await mac.tx.recv())
@cocotb.test()
async def run_test(dut):
tb = TB(dut)
await tb.init()
tb.log.info("Init driver model")
driver = cndm.Driver()
await driver.init_pcie_dev(tb.rc.find_device(tb.dev.functions[0].pcie_id))
tb.log.info("Init complete")
tb.log.info("Send and receive single packet on each port")
for k in range(len(driver.ports)):
data = f"Corundum rocks on port {k}!".encode('ascii')
await driver.ports[k].start_xmit(data)
pkt = await tb.port_mac[k].tx.recv()
tb.log.info("Got TX packet: %s", pkt)
assert bytes(pkt) == data
await tb.port_mac[k].rx.send(pkt)
pkt = await driver.ports[k].recv()
tb.log.info("Got RX packet: %s", pkt)
assert bytes(pkt) == data
tb.log.info("Multiple small packets")
count = 64
pkts = [bytearray([(x+k) % 256 for x in range(60)]) for k in range(count)]
tb.loopback_enable = True
for p in pkts:
await driver.ports[0].start_xmit(p)
for k in range(count):
pkt = await driver.ports[0].recv()
tb.log.info("Got RX packet: %s", pkt)
assert bytes(pkt) == pkts[k]
tb.loopback_enable = False
tb.log.info("Multiple large packets")
count = 64
pkts = [bytearray([(x+k) % 256 for x in range(1514)]) for k in range(count)]
tb.loopback_enable = True
for p in pkts:
await driver.ports[0].start_xmit(p)
for k in range(count):
pkt = await driver.ports[0].recv()
tb.log.info("Got RX packet: %s", pkt)
assert bytes(pkt) == pkts[k]
tb.loopback_enable = False
await RisingEdge(dut.pcie_clk)
await RisingEdge(dut.pcie_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(tests_dir, '..', '..', 'lib'))
taxi_src_dir = os.path.abspath(os.path.join(lib_dir, 'taxi', 'src'))
def process_f_files(files):
lst = {}
for f in files:
if f[-2:].lower() == '.f':
with open(f, 'r') as fp:
l = fp.read().split()
for f in process_f_files([os.path.join(os.path.dirname(f), x) for x in l]):
lst[os.path.basename(f)] = f
else:
lst[os.path.basename(f)] = f
return list(lst.values())
@pytest.mark.parametrize(("pcie_data_w", "mac_data_w"), [
(128, 32),
(128, 64),
(256, 32),
(256, 64),
(512, 32),
(512, 64),
(512, 512),
])
def test_cndm_lite_pcie_us(request, pcie_data_w, mac_data_w):
dut = "cndm_lite_pcie_us"
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = module
verilog_sources = [
os.path.join(tests_dir, f"{toplevel}.sv"),
os.path.join(rtl_dir, f"{dut}.f"),
]
verilog_sources = process_f_files(verilog_sources)
parameters = {}
parameters['SIM'] = "1'b1"
parameters['VENDOR'] = "\"XILINX\""
parameters['FAMILY'] = "\"virtexuplus\""
# Structural configuration
parameters['PORTS'] = 2
# PTP configuration
parameters['PTP_TS_EN'] = 1
parameters['PTP_TS_FMT_TOD'] = 0
parameters['PTP_CLK_PER_NS_NUM'] = 512
parameters['PTP_CLK_PER_NS_DENOM'] = 165
# PCIe interface configuration
parameters['AXIS_PCIE_DATA_W'] = pcie_data_w
# AXI lite interface configuration (control)
parameters['AXIL_CTRL_DATA_W'] = 32
parameters['AXIL_CTRL_ADDR_W'] = 24
# MAC configuration
parameters['MAC_DATA_W'] = mac_data_w
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(
simulator="verilator",
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
)

View File

@@ -0,0 +1,309 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2025-2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* FPGA core logic testbench
*/
module test_cndm_lite_pcie_us #
(
/* verilator lint_off WIDTHTRUNC */
parameter logic SIM = 1'b0,
parameter string VENDOR = "XILINX",
parameter string FAMILY = "virtexuplus",
// FW ID
parameter FPGA_ID = 32'hDEADBEEF,
parameter FW_ID = 32'h0000C002,
parameter FW_VER = 32'h000_01_000,
parameter BOARD_ID = 32'h1234_0000,
parameter BOARD_VER = 32'h001_00_000,
parameter BUILD_DATE = 32'd602976000,
parameter GIT_HASH = 32'h5f87c2e8,
parameter RELEASE_INFO = 32'h00000000,
// Structural configuration
parameter PORTS = 2,
// PTP configuration
parameter logic PTP_TS_EN = 1'b1,
parameter logic PTP_TS_FMT_TOD = 1'b0,
parameter PTP_CLK_PER_NS_NUM = 512,
parameter PTP_CLK_PER_NS_DENOM = 165,
// PCIe interface configuration
parameter AXIS_PCIE_DATA_W = 512,
parameter AXIS_PCIE_RC_USER_W = AXIS_PCIE_DATA_W < 512 ? 75 : 161,
parameter AXIS_PCIE_RQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 62 : 137,
parameter AXIS_PCIE_CQ_USER_W = AXIS_PCIE_DATA_W < 512 ? 85 : 183,
parameter AXIS_PCIE_CC_USER_W = AXIS_PCIE_DATA_W < 512 ? 33 : 81,
// AXI lite interface configuration (control)
parameter AXIL_CTRL_DATA_W = 32,
parameter AXIL_CTRL_ADDR_W = 24,
// MAC configuration
parameter MAC_DATA_W = 512
/* verilator lint_on WIDTHTRUNC */
)
();
localparam PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 48;
localparam AXIS_PCIE_KEEP_W = (AXIS_PCIE_DATA_W/32);
localparam RQ_SEQ_NUM_W = AXIS_PCIE_RQ_USER_W == 60 ? 4 : 6;
logic sfp_mgt_refclk_p;
logic sfp_mgt_refclk_n;
logic sfp_mgt_refclk_out;
logic [1:0] sfp_npres;
logic [1:0] sfp_tx_fault;
logic [1:0] sfp_los;
logic pcie_clk;
logic pcie_rst;
taxi_axis_if #(
.DATA_W(AXIS_PCIE_DATA_W),
.KEEP_EN(1),
.KEEP_W(AXIS_PCIE_KEEP_W),
.USER_EN(1),
.USER_W(AXIS_PCIE_CQ_USER_W)
) s_axis_pcie_cq();
taxi_axis_if #(
.DATA_W(AXIS_PCIE_DATA_W),
.KEEP_EN(1),
.KEEP_W(AXIS_PCIE_KEEP_W),
.USER_EN(1),
.USER_W(AXIS_PCIE_CC_USER_W)
) m_axis_pcie_cc();
taxi_axis_if #(
.DATA_W(AXIS_PCIE_DATA_W),
.KEEP_EN(1),
.KEEP_W(AXIS_PCIE_KEEP_W),
.USER_EN(1),
.USER_W(AXIS_PCIE_RQ_USER_W)
) m_axis_pcie_rq();
taxi_axis_if #(
.DATA_W(AXIS_PCIE_DATA_W),
.KEEP_EN(1),
.KEEP_W(AXIS_PCIE_KEEP_W),
.USER_EN(1),
.USER_W(AXIS_PCIE_RC_USER_W)
) s_axis_pcie_rc();
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num0;
logic pcie_rq_seq_num_vld0;
logic [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num1;
logic pcie_rq_seq_num_vld1;
logic [2:0] cfg_max_payload;
logic [2:0] cfg_max_read_req;
logic [3:0] cfg_rcb_status;
logic [9:0] cfg_mgmt_addr;
logic [7:0] cfg_mgmt_function_number;
logic cfg_mgmt_write;
logic [31:0] cfg_mgmt_write_data;
logic [3:0] cfg_mgmt_byte_enable;
logic cfg_mgmt_read;
logic [31:0] cfg_mgmt_read_data;
logic cfg_mgmt_read_write_done;
logic [7:0] cfg_fc_ph;
logic [11:0] cfg_fc_pd;
logic [7:0] cfg_fc_nph;
logic [11:0] cfg_fc_npd;
logic [7:0] cfg_fc_cplh;
logic [11:0] cfg_fc_cpld;
logic [2:0] cfg_fc_sel;
logic [3:0] cfg_interrupt_msi_enable;
logic [11:0] cfg_interrupt_msi_mmenable;
logic cfg_interrupt_msi_mask_update;
logic [31:0] cfg_interrupt_msi_data;
logic [1:0] cfg_interrupt_msi_select;
logic [31:0] cfg_interrupt_msi_int;
logic [31:0] cfg_interrupt_msi_pending_status;
logic cfg_interrupt_msi_pending_status_data_enable;
logic [1:0] cfg_interrupt_msi_pending_status_function_num;
logic cfg_interrupt_msi_sent;
logic cfg_interrupt_msi_fail;
logic [2:0] cfg_interrupt_msi_attr;
logic cfg_interrupt_msi_tph_present;
logic [1:0] cfg_interrupt_msi_tph_type;
logic [7:0] cfg_interrupt_msi_tph_st_tag;
logic [7:0] cfg_interrupt_msi_function_number;
logic ptp_rst;
logic ptp_clk;
logic ptp_sample_clk;
logic ptp_td_sdo;
logic ptp_pps;
logic ptp_pps_str;
logic ptp_sync_locked;
logic [63:0] ptp_sync_ts_rel;
logic ptp_sync_ts_rel_step;
logic [95:0] ptp_sync_ts_tod;
logic ptp_sync_ts_tod_step;
logic ptp_sync_pps;
logic ptp_sync_pps_str;
logic mac_tx_clk[PORTS];
logic mac_tx_rst[PORTS];
taxi_axis_if #(
.DATA_W(MAC_DATA_W),
.ID_W(8),
.USER_EN(1),
.USER_W(1)
) mac_axis_tx[PORTS]();
logic mac_rx_clk[PORTS];
logic mac_rx_rst[PORTS];
taxi_axis_if #(
.DATA_W(PTP_TS_W),
.KEEP_W(1),
.ID_W(8)
) mac_axis_tx_cpl[PORTS]();
taxi_axis_if #(
.DATA_W(MAC_DATA_W),
.ID_W(8),
.USER_EN(1),
.USER_W(PTP_TS_W+1)
) mac_axis_rx[PORTS]();
cndm_lite_pcie_us #(
.SIM(SIM),
.VENDOR(VENDOR),
.FAMILY(FAMILY),
// FW ID
.FPGA_ID(FPGA_ID),
.FW_ID(FW_ID),
.FW_VER(FW_VER),
.BOARD_ID(BOARD_ID),
.BOARD_VER(BOARD_VER),
.BUILD_DATE(BUILD_DATE),
.GIT_HASH(GIT_HASH),
.RELEASE_INFO(RELEASE_INFO),
// Structural configuration
.PORTS(PORTS),
// PTP configuration
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM),
// PCIe interface configuration
.RQ_SEQ_NUM_W(RQ_SEQ_NUM_W),
// AXI lite interface configuration (control)
.AXIL_CTRL_DATA_W(AXIL_CTRL_DATA_W),
.AXIL_CTRL_ADDR_W(AXIL_CTRL_ADDR_W)
)
uut (
/*
* PCIe
*/
.pcie_clk(pcie_clk),
.pcie_rst(pcie_rst),
.s_axis_pcie_cq(s_axis_pcie_cq),
.m_axis_pcie_cc(m_axis_pcie_cc),
.m_axis_pcie_rq(m_axis_pcie_rq),
.s_axis_pcie_rc(s_axis_pcie_rc),
.pcie_rq_seq_num0(pcie_rq_seq_num0),
.pcie_rq_seq_num_vld0(pcie_rq_seq_num_vld0),
.pcie_rq_seq_num1(pcie_rq_seq_num1),
.pcie_rq_seq_num_vld1(pcie_rq_seq_num_vld1),
.cfg_max_payload(cfg_max_payload),
.cfg_max_read_req(cfg_max_read_req),
.cfg_rcb_status(cfg_rcb_status),
.cfg_mgmt_addr(cfg_mgmt_addr),
.cfg_mgmt_function_number(cfg_mgmt_function_number),
.cfg_mgmt_write(cfg_mgmt_write),
.cfg_mgmt_write_data(cfg_mgmt_write_data),
.cfg_mgmt_byte_enable(cfg_mgmt_byte_enable),
.cfg_mgmt_read(cfg_mgmt_read),
.cfg_mgmt_read_data(cfg_mgmt_read_data),
.cfg_mgmt_read_write_done(cfg_mgmt_read_write_done),
.cfg_fc_ph(cfg_fc_ph),
.cfg_fc_pd(cfg_fc_pd),
.cfg_fc_nph(cfg_fc_nph),
.cfg_fc_npd(cfg_fc_npd),
.cfg_fc_cplh(cfg_fc_cplh),
.cfg_fc_cpld(cfg_fc_cpld),
.cfg_fc_sel(cfg_fc_sel),
.cfg_interrupt_msi_enable(cfg_interrupt_msi_enable),
.cfg_interrupt_msi_mmenable(cfg_interrupt_msi_mmenable),
.cfg_interrupt_msi_mask_update(cfg_interrupt_msi_mask_update),
.cfg_interrupt_msi_data(cfg_interrupt_msi_data),
.cfg_interrupt_msi_select(cfg_interrupt_msi_select),
.cfg_interrupt_msi_int(cfg_interrupt_msi_int),
.cfg_interrupt_msi_pending_status(cfg_interrupt_msi_pending_status),
.cfg_interrupt_msi_pending_status_data_enable(cfg_interrupt_msi_pending_status_data_enable),
.cfg_interrupt_msi_pending_status_function_num(cfg_interrupt_msi_pending_status_function_num),
.cfg_interrupt_msi_sent(cfg_interrupt_msi_sent),
.cfg_interrupt_msi_fail(cfg_interrupt_msi_fail),
.cfg_interrupt_msi_attr(cfg_interrupt_msi_attr),
.cfg_interrupt_msi_tph_present(cfg_interrupt_msi_tph_present),
.cfg_interrupt_msi_tph_type(cfg_interrupt_msi_tph_type),
.cfg_interrupt_msi_tph_st_tag(cfg_interrupt_msi_tph_st_tag),
.cfg_interrupt_msi_function_number(cfg_interrupt_msi_function_number),
/*
* PTP
*/
.ptp_clk(ptp_clk),
.ptp_rst(ptp_rst),
.ptp_sample_clk(ptp_sample_clk),
.ptp_td_sdo(ptp_td_sdo),
.ptp_pps(ptp_pps),
.ptp_pps_str(ptp_pps_str),
.ptp_sync_locked(ptp_sync_locked),
.ptp_sync_ts_rel(ptp_sync_ts_rel),
.ptp_sync_ts_rel_step(ptp_sync_ts_rel_step),
.ptp_sync_ts_tod(ptp_sync_ts_tod),
.ptp_sync_ts_tod_step(ptp_sync_ts_tod_step),
.ptp_sync_pps(ptp_sync_pps),
.ptp_sync_pps_str(ptp_sync_pps_str),
/*
* Ethernet: SFP+
*/
.mac_tx_clk(mac_tx_clk),
.mac_tx_rst(mac_tx_rst),
.mac_axis_tx(mac_axis_tx),
.mac_axis_tx_cpl(mac_axis_tx_cpl),
.mac_rx_clk(mac_rx_clk),
.mac_rx_rst(mac_rx_rst),
.mac_axis_rx(mac_axis_rx)
);
endmodule
`resetall