mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 12:38:44 -07:00
cndm: Initial implementation of command interface
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -7,6 +7,7 @@ obj-m += cndm.o
|
|||||||
cndm-y += cndm_main.o
|
cndm-y += cndm_main.o
|
||||||
cndm-y += cndm_devlink.o
|
cndm-y += cndm_devlink.o
|
||||||
cndm-y += cndm_irq.o
|
cndm-y += cndm_irq.o
|
||||||
|
cndm-y += cndm_cmd.o
|
||||||
cndm-y += cndm_dev.o
|
cndm-y += cndm_dev.o
|
||||||
cndm-y += cndm_netdev.o
|
cndm-y += cndm_netdev.o
|
||||||
cndm-y += cndm_ethtool.o
|
cndm-y += cndm_ethtool.o
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ Authors:
|
|||||||
#include <linux/ptp_clock_kernel.h>
|
#include <linux/ptp_clock_kernel.h>
|
||||||
#include <net/devlink.h>
|
#include <net/devlink.h>
|
||||||
|
|
||||||
|
#include "cndm_hw.h"
|
||||||
|
|
||||||
#define DRIVER_VERSION "0.1"
|
#define DRIVER_VERSION "0.1"
|
||||||
|
|
||||||
#define CNDM_MAX_IRQ 256
|
#define CNDM_MAX_IRQ 256
|
||||||
@@ -105,6 +107,7 @@ struct cndm_priv {
|
|||||||
u32 txq_mask;
|
u32 txq_mask;
|
||||||
u32 txq_prod;
|
u32 txq_prod;
|
||||||
u32 txq_cons;
|
u32 txq_cons;
|
||||||
|
u32 txq_db_offs;
|
||||||
|
|
||||||
size_t rxq_region_len;
|
size_t rxq_region_len;
|
||||||
void *rxq_region;
|
void *rxq_region;
|
||||||
@@ -115,6 +118,7 @@ struct cndm_priv {
|
|||||||
u32 rxq_mask;
|
u32 rxq_mask;
|
||||||
u32 rxq_prod;
|
u32 rxq_prod;
|
||||||
u32 rxq_cons;
|
u32 rxq_cons;
|
||||||
|
u32 rxq_db_offs;
|
||||||
|
|
||||||
size_t txcq_region_len;
|
size_t txcq_region_len;
|
||||||
void *txcq_region;
|
void *txcq_region;
|
||||||
@@ -137,20 +141,9 @@ struct cndm_priv {
|
|||||||
u32 rxcq_cons;
|
u32 rxcq_cons;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cndm_desc {
|
// cndm_cmd.c
|
||||||
__u8 rsvd[4];
|
int cndm_exec_mbox_cmd(struct cndm_dev *cdev, void *cmd, void *rsp);
|
||||||
__le32 len;
|
int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp);
|
||||||
__le64 addr;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cndm_cpl {
|
|
||||||
__u8 rsvd[4];
|
|
||||||
__le32 len;
|
|
||||||
__le32 ts_ns;
|
|
||||||
__le16 ts_fns;
|
|
||||||
__u8 ts_s;
|
|
||||||
__u8 phase;
|
|
||||||
};
|
|
||||||
|
|
||||||
// cndm_devlink.c
|
// cndm_devlink.c
|
||||||
struct devlink *cndm_devlink_alloc(struct device *dev);
|
struct devlink *cndm_devlink_alloc(struct device *dev);
|
||||||
@@ -161,7 +154,7 @@ int cndm_irq_init_pcie(struct cndm_dev *cdev);
|
|||||||
void cndm_irq_deinit_pcie(struct cndm_dev *cdev);
|
void cndm_irq_deinit_pcie(struct cndm_dev *cdev);
|
||||||
|
|
||||||
// cndm_netdev.c
|
// cndm_netdev.c
|
||||||
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __iomem *hw_addr);
|
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port);
|
||||||
void cndm_destroy_netdev(struct net_device *ndev);
|
void cndm_destroy_netdev(struct net_device *ndev);
|
||||||
|
|
||||||
// cndm_dev.c
|
// cndm_dev.c
|
||||||
|
|||||||
47
src/cndm/modules/cndm/cndm_cmd.c
Normal file
47
src/cndm/modules/cndm/cndm_cmd.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// SPDX-License-Identifier: GPL
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2026 FPGA Ninja, LLC
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
- Alex Forencich
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cndm.h"
|
||||||
|
|
||||||
|
int cndm_exec_mbox_cmd(struct cndm_dev *cdev, void *cmd, void *rsp)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if (!cmd || !rsp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
// write command to mailbox
|
||||||
|
for (k = 0; k < 16; k++) {
|
||||||
|
iowrite32(*((u32 *)(cmd + k*4)), cdev->hw_addr + 0x10000 + k*4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute it
|
||||||
|
iowrite32(0x00000001, cdev->hw_addr + 0x0200);
|
||||||
|
|
||||||
|
// wait for completion
|
||||||
|
for (k = 0; k < 10; k++) {
|
||||||
|
if ((ioread32(cdev->hw_addr + 0x0200) & 0x00000001) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
udelay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read response from mailbox
|
||||||
|
for (k = 0; k < 16; k++) {
|
||||||
|
*((u32 *)(rsp + k*4)) = ioread32(cdev->hw_addr + 0x10000 + 0x40 + k*4);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp)
|
||||||
|
{
|
||||||
|
return cndm_exec_mbox_cmd(cdev, cmd, rsp);
|
||||||
|
}
|
||||||
103
src/cndm/modules/cndm/cndm_hw.h
Normal file
103
src/cndm/modules/cndm/cndm_hw.h
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL */
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2025 FPGA Ninja, LLC
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
- Alex Forencich
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CNDM_HW_H
|
||||||
|
#define CNDM_HW_H
|
||||||
|
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_NOP 0x0000
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_CREATE_EQ 0x0200
|
||||||
|
#define CNDM_CMD_OP_MODIFY_EQ 0x0201
|
||||||
|
#define CNDM_CMD_OP_QUERY_EQ 0x0202
|
||||||
|
#define CNDM_CMD_OP_DESTROY_EQ 0x0203
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_CREATE_CQ 0x0210
|
||||||
|
#define CNDM_CMD_OP_MODIFY_CQ 0x0211
|
||||||
|
#define CNDM_CMD_OP_QUERY_CQ 0x0212
|
||||||
|
#define CNDM_CMD_OP_DESTROY_CQ 0x0213
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_CREATE_SQ 0x0220
|
||||||
|
#define CNDM_CMD_OP_MODIFY_SQ 0x0221
|
||||||
|
#define CNDM_CMD_OP_QUERY_SQ 0x0222
|
||||||
|
#define CNDM_CMD_OP_DESTROY_SQ 0x0223
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_CREATE_RQ 0x0230
|
||||||
|
#define CNDM_CMD_OP_MODIFY_RQ 0x0231
|
||||||
|
#define CNDM_CMD_OP_QUERY_RQ 0x0232
|
||||||
|
#define CNDM_CMD_OP_DESTROY_RQ 0x0233
|
||||||
|
|
||||||
|
#define CNDM_CMD_OP_CREATE_QP 0x0240
|
||||||
|
#define CNDM_CMD_OP_MODIFY_QP 0x0241
|
||||||
|
#define CNDM_CMD_OP_QUERY_QP 0x0242
|
||||||
|
#define CNDM_CMD_OP_DESTROY_QP 0x0243
|
||||||
|
|
||||||
|
struct cndm_cmd {
|
||||||
|
__le16 rsvd;
|
||||||
|
union {
|
||||||
|
__le16 opcode;
|
||||||
|
__le16 status;
|
||||||
|
};
|
||||||
|
__le32 flags;
|
||||||
|
__le32 port;
|
||||||
|
__le32 qn;
|
||||||
|
|
||||||
|
__le32 qn2;
|
||||||
|
__le32 pd;
|
||||||
|
__le32 size;
|
||||||
|
__le32 dboffs;
|
||||||
|
|
||||||
|
__le64 ptr1;
|
||||||
|
__le64 ptr2;
|
||||||
|
|
||||||
|
__le32 dw12;
|
||||||
|
__le32 dw13;
|
||||||
|
__le32 dw14;
|
||||||
|
__le32 dw15;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cndm_desc {
|
||||||
|
__le16 rsvd0;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
__le16 csum_cmd;
|
||||||
|
} tx;
|
||||||
|
struct {
|
||||||
|
__le16 rsvd0;
|
||||||
|
} rx;
|
||||||
|
};
|
||||||
|
|
||||||
|
__le32 len;
|
||||||
|
__le64 addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cndm_cpl {
|
||||||
|
__u8 rsvd[4];
|
||||||
|
__le32 len;
|
||||||
|
__le32 ts_ns;
|
||||||
|
__le16 ts_fns;
|
||||||
|
__u8 ts_s;
|
||||||
|
__u8 phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cndm_event {
|
||||||
|
__le16 type;
|
||||||
|
__le16 source;
|
||||||
|
__le32 rsvd0;
|
||||||
|
__le32 rsvd1;
|
||||||
|
__le32 rsvd2;
|
||||||
|
__le32 rsvd3;
|
||||||
|
__le32 rsvd4;
|
||||||
|
__le32 rsvd5;
|
||||||
|
__le32 phase;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,6 +9,7 @@ Authors:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cndm.h"
|
#include "cndm.h"
|
||||||
|
#include "cndm_hw.h"
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
@@ -68,7 +69,7 @@ static int cndm_common_probe(struct cndm_dev *cdev)
|
|||||||
for (k = 0; k < cdev->port_count; k++) {
|
for (k = 0; k < cdev->port_count; k++) {
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
|
|
||||||
ndev = cndm_create_netdev(cdev, k, cdev->hw_addr + cdev->port_offset + (cdev->port_stride*k));
|
ndev = cndm_create_netdev(cdev, k);
|
||||||
if (IS_ERR_OR_NULL(ndev)) {
|
if (IS_ERR_OR_NULL(ndev)) {
|
||||||
ret = PTR_ERR(ndev);
|
ret = PTR_ERR(ndev);
|
||||||
goto fail_netdev;
|
goto fail_netdev;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ Authors:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "cndm.h"
|
#include "cndm.h"
|
||||||
|
#include "cndm_hw.h"
|
||||||
|
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
|
|
||||||
@@ -170,13 +171,16 @@ static int cndm_netdev_irq(struct notifier_block *nb, unsigned long action, void
|
|||||||
return NOTIFY_DONE;
|
return NOTIFY_DONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __iomem *hw_addr)
|
struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
|
||||||
{
|
{
|
||||||
struct device *dev = cdev->dev;
|
struct device *dev = cdev->dev;
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
struct cndm_priv *priv;
|
struct cndm_priv *priv;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
struct cndm_cmd cmd;
|
||||||
|
struct cndm_cmd rsp;
|
||||||
|
|
||||||
ndev = alloc_etherdev_mqs(sizeof(*priv), 1, 1);
|
ndev = alloc_etherdev_mqs(sizeof(*priv), 1, 1);
|
||||||
if (!ndev) {
|
if (!ndev) {
|
||||||
dev_err(dev, "Failed to allocate net_device");
|
dev_err(dev, "Failed to allocate net_device");
|
||||||
@@ -193,7 +197,7 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __io
|
|||||||
priv->ndev = ndev;
|
priv->ndev = ndev;
|
||||||
priv->cdev = cdev;
|
priv->cdev = cdev;
|
||||||
|
|
||||||
priv->hw_addr = hw_addr;
|
priv->hw_addr = cdev->hw_addr;
|
||||||
|
|
||||||
netif_set_real_num_tx_queues(ndev, 1);
|
netif_set_real_num_tx_queues(ndev, 1);
|
||||||
netif_set_real_num_rx_queues(ndev, 1);
|
netif_set_real_num_rx_queues(ndev, 1);
|
||||||
@@ -281,27 +285,61 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port, void __io
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x200);
|
cmd.opcode = CNDM_CMD_OP_CREATE_CQ;
|
||||||
iowrite32(priv->rxq_prod & 0xffff, priv->hw_addr + 0x204);
|
cmd.flags = 0x00000000;
|
||||||
iowrite32(priv->rxq_region_addr & 0xffffffff, priv->hw_addr + 0x208);
|
cmd.port = port;
|
||||||
iowrite32(priv->rxq_region_addr >> 32, priv->hw_addr + 0x20c);
|
cmd.qn = 0;
|
||||||
iowrite32(0x00000001 | (priv->rxq_log_size << 16), priv->hw_addr + 0x200);
|
cmd.qn2 = 0;
|
||||||
|
cmd.pd = 0;
|
||||||
|
cmd.size = priv->rxcq_log_size;
|
||||||
|
cmd.dboffs = 0;
|
||||||
|
cmd.ptr1 = priv->rxcq_region_addr;
|
||||||
|
cmd.ptr2 = 0;
|
||||||
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x100);
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
iowrite32(priv->txq_prod & 0xffff, priv->hw_addr + 0x104);
|
|
||||||
iowrite32(priv->txq_region_addr & 0xffffffff, priv->hw_addr + 0x108);
|
|
||||||
iowrite32(priv->txq_region_addr >> 32, priv->hw_addr + 0x10c);
|
|
||||||
iowrite32(0x00000001 | (priv->txq_log_size << 16), priv->hw_addr + 0x100);
|
|
||||||
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x400);
|
cmd.opcode = CNDM_CMD_OP_CREATE_RQ;
|
||||||
iowrite32(priv->rxcq_region_addr & 0xffffffff, priv->hw_addr + 0x408);
|
cmd.flags = 0x00000000;
|
||||||
iowrite32(priv->rxcq_region_addr >> 32, priv->hw_addr + 0x40c);
|
cmd.port = port;
|
||||||
iowrite32(0x00000001 | (priv->rxcq_log_size << 16), priv->hw_addr + 0x400);
|
cmd.qn = 0;
|
||||||
|
cmd.qn2 = 0;
|
||||||
|
cmd.pd = 0;
|
||||||
|
cmd.size = priv->rxq_log_size;
|
||||||
|
cmd.dboffs = 0;
|
||||||
|
cmd.ptr1 = priv->rxq_region_addr;
|
||||||
|
cmd.ptr2 = 0;
|
||||||
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x300);
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
iowrite32(priv->txcq_region_addr & 0xffffffff, priv->hw_addr + 0x308);
|
|
||||||
iowrite32(priv->txcq_region_addr >> 32, priv->hw_addr + 0x30c);
|
priv->rxq_db_offs = rsp.dboffs;
|
||||||
iowrite32(0x00000001 | (priv->txcq_log_size << 16), priv->hw_addr + 0x300);
|
|
||||||
|
cmd.opcode = CNDM_CMD_OP_CREATE_CQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = port;
|
||||||
|
cmd.qn = 1;
|
||||||
|
cmd.qn2 = 0;
|
||||||
|
cmd.pd = 0;
|
||||||
|
cmd.size = priv->txcq_log_size;
|
||||||
|
cmd.dboffs = 0;
|
||||||
|
cmd.ptr1 = priv->txcq_region_addr;
|
||||||
|
cmd.ptr2 = 0;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
|
cmd.opcode = CNDM_CMD_OP_CREATE_SQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = port;
|
||||||
|
cmd.qn = 0;
|
||||||
|
cmd.qn2 = 0;
|
||||||
|
cmd.pd = 0;
|
||||||
|
cmd.size = priv->txq_log_size;
|
||||||
|
cmd.dboffs = 0;
|
||||||
|
cmd.ptr1 = priv->txq_region_addr;
|
||||||
|
cmd.ptr2 = 0;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
|
priv->txq_db_offs = rsp.dboffs;
|
||||||
|
|
||||||
netif_carrier_off(ndev);
|
netif_carrier_off(ndev);
|
||||||
|
|
||||||
@@ -332,12 +370,41 @@ fail:
|
|||||||
void cndm_destroy_netdev(struct net_device *ndev)
|
void cndm_destroy_netdev(struct net_device *ndev)
|
||||||
{
|
{
|
||||||
struct cndm_priv *priv = netdev_priv(ndev);
|
struct cndm_priv *priv = netdev_priv(ndev);
|
||||||
|
struct cndm_dev *cdev = priv->cdev;
|
||||||
struct device *dev = priv->dev;
|
struct device *dev = priv->dev;
|
||||||
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x200);
|
struct cndm_cmd cmd;
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x100);
|
struct cndm_cmd rsp;
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x400);
|
|
||||||
iowrite32(0x00000000, priv->hw_addr + 0x300);
|
cmd.opcode = CNDM_CMD_OP_DESTROY_CQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = ndev->dev_port;
|
||||||
|
cmd.qn = 0;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
|
cmd.opcode = CNDM_CMD_OP_DESTROY_RQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = ndev->dev_port;
|
||||||
|
cmd.qn = 0;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
|
priv->rxq_db_offs = rsp.dboffs;
|
||||||
|
|
||||||
|
cmd.opcode = CNDM_CMD_OP_DESTROY_CQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = ndev->dev_port;
|
||||||
|
cmd.qn = 1;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
|
cmd.opcode = CNDM_CMD_OP_DESTROY_SQ;
|
||||||
|
cmd.flags = 0x00000000;
|
||||||
|
cmd.port = ndev->dev_port;
|
||||||
|
cmd.qn = 0;
|
||||||
|
|
||||||
|
cndm_exec_cmd(cdev, &cmd, &rsp);
|
||||||
|
|
||||||
if (priv->irq)
|
if (priv->irq)
|
||||||
atomic_notifier_chain_unregister(&priv->irq->nh, &priv->irq_nb);
|
atomic_notifier_chain_unregister(&priv->irq->nh, &priv->irq_nb);
|
||||||
|
|||||||
@@ -148,12 +148,12 @@ void cndm_register_phc(struct cndm_dev *cdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
if (cdev->port_offset == 0x10000) {
|
if (cdev->port_offset == 0x20000) {
|
||||||
dev_info(cdev->dev, "PTP clock not present");
|
dev_info(cdev->dev, "PTP clock not present");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cdev->phc_regs = cdev->hw_addr + 0x10000; // TODO
|
cdev->phc_regs = cdev->hw_addr + 0x20000; // TODO
|
||||||
|
|
||||||
cdev->ptp_clock_info.owner = THIS_MODULE;
|
cdev->ptp_clock_info.owner = THIS_MODULE;
|
||||||
snprintf(cdev->ptp_clock_info.name, sizeof(cdev->ptp_clock_info.name), "%s_phc", cdev->name);
|
snprintf(cdev->ptp_clock_info.name, sizeof(cdev->ptp_clock_info.name), "%s_phc", cdev->name);
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ int cndm_refill_rx_buffers(struct cndm_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dma_wmb();
|
dma_wmb();
|
||||||
iowrite32(priv->rxq_prod & 0xffff, priv->hw_addr + 0x204);
|
iowrite32(priv->rxq_prod & 0xffff, priv->hw_addr + priv->rxq_db_offs);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ int cndm_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dma_wmb();
|
dma_wmb();
|
||||||
iowrite32(priv->txq_prod & 0xffff, priv->hw_addr + 0x104);
|
iowrite32(priv->txq_prod & 0xffff, priv->hw_addr + priv->txq_db_offs);
|
||||||
|
|
||||||
return NETDEV_TX_OK;
|
return NETDEV_TX_OK;
|
||||||
|
|
||||||
|
|||||||
265
src/cndm/rtl/cndm_micro_cmd_mbox.sv
Normal file
265
src/cndm/rtl/cndm_micro_cmd_mbox.sv
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2026 FPGA Ninja, LLC
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
- Alex Forencich
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
`resetall
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command mailbox
|
||||||
|
*/
|
||||||
|
module cndm_micro_cmd_mbox
|
||||||
|
(
|
||||||
|
input wire logic clk,
|
||||||
|
input wire logic rst,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AXI lite interface
|
||||||
|
*/
|
||||||
|
taxi_axil_if.wr_slv s_axil_wr,
|
||||||
|
taxi_axil_if.rd_slv s_axil_rd,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control
|
||||||
|
*/
|
||||||
|
input wire logic start,
|
||||||
|
output wire logic busy,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command interface
|
||||||
|
*/
|
||||||
|
taxi_axis_if.src m_axis_cmd,
|
||||||
|
taxi_axis_if.snk s_axis_rsp
|
||||||
|
);
|
||||||
|
|
||||||
|
localparam ADDR_W = 7;
|
||||||
|
|
||||||
|
// extract parameters
|
||||||
|
localparam DATA_W = s_axil_wr.DATA_W;
|
||||||
|
localparam STRB_W = s_axil_wr.STRB_W;
|
||||||
|
|
||||||
|
localparam VALID_ADDR_W = ADDR_W - $clog2(STRB_W);
|
||||||
|
localparam BYTE_LANES = STRB_W;
|
||||||
|
localparam BYTE_W = DATA_W/BYTE_LANES;
|
||||||
|
|
||||||
|
// check configuration
|
||||||
|
if (BYTE_W * STRB_W != DATA_W)
|
||||||
|
$fatal(0, "Error: AXI data width not evenly divisible (instance %m)");
|
||||||
|
|
||||||
|
if (2**$clog2(BYTE_LANES) != BYTE_LANES)
|
||||||
|
$fatal(0, "Error: AXI word width must be even power of two (instance %m)");
|
||||||
|
|
||||||
|
if (s_axil_rd.DATA_W != DATA_W)
|
||||||
|
$fatal(0, "Error: AXI interface configuration mismatch (instance %m)");
|
||||||
|
|
||||||
|
if (s_axil_wr.ADDR_W < ADDR_W || s_axil_wr.ADDR_W < ADDR_W)
|
||||||
|
$fatal(0, "Error: AXI address width is insufficient (instance %m)");
|
||||||
|
|
||||||
|
logic read_eligible;
|
||||||
|
logic write_eligible;
|
||||||
|
|
||||||
|
logic axil_mem_wr_en;
|
||||||
|
logic axil_mem_rd_en;
|
||||||
|
logic [4:0] axil_mem_addr;
|
||||||
|
|
||||||
|
logic cmd_mem_wr_en;
|
||||||
|
logic cmd_mem_rd_en;
|
||||||
|
logic [4:0] cmd_mem_addr;
|
||||||
|
|
||||||
|
logic last_read_reg = 1'b0, last_read_next;
|
||||||
|
|
||||||
|
logic [3:0] rd_ptr_reg = '0, rd_ptr_next;
|
||||||
|
logic [3:0] wr_ptr_reg = '0, wr_ptr_next;
|
||||||
|
logic busy_reg = 1'b0, busy_next;
|
||||||
|
|
||||||
|
logic s_axil_awready_reg = 1'b0, s_axil_awready_next;
|
||||||
|
logic s_axil_wready_reg = 1'b0, s_axil_wready_next;
|
||||||
|
logic s_axil_bvalid_reg = 1'b0, s_axil_bvalid_next;
|
||||||
|
logic s_axil_arready_reg = 1'b0, s_axil_arready_next;
|
||||||
|
// logic [DATA_W-1:0] s_axil_rdata_reg = '0, s_axil_rdata_next;
|
||||||
|
logic s_axil_rvalid_reg = 1'b0, s_axil_rvalid_next;
|
||||||
|
|
||||||
|
// logic [31:0] m_axis_cmd_tdata_reg = '0;
|
||||||
|
logic m_axis_cmd_tvalid_reg = 1'b0, m_axis_cmd_tvalid_next;
|
||||||
|
logic m_axis_cmd_tlast_reg = 1'b0, m_axis_cmd_tlast_next;
|
||||||
|
|
||||||
|
logic s_axis_rsp_tready_reg = 1'b0, s_axis_rsp_tready_next;
|
||||||
|
|
||||||
|
wire [VALID_ADDR_W-1:0] s_axil_awaddr_valid = VALID_ADDR_W'(s_axil_wr.awaddr >> (ADDR_W - VALID_ADDR_W));
|
||||||
|
wire [VALID_ADDR_W-1:0] s_axil_araddr_valid = VALID_ADDR_W'(s_axil_rd.araddr >> (ADDR_W - VALID_ADDR_W));
|
||||||
|
|
||||||
|
assign s_axil_wr.awready = s_axil_awready_reg;
|
||||||
|
assign s_axil_wr.wready = s_axil_wready_reg;
|
||||||
|
assign s_axil_wr.bresp = 2'b00;
|
||||||
|
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 = 2'b00;
|
||||||
|
assign s_axil_rd.ruser = '0;
|
||||||
|
assign s_axil_rd.rvalid = s_axil_rvalid_reg;
|
||||||
|
|
||||||
|
// assign m_axis_cmd.tdata = m_axis_cmd_tdata_reg;
|
||||||
|
assign m_axis_cmd.tkeep = '1;
|
||||||
|
assign m_axis_cmd.tstrb = m_axis_cmd.tkeep;
|
||||||
|
assign m_axis_cmd.tvalid = m_axis_cmd_tvalid_reg;
|
||||||
|
assign m_axis_cmd.tlast = m_axis_cmd_tlast_reg;
|
||||||
|
assign m_axis_cmd.tid = '0;
|
||||||
|
assign m_axis_cmd.tdest = '0;
|
||||||
|
assign m_axis_cmd.tuser = '0;
|
||||||
|
|
||||||
|
assign s_axis_rsp.tready = s_axis_rsp_tready_reg;
|
||||||
|
|
||||||
|
assign busy = busy_reg;
|
||||||
|
|
||||||
|
taxi_ram_2rw_1c #(
|
||||||
|
.ADDR_W(5),
|
||||||
|
.DATA_W(32),
|
||||||
|
.STRB_EN(1'b1),
|
||||||
|
.STRB_W(4)
|
||||||
|
)
|
||||||
|
ram_inst (
|
||||||
|
.clk(clk),
|
||||||
|
|
||||||
|
.a_en(axil_mem_wr_en || axil_mem_rd_en),
|
||||||
|
.a_addr(axil_mem_addr),
|
||||||
|
.a_wr_en(axil_mem_wr_en),
|
||||||
|
.a_wr_data(s_axil_wr.wdata),
|
||||||
|
.a_wr_strb(s_axil_wr.wstrb),
|
||||||
|
.a_rd_data(s_axil_rd.rdata),
|
||||||
|
|
||||||
|
.b_en(cmd_mem_wr_en || cmd_mem_rd_en),
|
||||||
|
.b_addr(cmd_mem_addr),
|
||||||
|
.b_wr_en(cmd_mem_wr_en),
|
||||||
|
.b_wr_data(s_axis_rsp.tdata),
|
||||||
|
.b_wr_strb('1),
|
||||||
|
.b_rd_data(m_axis_cmd.tdata)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register interface
|
||||||
|
always_comb begin
|
||||||
|
axil_mem_wr_en = 1'b0;
|
||||||
|
axil_mem_rd_en = 1'b0;
|
||||||
|
axil_mem_addr = s_axil_araddr_valid;
|
||||||
|
|
||||||
|
last_read_next = last_read_reg;
|
||||||
|
|
||||||
|
s_axil_awready_next = 1'b0;
|
||||||
|
s_axil_wready_next = 1'b0;
|
||||||
|
s_axil_bvalid_next = s_axil_bvalid_reg && !s_axil_wr.bready;
|
||||||
|
|
||||||
|
s_axil_arready_next = 1'b0;
|
||||||
|
s_axil_rvalid_next = s_axil_rvalid_reg && !s_axil_rd.rready;
|
||||||
|
|
||||||
|
write_eligible = s_axil_wr.awvalid && s_axil_wr.wvalid && (!s_axil_wr.bvalid || s_axil_wr.bready) && (!s_axil_wr.awready && !s_axil_wr.wready);
|
||||||
|
read_eligible = s_axil_rd.arvalid && (!s_axil_rd.rvalid || s_axil_rd.rready) && (!s_axil_rd.arready);
|
||||||
|
|
||||||
|
if (write_eligible && (!read_eligible || last_read_reg)) begin
|
||||||
|
last_read_next = 1'b0;
|
||||||
|
|
||||||
|
s_axil_awready_next = 1'b1;
|
||||||
|
s_axil_wready_next = 1'b1;
|
||||||
|
s_axil_bvalid_next = 1'b1;
|
||||||
|
|
||||||
|
axil_mem_wr_en = 1'b1;
|
||||||
|
axil_mem_addr = s_axil_awaddr_valid;
|
||||||
|
end else if (read_eligible) begin
|
||||||
|
last_read_next = 1'b1;
|
||||||
|
|
||||||
|
s_axil_arready_next = 1'b1;
|
||||||
|
s_axil_rvalid_next = 1'b1;
|
||||||
|
|
||||||
|
axil_mem_rd_en = 1'b1;
|
||||||
|
axil_mem_addr = s_axil_araddr_valid;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
last_read_reg <= last_read_next;
|
||||||
|
|
||||||
|
s_axil_awready_reg <= s_axil_awready_next;
|
||||||
|
s_axil_wready_reg <= s_axil_wready_next;
|
||||||
|
s_axil_bvalid_reg <= s_axil_bvalid_next;
|
||||||
|
|
||||||
|
s_axil_arready_reg <= s_axil_arready_next;
|
||||||
|
s_axil_rvalid_reg <= s_axil_rvalid_next;
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
last_read_reg <= 1'b0;
|
||||||
|
|
||||||
|
s_axil_awready_reg <= 1'b0;
|
||||||
|
s_axil_wready_reg <= 1'b0;
|
||||||
|
s_axil_bvalid_reg <= 1'b0;
|
||||||
|
|
||||||
|
s_axil_arready_reg <= 1'b0;
|
||||||
|
s_axil_rvalid_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// Command interface
|
||||||
|
always_comb begin
|
||||||
|
cmd_mem_rd_en = 1'b0;
|
||||||
|
cmd_mem_wr_en = 1'b0;
|
||||||
|
cmd_mem_addr = {1'b0, rd_ptr_reg};
|
||||||
|
|
||||||
|
rd_ptr_next = rd_ptr_reg;
|
||||||
|
wr_ptr_next = wr_ptr_reg;
|
||||||
|
busy_next = busy_reg;
|
||||||
|
|
||||||
|
m_axis_cmd_tvalid_next = m_axis_cmd_tvalid_reg && !m_axis_cmd.tready;
|
||||||
|
m_axis_cmd_tlast_next = m_axis_cmd_tlast_reg;
|
||||||
|
|
||||||
|
s_axis_rsp_tready_next = 1'b0;
|
||||||
|
|
||||||
|
if ((!m_axis_cmd_tvalid_reg || m_axis_cmd.tready) && (rd_ptr_reg != 0 || start)) begin
|
||||||
|
cmd_mem_rd_en = 1'b1;
|
||||||
|
cmd_mem_addr = {1'b0, rd_ptr_reg};
|
||||||
|
m_axis_cmd_tvalid_next = 1'b1;
|
||||||
|
m_axis_cmd_tlast_next = &rd_ptr_reg;
|
||||||
|
rd_ptr_next = rd_ptr_reg + 1;
|
||||||
|
busy_next = 1'b1;
|
||||||
|
end else if (s_axis_rsp.tvalid && !s_axis_rsp_tready_reg) begin
|
||||||
|
cmd_mem_wr_en = 1'b1;
|
||||||
|
cmd_mem_addr = {1'b1, wr_ptr_reg};
|
||||||
|
s_axis_rsp_tready_next = 1'b1;
|
||||||
|
if (s_axis_rsp.tlast) begin
|
||||||
|
wr_ptr_next = '0;
|
||||||
|
busy_next = 1'b0;
|
||||||
|
end else begin
|
||||||
|
wr_ptr_next = wr_ptr_reg + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
rd_ptr_reg <= rd_ptr_next;
|
||||||
|
wr_ptr_reg <= wr_ptr_next;
|
||||||
|
busy_reg <= busy_next;
|
||||||
|
|
||||||
|
m_axis_cmd_tvalid_reg <= m_axis_cmd_tvalid_next;
|
||||||
|
m_axis_cmd_tlast_reg <= m_axis_cmd_tlast_next;
|
||||||
|
|
||||||
|
s_axis_rsp_tready_reg <= s_axis_rsp_tready_next;
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
rd_ptr_reg <= '0;
|
||||||
|
wr_ptr_reg <= '0;
|
||||||
|
busy_reg <= 1'b0;
|
||||||
|
|
||||||
|
m_axis_cmd_tvalid_reg <= 1'b0;
|
||||||
|
|
||||||
|
s_axis_rsp_tready_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`resetall
|
||||||
@@ -1,13 +1,18 @@
|
|||||||
cndm_micro_core.sv
|
cndm_micro_core.sv
|
||||||
|
cndm_micro_cmd_mbox.sv
|
||||||
|
cndm_micro_dp_mgr.sv
|
||||||
cndm_micro_port.sv
|
cndm_micro_port.sv
|
||||||
cndm_micro_rx.sv
|
cndm_micro_rx.sv
|
||||||
cndm_micro_tx.sv
|
cndm_micro_tx.sv
|
||||||
cndm_micro_desc_rd.sv
|
cndm_micro_desc_rd.sv
|
||||||
cndm_micro_cpl_wr.sv
|
cndm_micro_cpl_wr.sv
|
||||||
|
../lib/taxi/src/prim/rtl/taxi_ram_2rw_1c.sv
|
||||||
../lib/taxi/src/dma/rtl/taxi_dma_client_axis_source.sv
|
../lib/taxi/src/dma/rtl/taxi_dma_client_axis_source.sv
|
||||||
../lib/taxi/src/dma/rtl/taxi_dma_client_axis_sink.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_if_mux.f
|
||||||
../lib/taxi/src/dma/rtl/taxi_dma_psdpram.sv
|
../lib/taxi/src/dma/rtl/taxi_dma_psdpram.sv
|
||||||
|
../lib/taxi/src/apb/rtl/taxi_apb_if.sv
|
||||||
|
../lib/taxi/src/apb/rtl/taxi_apb_interconnect.sv
|
||||||
../lib/taxi/src/axi/rtl/taxi_axil_interconnect_1s.f
|
../lib/taxi/src/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.f
|
||||||
../lib/taxi/src/axis/rtl/taxi_axis_arb_mux.f
|
../lib/taxi/src/axis/rtl/taxi_axis_arb_mux.f
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ module cndm_micro_core #(
|
|||||||
/*
|
/*
|
||||||
* Control register interface
|
* Control register interface
|
||||||
*/
|
*/
|
||||||
taxi_axil_if.wr_slv s_axil_wr,
|
taxi_axil_if.wr_slv s_axil_ctrl_wr,
|
||||||
taxi_axil_if.rd_slv s_axil_rd,
|
taxi_axil_if.rd_slv s_axil_ctrl_rd,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMA
|
* DMA
|
||||||
@@ -97,8 +97,8 @@ module cndm_micro_core #(
|
|||||||
|
|
||||||
localparam CL_PORTS = $clog2(PORTS);
|
localparam CL_PORTS = $clog2(PORTS);
|
||||||
|
|
||||||
localparam AXIL_ADDR_W = s_axil_wr.ADDR_W;
|
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
|
||||||
localparam AXIL_DATA_W = s_axil_wr.DATA_W;
|
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
|
||||||
|
|
||||||
localparam RAM_SEGS = dma_ram_wr.SEGS;
|
localparam RAM_SEGS = dma_ram_wr.SEGS;
|
||||||
localparam RAM_SEG_ADDR_W = dma_ram_wr.SEG_ADDR_W;
|
localparam RAM_SEG_ADDR_W = dma_ram_wr.SEG_ADDR_W;
|
||||||
@@ -106,32 +106,33 @@ localparam RAM_SEG_DATA_W = dma_ram_wr.SEG_DATA_W;
|
|||||||
localparam RAM_SEG_BE_W = dma_ram_wr.SEG_BE_W;
|
localparam RAM_SEG_BE_W = dma_ram_wr.SEG_BE_W;
|
||||||
localparam RAM_SEL_W = dma_ram_wr.SEL_W;
|
localparam RAM_SEL_W = dma_ram_wr.SEL_W;
|
||||||
|
|
||||||
localparam PORT_OFFSET = PTP_TS_EN ? 2 : 1;
|
localparam PORT_OFFSET = PTP_TS_EN ? 3 : 2;
|
||||||
|
localparam PORT_BASE_ADDR = PTP_TS_EN ? 32'h00030000 : 32'h00020000;
|
||||||
|
|
||||||
taxi_axil_if #(
|
taxi_axil_if #(
|
||||||
.DATA_W(s_axil_wr.DATA_W),
|
.DATA_W(s_axil_ctrl_wr.DATA_W),
|
||||||
.ADDR_W(16),
|
.ADDR_W(16),
|
||||||
.STRB_W(s_axil_wr.STRB_W),
|
.STRB_W(s_axil_ctrl_wr.STRB_W),
|
||||||
.AWUSER_EN(s_axil_wr.AWUSER_EN),
|
.AWUSER_EN(s_axil_ctrl_wr.AWUSER_EN),
|
||||||
.AWUSER_W(s_axil_wr.AWUSER_W),
|
.AWUSER_W(s_axil_ctrl_wr.AWUSER_W),
|
||||||
.WUSER_EN(s_axil_wr.WUSER_EN),
|
.WUSER_EN(s_axil_ctrl_wr.WUSER_EN),
|
||||||
.WUSER_W(s_axil_wr.WUSER_W),
|
.WUSER_W(s_axil_ctrl_wr.WUSER_W),
|
||||||
.BUSER_EN(s_axil_wr.BUSER_EN),
|
.BUSER_EN(s_axil_ctrl_wr.BUSER_EN),
|
||||||
.BUSER_W(s_axil_wr.BUSER_W),
|
.BUSER_W(s_axil_ctrl_wr.BUSER_W),
|
||||||
.ARUSER_EN(s_axil_wr.ARUSER_EN),
|
.ARUSER_EN(s_axil_ctrl_wr.ARUSER_EN),
|
||||||
.ARUSER_W(s_axil_wr.ARUSER_W),
|
.ARUSER_W(s_axil_ctrl_wr.ARUSER_W),
|
||||||
.RUSER_EN(s_axil_wr.RUSER_EN),
|
.RUSER_EN(s_axil_ctrl_wr.RUSER_EN),
|
||||||
.RUSER_W(s_axil_wr.RUSER_W)
|
.RUSER_W(s_axil_ctrl_wr.RUSER_W)
|
||||||
)
|
)
|
||||||
s_axil_ctrl[PORTS+PORT_OFFSET]();
|
axil_ctrl[PORTS+PORT_OFFSET]();
|
||||||
|
|
||||||
taxi_axil_interconnect_1s #(
|
taxi_axil_interconnect_1s #(
|
||||||
.M_COUNT($size(s_axil_ctrl)),
|
.M_COUNT($size(axil_ctrl)),
|
||||||
.ADDR_W(s_axil_wr.ADDR_W),
|
.ADDR_W(s_axil_ctrl_wr.ADDR_W),
|
||||||
.M_REGIONS(1),
|
.M_REGIONS(1),
|
||||||
.M_BASE_ADDR('0),
|
.M_BASE_ADDR('0),
|
||||||
.M_ADDR_W({$size(s_axil_ctrl){{1{32'd16}}}}),
|
.M_ADDR_W({$size(axil_ctrl){{1{32'd16}}}}),
|
||||||
.M_SECURE({$size(s_axil_ctrl){1'b0}})
|
.M_SECURE({$size(axil_ctrl){1'b0}})
|
||||||
)
|
)
|
||||||
port_intercon_inst (
|
port_intercon_inst (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
@@ -140,14 +141,14 @@ port_intercon_inst (
|
|||||||
/*
|
/*
|
||||||
* AXI4-lite slave interface
|
* AXI4-lite slave interface
|
||||||
*/
|
*/
|
||||||
.s_axil_wr(s_axil_wr),
|
.s_axil_wr(s_axil_ctrl_wr),
|
||||||
.s_axil_rd(s_axil_rd),
|
.s_axil_rd(s_axil_ctrl_rd),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AXI4-lite master interfaces
|
* AXI4-lite master interfaces
|
||||||
*/
|
*/
|
||||||
.m_axil_wr(s_axil_ctrl),
|
.m_axil_wr(axil_ctrl),
|
||||||
.m_axil_rd(s_axil_ctrl)
|
.m_axil_rd(axil_ctrl)
|
||||||
);
|
);
|
||||||
|
|
||||||
logic s_axil_awready_reg = 1'b0;
|
logic s_axil_awready_reg = 1'b0;
|
||||||
@@ -158,53 +159,64 @@ logic s_axil_arready_reg = 1'b0;
|
|||||||
logic [AXIL_DATA_W-1:0] s_axil_rdata_reg = '0;
|
logic [AXIL_DATA_W-1:0] s_axil_rdata_reg = '0;
|
||||||
logic s_axil_rvalid_reg = 1'b0;
|
logic s_axil_rvalid_reg = 1'b0;
|
||||||
|
|
||||||
assign s_axil_ctrl[0].awready = s_axil_awready_reg;
|
assign axil_ctrl[0].awready = s_axil_awready_reg;
|
||||||
assign s_axil_ctrl[0].wready = s_axil_wready_reg;
|
assign axil_ctrl[0].wready = s_axil_wready_reg;
|
||||||
assign s_axil_ctrl[0].bresp = '0;
|
assign axil_ctrl[0].bresp = '0;
|
||||||
assign s_axil_ctrl[0].buser = '0;
|
assign axil_ctrl[0].buser = '0;
|
||||||
assign s_axil_ctrl[0].bvalid = s_axil_bvalid_reg;
|
assign axil_ctrl[0].bvalid = s_axil_bvalid_reg;
|
||||||
|
|
||||||
assign s_axil_ctrl[0].arready = s_axil_arready_reg;
|
assign axil_ctrl[0].arready = s_axil_arready_reg;
|
||||||
assign s_axil_ctrl[0].rdata = s_axil_rdata_reg;
|
assign axil_ctrl[0].rdata = s_axil_rdata_reg;
|
||||||
assign s_axil_ctrl[0].rresp = '0;
|
assign axil_ctrl[0].rresp = '0;
|
||||||
assign s_axil_ctrl[0].ruser = '0;
|
assign axil_ctrl[0].ruser = '0;
|
||||||
assign s_axil_ctrl[0].rvalid = s_axil_rvalid_reg;
|
assign axil_ctrl[0].rvalid = s_axil_rvalid_reg;
|
||||||
|
|
||||||
|
logic cmd_mbox_start_reg = 1'b0;
|
||||||
|
wire cmd_mbox_busy;
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
s_axil_awready_reg <= 1'b0;
|
s_axil_awready_reg <= 1'b0;
|
||||||
s_axil_wready_reg <= 1'b0;
|
s_axil_wready_reg <= 1'b0;
|
||||||
s_axil_bvalid_reg <= s_axil_bvalid_reg && !s_axil_ctrl[0].bready;
|
s_axil_bvalid_reg <= s_axil_bvalid_reg && !axil_ctrl[0].bready;
|
||||||
|
|
||||||
s_axil_arready_reg <= 1'b0;
|
s_axil_arready_reg <= 1'b0;
|
||||||
s_axil_rvalid_reg <= s_axil_rvalid_reg && !s_axil_ctrl[0].rready;
|
s_axil_rvalid_reg <= s_axil_rvalid_reg && !axil_ctrl[0].rready;
|
||||||
|
|
||||||
if (s_axil_ctrl[0].awvalid && s_axil_ctrl[0].wvalid && !s_axil_bvalid_reg) begin
|
cmd_mbox_start_reg <= 1'b0;
|
||||||
|
|
||||||
|
if (axil_ctrl[0].awvalid && axil_ctrl[0].wvalid && !s_axil_bvalid_reg) begin
|
||||||
s_axil_awready_reg <= 1'b1;
|
s_axil_awready_reg <= 1'b1;
|
||||||
s_axil_wready_reg <= 1'b1;
|
s_axil_wready_reg <= 1'b1;
|
||||||
s_axil_bvalid_reg <= 1'b1;
|
s_axil_bvalid_reg <= 1'b1;
|
||||||
|
|
||||||
case ({s_axil_ctrl[0].awaddr[15:2], 2'b00})
|
case ({axil_ctrl[0].awaddr[15:2], 2'b00})
|
||||||
// 16'h0100: begin
|
// 16'h0100: begin
|
||||||
// txq_en_reg <= s_axil_ctrl[0].wdata[0];
|
// txq_en_reg <= axil_ctrl[0].wdata[0];
|
||||||
// txq_size_reg <= s_axil_ctrl[0].wdata[19:16];
|
// txq_size_reg <= axil_ctrl[0].wdata[19:16];
|
||||||
// end
|
// end
|
||||||
// 16'h0104: txq_prod_reg <= s_axil_ctrl[0].wdata[15:0];
|
// 16'h0104: txq_prod_reg <= axil_ctrl[0].wdata[15:0];
|
||||||
// 16'h0108: txq_base_addr_reg[31:0] <= s_axil_ctrl[0].wdata;
|
// 16'h0108: txq_base_addr_reg[31:0] <= axil_ctrl[0].wdata;
|
||||||
// 16'h010c: txq_base_addr_reg[63:32] <= s_axil_ctrl[0].wdata;
|
// 16'h010c: txq_base_addr_reg[63:32] <= axil_ctrl[0].wdata;
|
||||||
|
16'h0200: begin
|
||||||
|
cmd_mbox_start_reg <= axil_ctrl[0].wdata[0];
|
||||||
|
end
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
if (s_axil_ctrl[0].arvalid && !s_axil_rvalid_reg) begin
|
if (axil_ctrl[0].arvalid && !s_axil_rvalid_reg) begin
|
||||||
s_axil_rdata_reg <= '0;
|
s_axil_rdata_reg <= '0;
|
||||||
|
|
||||||
s_axil_arready_reg <= 1'b1;
|
s_axil_arready_reg <= 1'b1;
|
||||||
s_axil_rvalid_reg <= 1'b1;
|
s_axil_rvalid_reg <= 1'b1;
|
||||||
|
|
||||||
case ({s_axil_ctrl[0].araddr[15:2], 2'b00})
|
case ({axil_ctrl[0].araddr[15:2], 2'b00})
|
||||||
16'h0100: s_axil_rdata_reg <= PORTS; // port count
|
16'h0100: s_axil_rdata_reg <= PORTS; // port count
|
||||||
16'h0104: s_axil_rdata_reg <= PTP_TS_EN ? 32'h00020000 : 32'h00010000; // port offset
|
16'h0104: s_axil_rdata_reg <= PORT_BASE_ADDR; // port offset
|
||||||
16'h0108: s_axil_rdata_reg <= 32'h00010000; // port stride
|
16'h0108: s_axil_rdata_reg <= 32'h00010000; // port stride
|
||||||
|
16'h0200: begin
|
||||||
|
s_axil_rdata_reg[0] <= cmd_mbox_busy;
|
||||||
|
end
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
@@ -219,6 +231,106 @@ always_ff @(posedge clk) begin
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// command mailbox
|
||||||
|
taxi_axis_if #(
|
||||||
|
.DATA_W(32),
|
||||||
|
.KEEP_EN(1),
|
||||||
|
.LAST_EN(1),
|
||||||
|
.ID_EN(0),
|
||||||
|
.DEST_EN(0),
|
||||||
|
.USER_EN(0)
|
||||||
|
) axis_cmd();
|
||||||
|
|
||||||
|
taxi_axis_if #(
|
||||||
|
.DATA_W(32),
|
||||||
|
.KEEP_EN(1),
|
||||||
|
.LAST_EN(1),
|
||||||
|
.ID_EN(0),
|
||||||
|
.DEST_EN(0),
|
||||||
|
.USER_EN(0)
|
||||||
|
) axis_rsp();
|
||||||
|
|
||||||
|
cndm_micro_cmd_mbox
|
||||||
|
cmd_mbox_inst (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AXI lite interface
|
||||||
|
*/
|
||||||
|
.s_axil_wr(axil_ctrl[1]),
|
||||||
|
.s_axil_rd(axil_ctrl[1]),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control
|
||||||
|
*/
|
||||||
|
.start(cmd_mbox_start_reg),
|
||||||
|
.busy(cmd_mbox_busy),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command interface
|
||||||
|
*/
|
||||||
|
.m_axis_cmd(axis_cmd),
|
||||||
|
.s_axis_rsp(axis_rsp)
|
||||||
|
);
|
||||||
|
|
||||||
|
// datapath manager
|
||||||
|
|
||||||
|
taxi_apb_if #(
|
||||||
|
.DATA_W(32),
|
||||||
|
.ADDR_W(16+CL_PORTS)
|
||||||
|
)
|
||||||
|
apb_dp_ctrl();
|
||||||
|
|
||||||
|
cndm_micro_dp_mgr #(
|
||||||
|
.PORTS(PORTS),
|
||||||
|
.PORT_BASE_ADDR(PORT_BASE_ADDR)
|
||||||
|
)
|
||||||
|
dp_mgr_inst (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command interface
|
||||||
|
*/
|
||||||
|
.s_axis_cmd(axis_cmd),
|
||||||
|
.m_axis_rsp(axis_rsp),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APB master interface (datapath control)
|
||||||
|
*/
|
||||||
|
.m_apb_dp_ctrl(apb_dp_ctrl)
|
||||||
|
);
|
||||||
|
|
||||||
|
taxi_apb_if #(
|
||||||
|
.DATA_W(32),
|
||||||
|
.ADDR_W(16)
|
||||||
|
)
|
||||||
|
apb_port_dp_ctrl[PORTS]();
|
||||||
|
|
||||||
|
taxi_apb_interconnect #(
|
||||||
|
.M_CNT($size(apb_port_dp_ctrl)),
|
||||||
|
.ADDR_W(apb_dp_ctrl.ADDR_W),
|
||||||
|
.M_REGIONS(1),
|
||||||
|
.M_BASE_ADDR('0),
|
||||||
|
.M_ADDR_W({$size(apb_port_dp_ctrl){{1{32'd16}}}}),
|
||||||
|
.M_SECURE({$size(apb_port_dp_ctrl){1'b0}})
|
||||||
|
)
|
||||||
|
port_dp_intercon_inst (
|
||||||
|
.clk(clk),
|
||||||
|
.rst(rst),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APB slave interface
|
||||||
|
*/
|
||||||
|
.s_apb(apb_dp_ctrl),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APB master interfaces
|
||||||
|
*/
|
||||||
|
.m_apb(apb_port_dp_ctrl)
|
||||||
|
);
|
||||||
|
|
||||||
if (PTP_TS_EN) begin : ptp
|
if (PTP_TS_EN) begin : ptp
|
||||||
|
|
||||||
taxi_ptp_td_phc_axil #(
|
taxi_ptp_td_phc_axil #(
|
||||||
@@ -232,8 +344,8 @@ if (PTP_TS_EN) begin : ptp
|
|||||||
/*
|
/*
|
||||||
* Control register interface
|
* Control register interface
|
||||||
*/
|
*/
|
||||||
.s_axil_wr(s_axil_ctrl[1]),
|
.s_axil_wr(axil_ctrl[2]),
|
||||||
.s_axil_rd(s_axil_ctrl[1]),
|
.s_axil_rd(axil_ctrl[2]),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PTP
|
* PTP
|
||||||
@@ -362,8 +474,13 @@ for (genvar p = 0; p < PORTS; p = p + 1) begin : port
|
|||||||
/*
|
/*
|
||||||
* Control register interface
|
* Control register interface
|
||||||
*/
|
*/
|
||||||
.s_axil_wr(s_axil_ctrl[PORT_OFFSET+p]),
|
.s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET+p]),
|
||||||
.s_axil_rd(s_axil_ctrl[PORT_OFFSET+p]),
|
.s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET+p]),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Datapath control register interface
|
||||||
|
*/
|
||||||
|
.s_apb_dp_ctrl(apb_port_dp_ctrl[p]),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMA
|
* DMA
|
||||||
|
|||||||
546
src/cndm/rtl/cndm_micro_dp_mgr.sv
Normal file
546
src/cndm/rtl/cndm_micro_dp_mgr.sv
Normal file
@@ -0,0 +1,546 @@
|
|||||||
|
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2026 FPGA Ninja, LLC
|
||||||
|
|
||||||
|
Authors:
|
||||||
|
- Alex Forencich
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
`resetall
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
`default_nettype none
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Datapath manager
|
||||||
|
*/
|
||||||
|
module cndm_micro_dp_mgr #
|
||||||
|
(
|
||||||
|
parameter PORTS = 2,
|
||||||
|
parameter PORT_BASE_ADDR = 0
|
||||||
|
)
|
||||||
|
(
|
||||||
|
input wire logic clk,
|
||||||
|
input wire logic rst,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Command interface
|
||||||
|
*/
|
||||||
|
taxi_axis_if.snk s_axis_cmd,
|
||||||
|
taxi_axis_if.src m_axis_rsp,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* APB master interface (datapath control)
|
||||||
|
*/
|
||||||
|
taxi_apb_if.mst m_apb_dp_ctrl
|
||||||
|
);
|
||||||
|
|
||||||
|
// extract parameters
|
||||||
|
localparam DP_APB_ADDR_W = m_apb_dp_ctrl.ADDR_W;
|
||||||
|
localparam DP_APB_DATA_W = m_apb_dp_ctrl.DATA_W;
|
||||||
|
localparam DP_APB_STRB_W = m_apb_dp_ctrl.STRB_W;
|
||||||
|
|
||||||
|
typedef enum logic [15:0] {
|
||||||
|
CMD_OP_NOP = 16'h0000,
|
||||||
|
|
||||||
|
CMD_OP_CREATE_EQ = 16'h0200,
|
||||||
|
CMD_OP_MODIFY_EQ = 16'h0201,
|
||||||
|
CMD_OP_QUERY_EQ = 16'h0202,
|
||||||
|
CMD_OP_DESTROY_EQ = 16'h0203,
|
||||||
|
|
||||||
|
CMD_OP_CREATE_CQ = 16'h0210,
|
||||||
|
CMD_OP_MODIFY_CQ = 16'h0211,
|
||||||
|
CMD_OP_QUERY_CQ = 16'h0212,
|
||||||
|
CMD_OP_DESTROY_CQ = 16'h0213,
|
||||||
|
|
||||||
|
CMD_OP_CREATE_SQ = 16'h0220,
|
||||||
|
CMD_OP_MODIFY_SQ = 16'h0221,
|
||||||
|
CMD_OP_QUERY_SQ = 16'h0222,
|
||||||
|
CMD_OP_DESTROY_SQ = 16'h0223,
|
||||||
|
|
||||||
|
CMD_OP_CREATE_RQ = 16'h0230,
|
||||||
|
CMD_OP_MODIFY_RQ = 16'h0231,
|
||||||
|
CMD_OP_QUERY_RQ = 16'h0232,
|
||||||
|
CMD_OP_DESTROY_RQ = 16'h0233,
|
||||||
|
|
||||||
|
CMD_OP_CREATE_QP = 16'h0240,
|
||||||
|
CMD_OP_MODIFY_QP = 16'h0241,
|
||||||
|
CMD_OP_QUERY_QP = 16'h0242,
|
||||||
|
CMD_OP_DESTROY_QP = 16'h0243
|
||||||
|
} cmd_opcode_t;
|
||||||
|
|
||||||
|
typedef enum logic [4:0] {
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_START,
|
||||||
|
STATE_Q_RESET_1,
|
||||||
|
STATE_Q_RESET_2,
|
||||||
|
STATE_Q_SET_BASE_L,
|
||||||
|
STATE_Q_SET_BASE_H,
|
||||||
|
STATE_Q_ENABLE,
|
||||||
|
STATE_Q_DISABLE,
|
||||||
|
STATE_SEND_RSP,
|
||||||
|
STATE_PAD_RSP
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
state_t state_reg = STATE_IDLE, state_next;
|
||||||
|
|
||||||
|
logic s_axis_cmd_tready_reg = 1'b0, s_axis_cmd_tready_next;
|
||||||
|
|
||||||
|
logic [31:0] m_axis_rsp_tdata_reg = '0, m_axis_rsp_tdata_next;
|
||||||
|
logic m_axis_rsp_tvalid_reg = 1'b0, m_axis_rsp_tvalid_next;
|
||||||
|
logic m_axis_rsp_tlast_reg = 1'b0, m_axis_rsp_tlast_next;
|
||||||
|
|
||||||
|
logic [DP_APB_ADDR_W-1:0] m_apb_dp_ctrl_paddr_reg = '0, m_apb_dp_ctrl_paddr_next;
|
||||||
|
logic m_apb_dp_ctrl_psel_reg = 1'b0, m_apb_dp_ctrl_psel_next;
|
||||||
|
logic m_apb_dp_ctrl_penable_reg = 1'b0, m_apb_dp_ctrl_penable_next;
|
||||||
|
logic m_apb_dp_ctrl_pwrite_reg = 1'b0, m_apb_dp_ctrl_pwrite_next;
|
||||||
|
logic [DP_APB_DATA_W-1:0] m_apb_dp_ctrl_pwdata_reg = '0, m_apb_dp_ctrl_pwdata_next;
|
||||||
|
logic [DP_APB_STRB_W-1:0] m_apb_dp_ctrl_pstrb_reg = '0, m_apb_dp_ctrl_pstrb_next;
|
||||||
|
|
||||||
|
// command RAM
|
||||||
|
localparam CMD_AW = 4;
|
||||||
|
|
||||||
|
logic [31:0] cmd_ram[2**CMD_AW];
|
||||||
|
logic [31:0] cmd_ram_wr_data;
|
||||||
|
logic [CMD_AW-1:0] cmd_ram_wr_addr;
|
||||||
|
logic cmd_ram_wr_en;
|
||||||
|
logic [CMD_AW-1:0] cmd_ram_rd_addr;
|
||||||
|
wire [31:0] cmd_ram_rd_data = cmd_ram[cmd_ram_rd_addr];
|
||||||
|
|
||||||
|
assign s_axis_cmd.tready = s_axis_cmd_tready_reg;
|
||||||
|
|
||||||
|
assign m_axis_rsp.tdata = m_axis_rsp_tdata_reg;
|
||||||
|
assign m_axis_rsp.tkeep = '1;
|
||||||
|
assign m_axis_rsp.tstrb = m_axis_rsp.tkeep;
|
||||||
|
assign m_axis_rsp.tvalid = m_axis_rsp_tvalid_reg;
|
||||||
|
assign m_axis_rsp.tlast = m_axis_rsp_tlast_reg;
|
||||||
|
assign m_axis_rsp.tid = '0;
|
||||||
|
assign m_axis_rsp.tdest = '0;
|
||||||
|
assign m_axis_rsp.tuser = '0;
|
||||||
|
|
||||||
|
assign m_apb_dp_ctrl.paddr = m_apb_dp_ctrl_paddr_reg;
|
||||||
|
assign m_apb_dp_ctrl.pprot = 3'b010;
|
||||||
|
assign m_apb_dp_ctrl.psel = m_apb_dp_ctrl_psel_reg;
|
||||||
|
assign m_apb_dp_ctrl.penable = m_apb_dp_ctrl_penable_reg;
|
||||||
|
assign m_apb_dp_ctrl.pwrite = m_apb_dp_ctrl_pwrite_reg;
|
||||||
|
assign m_apb_dp_ctrl.pwdata = m_apb_dp_ctrl_pwdata_reg;
|
||||||
|
assign m_apb_dp_ctrl.pstrb = m_apb_dp_ctrl_pstrb_reg;
|
||||||
|
assign m_apb_dp_ctrl.pauser = '0;
|
||||||
|
assign m_apb_dp_ctrl.pwuser = '0;
|
||||||
|
|
||||||
|
logic cmd_frame_reg = 1'b0, cmd_frame_next;
|
||||||
|
logic [3:0] cmd_ptr_reg = '0, cmd_ptr_next;
|
||||||
|
logic rsp_frame_reg = 1'b0, rsp_frame_next;
|
||||||
|
logic [3:0] rsp_ptr_reg = '0, rsp_ptr_next;
|
||||||
|
|
||||||
|
logic drop_cmd_reg = 1'b0, drop_cmd_next;
|
||||||
|
|
||||||
|
logic [15:0] opcode_reg = '0, opcode_next;
|
||||||
|
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 [DP_APB_ADDR_W-1:0] block_base_addr_reg = '0, block_base_addr_next;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
|
||||||
|
s_axis_cmd_tready_next = 1'b0;
|
||||||
|
|
||||||
|
m_axis_rsp_tdata_next = m_axis_rsp_tdata_reg;
|
||||||
|
m_axis_rsp_tvalid_next = m_axis_rsp_tvalid_reg && !m_axis_rsp.tready;
|
||||||
|
m_axis_rsp_tlast_next = m_axis_rsp_tlast_reg;
|
||||||
|
|
||||||
|
m_apb_dp_ctrl_paddr_next = m_apb_dp_ctrl_paddr_reg;
|
||||||
|
m_apb_dp_ctrl_psel_next = m_apb_dp_ctrl_psel_reg && !m_apb_dp_ctrl.pready;
|
||||||
|
m_apb_dp_ctrl_penable_next = m_apb_dp_ctrl_psel_reg && !m_apb_dp_ctrl.pready;
|
||||||
|
m_apb_dp_ctrl_pwrite_next = m_apb_dp_ctrl_pwrite_reg;
|
||||||
|
m_apb_dp_ctrl_pwdata_next = m_apb_dp_ctrl_pwdata_reg;
|
||||||
|
m_apb_dp_ctrl_pstrb_next = m_apb_dp_ctrl_pstrb_reg;
|
||||||
|
|
||||||
|
cmd_ram_wr_data = s_axis_cmd.tdata;
|
||||||
|
cmd_ram_wr_addr = cmd_ptr_reg;
|
||||||
|
cmd_ram_wr_en = 1'b0;
|
||||||
|
cmd_ram_rd_addr = '0;
|
||||||
|
|
||||||
|
cmd_frame_next = cmd_frame_reg;
|
||||||
|
cmd_ptr_next = cmd_ptr_reg;
|
||||||
|
rsp_frame_next = rsp_frame_reg;
|
||||||
|
rsp_ptr_next = rsp_ptr_reg;
|
||||||
|
|
||||||
|
drop_cmd_next = drop_cmd_reg;
|
||||||
|
|
||||||
|
opcode_next = opcode_reg;
|
||||||
|
flags_next = flags_reg;
|
||||||
|
port_next = port_reg;
|
||||||
|
qn_next = qn_reg;
|
||||||
|
|
||||||
|
block_base_addr_next = block_base_addr_reg;
|
||||||
|
|
||||||
|
if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin
|
||||||
|
if (s_axis_cmd.tlast) begin
|
||||||
|
cmd_frame_next = 1'b0;
|
||||||
|
cmd_ptr_next = '0;
|
||||||
|
end else begin
|
||||||
|
cmd_ptr_next = cmd_ptr_reg + 1;
|
||||||
|
cmd_frame_next = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
case (state_reg)
|
||||||
|
STATE_IDLE: begin
|
||||||
|
s_axis_cmd_tready_next = !m_axis_rsp_tvalid_reg && !rsp_frame_reg;
|
||||||
|
|
||||||
|
cmd_ram_wr_data = s_axis_cmd.tdata;
|
||||||
|
cmd_ram_wr_addr = cmd_ptr_reg;
|
||||||
|
cmd_ram_wr_en = 1'b1;
|
||||||
|
|
||||||
|
// save some important fields
|
||||||
|
case (cmd_ptr_reg)
|
||||||
|
4'd0: opcode_next = s_axis_cmd.tdata[31:16];
|
||||||
|
4'd1: flags_next = s_axis_cmd.tdata;
|
||||||
|
4'd2: port_next = s_axis_cmd.tdata[15:0];
|
||||||
|
4'd3: qn_next = s_axis_cmd.tdata[23:0];
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (s_axis_cmd.tready && s_axis_cmd.tvalid && !drop_cmd_reg) begin
|
||||||
|
if (s_axis_cmd.tlast || &cmd_ptr_reg) begin
|
||||||
|
drop_cmd_next = !s_axis_cmd.tlast;
|
||||||
|
state_next = STATE_START;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_START: begin
|
||||||
|
// determine block base address
|
||||||
|
case (opcode_reg)
|
||||||
|
CMD_OP_CREATE_EQ,
|
||||||
|
CMD_OP_MODIFY_EQ,
|
||||||
|
CMD_OP_QUERY_EQ,
|
||||||
|
CMD_OP_DESTROY_EQ:
|
||||||
|
begin
|
||||||
|
// EQ
|
||||||
|
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 16'h0000);
|
||||||
|
end
|
||||||
|
CMD_OP_CREATE_CQ,
|
||||||
|
CMD_OP_MODIFY_CQ,
|
||||||
|
CMD_OP_QUERY_CQ,
|
||||||
|
CMD_OP_DESTROY_CQ:
|
||||||
|
begin
|
||||||
|
// CQ
|
||||||
|
if (qn_reg[0]) begin
|
||||||
|
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 16'h0300);
|
||||||
|
end else begin
|
||||||
|
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 16'h0400);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
CMD_OP_CREATE_SQ,
|
||||||
|
CMD_OP_MODIFY_SQ,
|
||||||
|
CMD_OP_QUERY_SQ,
|
||||||
|
CMD_OP_DESTROY_SQ:
|
||||||
|
begin
|
||||||
|
// SQ
|
||||||
|
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 16'h0100);
|
||||||
|
end
|
||||||
|
CMD_OP_CREATE_RQ,
|
||||||
|
CMD_OP_MODIFY_RQ,
|
||||||
|
CMD_OP_QUERY_RQ,
|
||||||
|
CMD_OP_DESTROY_RQ:
|
||||||
|
begin
|
||||||
|
// RQ
|
||||||
|
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 16'h0200);
|
||||||
|
end
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case (opcode_reg)
|
||||||
|
16'h0000: begin
|
||||||
|
// NOP
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
state_next = STATE_SEND_RSP;
|
||||||
|
end
|
||||||
|
CMD_OP_CREATE_EQ,
|
||||||
|
CMD_OP_CREATE_CQ,
|
||||||
|
CMD_OP_CREATE_SQ,
|
||||||
|
CMD_OP_CREATE_RQ:
|
||||||
|
begin
|
||||||
|
// create queue operation
|
||||||
|
state_next = STATE_Q_RESET_1;
|
||||||
|
end
|
||||||
|
CMD_OP_MODIFY_EQ,
|
||||||
|
CMD_OP_MODIFY_CQ,
|
||||||
|
CMD_OP_MODIFY_SQ,
|
||||||
|
CMD_OP_MODIFY_RQ:
|
||||||
|
begin
|
||||||
|
// modify queue operation
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
// determine base address
|
||||||
|
|
||||||
|
state_next = STATE_PAD_RSP;
|
||||||
|
end
|
||||||
|
CMD_OP_QUERY_EQ,
|
||||||
|
CMD_OP_QUERY_CQ,
|
||||||
|
CMD_OP_QUERY_SQ,
|
||||||
|
CMD_OP_QUERY_RQ:
|
||||||
|
begin
|
||||||
|
// query queue operation
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
// determine base address
|
||||||
|
|
||||||
|
state_next = STATE_PAD_RSP;
|
||||||
|
end
|
||||||
|
CMD_OP_DESTROY_EQ,
|
||||||
|
CMD_OP_DESTROY_CQ,
|
||||||
|
CMD_OP_DESTROY_SQ,
|
||||||
|
CMD_OP_DESTROY_RQ:
|
||||||
|
begin
|
||||||
|
// destroy queue operation
|
||||||
|
state_next = STATE_Q_DISABLE;
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
// unknown opcode
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO error code
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
state_next = STATE_PAD_RSP;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
STATE_Q_RESET_1: begin
|
||||||
|
// reset queue 1
|
||||||
|
if (!m_apb_dp_ctrl_psel_reg) begin
|
||||||
|
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 16'h0000;
|
||||||
|
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_Q_RESET_2;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_RESET_1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_Q_RESET_2: begin
|
||||||
|
// reset queue 2
|
||||||
|
|
||||||
|
cmd_ram_wr_data = 32'(block_base_addr_reg + 16'h0004) + PORT_BASE_ADDR;
|
||||||
|
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 = block_base_addr_reg + 16'h0004;
|
||||||
|
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_Q_SET_BASE_L;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_RESET_2;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_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 = block_base_addr_reg + 16'h0008;
|
||||||
|
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_Q_SET_BASE_H;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_SET_BASE_L;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_Q_SET_BASE_H: 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 = block_base_addr_reg + 16'h000C;
|
||||||
|
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_Q_ENABLE;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_SET_BASE_H;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_Q_ENABLE: begin
|
||||||
|
// enable queue
|
||||||
|
cmd_ram_rd_addr = 6;
|
||||||
|
if (!m_apb_dp_ctrl_psel_reg) begin
|
||||||
|
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 16'h0000;
|
||||||
|
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[19:16] = cmd_ram_rd_data[3:0];
|
||||||
|
m_apb_dp_ctrl_pwdata_next[0] = 1'b1;
|
||||||
|
m_apb_dp_ctrl_pstrb_next = '1;
|
||||||
|
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
state_next = STATE_SEND_RSP;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_ENABLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_Q_DISABLE: begin
|
||||||
|
// disable queue
|
||||||
|
if (!m_apb_dp_ctrl_psel_reg) begin
|
||||||
|
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 16'h0000;
|
||||||
|
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;
|
||||||
|
|
||||||
|
m_axis_rsp_tdata_next = '0; // TODO
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = 1'b0;
|
||||||
|
|
||||||
|
state_next = STATE_SEND_RSP;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_Q_DISABLE;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_SEND_RSP: begin
|
||||||
|
// send response in the form of an edited command
|
||||||
|
cmd_ram_rd_addr = rsp_ptr_reg;
|
||||||
|
if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin
|
||||||
|
m_axis_rsp_tdata_next = cmd_ram_rd_data;
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = &rsp_ptr_reg;
|
||||||
|
|
||||||
|
if (&rsp_ptr_reg) begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_SEND_RSP;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_SEND_RSP;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
STATE_PAD_RSP: begin
|
||||||
|
// zero pad response
|
||||||
|
if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin
|
||||||
|
m_axis_rsp_tdata_next = '0;
|
||||||
|
m_axis_rsp_tvalid_next = 1'b1;
|
||||||
|
m_axis_rsp_tlast_next = &rsp_ptr_reg;
|
||||||
|
|
||||||
|
if (&rsp_ptr_reg) begin
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_PAD_RSP;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
state_next = STATE_PAD_RSP;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default: begin
|
||||||
|
// unknown state; return to idle
|
||||||
|
state_next = STATE_IDLE;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
if (drop_cmd_reg) begin
|
||||||
|
s_axis_cmd_tready_next = 1'b1;
|
||||||
|
|
||||||
|
if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin
|
||||||
|
drop_cmd_next = !s_axis_cmd.tlast;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_axis_rsp_tvalid_next && (!m_axis_rsp_tvalid_reg || m_axis_rsp.tready)) begin
|
||||||
|
if (m_axis_rsp_tlast_next) begin
|
||||||
|
rsp_ptr_next = '0;
|
||||||
|
end else begin
|
||||||
|
rsp_ptr_next = rsp_ptr_reg + 1;
|
||||||
|
rsp_frame_next = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (m_axis_rsp.tready && m_axis_rsp.tvalid) begin
|
||||||
|
if (m_axis_rsp.tlast) begin
|
||||||
|
rsp_frame_next = 1'b0;
|
||||||
|
rsp_ptr_next = '0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (cmd_ram_wr_en) begin
|
||||||
|
cmd_ram[cmd_ram_wr_addr] = cmd_ram_wr_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
state_reg <= state_next;
|
||||||
|
|
||||||
|
s_axis_cmd_tready_reg <= s_axis_cmd_tready_next;
|
||||||
|
|
||||||
|
m_axis_rsp_tdata_reg <= m_axis_rsp_tdata_next;
|
||||||
|
m_axis_rsp_tvalid_reg <= m_axis_rsp_tvalid_next;
|
||||||
|
m_axis_rsp_tlast_reg <= m_axis_rsp_tlast_next;
|
||||||
|
|
||||||
|
m_apb_dp_ctrl_paddr_reg <= m_apb_dp_ctrl_paddr_next;
|
||||||
|
m_apb_dp_ctrl_psel_reg <= m_apb_dp_ctrl_psel_next;
|
||||||
|
m_apb_dp_ctrl_penable_reg <= m_apb_dp_ctrl_penable_next;
|
||||||
|
m_apb_dp_ctrl_pwrite_reg <= m_apb_dp_ctrl_pwrite_next;
|
||||||
|
m_apb_dp_ctrl_pwdata_reg <= m_apb_dp_ctrl_pwdata_next;
|
||||||
|
m_apb_dp_ctrl_pstrb_reg <= m_apb_dp_ctrl_pstrb_next;
|
||||||
|
|
||||||
|
cmd_frame_reg <= cmd_frame_next;
|
||||||
|
cmd_ptr_reg <= cmd_ptr_next;
|
||||||
|
rsp_frame_reg <= rsp_frame_next;
|
||||||
|
rsp_ptr_reg <= rsp_ptr_next;
|
||||||
|
|
||||||
|
drop_cmd_reg <= drop_cmd_next;
|
||||||
|
|
||||||
|
opcode_reg <= opcode_next;
|
||||||
|
flags_reg <= flags_next;
|
||||||
|
port_reg <= port_next;
|
||||||
|
qn_reg <= qn_next;
|
||||||
|
|
||||||
|
block_base_addr_reg <= block_base_addr_next;
|
||||||
|
|
||||||
|
if (rst) begin
|
||||||
|
state_reg <= STATE_IDLE;
|
||||||
|
|
||||||
|
s_axis_cmd_tready_reg <= 1'b0;
|
||||||
|
m_axis_rsp_tvalid_reg <= 1'b0;
|
||||||
|
|
||||||
|
m_apb_dp_ctrl_psel_reg <= 1'b0;
|
||||||
|
m_apb_dp_ctrl_penable_reg <= 1'b0;
|
||||||
|
|
||||||
|
cmd_frame_reg <= 1'b0;
|
||||||
|
cmd_ptr_reg <= '0;
|
||||||
|
rsp_frame_reg <= 1'b0;
|
||||||
|
rsp_ptr_reg <= '0;
|
||||||
|
|
||||||
|
drop_cmd_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
||||||
|
|
||||||
|
`resetall
|
||||||
@@ -523,8 +523,8 @@ core_inst (
|
|||||||
/*
|
/*
|
||||||
* Control register interface
|
* Control register interface
|
||||||
*/
|
*/
|
||||||
.s_axil_wr(axil_ctrl_bar),
|
.s_axil_ctrl_wr(axil_ctrl_bar),
|
||||||
.s_axil_rd(axil_ctrl_bar),
|
.s_axil_ctrl_rd(axil_ctrl_bar),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMA
|
* DMA
|
||||||
|
|||||||
@@ -26,8 +26,13 @@ module cndm_micro_port #(
|
|||||||
/*
|
/*
|
||||||
* Control register interface
|
* Control register interface
|
||||||
*/
|
*/
|
||||||
taxi_axil_if.wr_slv s_axil_wr,
|
taxi_axil_if.wr_slv s_axil_ctrl_wr,
|
||||||
taxi_axil_if.rd_slv s_axil_rd,
|
taxi_axil_if.rd_slv s_axil_ctrl_rd,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Datapath control register interface
|
||||||
|
*/
|
||||||
|
taxi_apb_if.slv s_apb_dp_ctrl,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DMA
|
* DMA
|
||||||
@@ -61,8 +66,8 @@ module cndm_micro_port #(
|
|||||||
taxi_axis_if.snk mac_axis_rx
|
taxi_axis_if.snk mac_axis_rx
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam AXIL_ADDR_W = s_axil_wr.ADDR_W;
|
localparam AXIL_ADDR_W = s_axil_ctrl_wr.ADDR_W;
|
||||||
localparam AXIL_DATA_W = s_axil_wr.DATA_W;
|
localparam AXIL_DATA_W = s_axil_ctrl_wr.DATA_W;
|
||||||
|
|
||||||
localparam RAM_SEGS = dma_ram_wr.SEGS;
|
localparam RAM_SEGS = dma_ram_wr.SEGS;
|
||||||
localparam RAM_SEG_ADDR_W = dma_ram_wr.SEG_ADDR_W;
|
localparam RAM_SEG_ADDR_W = dma_ram_wr.SEG_ADDR_W;
|
||||||
@@ -90,128 +95,222 @@ logic [3:0] rxcq_size_reg = '0;
|
|||||||
logic [63:0] rxcq_base_addr_reg = '0;
|
logic [63:0] rxcq_base_addr_reg = '0;
|
||||||
wire [15:0] rxcq_prod;
|
wire [15:0] rxcq_prod;
|
||||||
|
|
||||||
logic s_axil_awready_reg = 1'b0;
|
logic s_axil_ctrl_awready_reg = 1'b0;
|
||||||
logic s_axil_wready_reg = 1'b0;
|
logic s_axil_ctrl_wready_reg = 1'b0;
|
||||||
logic s_axil_bvalid_reg = 1'b0;
|
logic s_axil_ctrl_bvalid_reg = 1'b0;
|
||||||
|
|
||||||
logic s_axil_arready_reg = 1'b0;
|
logic s_axil_ctrl_arready_reg = 1'b0;
|
||||||
logic [AXIL_DATA_W-1:0] s_axil_rdata_reg = '0;
|
logic [AXIL_DATA_W-1:0] s_axil_ctrl_rdata_reg = '0;
|
||||||
logic s_axil_rvalid_reg = 1'b0;
|
logic s_axil_ctrl_rvalid_reg = 1'b0;
|
||||||
|
|
||||||
assign s_axil_wr.awready = s_axil_awready_reg;
|
assign s_axil_ctrl_wr.awready = s_axil_ctrl_awready_reg;
|
||||||
assign s_axil_wr.wready = s_axil_wready_reg;
|
assign s_axil_ctrl_wr.wready = s_axil_ctrl_wready_reg;
|
||||||
assign s_axil_wr.bresp = '0;
|
assign s_axil_ctrl_wr.bresp = '0;
|
||||||
assign s_axil_wr.buser = '0;
|
assign s_axil_ctrl_wr.buser = '0;
|
||||||
assign s_axil_wr.bvalid = s_axil_bvalid_reg;
|
assign s_axil_ctrl_wr.bvalid = s_axil_ctrl_bvalid_reg;
|
||||||
|
|
||||||
assign s_axil_rd.arready = s_axil_arready_reg;
|
assign s_axil_ctrl_rd.arready = s_axil_ctrl_arready_reg;
|
||||||
assign s_axil_rd.rdata = s_axil_rdata_reg;
|
assign s_axil_ctrl_rd.rdata = s_axil_ctrl_rdata_reg;
|
||||||
assign s_axil_rd.rresp = '0;
|
assign s_axil_ctrl_rd.rresp = '0;
|
||||||
assign s_axil_rd.ruser = '0;
|
assign s_axil_ctrl_rd.ruser = '0;
|
||||||
assign s_axil_rd.rvalid = s_axil_rvalid_reg;
|
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
|
always_ff @(posedge clk) begin
|
||||||
s_axil_awready_reg <= 1'b0;
|
s_axil_ctrl_awready_reg <= 1'b0;
|
||||||
s_axil_wready_reg <= 1'b0;
|
s_axil_ctrl_wready_reg <= 1'b0;
|
||||||
s_axil_bvalid_reg <= s_axil_bvalid_reg && !s_axil_wr.bready;
|
s_axil_ctrl_bvalid_reg <= s_axil_ctrl_bvalid_reg && !s_axil_ctrl_wr.bready;
|
||||||
|
|
||||||
s_axil_arready_reg <= 1'b0;
|
s_axil_ctrl_arready_reg <= 1'b0;
|
||||||
s_axil_rvalid_reg <= s_axil_rvalid_reg && !s_axil_rd.rready;
|
s_axil_ctrl_rvalid_reg <= s_axil_ctrl_rvalid_reg && !s_axil_ctrl_rd.rready;
|
||||||
|
|
||||||
if (s_axil_wr.awvalid && s_axil_wr.wvalid && !s_axil_bvalid_reg) begin
|
s_apb_dp_ctrl_pready_reg <= 1'b0;
|
||||||
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})
|
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[15:2], 2'b00})
|
||||||
16'h0100: begin
|
16'h0100: begin
|
||||||
txq_en_reg <= s_axil_wr.wdata[0];
|
txq_en_reg <= s_axil_ctrl_wr.wdata[0];
|
||||||
txq_size_reg <= s_axil_wr.wdata[19:16];
|
txq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
|
||||||
end
|
end
|
||||||
16'h0104: txq_prod_reg <= s_axil_wr.wdata[15:0];
|
16'h0104: txq_prod_reg <= s_axil_ctrl_wr.wdata[15:0];
|
||||||
16'h0108: txq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
16'h0108: txq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
|
||||||
16'h010c: txq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
16'h010c: txq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
|
||||||
|
|
||||||
16'h0200: begin
|
16'h0200: begin
|
||||||
rxq_en_reg <= s_axil_wr.wdata[0];
|
rxq_en_reg <= s_axil_ctrl_wr.wdata[0];
|
||||||
rxq_size_reg <= s_axil_wr.wdata[19:16];
|
rxq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
|
||||||
end
|
end
|
||||||
16'h0204: rxq_prod_reg <= s_axil_wr.wdata[15:0];
|
16'h0204: rxq_prod_reg <= s_axil_ctrl_wr.wdata[15:0];
|
||||||
16'h0208: rxq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
16'h0208: rxq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
|
||||||
16'h020c: rxq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
16'h020c: rxq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
|
||||||
|
|
||||||
16'h0300: begin
|
16'h0300: begin
|
||||||
txcq_en_reg <= s_axil_wr.wdata[0];
|
txcq_en_reg <= s_axil_ctrl_wr.wdata[0];
|
||||||
txcq_size_reg <= s_axil_wr.wdata[19:16];
|
txcq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
|
||||||
end
|
end
|
||||||
16'h0308: txcq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
16'h0308: txcq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
|
||||||
16'h030c: txcq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
16'h030c: txcq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
|
||||||
|
|
||||||
16'h0400: begin
|
16'h0400: begin
|
||||||
rxcq_en_reg <= s_axil_wr.wdata[0];
|
rxcq_en_reg <= s_axil_ctrl_wr.wdata[0];
|
||||||
rxcq_size_reg <= s_axil_wr.wdata[19:16];
|
rxcq_size_reg <= s_axil_ctrl_wr.wdata[19:16];
|
||||||
end
|
end
|
||||||
16'h0408: rxcq_base_addr_reg[31:0] <= s_axil_wr.wdata;
|
16'h0408: rxcq_base_addr_reg[31:0] <= s_axil_ctrl_wr.wdata;
|
||||||
16'h040c: rxcq_base_addr_reg[63:32] <= s_axil_wr.wdata;
|
16'h040c: rxcq_base_addr_reg[63:32] <= s_axil_ctrl_wr.wdata;
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
if (s_axil_rd.arvalid && !s_axil_rvalid_reg) begin
|
if (s_axil_ctrl_rd.arvalid && !s_axil_ctrl_rvalid_reg) begin
|
||||||
s_axil_rdata_reg <= '0;
|
s_axil_ctrl_rdata_reg <= '0;
|
||||||
|
|
||||||
s_axil_arready_reg <= 1'b1;
|
s_axil_ctrl_arready_reg <= 1'b1;
|
||||||
s_axil_rvalid_reg <= 1'b1;
|
s_axil_ctrl_rvalid_reg <= 1'b1;
|
||||||
|
|
||||||
case ({s_axil_rd.araddr[15:2], 2'b00})
|
case ({s_axil_ctrl_rd.araddr[15:2], 2'b00})
|
||||||
16'h0100: begin
|
16'h0100: begin
|
||||||
s_axil_rdata_reg[0] <= txq_en_reg;
|
s_axil_ctrl_rdata_reg[0] <= txq_en_reg;
|
||||||
s_axil_rdata_reg[19:16] <= txq_size_reg;
|
s_axil_ctrl_rdata_reg[19:16] <= txq_size_reg;
|
||||||
end
|
end
|
||||||
16'h0104: begin
|
16'h0104: begin
|
||||||
s_axil_rdata_reg[15:0] <= txq_prod_reg;
|
s_axil_ctrl_rdata_reg[15:0] <= txq_prod_reg;
|
||||||
s_axil_rdata_reg[31:16] <= txq_cons;
|
s_axil_ctrl_rdata_reg[31:16] <= txq_cons;
|
||||||
end
|
end
|
||||||
16'h0108: s_axil_rdata_reg <= txq_base_addr_reg[31:0];
|
16'h0108: s_axil_ctrl_rdata_reg <= txq_base_addr_reg[31:0];
|
||||||
16'h010c: s_axil_rdata_reg <= txq_base_addr_reg[63:32];
|
16'h010c: s_axil_ctrl_rdata_reg <= txq_base_addr_reg[63:32];
|
||||||
|
|
||||||
16'h0200: begin
|
16'h0200: begin
|
||||||
s_axil_rdata_reg[0] <= rxq_en_reg;
|
s_axil_ctrl_rdata_reg[0] <= rxq_en_reg;
|
||||||
s_axil_rdata_reg[19:16] <= rxq_size_reg;
|
s_axil_ctrl_rdata_reg[19:16] <= rxq_size_reg;
|
||||||
end
|
end
|
||||||
16'h0204: begin
|
16'h0204: begin
|
||||||
s_axil_rdata_reg[15:0] <= rxq_prod_reg;
|
s_axil_ctrl_rdata_reg[15:0] <= rxq_prod_reg;
|
||||||
s_axil_rdata_reg[31:16] <= rxq_cons;
|
s_axil_ctrl_rdata_reg[31:16] <= rxq_cons;
|
||||||
end
|
end
|
||||||
16'h0208: s_axil_rdata_reg <= rxq_base_addr_reg[31:0];
|
16'h0208: s_axil_ctrl_rdata_reg <= rxq_base_addr_reg[31:0];
|
||||||
16'h020c: s_axil_rdata_reg <= rxq_base_addr_reg[63:32];
|
16'h020c: s_axil_ctrl_rdata_reg <= rxq_base_addr_reg[63:32];
|
||||||
|
|
||||||
16'h0300: begin
|
16'h0300: begin
|
||||||
s_axil_rdata_reg[0] <= txcq_en_reg;
|
s_axil_ctrl_rdata_reg[0] <= txcq_en_reg;
|
||||||
s_axil_rdata_reg[19:16] <= txcq_size_reg;
|
s_axil_ctrl_rdata_reg[19:16] <= txcq_size_reg;
|
||||||
end
|
end
|
||||||
16'h0304: s_axil_rdata_reg[15:0] <= txcq_prod;
|
16'h0304: s_axil_ctrl_rdata_reg[15:0] <= txcq_prod;
|
||||||
16'h0308: s_axil_rdata_reg <= txcq_base_addr_reg[31:0];
|
16'h0308: s_axil_ctrl_rdata_reg <= txcq_base_addr_reg[31:0];
|
||||||
16'h030c: s_axil_rdata_reg <= txcq_base_addr_reg[63:32];
|
16'h030c: s_axil_ctrl_rdata_reg <= txcq_base_addr_reg[63:32];
|
||||||
|
|
||||||
16'h0400: begin
|
16'h0400: begin
|
||||||
s_axil_rdata_reg[0] <= rxcq_en_reg;
|
s_axil_ctrl_rdata_reg[0] <= rxcq_en_reg;
|
||||||
s_axil_rdata_reg[19:16] <= rxcq_size_reg;
|
s_axil_ctrl_rdata_reg[19:16] <= rxcq_size_reg;
|
||||||
end
|
end
|
||||||
16'h0404: s_axil_rdata_reg[15:0] <= rxcq_prod;
|
16'h0404: s_axil_ctrl_rdata_reg[15:0] <= rxcq_prod;
|
||||||
16'h0408: s_axil_rdata_reg <= rxcq_base_addr_reg[31:0];
|
16'h0408: s_axil_ctrl_rdata_reg <= rxcq_base_addr_reg[31:0];
|
||||||
16'h040c: s_axil_rdata_reg <= rxcq_base_addr_reg[63:32];
|
16'h040c: 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[15:2], 2'b00})
|
||||||
|
16'h0100: begin
|
||||||
|
txq_en_reg <= s_apb_dp_ctrl.pwdata[0];
|
||||||
|
txq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
|
||||||
|
end
|
||||||
|
16'h0104: txq_prod_reg <= s_apb_dp_ctrl.pwdata[15:0];
|
||||||
|
16'h0108: txq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
16'h010c: txq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
|
||||||
|
16'h0200: begin
|
||||||
|
rxq_en_reg <= s_apb_dp_ctrl.pwdata[0];
|
||||||
|
rxq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
|
||||||
|
end
|
||||||
|
16'h0204: rxq_prod_reg <= s_apb_dp_ctrl.pwdata[15:0];
|
||||||
|
16'h0208: rxq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
16'h020c: rxq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
|
||||||
|
16'h0300: begin
|
||||||
|
txcq_en_reg <= s_apb_dp_ctrl.pwdata[0];
|
||||||
|
txcq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
|
||||||
|
end
|
||||||
|
16'h0308: txcq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
16'h030c: txcq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
|
||||||
|
16'h0400: begin
|
||||||
|
rxcq_en_reg <= s_apb_dp_ctrl.pwdata[0];
|
||||||
|
rxcq_size_reg <= s_apb_dp_ctrl.pwdata[19:16];
|
||||||
|
end
|
||||||
|
16'h0408: rxcq_base_addr_reg[31:0] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
16'h040c: rxcq_base_addr_reg[63:32] <= s_apb_dp_ctrl.pwdata;
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
case ({s_apb_dp_ctrl.paddr[15:2], 2'b00})
|
||||||
|
16'h0100: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[0] <= txq_en_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[19:16] <= txq_size_reg;
|
||||||
|
end
|
||||||
|
16'h0104: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[15:0] <= txq_prod_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[31:16] <= txq_cons;
|
||||||
|
end
|
||||||
|
16'h0108: s_apb_dp_ctrl_prdata_reg <= txq_base_addr_reg[31:0];
|
||||||
|
16'h010c: s_apb_dp_ctrl_prdata_reg <= txq_base_addr_reg[63:32];
|
||||||
|
|
||||||
|
16'h0200: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[0] <= rxq_en_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[19:16] <= rxq_size_reg;
|
||||||
|
end
|
||||||
|
16'h0204: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[15:0] <= rxq_prod_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[31:16] <= rxq_cons;
|
||||||
|
end
|
||||||
|
16'h0208: s_apb_dp_ctrl_prdata_reg <= rxq_base_addr_reg[31:0];
|
||||||
|
16'h020c: s_apb_dp_ctrl_prdata_reg <= rxq_base_addr_reg[63:32];
|
||||||
|
|
||||||
|
16'h0300: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[0] <= txcq_en_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[19:16] <= txcq_size_reg;
|
||||||
|
end
|
||||||
|
16'h0304: s_apb_dp_ctrl_prdata_reg[15:0] <= txcq_prod;
|
||||||
|
16'h0308: s_apb_dp_ctrl_prdata_reg <= txcq_base_addr_reg[31:0];
|
||||||
|
16'h030c: s_apb_dp_ctrl_prdata_reg <= txcq_base_addr_reg[63:32];
|
||||||
|
|
||||||
|
16'h0400: begin
|
||||||
|
s_apb_dp_ctrl_prdata_reg[0] <= rxcq_en_reg;
|
||||||
|
s_apb_dp_ctrl_prdata_reg[19:16] <= rxcq_size_reg;
|
||||||
|
end
|
||||||
|
16'h0404: s_apb_dp_ctrl_prdata_reg[15:0] <= rxcq_prod;
|
||||||
|
16'h0408: s_apb_dp_ctrl_prdata_reg <= rxcq_base_addr_reg[31:0];
|
||||||
|
16'h040c: s_apb_dp_ctrl_prdata_reg <= rxcq_base_addr_reg[63:32];
|
||||||
default: begin end
|
default: begin end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
s_axil_awready_reg <= 1'b0;
|
s_axil_ctrl_awready_reg <= 1'b0;
|
||||||
s_axil_wready_reg <= 1'b0;
|
s_axil_ctrl_wready_reg <= 1'b0;
|
||||||
s_axil_bvalid_reg <= 1'b0;
|
s_axil_ctrl_bvalid_reg <= 1'b0;
|
||||||
|
|
||||||
s_axil_arready_reg <= 1'b0;
|
s_axil_ctrl_arready_reg <= 1'b0;
|
||||||
s_axil_rvalid_reg <= 1'b0;
|
s_axil_ctrl_rvalid_reg <= 1'b0;
|
||||||
|
|
||||||
|
s_apb_dp_ctrl_pready_reg <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,18 +8,49 @@ Authors:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import array
|
||||||
import logging
|
import logging
|
||||||
import struct
|
import struct
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from cocotb.queue import Queue
|
from cocotb.queue import Queue
|
||||||
|
|
||||||
|
|
||||||
|
# Command opcodes
|
||||||
|
CNDM_CMD_OP_NOP = 0x0000
|
||||||
|
|
||||||
|
CNDM_CMD_OP_CREATE_EQ = 0x0200
|
||||||
|
CNDM_CMD_OP_MODIFY_EQ = 0x0201
|
||||||
|
CNDM_CMD_OP_QUERY_EQ = 0x0202
|
||||||
|
CNDM_CMD_OP_DESTROY_EQ = 0x0203
|
||||||
|
|
||||||
|
CNDM_CMD_OP_CREATE_CQ = 0x0210
|
||||||
|
CNDM_CMD_OP_MODIFY_CQ = 0x0211
|
||||||
|
CNDM_CMD_OP_QUERY_CQ = 0x0212
|
||||||
|
CNDM_CMD_OP_DESTROY_CQ = 0x0213
|
||||||
|
|
||||||
|
CNDM_CMD_OP_CREATE_SQ = 0x0220
|
||||||
|
CNDM_CMD_OP_MODIFY_SQ = 0x0221
|
||||||
|
CNDM_CMD_OP_QUERY_SQ = 0x0222
|
||||||
|
CNDM_CMD_OP_DESTROY_SQ = 0x0223
|
||||||
|
|
||||||
|
CNDM_CMD_OP_CREATE_RQ = 0x0230
|
||||||
|
CNDM_CMD_OP_MODIFY_RQ = 0x0231
|
||||||
|
CNDM_CMD_OP_QUERY_RQ = 0x0232
|
||||||
|
CNDM_CMD_OP_DESTROY_RQ = 0x0233
|
||||||
|
|
||||||
|
CNDM_CMD_OP_CREATE_QP = 0x0240
|
||||||
|
CNDM_CMD_OP_MODIFY_QP = 0x0241
|
||||||
|
CNDM_CMD_OP_QUERY_QP = 0x0242
|
||||||
|
CNDM_CMD_OP_DESTROY_QP = 0x0243
|
||||||
|
|
||||||
|
|
||||||
class Port:
|
class Port:
|
||||||
def __init__(self, driver, index, hw_regs):
|
def __init__(self, driver, index):
|
||||||
self.driver = driver
|
self.driver = driver
|
||||||
self.log = driver.log
|
self.log = driver.log
|
||||||
self.index = index
|
self.index = index
|
||||||
self.hw_regs = hw_regs
|
self.hw_regs = driver.hw_regs
|
||||||
|
|
||||||
self.rxq_log_size = (256).bit_length()-1
|
self.rxq_log_size = (256).bit_length()-1
|
||||||
self.rxq_size = 2**self.rxq_log_size
|
self.rxq_size = 2**self.rxq_log_size
|
||||||
@@ -27,6 +58,8 @@ class Port:
|
|||||||
self.rxq = None
|
self.rxq = None
|
||||||
self.rxq_prod = 0
|
self.rxq_prod = 0
|
||||||
self.rxq_cons = 0
|
self.rxq_cons = 0
|
||||||
|
self.rx_rqn = 0
|
||||||
|
self.rxq_db_offs = 0
|
||||||
|
|
||||||
self.rx_info = [None] * self.rxq_size
|
self.rx_info = [None] * self.rxq_size
|
||||||
|
|
||||||
@@ -36,6 +69,7 @@ class Port:
|
|||||||
self.rxcq = None
|
self.rxcq = None
|
||||||
self.rxcq_prod = 0
|
self.rxcq_prod = 0
|
||||||
self.rxcq_cons = 0
|
self.rxcq_cons = 0
|
||||||
|
self.rx_cqn = 0
|
||||||
|
|
||||||
self.txq_log_size = (256).bit_length()-1
|
self.txq_log_size = (256).bit_length()-1
|
||||||
self.txq_size = 2**self.txq_log_size
|
self.txq_size = 2**self.txq_log_size
|
||||||
@@ -43,6 +77,8 @@ class Port:
|
|||||||
self.txq = None
|
self.txq = None
|
||||||
self.txq_prod = 0
|
self.txq_prod = 0
|
||||||
self.txq_cons = 0
|
self.txq_cons = 0
|
||||||
|
self.tx_sqn = 0
|
||||||
|
self.txq_db_offs = 0
|
||||||
|
|
||||||
self.tx_info = [None] * self.txq_size
|
self.tx_info = [None] * self.txq_size
|
||||||
|
|
||||||
@@ -52,43 +88,103 @@ class Port:
|
|||||||
self.txcq = None
|
self.txcq = None
|
||||||
self.txcq_prod = 0
|
self.txcq_prod = 0
|
||||||
self.txcq_cons = 0
|
self.txcq_cons = 0
|
||||||
|
self.tx_cqn = 0
|
||||||
|
|
||||||
self.rx_queue = Queue()
|
self.rx_queue = Queue()
|
||||||
|
|
||||||
async def init(self):
|
async def init(self):
|
||||||
|
|
||||||
self.rxq = self.driver.pool.alloc_region(self.rxq_size*16)
|
|
||||||
addr = self.rxq.get_absolute_address(0)
|
|
||||||
await self.hw_regs.write_dword(0x0200, 0x00000000)
|
|
||||||
await self.hw_regs.write_dword(0x0204, 0x00000000)
|
|
||||||
await self.hw_regs.write_dword(0x0208, addr & 0xffffffff)
|
|
||||||
await self.hw_regs.write_dword(0x020c, addr >> 32)
|
|
||||||
await self.hw_regs.write_dword(0x0200, 0x00000001 | (self.rxq_log_size << 16))
|
|
||||||
|
|
||||||
self.rxcq = self.driver.pool.alloc_region(self.rxcq_size*16)
|
self.rxcq = self.driver.pool.alloc_region(self.rxcq_size*16)
|
||||||
addr = self.rxcq.get_absolute_address(0)
|
addr = self.rxcq.get_absolute_address(0)
|
||||||
await self.hw_regs.write_dword(0x0400, 0x00000000)
|
|
||||||
await self.hw_regs.write_dword(0x0408, addr & 0xffffffff)
|
|
||||||
await self.hw_regs.write_dword(0x040c, addr >> 32)
|
|
||||||
await self.hw_regs.write_dword(0x0400, 0x00000001 | (self.rxcq_log_size << 16))
|
|
||||||
|
|
||||||
self.txq = self.driver.pool.alloc_region(self.txq_size*16)
|
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL",
|
||||||
addr = self.txq.get_absolute_address(0)
|
0, # rsvd
|
||||||
await self.hw_regs.write_dword(0x0100, 0x00000000)
|
CNDM_CMD_OP_CREATE_CQ, # opcode
|
||||||
await self.hw_regs.write_dword(0x0104, 0x00000000)
|
0x00000000, # flags
|
||||||
await self.hw_regs.write_dword(0x0108, addr & 0xffffffff)
|
self.index, # port
|
||||||
await self.hw_regs.write_dword(0x010c, addr >> 32)
|
0, # cqn
|
||||||
await self.hw_regs.write_dword(0x0100, 0x00000001 | (self.txq_log_size << 16))
|
0, # eqn
|
||||||
|
0, # pd
|
||||||
|
self.rxcq_log_size, # size
|
||||||
|
0, # dboffs
|
||||||
|
addr, # base addr
|
||||||
|
0, # ptr2
|
||||||
|
0, # prod_ptr
|
||||||
|
0, # cons_ptr
|
||||||
|
0, # rsvd
|
||||||
|
0, # rsvd
|
||||||
|
))
|
||||||
|
print(rsp)
|
||||||
|
|
||||||
|
self.rxq = self.driver.pool.alloc_region(self.rxq_size*16)
|
||||||
|
addr = self.rxq.get_absolute_address(0)
|
||||||
|
|
||||||
|
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL",
|
||||||
|
0, # rsvd
|
||||||
|
CNDM_CMD_OP_CREATE_RQ, # opcode
|
||||||
|
0x00000000, # flags
|
||||||
|
self.index, # port
|
||||||
|
0, # rqn
|
||||||
|
0, # cqn
|
||||||
|
0, # pd
|
||||||
|
self.rxq_log_size, # size
|
||||||
|
0, # dboffs
|
||||||
|
addr, # base addr
|
||||||
|
0, # ptr2
|
||||||
|
0, # prod_ptr
|
||||||
|
0, # cons_ptr
|
||||||
|
0, # rsvd
|
||||||
|
0, # rsvd
|
||||||
|
))
|
||||||
|
print(rsp)
|
||||||
|
|
||||||
|
self.rxq_db_offs = struct.unpack_from("<L", rsp, 7*4)[0]
|
||||||
|
|
||||||
self.txcq = self.driver.pool.alloc_region(self.txcq_size*16)
|
self.txcq = self.driver.pool.alloc_region(self.txcq_size*16)
|
||||||
addr = self.txcq.get_absolute_address(0)
|
addr = self.txcq.get_absolute_address(0)
|
||||||
await self.hw_regs.write_dword(0x0300, 0x00000000)
|
|
||||||
await self.hw_regs.write_dword(0x0308, addr & 0xffffffff)
|
|
||||||
await self.hw_regs.write_dword(0x030c, addr >> 32)
|
|
||||||
await self.hw_regs.write_dword(0x0300, 0x00000001 | (self.txcq_log_size << 16))
|
|
||||||
|
|
||||||
# wait for writes to complete
|
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL",
|
||||||
await self.hw_regs.read_dword(0)
|
0, # rsvd
|
||||||
|
CNDM_CMD_OP_CREATE_CQ, # opcode
|
||||||
|
0x00000000, # flags
|
||||||
|
self.index, # port
|
||||||
|
1, # cqn
|
||||||
|
0, # eqn
|
||||||
|
0, # pd
|
||||||
|
self.txcq_log_size, # size
|
||||||
|
0, # dboffs
|
||||||
|
addr, # base addr
|
||||||
|
0, # ptr2
|
||||||
|
0, # prod_ptr
|
||||||
|
0, # cons_ptr
|
||||||
|
0, # rsvd
|
||||||
|
0, # rsvd
|
||||||
|
))
|
||||||
|
print(rsp)
|
||||||
|
|
||||||
|
self.txq = self.driver.pool.alloc_region(self.txq_size*16)
|
||||||
|
addr = self.txq.get_absolute_address(0)
|
||||||
|
|
||||||
|
rsp = await self.driver.exec_cmd(struct.pack("<HHLLLLLLLLLLLLL",
|
||||||
|
0, # rsvd
|
||||||
|
CNDM_CMD_OP_CREATE_SQ, # opcode
|
||||||
|
0x00000000, # flags
|
||||||
|
self.index, # port
|
||||||
|
0, # sqn
|
||||||
|
1, # cqn
|
||||||
|
0, # pd
|
||||||
|
self.txq_log_size, # size
|
||||||
|
0, # dboffs
|
||||||
|
addr, # base addr
|
||||||
|
0, # ptr2
|
||||||
|
0, # prod_ptr
|
||||||
|
0, # cons_ptr
|
||||||
|
0, # rsvd
|
||||||
|
0, # rsvd
|
||||||
|
))
|
||||||
|
print(rsp)
|
||||||
|
|
||||||
|
self.txq_db_offs = struct.unpack_from("<L", rsp, 7*4)[0]
|
||||||
|
|
||||||
await self.refill_rx_buffers()
|
await self.refill_rx_buffers()
|
||||||
|
|
||||||
@@ -101,7 +197,7 @@ class Port:
|
|||||||
struct.pack_into('<xxxxLQ', self.txq.mem, 16*index, len(data), ptr+headroom)
|
struct.pack_into('<xxxxLQ', self.txq.mem, 16*index, len(data), ptr+headroom)
|
||||||
self.tx_info[index] = tx_buf
|
self.tx_info[index] = tx_buf
|
||||||
self.txq_prod += 1
|
self.txq_prod += 1
|
||||||
await self.hw_regs.write_dword(0x0104, self.txq_prod & 0xffff)
|
await self.hw_regs.write_dword(self.txq_db_offs, self.txq_prod & 0xffff)
|
||||||
|
|
||||||
async def recv(self):
|
async def recv(self):
|
||||||
return await self.rx_queue.get()
|
return await self.rx_queue.get()
|
||||||
@@ -177,7 +273,7 @@ class Port:
|
|||||||
self.prepare_rx_desc(self.rxq_prod & self.rxq_mask)
|
self.prepare_rx_desc(self.rxq_prod & self.rxq_mask)
|
||||||
self.rxq_prod += 1
|
self.rxq_prod += 1
|
||||||
|
|
||||||
await self.hw_regs.write_dword(0x0204, self.rxq_prod & 0xffff)
|
await self.hw_regs.write_dword(self.rxq_db_offs, self.rxq_prod & 0xffff)
|
||||||
|
|
||||||
async def process_rx_cq(self):
|
async def process_rx_cq(self):
|
||||||
|
|
||||||
@@ -229,6 +325,8 @@ class Driver:
|
|||||||
self.pool = None
|
self.pool = None
|
||||||
self.hw_regs = None
|
self.hw_regs = None
|
||||||
|
|
||||||
|
self.port_count = None
|
||||||
|
|
||||||
self.ports = []
|
self.ports = []
|
||||||
|
|
||||||
self.free_packets = deque()
|
self.free_packets = deque()
|
||||||
@@ -256,12 +354,40 @@ class Driver:
|
|||||||
self.log.info("Port stride: 0x%x", self.port_stride)
|
self.log.info("Port stride: 0x%x", self.port_stride)
|
||||||
|
|
||||||
for k in range(self.port_count):
|
for k in range(self.port_count):
|
||||||
port = Port(self, k, self.hw_regs.create_window(self.port_offset + self.port_stride*k))
|
port = Port(self, k)
|
||||||
await port.init()
|
await port.init()
|
||||||
self.dev.request_irq(k, port.interrupt_handler)
|
self.dev.request_irq(k, port.interrupt_handler)
|
||||||
|
|
||||||
self.ports.append(port)
|
self.ports.append(port)
|
||||||
|
|
||||||
|
async def exec_cmd(self, cmd):
|
||||||
|
return await self.exec_mbox_cmd(cmd)
|
||||||
|
|
||||||
|
async def exec_mbox_cmd(self, cmd):
|
||||||
|
cmd = bytes(cmd)
|
||||||
|
cmd = cmd.ljust(64, b'\x00')
|
||||||
|
|
||||||
|
if len(cmd) != 64:
|
||||||
|
raise ValueError("Invalid command length")
|
||||||
|
|
||||||
|
# write command to mailbox
|
||||||
|
a = array.array("I")
|
||||||
|
a.frombytes(cmd)
|
||||||
|
for k, dw in enumerate(a):
|
||||||
|
await self.hw_regs.write_dword(0x10000+k*4, dw)
|
||||||
|
|
||||||
|
# execute it
|
||||||
|
await self.hw_regs.write_dword(0x0200, 0x00000001)
|
||||||
|
|
||||||
|
# wait for completion
|
||||||
|
while await self.hw_regs.read_dword(0x0200) & 0x00000001:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# read response from mailbox
|
||||||
|
for k in range(16):
|
||||||
|
a[k] = await self.hw_regs.read_dword(0x10040+k*4)
|
||||||
|
return a.tobytes()
|
||||||
|
|
||||||
def alloc_pkt(self):
|
def alloc_pkt(self):
|
||||||
if self.free_packets:
|
if self.free_packets:
|
||||||
return self.free_packets.popleft()
|
return self.free_packets.popleft()
|
||||||
|
|||||||
Reference in New Issue
Block a user