OpenCores
URL https://opencores.org/ocsvn/openarty/openarty/trunk

Subversion Repositories openarty

[/] [openarty/] [trunk/] [rtl/] [enetpackets.v] - Diff between revs 33 and 49

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 33 Rev 49
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    enetpackets.v
// Filename:    enetpackets.v
//
//
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
// Project:     OpenArty, an entirely open SoC based upon the Arty platform
//
//
// Purpose:     To communicate between the Ethernet PHY, and thus to coordinate
// Purpose:     To communicate between the Ethernet PHY, and thus to coordinate
//              (and direct/arrange for) the transmission, and receiption, of 
//              (and direct/arrange for) the transmission, and receiption, of 
//      packets via the Ethernet interface.
//      packets via the Ethernet interface.
//
//
//
//
//      Using this interface requires four registers to be properly configured.
//      Using this interface requires four registers to be properly configured.
//      These are the receive and transmit control registers, as well as the
//      These are the receive and transmit control registers, as well as the
//      hardware MAC register(s).
//      hardware MAC register(s).
//
//
//
//
//      To use the interface, after the system has been alive for a full
//      To use the interface, after the system has been alive for a full
//      second, drop the reset line.  Do this by writing to the transmit
//      second, drop the reset line.  Do this by writing to the transmit
//      register a value with zero length, zero command, and the RESET bit as
//      register a value with zero length, zero command, and the RESET bit as
//      zero.
//      zero.
//
//
//      This interface is big endian.  Therefore, the most significant byte
//      This interface is big endian.  Therefore, the most significant byte
//      in each word will be transmitted first.  If the interface references
//      in each word will be transmitted first.  If the interface references
//      a number of octets less than a multiple of four, the least significant
//      a number of octets less than a multiple of four, the least significant
//      octets in the last word will not be transmitted/were not received.
//      octets in the last word will not be transmitted/were not received.
//
//
//      To transmit,
//      To transmit,
//              1. set the source MAC address in the two mac registers.  These
//              1. set the source MAC address in the two mac registers.  These
//                      are persistent across packets, so once set (whether for
//                      are persistent across packets, so once set (whether for
//                      transmit or receive) they need not be set again.
//                      transmit or receive) they need not be set again.
//              2. Fill the packet buffer with your packet.  In general, the
//              2. Fill the packet buffer with your packet.  In general, the
//                      first 32-bit word must contain the hardware MAC address
//                      first 32-bit word must contain the hardware MAC address
//                      of your destination, spilling into the 16-bits of the
//                      of your destination, spilling into the 16-bits of the
//                      next word.  The bottom 16-bits of that second word
//                      next word.  The bottom 16-bits of that second word
//                      must also contain the EtherType (0x0800 for IP,
//                      must also contain the EtherType (0x0800 for IP,
//                      0x0806 for ARP, etc.)  The third word will begin your
//                      0x0806 for ARP, etc.)  The third word will begin your
//                      user data.
//                      user data.
//              3. Write a 0x4000 plus the number of bytes in your buffer to
//              3. Write a 0x4000 plus the number of bytes in your buffer to
//                      the transmit command register.  If your packet is less
//                      the transmit command register.  If your packet is less
//                      than 64 bytes, it will automatically be paddedd to 64
//                      than 64 bytes, it will automatically be paddedd to 64
//                      bytes before being sent.
//                      bytes before being sent.
//              4. Once complete, the controller will raise an interrupt
//              4. Once complete, the controller will raise an interrupt
//                      line to note that the interface is idle.
//                      line to note that the interface is idle.
//      OPTIONS:
//      OPTIONS:
//              You can turn off the internal insertion of the hardware source
//              You can turn off the internal insertion of the hardware source
//              MAC by turning the respective bit on in the transmit command
//              MAC by turning the respective bit on in the transmit command
//              register.  If you do this, half of the second word and all the
//              register.  If you do this, half of the second word and all the
//              third word must contain the hardware MAC.  The third word must
//              third word must contain the hardware MAC.  The third word must
//              contain the EtherType, both in the top and bottom sixteen bits.
//              contain the EtherType, both in the top and bottom sixteen bits.
//              The Fourth word will begin user data.
//              The Fourth word will begin user data.
//
//
//              You can also turn off the automatic insertion of the FCS, or
//              You can also turn off the automatic insertion of the FCS, or
//              ethernet CRC.  Doing this means that you will need to both 
//              ethernet CRC.  Doing this means that you will need to both 
//              guarantee for yourself that the packet has a minimum of 64
//              guarantee for yourself that the packet has a minimum of 64
//              bytes in length, and that the last four bytes contain the
//              bytes in length, and that the last four bytes contain the
//              CRC.
//              CRC.
//
//
//      To Receive: 
//      To Receive: 
//              The receiver is always on.  Receiving is really just a matter
//              The receiver is always on.  Receiving is really just a matter
//              of pulling the received packet from the interface, and resetting
//              of pulling the received packet from the interface, and resetting
//              the interface for the next packet.
//              the interface for the next packet.
//
//
//              If the VALID bit is set, the receive interface has a valid
//              If the VALID bit is set, the receive interface has a valid
//              packet within it.  Write a zero to this bit to reset the
//              packet within it.  Write a zero to this bit to reset the
//              interface to accept the next packet.
//              interface to accept the next packet.
//
//
//              If a packet with a CRC error is received, the CRC error bit
//              If a packet with a CRC error is received, the CRC error bit
//              will be set.  Likewise if a packet has been missed, usually 
//              will be set.  Likewise if a packet has been missed, usually 
//              because the buffer was full when it started, the miss bit
//              because the buffer was full when it started, the miss bit
//              will be set.  Finally, if an error occurrs while receiving
//              will be set.  Finally, if an error occurrs while receiving
//              a packet, the error bit will be set.  These bits may be cleared
//              a packet, the error bit will be set.  These bits may be cleared
//              by writing a one to each of them--something that may be done
//              by writing a one to each of them--something that may be done
//              when clearing the interface for the next packet.
//              when clearing the interface for the next packet.
//      OPTIONS:
//      OPTIONS:
//              The same options that apply to the transmitter apply to the
//              The same options that apply to the transmitter apply to the
//              receiver:
//              receiver:
//
//
//              HWMAC.  If the hardware MAC is turned on, the receiver will
//              HWMAC.  If the hardware MAC is turned on, the receiver will
//              only accept packets to either 1) our network address, or 2)
//              only accept packets to either 1) our network address, or 2)
//              a broadcast address.  Further, the first two words will be
//              a broadcast address.  Further, the first two words will be
//              adjusted to contain the source MAC and the EtherType, so that
//              adjusted to contain the source MAC and the EtherType, so that
//              the user information begins on the third word.  If this feature
//              the user information begins on the third word.  If this feature
//              is turned off, all packets will be received, and the first
//              is turned off, all packets will be received, and the first
//              three words will contain the destination and then source
//              three words will contain the destination and then source
//              MAC.  The fourth word will contain the EtherType in the lowest,
//              MAC.  The fourth word will contain the EtherType in the lowest,
//              16 bits, meaning user data will begin on the fifth word.
//              16 bits, meaning user data will begin on the fifth word.
//
//
//              HWCRC.  If the HWCRC is turned on, the receiver will only
//              HWCRC.  If the HWCRC is turned on, the receiver will only
//              detect packets that pass their CRC check.  Further, the packet
//              detect packets that pass their CRC check.  Further, the packet
//              length (always in octets) will not include the CRC.  However,
//              length (always in octets) will not include the CRC.  However,
//              the CRC will still be left/written to packet memory either way.
//              the CRC will still be left/written to packet memory either way.
//
//
// Registers:
// Registers:
//      0        Receiver control
//      0        Receiver control
//              13'h0   |CRCerr|MISS|ERR|BUSY|VALID |14-bit length (in octets)|
//              13'h0   |CRCerr|MISS|ERR|BUSY|VALID |14-bit length (in octets)|
//
//
//      1       Transmitter control
//      1       Transmitter control
//              14'h0   |NET_RST|SW-MAC-CHK|SW-CRCn|BUSY/CMD | 14 bit length(in octets)|
//              14'h0   |NET_RST|SW-MAC-CHK|SW-CRCn|BUSY/CMD | 14 bit length(in octets)|
//
//
//      2       // MAC address (high) ??
//      2       // MAC address (high) ??
//      3       // MAC address (low)  ??
//      3       // MAC address (low)  ??
//      4       Number of receive packets missed (buffer was full)
//      4       Number of receive packets missed (buffer was full)
//      5       Number of receive packets ending in error
//      5       Number of receive packets ending in error
//      6       Number of receive packets with invalid CRCs
//      6       Number of receive packets with invalid CRCs
//      7       (Number of transmit collisions ??)
//      7       (Number of transmit collisions ??)
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2016, Gisselquist Technology, LLC
// Copyright (C) 2016, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
// `define      RX_SYNCHRONOUS_WITH_WB_CLK
// `define      RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`define RXCLK   i_wb_clk
`define RXCLK   i_wb_clk
`else
`else
`define RXCLK   i_net_rx_clk
`define RXCLK   i_net_rx_clk
`endif
`endif
// `define      TX_SYNCHRONOUS_WITH_WB_CLK
// `define      TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
`define TXCLK   i_wb_clk
`define TXCLK   i_wb_clk
`else
`else
`define TXCLK   i_net_tx_clk
`define TXCLK   i_net_tx_clk
`endif
`endif
module  enetpackets(i_wb_clk, i_reset,
module  enetpackets(i_wb_clk, i_reset,
        i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
        i_wb_cyc, i_wb_stb, i_wb_we, i_wb_addr, i_wb_data,
                o_wb_ack, o_wb_stall, o_wb_data,
                o_wb_ack, o_wb_stall, o_wb_data,
        //
        //
        o_net_reset_n,
        o_net_reset_n,
        i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd, i_net_rxerr,
        i_net_rx_clk, i_net_col, i_net_crs, i_net_dv, i_net_rxd, i_net_rxerr,
        i_net_tx_clk, o_net_tx_en, o_net_txd,
        i_net_tx_clk, o_net_tx_en, o_net_txd,
        //
        //
        o_rx_int, o_tx_int,
        o_rx_int, o_tx_int,
        //
        //
        o_debug
        o_debug
        );
        );
        parameter       MEMORY_ADDRESS_WIDTH = 12; // Log_2 octet width:11..14
        parameter       MEMORY_ADDRESS_WIDTH = 12; // Log_2 octet width:11..14
        localparam      MAW =((MEMORY_ADDRESS_WIDTH>14)? 14: // width of words
        localparam      MAW =((MEMORY_ADDRESS_WIDTH>14)? 14: // width of words
                        ((MEMORY_ADDRESS_WIDTH<11)? 11:MEMORY_ADDRESS_WIDTH))-2;
                        ((MEMORY_ADDRESS_WIDTH<11)? 11:MEMORY_ADDRESS_WIDTH))-2;
        input                   i_wb_clk, i_reset;
        input                   i_wb_clk, i_reset;
        //
        //
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
        input                   i_wb_cyc, i_wb_stb, i_wb_we;
        input   [(MAW+1):0]      i_wb_addr; // 1-bit for ctrl/data, 1 for tx/rx
        input   [(MAW+1):0]      i_wb_addr; // 1-bit for ctrl/data, 1 for tx/rx
        input   [31:0]           i_wb_data;
        input   [31:0]           i_wb_data;
        //
        //
        output  reg             o_wb_ack;
        output  reg             o_wb_ack;
        output  wire            o_wb_stall;
        output  wire            o_wb_stall;
        output  reg     [31:0]   o_wb_data;
        output  reg     [31:0]   o_wb_data;
        //
        //
        output  reg             o_net_reset_n;
        output  reg             o_net_reset_n;
        //
        //
        input                   i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
        input                   i_net_rx_clk, i_net_col, i_net_crs, i_net_dv;
        input           [3:0]    i_net_rxd;
        input           [3:0]    i_net_rxd;
        input                   i_net_rxerr;
        input                   i_net_rxerr;
        //
        //
        input                   i_net_tx_clk;
        input                   i_net_tx_clk;
        output  wire            o_net_tx_en;
        output  wire            o_net_tx_en;
        output  wire    [3:0]    o_net_txd;
        output  wire    [3:0]    o_net_txd;
        //
        //
        output  wire            o_rx_int, o_tx_int;
        output  wire            o_rx_int, o_tx_int;
        //
        //
        output  wire    [31:0]   o_debug;
        output  wire    [31:0]   o_debug;
 
 
        reg     wr_ctrl;
        reg     wr_ctrl;
        reg     [2:0]    wr_addr;
        reg     [2:0]    wr_addr;
        reg     [31:0]   wr_data;
        reg     [31:0]   wr_data;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                wr_ctrl<=((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b00));
                wr_ctrl<=((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b00));
                wr_addr <= i_wb_addr[2:0];
                wr_addr <= i_wb_addr[2:0];
                wr_data <= i_wb_data;
                wr_data <= i_wb_data;
        end
        end
 
 
        reg     [31:0]   txmem   [0:((1<<MAW)-1)];
        reg     [31:0]   txmem   [0:((1<<MAW)-1)];
        reg     [31:0]   rxmem   [0:((1<<MAW)-1)];
        reg     [31:0]   rxmem   [0:((1<<MAW)-1)];
 
 
        reg     [(MAW+1):0]      tx_len;
        reg     [(MAW+1):0]      tx_len;
 
 
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
 
        wire    rx_broadcast;
        wire    [(MAW+1):0]      rx_len;
        wire    [(MAW+1):0]      rx_len;
`else
`else
 
        (* ASYNC_REG = "TRUE" *) reg    rx_broadcast;
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      rx_len;
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      rx_len;
`endif
`endif
 
 
        reg     tx_cmd, tx_cancel;
        reg     tx_cmd, tx_cancel;
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
        wire    tx_busy, tx_complete;
        wire    tx_busy, tx_complete;
`else
`else
        reg     tx_busy, tx_complete;
        reg     tx_busy, tx_complete;
`endif
`endif
        reg     config_hw_crc, config_hw_mac, config_hw_ip_check;
        reg     config_hw_crc, config_hw_mac, config_hw_ip_check;
        reg     rx_crcerr, rx_err, rx_miss, rx_clear;
        reg     rx_crcerr, rx_err, rx_miss, rx_clear;
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
        wire    rx_valid, rx_busy;
        wire    rx_valid, rx_busy;
`else
`else
        reg     rx_valid, rx_busy;
        reg     rx_valid, rx_busy;
`endif
`endif
        reg     rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
        reg     rx_wb_valid, pre_ack, pre_cmd, tx_nzero_cmd;
        reg     [4:0]    caseaddr;
        reg     [4:0]    caseaddr;
        reg     [31:0]   rx_wb_data, tx_wb_data;
        reg     [31:0]   rx_wb_data, tx_wb_data;
        reg             rx_err_stb, rx_miss_stb, rx_crc_stb;
        reg             rx_err_stb, rx_miss_stb, rx_crc_stb;
 
 
        reg     [47:0]   hw_mac;
        reg     [47:0]   hw_mac;
        reg             p_rx_clear;
        reg             p_rx_clear;
        reg     [7:0]    clear_pipe;
        reg     [7:0]    clear_pipe;
 
 
        initial config_hw_crc = 0;
        initial config_hw_crc = 0;
        initial config_hw_mac = 0;
        initial config_hw_mac = 0;
        initial config_hw_ip_check = 0;
        initial config_hw_ip_check = 0;
        initial o_net_reset_n = 1'b0;
        initial o_net_reset_n = 1'b0;
        initial tx_cmd    = 1'b0;
        initial tx_cmd    = 1'b0;
        initial tx_cancel = 1'b0;
        initial tx_cancel = 1'b0;
        initial rx_crcerr = 1'b0;
        initial rx_crcerr = 1'b0;
        initial rx_err    = 1'b0;
        initial rx_err    = 1'b0;
        initial rx_miss   = 1'b0;
        initial rx_miss   = 1'b0;
        initial rx_clear  = 1'b0;
        initial rx_clear  = 1'b0;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                // if (i_wb_addr[(MAW+1):MAW] == 2'b10)
                // if (i_wb_addr[(MAW+1):MAW] == 2'b10)
                        // Writes to rx memory not allowed here
                        // Writes to rx memory not allowed here
                if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11))
                if ((i_wb_stb)&&(i_wb_we)&&(i_wb_addr[(MAW+1):MAW] == 2'b11))
                        txmem[i_wb_addr[(MAW-1):0]] <= i_wb_data;
                        txmem[i_wb_addr[(MAW-1):0]] <= i_wb_data;
 
 
                // Set the err bits on these conditions (filled out below)
                // Set the err bits on these conditions (filled out below)
                if (rx_err_stb)
                if (rx_err_stb)
                        rx_err <= 1'b1;
                        rx_err <= 1'b1;
                if (rx_miss_stb)
                if (rx_miss_stb)
                        rx_miss <= 1'b1;
                        rx_miss <= 1'b1;
                if (rx_crc_stb)
                if (rx_crc_stb)
                        rx_crcerr <= 1'b1;
                        rx_crcerr <= 1'b1;
 
 
                if ((wr_ctrl)&&(wr_addr==3'b000))
                if ((wr_ctrl)&&(wr_addr==3'b000))
                begin // RX command register
                begin // RX command register
                        rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
                        rx_crcerr<= (!wr_data[18])&&(!rx_crcerr);
                        rx_err   <= (!wr_data[17])&&(!rx_err);
                        rx_err   <= (!wr_data[17])&&(!rx_err);
                        rx_miss  <= (!wr_data[16])&&(!rx_miss);
                        rx_miss  <= (!wr_data[16])&&(!rx_miss);
                        // busy bit cannot be written to
                        // busy bit cannot be written to
                        rx_clear <= rx_clear || (wr_data[14]);
                        rx_clear <= rx_clear || (wr_data[14]);
                        // Length bits are cleared when invalid
                        // Length bits are cleared when invalid
                end else if (!rx_valid)
                end else if (!rx_valid)
                        rx_clear <= 1'b0;
                        rx_clear <= 1'b0;
 
 
                clear_pipe <= { clear_pipe[6:0], rx_clear };
                clear_pipe <= { clear_pipe[6:0], rx_clear };
                p_rx_clear <= |clear_pipe;
                p_rx_clear <= |clear_pipe;
 
 
                if ((tx_busy)||(tx_cancel))
                if ((tx_busy)||(tx_cancel))
                        tx_cmd <= 1'b0;
                        tx_cmd <= 1'b0;
                if (!tx_busy)
                if (!tx_busy)
                        tx_cancel <= 1'b0;
                        tx_cancel <= 1'b0;
                pre_cmd <= 1'b0;
                pre_cmd <= 1'b0;
                if ((wr_ctrl)&&(wr_addr==3'b001))
                if ((wr_ctrl)&&(wr_addr==3'b001))
                begin // TX command register
                begin // TX command register
 
 
                        // Reset bit must be held down to be valid
                        // Reset bit must be held down to be valid
                        config_hw_ip_check <= (!wr_data[18]);
                        config_hw_ip_check <= (!wr_data[18]);
                        o_net_reset_n <= (!wr_data[17]);
                        o_net_reset_n <= (!wr_data[17]);
                        config_hw_mac <= (!wr_data[16]);
                        config_hw_mac <= (!wr_data[16]);
                        config_hw_crc <= (!wr_data[15]);
                        config_hw_crc <= (!wr_data[15]);
                        pre_cmd <= (wr_data[14]);
                        pre_cmd <= (wr_data[14]);
                        tx_cancel <= (tx_busy)&&(!wr_data[14]);
                        tx_cancel <= (tx_busy)&&(!wr_data[14]);
//              14'h0   | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
//              14'h0   | SW-CRCn |NET-RST|BUSY/CMD | 14 bit length(in octets)|
                        tx_len <= wr_data[(MAW+1):0];
                        tx_len <= wr_data[(MAW+1):0];
                end
                end
                tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
                tx_nzero_cmd <= ((pre_cmd)&&(tx_len != 0));
                if (tx_nzero_cmd)
                if (tx_nzero_cmd)
                        tx_cmd <= 1'b1;
                        tx_cmd <= 1'b1;
                if (!o_net_reset_n)
                if (!o_net_reset_n)
                        tx_cancel <= 1'b1;
                        tx_cancel <= 1'b1;
                if (!o_net_reset_n)
                if (!o_net_reset_n)
                        tx_cmd <= 1'b0;
                        tx_cmd <= 1'b0;
 
 
                if ((wr_ctrl)&&(wr_addr==3'b010))
                if ((wr_ctrl)&&(wr_addr==3'b010))
                        hw_mac[47:32] <= wr_data[15:0];
                        hw_mac[47:32] <= wr_data[15:0];
                if ((wr_ctrl)&&(wr_addr==3'b011))
                if ((wr_ctrl)&&(wr_addr==3'b011))
                        hw_mac[31:0] <= wr_data[31:0];
                        hw_mac[31:0] <= wr_data[31:0];
        end
        end
 
 
        wire    [31:0]   w_tx_ctrl;
        wire    [31:0]   w_tx_ctrl;
        wire    [31:0]   w_rx_ctrl;
        wire    [31:0]   w_rx_ctrl;
        wire    [3:0]    w_maw;
        wire    [3:0]    w_maw;
 
 
        assign  w_maw = MAW+2; // Number of bits in the packet length field
        assign  w_maw = MAW+2; // Number of bits in the packet length field
        assign  w_rx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}}, rx_crcerr, rx_err,
        assign  w_rx_ctrl = { 4'h0, w_maw, {(24-20){1'b0}},
 
                        (rx_valid)&&(rx_broadcast)&&(!rx_clear),
 
                        rx_crcerr, rx_err,
                        rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
                        rx_miss, rx_busy, (rx_valid)&&(!rx_clear),
                        {(14-MAW-2){1'b0}}, rx_len };
                        {(14-MAW-2){1'b0}}, rx_len };
 
 
        assign  w_tx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}},
        assign  w_tx_ctrl = { 4'h0, w_maw, {(24-19){1'b0}},
                        !config_hw_ip_check,
                        !config_hw_ip_check,
                        !o_net_reset_n,!config_hw_mac,
                        !o_net_reset_n,!config_hw_mac,
                        !config_hw_crc, tx_busy,
                        !config_hw_crc, tx_busy,
                                {(14-MAW-2){1'b0}}, tx_len };
                                {(14-MAW-2){1'b0}}, tx_len };
 
 
        reg     [31:0]   counter_rx_miss, counter_rx_err, counter_rx_crc;
        reg     [31:0]   counter_rx_miss, counter_rx_err, counter_rx_crc;
        initial counter_rx_miss = 32'h00;
        initial counter_rx_miss = 32'h00;
        initial counter_rx_err  = 32'h00;
        initial counter_rx_err  = 32'h00;
        initial counter_rx_crc  = 32'h00;
        initial counter_rx_crc  = 32'h00;
 
 
        // Reads from the bus ... always done, regardless of i_wb_we
        // Reads from the bus ... always done, regardless of i_wb_we
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                rx_wb_data  <= rxmem[i_wb_addr[(MAW-1):0]];
                rx_wb_data  <= rxmem[i_wb_addr[(MAW-1):0]];
                rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
                rx_wb_valid <= (i_wb_addr[(MAW-1):0] <= { rx_len[(MAW+1):2] });
                tx_wb_data  <= txmem[i_wb_addr[(MAW-1):0]];
                tx_wb_data  <= txmem[i_wb_addr[(MAW-1):0]];
                pre_ack <= i_wb_stb;
                pre_ack <= i_wb_stb;
                caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
                caseaddr <= {i_wb_addr[(MAW+1):MAW], i_wb_addr[2:0] };
 
 
                casez(caseaddr)
                casez(caseaddr)
                5'h00: o_wb_data <= w_rx_ctrl;
                5'h00: o_wb_data <= w_rx_ctrl;
                5'h01: o_wb_data <= w_tx_ctrl;
                5'h01: o_wb_data <= w_tx_ctrl;
                5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
                5'h02: o_wb_data <= {16'h00, hw_mac[47:32] };
                5'h03: o_wb_data <= hw_mac[31:0];
                5'h03: o_wb_data <= hw_mac[31:0];
                5'h04: o_wb_data <= counter_rx_miss;
                5'h04: o_wb_data <= counter_rx_miss;
                5'h05: o_wb_data <= counter_rx_err;
                5'h05: o_wb_data <= counter_rx_err;
                5'h06: o_wb_data <= counter_rx_crc;
                5'h06: o_wb_data <= counter_rx_crc;
                5'h07: o_wb_data <= 32'h00;
                5'h07: o_wb_data <= 32'h00;
                5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
                5'b10???: o_wb_data <= (rx_wb_valid)?rx_wb_data:32'h00;
                5'b11???: o_wb_data <= tx_wb_data;
                5'b11???: o_wb_data <= tx_wb_data;
                default: o_wb_data <= 32'h00;
                default: o_wb_data <= 32'h00;
                endcase
                endcase
                o_wb_ack <= pre_ack;
                o_wb_ack <= pre_ack;
        end
        end
 
 
        /////////////////////////////////////
        /////////////////////////////////////
        //
        //
        //
        //
        //
        //
        // Transmitter code
        // Transmitter code
        //
        //
        //
        //
        //
        //
        /////////////////////////////////////
        /////////////////////////////////////
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
        reg     [(MAW+1):0]      n_tx_len;
        reg     [(MAW+1):0]      n_tx_len;
        wire    n_tx_cmd, n_tx_cancel;
        wire    n_tx_cmd, n_tx_cancel;
        assign  n_tx_cmd = tx_cmd;
        assign  n_tx_cmd = tx_cmd;
        assign  n_tx_cancel = tx_cancel;
        assign  n_tx_cancel = tx_cancel;
`else
`else
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      n_tx_len;
        (* ASYNC_REG = "TRUE" *) reg    [(MAW+1):0]      n_tx_len;
        (* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
        (* ASYNC_REG = "TRUE" *) reg r_tx_cmd, r_tx_cancel;
        reg     n_tx_cmd, n_tx_cancel;
        reg     n_tx_cmd, n_tx_cancel;
        always @(posedge `TXCLK)
        always @(posedge `TXCLK)
        begin
        begin
                r_tx_cmd    <= tx_cmd;
                r_tx_cmd    <= tx_cmd;
                r_tx_cancel <= tx_cancel;
                r_tx_cancel <= tx_cancel;
 
 
                n_tx_cmd    <= r_tx_cmd;
                n_tx_cmd    <= r_tx_cmd;
                n_tx_cancel <= r_tx_cancel;
                n_tx_cancel <= r_tx_cancel;
        end
        end
`endif
`endif
 
 
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCHRONOUS_WITH_WB_CLK
        reg     last_tx_clk, tx_clk_stb;
        reg     last_tx_clk, tx_clk_stb;
        (* ASYNC_REG = "TRUE" *) reg    r_tx_clk;
        (* ASYNC_REG = "TRUE" *) reg    r_tx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                r_tx_clk <= i_net_tx_clk;
                r_tx_clk <= i_net_tx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                last_tx_clk <= r_tx_clk;
                last_tx_clk <= r_tx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
                tx_clk_stb <= (r_tx_clk)&&(!last_tx_clk);
`else
`else
        wire    tx_clk_stb, last_tx_clk;
        wire    tx_clk_stb, last_tx_clk;
 
 
        assign  tx_clk_stb = 1'b1;
        assign  tx_clk_stb = 1'b1;
        assign  last_tx_clk= 1'b0;
        assign  last_tx_clk= 1'b0;
`endif
`endif
 
 
        wire    [(MAW+2):0]      rd_tx_addr;
        wire    [(MAW+2):0]      rd_tx_addr;
        assign  rd_tx_addr = (n_tx_addr+8);
        assign  rd_tx_addr = (n_tx_addr+8);
 
 
        reg     [(MAW+2):0]      n_tx_addr;
        reg     [(MAW+2):0]      n_tx_addr;
        reg     [31:0]           n_tx_data, n_next_tx_data;
        reg     [31:0]           n_tx_data, n_next_tx_data;
        reg                     n_tx_complete;
        reg                     n_tx_complete;
`ifdef  TX_SYNCHRONOUSH_WITH_WB
`ifdef  TX_SYNCHRONOUSH_WITH_WB
        reg             n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
        reg             n_tx_busy, n_tx_config_hw_mac, n_tx_config_hw_crc;
`else
`else
        (* ASYNC_REG = "TRUE" *) reg    n_tx_busy,
        (* ASYNC_REG = "TRUE" *) reg    n_tx_busy,
                                        n_tx_config_hw_mac, n_tx_config_hw_crc;
                                        n_tx_config_hw_mac, n_tx_config_hw_crc;
`endif
`endif
        (* ASYNC_REG = "TRUE" *) reg r_tx_crs;
        (* ASYNC_REG = "TRUE" *) reg r_tx_crs;
        reg     n_tx_crs;
        reg     n_tx_crs;
        always @(posedge `TXCLK)
        always @(posedge `TXCLK)
        begin
        begin
                r_tx_crs <= i_net_crs;
                r_tx_crs <= i_net_crs;
                n_tx_crs <= r_tx_crs;
                n_tx_crs <= r_tx_crs;
        end
        end
 
 
        wire    [31:0]   n_remap_tx_data;
        wire    [31:0]   n_remap_tx_data;
        assign  n_remap_tx_data[31:28] = n_next_tx_data[27:24];
        assign  n_remap_tx_data[31:28] = n_next_tx_data[27:24];
        assign  n_remap_tx_data[27:24] = n_next_tx_data[31:28];
        assign  n_remap_tx_data[27:24] = n_next_tx_data[31:28];
        assign  n_remap_tx_data[23:20] = n_next_tx_data[19:16];
        assign  n_remap_tx_data[23:20] = n_next_tx_data[19:16];
        assign  n_remap_tx_data[19:16] = n_next_tx_data[23:20];
        assign  n_remap_tx_data[19:16] = n_next_tx_data[23:20];
        assign  n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
        assign  n_remap_tx_data[15:12] = n_next_tx_data[11: 8];
        assign  n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
        assign  n_remap_tx_data[11: 8] = n_next_tx_data[15:12];
        assign  n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
        assign  n_remap_tx_data[ 7: 4] = n_next_tx_data[ 3: 0];
        assign  n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
        assign  n_remap_tx_data[ 3: 0] = n_next_tx_data[ 7: 4];
 
 
        reg             r_txd_en;
        reg             r_txd_en;
        reg     [3:0]    r_txd;
        reg     [3:0]    r_txd;
        initial r_txd_en = 1'b0;
        initial r_txd_en = 1'b0;
 
 
        initial n_tx_busy  = 1'b0;
        initial n_tx_busy  = 1'b0;
        initial n_tx_complete  = 1'b0;
        initial n_tx_complete  = 1'b0;
        always @(posedge `TXCLK)
        always @(posedge `TXCLK)
        begin
        begin
                if (tx_clk_stb)
                if (tx_clk_stb)
                begin
                begin
                        // While this operation doesn't strictly need to 
                        // While this operation doesn't strictly need to 
                        // operate *only* if tx_clk_stb is true, by doing so
                        // operate *only* if tx_clk_stb is true, by doing so
                        // our code stays compatible with both synchronous
                        // our code stays compatible with both synchronous
                        // to wishbone and synchronous to tx clk options.
                        // to wishbone and synchronous to tx clk options.
                        n_next_tx_data  <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
                        n_next_tx_data  <= txmem[(!n_tx_busy)?0:rd_tx_addr[(MAW+2):3]];
                end
                end
 
 
 
 
                if (n_tx_cancel)
                if (n_tx_cancel)
                        n_tx_busy <= 1'b0;
                        n_tx_busy <= 1'b0;
                else if (!n_tx_busy)
                else if (!n_tx_busy)
                        n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
                        n_tx_busy <= (n_tx_cmd)&&(!i_net_crs);
                else if (n_tx_addr >= { n_tx_len,1'b0 })
                else if (n_tx_addr >= { n_tx_len,1'b0 })
                        n_tx_busy     <= 1'b0;
                        n_tx_busy     <= 1'b0;
 
 
                if (!n_tx_busy)
                if (!n_tx_busy)
                begin
                begin
                        n_tx_addr  <= {{(MAW+2){1'b0}},1'b1};
                        n_tx_addr  <= {{(MAW+2){1'b0}},1'b1};
                        n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
                        n_tx_data <= { n_remap_tx_data[27:0], 4'h0 };
                        if (n_tx_complete)
                        if (n_tx_complete)
                                n_tx_complete <= (!n_tx_cmd);
                                n_tx_complete <= (!n_tx_cmd);
                        r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
                        r_txd_en <= (!n_tx_complete)&&(n_tx_cmd)&&(!i_net_crs);
                        r_txd  <= n_remap_tx_data[31:28];
                        r_txd  <= n_remap_tx_data[31:28];
                        n_tx_config_hw_mac <= config_hw_mac;
                        n_tx_config_hw_mac <= config_hw_mac;
                        n_tx_config_hw_crc <= config_hw_crc;
                        n_tx_config_hw_crc <= config_hw_crc;
                        n_tx_len <= tx_len;
                        n_tx_len <= tx_len;
                end else if (!r_txd_en)
                end else if (!r_txd_en)
                        r_txd_en <= (!n_tx_crs);
                        r_txd_en <= (!n_tx_crs);
                else if (tx_clk_stb) begin
                else if (tx_clk_stb) begin
                        n_tx_addr <= n_tx_addr + 1'b1;
                        n_tx_addr <= n_tx_addr + 1'b1;
                        r_txd <= n_tx_data[31:28];
                        r_txd <= n_tx_data[31:28];
                        if (n_tx_addr[2:0] == 3'h7)
                        if (n_tx_addr[2:0] == 3'h7)
                                n_tx_data <= n_remap_tx_data;
                                n_tx_data <= n_remap_tx_data;
                        else
                        else
                                n_tx_data <= { n_tx_data[27:0], 4'h0 };
                                n_tx_data <= { n_tx_data[27:0], 4'h0 };
                        if (n_tx_addr >= { n_tx_len,1'b0 })
                        if (n_tx_addr >= { n_tx_len,1'b0 })
                                n_tx_complete <= 1'b1;
                                n_tx_complete <= 1'b1;
                        r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
                        r_txd_en <= (n_tx_addr < { n_tx_len, 1'b0 });
                end
                end
        end
        end
 
 
        wire    n_tx_config_hw_preamble;
        wire    n_tx_config_hw_preamble;
        assign  n_tx_config_hw_preamble = 1'b1;
        assign  n_tx_config_hw_preamble = 1'b1;
 
 
        wire            w_macen, w_paden, w_txcrcen;
        wire            w_macen, w_paden, w_txcrcen;
        wire    [3:0]    w_macd,  w_padd,  w_txcrcd;
        wire    [3:0]    w_macd,  w_padd,  w_txcrcd;
 
 
`ifndef TX_BYPASS_HW_MAC
`ifndef TX_BYPASS_HW_MAC
        addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
        addemac txmaci(`TXCLK, tx_clk_stb, n_tx_config_hw_mac, n_tx_cancel,
                                hw_mac, r_txd_en, r_txd, w_macen, w_macd);
                                hw_mac, r_txd_en, r_txd, w_macen, w_macd);
`else
`else
        assign  w_macen = r_txd_en;
        assign  w_macen = r_txd_en;
        assign  w_macd  = r_txd;
        assign  w_macd  = r_txd;
`endif
`endif
 
 
`ifndef TX_BYPASS_PADDING
`ifndef TX_BYPASS_PADDING
        addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
        addepad txpadi(`TXCLK, tx_clk_stb, 1'b1, n_tx_cancel,
                                w_macen, w_macd, w_paden, w_padd);
                                w_macen, w_macd, w_paden, w_padd);
`else
`else
        assign  w_paden = w_macen;
        assign  w_paden = w_macen;
        assign  w_padd  = w_macd;
        assign  w_padd  = w_macd;
`endif
`endif
 
 
`ifndef TX_BYPASS_HW_CRC
`ifndef TX_BYPASS_HW_CRC
        addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
        addecrc txcrci(`TXCLK, tx_clk_stb, n_tx_config_hw_crc, n_tx_cancel,
                                w_paden, w_padd, w_txcrcen, w_txcrcd);
                                w_paden, w_padd, w_txcrcen, w_txcrcd);
`else
`else
        assign  w_txcrcen = w_macen;
        assign  w_txcrcen = w_macen;
        assign  w_txcrcd  = w_macd;
        assign  w_txcrcd  = w_macd;
`endif
`endif
 
 
        addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
        addepreamble txprei(`TXCLK, tx_clk_stb, n_tx_config_hw_preamble, n_tx_cancel,
                                w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
                                w_txcrcen, w_txcrcd, o_net_tx_en, o_net_txd);
 
 
`ifdef  TX_SYNCRONOUS_WITH_WB_CLK
`ifdef  TX_SYNCRONOUS_WITH_WB_CLK
        assign  tx_busy = n_tx_busy;
        assign  tx_busy = n_tx_busy;
        assign  tx_complete = n_tx_complete;
        assign  tx_complete = n_tx_complete;
`else
`else
        (* ASYNC_REG = "TRUE" *) reg    r_tx_busy, r_tx_complete;
        (* ASYNC_REG = "TRUE" *) reg    r_tx_busy, r_tx_complete;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
                r_tx_busy <= (n_tx_busy || o_net_tx_en || w_txcrcen || w_macen || w_paden);
                tx_busy <= r_tx_busy;
                tx_busy <= r_tx_busy;
 
 
                r_tx_complete <= n_tx_complete;
                r_tx_complete <= n_tx_complete;
                tx_busy <= r_tx_busy;
                tx_busy <= r_tx_busy;
        end
        end
`endif
`endif
 
 
 
 
 
 
 
 
 
 
        /////////////////////////////////////
        /////////////////////////////////////
        //
        //
        //
        //
        //
        //
        // Receiver code
        // Receiver code
        //
        //
        //
        //
        //
        //
        /////////////////////////////////////
        /////////////////////////////////////
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
        reg     last_rx_clk, rx_clk_stb;
        reg     last_rx_clk, rx_clk_stb;
        (* ASYNC_REG="TRUE" *) reg r_rx_clk;
        (* ASYNC_REG="TRUE" *) reg r_rx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                r_rx_clk <= i_net_rx_clk;
                r_rx_clk <= i_net_rx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                last_rx_clk <= r_rx_clk;
                last_rx_clk <= r_rx_clk;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
                rx_clk_stb <= (r_rx_clk)&&(!last_rx_clk);
 
 
`else
`else
        wire    rx_clk_stb, last_rx_clk;
        wire    rx_clk_stb, last_rx_clk;
        assign  rx_clk_stb = 1'b1;
        assign  rx_clk_stb = 1'b1;
        assign  last_rx_clk = 1'b0;
        assign  last_rx_clk = 1'b0;
`endif
`endif
 
 
 
 
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
        wire    n_rx_clear;
        wire    n_rx_clear;
        reg     n_rx_config_hw_mac, n_rx_config_hw_crc, n_rx_config_ip_check;
        reg     n_rx_config_hw_mac, n_rx_config_hw_crc, n_rx_config_ip_check;
        assign  n_rx_clear = rx_clear;
        assign  n_rx_clear = rx_clear;
`else
`else
        (* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc,
        (* ASYNC_REG = "TRUE" *) reg n_rx_config_hw_mac, n_rx_config_hw_crc,
                        n_rx_config_ip_check;
                        n_rx_config_ip_check;
        (* ASYNC_REG = "TRUE" *) reg r_rx_clear;
        (* ASYNC_REG = "TRUE" *) reg r_rx_clear;
        reg     n_rx_clear;
        reg     n_rx_clear;
        always @(posedge `RXCLK)
        always @(posedge `RXCLK)
        begin
        begin
                r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
                r_rx_clear <= (p_rx_clear)||(!o_net_reset_n);
                n_rx_clear <= r_rx_clear;
                n_rx_clear <= r_rx_clear;
        end
        end
`endif
`endif
 
 
 
 
        reg             n_rx_net_err;
        reg             n_rx_net_err;
        wire            w_npre,  w_rxmin,  w_rxcrc,  w_rxmac;
        wire            w_npre,  w_rxmin,  w_rxcrc,  w_rxmac;
        wire    [3:0]    w_npred, w_rxmind, w_rxcrcd, w_rxmacd;
        wire    [3:0]    w_npred, w_rxmind, w_rxcrcd, w_rxmacd;
        wire            w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
        wire            w_minerr, w_rxcrcerr, w_macerr, w_broadcast, w_iperr;
`ifndef RX_BYPASS_HW_PREAMBLE
`ifndef RX_BYPASS_HW_PREAMBLE
        rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
        rxepreambl rxprei(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
                        i_net_dv, i_net_rxd, w_npre, w_npred);
                        i_net_dv, i_net_rxd, w_npre, w_npred);
`else
`else
        assign  w_npre  = i_net_dv;
        assign  w_npre  = i_net_dv;
        assign  w_npred = i_net_rxerr;
        assign  w_npred = i_net_rxerr;
`endif
`endif
 
 
`ifdef  RX_BYPASS_HW_MINLENGTH
`ifdef  RX_BYPASS_HW_MINLENGTH
        // Insist on a minimum of 64-byte packets
        // Insist on a minimum of 64-byte packets
        rxemin  rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
        rxemin  rxmini(`RXCLK, rx_clk_stb, 1'b1, (n_rx_net_err),
                        w_npre, w_npred, w_minerr);
                        w_npre, w_npred, w_minerr);
`else
`else
        assign  w_minerr= 1'b0;
        assign  w_minerr= 1'b0;
`endif
`endif
        assign  w_rxmin = w_npre;
        assign  w_rxmin = w_npre;
        assign  w_rxmind= w_npred;
        assign  w_rxmind= w_npred;
 
 
`ifndef RX_BYPASS_HW_CRC
`ifndef RX_BYPASS_HW_CRC
        rxecrc  rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
        rxecrc  rxcrci(`RXCLK, rx_clk_stb, n_rx_config_hw_crc, (n_rx_net_err),
                        w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
                        w_rxmin, w_rxmind, w_rxcrc, w_rxcrcd, w_rxcrcerr);
`else
`else
        assign  w_rxcrc   = w_rxmin;
        assign  w_rxcrc   = w_rxmin;
        assign  w_rxcrcd  = w_rxmind;
        assign  w_rxcrcd  = w_rxmind;
        assign  w_rxcrcerr= 1'b0;
        assign  w_rxcrcerr= 1'b0;
`endif
`endif
 
 
`ifndef RX_BYPASS_HW_RMMAC
`ifndef RX_BYPASS_HW_RMMAC
        rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
        rxehwmac rxmaci(`RXCLK, rx_clk_stb, n_rx_config_hw_mac, (n_rx_net_err), hw_mac,
                        w_rxcrc, w_rxcrcd,
                        w_rxcrc, w_rxcrcd,
                        w_rxmac, w_rxmacd,
                        w_rxmac, w_rxmacd,
                        w_macerr, w_broadcast);
                        w_macerr, w_broadcast);
`else
`else
        assign  w_rxmac  = w_rxcrc;
        assign  w_rxmac  = w_rxcrc;
        assign  w_rxmacd = w_rxcrcd;
        assign  w_rxmacd = w_rxcrcd;
`endif
`endif
 
 
`define RX_HW_IPCHECK
`define RX_HW_IPCHECK
`ifdef  RX_HW_IPCHECK
`ifdef  RX_HW_IPCHECK
        // Check: if this packet is an IP packet, is the IP header checksum
        // Check: if this packet is an IP packet, is the IP header checksum
        // valid?
        // valid?
        rxeipchk rxipci(`RXCLK, rx_clk_stb, n_rx_config_ip_check,(n_rx_net_err),
        rxeipchk rxipci(`RXCLK, rx_clk_stb, n_rx_config_ip_check,(n_rx_net_err),
                        w_rxcrc, w_rxcrcd, w_iperr);
                        w_rxcrc, w_rxcrcd, w_iperr);
`else
`else
        assign  w_iperr = 1'b0;
        assign  w_iperr = 1'b0;
`endif
`endif
 
 
        wire                    w_rxwr;
        wire                    w_rxwr;
        wire    [(MAW-1):0]      w_rxaddr;
        wire    [(MAW-1):0]      w_rxaddr;
        wire    [31:0]           w_rxdata;
        wire    [31:0]           w_rxdata;
        wire    [(MAW+1):0]      w_rxlen;
        wire    [(MAW+1):0]      w_rxlen;
 
 
        rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxmac, w_rxmacd,
        rxewrite #(MAW) rxememi(`RXCLK, 1'b1, (n_rx_net_err), w_rxmac, w_rxmacd,
                        w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
                        w_rxwr, w_rxaddr, w_rxdata, w_rxlen);
 
 
        reg     last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
        reg     last_rxwr, n_rx_valid, n_rxmiss, n_eop, n_rx_busy, n_rx_crcerr,
                n_rx_err, n_rx_broadcast, n_rx_miss;
                n_rx_err, n_rx_broadcast, n_rx_miss;
        reg     [(MAW+1):0]      n_rx_len;
        reg     [(MAW+1):0]      n_rx_len;
 
 
        initial n_rx_valid = 1'b0;
        initial n_rx_valid = 1'b0;
        initial n_rx_clear = 1'b1;
        initial n_rx_clear = 1'b1;
        initial n_rx_miss  = 1'b0;
        initial n_rx_miss  = 1'b0;
        always @(posedge `RXCLK)
        always @(posedge `RXCLK)
        begin
        begin
                if ((w_rxwr)&&(!n_rx_valid))
                if ((w_rxwr)&&(!n_rx_valid))
                        rxmem[w_rxaddr] <= w_rxdata;
                        rxmem[w_rxaddr] <= w_rxdata;
 
 
                // n_rx_net_err goes true as soon as an error is detected,
                // n_rx_net_err goes true as soon as an error is detected,
                // and stays true as long as valid data is coming in
                // and stays true as long as valid data is coming in
                n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
                n_rx_net_err <= (i_net_dv)&&((i_net_rxerr)||(i_net_col)
                                ||(w_minerr)||(w_macerr)||(w_rxcrcerr)
                                ||(w_minerr)||(w_macerr)||(w_rxcrcerr)
                                ||(w_iperr)
                                ||(w_iperr)
                                ||(n_rx_net_err)
                                ||(n_rx_net_err)
                                ||((w_rxwr)&&(n_rx_valid)));
                                ||((w_rxwr)&&(n_rx_valid)));
 
 
                last_rxwr <= w_rxwr;
                last_rxwr <= w_rxwr;
                n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
                n_eop <= (!w_rxwr)&&(last_rxwr)&&(!n_rx_net_err);
 
 
                n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
                n_rx_busy <= (!n_rx_net_err)&&((i_net_dv)||(w_npre)||(w_rxmin)
                        ||(w_rxcrc)||(w_rxmac)||(w_rxwr));
                        ||(w_rxcrc)||(w_rxmac)||(w_rxwr));
 
 
                // Oops ... we missed a packet
                // Oops ... we missed a packet
                n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
                n_rx_miss <= (n_rx_valid)&&(w_rxwr)||
                        ((n_rx_miss)&&(!n_rx_clear));
                        ((n_rx_miss)&&(!n_rx_clear));
 
 
                n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
                n_rx_crcerr <= ((w_rxcrcerr)&&(!n_rx_net_err))
                        ||((n_rx_crcerr)&&(!n_rx_clear));
                        ||((n_rx_crcerr)&&(!n_rx_clear));
 
 
                n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
                n_rx_err <= ((n_rx_err)&&(!n_rx_clear))
                        ||((i_net_rxerr)||(i_net_col)||(w_minerr));
                        ||((i_net_rxerr)||(i_net_col)||(w_minerr));
 
 
                n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
                n_rx_broadcast <= (w_broadcast)||((n_rx_broadcast)&&(!n_rx_clear));
 
 
                if (n_rx_clear)
                if (n_rx_clear)
                begin
                begin
                        n_rx_valid <= 1'b0;
                        n_rx_valid <= 1'b0;
                        n_rx_len <= 0;
                        n_rx_len <= 0;
                end else if (n_eop)
                end else if (n_eop)
                begin
                begin
                        n_rx_valid <= 1'b1;
                        n_rx_valid <= 1'b1;
                        n_rx_len   <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
                        n_rx_len   <= w_rxlen - ((n_rx_config_hw_crc)?{{(MAW-1){1'b0}},3'h4}:0);
                end
                end
                // else n_rx_valid = n_rx_valid;
                // else n_rx_valid = n_rx_valid;
 
 
                if ((!i_net_dv)||(n_rx_clear))
                if ((!i_net_dv)||(n_rx_clear))
                begin
                begin
                        n_rx_config_hw_mac   <= config_hw_mac;
                        n_rx_config_hw_mac   <= config_hw_mac;
                        n_rx_config_hw_crc   <= config_hw_crc;
                        n_rx_config_hw_crc   <= config_hw_crc;
                        n_rx_config_ip_check <= config_hw_ip_check;
                        n_rx_config_ip_check <= config_hw_ip_check;
                end
                end
        end
        end
 
 
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
`ifdef  RX_SYNCHRONOUS_WITH_WB_CLK
        assign  rx_busy  = n_rx_busy;
        assign  rx_busy  = n_rx_busy;
        assign  rx_valid = n_rx_valid;
        assign  rx_valid = n_rx_valid;
        assign  rx_len   = n_rx_len;
        assign  rx_len   = n_rx_len;
 
        assign  rx_broadcast = n_rx_broadcast;
`else
`else
        reg     r_rx_busy, r_rx_valid;
        reg     r_rx_busy, r_rx_valid;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                r_rx_valid <= n_rx_valid;
                r_rx_valid <= n_rx_valid;
                rx_valid <= r_rx_valid;
                rx_valid <= r_rx_valid;
 
 
                r_rx_busy <= n_rx_busy;
                r_rx_busy <= n_rx_busy;
                rx_busy <= r_rx_busy;
                rx_busy <= r_rx_busy;
 
 
                rx_len <= n_rx_len;
                rx_len <= n_rx_len;
 
                rx_broadcast <= n_rx_broadcast;
        end
        end
 
 
`endif
`endif
 
 
        reg     [3:0]    rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
        reg     [3:0]    rx_err_pipe, rx_miss_pipe, rx_crc_pipe;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
        begin
        begin
                rx_err_pipe  <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb)  };
                rx_err_pipe  <= { rx_err_pipe[ 2:0],(n_rx_err)&&(rx_clk_stb)  };
                rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
                rx_miss_pipe <= { rx_miss_pipe[2:0],(n_rx_miss)&&(rx_clk_stb) };
                rx_crc_pipe  <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
                rx_crc_pipe  <= { rx_crc_pipe[ 2:0],(n_rx_crcerr)&&(rx_clk_stb) };
                rx_err_stb   <= (rx_err_pipe[ 3:2] == 2'b01);
                rx_err_stb   <= (rx_err_pipe[ 3:2] == 2'b01);
                rx_miss_stb  <= (rx_miss_pipe[3:2] == 2'b01);
                rx_miss_stb  <= (rx_miss_pipe[3:2] == 2'b01);
                rx_crc_stb   <= (rx_crc_pipe[ 3:2] == 2'b01);
                rx_crc_stb   <= (rx_crc_pipe[ 3:2] == 2'b01);
        end
        end
 
 
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                if (o_net_reset_n)
                if (o_net_reset_n)
                        counter_rx_miss <= 32'h0;
                        counter_rx_miss <= 32'h0;
                else if (rx_miss_stb)
                else if (rx_miss_stb)
                        counter_rx_miss <= counter_rx_miss + 32'h1;
                        counter_rx_miss <= counter_rx_miss + 32'h1;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                if (o_net_reset_n)
                if (o_net_reset_n)
                        counter_rx_err <= 32'h0;
                        counter_rx_err <= 32'h0;
                else if (rx_err_stb)
                else if (rx_err_stb)
                        counter_rx_err <= counter_rx_err + 32'h1;
                        counter_rx_err <= counter_rx_err + 32'h1;
        always @(posedge i_wb_clk)
        always @(posedge i_wb_clk)
                if (o_net_reset_n)
                if (o_net_reset_n)
                        counter_rx_crc <= 32'h0;
                        counter_rx_crc <= 32'h0;
                else if (rx_crc_stb)
                else if (rx_crc_stb)
                        counter_rx_crc <= counter_rx_crc + 32'h1;
                        counter_rx_crc <= counter_rx_crc + 32'h1;
 
 
        assign  o_tx_int = !tx_busy;
        assign  o_tx_int = !tx_busy;
        assign  o_rx_int = (rx_valid)&&(!rx_clear);
        assign  o_rx_int = (rx_valid)&&(!rx_clear);
        assign  o_wb_stall = 1'b0;
        assign  o_wb_stall = 1'b0;
 
 
        wire    [31:0]   rxdbg;
        wire    [31:0]   rxdbg;
        wire    rx_trigger; // reg      rx_trigger;
        wire    rx_trigger; // reg      rx_trigger;
        /*
        /*
        always @(posedge `RXCLK)
        always @(posedge `RXCLK)
        begin
        begin
                if ((n_rx_clear)&&(!rx_trigger))
                if ((n_rx_clear)&&(!rx_trigger))
                        rx_trigger <= 1'b1;
                        rx_trigger <= 1'b1;
                else if (!n_rx_clear)
                else if (!n_rx_clear)
                        rx_trigger <= 1'b0;
                        rx_trigger <= 1'b0;
        end
        end
        */
        */
        assign  rx_trigger = i_net_dv;
        assign  rx_trigger = i_net_dv;
 
 
        assign  rxdbg = { rx_trigger, n_eop, w_rxwr,
        assign  rxdbg = { rx_trigger, n_eop, w_rxwr,
                w_npre, w_npred,
                w_npre, w_npred,
                w_rxcrc, w_rxcrcd,
                w_rxcrc, w_rxcrcd,
                w_macerr, w_broadcast, w_rxmac, w_rxmacd,
                w_macerr, w_broadcast, w_rxmac, w_rxmacd,
                n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
                n_rx_clear, i_net_rxerr, n_rx_miss, n_rx_net_err,// 4 bits
                n_rx_valid, n_rx_busy, i_net_crs, i_net_dv,     // 4 bits
                n_rx_valid, n_rx_busy, i_net_crs, i_net_dv,     // 4 bits
                i_net_rxd };                                    // 4 bits
                i_net_rxd };                                    // 4 bits
 
 
 
 
        wire    [31:0]   txdbg;
        wire    [31:0]   txdbg;
        assign  txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
        assign  txdbg = { n_tx_cmd, i_net_dv, rx_busy, n_rx_err, i_net_rxd,
                        {(24-(MAW+3)-10){1'b0}},
                        {(24-(MAW+3)-10){1'b0}},
                        n_tx_addr[(MAW+2):0],
                        n_tx_addr[(MAW+2):0],
                tx_clk_stb, n_tx_cancel,
                tx_clk_stb, n_tx_cancel,
                n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
                n_tx_cmd, n_tx_complete, n_tx_busy, o_net_tx_en,
                o_net_txd
                o_net_txd
                };
                };
 
 
        assign  o_debug = rxdbg;
        assign  o_debug = rxdbg;
endmodule
endmodule
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.