eth: Integrate PTP TD leaf clock into MACs

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-02-13 21:54:11 -08:00
parent 380e2d521a
commit 31553f5734
30 changed files with 880 additions and 155 deletions

View File

@@ -584,10 +584,13 @@ always_ff @(posedge clk) begin
if (PTP_TS_EN && PTP_TS_FMT_TOD) begin if (PTP_TS_EN && PTP_TS_FMT_TOD) begin
// ns field rollover // 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_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_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[47:46] <= 0;
ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1; ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1;
/* verilator lint_on SELRANGE */
end end
// lane swapping and termination character detection // lane swapping and termination character detection
@@ -807,8 +810,11 @@ always_ff @(posedge clk) begin
if (input_start_swap_reg) begin if (input_start_swap_reg) begin
start_packet_reg <= 2'b10; start_packet_reg <= 2'b10;
if (PTP_TS_FMT_TOD) begin 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[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1);
ptp_ts_reg[95:48] <= ptp_ts[95:48]; ptp_ts_reg[95:48] <= ptp_ts[95:48];
/* verilator lint_on SELRANGE */
end else begin end else begin
ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1);
end end

View File

@@ -788,10 +788,13 @@ always_ff @(posedge clk) begin
if (PTP_TS_EN && PTP_TS_FMT_TOD) begin if (PTP_TS_EN && PTP_TS_FMT_TOD) begin
m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_int_reg; 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_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_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[47:46] <= 0;
m_axis_tx_cpl_ts_adj_reg[95:48] <= m_axis_tx_cpl_ts_reg[95:48] + 1; m_axis_tx_cpl_ts_adj_reg[95:48] <= m_axis_tx_cpl_ts_reg[95:48] + 1;
/* verilator lint_on SELRANGE */
end end
if (GBX_IF_EN && tx_gbx_req_stall) begin if (GBX_IF_EN && tx_gbx_req_stall) begin
@@ -810,8 +813,11 @@ always_ff @(posedge clk) begin
if (swap_lanes_reg) begin if (swap_lanes_reg) begin
if (PTP_TS_EN) begin if (PTP_TS_EN) begin
if (PTP_TS_FMT_TOD) 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[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1);
m_axis_tx_cpl_ts_reg[95:48] <= ptp_ts[95:48]; m_axis_tx_cpl_ts_reg[95:48] <= ptp_ts[95:48];
/* verilator lint_on SELRANGE */
end else begin end else begin
m_axis_tx_cpl_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); m_axis_tx_cpl_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1);
end end

View File

@@ -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_if.sv
../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv ../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv
../lib/taxi/src/axis/rtl/taxi_axis_tie.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 ../lib/taxi/src/sync/rtl/taxi_sync_signal.sv

View File

@@ -26,8 +26,10 @@ module taxi_eth_mac_10g #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic PFC_EN = 1'b0, parameter logic PFC_EN = 1'b0,
parameter logic PAUSE_EN = PFC_EN, parameter logic PAUSE_EN = PFC_EN,
parameter logic STAT_EN = 1'b0, parameter logic STAT_EN = 1'b0,
@@ -71,8 +73,18 @@ module taxi_eth_mac_10g #
/* /*
* PTP * PTP
*/ */
input wire logic [PTP_TS_W-1:0] tx_ptp_ts = '0, input wire logic ptp_clk = 1'b0,
input wire logic [PTP_TS_W-1:0] rx_ptp_ts = '0, 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) * 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(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(); 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 if (DATA_W == 64) begin
taxi_axis_xgmii_rx_64 #( taxi_axis_xgmii_rx_64 #(
@@ -245,7 +374,7 @@ if (DATA_W == 64) begin
/* /*
* PTP * PTP
*/ */
.ptp_ts(rx_ptp_ts), .ptp_ts(rx_ptp_ts_out),
/* /*
* Configuration * Configuration
@@ -310,7 +439,7 @@ if (DATA_W == 64) begin
/* /*
* PTP * PTP
*/ */
.ptp_ts(tx_ptp_ts), .ptp_ts(tx_ptp_ts_out),
/* /*
* Configuration * Configuration
@@ -364,7 +493,7 @@ end else if (DATA_W == 32) begin
/* /*
* PTP * PTP
*/ */
.ptp_ts(rx_ptp_ts), .ptp_ts(rx_ptp_ts_out),
/* /*
* Configuration * Configuration
@@ -431,7 +560,7 @@ end else if (DATA_W == 32) begin
/* /*
* PTP * PTP
*/ */
.ptp_ts(tx_ptp_ts), .ptp_ts(tx_ptp_ts_out),
/* /*
* Configuration * Configuration

View File

@@ -26,8 +26,10 @@ module taxi_eth_mac_10g_fifo #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic STAT_EN = 1'b0, parameter logic STAT_EN = 1'b0,
parameter STAT_TX_LEVEL = 1, parameter STAT_TX_LEVEL = 1,
parameter STAT_RX_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 tx_rst,
input wire logic logic_clk, input wire logic logic_clk,
input wire logic logic_rst, input wire logic logic_rst,
input wire logic ptp_sample_clk,
/* /*
* AXI4-Stream input (sink) * AXI4-Stream input (sink)
@@ -85,8 +86,18 @@ module taxi_eth_mac_10g_fifo #
/* /*
* PTP clock * PTP clock
*/ */
input wire logic [PTP_TS_W-1:0] ptp_ts = '0, input wire logic ptp_clk = 1'b0,
input wire logic ptp_ts_step = 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 * 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(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(); 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 // synchronize MAC status signals into logic clock domain
wire tx_error_underflow_int; wire tx_error_underflow_int;
@@ -195,7 +200,14 @@ always_ff @(posedge logic_clk or posedge logic_rst) begin
end end
// PTP timestamping // 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 #( taxi_ptp_clock_cdc #(
.TS_W(PTP_TS_W), .TS_W(PTP_TS_W),
@@ -207,10 +219,10 @@ if (PTP_TS_EN) begin : ptp
.output_clk(tx_clk), .output_clk(tx_clk),
.output_rst(tx_rst), .output_rst(tx_rst),
.sample_clk(ptp_sample_clk), .sample_clk(ptp_sample_clk),
.input_ts(ptp_ts), .input_ts(ptp_ts_in),
.input_ts_step(ptp_ts_step), .input_ts_step(ptp_ts_step_in),
.output_ts(tx_ptp_ts), .output_ts(tx_ptp_ts_int),
.output_ts_step(), .output_ts_step(tx_ptp_ts_step_out),
.output_pps(), .output_pps(),
.output_pps_str(), .output_pps_str(),
.locked(tx_ptp_locked) .locked(tx_ptp_locked)
@@ -226,10 +238,10 @@ if (PTP_TS_EN) begin : ptp
.output_clk(rx_clk), .output_clk(rx_clk),
.output_rst(rx_rst), .output_rst(rx_rst),
.sample_clk(ptp_sample_clk), .sample_clk(ptp_sample_clk),
.input_ts(ptp_ts), .input_ts(ptp_ts_in),
.input_ts_step(ptp_ts_step), .input_ts_step(ptp_ts_step_in),
.output_ts(rx_ptp_ts), .output_ts(rx_ptp_ts_int),
.output_ts_step(), .output_ts_step(rx_ptp_ts_step_out),
.output_pps(), .output_pps(),
.output_pps_str(), .output_pps_str(),
.locked(rx_ptp_locked) .locked(rx_ptp_locked)
@@ -237,11 +249,13 @@ if (PTP_TS_EN) begin : ptp
end else begin end else begin
assign tx_ptp_ts = '0; assign tx_ptp_ts_int = '0;
assign rx_ptp_ts = '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 tx_ptp_locked = tx_ptp_locked_int;
assign rx_ptp_locked = 1'b0; assign rx_ptp_locked = rx_ptp_locked_int;
end end
@@ -257,8 +271,10 @@ taxi_eth_mac_10g #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.PFC_EN(1'b0), .PFC_EN(1'b0),
.PAUSE_EN(1'b0), .PAUSE_EN(1'b0),
.STAT_EN(STAT_EN), .STAT_EN(STAT_EN),
@@ -302,8 +318,18 @@ eth_mac_10g_inst (
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -8,4 +8,5 @@ taxi_mac_pause_ctrl_tx.sv
taxi_mac_pause_ctrl_rx.sv taxi_mac_pause_ctrl_rx.sv
../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv ../lib/taxi/src/axis/rtl/taxi_axis_null_src.sv
../lib/taxi/src/axis/rtl/taxi_axis_tie.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 ../lib/taxi/src/sync/rtl/taxi_sync_signal.sv

View File

@@ -25,8 +25,10 @@ module taxi_eth_mac_phy_10g #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic BIT_REVERSE = 1'b0, parameter logic BIT_REVERSE = 1'b0,
parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0,
parameter logic PRBS31_EN = 1'b0, parameter logic PRBS31_EN = 1'b0,
@@ -82,8 +84,18 @@ module taxi_eth_mac_phy_10g #
/* /*
* PTP * PTP
*/ */
input wire logic [PTP_TS_W-1:0] tx_ptp_ts, input wire logic ptp_clk = 1'b0,
input wire logic [PTP_TS_W-1:0] rx_ptp_ts, 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) * 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(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(); 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 #( taxi_eth_mac_phy_10g_rx #(
.DATA_W(DATA_W), .DATA_W(DATA_W),
.HDR_W(HDR_W), .HDR_W(HDR_W),
@@ -263,7 +392,7 @@ eth_mac_phy_10g_rx_inst (
/* /*
* PTP * PTP
*/ */
.ptp_ts(rx_ptp_ts), .ptp_ts(rx_ptp_ts_out),
/* /*
* Status * Status
@@ -337,7 +466,7 @@ eth_mac_phy_10g_tx_inst (
/* /*
* PTP * PTP
*/ */
.ptp_ts(tx_ptp_ts), .ptp_ts(tx_ptp_ts_out),
/* /*
* Status * Status

View File

@@ -25,8 +25,10 @@ module taxi_eth_mac_phy_10g_fifo #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic BIT_REVERSE = 1'b0, parameter logic BIT_REVERSE = 1'b0,
parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0,
parameter logic PRBS31_EN = 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 tx_rst,
input wire logic logic_clk, input wire logic logic_clk,
input wire logic logic_rst, input wire logic logic_rst,
input wire logic ptp_sample_clk,
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -96,8 +97,18 @@ module taxi_eth_mac_phy_10g_fifo #
/* /*
* PTP clock * PTP clock
*/ */
input wire logic [PTP_TS_W-1:0] ptp_ts = '0, input wire logic ptp_clk = 1'b0,
input wire logic ptp_ts_step = 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 * 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(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(); 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 // synchronize MAC status signals into logic clock domain
wire tx_error_underflow_int; wire tx_error_underflow_int;
@@ -229,7 +234,14 @@ always_ff @(posedge logic_clk or posedge logic_rst) begin
end end
// PTP timestamping // 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 #( taxi_ptp_clock_cdc #(
.TS_W(PTP_TS_W), .TS_W(PTP_TS_W),
@@ -241,10 +253,10 @@ if (PTP_TS_EN) begin : ptp
.output_clk(tx_clk), .output_clk(tx_clk),
.output_rst(tx_rst), .output_rst(tx_rst),
.sample_clk(ptp_sample_clk), .sample_clk(ptp_sample_clk),
.input_ts(ptp_ts), .input_ts(ptp_ts_in),
.input_ts_step(ptp_ts_step), .input_ts_step(ptp_ts_step_in),
.output_ts(tx_ptp_ts), .output_ts(tx_ptp_ts_int),
.output_ts_step(), .output_ts_step(tx_ptp_ts_step_out),
.output_pps(), .output_pps(),
.output_pps_str(), .output_pps_str(),
.locked(tx_ptp_locked) .locked(tx_ptp_locked)
@@ -260,10 +272,10 @@ if (PTP_TS_EN) begin : ptp
.output_clk(rx_clk), .output_clk(rx_clk),
.output_rst(rx_rst), .output_rst(rx_rst),
.sample_clk(ptp_sample_clk), .sample_clk(ptp_sample_clk),
.input_ts(ptp_ts), .input_ts(ptp_ts_in),
.input_ts_step(ptp_ts_step), .input_ts_step(ptp_ts_step_in),
.output_ts(rx_ptp_ts), .output_ts(rx_ptp_ts_int),
.output_ts_step(), .output_ts_step(rx_ptp_ts_step_out),
.output_pps(), .output_pps(),
.output_pps_str(), .output_pps_str(),
.locked(rx_ptp_locked) .locked(rx_ptp_locked)
@@ -271,11 +283,13 @@ if (PTP_TS_EN) begin : ptp
end else begin end else begin
assign tx_ptp_ts = '0; assign tx_ptp_ts_int = '0;
assign rx_ptp_ts = '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 tx_ptp_locked = tx_ptp_locked_int;
assign rx_ptp_locked = 1'b0; assign rx_ptp_locked = rx_ptp_locked_int;
end end
@@ -290,8 +304,10 @@ taxi_eth_mac_phy_10g #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.BIT_REVERSE(BIT_REVERSE), .BIT_REVERSE(BIT_REVERSE),
.SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
@@ -345,8 +361,18 @@ eth_mac_phy_10g_inst (
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -58,8 +58,10 @@ module taxi_eth_mac_25g_us #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic PRBS31_EN = 1'b0, parameter logic PRBS31_EN = 1'b0,
parameter TX_SERDES_PIPELINE = 1, parameter TX_SERDES_PIPELINE = 1,
parameter RX_SERDES_PIPELINE = 1, parameter RX_SERDES_PIPELINE = 1,
@@ -121,7 +123,6 @@ module taxi_eth_mac_25g_us #
output wire logic tx_clk[CNT], output wire logic tx_clk[CNT],
input wire logic tx_rst_in[CNT] = '{CNT{1'b0}}, input wire logic tx_rst_in[CNT] = '{CNT{1'b0}},
output wire logic tx_rst_out[CNT], output wire logic tx_rst_out[CNT],
input wire logic ptp_sample_clk[CNT] = '{CNT{1'b0}},
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -137,10 +138,18 @@ module taxi_eth_mac_25g_us #
/* /*
* PTP clock * PTP clock
*/ */
input wire logic [PTP_TS_W-1:0] tx_ptp_ts[CNT] = '{CNT{'0}}, input wire logic ptp_clk = 1'b0,
input wire logic tx_ptp_ts_step[CNT] = '{CNT{1'b0}}, input wire logic ptp_rst = 1'b0,
input wire logic [PTP_TS_W-1:0] rx_ptp_ts[CNT] = '{CNT{'0}}, input wire logic ptp_sample_clk = 1'b0,
input wire logic rx_ptp_ts_step[CNT] = '{CNT{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) * 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), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE), .TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_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_clk(tx_clk[n]),
.tx_rst_in(tx_rst_in[n]), .tx_rst_in(tx_rst_in[n]),
.tx_rst_out(tx_rst_out[n]), .tx_rst_out(tx_rst_out[n]),
.ptp_sample_clk(ptp_sample_clk[n]),
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -513,10 +523,18 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch
/* /*
* PTP clock * PTP clock
*/ */
.tx_ptp_ts(tx_ptp_ts[n]), .ptp_clk(ptp_clk),
.tx_ptp_ts_step(tx_ptp_ts_step[n]), .ptp_rst(ptp_rst),
.rx_ptp_ts(rx_ptp_ts[n]), .ptp_sample_clk(ptp_sample_clk),
.rx_ptp_ts_step(rx_ptp_ts_step[n]), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -57,8 +57,10 @@ module taxi_eth_mac_25g_us_ch #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter logic PRBS31_EN = 1'b0, parameter logic PRBS31_EN = 1'b0,
parameter TX_SERDES_PIPELINE = 1, parameter TX_SERDES_PIPELINE = 1,
parameter RX_SERDES_PIPELINE = 1, parameter RX_SERDES_PIPELINE = 1,
@@ -134,7 +136,6 @@ module taxi_eth_mac_25g_us_ch #
output wire logic tx_clk, output wire logic tx_clk,
input wire logic tx_rst_in = 1'b0, input wire logic tx_rst_in = 1'b0,
output wire logic tx_rst_out, output wire logic tx_rst_out,
input wire logic ptp_sample_clk = 1'b0,
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -150,10 +151,18 @@ module taxi_eth_mac_25g_us_ch #
/* /*
* PTP clock * PTP clock
*/ */
input wire logic [PTP_TS_W-1:0] tx_ptp_ts = '0, input wire logic ptp_clk = 1'b0,
input wire logic tx_ptp_ts_step = 1'b0, input wire logic ptp_rst = 1'b0,
input wire logic [PTP_TS_W-1:0] rx_ptp_ts = '0, input wire logic ptp_sample_clk = 1'b0,
input wire logic rx_ptp_ts_step = 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) * 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), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.BIT_REVERSE(1'b1), .BIT_REVERSE(1'b1),
.SCRAMBLER_DISABLE(1'b0), .SCRAMBLER_DISABLE(1'b0),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
@@ -935,8 +946,18 @@ if (COMBINED_MAC_PCS) begin : mac
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)
@@ -1160,8 +1181,10 @@ end else begin : mac
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.PFC_EN(PFC_EN), .PFC_EN(PFC_EN),
.PAUSE_EN(PAUSE_EN), .PAUSE_EN(PAUSE_EN),
.STAT_EN(STAT_EN), .STAT_EN(STAT_EN),
@@ -1205,8 +1228,18 @@ end else begin : mac
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -40,8 +40,10 @@ export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64
export PARAM_PTP_TS_EN := 1 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_FMT_TOD := 1
export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) 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_TX_TAG_W := 16
export PARAM_PFC_EN := 1 export PARAM_PFC_EN := 1
export PARAM_PAUSE_EN := $(PARAM_PFC_EN) export PARAM_PAUSE_EN := $(PARAM_PFC_EN)

View File

@@ -0,0 +1 @@
../../lib/taxi/src/ptp/tb/ptp_td.py

View File

@@ -13,6 +13,7 @@ import itertools
import logging import logging
import os import os
import struct import struct
import sys
from scapy.layers.l2 import Ether 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.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamFrame 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: class TB:
def __init__(self, dut): 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.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.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, clock=dut.tx_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_req.setimmediatevalue(0)
dut.tx_lfc_resend.setimmediatevalue(0) dut.tx_lfc_resend.setimmediatevalue(0)
@@ -112,20 +135,26 @@ class TB:
async def reset(self): async def reset(self):
self.dut.rx_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0)
self.dut.tx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0)
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.stat_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
self.dut.rx_rst.value = 1 self.dut.rx_rst.value = 1
self.dut.tx_rst.value = 1 self.dut.tx_rst.value = 1
self.dut.ptp_rst.value = 1
self.dut.stat_rst.value = 1 self.dut.stat_rst.value = 1
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
self.dut.rx_rst.value = 0 self.dut.rx_rst.value = 0
self.dut.tx_rst.value = 0 self.dut.tx_rst.value = 0
self.dut.ptp_rst.value = 0
self.dut.stat_rst.value = 0 self.dut.stat_rst.value = 0
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
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): 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() 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()] test_frames = [payload_data(x) for x in payload_lengths()]
tx_frames = [] tx_frames = []
@@ -165,6 +201,9 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
assert rx_frame.tdata == test_data assert rx_frame.tdata == test_data
assert frame_error == 0 assert frame_error == 0
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 abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < 0.01
assert tb.axis_sink.empty() 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() 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()] test_frames = [payload_data(x) for x in payload_lengths()]
for test_data in test_frames: for test_data in test_frames:
@@ -208,6 +254,9 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
assert rx_frame.get_payload() == test_data assert rx_frame.get_payload() == test_data
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01
assert tb.xgmii_sink.empty() assert tb.xgmii_sink.empty()
@@ -231,6 +280,13 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12):
await tb.reset() 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 length in range(60, 92):
for k in range(10): for k in range(10):
@@ -261,6 +317,9 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12):
assert rx_frame.get_payload() == test_data assert rx_frame.get_payload() == test_data
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01
start_lane.append(rx_frame.start_lane) 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(("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]) @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" dut = "taxi_eth_mac_10g"
module = os.path.splitext(os.path.basename(__file__))[0] module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = module 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['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TD_EN'] = ptp_td_en
parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 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['TX_TAG_W'] = 16
parameters['PFC_EN'] = pfc_en parameters['PFC_EN'] = pfc_en
parameters['PAUSE_EN'] = parameters['PFC_EN'] parameters['PAUSE_EN'] = parameters['PFC_EN']

View File

@@ -26,8 +26,10 @@ module test_taxi_eth_mac_10g #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter TX_TAG_W = 16, parameter TX_TAG_W = 16,
parameter logic PFC_EN = 1'b0, parameter logic PFC_EN = 1'b0,
parameter logic PAUSE_EN = PFC_EN, 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 tx_gbx_req_stall;
logic [GBX_CNT-1:0] tx_gbx_sync; logic [GBX_CNT-1:0] tx_gbx_sync;
logic [PTP_TS_W-1:0] tx_ptp_ts; logic ptp_clk;
logic [PTP_TS_W-1:0] rx_ptp_ts; 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_req;
logic tx_lfc_resend; logic tx_lfc_resend;
@@ -183,8 +195,10 @@ taxi_eth_mac_10g #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.PFC_EN(PFC_EN), .PFC_EN(PFC_EN),
.PAUSE_EN(PAUSE_EN), .PAUSE_EN(PAUSE_EN),
.STAT_EN(STAT_EN), .STAT_EN(STAT_EN),
@@ -228,8 +242,18 @@ uut (
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -41,8 +41,10 @@ export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64
export PARAM_PTP_TS_EN := 1 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_FMT_TOD := 1
export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) 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_TX_TAG_W := 16
export PARAM_STAT_EN := 1 export PARAM_STAT_EN := 1
export PARAM_STAT_TX_LEVEL := 2 export PARAM_STAT_TX_LEVEL := 2

View File

@@ -0,0 +1 @@
../../lib/taxi/src/ptp/tb/ptp_td.py

View File

@@ -12,6 +12,7 @@ Authors:
import itertools import itertools
import logging import logging
import os import os
import sys
import pytest import pytest
import cocotb_test.simulator import cocotb_test.simulator
@@ -25,6 +26,16 @@ from cocotb.regression import TestFactory
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStreamFrame 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: class TB:
def __init__(self, dut): 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.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.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.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_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) 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.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_max_pkt_len.setimmediatevalue(0)
dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0)
@@ -67,22 +88,28 @@ class TB:
self.dut.logic_rst.setimmediatevalue(0) self.dut.logic_rst.setimmediatevalue(0)
self.dut.rx_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0)
self.dut.tx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0)
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.stat_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
self.dut.logic_rst.value = 1 self.dut.logic_rst.value = 1
self.dut.rx_rst.value = 1 self.dut.rx_rst.value = 1
self.dut.tx_rst.value = 1 self.dut.tx_rst.value = 1
self.dut.ptp_rst.value = 1
self.dut.stat_rst.value = 1 self.dut.stat_rst.value = 1
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
self.dut.logic_rst.value = 0 self.dut.logic_rst.value = 0
self.dut.rx_rst.value = 0 self.dut.rx_rst.value = 0
self.dut.tx_rst.value = 0 self.dut.tx_rst.value = 0
self.dut.ptp_rst.value = 0
self.dut.stat_rst.value = 0 self.dut.stat_rst.value = 0
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
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): 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() await tb.reset()
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.rx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.rx_clk) await RisingEdge(dut.rx_clk)
test_frames = [payload_data(x) for x in payload_lengths()] test_frames = [payload_data(x) for x in payload_lengths()]
@@ -128,6 +155,9 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
assert rx_frame.tdata == test_data assert rx_frame.tdata == test_data
assert frame_error == 0 assert frame_error == 0
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 abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period*2
assert tb.axis_sink.empty() 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() await tb.reset()
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.tx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
test_frames = [payload_data(x) for x in payload_lengths()] test_frames = [payload_data(x) for x in payload_lengths()]
@@ -177,6 +207,9 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
assert rx_frame.get_payload() == test_data assert rx_frame.get_payload() == test_data
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2
assert tb.xgmii_sink.empty() assert tb.xgmii_sink.empty()
@@ -201,9 +234,9 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12):
await tb.reset() await tb.reset()
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.tx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
for length in range(60, 92): for length in range(60, 92):
@@ -236,6 +269,9 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12):
assert rx_frame.get_payload() == test_data assert rx_frame.get_payload() == test_data
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period*2
start_lane.append(rx_frame.start_lane) 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['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TD_EN'] = parameters['PTP_TS_EN']
parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 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['TX_TAG_W'] = 16
parameters['STAT_EN'] = 1 parameters['STAT_EN'] = 1
parameters['STAT_TX_LEVEL'] = 2 parameters['STAT_TX_LEVEL'] = 2

View File

@@ -27,8 +27,10 @@ module test_taxi_eth_mac_10g_fifo #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter TX_TAG_W = 16, parameter TX_TAG_W = 16,
parameter logic STAT_EN = 1'b0, parameter logic STAT_EN = 1'b0,
parameter STAT_TX_LEVEL = 1, parameter STAT_TX_LEVEL = 1,
@@ -64,7 +66,6 @@ logic tx_clk;
logic tx_rst; logic tx_rst;
logic logic_clk; logic logic_clk;
logic logic_rst; 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(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(); 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 tx_gbx_req_stall;
logic [GBX_CNT-1:0] tx_gbx_sync; logic [GBX_CNT-1:0] tx_gbx_sync;
logic [PTP_TS_W-1:0] ptp_ts; logic ptp_clk;
logic ptp_ts_step; 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_clk;
logic stat_rst; logic stat_rst;
@@ -113,8 +124,10 @@ taxi_eth_mac_10g_fifo #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.STAT_EN(STAT_EN), .STAT_EN(STAT_EN),
.STAT_TX_LEVEL(STAT_TX_LEVEL), .STAT_TX_LEVEL(STAT_TX_LEVEL),
.STAT_RX_LEVEL(STAT_RX_LEVEL), .STAT_RX_LEVEL(STAT_RX_LEVEL),
@@ -143,7 +156,6 @@ uut (
.tx_rst(tx_rst), .tx_rst(tx_rst),
.logic_clk(logic_clk), .logic_clk(logic_clk),
.logic_rst(logic_rst), .logic_rst(logic_rst),
.ptp_sample_clk(ptp_sample_clk),
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -172,8 +184,18 @@ uut (
/* /*
* PTP clock * PTP clock
*/ */
.ptp_ts(ptp_ts), .ptp_clk(ptp_clk),
.ptp_ts_step(ptp_ts_step), .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 * Statistics

View File

@@ -48,8 +48,10 @@ export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64
export PARAM_PTP_TS_EN := 1 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_FMT_TOD := 1
export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) 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_TX_TAG_W := 16
export PARAM_PRBS31_EN := 1 export PARAM_PRBS31_EN := 1
export PARAM_TX_SERDES_PIPELINE := 2 export PARAM_TX_SERDES_PIPELINE := 2

View File

@@ -0,0 +1 @@
../../lib/taxi/src/ptp/tb/ptp_td.py

View File

@@ -32,11 +32,13 @@ from cocotbext.axi import ApbBus, ApbMaster
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
except ImportError: except ImportError:
# attempt import from current directory # attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__))) sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
finally: finally:
del sys.path[0] del sys.path[0]
@@ -118,8 +120,20 @@ class TB:
self.tx_ptp_clocks = [] self.tx_ptp_clocks = []
for k in range(4): 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.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[k], clock=dut.uut.ch[k].ch_inst.gt.gt_inst.tx_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.rx_rst_in.setimmediatevalue([0]*4)
dut.tx_rst_in.setimmediatevalue([0]*4) dut.tx_rst_in.setimmediatevalue([0]*4)
@@ -169,18 +183,24 @@ class TB:
async def reset(self): async def reset(self):
self.dut.xcvr_ctrl_rst.setimmediatevalue(0) self.dut.xcvr_ctrl_rst.setimmediatevalue(0)
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.stat_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0)
await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk)
await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk)
self.dut.xcvr_ctrl_rst.value = 1 self.dut.xcvr_ctrl_rst.value = 1
self.dut.ptp_rst.value = 1
self.dut.stat_rst.value = 1 self.dut.stat_rst.value = 1
await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk)
await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk)
self.dut.xcvr_ctrl_rst.value = 0 self.dut.xcvr_ctrl_rst.value = 0
self.dut.ptp_rst.value = 0
self.dut.stat_rst.value = 0 self.dut.stat_rst.value = 0
await RisingEdge(self.dut.xcvr_ctrl_clk) await RisingEdge(self.dut.xcvr_ctrl_clk)
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): async def run_test_regs(dut):
tb = TB(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): while not int(dut.rx_block_lock[port].value):
await RisingEdge(dut.xcvr_ctrl_clk) 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 tb.dut.cfg_rx_enable[port].value = 1
test_frames = [payload_data(x) for x in payload_lengths()] test_frames = [payload_data(x) for x in payload_lengths()]
@@ -267,6 +293,9 @@ async def run_test_rx(dut, port=0, payload_lengths=None, payload_data=None, ifg=
assert rx_frame.tdata == test_data assert rx_frame.tdata == test_data
assert frame_error == 0 assert frame_error == 0
if not tb.serdes_sources[port].gbx_seq_len: if not tb.serdes_sources[port].gbx_seq_len:
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 abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period[port]*pipe_delay) < 0.01
assert tb.axis_sinks[port].empty() 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): while int(dut.tx_rst_out[port].value):
await RisingEdge(dut.xcvr_ctrl_clk) 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) await RisingEdge(dut.xcvr_ctrl_clk)
tb.dut.cfg_tx_enable[port].value = 1 tb.dut.cfg_tx_enable[port].value = 1
@@ -337,6 +369,9 @@ async def run_test_tx(dut, port=0, payload_lengths=None, payload_data=None, ifg=
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if not tb.serdes_sinks[port].gbx_seq_len: if not tb.serdes_sinks[port].gbx_seq_len:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01
assert tb.serdes_sinks[port].empty() 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): while int(dut.tx_rst_out[port].value):
await RisingEdge(dut.xcvr_ctrl_clk) 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) await RisingEdge(dut.xcvr_ctrl_clk)
tb.dut.cfg_tx_enable[port].value = 1 tb.dut.cfg_tx_enable[port].value = 1
@@ -416,6 +454,9 @@ async def run_test_tx_alignment(dut, port=0, payload_data=None, ifg=12):
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if not tb.serdes_sinks[port].gbx_seq_len: if not tb.serdes_sinks[port].gbx_seq_len:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period[port]*pipe_delay) < 0.01
start_lane.append(rx_frame.start_lane) 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['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TD_EN'] = parameters['PTP_TS_EN']
parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 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['TX_TAG_W'] = 16
parameters['PRBS31_EN'] = 1 parameters['PRBS31_EN'] = 1
parameters['TX_SERDES_PIPELINE'] = 2 parameters['TX_SERDES_PIPELINE'] = 2

View File

@@ -47,8 +47,10 @@ module test_taxi_eth_mac_25g_us #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter TX_TAG_W = 16, parameter TX_TAG_W = 16,
parameter logic PRBS31_EN = 1'b0, parameter logic PRBS31_EN = 1'b0,
parameter TX_SERDES_PIPELINE = 1, parameter TX_SERDES_PIPELINE = 1,
@@ -108,16 +110,23 @@ logic rx_rst_out[CNT];
logic tx_clk[CNT]; logic tx_clk[CNT];
logic tx_rst_in[CNT]; logic tx_rst_in[CNT];
logic tx_rst_out[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(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(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](); 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 ptp_clk;
logic tx_ptp_ts_step[CNT]; logic ptp_rst;
logic [PTP_TS_W-1:0] rx_ptp_ts[CNT]; logic ptp_sample_clk;
logic rx_ptp_ts_step[CNT]; 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_req[CNT];
logic tx_lfc_resend[CNT]; logic tx_lfc_resend[CNT];
@@ -260,8 +269,10 @@ taxi_eth_mac_25g_us #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
.TX_SERDES_PIPELINE(TX_SERDES_PIPELINE), .TX_SERDES_PIPELINE(TX_SERDES_PIPELINE),
.RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE),
@@ -323,7 +334,6 @@ uut (
.tx_clk(tx_clk), .tx_clk(tx_clk),
.tx_rst_in(tx_rst_in), .tx_rst_in(tx_rst_in),
.tx_rst_out(tx_rst_out), .tx_rst_out(tx_rst_out),
.ptp_sample_clk(ptp_sample_clk),
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -339,10 +349,18 @@ uut (
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.tx_ptp_ts_step(tx_ptp_ts_step), .ptp_rst(ptp_rst),
.rx_ptp_ts(rx_ptp_ts), .ptp_sample_clk(ptp_sample_clk),
.rx_ptp_ts_step(rx_ptp_ts_step), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -40,8 +40,10 @@ export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64
export PARAM_PTP_TS_EN := 1 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_FMT_TOD := 1
export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) 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_TX_TAG_W := 16
export PARAM_BIT_REVERSE := 0 export PARAM_BIT_REVERSE := 0
export PARAM_SCRAMBLER_DISABLE := 0 export PARAM_SCRAMBLER_DISABLE := 0

View File

@@ -0,0 +1 @@
../../lib/taxi/src/ptp/tb/ptp_td.py

View File

@@ -31,11 +31,13 @@ from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStrea
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
except ImportError: except ImportError:
# attempt import from current directory # attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__))) sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
finally: finally:
del sys.path[0] 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.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.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, clock=dut.tx_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) dut.stat_rx_fifo_drop.setimmediatevalue(0)
@@ -136,20 +150,26 @@ class TB:
async def reset(self): async def reset(self):
self.dut.rx_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0)
self.dut.tx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0)
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.stat_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
self.dut.rx_rst.value = 1 self.dut.rx_rst.value = 1
self.dut.tx_rst.value = 1 self.dut.tx_rst.value = 1
self.dut.ptp_rst.value = 1
self.dut.stat_rst.value = 1 self.dut.stat_rst.value = 1
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
self.dut.rx_rst.value = 0 self.dut.rx_rst.value = 0
self.dut.tx_rst.value = 0 self.dut.tx_rst.value = 0
self.dut.ptp_rst.value = 0
self.dut.stat_rst.value = 0 self.dut.stat_rst.value = 0
await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk)
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): 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): while not int(dut.rx_block_lock.value):
await RisingEdge(dut.rx_clk) 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 tb.dut.cfg_rx_enable.value = 1
test_frames = [payload_data(x) for x in payload_lengths()] test_frames = [payload_data(x) for x in payload_lengths()]
@@ -208,6 +235,9 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
assert rx_frame.tdata == test_data assert rx_frame.tdata == test_data
assert frame_error == 0 assert frame_error == 0
if gbx_cfg is None: if gbx_cfg is None:
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 abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < 0.01
assert tb.axis_sink.empty() assert tb.axis_sink.empty()
@@ -231,6 +261,13 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
await tb.reset() 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)
else:
for k in range(100): for k in range(100):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
@@ -266,6 +303,9 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if gbx_cfg is None: if gbx_cfg is None:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01
assert tb.serdes_sink.empty() assert tb.serdes_sink.empty()
@@ -293,6 +333,13 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12):
await tb.reset() 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)
else:
for k in range(100): for k in range(100):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
@@ -333,6 +380,9 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12):
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if gbx_cfg is None: if gbx_cfg is None:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < 0.01
start_lane.append(rx_frame.start_lane) 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(("dic_en", "pfc_en"), [(1, 1), (1, 0), (0, 0)])
@pytest.mark.parametrize("gbx_en", [1, 0]) @pytest.mark.parametrize("gbx_en", [1, 0])
@pytest.mark.parametrize("ptp_td_en", [1, 0])
@pytest.mark.parametrize("data_w", [32, 64]) @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" dut = "taxi_eth_mac_phy_10g"
module = os.path.splitext(os.path.basename(__file__))[0] module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = module 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['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TD_EN'] = ptp_td_en
parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 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['TX_TAG_W'] = 16
parameters['BIT_REVERSE'] = 0 parameters['BIT_REVERSE'] = 0
parameters['SCRAMBLER_DISABLE'] = 0 parameters['SCRAMBLER_DISABLE'] = 0

View File

@@ -26,8 +26,10 @@ module test_taxi_eth_mac_phy_10g #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter TX_TAG_W = 16, parameter TX_TAG_W = 16,
parameter logic BIT_REVERSE = 1'b0, parameter logic BIT_REVERSE = 1'b0,
parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0,
@@ -76,8 +78,18 @@ logic serdes_rx_hdr_valid;
logic serdes_rx_bitslip; logic serdes_rx_bitslip;
logic serdes_rx_reset_req; logic serdes_rx_reset_req;
logic [PTP_TS_W-1:0] tx_ptp_ts; logic ptp_clk;
logic [PTP_TS_W-1:0] rx_ptp_ts; 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_req;
logic tx_lfc_resend; logic tx_lfc_resend;
@@ -199,8 +211,10 @@ taxi_eth_mac_phy_10g #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.BIT_REVERSE(BIT_REVERSE), .BIT_REVERSE(BIT_REVERSE),
.SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
@@ -256,8 +270,18 @@ uut (
/* /*
* PTP * PTP
*/ */
.tx_ptp_ts(tx_ptp_ts), .ptp_clk(ptp_clk),
.rx_ptp_ts(rx_ptp_ts), .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) * Link-level Flow Control (LFC) (IEEE 802.3 annex 31B PAUSE)

View File

@@ -41,8 +41,10 @@ export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64
export PARAM_PTP_TS_EN := 1 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_FMT_TOD := 1
export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) 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_TX_TAG_W := 16
export PARAM_BIT_REVERSE := 0 export PARAM_BIT_REVERSE := 0
export PARAM_SCRAMBLER_DISABLE := 0 export PARAM_SCRAMBLER_DISABLE := 0

View File

@@ -0,0 +1 @@
../../lib/taxi/src/ptp/tb/ptp_td.py

View File

@@ -28,11 +28,13 @@ from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink, AxiStrea
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
except ImportError: except ImportError:
# attempt import from current directory # attempt import from current directory
sys.path.insert(0, os.path.join(os.path.dirname(__file__))) sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
try: try:
from baser import BaseRSerdesSource, BaseRSerdesSink from baser import BaseRSerdesSource, BaseRSerdesSink
from ptp_td import PtpTdSource
finally: finally:
del sys.path[0] 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.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.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.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( self.serdes_source = BaseRSerdesSource(
data=dut.serdes_rx_data, 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.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_max_pkt_len.setimmediatevalue(0)
dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_ifg.setimmediatevalue(0)
@@ -104,22 +116,28 @@ class TB:
self.dut.logic_rst.setimmediatevalue(0) self.dut.logic_rst.setimmediatevalue(0)
self.dut.rx_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0)
self.dut.tx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0)
self.dut.ptp_rst.setimmediatevalue(0)
self.dut.stat_rst.setimmediatevalue(0) self.dut.stat_rst.setimmediatevalue(0)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
self.dut.logic_rst.value = 1 self.dut.logic_rst.value = 1
self.dut.rx_rst.value = 1 self.dut.rx_rst.value = 1
self.dut.tx_rst.value = 1 self.dut.tx_rst.value = 1
self.dut.ptp_rst.value = 1
self.dut.stat_rst.value = 1 self.dut.stat_rst.value = 1
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
self.dut.logic_rst.value = 0 self.dut.logic_rst.value = 0
self.dut.rx_rst.value = 0 self.dut.rx_rst.value = 0
self.dut.tx_rst.value = 0 self.dut.tx_rst.value = 0
self.dut.ptp_rst.value = 0
self.dut.stat_rst.value = 0 self.dut.stat_rst.value = 0
await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk)
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): 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) await RisingEdge(dut.rx_clk)
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.rx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.rx_clk) await RisingEdge(dut.rx_clk)
# clear out sink buffer # clear out sink buffer
@@ -181,6 +199,9 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
assert rx_frame.tdata == test_data assert rx_frame.tdata == test_data
assert frame_error == 0 assert frame_error == 0
if gbx_cfg is None: if gbx_cfg is None:
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 abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < tb.clk_period*2
assert tb.axis_sink.empty() 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() await tb.reset()
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.tx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
tb.dut.cfg_tx_enable.value = 1 tb.dut.cfg_tx_enable.value = 1
@@ -241,6 +262,9 @@ async def run_test_tx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if gbx_cfg is None: if gbx_cfg is None:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2
assert tb.serdes_sink.empty() 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() await tb.reset()
tb.log.info("Wait for PTP CDC lock") 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) await RisingEdge(dut.tx_clk)
for k in range(1000): for k in range(2000):
await RisingEdge(dut.tx_clk) await RisingEdge(dut.tx_clk)
tb.dut.cfg_tx_enable.value = 1 tb.dut.cfg_tx_enable.value = 1
@@ -311,6 +335,9 @@ async def run_test_tx_alignment(dut, gbx_cfg=None, payload_data=None, ifg=12):
assert rx_frame.check_fcs() assert rx_frame.check_fcs()
assert rx_frame.ctrl is None assert rx_frame.ctrl is None
if gbx_cfg is None: if gbx_cfg is None:
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 abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*pipe_delay) < tb.clk_period*2
start_lane.append(rx_frame.start_lane) 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['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TD_EN'] = parameters['PTP_TS_EN']
parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 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['TX_TAG_W'] = 16
parameters['BIT_REVERSE'] = 0 parameters['BIT_REVERSE'] = 0
parameters['SCRAMBLER_DISABLE'] = 0 parameters['SCRAMBLER_DISABLE'] = 0

View File

@@ -27,8 +27,10 @@ module test_taxi_eth_mac_phy_10g_fifo #
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter logic PTP_TD_EN = PTP_TS_EN,
parameter logic PTP_TS_FMT_TOD = 1'b1, parameter logic PTP_TS_FMT_TOD = 1'b1,
parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64,
parameter PTP_TD_SDI_PIPELINE = 2,
parameter TX_TAG_W = 16, parameter TX_TAG_W = 16,
parameter logic BIT_REVERSE = 1'b0, parameter logic BIT_REVERSE = 1'b0,
parameter logic SCRAMBLER_DISABLE = 1'b0, parameter logic SCRAMBLER_DISABLE = 1'b0,
@@ -71,7 +73,6 @@ logic tx_clk;
logic tx_rst; logic tx_rst;
logic logic_clk; logic logic_clk;
logic logic_rst; 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(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(); 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_bitslip;
logic serdes_rx_reset_req; logic serdes_rx_reset_req;
logic [PTP_TS_W-1:0] ptp_ts; logic ptp_clk;
logic ptp_ts_step; 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_clk;
logic stat_rst; logic stat_rst;
@@ -130,8 +141,10 @@ taxi_eth_mac_phy_10g_fifo #(
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TD_EN(PTP_TD_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W), .PTP_TS_W(PTP_TS_W),
.PTP_TD_SDI_PIPELINE(PTP_TD_SDI_PIPELINE),
.BIT_REVERSE(BIT_REVERSE), .BIT_REVERSE(BIT_REVERSE),
.SCRAMBLER_DISABLE(SCRAMBLER_DISABLE), .SCRAMBLER_DISABLE(SCRAMBLER_DISABLE),
.PRBS31_EN(PRBS31_EN), .PRBS31_EN(PRBS31_EN),
@@ -168,7 +181,6 @@ uut (
.tx_rst(tx_rst), .tx_rst(tx_rst),
.logic_clk(logic_clk), .logic_clk(logic_clk),
.logic_rst(logic_rst), .logic_rst(logic_rst),
.ptp_sample_clk(ptp_sample_clk),
/* /*
* Transmit interface (AXI stream) * Transmit interface (AXI stream)
@@ -201,8 +213,18 @@ uut (
/* /*
* PTP clock * PTP clock
*/ */
.ptp_ts(ptp_ts), .ptp_clk(ptp_clk),
.ptp_ts_step(ptp_ts_step), .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 * Statistics