mirror of
https://github.com/fpganinja/taxi.git
synced 2026-04-07 04:38:42 -07:00
cndm: Add PTP command
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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("<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):
|
||||
port = Port(self, k)
|
||||
@@ -365,24 +411,24 @@ class Driver:
|
||||
async def access_reg(self, reg, raw, write=False, data=0):
|
||||
flags = 0
|
||||
if raw:
|
||||
flags |= 0x00000100
|
||||
flags |= CNDM_CMD_REG_FLG_RAW
|
||||
if write:
|
||||
flags |= 0x00000001
|
||||
flags |= CNDM_CMD_REG_FLG_WRITE
|
||||
|
||||
rsp = await self.exec_cmd(struct.pack("<HHLLLLLLLQQLLLL",
|
||||
0, # rsvd
|
||||
CNDM_CMD_OP_ACCESS_REG, # opcode
|
||||
flags, # flags
|
||||
0, # port
|
||||
0, # sqn
|
||||
0, # cqn
|
||||
0, # pd
|
||||
0, # size
|
||||
reg, # dboffs
|
||||
data, # base addr
|
||||
0, # ptr2
|
||||
0, # prod_ptr
|
||||
0, # cons_ptr
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
reg, # reg
|
||||
data, # write data
|
||||
0, # read data
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
0, # rsvd
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user