Compare commits

...

10 Commits

Author SHA1 Message Date
Alex Forencich
ce8da1bc59 cndm: Fully share SQ/RQ HW resources
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-06 15:23:20 -08:00
Alex Forencich
d0c9ae0637 cndm: Avoid using parameters from interfaces defined in the same module
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-06 15:06:12 -08:00
Alex Forencich
a46b012c91 cndm: Widen internal datapath to prevent CDC-related bottlenecks
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-06 15:04:12 -08:00
Alex Forencich
595d744aa4 cndm: Add qtype field to queue state to enable sharing
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 22:12:39 -08:00
Alex Forencich
8263ebab24 cndm: Move SQ/RQ state into distributed RAM
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 20:49:35 -08:00
Alex Forencich
7dbe6df56a cndm: Peel off queue management logic, store queue state in distributed RAM
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 18:04:43 -08:00
Alex Forencich
8f1c082174 cndm: Rework driver model to support multiple queues
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 16:50:33 -08:00
Alex Forencich
39c9dce0fa cndm: Check for queue allocation failures in the driver
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 15:47:03 -08:00
Alex Forencich
f8764d581d cndm: Check for queue allocation failures in the driver model
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-05 15:46:30 -08:00
Alex Forencich
cce4c4525e cndm: Move queue setup/teardown into netdev open/close
Signed-off-by: Alex Forencich <alex@alexforencich.com>
2026-03-04 16:47:30 -08:00
16 changed files with 1084 additions and 629 deletions

View File

@@ -136,6 +136,9 @@ struct cndm_cq {
struct cndm_ring *src_ring;
void (*handler)(struct cndm_cq *cq);
u32 db_offset;
u8 __iomem *db_addr;
};
struct cndm_priv {
@@ -157,9 +160,7 @@ struct cndm_priv {
int txq_count;
struct cndm_ring *txq;
struct cndm_cq *txcq;
struct cndm_ring *rxq;
struct cndm_cq *rxcq;
};
// cndm_cmd.c

View File

@@ -27,6 +27,9 @@ struct cndm_cq *cndm_create_cq(struct cndm_priv *priv)
cq->cons_ptr = 0;
cq->db_offset = 0;
cq->db_addr = NULL;
return cq;
}
@@ -74,10 +77,20 @@ int cndm_open_cq(struct cndm_cq *cq, int irqn, int size)
cndm_exec_cmd(cq->cdev, &cmd, &rsp);
if (rsp.dboffs == 0) {
netdev_err(cq->priv->ndev, "Failed to allocate CQ");
ret = -1;
goto fail;
}
cq->cqn = rsp.qn;
cq->db_offset = rsp.dboffs;
cq->db_addr = cq->cdev->hw_addr + rsp.dboffs;
cq->enabled = 1;
netdev_dbg(cq->priv->ndev, "Opened CQ %d", cq->cqn);
return 0;
fail:
@@ -102,6 +115,8 @@ void cndm_close_cq(struct cndm_cq *cq)
cndm_exec_cmd(cdev, &cmd, &rsp);
cq->cqn = -1;
cq->db_offset = 0;
cq->db_addr = NULL;
}
if (cq->buf) {

View File

@@ -9,54 +9,168 @@ Authors:
*/
#include "cndm.h"
#include "cndm_hw.h"
#include <linux/version.h>
static int cndm_close(struct net_device *ndev);
static int cndm_open(struct net_device *ndev)
{
struct cndm_priv *priv = netdev_priv(ndev);
struct cndm_ring *q;
struct cndm_cq *cq;
int k;
int ret = 0;
cndm_refill_rx_buffers(priv->rxq);
netdev_info(ndev, "Open port");
priv->txq->tx_queue = netdev_get_tx_queue(ndev, 0);
netif_set_real_num_tx_queues(ndev, priv->txq_count);
netif_set_real_num_rx_queues(ndev, priv->rxq_count);
netif_napi_add_tx(ndev, &priv->txcq->napi, cndm_poll_tx_cq);
napi_enable(&priv->txcq->napi);
netif_napi_add(ndev, &priv->rxcq->napi, cndm_poll_rx_cq);
napi_enable(&priv->rxcq->napi);
// set up RX queues
for (k = 0; k < priv->rxq_count; k++) {
if (priv->rxq)
break;
cq = cndm_create_cq(priv);
if (IS_ERR_OR_NULL(cq)) {
ret = PTR_ERR(cq);
goto fail;
}
ret = cndm_open_cq(cq, 0, 256);
if (ret) {
cndm_destroy_cq(cq);
goto fail;
}
q = cndm_create_rq(priv);
if (IS_ERR_OR_NULL(q)) {
ret = PTR_ERR(q);
cndm_destroy_cq(cq);
goto fail;
}
ret = cndm_open_rq(q, priv, cq, 256);
if (ret) {
cndm_destroy_rq(q);
cndm_destroy_cq(cq);
goto fail;
}
priv->rxq = q;
netif_napi_add(ndev, &cq->napi, cndm_poll_rx_cq);
napi_enable(&cq->napi);
}
// set up TX queues
for (k = 0; k < priv->txq_count; k++) {
if (priv->txq)
break;
cq = cndm_create_cq(priv);
if (IS_ERR_OR_NULL(cq)) {
ret = PTR_ERR(cq);
goto fail;
}
ret = cndm_open_cq(cq, 0, 256);
if (ret) {
cndm_destroy_cq(cq);
goto fail;
}
q = cndm_create_sq(priv);
if (IS_ERR_OR_NULL(q)) {
ret = PTR_ERR(q);
cndm_destroy_cq(cq);
goto fail;
}
q->tx_queue = netdev_get_tx_queue(ndev, k);
ret = cndm_open_sq(q, priv, cq, 256);
if (ret) {
cndm_destroy_sq(q);
cndm_destroy_cq(cq);
goto fail;
}
priv->txq = q;
netif_napi_add_tx(ndev, &cq->napi, cndm_poll_tx_cq);
napi_enable(&cq->napi);
}
netif_tx_start_all_queues(ndev);
netif_carrier_on(ndev);
netif_device_attach(ndev);
netif_carrier_on(ndev);
priv->port_up = 1;
return 0;
fail:
cndm_close(ndev);
return ret;
}
static int cndm_close(struct net_device *ndev)
{
struct cndm_priv *priv = netdev_priv(ndev);
struct cndm_ring *q;
struct cndm_cq *cq;
int k;
netdev_info(ndev, "Close port");
if (!priv->port_up)
return 0;
priv->port_up = 0;
if (priv->txcq) {
napi_disable(&priv->txcq->napi);
netif_napi_del(&priv->txcq->napi);
}
if (priv->rxcq) {
napi_disable(&priv->rxcq->napi);
netif_napi_del(&priv->rxcq->napi);
}
netif_tx_lock_bh(ndev);
netif_tx_stop_all_queues(ndev);
netif_tx_unlock_bh(ndev);
netif_carrier_off(ndev);
netif_tx_disable(ndev);
priv->port_up = 0;
// clean up TX queues
for (k = 0; k < priv->txq_count; k++) {
if (!priv->txq)
break;
q = priv->txq;
cq = q->cq;
napi_disable(&cq->napi);
netif_napi_del(&cq->napi);
cndm_destroy_sq(q);
cndm_destroy_cq(cq);
priv->txq = NULL;
}
// clean up RX queues
for (k = 0; k < priv->rxq_count; k++) {
if (!priv->rxq)
break;
q = priv->rxq;
cq = q->cq;
napi_disable(&cq->napi);
netif_napi_del(&cq->napi);
cndm_destroy_rq(q);
cndm_destroy_cq(cq);
priv->rxq = NULL;
}
return 0;
}
@@ -171,8 +285,8 @@ static int cndm_netdev_irq(struct notifier_block *nb, unsigned long action, void
netdev_dbg(priv->ndev, "Interrupt");
if (priv->port_up) {
napi_schedule_irqoff(&priv->txcq->napi);
napi_schedule_irqoff(&priv->rxcq->napi);
napi_schedule_irqoff(&priv->txq->cq->napi);
napi_schedule_irqoff(&priv->rxq->cq->napi);
}
return NOTIFY_DONE;
@@ -226,54 +340,6 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
ndev->min_mtu = ETH_MIN_MTU;
ndev->max_mtu = 1500;
priv->rxcq = cndm_create_cq(priv);
if (IS_ERR_OR_NULL(priv->rxcq)) {
ret = PTR_ERR(priv->rxcq);
goto fail;
}
ret = cndm_open_cq(priv->rxcq, 0, 256);
if (ret) {
cndm_destroy_cq(priv->rxcq);
priv->rxcq = NULL;
goto fail;
}
priv->rxq = cndm_create_rq(priv);
if (IS_ERR_OR_NULL(priv->rxq)) {
ret = PTR_ERR(priv->rxq);
goto fail;
}
ret = cndm_open_rq(priv->rxq, priv, priv->rxcq, 256);
if (ret) {
cndm_destroy_rq(priv->rxq);
priv->rxq = NULL;
goto fail;
}
priv->txcq = cndm_create_cq(priv);
if (IS_ERR_OR_NULL(priv->txcq)) {
ret = PTR_ERR(priv->txcq);
goto fail;
}
ret = cndm_open_cq(priv->txcq, 0, 256);
if (ret) {
cndm_destroy_cq(priv->txcq);
priv->txcq = NULL;
goto fail;
}
priv->txq = cndm_create_sq(priv);
if (IS_ERR_OR_NULL(priv->txq)) {
ret = PTR_ERR(priv->txq);
goto fail;
}
ret = cndm_open_sq(priv->txq, priv, priv->txcq, 256);
if (ret) {
cndm_destroy_sq(priv->txq);
priv->txq = NULL;
goto fail;
}
netif_carrier_off(ndev);
ret = register_netdev(ndev);
@@ -292,7 +358,6 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
goto fail;
}
return ndev;
fail:
@@ -304,40 +369,13 @@ void cndm_destroy_netdev(struct net_device *ndev)
{
struct cndm_priv *priv = netdev_priv(ndev);
if (priv->port_up)
cndm_close(ndev);
if (priv->txq) {
cndm_close_sq(priv->txq);
cndm_destroy_sq(priv->txq);
priv->txq = NULL;
}
if (priv->txcq) {
cndm_close_cq(priv->txcq);
cndm_destroy_cq(priv->txcq);
priv->txcq = NULL;
}
if (priv->rxq) {
cndm_close_rq(priv->rxq);
cndm_destroy_rq(priv->rxq);
priv->rxq = NULL;
}
if (priv->rxcq) {
cndm_close_cq(priv->rxcq);
cndm_destroy_cq(priv->rxcq);
priv->rxcq = NULL;
}
if (priv->registered)
unregister_netdev(ndev);
if (priv->irq)
atomic_notifier_chain_unregister(&priv->irq->nh, &priv->irq_nb);
priv->irq = NULL;
if (priv->registered)
unregister_netdev(ndev);
free_netdev(ndev);
}

View File

@@ -87,12 +87,20 @@ int cndm_open_rq(struct cndm_ring *rq, struct cndm_priv *priv, struct cndm_cq *c
cndm_exec_cmd(rq->cdev, &cmd, &rsp);
if (rsp.dboffs == 0) {
netdev_err(rq->priv->ndev, "Failed to allocate RQ");
ret = -1;
goto fail;
}
rq->index = rsp.qn;
rq->db_offset = rsp.dboffs;
rq->db_addr = priv->cdev->hw_addr + rsp.dboffs;
rq->db_addr = rq->cdev->hw_addr + rsp.dboffs;
rq->enabled = 1;
netdev_dbg(cq->priv->ndev, "Opened RQ %d (CQ %d)", rq->index, cq->cqn);
ret = cndm_refill_rx_buffers(rq);
if (ret) {
netdev_err(priv->ndev, "failed to allocate RX buffer for RX queue index %d (of %u total) entry index %u (of %u total)",
@@ -135,6 +143,8 @@ void cndm_close_rq(struct cndm_ring *rq)
cndm_exec_cmd(cdev, &cmd, &rsp);
rq->index = -1;
rq->db_offset = 0;
rq->db_addr = NULL;
}
if (rq->buf) {

View File

@@ -87,12 +87,20 @@ int cndm_open_sq(struct cndm_ring *sq, struct cndm_priv *priv, struct cndm_cq *c
cndm_exec_cmd(sq->cdev, &cmd, &rsp);
if (rsp.dboffs == 0) {
netdev_err(sq->priv->ndev, "Failed to allocate SQ");
ret = -1;
goto fail;
}
sq->index = rsp.qn;
sq->db_offset = rsp.dboffs;
sq->db_addr = priv->cdev->hw_addr + rsp.dboffs;
sq->db_addr = sq->cdev->hw_addr + rsp.dboffs;
sq->enabled = 1;
netdev_dbg(cq->priv->ndev, "Opened SQ %d (CQ %d)", sq->index, cq->cqn);
return 0;
fail:
@@ -124,6 +132,8 @@ void cndm_close_sq(struct cndm_ring *sq)
cndm_exec_cmd(cdev, &cmd, &rsp);
sq->index = -1;
sq->db_offset = 0;
sq->db_addr = NULL;
}
if (sq->buf) {

View File

@@ -4,6 +4,7 @@ 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
@@ -14,7 +15,7 @@ cndm_micro_cpl_wr.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.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

View File

@@ -36,6 +36,10 @@ module cndm_micro_core #(
// 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,
@@ -300,16 +304,23 @@ cmd_mbox_inst (
// datapath manager
localparam APB_DP_ADDR_W = 16+$clog2(PORTS+PORT_OFFSET_DP);
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(16+$clog2(PORTS+PORT_OFFSET_DP))
.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)
)
@@ -337,7 +348,7 @@ apb_port_dp_ctrl[PORT_OFFSET_DP+PORTS]();
taxi_apb_interconnect #(
.M_CNT($size(apb_port_dp_ctrl)),
.ADDR_W(apb_dp_ctrl.ADDR_W),
.ADDR_W(APB_DP_ADDR_W),
.M_REGIONS(1),
.M_BASE_ADDR('0),
.M_ADDR_W({$size(apb_port_dp_ctrl){{1{32'd16}}}}),
@@ -490,6 +501,11 @@ dma_mux_inst (
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)
)

View File

@@ -1,7 +1,7 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2025 FPGA Ninja, LLC
Copyright (c) 2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
@@ -15,7 +15,9 @@ Authors:
/*
* Corundum-micro completion write module
*/
module cndm_micro_cpl_wr
module cndm_micro_cpl_wr #(
parameter CQN_W = 5
)
(
input wire logic clk,
input wire logic rst,
@@ -42,168 +44,59 @@ module cndm_micro_cpl_wr
output wire logic irq
);
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
localparam DMA_ADDR_W = dma_wr_desc_req.DST_ADDR_W;
localparam APB_ADDR_W = s_apb_dp_ctrl.ADDR_W;
localparam APB_DATA_W = s_apb_dp_ctrl.DATA_W;
logic [CQN_W-1:0] cq_req_cqn_reg = '0;
logic cq_req_valid_reg = 1'b0;
logic cq_req_ready;
logic [DMA_ADDR_W-1:0] cq_rsp_addr;
logic cq_rsp_phase_tag;
logic cq_rsp_error;
logic cq_rsp_valid;
logic cq_rsp_ready_reg = 1'b0;
logic txcq_en_reg = '0;
logic [3:0] txcq_size_reg = '0;
logic [63:0] txcq_base_addr_reg = '0;
logic rxcq_en_reg = '0;
logic [3:0] rxcq_size_reg = '0;
logic [63:0] rxcq_base_addr_reg = '0;
cndm_micro_queue_state #(
.QN_W(CQN_W),
.DQN_W(CQN_W), // TODO
.IS_CQ(1),
.QTYPE_EN(0),
.QE_SIZE(16),
.DMA_ADDR_W(DMA_ADDR_W)
)
cq_mgr_inst (
.clk(clk),
.rst(rst),
logic [15:0] txcq_prod_ptr_reg = '0;
logic [15:0] rxcq_prod_ptr_reg = '0;
/*
* Control register interface
*/
.s_axil_ctrl_wr(s_axil_ctrl_wr),
.s_axil_ctrl_rd(s_axil_ctrl_rd),
logic s_axil_ctrl_awready_reg = 1'b0;
logic s_axil_ctrl_wready_reg = 1'b0;
logic s_axil_ctrl_bvalid_reg = 1'b0;
/*
* Datapath control register interface
*/
.s_apb_dp_ctrl(s_apb_dp_ctrl),
logic s_axil_ctrl_arready_reg = 1'b0;
logic [AXIL_DATA_W-1:0] s_axil_ctrl_rdata_reg = '0;
logic s_axil_ctrl_rvalid_reg = 1'b0;
assign s_axil_ctrl_wr.awready = s_axil_ctrl_awready_reg;
assign s_axil_ctrl_wr.wready = s_axil_ctrl_wready_reg;
assign s_axil_ctrl_wr.bresp = '0;
assign s_axil_ctrl_wr.buser = '0;
assign s_axil_ctrl_wr.bvalid = s_axil_ctrl_bvalid_reg;
assign s_axil_ctrl_rd.arready = s_axil_ctrl_arready_reg;
assign s_axil_ctrl_rd.rdata = s_axil_ctrl_rdata_reg;
assign s_axil_ctrl_rd.rresp = '0;
assign s_axil_ctrl_rd.ruser = '0;
assign s_axil_ctrl_rd.rvalid = s_axil_ctrl_rvalid_reg;
logic s_apb_dp_ctrl_pready_reg = 1'b0;
logic [AXIL_DATA_W-1:0] s_apb_dp_ctrl_prdata_reg = '0;
assign s_apb_dp_ctrl.pready = s_apb_dp_ctrl_pready_reg;
assign s_apb_dp_ctrl.prdata = s_apb_dp_ctrl_prdata_reg;
assign s_apb_dp_ctrl.pslverr = 1'b0;
assign s_apb_dp_ctrl.pruser = '0;
assign s_apb_dp_ctrl.pbuser = '0;
always_ff @(posedge clk) begin
s_axil_ctrl_awready_reg <= 1'b0;
s_axil_ctrl_wready_reg <= 1'b0;
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_reg && !s_axil_ctrl_wr.bready;
s_axil_ctrl_arready_reg <= 1'b0;
s_axil_ctrl_rvalid_reg <= s_axil_ctrl_rvalid_reg && !s_axil_ctrl_rd.rready;
s_apb_dp_ctrl_pready_reg <= 1'b0;
if (s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
s_axil_ctrl_awready_reg <= 1'b1;
s_axil_ctrl_wready_reg <= 1'b1;
s_axil_ctrl_bvalid_reg <= 1'b1;
// case ({s_axil_ctrl_wr.awaddr[9:2], 2'b00})
// 10'h000: begin
// txcq_en_reg <= s_axil_ctrl_wr.wdata[0];
// txcq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
// end
// 10'h008: txcq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
// 10'h00c: txcq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
// 10'h100: begin
// rxcq_en_reg <= s_axil_ctrl_wr.wdata[0];
// rxcq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
// end
// 10'h108: rxcq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
// 10'h10c: rxcq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
// default: begin end
// endcase
end
if (s_axil_ctrl_rd.arvalid && !s_axil_ctrl_rvalid_reg) begin
s_axil_ctrl_rdata_reg <= '0;
s_axil_ctrl_arready_reg <= 1'b1;
s_axil_ctrl_rvalid_reg <= 1'b1;
// case ({s_axil_ctrl_rd.araddr[9:2], 2'b00})
// 10'h000: begin
// s_axil_ctrl_rdata_reg[0] <= txcq_en_reg;
// s_axil_ctrl_rdata_reg[19:16] <= txcq_size_reg;
// end
// 10'h004: s_axil_ctrl_rdata_reg[15:0] <= txcq_prod_ptr_reg;
// 10'h008: s_axil_ctrl_rdata_reg <= txcq_base_addr_reg[31:0];
// 10'h00c: s_axil_ctrl_rdata_reg <= txcq_base_addr_reg[63:32];
// 10'h100: begin
// s_axil_ctrl_rdata_reg[0] <= rxcq_en_reg;
// s_axil_ctrl_rdata_reg[19:16] <= rxcq_size_reg;
// end
// 10'h104: s_axil_ctrl_rdata_reg[15:0] <= rxcq_prod_ptr_reg;
// 10'h108: s_axil_ctrl_rdata_reg <= rxcq_base_addr_reg[31:0];
// 10'h10c: s_axil_ctrl_rdata_reg <= rxcq_base_addr_reg[63:32];
// default: begin end
// endcase
end
if (s_apb_dp_ctrl.penable && s_apb_dp_ctrl.psel && !s_apb_dp_ctrl_pready_reg) begin
s_apb_dp_ctrl_pready_reg <= 1'b1;
s_apb_dp_ctrl_prdata_reg <= '0;
if (s_apb_dp_ctrl.pwrite) begin
case ({s_apb_dp_ctrl.paddr[9:2], 2'b00})
10'h000: begin
txcq_en_reg <= s_apb_dp_ctrl.pwdata[0];
txcq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
end
10'h008: txcq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
10'h00c: txcq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
10'h100: begin
rxcq_en_reg <= s_apb_dp_ctrl.pwdata[0];
rxcq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
end
10'h108: rxcq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
10'h10c: rxcq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
default: begin end
endcase
end
case ({s_apb_dp_ctrl.paddr[9:2], 2'b00})
10'h000: begin
s_apb_dp_ctrl_prdata_reg[0] <= txcq_en_reg;
s_apb_dp_ctrl_prdata_reg[19:16] <= txcq_size_reg;
end
10'h004: s_apb_dp_ctrl_prdata_reg[15:0] <= txcq_prod_ptr_reg;
10'h008: s_apb_dp_ctrl_prdata_reg <= txcq_base_addr_reg[31:0];
10'h00c: s_apb_dp_ctrl_prdata_reg <= txcq_base_addr_reg[63:32];
10'h100: begin
s_apb_dp_ctrl_prdata_reg[0] <= rxcq_en_reg;
s_apb_dp_ctrl_prdata_reg[19:16] <= rxcq_size_reg;
end
10'h104: s_apb_dp_ctrl_prdata_reg[15:0] <= rxcq_prod_ptr_reg;
10'h108: s_apb_dp_ctrl_prdata_reg <= rxcq_base_addr_reg[31:0];
10'h10c: s_apb_dp_ctrl_prdata_reg <= rxcq_base_addr_reg[63:32];
default: begin end
endcase
end
if (rst) begin
s_axil_ctrl_awready_reg <= 1'b0;
s_axil_ctrl_wready_reg <= 1'b0;
s_axil_ctrl_bvalid_reg <= 1'b0;
s_axil_ctrl_arready_reg <= 1'b0;
s_axil_ctrl_rvalid_reg <= 1'b0;
s_apb_dp_ctrl_pready_reg <= 1'b0;
end
end
/*
* Queue management interface
*/
.req_qn(cq_req_cqn_reg),
.req_qtype('0),
.req_valid(cq_req_valid_reg),
.req_ready(cq_req_ready),
.rsp_qn(),
.rsp_dqn(),
.rsp_addr(cq_rsp_addr),
.rsp_phase_tag(cq_rsp_phase_tag),
.rsp_error(cq_rsp_error),
.rsp_valid(cq_rsp_valid),
.rsp_ready(cq_rsp_ready_reg)
);
typedef enum logic [1:0] {
STATE_IDLE,
STATE_RX_CPL,
STATE_QUERY_CQ,
STATE_WRITE_DATA
} state_t;
@@ -231,13 +124,8 @@ always_ff @(posedge clk) begin
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_reg) begin
txcq_prod_ptr_reg <= '0;
end
if (!rxcq_en_reg) begin
rxcq_prod_ptr_reg <= '0;
end
cq_req_valid_reg <= cq_req_valid_reg && !cq_req_ready;
cq_rsp_ready_reg <= 1'b0;
irq_reg <= 1'b0;
@@ -245,29 +133,32 @@ always_ff @(posedge clk) begin
STATE_IDLE: begin
dma_wr_desc_req.req_src_addr <= '0;
if (s_axis_cpl.tdest == 0) begin
dma_wr_desc_req.req_dst_addr <= txcq_base_addr_reg + 64'(16'(txcq_prod_ptr_reg & ({16{1'b1}} >> (16 - txcq_size_reg))) * 16);
phase_tag_reg <= !txcq_prod_ptr_reg[txcq_size_reg];
if (s_axis_cpl.tvalid && !s_axis_cpl.tready) begin
txcq_prod_ptr_reg <= txcq_prod_ptr_reg + 1;
if (txcq_en_reg) begin
dma_wr_desc_req.req_valid <= 1'b1;
state_reg <= STATE_WRITE_DATA;
end else begin
state_reg <= STATE_IDLE;
end
end
cq_req_cqn_reg <= s_axis_cpl.tdest;
if (s_axis_cpl.tvalid && !s_axis_cpl.tready) begin
cq_req_valid_reg <= 1'b1;
state_reg <= STATE_QUERY_CQ;
end else begin
dma_wr_desc_req.req_dst_addr <= rxcq_base_addr_reg + 64'(16'(rxcq_prod_ptr_reg & ({16{1'b1}} >> (16 - rxcq_size_reg))) * 16);
phase_tag_reg <= !rxcq_prod_ptr_reg[rxcq_size_reg];
if (s_axis_cpl.tvalid && !s_axis_cpl.tready) begin
rxcq_prod_ptr_reg <= rxcq_prod_ptr_reg + 1;
if (rxcq_en_reg) begin
dma_wr_desc_req.req_valid <= 1'b1;
state_reg <= STATE_WRITE_DATA;
end else begin
state_reg <= STATE_IDLE;
end
state_reg <= STATE_IDLE;
end
end
STATE_QUERY_CQ: begin
dma_wr_desc_req.req_src_addr <= '0;
cq_rsp_ready_reg <= 1'b1;
if (cq_rsp_valid && cq_rsp_ready_reg) begin
cq_rsp_ready_reg <= 1'b0;
dma_wr_desc_req.req_dst_addr <= cq_rsp_addr;
phase_tag_reg <= cq_rsp_phase_tag;
if (cq_rsp_error) begin
// drop completion
s_axis_cpl.tready <= 1'b1;
state_reg <= STATE_IDLE;
end else begin
dma_wr_desc_req.req_valid <= 1'b1;
state_reg <= STATE_WRITE_DATA;
end
end
end
@@ -285,8 +176,8 @@ always_ff @(posedge clk) begin
if (rst) begin
state_reg <= STATE_IDLE;
txcq_prod_ptr_reg <= '0;
rxcq_prod_ptr_reg <= '0;
cq_req_valid_reg <= 1'b0;
cq_rsp_ready_reg <= 1'b0;
irq_reg <= 1'b0;
end
end

View File

@@ -15,7 +15,10 @@ Authors:
/*
* Corundum-micro descriptor read module
*/
module cndm_micro_desc_rd
module cndm_micro_desc_rd #(
parameter WQN_W = 5,
parameter CQN_W = 5
)
(
input wire logic clk,
input wire logic rst,
@@ -38,194 +41,69 @@ module cndm_micro_desc_rd
taxi_dma_desc_if.sts_snk dma_rd_desc_sts,
taxi_dma_ram_if.wr_slv dma_ram_wr,
input wire logic [1:0] desc_req,
taxi_axis_if.snk s_axis_desc_req,
taxi_axis_if.src m_axis_desc
);
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
localparam APB_ADDR_W = s_apb_dp_ctrl.ADDR_W;
localparam APB_DATA_W = s_apb_dp_ctrl.DATA_W;
localparam DMA_ADDR_W = dma_rd_desc_req.SRC_ADDR_W;
localparam RAM_ADDR_W = 16;
logic txq_en_reg = '0;
logic [3:0] txq_size_reg = '0;
logic [7:0] txq_cqn_reg = '0;
logic [63:0] txq_base_addr_reg = '0;
logic [15:0] txq_prod_reg = '0;
logic rxq_en_reg = '0;
logic [3:0] rxq_size_reg = '0;
logic [7:0] rxq_cqn_reg = '0;
logic [63:0] rxq_base_addr_reg = '0;
logic [15:0] rxq_prod_reg = '0;
typedef enum logic [2:0] {
QTYPE_EQ,
QTYPE_CQ,
QTYPE_SQ,
QTYPE_RQ
} qtype_t;
logic [15:0] txq_cons_ptr_reg = '0;
logic [15:0] rxq_cons_ptr_reg = '0;
logic [WQN_W-1:0] wq_req_wqn_reg = '0;
logic [2:0] wq_req_qtype_reg = '0;
logic wq_req_valid_reg = 1'b0;
logic wq_req_ready;
logic [CQN_W-1:0] wq_rsp_cqn;
logic [DMA_ADDR_W-1:0] wq_rsp_addr;
logic wq_rsp_error;
logic wq_rsp_valid;
logic wq_rsp_ready_reg = 1'b0;
logic s_axil_ctrl_awready_reg = 1'b0;
logic s_axil_ctrl_wready_reg = 1'b0;
logic s_axil_ctrl_bvalid_reg = 1'b0;
cndm_micro_queue_state #(
.QN_W(WQN_W),
.DQN_W(CQN_W),
.IS_CQ(0),
.QTYPE_EN(1),
.QE_SIZE(16),
.DMA_ADDR_W(DMA_ADDR_W)
)
wq_mgr_inst (
.clk(clk),
.rst(rst),
logic s_axil_ctrl_arready_reg = 1'b0;
logic [AXIL_DATA_W-1:0] s_axil_ctrl_rdata_reg = '0;
logic s_axil_ctrl_rvalid_reg = 1'b0;
/*
* Control register interface
*/
.s_axil_ctrl_wr(s_axil_ctrl_wr),
.s_axil_ctrl_rd(s_axil_ctrl_rd),
assign s_axil_ctrl_wr.awready = s_axil_ctrl_awready_reg;
assign s_axil_ctrl_wr.wready = s_axil_ctrl_wready_reg;
assign s_axil_ctrl_wr.bresp = '0;
assign s_axil_ctrl_wr.buser = '0;
assign s_axil_ctrl_wr.bvalid = s_axil_ctrl_bvalid_reg;
/*
* Datapath control register interface
*/
.s_apb_dp_ctrl(s_apb_dp_ctrl),
assign s_axil_ctrl_rd.arready = s_axil_ctrl_arready_reg;
assign s_axil_ctrl_rd.rdata = s_axil_ctrl_rdata_reg;
assign s_axil_ctrl_rd.rresp = '0;
assign s_axil_ctrl_rd.ruser = '0;
assign s_axil_ctrl_rd.rvalid = s_axil_ctrl_rvalid_reg;
logic s_apb_dp_ctrl_pready_reg = 1'b0;
logic [AXIL_DATA_W-1:0] s_apb_dp_ctrl_prdata_reg = '0;
assign s_apb_dp_ctrl.pready = s_apb_dp_ctrl_pready_reg;
assign s_apb_dp_ctrl.prdata = s_apb_dp_ctrl_prdata_reg;
assign s_apb_dp_ctrl.pslverr = 1'b0;
assign s_apb_dp_ctrl.pruser = '0;
assign s_apb_dp_ctrl.pbuser = '0;
always_ff @(posedge clk) begin
s_axil_ctrl_awready_reg <= 1'b0;
s_axil_ctrl_wready_reg <= 1'b0;
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_reg && !s_axil_ctrl_wr.bready;
s_axil_ctrl_arready_reg <= 1'b0;
s_axil_ctrl_rvalid_reg <= s_axil_ctrl_rvalid_reg && !s_axil_ctrl_rd.rready;
s_apb_dp_ctrl_pready_reg <= 1'b0;
if (s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
s_axil_ctrl_awready_reg <= 1'b1;
s_axil_ctrl_wready_reg <= 1'b1;
s_axil_ctrl_bvalid_reg <= 1'b1;
case ({s_axil_ctrl_wr.awaddr[9:2], 2'b00})
// 10'h000: begin
// txq_en_reg <= s_axil_ctrl_wr.wdata[0];
// txq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
// end
10'h004: txq_prod_reg <= s_axil_ctrl_wr.wdata[15:0];
// 10'h008: txq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
// 10'h00c: txq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
// 10'h100: begin
// rxq_en_reg <= s_axil_ctrl_wr.wdata[0];
// rxq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
// end
10'h104: rxq_prod_reg <= s_axil_ctrl_wr.wdata[15:0];
// 10'h108: rxq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
// 10'h10c: rxq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
default: begin end
endcase
end
if (s_axil_ctrl_rd.arvalid && !s_axil_ctrl_rvalid_reg) begin
s_axil_ctrl_rdata_reg <= '0;
s_axil_ctrl_arready_reg <= 1'b1;
s_axil_ctrl_rvalid_reg <= 1'b1;
// case ({s_axil_ctrl_rd.araddr[9:2], 2'b00})
// 10'h000: begin
// s_axil_ctrl_rdata_reg[0] <= txq_en_reg;
// s_axil_ctrl_rdata_reg[19:16] <= txq_size_reg;
// end
// 10'h004: begin
// s_axil_ctrl_rdata_reg[15:0] <= txq_prod_reg;
// s_axil_ctrl_rdata_reg[31:16] <= txq_cons_ptr_reg;
// end
// 10'h008: s_axil_ctrl_rdata_reg <= txq_base_addr_reg[31:0];
// 10'h00c: s_axil_ctrl_rdata_reg <= txq_base_addr_reg[63:32];
// 10'h100: begin
// s_axil_ctrl_rdata_reg[0] <= rxq_en_reg;
// s_axil_ctrl_rdata_reg[19:16] <= rxq_size_reg;
// end
// 10'h104: begin
// s_axil_ctrl_rdata_reg[15:0] <= rxq_prod_reg;
// s_axil_ctrl_rdata_reg[31:16] <= rxq_cons_ptr_reg;
// end
// 10'h108: s_axil_ctrl_rdata_reg <= rxq_base_addr_reg[31:0];
// 10'h10c: s_axil_ctrl_rdata_reg <= rxq_base_addr_reg[63:32];
// default: begin end
// endcase
end
if (s_apb_dp_ctrl.penable && s_apb_dp_ctrl.psel && !s_apb_dp_ctrl_pready_reg) begin
s_apb_dp_ctrl_pready_reg <= 1'b1;
s_apb_dp_ctrl_prdata_reg <= '0;
if (s_apb_dp_ctrl.pwrite) begin
case ({s_apb_dp_ctrl.paddr[9:2], 2'b00})
10'h000: begin
txq_en_reg <= s_apb_dp_ctrl.pwdata[0];
txq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
txq_cqn_reg <= s_apb_dp_ctrl.pwdata[31:24];
end
10'h004: txq_prod_reg <= s_apb_dp_ctrl.pwdata[15:0];
10'h008: txq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
10'h00c: txq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
10'h100: begin
rxq_en_reg <= s_apb_dp_ctrl.pwdata[0];
rxq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
rxq_cqn_reg <= s_apb_dp_ctrl.pwdata[31:24];
end
10'h104: rxq_prod_reg <= s_apb_dp_ctrl.pwdata[15:0];
10'h108: rxq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
10'h10c: rxq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
default: begin end
endcase
end
case ({s_apb_dp_ctrl.paddr[9:2], 2'b00})
10'h000: begin
s_apb_dp_ctrl_prdata_reg[0] <= txq_en_reg;
s_apb_dp_ctrl_prdata_reg[19:16] <= txq_size_reg;
s_apb_dp_ctrl_prdata_reg[31:24] <= txq_cqn_reg;
end
10'h004: begin
s_apb_dp_ctrl_prdata_reg[15:0] <= txq_prod_reg;
s_apb_dp_ctrl_prdata_reg[31:16] <= txq_cons_ptr_reg;
end
10'h008: s_apb_dp_ctrl_prdata_reg <= txq_base_addr_reg[31:0];
10'h00c: s_apb_dp_ctrl_prdata_reg <= txq_base_addr_reg[63:32];
10'h100: begin
s_apb_dp_ctrl_prdata_reg[0] <= rxq_en_reg;
s_apb_dp_ctrl_prdata_reg[19:16] <= rxq_size_reg;
s_apb_dp_ctrl_prdata_reg[31:24] <= rxq_cqn_reg;
end
10'h104: begin
s_apb_dp_ctrl_prdata_reg[15:0] <= rxq_prod_reg;
s_apb_dp_ctrl_prdata_reg[31:16] <= rxq_cons_ptr_reg;
end
10'h108: s_apb_dp_ctrl_prdata_reg <= rxq_base_addr_reg[31:0];
10'h10c: s_apb_dp_ctrl_prdata_reg <= rxq_base_addr_reg[63:32];
default: begin end
endcase
end
if (rst) begin
s_axil_ctrl_awready_reg <= 1'b0;
s_axil_ctrl_wready_reg <= 1'b0;
s_axil_ctrl_bvalid_reg <= 1'b0;
s_axil_ctrl_arready_reg <= 1'b0;
s_axil_ctrl_rvalid_reg <= 1'b0;
s_apb_dp_ctrl_pready_reg <= 1'b0;
end
end
/*
* Queue management interface
*/
.req_qn(wq_req_wqn_reg),
.req_qtype(wq_req_qtype_reg),
.req_valid(wq_req_valid_reg),
.req_ready(wq_req_ready),
.rsp_qn(),
.rsp_dqn(wq_rsp_cqn),
.rsp_addr(wq_rsp_addr),
.rsp_phase_tag(),
.rsp_error(wq_rsp_error),
.rsp_valid(wq_rsp_valid),
.rsp_ready(wq_rsp_ready_reg)
);
taxi_dma_desc_if #(
.SRC_ADDR_W(RAM_ADDR_W),
@@ -247,18 +125,18 @@ taxi_dma_desc_if #(
typedef enum logic [1:0] {
STATE_IDLE,
STATE_QUERY_WQ,
STATE_READ_DESC,
STATE_READ_DATA,
STATE_TX_DESC
} state_t;
state_t state_reg = STATE_IDLE;
logic [1:0] desc_req_reg = '0;
logic s_axis_desc_req_tready_reg = 1'b0;
assign s_axis_desc_req.tready = s_axis_desc_req_tready_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;
@@ -284,46 +162,45 @@ always_ff @(posedge clk) begin
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;
wq_req_valid_reg <= wq_req_valid_reg && !wq_req_ready;
wq_rsp_ready_reg <= 1'b0;
if (!txq_en_reg) begin
txq_cons_ptr_reg <= '0;
end
if (!rxq_en_reg) begin
rxq_cons_ptr_reg <= '0;
end
s_axis_desc_req_tready_reg <= 1'b0;
case (state_reg)
STATE_IDLE: begin
if (desc_req_reg[1]) begin
dma_rd_desc_req.req_src_addr <= rxq_base_addr_reg + 64'(16'(rxq_cons_ptr_reg & ({16{1'b1}} >> (16 - rxq_size_reg))) * 16);
dma_desc.req_id <= 1'b1;
dma_desc.req_dest <= rxq_cqn_reg;
desc_req_reg[1] <= 1'b0;
if (rxq_cons_ptr_reg == rxq_prod_reg || !rxq_en_reg) begin
s_axis_desc_req_tready_reg <= 1'b1;
if (s_axis_desc_req.tvalid && s_axis_desc_req.tready) begin
s_axis_desc_req_tready_reg <= 1'b0;
wq_req_wqn_reg <= s_axis_desc_req.tdest;
wq_req_qtype_reg <= s_axis_desc_req.tuser;
wq_req_valid_reg <= 1'b1;
dma_desc.req_id <= s_axis_desc_req.tid;
state_reg <= STATE_QUERY_WQ;
end else begin
state_reg <= STATE_IDLE;
end
end
STATE_QUERY_WQ: begin
wq_rsp_ready_reg <= 1'b1;
if (wq_rsp_valid && wq_rsp_ready_reg) begin
wq_rsp_ready_reg <= 1'b0;
dma_rd_desc_req.req_src_addr <= wq_rsp_addr;
dma_desc.req_dest <= wq_rsp_cqn;
if (wq_rsp_error) begin
// report error
dma_desc.req_user <= 1'b1;
dma_desc.req_valid <= 1'b1;
state_reg <= STATE_TX_DESC;
end else begin
// read desc
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_reg + 64'(16'(txq_cons_ptr_reg & ({16{1'b1}} >> (16 - txq_size_reg))) * 16);
dma_desc.req_id <= 1'b0;
dma_desc.req_dest <= txq_cqn_reg;
desc_req_reg[0] <= 1'b0;
if (txq_cons_ptr_reg == txq_prod_reg || !txq_en_reg) 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

View File

@@ -18,10 +18,20 @@ Authors:
module cndm_micro_dp_mgr #
(
parameter PORTS = 2,
parameter WQN_W = 5,
parameter CQN_W = WQN_W,
parameter logic PTP_EN = 1'b1,
parameter PTP_BASE_ADDR_DP = 0,
parameter PORT_BASE_ADDR_DP = 0,
parameter PORT_BASE_ADDR_HOST = 0
parameter PORT_BASE_ADDR_HOST = 0,
parameter PORT_STRIDE = 'h10000,
parameter WQ_REG_STRIDE = 32,
parameter QM_OFFSET = 'h0000,
parameter CQM_OFFSET = 'h4000,
parameter PORT_CTRL_OFFSET = 'h8000
)
(
input wire logic clk,
@@ -76,6 +86,13 @@ typedef enum logic [15:0] {
CMD_OP_DESTROY_QP = 16'h0243
} cmd_opcode_t;
typedef enum logic [2:0] {
QTYPE_EQ,
QTYPE_CQ,
QTYPE_SQ,
QTYPE_RQ
} qtype_t;
typedef enum logic [4:0] {
STATE_IDLE,
STATE_START,
@@ -86,9 +103,12 @@ typedef enum logic [4:0] {
STATE_CREATE_Q_FIND_2,
STATE_CREATE_Q_RESET_1,
STATE_CREATE_Q_RESET_2,
STATE_CREATE_Q_RESET_3,
STATE_CREATE_Q_SET_BASE_L,
STATE_CREATE_Q_SET_BASE_H,
STATE_CREATE_Q_SET_DQN,
STATE_CREATE_Q_ENABLE,
STATE_CREATE_Q_PORT_CONFIG,
STATE_DESTROY_Q_DISABLE,
STATE_PTP_READ_1,
STATE_PTP_READ_2,
@@ -155,6 +175,7 @@ logic [31:0] flags_reg = '0, flags_next;
logic [15:0] port_reg = '0, port_next;
logic [23:0] qn_reg = '0, qn_next;
logic [23:0] qn2_reg = '0, qn2_next;
logic [2:0] qtype_reg = '0, qtype_next;
logic [3:0] cmd_ptr_reg = '0, cmd_ptr_next;
logic [DP_APB_ADDR_W-1:0] dp_ptr_reg = '0, dp_ptr_next;
@@ -194,6 +215,7 @@ always_comb begin
port_next = port_reg;
qn_next = qn_reg;
qn2_next = qn2_reg;
qtype_next = qtype_reg;
cmd_ptr_next = cmd_ptr_reg;
dp_ptr_next = dp_ptr_reg;
@@ -247,9 +269,9 @@ always_comb begin
// determine block base address
case (opcode_reg)
// // EQ
// CMD_OP_CREATE_EQ:
// begin
// // EQ
// qn_next = 0;
// dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h8000) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
// host_ptr_next = 32'({port_reg, 16'd0} | 'h8000) + PORT_BASE_ADDR_HOST;
@@ -258,54 +280,56 @@ always_comb begin
// CMD_OP_QUERY_EQ,
// CMD_OP_DESTROY_EQ:
// begin
// // EQ
// dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h8000) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
// host_ptr_next = 32'({port_reg, 16'd0} | 'h8000) + PORT_BASE_ADDR_HOST;
// end
// CQ
CMD_OP_CREATE_CQ:
begin
// CQ
cnt_next = 1;
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h8000) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h8000) + PORT_BASE_ADDR_HOST;
cnt_next = 2**CQN_W-1;
qtype_next = QTYPE_CQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + CQM_OFFSET + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + CQM_OFFSET + PORT_BASE_ADDR_HOST;
end
CMD_OP_MODIFY_CQ,
CMD_OP_QUERY_CQ,
CMD_OP_DESTROY_CQ:
begin
// CQ
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h8000 | {qn_reg, 8'd00}) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h8000 | {qn_reg, 8'd00}) + PORT_BASE_ADDR_HOST;
qtype_next = QTYPE_CQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + CQM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + CQM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_HOST;
end
// SQ
CMD_OP_CREATE_SQ:
begin
// SQ
cnt_next = 0;
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0000) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0000) + PORT_BASE_ADDR_HOST;
cnt_next = 2**WQN_W-1;
qtype_next = QTYPE_SQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + QM_OFFSET + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + QM_OFFSET + PORT_BASE_ADDR_HOST;
end
CMD_OP_MODIFY_SQ,
CMD_OP_QUERY_SQ,
CMD_OP_DESTROY_SQ:
begin
// SQ
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0000) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0000) + PORT_BASE_ADDR_HOST;
qtype_next = QTYPE_SQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + QM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + QM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_HOST;
end
// RQ
CMD_OP_CREATE_RQ:
begin
// RQ
cnt_next = 0;
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0100) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0100) + PORT_BASE_ADDR_HOST;
cnt_next = 2**WQN_W-1;
qtype_next = QTYPE_RQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + QM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + QM_OFFSET + (qn_reg * WQ_REG_STRIDE) + PORT_BASE_ADDR_HOST;
end
CMD_OP_MODIFY_RQ,
CMD_OP_QUERY_RQ,
CMD_OP_DESTROY_RQ:
begin
// RQ
dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0100) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0100) + PORT_BASE_ADDR_HOST;
qtype_next = QTYPE_RQ;
dp_ptr_next = DP_APB_ADDR_W'((port_reg * PORT_STRIDE) + QM_OFFSET + PORT_BASE_ADDR_DP);
host_ptr_next = (port_reg * PORT_STRIDE) + QM_OFFSET + PORT_BASE_ADDR_HOST;
end
default: begin end
endcase
@@ -470,7 +494,8 @@ always_comb begin
end else begin
// queue is active
qn_next = qn_reg + 1;
dp_ptr_next = dp_ptr_reg + 'h100;
dp_ptr_next = dp_ptr_reg + WQ_REG_STRIDE;
host_ptr_next = host_ptr_reg + WQ_REG_STRIDE;
if (cnt_reg == 0) begin
// no more queues
m_axis_rsp_tdata_next = '0; // TODO
@@ -511,12 +536,27 @@ always_comb begin
// reset queue 2
// store doorbell offset
cmd_ram_wr_data = host_ptr_reg + 'h0004;
cmd_ram_wr_data = host_ptr_reg + 'h0008;
cmd_ram_wr_addr = 7;
cmd_ram_wr_en = 1'b1;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0004;
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0008;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = 32'h00000000;
m_apb_dp_ctrl_pstrb_next = '1;
state_next = STATE_CREATE_Q_RESET_3;
end else begin
state_next = STATE_CREATE_Q_RESET_2;
end
end
STATE_CREATE_Q_RESET_3: begin
// reset queue 2
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h000c;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = 32'h00000000;
@@ -524,14 +564,14 @@ always_comb begin
state_next = STATE_CREATE_Q_SET_BASE_L;
end else begin
state_next = STATE_CREATE_Q_RESET_2;
state_next = STATE_CREATE_Q_RESET_3;
end
end
STATE_CREATE_Q_SET_BASE_L: begin
// set queue base addr (LSB)
cmd_ram_rd_addr = 8;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0008;
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0018;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data;
@@ -546,7 +586,7 @@ always_comb begin
// set queue base addr (MSB)
cmd_ram_rd_addr = 9;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h000C;
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h001C;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data;
@@ -554,7 +594,22 @@ always_comb begin
state_next = STATE_CREATE_Q_ENABLE;
end else begin
state_next = STATE_CREATE_Q_SET_BASE_H;
state_next = STATE_CREATE_Q_SET_DQN;
end
end
STATE_CREATE_Q_SET_DQN: begin
// set CQN/EQN/IRQN
cmd_ram_rd_addr = 4;
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0004;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data;
m_apb_dp_ctrl_pstrb_next = '1;
state_next = STATE_CREATE_Q_ENABLE;
end else begin
state_next = STATE_CREATE_Q_SET_DQN;
end
end
STATE_CREATE_Q_ENABLE: begin
@@ -565,9 +620,27 @@ always_comb begin
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = '0;
m_apb_dp_ctrl_pwdata_next[31:24] = qn2_reg[7:0];
m_apb_dp_ctrl_pwdata_next[19:16] = cmd_ram_rd_data[3:0];
m_apb_dp_ctrl_pwdata_next[0] = 1'b1;
m_apb_dp_ctrl_pwdata_next[23:20] = 4'(qtype_reg); // type
m_apb_dp_ctrl_pwdata_next[19:16] = cmd_ram_rd_data[3:0]; // size
m_apb_dp_ctrl_pwdata_next[0] = 1'b1; // enable
m_apb_dp_ctrl_pstrb_next = '1;
state_next = STATE_CREATE_Q_PORT_CONFIG;
end else begin
state_next = STATE_CREATE_Q_ENABLE;
end
end
STATE_CREATE_Q_PORT_CONFIG: begin
// set up port
if (!m_apb_dp_ctrl_psel_reg) begin
if (qtype_reg == QTYPE_SQ) begin
m_apb_dp_ctrl_paddr_next = DP_APB_ADDR_W'(PORT_BASE_ADDR_DP + (port_reg * PORT_STRIDE) + PORT_CTRL_OFFSET + 'h0010);
end else begin
m_apb_dp_ctrl_paddr_next = DP_APB_ADDR_W'(PORT_BASE_ADDR_DP + (port_reg * PORT_STRIDE) + PORT_CTRL_OFFSET + 'h0020);
end
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = qtype_reg == QTYPE_SQ || qtype_reg == QTYPE_RQ;
m_apb_dp_ctrl_pwdata_next = 32'(qn_reg);
m_apb_dp_ctrl_pstrb_next = '1;
m_axis_rsp_tdata_next = '0; // TODO
@@ -576,7 +649,7 @@ always_comb begin
state_next = STATE_SEND_RSP;
end else begin
state_next = STATE_CREATE_Q_ENABLE;
state_next = STATE_CREATE_Q_PORT_CONFIG;
end
end
STATE_DESTROY_Q_DISABLE: begin
@@ -822,6 +895,7 @@ always_ff @(posedge clk) begin
port_reg <= port_next;
qn_reg <= qn_next;
qn2_reg <= qn2_next;
qtype_reg <= qtype_next;
cmd_ptr_reg <= cmd_ptr_next;
dp_ptr_reg <= dp_ptr_next;

View File

@@ -36,6 +36,9 @@ module cndm_micro_pcie_us #(
// 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,
@@ -510,6 +513,9 @@ cndm_micro_core #(
// 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),

View File

@@ -16,6 +16,11 @@ Authors:
* Corundum-micro port module
*/
module cndm_micro_port #(
// 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
)
@@ -69,15 +74,20 @@ module cndm_micro_port #(
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
localparam APB_ADDR_W = s_apb_dp_ctrl.ADDR_W;
localparam APB_DATA_W = s_apb_dp_ctrl.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_ADDR_W = 14;
taxi_axil_if #(
.DATA_W(s_axil_ctrl_wr.DATA_W),
.ADDR_W(15),
.ADDR_W(PORT_ADDR_W),
.STRB_W(s_axil_ctrl_wr.STRB_W),
.AWUSER_EN(s_axil_ctrl_wr.AWUSER_EN),
.AWUSER_W(s_axil_ctrl_wr.AWUSER_W),
@@ -97,7 +107,7 @@ taxi_axil_interconnect_1s #(
.ADDR_W(s_axil_ctrl_wr.ADDR_W),
.M_REGIONS(1),
.M_BASE_ADDR('0),
.M_ADDR_W({$size(axil_ctrl){{1{32'd15}}}}),
.M_ADDR_W({$size(axil_ctrl){{1{32'd14}}}}),
.M_SECURE({$size(axil_ctrl){1'b0}})
)
port_intercon_inst (
@@ -119,16 +129,16 @@ port_intercon_inst (
taxi_apb_if #(
.DATA_W(32),
.ADDR_W(15)
.ADDR_W(PORT_ADDR_W)
)
apb_dp_ctrl[2]();
apb_dp_ctrl[3]();
taxi_apb_interconnect #(
.M_CNT($size(apb_dp_ctrl)),
.ADDR_W(s_apb_dp_ctrl.ADDR_W),
.M_REGIONS(1),
.M_BASE_ADDR('0),
.M_ADDR_W({$size(apb_dp_ctrl){{1{32'd15}}}}),
.M_ADDR_W({$size(apb_dp_ctrl){{1{32'd14}}}}),
.M_SECURE({$size(apb_dp_ctrl){1'b0}})
)
port_dp_intercon_inst (
@@ -146,6 +156,47 @@ port_dp_intercon_inst (
.m_apb(apb_dp_ctrl)
);
// Port control registers
logic apb_dp_ctrl_pready_reg = 1'b0;
logic [APB_DATA_W-1:0] apb_dp_ctrl_prdata_reg = '0;
assign apb_dp_ctrl[2].pready = apb_dp_ctrl_pready_reg;
assign apb_dp_ctrl[2].prdata = apb_dp_ctrl_prdata_reg;
assign apb_dp_ctrl[2].pslverr = 1'b0;
assign apb_dp_ctrl[2].pruser = '0;
assign apb_dp_ctrl[2].pbuser = '0;
logic [WQN_W-1:0] tx_queue_reg = '0;
logic [WQN_W-1:0] rx_queue_reg = '0;
always_ff @(posedge clk) begin
apb_dp_ctrl_pready_reg <= 1'b0;
if (apb_dp_ctrl[2].penable && apb_dp_ctrl[2].psel && !apb_dp_ctrl_pready_reg) begin
apb_dp_ctrl_pready_reg <= 1'b1;
apb_dp_ctrl_prdata_reg <= '0;
if (apb_dp_ctrl[2].pwrite) begin
case (8'({apb_dp_ctrl[2].paddr >> 2, 2'b00}))
8'h10: tx_queue_reg <= WQN_W'(apb_dp_ctrl[2].pwdata);
8'h20: rx_queue_reg <= WQN_W'(apb_dp_ctrl[2].pwdata);
default: begin end
endcase
end
case (8'({apb_dp_ctrl[2].paddr >> 2, 2'b00}))
8'h10: apb_dp_ctrl_prdata_reg <= 32'(tx_queue_reg);
8'h20: apb_dp_ctrl_prdata_reg <= 32'(rx_queue_reg);
default: begin end
endcase
end
if (rst) begin
apb_dp_ctrl_pready_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),
@@ -262,7 +313,50 @@ wr_dma_mux_inst (
);
// descriptor fetch
wire [1:0] desc_req;
taxi_axis_if #(
.DATA_W(8),
.KEEP_EN(0),
.LAST_EN(1),
.ID_EN(1),
.ID_W(1),
.DEST_EN(1),
.DEST_W(WQN_W),
.USER_EN(1),
.USER_W(3)
) axis_desc_req();
taxi_axis_if #(
.DATA_W(8),
.KEEP_EN(0),
.LAST_EN(1),
.ID_EN(1),
.ID_W(1),
.DEST_EN(1),
.DEST_W(WQN_W),
.USER_EN(1),
.USER_W(3)
) axis_desc_req_txrx[2]();
taxi_axis_arb_mux #(
.S_COUNT(2),
.UPDATE_TID(1),
.ARB_ROUND_ROBIN(0),
.ARB_LSB_HIGH_PRIO(0) // prefer RX requests
)
desc_req_mux_inst (
.clk(clk),
.rst(rst),
/*
* AXI4-Stream input (sink)
*/
.s_axis(axis_desc_req_txrx),
/*
* AXI4-Stream output (source)
*/
.m_axis(axis_desc_req)
);
taxi_axis_if #(
.DATA_W(16*8),
@@ -271,12 +365,15 @@ taxi_axis_if #(
.ID_EN(1),
.ID_W(1),
.DEST_EN(1),
.DEST_W(8),
.DEST_W(WQN_W),
.USER_EN(1),
.USER_W(1)
) axis_desc();
cndm_micro_desc_rd
cndm_micro_desc_rd #(
.WQN_W(WQN_W),
.CQN_W(CQN_W)
)
desc_rd_inst (
.clk(clk),
.rst(rst),
@@ -299,22 +396,21 @@ desc_rd_inst (
.dma_rd_desc_sts(dma_rd_desc_int[0]),
.dma_ram_wr(dma_ram_wr_int[0]),
.desc_req(desc_req),
.s_axis_desc_req(axis_desc_req),
.m_axis_desc(axis_desc)
);
// desc demux
taxi_axis_if #(
.DATA_W(axis_desc.DATA_W),
.KEEP_EN(axis_desc.KEEP_EN),
.KEEP_W(axis_desc.KEEP_W),
.LAST_EN(axis_desc.LAST_EN),
.ID_EN(axis_desc.ID_EN),
.ID_W(axis_desc.ID_W),
.DEST_EN(axis_desc.DEST_EN),
.DEST_W(axis_desc.DEST_W),
.USER_EN(axis_desc.USER_EN),
.USER_W(axis_desc.USER_W)
.DATA_W(16*8),
.KEEP_EN(1),
.LAST_EN(1),
.ID_EN(1),
.ID_W(1),
.DEST_EN(1),
.DEST_W(WQN_W),
.USER_EN(1),
.USER_W(1)
) axis_desc_txrx[2]();
taxi_axis_demux #(
@@ -350,21 +446,18 @@ taxi_axis_if #(
.LAST_EN(1),
.ID_EN(0),
.DEST_EN(1),
.DEST_W(8),
.DEST_W(CQN_W),
.USER_EN(0)
) axis_cpl();
taxi_axis_if #(
.DATA_W(axis_cpl.DATA_W),
.KEEP_EN(axis_cpl.KEEP_EN),
.KEEP_W(axis_cpl.KEEP_W),
.LAST_EN(axis_cpl.LAST_EN),
.ID_EN(axis_cpl.ID_EN),
.ID_W(axis_cpl.ID_W),
.DEST_EN(axis_cpl.DEST_EN),
.DEST_W(axis_cpl.DEST_W),
.USER_EN(axis_cpl.USER_EN),
.USER_W(axis_cpl.USER_W)
.DATA_W(16*8),
.KEEP_EN(1),
.LAST_EN(1),
.ID_EN(0),
.DEST_EN(1),
.DEST_W(CQN_W),
.USER_EN(0)
) axis_cpl_txrx[2]();
taxi_axis_arb_mux #(
@@ -387,7 +480,9 @@ cpl_mux_inst (
.m_axis(axis_cpl)
);
cndm_micro_cpl_wr
cndm_micro_cpl_wr #(
.CQN_W(CQN_W)
)
cpl_wr_inst (
.clk(clk),
.rst(rst),
@@ -416,12 +511,12 @@ cpl_wr_inst (
// TX path
taxi_axis_if #(
.DATA_W(mac_axis_tx.DATA_W),
.DATA_W(mac_axis_tx.DATA_W*2),
.USER_EN(1),
.USER_W(1)
) mac_tx_int();
taxi_axis_async_fifo #(
taxi_axis_async_fifo_adapter #(
.DEPTH(16384),
.RAM_PIPELINE(2),
.FRAME_FIFO(1),
@@ -527,6 +622,8 @@ tx_cpl_fifo (
);
cndm_micro_tx #(
.WQN_W(WQN_W),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
)
@@ -548,7 +645,8 @@ tx_inst (
.dma_rd_desc_sts(dma_rd_desc_int[1]),
.dma_ram_wr(dma_ram_wr_int[1]),
.desc_req(desc_req[0]),
.tx_queue(tx_queue_reg),
.m_axis_desc_req(axis_desc_req_txrx[0]),
.s_axis_desc(axis_desc_txrx[0]),
.tx_data(mac_tx_int),
.tx_cpl(mac_tx_cpl_int),
@@ -557,13 +655,13 @@ tx_inst (
// RX path
taxi_axis_if #(
.DATA_W(mac_axis_rx.DATA_W),
.DATA_W(mac_axis_rx.DATA_W*2),
.USER_EN(1),
.USER_W(mac_axis_rx.USER_W)
) mac_rx_int();
taxi_axis_async_fifo #(
.DEPTH(16384),
taxi_axis_async_fifo_adapter #(
.DEPTH(32768),
.RAM_PIPELINE(2),
.FRAME_FIFO(1),
.USER_BAD_FRAME_VALUE(1'b1),
@@ -611,6 +709,8 @@ rx_fifo (
);
cndm_micro_rx #(
.WQN_W(WQN_W),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD)
)
@@ -633,7 +733,8 @@ rx_inst (
.dma_ram_rd(dma_ram_rd_int[1]),
.rx_data(mac_rx_int),
.desc_req(desc_req[1]),
.rx_queue(rx_queue_reg),
.m_axis_desc_req(axis_desc_req_txrx[1]),
.s_axis_desc(axis_desc_txrx[1]),
.m_axis_cpl(axis_cpl_txrx[1])
);

View File

@@ -0,0 +1,341 @@
// SPDX-License-Identifier: CERN-OHL-S-2.0
/*
Copyright (c) 2026 FPGA Ninja, LLC
Authors:
- Alex Forencich
*/
`resetall
`timescale 1ns / 1ps
`default_nettype none
/*
* Corundum-micro queue state manager module
*/
module cndm_micro_queue_state #(
parameter QN_W = 5,
parameter DQN_W = 5,
parameter logic IS_CQ = 1'b0,
parameter logic QTYPE_EN = !IS_CQ,
parameter QE_SIZE = 16,
parameter DMA_ADDR_W = 64
)
(
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,
/*
* Datapath control register interface
*/
taxi_apb_if.slv s_apb_dp_ctrl,
/*
* Queue management interface
*/
input wire logic [QN_W-1:0] req_qn,
input wire logic [2:0] req_qtype,
input wire logic req_valid,
output wire logic req_ready,
output wire logic [QN_W-1:0] rsp_qn,
output wire logic [DQN_W-1:0] rsp_dqn,
output wire logic [DMA_ADDR_W-1:0] rsp_addr,
output wire logic rsp_phase_tag,
output wire logic rsp_error,
output wire logic rsp_valid,
input wire logic rsp_ready
);
localparam PTR_W = 16;
localparam ADDR_W = QN_W+5;
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
localparam APB_ADDR_W = s_apb_dp_ctrl.ADDR_W;
localparam APB_DATA_W = s_apb_dp_ctrl.DATA_W;
// check configuration
if (s_axil_ctrl_rd.DATA_W != 32 || s_axil_ctrl_wr.DATA_W != 32)
$fatal(0, "Error: AXI data width must be 32 (instance %m)");
if (s_axil_ctrl_rd.ADDR_W < ADDR_W || s_axil_ctrl_wr.ADDR_W < ADDR_W)
$fatal(0, "Error: AXI address width is insufficient (instance %m)");
if (s_apb_dp_ctrl.DATA_W != 32)
$fatal(0, "Error: APB data width must be 32 (instance %m)");
if (s_apb_dp_ctrl.ADDR_W < ADDR_W)
$fatal(0, "Error: APB address width is insufficient (instance %m)");
logic s_axil_ctrl_awready_reg = 1'b0, s_axil_ctrl_awready_next;
logic s_axil_ctrl_wready_reg = 1'b0, s_axil_ctrl_wready_next;
logic s_axil_ctrl_bvalid_reg = 1'b0, s_axil_ctrl_bvalid_next;
logic s_axil_ctrl_arready_reg = 1'b0, s_axil_ctrl_arready_next;
logic [AXIL_DATA_W-1:0] s_axil_ctrl_rdata_reg = '0, s_axil_ctrl_rdata_next;
logic s_axil_ctrl_rvalid_reg = 1'b0, s_axil_ctrl_rvalid_next;
assign s_axil_ctrl_wr.awready = s_axil_ctrl_awready_reg;
assign s_axil_ctrl_wr.wready = s_axil_ctrl_wready_reg;
assign s_axil_ctrl_wr.bresp = '0;
assign s_axil_ctrl_wr.buser = '0;
assign s_axil_ctrl_wr.bvalid = s_axil_ctrl_bvalid_reg;
assign s_axil_ctrl_rd.arready = s_axil_ctrl_arready_reg;
assign s_axil_ctrl_rd.rdata = s_axil_ctrl_rdata_reg;
assign s_axil_ctrl_rd.rresp = '0;
assign s_axil_ctrl_rd.ruser = '0;
assign s_axil_ctrl_rd.rvalid = s_axil_ctrl_rvalid_reg;
wire [QN_W-1:0] s_axil_ctrl_awaddr_queue_index = s_axil_ctrl_wr.awaddr[5 +: QN_W];
wire [2:0] s_axil_ctrl_awaddr_reg_index = s_axil_ctrl_wr.awaddr[4:2];
wire [QN_W-1:0] s_axil_ctrl_araddr_queue_index = s_axil_ctrl_rd.araddr[5 +: QN_W];
wire [2:0] s_axil_ctrl_araddr_reg_index = s_axil_ctrl_rd.araddr[4:2];
logic s_apb_dp_ctrl_pready_reg = 1'b0, s_apb_dp_ctrl_pready_next;
logic [AXIL_DATA_W-1:0] s_apb_dp_ctrl_prdata_reg = '0, s_apb_dp_ctrl_prdata_next;
assign s_apb_dp_ctrl.pready = s_apb_dp_ctrl_pready_reg;
assign s_apb_dp_ctrl.prdata = s_apb_dp_ctrl_prdata_reg;
assign s_apb_dp_ctrl.pslverr = 1'b0;
assign s_apb_dp_ctrl.pruser = '0;
assign s_apb_dp_ctrl.pbuser = '0;
wire [QN_W-1:0] s_apb_dp_ctrl_paddr_queue_index = s_apb_dp_ctrl.paddr[5 +: QN_W];
wire [2:0] s_apb_dp_ctrl_paddr_reg_index = s_apb_dp_ctrl.paddr[4:2];
logic req_ready_reg = 1'b0, req_ready_next;
logic [QN_W-1:0] rsp_qn_reg = '0, rsp_qn_next;
logic [DQN_W-1:0] rsp_dqn_reg = '0, rsp_dqn_next;
logic [DMA_ADDR_W-1:0] rsp_addr_reg = '0, rsp_addr_next;
logic rsp_phase_tag_reg = 1'b0, rsp_phase_tag_next;
logic rsp_error_reg = 1'b0, rsp_error_next;
logic rsp_valid_reg = 1'b0, rsp_valid_next;
assign req_ready = req_ready_reg;
assign rsp_qn = rsp_qn_reg;
assign rsp_dqn = rsp_dqn_reg;
assign rsp_addr = rsp_addr_reg;
assign rsp_phase_tag = rsp_phase_tag_reg;
assign rsp_error = rsp_error_reg;
assign rsp_valid = rsp_valid_reg;
logic [2**QN_W-1:0] queue_enable_reg = '0;
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [2:0] queue_mem_qtype[2**QN_W] = '{default: '0};
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [DQN_W-1:0] queue_mem_dqn[2**QN_W] = '{default: '0};
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [3:0] queue_mem_log_size[2**QN_W] = '{default: '0};
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [DMA_ADDR_W-1:0] queue_mem_base_addr[2**QN_W] = '{default: '0};
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [PTR_W-1:0] queue_mem_prod_ptr[2**QN_W] = '{default: '0};
(* ram_style = "distributed", ramstyle = "no_rw_check, mlab" *)
logic [PTR_W-1:0] queue_mem_cons_ptr[2**QN_W] = '{default: '0};
logic queue_mem_wr_en;
logic [QN_W-1:0] queue_mem_addr;
wire queue_mem_rd_enable = queue_enable_reg[queue_mem_addr];
wire [2:0] queue_mem_rd_qtype = queue_mem_qtype[queue_mem_addr];
wire [DQN_W-1:0] queue_mem_rd_dqn = queue_mem_dqn[queue_mem_addr];
wire [3:0] queue_mem_rd_log_size = queue_mem_log_size[queue_mem_addr];
wire [DMA_ADDR_W-1:0] queue_mem_rd_base_addr = queue_mem_base_addr[queue_mem_addr];
wire [PTR_W-1:0] queue_mem_rd_prod_ptr = queue_mem_prod_ptr[queue_mem_addr];
wire [PTR_W-1:0] queue_mem_rd_cons_ptr = queue_mem_cons_ptr[queue_mem_addr];
logic queue_mem_wr_enable;
logic [2:0] queue_mem_wr_qtype;
logic [DQN_W-1:0] queue_mem_wr_dqn;
logic [3:0] queue_mem_wr_log_size;
logic [DMA_ADDR_W-1:0] queue_mem_wr_base_addr;
logic [PTR_W-1:0] queue_mem_wr_prod_ptr;
logic [PTR_W-1:0] queue_mem_wr_cons_ptr;
always_comb begin
s_axil_ctrl_awready_next = 1'b0;
s_axil_ctrl_wready_next = 1'b0;
s_axil_ctrl_bvalid_next = 1'b0;
s_axil_ctrl_arready_next = 1'b0;
s_axil_ctrl_rdata_next = s_axil_ctrl_rdata_reg;
s_axil_ctrl_rvalid_next = 1'b0;
s_apb_dp_ctrl_pready_next = 1'b0;
s_apb_dp_ctrl_prdata_next = s_apb_dp_ctrl_prdata_reg;
req_ready_next = 1'b0;
rsp_qn_next = rsp_qn_reg;
rsp_dqn_next = rsp_dqn_reg;
rsp_addr_next = rsp_addr_reg;
rsp_phase_tag_next = rsp_phase_tag_reg;
rsp_error_next = rsp_error_reg;
rsp_valid_next = rsp_valid_reg && !rsp_ready;
queue_mem_wr_en = 1'b0;
queue_mem_addr = '0;
queue_mem_wr_enable = queue_mem_rd_enable;
queue_mem_wr_qtype = queue_mem_rd_qtype;
queue_mem_wr_dqn = queue_mem_rd_dqn;
queue_mem_wr_log_size = queue_mem_rd_log_size;
queue_mem_wr_base_addr = queue_mem_rd_base_addr;
queue_mem_wr_prod_ptr = queue_mem_rd_prod_ptr;
queue_mem_wr_cons_ptr = queue_mem_rd_cons_ptr;
// terminate AXI lite writes
if (IS_CQ && s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
s_axil_ctrl_awready_next = 1'b1;
s_axil_ctrl_wready_next = 1'b1;
s_axil_ctrl_bvalid_next = 1'b1;
end
// terminate AXI lite reads
if (s_axil_ctrl_rd.arvalid && !s_axil_ctrl_rvalid_reg) begin
s_axil_ctrl_rdata_next = '0;
s_axil_ctrl_arready_next = 1'b1;
s_axil_ctrl_rvalid_next = 1'b1;
end
if (!IS_CQ && s_axil_ctrl_wr.awvalid && s_axil_ctrl_wr.wvalid && !s_axil_ctrl_bvalid_reg) begin
// AXI lite write
s_axil_ctrl_awready_next = 1'b1;
s_axil_ctrl_wready_next = 1'b1;
s_axil_ctrl_bvalid_next = 1'b1;
queue_mem_wr_en = 1'b1;
queue_mem_addr = s_axil_ctrl_awaddr_queue_index;
case (s_axil_ctrl_awaddr_reg_index)
3'd2: queue_mem_wr_prod_ptr = s_axil_ctrl_wr.wdata[15:0];
default: begin end
endcase
end else if (s_apb_dp_ctrl.penable && s_apb_dp_ctrl.psel && !s_apb_dp_ctrl_pready_reg) begin
// APB read/write
s_apb_dp_ctrl_pready_next = 1'b1;
s_apb_dp_ctrl_prdata_next = '0;
queue_mem_addr = s_apb_dp_ctrl_paddr_queue_index;
if (s_apb_dp_ctrl.pwrite) begin
queue_mem_wr_en = 1'b1;
case (s_apb_dp_ctrl_paddr_reg_index)
3'd0: begin
queue_mem_wr_enable = s_apb_dp_ctrl.pwdata[0];
queue_mem_wr_log_size = s_apb_dp_ctrl.pwdata[19:16];
queue_mem_wr_qtype = 3'(s_apb_dp_ctrl.pwdata[23:20]);
end
3'd1: queue_mem_wr_dqn = s_apb_dp_ctrl.pwdata[DQN_W-1:0];
3'd2: queue_mem_wr_prod_ptr = s_apb_dp_ctrl.pwdata[15:0];
3'd3: queue_mem_wr_cons_ptr = s_apb_dp_ctrl.pwdata[15:0];
3'd6: queue_mem_wr_base_addr[31:0] = s_apb_dp_ctrl.pwdata;
3'd7: queue_mem_wr_base_addr[63:32] = s_apb_dp_ctrl.pwdata;
default: begin end
endcase
end
case (s_apb_dp_ctrl_paddr_reg_index)
3'd0: begin
s_apb_dp_ctrl_prdata_next[0] = queue_mem_rd_enable;
s_apb_dp_ctrl_prdata_next[19:16] = queue_mem_rd_log_size;
s_apb_dp_ctrl_prdata_next[23:20] = 4'(queue_mem_rd_qtype);
end
3'd1: s_apb_dp_ctrl_prdata_next = 32'(queue_mem_rd_dqn);
3'd2: s_apb_dp_ctrl_prdata_next[15:0] = queue_mem_rd_prod_ptr;
3'd3: s_apb_dp_ctrl_prdata_next[15:0] = IS_CQ ? '0 : queue_mem_rd_cons_ptr;
3'd6: s_apb_dp_ctrl_prdata_next = queue_mem_rd_base_addr[31:0];
3'd7: s_apb_dp_ctrl_prdata_next = queue_mem_rd_base_addr[63:32];
default: begin end
endcase
end else if (req_valid && !req_ready && (!rsp_valid || rsp_ready)) begin
// completion enqueue request
req_ready_next = 1'b1;
queue_mem_addr = req_qn;
rsp_qn_next = req_qn;
rsp_dqn_next = queue_mem_rd_dqn;
rsp_error_next = !queue_mem_rd_enable || (QTYPE_EN && req_qtype != queue_mem_rd_qtype);
if (IS_CQ) begin
rsp_addr_next = queue_mem_rd_base_addr + DMA_ADDR_W'(16'(queue_mem_rd_prod_ptr & ({16{1'b1}} >> (16 - queue_mem_rd_log_size))) * QE_SIZE);
rsp_phase_tag_next = !queue_mem_rd_prod_ptr[queue_mem_rd_log_size];
queue_mem_wr_prod_ptr = queue_mem_rd_prod_ptr + 1;
end else begin
rsp_addr_next = queue_mem_rd_base_addr + DMA_ADDR_W'(16'(queue_mem_rd_cons_ptr & ({16{1'b1}} >> (16 - queue_mem_rd_log_size))) * QE_SIZE);
if (queue_mem_rd_prod_ptr == queue_mem_rd_cons_ptr)
rsp_error_next = 1'b1;
queue_mem_wr_cons_ptr = queue_mem_rd_cons_ptr + 1;
end
rsp_valid_next = 1'b1;
if (!rsp_error_next) begin
queue_mem_wr_en = 1'b1;
end
end
end
always @(posedge clk) begin
s_axil_ctrl_awready_reg <= s_axil_ctrl_awready_next;
s_axil_ctrl_wready_reg <= s_axil_ctrl_wready_next;
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_next;
s_axil_ctrl_arready_reg <= s_axil_ctrl_arready_next;
s_axil_ctrl_rdata_reg <= s_axil_ctrl_rdata_next;
s_axil_ctrl_rvalid_reg <= s_axil_ctrl_rvalid_next;
s_apb_dp_ctrl_pready_reg <= s_apb_dp_ctrl_pready_next;
s_apb_dp_ctrl_prdata_reg <= s_apb_dp_ctrl_prdata_next;
req_ready_reg <= req_ready_next;
rsp_qn_reg <= rsp_qn_next;
rsp_dqn_reg <= rsp_dqn_next;
rsp_addr_reg <= rsp_addr_next;
rsp_phase_tag_reg <= rsp_phase_tag_next;
rsp_error_reg <= rsp_error_next;
rsp_valid_reg <= rsp_valid_next;
if (queue_mem_wr_en) begin
queue_enable_reg[queue_mem_addr] <= queue_mem_wr_enable;
queue_mem_qtype[queue_mem_addr] <= queue_mem_wr_qtype;
queue_mem_dqn[queue_mem_addr] <= queue_mem_wr_dqn;
queue_mem_log_size[queue_mem_addr] <= queue_mem_wr_log_size;
queue_mem_base_addr[queue_mem_addr] <= queue_mem_wr_base_addr;
queue_mem_prod_ptr[queue_mem_addr] <= queue_mem_wr_prod_ptr;
queue_mem_cons_ptr[queue_mem_addr] <= queue_mem_wr_cons_ptr;
end
if (rst) begin
s_axil_ctrl_awready_reg <= 1'b0;
s_axil_ctrl_wready_reg <= 1'b0;
s_axil_ctrl_bvalid_reg <= 1'b0;
s_axil_ctrl_arready_reg <= 1'b0;
s_axil_ctrl_rvalid_reg <= 1'b0;
s_apb_dp_ctrl_pready_reg <= 1'b0;
req_ready_reg <= 1'b0;
rsp_valid_reg <= 1'b0;
queue_enable_reg <= '0;
end
end
endmodule
`resetall

View File

@@ -16,35 +16,45 @@ Authors:
* Corundum-micro receive datapath
*/
module cndm_micro_rx #(
parameter WQN_W = 5,
parameter logic PTP_TS_EN = 1'b1,
parameter logic PTP_TS_FMT_TOD = 1'b0
)
(
input wire logic clk,
input wire logic rst,
input wire logic clk,
input wire logic rst,
/*
* PTP
*/
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
/*
* 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_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 s_axis_desc,
taxi_axis_if.src m_axis_cpl
taxi_axis_if.snk rx_data,
input wire logic [WQN_W-1:0] rx_queue,
taxi_axis_if.src m_axis_desc_req,
taxi_axis_if.snk s_axis_desc,
taxi_axis_if.src m_axis_cpl
);
localparam RAM_ADDR_W = 16;
typedef enum logic [2:0] {
QTYPE_EQ,
QTYPE_CQ,
QTYPE_SQ,
QTYPE_RQ
} qtype_t;
taxi_dma_desc_if #(
.SRC_ADDR_W(RAM_ADDR_W),
.SRC_SEL_EN(1'b0),
@@ -70,9 +80,18 @@ typedef enum logic [1:0] {
state_t state_reg = STATE_IDLE;
logic desc_req_reg = 1'b0;
logic m_axis_desc_req_tvalid_reg = 1'b0;
logic [WQN_W-1:0] m_axis_desc_req_tdest_reg = '0;
logic [2:0] m_axis_desc_req_tuser_reg = '0;
assign desc_req = desc_req_reg;
assign m_axis_desc_req.tdata = '0;
assign m_axis_desc_req.tkeep = '0;
assign m_axis_desc_req.tstrb = '0;
assign m_axis_desc_req.tlast = 1'b1;
assign m_axis_desc_req.tvalid = m_axis_desc_req_tvalid_reg;
assign m_axis_desc_req.tid = '0;
assign m_axis_desc_req.tdest = rx_queue;
assign m_axis_desc_req.tuser = m_axis_desc_req_tuser_reg;
wire [95:0] rx_ptp_ts;
wire rx_ptp_ts_valid;
@@ -153,7 +172,7 @@ end else begin
end
always_ff @(posedge clk) begin
desc_req_reg <= 1'b0;
m_axis_desc_req_tvalid_reg <= m_axis_desc_req_tvalid_reg && !m_axis_desc_req.tready;
s_axis_desc.tready <= 1'b0;
@@ -205,7 +224,9 @@ always_ff @(posedge clk) begin
dma_wr_desc_req.req_len <= 20'(dma_desc.sts_len);
m_axis_cpl.tdata[47:32] <= 16'(dma_desc.sts_len);
if (dma_desc.sts_valid) begin
desc_req_reg <= 1'b1;
m_axis_desc_req_tvalid_reg <= 1'b1;
m_axis_desc_req_tdest_reg <= rx_queue;
m_axis_desc_req_tuser_reg <= QTYPE_RQ;
state_reg <= STATE_READ_DESC;
end
end

View File

@@ -16,36 +16,46 @@ Authors:
* Corundum-micro transmit datapath
*/
module cndm_micro_tx #(
parameter WQN_W = 5,
parameter logic PTP_TS_EN = 1'b1,
parameter logic PTP_TS_FMT_TOD = 1'b0
)
(
input wire logic clk,
input wire logic rst,
input wire logic clk,
input wire logic rst,
/*
* PTP
*/
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
input wire logic ptp_clk = 1'b0,
input wire logic ptp_rst = 1'b0,
input wire logic ptp_td_sdi = 1'b0,
/*
* 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,
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 s_axis_desc,
taxi_axis_if.src tx_data,
taxi_axis_if.snk tx_cpl,
taxi_axis_if.src m_axis_cpl
input wire logic [WQN_W-1:0] tx_queue,
taxi_axis_if.src m_axis_desc_req,
taxi_axis_if.snk s_axis_desc,
taxi_axis_if.src tx_data,
taxi_axis_if.snk tx_cpl,
taxi_axis_if.src m_axis_cpl
);
localparam RAM_ADDR_W = 16;
typedef enum logic [2:0] {
QTYPE_EQ,
QTYPE_CQ,
QTYPE_SQ,
QTYPE_RQ
} qtype_t;
taxi_dma_desc_if #(
.SRC_ADDR_W(RAM_ADDR_W),
.SRC_SEL_EN(1'b0),
@@ -71,9 +81,18 @@ typedef enum logic [1:0] {
state_t state_reg = STATE_IDLE;
logic desc_req_reg = 1'b0;
logic m_axis_desc_req_tvalid_reg = 1'b0;
logic [WQN_W-1:0] m_axis_desc_req_tdest_reg = '0;
logic [2:0] m_axis_desc_req_tuser_reg = '0;
assign desc_req = desc_req_reg;
assign m_axis_desc_req.tdata = '0;
assign m_axis_desc_req.tkeep = '0;
assign m_axis_desc_req.tstrb = '0;
assign m_axis_desc_req.tlast = 1'b1;
assign m_axis_desc_req.tvalid = m_axis_desc_req_tvalid_reg;
assign m_axis_desc_req.tid = '0;
assign m_axis_desc_req.tdest = m_axis_desc_req_tdest_reg;
assign m_axis_desc_req.tuser = m_axis_desc_req_tuser_reg;
wire [95:0] tx_cpl_ptp_ts;
wire tx_cpl_valid;
@@ -138,7 +157,7 @@ end else begin
end
always_ff @(posedge clk) begin
desc_req_reg <= 1'b0;
m_axis_desc_req_tvalid_reg <= m_axis_desc_req_tvalid_reg && !m_axis_desc_req.tready;
s_axis_desc.tready <= 1'b0;
@@ -175,7 +194,10 @@ always_ff @(posedge clk) begin
case (state_reg)
STATE_IDLE: begin
desc_req_reg <= 1'b1;
m_axis_desc_req_tvalid_reg <= 1'b1;
m_axis_desc_req_tdest_reg <= tx_queue;
m_axis_desc_req_tuser_reg <= QTYPE_SQ;
state_reg <= STATE_READ_DESC;
end
STATE_READ_DESC: begin

View File

@@ -85,6 +85,8 @@ class Cq:
self.cons_ptr = None
self.db_offset = None
self.hw_regs = self.driver.hw_regs
async def open(self, irqn, size):
@@ -128,6 +130,13 @@ class Cq:
rsp_unpacked = struct.unpack("<HHLLLLLLLQQLLLL", rsp)
print(rsp_unpacked)
self.cqn = rsp_unpacked[4]
self.db_offset = rsp_unpacked[8]
if self.db_offset == 0:
self.cqn = None
self.db_offset = None
self.log.error("Failed to allocate CQ")
return
self.log.info("Opened CQ %d", self.cqn)
@@ -242,7 +251,13 @@ class Sq:
self.sqn = rsp_unpacked[4]
self.db_offset = rsp_unpacked[8]
self.log.info("Opened SQ %d", self.sqn)
if self.db_offset == 0:
self.sqn = None
self.db_offset = None
self.log.error("Failed to allocate SQ")
return
self.log.info("Opened SQ %d (CQ %d)", self.sqn, cq.cqn)
self.enabled = True
@@ -408,7 +423,13 @@ class Rq:
self.rqn = rsp_unpacked[4]
self.db_offset = rsp_unpacked[8]
self.log.info("Opened RQ %d", self.rqn)
if self.db_offset == 0:
self.rqn = None
self.db_offset = None
self.log.error("Failed to allocate RQ")
return
self.log.info("Opened RQ %d (CQ %d)", self.rqn, cq.cqn)
self.enabled = True
@@ -522,30 +543,38 @@ class Port:
self.index = index
self.hw_regs = driver.hw_regs
self.rxq = None
self.rxcq = None
self.rxq_count = 1
self.rxq = []
self.txq = None
self.txcq = None
self.txq_count = 1
self.txq = []
self.rx_queue = Queue()
async def init(self):
await self.open()
self.rxcq = Cq(self.driver, self)
await self.rxcq.open(self.index, 256)
async def open(self):
for k in range(self.rxq_count):
cq = Cq(self.driver, self)
await cq.open(self.index, 256)
self.rxq = Rq(self.driver, self)
await self.rxq.open(self.rxcq, 256)
q = Rq(self.driver, self)
await q.open(cq, 256)
self.txcq = Cq(self.driver, self)
await self.txcq.open(self.index, 256)
self.rxq.append(q)
self.txq = Sq(self.driver, self)
await self.txq.open(self.txcq, 256)
for k in range(self.txq_count):
cq = Cq(self.driver, self)
await cq.open(self.index, 256)
async def start_xmit(self, data):
await self.txq.start_xmit(data)
q = Sq(self.driver, self)
await q.open(cq, 256)
self.txq.append(q)
async def start_xmit(self, data, tx_ring=0):
await self.txq[tx_ring].start_xmit(data)
async def recv(self):
return await self.rx_queue.get()
@@ -555,8 +584,10 @@ class Port:
async def interrupt_handler(self):
self.log.info("Interrupt")
await self.rxcq.handler(self.rxcq)
await self.txcq.handler(self.txcq)
for q in self.rxq:
await q.cq.handler(q.cq)
for q in self.txq:
await q.cq.handler(q.cq)
class Driver: