diff --git a/src/eth/rtl/taxi_axis_xgmii_rx_32.sv b/src/eth/rtl/taxi_axis_xgmii_rx_32.sv index f8fc145..d545faa 100644 --- a/src/eth/rtl/taxi_axis_xgmii_rx_32.sv +++ b/src/eth/rtl/taxi_axis_xgmii_rx_32.sv @@ -19,6 +19,7 @@ module taxi_axis_xgmii_rx_32 # ( parameter DATA_W = 32, parameter CTRL_W = (DATA_W/8), + parameter logic GBX_IF_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0, 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 [CTRL_W-1:0] xgmii_rxc, + input wire logic xgmii_rx_valid, /* * Receive interface (AXI stream) @@ -257,207 +259,212 @@ always_comb begin stat_rx_err_framing_next = 1'b0; stat_rx_err_preamble_next = 1'b0; - // 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); + if (GBX_IF_EN && !xgmii_rx_valid) begin + // XGMII data not valid - hold state + state_next = state_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 - frame_len_next = frame_len_reg + 16'(CTRL_W); + frame_len_next = '1; end - 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 = xgmii_rxd_d2[0]; - is_bcast_next = &xgmii_rxd_d2; + // 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 - 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 + + // address and ethertype checks + if (&hdr_ptr_reg == 0) begin + hdr_ptr_next = hdr_ptr_reg + 1; end - endcase - case (state_reg) - STATE_IDLE: begin - // idle state - wait for packet - reset_crc = 1'b1; + case (hdr_ptr_reg) + 3'd0: begin + is_mcast_next = xgmii_rxd_d2[0]; + 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); - frame_len_lim_next = cfg_rx_max_pkt_len; - hdr_ptr_next = 0; + case (state_reg) + STATE_IDLE: begin + // 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 - // control or error characters in first data word + // control or error characters in packet stat_rx_err_framing_next = 1'b1; state_next = STATE_IDLE; end else begin - reset_crc = 1'b0; + start_packet_next = 1'b1; stat_rx_byte_next = 3'(CTRL_W); - state_next = STATE_PREAMBLE; + state_next = STATE_PAYLOAD; end - end else begin - if (PTP_TS_EN) begin - ptp_ts_out_next = ptp_ts; + 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 - 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 (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; + if (framing_error_reg) begin + // control or error characters in packet 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 + 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; + 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 - // need extra cycle - state_next = STATE_LAST; + state_next = STATE_PAYLOAD; end - end else begin - state_next = STATE_PAYLOAD; end - end - STATE_LAST: begin - // last cycle of packet - 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_tvalid_next = 1'b1; - m_axis_rx_tlast_next = 1'b1; - m_axis_rx_tuser_next = 1'b0; + STATE_LAST: begin + // last cycle of packet + 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_tvalid_next = 1'b1; + m_axis_rx_tlast_next = 1'b1; + 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]) || - (term_lane_d0_reg == 2 && crc_valid_save[1]) || - (term_lane_d0_reg == 3 && crc_valid_save[2])) begin - // CRC valid - if (frame_oversize_reg) begin - // too long + if ((term_lane_d0_reg == 1 && crc_valid_save[0]) || + (term_lane_d0_reg == 2 && crc_valid_save[1]) || + (term_lane_d0_reg == 3 && crc_valid_save[2])) begin + // CRC valid + if (frame_oversize_reg) 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_reg[15:6] == 0; + stat_rx_pkt_jabber_next = frame_oversize_reg; 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; + stat_rx_err_bad_fcs_next = 1'b1; end - end else begin - 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_err_bad_fcs_next = 1'b1; + + stat_rx_pkt_len_next = frame_len_reg; + 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_reg; + stat_rx_err_preamble_next = !pre_ok_reg; + + state_next = STATE_IDLE; end - - stat_rx_pkt_len_next = frame_len_reg; - 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_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 + default: begin + // invalid state, return to idle + state_next = STATE_IDLE; + end + endcase + end end 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_preamble_reg <= stat_rx_err_preamble_next; - term_lane_reg <= 0; - term_present_reg <= 1'b0; - framing_error_reg <= xgmii_rxc != 0; + if (!GBX_IF_EN || xgmii_rx_valid) begin + term_lane_reg <= 0; + term_present_reg <= 1'b0; + framing_error_reg <= xgmii_rxc != 0; - for (integer i = CTRL_W-1; i >= 0; i = i - 1) begin - if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin - term_lane_reg <= 2'(i); - term_present_reg <= 1'b1; - framing_error_reg <= (xgmii_rxc & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0; + for (integer i = CTRL_W-1; i >= 0; i = i - 1) begin + if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin + term_lane_reg <= 2'(i); + term_present_reg <= 1'b1; + framing_error_reg <= (xgmii_rxc & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0; + 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 - 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 state_reg <= STATE_IDLE; diff --git a/src/eth/rtl/taxi_axis_xgmii_tx_32.sv b/src/eth/rtl/taxi_axis_xgmii_tx_32.sv index 0e5eb29..cc347d8 100644 --- a/src/eth/rtl/taxi_axis_xgmii_tx_32.sv +++ b/src/eth/rtl/taxi_axis_xgmii_tx_32.sv @@ -19,6 +19,8 @@ module taxi_axis_xgmii_tx_32 # ( parameter DATA_W = 32, 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 DIC_EN = 1'b1, 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 [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 @@ -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 [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; @@ -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_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_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.tkeep = 1'b1; @@ -340,192 +350,216 @@ always_comb begin frame_next = !s_axis_tx.tlast; end - // counter for min frame length enforcement - if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin - frame_min_count_next = MIN_LEN_W'(frame_min_count_reg - CTRL_W); + if (GBX_IF_EN && tx_gbx_req_stall) begin + // gearbox stall - hold state + state_next = state_reg; + // frame_start_next = frame_start_reg; + s_axis_tx_tready_next = s_axis_tx_tready_reg; end else begin - frame_min_count_next = 0; - end - - // counter to measure frame length - if (&frame_len_reg[15:2] == 0) begin - 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; + // counter for min frame length enforcement + if (frame_min_count_reg > MIN_LEN_W'(CTRL_W)) begin + frame_min_count_next = MIN_LEN_W'(frame_min_count_reg - CTRL_W); + end else begin + frame_min_count_next = 0; 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 + + // counter to measure frame length + if (&frame_len_reg[15:2] == 0) begin + frame_len_next = frame_len_reg + 16'(CTRL_W); + end else begin + frame_len_next = '1; end - endcase - if (ifg_cnt_reg[7:2] != 0) begin - ifg_cnt_next = ifg_cnt_reg - 8'(CTRL_W); - end else begin - ifg_cnt_next = '0; - 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 - 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; + // address and ethertype checks + if (&hdr_ptr_reg == 0) begin + hdr_ptr_next = hdr_ptr_reg + 1; + end - // XGMII idle - xgmii_txd_next = {CTRL_W{XGMII_IDLE}}; - xgmii_txc_next = {CTRL_W{1'b1}}; + case (hdr_ptr_reg) + 3'd0: begin + 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; - s_empty_next = keep2empty(s_axis_tx.tkeep); + if (ifg_cnt_reg[7:2] != 0) begin + 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; - state_next = STATE_PREAMBLE; - end else begin - ifg_count_next = 8'd0; - deficit_idle_count_next = 2'd0; - state_next = STATE_IDLE; + start_packet_next = 1'b1; + state_next = STATE_PAYLOAD; end - end - STATE_PREAMBLE: begin - // send preamble - reset_crc = 1'b1; + STATE_PAYLOAD: begin + // transfer payload + update_crc = 1'b1; + s_axis_tx_tready_next = 1'b1; - hdr_ptr_next = 0; - frame_len_next = 0; - frame_len_lim_next = cfg_tx_max_pkt_len; + xgmii_txd_next = s_tdata_reg; + xgmii_txc_next = {CTRL_W{1'b0}}; - s_tdata_next = s_axis_tx_tdata_masked; - s_empty_next = keep2empty(s_axis_tx.tkeep); + 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}}; + stat_tx_byte_next = 3'(CTRL_W); - s_axis_tx_tready_next = 1'b1; - start_packet_next = 1'b1; - state_next = STATE_PAYLOAD; - end - STATE_PAYLOAD: begin - // transfer payload - update_crc = 1'b1; - s_axis_tx_tready_next = 1'b1; + if (s_axis_tx.tvalid && s_axis_tx.tlast) begin + frame_oversize_next = frame_len_lim_reg < 16'(4+4+4-keep2empty(s_axis_tx.tkeep)); + end else begin + frame_oversize_next = frame_len_lim_reg < 4+4; + end - xgmii_txd_next = s_tdata_reg; - xgmii_txc_next = {CTRL_W{1'b0}}; + 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; - s_tdata_next = s_axis_tx_tdata_masked; - s_empty_next = keep2empty(s_axis_tx.tkeep); - - stat_tx_byte_next = 3'(CTRL_W); - - if (s_axis_tx.tvalid && s_axis_tx.tlast) begin - frame_oversize_next = frame_len_lim_reg < 16'(4+4+4-keep2empty(s_axis_tx.tkeep)); - end else begin - frame_oversize_next = frame_len_lim_reg < 4+4; - 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); + 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 + state_next = STATE_FCS_1; end + end else begin state_next = STATE_FCS_1; end 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; end - 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 + STATE_FCS_1: begin + // last cycle + s_axis_tx_tready_next = frame_next; // drop frame - xgmii_txd_next = s_tdata_reg; - xgmii_txc_next = {CTRL_W{1'b0}}; + xgmii_txd_next = fcs_output_txd_0; + xgmii_txc_next = fcs_output_txc_0; - s_tdata_next = 32'd0; - s_empty_next = 0; + stat_tx_byte_next = 3'(CTRL_W); - stat_tx_byte_next = 3'(CTRL_W); + update_crc = 1'b1; - 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; + 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 + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_2; + end end - end - STATE_FCS_1: begin - // last cycle - s_axis_tx_tready_next = frame_next; // drop frame + STATE_FCS_2: begin + // last cycle + s_axis_tx_tready_next = frame_next; // drop frame - xgmii_txd_next = fcs_output_txd_0; - xgmii_txc_next = fcs_output_txc_0; + xgmii_txd_next = fcs_output_txd_1; + 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; - - 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 - state_next = STATE_ERR; - end else begin - state_next = STATE_FCS_2; + 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_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 end - end - STATE_FCS_2: begin - // last cycle - s_axis_tx_tready_next = frame_next; // drop frame + STATE_FCS_3: begin + // last cycle + s_axis_tx_tready_next = frame_next; // drop frame - xgmii_txd_next = fcs_output_txd_1; - xgmii_txc_next = fcs_output_txc_1; + xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM}; + xgmii_txc_next = {CTRL_W{1'b1}}; - stat_tx_byte_next = 4-s_empty_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_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; @@ -533,98 +567,81 @@ always_comb begin 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 + 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; end - end - STATE_FCS_3: begin - // last cycle - s_axis_tx_tready_next = frame_next; // drop frame + STATE_IFG: begin + // send IFG + s_axis_tx_tready_next = frame_next; // drop frame - xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM}; - xgmii_txc_next = {CTRL_W{1'b1}}; + // XGMII idle + xgmii_txd_next = {CTRL_W{XGMII_IDLE}}; + xgmii_txc_next = {CTRL_W{1'b1}}; - 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; - - if (DIC_EN) begin - if (ifg_count_next > 8'd3) begin - state_next = STATE_IFG; + if (ifg_count_reg > 8'd4) begin + ifg_count_next = ifg_count_reg - 8'd4; 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; + + if (DIC_EN) begin + 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 - 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 - 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; - 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; + default: begin + // invalid state, return to idle + state_next = STATE_IDLE; end - - if (DIC_EN) begin - 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 + endcase + end end 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_valid_reg <= m_axis_tx_cpl_valid_next; - for (integer i = 0; i < 3; i = i + 1) begin - crc_state_reg[i] <= crc_state_next[i]; + if (GBX_IF_EN && tx_gbx_req_stall) begin + // 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 if (update_crc) begin @@ -668,6 +689,7 @@ always_ff @(posedge clk) begin xgmii_txd_reg <= xgmii_txd_next; xgmii_txc_reg <= xgmii_txc_next; + xgmii_tx_valid_reg <= !tx_gbx_req_stall; 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_underflow_reg <= stat_tx_err_underflow_next; + tx_gbx_sync_reg <= tx_gbx_req_sync; + if (rst) begin state_reg <= STATE_IDLE; @@ -697,6 +721,8 @@ always_ff @(posedge clk) begin xgmii_txd_reg <= {CTRL_W{XGMII_IDLE}}; xgmii_txc_reg <= {CTRL_W{1'b1}}; + xgmii_tx_valid_reg <= 1'b0; + tx_gbx_sync_reg <= '0; start_packet_reg <= 1'b0; diff --git a/src/eth/rtl/taxi_eth_mac_10g.sv b/src/eth/rtl/taxi_eth_mac_10g.sv index 28a9504..af7404a 100644 --- a/src/eth/rtl/taxi_eth_mac_10g.sv +++ b/src/eth/rtl/taxi_eth_mac_10g.sv @@ -341,6 +341,7 @@ end else if (DATA_W == 32) begin taxi_axis_xgmii_rx_32 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), + .GBX_IF_EN(RX_GBX_IF_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -353,6 +354,7 @@ end else if (DATA_W == 32) begin */ .xgmii_rxd(xgmii_rxd), .xgmii_rxc(xgmii_rxc), + .xgmii_rx_valid(xgmii_rx_valid), /* * Receive interface (AXI stream) @@ -397,6 +399,8 @@ end else if (DATA_W == 32) begin taxi_axis_xgmii_tx_32 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), + .GBX_IF_EN(TX_GBX_IF_EN), + .GBX_CNT(GBX_CNT), .PADDING_EN(PADDING_EN), .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), @@ -419,6 +423,10 @@ end else if (DATA_W == 32) begin */ .xgmii_txd(xgmii_txd), .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 diff --git a/src/eth/tb/taxi_axis_xgmii_rx_32/Makefile b/src/eth/tb/taxi_axis_xgmii_rx_32/Makefile index 0490b87..ae870c3 100644 --- a/src/eth/tb/taxi_axis_xgmii_rx_32/Makefile +++ b/src/eth/tb/taxi_axis_xgmii_rx_32/Makefile @@ -35,6 +35,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters export PARAM_DATA_W := 32 +export PARAM_GBX_IF_EN := 0 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_W := 96 diff --git a/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py b/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py index 256f060..d6268b3 100644 --- a/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py +++ b/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py @@ -39,6 +39,8 @@ class TB: 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_enable.setimmediatevalue(0) @@ -305,6 +307,7 @@ def test_taxi_axis_xgmii_rx_32(request): parameters = {} parameters['DATA_W'] = 32 + parameters['GBX_IF_EN'] = 0 parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_W'] = 96 diff --git a/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.sv b/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.sv index c58b0f5..d4c4cb5 100644 --- a/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.sv +++ b/src/eth/tb/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.sv @@ -19,6 +19,7 @@ module test_taxi_axis_xgmii_rx_32 # ( /* verilator lint_off WIDTHTRUNC */ parameter DATA_W = 32, + parameter logic GBX_IF_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96 /* verilator lint_on WIDTHTRUNC */ @@ -33,6 +34,7 @@ logic rst; logic [DATA_W-1:0] xgmii_rxd; 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(); @@ -61,6 +63,7 @@ logic stat_rx_err_preamble; taxi_axis_xgmii_rx_32 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), + .GBX_IF_EN(GBX_IF_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -73,6 +76,7 @@ uut ( */ .xgmii_rxd(xgmii_rxd), .xgmii_rxc(xgmii_rxc), + .xgmii_rx_valid(xgmii_rx_valid), /* * AXI4-Stream output (source) diff --git a/src/eth/tb/taxi_axis_xgmii_tx_32/Makefile b/src/eth/tb/taxi_axis_xgmii_tx_32/Makefile index cb48932..6c7a4f4 100644 --- a/src/eth/tb/taxi_axis_xgmii_tx_32/Makefile +++ b/src/eth/tb/taxi_axis_xgmii_tx_32/Makefile @@ -35,6 +35,8 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters export PARAM_DATA_W := 32 +export PARAM_GBX_IF_EN := 0 +export PARAM_GBX_CNT := 1 export PARAM_PADDING_EN := 1 export PARAM_DIC_EN := 1 export PARAM_MIN_FRAME_LEN := 64 diff --git a/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.py b/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.py index 67e0e25..4473e54 100644 --- a/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.py +++ b/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.py @@ -520,6 +520,8 @@ def test_taxi_axis_xgmii_tx_32(request, dic_en): parameters = {} parameters['DATA_W'] = 32 + parameters['GBX_IF_EN'] = 0 + parameters['GBX_CNT'] = 1 parameters['PADDING_EN'] = 1 parameters['DIC_EN'] = dic_en parameters['MIN_FRAME_LEN'] = 64 diff --git a/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.sv b/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.sv index d3852ae..ea1b565 100644 --- a/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.sv +++ b/src/eth/tb/taxi_axis_xgmii_tx_32/test_taxi_axis_xgmii_tx_32.sv @@ -19,6 +19,8 @@ module test_taxi_axis_xgmii_tx_32 # ( /* verilator lint_off WIDTHTRUNC */ parameter DATA_W = 32, + parameter logic GBX_IF_EN = 1'b0, + parameter GBX_CNT = 1, parameter logic PADDING_EN = 1'b1, parameter logic DIC_EN = 1'b1, 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 [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; @@ -64,6 +70,8 @@ logic stat_tx_err_underflow; taxi_axis_xgmii_tx_32 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), + .GBX_IF_EN(GBX_IF_EN), + .GBX_CNT(GBX_CNT), .PADDING_EN(PADDING_EN), .DIC_EN(DIC_EN), .MIN_FRAME_LEN(MIN_FRAME_LEN), @@ -86,6 +94,10 @@ uut ( */ .xgmii_txd(xgmii_txd), .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