diff --git a/src/cndm/modules/cndm/cndm.h b/src/cndm/modules/cndm/cndm.h index be18897..ad3aa8f 100644 --- a/src/cndm/modules/cndm/cndm.h +++ b/src/cndm/modules/cndm/cndm.h @@ -54,12 +54,10 @@ struct cndm_dev { struct mutex mbox_lock; u32 port_count; - u32 port_offset; - u32 port_stride; - void __iomem *phc_regs; struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_info; + u64 ptp_nom_period; }; struct cndm_tx_info { diff --git a/src/cndm/modules/cndm/cndm_cmd.c b/src/cndm/modules/cndm/cndm_cmd.c index 5aed20a..1c0c45f 100644 --- a/src/cndm/modules/cndm/cndm_cmd.c +++ b/src/cndm/modules/cndm/cndm_cmd.c @@ -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) { - struct cndm_cmd cmd; - struct cndm_cmd rsp; + struct cndm_cmd_reg cmd; + struct cndm_cmd_reg rsp; cmd.opcode = CNDM_CMD_OP_ACCESS_REG; cmd.flags = 0x00000000; - cmd.port = 0; - cmd.qn = 0; - cmd.qn2 = 0; - cmd.pd = 0; - cmd.size = 0; - cmd.dboffs = reg; - cmd.ptr1 = *data; - cmd.ptr2 = 0; + cmd.reg_addr = reg; + cmd.write_val = *data; + cmd.read_val = 0; if (write) - cmd.flags |= 0x00000001; + cmd.flags |= CNDM_CMD_REG_FLG_WRITE; if (raw) - cmd.flags |= 0x00000100; + cmd.flags |= CNDM_CMD_REG_FLG_RAW; cndm_exec_cmd(cdev, &cmd, &rsp); if (!write) - *data = rsp.ptr2; + *data = rsp.read_val; return 0; } diff --git a/src/cndm/modules/cndm/cndm_hw.h b/src/cndm/modules/cndm/cndm_hw.h index b661a7d..352f2fc 100644 --- a/src/cndm/modules/cndm/cndm_hw.h +++ b/src/cndm/modules/cndm/cndm_hw.h @@ -16,6 +16,7 @@ Authors: #define CNDM_CMD_OP_NOP 0x0000 #define CNDM_CMD_OP_ACCESS_REG 0x0180 +#define CNDM_CMD_OP_PTP 0x0190 #define CNDM_CMD_OP_CREATE_EQ 0x0200 #define CNDM_CMD_OP_MODIFY_EQ 0x0201 @@ -42,7 +43,7 @@ Authors: #define CNDM_CMD_OP_QUERY_QP 0x0242 #define CNDM_CMD_OP_DESTROY_QP 0x0243 -struct cndm_cmd { +struct cndm_cmd_queue { __le16 rsvd; union { __le16 opcode; @@ -66,6 +67,61 @@ struct cndm_cmd { __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 { __le16 rsvd0; union { diff --git a/src/cndm/modules/cndm/cndm_main.c b/src/cndm/modules/cndm/cndm_main.c index 510fb4a..f894cb7 100644 --- a/src/cndm/modules/cndm/cndm_main.c +++ b/src/cndm/modules/cndm/cndm_main.c @@ -56,12 +56,8 @@ static int cndm_common_probe(struct cndm_dev *cdev) #endif 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 offset: 0x%x", cdev->port_offset); - dev_info(dev, "Port stride: 0x%x", cdev->port_stride); if (cdev->port_count > ARRAY_SIZE(cdev->ndev)) cdev->port_count = ARRAY_SIZE(cdev->ndev); diff --git a/src/cndm/modules/cndm/cndm_netdev.c b/src/cndm/modules/cndm/cndm_netdev.c index ca63eac..98f980d 100644 --- a/src/cndm/modules/cndm/cndm_netdev.c +++ b/src/cndm/modules/cndm/cndm_netdev.c @@ -178,8 +178,8 @@ struct net_device *cndm_create_netdev(struct cndm_dev *cdev, int port) struct cndm_priv *priv; int ret = 0; - struct cndm_cmd cmd; - struct cndm_cmd rsp; + struct cndm_cmd_queue cmd; + struct cndm_cmd_queue rsp; ndev = alloc_etherdev_mqs(sizeof(*priv), 1, 1); if (!ndev) { @@ -373,8 +373,8 @@ void cndm_destroy_netdev(struct net_device *ndev) struct cndm_dev *cdev = priv->cdev; struct device *dev = priv->dev; - struct cndm_cmd cmd; - struct cndm_cmd rsp; + struct cndm_cmd_queue cmd; + struct cndm_cmd_queue rsp; cmd.opcode = CNDM_CMD_OP_DESTROY_CQ; cmd.flags = 0x00000000; diff --git a/src/cndm/modules/cndm/cndm_ptp.c b/src/cndm/modules/cndm/cndm_ptp.c index 2c33ecc..0f04f87 100644 --- a/src/cndm/modules/cndm/cndm_ptp.c +++ b/src/cndm/modules/cndm/cndm_ptp.c @@ -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)) { // seconds MSBs do not match, update cached timestamp - if (cdev->phc_regs) { - priv->ts_s = ioread32(cdev->phc_regs + 0x18); - priv->ts_s |= (u64) ioread32(cdev->phc_regs + 0x1C) << 32; - priv->ts_valid = 1; - } + priv->ts_s = ioread32(cdev->hw_addr + 0x0308); + priv->ts_s |= (u64) ioread32(cdev->hw_addr + 0x030C) << 32; + priv->ts_valid = 1; } 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); } 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_cmd_ptp cmd; + struct cndm_cmd_ptp rsp; bool neg = false; 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; } - nom_per_fns = ioread32(cdev->phc_regs + 0x70); - nom_per_fns |= (u64) ioread32(cdev->phc_regs + 0x74) << 32; + nom_per_fns = cdev->ptp_nom_period; if (nom_per_fns == 0) nom_per_fns = 0x4ULL << 32; @@ -60,8 +61,11 @@ static int cndm_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) else adj = nom_per_fns + adj; - iowrite32(adj & 0xffffffff, cdev->phc_regs + 0x78); - iowrite32(adj >> 32, cdev->phc_regs + 0x7C); + cmd.opcode = CNDM_CMD_OP_PTP; + 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); @@ -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); - ioread32(cdev->phc_regs + 0x30); - ts->tv_nsec = ioread32(cdev->phc_regs + 0x34); - ts->tv_sec = ioread32(cdev->phc_regs + 0x38); - ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32; + ioread32(cdev->hw_addr + 0x0320); + ts->tv_nsec = ioread32(cdev->hw_addr + 0x0324); + ts->tv_sec = ioread32(cdev->hw_addr + 0x0328); + 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; } @@ -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); ptp_read_system_prets(sts); - ioread32(cdev->phc_regs + 0x30); + ioread32(cdev->hw_addr + 0x0320); ptp_read_system_postts(sts); - ts->tv_nsec = ioread32(cdev->phc_regs + 0x34); - ts->tv_sec = ioread32(cdev->phc_regs + 0x38); - ts->tv_sec |= (u64) ioread32(cdev->phc_regs + 0x3C) << 32; + ts->tv_nsec = ioread32(cdev->hw_addr + 0x0324); + ts->tv_sec = ioread32(cdev->hw_addr + 0x0328); + 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; } @@ -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) { 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); - iowrite32(ts->tv_sec & 0xffffffff, cdev->phc_regs + 0x58); - iowrite32(ts->tv_sec >> 32, cdev->phc_regs + 0x5C); + cmd.opcode = CNDM_CMD_OP_PTP; + cmd.flags = CNDM_CMD_PTP_FLG_SET_TOD; + cmd.tod_ns = ts->tv_nsec; + cmd.tod_sec = ts->tv_sec; + + cndm_exec_cmd(cdev, &cmd, &rsp); 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 timespec64 ts; + struct cndm_cmd_ptp cmd; + struct cndm_cmd_ptp rsp; 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); } else { // 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; @@ -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) { + struct cndm_cmd_ptp cmd; + struct cndm_cmd_ptp rsp; + if (cdev->ptp_clock) { dev_warn(cdev->dev, "PTP clock already registered"); return; } - // TODO - if (cdev->port_offset == 0x20000) { + cmd.opcode = CNDM_CMD_OP_PTP; + 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"); 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; snprintf(cdev->ptp_clock_info.name, sizeof(cdev->ptp_clock_info.name), "%s_phc", cdev->name); diff --git a/src/cndm/rtl/cndm_micro_core.f b/src/cndm/rtl/cndm_micro_core.f index 422d878..988d583 100644 --- a/src/cndm/rtl/cndm_micro_core.f +++ b/src/cndm/rtl/cndm_micro_core.f @@ -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_arb_mux.f ../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 diff --git a/src/cndm/rtl/cndm_micro_core.sv b/src/cndm/rtl/cndm_micro_core.sv index 1e7d776..c654c64 100644 --- a/src/cndm/rtl/cndm_micro_core.sv +++ b/src/cndm/rtl/cndm_micro_core.sv @@ -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_SEL_W = dma_ram_wr.SEL_W; -localparam PORT_OFFSET = PTP_TS_EN ? 3 : 2; -localparam PORT_BASE_ADDR = PTP_TS_EN ? 32'h00030000 : 32'h00020000; +localparam PORT_OFFSET_DP = PTP_TS_EN ? 1 : 0; +localparam PORT_OFFSET_HOST = 2; +localparam PORT_BASE_ADDR_DP = PTP_TS_EN ? 32'h00010000 : 32'h00000000; +localparam PORT_BASE_ADDR_HOST = 32'h00020000; taxi_axil_if #( .DATA_W(s_axil_ctrl_wr.DATA_W), @@ -124,7 +126,7 @@ taxi_axil_if #( .RUSER_EN(s_axil_ctrl_wr.RUSER_EN), .RUSER_W(s_axil_ctrl_wr.RUSER_W) ) -axil_ctrl[PORTS+PORT_OFFSET](); +axil_ctrl[PORTS+PORT_OFFSET_HOST](); taxi_axil_interconnect_1s #( .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; wire cmd_mbox_busy; +logic [95:0] get_ptp_ts_tod_reg = '0; +logic [63:0] get_ptp_ts_rel_reg = '0; + always_ff @(posedge clk) begin s_axil_awready_reg <= 1'b0; s_axil_wready_reg <= 1'b0; @@ -212,11 +217,30 @@ always_ff @(posedge clk) begin case ({axil_ctrl[0].araddr[15:2], 2'b00}) 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 s_axil_rdata_reg[0] <= cmd_mbox_busy; end + 16'h0300: s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0}; // PTP cur fns + 16'h0304: s_axil_rdata_reg <= ptp_sync_ts_tod[47:16]; // PTP cur ToD ns + 16'h0308: s_axil_rdata_reg <= ptp_sync_ts_tod[79:48]; // PTP cur ToD sec l + 16'h030C: s_axil_rdata_reg <= 32'(ptp_sync_ts_tod[95:80]); // PTP cur ToD sec h + 16'h0310: s_axil_rdata_reg <= ptp_sync_ts_rel[47:16]; // PTP cur rel ns l + 16'h0314: s_axil_rdata_reg <= 32'(ptp_sync_ts_rel[63:48]); // PTP cur rel ns h + 16'h0318: s_axil_rdata_reg <= '0; // PTP cur PTM l + 16'h031C: s_axil_rdata_reg <= '0; // PTP cur PTM h + 16'h0320: begin + // PTP snapshot fns + get_ptp_ts_tod_reg <= ptp_sync_ts_tod; + get_ptp_ts_rel_reg <= ptp_sync_ts_rel; + s_axil_rdata_reg <= {ptp_sync_ts_tod[15:0], 16'd0}; + end + 16'h0324: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[45:16]); // PTP snapshot ToD ns + 16'h0328: s_axil_rdata_reg <= get_ptp_ts_tod_reg[79:48]; // PTP snapshot ToD sec l + 16'h032C: s_axil_rdata_reg <= 32'(get_ptp_ts_tod_reg[95:80]); // PTP snapshot ToD sec h + 16'h0330: s_axil_rdata_reg <= get_ptp_ts_rel_reg[47:16]; // PTP snapshot rel ns l + 16'h0334: s_axil_rdata_reg <= 32'(get_ptp_ts_rel_reg[63:48]); // PTP snapshot rel ns h + 16'h0338: s_axil_rdata_reg <= '0; // PTP snapshot PTM l + 16'h033C: s_axil_rdata_reg <= '0; // PTP snapshot PTM h default: begin end endcase end @@ -278,13 +302,16 @@ cmd_mbox_inst ( taxi_apb_if #( .DATA_W(32), - .ADDR_W(16+CL_PORTS) + .ADDR_W(16+$clog2(PORTS+PORT_OFFSET_DP)) ) apb_dp_ctrl(); cndm_micro_dp_mgr #( .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 ( .clk(clk), @@ -306,7 +333,7 @@ taxi_apb_if #( .DATA_W(32), .ADDR_W(16) ) -apb_port_dp_ctrl[PORTS](); +apb_port_dp_ctrl[PORT_OFFSET_DP+PORTS](); taxi_apb_interconnect #( .M_CNT($size(apb_port_dp_ctrl)), @@ -333,7 +360,7 @@ port_dp_intercon_inst ( 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_DENOM(PTP_CLK_PER_NS_DENOM) ) @@ -344,8 +371,7 @@ if (PTP_TS_EN) begin : ptp /* * Control register interface */ - .s_axil_wr(axil_ctrl[2]), - .s_axil_rd(axil_ctrl[2]), + .s_apb(apb_port_dp_ctrl[0]), /* * PTP @@ -474,13 +500,13 @@ for (genvar p = 0; p < PORTS; p = p + 1) begin : port /* * Control register interface */ - .s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET+p]), - .s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET+p]), + .s_axil_ctrl_wr(axil_ctrl[PORT_OFFSET_HOST+p]), + .s_axil_ctrl_rd(axil_ctrl[PORT_OFFSET_HOST+p]), /* * Datapath control register interface */ - .s_apb_dp_ctrl(apb_port_dp_ctrl[p]), + .s_apb_dp_ctrl(apb_port_dp_ctrl[PORT_OFFSET_DP+p]), /* * DMA diff --git a/src/cndm/rtl/cndm_micro_dp_mgr.sv b/src/cndm/rtl/cndm_micro_dp_mgr.sv index 1b5775c..6b3de1e 100644 --- a/src/cndm/rtl/cndm_micro_dp_mgr.sv +++ b/src/cndm/rtl/cndm_micro_dp_mgr.sv @@ -18,7 +18,10 @@ Authors: module cndm_micro_dp_mgr # ( 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, @@ -45,6 +48,7 @@ typedef enum logic [15:0] { CMD_OP_NOP = 16'h0000, CMD_OP_ACCESS_REG = 16'h0180, + CMD_OP_PTP = 16'h0190, CMD_OP_CREATE_EQ = 16'h0200, CMD_OP_MODIFY_EQ = 16'h0201, @@ -84,6 +88,9 @@ typedef enum logic [4:0] { STATE_Q_SET_BASE_H, STATE_Q_ENABLE, STATE_Q_DISABLE, + STATE_PTP_READ_1, + STATE_PTP_READ_2, + STATE_PTP_SET, STATE_SEND_RSP, STATE_PAD_RSP } state_t; @@ -135,9 +142,9 @@ 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 [3:0] cmd_wr_ptr_reg = '0, cmd_wr_ptr_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; @@ -146,7 +153,10 @@ 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; +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 state_next = STATE_IDLE; @@ -165,14 +175,14 @@ always_comb begin 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_addr = cmd_wr_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; + cmd_wr_ptr_next = cmd_wr_ptr_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; @@ -181,14 +191,17 @@ always_comb begin port_next = port_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.tlast) begin cmd_frame_next = 1'b0; - cmd_ptr_next = '0; + cmd_wr_ptr_next = '0; end else begin - cmd_ptr_next = cmd_ptr_reg + 1; + cmd_wr_ptr_next = cmd_wr_ptr_reg + 1; cmd_frame_next = 1'b1; end end @@ -198,11 +211,11 @@ always_comb 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_addr = cmd_wr_ptr_reg; cmd_ram_wr_en = 1'b1; // save some important fields - case (cmd_ptr_reg) + case (cmd_wr_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]; @@ -211,7 +224,7 @@ always_comb begin endcase 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; state_next = STATE_START; end else begin @@ -222,6 +235,11 @@ always_comb begin end end STATE_START: begin + cmd_ptr_next = '0; + dp_ptr_next = '0; + host_ptr_next = '0; + cnt_next = '0; + // determine block base address case (opcode_reg) CMD_OP_CREATE_EQ, @@ -230,7 +248,8 @@ always_comb begin CMD_OP_DESTROY_EQ: begin // 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 CMD_OP_CREATE_CQ, CMD_OP_MODIFY_CQ, @@ -239,9 +258,11 @@ always_comb begin begin // CQ 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 - 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 CMD_OP_CREATE_SQ, @@ -250,7 +271,8 @@ always_comb begin CMD_OP_DESTROY_SQ: begin // 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 CMD_OP_CREATE_RQ, CMD_OP_MODIFY_RQ, @@ -258,7 +280,8 @@ always_comb begin CMD_OP_DESTROY_RQ: begin // 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 default: begin end endcase @@ -276,6 +299,31 @@ always_comb begin // access register state_next = STATE_REG_1; 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_CQ, CMD_OP_CREATE_SQ, @@ -375,7 +423,7 @@ always_comb begin 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 + 'h0000; + m_apb_dp_ctrl_paddr_next = dp_ptr_reg + '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; @@ -389,12 +437,12 @@ always_comb begin STATE_Q_RESET_2: begin // 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_en = 1'b1; 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_pwrite_next = 1'b1; m_apb_dp_ctrl_pwdata_next = 32'h00000000; @@ -409,7 +457,7 @@ always_comb 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 + 'h0008; + m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0008; m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data; @@ -424,7 +472,7 @@ always_comb begin // set queue base addr (MSB) cmd_ram_rd_addr = 9; if (!m_apb_dp_ctrl_psel_reg) begin - m_apb_dp_ctrl_paddr_next = 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_pwrite_next = 1'b1; m_apb_dp_ctrl_pwdata_next = cmd_ram_rd_data; @@ -439,7 +487,7 @@ always_comb 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 + 'h0000; + m_apb_dp_ctrl_paddr_next = dp_ptr_reg + 'h0000; m_apb_dp_ctrl_psel_next = 1'b1; m_apb_dp_ctrl_pwrite_next = 1'b1; m_apb_dp_ctrl_pwdata_next = '0; @@ -459,7 +507,7 @@ always_comb begin STATE_Q_DISABLE: begin // disable queue 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_pwrite_next = 1'b1; m_apb_dp_ctrl_pwdata_next = 32'h00000000; @@ -474,15 +522,142 @@ always_comb begin state_next = STATE_Q_DISABLE; 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 // 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 m_axis_rsp_tdata_next = cmd_ram_rd_data; 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; end else begin state_next = STATE_SEND_RSP; @@ -496,9 +671,9 @@ always_comb begin 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; + m_axis_rsp_tlast_next = &rsp_rd_ptr_reg; - if (&rsp_ptr_reg) begin + if (&rsp_rd_ptr_reg) begin state_next = STATE_IDLE; end else begin 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_tlast_next) begin - rsp_ptr_next = '0; + rsp_rd_ptr_next = '0; end else begin - rsp_ptr_next = rsp_ptr_reg + 1; + rsp_rd_ptr_next = rsp_rd_ptr_reg + 1; rsp_frame_next = 1'b1; end end @@ -533,7 +708,7 @@ always_comb begin 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; + rsp_rd_ptr_next = '0; end end end @@ -561,9 +736,9 @@ always_ff @(posedge clk) begin m_apb_dp_ctrl_pstrb_reg <= m_apb_dp_ctrl_pstrb_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_ptr_reg <= rsp_ptr_next; + rsp_rd_ptr_reg <= rsp_rd_ptr_next; drop_cmd_reg <= drop_cmd_next; @@ -572,7 +747,10 @@ always_ff @(posedge clk) begin port_reg <= port_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 state_reg <= STATE_IDLE; @@ -584,9 +762,9 @@ always_ff @(posedge clk) begin m_apb_dp_ctrl_penable_reg <= 1'b0; cmd_frame_reg <= 1'b0; - cmd_ptr_reg <= '0; + cmd_wr_ptr_reg <= '0; rsp_frame_reg <= 1'b0; - rsp_ptr_reg <= '0; + rsp_rd_ptr_reg <= '0; drop_cmd_reg <= 1'b0; end diff --git a/src/cndm/tb/cndm.py b/src/cndm/tb/cndm.py index 9dc58de..dd653ba 100644 --- a/src/cndm/tb/cndm.py +++ b/src/cndm/tb/cndm.py @@ -20,6 +20,7 @@ from cocotb.queue import Queue CNDM_CMD_OP_NOP = 0x0000 CNDM_CMD_OP_ACCESS_REG = 0x0180 +CNDM_CMD_OP_PTP = 0x0190 CNDM_CMD_OP_CREATE_EQ = 0x0200 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_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: def __init__(self, driver, index): @@ -348,12 +358,48 @@ class Driver: async def init_common(self): 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 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("