eth: Add gearbox delay compensation for BASE-R RX

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2026-08-27 23:20:01 -07:00
parent cfff289fa9
commit 8afb79a7ed
26 changed files with 643 additions and 211 deletions

View File

@@ -20,69 +20,75 @@ module taxi_axis_baser_rx_32 #
parameter DATA_W = 32,
parameter HDR_W = 2,
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic USXGMII_EN = 1'b0,
parameter logic PTP_TS_EN = 1'b0,
parameter PTP_TS_W = 96
parameter PTP_TS_W = 96,
parameter logic PTP_TS_COR_EN = PTP_TS_EN && GBX_IF_EN,
parameter PTP_TS_COR_W = 16+4
)
(
input wire logic clk,
input wire logic rst,
input wire logic clk,
input wire logic rst,
/*
* 10GBASE-R encoded input
*/
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid,
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid,
input wire logic [GBX_CNT-1:0] rx_gbx_sync = '0,
/*
* Receive interface (AXI stream)
*/
taxi_axis_if.src m_axis_rx,
taxi_axis_if.src m_axis_rx,
/*
* Ordered sets
*/
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
/*
* PTP
*/
input wire logic [PTP_TS_W-1:0] ptp_ts,
input wire logic [PTP_TS_W-1:0] ptp_ts,
output wire logic [GBX_CNT-1:0] ptp_ts_cor_sync,
input wire logic [PTP_TS_COR_W-1:0] ptp_ts_cor_val = '0,
/*
* Configuration
*/
input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1,
input wire logic cfg_rx_enable,
input wire logic cfg_rx_usxgmii_en = 1'b1,
input wire logic cfg_rx_usxgmii_5g = 1'b0,
input wire logic [2:0] cfg_rx_usxgmii_speed = 3'b011,
input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1,
input wire logic cfg_rx_enable,
input wire logic cfg_rx_usxgmii_en = 1'b1,
input wire logic cfg_rx_usxgmii_5g = 1'b0,
input wire logic [2:0] cfg_rx_usxgmii_speed = 3'b011,
/*
* Status
*/
output wire logic rx_start_packet,
output wire logic [2:0] stat_rx_byte,
output wire logic [15:0] stat_rx_pkt_len,
output wire logic stat_rx_pkt_fragment,
output wire logic stat_rx_pkt_jabber,
output wire logic stat_rx_pkt_ucast,
output wire logic stat_rx_pkt_mcast,
output wire logic stat_rx_pkt_bcast,
output wire logic stat_rx_pkt_vlan,
output wire logic stat_rx_pkt_good,
output wire logic stat_rx_pkt_bad,
output wire logic stat_rx_err_oversize,
output wire logic stat_rx_err_bad_fcs,
output wire logic stat_rx_err_bad_block,
output wire logic stat_rx_err_framing,
output wire logic stat_rx_err_preamble
output wire logic rx_start_packet,
output wire logic [2:0] stat_rx_byte,
output wire logic [15:0] stat_rx_pkt_len,
output wire logic stat_rx_pkt_fragment,
output wire logic stat_rx_pkt_jabber,
output wire logic stat_rx_pkt_ucast,
output wire logic stat_rx_pkt_mcast,
output wire logic stat_rx_pkt_bcast,
output wire logic stat_rx_pkt_vlan,
output wire logic stat_rx_pkt_good,
output wire logic stat_rx_pkt_bad,
output wire logic stat_rx_err_oversize,
output wire logic stat_rx_err_bad_fcs,
output wire logic stat_rx_err_bad_block,
output wire logic stat_rx_err_framing,
output wire logic stat_rx_err_preamble
);
// extract parameters
@@ -187,6 +193,8 @@ logic input_start_alt_reg = 1'b0;
logic input_start_d0_reg = 1'b0;
logic input_start_d1_reg = 1'b0;
logic input_start_d2_reg = 1'b0;
logic input_start_int_reg = 1'b0;
logic input_start_lane_reg = 1'b0;
logic [DATA_W-1:0] encoded_rx_data_reg = '0;
logic [HDR_W-1:0] encoded_rx_hdr_reg = '0;
@@ -250,6 +258,11 @@ assign crc_valid[2] = crc_state == ~32'hc622f71d;
assign crc_valid[1] = crc_state == ~32'hb1c2a1a3;
assign crc_valid[0] = crc_state == ~32'h9d6cdf7e;
logic [4+16-1:0] last_ts_reg = '0;
logic [4+16-1:0] ts_inc_reg = '0;
logic gbx_en_reg = 1'b0;
logic [GBX_CNT-1:0] rx_gbx_sync_reg = '0;
assign m_axis_rx.tdata = m_axis_rx_tdata_reg;
assign m_axis_rx.tkeep = m_axis_rx_tkeep_reg;
assign m_axis_rx.tstrb = m_axis_rx.tkeep;
@@ -268,6 +281,8 @@ assign rx_os_valid = rx_os_valid_reg;
assign rx_os_match = rx_os_match_reg[1];
assign rx_idle_match = rx_idle_match_reg[1];
assign ptp_ts_cor_sync = (GBX_IF_EN && PTP_TS_COR_EN) ? rx_gbx_sync_reg : '0;
assign rx_start_packet = start_packet_reg;
assign stat_rx_byte = stat_rx_byte_reg;
@@ -610,6 +625,10 @@ always_ff @(posedge clk) begin
input_valid_reg <= 1'b0;
if (start_packet_reg) begin
ptp_ts_out_reg <= ptp_ts + (PTP_TS_COR_EN ? PTP_TS_W'(ptp_ts_cor_val) + (GBX_IF_EN && gbx_en_reg && input_start_lane_reg ? PTP_TS_W'(ts_inc_reg >> 5) : '0) : '0);
end
if (!(GBX_IF_EN || USXGMII_EN) || input_valid_reg) begin
term_lane_d0_reg <= term_lane_reg;
@@ -648,17 +667,19 @@ always_ff @(posedge clk) begin
input_valid_reg <= 1'b0;
input_start_alt_reg <= 1'b0;
input_start_int_reg <= 1'b0;
if (input_start_d1_reg) begin
ptp_ts_out_reg <= ptp_ts;
if (input_start_int_reg) begin
input_start_lane_reg <= encoded_rx_hdr_valid_reg;
if (!USXGMII_EN || !rep_en_reg) begin
start_packet_reg <= 1'b1;
end
end
if (USXGMII_EN && rep_start_reg && !rep_stall_reg) begin
ptp_ts_out_reg <= ptp_ts;
if (USXGMII_EN && rep_start_reg && rep_cnt_reg == 0) begin
input_start_lane_reg <= encoded_rx_hdr_valid_reg;
start_packet_reg <= 1'b1;
rep_start_reg <= 1'b0;
end
if (encoded_rx_hdr_valid_reg) begin
@@ -721,6 +742,7 @@ always_ff @(posedge clk) begin
input_data_d0_reg <= encoded_rx_data_reg;
input_valid_reg <= 1'b1;
input_start_d0_reg <= 1'b1;
input_start_int_reg <= 1'b1;
framing_error_reg <= frame_reg;
frame_reg <= 1'b1;
end
@@ -853,6 +875,7 @@ always_ff @(posedge clk) begin
if (input_start_alt_reg) begin
input_start_d0_reg <= 1'b1;
input_start_int_reg <= 1'b1;
input_valid_reg <= 1'b1;
end
@@ -924,7 +947,7 @@ always_ff @(posedge clk) begin
end
end else if (rep_cnt_reg == 0) begin
rep_en_reg <= 1'b1;
rep_start_reg <= input_start_d2_reg;
rep_start_reg <= input_start_d1_reg;
if (cfg_rx_usxgmii_5g) begin
case (cfg_rx_usxgmii_speed)
3'b000: rep_cnt_reg <= 499; // 10 Mbps
@@ -932,7 +955,7 @@ always_ff @(posedge clk) begin
3'b010: rep_cnt_reg <= 4; // 1 Gbps
3'b100: begin
rep_cnt_reg <= 1; // 2.5 Gbps
rep_start_reg <= input_start_d1_reg;
rep_start_reg <= input_start_int_reg;
end
default: begin
// 5 Gbps
@@ -949,7 +972,7 @@ always_ff @(posedge clk) begin
3'b100: rep_cnt_reg <= 3; // 2.5 Gbps
3'b101: begin
rep_cnt_reg <= 1; // 5 Gbps
rep_start_reg <= input_start_d1_reg;
rep_start_reg <= input_start_int_reg;
end
default: begin
// 10 Gbps
@@ -973,6 +996,15 @@ always_ff @(posedge clk) begin
end
end
last_ts_reg <= (4+16)'(ptp_ts);
ts_inc_reg <= (4+16)'(ptp_ts) - last_ts_reg;
if (rx_gbx_sync || !encoded_rx_data_valid) begin
gbx_en_reg <= 1'b1;
end
rx_gbx_sync_reg <= rx_gbx_sync;
if (rst) begin
state_reg <= STATE_IDLE;
@@ -992,6 +1024,9 @@ always_ff @(posedge clk) begin
start_packet_reg <= 1'b0;
frame_reg <= 1'b0;
gbx_en_reg <= 1'b0;
rx_gbx_sync_reg <= '0;
stat_rx_byte_reg <= '0;
stat_rx_pkt_len_reg <= '0;
stat_rx_pkt_fragment_reg <= 1'b0;
@@ -1012,6 +1047,8 @@ always_ff @(posedge clk) begin
input_start_d0_reg <= 1'b0;
input_start_d1_reg <= 1'b0;
input_start_d2_reg <= 1'b0;
input_start_int_reg <= 1'b0;
input_start_lane_reg <= 1'b0;
end
end

View File

@@ -20,70 +20,76 @@ module taxi_axis_baser_rx_64 #
parameter DATA_W = 64,
parameter HDR_W = 2,
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic USXGMII_EN = 1'b0,
parameter logic PTP_TS_EN = 1'b0,
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 logic PTP_TS_COR_EN = PTP_TS_EN && GBX_IF_EN,
parameter PTP_TS_COR_W = 16+4
)
(
input wire logic clk,
input wire logic rst,
input wire logic clk,
input wire logic rst,
/*
* 10GBASE-R encoded input
*/
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid,
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid,
input wire logic [GBX_CNT-1:0] rx_gbx_sync = '0,
/*
* Receive interface (AXI stream)
*/
taxi_axis_if.src m_axis_rx,
taxi_axis_if.src m_axis_rx,
/*
* Ordered sets
*/
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
/*
* PTP
*/
input wire logic [PTP_TS_W-1:0] ptp_ts,
input wire logic [PTP_TS_W-1:0] ptp_ts,
output wire logic [GBX_CNT-1:0] ptp_ts_cor_sync,
input wire logic [PTP_TS_COR_W-1:0] ptp_ts_cor_val = '0,
/*
* Configuration
*/
input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1,
input wire logic cfg_rx_enable,
input wire logic cfg_rx_usxgmii_en = 1'b1,
input wire logic cfg_rx_usxgmii_5g = 1'b0,
input wire logic [2:0] cfg_rx_usxgmii_speed = 3'b011,
input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1,
input wire logic cfg_rx_enable,
input wire logic cfg_rx_usxgmii_en = 1'b1,
input wire logic cfg_rx_usxgmii_5g = 1'b0,
input wire logic [2:0] cfg_rx_usxgmii_speed = 3'b011,
/*
* Status
*/
output wire logic [1:0] rx_start_packet,
output wire logic [3:0] stat_rx_byte,
output wire logic [15:0] stat_rx_pkt_len,
output wire logic stat_rx_pkt_fragment,
output wire logic stat_rx_pkt_jabber,
output wire logic stat_rx_pkt_ucast,
output wire logic stat_rx_pkt_mcast,
output wire logic stat_rx_pkt_bcast,
output wire logic stat_rx_pkt_vlan,
output wire logic stat_rx_pkt_good,
output wire logic stat_rx_pkt_bad,
output wire logic stat_rx_err_oversize,
output wire logic stat_rx_err_bad_fcs,
output wire logic stat_rx_err_bad_block,
output wire logic stat_rx_err_framing,
output wire logic stat_rx_err_preamble
output wire logic [1:0] rx_start_packet,
output wire logic [3:0] stat_rx_byte,
output wire logic [15:0] stat_rx_pkt_len,
output wire logic stat_rx_pkt_fragment,
output wire logic stat_rx_pkt_jabber,
output wire logic stat_rx_pkt_ucast,
output wire logic stat_rx_pkt_mcast,
output wire logic stat_rx_pkt_bcast,
output wire logic stat_rx_pkt_vlan,
output wire logic stat_rx_pkt_good,
output wire logic stat_rx_pkt_bad,
output wire logic stat_rx_err_oversize,
output wire logic stat_rx_err_bad_fcs,
output wire logic stat_rx_err_bad_block,
output wire logic stat_rx_err_framing,
output wire logic stat_rx_err_preamble
);
// extract parameters
@@ -179,6 +185,9 @@ logic input_start_swap_reg = 1'b0;
logic input_start_d0_reg = 1'b0;
logic input_start_d1_reg = 1'b0;
logic encoded_rx_data_valid_d0_reg = 1'b0;
logic [1:0] encoded_rx_start_remap_d0_reg = 2'b00;
logic frame_oversize_reg = 1'b0, frame_oversize_next;
logic pre_ok_reg = 1'b0, pre_ok_next;
logic [1:0] hdr_ptr_reg = '0, hdr_ptr_next;
@@ -244,6 +253,8 @@ assign crc_valid[0] = crc_state_reg == ~32'h6b87b1ec;
logic [4+16-1:0] last_ts_reg = '0;
logic [4+16-1:0] ts_inc_reg = '0;
logic [4+16-1:0] ts_offs_reg = '0;
logic gbx_en_reg = 1'b0;
assign m_axis_rx.tdata = m_axis_rx_tdata_reg;
assign m_axis_rx.tkeep = m_axis_rx_tkeep_reg;
@@ -320,6 +331,7 @@ if (USXGMII_EN) begin : usxgmii
logic [3:0] encoded_rx_type_remap_reg = '0;
logic encoded_rx_data_remap_valid_reg = 1'b0;
logic [1:0] encoded_rx_start_remap_reg = '0;
logic [GBX_CNT-1:0] rx_gbx_sync_reg = '0;
logic [8:0] rep_cnt_reg = '0;
logic rep_stall_reg = 1'b0;
@@ -333,8 +345,11 @@ if (USXGMII_EN) begin : usxgmii
assign encoded_rx_data_remap_valid = encoded_rx_data_remap_valid_reg;
assign encoded_rx_start_remap = encoded_rx_start_remap_reg;
assign ptp_ts_cor_sync = (GBX_IF_EN && PTP_TS_COR_EN) ? rx_gbx_sync_reg : '0;
always_ff @(posedge clk) begin
encoded_rx_data_remap_valid_reg <= 1'b0;
rx_gbx_sync_reg <= rx_gbx_sync;
if (!GBX_IF_EN || encoded_rx_data_valid) begin
@@ -543,6 +558,8 @@ if (USXGMII_EN) begin : usxgmii
encoded_rx_data_remap_valid_reg <= 1'b0;
encoded_rx_start_remap_reg <= '0;
rx_gbx_sync_reg <= '0;
rep_cnt_reg <= '0;
rep_stall_reg <= 1'b0;
rep_en_reg <= 1'b0;
@@ -559,6 +576,8 @@ end else begin
assign encoded_rx_start_remap[0] = encoded_rx_hdr[0] == SYNC_CTRL[0] && encoded_rx_data[7:4] == BLOCK_TYPE_START_0[7:4];
assign encoded_rx_start_remap[1] = encoded_rx_hdr[0] == SYNC_CTRL[0] && (encoded_rx_data[7:4] == BLOCK_TYPE_START_4[7:4] || encoded_rx_data[7:4] == BLOCK_TYPE_OS_START[7:4]);
assign ptp_ts_cor_sync = (GBX_IF_EN && PTP_TS_COR_EN) ? rx_gbx_sync : '0;
end
// FCS verification
@@ -866,24 +885,27 @@ always_ff @(posedge clk) begin
stat_rx_err_framing_reg <= stat_rx_err_framing_next;
stat_rx_err_preamble_reg <= stat_rx_err_preamble_next;
if (!GBX_IF_EN || encoded_rx_data_valid) begin
encoded_rx_data_valid_d0_reg <= encoded_rx_data_valid;
encoded_rx_start_remap_d0_reg <= encoded_rx_start_remap;
if (!GBX_IF_EN || encoded_rx_data_valid_d0_reg) begin
// capture timestamps
if (encoded_rx_start_remap[1]) begin
if (encoded_rx_start_remap_d0_reg[1]) 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[45:0] <= ptp_ts[45:0] + (GBX_IF_EN ? 46'(ts_offs_reg) : 46'(ts_inc_reg >> 1)) + (PTP_TS_COR_EN ? 46'(ptp_ts_cor_val) : '0);
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);
ptp_ts_reg <= ptp_ts + (GBX_IF_EN ? PTP_TS_W'(ts_offs_reg) : PTP_TS_W'(ts_inc_reg >> 1)) + (PTP_TS_COR_EN ? PTP_TS_W'(ptp_ts_cor_val) : '0);
end
end
if (encoded_rx_start_remap[0]) begin
if (encoded_rx_start_remap_d0_reg[0]) begin
start_packet_reg <= 2'b01;
ptp_ts_reg <= ptp_ts;
ptp_ts_reg <= ptp_ts + (PTP_TS_COR_EN ? PTP_TS_W'(ptp_ts_cor_val) : '0);
end
end
@@ -1168,6 +1190,11 @@ always_ff @(posedge clk) begin
last_ts_reg <= (4+16)'(ptp_ts);
ts_inc_reg <= (4+16)'(ptp_ts) - last_ts_reg;
ts_offs_reg <= (ts_inc_reg >> 1) + (gbx_en_reg ? ts_inc_reg >> 6 : '0);
if (rx_gbx_sync || !encoded_rx_data_valid) begin
gbx_en_reg <= 1'b1;
end
if (rst) begin
state_reg <= STATE_IDLE;
@@ -1181,6 +1208,8 @@ always_ff @(posedge clk) begin
start_packet_reg <= 2'b00;
frame_reg <= 1'b0;
gbx_en_reg <= 1'b0;
stat_rx_byte_reg <= '0;
stat_rx_pkt_len_reg <= '0;
stat_rx_pkt_fragment_reg <= 1'b0;
@@ -1201,6 +1230,9 @@ always_ff @(posedge clk) begin
input_start_d0_reg <= 1'b0;
input_start_d1_reg <= 1'b0;
encoded_rx_data_valid_d0_reg <= 1'b0;
encoded_rx_start_remap_d0_reg <= 2'b00;
lanes_swapped_reg <= 1'b0;
lanes_swapped_d1_reg <= 1'b0;
end

View File

@@ -80,6 +80,7 @@ module taxi_eth_mac_phy_10g #
input wire logic serdes_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid = 1'b1,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -559,6 +560,7 @@ eth_mac_phy_10g_rx_inst (
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
/*
* Ordered sets

View File

@@ -93,6 +93,7 @@ module taxi_eth_mac_phy_10g_fifo #
input wire logic serdes_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid = 1'b1,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -386,6 +387,7 @@ eth_mac_phy_10g_inst (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),

View File

@@ -50,6 +50,7 @@ module taxi_eth_mac_phy_10g_rx #
input wire logic serdes_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid = 1'b1,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -109,6 +110,8 @@ wire encoded_rx_data_valid;
wire [HDR_W-1:0] encoded_rx_hdr;
wire encoded_rx_hdr_valid;
wire rx_gbx_sync;
taxi_eth_phy_10g_rx_if #(
.DATA_W(DATA_W),
.HDR_W(HDR_W),
@@ -132,6 +135,7 @@ eth_phy_10g_rx_if_inst (
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* SERDES interface
@@ -140,6 +144,7 @@ eth_phy_10g_rx_if_inst (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),
@@ -165,10 +170,13 @@ if (DATA_W == 64) begin
.DATA_W(DATA_W),
.HDR_W(HDR_W),
.GBX_IF_EN(GBX_IF_EN),
.GBX_CNT(1),
.USXGMII_EN(USXGMII_EN),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W)
.PTP_TS_W(PTP_TS_W),
.PTP_TS_COR_EN(PTP_TS_COR_EN),
.PTP_TS_COR_W(PTP_TS_COR_W)
)
axis_baser_rx_inst (
.clk(clk),
@@ -181,6 +189,7 @@ if (DATA_W == 64) begin
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* Receive interface (AXI stream)
@@ -200,6 +209,8 @@ if (DATA_W == 64) begin
* PTP
*/
.ptp_ts(ptp_ts),
.ptp_ts_cor_sync(ptp_ts_cor_sync),
.ptp_ts_cor_val(ptp_ts_cor_val),
/*
* Configuration
@@ -237,9 +248,12 @@ end else begin
.DATA_W(DATA_W),
.HDR_W(HDR_W),
.GBX_IF_EN(GBX_IF_EN),
.GBX_CNT(1),
.USXGMII_EN(USXGMII_EN),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_W(PTP_TS_W)
.PTP_TS_W(PTP_TS_W),
.PTP_TS_COR_EN(PTP_TS_COR_EN),
.PTP_TS_COR_W(PTP_TS_COR_W)
)
axis_baser_rx_inst (
.clk(clk),
@@ -252,6 +266,7 @@ end else begin
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* Receive interface (AXI stream)
@@ -271,6 +286,8 @@ end else begin
* PTP
*/
.ptp_ts(ptp_ts),
.ptp_ts_cor_sync(ptp_ts_cor_sync),
.ptp_ts_cor_val(ptp_ts_cor_val),
/*
* Configuration

View File

@@ -49,6 +49,7 @@ module taxi_eth_phy_10g #
output wire logic tx_gbx_req_sync,
output wire logic tx_gbx_req_stall,
input wire logic tx_gbx_sync = 1'b0,
output wire logic rx_gbx_sync,
/*
* SERDES interface
@@ -64,6 +65,7 @@ module taxi_eth_phy_10g #
input wire logic serdes_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid = 1'b1,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -108,6 +110,7 @@ eth_phy_10g_rx_inst (
.xgmii_rxd(xgmii_rxd),
.xgmii_rxc(xgmii_rxc),
.xgmii_rx_valid(xgmii_rx_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* SERDES interface
@@ -116,6 +119,7 @@ eth_phy_10g_rx_inst (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),

View File

@@ -39,6 +39,7 @@ module taxi_eth_phy_10g_rx #
output wire logic [DATA_W-1:0] xgmii_rxd,
output wire logic [CTRL_W-1:0] xgmii_rxc,
output wire logic xgmii_rx_valid,
output wire logic rx_gbx_sync,
/*
* SERDES interface
@@ -47,6 +48,7 @@ module taxi_eth_phy_10g_rx #
input wire logic serdes_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid = 1'b1,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -71,6 +73,8 @@ wire encoded_rx_data_valid;
wire [HDR_W-1:0] encoded_rx_hdr;
wire encoded_rx_hdr_valid;
wire rx_gbx_sync_int;
taxi_eth_phy_10g_rx_if #(
.DATA_W(DATA_W),
.HDR_W(HDR_W),
@@ -94,6 +98,7 @@ eth_phy_10g_rx_if_inst (
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync_int),
/*
* SERDES interface
@@ -102,6 +107,7 @@ eth_phy_10g_rx_if_inst (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),
@@ -138,6 +144,7 @@ xgmii_baser_dec_inst (
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync_in(rx_gbx_sync_int),
/*
* XGMII interface
@@ -145,6 +152,7 @@ xgmii_baser_dec_inst (
.xgmii_rxd(xgmii_rxd),
.xgmii_rxc(xgmii_rxc),
.xgmii_rx_valid(xgmii_rx_valid),
.rx_gbx_sync_out(rx_gbx_sync),
/*
* Ordered sets

View File

@@ -39,6 +39,7 @@ module taxi_eth_phy_10g_rx_if #
output wire logic encoded_rx_data_valid,
output wire logic [HDR_W-1:0] encoded_rx_hdr,
output wire logic encoded_rx_hdr_valid,
output wire logic rx_gbx_sync,
/*
* SERDES interface
@@ -47,6 +48,7 @@ module taxi_eth_phy_10g_rx_if #
input wire logic serdes_rx_data_valid,
input wire logic [HDR_W-1:0] serdes_rx_hdr,
input wire logic serdes_rx_hdr_valid,
input wire logic serdes_rx_gbx_sync = 1'b0,
output wire logic serdes_rx_bitslip,
output wire logic serdes_rx_reset_req,
@@ -79,6 +81,7 @@ wire [DATA_W-1:0] serdes_rx_data_rev, serdes_rx_data_int;
wire serdes_rx_data_valid_int;
wire [HDR_W-1:0] serdes_rx_hdr_rev, serdes_rx_hdr_int;
wire serdes_rx_hdr_valid_int;
wire serdes_rx_gbx_sync_int;
if (BIT_REVERSE) begin
for (genvar n = 0; n < DATA_W; n = n + 1) begin
@@ -102,6 +105,8 @@ if (SERDES_PIPELINE > 0) begin
logic [HDR_W-1:0] serdes_rx_hdr_pipe_reg[SERDES_PIPELINE-1:0] = '{default: '0};
(* srl_style = "register" *)
logic serdes_rx_hdr_valid_pipe_reg[SERDES_PIPELINE-1:0] = '{default: '0};
(* srl_style = "register" *)
logic serdes_rx_gbx_sync_pipe_reg[SERDES_PIPELINE-1:0] = '{default: '0};
for (genvar n = 0; n < SERDES_PIPELINE; n = n + 1) begin
always_ff @(posedge clk) begin
@@ -109,6 +114,7 @@ if (SERDES_PIPELINE > 0) begin
serdes_rx_data_valid_pipe_reg[n] <= n == 0 ? serdes_rx_data_valid : serdes_rx_data_valid_pipe_reg[n-1];
serdes_rx_hdr_pipe_reg[n] <= n == 0 ? serdes_rx_hdr_rev : serdes_rx_hdr_pipe_reg[n-1];
serdes_rx_hdr_valid_pipe_reg[n] <= n == 0 ? serdes_rx_hdr_valid : serdes_rx_hdr_valid_pipe_reg[n-1];
serdes_rx_gbx_sync_pipe_reg[n] <= n == 0 ? serdes_rx_gbx_sync : serdes_rx_gbx_sync_pipe_reg[n-1];
end
end
@@ -116,11 +122,13 @@ if (SERDES_PIPELINE > 0) begin
assign serdes_rx_data_valid_int = GBX_IF_EN ? serdes_rx_data_valid_pipe_reg[SERDES_PIPELINE-1] : 1'b1;
assign serdes_rx_hdr_int = serdes_rx_hdr_pipe_reg[SERDES_PIPELINE-1];
assign serdes_rx_hdr_valid_int = USE_HDR_VLD ? serdes_rx_hdr_valid_pipe_reg[SERDES_PIPELINE-1] : 1'b1;
assign serdes_rx_gbx_sync_int = GBX_IF_EN ? serdes_rx_gbx_sync_pipe_reg[SERDES_PIPELINE-1] : 1'b0;
end else begin
assign serdes_rx_data_int = serdes_rx_data_rev;
assign serdes_rx_data_valid_int = GBX_IF_EN ? serdes_rx_data_valid : 1'b1;
assign serdes_rx_hdr_int = serdes_rx_hdr_rev;
assign serdes_rx_hdr_valid_int = USE_HDR_VLD ? serdes_rx_hdr_valid : 1'b1;
assign serdes_rx_gbx_sync_int = GBX_IF_EN ? serdes_rx_gbx_sync : 1'b0;
end
wire [DATA_W-1:0] descrambled_rx_data;
@@ -129,6 +137,7 @@ logic [DATA_W-1:0] encoded_rx_data_reg = '0;
logic encoded_rx_data_valid_reg = 1'b0;
logic [HDR_W-1:0] encoded_rx_hdr_reg = '0;
logic encoded_rx_hdr_valid_reg = 1'b0;
logic rx_gbx_sync_reg = 1'b0;
logic [57:0] scrambler_state_reg = '1;
wire [57:0] scrambler_state;
@@ -201,6 +210,7 @@ always_ff @(posedge clk) begin
encoded_rx_data_valid_reg <= serdes_rx_data_valid_int;
encoded_rx_hdr_reg <= serdes_rx_hdr_int;
encoded_rx_hdr_valid_reg <= serdes_rx_hdr_valid_int;
rx_gbx_sync_reg <= serdes_rx_gbx_sync_int;
if (PRBS31_EN) begin
if (cfg_rx_prbs31_enable && (!GBX_IF_EN || serdes_rx_data_valid_int)) begin
@@ -222,6 +232,7 @@ assign encoded_rx_data = encoded_rx_data_reg;
assign encoded_rx_data_valid = GBX_IF_EN ? encoded_rx_data_valid_reg : 1'b1;
assign encoded_rx_hdr = encoded_rx_hdr_reg;
assign encoded_rx_hdr_valid = USE_HDR_VLD ? encoded_rx_hdr_valid_reg : 1'b1;
assign rx_gbx_sync = GBX_IF_EN ? rx_gbx_sync_reg : 1'b1;
assign rx_error_count = rx_error_count_reg;

View File

@@ -20,7 +20,8 @@ module taxi_xgmii_baser_dec #
parameter DATA_W = 64,
parameter CTRL_W = (DATA_W/8),
parameter HDR_W = 2,
parameter logic GBX_IF_EN = 1'b0
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1
)
(
input wire logic clk,
@@ -29,32 +30,34 @@ module taxi_xgmii_baser_dec #
/*
* 10GBASE-R encoded input
*/
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid = 1'b1,
input wire logic [DATA_W-1:0] encoded_rx_data,
input wire logic encoded_rx_data_valid = 1'b1,
input wire logic [HDR_W-1:0] encoded_rx_hdr,
input wire logic encoded_rx_hdr_valid = 1'b1,
input wire logic [GBX_CNT-1:0] rx_gbx_sync_in = '0,
/*
* XGMII interface
*/
output wire logic [DATA_W-1:0] xgmii_rxd,
output wire logic [CTRL_W-1:0] xgmii_rxc,
output wire logic xgmii_rx_valid,
output wire logic [DATA_W-1:0] xgmii_rxd,
output wire logic [CTRL_W-1:0] xgmii_rxc,
output wire logic xgmii_rx_valid,
output wire logic rx_gbx_sync_out,
/*
* Ordered sets
*/
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
output wire logic [23:0] rx_os,
output wire logic rx_os_sig,
output wire logic rx_os_valid,
output wire logic rx_os_match,
output wire logic rx_idle_match,
/*
* Status
*/
output wire logic rx_bad_block,
output wire logic rx_sequence_error
output wire logic rx_bad_block,
output wire logic rx_sequence_error
);
localparam DATA_W_INT = 64;
@@ -138,6 +141,7 @@ logic [CTRL_W_INT-1:0] decode_err;
logic [DATA_W_INT-1:0] xgmii_rxd_reg = '0, xgmii_rxd_next;
logic [CTRL_W_INT-1:0] xgmii_rxc_reg = '0, xgmii_rxc_next;
logic [SEG_CNT-1:0] xgmii_rx_valid_reg = '0, xgmii_rx_valid_next;
logic [GBX_CNT-1:0] rx_gbx_sync_reg = '0, rx_gbx_sync_next;
logic [23:0] rx_os_reg = '0, rx_os_next;
logic rx_os_sig_reg = 1'b0, rx_os_sig_next;
@@ -557,12 +561,15 @@ always_comb begin
xgmii_rxc_next = '1;
rx_bad_block_next = 1'b1;
end
rx_gbx_sync_next = rx_gbx_sync_in;
end
always_ff @(posedge clk) begin
xgmii_rxd_reg <= xgmii_rxd_next;
xgmii_rxc_reg <= xgmii_rxc_next;
xgmii_rx_valid_reg <= xgmii_rx_valid_next;
rx_gbx_sync_reg <= rx_gbx_sync_next;
rx_os_reg <= rx_os_next;
rx_os_sig_reg <= rx_os_sig_next;
@@ -576,6 +583,7 @@ always_ff @(posedge clk) begin
if (rst) begin
xgmii_rx_valid_reg <= '0;
rx_gbx_sync_reg <= '0;
rx_os_valid_reg <= 1'b0;
rx_os_match_reg <= '0;
rx_idle_match_reg <= '0;

View File

@@ -338,6 +338,7 @@ wire [DATA_W-1:0] serdes_rx_data;
wire serdes_rx_data_valid;
wire [HDR_W-1:0] serdes_rx_hdr;
wire serdes_rx_hdr_valid;
wire serdes_rx_gbx_sync;
wire serdes_rx_bitslip;
wire tx_ptp_ts_cor_sync;
@@ -376,7 +377,9 @@ if (GT_7) begin : gt
// MAC/PHY parameters
.DATA_W(DATA_W),
.HDR_W(HDR_W)
.HDR_W(HDR_W),
.TS_FNS_W(PTP_TS_FNS_W),
.TS_COR_W(PTP_TS_COR_W)
)
gt_inst (
.xcvr_ctrl_clk(xcvr_ctrl_clk),
@@ -437,7 +440,18 @@ if (GT_7) begin : gt
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_bitslip(serdes_rx_bitslip)
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
/*
* Timestamp correction
*/
.tx_ts_cor_sync(tx_ptp_ts_cor_sync),
.tx_ts_inc(20'h31a60), // TODO
.tx_ts_cor_val(tx_ptp_ts_cor_val),
.rx_ts_cor_sync(rx_ptp_ts_cor_sync),
.rx_ts_inc(20'h31a60), // TODO
.rx_ts_cor_val(rx_ptp_ts_cor_val)
);
assign xcvr_gtpowergood_out = 1'b1;
@@ -446,9 +460,6 @@ if (GT_7) begin : gt
assign xcvr_qpll1clk_out = 1'b0;
assign xcvr_qpll1refclk_out = 1'b0;
assign tx_ptp_ts_cor_val = '0;
assign rx_ptp_ts_cor_val = '0;
end else if (DATA_W == 64 && CFG_LOW_LATENCY) begin : gt
taxi_eth_phy_25g_us_gt_ll #(
@@ -562,6 +573,7 @@ end else if (DATA_W == 64 && CFG_LOW_LATENCY) begin : gt
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
/*
@@ -689,6 +701,7 @@ end else if (DATA_W == 64 && !CFG_LOW_LATENCY) begin : gt
.serdes_rx_bitslip(serdes_rx_bitslip)
);
assign serdes_rx_gbx_sync = '0;
assign tx_ptp_ts_cor_val = '0;
assign rx_ptp_ts_cor_val = '0;
@@ -805,6 +818,7 @@ end else if (DATA_W == 32 && CFG_LOW_LATENCY) begin : gt
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
/*
@@ -932,6 +946,7 @@ end else if (DATA_W == 32 && !CFG_LOW_LATENCY) begin : gt
.serdes_rx_bitslip(serdes_rx_bitslip)
);
assign serdes_rx_gbx_sync = '0;
assign tx_ptp_ts_cor_val = '0;
assign rx_ptp_ts_cor_val = '0;
@@ -1007,6 +1022,7 @@ if (COMBINED_MAC_PCS) begin : mac
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(rx_reset_req),
@@ -1200,6 +1216,7 @@ end else begin : mac
wire tx_gbx_req_sync;
wire tx_gbx_req_stall;
wire tx_gbx_sync;
wire rx_gbx_sync;
taxi_eth_phy_10g #(
.DATA_W(DATA_W),
@@ -1234,6 +1251,7 @@ end else begin : mac
.tx_gbx_req_sync(tx_gbx_req_sync),
.tx_gbx_req_stall(tx_gbx_req_stall),
.tx_gbx_sync(tx_gbx_sync),
.rx_gbx_sync(rx_gbx_sync),
/*
* SERDES interface
@@ -1249,6 +1267,7 @@ end else begin : mac
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(rx_reset_req),

View File

@@ -45,68 +45,81 @@ module taxi_eth_phy_10g_7_gt #
// MAC/PHY parameters
parameter DATA_W = 32,
parameter HDR_W = 2
parameter HDR_W = 2,
parameter TS_FNS_W = 16,
parameter TS_COR_W = TS_FNS_W+4
)
(
input wire logic xcvr_ctrl_clk,
input wire logic xcvr_ctrl_rst,
input wire logic xcvr_ctrl_clk,
input wire logic xcvr_ctrl_rst,
/*
* Transceiver control
*/
taxi_apb_if.slv s_apb_ctrl,
taxi_apb_if.slv s_apb_ctrl,
/*
* PLL out
*/
input wire logic xcvr_gtrefclk0_in = 1'b0,
input wire logic xcvr_qpllpd_in = 1'b0,
input wire logic xcvr_qpllreset_in = 1'b0,
input wire logic [2:0] xcvr_qpllpcierate_in = 3'd0,
output wire logic xcvr_qplllock_out,
output wire logic xcvr_qpllclk_out,
output wire logic xcvr_qpllrefclk_out,
input wire logic xcvr_gtrefclk0_in = 1'b0,
input wire logic xcvr_qpllpd_in = 1'b0,
input wire logic xcvr_qpllreset_in = 1'b0,
input wire logic [2:0] xcvr_qpllpcierate_in = 3'd0,
output wire logic xcvr_qplllock_out,
output wire logic xcvr_qpllclk_out,
output wire logic xcvr_qpllrefclk_out,
/*
* PLL in
*/
input wire logic xcvr_qplllock_in = 1'b0,
input wire logic xcvr_qpllclk_in = 1'b0,
input wire logic xcvr_qpllrefclk_in = 1'b0,
input wire logic xcvr_qplllock_in = 1'b0,
input wire logic xcvr_qpllclk_in = 1'b0,
input wire logic xcvr_qpllrefclk_in = 1'b0,
/*
* Serial data
*/
output wire logic xcvr_txp,
output wire logic xcvr_txn,
input wire logic xcvr_rxp,
input wire logic xcvr_rxn,
output wire logic xcvr_txp,
output wire logic xcvr_txn,
input wire logic xcvr_rxp,
input wire logic xcvr_rxn,
/*
* GT user clocks
*/
output wire logic rx_clk,
input wire logic rx_rst_in = 1'b0,
output wire logic rx_rst_out,
output wire logic tx_clk,
input wire logic tx_rst_in = 1'b0,
output wire logic tx_rst_out,
output wire logic rx_clk,
input wire logic rx_rst_in = 1'b0,
output wire logic rx_rst_out,
output wire logic tx_clk,
input wire logic tx_rst_in = 1'b0,
output wire logic tx_rst_out,
/*
* Serdes interface
*/
input wire logic [DATA_W-1:0] serdes_tx_data,
input wire logic serdes_tx_data_valid,
input wire logic [HDR_W-1:0] serdes_tx_hdr,
input wire logic serdes_tx_hdr_valid,
output wire logic serdes_tx_gbx_req_sync,
output wire logic serdes_tx_gbx_req_stall,
input wire logic serdes_tx_gbx_sync,
output wire logic [DATA_W-1:0] serdes_rx_data,
output wire logic serdes_rx_data_valid,
output wire logic [HDR_W-1:0] serdes_rx_hdr,
output wire logic serdes_rx_hdr_valid,
input wire logic serdes_rx_bitslip
input wire logic [DATA_W-1:0] serdes_tx_data,
input wire logic serdes_tx_data_valid,
input wire logic [HDR_W-1:0] serdes_tx_hdr,
input wire logic serdes_tx_hdr_valid,
output wire logic serdes_tx_gbx_req_sync,
output wire logic serdes_tx_gbx_req_stall,
input wire logic serdes_tx_gbx_sync,
output wire logic [DATA_W-1:0] serdes_rx_data,
output wire logic serdes_rx_data_valid,
output wire logic [HDR_W-1:0] serdes_rx_hdr,
output wire logic serdes_rx_hdr_valid,
output wire logic serdes_rx_gbx_sync,
input wire logic serdes_rx_bitslip,
/*
* Timestamp correction
*/
input wire logic tx_ts_cor_sync = 1'b0,
input wire logic [TS_COR_W-1:0] tx_ts_inc = 20'h31a60,
output wire logic [TS_COR_W-1:0] tx_ts_cor_val,
input wire logic rx_ts_cor_sync = 1'b0,
input wire logic [TS_COR_W-1:0] rx_ts_inc = 20'h31a60,
output wire logic [TS_COR_W-1:0] rx_ts_cor_val
);
// check configuration
@@ -519,6 +532,14 @@ if (!SIM) begin
assign serdes_rx_hdr_valid = gt_rxheadervalid[0];
end
logic serdes_rx_data_valid_last_reg = 1'b0;
assign serdes_rx_gbx_sync = serdes_rx_data_valid && !serdes_rx_data_valid_last_reg;
always_ff @(posedge rx_clk) begin
serdes_rx_data_valid_last_reg <= serdes_rx_data_valid;
end
// 66 clock cycle sequence, with two stalls on cycles 64 and 65
// 32-bit internal, 32-bit external datapath width
@@ -559,6 +580,46 @@ always_ff @(posedge tx_clk) begin
end
end
// Generate TX timestamp correction
logic [6:0] tx_ts_cor_seq_reg = '0;
logic [TS_COR_W-1:0] tx_ts_cor_val_reg = '0;
assign tx_ts_cor_val = tx_ts_cor_val_reg;
always_ff @(posedge tx_clk) begin
tx_ts_cor_seq_reg <= tx_ts_cor_seq_reg + 1;
if (tx_ts_cor_seq_reg[0]) begin
tx_ts_cor_val_reg <= tx_ts_cor_val_reg + (tx_ts_inc >> 4);
end
if (tx_ts_cor_seq_reg == 65) begin
tx_ts_cor_seq_reg <= '0;
tx_ts_cor_val_reg <= '0;
end
if (tx_ts_cor_sync) begin
tx_ts_cor_seq_reg <= 1;
end
end
// Generate RX timestamp correction
logic [6:0] rx_ts_cor_seq_reg = '0;
logic [TS_COR_W-1:0] rx_ts_cor_val_reg = '0;
assign rx_ts_cor_val = rx_ts_cor_val_reg;
always_ff @(posedge rx_clk) begin
rx_ts_cor_seq_reg <= rx_ts_cor_seq_reg + 1;
if (rx_ts_cor_seq_reg[0]) begin
rx_ts_cor_val_reg <= rx_ts_cor_val_reg + (tx_ts_inc >> 4);
end
if (rx_ts_cor_seq_reg == 65) begin
rx_ts_cor_seq_reg <= '0;
rx_ts_cor_val_reg <= '0; // TODO odd offset
end
if (rx_ts_cor_sync) begin
rx_ts_cor_seq_reg <= 1;
end
end
if (SIM) begin : xcvr
// simulation (no GT core)

View File

@@ -127,6 +127,7 @@ module taxi_eth_phy_10g_us_gt_ll #
output wire logic serdes_rx_data_valid,
output wire logic [HDR_W-1:0] serdes_rx_hdr,
output wire logic serdes_rx_hdr_valid,
output wire logic serdes_rx_gbx_sync,
input wire logic serdes_rx_bitslip,
/*
@@ -558,6 +559,14 @@ if (!SIM) begin
assign serdes_rx_hdr_valid = gt_rxheadervalid[0];
end
logic serdes_rx_data_valid_last_reg = 1'b0;
assign serdes_rx_gbx_sync = serdes_rx_data_valid && !serdes_rx_data_valid_last_reg;
always_ff @(posedge rx_clk) begin
serdes_rx_data_valid_last_reg <= serdes_rx_data_valid;
end
// 66 clock cycle sequence, with two stalls on cycles 64 and 65
// 32-bit internal, 32-bit external datapath width
@@ -627,11 +636,11 @@ assign rx_ts_cor_val = rx_ts_cor_val_reg;
always_ff @(posedge rx_clk) begin
rx_ts_cor_seq_reg <= rx_ts_cor_seq_reg + 1;
if (rx_ts_cor_seq_reg[0]) begin
rx_ts_cor_val_reg <= rx_ts_cor_val_reg - (tx_ts_inc >> 4);
rx_ts_cor_val_reg <= rx_ts_cor_val_reg + (tx_ts_inc >> 4);
end
if (rx_ts_cor_seq_reg == 65) begin
rx_ts_cor_seq_reg <= '0;
rx_ts_cor_val_reg <= rx_ts_inc << 1; // TODO odd offset
rx_ts_cor_val_reg <= '0; // TODO odd offset
end
if (rx_ts_cor_sync) begin
rx_ts_cor_seq_reg <= 1;

View File

@@ -127,6 +127,7 @@ module taxi_eth_phy_25g_us_gt_ll #
output wire logic serdes_rx_data_valid,
output wire logic [HDR_W-1:0] serdes_rx_hdr,
output wire logic serdes_rx_hdr_valid,
output wire logic serdes_rx_gbx_sync,
input wire logic serdes_rx_bitslip,
/*
@@ -558,6 +559,14 @@ if (!SIM) begin
assign serdes_rx_hdr_valid = gt_rxheadervalid[0];
end
logic serdes_rx_data_valid_last_reg = 1'b0;
assign serdes_rx_gbx_sync = serdes_rx_data_valid && !serdes_rx_data_valid_last_reg;
always_ff @(posedge rx_clk) begin
serdes_rx_data_valid_last_reg <= serdes_rx_data_valid;
end
if (GT_TYPE == "GTY") begin : tx_seq
// 66 clock cycle sequence for GTY, with two stalls on cycles 64 and 65
// 64-bit internal, 64-bit external datapath width (required for operation at 25G)
@@ -625,10 +634,10 @@ if (GT_TYPE == "GTY") begin : tx_seq
always_ff @(posedge rx_clk) begin
rx_ts_cor_seq_reg <= rx_ts_cor_seq_reg + 1;
rx_ts_cor_val_reg <= rx_ts_cor_val_reg - (tx_ts_inc >> 5);
rx_ts_cor_val_reg <= rx_ts_cor_val_reg + (tx_ts_inc >> 5);
if (rx_ts_cor_seq_reg == 65) begin
rx_ts_cor_seq_reg <= '0;
rx_ts_cor_val_reg <= rx_ts_inc << 1; // TODO odd offset
rx_ts_cor_val_reg <= '0; // TODO odd offset
end
if (rx_ts_cor_sync) begin
rx_ts_cor_seq_reg <= 1;
@@ -702,10 +711,10 @@ end else begin : tx_seq
always_ff @(posedge rx_clk) begin
rx_ts_cor_seq_reg <= rx_ts_cor_seq_reg + 1;
rx_ts_cor_val_reg <= rx_ts_cor_val_reg - (rx_ts_inc >> 5);
rx_ts_cor_val_reg <= rx_ts_cor_val_reg + (rx_ts_inc >> 5);
if (rx_ts_cor_seq_reg == 32) begin
rx_ts_cor_seq_reg <= '0;
rx_ts_cor_val_reg <= rx_ts_inc; // TODO odd offset
rx_ts_cor_val_reg <= '0; // TODO odd offset
end
if (rx_ts_cor_sync) begin
rx_ts_cor_seq_reg <= 1;

View File

@@ -127,16 +127,16 @@ class BaseRSerdesSource():
self.log.info(" Sequence length: %d cycles", seq_len)
self.log.info(" Stall cycles: %s", seq_stall)
out_bits = 66
out_bits = self.width
in_cycles = seq_len
out_cycles = in_cycles - len(seq_stall)
in_bits = (out_bits * out_cycles) // in_cycles
in_bits = int(((out_bits + 2/self.pack_cnt) * out_cycles) / in_cycles)
self.log.info(" Input: %d bits (%d cycles)", in_bits, in_cycles)
self.log.info(" Input: %d+2 bits (%d cycles)", in_bits, in_cycles)
self.log.info(" Output: %d bits (%d cycles)", out_bits, out_cycles)
self.log.info(" Gearbox ratio: %d:%d", in_bits, out_bits)
self.log.info(" Gearbox ratio: %d+2:%d", in_bits, out_bits)
assert in_cycles*in_bits == out_cycles*out_bits
assert in_cycles*in_bits == out_cycles*(out_bits + 2/self.pack_cnt)
self.gbx_seq = 0
self.gbx_seq_len = seq_len
@@ -151,6 +151,9 @@ class BaseRSerdesSource():
continue
self.gbx_bit_cnt = max(self.gbx_bit_cnt - out_bits, 0)
# sync packing with gearbox
self.pack_seq = max(self.pack_cnt-1, 0)
async def send(self, frame):
while self.full():
self.dequeue_event.clear()
@@ -234,6 +237,8 @@ class BaseRSerdesSource():
clk_period = 0
last_clk = 0
symb_period = 0
symb_start = 0
gbx_delay = 0
data = 0
@@ -255,15 +260,32 @@ class BaseRSerdesSource():
# gearbox sequence
if self.gbx_seq_len:
symb_period = (clk_period * (self.pack_cnt*self.gbx_out_bits + 2)) // self.gbx_in_bits
self.gbx_seq = (self.gbx_seq + 1) % self.gbx_seq_len
if self.gbx_sync is not None:
self.gbx_sync.value = (self.gbx_seq == 0)
if self.gbx_seq == 0:
self.gbx_bit_cnt = 2*(self.gbx_seq_len-len(self.gbx_seq_stall))//self.pack_cnt
self.pack_seq = max(self.pack_cnt-2, 0)
gbx_delay = (self.gbx_bit_cnt * clk_period) // self.gbx_in_bits
stall = self.gbx_seq in self.gbx_seq_stall
self.gbx_bit_cnt += self.gbx_in_bits
if not stall:
self.gbx_bit_cnt -= self.gbx_out_bits
if self.pack_cnt == 1 or self.pack_seq == 0:
self.gbx_bit_cnt -= 2
if self.gbx_bit_cnt < 0:
self.gbx_bit_cnt = 0
# stall cycle
if self.gbx_seq in self.gbx_seq_stall:
if stall:
self.data.value = 0
if self.data_valid is not None:
self.data_valid.value = 0
@@ -271,10 +293,9 @@ class BaseRSerdesSource():
if self.hdr_valid is not None:
self.hdr_valid.value = 0
continue
self.gbx_bit_cnt = max(self.gbx_bit_cnt - self.gbx_out_bits, 0)
gbx_delay = (self.gbx_bit_cnt * clk_period) // self.gbx_in_bits
else:
symb_period = clk_period * self.pack_cnt
self.gbx_seq = 0
self.gbx_bit_cnt = 0
gbx_delay = 0
@@ -284,6 +305,9 @@ class BaseRSerdesSource():
if self.pack_seq:
# output data
if self.pack_seq == 0:
symb_start = sim_time - gbx_delay
data_out = data >> (self.width*(self.pack_cnt-self.pack_seq))
self.pack_seq = self.pack_seq-1
@@ -299,6 +323,8 @@ class BaseRSerdesSource():
self.hdr_valid.value = 0
continue
else:
symb_start = sim_time - gbx_delay
dl = bytearray()
cl = []
@@ -353,13 +379,13 @@ class BaseRSerdesSource():
d = XgmiiCtrl.START
c = 1
frame.start_lane = k
frame.sim_time_start = sim_time + (clk_period // self.byte_lanes * k) - gbx_delay
frame.sim_time_start = symb_start + ((symb_period * k) // 8)
elif frame_offset >= len(frame.data):
d = XgmiiCtrl.TERM
c = 1
in_term = True
ifg_cnt = max(self.ifg - (8-k), 0)
frame.sim_time_end = sim_time + (clk_period // self.byte_lanes * k) - gbx_delay
frame.sim_time_end = symb_start + ((symb_period * k) // 8)
frame.handle_tx_complete()
frame = None
self.current_frame = None
@@ -367,7 +393,7 @@ class BaseRSerdesSource():
d = frame.data[frame_offset]
c = frame.ctrl[frame_offset]
if frame.sim_time_sfd is None and not in_pre:
frame.sim_time_sfd = sim_time + (clk_period // self.byte_lanes * k) - gbx_delay
frame.sim_time_sfd = symb_start + ((symb_period * k) // 8)
if d == EthPre.SFD and (not self.xgmii_rep_count or rep_cnt == 1):
in_pre = False
if frame_offset == 0:

View File

@@ -11,7 +11,7 @@ SIM ?= verilator
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
COCOTB_HDL_TIMEPRECISION = 1fs
RTL_DIR = ../../rtl
LIB_DIR = ../../lib
@@ -37,9 +37,13 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
export PARAM_DATA_W := 32
export PARAM_HDR_W := 2
export PARAM_GBX_IF_EN := 1
export PARAM_GBX_CNT := 1
export PARAM_USXGMII_EN := 1
export PARAM_PTP_TS_EN := 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_COR_EN := 1
export PARAM_PTP_TS_COR_W := 20
ifeq ($(SIM), icarus)
PLUSARGS += -fst

View File

@@ -14,13 +14,12 @@ import logging
import os
import sys
import cocotb_test.simulator
import pytest
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.utils import get_time_from_sim_steps
from cocotb_tools.runner import get_runner
from cocotbext.eth import XgmiiFrame, PtpClockSimTime
from cocotbext.axi import AxiStreamBus, AxiStreamSink
@@ -44,7 +43,7 @@ class TB:
self.log.setLevel(logging.DEBUG)
if gbx_cfg:
self.clk_period = 3.102
self.clk_period = 3.103102
else:
self.clk_period = 3.2
@@ -55,6 +54,7 @@ class TB:
data_valid=dut.encoded_rx_data_valid,
hdr=dut.encoded_rx_hdr,
hdr_valid=dut.encoded_rx_hdr_valid,
gbx_sync=dut.rx_gbx_sync,
clock=dut.clk,
scramble=False,
gbx_cfg=gbx_cfg
@@ -63,6 +63,8 @@ class TB:
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.ptp_ts_cor_val.setimmediatevalue(0)
dut.cfg_rx_max_pkt_len.setimmediatevalue(0)
dut.cfg_rx_enable.setimmediatevalue(0)
if usxgmii_speed is not None:
@@ -119,6 +121,8 @@ class TB:
self.stats["stat_rx_err_preamble"] = 0
cocotb.start_soon(self._run_stats_counters())
if gbx_cfg:
cocotb.start_soon(self._run_ts_cor())
async def reset(self):
self.dut.rst.setimmediatevalue(0)
@@ -143,6 +147,24 @@ class TB:
for stat in self.stats:
self.stats[stat] += int(getattr(self.dut, stat).value)
async def _run_ts_cor(self):
seq_len = self.source.gbx_seq_len
seq = 0
val = 0
ui = self.clk_period / self.source.width
step = int(ui*2*65536+0.5)
while True:
await RisingEdge(self.dut.clk)
seq += 1
if seq % 2 == 0:
val += step
if seq >= seq_len:
seq = 0
val = 0
self.dut.ptp_ts_cor_val.value = val
if int(self.dut.ptp_ts_cor_sync.value):
seq = 1
def size_list():
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)]
@@ -173,6 +195,12 @@ if getattr(cocotb, 'top', None) is not None:
)
async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, payload_lengths=None, payload_data=None, ifg=12):
pipe_delay = 2
if gbx_cfg:
# baseline gearbox delay
pipe_delay += len(gbx_cfg[1])
tb = TB(dut, gbx_cfg, usxgmii_speed)
tb.source.ifg = ifg
@@ -182,6 +210,9 @@ async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, pa
await tb.reset()
for k in range(200):
await RisingEdge(dut.clk)
test_frames = [payload_data(x) for x in payload_lengths()]
tx_frames = []
@@ -210,8 +241,7 @@ async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, pa
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*2) < 0.01
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < 0.001
assert tb.sink.empty()
@@ -392,37 +422,55 @@ def test_taxi_axis_baser_rx_32(request, gbx_en):
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = module
verilog_sources = [
sources = [
os.path.join(tests_dir, f"{toplevel}.sv"),
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(taxi_src_dir, "lfsr", "rtl", "taxi_lfsr.sv"),
os.path.join(taxi_src_dir, "axis", "rtl", "taxi_axis_if.sv"),
]
verilog_sources = process_f_files(verilog_sources)
sources = process_f_files(sources)
parameters = {}
parameters['DATA_W'] = 32
parameters['HDR_W'] = 2
parameters['GBX_IF_EN'] = gbx_en
parameters['GBX_CNT'] = 1
parameters['USXGMII_EN'] = 1
parameters['PTP_TS_EN'] = 1
parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64
parameters['PTP_TS_COR_EN'] = 1
parameters['PTP_TS_COR_W'] = 16+4
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
simulator="verilator",
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
timescale = ("1ns", "1fs")
sim = os.getenv("SIM", "verilator")
waves = bool(int(os.getenv("WAVES", 0)))
sys.path.append(tests_dir)
runner = get_runner(sim)
runner.build(
sources=sources,
hdl_toplevel=toplevel,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
always=True,
build_dir=sim_build,
timescale=timescale,
waves=waves,
)
runner.test(
hdl_toplevel=toplevel,
test_module=module,
parameters=parameters,
extra_env=extra_env,
build_dir=sim_build,
timescale=timescale,
waves=waves,
)

View File

@@ -21,10 +21,13 @@ module test_taxi_axis_baser_rx_32 #
parameter DATA_W = 32,
parameter HDR_W = 2,
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic USXGMII_EN = 1'b1,
parameter logic PTP_TS_EN = 1'b0,
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 logic PTP_TS_COR_EN = PTP_TS_EN && GBX_IF_EN,
parameter PTP_TS_COR_W = 16+4
/* verilator lint_on WIDTHTRUNC */
)
();
@@ -38,6 +41,7 @@ logic [DATA_W-1:0] encoded_rx_data;
logic encoded_rx_data_valid;
logic [HDR_W-1:0] encoded_rx_hdr;
logic encoded_rx_hdr_valid;
logic [GBX_CNT-1:0] rx_gbx_sync;
taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx();
@@ -48,6 +52,8 @@ logic rx_os_match;
logic rx_idle_match;
logic [PTP_TS_W-1:0] ptp_ts;
logic [GBX_CNT-1:0] ptp_ts_cor_sync;
logic [PTP_TS_COR_W-1:0] ptp_ts_cor_val;
logic [15:0] cfg_rx_max_pkt_len;
logic cfg_rx_enable;
@@ -78,7 +84,9 @@ taxi_axis_baser_rx_32 #(
.GBX_IF_EN(GBX_IF_EN),
.USXGMII_EN(USXGMII_EN),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_W(PTP_TS_W)
.PTP_TS_W(PTP_TS_W),
.PTP_TS_COR_EN(PTP_TS_COR_EN),
.PTP_TS_COR_W(PTP_TS_COR_W)
)
uut (
.clk(clk),
@@ -91,6 +99,7 @@ uut (
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* AXI4-Stream output (source)
@@ -110,6 +119,8 @@ uut (
* PTP
*/
.ptp_ts(ptp_ts),
.ptp_ts_cor_sync(ptp_ts_cor_sync),
.ptp_ts_cor_val(ptp_ts_cor_val),
/*
* Configuration

View File

@@ -11,7 +11,7 @@ SIM ?= verilator
WAVES ?= 0
COCOTB_HDL_TIMEUNIT = 1ns
COCOTB_HDL_TIMEPRECISION = 1ps
COCOTB_HDL_TIMEPRECISION = 1fs
RTL_DIR = ../../rtl
LIB_DIR = ../../lib
@@ -37,9 +37,13 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
export PARAM_DATA_W := 64
export PARAM_HDR_W := 2
export PARAM_GBX_IF_EN := 1
export PARAM_GBX_CNT := 1
export PARAM_USXGMII_EN := 1
export PARAM_PTP_TS_EN := 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_COR_EN := 1
export PARAM_PTP_TS_COR_W := 20
ifeq ($(SIM), icarus)
PLUSARGS += -fst

View File

@@ -14,13 +14,12 @@ import logging
import os
import sys
import cocotb_test.simulator
import pytest
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
from cocotb.utils import get_time_from_sim_steps
from cocotb_tools.runner import get_runner
from cocotbext.eth import XgmiiFrame, PtpClockSimTime
from cocotbext.axi import AxiStreamBus, AxiStreamSink
@@ -44,7 +43,7 @@ class TB:
self.log.setLevel(logging.DEBUG)
if gbx_cfg:
self.clk_period = 6.206
self.clk_period = 6.206206
else:
self.clk_period = 6.4
@@ -55,6 +54,7 @@ class TB:
data_valid=dut.encoded_rx_data_valid,
hdr=dut.encoded_rx_hdr,
hdr_valid=dut.encoded_rx_hdr_valid,
gbx_sync=dut.rx_gbx_sync,
clock=dut.clk,
scramble=False,
gbx_cfg=gbx_cfg
@@ -63,6 +63,8 @@ class TB:
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.ptp_ts_cor_val.setimmediatevalue(0)
dut.cfg_rx_max_pkt_len.setimmediatevalue(0)
dut.cfg_rx_enable.setimmediatevalue(0)
if usxgmii_speed is not None:
@@ -119,6 +121,8 @@ class TB:
self.stats["stat_rx_err_preamble"] = 0
cocotb.start_soon(self._run_stats_counters())
if gbx_cfg:
cocotb.start_soon(self._run_ts_cor())
async def reset(self):
self.dut.rst.setimmediatevalue(0)
@@ -143,6 +147,23 @@ class TB:
for stat in self.stats:
self.stats[stat] += int(getattr(self.dut, stat).value)
async def _run_ts_cor(self):
seq_len = self.source.gbx_seq_len
seq = 0
val = 0
ui = self.clk_period / self.source.width
step = int(ui*2*65536+0.5)
while True:
await RisingEdge(self.dut.clk)
seq += 1
val += step
if seq >= seq_len:
seq = 0
val = 0
self.dut.ptp_ts_cor_val.value = val
if int(self.dut.ptp_ts_cor_sync.value):
seq = 1
def size_list():
return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)]
@@ -173,9 +194,13 @@ if getattr(cocotb, 'top', None) is not None:
async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, payload_lengths=None, payload_data=None, ifg=12):
if dut.USXGMII_EN.value:
pipe_delay = 1
pipe_delay = 2
else:
pipe_delay = 0
pipe_delay = 1
if gbx_cfg:
# baseline gearbox delay
pipe_delay += len(gbx_cfg[1])
tb = TB(dut, gbx_cfg, usxgmii_speed)
@@ -186,6 +211,9 @@ async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, pa
await tb.reset()
for k in range(200):
await RisingEdge(dut.clk)
test_frames = [payload_data(x) for x in payload_lengths()]
tx_frames = []
@@ -214,8 +242,7 @@ async def run_test(dut, gbx_cfg=None, offset_start=False, usxgmii_speed=None, pa
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
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*pipe_delay) < 0.001
assert tb.sink.empty()
@@ -397,37 +424,55 @@ def test_taxi_axis_baser_rx_64(request, gbx_en, usxgmii_en):
module = os.path.splitext(os.path.basename(__file__))[0]
toplevel = module
verilog_sources = [
sources = [
os.path.join(tests_dir, f"{toplevel}.sv"),
os.path.join(rtl_dir, f"{dut}.sv"),
os.path.join(taxi_src_dir, "lfsr", "rtl", "taxi_lfsr.sv"),
os.path.join(taxi_src_dir, "axis", "rtl", "taxi_axis_if.sv"),
]
verilog_sources = process_f_files(verilog_sources)
sources = process_f_files(sources)
parameters = {}
parameters['DATA_W'] = 64
parameters['HDR_W'] = 2
parameters['GBX_IF_EN'] = gbx_en
parameters['GBX_CNT'] = 1
parameters['USXGMII_EN'] = usxgmii_en
parameters['PTP_TS_EN'] = 1
parameters['PTP_TS_FMT_TOD'] = 1
parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64
parameters['PTP_TS_COR_EN'] = 1
parameters['PTP_TS_COR_W'] = 16+4
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
sim_build = os.path.join(tests_dir, "sim_build",
request.node.name.replace('[', '-').replace(']', ''))
cocotb_test.simulator.run(
simulator="verilator",
python_search=[tests_dir],
verilog_sources=verilog_sources,
toplevel=toplevel,
module=module,
timescale = ("1ns", "1fs")
sim = os.getenv("SIM", "verilator")
waves = bool(int(os.getenv("WAVES", 0)))
sys.path.append(tests_dir)
runner = get_runner(sim)
runner.build(
sources=sources,
hdl_toplevel=toplevel,
parameters=parameters,
sim_build=sim_build,
extra_env=extra_env,
always=True,
build_dir=sim_build,
timescale=timescale,
waves=waves,
)
runner.test(
hdl_toplevel=toplevel,
test_module=module,
parameters=parameters,
extra_env=extra_env,
build_dir=sim_build,
timescale=timescale,
waves=waves,
)

View File

@@ -21,10 +21,13 @@ module test_taxi_axis_baser_rx_64 #
parameter DATA_W = 64,
parameter HDR_W = 2,
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic USXGMII_EN = 1'b1,
parameter logic PTP_TS_EN = 1'b0,
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 logic PTP_TS_COR_EN = PTP_TS_EN && GBX_IF_EN,
parameter PTP_TS_COR_W = 16+4
/* verilator lint_on WIDTHTRUNC */
)
();
@@ -38,6 +41,7 @@ logic [DATA_W-1:0] encoded_rx_data;
logic encoded_rx_data_valid;
logic [HDR_W-1:0] encoded_rx_hdr;
logic encoded_rx_hdr_valid;
logic [GBX_CNT-1:0] rx_gbx_sync;
taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx();
@@ -48,6 +52,8 @@ logic rx_os_match;
logic rx_idle_match;
logic [PTP_TS_W-1:0] ptp_ts;
logic [GBX_CNT-1:0] ptp_ts_cor_sync;
logic [PTP_TS_COR_W-1:0] ptp_ts_cor_val;
logic [15:0] cfg_rx_max_pkt_len;
logic cfg_rx_enable;
@@ -79,7 +85,9 @@ taxi_axis_baser_rx_64 #(
.USXGMII_EN(USXGMII_EN),
.PTP_TS_EN(PTP_TS_EN),
.PTP_TS_FMT_TOD(PTP_TS_FMT_TOD),
.PTP_TS_W(PTP_TS_W)
.PTP_TS_W(PTP_TS_W),
.PTP_TS_COR_EN(PTP_TS_COR_EN),
.PTP_TS_COR_W(PTP_TS_COR_W)
)
uut (
.clk(clk),
@@ -92,6 +100,7 @@ uut (
.encoded_rx_data_valid(encoded_rx_data_valid),
.encoded_rx_hdr(encoded_rx_hdr),
.encoded_rx_hdr_valid(encoded_rx_hdr_valid),
.rx_gbx_sync(rx_gbx_sync),
/*
* AXI4-Stream output (source)
@@ -111,6 +120,8 @@ uut (
* PTP
*/
.ptp_ts(ptp_ts),
.ptp_ts_cor_sync(ptp_ts_cor_sync),
.ptp_ts_cor_val(ptp_ts_cor_val),
/*
* Configuration

View File

@@ -256,7 +256,7 @@ async def run_test_rx(dut, port=0, payload_lengths=None, payload_data=None, ifg=
if dut.DATA_W.value == 64:
if dut.COMBINED_MAC_PCS.value:
pipe_delay = 0 + 1
pipe_delay = 1 + 1
else:
pipe_delay = 2 + 1
if dut.USXGMII_EN.value:
@@ -268,6 +268,10 @@ async def run_test_rx(dut, port=0, payload_lengths=None, payload_data=None, ifg=
pipe_delay = 3 + 1
pipe_delay += int(dut.RX_SERDES_PIPELINE.value)
if dut.CFG_LOW_LATENCY.value:
# baseline gearbox delay
pipe_delay += 2 # TODO this is too simplistic
tb = TB(dut)
tb.serdes_sources[port].ifg = ifg
@@ -320,7 +324,7 @@ 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:
if not tb.serdes_sources[port].gbx_seq_len or dut.COMBINED_MAC_PCS.value:
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:

View File

@@ -67,6 +67,7 @@ class TB:
data_valid=dut.serdes_rx_data_valid,
hdr=dut.serdes_rx_hdr,
hdr_valid=dut.serdes_rx_hdr_valid,
gbx_sync=dut.serdes_rx_gbx_sync,
clock=dut.rx_clk,
slip=dut.serdes_rx_bitslip,
gbx_cfg=gbx_cfg
@@ -160,6 +161,7 @@ class TB:
dut.cfg_rx_pfc_en.setimmediatevalue(0)
if gbx_cfg:
cocotb.start_soon(self._run_rx_ts_cor())
cocotb.start_soon(self._run_tx_ts_cor())
async def reset(self):
@@ -185,6 +187,24 @@ class TB:
self.ptp_td_source.set_ts_tod_sim_time()
self.ptp_td_source.set_ts_rel_sim_time()
async def _run_rx_ts_cor(self):
seq_len = self.serdes_source.gbx_seq_len
seq = 0
val = 0
ui = self.clk_period / self.serdes_source.width
step = int(ui*2*65536+0.5)
while True:
await RisingEdge(self.dut.rx_clk)
seq += 1
if self.serdes_sink.width == 64 or seq % 2 == 0:
val += step
if seq >= seq_len:
seq = 0
val = 0
self.dut.rx_ptp_ts_cor_val.value = val
if int(self.dut.rx_ptp_ts_cor_sync.value):
seq = 1
async def _run_tx_ts_cor(self):
seq_len = self.serdes_sink.gbx_seq_len
seq = 0
@@ -235,13 +255,18 @@ if getattr(cocotb, 'top', None) is not None:
async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, ifg=12):
if len(dut.serdes_rx_data) == 64:
pipe_delay = 0 + 1
pipe_delay = 1 + 1
if dut.USXGMII_EN.value:
pipe_delay += 1
else:
pipe_delay = 2 + 1
pipe_delay += int(dut.RX_SERDES_PIPELINE.value)
if gbx_cfg:
# baseline gearbox delay
pipe_delay += len(gbx_cfg[1])
tb = TB(dut, gbx_cfg)
tb.serdes_source.ifg = ifg
@@ -263,6 +288,9 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
for k in range(2000):
await RisingEdge(dut.rx_clk)
for k in range(100):
await RisingEdge(dut.rx_clk)
tb.dut.cfg_rx_enable.value = 1
test_frames = [payload_data(x) for x in payload_lengths()]
@@ -291,11 +319,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:
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
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.001
assert tb.axis_sink.empty()

View File

@@ -77,6 +77,7 @@ logic [DATA_W-1:0] serdes_rx_data;
logic serdes_rx_data_valid;
logic [HDR_W-1:0] serdes_rx_hdr;
logic serdes_rx_hdr_valid;
logic serdes_rx_gbx_sync;
logic serdes_rx_bitslip;
logic serdes_rx_reset_req;
@@ -293,6 +294,7 @@ uut (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),

View File

@@ -65,6 +65,7 @@ class TB:
data_valid=dut.serdes_rx_data_valid,
hdr=dut.serdes_rx_hdr,
hdr_valid=dut.serdes_rx_hdr_valid,
gbx_sync=dut.serdes_rx_gbx_sync,
clock=dut.rx_clk,
slip=dut.serdes_rx_bitslip,
gbx_cfg=gbx_cfg
@@ -125,6 +126,7 @@ class TB:
dut.cfg_rx_prbs31_enable.setimmediatevalue(0)
if gbx_cfg:
cocotb.start_soon(self._run_rx_ts_cor())
cocotb.start_soon(self._run_tx_ts_cor())
async def reset(self):
@@ -153,6 +155,24 @@ class TB:
self.ptp_td_source.set_ts_tod_sim_time()
self.ptp_td_source.set_ts_rel_sim_time()
async def _run_rx_ts_cor(self):
seq_len = self.serdes_source.gbx_seq_len
seq = 0
val = 0
ui = self.clk_period / self.serdes_source.width
step = int(ui*2*65536+0.5)
while True:
await RisingEdge(self.dut.rx_clk)
seq += 1
if self.serdes_sink.width == 64 or seq % 2 == 0:
val += step
if seq >= seq_len:
seq = 0
val = 0
self.dut.rx_ptp_ts_cor_val.value = val
if int(self.dut.rx_ptp_ts_cor_sync.value):
seq = 1
async def _run_tx_ts_cor(self):
seq_len = self.serdes_sink.gbx_seq_len
seq = 0
@@ -201,13 +221,18 @@ if getattr(cocotb, 'top', None) is not None:
async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, ifg=12):
if len(dut.serdes_rx_data) == 64:
pipe_delay = 0 + 1
pipe_delay = 1 + 1
if dut.USXGMII_EN.value:
pipe_delay += 1
else:
pipe_delay = 2 + 1
pipe_delay += int(dut.RX_SERDES_PIPELINE.value)
if gbx_cfg:
# baseline gearbox delay
pipe_delay += len(gbx_cfg[1])
tb = TB(dut, gbx_cfg)
tb.serdes_source.ifg = ifg
@@ -227,6 +252,9 @@ async def run_test_rx(dut, gbx_cfg=None, payload_lengths=None, payload_data=None
for k in range(2000):
await RisingEdge(dut.rx_clk)
for k in range(100):
await RisingEdge(dut.rx_clk)
# clear out sink buffer
tb.axis_sink.clear()
@@ -253,11 +281,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:
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
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()

View File

@@ -91,6 +91,7 @@ logic [DATA_W-1:0] serdes_rx_data;
logic serdes_rx_data_valid;
logic [HDR_W-1:0] serdes_rx_hdr;
logic serdes_rx_hdr_valid;
logic serdes_rx_gbx_sync;
logic serdes_rx_bitslip;
logic serdes_rx_reset_req;
@@ -235,6 +236,7 @@ uut (
.serdes_rx_data_valid(serdes_rx_data_valid),
.serdes_rx_hdr(serdes_rx_hdr),
.serdes_rx_hdr_valid(serdes_rx_hdr_valid),
.serdes_rx_gbx_sync(serdes_rx_gbx_sync),
.serdes_rx_bitslip(serdes_rx_bitslip),
.serdes_rx_reset_req(serdes_rx_reset_req),

View File

@@ -60,6 +60,7 @@ class TB:
dut.encoded_rx_data_valid.setimmediatevalue(1)
dut.encoded_rx_hdr_valid.setimmediatevalue(1)
dut.rx_gbx_sync_in.setimmediatevalue(0)
async def reset(self):
self.dut.rst.setimmediatevalue(0)
@@ -269,6 +270,7 @@ def test_taxi_xgmii_baser_dec(request, data_w):
parameters['CTRL_W'] = parameters['DATA_W'] // 8
parameters['HDR_W'] = 2
parameters['GBX_IF_EN'] = 0
parameters['GBX_CNT'] = 1
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}