mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
cndm: Copy cndm-micro core logic as cndm-lite
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
22
src/cndm/rtl/cndm_lite_core.f
Normal file
22
src/cndm/rtl/cndm_lite_core.f
Normal 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
|
||||
563
src/cndm/rtl/cndm_lite_core.sv
Normal file
563
src/cndm/rtl/cndm_lite_core.sv
Normal 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
|
||||
6
src/cndm/rtl/cndm_lite_pcie_us.f
Normal file
6
src/cndm/rtl/cndm_lite_pcie_us.f
Normal 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
|
||||
580
src/cndm/rtl/cndm_lite_pcie_us.sv
Normal file
580
src/cndm/rtl/cndm_lite_pcie_us.sv
Normal 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
|
||||
71
src/cndm/tb/cndm_lite_pcie_us/Makefile
Normal file
71
src/cndm/tb/cndm_lite_pcie_us/Makefile
Normal 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
|
||||
1
src/cndm/tb/cndm_lite_pcie_us/cndm.py
Symbolic link
1
src/cndm/tb/cndm_lite_pcie_us/cndm.py
Symbolic link
@@ -0,0 +1 @@
|
||||
../cndm.py
|
||||
516
src/cndm/tb/cndm_lite_pcie_us/test_cndm_lite_pcie_us.py
Normal file
516
src/cndm/tb/cndm_lite_pcie_us/test_cndm_lite_pcie_us.py
Normal 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,
|
||||
)
|
||||
309
src/cndm/tb/cndm_lite_pcie_us/test_cndm_lite_pcie_us.sv
Normal file
309
src/cndm/tb/cndm_lite_pcie_us/test_cndm_lite_pcie_us.sv
Normal 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
|
||||
Reference in New Issue
Block a user