eth: Support 32-bit sync gearbox in 10G MAC

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich
2025-06-15 13:11:26 -07:00
parent ab09ceb891
commit 6407b4c7f0
9 changed files with 498 additions and 431 deletions

View File

@@ -19,6 +19,7 @@ module taxi_axis_xgmii_rx_32 #
( (
parameter DATA_W = 32, parameter DATA_W = 32,
parameter CTRL_W = (DATA_W/8), parameter CTRL_W = (DATA_W/8),
parameter logic GBX_IF_EN = 1'b0,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter PTP_TS_W = 96 parameter PTP_TS_W = 96
) )
@@ -31,6 +32,7 @@ module taxi_axis_xgmii_rx_32 #
*/ */
input wire logic [DATA_W-1:0] xgmii_rxd, input wire logic [DATA_W-1:0] xgmii_rxd,
input wire logic [CTRL_W-1:0] xgmii_rxc, input wire logic [CTRL_W-1:0] xgmii_rxc,
input wire logic xgmii_rx_valid,
/* /*
* Receive interface (AXI stream) * Receive interface (AXI stream)
@@ -257,207 +259,212 @@ always_comb begin
stat_rx_err_framing_next = 1'b0; stat_rx_err_framing_next = 1'b0;
stat_rx_err_preamble_next = 1'b0; stat_rx_err_preamble_next = 1'b0;
// counter to measure frame length if (GBX_IF_EN && !xgmii_rx_valid) begin
if (&frame_len_reg[15:2] == 0) begin // XGMII data not valid - hold state
if (term_present_reg) begin state_next = state_reg;
frame_len_next = frame_len_reg + 16'(term_lane_reg); end else begin
// counter to measure frame length
if (&frame_len_reg[15:2] == 0) begin
if (term_present_reg) begin
frame_len_next = frame_len_reg + 16'(term_lane_reg);
end else begin
frame_len_next = frame_len_reg + 16'(CTRL_W);
end
end else begin end else begin
frame_len_next = frame_len_reg + 16'(CTRL_W); frame_len_next = '1;
end end
end else begin
frame_len_next = '1;
end
// counter for max frame length enforcement // counter for max frame length enforcement
if (frame_len_lim_reg[15:2] != 0) begin if (frame_len_lim_reg[15:2] != 0) begin
frame_len_lim_next = frame_len_lim_reg - 16'(CTRL_W); frame_len_lim_next = frame_len_lim_reg - 16'(CTRL_W);
end else begin end else begin
frame_len_lim_next = '0; frame_len_lim_next = '0;
end
// address and ethertype checks
if (&hdr_ptr_reg == 0) begin
hdr_ptr_next = hdr_ptr_reg + 1;
end
case (hdr_ptr_reg)
3'd0: begin
is_mcast_next = xgmii_rxd_d2[0];
is_bcast_next = &xgmii_rxd_d2;
end end
3'd1: is_bcast_next = is_bcast_reg && &xgmii_rxd_d2[15:0];
3'd3: is_8021q_next = {xgmii_rxd_d2[7:0], xgmii_rxd_d2[15:8]} == 16'h8100; // address and ethertype checks
default: begin if (&hdr_ptr_reg == 0) begin
// do nothing hdr_ptr_next = hdr_ptr_reg + 1;
end end
endcase
case (state_reg) case (hdr_ptr_reg)
STATE_IDLE: begin 3'd0: begin
// idle state - wait for packet is_mcast_next = xgmii_rxd_d2[0];
reset_crc = 1'b1; is_bcast_next = &xgmii_rxd_d2;
end
3'd1: is_bcast_next = is_bcast_reg && &xgmii_rxd_d2[15:0];
3'd3: is_8021q_next = {xgmii_rxd_d2[7:0], xgmii_rxd_d2[15:8]} == 16'h8100;
default: begin
// do nothing
end
endcase
frame_len_next = 16'(CTRL_W); case (state_reg)
frame_len_lim_next = cfg_rx_max_pkt_len; STATE_IDLE: begin
hdr_ptr_next = 0; // idle state - wait for packet
reset_crc = 1'b1;
pre_ok_next = xgmii_rxd_d2[31:8] == 24'h555555; frame_len_next = 16'(CTRL_W);
frame_len_lim_next = cfg_rx_max_pkt_len;
hdr_ptr_next = 0;
pre_ok_next = xgmii_rxd_d2[31:8] == 24'h555555;
if (xgmii_start_d2 && cfg_rx_enable) begin
// start condition
if (framing_error_reg) begin
// control or error characters in first data word
stat_rx_err_framing_next = 1'b1;
state_next = STATE_IDLE;
end else begin
reset_crc = 1'b0;
stat_rx_byte_next = 3'(CTRL_W);
state_next = STATE_PREAMBLE;
end
end else begin
if (PTP_TS_EN) begin
ptp_ts_out_next = ptp_ts;
end
state_next = STATE_IDLE;
end
end
STATE_PREAMBLE: begin
// drop preamble
frame_len_lim_next = cfg_rx_max_pkt_len;
hdr_ptr_next = 0;
pre_ok_next = pre_ok_reg && xgmii_rxd_d2 == 32'hD5555555;
if (xgmii_start_d2 && cfg_rx_enable) begin
// start condition
if (framing_error_reg) begin if (framing_error_reg) begin
// control or error characters in first data word // control or error characters in packet
stat_rx_err_framing_next = 1'b1; stat_rx_err_framing_next = 1'b1;
state_next = STATE_IDLE; state_next = STATE_IDLE;
end else begin end else begin
reset_crc = 1'b0; start_packet_next = 1'b1;
stat_rx_byte_next = 3'(CTRL_W); stat_rx_byte_next = 3'(CTRL_W);
state_next = STATE_PREAMBLE; state_next = STATE_PAYLOAD;
end end
end else begin end
if (PTP_TS_EN) begin STATE_PAYLOAD: begin
ptp_ts_out_next = ptp_ts; // read payload
m_axis_rx_tdata_next = xgmii_rxd_d2;
m_axis_rx_tkeep_next = {KEEP_W{1'b1}};
m_axis_rx_tvalid_next = 1'b1;
m_axis_rx_tlast_next = 1'b0;
m_axis_rx_tuser_next = 1'b0;
if (term_present_reg) begin
stat_rx_byte_next = 3'(term_lane_reg);
frame_oversize_next = frame_len_lim_reg < 16'(4+4+term_lane_reg);
end else begin
stat_rx_byte_next = 3'(CTRL_W);
frame_oversize_next = frame_len_lim_reg < 4+4;
end end
state_next = STATE_IDLE;
end
end
STATE_PREAMBLE: begin
// drop preamble
frame_len_lim_next = cfg_rx_max_pkt_len; if (framing_error_reg) begin
hdr_ptr_next = 0; // control or error characters in packet
pre_ok_next = pre_ok_reg && xgmii_rxd_d2 == 32'hD5555555;
if (framing_error_reg) begin
// control or error characters in packet
stat_rx_err_framing_next = 1'b1;
state_next = STATE_IDLE;
end else begin
start_packet_next = 1'b1;
stat_rx_byte_next = 3'(CTRL_W);
state_next = STATE_PAYLOAD;
end
end
STATE_PAYLOAD: begin
// read payload
m_axis_rx_tdata_next = xgmii_rxd_d2;
m_axis_rx_tkeep_next = {KEEP_W{1'b1}};
m_axis_rx_tvalid_next = 1'b1;
m_axis_rx_tlast_next = 1'b0;
m_axis_rx_tuser_next = 1'b0;
if (term_present_reg) begin
stat_rx_byte_next = 3'(term_lane_reg);
frame_oversize_next = frame_len_lim_reg < 16'(4+4+term_lane_reg);
end else begin
stat_rx_byte_next = 3'(CTRL_W);
frame_oversize_next = frame_len_lim_reg < 4+4;
end
if (framing_error_reg) begin
// control or error characters in packet
m_axis_rx_tlast_next = 1'b1;
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_bad_next = 1'b1;
stat_rx_pkt_len_next = frame_len_next;
stat_rx_pkt_ucast_next = !is_mcast_reg;
stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_rx_pkt_bcast_next = is_bcast_reg;
stat_rx_pkt_vlan_next = is_8021q_reg;
stat_rx_err_oversize_next = frame_oversize_next;
stat_rx_err_framing_next = 1'b1;
stat_rx_err_preamble_next = !pre_ok_reg;
stat_rx_pkt_fragment_next = frame_len_next[15:6] == 0;
stat_rx_pkt_jabber_next = frame_oversize_next;
reset_crc = 1'b1;
state_next = STATE_IDLE;
end else if (term_present_reg) begin
reset_crc = 1'b1;
if (term_lane_reg == 0) begin
// end this cycle
m_axis_rx_tkeep_next = 4'b1111;
m_axis_rx_tlast_next = 1'b1; m_axis_rx_tlast_next = 1'b1;
if (term_lane_reg == 0 && crc_valid_save[3]) begin m_axis_rx_tuser_next = 1'b1;
// CRC valid stat_rx_pkt_bad_next = 1'b1;
if (frame_oversize_next) begin
// too long
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_bad_next = 1'b1;
end else begin
// length OK
m_axis_rx_tuser_next = 1'b0;
stat_rx_pkt_good_next = 1'b1;
end
end else begin
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_fragment_next = frame_len_next[15:6] == 0;
stat_rx_pkt_jabber_next = frame_oversize_next;
stat_rx_pkt_bad_next = 1'b1;
stat_rx_err_bad_fcs_next = 1'b1;
end
stat_rx_pkt_len_next = frame_len_next; stat_rx_pkt_len_next = frame_len_next;
stat_rx_pkt_ucast_next = !is_mcast_reg; stat_rx_pkt_ucast_next = !is_mcast_reg;
stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg; stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_rx_pkt_bcast_next = is_bcast_reg; stat_rx_pkt_bcast_next = is_bcast_reg;
stat_rx_pkt_vlan_next = is_8021q_reg; stat_rx_pkt_vlan_next = is_8021q_reg;
stat_rx_err_oversize_next = frame_oversize_next; stat_rx_err_oversize_next = frame_oversize_next;
stat_rx_err_framing_next = 1'b1;
stat_rx_err_preamble_next = !pre_ok_reg; stat_rx_err_preamble_next = !pre_ok_reg;
stat_rx_pkt_fragment_next = frame_len_next[15:6] == 0;
stat_rx_pkt_jabber_next = frame_oversize_next;
reset_crc = 1'b1;
state_next = STATE_IDLE; state_next = STATE_IDLE;
end else if (term_present_reg) begin
reset_crc = 1'b1;
if (term_lane_reg == 0) begin
// end this cycle
m_axis_rx_tkeep_next = 4'b1111;
m_axis_rx_tlast_next = 1'b1;
if (term_lane_reg == 0 && crc_valid_save[3]) begin
// CRC valid
if (frame_oversize_next) begin
// too long
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_bad_next = 1'b1;
end else begin
// length OK
m_axis_rx_tuser_next = 1'b0;
stat_rx_pkt_good_next = 1'b1;
end
end else begin
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_fragment_next = frame_len_next[15:6] == 0;
stat_rx_pkt_jabber_next = frame_oversize_next;
stat_rx_pkt_bad_next = 1'b1;
stat_rx_err_bad_fcs_next = 1'b1;
end
stat_rx_pkt_len_next = frame_len_next;
stat_rx_pkt_ucast_next = !is_mcast_reg;
stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_rx_pkt_bcast_next = is_bcast_reg;
stat_rx_pkt_vlan_next = is_8021q_reg;
stat_rx_err_oversize_next = frame_oversize_next;
stat_rx_err_preamble_next = !pre_ok_reg;
state_next = STATE_IDLE;
end else begin
// need extra cycle
state_next = STATE_LAST;
end
end else begin end else begin
// need extra cycle state_next = STATE_PAYLOAD;
state_next = STATE_LAST;
end end
end else begin
state_next = STATE_PAYLOAD;
end end
end STATE_LAST: begin
STATE_LAST: begin // last cycle of packet
// last cycle of packet m_axis_rx_tdata_next = xgmii_rxd_d2;
m_axis_rx_tdata_next = xgmii_rxd_d2; m_axis_rx_tkeep_next = {KEEP_W{1'b1}} >> 2'(CTRL_W-term_lane_d0_reg);
m_axis_rx_tkeep_next = {KEEP_W{1'b1}} >> 2'(CTRL_W-term_lane_d0_reg); m_axis_rx_tvalid_next = 1'b1;
m_axis_rx_tvalid_next = 1'b1; m_axis_rx_tlast_next = 1'b1;
m_axis_rx_tlast_next = 1'b1; m_axis_rx_tuser_next = 1'b0;
m_axis_rx_tuser_next = 1'b0;
reset_crc = 1'b1; reset_crc = 1'b1;
if ((term_lane_d0_reg == 1 && crc_valid_save[0]) || if ((term_lane_d0_reg == 1 && crc_valid_save[0]) ||
(term_lane_d0_reg == 2 && crc_valid_save[1]) || (term_lane_d0_reg == 2 && crc_valid_save[1]) ||
(term_lane_d0_reg == 3 && crc_valid_save[2])) begin (term_lane_d0_reg == 3 && crc_valid_save[2])) begin
// CRC valid // CRC valid
if (frame_oversize_reg) begin if (frame_oversize_reg) begin
// too long // too long
m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_bad_next = 1'b1;
end else begin
// length OK
m_axis_rx_tuser_next = 1'b0;
stat_rx_pkt_good_next = 1'b1;
end
end else begin
m_axis_rx_tuser_next = 1'b1; m_axis_rx_tuser_next = 1'b1;
stat_rx_pkt_fragment_next = frame_len_reg[15:6] == 0;
stat_rx_pkt_jabber_next = frame_oversize_reg;
stat_rx_pkt_bad_next = 1'b1; stat_rx_pkt_bad_next = 1'b1;
end else begin stat_rx_err_bad_fcs_next = 1'b1;
// length OK
m_axis_rx_tuser_next = 1'b0;
stat_rx_pkt_good_next = 1'b1;
end end
end else begin
m_axis_rx_tuser_next = 1'b1; stat_rx_pkt_len_next = frame_len_reg;
stat_rx_pkt_fragment_next = frame_len_reg[15:6] == 0; stat_rx_pkt_ucast_next = !is_mcast_reg;
stat_rx_pkt_jabber_next = frame_oversize_reg; stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_rx_pkt_bad_next = 1'b1; stat_rx_pkt_bcast_next = is_bcast_reg;
stat_rx_err_bad_fcs_next = 1'b1; stat_rx_pkt_vlan_next = is_8021q_reg;
stat_rx_err_oversize_next = frame_oversize_reg;
stat_rx_err_preamble_next = !pre_ok_reg;
state_next = STATE_IDLE;
end end
default: begin
stat_rx_pkt_len_next = frame_len_reg; // invalid state, return to idle
stat_rx_pkt_ucast_next = !is_mcast_reg; state_next = STATE_IDLE;
stat_rx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg; end
stat_rx_pkt_bcast_next = is_bcast_reg; endcase
stat_rx_pkt_vlan_next = is_8021q_reg; end
stat_rx_err_oversize_next = frame_oversize_reg;
stat_rx_err_preamble_next = !pre_ok_reg;
state_next = STATE_IDLE;
end
default: begin
// invalid state, return to idle
state_next = STATE_IDLE;
end
endcase
end end
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
@@ -498,39 +505,41 @@ always_ff @(posedge clk) begin
stat_rx_err_framing_reg <= stat_rx_err_framing_next; stat_rx_err_framing_reg <= stat_rx_err_framing_next;
stat_rx_err_preamble_reg <= stat_rx_err_preamble_next; stat_rx_err_preamble_reg <= stat_rx_err_preamble_next;
term_lane_reg <= 0; if (!GBX_IF_EN || xgmii_rx_valid) begin
term_present_reg <= 1'b0; term_lane_reg <= 0;
framing_error_reg <= xgmii_rxc != 0; term_present_reg <= 1'b0;
framing_error_reg <= xgmii_rxc != 0;
for (integer i = CTRL_W-1; i >= 0; i = i - 1) begin for (integer i = CTRL_W-1; i >= 0; i = i - 1) begin
if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin
term_lane_reg <= 2'(i); term_lane_reg <= 2'(i);
term_present_reg <= 1'b1; term_present_reg <= 1'b1;
framing_error_reg <= (xgmii_rxc & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0; framing_error_reg <= (xgmii_rxc & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0;
end
end end
term_lane_d0_reg <= term_lane_reg;
if (reset_crc) begin
crc_state <= '1;
end else begin
crc_state <= crc_next;
end
crc_valid_save <= crc_valid;
for (integer i = 0; i < CTRL_W; i = i + 1) begin
xgmii_rxd_d0[i*8 +: 8] <= xgmii_rxc[i] ? 8'd0 : xgmii_rxd[i*8 +: 8];
end
xgmii_rxc_d0 <= xgmii_rxc;
xgmii_rxd_d1 <= xgmii_rxd_d0;
xgmii_rxd_d2 <= xgmii_rxd_d1;
xgmii_start_d0 <= xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START;
xgmii_start_d1 <= xgmii_start_d0;
xgmii_start_d2 <= xgmii_start_d1;
end end
term_lane_d0_reg <= term_lane_reg;
if (reset_crc) begin
crc_state <= '1;
end else begin
crc_state <= crc_next;
end
crc_valid_save <= crc_valid;
for (integer i = 0; i < CTRL_W; i = i + 1) begin
xgmii_rxd_d0[i*8 +: 8] <= xgmii_rxc[i] ? 8'd0 : xgmii_rxd[i*8 +: 8];
end
xgmii_rxc_d0 <= xgmii_rxc;
xgmii_rxd_d1 <= xgmii_rxd_d0;
xgmii_rxd_d2 <= xgmii_rxd_d1;
xgmii_start_d0 <= xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START;
xgmii_start_d1 <= xgmii_start_d0;
xgmii_start_d2 <= xgmii_start_d1;
if (rst) begin if (rst) begin
state_reg <= STATE_IDLE; state_reg <= STATE_IDLE;

View File

@@ -19,6 +19,8 @@ module taxi_axis_xgmii_tx_32 #
( (
parameter DATA_W = 32, parameter DATA_W = 32,
parameter CTRL_W = (DATA_W/8), parameter CTRL_W = (DATA_W/8),
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic PADDING_EN = 1'b1, parameter logic PADDING_EN = 1'b1,
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
@@ -41,6 +43,10 @@ module taxi_axis_xgmii_tx_32 #
*/ */
output wire logic [DATA_W-1:0] xgmii_txd, output wire logic [DATA_W-1:0] xgmii_txd,
output wire logic [CTRL_W-1:0] xgmii_txc, output wire logic [CTRL_W-1:0] xgmii_txc,
output wire logic xgmii_tx_valid,
input wire logic [GBX_CNT-1:0] tx_gbx_req_sync = '0,
input wire logic tx_gbx_req_stall = '0,
output wire logic [GBX_CNT-1:0] tx_gbx_sync,
/* /*
* PTP * PTP
@@ -157,6 +163,8 @@ wire [31:0] crc_state_next[3:0];
logic [DATA_W-1:0] xgmii_txd_reg = {CTRL_W{XGMII_IDLE}}, xgmii_txd_next; logic [DATA_W-1:0] xgmii_txd_reg = {CTRL_W{XGMII_IDLE}}, xgmii_txd_next;
logic [CTRL_W-1:0] xgmii_txc_reg = {CTRL_W{1'b1}}, xgmii_txc_next; logic [CTRL_W-1:0] xgmii_txc_reg = {CTRL_W{1'b1}}, xgmii_txc_next;
logic xgmii_tx_valid_reg = 1'b0;
logic [GBX_CNT-1:0] tx_gbx_sync_reg = '0;
logic start_packet_reg = 1'b0, start_packet_next; logic start_packet_reg = 1'b0, start_packet_next;
@@ -172,10 +180,12 @@ logic stat_tx_err_oversize_reg = 1'b0, stat_tx_err_oversize_next;
logic stat_tx_err_user_reg = 1'b0, stat_tx_err_user_next; logic stat_tx_err_user_reg = 1'b0, stat_tx_err_user_next;
logic stat_tx_err_underflow_reg = 1'b0, stat_tx_err_underflow_next; logic stat_tx_err_underflow_reg = 1'b0, stat_tx_err_underflow_next;
assign s_axis_tx.tready = s_axis_tx_tready_reg; assign s_axis_tx.tready = s_axis_tx_tready_reg && (!GBX_IF_EN || !tx_gbx_req_stall);
assign xgmii_txd = xgmii_txd_reg; assign xgmii_txd = xgmii_txd_reg;
assign xgmii_txc = xgmii_txc_reg; assign xgmii_txc = xgmii_txc_reg;
assign xgmii_tx_valid = GBX_IF_EN ? xgmii_tx_valid_reg : 1'b1;
assign tx_gbx_sync = GBX_IF_EN ? tx_gbx_sync_reg : '0;
assign m_axis_tx_cpl.tdata = PTP_TS_EN ? m_axis_tx_cpl_ts_reg : '0; assign m_axis_tx_cpl.tdata = PTP_TS_EN ? m_axis_tx_cpl_ts_reg : '0;
assign m_axis_tx_cpl.tkeep = 1'b1; assign m_axis_tx_cpl.tkeep = 1'b1;
@@ -340,192 +350,216 @@ always_comb begin
frame_next = !s_axis_tx.tlast; frame_next = !s_axis_tx.tlast;
end end
// counter for min frame length enforcement if (GBX_IF_EN && tx_gbx_req_stall) begin
if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin // gearbox stall - hold state
frame_min_count_next = MIN_LEN_W'(frame_min_count_reg - CTRL_W); state_next = state_reg;
// frame_start_next = frame_start_reg;
s_axis_tx_tready_next = s_axis_tx_tready_reg;
end else begin end else begin
frame_min_count_next = 0; // counter for min frame length enforcement
end if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin
frame_min_count_next = MIN_LEN_W'(frame_min_count_reg - CTRL_W);
// counter to measure frame length end else begin
if (&frame_len_reg[15:2] == 0) begin frame_min_count_next = 0;
frame_len_next = frame_len_reg + 16'(CTRL_W);
end else begin
frame_len_next = '1;
end
// counter for max frame length enforcement
if (frame_len_lim_reg[15:2] != 0) begin
frame_len_lim_next = frame_len_lim_reg - 16'(CTRL_W);
end else begin
frame_len_lim_next = '0;
end
// address and ethertype checks
if (&hdr_ptr_reg == 0) begin
hdr_ptr_next = hdr_ptr_reg + 1;
end
case (hdr_ptr_reg)
3'd0: begin
is_mcast_next = s_tdata_reg[0];
is_bcast_next = &s_tdata_reg;
end end
3'd1: is_bcast_next = is_bcast_reg && &s_tdata_reg[15:0];
3'd3: is_8021q_next = {s_tdata_reg[7:0], s_tdata_reg[15:8]} == 16'h8100; // counter to measure frame length
default: begin if (&frame_len_reg[15:2] == 0) begin
// do nothing frame_len_next = frame_len_reg + 16'(CTRL_W);
end else begin
frame_len_next = '1;
end end
endcase
if (ifg_cnt_reg[7:2] != 0) begin // counter for max frame length enforcement
ifg_cnt_next = ifg_cnt_reg - 8'(CTRL_W); if (frame_len_lim_reg[15:2] != 0) begin
end else begin frame_len_lim_next = frame_len_lim_reg - 16'(CTRL_W);
ifg_cnt_next = '0; end else begin
end frame_len_lim_next = '0;
end
case (state_reg) // address and ethertype checks
STATE_IDLE: begin if (&hdr_ptr_reg == 0) begin
// idle state - wait for data hdr_ptr_next = hdr_ptr_reg + 1;
frame_error_next = 1'b0; end
frame_min_count_next = MIN_LEN_W'(MIN_FRAME_LEN-4-CTRL_W);
hdr_ptr_next = 0;
frame_len_next = 0;
frame_len_lim_next = cfg_tx_max_pkt_len;
reset_crc = 1'b1;
// XGMII idle case (hdr_ptr_reg)
xgmii_txd_next = {CTRL_W{XGMII_IDLE}}; 3'd0: begin
xgmii_txc_next = {CTRL_W{1'b1}}; is_mcast_next = s_tdata_reg[0];
is_bcast_next = &s_tdata_reg;
end
3'd1: is_bcast_next = is_bcast_reg && &s_tdata_reg[15:0];
3'd3: is_8021q_next = {s_tdata_reg[7:0], s_tdata_reg[15:8]} == 16'h8100;
default: begin
// do nothing
end
endcase
s_tdata_next = s_axis_tx_tdata_masked; if (ifg_cnt_reg[7:2] != 0) begin
s_empty_next = keep2empty(s_axis_tx.tkeep); ifg_cnt_next = ifg_cnt_reg - 8'(CTRL_W);
end else begin
ifg_cnt_next = '0;
end
case (state_reg)
STATE_IDLE: begin
// idle state - wait for data
frame_error_next = 1'b0;
frame_min_count_next = MIN_LEN_W'(MIN_FRAME_LEN-4-CTRL_W);
hdr_ptr_next = 0;
frame_len_next = 0;
frame_len_lim_next = cfg_tx_max_pkt_len;
reset_crc = 1'b1;
// XGMII idle
xgmii_txd_next = {CTRL_W{XGMII_IDLE}};
xgmii_txc_next = {CTRL_W{1'b1}};
s_tdata_next = s_axis_tx_tdata_masked;
s_empty_next = keep2empty(s_axis_tx.tkeep);
if (s_axis_tx.tvalid && cfg_tx_enable) begin
// XGMII start and preamble
xgmii_txd_next = {{3{ETH_PRE}}, XGMII_START};
xgmii_txc_next = 4'b0001;
s_axis_tx_tready_next = 1'b1;
state_next = STATE_PREAMBLE;
end else begin
ifg_count_next = 8'd0;
deficit_idle_count_next = 2'd0;
state_next = STATE_IDLE;
end
end
STATE_PREAMBLE: begin
// send preamble
reset_crc = 1'b1;
hdr_ptr_next = 0;
frame_len_next = 0;
frame_len_lim_next = cfg_tx_max_pkt_len;
s_tdata_next = s_axis_tx_tdata_masked;
s_empty_next = keep2empty(s_axis_tx.tkeep);
xgmii_txd_next = {ETH_SFD, {3{ETH_PRE}}};
xgmii_txc_next = {CTRL_W{1'b0}};
if (s_axis_tx.tvalid && cfg_tx_enable) begin
// XGMII start and preamble
xgmii_txd_next = {{3{ETH_PRE}}, XGMII_START};
xgmii_txc_next = 4'b0001;
s_axis_tx_tready_next = 1'b1; s_axis_tx_tready_next = 1'b1;
state_next = STATE_PREAMBLE; start_packet_next = 1'b1;
end else begin state_next = STATE_PAYLOAD;
ifg_count_next = 8'd0;
deficit_idle_count_next = 2'd0;
state_next = STATE_IDLE;
end end
end STATE_PAYLOAD: begin
STATE_PREAMBLE: begin // transfer payload
// send preamble update_crc = 1'b1;
reset_crc = 1'b1; s_axis_tx_tready_next = 1'b1;
hdr_ptr_next = 0; xgmii_txd_next = s_tdata_reg;
frame_len_next = 0; xgmii_txc_next = {CTRL_W{1'b0}};
frame_len_lim_next = cfg_tx_max_pkt_len;
s_tdata_next = s_axis_tx_tdata_masked; s_tdata_next = s_axis_tx_tdata_masked;
s_empty_next = keep2empty(s_axis_tx.tkeep); s_empty_next = keep2empty(s_axis_tx.tkeep);
xgmii_txd_next = {ETH_SFD, {3{ETH_PRE}}}; stat_tx_byte_next = 3'(CTRL_W);
xgmii_txc_next = {CTRL_W{1'b0}};
s_axis_tx_tready_next = 1'b1; if (s_axis_tx.tvalid && s_axis_tx.tlast) begin
start_packet_next = 1'b1; frame_oversize_next = frame_len_lim_reg < 16'(4+4+4-keep2empty(s_axis_tx.tkeep));
state_next = STATE_PAYLOAD; end else begin
end frame_oversize_next = frame_len_lim_reg < 4+4;
STATE_PAYLOAD: begin end
// transfer payload
update_crc = 1'b1;
s_axis_tx_tready_next = 1'b1;
xgmii_txd_next = s_tdata_reg; if (!s_axis_tx.tvalid || s_axis_tx.tlast || frame_oversize_next) begin
xgmii_txc_next = {CTRL_W{1'b0}}; s_axis_tx_tready_next = frame_next; // drop frame
frame_error_next = !s_axis_tx.tvalid || s_axis_tx.tuser[0] || frame_oversize_next;
stat_tx_err_user_next = s_axis_tx.tuser[0];
stat_tx_err_underflow_next = !s_axis_tx.tvalid;
s_tdata_next = s_axis_tx_tdata_masked; if (PADDING_EN && frame_min_count_reg != 0) begin
s_empty_next = keep2empty(s_axis_tx.tkeep); if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin
s_empty_next = 0;
stat_tx_byte_next = 3'(CTRL_W); state_next = STATE_PAD;
end else begin
if (s_axis_tx.tvalid && s_axis_tx.tlast) begin if (keep2empty(s_axis_tx.tkeep) > 2'(CTRL_W-frame_min_count_reg)) begin
frame_oversize_next = frame_len_lim_reg < 16'(4+4+4-keep2empty(s_axis_tx.tkeep)); s_empty_next = 2'(CTRL_W-frame_min_count_reg);
end else begin end
frame_oversize_next = frame_len_lim_reg < 4+4; state_next = STATE_FCS_1;
end
if (!s_axis_tx.tvalid || s_axis_tx.tlast || frame_oversize_next) begin
s_axis_tx_tready_next = frame_next; // drop frame
frame_error_next = !s_axis_tx.tvalid || s_axis_tx.tuser[0] || frame_oversize_next;
stat_tx_err_user_next = s_axis_tx.tuser[0];
stat_tx_err_underflow_next = !s_axis_tx.tvalid;
if (PADDING_EN && frame_min_count_reg != 0) begin
if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin
s_empty_next = 0;
state_next = STATE_PAD;
end else begin
if (keep2empty(s_axis_tx.tkeep) > 2'(CTRL_W-frame_min_count_reg)) begin
s_empty_next = 2'(CTRL_W-frame_min_count_reg);
end end
end else begin
state_next = STATE_FCS_1; state_next = STATE_FCS_1;
end end
end else begin end else begin
state_next = STATE_PAYLOAD;
end
end
STATE_PAD: begin
// pad frame to MIN_FRAME_LEN
s_axis_tx_tready_next = frame_next; // drop frame
xgmii_txd_next = s_tdata_reg;
xgmii_txc_next = {CTRL_W{1'b0}};
s_tdata_next = 32'd0;
s_empty_next = 0;
stat_tx_byte_next = 3'(CTRL_W);
update_crc = 1'b1;
if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin
state_next = STATE_PAD;
end else begin
s_empty_next = 2'(CTRL_W-frame_min_count_reg);
state_next = STATE_FCS_1; state_next = STATE_FCS_1;
end end
end else begin
state_next = STATE_PAYLOAD;
end end
end STATE_FCS_1: begin
STATE_PAD: begin // last cycle
// pad frame to MIN_FRAME_LEN s_axis_tx_tready_next = frame_next; // drop frame
s_axis_tx_tready_next = frame_next; // drop frame
xgmii_txd_next = s_tdata_reg; xgmii_txd_next = fcs_output_txd_0;
xgmii_txc_next = {CTRL_W{1'b0}}; xgmii_txc_next = fcs_output_txc_0;
s_tdata_next = 32'd0; stat_tx_byte_next = 3'(CTRL_W);
s_empty_next = 0;
stat_tx_byte_next = 3'(CTRL_W); update_crc = 1'b1;
update_crc = 1'b1; ifg_count_next = (cfg_tx_ifg > 8'd12 ? cfg_tx_ifg : 8'd12) - ifg_offset + 8'(deficit_idle_count_reg);
if (frame_error_reg) begin
if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin state_next = STATE_ERR;
state_next = STATE_PAD; end else begin
end else begin state_next = STATE_FCS_2;
s_empty_next = 2'(CTRL_W-frame_min_count_reg); end
state_next = STATE_FCS_1;
end end
end STATE_FCS_2: begin
STATE_FCS_1: begin // last cycle
// last cycle s_axis_tx_tready_next = frame_next; // drop frame
s_axis_tx_tready_next = frame_next; // drop frame
xgmii_txd_next = fcs_output_txd_0; xgmii_txd_next = fcs_output_txd_1;
xgmii_txc_next = fcs_output_txc_0; xgmii_txc_next = fcs_output_txc_1;
stat_tx_byte_next = 3'(CTRL_W); stat_tx_byte_next = 4-s_empty_reg;
frame_len_next = frame_len_reg + 16'(4-s_empty_reg);
update_crc = 1'b1; if (extra_cycle) begin
state_next = STATE_FCS_3;
ifg_count_next = (cfg_tx_ifg > 8'd12 ? cfg_tx_ifg : 8'd12) - ifg_offset + 8'(deficit_idle_count_reg); end else begin
if (frame_error_reg) begin stat_tx_pkt_len_next = frame_len_next;
state_next = STATE_ERR; stat_tx_pkt_good_next = !frame_error_reg;
end else begin stat_tx_pkt_bad_next = frame_error_reg;
state_next = STATE_FCS_2; stat_tx_pkt_ucast_next = !is_mcast_reg;
stat_tx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_tx_pkt_bcast_next = is_bcast_reg;
stat_tx_pkt_vlan_next = is_8021q_reg;
stat_tx_err_oversize_next = frame_oversize_reg;
state_next = STATE_IFG;
end
end end
end STATE_FCS_3: begin
STATE_FCS_2: begin // last cycle
// last cycle s_axis_tx_tready_next = frame_next; // drop frame
s_axis_tx_tready_next = frame_next; // drop frame
xgmii_txd_next = fcs_output_txd_1; xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM};
xgmii_txc_next = fcs_output_txc_1; xgmii_txc_next = {CTRL_W{1'b1}};
stat_tx_byte_next = 4-s_empty_reg; stat_tx_pkt_len_next = frame_len_reg;
frame_len_next = frame_len_reg + 16'(4-s_empty_reg);
if (extra_cycle) begin
state_next = STATE_FCS_3;
end else begin
stat_tx_pkt_len_next = frame_len_next;
stat_tx_pkt_good_next = !frame_error_reg; stat_tx_pkt_good_next = !frame_error_reg;
stat_tx_pkt_bad_next = frame_error_reg; stat_tx_pkt_bad_next = frame_error_reg;
stat_tx_pkt_ucast_next = !is_mcast_reg; stat_tx_pkt_ucast_next = !is_mcast_reg;
@@ -533,98 +567,81 @@ always_comb begin
stat_tx_pkt_bcast_next = is_bcast_reg; stat_tx_pkt_bcast_next = is_bcast_reg;
stat_tx_pkt_vlan_next = is_8021q_reg; stat_tx_pkt_vlan_next = is_8021q_reg;
stat_tx_err_oversize_next = frame_oversize_reg; stat_tx_err_oversize_next = frame_oversize_reg;
if (DIC_EN) begin
if (ifg_count_next > 8'd3) begin
state_next = STATE_IFG;
end else begin
deficit_idle_count_next = 2'(ifg_count_next);
ifg_count_next = 8'd0;
s_axis_tx_tready_next = 1'b1;
state_next = STATE_IDLE;
end
end else begin
if (ifg_count_next > 8'd0) begin
state_next = STATE_IFG;
end else begin
state_next = STATE_IDLE;
end
end
end
STATE_ERR: begin
// terminate packet with error
s_axis_tx_tready_next = frame_next; // drop frame
// XGMII error
xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}};
xgmii_txc_next = {CTRL_W{1'b1}};
ifg_count_next = cfg_tx_ifg > 8'd12 ? cfg_tx_ifg : 8'd12;
stat_tx_pkt_len_next = frame_len_reg;
stat_tx_pkt_good_next = !frame_error_reg;
stat_tx_pkt_bad_next = frame_error_reg;
stat_tx_pkt_ucast_next = !is_mcast_reg;
stat_tx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_tx_pkt_bcast_next = is_bcast_reg;
stat_tx_pkt_vlan_next = is_8021q_reg;
stat_tx_err_oversize_next = frame_oversize_reg;
state_next = STATE_IFG; state_next = STATE_IFG;
end end
end STATE_IFG: begin
STATE_FCS_3: begin // send IFG
// last cycle s_axis_tx_tready_next = frame_next; // drop frame
s_axis_tx_tready_next = frame_next; // drop frame
xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM}; // XGMII idle
xgmii_txc_next = {CTRL_W{1'b1}}; xgmii_txd_next = {CTRL_W{XGMII_IDLE}};
xgmii_txc_next = {CTRL_W{1'b1}};
stat_tx_pkt_len_next = frame_len_reg; if (ifg_count_reg > 8'd4) begin
stat_tx_pkt_good_next = !frame_error_reg; ifg_count_next = ifg_count_reg - 8'd4;
stat_tx_pkt_bad_next = frame_error_reg;
stat_tx_pkt_ucast_next = !is_mcast_reg;
stat_tx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_tx_pkt_bcast_next = is_bcast_reg;
stat_tx_pkt_vlan_next = is_8021q_reg;
stat_tx_err_oversize_next = frame_oversize_reg;
if (DIC_EN) begin
if (ifg_count_next > 8'd3) begin
state_next = STATE_IFG;
end else begin end else begin
deficit_idle_count_next = 2'(ifg_count_next);
ifg_count_next = 8'd0; ifg_count_next = 8'd0;
s_axis_tx_tready_next = 1'b1;
state_next = STATE_IDLE;
end end
end else begin
if (ifg_count_next > 8'd0) begin if (DIC_EN) begin
state_next = STATE_IFG; if (ifg_count_next > 8'd3 || frame_reg) begin
state_next = STATE_IFG;
end else begin
deficit_idle_count_next = 2'(ifg_count_next);
ifg_count_next = 8'd0;
state_next = STATE_IDLE;
end
end else begin end else begin
state_next = STATE_IDLE; if (ifg_count_next > 8'd0 || frame_reg) begin
state_next = STATE_IFG;
end else begin
state_next = STATE_IDLE;
end
end end
end end
end default: begin
STATE_ERR: begin // invalid state, return to idle
// terminate packet with error state_next = STATE_IDLE;
s_axis_tx_tready_next = frame_next; // drop frame
// XGMII error
xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}};
xgmii_txc_next = {CTRL_W{1'b1}};
ifg_count_next = cfg_tx_ifg > 8'd12 ? cfg_tx_ifg : 8'd12;
stat_tx_pkt_len_next = frame_len_reg;
stat_tx_pkt_good_next = !frame_error_reg;
stat_tx_pkt_bad_next = frame_error_reg;
stat_tx_pkt_ucast_next = !is_mcast_reg;
stat_tx_pkt_mcast_next = is_mcast_reg && !is_bcast_reg;
stat_tx_pkt_bcast_next = is_bcast_reg;
stat_tx_pkt_vlan_next = is_8021q_reg;
stat_tx_err_oversize_next = frame_oversize_reg;
state_next = STATE_IFG;
end
STATE_IFG: begin
// send IFG
s_axis_tx_tready_next = frame_next; // drop frame
// XGMII idle
xgmii_txd_next = {CTRL_W{XGMII_IDLE}};
xgmii_txc_next = {CTRL_W{1'b1}};
if (ifg_count_reg > 8'd4) begin
ifg_count_next = ifg_count_reg - 8'd4;
end else begin
ifg_count_next = 8'd0;
end end
endcase
if (DIC_EN) begin end
if (ifg_count_next > 8'd3 || frame_reg) begin
state_next = STATE_IFG;
end else begin
deficit_idle_count_next = 2'(ifg_count_next);
ifg_count_next = 8'd0;
state_next = STATE_IDLE;
end
end else begin
if (ifg_count_next > 8'd0 || frame_reg) begin
state_next = STATE_IFG;
end else begin
state_next = STATE_IDLE;
end
end
end
default: begin
// invalid state, return to idle
state_next = STATE_IDLE;
end
endcase
end end
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
@@ -654,8 +671,12 @@ always_ff @(posedge clk) begin
m_axis_tx_cpl_tag_reg <= m_axis_tx_cpl_tag_next; m_axis_tx_cpl_tag_reg <= m_axis_tx_cpl_tag_next;
m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_next; m_axis_tx_cpl_valid_reg <= m_axis_tx_cpl_valid_next;
for (integer i = 0; i < 3; i = i + 1) begin if (GBX_IF_EN && tx_gbx_req_stall) begin
crc_state_reg[i] <= crc_state_next[i]; // gearbox stall
end else begin
for (integer i = 0; i < 3; i = i + 1) begin
crc_state_reg[i] <= crc_state_next[i];
end
end end
if (update_crc) begin if (update_crc) begin
@@ -668,6 +689,7 @@ always_ff @(posedge clk) begin
xgmii_txd_reg <= xgmii_txd_next; xgmii_txd_reg <= xgmii_txd_next;
xgmii_txc_reg <= xgmii_txc_next; xgmii_txc_reg <= xgmii_txc_next;
xgmii_tx_valid_reg <= !tx_gbx_req_stall;
start_packet_reg <= start_packet_next; start_packet_reg <= start_packet_next;
@@ -683,6 +705,8 @@ always_ff @(posedge clk) begin
stat_tx_err_user_reg <= stat_tx_err_user_next; stat_tx_err_user_reg <= stat_tx_err_user_next;
stat_tx_err_underflow_reg <= stat_tx_err_underflow_next; stat_tx_err_underflow_reg <= stat_tx_err_underflow_next;
tx_gbx_sync_reg <= tx_gbx_req_sync;
if (rst) begin if (rst) begin
state_reg <= STATE_IDLE; state_reg <= STATE_IDLE;
@@ -697,6 +721,8 @@ always_ff @(posedge clk) begin
xgmii_txd_reg <= {CTRL_W{XGMII_IDLE}}; xgmii_txd_reg <= {CTRL_W{XGMII_IDLE}};
xgmii_txc_reg <= {CTRL_W{1'b1}}; xgmii_txc_reg <= {CTRL_W{1'b1}};
xgmii_tx_valid_reg <= 1'b0;
tx_gbx_sync_reg <= '0;
start_packet_reg <= 1'b0; start_packet_reg <= 1'b0;

View File

@@ -341,6 +341,7 @@ end else if (DATA_W == 32) begin
taxi_axis_xgmii_rx_32 #( taxi_axis_xgmii_rx_32 #(
.DATA_W(DATA_W), .DATA_W(DATA_W),
.CTRL_W(CTRL_W), .CTRL_W(CTRL_W),
.GBX_IF_EN(RX_GBX_IF_EN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TS_W(PTP_TS_W) .PTP_TS_W(PTP_TS_W)
) )
@@ -353,6 +354,7 @@ end else if (DATA_W == 32) begin
*/ */
.xgmii_rxd(xgmii_rxd), .xgmii_rxd(xgmii_rxd),
.xgmii_rxc(xgmii_rxc), .xgmii_rxc(xgmii_rxc),
.xgmii_rx_valid(xgmii_rx_valid),
/* /*
* Receive interface (AXI stream) * Receive interface (AXI stream)
@@ -397,6 +399,8 @@ end else if (DATA_W == 32) begin
taxi_axis_xgmii_tx_32 #( taxi_axis_xgmii_tx_32 #(
.DATA_W(DATA_W), .DATA_W(DATA_W),
.CTRL_W(CTRL_W), .CTRL_W(CTRL_W),
.GBX_IF_EN(TX_GBX_IF_EN),
.GBX_CNT(GBX_CNT),
.PADDING_EN(PADDING_EN), .PADDING_EN(PADDING_EN),
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
@@ -419,6 +423,10 @@ end else if (DATA_W == 32) begin
*/ */
.xgmii_txd(xgmii_txd), .xgmii_txd(xgmii_txd),
.xgmii_txc(xgmii_txc), .xgmii_txc(xgmii_txc),
.xgmii_tx_valid(xgmii_tx_valid),
.tx_gbx_req_sync(tx_gbx_req_sync),
.tx_gbx_req_stall(tx_gbx_req_stall),
.tx_gbx_sync(tx_gbx_sync),
/* /*
* PTP * PTP

View File

@@ -35,6 +35,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
# module parameters # module parameters
export PARAM_DATA_W := 32 export PARAM_DATA_W := 32
export PARAM_GBX_IF_EN := 0
export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_EN := 1
export PARAM_PTP_TS_W := 96 export PARAM_PTP_TS_W := 96

View File

@@ -39,6 +39,8 @@ class TB:
self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk) self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.clk)
dut.xgmii_rx_valid.setimmediatevalue(1)
dut.cfg_rx_max_pkt_len.setimmediatevalue(0) dut.cfg_rx_max_pkt_len.setimmediatevalue(0)
dut.cfg_rx_enable.setimmediatevalue(0) dut.cfg_rx_enable.setimmediatevalue(0)
@@ -305,6 +307,7 @@ def test_taxi_axis_xgmii_rx_32(request):
parameters = {} parameters = {}
parameters['DATA_W'] = 32 parameters['DATA_W'] = 32
parameters['GBX_IF_EN'] = 0
parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_EN'] = 1
parameters['PTP_TS_W'] = 96 parameters['PTP_TS_W'] = 96

View File

@@ -19,6 +19,7 @@ module test_taxi_axis_xgmii_rx_32 #
( (
/* verilator lint_off WIDTHTRUNC */ /* verilator lint_off WIDTHTRUNC */
parameter DATA_W = 32, parameter DATA_W = 32,
parameter logic GBX_IF_EN = 1'b0,
parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0,
parameter PTP_TS_W = 96 parameter PTP_TS_W = 96
/* verilator lint_on WIDTHTRUNC */ /* verilator lint_on WIDTHTRUNC */
@@ -33,6 +34,7 @@ logic rst;
logic [DATA_W-1:0] xgmii_rxd; logic [DATA_W-1:0] xgmii_rxd;
logic [CTRL_W-1:0] xgmii_rxc; logic [CTRL_W-1:0] xgmii_rxc;
logic xgmii_rx_valid;
taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx(); taxi_axis_if #(.DATA_W(DATA_W), .USER_EN(1), .USER_W(USER_W)) m_axis_rx();
@@ -61,6 +63,7 @@ logic stat_rx_err_preamble;
taxi_axis_xgmii_rx_32 #( taxi_axis_xgmii_rx_32 #(
.DATA_W(DATA_W), .DATA_W(DATA_W),
.CTRL_W(CTRL_W), .CTRL_W(CTRL_W),
.GBX_IF_EN(GBX_IF_EN),
.PTP_TS_EN(PTP_TS_EN), .PTP_TS_EN(PTP_TS_EN),
.PTP_TS_W(PTP_TS_W) .PTP_TS_W(PTP_TS_W)
) )
@@ -73,6 +76,7 @@ uut (
*/ */
.xgmii_rxd(xgmii_rxd), .xgmii_rxd(xgmii_rxd),
.xgmii_rxc(xgmii_rxc), .xgmii_rxc(xgmii_rxc),
.xgmii_rx_valid(xgmii_rx_valid),
/* /*
* AXI4-Stream output (source) * AXI4-Stream output (source)

View File

@@ -35,6 +35,8 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES)))
# module parameters # module parameters
export PARAM_DATA_W := 32 export PARAM_DATA_W := 32
export PARAM_GBX_IF_EN := 0
export PARAM_GBX_CNT := 1
export PARAM_PADDING_EN := 1 export PARAM_PADDING_EN := 1
export PARAM_DIC_EN := 1 export PARAM_DIC_EN := 1
export PARAM_MIN_FRAME_LEN := 64 export PARAM_MIN_FRAME_LEN := 64

View File

@@ -520,6 +520,8 @@ def test_taxi_axis_xgmii_tx_32(request, dic_en):
parameters = {} parameters = {}
parameters['DATA_W'] = 32 parameters['DATA_W'] = 32
parameters['GBX_IF_EN'] = 0
parameters['GBX_CNT'] = 1
parameters['PADDING_EN'] = 1 parameters['PADDING_EN'] = 1
parameters['DIC_EN'] = dic_en parameters['DIC_EN'] = dic_en
parameters['MIN_FRAME_LEN'] = 64 parameters['MIN_FRAME_LEN'] = 64

View File

@@ -19,6 +19,8 @@ module test_taxi_axis_xgmii_tx_32 #
( (
/* verilator lint_off WIDTHTRUNC */ /* verilator lint_off WIDTHTRUNC */
parameter DATA_W = 32, parameter DATA_W = 32,
parameter logic GBX_IF_EN = 1'b0,
parameter GBX_CNT = 1,
parameter logic PADDING_EN = 1'b1, parameter logic PADDING_EN = 1'b1,
parameter logic DIC_EN = 1'b1, parameter logic DIC_EN = 1'b1,
parameter MIN_FRAME_LEN = 64, parameter MIN_FRAME_LEN = 64,
@@ -41,6 +43,10 @@ taxi_axis_if #(.DATA_W(PTP_TS_W), .KEEP_W(1), .ID_EN(1), .ID_W(TX_TAG_W)) m_axis
logic [DATA_W-1:0] xgmii_txd; logic [DATA_W-1:0] xgmii_txd;
logic [CTRL_W-1:0] xgmii_txc; logic [CTRL_W-1:0] xgmii_txc;
logic xgmii_tx_valid;
logic [GBX_CNT-1:0] tx_gbx_req_sync;
logic tx_gbx_req_stall;
logic [GBX_CNT-1:0] tx_gbx_sync;
logic [PTP_TS_W-1:0] ptp_ts; logic [PTP_TS_W-1:0] ptp_ts;
@@ -64,6 +70,8 @@ logic stat_tx_err_underflow;
taxi_axis_xgmii_tx_32 #( taxi_axis_xgmii_tx_32 #(
.DATA_W(DATA_W), .DATA_W(DATA_W),
.CTRL_W(CTRL_W), .CTRL_W(CTRL_W),
.GBX_IF_EN(GBX_IF_EN),
.GBX_CNT(GBX_CNT),
.PADDING_EN(PADDING_EN), .PADDING_EN(PADDING_EN),
.DIC_EN(DIC_EN), .DIC_EN(DIC_EN),
.MIN_FRAME_LEN(MIN_FRAME_LEN), .MIN_FRAME_LEN(MIN_FRAME_LEN),
@@ -86,6 +94,10 @@ uut (
*/ */
.xgmii_txd(xgmii_txd), .xgmii_txd(xgmii_txd),
.xgmii_txc(xgmii_txc), .xgmii_txc(xgmii_txc),
.xgmii_tx_valid(xgmii_tx_valid),
.tx_gbx_req_sync(tx_gbx_req_sync),
.tx_gbx_req_stall(tx_gbx_req_stall),
.tx_gbx_sync(tx_gbx_sync),
/* /*
* PTP * PTP