mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
cndm: Initial commit of corundum-micro
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
16
src/cndm/rtl/cndm_micro_core.f
Normal file
16
src/cndm/rtl/cndm_micro_core.f
Normal file
@@ -0,0 +1,16 @@
|
||||
cndm_micro_core.sv
|
||||
cndm_micro_port.sv
|
||||
cndm_micro_rx.sv
|
||||
cndm_micro_tx.sv
|
||||
cndm_micro_desc_rd.sv
|
||||
cndm_micro_cpl_wr.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/axi/rtl/taxi_axil_interconnect_1s.f
|
||||
../lib/taxi/src/axis/rtl/taxi_axis_async_fifo.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.sv
|
||||
../lib/taxi/src/ptp/rtl/taxi_ptp_td_leaf.sv
|
||||
369
src/cndm/rtl/cndm_micro_core.sv
Normal file
369
src/cndm/rtl/cndm_micro_core.sv
Normal file
@@ -0,0 +1,369 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro core logic
|
||||
*/
|
||||
module cndm_micro_core #(
|
||||
parameter PORTS = 2//,
|
||||
// parameter logic PTP_TS_EN = 1'b1,
|
||||
// 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_wr,
|
||||
taxi_axil_if.rd_slv s_axil_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,
|
||||
// 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_wr.ADDR_W;
|
||||
localparam AXIL_DATA_W = s_axil_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 = 1;
|
||||
// localparam PORT_OFFSET = PTP_TS_EN ? 2 : 1;
|
||||
|
||||
taxi_axil_if #(
|
||||
.DATA_W(s_axil_wr.DATA_W),
|
||||
.ADDR_W(16),
|
||||
.STRB_W(s_axil_wr.STRB_W),
|
||||
.AWUSER_EN(s_axil_wr.AWUSER_EN),
|
||||
.AWUSER_W(s_axil_wr.AWUSER_W),
|
||||
.WUSER_EN(s_axil_wr.WUSER_EN),
|
||||
.WUSER_W(s_axil_wr.WUSER_W),
|
||||
.BUSER_EN(s_axil_wr.BUSER_EN),
|
||||
.BUSER_W(s_axil_wr.BUSER_W),
|
||||
.ARUSER_EN(s_axil_wr.ARUSER_EN),
|
||||
.ARUSER_W(s_axil_wr.ARUSER_W),
|
||||
.RUSER_EN(s_axil_wr.RUSER_EN),
|
||||
.RUSER_W(s_axil_wr.RUSER_W)
|
||||
)
|
||||
s_axil_ctrl[PORTS+PORT_OFFSET]();
|
||||
|
||||
taxi_axil_interconnect_1s #(
|
||||
.M_COUNT($size(s_axil_ctrl)),
|
||||
.ADDR_W(s_axil_wr.ADDR_W),
|
||||
.M_REGIONS(1),
|
||||
.M_BASE_ADDR('0),
|
||||
.M_ADDR_W({$size(s_axil_ctrl){{1{32'd16}}}}),
|
||||
.M_SECURE({$size(s_axil_ctrl){1'b0}})
|
||||
)
|
||||
port_intercon_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI4-lite slave interface
|
||||
*/
|
||||
.s_axil_wr(s_axil_wr),
|
||||
.s_axil_rd(s_axil_rd),
|
||||
|
||||
/*
|
||||
* AXI4-lite master interfaces
|
||||
*/
|
||||
.m_axil_wr(s_axil_ctrl),
|
||||
.m_axil_rd(s_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 s_axil_ctrl[0].awready = s_axil_awready_reg;
|
||||
assign s_axil_ctrl[0].wready = s_axil_wready_reg;
|
||||
assign s_axil_ctrl[0].bresp = '0;
|
||||
assign s_axil_ctrl[0].buser = '0;
|
||||
assign s_axil_ctrl[0].bvalid = s_axil_bvalid_reg;
|
||||
|
||||
assign s_axil_ctrl[0].arready = s_axil_arready_reg;
|
||||
assign s_axil_ctrl[0].rdata = s_axil_rdata_reg;
|
||||
assign s_axil_ctrl[0].rresp = '0;
|
||||
assign s_axil_ctrl[0].ruser = '0;
|
||||
assign s_axil_ctrl[0].rvalid = s_axil_rvalid_reg;
|
||||
|
||||
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 && !s_axil_ctrl[0].bready;
|
||||
|
||||
s_axil_arready_reg <= 1'b0;
|
||||
s_axil_rvalid_reg <= s_axil_rvalid_reg && !s_axil_ctrl[0].rready;
|
||||
|
||||
if (s_axil_ctrl[0].awvalid && s_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 ({s_axil_ctrl[0].awaddr[15:2], 2'b00})
|
||||
// 16'h0100: begin
|
||||
// txq_en_reg <= s_axil_ctrl[0].wdata[0];
|
||||
// txq_size_reg <= s_axil_ctrl[0].wdata[19:16];
|
||||
// end
|
||||
// 16'h0104: txq_prod_reg <= s_axil_ctrl[0].wdata[15:0];
|
||||
// 16'h0108: txq_base_addr_reg[31:0] <= s_axil_ctrl[0].wdata;
|
||||
// 16'h010c: txq_base_addr_reg[63:32] <= s_axil_ctrl[0].wdata;
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (s_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 ({s_axil_ctrl[0].araddr[15:2], 2'b00})
|
||||
16'h0100: s_axil_rdata_reg <= PORTS; // port count
|
||||
16'h0104: s_axil_rdata_reg <= 32'h00010000; // port offset
|
||||
// 16'h0104: s_axil_rdata_reg <= PTP_TS_EN ? 32'h00020000 : 32'h00010000; // port offset
|
||||
16'h0108: s_axil_rdata_reg <= 32'h00010000; // port stride
|
||||
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
|
||||
|
||||
// if (PTP_TS_EN) begin : ptp
|
||||
|
||||
// cndm_micro_ptp #(
|
||||
// .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_axil_wr(s_axil_ctrl[1]),
|
||||
// .s_axil_rd(s_axil_ctrl[1]),
|
||||
|
||||
// /*
|
||||
// * 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;
|
||||
|
||||
// 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 #(
|
||||
// .PTP_TS_EN(PTP_TS_EN)
|
||||
)
|
||||
port_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Control register interface
|
||||
*/
|
||||
.s_axil_wr(s_axil_ctrl[PORT_OFFSET+p]),
|
||||
.s_axil_rd(s_axil_ctrl[PORT_OFFSET+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]),
|
||||
|
||||
/*
|
||||
* 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
|
||||
227
src/cndm/rtl/cndm_micro_cpl_wr.sv
Normal file
227
src/cndm/rtl/cndm_micro_cpl_wr.sv
Normal file
@@ -0,0 +1,227 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro completion write module
|
||||
*/
|
||||
module cndm_micro_cpl_wr
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
taxi_dma_desc_if.req_src dma_wr_desc_req,
|
||||
taxi_dma_desc_if.sts_snk dma_wr_desc_sts,
|
||||
taxi_dma_ram_if.rd_slv dma_ram_rd,
|
||||
|
||||
input wire logic txcq_en,
|
||||
input wire logic [3:0] txcq_size,
|
||||
input wire logic [63:0] txcq_base_addr,
|
||||
output wire logic [15:0] txcq_prod,
|
||||
input wire logic rxcq_en,
|
||||
input wire logic [3:0] rxcq_size,
|
||||
input wire logic [63:0] rxcq_base_addr,
|
||||
output wire logic [15:0] rxcq_prod,
|
||||
|
||||
taxi_axis_if.snk axis_cpl[2],
|
||||
output wire logic irq
|
||||
);
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(axis_cpl[0].DATA_W),
|
||||
.KEEP_EN(axis_cpl[0].KEEP_EN),
|
||||
.KEEP_W(axis_cpl[0].KEEP_W),
|
||||
.STRB_EN(axis_cpl[0].STRB_EN),
|
||||
.LAST_EN(axis_cpl[0].LAST_EN),
|
||||
.ID_EN(1),
|
||||
.ID_W(1),
|
||||
.DEST_EN(axis_cpl[0].DEST_EN),
|
||||
.DEST_W(axis_cpl[0].DEST_W),
|
||||
.USER_EN(axis_cpl[0].USER_EN),
|
||||
.USER_W(axis_cpl[0].USER_W)
|
||||
) cpl_comb();
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 0,
|
||||
STATE_RX_CPL = 1,
|
||||
STATE_WRITE_DATA = 2;
|
||||
|
||||
logic [2:0] state_reg = STATE_IDLE;
|
||||
|
||||
logic [15:0] txcq_prod_ptr_reg = '0;
|
||||
logic [15:0] rxcq_prod_ptr_reg = '0;
|
||||
|
||||
logic phase_tag_reg = 1'b0;
|
||||
|
||||
logic irq_reg = 1'b0;
|
||||
|
||||
assign txcq_prod = txcq_prod_ptr_reg;
|
||||
assign rxcq_prod = rxcq_prod_ptr_reg;
|
||||
|
||||
assign irq = irq_reg;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
cpl_comb.tready <= 1'b0;
|
||||
|
||||
dma_wr_desc_req.req_src_sel <= '0;
|
||||
dma_wr_desc_req.req_src_asid <= '0;
|
||||
dma_wr_desc_req.req_dst_sel <= '0;
|
||||
dma_wr_desc_req.req_dst_asid <= '0;
|
||||
dma_wr_desc_req.req_imm <= '0;
|
||||
dma_wr_desc_req.req_imm_en <= '0;
|
||||
dma_wr_desc_req.req_len <= 16;
|
||||
dma_wr_desc_req.req_tag <= '0;
|
||||
dma_wr_desc_req.req_id <= '0;
|
||||
dma_wr_desc_req.req_dest <= '0;
|
||||
dma_wr_desc_req.req_user <= '0;
|
||||
dma_wr_desc_req.req_valid <= dma_wr_desc_req.req_valid && !dma_wr_desc_req.req_ready;
|
||||
|
||||
if (!txcq_en) begin
|
||||
txcq_prod_ptr_reg <= '0;
|
||||
end
|
||||
|
||||
if (!rxcq_en) begin
|
||||
rxcq_prod_ptr_reg <= '0;
|
||||
end
|
||||
|
||||
irq_reg <= 1'b0;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
dma_wr_desc_req.req_src_addr <= '0;
|
||||
|
||||
if (cpl_comb.tid == 0) begin
|
||||
dma_wr_desc_req.req_dst_addr <= txcq_base_addr + 64'(16'(txcq_prod_ptr_reg & ({16{1'b1}} >> (16 - txcq_size))) * 16);
|
||||
phase_tag_reg <= !txcq_prod_ptr_reg[txcq_size];
|
||||
if (cpl_comb.tvalid && !cpl_comb.tready) begin
|
||||
txcq_prod_ptr_reg <= txcq_prod_ptr_reg + 1;
|
||||
if (txcq_en) begin
|
||||
dma_wr_desc_req.req_valid <= 1'b1;
|
||||
state_reg <= STATE_WRITE_DATA;
|
||||
end else begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
dma_wr_desc_req.req_dst_addr <= rxcq_base_addr + 64'(16'(rxcq_prod_ptr_reg & ({16{1'b1}} >> (16 - rxcq_size))) * 16);
|
||||
phase_tag_reg <= !rxcq_prod_ptr_reg[rxcq_size];
|
||||
if (cpl_comb.tvalid && !cpl_comb.tready) begin
|
||||
rxcq_prod_ptr_reg <= rxcq_prod_ptr_reg + 1;
|
||||
if (rxcq_en) begin
|
||||
dma_wr_desc_req.req_valid <= 1'b1;
|
||||
state_reg <= STATE_WRITE_DATA;
|
||||
end else begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
STATE_WRITE_DATA: begin
|
||||
if (dma_wr_desc_sts.sts_valid) begin
|
||||
cpl_comb.tready <= 1'b1;
|
||||
irq_reg <= 1'b1;
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
txcq_prod_ptr_reg <= '0;
|
||||
rxcq_prod_ptr_reg <= '0;
|
||||
irq_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
taxi_axis_arb_mux #(
|
||||
.S_COUNT(2),
|
||||
.UPDATE_TID(1),
|
||||
.ARB_ROUND_ROBIN(1),
|
||||
.ARB_LSB_HIGH_PRIO(1)
|
||||
)
|
||||
mux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI4-Stream input (sink)
|
||||
*/
|
||||
.s_axis(axis_cpl),
|
||||
|
||||
/*
|
||||
* AXI4-Stream output (source)
|
||||
*/
|
||||
.m_axis(cpl_comb)
|
||||
);
|
||||
|
||||
// extract parameters
|
||||
localparam SEGS = dma_ram_rd.SEGS;
|
||||
localparam SEG_ADDR_W = dma_ram_rd.SEG_ADDR_W;
|
||||
localparam SEG_DATA_W = dma_ram_rd.SEG_DATA_W;
|
||||
localparam SEG_BE_W = dma_ram_rd.SEG_BE_W;
|
||||
|
||||
if (SEGS*SEG_DATA_W < 128)
|
||||
$fatal(0, "Total segmented interface width must be at least 128 (instance %m)");
|
||||
|
||||
wire [SEGS-1:0][SEG_DATA_W-1:0] ram_data = (SEG_DATA_W*SEGS)'({phase_tag_reg, cpl_comb.tdata[126:0]});
|
||||
|
||||
for (genvar n = 0; n < SEGS; n = n + 1) begin
|
||||
|
||||
logic [0:0] rd_resp_valid_pipe_reg = '0;
|
||||
logic [SEG_DATA_W-1:0] rd_resp_data_pipe_reg[1];
|
||||
|
||||
initial begin
|
||||
for (integer i = 0; i < 1; i = i + 1) begin
|
||||
rd_resp_data_pipe_reg[i] = '0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (dma_ram_rd.rd_resp_ready[n]) begin
|
||||
rd_resp_valid_pipe_reg[0] <= 1'b0;
|
||||
end
|
||||
|
||||
for (integer j = 0; j > 0; j = j - 1) begin
|
||||
if (dma_ram_rd.rd_resp_ready[n] || (1'(~rd_resp_valid_pipe_reg) >> j) != 0) begin
|
||||
rd_resp_valid_pipe_reg[j] <= rd_resp_valid_pipe_reg[j-1];
|
||||
rd_resp_data_pipe_reg[j] <= rd_resp_data_pipe_reg[j-1];
|
||||
rd_resp_valid_pipe_reg[j-1] <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
if (dma_ram_rd.rd_cmd_valid[n] && dma_ram_rd.rd_cmd_ready[n]) begin
|
||||
rd_resp_valid_pipe_reg[0] <= 1'b1;
|
||||
rd_resp_data_pipe_reg[0] <= ram_data[0];
|
||||
end
|
||||
|
||||
if (rst) begin
|
||||
rd_resp_valid_pipe_reg <= '0;
|
||||
end
|
||||
end
|
||||
|
||||
assign dma_ram_rd.rd_cmd_ready[n] = dma_ram_rd.rd_resp_ready[n] || &rd_resp_valid_pipe_reg == 0;
|
||||
|
||||
assign dma_ram_rd.rd_resp_valid[n] = rd_resp_valid_pipe_reg[0];
|
||||
assign dma_ram_rd.rd_resp_data[n] = rd_resp_data_pipe_reg[0];
|
||||
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
266
src/cndm/rtl/cndm_micro_desc_rd.sv
Normal file
266
src/cndm/rtl/cndm_micro_desc_rd.sv
Normal file
@@ -0,0 +1,266 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro descriptor read module
|
||||
*/
|
||||
module cndm_micro_desc_rd
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
taxi_dma_desc_if.req_src dma_rd_desc_req,
|
||||
taxi_dma_desc_if.sts_snk dma_rd_desc_sts,
|
||||
taxi_dma_ram_if.wr_slv dma_ram_wr,
|
||||
|
||||
input wire logic txq_en,
|
||||
input wire logic [3:0] txq_size,
|
||||
input wire logic [63:0] txq_base_addr,
|
||||
input wire logic [15:0] txq_prod,
|
||||
output wire logic [15:0] txq_cons,
|
||||
input wire logic rxq_en,
|
||||
input wire logic [3:0] rxq_size,
|
||||
input wire logic [63:0] rxq_base_addr,
|
||||
input wire logic [15:0] rxq_prod,
|
||||
output wire logic [15:0] rxq_cons,
|
||||
|
||||
input wire logic [1:0] desc_req,
|
||||
taxi_axis_if.src axis_desc[2]
|
||||
);
|
||||
|
||||
localparam RAM_ADDR_W = 16;
|
||||
|
||||
taxi_dma_desc_if #(
|
||||
.SRC_ADDR_W(RAM_ADDR_W),
|
||||
.SRC_SEL_EN(1'b0),
|
||||
.SRC_ASID_EN(1'b0),
|
||||
.DST_ADDR_W(RAM_ADDR_W),
|
||||
.DST_SEL_EN(1'b0),
|
||||
.DST_ASID_EN(1'b0),
|
||||
.IMM_EN(1'b0),
|
||||
.LEN_W(5),
|
||||
.TAG_W(1),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(1),
|
||||
.DEST_W(1),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) dma_desc();
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 0,
|
||||
STATE_READ_DESC = 1,
|
||||
STATE_READ_DATA = 2,
|
||||
STATE_TX_DESC = 3;
|
||||
|
||||
logic [2:0] state_reg = STATE_IDLE;
|
||||
|
||||
logic [1:0] desc_req_reg = '0;
|
||||
|
||||
logic [15:0] txq_cons_ptr_reg = '0;
|
||||
logic [15:0] rxq_cons_ptr_reg = '0;
|
||||
|
||||
assign txq_cons = txq_cons_ptr_reg;
|
||||
assign rxq_cons = rxq_cons_ptr_reg;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
// axis_desc.tready <= 1'b0;
|
||||
|
||||
dma_rd_desc_req.req_src_sel <= '0;
|
||||
dma_rd_desc_req.req_src_asid <= '0;
|
||||
dma_rd_desc_req.req_dst_sel <= '0;
|
||||
dma_rd_desc_req.req_dst_asid <= '0;
|
||||
dma_rd_desc_req.req_imm <= '0;
|
||||
dma_rd_desc_req.req_imm_en <= '0;
|
||||
dma_rd_desc_req.req_len <= 16;
|
||||
dma_rd_desc_req.req_tag <= '0;
|
||||
dma_rd_desc_req.req_id <= '0;
|
||||
dma_rd_desc_req.req_dest <= '0;
|
||||
dma_rd_desc_req.req_user <= '0;
|
||||
dma_rd_desc_req.req_valid <= dma_rd_desc_req.req_valid && !dma_rd_desc_req.req_ready;
|
||||
|
||||
dma_desc.req_src_sel <= '0;
|
||||
dma_desc.req_src_asid <= '0;
|
||||
dma_desc.req_dst_addr <= '0;
|
||||
dma_desc.req_dst_sel <= '0;
|
||||
dma_desc.req_dst_asid <= '0;
|
||||
dma_desc.req_imm <= '0;
|
||||
dma_desc.req_imm_en <= '0;
|
||||
dma_desc.req_len <= 16;
|
||||
dma_desc.req_tag <= '0;
|
||||
dma_desc.req_id <= '0;
|
||||
dma_desc.req_user <= '0;
|
||||
dma_desc.req_valid <= dma_desc.req_valid && !dma_desc.req_ready;
|
||||
|
||||
desc_req_reg <= desc_req_reg | desc_req;
|
||||
|
||||
if (!txq_en) begin
|
||||
txq_cons_ptr_reg <= '0;
|
||||
end
|
||||
|
||||
if (!rxq_en) begin
|
||||
rxq_cons_ptr_reg <= '0;
|
||||
end
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
if (desc_req_reg[1]) begin
|
||||
dma_rd_desc_req.req_src_addr <= rxq_base_addr + 64'(16'(rxq_cons_ptr_reg & ({16{1'b1}} >> (16 - rxq_size))) * 16);
|
||||
dma_desc.req_dest <= 1'b1;
|
||||
desc_req_reg[1] <= 1'b0;
|
||||
if (rxq_cons_ptr_reg == rxq_prod || !rxq_en) begin
|
||||
dma_desc.req_user <= 1'b1;
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
state_reg <= STATE_TX_DESC;
|
||||
end else begin
|
||||
dma_desc.req_user <= 1'b0;
|
||||
dma_rd_desc_req.req_valid <= 1'b1;
|
||||
rxq_cons_ptr_reg <= rxq_cons_ptr_reg + 1;
|
||||
state_reg <= STATE_READ_DESC;
|
||||
end
|
||||
end else if (desc_req_reg[0]) begin
|
||||
dma_rd_desc_req.req_src_addr <= txq_base_addr + 64'(16'(txq_cons_ptr_reg & ({16{1'b1}} >> (16 - txq_size))) * 16);
|
||||
dma_desc.req_dest <= 1'b0;
|
||||
desc_req_reg[0] <= 1'b0;
|
||||
if (txq_cons_ptr_reg == txq_prod || !txq_en) begin
|
||||
dma_desc.req_user <= 1'b1;
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
state_reg <= STATE_TX_DESC;
|
||||
end else begin
|
||||
dma_desc.req_user <= 1'b0;
|
||||
dma_rd_desc_req.req_valid <= 1'b1;
|
||||
txq_cons_ptr_reg <= txq_cons_ptr_reg + 1;
|
||||
state_reg <= STATE_READ_DESC;
|
||||
end
|
||||
end
|
||||
end
|
||||
STATE_READ_DESC: begin
|
||||
if (dma_rd_desc_sts.sts_valid) begin
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
state_reg <= STATE_TX_DESC;
|
||||
end
|
||||
end
|
||||
STATE_TX_DESC: begin
|
||||
if (dma_desc.sts_valid) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
taxi_dma_ram_if #(
|
||||
.SEGS(dma_ram_wr.SEGS),
|
||||
.SEG_ADDR_W(dma_ram_wr.SEG_ADDR_W),
|
||||
.SEG_DATA_W(dma_ram_wr.SEG_DATA_W),
|
||||
.SEG_BE_W(dma_ram_wr.SEG_BE_W)
|
||||
) dma_ram_rd();
|
||||
|
||||
taxi_dma_psdpram #(
|
||||
.SIZE(1024),
|
||||
.PIPELINE(2)
|
||||
)
|
||||
ram_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Write port
|
||||
*/
|
||||
.dma_ram_wr(dma_ram_wr),
|
||||
|
||||
/*
|
||||
* Read port
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd)
|
||||
);
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(axis_desc[0].DATA_W),
|
||||
.KEEP_EN(axis_desc[0].KEEP_EN),
|
||||
.KEEP_W(axis_desc[0].KEEP_W),
|
||||
.LAST_EN(axis_desc[0].LAST_EN),
|
||||
.ID_EN(axis_desc[0].ID_EN),
|
||||
.ID_W(axis_desc[0].ID_W),
|
||||
.DEST_EN(1),
|
||||
.DEST_W(1),
|
||||
.USER_EN(axis_desc[0].USER_EN),
|
||||
.USER_W(axis_desc[0].USER_W)
|
||||
) m_axis_rd_data();
|
||||
|
||||
taxi_dma_client_axis_source
|
||||
dma_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA descriptor
|
||||
*/
|
||||
.desc_req(dma_desc),
|
||||
.desc_sts(dma_desc),
|
||||
|
||||
/*
|
||||
* AXI stream read data output
|
||||
*/
|
||||
.m_axis_rd_data(m_axis_rd_data),
|
||||
|
||||
/*
|
||||
* RAM interface
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.enable(1'b1)
|
||||
);
|
||||
|
||||
taxi_axis_demux #(
|
||||
.M_COUNT(2),
|
||||
.TDEST_ROUTE(1)
|
||||
)
|
||||
demux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI4-Stream input (sink)
|
||||
*/
|
||||
.s_axis(m_axis_rd_data),
|
||||
|
||||
/*
|
||||
* AXI4-Stream output (source)
|
||||
*/
|
||||
.m_axis(axis_desc),
|
||||
|
||||
/*
|
||||
* Control
|
||||
*/
|
||||
.enable(1'b1),
|
||||
.drop(1'b0),
|
||||
.select('0)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
5
src/cndm/rtl/cndm_micro_pcie_us.f
Normal file
5
src/cndm/rtl/cndm_micro_pcie_us.f
Normal file
@@ -0,0 +1,5 @@
|
||||
cndm_micro_pcie_us.sv
|
||||
cndm_micro_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/dma/rtl/taxi_dma_if_pcie_us.f
|
||||
465
src/cndm/rtl/cndm_micro_pcie_us.sv
Normal file
465
src/cndm/rtl/cndm_micro_pcie_us.sv
Normal file
@@ -0,0 +1,465 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro core logic for UltraScale PCIe
|
||||
*/
|
||||
module cndm_micro_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",
|
||||
parameter PORTS = 2,
|
||||
parameter RQ_SEQ_NUM_W = 6,
|
||||
parameter BAR0_APERTURE = 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 [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num0,
|
||||
input wire pcie_rq_seq_num_vld0,
|
||||
input wire [RQ_SEQ_NUM_W-1:0] pcie_rq_seq_num1,
|
||||
input wire pcie_rq_seq_num_vld1,
|
||||
|
||||
input wire [2:0] cfg_max_payload,
|
||||
input wire [2:0] cfg_max_read_req,
|
||||
input wire [3:0] cfg_rcb_status,
|
||||
|
||||
output wire [9:0] cfg_mgmt_addr,
|
||||
output wire [7:0] cfg_mgmt_function_number,
|
||||
output wire cfg_mgmt_write,
|
||||
output wire [31:0] cfg_mgmt_write_data,
|
||||
output wire [3:0] cfg_mgmt_byte_enable,
|
||||
output wire cfg_mgmt_read,
|
||||
input wire [31:0] cfg_mgmt_read_data,
|
||||
input wire cfg_mgmt_read_write_done,
|
||||
|
||||
input wire [7:0] cfg_fc_ph,
|
||||
input wire [11:0] cfg_fc_pd,
|
||||
input wire [7:0] cfg_fc_nph,
|
||||
input wire [11:0] cfg_fc_npd,
|
||||
input wire [7:0] cfg_fc_cplh,
|
||||
input wire [11:0] cfg_fc_cpld,
|
||||
output wire [2:0] cfg_fc_sel,
|
||||
|
||||
input wire [3:0] cfg_interrupt_msi_enable,
|
||||
input wire [11:0] cfg_interrupt_msi_mmenable,
|
||||
input wire cfg_interrupt_msi_mask_update,
|
||||
input wire [31:0] cfg_interrupt_msi_data,
|
||||
output wire [1:0] cfg_interrupt_msi_select,
|
||||
output wire [31:0] cfg_interrupt_msi_int,
|
||||
output wire [31:0] cfg_interrupt_msi_pending_status,
|
||||
output wire cfg_interrupt_msi_pending_status_data_enable,
|
||||
output wire [1:0] cfg_interrupt_msi_pending_status_function_num,
|
||||
input wire cfg_interrupt_msi_sent,
|
||||
input wire cfg_interrupt_msi_fail,
|
||||
output wire [2:0] cfg_interrupt_msi_attr,
|
||||
output wire cfg_interrupt_msi_tph_present,
|
||||
output wire [1:0] cfg_interrupt_msi_tph_type,
|
||||
output wire [7:0] cfg_interrupt_msi_tph_st_tag,
|
||||
output wire [7:0] cfg_interrupt_msi_function_number,
|
||||
|
||||
/*
|
||||
* 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_DATA_W = 32;
|
||||
localparam AXIL_ADDR_W = BAR0_APERTURE;
|
||||
|
||||
taxi_axil_if #(
|
||||
.DATA_W(AXIL_DATA_W),
|
||||
.ADDR_W(AXIL_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;
|
||||
|
||||
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(1'b0), // TODO
|
||||
.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)
|
||||
);
|
||||
|
||||
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_micro_core #(
|
||||
.PORTS(PORTS)
|
||||
)
|
||||
core_inst (
|
||||
.clk(pcie_clk),
|
||||
.rst(pcie_rst),
|
||||
|
||||
/*
|
||||
* Control register interface
|
||||
*/
|
||||
.s_axil_wr(axil_ctrl_bar),
|
||||
.s_axil_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),
|
||||
|
||||
/*
|
||||
* 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
|
||||
606
src/cndm/rtl/cndm_micro_port.sv
Normal file
606
src/cndm/rtl/cndm_micro_port.sv
Normal file
@@ -0,0 +1,606 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro port module
|
||||
*/
|
||||
module cndm_micro_port #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* Control register interface
|
||||
*/
|
||||
taxi_axil_if.wr_slv s_axil_wr,
|
||||
taxi_axil_if.rd_slv s_axil_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 irq,
|
||||
|
||||
/*
|
||||
* Ethernet
|
||||
*/
|
||||
input wire logic mac_tx_clk,
|
||||
input wire logic mac_tx_rst,
|
||||
taxi_axis_if.src mac_axis_tx,
|
||||
taxi_axis_if.snk mac_axis_tx_cpl,
|
||||
|
||||
input wire logic mac_rx_clk,
|
||||
input wire logic mac_rx_rst,
|
||||
taxi_axis_if.snk mac_axis_rx
|
||||
);
|
||||
|
||||
localparam AXIL_ADDR_W = s_axil_wr.ADDR_W;
|
||||
localparam AXIL_DATA_W = s_axil_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;
|
||||
|
||||
logic txq_en_reg = '0;
|
||||
logic [3:0] txq_size_reg = '0;
|
||||
logic [63:0] txq_base_addr_reg = '0;
|
||||
logic [15:0] txq_prod_reg = '0;
|
||||
wire [15:0] txq_cons;
|
||||
logic rxq_en_reg = '0;
|
||||
logic [3:0] rxq_size_reg = '0;
|
||||
logic [63:0] rxq_base_addr_reg = '0;
|
||||
logic [15:0] rxq_prod_reg = '0;
|
||||
wire [15:0] rxq_cons;
|
||||
|
||||
logic txcq_en_reg = '0;
|
||||
logic [3:0] txcq_size_reg = '0;
|
||||
logic [63:0] txcq_base_addr_reg = '0;
|
||||
wire [15:0] txcq_prod;
|
||||
logic rxcq_en_reg = '0;
|
||||
logic [3:0] rxcq_size_reg = '0;
|
||||
logic [63:0] rxcq_base_addr_reg = '0;
|
||||
wire [15:0] rxcq_prod;
|
||||
|
||||
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 s_axil_wr.awready = s_axil_awready_reg;
|
||||
assign s_axil_wr.wready = s_axil_wready_reg;
|
||||
assign s_axil_wr.bresp = '0;
|
||||
assign s_axil_wr.buser = '0;
|
||||
assign s_axil_wr.bvalid = s_axil_bvalid_reg;
|
||||
|
||||
assign s_axil_rd.arready = s_axil_arready_reg;
|
||||
assign s_axil_rd.rdata = s_axil_rdata_reg;
|
||||
assign s_axil_rd.rresp = '0;
|
||||
assign s_axil_rd.ruser = '0;
|
||||
assign s_axil_rd.rvalid = s_axil_rvalid_reg;
|
||||
|
||||
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 && !s_axil_wr.bready;
|
||||
|
||||
s_axil_arready_reg <= 1'b0;
|
||||
s_axil_rvalid_reg <= s_axil_rvalid_reg && !s_axil_rd.rready;
|
||||
|
||||
if (s_axil_wr.awvalid && s_axil_wr.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 ({s_axil_wr.awaddr[15:2], 2'b00})
|
||||
16'h0100: begin
|
||||
txq_en_reg <= s_axil_wr.wdata[0];
|
||||
txq_size_reg <= s_axil_wr.wdata[19:16];
|
||||
end
|
||||
16'h0104: txq_prod_reg <= s_axil_wr.wdata[15:0];
|
||||
16'h0108: txq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
||||
16'h010c: txq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
||||
|
||||
16'h0200: begin
|
||||
rxq_en_reg <= s_axil_wr.wdata[0];
|
||||
rxq_size_reg <= s_axil_wr.wdata[19:16];
|
||||
end
|
||||
16'h0204: rxq_prod_reg <= s_axil_wr.wdata[15:0];
|
||||
16'h0208: rxq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
||||
16'h020c: rxq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
||||
|
||||
16'h0300: begin
|
||||
txcq_en_reg <= s_axil_wr.wdata[0];
|
||||
txcq_size_reg <= s_axil_wr.wdata[19:16];
|
||||
end
|
||||
16'h0308: txcq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
||||
16'h030c: txcq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
||||
|
||||
16'h0400: begin
|
||||
rxcq_en_reg <= s_axil_wr.wdata[0];
|
||||
rxcq_size_reg <= s_axil_wr.wdata[19:16];
|
||||
end
|
||||
16'h0408: rxcq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
||||
16'h040c: rxcq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
||||
default: begin end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (s_axil_rd.arvalid && !s_axil_rvalid_reg) begin
|
||||
s_axil_rdata_reg <= '0;
|
||||
|
||||
s_axil_arready_reg <= 1'b1;
|
||||
s_axil_rvalid_reg <= 1'b1;
|
||||
|
||||
case ({s_axil_rd.araddr[15:2], 2'b00})
|
||||
16'h0100: begin
|
||||
s_axil_rdata_reg[0] <= txq_en_reg;
|
||||
s_axil_rdata_reg[19:16] <= txq_size_reg;
|
||||
end
|
||||
16'h0104: begin
|
||||
s_axil_rdata_reg[15:0] <= txq_prod_reg;
|
||||
s_axil_rdata_reg[31:16] <= txq_cons;
|
||||
end
|
||||
16'h0108: s_axil_rdata_reg <= txq_base_addr_reg[31:0];
|
||||
16'h010c: s_axil_rdata_reg <= txq_base_addr_reg[63:32];
|
||||
|
||||
16'h0200: begin
|
||||
s_axil_rdata_reg[0] <= rxq_en_reg;
|
||||
s_axil_rdata_reg[19:16] <= rxq_size_reg;
|
||||
end
|
||||
16'h0204: begin
|
||||
s_axil_rdata_reg[15:0] <= rxq_prod_reg;
|
||||
s_axil_rdata_reg[31:16] <= rxq_cons;
|
||||
end
|
||||
16'h0208: s_axil_rdata_reg <= rxq_base_addr_reg[31:0];
|
||||
16'h020c: s_axil_rdata_reg <= rxq_base_addr_reg[63:32];
|
||||
|
||||
16'h0300: begin
|
||||
s_axil_rdata_reg[0] <= txcq_en_reg;
|
||||
s_axil_rdata_reg[19:16] <= txcq_size_reg;
|
||||
end
|
||||
16'h0304: s_axil_rdata_reg[15:0] <= txcq_prod;
|
||||
16'h0308: s_axil_rdata_reg <= txcq_base_addr_reg[31:0];
|
||||
16'h030c: s_axil_rdata_reg <= txcq_base_addr_reg[63:32];
|
||||
|
||||
16'h0400: begin
|
||||
s_axil_rdata_reg[0] <= rxcq_en_reg;
|
||||
s_axil_rdata_reg[19:16] <= rxcq_size_reg;
|
||||
end
|
||||
16'h0404: s_axil_rdata_reg[15:0] <= rxcq_prod;
|
||||
16'h0408: s_axil_rdata_reg <= rxcq_base_addr_reg[31:0];
|
||||
16'h040c: s_axil_rdata_reg <= rxcq_base_addr_reg[63:32];
|
||||
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
|
||||
|
||||
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-1),
|
||||
.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-1),
|
||||
.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[2]();
|
||||
|
||||
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-1)
|
||||
) dma_ram_wr_int[2]();
|
||||
|
||||
taxi_dma_if_mux_rd #(
|
||||
.PORTS(2),
|
||||
.ARB_ROUND_ROBIN(1),
|
||||
.ARB_LSB_HIGH_PRIO(1)
|
||||
)
|
||||
rd_dma_mux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA descriptors from clients
|
||||
*/
|
||||
.client_req(dma_rd_desc_int),
|
||||
.client_sts(dma_rd_desc_int),
|
||||
|
||||
/*
|
||||
* DMA descriptors to DMA engines
|
||||
*/
|
||||
.dma_req(dma_rd_desc_req),
|
||||
.dma_sts(dma_rd_desc_sts),
|
||||
|
||||
/*
|
||||
* RAM interface (from DMA interface)
|
||||
*/
|
||||
.dma_ram_wr(dma_ram_wr),
|
||||
|
||||
/*
|
||||
* RAM interface (towards RAM)
|
||||
*/
|
||||
.client_ram_wr(dma_ram_wr_int)
|
||||
);
|
||||
|
||||
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-1),
|
||||
.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-1),
|
||||
.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[2]();
|
||||
|
||||
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-1)
|
||||
) dma_ram_rd_int[2]();
|
||||
|
||||
taxi_dma_if_mux_wr #(
|
||||
.PORTS(2),
|
||||
.ARB_ROUND_ROBIN(1),
|
||||
.ARB_LSB_HIGH_PRIO(1)
|
||||
)
|
||||
wr_dma_mux_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA descriptors from clients
|
||||
*/
|
||||
.client_req(dma_wr_desc_int),
|
||||
.client_sts(dma_wr_desc_int),
|
||||
|
||||
/*
|
||||
* DMA descriptors to DMA engines
|
||||
*/
|
||||
.dma_req(dma_wr_desc_req),
|
||||
.dma_sts(dma_wr_desc_sts),
|
||||
|
||||
/*
|
||||
* RAM interface (from DMA interface)
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd),
|
||||
|
||||
/*
|
||||
* RAM interface (towards RAM)
|
||||
*/
|
||||
.client_ram_rd(dma_ram_rd_int)
|
||||
);
|
||||
|
||||
wire [1:0] desc_req;
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(16*8),
|
||||
.KEEP_EN(1),
|
||||
.LAST_EN(1),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(1), // TODO
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) axis_desc[2]();
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(16*8),
|
||||
.KEEP_EN(1),
|
||||
.LAST_EN(1),
|
||||
.ID_EN(1), // TODO
|
||||
.DEST_EN(0),
|
||||
.USER_EN(0)
|
||||
) axis_cpl[2]();
|
||||
|
||||
cndm_micro_desc_rd
|
||||
desc_rd_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
.dma_rd_desc_req(dma_rd_desc_int[0]),
|
||||
.dma_rd_desc_sts(dma_rd_desc_int[0]),
|
||||
.dma_ram_wr(dma_ram_wr_int[0]),
|
||||
|
||||
.txq_en(txq_en_reg),
|
||||
.txq_size(txq_size_reg),
|
||||
.txq_base_addr(txq_base_addr_reg),
|
||||
.txq_prod(txq_prod_reg),
|
||||
.txq_cons(txq_cons),
|
||||
.rxq_en(rxq_en_reg),
|
||||
.rxq_size(rxq_size_reg),
|
||||
.rxq_base_addr(rxq_base_addr_reg),
|
||||
.rxq_prod(rxq_prod_reg),
|
||||
.rxq_cons(rxq_cons),
|
||||
|
||||
.desc_req(desc_req),
|
||||
.axis_desc(axis_desc)
|
||||
);
|
||||
|
||||
cndm_micro_cpl_wr
|
||||
cpl_wr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
.dma_wr_desc_req(dma_wr_desc_int[0]),
|
||||
.dma_wr_desc_sts(dma_wr_desc_int[0]),
|
||||
.dma_ram_rd(dma_ram_rd_int[0]),
|
||||
|
||||
.txcq_en(txcq_en_reg),
|
||||
.txcq_size(txcq_size_reg),
|
||||
.txcq_base_addr(txcq_base_addr_reg),
|
||||
.txcq_prod(txcq_prod),
|
||||
.rxcq_en(rxcq_en_reg),
|
||||
.rxcq_size(rxcq_size_reg),
|
||||
.rxcq_base_addr(rxcq_base_addr_reg),
|
||||
.rxcq_prod(rxcq_prod),
|
||||
|
||||
.axis_cpl(axis_cpl),
|
||||
.irq(irq)
|
||||
);
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(mac_axis_tx.DATA_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) mac_tx_int();
|
||||
|
||||
taxi_axis_async_fifo #(
|
||||
.DEPTH(16384),
|
||||
.RAM_PIPELINE(2),
|
||||
.FRAME_FIFO(1),
|
||||
.USER_BAD_FRAME_VALUE(1'b1),
|
||||
.USER_BAD_FRAME_MASK(1'b1),
|
||||
.DROP_OVERSIZE_FRAME(1),
|
||||
.DROP_BAD_FRAME(1),
|
||||
.DROP_WHEN_FULL(1)
|
||||
)
|
||||
tx_fifo (
|
||||
/*
|
||||
* AXI4-Stream input (sink)
|
||||
*/
|
||||
.s_clk(clk),
|
||||
.s_rst(rst),
|
||||
.s_axis(mac_tx_int),
|
||||
|
||||
/*
|
||||
* AXI4-Stream output (source)
|
||||
*/
|
||||
.m_clk(mac_tx_clk),
|
||||
.m_rst(mac_tx_rst),
|
||||
.m_axis(mac_axis_tx),
|
||||
|
||||
/*
|
||||
* Pause
|
||||
*/
|
||||
.s_pause_req(1'b0),
|
||||
.s_pause_ack(),
|
||||
.m_pause_req(1'b0),
|
||||
.m_pause_ack(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.s_status_depth(),
|
||||
.s_status_depth_commit(),
|
||||
.s_status_overflow(),
|
||||
.s_status_bad_frame(),
|
||||
.s_status_good_frame(),
|
||||
.m_status_depth(),
|
||||
.m_status_depth_commit(),
|
||||
.m_status_overflow(),
|
||||
.m_status_bad_frame(),
|
||||
.m_status_good_frame()
|
||||
);
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(mac_axis_tx_cpl.DATA_W),
|
||||
.KEEP_EN(mac_axis_tx_cpl.KEEP_EN),
|
||||
.KEEP_W(mac_axis_tx_cpl.KEEP_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
)
|
||||
mac_tx_cpl_int();
|
||||
|
||||
taxi_axis_async_fifo #(
|
||||
.DEPTH(256),
|
||||
.RAM_PIPELINE(2),
|
||||
.FRAME_FIFO(0),
|
||||
.USER_BAD_FRAME_VALUE(1'b1),
|
||||
.USER_BAD_FRAME_MASK(1'b1),
|
||||
.DROP_OVERSIZE_FRAME(0),
|
||||
.DROP_BAD_FRAME(0),
|
||||
.DROP_WHEN_FULL(0)
|
||||
)
|
||||
tx_cpl_fifo (
|
||||
/*
|
||||
* AXI4-Stream input (sink)
|
||||
*/
|
||||
.s_clk(mac_tx_clk),
|
||||
.s_rst(mac_tx_rst),
|
||||
.s_axis(mac_axis_tx_cpl),
|
||||
|
||||
/*
|
||||
* AXI4-Stream output (source)
|
||||
*/
|
||||
.m_clk(clk),
|
||||
.m_rst(rst),
|
||||
.m_axis(mac_tx_cpl_int),
|
||||
|
||||
/*
|
||||
* Pause
|
||||
*/
|
||||
.s_pause_req(1'b0),
|
||||
.s_pause_ack(),
|
||||
.m_pause_req(1'b0),
|
||||
.m_pause_ack(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.s_status_depth(),
|
||||
.s_status_depth_commit(),
|
||||
.s_status_overflow(),
|
||||
.s_status_bad_frame(),
|
||||
.s_status_good_frame(),
|
||||
.m_status_depth(),
|
||||
.m_status_depth_commit(),
|
||||
.m_status_overflow(),
|
||||
.m_status_bad_frame(),
|
||||
.m_status_good_frame()
|
||||
);
|
||||
|
||||
cndm_micro_tx #(
|
||||
.PTP_TS_EN(PTP_TS_EN)
|
||||
)
|
||||
tx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
.dma_rd_desc_req(dma_rd_desc_int[1]),
|
||||
.dma_rd_desc_sts(dma_rd_desc_int[1]),
|
||||
.dma_ram_wr(dma_ram_wr_int[1]),
|
||||
|
||||
.desc_req(desc_req[0]),
|
||||
.axis_desc(axis_desc[0]),
|
||||
.tx_data(mac_tx_int),
|
||||
.tx_cpl(mac_tx_cpl_int),
|
||||
.axis_cpl(axis_cpl[0])
|
||||
);
|
||||
|
||||
taxi_axis_if #(
|
||||
.DATA_W(mac_axis_rx.DATA_W),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) mac_rx_int();
|
||||
|
||||
taxi_axis_async_fifo #(
|
||||
.DEPTH(16384),
|
||||
.RAM_PIPELINE(2),
|
||||
.FRAME_FIFO(1),
|
||||
.USER_BAD_FRAME_VALUE(1'b1),
|
||||
.USER_BAD_FRAME_MASK(1'b1),
|
||||
.DROP_OVERSIZE_FRAME(1),
|
||||
.DROP_BAD_FRAME(1),
|
||||
.DROP_WHEN_FULL(1)
|
||||
)
|
||||
rx_fifo (
|
||||
/*
|
||||
* AXI4-Stream input (sink)
|
||||
*/
|
||||
.s_clk(mac_rx_clk),
|
||||
.s_rst(mac_rx_rst),
|
||||
.s_axis(mac_axis_rx),
|
||||
|
||||
/*
|
||||
* AXI4-Stream output (source)
|
||||
*/
|
||||
.m_clk(clk),
|
||||
.m_rst(rst),
|
||||
.m_axis(mac_rx_int),
|
||||
|
||||
/*
|
||||
* Pause
|
||||
*/
|
||||
.s_pause_req(1'b0),
|
||||
.s_pause_ack(),
|
||||
.m_pause_req(1'b0),
|
||||
.m_pause_ack(),
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
.s_status_depth(),
|
||||
.s_status_depth_commit(),
|
||||
.s_status_overflow(),
|
||||
.s_status_bad_frame(),
|
||||
.s_status_good_frame(),
|
||||
.m_status_depth(),
|
||||
.m_status_depth_commit(),
|
||||
.m_status_overflow(),
|
||||
.m_status_bad_frame(),
|
||||
.m_status_good_frame()
|
||||
);
|
||||
|
||||
cndm_micro_rx #(
|
||||
.PTP_TS_EN(PTP_TS_EN)
|
||||
)
|
||||
rx_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
.dma_wr_desc_req(dma_wr_desc_int[1]),
|
||||
.dma_wr_desc_sts(dma_wr_desc_int[1]),
|
||||
.dma_ram_rd(dma_ram_rd_int[1]),
|
||||
|
||||
.rx_data(mac_rx_int),
|
||||
.desc_req(desc_req[1]),
|
||||
.axis_desc(axis_desc[1]),
|
||||
.axis_cpl(axis_cpl[1])
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
213
src/cndm/rtl/cndm_micro_rx.sv
Normal file
213
src/cndm/rtl/cndm_micro_rx.sv
Normal file
@@ -0,0 +1,213 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro receive datapath
|
||||
*/
|
||||
module cndm_micro_rx #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
taxi_dma_desc_if.req_src dma_wr_desc_req,
|
||||
taxi_dma_desc_if.sts_snk dma_wr_desc_sts,
|
||||
taxi_dma_ram_if.rd_slv dma_ram_rd,
|
||||
|
||||
taxi_axis_if.snk rx_data,
|
||||
output wire logic desc_req,
|
||||
taxi_axis_if.snk axis_desc,
|
||||
taxi_axis_if.src axis_cpl
|
||||
);
|
||||
|
||||
localparam RAM_ADDR_W = 16;
|
||||
|
||||
taxi_dma_desc_if #(
|
||||
.SRC_ADDR_W(RAM_ADDR_W),
|
||||
.SRC_SEL_EN(1'b0),
|
||||
.SRC_ASID_EN(1'b0),
|
||||
.DST_ADDR_W(RAM_ADDR_W),
|
||||
.DST_SEL_EN(1'b0),
|
||||
.DST_ASID_EN(1'b0),
|
||||
.IMM_EN(1'b0),
|
||||
.LEN_W(16),
|
||||
.TAG_W(1),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) dma_desc();
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 0,
|
||||
STATE_RX_DATA = 1,
|
||||
STATE_READ_DESC = 2,
|
||||
STATE_WRITE_DATA = 3;
|
||||
|
||||
logic [2:0] state_reg = STATE_IDLE;
|
||||
|
||||
logic desc_req_reg = 1'b0;
|
||||
|
||||
assign desc_req = desc_req_reg;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
desc_req_reg <= 1'b0;
|
||||
|
||||
axis_desc.tready <= 1'b0;
|
||||
|
||||
dma_wr_desc_req.req_src_sel <= '0;
|
||||
dma_wr_desc_req.req_src_asid <= '0;
|
||||
dma_wr_desc_req.req_dst_sel <= '0;
|
||||
dma_wr_desc_req.req_dst_asid <= '0;
|
||||
dma_wr_desc_req.req_imm <= '0;
|
||||
dma_wr_desc_req.req_imm_en <= '0;
|
||||
dma_wr_desc_req.req_tag <= '0;
|
||||
dma_wr_desc_req.req_id <= '0;
|
||||
dma_wr_desc_req.req_dest <= '0;
|
||||
dma_wr_desc_req.req_user <= '0;
|
||||
dma_wr_desc_req.req_valid <= dma_wr_desc_req.req_valid && !dma_wr_desc_req.req_ready;
|
||||
|
||||
dma_desc.req_src_addr <= '0;
|
||||
dma_desc.req_src_sel <= '0;
|
||||
dma_desc.req_src_asid <= '0;
|
||||
dma_desc.req_dst_addr <= '0;
|
||||
dma_desc.req_dst_sel <= '0;
|
||||
dma_desc.req_dst_asid <= '0;
|
||||
dma_desc.req_imm <= '0;
|
||||
dma_desc.req_imm_en <= '0;
|
||||
dma_desc.req_len <= 4096;
|
||||
dma_desc.req_tag <= '0;
|
||||
dma_desc.req_id <= '0;
|
||||
dma_desc.req_dest <= '0;
|
||||
dma_desc.req_user <= '0;
|
||||
dma_desc.req_valid <= dma_desc.req_valid && !dma_desc.req_ready;
|
||||
|
||||
axis_cpl.tkeep <= '0;
|
||||
axis_cpl.tid <= '0;
|
||||
axis_cpl.tdest <= '0;
|
||||
axis_cpl.tuser <= '0;
|
||||
axis_cpl.tlast <= 1'b1;
|
||||
axis_cpl.tvalid <= axis_cpl.tvalid && !axis_cpl.tready;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
state_reg <= STATE_RX_DATA;
|
||||
end
|
||||
STATE_RX_DATA: begin
|
||||
dma_wr_desc_req.req_len <= 20'(dma_desc.sts_len);
|
||||
axis_cpl.tdata[47:32] <= 16'(dma_desc.sts_len);
|
||||
if (dma_desc.sts_valid) begin
|
||||
desc_req_reg <= 1'b1;
|
||||
state_reg <= STATE_READ_DESC;
|
||||
end
|
||||
end
|
||||
STATE_READ_DESC: begin
|
||||
axis_desc.tready <= 1'b1;
|
||||
|
||||
dma_wr_desc_req.req_src_addr <= '0;
|
||||
dma_wr_desc_req.req_dst_addr <= axis_desc.tdata[127:64];
|
||||
|
||||
if (axis_desc.tvalid && axis_desc.tready) begin
|
||||
if (dma_wr_desc_req.req_len > 20'(axis_desc.tdata[47:32])) begin
|
||||
dma_wr_desc_req.req_len <= 20'(axis_desc.tdata[47:32]);
|
||||
end
|
||||
|
||||
if (axis_desc.tuser) begin
|
||||
// failed to read desc
|
||||
state_reg <= STATE_IDLE;
|
||||
end else begin
|
||||
dma_wr_desc_req.req_valid <= 1'b1;
|
||||
state_reg <= STATE_WRITE_DATA;
|
||||
end
|
||||
end
|
||||
end
|
||||
STATE_WRITE_DATA: begin
|
||||
if (dma_wr_desc_sts.sts_valid) begin
|
||||
axis_cpl.tvalid <= 1'b1;
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
taxi_dma_ram_if #(
|
||||
.SEGS(dma_ram_rd.SEGS),
|
||||
.SEG_ADDR_W(dma_ram_rd.SEG_ADDR_W),
|
||||
.SEG_DATA_W(dma_ram_rd.SEG_DATA_W),
|
||||
.SEG_BE_W(dma_ram_rd.SEG_BE_W)
|
||||
) dma_ram_wr();
|
||||
|
||||
taxi_dma_psdpram #(
|
||||
.SIZE(4096),
|
||||
.PIPELINE(2)
|
||||
)
|
||||
ram_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Write port
|
||||
*/
|
||||
.dma_ram_wr(dma_ram_wr),
|
||||
|
||||
/*
|
||||
* Read port
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd)
|
||||
);
|
||||
|
||||
taxi_dma_client_axis_sink
|
||||
dma_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA descriptor
|
||||
*/
|
||||
.desc_req(dma_desc),
|
||||
.desc_sts(dma_desc),
|
||||
|
||||
/*
|
||||
* AXI stream write data input
|
||||
*/
|
||||
.s_axis_wr_data(rx_data),
|
||||
|
||||
/*
|
||||
* RAM interface
|
||||
*/
|
||||
.dma_ram_wr(dma_ram_wr),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.enable(1),
|
||||
.abort(0)
|
||||
);
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
208
src/cndm/rtl/cndm_micro_tx.sv
Normal file
208
src/cndm/rtl/cndm_micro_tx.sv
Normal file
@@ -0,0 +1,208 @@
|
||||
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||
/*
|
||||
|
||||
Copyright (c) 2025 FPGA Ninja, LLC
|
||||
|
||||
Authors:
|
||||
- Alex Forencich
|
||||
|
||||
*/
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Corundum-micro transmit datapath
|
||||
*/
|
||||
module cndm_micro_tx #(
|
||||
parameter logic PTP_TS_EN = 1'b1
|
||||
)
|
||||
(
|
||||
input wire logic clk,
|
||||
input wire logic rst,
|
||||
|
||||
/*
|
||||
* DMA
|
||||
*/
|
||||
taxi_dma_desc_if.req_src dma_rd_desc_req,
|
||||
taxi_dma_desc_if.sts_snk dma_rd_desc_sts,
|
||||
taxi_dma_ram_if.wr_slv dma_ram_wr,
|
||||
|
||||
output wire logic desc_req,
|
||||
taxi_axis_if.snk axis_desc,
|
||||
taxi_axis_if.src tx_data,
|
||||
taxi_axis_if.snk tx_cpl,
|
||||
taxi_axis_if.src axis_cpl
|
||||
);
|
||||
|
||||
localparam RAM_ADDR_W = 16;
|
||||
|
||||
taxi_dma_desc_if #(
|
||||
.SRC_ADDR_W(RAM_ADDR_W),
|
||||
.SRC_SEL_EN(1'b0),
|
||||
.SRC_ASID_EN(1'b0),
|
||||
.DST_ADDR_W(RAM_ADDR_W),
|
||||
.DST_SEL_EN(1'b0),
|
||||
.DST_ASID_EN(1'b0),
|
||||
.IMM_EN(1'b0),
|
||||
.LEN_W(16),
|
||||
.TAG_W(1),
|
||||
.ID_EN(0),
|
||||
.DEST_EN(0),
|
||||
.USER_EN(1),
|
||||
.USER_W(1)
|
||||
) dma_desc();
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 0,
|
||||
STATE_READ_DESC = 1,
|
||||
STATE_READ_DATA = 2,
|
||||
STATE_TX_DATA = 3;
|
||||
|
||||
logic [2:0] state_reg = STATE_IDLE;
|
||||
|
||||
logic desc_req_reg = 1'b0;
|
||||
|
||||
assign desc_req = desc_req_reg;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
desc_req_reg <= 1'b0;
|
||||
|
||||
axis_desc.tready <= 1'b0;
|
||||
|
||||
dma_rd_desc_req.req_src_sel <= '0;
|
||||
dma_rd_desc_req.req_src_asid <= '0;
|
||||
dma_rd_desc_req.req_dst_sel <= '0;
|
||||
dma_rd_desc_req.req_dst_asid <= '0;
|
||||
dma_rd_desc_req.req_imm <= '0;
|
||||
dma_rd_desc_req.req_imm_en <= '0;
|
||||
dma_rd_desc_req.req_tag <= '0;
|
||||
dma_rd_desc_req.req_id <= '0;
|
||||
dma_rd_desc_req.req_dest <= '0;
|
||||
dma_rd_desc_req.req_user <= '0;
|
||||
dma_rd_desc_req.req_valid <= dma_rd_desc_req.req_valid && !dma_rd_desc_req.req_ready;
|
||||
|
||||
dma_desc.req_src_sel <= '0;
|
||||
dma_desc.req_src_asid <= '0;
|
||||
dma_desc.req_dst_addr <= '0;
|
||||
dma_desc.req_dst_sel <= '0;
|
||||
dma_desc.req_dst_asid <= '0;
|
||||
dma_desc.req_imm <= '0;
|
||||
dma_desc.req_imm_en <= '0;
|
||||
dma_desc.req_tag <= '0;
|
||||
dma_desc.req_id <= '0;
|
||||
dma_desc.req_dest <= '0;
|
||||
dma_desc.req_user <= '0;
|
||||
dma_desc.req_valid <= dma_desc.req_valid && !dma_desc.req_ready;
|
||||
|
||||
axis_cpl.tkeep <= '0;
|
||||
axis_cpl.tid <= '0;
|
||||
axis_cpl.tdest <= '0;
|
||||
axis_cpl.tuser <= '0;
|
||||
axis_cpl.tlast <= 1'b1;
|
||||
axis_cpl.tvalid <= axis_cpl.tvalid && !axis_cpl.tready;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
desc_req_reg <= 1'b1;
|
||||
state_reg <= STATE_READ_DESC;
|
||||
end
|
||||
STATE_READ_DESC: begin
|
||||
axis_desc.tready <= 1'b1;
|
||||
|
||||
dma_rd_desc_req.req_src_addr <= axis_desc.tdata[127:64];
|
||||
dma_rd_desc_req.req_dst_addr <= '0;
|
||||
dma_rd_desc_req.req_len <= 20'(axis_desc.tdata[47:32]);
|
||||
|
||||
dma_desc.req_src_addr <= '0;
|
||||
dma_desc.req_len <= axis_desc.tdata[47:32];
|
||||
|
||||
if (axis_desc.tvalid && axis_desc.tready) begin
|
||||
if (axis_desc.tuser) begin
|
||||
// failed to read desc
|
||||
state_reg <= STATE_IDLE;
|
||||
end else begin
|
||||
dma_rd_desc_req.req_valid <= 1'b1;
|
||||
state_reg <= STATE_READ_DATA;
|
||||
end
|
||||
end
|
||||
end
|
||||
STATE_READ_DATA: begin
|
||||
if (dma_rd_desc_sts.sts_valid) begin
|
||||
dma_desc.req_valid <= 1'b1;
|
||||
state_reg <= STATE_TX_DATA;
|
||||
end
|
||||
end
|
||||
STATE_TX_DATA: begin
|
||||
if (dma_desc.sts_valid) begin
|
||||
axis_cpl.tvalid <= 1'b1;
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
endcase
|
||||
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
taxi_dma_ram_if #(
|
||||
.SEGS(dma_ram_wr.SEGS),
|
||||
.SEG_ADDR_W(dma_ram_wr.SEG_ADDR_W),
|
||||
.SEG_DATA_W(dma_ram_wr.SEG_DATA_W),
|
||||
.SEG_BE_W(dma_ram_wr.SEG_BE_W)
|
||||
) dma_ram_rd();
|
||||
|
||||
taxi_dma_psdpram #(
|
||||
.SIZE(4096),
|
||||
.PIPELINE(2)
|
||||
)
|
||||
ram_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Write port
|
||||
*/
|
||||
.dma_ram_wr(dma_ram_wr),
|
||||
|
||||
/*
|
||||
* Read port
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd)
|
||||
);
|
||||
|
||||
taxi_dma_client_axis_source
|
||||
dma_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* DMA descriptor
|
||||
*/
|
||||
.desc_req(dma_desc),
|
||||
.desc_sts(dma_desc),
|
||||
|
||||
/*
|
||||
* AXI stream read data output
|
||||
*/
|
||||
.m_axis_rd_data(tx_data),
|
||||
|
||||
/*
|
||||
* RAM interface
|
||||
*/
|
||||
.dma_ram_rd(dma_ram_rd),
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
*/
|
||||
.enable(1'b1)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
||||
Reference in New Issue
Block a user