mirror of
https://github.com/fpganinja/taxi.git
synced 2026-08-29 08:05:00 -07:00
eth: Add gearbox delay compensation for BASE-R RX
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
|
||||
@@ -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()}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user