cndm: Add PTP command

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-03-02 18:27:33 -08:00
parent 14d35dd75f
commit 0d4a030e3f
10 changed files with 443 additions and 118 deletions

View File

@@ -54,12 +54,10 @@ struct cndm_dev {
struct mutex mbox_lock; struct mutex mbox_lock;
u32 port_count; u32 port_count;
u32 port_offset;
u32 port_stride;
void __iomem *phc_regs;
struct ptp_clock *ptp_clock; struct ptp_clock *ptp_clock;
struct ptp_clock_info ptp_clock_info; struct ptp_clock_info ptp_clock_info;
u64 ptp_nom_period;
}; };
struct cndm_tx_info { struct cndm_tx_info {

View File

@@ -53,29 +53,24 @@ int cndm_exec_cmd(struct cndm_dev *cdev, void *cmd, void *rsp)
int cndm_access_reg(struct cndm_dev *cdev, u32 reg, int raw, int write, u64 *data) int cndm_access_reg(struct cndm_dev *cdev, u32 reg, int raw, int write, u64 *data)
{ {
struct cndm_cmd cmd; struct cndm_cmd_reg cmd;
struct cndm_cmd rsp; struct cndm_cmd_reg rsp;
cmd.opcode = CNDM_CMD_OP_ACCESS_REG; cmd.opcode = CNDM_CMD_OP_ACCESS_REG;
cmd.flags = 0x00000000; cmd.flags = 0x00000000;
cmd.port = 0; cmd.reg_addr = reg;
cmd.qn = 0; cmd.write_val = *data;
cmd.qn2 = 0; cmd.read_val = 0;
cmd.pd = 0;
cmd.size = 0;
cmd.dboffs = reg;
cmd.ptr1 = *data;
cmd.ptr2 = 0;
if (write) if (write)
cmd.flags |= 0x00000001; cmd.flags |= CNDM_CMD_REG_FLG_WRITE;
if (raw) if (raw)
cmd.flags |= 0x00000100; cmd.flags |= CNDM_CMD_REG_FLG_RAW;
cndm_exec_cmd(cdev, &cmd, &rsp); cndm_exec_cmd(cdev, &cmd, &rsp);
if (!write) if (!write)
*data = rsp.ptr2; *data = rsp.read_val;
return 0; return 0;
} }

View File

@@ -16,6 +16,7 @@ Authors:
#define CNDM_CMD_OP_NOP 0x0000 #define CNDM_CMD_OP_NOP 0x0000
#define CNDM_CMD_OP_ACCESS_REG 0x0180 #define CNDM_CMD_OP_ACCESS_REG 0x0180
#define CNDM_CMD_OP_PTP 0x0190
#define CNDM_CMD_OP_CREATE_EQ 0x0200 #define CNDM_CMD_OP_CREATE_EQ 0x0200
#define CNDM_CMD_OP_MODIFY_EQ 0x0201 #define CNDM_CMD_OP_MODIFY_EQ 0x0201
@@ -42,7 +43,7 @@ Authors:
#define CNDM_CMD_OP_QUERY_QP 0x0242 #define CNDM_CMD_OP_QUERY_QP 0x0242
#define CNDM_CMD_OP_DESTROY_QP 0x0243 #define CNDM_CMD_OP_DESTROY_QP 0x0243
struct cndm_cmd { struct cndm_cmd_queue {
__le16 rsvd; __le16 rsvd;
union { union {
__le16 opcode; __le16 opcode;
@@ -66,6 +67,61 @@ struct cndm_cmd {
__le32 dw15; __le32 dw15;
}; };
#define CNDM_CMD_REG_FLG_WRITE 0x00000001
#define CNDM_CMD_REG_FLG_RAW 0x00000100
struct cndm_cmd_reg {
__le16 rsvd;
union {
__le16 opcode;
__le16 status;
};
__le32 flags;
__le32 dw2;
__le32 dw3;
__le32 dw4;
__le32 dw5;
__le32 dw6;
__le32 reg_addr;
__le64 write_val;
__le64 read_val;
__le32 dw12;
__le32 dw13;
__le32 dw14;
__le32 dw15;
};
#define CNDM_CMD_PTP_FLG_SET_TOD 0x00000001
#define CNDM_CMD_PTP_FLG_OFFSET_TOD 0x00000002
#define CNDM_CMD_PTP_FLG_SET_REL 0x00000004
#define CNDM_CMD_PTP_FLG_OFFSET_REL 0x00000008
#define CNDM_CMD_PTP_FLG_OFFSET_FNS 0x00000010
#define CNDM_CMD_PTP_FLG_SET_PERIOD 0x00000080
struct cndm_cmd_ptp {
__le16 rsvd;
union {
__le16 opcode;
__le16 status;
};
__le32 flags;
__le32 fns;
__le32 tod_ns;
__le64 tod_sec;
__le64 rel_ns;
__le64 ptm;
__le64 nom_period;
__le64 period;
__le32 dw14;
__le32 dw15;
};
struct cndm_desc { struct cndm_desc {
__le16 rsvd0; __le16 rsvd0;
union { union {

View File

@@ -56,12 +56,8 @@ static int cndm_common_probe(struct cndm_dev *cdev)
#endif #endif
cdev->port_count = ioread32(cdev->hw_addr + 0x0100); cdev->port_count = ioread32(cdev->hw_addr + 0x0100);
cdev->port_offset = ioread32(cdev->hw_addr + 0x0104);
cdev->port_stride = ioread32(cdev->hw_addr + 0x0108);
dev_info(dev, "Port count: %d", cdev->port_count); dev_info(dev, "Port count: %d", cdev->port_count);
dev_info(dev, "Port offset: 0x%x", cdev->port_offset);
dev_info(dev, "Port stride: 0x%x", cdev->port_stride);
if (cdev->port_count > ARRAY_SIZE(cdev->ndev)) if (cdev->port_count > ARRAY_SIZE(cdev->ndev))
cdev->port_count = ARRAY_SIZE(cdev->ndev); cdev->port_count = ARRAY_SIZE(cdev->ndev);

View File

@@ -178,8 +178,8 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port)
struct cndm_priv *priv; struct cndm_priv *priv;
int ret = 0; int ret = 0;
struct cndm_cmd cmd; struct cndm_cmd_queue cmd;
struct cndm_cmd rsp; struct cndm_cmd_queue rsp;
ndev = alloc_etherdev_mqs(sizeof(*priv), 1, 1); ndev = alloc_etherdev_mqs(sizeof(*priv), 1, 1);
if (!ndev) { if (!ndev) {
@@ -373,8 +373,8 @@ void cndm_destroy_netdev(struct net_device *ndev)
struct cndm_dev *cdev = priv->cdev; struct cndm_dev *cdev = priv->cdev;
struct device *dev = priv->dev; struct device *dev = priv->dev;
struct cndm_cmd cmd; struct cndm_cmd_queue cmd;
struct cndm_cmd rsp; struct cndm_cmd_queue rsp;
cmd.opcode = CNDM_CMD_OP_DESTROY_CQ; cmd.opcode = CNDM_CMD_OP_DESTROY_CQ;
cmd.flags = 0x00000000; cmd.flags = 0x00000000;

View File

@@ -21,21 +21,23 @@ ktime_t cndm_read_cpl_ts(struct cndm_priv *priv, const struct cndm_cpl *cpl)
if (unlikely(!priv->ts_valid || (priv->ts_s ^ ts_s) & 0xf0)) { if (unlikely(!priv->ts_valid || (priv->ts_s ^ ts_s) & 0xf0)) {
// seconds MSBs do not match, update cached timestamp // seconds MSBs do not match, update cached timestamp
if (cdev->phc_regs) { priv->ts_s = ioread32(cdev->hw_addr + 0x0308);
priv->ts_s = ioread32(cdev->phc_regs + 0x18); priv->ts_s |= (u64) ioread32(cdev->hw_addr + 0x030C) << 32;
priv->ts_s |= (u64) ioread32(cdev->phc_regs + 0x1C) << 32; priv->ts_valid = 1;
priv->ts_valid = 1;
}
} }
ts_s |= priv->ts_s & 0xfffffffffffffff0; ts_s |= priv->ts_s & 0xfffffffffffffff0;
dev_dbg(cdev->dev, "%s: Read timestamp: %lld.%09d", __func__, ts_s, ts_ns);
return ktime_set(ts_s, ts_ns); return ktime_set(ts_s, ts_ns);
} }
static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{ {
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info); struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
struct cndm_cmd_ptp cmd;
struct cndm_cmd_ptp rsp;
bool neg = false; bool neg = false;
u64 nom_per_fns, adj; u64 nom_per_fns, adj;
@@ -47,8 +49,7 @@ static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
scaled_ppm = -scaled_ppm; scaled_ppm = -scaled_ppm;
} }
nom_per_fns = ioread32(cdev->phc_regs + 0x70); nom_per_fns = cdev->ptp_nom_period;
nom_per_fns |= (u64) ioread32(cdev->phc_regs + 0x74) << 32;
if (nom_per_fns == 0) if (nom_per_fns == 0)
nom_per_fns = 0x4ULL << 32; nom_per_fns = 0x4ULL << 32;
@@ -60,8 +61,11 @@ static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
else else
adj = nom_per_fns + adj; adj = nom_per_fns + adj;
iowrite32(adj & 0xffffffff, cdev->phc_regs + 0x78); cmd.opcode = CNDM_CMD_OP_PTP;
iowrite32(adj >> 32, cdev->phc_regs + 0x7C); cmd.flags = CNDM_CMD_PTP_FLG_SET_PERIOD;
cmd.period = adj;
cndm_exec_cmd(cdev, &cmd, &rsp);
dev_dbg(cdev->dev, "%s adj: 0x%llx", __func__, adj); dev_dbg(cdev->dev, "%s adj: 0x%llx", __func__, adj);
@@ -72,10 +76,12 @@ static int cndm_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
{ {
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info); struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
ioread32(cdev->phc_regs + 0x30); ioread32(cdev->hw_addr + 0x0320);
ts->tv_nsec = ioread32(cdev->phc_regs + 0x34); ts->tv_nsec = ioread32(cdev->hw_addr + 0x0324);
ts->tv_sec = ioread32(cdev->phc_regs + 0x38); ts->tv_sec = ioread32(cdev->hw_addr + 0x0328);
ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32; ts->tv_sec |= (u64) ioread32(cdev->hw_addr + 0x032C) << 32;
dev_dbg(cdev->dev, "%s: Get time: %lld.%09ld", __func__, ts->tv_sec, ts->tv_nsec);
return 0; return 0;
} }
@@ -86,11 +92,13 @@ static int cndm_phc_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info); struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
ptp_read_system_prets(sts); ptp_read_system_prets(sts);
ioread32(cdev->phc_regs + 0x30); ioread32(cdev->hw_addr + 0x0320);
ptp_read_system_postts(sts); ptp_read_system_postts(sts);
ts->tv_nsec = ioread32(cdev->phc_regs + 0x34); ts->tv_nsec = ioread32(cdev->hw_addr + 0x0324);
ts->tv_sec = ioread32(cdev->phc_regs + 0x38); ts->tv_sec = ioread32(cdev->hw_addr + 0x0328);
ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32; ts->tv_sec |= (u64) ioread32(cdev->hw_addr + 0x032C) << 32;
dev_dbg(cdev->dev, "%s: Get time: %lld.%09ld", __func__, ts->tv_sec, ts->tv_nsec);
return 0; return 0;
} }
@@ -99,10 +107,15 @@ static int cndm_phc_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts,
static int cndm_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) static int cndm_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts)
{ {
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info); struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
struct cndm_cmd_ptp cmd;
struct cndm_cmd_ptp rsp;
iowrite32(ts->tv_nsec, cdev->phc_regs + 0x54); cmd.opcode = CNDM_CMD_OP_PTP;
iowrite32(ts->tv_sec & 0xffffffff, cdev->phc_regs + 0x58); cmd.flags = CNDM_CMD_PTP_FLG_SET_TOD;
iowrite32(ts->tv_sec >> 32, cdev->phc_regs + 0x5C); cmd.tod_ns = ts->tv_nsec;
cmd.tod_sec = ts->tv_sec;
cndm_exec_cmd(cdev, &cmd, &rsp);
return 0; return 0;
} }
@@ -111,6 +124,8 @@ static int cndm_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
{ {
struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info); struct cndm_dev *cdev = container_of(ptp, struct cndm_dev, ptp_clock_info);
struct timespec64 ts; struct timespec64 ts;
struct cndm_cmd_ptp cmd;
struct cndm_cmd_ptp rsp;
dev_dbg(cdev->dev, "%s: delta: %lld", __func__, delta); dev_dbg(cdev->dev, "%s: delta: %lld", __func__, delta);
@@ -121,7 +136,11 @@ static int cndm_phc_adjtime(struct ptp_clock_info *ptp, s64 delta)
cndm_phc_settime(ptp, &ts); cndm_phc_settime(ptp, &ts);
} else { } else {
// for a small delta, perform a precision atomic offset // for a small delta, perform a precision atomic offset
iowrite32(delta & 0xffffffff, cdev->phc_regs + 0x50); cmd.opcode = CNDM_CMD_OP_PTP;
cmd.flags = CNDM_CMD_PTP_FLG_OFFSET_TOD;
cmd.tod_ns = delta & 0xffffffff;
cndm_exec_cmd(cdev, &cmd, &rsp);
} }
return 0; return 0;
@@ -142,18 +161,29 @@ static void cndm_phc_set_from_system_clock(struct ptp_clock_info *ptp)
void cndm_register_phc(struct cndm_dev *cdev) void cndm_register_phc(struct cndm_dev *cdev)
{ {
struct cndm_cmd_ptp cmd;
struct cndm_cmd_ptp rsp;
if (cdev->ptp_clock) { if (cdev->ptp_clock) {
dev_warn(cdev->dev, "PTP clock already registered"); dev_warn(cdev->dev, "PTP clock already registered");
return; return;
} }
// TODO cmd.opcode = CNDM_CMD_OP_PTP;
if (cdev->port_offset == 0x20000) { cmd.flags = 0x00000000;
cmd.nom_period = 0;
cndm_exec_cmd(cdev, &cmd, &rsp);
if (rsp.nom_period == 0) {
dev_info(cdev->dev, "PTP clock not present"); dev_info(cdev->dev, "PTP clock not present");
return; return;
} }
cdev->phc_regs = cdev->hw_addr + 0x20000; // TODO cdev->ptp_nom_period = rsp.nom_period;
dev_info(cdev->dev, "PHC nominal period: %lld.%08lld ns (raw 0x%llx)", cdev->ptp_nom_period >> 32,
((cdev->ptp_nom_period & 0xffffffff) * 1000000000) / 0x100000000ll, cdev->ptp_nom_period);
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);

View File

@@ -17,5 +17,5 @@ cndm_micro_cpl_wr.sv
../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
../lib/taxi/src/axis/rtl/taxi_axis_demux.sv ../lib/taxi/src/axis/rtl/taxi_axis_demux.sv
../lib/taxi/src/ptp/rtl/taxi_ptp_td_phc_axil.f ../lib/taxi/src/ptp/rtl/taxi_ptp_td_phc_apb.f
../lib/taxi/src/ptp/rtl/taxi_ptp_td_rel2tod.sv ../lib/taxi/src/ptp/rtl/taxi_ptp_td_rel2tod.sv

View File

@@ -106,8 +106,10 @@ 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 ? 3 : 2; localparam PORT_OFFSET_DP = PTP_TS_EN ? 1 : 0;
localparam PORT_BASE_ADDR = PTP_TS_EN ? 32'h00030000 : 32'h00020000; localparam PORT_OFFSET_HOST = 2;
localparam PORT_BASE_ADDR_DP = PTP_TS_EN ? 32'h00010000 : 32'h00000000;
localparam PORT_BASE_ADDR_HOST = 32'h00020000;
taxi_axil_if #( taxi_axil_if #(
.DATA_W(s_axil_ctrl_wr.DATA_W), .DATA_W(s_axil_ctrl_wr.DATA_W),
@@ -124,7 +126,7 @@ taxi_axil_if #(
.RUSER_EN(s_axil_ctrl_wr.RUSER_EN), .RUSER_EN(s_axil_ctrl_wr.RUSER_EN),
.RUSER_W(s_axil_ctrl_wr.RUSER_W) .RUSER_W(s_axil_ctrl_wr.RUSER_W)
) )
axil_ctrl[PORTS+PORT_OFFSET](); axil_ctrl[PORTS+PORT_OFFSET_HOST]();
taxi_axil_interconnect_1s #( taxi_axil_interconnect_1s #(
.M_COUNT($size(axil_ctrl)), .M_COUNT($size(axil_ctrl)),
@@ -174,6 +176,9 @@ assign axil_ctrl[0].rvalid = s_axil_rvalid_reg;
logic cmd_mbox_start_reg = 1'b0; logic cmd_mbox_start_reg = 1'b0;
wire cmd_mbox_busy; wire cmd_mbox_busy;
logic [95:0] get_ptp_ts_tod_reg = '0;
logic [63:0] get_ptp_ts_rel_reg = '0;
always_ff @(posedge clk) begin 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;
@@ -212,11 +217,30 @@ always_ff @(posedge clk) begin
case ({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 <= PORT_BASE_ADDR; // port offset
16'h0108: s_axil_rdata_reg <= 32'h00010000; // port stride
16'h0200: begin 16'h0200: begin
s_axil_rdata_reg[0] <= cmd_mbox_busy; s_axil_rdata_reg[0] <= cmd_mbox_busy;
end end
16'h0300: s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0}; // PTP cur fns
16'h0304: s_axil_rdata_reg <= ptp_sync_ts_tod[47:16]; // PTP cur ToD ns
16'h0308: s_axil_rdata_reg <= ptp_sync_ts_tod[79:48]; // PTP cur ToD sec l
16'h030C: s_axil_rdata_reg <= 32'(ptp_sync_ts_tod[95:80]); // PTP cur ToD sec h
16'h0310: s_axil_rdata_reg <= ptp_sync_ts_rel[47:16]; // PTP cur rel ns l
16'h0314: s_axil_rdata_reg <= 32'(ptp_sync_ts_rel[63:48]); // PTP cur rel ns h
16'h0318: s_axil_rdata_reg <= '0; // PTP cur PTM l
16'h031C: s_axil_rdata_reg <= '0; // PTP cur PTM h
16'h0320: begin
// PTP snapshot fns
get_ptp_ts_tod_reg <= ptp_sync_ts_tod;
get_ptp_ts_rel_reg <= ptp_sync_ts_rel;
s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0};
end
16'h0324: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[45:16]); // PTP snapshot ToD ns
16'h0328: s_axil_rdata_reg <= get_ptp_ts_tod_reg[79:48]; // PTP snapshot ToD sec l
16'h032C: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[95:80]); // PTP snapshot ToD sec h
16'h0330: s_axil_rdata_reg <= get_ptp_ts_rel_reg[47:16]; // PTP snapshot rel ns l
16'h0334: s_axil_rdata_reg <= 32'(get_ptp_ts_rel_reg[63:48]); // PTP snapshot rel ns h
16'h0338: s_axil_rdata_reg <= '0; // PTP snapshot PTM l
16'h033C: s_axil_rdata_reg <= '0; // PTP snapshot PTM h
default: begin end default: begin end
endcase endcase
end end
@@ -278,13 +302,16 @@ cmd_mbox_inst (
taxi_apb_if #( taxi_apb_if #(
.DATA_W(32), .DATA_W(32),
.ADDR_W(16+CL_PORTS) .ADDR_W(16+$clog2(PORTS+PORT_OFFSET_DP))
) )
apb_dp_ctrl(); apb_dp_ctrl();
cndm_micro_dp_mgr #( cndm_micro_dp_mgr #(
.PORTS(PORTS), .PORTS(PORTS),
.PORT_BASE_ADDR(PORT_BASE_ADDR) .PTP_EN(PTP_TS_EN),
.PTP_BASE_ADDR_DP(0),
.PORT_BASE_ADDR_DP(PORT_BASE_ADDR_DP),
.PORT_BASE_ADDR_HOST(PORT_BASE_ADDR_HOST)
) )
dp_mgr_inst ( dp_mgr_inst (
.clk(clk), .clk(clk),
@@ -306,7 +333,7 @@ taxi_apb_if #(
.DATA_W(32), .DATA_W(32),
.ADDR_W(16) .ADDR_W(16)
) )
apb_port_dp_ctrl[PORTS](); apb_port_dp_ctrl[PORT_OFFSET_DP+PORTS]();
taxi_apb_interconnect #( taxi_apb_interconnect #(
.M_CNT($size(apb_port_dp_ctrl)), .M_CNT($size(apb_port_dp_ctrl)),
@@ -333,7 +360,7 @@ port_dp_intercon_inst (
if (PTP_TS_EN) begin : ptp if (PTP_TS_EN) begin : ptp
taxi_ptp_td_phc_axil #( taxi_ptp_td_phc_apb #(
.PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM), .PTP_CLK_PER_NS_NUM(PTP_CLK_PER_NS_NUM),
.PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM) .PTP_CLK_PER_NS_DENOM(PTP_CLK_PER_NS_DENOM)
) )
@@ -344,8 +371,7 @@ if (PTP_TS_EN) begin : ptp
/* /*
* Control register interface * Control register interface
*/ */
.s_axil_wr(axil_ctrl[2]), .s_apb(apb_port_dp_ctrl[0]),
.s_axil_rd(axil_ctrl[2]),
/* /*
* PTP * PTP
@@ -474,13 +500,13 @@ for (genvar p = 0; p < PORTS; p = p + 1) begin : port
/* /*
* Control register interface * Control register interface
*/ */
.s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET+p]), .s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET_HOST+p]),
.s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET+p]), .s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET_HOST+p]),
/* /*
* Datapath control register interface * Datapath control register interface
*/ */
.s_apb_dp_ctrl(apb_port_dp_ctrl[p]), .s_apb_dp_ctrl(apb_port_dp_ctrl[PORT_OFFSET_DP+p]),
/* /*
* DMA * DMA

View File

@@ -18,7 +18,10 @@ Authors:
module cndm_micro_dp_mgr # module cndm_micro_dp_mgr #
( (
parameter PORTS = 2, parameter PORTS = 2,
parameter PORT_BASE_ADDR = 0 parameter logic PTP_EN = 1'b1,
parameter PTP_BASE_ADDR_DP = 0,
parameter PORT_BASE_ADDR_DP = 0,
parameter PORT_BASE_ADDR_HOST = 0
) )
( (
input wire logic clk, input wire logic clk,
@@ -45,6 +48,7 @@ typedef enum logic [15:0] {
CMD_OP_NOP = 16'h0000, CMD_OP_NOP = 16'h0000,
CMD_OP_ACCESS_REG = 16'h0180, CMD_OP_ACCESS_REG = 16'h0180,
CMD_OP_PTP = 16'h0190,
CMD_OP_CREATE_EQ = 16'h0200, CMD_OP_CREATE_EQ = 16'h0200,
CMD_OP_MODIFY_EQ = 16'h0201, CMD_OP_MODIFY_EQ = 16'h0201,
@@ -84,6 +88,9 @@ typedef enum logic [4:0] {
STATE_Q_SET_BASE_H, STATE_Q_SET_BASE_H,
STATE_Q_ENABLE, STATE_Q_ENABLE,
STATE_Q_DISABLE, STATE_Q_DISABLE,
STATE_PTP_READ_1,
STATE_PTP_READ_2,
STATE_PTP_SET,
STATE_SEND_RSP, STATE_SEND_RSP,
STATE_PAD_RSP STATE_PAD_RSP
} state_t; } state_t;
@@ -135,9 +142,9 @@ assign m_apb_dp_ctrl.pauser = '0;
assign m_apb_dp_ctrl.pwuser = '0; assign m_apb_dp_ctrl.pwuser = '0;
logic cmd_frame_reg = 1'b0, cmd_frame_next; logic cmd_frame_reg = 1'b0, cmd_frame_next;
logic [3:0] cmd_ptr_reg = '0, cmd_ptr_next; logic [3:0] cmd_wr_ptr_reg = '0, cmd_wr_ptr_next;
logic rsp_frame_reg = 1'b0, rsp_frame_next; logic rsp_frame_reg = 1'b0, rsp_frame_next;
logic [3:0] rsp_ptr_reg = '0, rsp_ptr_next; logic [3:0] rsp_rd_ptr_reg = '0, rsp_rd_ptr_next;
logic drop_cmd_reg = 1'b0, drop_cmd_next; logic drop_cmd_reg = 1'b0, drop_cmd_next;
@@ -146,7 +153,10 @@ logic [31:0] flags_reg = '0, flags_next;
logic [15:0] port_reg = '0, port_next; logic [15:0] port_reg = '0, port_next;
logic [23:0] qn_reg = '0, qn_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; logic [3:0] cmd_ptr_reg = '0, cmd_ptr_next;
logic [DP_APB_ADDR_W-1:0] dp_ptr_reg = '0, dp_ptr_next;
logic [31:0] host_ptr_reg = '0, host_ptr_next;
logic [15:0] cnt_reg = '0, cnt_next;
always_comb begin always_comb begin
state_next = STATE_IDLE; state_next = STATE_IDLE;
@@ -165,14 +175,14 @@ always_comb begin
m_apb_dp_ctrl_pstrb_next = m_apb_dp_ctrl_pstrb_reg; m_apb_dp_ctrl_pstrb_next = m_apb_dp_ctrl_pstrb_reg;
cmd_ram_wr_data = s_axis_cmd.tdata; cmd_ram_wr_data = s_axis_cmd.tdata;
cmd_ram_wr_addr = cmd_ptr_reg; cmd_ram_wr_addr = cmd_wr_ptr_reg;
cmd_ram_wr_en = 1'b0; cmd_ram_wr_en = 1'b0;
cmd_ram_rd_addr = '0; cmd_ram_rd_addr = '0;
cmd_frame_next = cmd_frame_reg; cmd_frame_next = cmd_frame_reg;
cmd_ptr_next = cmd_ptr_reg; cmd_wr_ptr_next = cmd_wr_ptr_reg;
rsp_frame_next = rsp_frame_reg; rsp_frame_next = rsp_frame_reg;
rsp_ptr_next = rsp_ptr_reg; rsp_rd_ptr_next = rsp_rd_ptr_reg;
drop_cmd_next = drop_cmd_reg; drop_cmd_next = drop_cmd_reg;
@@ -181,14 +191,17 @@ always_comb begin
port_next = port_reg; port_next = port_reg;
qn_next = qn_reg; qn_next = qn_reg;
block_base_addr_next = block_base_addr_reg; cmd_ptr_next = cmd_ptr_reg;
dp_ptr_next = dp_ptr_reg;
host_ptr_next = host_ptr_reg;
cnt_next = cnt_reg;
if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin if (s_axis_cmd.tready && s_axis_cmd.tvalid) begin
if (s_axis_cmd.tlast) begin if (s_axis_cmd.tlast) begin
cmd_frame_next = 1'b0; cmd_frame_next = 1'b0;
cmd_ptr_next = '0; cmd_wr_ptr_next = '0;
end else begin end else begin
cmd_ptr_next = cmd_ptr_reg + 1; cmd_wr_ptr_next = cmd_wr_ptr_reg + 1;
cmd_frame_next = 1'b1; cmd_frame_next = 1'b1;
end end
end end
@@ -198,11 +211,11 @@ always_comb begin
s_axis_cmd_tready_next = !m_axis_rsp_tvalid_reg && !rsp_frame_reg; s_axis_cmd_tready_next = !m_axis_rsp_tvalid_reg && !rsp_frame_reg;
cmd_ram_wr_data = s_axis_cmd.tdata; cmd_ram_wr_data = s_axis_cmd.tdata;
cmd_ram_wr_addr = cmd_ptr_reg; cmd_ram_wr_addr = cmd_wr_ptr_reg;
cmd_ram_wr_en = 1'b1; cmd_ram_wr_en = 1'b1;
// save some important fields // save some important fields
case (cmd_ptr_reg) case (cmd_wr_ptr_reg)
4'd0: opcode_next = s_axis_cmd.tdata[31:16]; 4'd0: opcode_next = s_axis_cmd.tdata[31:16];
4'd1: flags_next = s_axis_cmd.tdata; 4'd1: flags_next = s_axis_cmd.tdata;
4'd2: port_next = s_axis_cmd.tdata[15:0]; 4'd2: port_next = s_axis_cmd.tdata[15:0];
@@ -211,7 +224,7 @@ always_comb begin
endcase endcase
if (s_axis_cmd.tready && s_axis_cmd.tvalid && !drop_cmd_reg) begin if (s_axis_cmd.tready && s_axis_cmd.tvalid && !drop_cmd_reg) begin
if (s_axis_cmd.tlast || &cmd_ptr_reg) begin if (s_axis_cmd.tlast || &cmd_wr_ptr_reg) begin
drop_cmd_next = !s_axis_cmd.tlast; drop_cmd_next = !s_axis_cmd.tlast;
state_next = STATE_START; state_next = STATE_START;
end else begin end else begin
@@ -222,6 +235,11 @@ always_comb begin
end end
end end
STATE_START: begin STATE_START: begin
cmd_ptr_next = '0;
dp_ptr_next = '0;
host_ptr_next = '0;
cnt_next = '0;
// determine block base address // determine block base address
case (opcode_reg) case (opcode_reg)
CMD_OP_CREATE_EQ, CMD_OP_CREATE_EQ,
@@ -230,7 +248,8 @@ always_comb begin
CMD_OP_DESTROY_EQ: CMD_OP_DESTROY_EQ:
begin begin
// EQ // EQ
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0000); 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;
end end
CMD_OP_CREATE_CQ, CMD_OP_CREATE_CQ,
CMD_OP_MODIFY_CQ, CMD_OP_MODIFY_CQ,
@@ -239,9 +258,11 @@ always_comb begin
begin begin
// CQ // CQ
if (qn_reg[0]) begin if (qn_reg[0]) begin
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0300); dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0300) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0300) + PORT_BASE_ADDR_HOST;
end else begin end else begin
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0400); dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0400) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0400) + PORT_BASE_ADDR_HOST;
end end
end end
CMD_OP_CREATE_SQ, CMD_OP_CREATE_SQ,
@@ -250,7 +271,8 @@ always_comb begin
CMD_OP_DESTROY_SQ: CMD_OP_DESTROY_SQ:
begin begin
// SQ // SQ
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0100); 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;
end end
CMD_OP_CREATE_RQ, CMD_OP_CREATE_RQ,
CMD_OP_MODIFY_RQ, CMD_OP_MODIFY_RQ,
@@ -258,7 +280,8 @@ always_comb begin
CMD_OP_DESTROY_RQ: CMD_OP_DESTROY_RQ:
begin begin
// RQ // RQ
block_base_addr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0200); dp_ptr_next = DP_APB_ADDR_W'({port_reg, 16'd0} | 'h0200) + DP_APB_ADDR_W'(PORT_BASE_ADDR_DP);
host_ptr_next = 32'({port_reg, 16'd0} | 'h0200) + PORT_BASE_ADDR_HOST;
end end
default: begin end default: begin end
endcase endcase
@@ -276,6 +299,31 @@ always_comb begin
// access register // access register
state_next = STATE_REG_1; state_next = STATE_REG_1;
end end
CMD_OP_PTP: begin
// PTP control
if (PTP_EN) begin
if (flags_reg[15:0] != 0) begin
// update something
cmd_ptr_next = 2;
dp_ptr_next = PTP_BASE_ADDR_DP + 'h50;
cnt_next = '0;
state_next = STATE_PTP_SET;
end else begin
// dump state
cmd_ptr_next = 2;
dp_ptr_next = PTP_BASE_ADDR_DP + 'h30;
cnt_next = '0;
state_next = STATE_PTP_READ_1;
end
end else begin
// PTP not enabled
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
end
CMD_OP_CREATE_EQ, CMD_OP_CREATE_EQ,
CMD_OP_CREATE_CQ, CMD_OP_CREATE_CQ,
CMD_OP_CREATE_SQ, CMD_OP_CREATE_SQ,
@@ -375,7 +423,7 @@ always_comb begin
STATE_Q_RESET_1: begin STATE_Q_RESET_1: begin
// reset queue 1 // reset queue 1
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h0000; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0000;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = 32'h00000000; m_apb_dp_ctrl_pwdata_next = 32'h00000000;
@@ -389,12 +437,12 @@ always_comb begin
STATE_Q_RESET_2: begin STATE_Q_RESET_2: begin
// reset queue 2 // reset queue 2
cmd_ram_wr_data = 32'(block_base_addr_reg + 'h0004) + PORT_BASE_ADDR; cmd_ram_wr_data = host_ptr_reg + 'h0004;
cmd_ram_wr_addr = 7; cmd_ram_wr_addr = 7;
cmd_ram_wr_en = 1'b1; cmd_ram_wr_en = 1'b1;
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h0004; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0004;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = 32'h00000000; m_apb_dp_ctrl_pwdata_next = 32'h00000000;
@@ -409,7 +457,7 @@ always_comb begin
// set queue base addr (LSB) // set queue base addr (LSB)
cmd_ram_rd_addr = 8; cmd_ram_rd_addr = 8;
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h0008; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0008;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_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_pwdata_next = cmd_ram_rd_data;
@@ -424,7 +472,7 @@ always_comb begin
// set queue base addr (MSB) // set queue base addr (MSB)
cmd_ram_rd_addr = 9; cmd_ram_rd_addr = 9;
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h000C; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h000C;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_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_pwdata_next = cmd_ram_rd_data;
@@ -439,7 +487,7 @@ always_comb begin
// enable queue // enable queue
cmd_ram_rd_addr = 6; cmd_ram_rd_addr = 6;
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h0000; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0000;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = '0; m_apb_dp_ctrl_pwdata_next = '0;
@@ -459,7 +507,7 @@ always_comb begin
STATE_Q_DISABLE: begin STATE_Q_DISABLE: begin
// disable queue // disable queue
if (!m_apb_dp_ctrl_psel_reg) begin if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = block_base_addr_reg + 'h0000; m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0000;
m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1;
m_apb_dp_ctrl_pwdata_next = 32'h00000000; m_apb_dp_ctrl_pwdata_next = 32'h00000000;
@@ -474,15 +522,142 @@ always_comb begin
state_next = STATE_Q_DISABLE; state_next = STATE_Q_DISABLE;
end end
end end
STATE_PTP_READ_1: begin
// read PTP register
if (!m_apb_dp_ctrl_psel_reg) begin
m_apb_dp_ctrl_paddr_next = dp_ptr_reg;
m_apb_dp_ctrl_psel_next = 1'b1;
m_apb_dp_ctrl_pwrite_next = 1'b0;
m_apb_dp_ctrl_pwdata_next = '0;
m_apb_dp_ctrl_pstrb_next = '1;
state_next = STATE_PTP_READ_2;
end else begin
state_next = STATE_PTP_READ_1;
end
end
STATE_PTP_READ_2: begin
// store read value and iterate
cmd_ram_wr_data = m_apb_dp_ctrl.prdata;
cmd_ram_wr_addr = cmd_ptr_reg;
cmd_ram_wr_en = 1'b1;
if (m_apb_dp_ctrl.pready) begin
cnt_next = cnt_reg + 1;
cmd_ptr_next = cmd_ptr_reg + 1;
dp_ptr_next = dp_ptr_reg + 4;
if (cnt_reg == 11) begin
// done
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 if (cnt_reg == 7) begin
// jump to period registers
dp_ptr_next = PTP_BASE_ADDR_DP + 'h70;
state_next = STATE_PTP_READ_1;
end else begin
// more to read
state_next = STATE_PTP_READ_1;
end
end else begin
state_next = STATE_PTP_READ_2;
end
end
STATE_PTP_SET: begin
// update PTP registers
if (!m_apb_dp_ctrl_psel_reg) begin
cnt_next = cnt_reg + 1;
dp_ptr_next = dp_ptr_reg + 4;
case (cnt_reg[3:0])
4'd0: begin
// offset ToD
cmd_ram_rd_addr = 3;
m_apb_dp_ctrl_psel_next = flags_reg[1];
end
4'd1: begin
// set ToD ns
cmd_ram_rd_addr = 3;
m_apb_dp_ctrl_psel_next = flags_reg[0];
end
4'd2: begin
// set ToD sec l
cmd_ram_rd_addr = 4;
m_apb_dp_ctrl_psel_next = flags_reg[0];
end
4'd3: begin
// set ToD sec h
cmd_ram_rd_addr = 5;
m_apb_dp_ctrl_psel_next = flags_reg[0];
end
4'd4: begin
// set rel ns l
cmd_ram_rd_addr = 6;
m_apb_dp_ctrl_psel_next = flags_reg[2];
end
4'd5: begin
// set rel ns h
cmd_ram_rd_addr = 7;
m_apb_dp_ctrl_psel_next = flags_reg[2];
end
4'd6: begin
// offset rel
cmd_ram_rd_addr = 6;
m_apb_dp_ctrl_psel_next = flags_reg[3];
end
4'd7: begin
// offset FNS
cmd_ram_rd_addr = 2;
m_apb_dp_ctrl_psel_next = flags_reg[4];
end
4'd10: begin
// period fns
cmd_ram_rd_addr = 12;
m_apb_dp_ctrl_psel_next = flags_reg[7];
end
4'd11: begin
// period ns
cmd_ram_rd_addr = 13;
m_apb_dp_ctrl_psel_next = flags_reg[7];
end
default: begin
// skip
m_apb_dp_ctrl_psel_next = 1'b0;
end
endcase
m_apb_dp_ctrl_paddr_next = dp_ptr_reg;
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;
if (cnt_reg == 11) begin
// done
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
// loop
state_next = STATE_PTP_SET;
end
end else begin
state_next = STATE_PTP_SET;
end
end
STATE_SEND_RSP: begin STATE_SEND_RSP: begin
// send response in the form of an edited command // send response in the form of an edited command
cmd_ram_rd_addr = rsp_ptr_reg; cmd_ram_rd_addr = rsp_rd_ptr_reg;
if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin
m_axis_rsp_tdata_next = cmd_ram_rd_data; m_axis_rsp_tdata_next = cmd_ram_rd_data;
m_axis_rsp_tvalid_next = 1'b1; m_axis_rsp_tvalid_next = 1'b1;
m_axis_rsp_tlast_next = &rsp_ptr_reg; m_axis_rsp_tlast_next = &rsp_rd_ptr_reg;
if (&rsp_ptr_reg) begin if (&rsp_rd_ptr_reg) begin
state_next = STATE_IDLE; state_next = STATE_IDLE;
end else begin end else begin
state_next = STATE_SEND_RSP; state_next = STATE_SEND_RSP;
@@ -496,9 +671,9 @@ always_comb begin
if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin if (m_axis_rsp.tready || !m_axis_rsp.tvalid) begin
m_axis_rsp_tdata_next = '0; m_axis_rsp_tdata_next = '0;
m_axis_rsp_tvalid_next = 1'b1; m_axis_rsp_tvalid_next = 1'b1;
m_axis_rsp_tlast_next = &rsp_ptr_reg; m_axis_rsp_tlast_next = &rsp_rd_ptr_reg;
if (&rsp_ptr_reg) begin if (&rsp_rd_ptr_reg) begin
state_next = STATE_IDLE; state_next = STATE_IDLE;
end else begin end else begin
state_next = STATE_PAD_RSP; state_next = STATE_PAD_RSP;
@@ -523,9 +698,9 @@ always_comb begin
if (m_axis_rsp_tvalid_next && (!m_axis_rsp_tvalid_reg || m_axis_rsp.tready)) begin if (m_axis_rsp_tvalid_next && (!m_axis_rsp_tvalid_reg || m_axis_rsp.tready)) begin
if (m_axis_rsp_tlast_next) begin if (m_axis_rsp_tlast_next) begin
rsp_ptr_next = '0; rsp_rd_ptr_next = '0;
end else begin end else begin
rsp_ptr_next = rsp_ptr_reg + 1; rsp_rd_ptr_next = rsp_rd_ptr_reg + 1;
rsp_frame_next = 1'b1; rsp_frame_next = 1'b1;
end end
end end
@@ -533,7 +708,7 @@ always_comb begin
if (m_axis_rsp.tready && m_axis_rsp.tvalid) begin if (m_axis_rsp.tready && m_axis_rsp.tvalid) begin
if (m_axis_rsp.tlast) begin if (m_axis_rsp.tlast) begin
rsp_frame_next = 1'b0; rsp_frame_next = 1'b0;
rsp_ptr_next = '0; rsp_rd_ptr_next = '0;
end end
end end
end end
@@ -561,9 +736,9 @@ always_ff @(posedge clk) begin
m_apb_dp_ctrl_pstrb_reg <= m_apb_dp_ctrl_pstrb_next; m_apb_dp_ctrl_pstrb_reg <= m_apb_dp_ctrl_pstrb_next;
cmd_frame_reg <= cmd_frame_next; cmd_frame_reg <= cmd_frame_next;
cmd_ptr_reg <= cmd_ptr_next; cmd_wr_ptr_reg <= cmd_wr_ptr_next;
rsp_frame_reg <= rsp_frame_next; rsp_frame_reg <= rsp_frame_next;
rsp_ptr_reg <= rsp_ptr_next; rsp_rd_ptr_reg <= rsp_rd_ptr_next;
drop_cmd_reg <= drop_cmd_next; drop_cmd_reg <= drop_cmd_next;
@@ -572,7 +747,10 @@ always_ff @(posedge clk) begin
port_reg <= port_next; port_reg <= port_next;
qn_reg <= qn_next; qn_reg <= qn_next;
block_base_addr_reg <= block_base_addr_next; cmd_ptr_reg <= cmd_ptr_next;
dp_ptr_reg <= dp_ptr_next;
host_ptr_reg <= host_ptr_next;
cnt_reg <= cnt_next;
if (rst) begin if (rst) begin
state_reg <= STATE_IDLE; state_reg <= STATE_IDLE;
@@ -584,9 +762,9 @@ always_ff @(posedge clk) begin
m_apb_dp_ctrl_penable_reg <= 1'b0; m_apb_dp_ctrl_penable_reg <= 1'b0;
cmd_frame_reg <= 1'b0; cmd_frame_reg <= 1'b0;
cmd_ptr_reg <= '0; cmd_wr_ptr_reg <= '0;
rsp_frame_reg <= 1'b0; rsp_frame_reg <= 1'b0;
rsp_ptr_reg <= '0; rsp_rd_ptr_reg <= '0;
drop_cmd_reg <= 1'b0; drop_cmd_reg <= 1'b0;
end end

View File

@@ -20,6 +20,7 @@ from cocotb.queue import Queue
CNDM_CMD_OP_NOP = 0x0000 CNDM_CMD_OP_NOP = 0x0000
CNDM_CMD_OP_ACCESS_REG = 0x0180 CNDM_CMD_OP_ACCESS_REG = 0x0180
CNDM_CMD_OP_PTP = 0x0190
CNDM_CMD_OP_CREATE_EQ = 0x0200 CNDM_CMD_OP_CREATE_EQ = 0x0200
CNDM_CMD_OP_MODIFY_EQ = 0x0201 CNDM_CMD_OP_MODIFY_EQ = 0x0201
@@ -46,6 +47,15 @@ CNDM_CMD_OP_MODIFY_QP = 0x0241
CNDM_CMD_OP_QUERY_QP = 0x0242 CNDM_CMD_OP_QUERY_QP = 0x0242
CNDM_CMD_OP_DESTROY_QP = 0x0243 CNDM_CMD_OP_DESTROY_QP = 0x0243
CNDM_CMD_REG_FLG_WRITE = 0x00000001
CNDM_CMD_REG_FLG_RAW = 0x00000100
CNDM_CMD_PTP_FLG_SET_TOD = 0x00000001
CNDM_CMD_PTP_FLG_OFFSET_TOD = 0x00000002
CNDM_CMD_PTP_FLG_SET_REL = 0x00000004
CNDM_CMD_PTP_FLG_OFFSET_REL = 0x00000008
CNDM_CMD_PTP_FLG_OFFSET_FNS = 0x00000010
CNDM_CMD_PTP_FLG_SET_PERIOD = 0x00000080
class Port: class Port:
def __init__(self, driver, index): def __init__(self, driver, index):
@@ -348,12 +358,48 @@ class Driver:
async def init_common(self): async def init_common(self):
self.port_count = await self.hw_regs.read_dword(0x0100) self.port_count = await self.hw_regs.read_dword(0x0100)
self.port_offset = await self.hw_regs.read_dword(0x0104)
self.port_stride = await self.hw_regs.read_dword(0x0108)
self.log.info("Port count: %d", self.port_count) self.log.info("Port count: %d", self.port_count)
self.log.info("Port offset: 0x%x", self.port_offset)
self.log.info("Port stride: 0x%x", self.port_stride) # Get PTP information
rsp = await self.exec_cmd(struct.pack("<HHLLLQQQQQLL",
0, # rsvd
CNDM_CMD_OP_PTP, # opcode
0x00000000, # flags
0, # fns
0, # tod_ns
0, # tod_sec
0, # rel_ns
0, # ptm
0, # nom_period
0, # period
0, # rsvd
0, # rsvd
))
rsp_unpacked = struct.unpack("<HHLLLQQQQQLL", rsp)
print(rsp_unpacked)
nom_period = rsp_unpacked[8]
self.log.info("PHC nominal period: %.09f ns (raw 0x%x)", nom_period / 2**32, nom_period)
rsp = await self.exec_cmd(struct.pack("<HHLLLQQQQQLL",
0, # rsvd
CNDM_CMD_OP_PTP, # opcode
CNDM_CMD_PTP_FLG_SET_TOD | CNDM_CMD_PTP_FLG_SET_REL | CNDM_CMD_PTP_FLG_SET_PERIOD, # flags
0, # fns
0x12345678, # tod_ns
0x123456654321, # tod_sec
0x11223344, # rel_ns
0, # ptm
0, # nom_period
nom_period, # period
0, # rsvd
0, # rsvd
))
rsp_unpacked = struct.unpack("<HHLLLQQQQQLL", rsp)
print(rsp_unpacked)
for k in range(self.port_count): for k in range(self.port_count):
port = Port(self, k) port = Port(self, k)
@@ -365,24 +411,24 @@ class Driver:
async def access_reg(self, reg, raw, write=False, data=0): async def access_reg(self, reg, raw, write=False, data=0):
flags = 0 flags = 0
if raw: if raw:
flags |= 0x00000100 flags |= CNDM_CMD_REG_FLG_RAW
if write: if write:
flags |= 0x00000001 flags |= CNDM_CMD_REG_FLG_WRITE
rsp = await self.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL", rsp = await self.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
0, # rsvd 0, # rsvd
CNDM_CMD_OP_ACCESS_REG, # opcode CNDM_CMD_OP_ACCESS_REG, # opcode
flags, # flags flags, # flags
0, # port 0, # rsvd
0, # sqn 0, # rsvd
0, # cqn 0, # rsvd
0, # pd 0, # rsvd
0, # size 0, # rsvd
reg, # dboffs reg, # reg
data, # base addr data, # write data
0, # ptr2 0, # read data
0, # prod_ptr 0, # rsvd
0, # cons_ptr 0, # rsvd
0, # rsvd 0, # rsvd
0, # rsvd 0, # rsvd
)) ))