diff --git a/src/eth/rtl/taxi_axis_baser_rx_64.sv b/src/eth/rtl/taxi_axis_baser_rx_64.sv index 605d19a..d0fca56 100644 --- a/src/eth/rtl/taxi_axis_baser_rx_64.sv +++ b/src/eth/rtl/taxi_axis_baser_rx_64.sv @@ -584,10 +584,13 @@ always_ff @(posedge clk) begin if (PTP_TS_EN && PTP_TS_FMT_TOD) begin // ns field rollover + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ ptp_ts_adj_reg[15:0] <= ptp_ts_reg[15:0]; {ptp_ts_borrow_reg, ptp_ts_adj_reg[45:16]} <= $signed({1'b0, ptp_ts_reg[45:16]}) - $signed(31'd1000000000); ptp_ts_adj_reg[47:46] <= 0; ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1; + /* verilator lint_on SELRANGE */ end // lane swapping and termination character detection @@ -807,8 +810,11 @@ always_ff @(posedge clk) begin if (input_start_swap_reg) begin start_packet_reg <= 2'b10; if (PTP_TS_FMT_TOD) begin + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ ptp_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); ptp_ts_reg[95:48] <= ptp_ts[95:48]; + /* verilator lint_on SELRANGE */ end else begin ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); end diff --git a/src/eth/rtl/taxi_axis_baser_tx_64.sv b/src/eth/rtl/taxi_axis_baser_tx_64.sv index f0522f7..f3bae5f 100644 --- a/src/eth/rtl/taxi_axis_baser_tx_64.sv +++ b/src/eth/rtl/taxi_axis_baser_tx_64.sv @@ -788,10 +788,13 @@ always_ff @(posedge clk) begin if (PTP_TS_EN && PTP_TS_FMT_TOD) begin m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_int_reg; + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ m_axis_tx_cpl_ts_adj_reg[15:0] <= m_axis_tx_cpl_ts_reg[15:0]; {m_axis_tx_cpl_ts_borrow_reg, m_axis_tx_cpl_ts_adj_reg[45:16]} <= $signed({1'b0, m_axis_tx_cpl_ts_reg[45:16]}) - $signed(31'd1000000000); m_axis_tx_cpl_ts_adj_reg[47:46] <= 0; m_axis_tx_cpl_ts_adj_reg[95:48] <= m_axis_tx_cpl_ts_reg[95:48] + 1; + /* verilator lint_on SELRANGE */ end if (GBX_IF_EN && tx_gbx_req_stall) begin @@ -810,8 +813,11 @@ always_ff @(posedge clk) begin if (swap_lanes_reg) begin if (PTP_TS_EN) begin if (PTP_TS_FMT_TOD) begin + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ m_axis_tx_cpl_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); m_axis_tx_cpl_ts_reg[95:48] <= ptp_ts[95:48]; + /* verilator lint_on SELRANGE */ end else begin m_axis_tx_cpl_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); end diff --git a/src/eth/rtl/taxi_eth_mac_10g.f b/src/eth/rtl/taxi_eth_mac_10g.f index b89e559..031c807 100644 --- a/src/eth/rtl/taxi_eth_mac_10g.f +++ b/src/eth/rtl/taxi_eth_mac_10g.f @@ -12,4 +12,5 @@ taxi_mac_pause_ctrl_rx.sv ../lib/taxi/src/axis/rtl/taxi_axis_if.sv ../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv ../lib/taxi/src/axis/rtl/taxi_axis_tie.sv +../lib/taxi/src/ptp/rtl/taxi_ptp_td_leaf.sv ../lib/taxi/src/sync/rtl/taxi_sync_signal.sv diff --git a/src/eth/rtl/taxi_eth_mac_10g.sv b/src/eth/rtl/taxi_eth_mac_10g.sv index 6ea976f..23ba70d 100644 --- a/src/eth/rtl/taxi_eth_mac_10g.sv +++ b/src/eth/rtl/taxi_eth_mac_10g.sv @@ -26,8 +26,10 @@ module taxi_eth_mac_10g # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic PFC_EN = 1'b0, parameter logic PAUSE_EN = PFC_EN, parameter logic STAT_EN = 1'b0, @@ -71,8 +73,18 @@ module taxi_eth_mac_10g # /* * PTP */ - input wire logic [PTP_TS_W-1:0] tx_ptp_ts = '0, - input wire logic [PTP_TS_W-1:0] rx_ptp_ts = '0, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] tx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out, + output wire logic tx_ptp_ts_step_out, + output wire logic tx_ptp_locked, + input wire logic [PTP_TS_W-1:0] rx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out, + output wire logic rx_ptp_ts_step_out, + output wire logic rx_ptp_locked, /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) @@ -216,6 +228,123 @@ if (KEEP_W*8 != DATA_W || CTRL_W*8 != DATA_W) taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(TX_USER_W_INT), .ID_EN(1), .ID_W(TX_TAG_W)) axis_tx_int(); taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(RX_USER_W)) axis_rx_int(); +// PTP timestamping +if (PTP_TS_EN && PTP_TD_EN) begin : ptp + + // TX + wire [PTP_TS_W-1:0] tx_ptp_ts_rel; + wire tx_ptp_ts_rel_step; + wire [PTP_TS_W-1:0] tx_ptp_ts_tod; + wire tx_ptp_ts_tod_step; + + taxi_ptp_td_leaf #( + .TS_REL_EN(!PTP_TS_FMT_TOD), + .TS_TOD_EN(PTP_TS_FMT_TOD), + .TS_FNS_W(16), + .TS_REL_NS_W(PTP_TS_FMT_TOD ? 48 : PTP_TS_W-16), + .TS_TOD_S_W(PTP_TS_FMT_TOD ? PTP_TS_W-32-16 : 48), + .TS_REL_W(PTP_TS_W), + .TS_TOD_W(PTP_TS_W), + .TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE) + ) + tx_leaf_inst ( + .clk(tx_clk), + .rst(tx_rst), + .sample_clk(ptp_sample_clk), + + /* + * PTP clock interface + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_td_sdi(ptp_td_sdi), + + /* + * Timestamp output + */ + .output_ts_rel(tx_ptp_ts_rel), + .output_ts_rel_step(tx_ptp_ts_rel_step), + .output_ts_tod(tx_ptp_ts_tod), + .output_ts_tod_step(tx_ptp_ts_tod_step), + + /* + * PPS output (ToD format only) + */ + .output_pps(), + .output_pps_str(), + + /* + * Status + */ + .locked(tx_ptp_locked) + ); + + assign tx_ptp_ts_out = PTP_TS_FMT_TOD ? tx_ptp_ts_tod : tx_ptp_ts_rel; + assign tx_ptp_ts_step_out = PTP_TS_FMT_TOD ? tx_ptp_ts_tod_step : tx_ptp_ts_rel_step; + + // RX + wire [PTP_TS_W-1:0] rx_ptp_ts_rel; + wire rx_ptp_ts_rel_step; + wire [PTP_TS_W-1:0] rx_ptp_ts_tod; + wire rx_ptp_ts_tod_step; + + taxi_ptp_td_leaf #( + .TS_REL_EN(!PTP_TS_FMT_TOD), + .TS_TOD_EN(PTP_TS_FMT_TOD), + .TS_FNS_W(16), + .TS_REL_NS_W(PTP_TS_FMT_TOD ? 48 : PTP_TS_W-16), + .TS_TOD_S_W(PTP_TS_FMT_TOD ? PTP_TS_W-32-16 : 48), + .TS_REL_W(PTP_TS_W), + .TS_TOD_W(PTP_TS_W), + .TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE) + ) + rx_leaf_inst ( + .clk(rx_clk), + .rst(rx_rst), + .sample_clk(ptp_sample_clk), + + /* + * PTP clock interface + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_td_sdi(ptp_td_sdi), + + /* + * Timestamp output + */ + .output_ts_rel(rx_ptp_ts_rel), + .output_ts_rel_step(rx_ptp_ts_rel_step), + .output_ts_tod(rx_ptp_ts_tod), + .output_ts_tod_step(rx_ptp_ts_tod_step), + + /* + * PPS output (ToD format only) + */ + .output_pps(), + .output_pps_str(), + + /* + * Status + */ + .locked(rx_ptp_locked) + ); + + assign rx_ptp_ts_out = PTP_TS_FMT_TOD ? rx_ptp_ts_tod : rx_ptp_ts_rel; + assign rx_ptp_ts_step_out = PTP_TS_FMT_TOD ? rx_ptp_ts_tod_step : rx_ptp_ts_rel_step; + +end else begin + + assign tx_ptp_ts_out = tx_ptp_ts_in; + assign tx_ptp_ts_step_out = 1'b0; + assign rx_ptp_ts_out = rx_ptp_ts_in; + assign rx_ptp_ts_step_out = 1'b0; + + assign tx_ptp_locked = 1'b0; + assign rx_ptp_locked = 1'b0; + +end + if (DATA_W == 64) begin taxi_axis_xgmii_rx_64 #( @@ -245,7 +374,7 @@ if (DATA_W == 64) begin /* * PTP */ - .ptp_ts(rx_ptp_ts), + .ptp_ts(rx_ptp_ts_out), /* * Configuration @@ -310,7 +439,7 @@ if (DATA_W == 64) begin /* * PTP */ - .ptp_ts(tx_ptp_ts), + .ptp_ts(tx_ptp_ts_out), /* * Configuration @@ -364,7 +493,7 @@ end else if (DATA_W == 32) begin /* * PTP */ - .ptp_ts(rx_ptp_ts), + .ptp_ts(rx_ptp_ts_out), /* * Configuration @@ -431,7 +560,7 @@ end else if (DATA_W == 32) begin /* * PTP */ - .ptp_ts(tx_ptp_ts), + .ptp_ts(tx_ptp_ts_out), /* * Configuration diff --git a/src/eth/rtl/taxi_eth_mac_10g_fifo.sv b/src/eth/rtl/taxi_eth_mac_10g_fifo.sv index 9a17a59..4c23cf6 100644 --- a/src/eth/rtl/taxi_eth_mac_10g_fifo.sv +++ b/src/eth/rtl/taxi_eth_mac_10g_fifo.sv @@ -26,8 +26,10 @@ module taxi_eth_mac_10g_fifo # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic STAT_EN = 1'b0, parameter STAT_TX_LEVEL = 1, parameter STAT_RX_LEVEL = 1, @@ -56,7 +58,6 @@ module taxi_eth_mac_10g_fifo # input wire logic tx_rst, input wire logic logic_clk, input wire logic logic_rst, - input wire logic ptp_sample_clk, /* * AXI4-Stream input (sink) @@ -85,8 +86,18 @@ module taxi_eth_mac_10g_fifo # /* * PTP clock */ - input wire logic [PTP_TS_W-1:0] ptp_ts = '0, - input wire logic ptp_ts_step = 1'b0, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] ptp_ts_in = '0, + input wire logic ptp_ts_step_in = 1'b0, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out, + output wire logic tx_ptp_ts_step_out, + output wire logic tx_ptp_locked, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out, + output wire logic rx_ptp_ts_step_out, + output wire logic rx_ptp_locked, /* * Statistics @@ -127,12 +138,6 @@ taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(TX_USER_W) taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) axis_tx_cpl_int(); taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(RX_USER_W)) axis_rx_int(); -wire [PTP_TS_W-1:0] tx_ptp_ts; -wire [PTP_TS_W-1:0] rx_ptp_ts; - -wire tx_ptp_locked; -wire rx_ptp_locked; - // synchronize MAC status signals into logic clock domain wire tx_error_underflow_int; @@ -195,7 +200,14 @@ always_ff @(posedge logic_clk or posedge logic_rst) begin end // PTP timestamping -if (PTP_TS_EN) begin : ptp +wire [PTP_TS_W-1:0] tx_ptp_ts_int; +wire tx_ptp_ts_step_int; +wire tx_ptp_locked_int; +wire [PTP_TS_W-1:0] rx_ptp_ts_int; +wire rx_ptp_ts_step_int; +wire rx_ptp_locked_int; + +if (PTP_TS_EN && !PTP_TD_EN) begin : ptp taxi_ptp_clock_cdc #( .TS_W(PTP_TS_W), @@ -207,10 +219,10 @@ if (PTP_TS_EN) begin : ptp .output_clk(tx_clk), .output_rst(tx_rst), .sample_clk(ptp_sample_clk), - .input_ts(ptp_ts), - .input_ts_step(ptp_ts_step), - .output_ts(tx_ptp_ts), - .output_ts_step(), + .input_ts(ptp_ts_in), + .input_ts_step(ptp_ts_step_in), + .output_ts(tx_ptp_ts_int), + .output_ts_step(tx_ptp_ts_step_out), .output_pps(), .output_pps_str(), .locked(tx_ptp_locked) @@ -226,10 +238,10 @@ if (PTP_TS_EN) begin : ptp .output_clk(rx_clk), .output_rst(rx_rst), .sample_clk(ptp_sample_clk), - .input_ts(ptp_ts), - .input_ts_step(ptp_ts_step), - .output_ts(rx_ptp_ts), - .output_ts_step(), + .input_ts(ptp_ts_in), + .input_ts_step(ptp_ts_step_in), + .output_ts(rx_ptp_ts_int), + .output_ts_step(rx_ptp_ts_step_out), .output_pps(), .output_pps_str(), .locked(rx_ptp_locked) @@ -237,11 +249,13 @@ if (PTP_TS_EN) begin : ptp end else begin - assign tx_ptp_ts = '0; - assign rx_ptp_ts = '0; + assign tx_ptp_ts_int = '0; + assign tx_ptp_ts_step_out = tx_ptp_ts_step_int; + assign rx_ptp_ts_int = '0; + assign rx_ptp_ts_step_out = rx_ptp_ts_step_int; - assign tx_ptp_locked = 1'b0; - assign rx_ptp_locked = 1'b0; + assign tx_ptp_locked = tx_ptp_locked_int; + assign rx_ptp_locked = rx_ptp_locked_int; end @@ -257,8 +271,10 @@ taxi_eth_mac_10g #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .PFC_EN(1'b0), .PAUSE_EN(1'b0), .STAT_EN(STAT_EN), @@ -302,8 +318,18 @@ eth_mac_10g_inst ( /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_int), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_int), + .tx_ptp_locked(tx_ptp_locked_int), + .rx_ptp_ts_in(rx_ptp_ts_int), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_int), + .rx_ptp_locked(rx_ptp_locked_int), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/rtl/taxi_eth_mac_phy_10g.f b/src/eth/rtl/taxi_eth_mac_phy_10g.f index ff0beab..90baa47 100644 --- a/src/eth/rtl/taxi_eth_mac_phy_10g.f +++ b/src/eth/rtl/taxi_eth_mac_phy_10g.f @@ -8,4 +8,5 @@ taxi_mac_pause_ctrl_tx.sv taxi_mac_pause_ctrl_rx.sv ../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv ../lib/taxi/src/axis/rtl/taxi_axis_tie.sv +../lib/taxi/src/ptp/rtl/taxi_ptp_td_leaf.sv ../lib/taxi/src/sync/rtl/taxi_sync_signal.sv diff --git a/src/eth/rtl/taxi_eth_mac_phy_10g.sv b/src/eth/rtl/taxi_eth_mac_phy_10g.sv index a2bc207..010a122 100644 --- a/src/eth/rtl/taxi_eth_mac_phy_10g.sv +++ b/src/eth/rtl/taxi_eth_mac_phy_10g.sv @@ -25,8 +25,10 @@ module taxi_eth_mac_phy_10g # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic BIT_REVERSE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic PRBS31_EN = 1'b0, @@ -82,8 +84,18 @@ module taxi_eth_mac_phy_10g # /* * PTP */ - input wire logic [PTP_TS_W-1:0] tx_ptp_ts, - input wire logic [PTP_TS_W-1:0] rx_ptp_ts, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] tx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out, + output wire logic tx_ptp_ts_step_out, + output wire logic tx_ptp_locked, + input wire logic [PTP_TS_W-1:0] rx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out, + output wire logic rx_ptp_ts_step_out, + output wire logic rx_ptp_locked, /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) @@ -226,6 +238,123 @@ localparam TX_USER_W_INT = (MAC_CTRL_EN ? 1 : 0) + TX_USER_W; taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(TX_USER_W_INT), .ID_EN(1), .ID_W(TX_TAG_W)) axis_tx_int(); taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(RX_USER_W)) axis_rx_int(); +// PTP timestamping +if (PTP_TS_EN && PTP_TD_EN) begin : ptp + + // TX + wire [PTP_TS_W-1:0] tx_ptp_ts_rel; + wire tx_ptp_ts_rel_step; + wire [PTP_TS_W-1:0] tx_ptp_ts_tod; + wire tx_ptp_ts_tod_step; + + taxi_ptp_td_leaf #( + .TS_REL_EN(!PTP_TS_FMT_TOD), + .TS_TOD_EN(PTP_TS_FMT_TOD), + .TS_FNS_W(16), + .TS_REL_NS_W(PTP_TS_FMT_TOD ? 48 : PTP_TS_W-16), + .TS_TOD_S_W(PTP_TS_FMT_TOD ? PTP_TS_W-32-16 : 48), + .TS_REL_W(PTP_TS_W), + .TS_TOD_W(PTP_TS_W), + .TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE) + ) + tx_leaf_inst ( + .clk(tx_clk), + .rst(tx_rst), + .sample_clk(ptp_sample_clk), + + /* + * PTP clock interface + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_td_sdi(ptp_td_sdi), + + /* + * Timestamp output + */ + .output_ts_rel(tx_ptp_ts_rel), + .output_ts_rel_step(tx_ptp_ts_rel_step), + .output_ts_tod(tx_ptp_ts_tod), + .output_ts_tod_step(tx_ptp_ts_tod_step), + + /* + * PPS output (ToD format only) + */ + .output_pps(), + .output_pps_str(), + + /* + * Status + */ + .locked(tx_ptp_locked) + ); + + assign tx_ptp_ts_out = PTP_TS_FMT_TOD ? tx_ptp_ts_tod : tx_ptp_ts_rel; + assign tx_ptp_ts_step_out = PTP_TS_FMT_TOD ? tx_ptp_ts_tod_step : tx_ptp_ts_rel_step; + + // RX + wire [PTP_TS_W-1:0] rx_ptp_ts_rel; + wire rx_ptp_ts_rel_step; + wire [PTP_TS_W-1:0] rx_ptp_ts_tod; + wire rx_ptp_ts_tod_step; + + taxi_ptp_td_leaf #( + .TS_REL_EN(!PTP_TS_FMT_TOD), + .TS_TOD_EN(PTP_TS_FMT_TOD), + .TS_FNS_W(16), + .TS_REL_NS_W(PTP_TS_FMT_TOD ? 48 : PTP_TS_W-16), + .TS_TOD_S_W(PTP_TS_FMT_TOD ? PTP_TS_W-32-16 : 48), + .TS_REL_W(PTP_TS_W), + .TS_TOD_W(PTP_TS_W), + .TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE) + ) + rx_leaf_inst ( + .clk(rx_clk), + .rst(rx_rst), + .sample_clk(ptp_sample_clk), + + /* + * PTP clock interface + */ + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_td_sdi(ptp_td_sdi), + + /* + * Timestamp output + */ + .output_ts_rel(rx_ptp_ts_rel), + .output_ts_rel_step(rx_ptp_ts_rel_step), + .output_ts_tod(rx_ptp_ts_tod), + .output_ts_tod_step(rx_ptp_ts_tod_step), + + /* + * PPS output (ToD format only) + */ + .output_pps(), + .output_pps_str(), + + /* + * Status + */ + .locked(rx_ptp_locked) + ); + + assign rx_ptp_ts_out = PTP_TS_FMT_TOD ? rx_ptp_ts_tod : rx_ptp_ts_rel; + assign rx_ptp_ts_step_out = PTP_TS_FMT_TOD ? rx_ptp_ts_tod_step : rx_ptp_ts_rel_step; + +end else begin + + assign tx_ptp_ts_out = tx_ptp_ts_in; + assign tx_ptp_ts_step_out = 1'b0; + assign rx_ptp_ts_out = rx_ptp_ts_in; + assign rx_ptp_ts_step_out = 1'b0; + + assign tx_ptp_locked = 1'b0; + assign rx_ptp_locked = 1'b0; + +end + taxi_eth_mac_phy_10g_rx #( .DATA_W(DATA_W), .HDR_W(HDR_W), @@ -263,7 +392,7 @@ eth_mac_phy_10g_rx_inst ( /* * PTP */ - .ptp_ts(rx_ptp_ts), + .ptp_ts(rx_ptp_ts_out), /* * Status @@ -337,7 +466,7 @@ eth_mac_phy_10g_tx_inst ( /* * PTP */ - .ptp_ts(tx_ptp_ts), + .ptp_ts(tx_ptp_ts_out), /* * Status diff --git a/src/eth/rtl/taxi_eth_mac_phy_10g_fifo.sv b/src/eth/rtl/taxi_eth_mac_phy_10g_fifo.sv index d4624ec..c5f5757 100644 --- a/src/eth/rtl/taxi_eth_mac_phy_10g_fifo.sv +++ b/src/eth/rtl/taxi_eth_mac_phy_10g_fifo.sv @@ -25,8 +25,10 @@ module taxi_eth_mac_phy_10g_fifo # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic BIT_REVERSE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic PRBS31_EN = 1'b0, @@ -63,7 +65,6 @@ module taxi_eth_mac_phy_10g_fifo # input wire logic tx_rst, input wire logic logic_clk, input wire logic logic_rst, - input wire logic ptp_sample_clk, /* * Transmit interface (AXI stream) @@ -96,8 +97,18 @@ module taxi_eth_mac_phy_10g_fifo # /* * PTP clock */ - input wire logic [PTP_TS_W-1:0] ptp_ts = '0, - input wire logic ptp_ts_step = 1'b0, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] ptp_ts_in = '0, + input wire logic ptp_ts_step_in = 1'b0, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out, + output wire logic tx_ptp_ts_step_out, + output wire logic tx_ptp_locked, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out, + output wire logic rx_ptp_ts_step_out, + output wire logic rx_ptp_locked, /* * Statistics @@ -145,12 +156,6 @@ taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(TX_USER_W) taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) axis_tx_cpl_int(); taxi_axis_if #(.DATA_W(DATA_W), .KEEP_W(KEEP_W), .USER_EN(1), .USER_W(RX_USER_W)) axis_rx_int(); -wire [PTP_TS_W-1:0] tx_ptp_ts; -wire [PTP_TS_W-1:0] rx_ptp_ts; - -wire tx_ptp_locked; -wire rx_ptp_locked; - // synchronize MAC status signals into logic clock domain wire tx_error_underflow_int; @@ -229,8 +234,15 @@ always_ff @(posedge logic_clk or posedge logic_rst) begin end // PTP timestamping -if (PTP_TS_EN) begin : ptp - +wire [PTP_TS_W-1:0] tx_ptp_ts_int; +wire tx_ptp_ts_step_int; +wire tx_ptp_locked_int; +wire [PTP_TS_W-1:0] rx_ptp_ts_int; +wire rx_ptp_ts_step_int; +wire rx_ptp_locked_int; + +if (PTP_TS_EN && !PTP_TD_EN) begin : ptp + taxi_ptp_clock_cdc #( .TS_W(PTP_TS_W), .NS_W(6) @@ -241,10 +253,10 @@ if (PTP_TS_EN) begin : ptp .output_clk(tx_clk), .output_rst(tx_rst), .sample_clk(ptp_sample_clk), - .input_ts(ptp_ts), - .input_ts_step(ptp_ts_step), - .output_ts(tx_ptp_ts), - .output_ts_step(), + .input_ts(ptp_ts_in), + .input_ts_step(ptp_ts_step_in), + .output_ts(tx_ptp_ts_int), + .output_ts_step(tx_ptp_ts_step_out), .output_pps(), .output_pps_str(), .locked(tx_ptp_locked) @@ -260,10 +272,10 @@ if (PTP_TS_EN) begin : ptp .output_clk(rx_clk), .output_rst(rx_rst), .sample_clk(ptp_sample_clk), - .input_ts(ptp_ts), - .input_ts_step(ptp_ts_step), - .output_ts(rx_ptp_ts), - .output_ts_step(), + .input_ts(ptp_ts_in), + .input_ts_step(ptp_ts_step_in), + .output_ts(rx_ptp_ts_int), + .output_ts_step(rx_ptp_ts_step_out), .output_pps(), .output_pps_str(), .locked(rx_ptp_locked) @@ -271,11 +283,13 @@ if (PTP_TS_EN) begin : ptp end else begin - assign tx_ptp_ts = '0; - assign rx_ptp_ts = '0; + assign tx_ptp_ts_int = '0; + assign tx_ptp_ts_step_out = tx_ptp_ts_step_int; + assign rx_ptp_ts_int = '0; + assign rx_ptp_ts_step_out = rx_ptp_ts_step_int; - assign tx_ptp_locked = 1'b0; - assign rx_ptp_locked = 1'b0; + assign tx_ptp_locked = tx_ptp_locked_int; + assign rx_ptp_locked = rx_ptp_locked_int; end @@ -290,8 +304,10 @@ taxi_eth_mac_phy_10g #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .BIT_REVERSE(BIT_REVERSE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .PRBS31_EN(PRBS31_EN), @@ -345,8 +361,18 @@ eth_mac_phy_10g_inst ( /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_int), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_int), + .tx_ptp_locked(tx_ptp_locked_int), + .rx_ptp_ts_in(rx_ptp_ts_int), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_int), + .rx_ptp_locked(rx_ptp_locked_int), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/rtl/us/taxi_eth_mac_25g_us.sv b/src/eth/rtl/us/taxi_eth_mac_25g_us.sv index 5925336..689a329 100644 --- a/src/eth/rtl/us/taxi_eth_mac_25g_us.sv +++ b/src/eth/rtl/us/taxi_eth_mac_25g_us.sv @@ -58,8 +58,10 @@ module taxi_eth_mac_25g_us # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic PRBS31_EN = 1'b0, parameter TX_SERDES_PIPELINE = 1, parameter RX_SERDES_PIPELINE = 1, @@ -121,7 +123,6 @@ module taxi_eth_mac_25g_us # output wire logic tx_clk[CNT], input wire logic tx_rst_in[CNT] = '{CNT{1'b0}}, output wire logic tx_rst_out[CNT], - input wire logic ptp_sample_clk[CNT] = '{CNT{1'b0}}, /* * Transmit interface (AXI stream) @@ -137,10 +138,18 @@ module taxi_eth_mac_25g_us # /* * PTP clock */ - input wire logic [PTP_TS_W-1:0] tx_ptp_ts[CNT] = '{CNT{'0}}, - input wire logic tx_ptp_ts_step[CNT] = '{CNT{1'b0}}, - input wire logic [PTP_TS_W-1:0] rx_ptp_ts[CNT] = '{CNT{'0}}, - input wire logic rx_ptp_ts_step[CNT] = '{CNT{1'b0}}, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] tx_ptp_ts_in[CNT] = '{CNT{'0}}, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out[CNT], + output wire logic tx_ptp_ts_step_out[CNT], + output wire logic tx_ptp_locked[CNT], + input wire logic [PTP_TS_W-1:0] rx_ptp_ts_in[CNT] = '{CNT{'0}}, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out[CNT], + output wire logic rx_ptp_ts_step_out[CNT], + output wire logic rx_ptp_locked[CNT], /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) @@ -420,8 +429,10 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .PRBS31_EN(PRBS31_EN), .TX_SERDES_PIPELINE(TX_SERDES_PIPELINE), .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), @@ -497,7 +508,6 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch .tx_clk(tx_clk[n]), .tx_rst_in(tx_rst_in[n]), .tx_rst_out(tx_rst_out[n]), - .ptp_sample_clk(ptp_sample_clk[n]), /* * Transmit interface (AXI stream) @@ -513,10 +523,18 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch /* * PTP clock */ - .tx_ptp_ts(tx_ptp_ts[n]), - .tx_ptp_ts_step(tx_ptp_ts_step[n]), - .rx_ptp_ts(rx_ptp_ts[n]), - .rx_ptp_ts_step(rx_ptp_ts_step[n]), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in[n]), + .tx_ptp_ts_out(tx_ptp_ts_out[n]), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out[n]), + .tx_ptp_locked(tx_ptp_locked[n]), + .rx_ptp_ts_in(rx_ptp_ts_in[n]), + .rx_ptp_ts_out(rx_ptp_ts_out[n]), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out[n]), + .rx_ptp_locked(rx_ptp_locked[n]), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/rtl/us/taxi_eth_mac_25g_us_ch.sv b/src/eth/rtl/us/taxi_eth_mac_25g_us_ch.sv index c20933a..db399c1 100644 --- a/src/eth/rtl/us/taxi_eth_mac_25g_us_ch.sv +++ b/src/eth/rtl/us/taxi_eth_mac_25g_us_ch.sv @@ -57,8 +57,10 @@ module taxi_eth_mac_25g_us_ch # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter logic PRBS31_EN = 1'b0, parameter TX_SERDES_PIPELINE = 1, parameter RX_SERDES_PIPELINE = 1, @@ -134,7 +136,6 @@ module taxi_eth_mac_25g_us_ch # output wire logic tx_clk, input wire logic tx_rst_in = 1'b0, output wire logic tx_rst_out, - input wire logic ptp_sample_clk = 1'b0, /* * Transmit interface (AXI stream) @@ -150,10 +151,18 @@ module taxi_eth_mac_25g_us_ch # /* * PTP clock */ - input wire logic [PTP_TS_W-1:0] tx_ptp_ts = '0, - input wire logic tx_ptp_ts_step = 1'b0, - input wire logic [PTP_TS_W-1:0] rx_ptp_ts = '0, - input wire logic rx_ptp_ts_step = 1'b0, + input wire logic ptp_clk = 1'b0, + input wire logic ptp_rst = 1'b0, + input wire logic ptp_sample_clk = 1'b0, + input wire logic ptp_td_sdi = 1'b0, + input wire logic [PTP_TS_W-1:0] tx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] tx_ptp_ts_out, + output wire logic tx_ptp_ts_step_out, + output wire logic tx_ptp_locked, + input wire logic [PTP_TS_W-1:0] rx_ptp_ts_in = '0, + output wire logic [PTP_TS_W-1:0] rx_ptp_ts_out, + output wire logic rx_ptp_ts_step_out, + output wire logic rx_ptp_locked, /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) @@ -878,8 +887,10 @@ if (COMBINED_MAC_PCS) begin : mac .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .BIT_REVERSE(1'b1), .SCRAMBLER_DISABLE(1'b0), .PRBS31_EN(PRBS31_EN), @@ -935,8 +946,18 @@ if (COMBINED_MAC_PCS) begin : mac /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_in(rx_ptp_ts_in), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) @@ -1160,8 +1181,10 @@ end else begin : mac .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .PFC_EN(PFC_EN), .PAUSE_EN(PAUSE_EN), .STAT_EN(STAT_EN), @@ -1205,8 +1228,18 @@ end else begin : mac /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_in(rx_ptp_ts_in), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/tb/taxi_eth_mac_10g/Makefile b/src/eth/tb/taxi_eth_mac_10g/Makefile index d76c3ab..3fcd19a 100644 --- a/src/eth/tb/taxi_eth_mac_10g/Makefile +++ b/src/eth/tb/taxi_eth_mac_10g/Makefile @@ -40,8 +40,10 @@ export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_PTP_TS_EN := 1 +export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN) export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) +export PARAM_PTP_TD_SDI_PIPELINE := 2 export PARAM_TX_TAG_W := 16 export PARAM_PFC_EN := 1 export PARAM_PAUSE_EN := $(PARAM_PFC_EN) diff --git a/src/eth/tb/taxi_eth_mac_10g/ptp_td.py b/src/eth/tb/taxi_eth_mac_10g/ptp_td.py new file mode 120000 index 0000000..d08acc1 --- /dev/null +++ b/src/eth/tb/taxi_eth_mac_10g/ptp_td.py @@ -0,0 +1 @@ +../../lib/taxi/src/ptp/tb/ptp_td.py \ No newline at end of file diff --git a/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py b/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py index 3f90c3a..f09b4d2 100644 --- a/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py +++ b/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py @@ -13,6 +13,7 @@ import itertools import logging import os import struct +import sys from scapy.layers.l2 import Ether @@ -28,6 +29,16 @@ from cocotb.regression import TestFactory from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamFrame +try: + from ptp_td import PtpTdSource +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from ptp_td import PtpTdSource + finally: + del sys.path[0] + class TB: def __init__(self, dut): @@ -54,8 +65,20 @@ class TB: self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) - self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk) - self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk) + self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts_in, clock=dut.rx_clk) + self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts_in, clock=dut.tx_clk) + + self.ptp_clk_period = self.clk_period + + cocotb.start_soon(Clock(dut.ptp_clk, self.ptp_clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start()) + + self.ptp_td_source = PtpTdSource( + data=dut.ptp_td_sdi, + clock=dut.ptp_clk, + reset=dut.ptp_rst, + period_ns=self.ptp_clk_period + ) dut.tx_lfc_req.setimmediatevalue(0) dut.tx_lfc_resend.setimmediatevalue(0) @@ -112,20 +135,26 @@ class TB: async def reset(self): self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.ptp_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.ptp_rst.value = 1 self.dut.stat_rst.value = 1 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.ptp_rst.value = 0 self.dut.stat_rst.value = 0 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) + self.ptp_td_source.set_ts_tod_sim_time() + self.ptp_td_source.set_ts_rel_sim_time() + async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): @@ -138,6 +167,13 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): await tb.reset() + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.rx_ptp_locked.value): + await RisingEdge(dut.rx_clk) + for k in range(2000): + await RisingEdge(dut.rx_clk) + test_frames = [payload_data(x) for x in payload_lengths()] tx_frames = [] @@ -165,7 +201,10 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.tdata == test_data assert frame_error == 0 - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*5 + else: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < 0.01 assert tb.axis_sink.empty() @@ -184,6 +223,13 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): await tb.reset() + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked.value): + await RisingEdge(dut.tx_clk) + for k in range(2000): + await RisingEdge(dut.tx_clk) + test_frames = [payload_data(x) for x in payload_lengths()] for test_data in test_frames: @@ -208,7 +254,10 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01 assert tb.xgmii_sink.empty() @@ -231,6 +280,13 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): await tb.reset() + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked.value): + await RisingEdge(dut.tx_clk) + for k in range(2000): + await RisingEdge(dut.tx_clk) + for length in range(60, 92): for k in range(10): @@ -261,7 +317,10 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01 start_lane.append(rx_frame.start_lane) @@ -731,8 +790,9 @@ def process_f_files(files): @pytest.mark.parametrize(("dic_en", "pfc_en"), [(1, 1), (1, 0), (0, 0)]) +@pytest.mark.parametrize("ptp_td_en", [1, 0]) @pytest.mark.parametrize("data_w", [32, 64]) -def test_taxi_eth_mac_10g(request, data_w, dic_en, pfc_en): +def test_taxi_eth_mac_10g(request, data_w, ptp_td_en, dic_en, pfc_en): dut = "taxi_eth_mac_10g" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = module @@ -754,8 +814,10 @@ def test_taxi_eth_mac_10g(request, data_w, dic_en, pfc_en): parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 parameters['PTP_TS_EN'] = 1 + parameters['PTP_TD_EN'] = ptp_td_en parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 + parameters['PTP_TD_SDI_PIPELINE'] = 2 parameters['TX_TAG_W'] = 16 parameters['PFC_EN'] = pfc_en parameters['PAUSE_EN'] = parameters['PFC_EN'] diff --git a/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv b/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv index 895d343..2872b6f 100644 --- a/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv +++ b/src/eth/tb/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv @@ -26,8 +26,10 @@ module test_taxi_eth_mac_10g # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter TX_TAG_W = 16, parameter logic PFC_EN = 1'b0, parameter logic PAUSE_EN = PFC_EN, @@ -65,8 +67,18 @@ logic [GBX_CNT-1:0] tx_gbx_req_sync; logic tx_gbx_req_stall; logic [GBX_CNT-1:0] tx_gbx_sync; -logic [PTP_TS_W-1:0] tx_ptp_ts; -logic [PTP_TS_W-1:0] rx_ptp_ts; +logic ptp_clk; +logic ptp_rst; +logic ptp_sample_clk; +logic ptp_td_sdi; +logic [PTP_TS_W-1:0] tx_ptp_ts_in; +logic [PTP_TS_W-1:0] tx_ptp_ts_out; +logic tx_ptp_ts_step_out; +logic tx_ptp_locked; +logic [PTP_TS_W-1:0] rx_ptp_ts_in; +logic [PTP_TS_W-1:0] rx_ptp_ts_out; +logic rx_ptp_ts_step_out; +logic rx_ptp_locked; logic tx_lfc_req; logic tx_lfc_resend; @@ -183,8 +195,10 @@ taxi_eth_mac_10g #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .PFC_EN(PFC_EN), .PAUSE_EN(PAUSE_EN), .STAT_EN(STAT_EN), @@ -228,8 +242,18 @@ uut ( /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_in(rx_ptp_ts_in), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/tb/taxi_eth_mac_10g_fifo/Makefile b/src/eth/tb/taxi_eth_mac_10g_fifo/Makefile index 71f075c..5b13bc4 100644 --- a/src/eth/tb/taxi_eth_mac_10g_fifo/Makefile +++ b/src/eth/tb/taxi_eth_mac_10g_fifo/Makefile @@ -41,8 +41,10 @@ export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_PTP_TS_EN := 1 +export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN) export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) +export PARAM_PTP_TD_SDI_PIPELINE := 2 export PARAM_TX_TAG_W := 16 export PARAM_STAT_EN := 1 export PARAM_STAT_TX_LEVEL := 2 diff --git a/src/eth/tb/taxi_eth_mac_10g_fifo/ptp_td.py b/src/eth/tb/taxi_eth_mac_10g_fifo/ptp_td.py new file mode 120000 index 0000000..d08acc1 --- /dev/null +++ b/src/eth/tb/taxi_eth_mac_10g_fifo/ptp_td.py @@ -0,0 +1 @@ +../../lib/taxi/src/ptp/tb/ptp_td.py \ No newline at end of file diff --git a/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py b/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py index fba87c0..69bab6e 100644 --- a/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py +++ b/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py @@ -12,6 +12,7 @@ Authors: import itertools import logging import os +import sys import pytest import cocotb_test.simulator @@ -25,6 +26,16 @@ from cocotb.regression import TestFactory from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamFrame +try: + from ptp_td import PtpTdSource +except ImportError: + # attempt import from current directory + sys.path.insert(0, os.path.join(os.path.dirname(__file__))) + try: + from ptp_td import PtpTdSource + finally: + del sys.path[0] + class TB: def __init__(self, dut): @@ -42,7 +53,6 @@ class TB: cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.stat_clk, self.clk_period, units="ns").start()) - cocotb.start_soon(Clock(dut.ptp_sample_clk, 9.9, units="ns").start()) self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) @@ -53,9 +63,20 @@ class TB: self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) - self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.logic_clk) + self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts_in, clock=dut.logic_clk) + dut.ptp_ts_step_in.setimmediatevalue(0) - dut.ptp_ts_step.setimmediatevalue(0) + self.ptp_clk_period = self.clk_period + + cocotb.start_soon(Clock(dut.ptp_clk, self.ptp_clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start()) + + self.ptp_td_source = PtpTdSource( + data=dut.ptp_td_sdi, + clock=dut.ptp_clk, + reset=dut.ptp_rst, + period_ns=self.ptp_clk_period + ) dut.cfg_tx_max_pkt_len.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0) @@ -67,22 +88,28 @@ class TB: self.dut.logic_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.ptp_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 1 self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.ptp_rst.value = 1 self.dut.stat_rst.value = 1 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 0 self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.ptp_rst.value = 0 self.dut.stat_rst.value = 0 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) + self.ptp_td_source.set_ts_tod_sim_time() + self.ptp_td_source.set_ts_rel_sim_time() + async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): @@ -96,9 +123,9 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.rx_ptp_locked.value): + while not int(dut.rx_ptp_locked.value): await RisingEdge(dut.rx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.rx_clk) test_frames = [payload_data(x) for x in payload_lengths()] @@ -128,7 +155,10 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.tdata == test_data assert frame_error == 0 - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*4 + else: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*2 assert tb.axis_sink.empty() @@ -148,9 +178,9 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.tx_ptp_locked.value): + while not int(dut.tx_ptp_locked.value): await RisingEdge(dut.tx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.tx_clk) test_frames = [payload_data(x) for x in payload_lengths()] @@ -177,7 +207,10 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*4 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 assert tb.xgmii_sink.empty() @@ -201,9 +234,9 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.tx_ptp_locked.value): + while not int(dut.tx_ptp_locked.value): await RisingEdge(dut.tx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.tx_clk) for length in range(60, 92): @@ -236,7 +269,10 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): assert rx_frame.get_payload() == test_data assert rx_frame.check_fcs() assert rx_frame.ctrl is None - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*4 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2 start_lane.append(rx_frame.start_lane) @@ -354,8 +390,10 @@ def test_taxi_eth_mac_10g_fifo(request, data_w, dic_en): parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 parameters['PTP_TS_EN'] = 1 + parameters['PTP_TD_EN'] = parameters['PTP_TS_EN'] parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 + parameters['PTP_TD_SDI_PIPELINE'] = 2 parameters['TX_TAG_W'] = 16 parameters['STAT_EN'] = 1 parameters['STAT_TX_LEVEL'] = 2 diff --git a/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv b/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv index 7f37fbe..245bdc1 100644 --- a/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv +++ b/src/eth/tb/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv @@ -27,8 +27,10 @@ module test_taxi_eth_mac_10g_fifo # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter TX_TAG_W = 16, parameter logic STAT_EN = 1'b0, parameter STAT_TX_LEVEL = 1, @@ -64,7 +66,6 @@ logic tx_clk; logic tx_rst; logic logic_clk; logic logic_rst; -logic ptp_sample_clk; taxi_axis_if #(.DATA_W(AXIS_DATA_W), .USER_EN(1), .USER_W(TX_USER_W), .ID_EN(1), .ID_W(TX_TAG_W)) s_axis_tx(); taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) m_axis_tx_cpl(); @@ -80,8 +81,18 @@ logic [GBX_CNT-1:0] tx_gbx_req_sync; logic tx_gbx_req_stall; logic [GBX_CNT-1:0] tx_gbx_sync; -logic [PTP_TS_W-1:0] ptp_ts; -logic ptp_ts_step; +logic ptp_clk; +logic ptp_rst; +logic ptp_sample_clk; +logic ptp_td_sdi; +logic [PTP_TS_W-1:0] ptp_ts_in; +logic ptp_ts_step_in; +logic [PTP_TS_W-1:0] tx_ptp_ts_out; +logic tx_ptp_ts_step_out; +logic tx_ptp_locked; +logic [PTP_TS_W-1:0] rx_ptp_ts_out; +logic rx_ptp_ts_step_out; +logic rx_ptp_locked; logic stat_clk; logic stat_rst; @@ -113,8 +124,10 @@ taxi_eth_mac_10g_fifo #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .STAT_EN(STAT_EN), .STAT_TX_LEVEL(STAT_TX_LEVEL), .STAT_RX_LEVEL(STAT_RX_LEVEL), @@ -143,7 +156,6 @@ uut ( .tx_rst(tx_rst), .logic_clk(logic_clk), .logic_rst(logic_rst), - .ptp_sample_clk(ptp_sample_clk), /* * Transmit interface (AXI stream) @@ -172,8 +184,18 @@ uut ( /* * PTP clock */ - .ptp_ts(ptp_ts), - .ptp_ts_step(ptp_ts_step), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .ptp_ts_in(ptp_ts_in), + .ptp_ts_step_in(ptp_ts_step_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Statistics diff --git a/src/eth/tb/taxi_eth_mac_25g_us/Makefile b/src/eth/tb/taxi_eth_mac_25g_us/Makefile index c00500b..a5af889 100644 --- a/src/eth/tb/taxi_eth_mac_25g_us/Makefile +++ b/src/eth/tb/taxi_eth_mac_25g_us/Makefile @@ -48,8 +48,10 @@ export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_PTP_TS_EN := 1 +export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN) export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) +export PARAM_PTP_TD_SDI_PIPELINE := 2 export PARAM_TX_TAG_W := 16 export PARAM_PRBS31_EN := 1 export PARAM_TX_SERDES_PIPELINE := 2 diff --git a/src/eth/tb/taxi_eth_mac_25g_us/ptp_td.py b/src/eth/tb/taxi_eth_mac_25g_us/ptp_td.py new file mode 120000 index 0000000..d08acc1 --- /dev/null +++ b/src/eth/tb/taxi_eth_mac_25g_us/ptp_td.py @@ -0,0 +1 @@ +../../lib/taxi/src/ptp/tb/ptp_td.py \ No newline at end of file diff --git a/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.py b/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.py index 90d3314..45049b2 100644 --- a/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.py +++ b/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.py @@ -32,11 +32,13 @@ from cocotbext.axi import ApbBus, ApbMaster try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource finally: del sys.path[0] @@ -118,8 +120,20 @@ class TB: self.tx_ptp_clocks = [] for k in range(4): - self.rx_ptp_clocks.append(PtpClockSimTime(ts_tod=dut.rx_ptp_ts[k], clock=dut.uut.ch[k].ch_inst.gt.gt_inst.rx_clk)) - self.tx_ptp_clocks.append(PtpClockSimTime(ts_tod=dut.tx_ptp_ts[k], clock=dut.uut.ch[k].ch_inst.gt.gt_inst.tx_clk)) + self.rx_ptp_clocks.append(PtpClockSimTime(ts_tod=dut.rx_ptp_ts_in[k], clock=dut.uut.ch[k].ch_inst.gt.gt_inst.rx_clk)) + self.tx_ptp_clocks.append(PtpClockSimTime(ts_tod=dut.tx_ptp_ts_in[k], clock=dut.uut.ch[k].ch_inst.gt.gt_inst.tx_clk)) + + self.ptp_clk_period = self.clk_period[0] + + cocotb.start_soon(Clock(dut.ptp_clk, self.ptp_clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start()) + + self.ptp_td_source = PtpTdSource( + data=dut.ptp_td_sdi, + clock=dut.ptp_clk, + reset=dut.ptp_rst, + period_ns=self.ptp_clk_period + ) dut.rx_rst_in.setimmediatevalue([0]*4) dut.tx_rst_in.setimmediatevalue([0]*4) @@ -169,18 +183,24 @@ class TB: async def reset(self): self.dut.xcvr_ctrl_rst.setimmediatevalue(0) + self.dut.ptp_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk) self.dut.xcvr_ctrl_rst.value = 1 + self.dut.ptp_rst.value = 1 self.dut.stat_rst.value = 1 await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk) self.dut.xcvr_ctrl_rst.value = 0 + self.dut.ptp_rst.value = 0 self.dut.stat_rst.value = 0 await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk) + self.ptp_td_source.set_ts_tod_sim_time() + self.ptp_td_source.set_ts_rel_sim_time() + async def run_test_regs(dut): tb = TB(dut) @@ -231,6 +251,12 @@ async def run_test_rx(dut, port=0, payload_lengths=None, payload_data=None, ifg= while not int(dut.rx_block_lock[port].value): await RisingEdge(dut.xcvr_ctrl_clk) + tb.log.info("Wait for PTP CDC lock") + while not int(dut.rx_ptp_locked[port].value): + await RisingEdge(dut.xcvr_ctrl_clk) + for k in range(2000): + await RisingEdge(dut.xcvr_ctrl_clk) + tb.dut.cfg_rx_enable[port].value = 1 test_frames = [payload_data(x) for x in payload_lengths()] @@ -267,7 +293,10 @@ async def run_test_rx(dut, port=0, payload_lengths=None, payload_data=None, ifg= assert rx_frame.tdata == test_data assert frame_error == 0 if not tb.serdes_sources[port].gbx_seq_len: - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period[port]*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period[port]*pipe_delay) < tb.clk_period[port]*3 + else: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period[port]*pipe_delay) < 0.01 assert tb.axis_sinks[port].empty() @@ -300,7 +329,10 @@ async def run_test_tx(dut, port=0, payload_lengths=None, payload_data=None, ifg= while int(dut.tx_rst_out[port].value): await RisingEdge(dut.xcvr_ctrl_clk) - for k in range(100): + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked[port].value): + await RisingEdge(dut.xcvr_ctrl_clk) + for k in range(2000): await RisingEdge(dut.xcvr_ctrl_clk) tb.dut.cfg_tx_enable[port].value = 1 @@ -337,7 +369,10 @@ async def run_test_tx(dut, port=0, payload_lengths=None, payload_data=None, ifg= assert rx_frame.check_fcs() assert rx_frame.ctrl is None if not tb.serdes_sinks[port].gbx_seq_len: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < tb.clk_period[port]*3 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01 assert tb.serdes_sinks[port].empty() @@ -374,7 +409,10 @@ async def run_test_tx_alignment(dut, port=0, payload_data=None, ifg=12): while int(dut.tx_rst_out[port].value): await RisingEdge(dut.xcvr_ctrl_clk) - for k in range(100): + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked[port].value): + await RisingEdge(dut.xcvr_ctrl_clk) + for k in range(2000): await RisingEdge(dut.xcvr_ctrl_clk) tb.dut.cfg_tx_enable[port].value = 1 @@ -416,7 +454,10 @@ async def run_test_tx_alignment(dut, port=0, payload_data=None, ifg=12): assert rx_frame.check_fcs() assert rx_frame.ctrl is None if not tb.serdes_sinks[port].gbx_seq_len: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < tb.clk_period[port]*3 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01 start_lane.append(rx_frame.start_lane) @@ -1024,8 +1065,10 @@ def test_taxi_eth_mac_25g_us(request, data_w, combined_mac_pcs, low_latency, dic parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 parameters['PTP_TS_EN'] = 1 + parameters['PTP_TD_EN'] = parameters['PTP_TS_EN'] parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 + parameters['PTP_TD_SDI_PIPELINE'] = 2 parameters['TX_TAG_W'] = 16 parameters['PRBS31_EN'] = 1 parameters['TX_SERDES_PIPELINE'] = 2 diff --git a/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.sv b/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.sv index 0a05e3d..e6e85b8 100644 --- a/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.sv +++ b/src/eth/tb/taxi_eth_mac_25g_us/test_taxi_eth_mac_25g_us.sv @@ -47,8 +47,10 @@ module test_taxi_eth_mac_25g_us # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter TX_TAG_W = 16, parameter logic PRBS31_EN = 1'b0, parameter TX_SERDES_PIPELINE = 1, @@ -108,16 +110,23 @@ logic rx_rst_out[CNT]; logic tx_clk[CNT]; logic tx_rst_in[CNT]; logic tx_rst_out[CNT]; -logic ptp_sample_clk[CNT]; taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(TX_USER_W), .ID_EN(1), .ID_W(TX_TAG_W)) s_axis_tx[CNT](); taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) m_axis_tx_cpl[CNT](); taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(RX_USER_W)) m_axis_rx[CNT](); -logic [PTP_TS_W-1:0] tx_ptp_ts[CNT]; -logic tx_ptp_ts_step[CNT]; -logic [PTP_TS_W-1:0] rx_ptp_ts[CNT]; -logic rx_ptp_ts_step[CNT]; +logic ptp_clk; +logic ptp_rst; +logic ptp_sample_clk; +logic ptp_td_sdi; +logic [PTP_TS_W-1:0] tx_ptp_ts_in[CNT]; +logic [PTP_TS_W-1:0] tx_ptp_ts_out[CNT]; +logic tx_ptp_ts_step_out[CNT]; +logic tx_ptp_locked[CNT]; +logic [PTP_TS_W-1:0] rx_ptp_ts_in[CNT]; +logic [PTP_TS_W-1:0] rx_ptp_ts_out[CNT]; +logic rx_ptp_ts_step_out[CNT]; +logic rx_ptp_locked[CNT]; logic tx_lfc_req[CNT]; logic tx_lfc_resend[CNT]; @@ -260,8 +269,10 @@ taxi_eth_mac_25g_us #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .PRBS31_EN(PRBS31_EN), .TX_SERDES_PIPELINE(TX_SERDES_PIPELINE), .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), @@ -323,7 +334,6 @@ uut ( .tx_clk(tx_clk), .tx_rst_in(tx_rst_in), .tx_rst_out(tx_rst_out), - .ptp_sample_clk(ptp_sample_clk), /* * Transmit interface (AXI stream) @@ -339,10 +349,18 @@ uut ( /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .tx_ptp_ts_step(tx_ptp_ts_step), - .rx_ptp_ts(rx_ptp_ts), - .rx_ptp_ts_step(rx_ptp_ts_step), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_in(rx_ptp_ts_in), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/tb/taxi_eth_mac_phy_10g/Makefile b/src/eth/tb/taxi_eth_mac_phy_10g/Makefile index 495dd63..191a55f 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g/Makefile +++ b/src/eth/tb/taxi_eth_mac_phy_10g/Makefile @@ -40,8 +40,10 @@ export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_PTP_TS_EN := 1 +export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN) export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) +export PARAM_PTP_TD_SDI_PIPELINE := 2 export PARAM_TX_TAG_W := 16 export PARAM_BIT_REVERSE := 0 export PARAM_SCRAMBLER_DISABLE := 0 diff --git a/src/eth/tb/taxi_eth_mac_phy_10g/ptp_td.py b/src/eth/tb/taxi_eth_mac_phy_10g/ptp_td.py new file mode 120000 index 0000000..d08acc1 --- /dev/null +++ b/src/eth/tb/taxi_eth_mac_phy_10g/ptp_td.py @@ -0,0 +1 @@ +../../lib/taxi/src/ptp/tb/ptp_td.py \ No newline at end of file diff --git a/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py b/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py index c7a4c9e..dad8f53 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py +++ b/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py @@ -31,11 +31,13 @@ from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStrea try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource finally: del sys.path[0] @@ -89,8 +91,20 @@ class TB: self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) - self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk) - self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk) + self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts_in, clock=dut.rx_clk) + self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts_in, clock=dut.tx_clk) + + self.ptp_clk_period = self.clk_period + + cocotb.start_soon(Clock(dut.ptp_clk, self.ptp_clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start()) + + self.ptp_td_source = PtpTdSource( + data=dut.ptp_td_sdi, + clock=dut.ptp_clk, + reset=dut.ptp_rst, + period_ns=self.ptp_clk_period + ) dut.stat_rx_fifo_drop.setimmediatevalue(0) @@ -136,20 +150,26 @@ class TB: async def reset(self): self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.ptp_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.ptp_rst.value = 1 self.dut.stat_rst.value = 1 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.ptp_rst.value = 0 self.dut.stat_rst.value = 0 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) + self.ptp_td_source.set_ts_tod_sim_time() + self.ptp_td_source.set_ts_rel_sim_time() + async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, ifg=12): @@ -172,6 +192,13 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None while not int(dut.rx_block_lock.value): await RisingEdge(dut.rx_clk) + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.rx_ptp_locked.value): + await RisingEdge(dut.rx_clk) + for k in range(2000): + await RisingEdge(dut.rx_clk) + tb.dut.cfg_rx_enable.value = 1 test_frames = [payload_data(x) for x in payload_lengths()] @@ -208,7 +235,10 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None assert rx_frame.tdata == test_data assert frame_error == 0 if gbx_cfg is None: - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < 0.01 assert tb.axis_sink.empty() @@ -231,8 +261,15 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None await tb.reset() - for k in range(100): - await RisingEdge(dut.tx_clk) + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked.value): + await RisingEdge(dut.tx_clk) + for k in range(2000): + await RisingEdge(dut.tx_clk) + else: + for k in range(100): + await RisingEdge(dut.tx_clk) tb.dut.cfg_tx_enable.value = 1 tb.serdes_sink.clear() @@ -266,7 +303,10 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None assert rx_frame.check_fcs() assert rx_frame.ctrl is None if gbx_cfg is None: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01 assert tb.serdes_sink.empty() @@ -293,8 +333,15 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12): await tb.reset() - for k in range(100): - await RisingEdge(dut.tx_clk) + if dut.PTP_TD_EN.value: + tb.log.info("Wait for PTP CDC lock") + while not int(dut.tx_ptp_locked.value): + await RisingEdge(dut.tx_clk) + for k in range(2000): + await RisingEdge(dut.tx_clk) + else: + for k in range(100): + await RisingEdge(dut.tx_clk) tb.dut.cfg_tx_enable.value = 1 tb.serdes_sink.clear() @@ -333,7 +380,10 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12): assert rx_frame.check_fcs() assert rx_frame.ctrl is None if gbx_cfg is None: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01 start_lane.append(rx_frame.start_lane) @@ -885,8 +935,9 @@ def process_f_files(files): @pytest.mark.parametrize(("dic_en", "pfc_en"), [(1, 1), (1, 0), (0, 0)]) @pytest.mark.parametrize("gbx_en", [1, 0]) +@pytest.mark.parametrize("ptp_td_en", [1, 0]) @pytest.mark.parametrize("data_w", [32, 64]) -def test_taxi_eth_mac_phy_10g(request, data_w, gbx_en, dic_en, pfc_en): +def test_taxi_eth_mac_phy_10g(request, data_w, ptp_td_en, gbx_en, dic_en, pfc_en): dut = "taxi_eth_mac_phy_10g" module = os.path.splitext(os.path.basename(__file__))[0] toplevel = module @@ -908,8 +959,10 @@ def test_taxi_eth_mac_phy_10g(request, data_w, gbx_en, dic_en, pfc_en): parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 parameters['PTP_TS_EN'] = 1 + parameters['PTP_TD_EN'] = ptp_td_en parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 + parameters['PTP_TD_SDI_PIPELINE'] = 2 parameters['TX_TAG_W'] = 16 parameters['BIT_REVERSE'] = 0 parameters['SCRAMBLER_DISABLE'] = 0 diff --git a/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv b/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv index 42b8185..d8a141f 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv +++ b/src/eth/tb/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv @@ -26,8 +26,10 @@ module test_taxi_eth_mac_phy_10g # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter TX_TAG_W = 16, parameter logic BIT_REVERSE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0, @@ -76,8 +78,18 @@ logic serdes_rx_hdr_valid; logic serdes_rx_bitslip; logic serdes_rx_reset_req; -logic [PTP_TS_W-1:0] tx_ptp_ts; -logic [PTP_TS_W-1:0] rx_ptp_ts; +logic ptp_clk; +logic ptp_rst; +logic ptp_sample_clk; +logic ptp_td_sdi; +logic [PTP_TS_W-1:0] tx_ptp_ts_in; +logic [PTP_TS_W-1:0] tx_ptp_ts_out; +logic tx_ptp_ts_step_out; +logic tx_ptp_locked; +logic [PTP_TS_W-1:0] rx_ptp_ts_in; +logic [PTP_TS_W-1:0] rx_ptp_ts_out; +logic rx_ptp_ts_step_out; +logic rx_ptp_locked; logic tx_lfc_req; logic tx_lfc_resend; @@ -199,8 +211,10 @@ taxi_eth_mac_phy_10g #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .BIT_REVERSE(BIT_REVERSE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .PRBS31_EN(PRBS31_EN), @@ -256,8 +270,18 @@ uut ( /* * PTP */ - .tx_ptp_ts(tx_ptp_ts), - .rx_ptp_ts(rx_ptp_ts), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .tx_ptp_ts_in(tx_ptp_ts_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_in(rx_ptp_ts_in), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE) diff --git a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/Makefile b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/Makefile index 7d4c4f4..e0189c6 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/Makefile +++ b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/Makefile @@ -41,8 +41,10 @@ export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 export PARAM_PTP_TS_EN := 1 +export PARAM_PTP_TD_EN := $(PARAM_PTP_TS_EN) export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) +export PARAM_PTP_TD_SDI_PIPELINE := 2 export PARAM_TX_TAG_W := 16 export PARAM_BIT_REVERSE := 0 export PARAM_SCRAMBLER_DISABLE := 0 diff --git a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/ptp_td.py b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/ptp_td.py new file mode 120000 index 0000000..d08acc1 --- /dev/null +++ b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/ptp_td.py @@ -0,0 +1 @@ +../../lib/taxi/src/ptp/tb/ptp_td.py \ No newline at end of file diff --git a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py index 5a02a66..9f9754f 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py +++ b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py @@ -28,11 +28,13 @@ from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStrea try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource except ImportError: # attempt import from current directory sys.path.insert(0, os.path.join(os.path.dirname(__file__))) try: from baser import BaseRSerdesSource, BaseRSerdesSink + from ptp_td import PtpTdSource finally: del sys.path[0] @@ -59,7 +61,6 @@ class TB: cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.stat_clk, self.clk_period, units="ns").start()) - cocotb.start_soon(Clock(dut.ptp_sample_clk, 9.9, units="ns").start()) self.serdes_source = BaseRSerdesSource( data=dut.serdes_rx_data, @@ -88,9 +89,20 @@ class TB: self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) - self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.logic_clk) + self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts_in, clock=dut.logic_clk) + dut.ptp_ts_step_in.setimmediatevalue(0) - dut.ptp_ts_step.setimmediatevalue(0) + self.ptp_clk_period = self.clk_period + + cocotb.start_soon(Clock(dut.ptp_clk, self.ptp_clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.ptp_sample_clk, 8, units="ns").start()) + + self.ptp_td_source = PtpTdSource( + data=dut.ptp_td_sdi, + clock=dut.ptp_clk, + reset=dut.ptp_rst, + period_ns=self.ptp_clk_period + ) dut.cfg_tx_max_pkt_len.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0) @@ -104,22 +116,28 @@ class TB: self.dut.logic_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.ptp_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 1 self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.ptp_rst.value = 1 self.dut.stat_rst.value = 1 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 0 self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.ptp_rst.value = 0 self.dut.stat_rst.value = 0 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) + self.ptp_td_source.set_ts_tod_sim_time() + self.ptp_td_source.set_ts_rel_sim_time() + async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, ifg=12): @@ -142,9 +160,9 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None await RisingEdge(dut.rx_clk) tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.rx_ptp_locked.value): + while not int(dut.rx_ptp_locked.value): await RisingEdge(dut.rx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.rx_clk) # clear out sink buffer @@ -181,7 +199,10 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None assert rx_frame.tdata == test_data assert frame_error == 0 if gbx_cfg is None: - assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 assert tb.axis_sink.empty() @@ -205,9 +226,9 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.tx_ptp_locked.value): + while not int(dut.tx_ptp_locked.value): await RisingEdge(dut.tx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.tx_clk) tb.dut.cfg_tx_enable.value = 1 @@ -241,7 +262,10 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None assert rx_frame.check_fcs() assert rx_frame.ctrl is None if gbx_cfg is None: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 assert tb.serdes_sink.empty() @@ -269,9 +293,9 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12): await tb.reset() tb.log.info("Wait for PTP CDC lock") - while not int(dut.uut.tx_ptp_locked.value): + while not int(dut.tx_ptp_locked.value): await RisingEdge(dut.tx_clk) - for k in range(1000): + for k in range(2000): await RisingEdge(dut.tx_clk) tb.dut.cfg_tx_enable.value = 1 @@ -311,7 +335,10 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12): assert rx_frame.check_fcs() assert rx_frame.ctrl is None if gbx_cfg is None: - assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 + if dut.PTP_TD_EN.value: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*5 + else: + assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2 start_lane.append(rx_frame.start_lane) @@ -481,8 +508,10 @@ def test_taxi_eth_mac_phy_10g_fifo(request, data_w, gbx_en, dic_en): parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 parameters['PTP_TS_EN'] = 1 + parameters['PTP_TD_EN'] = parameters['PTP_TS_EN'] parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 + parameters['PTP_TD_SDI_PIPELINE'] = 2 parameters['TX_TAG_W'] = 16 parameters['BIT_REVERSE'] = 0 parameters['SCRAMBLER_DISABLE'] = 0 diff --git a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv index 89288aa..623a979 100644 --- a/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv +++ b/src/eth/tb/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv @@ -27,8 +27,10 @@ module test_taxi_eth_mac_phy_10g_fifo # parameter logic DIC_EN = 1'b1, parameter MIN_FRAME_LEN = 64, parameter logic PTP_TS_EN = 1'b0, + parameter logic PTP_TD_EN = PTP_TS_EN, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + parameter PTP_TD_SDI_PIPELINE = 2, parameter TX_TAG_W = 16, parameter logic BIT_REVERSE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0, @@ -71,7 +73,6 @@ logic tx_clk; logic tx_rst; logic logic_clk; logic logic_rst; -logic ptp_sample_clk; taxi_axis_if #(.DATA_W(AXIS_DATA_W), .USER_EN(1), .USER_W(TX_USER_W), .ID_EN(1), .ID_W(TX_TAG_W)) s_axis_tx(); taxi_axis_if #(.DATA_W(96), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) m_axis_tx_cpl(); @@ -91,8 +92,18 @@ logic serdes_rx_hdr_valid; logic serdes_rx_bitslip; logic serdes_rx_reset_req; -logic [PTP_TS_W-1:0] ptp_ts; -logic ptp_ts_step; +logic ptp_clk; +logic ptp_rst; +logic ptp_sample_clk; +logic ptp_td_sdi; +logic [PTP_TS_W-1:0] ptp_ts_in; +logic ptp_ts_step_in; +logic [PTP_TS_W-1:0] tx_ptp_ts_out; +logic tx_ptp_ts_step_out; +logic tx_ptp_locked; +logic [PTP_TS_W-1:0] rx_ptp_ts_out; +logic rx_ptp_ts_step_out; +logic rx_ptp_locked; logic stat_clk; logic stat_rst; @@ -130,8 +141,10 @@ taxi_eth_mac_phy_10g_fifo #( .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), .PTP_TS_EN(PTP_TS_EN), + .PTP_TD_EN(PTP_TD_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE), .BIT_REVERSE(BIT_REVERSE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .PRBS31_EN(PRBS31_EN), @@ -168,7 +181,6 @@ uut ( .tx_rst(tx_rst), .logic_clk(logic_clk), .logic_rst(logic_rst), - .ptp_sample_clk(ptp_sample_clk), /* * Transmit interface (AXI stream) @@ -201,8 +213,18 @@ uut ( /* * PTP clock */ - .ptp_ts(ptp_ts), - .ptp_ts_step(ptp_ts_step), + .ptp_clk(ptp_clk), + .ptp_rst(ptp_rst), + .ptp_sample_clk(ptp_sample_clk), + .ptp_td_sdi(ptp_td_sdi), + .ptp_ts_in(ptp_ts_in), + .ptp_ts_step_in(ptp_ts_step_in), + .tx_ptp_ts_out(tx_ptp_ts_out), + .tx_ptp_ts_step_out(tx_ptp_ts_step_out), + .tx_ptp_locked(tx_ptp_locked), + .rx_ptp_ts_out(rx_ptp_ts_out), + .rx_ptp_ts_step_out(rx_ptp_ts_step_out), + .rx_ptp_locked(rx_ptp_locked), /* * Statistics