diff options
author | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 |
---|---|---|
committer | Ben Hilburn <ben.hilburn@ettus.com> | 2014-02-14 12:05:07 -0800 |
commit | ff1546f8137f7f92bb250f685561b0c34cc0e053 (patch) | |
tree | 7fa6fd05c8828df256a1b20e2935bd3ba9899e2c /fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v | |
parent | 4f691d88123784c2b405816925f1a1aef69d18c1 (diff) | |
download | uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.gz uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.tar.bz2 uhd-ff1546f8137f7f92bb250f685561b0c34cc0e053.zip |
Pushing the bulk of UHD-3.7.0 code.
Diffstat (limited to 'fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v')
-rw-r--r-- | fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v | 763 |
1 files changed, 763 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v b/fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v new file mode 100644 index 000000000..98a5ac660 --- /dev/null +++ b/fpga/usrp3/lib/xge/rtl/verilog/rx_enqueue.v @@ -0,0 +1,763 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// File name "rx_enqueue.v" //// +//// //// +//// This file is part of the "10GE MAC" project //// +//// http://www.opencores.org/cores/xge_mac/ //// +//// //// +//// Author(s): //// +//// - A. Tanguay (antanguay@opencores.org) //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2008 AUTHORS. All rights reserved. //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + + +`include "defines.v" + +module rx_enqueue(/*AUTOARG*/ + // Outputs + rxdfifo_wdata, rxdfifo_wstatus, rxdfifo_wen, rxhfifo_ren, + rxhfifo_wdata, rxhfifo_wstatus, rxhfifo_wen, local_fault_msg_det, + remote_fault_msg_det, status_crc_error_tog, + status_fragment_error_tog, status_rxdfifo_ovflow_tog, + status_pause_frame_rx_tog, + // Inputs + clk_xgmii_rx, reset_xgmii_rx_n, xgmii_rxd, xgmii_rxc, rxdfifo_wfull, + rxhfifo_rdata, rxhfifo_rstatus, rxhfifo_rempty, + rxhfifo_ralmost_empty + ); + +`include "CRC32_D64.v" +`include "CRC32_D8.v" +`include "utils.v" + +input clk_xgmii_rx; +input reset_xgmii_rx_n; + +input [63:0] xgmii_rxd; +input [7:0] xgmii_rxc; + +input rxdfifo_wfull; + +input [63:0] rxhfifo_rdata; +input [7:0] rxhfifo_rstatus; +input rxhfifo_rempty; +input rxhfifo_ralmost_empty; + +output [63:0] rxdfifo_wdata; +output [7:0] rxdfifo_wstatus; +output rxdfifo_wen; + +output rxhfifo_ren; + +output [63:0] rxhfifo_wdata; +output [7:0] rxhfifo_wstatus; +output rxhfifo_wen; + +output [1:0] local_fault_msg_det; +output [1:0] remote_fault_msg_det; + +output status_crc_error_tog; +output status_fragment_error_tog; +output status_rxdfifo_ovflow_tog; + +output status_pause_frame_rx_tog; + + + + +/*AUTOREG*/ +// Beginning of automatic regs (for this module's undeclared outputs) +reg [1:0] local_fault_msg_det; +reg [1:0] remote_fault_msg_det; +reg [63:0] rxdfifo_wdata; +reg rxdfifo_wen; +reg [7:0] rxdfifo_wstatus; +reg rxhfifo_ren; +reg [63:0] rxhfifo_wdata; +reg rxhfifo_wen; +reg [7:0] rxhfifo_wstatus; +reg status_crc_error_tog; +reg status_fragment_error_tog; +reg status_pause_frame_rx_tog; +reg status_rxdfifo_ovflow_tog; +// End of automatics + +/*AUTOWIRE*/ + + +reg [63:32] xgmii_rxd_d1; +reg [7:4] xgmii_rxc_d1; + +reg [63:0] xgxs_rxd_barrel; +reg [7:0] xgxs_rxc_barrel; + +reg [63:0] xgxs_rxd_barrel_d1; +reg [7:0] xgxs_rxc_barrel_d1; + +reg barrel_shift; + +reg [31:0] crc32_d64; +reg [31:0] crc32_d8; + +reg [3:0] crc_bytes; +reg [3:0] next_crc_bytes; + +reg [63:0] crc_shift_data; +reg crc_start_8b; +reg crc_done; +reg crc_good; +reg crc_clear; + +reg [31:0] crc_rx; +reg [31:0] next_crc_rx; + +reg [2:0] curr_state; +reg [2:0] next_state; + +reg [13:0] curr_byte_cnt; +reg [13:0] next_byte_cnt; + +reg fragment_error; +reg rxd_ovflow_error; + +reg coding_error; +reg next_coding_error; + +reg [7:0] addmask; +reg [7:0] datamask; + +reg pause_frame; +reg next_pause_frame; +reg pause_frame_hold; + +reg good_pause_frame; + +reg drop_data; +reg next_drop_data; + +reg pkt_pending; + +reg rxhfifo_ren_d1; + +reg rxhfifo_ralmost_empty_d1; + + +parameter [2:0] + SM_IDLE = 3'd0, + SM_RX = 3'd1; + +always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin + + if (reset_xgmii_rx_n == 1'b0) begin + + xgmii_rxd_d1 <= 32'b0; + xgmii_rxc_d1 <= 4'b0; + + xgxs_rxd_barrel <= 64'b0; + xgxs_rxc_barrel <= 8'b0; + + xgxs_rxd_barrel_d1 <= 64'b0; + xgxs_rxc_barrel_d1 <= 8'b0; + + barrel_shift <= 1'b0; + + local_fault_msg_det <= 2'b0; + remote_fault_msg_det <= 2'b0; + + crc32_d64 <= 32'b0; + crc32_d8 <= 32'b0; + crc_bytes <= 4'b0; + + crc_shift_data <= 64'b0; + crc_done <= 1'b0; + crc_rx <= 32'b0; + + pause_frame_hold <= 1'b0; + + status_crc_error_tog <= 1'b0; + status_fragment_error_tog <= 1'b0; + status_rxdfifo_ovflow_tog <= 1'b0; + + status_pause_frame_rx_tog <= 1'b0; + + end + else begin + + //--- + // Link status RC layer + // Look for local/remote messages on lower 4 lanes and upper + // 4 lanes. This is a 64-bit interface but look at each 32-bit + // independantly. + + local_fault_msg_det[1] <= (xgmii_rxd[63:32] == + {`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} && + xgmii_rxc[7:4] == 4'b0001); + + local_fault_msg_det[0] <= (xgmii_rxd[31:0] == + {`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} && + xgmii_rxc[3:0] == 4'b0001); + + remote_fault_msg_det[1] <= (xgmii_rxd[63:32] == + {`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} && + xgmii_rxc[7:4] == 4'b0001); + + remote_fault_msg_det[0] <= (xgmii_rxd[31:0] == + {`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} && + xgmii_rxc[3:0] == 4'b0001); + + + //--- + // Rotating barrel. This function allow us to always align the start of + // a frame with LANE0. If frame starts in LANE4, it will be shifted 4 bytes + // to LANE0, thus reducing the amount of logic needed at the next stage. + + xgmii_rxd_d1[63:32] <= xgmii_rxd[63:32]; + xgmii_rxc_d1[7:4] <= xgmii_rxc[7:4]; + + if (xgmii_rxd[`LANE0] == `START && xgmii_rxc[0]) begin + + xgxs_rxd_barrel <= xgmii_rxd; + xgxs_rxc_barrel <= xgmii_rxc; + + barrel_shift <= 1'b0; + + end + else if (xgmii_rxd[`LANE4] == `START && xgmii_rxc[4]) begin + + xgxs_rxd_barrel <= {xgmii_rxd[31:0], xgmii_rxd_d1[63:32]}; + xgxs_rxc_barrel <= {xgmii_rxc[3:0], xgmii_rxc_d1[7:4]}; + + barrel_shift <= 1'b1; + + end + else if (barrel_shift) begin + + xgxs_rxd_barrel <= {xgmii_rxd[31:0], xgmii_rxd_d1[63:32]}; + xgxs_rxc_barrel <= {xgmii_rxc[3:0], xgmii_rxc_d1[7:4]}; + + end + else begin + + xgxs_rxd_barrel <= xgmii_rxd; + xgxs_rxc_barrel <= xgmii_rxc; + + end + + xgxs_rxd_barrel_d1 <= xgxs_rxd_barrel; + xgxs_rxc_barrel_d1 <= xgxs_rxc_barrel; + + + //--- + // When final CRC calculation begins we capture info relevant to + // current frame CRC claculation continues while next frame is + // being received. + + if (crc_start_8b) begin + + pause_frame_hold <= pause_frame; + + end + + //--- + // CRC Checking + + crc_rx <= next_crc_rx; + + if (crc_clear) begin + + // CRC is cleared at the beginning of the frame, calculate + // 64-bit at a time otherwise + + crc32_d64 <= 32'hffffffff; + + end + else begin + + crc32_d64 <= nextCRC32_D64(reverse_64b(xgxs_rxd_barrel_d1), crc32_d64); + + end + + if (crc_bytes != 4'b0) begin + + // When reaching the end of the frame we switch from 64-bit mode + // to 8-bit mode to accomodate odd number of bytes in the frame. + // crc_bytes indicated the number of remaining payload byte to + // compute CRC on. Calculate and decrement until it reaches 0. + + if (crc_bytes == 4'b1) begin + crc_done <= 1'b1; + end + + crc32_d8 <= nextCRC32_D8(reverse_8b(crc_shift_data[7:0]), crc32_d8); + crc_shift_data <= {8'h00, crc_shift_data[63:8]}; + crc_bytes <= crc_bytes - 4'b1; + + end + else if (crc_bytes == 4'b0) begin + + // Per Clause 46. Control code during data must be reported + // as a CRC error. Indicated here by coding_error. Corrupt CRC + // if coding error is detected. + + if (coding_error || next_coding_error) begin + crc32_d8 <= ~crc32_d64; + end + else begin + crc32_d8 <= crc32_d64; + end + + crc_done <= 1'b0; + + crc_shift_data <= xgxs_rxd_barrel_d1; + crc_bytes <= next_crc_bytes; + + end + + //--- + // Error detection + + if (crc_done && !crc_good) begin + status_crc_error_tog <= ~status_crc_error_tog; + end + + if (fragment_error) begin + status_fragment_error_tog <= ~status_fragment_error_tog; + end + + if (rxd_ovflow_error) begin + status_rxdfifo_ovflow_tog <= ~status_rxdfifo_ovflow_tog; + end + + //--- + // Frame receive indication + + if (good_pause_frame) begin + status_pause_frame_rx_tog <= ~status_pause_frame_rx_tog; + end + + end + +end + + +always @(/*AS*/crc32_d8 or crc_done or crc_rx or pause_frame_hold) begin + + + crc_good = 1'b0; + good_pause_frame = 1'b0; + + if (crc_done) begin + + // Check CRC. If this is a pause frame, report it to cpu. + + if (crc_rx == ~reverse_32b(crc32_d8)) begin + crc_good = 1'b1; + good_pause_frame = pause_frame_hold; + end + + end + +end + +always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin + + if (reset_xgmii_rx_n == 1'b0) begin + + curr_state <= SM_IDLE; + curr_byte_cnt <= 14'b0; + coding_error <= 1'b0; + pause_frame <= 1'b0; + + end + else begin + + curr_state <= next_state; + curr_byte_cnt <= next_byte_cnt; + coding_error <= next_coding_error; + pause_frame <= next_pause_frame; + + end + +end + + +always @(/*AS*/coding_error or crc_rx or curr_byte_cnt or curr_state + or pause_frame or xgxs_rxc_barrel or xgxs_rxc_barrel_d1 + or xgxs_rxd_barrel or xgxs_rxd_barrel_d1) begin + + next_state = curr_state; + + rxhfifo_wdata = xgxs_rxd_barrel_d1; + rxhfifo_wstatus = `RXSTATUS_NONE; + rxhfifo_wen = 1'b0; + + addmask[0] = !(xgxs_rxd_barrel_d1[`LANE0] == `TERMINATE && xgxs_rxc_barrel_d1[0]); + addmask[1] = !(xgxs_rxd_barrel_d1[`LANE1] == `TERMINATE && xgxs_rxc_barrel_d1[1]); + addmask[2] = !(xgxs_rxd_barrel_d1[`LANE2] == `TERMINATE && xgxs_rxc_barrel_d1[2]); + addmask[3] = !(xgxs_rxd_barrel_d1[`LANE3] == `TERMINATE && xgxs_rxc_barrel_d1[3]); + addmask[4] = !(xgxs_rxd_barrel_d1[`LANE4] == `TERMINATE && xgxs_rxc_barrel_d1[4]); + addmask[5] = !(xgxs_rxd_barrel_d1[`LANE5] == `TERMINATE && xgxs_rxc_barrel_d1[5]); + addmask[6] = !(xgxs_rxd_barrel_d1[`LANE6] == `TERMINATE && xgxs_rxc_barrel_d1[6]); + addmask[7] = !(xgxs_rxd_barrel_d1[`LANE7] == `TERMINATE && xgxs_rxc_barrel_d1[7]); + + datamask[0] = addmask[0]; + datamask[1] = &addmask[1:0]; + datamask[2] = &addmask[2:0]; + datamask[3] = &addmask[3:0]; + datamask[4] = &addmask[4:0]; + datamask[5] = &addmask[5:0]; + datamask[6] = &addmask[6:0]; + datamask[7] = &addmask[7:0]; + + next_crc_bytes = 4'b0; + next_crc_rx = crc_rx; + crc_start_8b = 1'b0; + crc_clear = 1'b0; + + next_byte_cnt = curr_byte_cnt; + + fragment_error = 1'b0; + + next_coding_error = coding_error; + next_pause_frame = pause_frame; + + case (curr_state) + + SM_IDLE: + begin + + next_byte_cnt = 14'b0; + crc_clear = 1'b1; + next_coding_error = 1'b0; + next_pause_frame = 1'b0; + + + // Detect the start of a frame + + if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] && + xgxs_rxd_barrel_d1[`LANE1] == `PREAMBLE && !xgxs_rxc_barrel_d1[1] && + xgxs_rxd_barrel_d1[`LANE2] == `PREAMBLE && !xgxs_rxc_barrel_d1[2] && + xgxs_rxd_barrel_d1[`LANE3] == `PREAMBLE && !xgxs_rxc_barrel_d1[3] && + xgxs_rxd_barrel_d1[`LANE4] == `PREAMBLE && !xgxs_rxc_barrel_d1[4] && + xgxs_rxd_barrel_d1[`LANE5] == `PREAMBLE && !xgxs_rxc_barrel_d1[5] && + xgxs_rxd_barrel_d1[`LANE6] == `PREAMBLE && !xgxs_rxc_barrel_d1[6] && + xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin + + next_state = SM_RX; + end + + end + + SM_RX: + begin + + // Pause frames are filtered + + rxhfifo_wen = !pause_frame; + + + if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] && + xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin + + // Fragment received, if we are still at SOP stage don't store + // the frame. If not, write a fake EOP and flag frame as bad. + + next_byte_cnt = 14'b0; + crc_clear = 1'b1; + next_coding_error = 1'b0; + + fragment_error = 1'b1; + rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1; + + if (curr_byte_cnt == 14'b0) begin + rxhfifo_wen = 1'b0; + end + else begin + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + end + + end + else if (curr_byte_cnt > 14'd9900) begin + + // Frame too long, TERMMINATE must have been corrupted. + // Abort transfer, write a fake EOP, report as fragment. + + fragment_error = 1'b1; + rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1; + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + next_state = SM_IDLE; + + end + else begin + + // Pause frame receive, these frame will be filtered + + if (curr_byte_cnt == 14'd0 && + xgxs_rxd_barrel_d1[47:0] == `PAUSE_FRAME) begin + + rxhfifo_wen = 1'b0; + next_pause_frame = 1'b1; + end + + + // Control character during data phase, force CRC error + + if (|(xgxs_rxc_barrel_d1 & datamask)) begin + + next_coding_error = 1'b1; + end + + + // Write SOP to status bits during first byte + + if (curr_byte_cnt == 14'b0) begin + rxhfifo_wstatus[`RXSTATUS_SOP] = 1'b1; + end + + /* verilator lint_off WIDTH */ + next_byte_cnt = curr_byte_cnt + + addmask[0] + addmask[1] + addmask[2] + addmask[3] + + addmask[4] + addmask[5] + addmask[6] + addmask[7]; + /* verilator lint_on WIDTH */ + + + + // We will not write to the fifo if all is left + // are four or less bytes of crc. We also strip off the + // crc, which requires looking one cycle ahead + // wstatus: + // [2:0] modulus of packet length + + // Look one cycle ahead for TERMINATE in lanes 0 to 4 + + if (xgxs_rxd_barrel[`LANE4] == `TERMINATE && xgxs_rxc_barrel[4]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd0; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd8; + next_crc_rx = xgxs_rxd_barrel[31:0]; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel[`LANE3] == `TERMINATE && xgxs_rxc_barrel[3]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd7; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd7; + next_crc_rx = {xgxs_rxd_barrel[23:0], xgxs_rxd_barrel_d1[63:56]}; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel[`LANE2] == `TERMINATE && xgxs_rxc_barrel[2]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd6; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd6; + next_crc_rx = {xgxs_rxd_barrel[15:0], xgxs_rxd_barrel_d1[63:48]}; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel[`LANE1] == `TERMINATE && xgxs_rxc_barrel[1]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd5; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd5; + next_crc_rx = {xgxs_rxd_barrel[7:0], xgxs_rxd_barrel_d1[63:40]}; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel[`LANE0] == `TERMINATE && xgxs_rxc_barrel[0]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd4; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd4; + next_crc_rx = xgxs_rxd_barrel_d1[63:32]; + + next_state = SM_IDLE; + + end + + // Look at current cycle for TERMINATE in lanes 5 to 7 + + if (xgxs_rxd_barrel_d1[`LANE7] == `TERMINATE && + xgxs_rxc_barrel_d1[7]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd3; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd3; + next_crc_rx = xgxs_rxd_barrel_d1[55:24]; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel_d1[`LANE6] == `TERMINATE && + xgxs_rxc_barrel_d1[6]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd2; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd2; + next_crc_rx = xgxs_rxd_barrel_d1[47:16]; + + next_state = SM_IDLE; + + end + + if (xgxs_rxd_barrel_d1[`LANE5] == `TERMINATE && + xgxs_rxc_barrel_d1[5]) begin + + rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1; + rxhfifo_wstatus[2:0] = 3'd1; + + crc_start_8b = 1'b1; + next_crc_bytes = 4'd1; + next_crc_rx = xgxs_rxd_barrel_d1[39:8]; + + next_state = SM_IDLE; + + end + end + end + + default: + begin + next_state = SM_IDLE; + end + + endcase + +end + + +always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin + + if (reset_xgmii_rx_n == 1'b0) begin + + rxhfifo_ralmost_empty_d1 <= 1'b1; + + drop_data <= 1'b0; + + pkt_pending <= 1'b0; + + rxhfifo_ren_d1 <= 1'b0; + + end + else begin + + rxhfifo_ralmost_empty_d1 <= rxhfifo_ralmost_empty; + + drop_data <= next_drop_data; + + pkt_pending <= rxhfifo_ren; + + rxhfifo_ren_d1 <= rxhfifo_ren; + + end + +end + +always @(/*AS*/crc_done or crc_good or drop_data or pkt_pending + or rxdfifo_wfull or rxhfifo_ralmost_empty_d1 or rxhfifo_rdata + or rxhfifo_ren_d1 or rxhfifo_rstatus) begin + + rxd_ovflow_error = 1'b0; + + rxdfifo_wdata = rxhfifo_rdata; + rxdfifo_wstatus = rxhfifo_rstatus; + + next_drop_data = drop_data; + + + // There must be at least 8 words in holding FIFO before we start reading. + // This provides enough time for CRC calculation. + + rxhfifo_ren = !rxhfifo_ralmost_empty_d1 || + (pkt_pending && !rxhfifo_rstatus[`RXSTATUS_EOP]); + + + if (rxhfifo_ren_d1 && rxhfifo_rstatus[`RXSTATUS_SOP]) begin + + // Reset drop flag on SOP + + next_drop_data = 1'b0; + + end + + if (rxhfifo_ren_d1 && rxdfifo_wfull && !next_drop_data) begin + + // FIFO overflow, abort transfer. The rest of the frame + // will be dropped. Since we can't put an EOP indication + // in a fifo already full, there will be no EOP and receive + // side will need to sync on next SOP. + + rxd_ovflow_error = 1'b1; + next_drop_data = 1'b1; + + end + + + rxdfifo_wen = rxhfifo_ren_d1 && !next_drop_data; + + + + if (crc_done && !crc_good) begin + + // Flag packet with error when CRC error is detected + + rxdfifo_wstatus[`RXSTATUS_ERR] = 1'b1; + + end + +end + +endmodule + +
\ No newline at end of file |