mirror of
https://github.com/corundum/corundum.git
synced 2025-01-16 08:12:53 +08:00
merged changes in eth
This commit is contained in:
commit
5058b797d2
@ -182,7 +182,7 @@ reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next;
|
||||
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}, m_axis_tkeep_next;
|
||||
reg m_axis_tvalid_reg = 1'b0, m_axis_tvalid_next;
|
||||
reg m_axis_tlast_reg = 1'b0, m_axis_tlast_next;
|
||||
reg m_axis_tuser_reg = 1'b0, m_axis_tuser_next;
|
||||
reg [USER_WIDTH-1:0] m_axis_tuser_reg = {USER_WIDTH{1'b0}}, m_axis_tuser_next;
|
||||
|
||||
reg [1:0] start_packet_reg = 2'b00;
|
||||
reg error_bad_frame_reg = 1'b0, error_bad_frame_next;
|
||||
@ -212,7 +212,7 @@ assign m_axis_tdata = m_axis_tdata_reg;
|
||||
assign m_axis_tkeep = m_axis_tkeep_reg;
|
||||
assign m_axis_tvalid = m_axis_tvalid_reg;
|
||||
assign m_axis_tlast = m_axis_tlast_reg;
|
||||
assign m_axis_tuser = PTP_TS_ENABLE ? {ptp_ts_reg, m_axis_tuser_reg} : m_axis_tuser_reg;
|
||||
assign m_axis_tuser = m_axis_tuser_reg;
|
||||
|
||||
assign start_packet = start_packet_reg;
|
||||
assign error_bad_frame = error_bad_frame_reg;
|
||||
@ -309,7 +309,8 @@ always @* begin
|
||||
m_axis_tkeep_next = 8'd0;
|
||||
m_axis_tvalid_next = 1'b0;
|
||||
m_axis_tlast_next = 1'b0;
|
||||
m_axis_tuser_next = 1'b0;
|
||||
m_axis_tuser_next = m_axis_tuser_reg;
|
||||
m_axis_tuser_next[0] = 1'b0;
|
||||
|
||||
error_bad_frame_next = 1'b0;
|
||||
error_bad_fcs_next = 1'b0;
|
||||
@ -319,6 +320,10 @@ always @* begin
|
||||
// idle state - wait for packet
|
||||
reset_crc = 1'b1;
|
||||
|
||||
if (PTP_TS_ENABLE) begin
|
||||
m_axis_tuser_next[1 +: PTP_TS_WIDTH] = ptp_ts_reg;
|
||||
end
|
||||
|
||||
if (input_type_d1 == INPUT_TYPE_START_0) begin
|
||||
// start condition
|
||||
reset_crc = 1'b0;
|
||||
@ -333,7 +338,7 @@ always @* begin
|
||||
m_axis_tkeep_next = 8'hff;
|
||||
m_axis_tvalid_next = 1'b1;
|
||||
m_axis_tlast_next = 1'b0;
|
||||
m_axis_tuser_next = 1'b0;
|
||||
m_axis_tuser_next[0] = 1'b0;
|
||||
|
||||
if (input_type_d0 == INPUT_TYPE_DATA) begin
|
||||
state_next = STATE_PAYLOAD;
|
||||
@ -357,7 +362,7 @@ always @* begin
|
||||
(input_type_d0 == INPUT_TYPE_TERM_4 && crc_valid3)) begin
|
||||
// CRC valid
|
||||
end else begin
|
||||
m_axis_tuser_next = 1'b1;
|
||||
m_axis_tuser_next[0] = 1'b1;
|
||||
error_bad_frame_next = 1'b1;
|
||||
error_bad_fcs_next = 1'b1;
|
||||
end
|
||||
@ -370,7 +375,7 @@ always @* begin
|
||||
end else begin
|
||||
// control or error characters in packet
|
||||
m_axis_tlast_next = 1'b1;
|
||||
m_axis_tuser_next = 1'b1;
|
||||
m_axis_tuser_next[0] = 1'b1;
|
||||
error_bad_frame_next = 1'b1;
|
||||
reset_crc = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
@ -382,7 +387,7 @@ always @* begin
|
||||
m_axis_tkeep_next = 8'hff;
|
||||
m_axis_tvalid_next = 1'b1;
|
||||
m_axis_tlast_next = 1'b1;
|
||||
m_axis_tuser_next = 1'b0;
|
||||
m_axis_tuser_next[0] = 1'b0;
|
||||
|
||||
reset_crc = 1'b1;
|
||||
|
||||
@ -397,7 +402,7 @@ always @* begin
|
||||
(input_type_d1 == INPUT_TYPE_TERM_7 && crc_valid2)) begin
|
||||
// CRC valid
|
||||
end else begin
|
||||
m_axis_tuser_next = 1'b1;
|
||||
m_axis_tuser_next[0] = 1'b1;
|
||||
error_bad_frame_next = 1'b1;
|
||||
error_bad_fcs_next = 1'b1;
|
||||
end
|
||||
|
@ -126,8 +126,6 @@ reg start_packet_reg = 1'b0, start_packet_next;
|
||||
reg error_bad_frame_reg = 1'b0, error_bad_frame_next;
|
||||
reg error_bad_fcs_reg = 1'b0, error_bad_fcs_next;
|
||||
|
||||
reg [PTP_TS_WIDTH-1:0] ptp_ts_reg = 0, ptp_ts_next;
|
||||
|
||||
reg [31:0] crc_state = 32'hFFFFFFFF;
|
||||
|
||||
wire [31:0] crc_next0;
|
||||
@ -279,17 +277,11 @@ always @* begin
|
||||
error_bad_frame_next = 1'b0;
|
||||
error_bad_fcs_next = 1'b0;
|
||||
|
||||
ptp_ts_next = ptp_ts_reg;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state - wait for packet
|
||||
reset_crc = 1'b1;
|
||||
|
||||
if (PTP_TS_ENABLE) begin
|
||||
m_axis_tuser_next[1 +: PTP_TS_WIDTH] = ptp_ts_reg;
|
||||
end
|
||||
|
||||
if (xgmii_rxc_d2[0] && xgmii_rxd_d2[7:0] == XGMII_START) begin
|
||||
// start condition
|
||||
if (control_masked) begin
|
||||
@ -306,12 +298,14 @@ always @* begin
|
||||
state_next = STATE_PREAMBLE;
|
||||
end
|
||||
end else begin
|
||||
if (PTP_TS_ENABLE) begin
|
||||
m_axis_tuser_next[1 +: PTP_TS_WIDTH] = ptp_ts;
|
||||
end
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end
|
||||
STATE_PREAMBLE: begin
|
||||
// drop preamble
|
||||
ptp_ts_next = ptp_ts;
|
||||
start_packet_next = 1'b1;
|
||||
state_next = STATE_PAYLOAD;
|
||||
end
|
||||
@ -392,8 +386,6 @@ always @(posedge clk) begin
|
||||
error_bad_frame_reg <= error_bad_frame_next;
|
||||
error_bad_fcs_reg <= error_bad_fcs_next;
|
||||
|
||||
ptp_ts_reg <= ptp_ts_next;
|
||||
|
||||
last_cycle_tkeep_reg <= last_cycle_tkeep_next;
|
||||
|
||||
for (i = 0; i < 4; i = i + 1) begin
|
||||
|
@ -329,6 +329,12 @@ always @* begin
|
||||
m_axis_ptp_ts_tag_next = m_axis_ptp_ts_tag_reg;
|
||||
m_axis_ptp_ts_valid_next = 1'b0;
|
||||
|
||||
if (start_packet_reg) begin
|
||||
m_axis_ptp_ts_next = ptp_ts;
|
||||
m_axis_ptp_ts_tag_next = s_axis_tuser >> 1;
|
||||
m_axis_ptp_ts_valid_next = 1'b1;
|
||||
end
|
||||
|
||||
// XGMII idle
|
||||
xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}};
|
||||
xgmii_txc_next = {CTRL_WIDTH{1'b1}};
|
||||
@ -370,9 +376,6 @@ always @* begin
|
||||
xgmii_txd_next = {ETH_SFD, {3{ETH_PRE}}};
|
||||
xgmii_txc_next = 4'b0000;
|
||||
s_axis_tready_next = 1'b1;
|
||||
m_axis_ptp_ts_next = ptp_ts;
|
||||
m_axis_ptp_ts_tag_next = s_axis_tuser >> 1;
|
||||
m_axis_ptp_ts_valid_next = 1'b1;
|
||||
start_packet_next = 1'b1;
|
||||
state_next = STATE_PAYLOAD;
|
||||
end
|
||||
|
@ -221,11 +221,11 @@ end
|
||||
// PTP timestamping
|
||||
generate
|
||||
|
||||
if (TX_PTP_TS_ENABLE) begin
|
||||
if (TX_PTP_TS_ENABLE) begin : tx_ptp
|
||||
|
||||
ptp_clock_cdc #(
|
||||
.TS_WIDTH(PTP_TS_WIDTH),
|
||||
.NS_WIDTH(4),
|
||||
.NS_WIDTH(6),
|
||||
.FNS_WIDTH(16),
|
||||
.USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK)
|
||||
)
|
||||
@ -255,10 +255,9 @@ if (TX_PTP_TS_ENABLE) begin
|
||||
.FRAME_FIFO(0)
|
||||
)
|
||||
tx_ptp_ts_fifo (
|
||||
.async_rst(logic_rst | tx_rst),
|
||||
|
||||
// AXI input
|
||||
.s_clk(tx_clk),
|
||||
.s_rst(tx_rst),
|
||||
.s_axis_tdata(tx_axis_ptp_ts_96),
|
||||
.s_axis_tkeep(0),
|
||||
.s_axis_tvalid(tx_axis_ptp_ts_valid),
|
||||
@ -270,6 +269,7 @@ if (TX_PTP_TS_ENABLE) begin
|
||||
|
||||
// AXI output
|
||||
.m_clk(logic_clk),
|
||||
.m_rst(logic_rst),
|
||||
.m_axis_tdata(m_axis_tx_ptp_ts_96),
|
||||
.m_axis_tkeep(),
|
||||
.m_axis_tvalid(m_axis_tx_ptp_ts_valid),
|
||||
@ -298,11 +298,11 @@ end else begin
|
||||
|
||||
end
|
||||
|
||||
if (RX_PTP_TS_ENABLE) begin
|
||||
if (RX_PTP_TS_ENABLE) begin : rx_ptp
|
||||
|
||||
ptp_clock_cdc #(
|
||||
.TS_WIDTH(PTP_TS_WIDTH),
|
||||
.NS_WIDTH(4),
|
||||
.NS_WIDTH(6),
|
||||
.FNS_WIDTH(16),
|
||||
.USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK)
|
||||
)
|
||||
|
@ -113,6 +113,7 @@ module eth_mac_phy_10g #
|
||||
output wire rx_bad_block,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -158,6 +159,7 @@ eth_mac_phy_10g_rx_inst (
|
||||
.rx_bad_block(rx_bad_block),
|
||||
.rx_block_lock(rx_block_lock),
|
||||
.rx_high_ber(rx_high_ber),
|
||||
.rx_status(rx_status),
|
||||
.rx_prbs31_enable(rx_prbs31_enable)
|
||||
);
|
||||
|
||||
|
@ -131,6 +131,7 @@ module eth_mac_phy_10g_fifo #
|
||||
output wire rx_bad_block,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
output wire rx_fifo_overflow,
|
||||
output wire rx_fifo_bad_frame,
|
||||
output wire rx_fifo_good_frame,
|
||||
@ -206,31 +207,38 @@ wire rx_error_bad_fcs_int;
|
||||
wire rx_bad_block_int;
|
||||
wire rx_block_lock_int;
|
||||
wire rx_high_ber_int;
|
||||
wire rx_status_int;
|
||||
|
||||
reg [4:0] rx_sync_reg_1 = 5'd0;
|
||||
reg [4:0] rx_sync_reg_2 = 5'd0;
|
||||
reg [4:0] rx_sync_reg_3 = 5'd0;
|
||||
reg [4:0] rx_sync_reg_4 = 5'd0;
|
||||
reg [5:0] rx_sync_reg_1 = 6'd0;
|
||||
reg [5:0] rx_sync_reg_2 = 6'd0;
|
||||
reg [5:0] rx_sync_reg_3 = 6'd0;
|
||||
reg [5:0] rx_sync_reg_4 = 6'd0;
|
||||
|
||||
assign rx_error_bad_frame = rx_sync_reg_3[0] ^ rx_sync_reg_4[0];
|
||||
assign rx_error_bad_fcs = rx_sync_reg_3[1] ^ rx_sync_reg_4[1];
|
||||
assign rx_bad_block = rx_sync_reg_3[2] ^ rx_sync_reg_4[2];
|
||||
assign rx_block_lock = rx_sync_reg_3[3] ^ rx_sync_reg_4[3];
|
||||
assign rx_high_ber = rx_sync_reg_3[4] ^ rx_sync_reg_4[4];
|
||||
assign rx_block_lock = rx_sync_reg_4[3];
|
||||
assign rx_high_ber = rx_sync_reg_4[4];
|
||||
assign rx_status = rx_sync_reg_4[5];
|
||||
|
||||
always @(posedge rx_clk or posedge rx_rst) begin
|
||||
if (rx_rst) begin
|
||||
rx_sync_reg_1 <= 5'd0;
|
||||
rx_sync_reg_1 <= 6'd0;
|
||||
end else begin
|
||||
rx_sync_reg_1 <= rx_sync_reg_1 ^ {rx_high_ber_int, rx_block_lock_int, rx_bad_block_int, rx_error_bad_fcs_int, rx_error_bad_frame_int};
|
||||
rx_sync_reg_1[0] <= rx_sync_reg_1[0] ^ rx_error_bad_frame_int;
|
||||
rx_sync_reg_1[1] <= rx_sync_reg_1[1] ^ rx_error_bad_fcs_int;
|
||||
rx_sync_reg_1[2] <= rx_sync_reg_1[2] ^ rx_bad_block_int;
|
||||
rx_sync_reg_1[3] <= rx_block_lock_int;
|
||||
rx_sync_reg_1[4] <= rx_high_ber_int;
|
||||
rx_sync_reg_1[5] <= rx_status_int;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge logic_clk or posedge logic_rst) begin
|
||||
if (logic_rst) begin
|
||||
rx_sync_reg_2 <= 5'd0;
|
||||
rx_sync_reg_3 <= 5'd0;
|
||||
rx_sync_reg_4 <= 5'd0;
|
||||
rx_sync_reg_2 <= 6'd0;
|
||||
rx_sync_reg_3 <= 6'd0;
|
||||
rx_sync_reg_4 <= 6'd0;
|
||||
end else begin
|
||||
rx_sync_reg_2 <= rx_sync_reg_1;
|
||||
rx_sync_reg_3 <= rx_sync_reg_2;
|
||||
@ -241,11 +249,11 @@ end
|
||||
// PTP timestamping
|
||||
generate
|
||||
|
||||
if (TX_PTP_TS_ENABLE) begin
|
||||
if (TX_PTP_TS_ENABLE) begin : tx_ptp
|
||||
|
||||
ptp_clock_cdc #(
|
||||
.TS_WIDTH(PTP_TS_WIDTH),
|
||||
.NS_WIDTH(4),
|
||||
.NS_WIDTH(6),
|
||||
.FNS_WIDTH(16),
|
||||
.USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK)
|
||||
)
|
||||
@ -275,10 +283,9 @@ if (TX_PTP_TS_ENABLE) begin
|
||||
.FRAME_FIFO(0)
|
||||
)
|
||||
tx_ptp_ts_fifo (
|
||||
.async_rst(logic_rst | tx_rst),
|
||||
|
||||
// AXI input
|
||||
.s_clk(tx_clk),
|
||||
.s_rst(tx_rst),
|
||||
.s_axis_tdata(tx_axis_ptp_ts_96),
|
||||
.s_axis_tkeep(0),
|
||||
.s_axis_tvalid(tx_axis_ptp_ts_valid),
|
||||
@ -290,6 +297,7 @@ if (TX_PTP_TS_ENABLE) begin
|
||||
|
||||
// AXI output
|
||||
.m_clk(logic_clk),
|
||||
.m_rst(logic_rst),
|
||||
.m_axis_tdata(m_axis_tx_ptp_ts_96),
|
||||
.m_axis_tkeep(),
|
||||
.m_axis_tvalid(m_axis_tx_ptp_ts_valid),
|
||||
@ -318,11 +326,11 @@ end else begin
|
||||
|
||||
end
|
||||
|
||||
if (RX_PTP_TS_ENABLE) begin
|
||||
if (RX_PTP_TS_ENABLE) begin : rx_ptp
|
||||
|
||||
ptp_clock_cdc #(
|
||||
.TS_WIDTH(PTP_TS_WIDTH),
|
||||
.NS_WIDTH(4),
|
||||
.NS_WIDTH(6),
|
||||
.FNS_WIDTH(16),
|
||||
.USE_SAMPLE_CLOCK(PTP_USE_SAMPLE_CLOCK)
|
||||
)
|
||||
@ -411,6 +419,7 @@ eth_mac_phy_10g_inst (
|
||||
.rx_bad_block(rx_bad_block_int),
|
||||
.rx_block_lock(rx_block_lock_int),
|
||||
.rx_high_ber(rx_high_ber_int),
|
||||
.rx_status(rx_status_int),
|
||||
|
||||
.ifg_delay(ifg_delay),
|
||||
|
||||
|
@ -84,6 +84,7 @@ module eth_mac_phy_10g_rx #
|
||||
output wire rx_bad_block,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -134,6 +135,7 @@ eth_phy_10g_rx_if_inst (
|
||||
.rx_error_count(rx_error_count),
|
||||
.rx_block_lock(rx_block_lock),
|
||||
.rx_high_ber(rx_high_ber),
|
||||
.rx_status(rx_status),
|
||||
.rx_prbs31_enable(rx_prbs31_enable)
|
||||
);
|
||||
|
||||
|
@ -78,6 +78,7 @@ module eth_phy_10g #
|
||||
output wire rx_sequence_error,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -112,6 +113,7 @@ eth_phy_10g_rx_inst (
|
||||
.rx_sequence_error(rx_sequence_error),
|
||||
.rx_block_lock(rx_block_lock),
|
||||
.rx_high_ber(rx_high_ber),
|
||||
.rx_status(rx_status),
|
||||
.rx_prbs31_enable(rx_prbs31_enable)
|
||||
);
|
||||
|
||||
|
@ -70,6 +70,7 @@ module eth_phy_10g_rx #
|
||||
output wire rx_sequence_error,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -123,6 +124,7 @@ eth_phy_10g_rx_if_inst (
|
||||
.rx_error_count(rx_error_count),
|
||||
.rx_block_lock(rx_block_lock),
|
||||
.rx_high_ber(rx_high_ber),
|
||||
.rx_status(rx_status),
|
||||
.rx_prbs31_enable(rx_prbs31_enable)
|
||||
);
|
||||
|
||||
|
@ -69,6 +69,7 @@ module eth_phy_10g_rx_if #
|
||||
output wire [6:0] rx_error_count,
|
||||
output wire rx_block_lock,
|
||||
output wire rx_high_ber,
|
||||
output wire rx_status,
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -260,7 +261,8 @@ eth_phy_10g_rx_watchdog_inst (
|
||||
.rx_bad_block(rx_bad_block),
|
||||
.rx_sequence_error(rx_sequence_error),
|
||||
.rx_block_lock(rx_block_lock),
|
||||
.rx_high_ber(rx_high_ber)
|
||||
.rx_high_ber(rx_high_ber),
|
||||
.rx_status(rx_status)
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -52,7 +52,12 @@ module eth_phy_10g_rx_watchdog #
|
||||
input wire rx_bad_block,
|
||||
input wire rx_sequence_error,
|
||||
input wire rx_block_lock,
|
||||
input wire rx_high_ber
|
||||
input wire rx_high_ber,
|
||||
|
||||
/*
|
||||
* Status
|
||||
*/
|
||||
output wire rx_status
|
||||
);
|
||||
|
||||
// bus width assertions
|
||||
@ -71,22 +76,30 @@ localparam [1:0]
|
||||
|
||||
reg [COUNT_WIDTH-1:0] time_count_reg = 0, time_count_next;
|
||||
reg [3:0] error_count_reg = 0, error_count_next;
|
||||
reg [3:0] status_count_reg = 0, status_count_next;
|
||||
|
||||
reg saw_ctrl_sh_reg = 1'b0, saw_ctrl_sh_next;
|
||||
reg [9:0] block_error_count_reg = 0, block_error_count_next;
|
||||
|
||||
reg serdes_rx_reset_req_reg = 1'b0, serdes_rx_reset_req_next;
|
||||
|
||||
reg rx_status_reg = 1'b0, rx_status_next;
|
||||
|
||||
assign serdes_rx_reset_req = serdes_rx_reset_req_reg;
|
||||
|
||||
assign rx_status = rx_status_reg;
|
||||
|
||||
always @* begin
|
||||
error_count_next = error_count_reg;
|
||||
status_count_next = status_count_reg;
|
||||
|
||||
saw_ctrl_sh_next = saw_ctrl_sh_reg;
|
||||
block_error_count_next = block_error_count_reg;
|
||||
|
||||
serdes_rx_reset_req_next = 1'b0;
|
||||
|
||||
rx_status_next = rx_status_reg;
|
||||
|
||||
if (rx_block_lock) begin
|
||||
if (serdes_rx_hdr == SYNC_CTRL) begin
|
||||
saw_ctrl_sh_next = 1'b1;
|
||||
@ -94,6 +107,9 @@ always @* begin
|
||||
if ((rx_bad_block || rx_sequence_error) && !(&block_error_count_reg)) begin
|
||||
block_error_count_next = block_error_count_reg + 1;
|
||||
end
|
||||
end else begin
|
||||
rx_status_next = 1'b0;
|
||||
status_count_next = 0;
|
||||
end
|
||||
|
||||
if (time_count_reg != 0) begin
|
||||
@ -103,8 +119,12 @@ always @* begin
|
||||
|
||||
if (!saw_ctrl_sh_reg || &block_error_count_reg) begin
|
||||
error_count_next = error_count_reg + 1;
|
||||
status_count_next = 0;
|
||||
end else begin
|
||||
error_count_next = 0;
|
||||
if (!(&status_count_reg)) begin
|
||||
status_count_next = status_count_reg + 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (&error_count_reg) begin
|
||||
@ -112,6 +132,10 @@ always @* begin
|
||||
serdes_rx_reset_req_next = 1'b1;
|
||||
end
|
||||
|
||||
if (&status_count_reg) begin
|
||||
rx_status_next = 1'b1;
|
||||
end
|
||||
|
||||
saw_ctrl_sh_next = 1'b0;
|
||||
block_error_count_next = 0;
|
||||
end
|
||||
@ -120,14 +144,18 @@ end
|
||||
always @(posedge clk) begin
|
||||
time_count_reg <= time_count_next;
|
||||
error_count_reg <= error_count_next;
|
||||
status_count_reg <= status_count_next;
|
||||
saw_ctrl_sh_reg <= saw_ctrl_sh_next;
|
||||
block_error_count_reg <= block_error_count_next;
|
||||
rx_status_reg <= rx_status_next;
|
||||
|
||||
if (rst) begin
|
||||
time_count_reg <= COUNT_125US;
|
||||
error_count_reg <= 0;
|
||||
status_count_reg <= 0;
|
||||
saw_ctrl_sh_reg <= 1'b0;
|
||||
block_error_count_reg <= 0;
|
||||
rx_status_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -304,7 +304,6 @@ always @(posedge sample_clk) begin
|
||||
if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin
|
||||
edge_1_reg <= 1'b0;
|
||||
edge_2_reg <= 1'b0;
|
||||
active_reg[0] <= 1'b1;
|
||||
end else begin
|
||||
edge_1_reg <= !edge_2_reg;
|
||||
edge_2_reg <= 1'b0;
|
||||
@ -312,7 +311,6 @@ always @(posedge sample_clk) begin
|
||||
end else if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin
|
||||
edge_1_reg <= 1'b0;
|
||||
edge_2_reg <= !edge_1_reg;
|
||||
active_reg[0] <= 1'b1;
|
||||
end
|
||||
|
||||
// accumulator
|
||||
@ -320,8 +318,12 @@ always @(posedge sample_clk) begin
|
||||
|
||||
sample_cnt_reg <= sample_cnt_reg + 1;
|
||||
|
||||
if (src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg) begin
|
||||
active_reg[0] <= 1'b1;
|
||||
end
|
||||
|
||||
if (sample_cnt_reg == 0) begin
|
||||
active_reg <= active_reg << 1;
|
||||
active_reg <= {active_reg, src_sync_sample_sync2_reg && !src_sync_sample_sync3_reg};
|
||||
sample_acc_reg <= $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg});
|
||||
sample_acc_out_reg <= sample_acc_reg;
|
||||
if (active_reg != 0) begin
|
||||
@ -354,7 +356,6 @@ always @(posedge output_clk) begin
|
||||
if (src_sync_sync2_reg && !src_sync_sync3_reg) begin
|
||||
edge_1_reg <= 1'b0;
|
||||
edge_2_reg <= 1'b0;
|
||||
active_reg[0] <= 1'b1;
|
||||
end else begin
|
||||
edge_1_reg <= !edge_2_reg;
|
||||
edge_2_reg <= 1'b0;
|
||||
@ -362,7 +363,6 @@ always @(posedge output_clk) begin
|
||||
end else if (src_sync_sync2_reg && !src_sync_sync3_reg) begin
|
||||
edge_1_reg <= 1'b0;
|
||||
edge_2_reg <= !edge_1_reg;
|
||||
active_reg[0] <= 1'b1;
|
||||
end
|
||||
|
||||
// accumulator
|
||||
@ -370,13 +370,16 @@ always @(posedge output_clk) begin
|
||||
|
||||
sample_cnt_reg <= sample_cnt_reg + 1;
|
||||
|
||||
if (src_sync_sync2_reg && !src_sync_sync3_reg) begin
|
||||
active_reg[0] <= 1'b1;
|
||||
end
|
||||
|
||||
sample_acc_sync_valid_reg <= 1'b0;
|
||||
if (sample_cnt_reg == 0) begin
|
||||
active_reg <= active_reg << 1;
|
||||
active_reg <= {active_reg, src_sync_sync2_reg && !src_sync_sync3_reg};
|
||||
sample_acc_reg <= $signed({1'b0, edge_2_reg}) - $signed({1'b0, edge_1_reg});
|
||||
sample_acc_sync_reg <= sample_acc_reg;
|
||||
if (active_reg != 0) begin
|
||||
sample_update_reg <= !sample_update_reg;
|
||||
sample_acc_sync_valid_reg <= 1'b1;
|
||||
end
|
||||
end
|
||||
@ -698,6 +701,13 @@ always @* begin
|
||||
{period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b1}};
|
||||
end
|
||||
|
||||
// adjust period if integrator is saturated
|
||||
if (time_err_int_reg == 0) begin
|
||||
{period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b0}};
|
||||
end else if (~time_err_int_reg == 0) begin
|
||||
{period_ns_next, period_fns_next} = {NS_WIDTH+FNS_WIDTH{1'b1}};
|
||||
end
|
||||
|
||||
// locked status
|
||||
if ($signed(ts_ns_diff_corr_reg[17-1:4]) == 0 || $signed(ts_ns_diff_corr_reg[17-1:4]) == -1) begin
|
||||
if (ptp_lock_count_reg == {PTP_LOCK_WIDTH{1'b1}}) begin
|
||||
|
@ -36,10 +36,9 @@ VERILOG_SOURCES += ../../rtl/lfsr.v
|
||||
export PARAM_DATA_WIDTH ?= 64
|
||||
export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_HDR_WIDTH ?= 2
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TS_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -33,9 +33,10 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame
|
||||
from cocotbext.eth import XgmiiFrame, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSink
|
||||
|
||||
try:
|
||||
@ -61,7 +62,7 @@ class TB:
|
||||
self.source = BaseRSerdesSource(dut.encoded_rx_data, dut.encoded_rx_hdr, dut.clk, scramble=False)
|
||||
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
|
||||
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -84,16 +85,32 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
await tb.reset()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - 6.4) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -145,7 +162,7 @@ def test_axis_baser_rx_64(request):
|
||||
parameters['DATA_WIDTH'] = 64
|
||||
parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8
|
||||
parameters['HDR_WIDTH'] = 2
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
|
||||
|
@ -39,12 +39,11 @@ export PARAM_HDR_WIDTH ?= 2
|
||||
export PARAM_ENABLE_PADDING ?= 1
|
||||
export PARAM_ENABLE_DIC ?= 1
|
||||
export PARAM_MIN_FRAME_LENGTH ?= 64
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE)
|
||||
export PARAM_PTP_TAG_WIDTH ?= 16
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TAG_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -34,9 +34,12 @@ 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.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
try:
|
||||
from baser import BaseRSerdesSink
|
||||
@ -49,6 +52,12 @@ except ImportError:
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
@ -61,8 +70,10 @@ class TB:
|
||||
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
|
||||
self.sink = BaseRSerdesSink(dut.encoded_tx_data, dut.encoded_tx_hdr, dut.clk, scramble=False)
|
||||
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
|
||||
|
||||
dut.ifg_delay.setimmediatevalue(0)
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -91,9 +102,23 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 12.8) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -123,10 +148,23 @@ async def run_test_alignment(dut, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 12.8) < 0.01
|
||||
|
||||
start_lane.append(rx_frame.start_lane)
|
||||
|
||||
@ -223,7 +261,7 @@ def test_axis_baser_tx_64(request, enable_dic):
|
||||
parameters['ENABLE_PADDING'] = 1
|
||||
parameters['ENABLE_DIC'] = enable_dic
|
||||
parameters['MIN_FRAME_LENGTH'] = 64
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE']
|
||||
parameters['PTP_TAG_WIDTH'] = 16
|
||||
|
@ -36,10 +36,9 @@ VERILOG_SOURCES += ../../rtl/lfsr.v
|
||||
export PARAM_DATA_WIDTH ?= 32
|
||||
export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TS_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -32,9 +32,10 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSink
|
||||
|
||||
|
||||
@ -50,7 +51,7 @@ class TB:
|
||||
self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst)
|
||||
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
|
||||
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -73,16 +74,28 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
await tb.reset()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - 3.2) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -134,7 +147,7 @@ def test_axis_xgmii_rx_32(request):
|
||||
parameters['DATA_WIDTH'] = 32
|
||||
parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8
|
||||
parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
|
||||
|
@ -36,10 +36,9 @@ VERILOG_SOURCES += ../../rtl/lfsr.v
|
||||
export PARAM_DATA_WIDTH ?= 64
|
||||
export PARAM_KEEP_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TS_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -32,9 +32,10 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSink
|
||||
|
||||
|
||||
@ -50,7 +51,7 @@ class TB:
|
||||
self.source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.clk, dut.rst)
|
||||
self.sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "m_axis"), dut.clk, dut.rst)
|
||||
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -73,16 +74,32 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
await tb.reset()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - 6.4) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -134,7 +151,7 @@ def test_axis_xgmii_rx_64(request):
|
||||
parameters['DATA_WIDTH'] = 64
|
||||
parameters['KEEP_WIDTH'] = parameters['DATA_WIDTH'] // 8
|
||||
parameters['CTRL_WIDTH'] = parameters['DATA_WIDTH'] // 8
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['PTP_TS_ENABLE'] else 0) + 1
|
||||
|
||||
|
@ -39,12 +39,11 @@ export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_ENABLE_PADDING ?= 1
|
||||
export PARAM_ENABLE_DIC ?= 1
|
||||
export PARAM_MIN_FRAME_LENGTH ?= 64
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE)
|
||||
export PARAM_PTP_TAG_WIDTH ?= 16
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TAG_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -33,10 +33,18 @@ 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.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiSink
|
||||
from cocotbext.eth import XgmiiSink, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
@ -51,8 +59,10 @@ class TB:
|
||||
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
|
||||
self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst)
|
||||
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
|
||||
|
||||
dut.ifg_delay.setimmediatevalue(0)
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -81,9 +91,19 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 3.2) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -113,10 +133,19 @@ async def run_test_alignment(dut, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 3.2) < 0.01
|
||||
|
||||
start_lane.append(rx_frame.start_lane)
|
||||
|
||||
@ -213,7 +242,7 @@ def test_axis_xgmii_tx_32(request, enable_dic):
|
||||
parameters['ENABLE_PADDING'] = 1
|
||||
parameters['ENABLE_DIC'] = enable_dic
|
||||
parameters['MIN_FRAME_LENGTH'] = 64
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE']
|
||||
parameters['PTP_TAG_WIDTH'] = 16
|
||||
|
@ -39,12 +39,11 @@ export PARAM_CTRL_WIDTH ?= $(shell expr $(PARAM_DATA_WIDTH) / 8 )
|
||||
export PARAM_ENABLE_PADDING ?= 1
|
||||
export PARAM_ENABLE_DIC ?= 1
|
||||
export PARAM_MIN_FRAME_LENGTH ?= 64
|
||||
export PARAM_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_PTP_TAG_ENABLE ?= $(PARAM_PTP_TS_ENABLE)
|
||||
export PARAM_PTP_TAG_WIDTH ?= 16
|
||||
#export PARAM_USER_WIDTH ?= (parameters['PTP_TAG_WIDTH'] if parameters['PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_USER_WIDTH ?= 1
|
||||
export PARAM_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TAG_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -33,10 +33,18 @@ 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.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiSink
|
||||
from cocotbext.eth import XgmiiSink, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
@ -51,8 +59,10 @@ class TB:
|
||||
self.source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "s_axis"), dut.clk, dut.rst)
|
||||
self.sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.clk, dut.rst)
|
||||
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts, clock=dut.clk)
|
||||
self.ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "m_axis_ptp"), dut.clk, dut.rst)
|
||||
|
||||
dut.ifg_delay.setimmediatevalue(0)
|
||||
dut.ptp_ts.setimmediatevalue(0)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rst.setimmediatevalue(0)
|
||||
@ -81,9 +91,23 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 6.4) < 0.01
|
||||
|
||||
assert tb.sink.empty()
|
||||
|
||||
@ -113,10 +137,23 @@ async def run_test_alignment(dut, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.sink.recv()
|
||||
ptp_ts = await tb.ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= 3.2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - 6.4) < 0.01
|
||||
|
||||
start_lane.append(rx_frame.start_lane)
|
||||
|
||||
@ -213,7 +250,7 @@ def test_axis_xgmii_tx_64(request, enable_dic):
|
||||
parameters['ENABLE_PADDING'] = 1
|
||||
parameters['ENABLE_DIC'] = enable_dic
|
||||
parameters['MIN_FRAME_LENGTH'] = 64
|
||||
parameters['PTP_TS_ENABLE'] = 0
|
||||
parameters['PTP_TS_ENABLE'] = 1
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['PTP_TAG_ENABLE'] = parameters['PTP_TS_ENABLE']
|
||||
parameters['PTP_TAG_WIDTH'] = 16
|
||||
|
@ -45,16 +45,14 @@ export PARAM_ENABLE_DIC ?= 1
|
||||
export PARAM_MIN_FRAME_LENGTH ?= 64
|
||||
export PARAM_PTP_PERIOD_NS ?= 6
|
||||
export PARAM_PTP_PERIOD_FNS ?= 26214
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_TX_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE)
|
||||
export PARAM_TX_PTP_TAG_WIDTH ?= 16
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_RX_PTP_TS_WIDTH ?= 96
|
||||
# export PARAM_TX_USER_WIDTH ?= (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_TX_USER_WIDTH ?= 1
|
||||
# export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_RX_USER_WIDTH ?= 1
|
||||
export PARAM_TX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_TX_PTP_TAG_ENABLE)),1,$(shell expr $(PARAM_TX_PTP_TAG_WIDTH) + 1 ))
|
||||
export PARAM_RX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_RX_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_RX_PTP_TS_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -33,10 +33,18 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
@ -47,11 +55,12 @@ class TB:
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
if len(dut.xgmii_txd) == 64:
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start())
|
||||
self.clk_period = 6.4
|
||||
else:
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 3.2, units="ns").start())
|
||||
self.clk_period = 3.2
|
||||
|
||||
cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start())
|
||||
|
||||
self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst)
|
||||
self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst)
|
||||
@ -59,8 +68,9 @@ class TB:
|
||||
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.tx_clk, dut.tx_rst)
|
||||
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.rx_clk, dut.rx_rst)
|
||||
|
||||
dut.rx_ptp_ts.setimmediatevalue(0)
|
||||
dut.tx_ptp_ts.setimmediatevalue(0)
|
||||
self.rx_ptp_clock = PtpClockSimTime(ts_64=dut.rx_ptp_ts, clock=dut.rx_clk)
|
||||
self.tx_ptp_clock = PtpClockSimTime(ts_64=dut.tx_ptp_ts, clock=dut.tx_clk)
|
||||
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
|
||||
|
||||
async def reset(self):
|
||||
self.dut.rx_rst.setimmediatevalue(0)
|
||||
@ -87,16 +97,32 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
await tb.reset()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.xgmii_source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.axis_sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < 0.01
|
||||
|
||||
assert tb.axis_sink.empty()
|
||||
|
||||
@ -120,9 +146,23 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.xgmii_sink.recv()
|
||||
ptp_ts = await tb.tx_ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < 0.01
|
||||
|
||||
assert tb.xgmii_sink.empty()
|
||||
|
||||
@ -262,11 +302,11 @@ def test_eth_mac_10g(request, data_width, enable_dic):
|
||||
parameters['MIN_FRAME_LENGTH'] = 64
|
||||
parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3
|
||||
parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333
|
||||
parameters['TX_PTP_TS_ENABLE'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 1
|
||||
parameters['TX_PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE']
|
||||
parameters['TX_PTP_TAG_WIDTH'] = 16
|
||||
parameters['RX_PTP_TS_ENABLE'] = 0
|
||||
parameters['RX_PTP_TS_ENABLE'] = 1
|
||||
parameters['RX_PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
|
@ -36,6 +36,7 @@ VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_32.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_xgmii_rx_64.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_xgmii_tx_64.v
|
||||
VERILOG_SOURCES += ../../rtl/lfsr.v
|
||||
VERILOG_SOURCES += ../../rtl/ptp_clock_cdc.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v
|
||||
@ -64,16 +65,14 @@ export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_DROP_OVERSIZE_FRAME)
|
||||
export PARAM_PTP_PERIOD_NS ?= 6
|
||||
export PARAM_PTP_PERIOD_FNS ?= 26214
|
||||
export PARAM_PTP_USE_SAMPLE_CLOCK ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_TX_PTP_TS_FIFO_DEPTH ?= 64
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE)
|
||||
export PARAM_PTP_TAG_WIDTH ?= 16
|
||||
# export PARAM_TX_USER_WIDTH ?= (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_TX_USER_WIDTH ?= 1
|
||||
# export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_RX_USER_WIDTH ?= 1
|
||||
export PARAM_TX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_TX_PTP_TAG_ENABLE)),1,$(shell expr $(PARAM_PTP_TAG_WIDTH) + 1 ))
|
||||
export PARAM_RX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_RX_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TS_WIDTH) + 1 ))
|
||||
|
||||
ifeq ($(SIM), icarus)
|
||||
PLUSARGS += -fst
|
||||
|
@ -33,10 +33,18 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink
|
||||
from cocotbext.eth import XgmiiFrame, XgmiiSource, XgmiiSink, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts_96", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
@ -47,13 +55,13 @@ class TB:
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
if len(dut.xgmii_txd) == 64:
|
||||
cocotb.start_soon(Clock(dut.logic_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start())
|
||||
self.clk_period = 6.4
|
||||
else:
|
||||
cocotb.start_soon(Clock(dut.logic_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 3.2, units="ns").start())
|
||||
self.clk_period = 3.2
|
||||
|
||||
cocotb.start_soon(Clock(dut.logic_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start())
|
||||
|
||||
self.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst)
|
||||
self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst)
|
||||
@ -61,8 +69,10 @@ class TB:
|
||||
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.logic_clk, dut.logic_rst)
|
||||
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.logic_clk, dut.logic_rst)
|
||||
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk)
|
||||
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
|
||||
|
||||
dut.ptp_sample_clk.setimmediatevalue(0)
|
||||
dut.ptp_ts_96.setimmediatevalue(0)
|
||||
dut.ptp_ts_step.setimmediatevalue(0)
|
||||
|
||||
async def reset(self):
|
||||
@ -92,17 +102,37 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
await tb.reset()
|
||||
|
||||
tb.log.info("Wait for PTP CDC lock")
|
||||
while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.xgmii_source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.axis_sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period) < tb.clk_period
|
||||
|
||||
assert tb.axis_sink.empty()
|
||||
|
||||
@ -119,6 +149,10 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
await tb.reset()
|
||||
|
||||
tb.log.info("Wait for PTP CDC lock")
|
||||
while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
|
||||
for test_data in test_frames:
|
||||
@ -126,9 +160,23 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.xgmii_sink.recv()
|
||||
ptp_ts = await tb.tx_ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts_96) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period) < tb.clk_period
|
||||
|
||||
assert tb.xgmii_sink.empty()
|
||||
|
||||
@ -257,6 +305,7 @@ def test_eth_mac_10g_fifo(request, data_width, enable_dic):
|
||||
os.path.join(rtl_dir, "axis_xgmii_tx_32.v"),
|
||||
os.path.join(rtl_dir, "axis_xgmii_tx_64.v"),
|
||||
os.path.join(rtl_dir, "lfsr.v"),
|
||||
os.path.join(rtl_dir, "ptp_clock_cdc.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_adapter.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
|
||||
@ -287,14 +336,14 @@ def test_eth_mac_10g_fifo(request, data_width, enable_dic):
|
||||
parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3
|
||||
parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333
|
||||
parameters['PTP_USE_SAMPLE_CLOCK'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 0
|
||||
parameters['RX_PTP_TS_ENABLE'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 1
|
||||
parameters['RX_PTP_TS_ENABLE'] = 1
|
||||
parameters['TX_PTP_TS_FIFO_DEPTH'] = 64
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_PTP_TAG_ENABLE'] = 0
|
||||
parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE']
|
||||
parameters['PTP_TAG_WIDTH'] = 16
|
||||
parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
parameters['TX_USER_WIDTH'] = (parameters['PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
|
||||
extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()}
|
||||
|
||||
|
@ -50,16 +50,14 @@ export PARAM_ENABLE_DIC ?= 1
|
||||
export PARAM_MIN_FRAME_LENGTH ?= 64
|
||||
export PARAM_PTP_PERIOD_NS ?= 6
|
||||
export PARAM_PTP_PERIOD_FNS ?= 26214
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_TX_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE)
|
||||
export PARAM_TX_PTP_TAG_WIDTH ?= 16
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_RX_PTP_TS_WIDTH ?= 96
|
||||
# export PARAM_TX_USER_WIDTH ?= (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_TX_USER_WIDTH ?= 1
|
||||
# export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_RX_USER_WIDTH ?= 1
|
||||
export PARAM_TX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_TX_PTP_TAG_ENABLE)),1,$(shell expr $(PARAM_TX_PTP_TAG_WIDTH) + 1 ))
|
||||
export PARAM_RX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_RX_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_RX_PTP_TS_WIDTH) + 1 ))
|
||||
export PARAM_BIT_REVERSE ?= 0
|
||||
export PARAM_SCRAMBLER_DISABLE ?= 0
|
||||
export PARAM_PRBS31_ENABLE ?= 1
|
||||
|
@ -34,10 +34,12 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame
|
||||
from cocotbext.eth import XgmiiFrame, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
try:
|
||||
from baser import BaseRSerdesSource, BaseRSerdesSink
|
||||
@ -50,6 +52,12 @@ except ImportError:
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
@ -58,11 +66,12 @@ class TB:
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
if len(dut.serdes_tx_data) == 64:
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start())
|
||||
self.clk_period = 6.4
|
||||
else:
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 3.2, units="ns").start())
|
||||
self.clk_period = 3.2
|
||||
|
||||
cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start())
|
||||
|
||||
self.serdes_source = BaseRSerdesSource(dut.serdes_rx_data, dut.serdes_rx_hdr, dut.rx_clk, slip=dut.serdes_rx_bitslip)
|
||||
self.serdes_sink = BaseRSerdesSink(dut.serdes_tx_data, dut.serdes_tx_hdr, dut.tx_clk)
|
||||
@ -70,8 +79,9 @@ class TB:
|
||||
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.tx_clk, dut.tx_rst)
|
||||
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.rx_clk, dut.rx_rst)
|
||||
|
||||
dut.rx_ptp_ts.setimmediatevalue(0)
|
||||
dut.tx_ptp_ts.setimmediatevalue(0)
|
||||
self.rx_ptp_clock = PtpClockSimTime(ts_64=dut.rx_ptp_ts, clock=dut.rx_clk)
|
||||
self.tx_ptp_clock = PtpClockSimTime(ts_64=dut.tx_ptp_ts, clock=dut.tx_clk)
|
||||
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
|
||||
|
||||
dut.tx_prbs31_enable.setimmediatevalue(0)
|
||||
dut.rx_prbs31_enable.setimmediatevalue(0)
|
||||
@ -108,16 +118,34 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
tb.axis_sink.clear()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.serdes_source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.axis_sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
print(tx_frame)
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*4) < 0.01
|
||||
|
||||
assert tb.axis_sink.empty()
|
||||
|
||||
@ -141,9 +169,23 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.serdes_sink.recv()
|
||||
ptp_ts = await tb.tx_ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < 0.01
|
||||
|
||||
assert tb.serdes_sink.empty()
|
||||
|
||||
@ -329,11 +371,11 @@ def test_eth_mac_phy_10g(request, data_width, enable_dic):
|
||||
parameters['MIN_FRAME_LENGTH'] = 64
|
||||
parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3
|
||||
parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333
|
||||
parameters['TX_PTP_TS_ENABLE'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 1
|
||||
parameters['TX_PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE']
|
||||
parameters['TX_PTP_TAG_WIDTH'] = 16
|
||||
parameters['RX_PTP_TS_ENABLE'] = 0
|
||||
parameters['RX_PTP_TS_ENABLE'] = 1
|
||||
parameters['RX_PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
|
@ -41,6 +41,7 @@ VERILOG_SOURCES += ../../rtl/eth_phy_10g_tx_if.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_baser_rx_64.v
|
||||
VERILOG_SOURCES += ../../rtl/axis_baser_tx_64.v
|
||||
VERILOG_SOURCES += ../../rtl/lfsr.v
|
||||
VERILOG_SOURCES += ../../rtl/ptp_clock_cdc.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_adapter.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo.v
|
||||
VERILOG_SOURCES += ../../lib/axis/rtl/axis_async_fifo_adapter.v
|
||||
@ -69,16 +70,14 @@ export PARAM_RX_DROP_WHEN_FULL ?= $(PARAM_RX_DROP_OVERSIZE_FRAME)
|
||||
export PARAM_PTP_PERIOD_NS ?= 6
|
||||
export PARAM_PTP_PERIOD_FNS ?= 26214
|
||||
export PARAM_PTP_USE_SAMPLE_CLOCK ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_RX_PTP_TS_ENABLE ?= 1
|
||||
export PARAM_TX_PTP_TS_FIFO_DEPTH ?= 64
|
||||
export PARAM_PTP_TS_WIDTH ?= 96
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= 0
|
||||
export PARAM_TX_PTP_TAG_ENABLE ?= $(PARAM_TX_PTP_TS_ENABLE)
|
||||
export PARAM_PTP_TAG_WIDTH ?= 16
|
||||
# export PARAM_TX_USER_WIDTH ?= (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
export PARAM_TX_USER_WIDTH ?= 1
|
||||
# export PARAM_RX_USER_WIDTH ?= (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
export PARAM_RX_USER_WIDTH ?= 1
|
||||
export PARAM_TX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_TX_PTP_TAG_ENABLE)),1,$(shell expr $(PARAM_PTP_TAG_WIDTH) + 1 ))
|
||||
export PARAM_RX_USER_WIDTH ?= $(if $(filter-out 1,$(PARAM_RX_PTP_TS_ENABLE)),1,$(shell expr $(PARAM_PTP_TS_WIDTH) + 1 ))
|
||||
export PARAM_BIT_REVERSE ?= 0
|
||||
export PARAM_SCRAMBLER_DISABLE ?= 0
|
||||
export PARAM_PRBS31_ENABLE ?= 1
|
||||
|
@ -34,10 +34,12 @@ import cocotb_test.simulator
|
||||
import cocotb
|
||||
from cocotb.clock import Clock
|
||||
from cocotb.triggers import RisingEdge
|
||||
from cocotb.utils import get_time_from_sim_steps
|
||||
from cocotb.regression import TestFactory
|
||||
|
||||
from cocotbext.eth import XgmiiFrame
|
||||
from cocotbext.eth import XgmiiFrame, PtpClockSimTime
|
||||
from cocotbext.axi import AxiStreamBus, AxiStreamSource, AxiStreamSink
|
||||
from cocotbext.axi.stream import define_stream
|
||||
|
||||
try:
|
||||
from baser import BaseRSerdesSource, BaseRSerdesSink
|
||||
@ -50,6 +52,12 @@ except ImportError:
|
||||
del sys.path[0]
|
||||
|
||||
|
||||
PtpTsBus, PtpTsTransaction, PtpTsSource, PtpTsSink, PtpTsMonitor = define_stream("PtpTs",
|
||||
signals=["ts_96", "ts_valid"],
|
||||
optional_signals=["ts_tag", "ts_ready"]
|
||||
)
|
||||
|
||||
|
||||
class TB:
|
||||
def __init__(self, dut):
|
||||
self.dut = dut
|
||||
@ -58,13 +66,13 @@ class TB:
|
||||
self.log.setLevel(logging.DEBUG)
|
||||
|
||||
if len(dut.serdes_tx_data) == 64:
|
||||
cocotb.start_soon(Clock(dut.logic_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 6.4, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 6.4, units="ns").start())
|
||||
self.clk_period = 6.4
|
||||
else:
|
||||
cocotb.start_soon(Clock(dut.logic_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, 3.2, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, 3.2, units="ns").start())
|
||||
self.clk_period = 3.2
|
||||
|
||||
cocotb.start_soon(Clock(dut.logic_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start())
|
||||
cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start())
|
||||
|
||||
self.serdes_source = BaseRSerdesSource(dut.serdes_rx_data, dut.serdes_rx_hdr, dut.rx_clk, slip=dut.serdes_rx_bitslip)
|
||||
self.serdes_sink = BaseRSerdesSink(dut.serdes_tx_data, dut.serdes_tx_hdr, dut.tx_clk)
|
||||
@ -72,8 +80,10 @@ class TB:
|
||||
self.axis_source = AxiStreamSource(AxiStreamBus.from_prefix(dut, "tx_axis"), dut.logic_clk, dut.logic_rst)
|
||||
self.axis_sink = AxiStreamSink(AxiStreamBus.from_prefix(dut, "rx_axis"), dut.logic_clk, dut.logic_rst)
|
||||
|
||||
self.ptp_clock = PtpClockSimTime(ts_64=dut.ptp_ts_96, clock=dut.logic_clk)
|
||||
self.tx_ptp_ts_sink = PtpTsSink(PtpTsBus.from_prefix(dut, "tx_axis_ptp"), dut.tx_clk, dut.tx_rst)
|
||||
|
||||
dut.ptp_sample_clk.setimmediatevalue(0)
|
||||
dut.ptp_ts_96.setimmediatevalue(0)
|
||||
dut.ptp_ts_step.setimmediatevalue(0)
|
||||
|
||||
dut.tx_prbs31_enable.setimmediatevalue(0)
|
||||
@ -110,20 +120,40 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
while not dut.rx_block_lock.value.integer:
|
||||
await RisingEdge(dut.rx_clk)
|
||||
|
||||
tb.log.info("Wait for PTP CDC lock")
|
||||
while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
# clear out sink buffer
|
||||
tb.axis_sink.clear()
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
tx_frames = []
|
||||
|
||||
for test_data in test_frames:
|
||||
test_frame = XgmiiFrame.from_payload(test_data)
|
||||
test_frame = XgmiiFrame.from_payload(test_data, tx_complete=tx_frames.append)
|
||||
await tb.serdes_source.send(test_frame)
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.axis_sink.recv()
|
||||
tx_frame = tx_frames.pop(0)
|
||||
|
||||
frame_error = rx_frame.tuser & 1
|
||||
ptp_ts = rx_frame.tuser >> 1
|
||||
ptp_ts_ns = ptp_ts / 2**16
|
||||
|
||||
tx_frame_sfd_ns = get_time_from_sim_steps(tx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if tx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
tx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("RX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("TX frame SFD sim time: %f ns", tx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.tdata == test_data
|
||||
assert rx_frame.tuser == 0
|
||||
assert frame_error == 0
|
||||
assert abs(ptp_ts_ns - tx_frame_sfd_ns - tb.clk_period*4) < tb.clk_period
|
||||
|
||||
assert tb.axis_sink.empty()
|
||||
|
||||
@ -140,6 +170,10 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
await tb.reset()
|
||||
|
||||
tb.log.info("Wait for PTP CDC lock")
|
||||
while not dut.tx_ptp.tx_ptp_cdc.locked.value.integer:
|
||||
await RisingEdge(dut.tx_clk)
|
||||
|
||||
test_frames = [payload_data(x) for x in payload_lengths()]
|
||||
|
||||
for test_data in test_frames:
|
||||
@ -147,9 +181,23 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12):
|
||||
|
||||
for test_data in test_frames:
|
||||
rx_frame = await tb.serdes_sink.recv()
|
||||
ptp_ts = await tb.tx_ptp_ts_sink.recv()
|
||||
|
||||
ptp_ts_ns = int(ptp_ts.ts_96) / 2**16
|
||||
|
||||
rx_frame_sfd_ns = get_time_from_sim_steps(rx_frame.sim_time_sfd, "ns")
|
||||
|
||||
if rx_frame.start_lane == 4:
|
||||
# start in lane 4 reports 1 full cycle delay, so subtract half clock period
|
||||
rx_frame_sfd_ns -= tb.clk_period/2
|
||||
|
||||
tb.log.info("TX frame PTP TS: %f ns", ptp_ts_ns)
|
||||
tb.log.info("RX frame SFD sim time: %f ns", rx_frame_sfd_ns)
|
||||
|
||||
assert rx_frame.get_payload() == test_data
|
||||
assert rx_frame.check_fcs()
|
||||
assert rx_frame.ctrl is None
|
||||
assert abs(rx_frame_sfd_ns - ptp_ts_ns - tb.clk_period*5) < tb.clk_period
|
||||
|
||||
assert tb.serdes_sink.empty()
|
||||
|
||||
@ -324,6 +372,7 @@ def test_eth_mac_phy_10g_fifo(request, data_width, enable_dic):
|
||||
os.path.join(rtl_dir, "axis_baser_rx_64.v"),
|
||||
os.path.join(rtl_dir, "axis_baser_tx_64.v"),
|
||||
os.path.join(rtl_dir, "lfsr.v"),
|
||||
os.path.join(rtl_dir, "ptp_clock_cdc.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_adapter.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_async_fifo.v"),
|
||||
os.path.join(axis_rtl_dir, "axis_async_fifo_adapter.v"),
|
||||
@ -354,14 +403,14 @@ def test_eth_mac_phy_10g_fifo(request, data_width, enable_dic):
|
||||
parameters['PTP_PERIOD_NS'] = 0x6 if parameters['DATA_WIDTH'] == 64 else 0x3
|
||||
parameters['PTP_PERIOD_FNS'] = 0x6666 if parameters['DATA_WIDTH'] == 64 else 0x3333
|
||||
parameters['PTP_USE_SAMPLE_CLOCK'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 0
|
||||
parameters['RX_PTP_TS_ENABLE'] = 0
|
||||
parameters['TX_PTP_TS_ENABLE'] = 1
|
||||
parameters['RX_PTP_TS_ENABLE'] = 1
|
||||
parameters['TX_PTP_TS_FIFO_DEPTH'] = 64
|
||||
parameters['PTP_TS_WIDTH'] = 96
|
||||
parameters['TX_PTP_TAG_ENABLE'] = 0
|
||||
parameters['TX_PTP_TAG_ENABLE'] = parameters['TX_PTP_TS_ENABLE']
|
||||
parameters['PTP_TAG_WIDTH'] = 16
|
||||
parameters['TX_USER_WIDTH'] = (parameters['TX_PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['RX_PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
parameters['TX_USER_WIDTH'] = (parameters['PTP_TAG_WIDTH'] if parameters['TX_PTP_TS_ENABLE'] and parameters['TX_PTP_TAG_ENABLE'] else 0) + 1
|
||||
parameters['RX_USER_WIDTH'] = (parameters['PTP_TS_WIDTH'] if parameters['RX_PTP_TS_ENABLE'] else 0) + 1
|
||||
parameters['BIT_REVERSE'] = 0
|
||||
parameters['SCRAMBLER_DISABLE'] = 0
|
||||
parameters['PRBS31_ENABLE'] = 1
|
||||
|
Loading…
x
Reference in New Issue
Block a user