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

Subversion Repositories ethmac

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ethmac/tags/rel_2
    from Rev 335 to Rev 338
    Reverse comparison

Rev 335 → Rev 338

/rtl/verilog/eth_wishbone.v
0,0 → 1,2151
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_wishbone.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.30 2002/07/23 15:28:31 mohor
// Ram , used for BDs changed from generic_spram to eth_spram_256x32.
//
// Revision 1.29 2002/07/20 00:41:32 mohor
// ShiftEnded synchronization changed.
//
// Revision 1.28 2002/07/18 16:11:46 mohor
// RxBDAddress takes `ETH_TX_BD_NUM_DEF value after reset.
//
// Revision 1.27 2002/07/11 02:53:20 mohor
// RxPointer bug fixed.
//
// Revision 1.26 2002/07/10 13:12:38 mohor
// Previous bug wasn't succesfully removed. Now fixed.
//
// Revision 1.25 2002/07/09 23:53:24 mohor
// Master state machine had a bug when switching from master write to
// master read.
//
// Revision 1.24 2002/07/09 20:44:41 mohor
// m_wb_cyc_o signal released after every single transfer.
//
// Revision 1.23 2002/05/03 10:15:50 mohor
// Outputs registered. Reset changed for eth_wishbone module.
//
// Revision 1.22 2002/04/24 08:52:19 mohor
// Compiler directives added. Tx and Rx fifo size incremented. A "late collision"
// bug fixed.
//
// Revision 1.21 2002/03/29 16:18:11 lampret
// Small typo fixed.
//
// Revision 1.20 2002/03/25 16:19:12 mohor
// Any address can be used for Tx and Rx BD pointers. Address does not need
// to be aligned.
//
// Revision 1.19 2002/03/19 12:51:50 mohor
// Comments in Slovene language removed.
//
// Revision 1.18 2002/03/19 12:46:52 mohor
// casex changed with case, fifo reset changed.
//
// Revision 1.17 2002/03/09 16:08:45 mohor
// rx_fifo was not always cleared ok. Fixed.
//
// Revision 1.16 2002/03/09 13:51:20 mohor
// Status was not latched correctly sometimes. Fixed.
//
// Revision 1.15 2002/03/08 06:56:46 mohor
// Big Endian problem when sending frames fixed.
//
// Revision 1.14 2002/03/02 19:12:40 mohor
// Byte ordering changed (Big Endian used). casex changed with case because
// Xilinx Foundation had problems. Tested in HW. It WORKS.
//
// Revision 1.13 2002/02/26 16:59:55 mohor
// Small fixes for external/internal DMA missmatches.
//
// Revision 1.12 2002/02/26 16:22:07 mohor
// Interrupts changed
//
// Revision 1.11 2002/02/15 17:07:39 mohor
// Status was not written correctly when frames were discarted because of
// address mismatch.
//
// Revision 1.10 2002/02/15 12:17:39 mohor
// RxStartFrm cleared when abort or retry comes.
//
// Revision 1.9 2002/02/15 11:59:10 mohor
// Changes that were lost when updating from 1.5 to 1.8 fixed.
//
// Revision 1.8 2002/02/14 20:54:33 billditt
// Addition of new module eth_addrcheck.v
//
// Revision 1.7 2002/02/12 17:03:47 mohor
// RxOverRun added to statuses.
//
// Revision 1.6 2002/02/11 09:18:22 mohor
// Tx status is written back to the BD.
//
// Revision 1.5 2002/02/08 16:21:54 mohor
// Rx status is written back to the BD.
//
// Revision 1.4 2002/02/06 14:10:21 mohor
// non-DMA host interface added. Select the right configutation in eth_defines.
//
// Revision 1.3 2002/02/05 16:44:39 mohor
// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200
// MHz. Statuses, overrun, control frame transmission and reception still need
// to be fixed.
//
// Revision 1.2 2002/02/01 12:46:51 mohor
// Tx part finished. TxStatus needs to be fixed. Pause request needs to be
// added.
//
// Revision 1.1 2002/01/23 10:47:59 mohor
// Initial version. Equals to eth_wishbonedma.v at this moment.
//
//
//
//
 
// Build pause frame
// Check GotData and evaluate data (abort or something like that comes before StartFrm)
// m_wb_err_i should start status underrun or uverrun
// r_RecSmall not used
 
`include "eth_defines.v"
`include "timescale.v"
 
 
module eth_wishbone
(
 
// WISHBONE common
WB_CLK_I, WB_DAT_I, WB_DAT_O,
 
// WISHBONE slave
WB_ADR_I, WB_WE_I, WB_ACK_O,
BDCs,
 
Reset,
 
// WISHBONE master
m_wb_adr_o, m_wb_sel_o, m_wb_we_o,
m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o,
m_wb_stb_o, m_wb_ack_i, m_wb_err_i,
 
//TX
MTxClk, TxStartFrm, TxEndFrm, TxUsedData, TxData,
TxRetry, TxAbort, TxUnderRun, TxDone, TPauseRq, TxPauseTV, PerPacketCrcEn,
PerPacketPad,
 
//RX
MRxClk, RxData, RxValid, RxStartFrm, RxEndFrm, RxAbort,
// Register
r_TxEn, r_RxEn, r_TxBDNum, TX_BD_NUM_Wr, r_RecSmall,
 
WillSendControlFrame, TxCtrlEndFrm, // WillSendControlFrame out ?
// Interrupts
TxB_IRQ, TxE_IRQ, RxB_IRQ, RxE_IRQ, Busy_IRQ, TxC_IRQ, RxC_IRQ,
// Rx Status
InvalidSymbol, LatchedCrcError, RxLateCollision, ShortFrame, DribbleNibble,
ReceivedPacketTooBig, RxLength, LoadRxStatus, ReceivedPacketGood,
// Tx Status
RetryCntLatched, RetryLimit, LateCollLatched, DeferLatched, CarrierSenseLost
);
 
 
parameter Tp = 1;
 
// WISHBONE common
input WB_CLK_I; // WISHBONE clock
input [31:0] WB_DAT_I; // WISHBONE data input
output [31:0] WB_DAT_O; // WISHBONE data output
 
// WISHBONE slave
input [9:2] WB_ADR_I; // WISHBONE address input
input WB_WE_I; // WISHBONE write enable input
input BDCs; // Buffer descriptors are selected
output WB_ACK_O; // WISHBONE acknowledge output
 
// WISHBONE master
output [31:0] m_wb_adr_o; //
output [3:0] m_wb_sel_o; //
output m_wb_we_o; //
output [31:0] m_wb_dat_o; //
output m_wb_cyc_o; //
output m_wb_stb_o; //
input [31:0] m_wb_dat_i; //
input m_wb_ack_i; //
input m_wb_err_i; //
 
input Reset; // Reset signal
 
// Rx Status signals
input InvalidSymbol; // Invalid symbol was received during reception in 100 Mbps mode
input LatchedCrcError; // CRC error
input RxLateCollision; // Late collision occured while receiving frame
input ShortFrame; // Frame shorter then the minimum size (r_MinFL) was received while small packets are enabled (r_RecSmall)
input DribbleNibble; // Extra nibble received
input ReceivedPacketTooBig;// Received packet is bigger than r_MaxFL
input [15:0] RxLength; // Length of the incoming frame
input LoadRxStatus; // Rx status was loaded
input ReceivedPacketGood;// Received packet's length and CRC are good
 
// Tx Status signals
input [3:0] RetryCntLatched; // Latched Retry Counter
input RetryLimit; // Retry limit reached (Retry Max value + 1 attempts were made)
input LateCollLatched; // Late collision occured
input DeferLatched; // Defer indication (Frame was defered before sucessfully sent)
input CarrierSenseLost; // Carrier Sense was lost during the frame transmission
 
// Tx
input MTxClk; // Transmit clock (from PHY)
input TxUsedData; // Transmit packet used data
input TxRetry; // Transmit packet retry
input TxAbort; // Transmit packet abort
input TxDone; // Transmission ended
output TxStartFrm; // Transmit packet start frame
output TxEndFrm; // Transmit packet end frame
output [7:0] TxData; // Transmit packet data byte
output TxUnderRun; // Transmit packet under-run
output PerPacketCrcEn; // Per packet crc enable
output PerPacketPad; // Per packet pading
output TPauseRq; // Tx PAUSE control frame
output [15:0] TxPauseTV; // PAUSE timer value
input WillSendControlFrame;
input TxCtrlEndFrm;
 
// Rx
input MRxClk; // Receive clock (from PHY)
input [7:0] RxData; // Received data byte (from PHY)
input RxValid; //
input RxStartFrm; //
input RxEndFrm; //
input RxAbort; // This signal is set when address doesn't match.
 
//Register
input r_TxEn; // Transmit enable
input r_RxEn; // Receive enable
input [7:0] r_TxBDNum; // Receive buffer descriptor number
input TX_BD_NUM_Wr; // RxBDNumber written
input r_RecSmall; // Receive small frames igor !!! tega uporabi
 
// Interrupts
output TxB_IRQ;
output TxE_IRQ;
output RxB_IRQ;
output RxE_IRQ;
output Busy_IRQ;
output TxC_IRQ;
output RxC_IRQ;
 
 
reg TxB_IRQ;
reg TxE_IRQ;
reg RxB_IRQ;
reg RxE_IRQ;
 
 
reg TxStartFrm;
reg TxEndFrm;
reg [7:0] TxData;
 
reg TxUnderRun;
reg TxUnderRun_wb;
 
reg TxBDRead;
wire TxStatusWrite;
 
reg [1:0] TxValidBytesLatched;
 
reg [15:0] TxLength;
reg [15:0] LatchedTxLength;
reg [14:11] TxStatus;
 
reg [14:13] RxStatus;
 
reg TxStartFrm_wb;
reg TxRetry_wb;
reg TxAbort_wb;
reg TxDone_wb;
 
reg TxDone_wb_q;
reg TxAbort_wb_q;
reg TxRetry_wb_q;
reg TxDone_wb_q2;
reg TxAbort_wb_q2;
reg TxRetry_wb_q2;
reg RxBDReady;
reg TxBDReady;
 
reg RxBDRead;
wire RxStatusWrite;
 
reg [31:0] TxDataLatched;
reg [1:0] TxByteCnt;
reg LastWord;
reg ReadTxDataFromFifo_tck;
 
reg BlockingTxStatusWrite;
reg BlockingTxBDRead;
 
reg Flop;
 
reg [7:0] TxBDAddress;
reg [7:0] RxBDAddress;
 
reg TxRetrySync1;
reg TxAbortSync1;
reg TxDoneSync1;
 
reg TxAbort_q;
reg TxRetry_q;
reg TxUsedData_q;
 
reg [31:0] RxDataLatched2;
 
// reg [23:0] RxDataLatched1;
reg [31:8] RxDataLatched1; // Big Endian Byte Ordering
 
reg [1:0] RxValidBytes;
reg [1:0] RxByteCnt;
reg LastByteIn;
reg ShiftWillEnd;
 
reg WriteRxDataToFifo;
reg [15:0] LatchedRxLength;
reg RxAbortLatched;
 
reg ShiftEnded;
reg RxOverrun;
 
reg BDWrite; // BD Write Enable for access from WISHBONE side
reg BDRead; // BD Read access from WISHBONE side
wire [31:0] RxBDDataIn; // Rx BD data in
wire [31:0] TxBDDataIn; // Tx BD data in
 
reg TxEndFrm_wb;
 
wire TxRetryPulse;
wire TxDonePulse;
wire TxAbortPulse;
wire TxRetryPulse_q;
wire TxDonePulse_q;
wire TxAbortPulse_q;
 
wire StartRxBDRead;
 
wire StartTxBDRead;
 
wire TxIRQEn;
wire WrapTxStatusBit;
 
wire RxIRQEn;
wire WrapRxStatusBit;
 
wire [1:0] TxValidBytes;
 
wire [7:0] TempTxBDAddress;
wire [7:0] TempRxBDAddress;
 
wire SetGotData;
wire GotDataEvaluate;
 
reg WB_ACK_O;
 
wire [6:0] RxStatusIn;
reg [6:0] RxStatusInLatched;
 
reg WbEn, WbEn_q;
reg RxEn, RxEn_q;
reg TxEn, TxEn_q;
 
wire ram_ce;
wire ram_we;
wire ram_oe;
reg [7:0] ram_addr;
reg [31:0] ram_di;
wire [31:0] ram_do;
 
wire StartTxPointerRead;
reg TxPointerRead;
reg TxEn_needed;
reg RxEn_needed;
 
wire StartRxPointerRead;
reg RxPointerRead;
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
begin
WB_ACK_O <=#Tp 1'b0;
end
else
begin
WB_ACK_O <=#Tp BDWrite & WbEn & WbEn_q | BDRead & WbEn & ~WbEn_q;
end
end
 
assign WB_DAT_O = ram_do;
 
// Generic synchronous single-port RAM interface
eth_spram_256x32 bd_ram (
// Generic synchronous single-port RAM interface
.clk(WB_CLK_I), .rst(Reset), .ce(ram_ce), .we(ram_we), .oe(ram_oe), .addr(ram_addr), .di(ram_di), .do(ram_do)
);
 
assign ram_ce = 1'b1;
assign ram_we = BDWrite & WbEn & WbEn_q | TxStatusWrite | RxStatusWrite;
assign ram_oe = BDRead & WbEn & WbEn_q | TxEn & TxEn_q & (TxBDRead | TxPointerRead) | RxEn & RxEn_q & (RxBDRead | RxPointerRead);
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxEn_needed <=#Tp 1'b0;
else
if(~TxBDReady & r_TxEn & WbEn & ~WbEn_q)
TxEn_needed <=#Tp 1'b1;
else
if(TxPointerRead & TxEn & TxEn_q)
TxEn_needed <=#Tp 1'b0;
end
 
// Enabling access to the RAM for three devices.
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
begin
WbEn <=#Tp 1'b1;
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b0;
ram_addr <=#Tp 8'h0;
ram_di <=#Tp 32'h0;
BDRead <=#Tp 1'b0;
BDWrite <=#Tp 1'b0;
end
else
begin
// Switching between three stages depends on enable signals
case ({WbEn_q, RxEn_q, TxEn_q, RxEn_needed, TxEn_needed}) // synopsys parallel_case
5'b100_10, 5'b100_11 :
begin
WbEn <=#Tp 1'b0;
RxEn <=#Tp 1'b1; // wb access stage and r_RxEn is enabled
TxEn <=#Tp 1'b0;
ram_addr <=#Tp RxBDAddress + RxPointerRead;
ram_di <=#Tp RxBDDataIn;
end
5'b100_01 :
begin
WbEn <=#Tp 1'b0;
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b1; // wb access stage, r_RxEn is disabled but r_TxEn is enabled
ram_addr <=#Tp TxBDAddress + TxPointerRead;
ram_di <=#Tp TxBDDataIn;
end
5'b010_00, 5'b010_10 :
begin
WbEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is disabled
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b0;
ram_addr <=#Tp WB_ADR_I[9:2];
ram_di <=#Tp WB_DAT_I;
BDWrite <=#Tp BDCs & WB_WE_I;
BDRead <=#Tp BDCs & ~WB_WE_I;
end
5'b010_01, 5'b010_11 :
begin
WbEn <=#Tp 1'b0;
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b1; // RxEn access stage and r_TxEn is enabled
ram_addr <=#Tp TxBDAddress + TxPointerRead;
ram_di <=#Tp TxBDDataIn;
end
5'b001_00, 5'b001_01, 5'b001_10, 5'b001_11 :
begin
WbEn <=#Tp 1'b1; // TxEn access stage (we always go to wb access stage)
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b0;
ram_addr <=#Tp WB_ADR_I[9:2];
ram_di <=#Tp WB_DAT_I;
BDWrite <=#Tp BDCs & WB_WE_I;
BDRead <=#Tp BDCs & ~WB_WE_I;
end
5'b100_00 :
begin
WbEn <=#Tp 1'b0; // WbEn access stage and there is no need for other stages. WbEn needs to be switched off for a bit
end
5'b000_00 :
begin
WbEn <=#Tp 1'b1; // Idle state. We go to WbEn access stage.
RxEn <=#Tp 1'b0;
TxEn <=#Tp 1'b0;
ram_addr <=#Tp WB_ADR_I[9:2];
ram_di <=#Tp WB_DAT_I;
BDWrite <=#Tp BDCs & WB_WE_I;
BDRead <=#Tp BDCs & ~WB_WE_I;
end
endcase
end
end
 
 
// Delayed stage signals
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
begin
WbEn_q <=#Tp 1'b0;
RxEn_q <=#Tp 1'b0;
TxEn_q <=#Tp 1'b0;
end
else
begin
WbEn_q <=#Tp WbEn;
RxEn_q <=#Tp RxEn;
TxEn_q <=#Tp TxEn;
end
end
 
// Changes for tx occur every second clock. Flop is used for this manner.
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
Flop <=#Tp 1'b0;
else
if(TxDone | TxAbort | TxRetry_q)
Flop <=#Tp 1'b0;
else
if(TxUsedData)
Flop <=#Tp ~Flop;
end
 
wire ResetTxBDReady;
assign ResetTxBDReady = TxDonePulse | TxAbortPulse | TxRetryPulse;
 
// Latching READY status of the Tx buffer descriptor
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxBDReady <=#Tp 1'b0;
else
if(TxEn & TxEn_q & TxBDRead)
TxBDReady <=#Tp ram_do[15] & (ram_do[31:16] > 4); // TxBDReady is sampled only once at the beginning.
else // Only packets larger then 4 bytes are transmitted.
if(ResetTxBDReady)
TxBDReady <=#Tp 1'b0;
end
 
 
// Reading the Tx buffer descriptor
assign StartTxBDRead = (TxRetry_wb | TxStatusWrite) & ~BlockingTxBDRead & ~TxBDReady;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxBDRead <=#Tp 1'b1;
else
if(StartTxBDRead)
TxBDRead <=#Tp 1'b1;
else
if(TxBDReady)
TxBDRead <=#Tp 1'b0;
end
 
 
// Reading Tx BD pointer
assign StartTxPointerRead = TxBDRead & TxBDReady;
 
// Reading Tx BD Pointer
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxPointerRead <=#Tp 1'b0;
else
if(StartTxPointerRead)
TxPointerRead <=#Tp 1'b1;
else
if(TxEn_q)
TxPointerRead <=#Tp 1'b0;
end
 
 
// Writing status back to the Tx buffer descriptor
assign TxStatusWrite = (TxDone_wb | TxAbort_wb) & TxEn & TxEn_q & ~BlockingTxStatusWrite;
 
 
 
// Status writing must occur only once. Meanwhile it is blocked.
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
BlockingTxStatusWrite <=#Tp 1'b0;
else
if(TxStatusWrite)
BlockingTxStatusWrite <=#Tp 1'b1;
else
if(~TxDone_wb & ~TxAbort_wb)
BlockingTxStatusWrite <=#Tp 1'b0;
end
 
 
// TxBDRead state is activated only once.
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
BlockingTxBDRead <=#Tp 1'b0;
else
if(StartTxBDRead)
BlockingTxBDRead <=#Tp 1'b1;
else
if(~StartTxBDRead & ~TxBDReady)
BlockingTxBDRead <=#Tp 1'b0;
end
 
 
// Latching status from the tx buffer descriptor
// Data is avaliable one cycle after the access is started (at that time signal TxEn is not active)
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxStatus <=#Tp 4'h0;
else
if(TxEn & TxEn_q & TxBDRead)
TxStatus <=#Tp ram_do[14:11];
end
 
reg ReadTxDataFromMemory;
wire WriteRxDataToMemory;
 
reg MasterWbTX;
reg MasterWbRX;
 
reg [31:0] m_wb_adr_o;
reg m_wb_cyc_o;
reg m_wb_stb_o;
reg [3:0] m_wb_sel_o;
reg m_wb_we_o;
 
wire TxLengthEq0;
wire TxLengthLt4;
 
wire WordAccFinished;
wire HalfAccFinished;
 
//Latching length from the buffer descriptor;
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxLength <=#Tp 16'h0;
else
if(TxEn & TxEn_q & TxBDRead)
TxLength <=#Tp ram_do[31:16];
else
if(MasterWbTX & m_wb_ack_i)
begin
if(TxLengthLt4)
TxLength <=#Tp 16'h0;
else if(WordAccFinished)
TxLength <=#Tp TxLength - 3'h4; // Length is subtracted at the data request
else if(HalfAccFinished)
TxLength <=#Tp TxLength - 2'h2; // Length is subtracted at the data request
else
TxLength <=#Tp TxLength - 1'h1; // Length is subtracted at the data request
end
end
 
assign WordAccFinished = &m_wb_sel_o[3:0];
assign HalfAccFinished = &m_wb_sel_o[1:0];
 
 
 
//Latching length from the buffer descriptor;
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
LatchedTxLength <=#Tp 16'h0;
else
if(TxEn & TxEn_q & TxBDRead)
LatchedTxLength <=#Tp ram_do[31:16];
end
 
assign TxLengthEq0 = TxLength == 0;
assign TxLengthLt4 = TxLength < 4;
 
 
reg BlockingIncrementTxPointer;
 
reg [31:0] TxPointer;
reg [1:0] TxPointerLatched;
reg [31:0] RxPointer;
reg [1:0] RxPointerLatched;
 
wire TxBurstAcc;
wire TxWordAcc;
wire TxHalfAcc;
wire TxByteAcc;
 
wire RxBurstAcc;
wire RxWordAcc;
wire RxHalfAcc;
wire RxByteAcc;
 
 
//Latching Tx buffer pointer from buffer descriptor;
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxPointer <=#Tp 0;
else
if(TxEn & TxEn_q & TxPointerRead)
TxPointer <=#Tp ram_do;
else
if(MasterWbTX & ~BlockingIncrementTxPointer)
if(TxWordAcc)
TxPointer <=#Tp TxPointer + 3'h4; // Word access
else if(TxHalfAcc)
TxPointer <=#Tp TxPointer + 2'h2; // Half access
else
TxPointer <=#Tp TxPointer + 1'h1; // Byte access
end
 
 
 
//Latching last addresses from buffer descriptor (used as byte-half-word indicator);
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxPointerLatched[1:0] <=#Tp 0;
else
if(TxEn & TxEn_q & TxPointerRead)
TxPointerLatched[1:0] <=#Tp ram_do[1:0];
end
 
 
assign TxBurstAcc = ~TxPointer[3] & ~TxPointer[2] & ~TxPointer[1] & ~TxPointer[0]; // Add a counter that count burst to 4
assign TxWordAcc = ~TxPointer[1] & ~TxPointer[0];
assign TxHalfAcc = TxPointer[1] & ~TxPointer[0];
assign TxByteAcc = TxPointer[0];
 
wire [3:0] m_wb_sel_tmp_tx;
reg [3:0] m_wb_sel_tmp_rx;
 
 
assign m_wb_sel_tmp_tx[0] = TxWordAcc | TxHalfAcc | TxByteAcc & TxPointer[1];
assign m_wb_sel_tmp_tx[1] = TxWordAcc | TxHalfAcc;
assign m_wb_sel_tmp_tx[2] = TxWordAcc | TxByteAcc & ~TxPointer[1];
assign m_wb_sel_tmp_tx[3] = TxWordAcc;
 
 
wire MasterAccessFinished;
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
BlockingIncrementTxPointer <=#Tp 0;
else
if(MasterAccessFinished)
BlockingIncrementTxPointer <=#Tp 0;
else
if(MasterWbTX)
BlockingIncrementTxPointer <=#Tp 1'b1;
end
 
 
wire TxBufferAlmostFull;
wire TxBufferFull;
wire TxBufferEmpty;
wire TxBufferAlmostEmpty;
wire ResetReadTxDataFromMemory;
wire SetReadTxDataFromMemory;
 
reg BlockReadTxDataFromMemory;
 
assign ResetReadTxDataFromMemory = (TxLengthEq0) | TxAbortPulse_q | TxRetryPulse_q;
assign SetReadTxDataFromMemory = TxEn & TxEn_q & TxPointerRead;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ReadTxDataFromMemory <=#Tp 1'b0;
else
if(ResetReadTxDataFromMemory)
ReadTxDataFromMemory <=#Tp 1'b0;
else
if(SetReadTxDataFromMemory)
ReadTxDataFromMemory <=#Tp 1'b1;
end
 
wire ReadTxDataFromMemory_2 = ReadTxDataFromMemory & ~BlockReadTxDataFromMemory;
wire [31:0] TxData_wb;
wire ReadTxDataFromFifo_wb;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
BlockReadTxDataFromMemory <=#Tp 1'b0;
else
if(ReadTxDataFromFifo_wb | ResetReadTxDataFromMemory)
BlockReadTxDataFromMemory <=#Tp 1'b0;
else
if((TxBufferAlmostFull | TxLength <= 4)& MasterWbTX)
BlockReadTxDataFromMemory <=#Tp 1'b1;
end
 
 
 
assign MasterAccessFinished = m_wb_ack_i | m_wb_err_i;
reg cyc_cleared;
 
// Enabling master wishbone access to the memory for two devices TX and RX.
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
begin
MasterWbTX <=#Tp 1'b0;
MasterWbRX <=#Tp 1'b0;
m_wb_adr_o <=#Tp 32'h0;
m_wb_cyc_o <=#Tp 1'b0;
m_wb_stb_o <=#Tp 1'b0;
m_wb_we_o <=#Tp 1'b0;
m_wb_sel_o <=#Tp 4'h0;
cyc_cleared<=#Tp 1'b0;
end
else
begin
// Switching between two stages depends on enable signals
casex ({MasterWbTX, MasterWbRX, ReadTxDataFromMemory_2, WriteRxDataToMemory, MasterAccessFinished, cyc_cleared}) // synopsys parallel_case
6'b00_01_0_x, 6'b00_11_0_x :
begin
MasterWbTX <=#Tp 1'b0; // idle and master write is needed (data write to rx buffer)
MasterWbRX <=#Tp 1'b1;
m_wb_adr_o <=#Tp RxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b1;
m_wb_sel_o <=#Tp m_wb_sel_tmp_rx;
end
6'b00_10_0_x, 6'b00_10_1_x :
begin
MasterWbTX <=#Tp 1'b1; // idle and master read is needed (data read from tx buffer)
MasterWbRX <=#Tp 1'b0;
m_wb_adr_o <=#Tp TxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b0;
m_wb_sel_o <=#Tp m_wb_sel_tmp_tx;
end
6'b10_10_0_1 :
begin
MasterWbTX <=#Tp 1'b1; // master read and master read is needed (data read from tx buffer)
MasterWbRX <=#Tp 1'b0;
m_wb_adr_o <=#Tp TxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b0;
m_wb_sel_o <=#Tp m_wb_sel_tmp_tx;
cyc_cleared<=#Tp 1'b0;
end
6'b01_01_0_1 :
begin
MasterWbTX <=#Tp 1'b0; // master write and master write is needed (data write to rx buffer)
MasterWbRX <=#Tp 1'b1;
m_wb_adr_o <=#Tp RxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b1;
m_wb_sel_o <=#Tp m_wb_sel_tmp_rx;
cyc_cleared<=#Tp 1'b0;
end
6'b10_01_0_1, 6'b10_11_0_1 :
begin
MasterWbTX <=#Tp 1'b0; // master read and master write is needed (data write to rx buffer)
MasterWbRX <=#Tp 1'b1;
m_wb_adr_o <=#Tp RxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b1;
m_wb_sel_o <=#Tp m_wb_sel_tmp_rx;
cyc_cleared<=#Tp 1'b0;
end
6'b01_10_0_1, 6'b01_11_0_1 :
begin
MasterWbTX <=#Tp 1'b1; // master write and master read is needed (data read from tx buffer)
MasterWbRX <=#Tp 1'b0;
m_wb_adr_o <=#Tp TxPointer;
m_wb_cyc_o <=#Tp 1'b1;
m_wb_stb_o <=#Tp 1'b1;
m_wb_we_o <=#Tp 1'b0;
m_wb_sel_o <=#Tp m_wb_sel_tmp_tx;
cyc_cleared<=#Tp 1'b0;
end
6'b10_10_1_0, 6'b01_01_1_0, 6'b10_01_1_0, 6'b10_11_1_0, 6'b01_10_1_0, 6'b01_11_1_0 :
begin
m_wb_cyc_o <=#Tp 1'b0; // whatever and master read or write is needed. We need to clear m_wb_cyc_o before next access is started
m_wb_stb_o <=#Tp 1'b0;
cyc_cleared<=#Tp 1'b1;
end
6'b10_00_1_x, 6'b01_00_1_x :
begin
MasterWbTX <=#Tp 1'b0; // whatever and no master read or write is needed (ack or err comes finishing previous access)
MasterWbRX <=#Tp 1'b0;
m_wb_cyc_o <=#Tp 1'b0;
m_wb_stb_o <=#Tp 1'b0;
end
6'b10_00_0_1, 6'b01_00_0_1 :
begin
MasterWbTX <=#Tp 1'b0; // Between cyc_cleared request was cleared
MasterWbRX <=#Tp 1'b0;
m_wb_cyc_o <=#Tp 1'b0;
m_wb_stb_o <=#Tp 1'b0;
end
default: // Don't touch
begin
MasterWbTX <=#Tp MasterWbTX;
MasterWbRX <=#Tp MasterWbRX;
m_wb_cyc_o <=#Tp m_wb_cyc_o;
m_wb_stb_o <=#Tp m_wb_stb_o;
m_wb_sel_o <=#Tp m_wb_sel_o;
end
endcase
end
end
 
 
 
wire TxFifoClear;
wire [31:0] tx_fifo_dat_i;
 
assign TxFifoClear = (TxAbort_wb | TxRetry_wb) & ~TxBDReady;
 
reg [23:16] LatchedData;
wire [23:16] TempData;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
LatchedData[23:16] <=#Tp 0;
else
if(MasterWbTX & m_wb_ack_i & m_wb_sel_o[2])
LatchedData[23:16] <=#Tp m_wb_dat_i[23:16];
end
 
assign TempData[23:16] = m_wb_sel_o[2]? m_wb_dat_i[23:16] : LatchedData[23:16];
 
assign tx_fifo_dat_i[31:0] = {m_wb_dat_i[31:24], TempData[23:16], m_wb_dat_i[15:8], m_wb_dat_i[7:0]};
 
 
eth_fifo #(`TX_FIFO_DATA_WIDTH, `TX_FIFO_DEPTH, `TX_FIFO_CNT_WIDTH)
tx_fifo ( .data_in(tx_fifo_dat_i), .data_out(TxData_wb),
.clk(WB_CLK_I), .reset(Reset),
.write(MasterWbTX & m_wb_ack_i & m_wb_sel_o[0]), .read(ReadTxDataFromFifo_wb),
.clear(TxFifoClear), .full(TxBufferFull),
.almost_full(TxBufferAlmostFull), .almost_empty(TxBufferAlmostEmpty),
.empty(TxBufferEmpty), .cnt()
);
 
 
reg StartOccured;
reg TxStartFrm_sync1;
reg TxStartFrm_sync2;
reg TxStartFrm_syncb1;
reg TxStartFrm_syncb2;
 
 
 
// Start: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxStartFrm_wb <=#Tp 1'b0;
else
if(TxBDReady & ~StartOccured & (TxBufferFull | TxLengthEq0))
TxStartFrm_wb <=#Tp 1'b1;
else
if(TxStartFrm_syncb2)
TxStartFrm_wb <=#Tp 1'b0;
end
 
// StartOccured: TxStartFrm_wb occurs only ones at the beginning. Then it's blocked.
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
StartOccured <=#Tp 1'b0;
else
if(TxStartFrm_wb)
StartOccured <=#Tp 1'b1;
else
if(ResetTxBDReady)
StartOccured <=#Tp 1'b0;
end
 
// Synchronizing TxStartFrm_wb to MTxClk
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxStartFrm_sync1 <=#Tp 1'b0;
else
TxStartFrm_sync1 <=#Tp TxStartFrm_wb;
end
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxStartFrm_sync2 <=#Tp 1'b0;
else
TxStartFrm_sync2 <=#Tp TxStartFrm_sync1;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxStartFrm_syncb1 <=#Tp 1'b0;
else
TxStartFrm_syncb1 <=#Tp TxStartFrm_sync2;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxStartFrm_syncb2 <=#Tp 1'b0;
else
TxStartFrm_syncb2 <=#Tp TxStartFrm_syncb1;
end
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxStartFrm <=#Tp 1'b0;
else
if(TxStartFrm_sync2)
TxStartFrm <=#Tp 1'b1;
else
if(TxUsedData_q | ~TxStartFrm_sync2 & (TxRetry | TxAbort))
TxStartFrm <=#Tp 1'b0;
end
// End: Generation of the TxStartFrm_wb which is then synchronized to the MTxClk
 
 
// TxEndFrm_wb: indicator of the end of frame
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxEndFrm_wb <=#Tp 1'b0;
else
if(TxLengthLt4 & TxBufferAlmostEmpty & TxUsedData)
TxEndFrm_wb <=#Tp 1'b1;
else
if(TxRetryPulse | TxDonePulse | TxAbortPulse)
TxEndFrm_wb <=#Tp 1'b0;
end
 
 
// Marks which bytes are valid within the word.
assign TxValidBytes = TxLengthLt4 ? TxLength[1:0] : 2'b0;
 
reg LatchValidBytes;
reg LatchValidBytes_q;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
LatchValidBytes <=#Tp 1'b0;
else
if(TxLengthLt4 & TxBDReady)
LatchValidBytes <=#Tp 1'b1;
else
LatchValidBytes <=#Tp 1'b0;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
LatchValidBytes_q <=#Tp 1'b0;
else
LatchValidBytes_q <=#Tp LatchValidBytes;
end
 
 
// Latching valid bytes
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxValidBytesLatched <=#Tp 2'h0;
else
if(LatchValidBytes & ~LatchValidBytes_q)
TxValidBytesLatched <=#Tp TxValidBytes;
else
if(TxRetryPulse | TxDonePulse | TxAbortPulse)
TxValidBytesLatched <=#Tp 2'h0;
end
 
 
assign TxIRQEn = TxStatus[14];
assign WrapTxStatusBit = TxStatus[13];
assign PerPacketPad = TxStatus[12];
assign PerPacketCrcEn = TxStatus[11];
 
 
assign RxIRQEn = RxStatus[14];
assign WrapRxStatusBit = RxStatus[13];
 
 
// Temporary Tx and Rx buffer descriptor address
assign TempTxBDAddress[7:0] = {8{ TxStatusWrite & ~WrapTxStatusBit}} & (TxBDAddress + 2'h2) ; // Tx BD increment or wrap (last BD)
assign TempRxBDAddress[7:0] = {8{ WrapRxStatusBit}} & (r_TxBDNum) | // Using first Rx BD
{8{~WrapRxStatusBit}} & (RxBDAddress + 2'h2) ; // Using next Rx BD (incremenrement address)
 
 
// Latching Tx buffer descriptor address
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxBDAddress <=#Tp 8'h0;
else
if(TxStatusWrite)
TxBDAddress <=#Tp TempTxBDAddress;
end
 
 
// Latching Rx buffer descriptor address
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxBDAddress <=#Tp `ETH_TX_BD_NUM_DEF;
else
if(TX_BD_NUM_Wr) // When r_TxBDNum is updated, RxBDAddress is also
RxBDAddress <=#Tp WB_DAT_I[7:0];
else
if(RxStatusWrite)
RxBDAddress <=#Tp TempRxBDAddress;
end
 
wire [8:0] TxStatusInLatched = {TxUnderRun, RetryCntLatched[3:0], RetryLimit, LateCollLatched, DeferLatched, CarrierSenseLost};
 
assign RxBDDataIn = {LatchedRxLength, 1'b0, RxStatus, 6'h0, RxStatusInLatched};
assign TxBDDataIn = {LatchedTxLength, 1'b0, TxStatus, 2'h0, TxStatusInLatched};
 
 
// Signals used for various purposes
assign TxRetryPulse = TxRetry_wb & ~TxRetry_wb_q;
assign TxDonePulse = TxDone_wb & ~TxDone_wb_q;
assign TxAbortPulse = TxAbort_wb & ~TxAbort_wb_q;
assign TxRetryPulse_q = TxRetry_wb_q & ~TxRetry_wb_q2;
assign TxDonePulse_q = TxDone_wb_q & ~TxDone_wb_q2;
assign TxAbortPulse_q = TxAbort_wb_q & ~TxAbort_wb_q2;
 
 
assign TPauseRq = 0;
assign TxPauseTV[15:0] = TxLength[15:0];
 
 
// Generating delayed signals
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
begin
TxAbort_q <=#Tp 1'b0;
TxRetry_q <=#Tp 1'b0;
TxUsedData_q <=#Tp 1'b0;
end
else
begin
TxAbort_q <=#Tp TxAbort;
TxRetry_q <=#Tp TxRetry;
TxUsedData_q <=#Tp TxUsedData;
end
end
 
// Generating delayed signals
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
begin
TxDone_wb_q <=#Tp 1'b0;
TxAbort_wb_q <=#Tp 1'b0;
TxRetry_wb_q <=#Tp 1'b0;
TxDone_wb_q2 <=#Tp 1'b0;
TxAbort_wb_q2 <=#Tp 1'b0;
TxRetry_wb_q2 <=#Tp 1'b0;
end
else
begin
TxDone_wb_q <=#Tp TxDone_wb;
TxAbort_wb_q <=#Tp TxAbort_wb;
TxRetry_wb_q <=#Tp TxRetry_wb;
TxDone_wb_q2 <=#Tp TxDone_wb_q;
TxAbort_wb_q2 <=#Tp TxAbort_wb_q;
TxRetry_wb_q2 <=#Tp TxRetry_wb_q;
end
end
 
 
// Sinchronizing and evaluating tx data
//assign SetGotData = (TxStartFrm_wb | NewTxDataAvaliable_wb & ~TxAbort_wb & ~TxRetry_wb) & ~WB_CLK_I;
assign SetGotData = (TxStartFrm_wb); // igor namesto zgornje
 
// Evaluating data. If abort or retry occured meanwhile than data is ignored.
//assign GotDataEvaluate = GotDataSync3 & ~GotData & (~TxRetry & ~TxAbort | (TxRetry | TxAbort) & (TxStartFrm));
assign GotDataEvaluate = (~TxRetry & ~TxAbort | (TxRetry | TxAbort) & (TxStartFrm));
 
 
// Indication of the last word
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
LastWord <=#Tp 1'b0;
else
if((TxEndFrm | TxAbort | TxRetry) & Flop)
LastWord <=#Tp 1'b0;
else
if(TxUsedData & Flop & TxByteCnt == 2'h3)
LastWord <=#Tp TxEndFrm_wb;
end
 
 
// Tx end frame generation
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxEndFrm <=#Tp 1'b0;
else
if(Flop & TxEndFrm | TxAbort | TxRetry_q)
TxEndFrm <=#Tp 1'b0;
else
if(Flop & LastWord)
begin
case (TxValidBytesLatched) // synopsys parallel_case
1 : TxEndFrm <=#Tp TxByteCnt == 2'h0;
2 : TxEndFrm <=#Tp TxByteCnt == 2'h1;
3 : TxEndFrm <=#Tp TxByteCnt == 2'h2;
0 : TxEndFrm <=#Tp TxByteCnt == 2'h3;
default : TxEndFrm <=#Tp 1'b0;
endcase
end
end
 
 
// Tx data selection (latching)
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxData <=#Tp 0;
else
if(TxStartFrm_sync2 & ~TxStartFrm)
case(TxPointerLatched) // synopsys parallel_case
2'h0 : TxData <=#Tp TxData_wb[31:24]; // Big Endian Byte Ordering
2'h1 : TxData <=#Tp TxData_wb[23:16]; // Big Endian Byte Ordering
2'h2 : TxData <=#Tp TxData_wb[15:08]; // Big Endian Byte Ordering
2'h3 : TxData <=#Tp TxData_wb[07:00]; // Big Endian Byte Ordering
endcase
else
if(TxStartFrm & TxUsedData & TxPointerLatched==2'h3)
TxData <=#Tp TxData_wb[31:24]; // Big Endian Byte Ordering
else
if(TxUsedData & Flop)
begin
case(TxByteCnt) // synopsys parallel_case
0 : TxData <=#Tp TxDataLatched[31:24]; // Big Endian Byte Ordering
1 : TxData <=#Tp TxDataLatched[23:16];
2 : TxData <=#Tp TxDataLatched[15:8];
3 : TxData <=#Tp TxDataLatched[7:0];
endcase
end
end
 
 
// Latching tx data
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxDataLatched[31:0] <=#Tp 32'h0;
else
if(TxStartFrm_sync2 & ~TxStartFrm | TxUsedData & Flop & TxByteCnt == 2'h3 | TxStartFrm & TxUsedData & Flop & TxByteCnt == 2'h0)
TxDataLatched[31:0] <=#Tp TxData_wb[31:0];
end
 
 
// Tx under run
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxUnderRun_wb <=#Tp 1'b0;
else
if(TxAbortPulse)
TxUnderRun_wb <=#Tp 1'b0;
else
if(TxBufferEmpty & ReadTxDataFromFifo_wb)
TxUnderRun_wb <=#Tp 1'b1;
end
 
 
// Tx under run
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxUnderRun <=#Tp 1'b0;
else
if(TxUnderRun_wb)
TxUnderRun <=#Tp 1'b1;
else
if(BlockingTxStatusWrite)
TxUnderRun <=#Tp 1'b0;
end
 
 
// Tx Byte counter
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxByteCnt <=#Tp 2'h0;
else
if(TxAbort_q | TxRetry_q)
TxByteCnt <=#Tp 2'h0;
else
if(TxStartFrm & ~TxUsedData)
case(TxPointerLatched) // synopsys parallel_case
2'h0 : TxByteCnt <=#Tp 2'h1;
2'h1 : TxByteCnt <=#Tp 2'h2;
2'h2 : TxByteCnt <=#Tp 2'h3;
2'h3 : TxByteCnt <=#Tp 2'h0;
endcase
else
if(TxUsedData & Flop)
TxByteCnt <=#Tp TxByteCnt + 1'b1;
end
 
 
// Start: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I
reg ReadTxDataFromFifo_sync1;
reg ReadTxDataFromFifo_sync2;
reg ReadTxDataFromFifo_sync3;
reg ReadTxDataFromFifo_syncb1;
reg ReadTxDataFromFifo_syncb2;
 
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_tck <=#Tp 1'b0;
else
if(ReadTxDataFromFifo_syncb2)
ReadTxDataFromFifo_tck <=#Tp 1'b0;
else
if(TxStartFrm_sync2 & ~TxStartFrm | TxUsedData & Flop & TxByteCnt == 2'h3 & ~LastWord | TxStartFrm & TxUsedData & Flop & TxByteCnt == 2'h0)
ReadTxDataFromFifo_tck <=#Tp 1'b1;
end
 
// Synchronizing TxStartFrm_wb to MTxClk
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_sync1 <=#Tp 1'b0;
else
ReadTxDataFromFifo_sync1 <=#Tp ReadTxDataFromFifo_tck;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_sync2 <=#Tp 1'b0;
else
ReadTxDataFromFifo_sync2 <=#Tp ReadTxDataFromFifo_sync1;
end
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_syncb1 <=#Tp 1'b0;
else
ReadTxDataFromFifo_syncb1 <=#Tp ReadTxDataFromFifo_sync2;
end
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_syncb2 <=#Tp 1'b0;
else
ReadTxDataFromFifo_syncb2 <=#Tp ReadTxDataFromFifo_syncb1;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ReadTxDataFromFifo_sync3 <=#Tp 1'b0;
else
ReadTxDataFromFifo_sync3 <=#Tp ReadTxDataFromFifo_sync2;
end
 
assign ReadTxDataFromFifo_wb = ReadTxDataFromFifo_sync2 & ~ReadTxDataFromFifo_sync3;
// End: Generation of the ReadTxDataFromFifo_tck signal and synchronization to the WB_CLK_I
 
 
// Synchronizing TxRetry signal (synchronized to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxRetrySync1 <=#Tp 1'b0;
else
TxRetrySync1 <=#Tp TxRetry;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxRetry_wb <=#Tp 1'b0;
else
TxRetry_wb <=#Tp TxRetrySync1;
end
 
 
// Synchronized TxDone_wb signal (synchronized to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxDoneSync1 <=#Tp 1'b0;
else
TxDoneSync1 <=#Tp TxDone;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxDone_wb <=#Tp 1'b0;
else
TxDone_wb <=#Tp TxDoneSync1;
end
 
// Synchronizing TxAbort signal (synchronized to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxAbortSync1 <=#Tp 1'b0;
else
TxAbortSync1 <=#Tp TxAbort;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxAbort_wb <=#Tp 1'b0;
else
TxAbort_wb <=#Tp TxAbortSync1;
end
 
 
assign StartRxBDRead = RxStatusWrite | RxAbortLatched;
 
// Reading the Rx buffer descriptor
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxBDRead <=#Tp 1'b1;
else
if(StartRxBDRead & ~RxBDReady)
RxBDRead <=#Tp 1'b1;
else
if(RxBDReady)
RxBDRead <=#Tp 1'b0;
end
 
 
// Reading of the next receive buffer descriptor starts after reception status is
// written to the previous one.
 
// Latching READY status of the Rx buffer descriptor
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxBDReady <=#Tp 1'b0;
else
if(RxEn & RxEn_q & RxBDRead)
RxBDReady <=#Tp ram_do[15]; // RxBDReady is sampled only once at the beginning
else
if(ShiftEnded | RxAbort)
RxBDReady <=#Tp 1'b0;
end
 
// Latching Rx buffer descriptor status
// Data is avaliable one cycle after the access is started (at that time signal RxEn is not active)
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxStatus <=#Tp 2'h0;
else
if(RxEn & RxEn_q & RxBDRead)
RxStatus <=#Tp ram_do[14:13];
end
 
 
 
 
// Reading Rx BD pointer
 
 
assign StartRxPointerRead = RxBDRead & RxBDReady;
 
// Reading Tx BD Pointer
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxPointerRead <=#Tp 1'b0;
else
if(StartRxPointerRead)
RxPointerRead <=#Tp 1'b1;
else
if(RxEn_q)
RxPointerRead <=#Tp 1'b0;
end
 
 
//Latching Rx buffer pointer from buffer descriptor;
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxPointer <=#Tp 32'h0;
else
if(RxEn & RxEn_q & RxPointerRead)
RxPointer <=#Tp {ram_do[31:2], 2'h0};
else
if(MasterWbRX & m_wb_ack_i)
RxPointer <=#Tp RxPointer + 3'h4; // Word access (always word access. m_wb_sel_o are used for selecting bytes)
end
 
 
//Latching last addresses from buffer descriptor (used as byte-half-word indicator);
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxPointerLatched[1:0] <=#Tp 0;
else
if(MasterWbRX & m_wb_ack_i) // After first write all m_wb_sel_tmp_rx are active
RxPointerLatched[1:0] <=#Tp 0;
else
if(RxEn & RxEn_q & RxPointerRead)
RxPointerLatched[1:0] <=#Tp ram_do[1:0];
end
 
 
always @ (RxPointerLatched)
begin
case(RxPointerLatched[1:0]) // synopsys parallel_case
2'h0 : m_wb_sel_tmp_rx[3:0] = 4'hf;
2'h1 : m_wb_sel_tmp_rx[3:0] = 4'h7;
2'h2 : m_wb_sel_tmp_rx[3:0] = 4'h3;
2'h3 : m_wb_sel_tmp_rx[3:0] = 4'h1;
endcase
end
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxEn_needed <=#Tp 1'b0;
else
if(~RxBDReady & r_RxEn & WbEn & ~WbEn_q)
RxEn_needed <=#Tp 1'b1;
else
if(RxPointerRead & RxEn & RxEn_q)
RxEn_needed <=#Tp 1'b0;
end
 
 
// Reception status is written back to the buffer descriptor after the end of frame is detected.
assign RxStatusWrite = ShiftEnded & RxEn & RxEn_q;
 
reg RxStatusWriteLatched;
reg RxStatusWrite_rck;
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxStatusWriteLatched <=#Tp 1'b0;
else
if(RxStatusWrite & ~RxStatusWrite_rck)
RxStatusWriteLatched <=#Tp 1'b1;
else
if(RxStatusWrite_rck)
RxStatusWriteLatched <=#Tp 1'b0;
end
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxStatusWrite_rck <=#Tp 1'b0;
else
if(RxStatusWriteLatched)
RxStatusWrite_rck <=#Tp 1'b1;
else
RxStatusWrite_rck <=#Tp 1'b0;
end
 
 
reg RxEnableWindow;
 
// Indicating that last byte is being reveived
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LastByteIn <=#Tp 1'b0;
else
if(ShiftWillEnd & (&RxByteCnt) | RxAbort)
LastByteIn <=#Tp 1'b0;
else
if(RxValid & RxBDReady & RxEndFrm & ~(&RxByteCnt) & RxEnableWindow)
LastByteIn <=#Tp 1'b1;
end
 
reg ShiftEnded_tck;
reg ShiftEndedSync1;
reg ShiftEndedSync2;
reg ShiftEndedSync3;
reg ShiftEndedSync_c1;
reg ShiftEndedSync_c2;
 
wire StartShiftWillEnd;
//assign StartShiftWillEnd = LastByteIn & (&RxByteCnt) | RxValid & RxEndFrm & (&RxByteCnt) & RxEnableWindow;
assign StartShiftWillEnd = LastByteIn | RxValid & RxEndFrm & (&RxByteCnt) & RxEnableWindow;
 
// Indicating that data reception will end
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ShiftWillEnd <=#Tp 1'b0;
else
if(ShiftEnded_tck | RxAbort)
ShiftWillEnd <=#Tp 1'b0;
else
if(StartShiftWillEnd)
ShiftWillEnd <=#Tp 1'b1;
end
 
 
 
// Receive byte counter
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxByteCnt <=#Tp 2'h0;
else
if(ShiftEnded_tck | RxAbort)
RxByteCnt <=#Tp 2'h0;
else
if(RxValid & RxStartFrm & RxBDReady)
case(RxPointerLatched) // synopsys parallel_case
2'h0 : RxByteCnt <=#Tp 2'h1;
2'h1 : RxByteCnt <=#Tp 2'h2;
2'h2 : RxByteCnt <=#Tp 2'h3;
2'h3 : RxByteCnt <=#Tp 2'h0;
endcase
else
if(RxValid & RxEnableWindow & RxBDReady | LastByteIn)
RxByteCnt <=#Tp RxByteCnt + 1'b1;
end
 
 
// Indicates how many bytes are valid within the last word
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxValidBytes <=#Tp 2'h1;
else
if(RxValid & RxStartFrm)
case(RxPointerLatched) // synopsys parallel_case
2'h0 : RxValidBytes <=#Tp 2'h1;
2'h1 : RxValidBytes <=#Tp 2'h2;
2'h2 : RxValidBytes <=#Tp 2'h3;
2'h3 : RxValidBytes <=#Tp 2'h0;
endcase
else
if(RxValid & ~LastByteIn & ~RxStartFrm & RxEnableWindow)
RxValidBytes <=#Tp RxValidBytes + 1;
end
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxDataLatched1 <=#Tp 24'h0;
else
if(RxValid & RxBDReady & ~LastByteIn)
if(RxStartFrm)
begin
case(RxPointerLatched) // synopsys parallel_case
2'h0: RxDataLatched1[31:24] <=#Tp RxData; // Big Endian Byte Ordering
2'h1: RxDataLatched1[23:16] <=#Tp RxData;
2'h2: RxDataLatched1[15:8] <=#Tp RxData;
2'h3: RxDataLatched1 <=#Tp RxDataLatched1;
endcase
end
else if (RxEnableWindow)
begin
case(RxByteCnt) // synopsys parallel_case
2'h0: RxDataLatched1[31:24] <=#Tp RxData; // Big Endian Byte Ordering
2'h1: RxDataLatched1[23:16] <=#Tp RxData;
2'h2: RxDataLatched1[15:8] <=#Tp RxData;
2'h3: RxDataLatched1 <=#Tp RxDataLatched1;
endcase
end
end
 
wire SetWriteRxDataToFifo;
 
// Assembling data that will be written to the rx_fifo
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxDataLatched2 <=#Tp 32'h0;
else
if(SetWriteRxDataToFifo & ~ShiftWillEnd)
RxDataLatched2 <=#Tp {RxDataLatched1[31:8], RxData}; // Big Endian Byte Ordering
else
if(SetWriteRxDataToFifo & ShiftWillEnd)
case(RxValidBytes) // synopsys parallel_case
// 0 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], RxData}; // Big Endian Byte Ordering
// 1 : RxDataLatched2 <=#Tp {RxDataLatched1[31:24], 24'h0};
// 2 : RxDataLatched2 <=#Tp {RxDataLatched1[31:16], 16'h0};
// 3 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], 8'h0};
0 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], RxData}; // Big Endian Byte Ordering
1 : RxDataLatched2 <=#Tp {RxDataLatched1[31:24], 24'h0};
2 : RxDataLatched2 <=#Tp {RxDataLatched1[31:16], 16'h0};
3 : RxDataLatched2 <=#Tp {RxDataLatched1[31:8], 8'h0};
endcase
end
 
 
reg WriteRxDataToFifoSync1;
reg WriteRxDataToFifoSync2;
 
 
// Indicating start of the reception process
//assign SetWriteRxDataToFifo = (RxValid & RxBDReady & ~RxStartFrm & RxEnableWindow & (&RxByteCnt)) | (ShiftWillEnd & LastByteIn & (&RxByteCnt));
assign SetWriteRxDataToFifo = (RxValid & RxBDReady & ~RxStartFrm & RxEnableWindow & (&RxByteCnt)) | (RxValid & RxBDReady & RxStartFrm & (&RxPointerLatched)) | (ShiftWillEnd & LastByteIn & (&RxByteCnt));
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
WriteRxDataToFifo <=#Tp 1'b0;
else
if(SetWriteRxDataToFifo & ~RxAbort)
WriteRxDataToFifo <=#Tp 1'b1;
else
if(WriteRxDataToFifoSync1 | RxAbort)
WriteRxDataToFifo <=#Tp 1'b0;
end
 
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
WriteRxDataToFifoSync1 <=#Tp 1'b0;
else
if(WriteRxDataToFifo)
WriteRxDataToFifoSync1 <=#Tp 1'b1;
else
WriteRxDataToFifoSync1 <=#Tp 1'b0;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
WriteRxDataToFifoSync2 <=#Tp 1'b0;
else
WriteRxDataToFifoSync2 <=#Tp WriteRxDataToFifoSync1;
end
 
wire WriteRxDataToFifo_wb;
assign WriteRxDataToFifo_wb = WriteRxDataToFifoSync1 & ~WriteRxDataToFifoSync2;
 
reg RxAbortSync1;
reg RxAbortSync2;
reg RxAbortSyncb1;
reg RxAbortSyncb2;
 
reg LatchedRxStartFrm;
reg SyncRxStartFrm;
reg SyncRxStartFrm_q;
wire RxFifoReset;
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedRxStartFrm <=#Tp 0;
else
if(RxStartFrm & ~SyncRxStartFrm)
LatchedRxStartFrm <=#Tp 1;
else
if(SyncRxStartFrm)
LatchedRxStartFrm <=#Tp 0;
end
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
SyncRxStartFrm <=#Tp 0;
else
if(LatchedRxStartFrm)
SyncRxStartFrm <=#Tp 1;
else
SyncRxStartFrm <=#Tp 0;
end
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
SyncRxStartFrm_q <=#Tp 0;
else
SyncRxStartFrm_q <=#Tp SyncRxStartFrm;
end
 
 
assign RxFifoReset = SyncRxStartFrm & ~SyncRxStartFrm_q;
 
 
eth_fifo #(`RX_FIFO_DATA_WIDTH, `RX_FIFO_DEPTH, `RX_FIFO_CNT_WIDTH)
rx_fifo (.data_in(RxDataLatched2), .data_out(m_wb_dat_o),
.clk(WB_CLK_I), .reset(Reset),
.write(WriteRxDataToFifo_wb), .read(MasterWbRX & m_wb_ack_i),
.clear(RxFifoReset), .full(RxBufferFull),
.almost_full(), .almost_empty(RxBufferAlmostEmpty),
.empty(RxBufferEmpty), .cnt()
);
 
assign WriteRxDataToMemory = ~RxBufferEmpty & ~MasterWbRX;
 
 
 
// Generation of the end-of-frame signal
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ShiftEnded_tck <=#Tp 1'b0;
else
if(~RxAbort & SetWriteRxDataToFifo & StartShiftWillEnd)
ShiftEnded_tck <=#Tp 1'b1;
else
if(RxAbort | ShiftEndedSync_c1 & ShiftEndedSync_c2)
ShiftEnded_tck <=#Tp 1'b0;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ShiftEndedSync1 <=#Tp 1'b0;
else
ShiftEndedSync1 <=#Tp ShiftEnded_tck;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ShiftEndedSync2 <=#Tp 1'b0;
else
ShiftEndedSync2 <=#Tp ShiftEndedSync1;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ShiftEndedSync3 <=#Tp 1'b0;
else
if(ShiftEndedSync1 & ~ShiftEndedSync2)
ShiftEndedSync3 <=#Tp 1'b1;
else
if(ShiftEnded)
ShiftEndedSync3 <=#Tp 1'b0;
end
 
// Generation of the end-of-frame signal
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
ShiftEnded <=#Tp 1'b0;
else
if(ShiftEndedSync3 & MasterWbRX & m_wb_ack_i & RxBufferAlmostEmpty & ~ShiftEnded)
ShiftEnded <=#Tp 1'b1;
else
if(RxStatusWrite)
ShiftEnded <=#Tp 1'b0;
end
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ShiftEndedSync_c1 <=#Tp 1'b0;
else
ShiftEndedSync_c1 <=#Tp ShiftEndedSync2;
end
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ShiftEndedSync_c2 <=#Tp 1'b0;
else
ShiftEndedSync_c2 <=#Tp ShiftEndedSync_c1;
end
 
// Generation of the end-of-frame signal
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxEnableWindow <=#Tp 1'b0;
else
if(RxStartFrm)
RxEnableWindow <=#Tp 1'b1;
else
if(RxEndFrm | RxAbort)
RxEnableWindow <=#Tp 1'b0;
end
 
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxAbortSync1 <=#Tp 1'b0;
else
RxAbortSync1 <=#Tp RxAbort;
end
 
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxAbortSync2 <=#Tp 1'b0;
else
RxAbortSync2 <=#Tp RxAbortSync1;
end
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxAbortSyncb1 <=#Tp 1'b0;
else
RxAbortSyncb1 <=#Tp RxAbortSync2;
end
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxAbortSyncb2 <=#Tp 1'b0;
else
RxAbortSyncb2 <=#Tp RxAbortSyncb1;
end
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxAbortLatched <=#Tp 1'b0;
else
if(RxAbort)
RxAbortLatched <=#Tp 1'b1;
else
if(RxStartFrm)
RxAbortLatched <=#Tp 1'b0;
end
 
 
reg LoadStatusBlocked;
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LoadStatusBlocked <=#Tp 1'b0;
else
if(LoadRxStatus & ~RxAbortLatched)
LoadStatusBlocked <=#Tp 1'b1;
else
if(RxStatusWrite_rck | RxStartFrm)
LoadStatusBlocked <=#Tp 1'b0;
end
 
// LatchedRxLength[15:0]
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedRxLength[15:0] <=#Tp 16'h0;
else
if(LoadRxStatus & ~RxAbortLatched & ~LoadStatusBlocked)
LatchedRxLength[15:0] <=#Tp RxLength[15:0];
end
 
 
assign RxStatusIn = {RxOverrun, InvalidSymbol, DribbleNibble, ReceivedPacketTooBig, ShortFrame, LatchedCrcError, RxLateCollision};
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxStatusInLatched <=#Tp 'h0;
else
if(LoadRxStatus & ~RxAbortLatched & ~LoadStatusBlocked)
RxStatusInLatched <=#Tp RxStatusIn;
end
 
 
// Rx overrun
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxOverrun <=#Tp 1'b0;
else
if(RxStatusWrite)
RxOverrun <=#Tp 1'b0;
else
if(RxBufferFull & WriteRxDataToFifo_wb)
RxOverrun <=#Tp 1'b1;
end
 
 
 
wire TxError;
assign TxError = TxUnderRun | RetryLimit | LateCollLatched | CarrierSenseLost;
 
wire RxError;
assign RxError = |RxStatusInLatched[6:0];
 
// Tx Done Interrupt
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxB_IRQ <=#Tp 1'b0;
else
if(TxStatusWrite & TxIRQEn)
TxB_IRQ <=#Tp ~TxError;
else
TxB_IRQ <=#Tp 1'b0;
end
 
 
// Tx Error Interrupt
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
TxE_IRQ <=#Tp 1'b0;
else
if(TxStatusWrite & TxIRQEn)
TxE_IRQ <=#Tp TxError;
else
TxE_IRQ <=#Tp 1'b0;
end
 
 
// Rx Done Interrupt
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxB_IRQ <=#Tp 1'b0;
else
if(RxStatusWrite & RxIRQEn)
RxB_IRQ <=#Tp ReceivedPacketGood;
else
RxB_IRQ <=#Tp 1'b0;
end
 
 
// Rx Error Interrupt
always @ (posedge WB_CLK_I or posedge Reset)
begin
if(Reset)
RxE_IRQ <=#Tp 1'b0;
else
if(RxStatusWrite & RxIRQEn)
RxE_IRQ <=#Tp RxError;
else
RxE_IRQ <=#Tp 1'b0;
end
 
 
assign RxC_IRQ = 1'b0;
assign TxC_IRQ = 1'b0;
assign Busy_IRQ = 1'b0;
 
 
 
 
// TX
// bit 15 ready
// bit 14 interrupt
// bit 13 wrap
// bit 12 pad
// bit 11 crc
// bit 10 last
// bit 9 pause request (control frame)
// bit 8 TxUnderRun
// bit 7-4 RetryCntLatched
// bit 3 retransmittion limit
// bit 2 LateCollLatched
// bit 1 DeferLatched
// bit 0 CarrierSenseLost
 
 
// RX
// bit 15 od rx je empty
// bit 14 od rx je interrupt
// bit 13 od rx je wrap
// bit 12 od rx je reserved
// bit 11 od rx je reserved
// bit 10 od rx je reserved
// bit 9 od rx je reserved
// bit 8 od rx je reserved
// bit 7 od rx je Miss
// bit 6 od rx je RxOverrun
// bit 5 od rx je InvalidSymbol
// bit 4 od rx je DribbleNibble
// bit 3 od rx je ReceivedPacketTooBig
// bit 2 od rx je ShortFrame
// bit 1 od rx je LatchedCrcError
// bit 0 od rx je RxLateCollision
 
 
 
endmodule
 
/rtl/verilog/eth_macstatus.v
0,0 → 1,397
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_macstatus.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.9 2002/04/22 13:51:44 mohor
// Short frame and ReceivedLengthOK were not detected correctly.
//
// Revision 1.8 2002/02/18 10:40:17 mohor
// Small fixes.
//
// Revision 1.7 2002/02/15 17:07:39 mohor
// Status was not written correctly when frames were discarted because of
// address mismatch.
//
// Revision 1.6 2002/02/11 09:18:21 mohor
// Tx status is written back to the BD.
//
// Revision 1.5 2002/02/08 16:21:54 mohor
// Rx status is written back to the BD.
//
// Revision 1.4 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
`include "timescale.v"
 
 
module eth_macstatus(
MRxClk, Reset, ReceivedLengthOK, ReceiveEnd, ReceivedPacketGood, RxCrcError,
MRxErr, MRxDV, RxStateSFD, RxStateData, RxStatePreamble, RxStateIdle, Transmitting,
RxByteCnt, RxByteCntEq0, RxByteCntGreat2, RxByteCntMaxFrame, ReceivedPauseFrm,
InvalidSymbol, MRxD, LatchedCrcError, Collision, CollValid, RxLateCollision,
r_RecSmall, r_MinFL, r_MaxFL, ShortFrame, DribbleNibble, ReceivedPacketTooBig, r_HugEn,
LoadRxStatus, StartTxDone, StartTxAbort, RetryCnt, RetryCntLatched, MTxClk, MaxCollisionOccured,
RetryLimit, LateCollision, LateCollLatched, StartDefer, DeferLatched, TxStartFrm,
StatePreamble, StateData, CarrierSense, CarrierSenseLost, TxUsedData, LatchedMRxErr
);
 
 
 
parameter Tp = 1;
 
 
input MRxClk;
input Reset;
input RxCrcError;
input MRxErr;
input MRxDV;
 
input RxStateSFD;
input [1:0] RxStateData;
input RxStatePreamble;
input RxStateIdle;
input Transmitting;
input [15:0] RxByteCnt;
input RxByteCntEq0;
input RxByteCntGreat2;
input RxByteCntMaxFrame;
input ReceivedPauseFrm;
input [3:0] MRxD;
input Collision;
input [5:0] CollValid;
input r_RecSmall;
input [15:0] r_MinFL;
input [15:0] r_MaxFL;
input r_HugEn;
input StartTxDone;
input StartTxAbort;
input [3:0] RetryCnt;
input MTxClk;
input MaxCollisionOccured;
input LateCollision;
input StartDefer;
input TxStartFrm;
input StatePreamble;
input [1:0] StateData;
input CarrierSense;
input TxUsedData;
 
 
output ReceivedLengthOK;
output ReceiveEnd;
output ReceivedPacketGood;
output InvalidSymbol;
output LatchedCrcError;
output RxLateCollision;
output ShortFrame;
output DribbleNibble;
output ReceivedPacketTooBig;
output LoadRxStatus;
output [3:0] RetryCntLatched;
output RetryLimit;
output LateCollLatched;
output DeferLatched;
output CarrierSenseLost;
output LatchedMRxErr;
 
 
reg ReceiveEnd;
 
reg LatchedCrcError;
reg LatchedMRxErr;
reg LoadRxStatus;
reg InvalidSymbol;
reg [3:0] RetryCntLatched;
reg RetryLimit;
reg LateCollLatched;
reg DeferLatched;
reg CarrierSenseLost;
 
wire TakeSample;
wire SetInvalidSymbol; // Invalid symbol was received during reception in 100Mbps
 
// Crc error
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedCrcError <=#Tp 1'b0;
else
if(RxStateSFD)
LatchedCrcError <=#Tp 1'b0;
else
if(RxStateData[0])
LatchedCrcError <=#Tp RxCrcError & ~RxByteCntEq0;
end
 
 
// LatchedMRxErr
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedMRxErr <=#Tp 1'b0;
else
if(MRxErr & MRxDV & (RxStatePreamble | RxStateSFD | (|RxStateData) | RxStateIdle & ~Transmitting))
LatchedMRxErr <=#Tp 1'b1;
else
LatchedMRxErr <=#Tp 1'b0;
end
 
 
// ReceivedPacketGood
assign ReceivedPacketGood = ~LatchedCrcError;
 
 
// ReceivedLengthOK
assign ReceivedLengthOK = RxByteCnt[15:0] >= r_MinFL[15:0] & RxByteCnt[15:0] <= r_MaxFL[15:0];
 
 
 
 
 
// Time to take a sample
assign TakeSample = |RxStateData & ~MRxDV & RxByteCntGreat2 |
RxStateData[0] & MRxDV & RxByteCntMaxFrame;
 
 
// LoadRxStatus
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LoadRxStatus <=#Tp 1'b0;
else
LoadRxStatus <=#Tp TakeSample;
end
 
 
 
// ReceiveEnd
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ReceiveEnd <=#Tp 1'b0;
else
ReceiveEnd <=#Tp LoadRxStatus;
end
 
 
// Invalid Symbol received during 100Mbps mode
assign SetInvalidSymbol = MRxDV & MRxErr & MRxD[3:0] == 4'he;
 
 
// InvalidSymbol
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
InvalidSymbol <=#Tp 1'b0;
else
if(LoadRxStatus & ~SetInvalidSymbol)
InvalidSymbol <=#Tp 1'b0;
else
if(SetInvalidSymbol)
InvalidSymbol <=#Tp 1'b1;
end
 
 
// Late Collision
 
reg RxLateCollision;
reg RxColWindow;
// Collision Window
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxLateCollision <=#Tp 1'b0;
else
if(LoadRxStatus)
RxLateCollision <=#Tp 1'b0;
else
if(Collision & (~RxColWindow | r_RecSmall))
RxLateCollision <=#Tp 1'b1;
end
 
// Collision Window
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxColWindow <=#Tp 1'b1;
else
if(~Collision & RxByteCnt[5:0] == CollValid[5:0] & RxStateData[1])
RxColWindow <=#Tp 1'b0;
else
if(RxStateIdle)
RxColWindow <=#Tp 1'b1;
end
 
 
// ShortFrame
reg ShortFrame;
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ShortFrame <=#Tp 1'b0;
else
if(LoadRxStatus)
ShortFrame <=#Tp 1'b0;
else
if(TakeSample)
ShortFrame <=#Tp RxByteCnt[15:0] < r_MinFL[15:0];
end
 
 
// DribbleNibble
reg DribbleNibble;
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
DribbleNibble <=#Tp 1'b0;
else
if(RxStateSFD)
DribbleNibble <=#Tp 1'b0;
else
if(~MRxDV & RxStateData[1])
DribbleNibble <=#Tp 1'b1;
end
 
 
reg ReceivedPacketTooBig;
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ReceivedPacketTooBig <=#Tp 1'b0;
else
if(LoadRxStatus)
ReceivedPacketTooBig <=#Tp 1'b0;
else
if(TakeSample)
ReceivedPacketTooBig <=#Tp ~r_HugEn & RxByteCnt[15:0] > r_MaxFL[15:0];
end
 
 
 
// Latched Retry counter for tx status
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
RetryCntLatched <=#Tp 4'h0;
else
if(StartTxDone | StartTxAbort)
RetryCntLatched <=#Tp RetryCnt;
end
 
 
// Latched Retransmission limit
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
RetryLimit <=#Tp 4'h0;
else
if(StartTxDone | StartTxAbort)
RetryLimit <=#Tp MaxCollisionOccured;
end
 
 
// Latched Late Collision
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
LateCollLatched <=#Tp 1'b0;
else
if(StartTxDone | StartTxAbort)
LateCollLatched <=#Tp LateCollision;
end
 
 
 
// Latched Defer state
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
DeferLatched <=#Tp 1'b0;
else
if(StartDefer & TxUsedData)
DeferLatched <=#Tp 1'b1;
else
if(TxStartFrm)
DeferLatched <=#Tp 1'b0;
end
 
 
// CarrierSenseLost
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
CarrierSenseLost <=#Tp 1'b0;
else
if((StatePreamble | (|StateData)) & ~CarrierSense & ~Collision)
CarrierSenseLost <=#Tp 1'b1;
else
if(TxStartFrm)
CarrierSenseLost <=#Tp 1'b0;
end
 
 
endmodule
/rtl/verilog/eth_top.v
0,0 → 1,700
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_top.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.26 2002/07/17 18:51:50 mohor
// EXTERNAL_DMA removed. External DMA not supported.
//
// Revision 1.25 2002/05/03 10:15:50 mohor
// Outputs registered. Reset changed for eth_wishbone module.
//
// Revision 1.24 2002/04/22 14:15:42 mohor
// Wishbone signals are registered when ETH_REGISTERED_OUTPUTS is
// selected in eth_defines.v
//
// Revision 1.23 2002/03/25 13:33:53 mohor
// md_padoen_o changed to md_padoe_o. Signal was always active high, just
// name was incorrect.
//
// Revision 1.22 2002/02/26 16:59:54 mohor
// Small fixes for external/internal DMA missmatches.
//
// Revision 1.21 2002/02/26 16:21:00 mohor
// Interrupts changed in the top file
//
// Revision 1.20 2002/02/18 10:40:17 mohor
// Small fixes.
//
// Revision 1.19 2002/02/16 14:03:44 mohor
// Registered trimmed. Unused registers removed.
//
// Revision 1.18 2002/02/16 13:06:33 mohor
// EXTERNAL_DMA used instead of WISHBONE_DMA.
//
// Revision 1.17 2002/02/16 07:15:27 mohor
// Testbench fixed, code simplified, unused signals removed.
//
// Revision 1.16 2002/02/15 13:49:39 mohor
// RxAbort is connected differently.
//
// Revision 1.15 2002/02/15 11:38:26 mohor
// Changes that were lost when updating from 1.11 to 1.14 fixed.
//
// Revision 1.14 2002/02/14 20:19:11 billditt
// Modified for Address Checking,
// addition of eth_addrcheck.v
//
// Revision 1.13 2002/02/12 17:03:03 mohor
// HASH0 and HASH1 registers added. Registers address width was
// changed to 8 bits.
//
// Revision 1.12 2002/02/11 09:18:22 mohor
// Tx status is written back to the BD.
//
// Revision 1.11 2002/02/08 16:21:54 mohor
// Rx status is written back to the BD.
//
// Revision 1.10 2002/02/06 14:10:21 mohor
// non-DMA host interface added. Select the right configutation in eth_defines.
//
// Revision 1.9 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.8 2001/12/05 15:00:16 mohor
// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors
// instead of the number of RX descriptors).
//
// Revision 1.7 2001/12/05 10:45:59 mohor
// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead.
//
// Revision 1.6 2001/10/19 11:24:29 mohor
// Number of addresses (wb_adr_i) minimized.
//
// Revision 1.5 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.4 2001/10/18 12:07:11 mohor
// Status signals changed, Adress decoding changed, interrupt controller
// added.
//
// Revision 1.3 2001/09/24 15:02:56 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.2 2001/08/15 14:03:59 mohor
// Signal names changed on the top level for easier pad insertion (ASIC).
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.2 2001/08/02 09:25:31 mohor
// Unconnected signals are now connected.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
 
 
`include "eth_defines.v"
`include "timescale.v"
 
 
module eth_top
(
// WISHBONE common
wb_clk_i, wb_rst_i, wb_dat_i, wb_dat_o,
 
// WISHBONE slave
wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i, wb_stb_i, wb_ack_o, wb_err_o,
 
// WISHBONE master
m_wb_adr_o, m_wb_sel_o, m_wb_we_o,
m_wb_dat_o, m_wb_dat_i, m_wb_cyc_o,
m_wb_stb_o, m_wb_ack_i, m_wb_err_i,
 
//TX
mtx_clk_pad_i, mtxd_pad_o, mtxen_pad_o, mtxerr_pad_o,
 
//RX
mrx_clk_pad_i, mrxd_pad_i, mrxdv_pad_i, mrxerr_pad_i, mcoll_pad_i, mcrs_pad_i,
// MIIM
mdc_pad_o, md_pad_i, md_pad_o, md_padoe_o,
 
int_o
 
 
);
 
 
parameter Tp = 1;
 
 
// WISHBONE common
input wb_clk_i; // WISHBONE clock
input wb_rst_i; // WISHBONE reset
input [31:0] wb_dat_i; // WISHBONE data input
output [31:0] wb_dat_o; // WISHBONE data output
output wb_err_o; // WISHBONE error output
 
// WISHBONE slave
input [11:2] wb_adr_i; // WISHBONE address input
input [3:0] wb_sel_i; // WISHBONE byte select input
input wb_we_i; // WISHBONE write enable input
input wb_cyc_i; // WISHBONE cycle input
input wb_stb_i; // WISHBONE strobe input
output wb_ack_o; // WISHBONE acknowledge output
 
// WISHBONE master
output [31:0] m_wb_adr_o;
output [3:0] m_wb_sel_o;
output m_wb_we_o;
input [31:0] m_wb_dat_i;
output [31:0] m_wb_dat_o;
output m_wb_cyc_o;
output m_wb_stb_o;
input m_wb_ack_i;
input m_wb_err_i;
 
 
// Tx
input mtx_clk_pad_i; // Transmit clock (from PHY)
output [3:0] mtxd_pad_o; // Transmit nibble (to PHY)
output mtxen_pad_o; // Transmit enable (to PHY)
output mtxerr_pad_o; // Transmit error (to PHY)
 
// Rx
input mrx_clk_pad_i; // Receive clock (from PHY)
input [3:0] mrxd_pad_i; // Receive nibble (from PHY)
input mrxdv_pad_i; // Receive data valid (from PHY)
input mrxerr_pad_i; // Receive data error (from PHY)
 
// Common Tx and Rx
input mcoll_pad_i; // Collision (from PHY)
input mcrs_pad_i; // Carrier sense (from PHY)
 
// MII Management interface
input md_pad_i; // MII data input (from I/O cell)
output mdc_pad_o; // MII Management data clock (to PHY)
output md_pad_o; // MII data output (to I/O cell)
output md_padoe_o; // MII data output enable (to I/O cell)
 
output int_o; // Interrupt output
 
wire [7:0] r_ClkDiv;
wire r_MiiNoPre;
wire [15:0] r_CtrlData;
wire [4:0] r_FIAD;
wire [4:0] r_RGAD;
wire r_WCtrlData;
wire r_RStat;
wire r_ScanStat;
wire NValid_stat;
wire Busy_stat;
wire LinkFail;
wire r_MiiMRst;
wire [15:0] Prsd; // Read Status Data (data read from the PHY)
wire WCtrlDataStart;
wire RStatStart;
wire UpdateMIIRX_DATAReg;
 
wire TxStartFrm;
wire TxEndFrm;
wire TxUsedData;
wire [7:0] TxData;
wire TxRetry;
wire TxAbort;
wire TxUnderRun;
wire TxDone;
wire [5:0] CollValid;
 
 
 
 
// Connecting Miim module
eth_miim miim1
(
.Clk(wb_clk_i), .Reset(r_MiiMRst), .Divider(r_ClkDiv),
.NoPre(r_MiiNoPre), .CtrlData(r_CtrlData), .Rgad(r_RGAD),
.Fiad(r_FIAD), .WCtrlData(r_WCtrlData), .RStat(r_RStat),
.ScanStat(r_ScanStat), .Mdi(md_pad_i), .Mdo(md_pad_o),
.MdoEn(md_padoe_o), .Mdc(mdc_pad_o), .Busy(Busy_stat),
.Prsd(Prsd), .LinkFail(LinkFail), .Nvalid(NValid_stat),
.WCtrlDataStart(WCtrlDataStart), .RStatStart(RStatStart), .UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg)
);
 
 
 
 
wire RegCs; // Connected to registers
wire [31:0] RegDataOut; // Multiplexed to wb_dat_o
wire r_RecSmall; // Receive small frames
wire r_Rst; // Reset
wire r_LoopBck; // Loopback
wire r_TxEn; // Tx Enable
wire r_RxEn; // Rx Enable
 
wire MRxDV_Lb; // Muxed MII receive data valid
wire MRxErr_Lb; // Muxed MII Receive Error
wire [3:0] MRxD_Lb; // Muxed MII Receive Data
wire Transmitting; // Indication that TxEthMAC is transmitting
wire r_HugEn; // Huge packet enable
wire r_DlyCrcEn; // Delayed CRC enabled
wire [15:0] r_MaxFL; // Maximum frame length
 
wire [15:0] r_MinFL; // Minimum frame length
wire ShortFrame;
wire DribbleNibble; // Extra nibble received
wire ReceivedPacketTooBig; // Received packet is too big
wire [47:0] r_MAC; // MAC address
wire LoadRxStatus; // Rx status was loaded
wire [31:0] r_HASH0; // HASH table, lower 4 bytes
wire [31:0] r_HASH1; // HASH table, upper 4 bytes
wire [7:0] r_TxBDNum; // Receive buffer descriptor number
wire [6:0] r_IPGT; //
wire [6:0] r_IPGR1; //
wire [6:0] r_IPGR2; //
wire [5:0] r_CollValid; //
wire r_TPauseRq; // Transmit PAUSE request pulse
 
wire [3:0] r_MaxRet; //
wire r_NoBckof; //
wire r_ExDfrEn; //
wire TX_BD_NUM_Wr; // Write enable that writes RX_BD_NUM to the registers.
wire TPauseRq; // Sinhronized Tx PAUSE request
wire [15:0] TxPauseTV; // Tx PAUSE timer value
wire r_TxFlow; // Tx flow control enable
wire r_IFG; // Minimum interframe gap for incoming packets
 
wire TxB_IRQ; // Interrupt Tx Buffer
wire TxE_IRQ; // Interrupt Tx Error
wire RxB_IRQ; // Interrupt Rx Buffer
wire RxE_IRQ; // Interrupt Rx Error
wire Busy_IRQ; // Interrupt Busy (lack of buffers)
wire TxC_IRQ; // Interrupt Tx Control Frame
wire RxC_IRQ; // Interrupt Rx Control Frame
 
wire DWord;
wire BDAck;
wire [31:0] BD_WB_DAT_O; // wb_dat_o that comes from the Wishbone module (for buffer descriptors read/write)
wire BDCs; // Buffer descriptor CS
 
wire temp_wb_ack_o;
wire [31:0] temp_wb_dat_o;
wire temp_wb_err_o;
 
`ifdef ETH_REGISTERED_OUTPUTS
reg temp_wb_ack_o_reg;
reg [31:0] temp_wb_dat_o_reg;
reg temp_wb_err_o_reg;
`endif
 
assign DWord = &wb_sel_i;
assign RegCs = wb_stb_i & wb_cyc_i & DWord & ~wb_adr_i[11] & ~wb_adr_i[10]; // 0x0 - 0x3FF
assign BDCs = wb_stb_i & wb_cyc_i & DWord & ~wb_adr_i[11] & wb_adr_i[10]; // 0x400 - 0x7FF
assign temp_wb_ack_o = RegCs | BDAck;
assign temp_wb_dat_o = (RegCs & ~wb_we_i)? RegDataOut : BD_WB_DAT_O;
assign temp_wb_err_o = wb_stb_i & wb_cyc_i & ~DWord;
 
`ifdef ETH_REGISTERED_OUTPUTS
assign wb_ack_o = temp_wb_ack_o_reg;
assign wb_dat_o[31:0] = temp_wb_dat_o_reg;
assign wb_err_o = temp_wb_err_o_reg;
`else
assign wb_ack_o = temp_wb_ack_o;
assign wb_dat_o[31:0] = temp_wb_dat_o;
assign wb_err_o = temp_wb_err_o;
`endif
 
 
 
`ifdef ETH_REGISTERED_OUTPUTS
always @ (posedge wb_clk_i or posedge wb_rst_i)
begin
if(wb_rst_i)
begin
temp_wb_ack_o_reg <=#Tp 1'b0;
temp_wb_dat_o_reg <=#Tp 32'h0;
temp_wb_err_o_reg <=#Tp 1'b0;
end
else
begin
temp_wb_ack_o_reg <=#Tp temp_wb_ack_o & ~temp_wb_ack_o_reg;
temp_wb_dat_o_reg <=#Tp temp_wb_dat_o;
temp_wb_err_o_reg <=#Tp temp_wb_err_o & ~temp_wb_err_o_reg;
end
end
`endif
 
 
 
// Connecting Ethernet registers
eth_registers ethreg1
(
.DataIn(wb_dat_i), .Address(wb_adr_i[9:2]), .Rw(wb_we_i),
.Cs(RegCs), .Clk(wb_clk_i), .Reset(wb_rst_i),
.DataOut(RegDataOut), .r_RecSmall(r_RecSmall),
.r_Pad(r_Pad), .r_HugEn(r_HugEn), .r_CrcEn(r_CrcEn),
.r_DlyCrcEn(r_DlyCrcEn), .r_Rst(r_Rst), .r_FullD(r_FullD),
.r_ExDfrEn(r_ExDfrEn), .r_NoBckof(r_NoBckof), .r_LoopBck(r_LoopBck),
.r_IFG(r_IFG), .r_Pro(r_Pro), .r_Iam(),
.r_Bro(r_Bro), .r_NoPre(r_NoPre), .r_TxEn(r_TxEn),
.r_RxEn(r_RxEn), .Busy_IRQ(Busy_IRQ), .RxE_IRQ(RxE_IRQ),
.RxB_IRQ(RxB_IRQ), .TxE_IRQ(TxE_IRQ), .TxB_IRQ(TxB_IRQ),
.TxC_IRQ(TxC_IRQ), .RxC_IRQ(RxC_IRQ), .r_IPGT(r_IPGT),
.r_IPGR1(r_IPGR1), .r_IPGR2(r_IPGR2), .r_MinFL(r_MinFL),
.r_MaxFL(r_MaxFL), .r_MaxRet(r_MaxRet), .r_CollValid(r_CollValid),
.r_TxFlow(r_TxFlow), .r_RxFlow(r_RxFlow), .r_PassAll(r_PassAll),
.r_MiiMRst(r_MiiMRst), .r_MiiNoPre(r_MiiNoPre), .r_ClkDiv(r_ClkDiv),
.r_WCtrlData(r_WCtrlData), .r_RStat(r_RStat), .r_ScanStat(r_ScanStat),
.r_RGAD(r_RGAD), .r_FIAD(r_FIAD), .r_CtrlData(r_CtrlData),
.NValid_stat(NValid_stat), .Busy_stat(Busy_stat),
.LinkFail(LinkFail), .r_MAC(r_MAC), .WCtrlDataStart(WCtrlDataStart),
.RStatStart(RStatStart), .UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg), .Prsd(Prsd),
.r_TxBDNum(r_TxBDNum), .TX_BD_NUM_Wr(TX_BD_NUM_Wr), .int_o(int_o),
.r_HASH0(r_HASH0), .r_HASH1(r_HASH1)
);
 
 
 
wire [7:0] RxData;
wire RxValid;
wire RxStartFrm;
wire RxEndFrm;
wire RxAbort;
 
wire WillTransmit; // Will transmit (to RxEthMAC)
wire ResetCollision; // Reset Collision (for synchronizing collision)
wire [7:0] TxDataOut; // Transmit Packet Data (to TxEthMAC)
wire WillSendControlFrame;
wire TxCtrlEndFrm;
wire ReceivedPauseFrm;
wire ReceiveEnd;
wire ReceivedPacketGood;
wire ReceivedLengthOK;
wire InvalidSymbol;
wire LatchedCrcError;
wire RxLateCollision;
wire [3:0] RetryCntLatched;
wire [3:0] RetryCnt;
wire StartTxDone;
wire StartTxAbort;
wire MaxCollisionOccured;
wire RetryLimit;
wire StatePreamble;
wire [1:0] StateData;
 
// Connecting MACControl
eth_maccontrol maccontrol1
(
.MTxClk(mtx_clk_pad_i), .TPauseRq(TPauseRq),
.TxPauseTV(TxPauseTV), .TxDataIn(TxData),
.TxStartFrmIn(TxStartFrm), .TxEndFrmIn(TxEndFrm),
.TxUsedDataIn(TxUsedDataIn), .TxDoneIn(TxDoneIn),
.TxAbortIn(TxAbortIn), .MRxClk(mrx_clk_pad_i),
.RxData(RxData), .RxValid(RxValid),
.RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm),
.ReceiveEnd(ReceiveEnd), .ReceivedPacketGood(ReceivedPacketGood),
.PassAll(r_PassAll), .TxFlow(r_TxFlow),
.RxFlow(r_RxFlow), .DlyCrcEn(r_DlyCrcEn),
.MAC(r_MAC), .PadIn(r_Pad | PerPacketPad),
.PadOut(PadOut), .CrcEnIn(r_CrcEn | PerPacketCrcEn),
.CrcEnOut(CrcEnOut), .TxReset(r_Rst),
.RxReset(r_Rst), .ReceivedLengthOK(ReceivedLengthOK),
.TxDataOut(TxDataOut), .TxStartFrmOut(TxStartFrmOut),
.TxEndFrmOut(TxEndFrmOut), .TxUsedDataOut(TxUsedData),
.TxDoneOut(TxDone), .TxAbortOut(TxAbort),
.WillSendControlFrame(WillSendControlFrame), .TxCtrlEndFrm(TxCtrlEndFrm),
.ReceivedPauseFrm(ReceivedPauseFrm)
);
 
 
 
wire TxCarrierSense; // Synchronized CarrierSense (to Tx clock)
wire Collision; // Synchronized Collision
 
reg CarrierSense_Tx1;
reg CarrierSense_Tx2;
reg Collision_Tx1;
reg Collision_Tx2;
 
reg RxEnSync; // Synchronized Receive Enable
reg CarrierSense_Rx1;
reg RxCarrierSense; // Synchronized CarrierSense (to Rx clock)
reg WillTransmit_q;
reg WillTransmit_q2;
 
 
 
// Muxed MII receive data valid
assign MRxDV_Lb = r_LoopBck? mtxen_pad_o : mrxdv_pad_i & RxEnSync;
 
// Muxed MII Receive Error
assign MRxErr_Lb = r_LoopBck? mtxerr_pad_o : mrxerr_pad_i & RxEnSync;
 
// Muxed MII Receive Data
assign MRxD_Lb[3:0] = r_LoopBck? mtxd_pad_o[3:0] : mrxd_pad_i[3:0];
 
 
 
// Connecting TxEthMAC
eth_txethmac txethmac1
(
.MTxClk(mtx_clk_pad_i), .Reset(r_Rst), .CarrierSense(TxCarrierSense),
.Collision(Collision), .TxData(TxDataOut), .TxStartFrm(TxStartFrmOut),
.TxUnderRun(TxUnderRun), .TxEndFrm(TxEndFrmOut), .Pad(PadOut),
.MinFL(r_MinFL), .CrcEn(CrcEnOut), .FullD(r_FullD),
.HugEn(r_HugEn), .DlyCrcEn(r_DlyCrcEn), .IPGT(r_IPGT),
.IPGR1(r_IPGR1), .IPGR2(r_IPGR2), .CollValid(r_CollValid),
.MaxRet(r_MaxRet), .NoBckof(r_NoBckof), .ExDfrEn(r_ExDfrEn),
.MaxFL(r_MaxFL), .MTxEn(mtxen_pad_o), .MTxD(mtxd_pad_o),
.MTxErr(mtxerr_pad_o), .TxUsedData(TxUsedDataIn), .TxDone(TxDoneIn),
.TxRetry(TxRetry), .TxAbort(TxAbortIn), .WillTransmit(WillTransmit),
.ResetCollision(ResetCollision), .RetryCnt(RetryCnt), .StartTxDone(StartTxDone),
.StartTxAbort(StartTxAbort), .MaxCollisionOccured(MaxCollisionOccured), .LateCollision(LateCollision),
.StartDefer(StartDefer), .StatePreamble(StatePreamble), .StateData(StateData)
);
 
 
 
 
wire [15:0] RxByteCnt;
wire RxByteCntEq0;
wire RxByteCntGreat2;
wire RxByteCntMaxFrame;
wire RxCrcError;
wire RxStateIdle;
wire RxStatePreamble;
wire RxStateSFD;
wire [1:0] RxStateData;
 
 
 
 
// Connecting RxEthMAC
eth_rxethmac rxethmac1
(
.MRxClk(mrx_clk_pad_i), .MRxDV(MRxDV_Lb), .MRxD(MRxD_Lb),
.Transmitting(Transmitting), .HugEn(r_HugEn), .DlyCrcEn(r_DlyCrcEn),
.MaxFL(r_MaxFL), .r_IFG(r_IFG), .Reset(r_Rst),
.RxData(RxData), .RxValid(RxValid), .RxStartFrm(RxStartFrm),
.RxEndFrm(RxEndFrm), .ByteCnt(RxByteCnt),
.ByteCntEq0(RxByteCntEq0), .ByteCntGreat2(RxByteCntGreat2), .ByteCntMaxFrame(RxByteCntMaxFrame),
.CrcError(RxCrcError), .StateIdle(RxStateIdle), .StatePreamble(RxStatePreamble),
.StateSFD(RxStateSFD), .StateData(RxStateData),
.MAC(r_MAC), .r_Pro(r_Pro), .r_Bro(r_Bro),
.r_HASH0(r_HASH0), .r_HASH1(r_HASH1), .RxAbort(RxAbort)
);
 
 
// MII Carrier Sense Synchronization
always @ (posedge mtx_clk_pad_i or posedge r_Rst)
begin
if(r_Rst)
begin
CarrierSense_Tx1 <= #Tp 1'b0;
CarrierSense_Tx2 <= #Tp 1'b0;
end
else
begin
CarrierSense_Tx1 <= #Tp mcrs_pad_i;
CarrierSense_Tx2 <= #Tp CarrierSense_Tx1;
end
end
 
assign TxCarrierSense = ~r_FullD & CarrierSense_Tx2;
 
 
// MII Collision Synchronization
always @ (posedge mtx_clk_pad_i or posedge r_Rst)
begin
if(r_Rst)
begin
Collision_Tx1 <= #Tp 1'b0;
Collision_Tx2 <= #Tp 1'b0;
end
else
begin
Collision_Tx1 <= #Tp mcoll_pad_i;
if(ResetCollision)
Collision_Tx2 <= #Tp 1'b0;
else
if(Collision_Tx1)
Collision_Tx2 <= #Tp 1'b1;
end
end
 
 
// Synchronized Collision
assign Collision = ~r_FullD & Collision_Tx2;
 
 
 
// Carrier sense is synchronized to receive clock.
always @ (posedge mrx_clk_pad_i or posedge r_Rst)
begin
if(r_Rst)
begin
CarrierSense_Rx1 <= #Tp 1'h0;
RxCarrierSense <= #Tp 1'h0;
end
else
begin
CarrierSense_Rx1 <= #Tp mcrs_pad_i;
RxCarrierSense <= #Tp CarrierSense_Rx1;
end
end
 
 
// Delayed WillTransmit
always @ (posedge mrx_clk_pad_i)
begin
WillTransmit_q <= #Tp WillTransmit;
WillTransmit_q2 <= #Tp WillTransmit_q;
end
 
 
assign Transmitting = ~r_FullD & WillTransmit_q2;
 
 
 
// Synchronized Receive Enable
always @ (posedge mrx_clk_pad_i or posedge r_Rst)
begin
if(r_Rst)
RxEnSync <= #Tp 1'b0;
else
if(~RxCarrierSense | RxCarrierSense & Transmitting)
RxEnSync <= #Tp r_RxEn;
end
 
 
 
 
// Connecting Wishbone module
eth_wishbone wishbone
(
.WB_CLK_I(wb_clk_i), .WB_DAT_I(wb_dat_i),
.WB_DAT_O(BD_WB_DAT_O),
 
// WISHBONE slave
.WB_ADR_I(wb_adr_i[9:2]), .WB_WE_I(wb_we_i),
.BDCs(BDCs), .WB_ACK_O(BDAck),
 
.Reset(r_Rst),
 
// WISHBONE master
.m_wb_adr_o(m_wb_adr_o), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o),
.m_wb_dat_i(m_wb_dat_i), .m_wb_dat_o(m_wb_dat_o), .m_wb_cyc_o(m_wb_cyc_o),
.m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i), .m_wb_err_i(m_wb_err_i),
 
//TX
.MTxClk(mtx_clk_pad_i), .TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm),
.TxUsedData(TxUsedData), .TxData(TxData),
.TxRetry(TxRetry), .TxAbort(TxAbort), .TxUnderRun(TxUnderRun),
.TxDone(TxDone), .TPauseRq(TPauseRq), .TxPauseTV(TxPauseTV),
.PerPacketCrcEn(PerPacketCrcEn), .PerPacketPad(PerPacketPad), .WillSendControlFrame(WillSendControlFrame),
.TxCtrlEndFrm(TxCtrlEndFrm),
 
// Register
.r_TxEn(r_TxEn), .r_RxEn(r_RxEn), .r_TxBDNum(r_TxBDNum),
.TX_BD_NUM_Wr(TX_BD_NUM_Wr), .r_RecSmall(r_RecSmall),
 
//RX
.MRxClk(mrx_clk_pad_i), .RxData(RxData), .RxValid(RxValid),
.RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm),
.Busy_IRQ(Busy_IRQ), .RxE_IRQ(RxE_IRQ), .RxB_IRQ(RxB_IRQ),
.TxE_IRQ(TxE_IRQ), .TxB_IRQ(TxB_IRQ), .TxC_IRQ(TxC_IRQ),
.RxC_IRQ(RxC_IRQ),
 
.RxAbort(RxAbort | (ShortFrame & ~r_RecSmall) | LatchedMRxErr & ~InvalidSymbol),
 
.InvalidSymbol(InvalidSymbol), .LatchedCrcError(LatchedCrcError), .RxLength(RxByteCnt),
.RxLateCollision(RxLateCollision), .ShortFrame(ShortFrame), .DribbleNibble(DribbleNibble),
.ReceivedPacketTooBig(ReceivedPacketTooBig), .LoadRxStatus(LoadRxStatus), .RetryCntLatched(RetryCntLatched),
.RetryLimit(RetryLimit), .LateCollLatched(LateCollLatched), .DeferLatched(DeferLatched),
.CarrierSenseLost(CarrierSenseLost),.ReceivedPacketGood(ReceivedPacketGood)
 
 
);
 
 
 
// Connecting MacStatus module
eth_macstatus macstatus1
(
.MRxClk(mrx_clk_pad_i), .Reset(r_Rst),
.ReceiveEnd(ReceiveEnd), .ReceivedPacketGood(ReceivedPacketGood), .ReceivedLengthOK(ReceivedLengthOK),
.RxCrcError(RxCrcError), .MRxErr(MRxErr_Lb), .MRxDV(MRxDV_Lb),
.RxStateSFD(RxStateSFD), .RxStateData(RxStateData), .RxStatePreamble(RxStatePreamble),
.RxStateIdle(RxStateIdle), .Transmitting(Transmitting), .RxByteCnt(RxByteCnt),
.RxByteCntEq0(RxByteCntEq0), .RxByteCntGreat2(RxByteCntGreat2), .RxByteCntMaxFrame(RxByteCntMaxFrame),
.ReceivedPauseFrm(ReceivedPauseFrm),.InvalidSymbol(InvalidSymbol),
.MRxD(MRxD_Lb), .LatchedCrcError(LatchedCrcError), .Collision(mcoll_pad_i),
.CollValid(r_CollValid), .RxLateCollision(RxLateCollision), .r_RecSmall(r_RecSmall),
.r_MinFL(r_MinFL), .r_MaxFL(r_MaxFL), .ShortFrame(ShortFrame),
.DribbleNibble(DribbleNibble), .ReceivedPacketTooBig(ReceivedPacketTooBig), .r_HugEn(r_HugEn),
.LoadRxStatus(LoadRxStatus), .RetryCnt(RetryCnt), .StartTxDone(StartTxDone),
.StartTxAbort(StartTxAbort), .RetryCntLatched(RetryCntLatched), .MTxClk(mtx_clk_pad_i),
.MaxCollisionOccured(MaxCollisionOccured), .RetryLimit(RetryLimit), .LateCollision(LateCollision),
.LateCollLatched(LateCollLatched), .StartDefer(StartDefer), .DeferLatched(DeferLatched),
.TxStartFrm(TxStartFrmOut), .StatePreamble(StatePreamble), .StateData(StateData),
.CarrierSense(CarrierSense_Tx2), .CarrierSenseLost(CarrierSenseLost), .TxUsedData(TxUsedDataIn),
.LatchedMRxErr(LatchedMRxErr)
);
 
 
endmodule
/rtl/verilog/eth_spram_256x32.v
0,0 → 1,139
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_spram_256x32.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
 
`include "timescale.v"
 
 
module eth_spram_256x32(
// Generic synchronous single-port RAM interface
clk, rst, ce, we, oe, addr, di, do
);
 
//
// Generic synchronous single-port RAM interface
//
input clk; // Clock, rising edge
input rst; // Reset, active high
input ce; // Chip enable input, active high
input we; // Write enable input, active high
input oe; // Output enable input, active high
input [7:0] addr; // address bus inputs
input [31:0] di; // input data bus
output [31:0] do; // output data bus
 
 
`ifdef ETH_XILINX_RAMB4
 
RAMB4_S16 ram0
(
.DO (do[15:0]),
.ADDR (addr),
.DI (di[15:0]),
.EN (ce),
.CLK (clk),
.WE (we),
.RST (rst)
);
 
RAMB4_S16 ram1
(
.DO (do[31:16]),
.ADDR (addr),
.DI (di[31:16]),
.EN (ce),
.CLK (clk),
.WE (we),
.RST (rst)
);
 
`else
 
//
// Generic single-port synchronous RAM model
//
 
//
// Generic RAM's registers and wires
//
reg [31:0] mem [255:0]; // RAM content
wire [31:0] q; // RAM output
reg [7:0] raddr; // RAM read address
//
// Data output drivers
//
assign do = (oe & ce) ? q : {32{1'bz}};
 
//
// RAM read and write
//
 
// read operation
always@(posedge clk)
if (ce) // && !we)
raddr <= #1 addr; // read address needs to be registered to read clock
 
assign #1 q = rst ? {32{1'b0}} : mem[raddr];
 
// write operation
always@(posedge clk)
if (ce && we)
mem[addr] <= #1 di;
 
// Task prints range of memory
// *** Remember that tasks are non reentrant, don't call this task in parallel for multiple instantiations.
task print_ram;
input [7:0] start;
input [7:0] finish;
integer rnum;
begin
for (rnum=start;rnum<=finish;rnum=rnum+1)
$display("Addr %h = %h",rnum,mem[rnum]);
end
endtask
 
`endif
 
endmodule
/rtl/verilog/eth_defines.v
0,0 → 1,187
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.18 2002/05/03 10:15:50 mohor
// Outputs registered. Reset changed for eth_wishbone module.
//
// Revision 1.17 2002/04/24 08:52:19 mohor
// Compiler directives added. Tx and Rx fifo size incremented. A "late collision"
// bug fixed.
//
// Revision 1.16 2002/03/19 12:53:29 mohor
// Some defines that are used in testbench only were moved to tb_eth_defines.v
// file.
//
// Revision 1.15 2002/02/26 16:11:32 mohor
// Number of interrupts changed
//
// Revision 1.14 2002/02/16 14:03:44 mohor
// Registered trimmed. Unused registers removed.
//
// Revision 1.13 2002/02/16 13:06:33 mohor
// EXTERNAL_DMA used instead of WISHBONE_DMA.
//
// Revision 1.12 2002/02/15 10:58:31 mohor
// Changed that were lost with last update put back to the file.
//
// Revision 1.11 2002/02/14 20:19:41 billditt
// Modified for Address Checking,
// addition of eth_addrcheck.v
//
// Revision 1.10 2002/02/12 17:01:19 mohor
// HASH0 and HASH1 registers added.
 
// Revision 1.9 2002/02/08 16:21:54 mohor
// Rx status is written back to the BD.
//
// Revision 1.8 2002/02/05 16:44:38 mohor
// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200
// MHz. Statuses, overrun, control frame transmission and reception still need
// to be fixed.
//
// Revision 1.7 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.6 2001/12/05 15:00:16 mohor
// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors
// instead of the number of RX descriptors).
//
// Revision 1.5 2001/12/05 10:21:37 mohor
// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead.
//
// Revision 1.4 2001/11/13 14:23:56 mohor
// Generic memory model is used. Defines are changed for the same reason.
//
// Revision 1.3 2001/10/18 12:07:11 mohor
// Status signals changed, Adress decoding changed, interrupt controller
// added.
//
// Revision 1.2 2001/09/24 15:02:56 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
//`define ETH_FIFO_XILINX // Use Xilinx distributed ram for tx and rx fifo
 
 
// Selection of the used memory for Buffer descriptors
//`define ETH_XILINX_RAMB4 // Core is going to be implemented in Virtex FPGA and contains Virtex
// specific elements.
 
 
 
`define ETH_MODER_ADR 8'h0 // 0x0
`define ETH_INT_SOURCE_ADR 8'h1 // 0x4
`define ETH_INT_MASK_ADR 8'h2 // 0x8
`define ETH_IPGT_ADR 8'h3 // 0xC
`define ETH_IPGR1_ADR 8'h4 // 0x10
`define ETH_IPGR2_ADR 8'h5 // 0x14
`define ETH_PACKETLEN_ADR 8'h6 // 0x18
`define ETH_COLLCONF_ADR 8'h7 // 0x1C
`define ETH_TX_BD_NUM_ADR 8'h8 // 0x20
`define ETH_CTRLMODER_ADR 8'h9 // 0x24
`define ETH_MIIMODER_ADR 8'hA // 0x28
`define ETH_MIICOMMAND_ADR 8'hB // 0x2C
`define ETH_MIIADDRESS_ADR 8'hC // 0x30
`define ETH_MIITX_DATA_ADR 8'hD // 0x34
`define ETH_MIIRX_DATA_ADR 8'hE // 0x38
`define ETH_MIISTATUS_ADR 8'hF // 0x3C
`define ETH_MAC_ADDR0_ADR 8'h10 // 0x40
`define ETH_MAC_ADDR1_ADR 8'h11 // 0x44
`define ETH_HASH0_ADR 8'h12 // 0x48
`define ETH_HASH1_ADR 8'h13 // 0x4C
 
 
`define ETH_MODER_DEF 17'h0A800
`define ETH_INT_SOURCE_DEF 32'h00000000
`define ETH_INT_MASK_DEF 7'h0
`define ETH_IPGT_DEF 7'h12
`define ETH_IPGR1_DEF 7'h0C
`define ETH_IPGR2_DEF 7'h12
`define ETH_PACKETLEN_DEF 32'h00400600
`define ETH_COLLCONF0_DEF 6'h3f
`define ETH_COLLCONF1_DEF 4'hF
`define ETH_TX_BD_NUM_DEF 8'h80
`define ETH_CTRLMODER_DEF 3'h0
`define ETH_MIIMODER_DEF 11'h064
`define ETH_MIIADDRESS0_DEF 5'h00
`define ETH_MIIADDRESS1_DEF 5'h00
`define ETH_MIITX_DATA_DEF 16'h0000
`define ETH_MIIRX_DATA_DEF 16'h0000
`define ETH_MIISTATUS_DEF 32'h00000000
`define ETH_MAC_ADDR0_DEF 32'h00000000
`define ETH_MAC_ADDR1_DEF 16'h0000
`define ETH_HASH0_DEF 32'h00000000
`define ETH_HASH1_DEF 32'h00000000
 
 
// Outputs are registered (uncomment when needed)
`define ETH_REGISTERED_OUTPUTS
 
`define TX_FIFO_CNT_WIDTH 5
`define TX_FIFO_DEPTH 16
`define TX_FIFO_DATA_WIDTH 32
 
`define RX_FIFO_CNT_WIDTH 5
`define RX_FIFO_DEPTH 16
`define RX_FIFO_DATA_WIDTH 32
/rtl/verilog/eth_outputcontrol.v
0,0 → 1,147
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_outputcontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/01 22:28:56 mohor
// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
//
//
 
`include "timescale.v"
 
module eth_outputcontrol(Clk, Reset, InProgress, ShiftedBit, BitCounter, WriteOp, NoPre, MdcEn_n, Mdo, MdoEn);
 
parameter Tp = 1;
 
input Clk; // Host Clock
input Reset; // General Reset
input WriteOp; // Write Operation Latch (When asserted, write operation is in progress)
input NoPre; // No Preamble (no 32-bit preamble)
input InProgress; // Operation in progress
input ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal
input [6:0] BitCounter; // Bit Counter
input MdcEn_n; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc falls.
 
output Mdo; // MII Management Data Output
output MdoEn; // MII Management Data Output Enable
 
wire SerialEn;
 
reg MdoEn_2d;
reg MdoEn_d;
reg MdoEn;
 
reg Mdo_2d;
reg Mdo_d;
reg Mdo; // MII Management Data Output
 
 
 
// Generation of the Serial Enable signal (enables the serialization of the data)
assign SerialEn = WriteOp & InProgress & ( BitCounter>31 | ( ( BitCounter == 0 ) & NoPre ) )
| ~WriteOp & InProgress & (( BitCounter>31 & BitCounter<46 ) | ( ( BitCounter == 0 ) & NoPre ));
 
 
// Generation of the MdoEn signal
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
MdoEn_2d <= #Tp 1'b0;
MdoEn_d <= #Tp 1'b0;
MdoEn <= #Tp 1'b0;
end
else
begin
if(MdcEn_n)
begin
MdoEn_2d <= #Tp SerialEn | InProgress & BitCounter<32;
MdoEn_d <= #Tp MdoEn_2d;
MdoEn <= #Tp MdoEn_d;
end
end
end
 
 
// Generation of the Mdo signal.
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
Mdo_2d <= #Tp 1'b0;
Mdo_d <= #Tp 1'b0;
Mdo <= #Tp 1'b0;
end
else
begin
if(MdcEn_n)
begin
Mdo_2d <= #Tp ~SerialEn & BitCounter<32;
Mdo_d <= #Tp ShiftedBit | Mdo_2d;
Mdo <= #Tp Mdo_d;
end
end
end
 
 
 
endmodule
/rtl/verilog/eth_txcounters.v
0,0 → 1,218
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txcounters.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.4 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.4 2001/06/27 21:27:45 mohor
// Few typos fixed.
//
// Revision 1.2 2001/06/19 10:38:07 mohor
// Minor changes in header.
//
// Revision 1.1 2001/06/19 10:27:57 mohor
// TxEthMAC initial release.
//
//
//
 
 
`include "timescale.v"
 
 
module eth_txcounters (StatePreamble, StateIPG, StateData, StatePAD, StateFCS, StateJam,
StateBackOff, StateDefer, StateIdle, StartDefer, StartIPG, StartFCS,
StartJam, StartBackoff, TxStartFrm, MTxClk, Reset, MinFL, MaxFL, HugEn,
ExDfrEn, PacketFinished_q, DlyCrcEn, StateSFD, ByteCnt, NibCnt,
ExcessiveDefer, NibCntEq7, NibCntEq15, MaxFrame, NibbleMinFl, DlyCrcCnt
);
 
parameter Tp = 1;
 
input MTxClk; // Tx clock
input Reset; // Reset
input StatePreamble; // Preamble state
input StateIPG; // IPG state
input [1:0] StateData; // Data state
input StatePAD; // PAD state
input StateFCS; // FCS state
input StateJam; // Jam state
input StateBackOff; // Backoff state
input StateDefer; // Defer state
input StateIdle; // Idle state
input StateSFD; // SFD state
input StartDefer; // Defer state will be activated in next clock
input StartIPG; // IPG state will be activated in next clock
input StartFCS; // FCS state will be activated in next clock
input StartJam; // Jam state will be activated in next clock
input StartBackoff; // Backoff state will be activated in next clock
input TxStartFrm; // Tx start frame
input [15:0] MinFL; // Minimum frame length (in bytes)
input [15:0] MaxFL; // Miximum frame length (in bytes)
input HugEn; // Pakets bigger then MaxFL enabled
input ExDfrEn; // Excessive deferral enabled
input PacketFinished_q;
input DlyCrcEn; // Delayed CRC enabled
 
output [15:0] ByteCnt; // Byte counter
output [15:0] NibCnt; // Nibble counter
output ExcessiveDefer; // Excessive Deferral occuring
output NibCntEq7; // Nibble counter is equal to 7
output NibCntEq15; // Nibble counter is equal to 15
output MaxFrame; // Maximum frame occured
output NibbleMinFl; // Nibble counter is greater than the minimum frame length
output [2:0] DlyCrcCnt; // Delayed CRC Count
 
wire ExcessiveDeferCnt;
wire ResetNibCnt;
wire IncrementNibCnt;
wire ResetByteCnt;
wire IncrementByteCnt;
wire ByteCntMax;
 
reg [15:0] NibCnt;
reg [15:0] ByteCnt;
reg [2:0] DlyCrcCnt;
 
 
 
assign IncrementNibCnt = StateIPG | StatePreamble | (|StateData) & ~|DlyCrcCnt[2:0] | StatePAD
| StateFCS | StateJam | StateBackOff | StateDefer & ~ExcessiveDefer & TxStartFrm;
 
 
assign ResetNibCnt = StateDefer & ExcessiveDefer & ~TxStartFrm | StatePreamble & NibCntEq15
| StateJam & NibCntEq7 | StateIdle | StartDefer | StartIPG | StartFCS | StartJam;
 
// Nibble Counter
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
NibCnt <= #Tp 16'h0;
else
begin
if(ResetNibCnt)
NibCnt <= #Tp 16'h0;
else
if(IncrementNibCnt)
NibCnt <= #Tp NibCnt + 1'b1;
end
end
 
 
assign NibCntEq7 = &NibCnt[2:0];
assign NibCntEq15 = &NibCnt[3:0];
 
assign NibbleMinFl = NibCnt >= (((MinFL-3'h4)<<1) -1); // FCS should not be included in NibbleMinFl
 
assign ExcessiveDeferCnt = NibCnt[13:0] == 16'h17b7;
 
assign ExcessiveDefer = NibCnt[13:0] == 16'h17b7 & ~ExDfrEn; // 6071 nibbles
 
assign IncrementByteCnt = StateData[1] & ~ByteCntMax & ~|DlyCrcCnt[2:0]
| StateBackOff & (&NibCnt[6:0])
| (StatePAD | StateFCS) & NibCnt[0] & ~ByteCntMax;
 
assign ResetByteCnt = StartBackoff | StateIdle & TxStartFrm | PacketFinished_q;
 
 
// Transmit Byte Counter
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
ByteCnt[15:0] <= #Tp 16'h0;
else
begin
if(ResetByteCnt)
ByteCnt[15:0] <= #Tp 16'h0;
else
if(IncrementByteCnt)
ByteCnt[15:0] <= #Tp ByteCnt[15:0] + 1'b1;
end
end
 
 
assign MaxFrame = ByteCnt[15:0] == MaxFL[15:0] & ~HugEn;
 
assign ByteCntMax = &ByteCnt[15:0];
 
 
// Delayed CRC counter
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
DlyCrcCnt <= #Tp 3'h0;
else
begin
if(StateData[1] & DlyCrcCnt == 3'h4 | StartJam | PacketFinished_q)
DlyCrcCnt <= #Tp 3'h0;
else
if(DlyCrcEn & (StateSFD | StateData[1] & (|DlyCrcCnt[2:0])))
DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1;
end
end
 
 
 
endmodule
/rtl/verilog/eth_registers.v
0,0 → 1,549
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_registers.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.13 2002/02/26 16:18:09 mohor
// Reset values are passed to registers through parameters
//
// Revision 1.12 2002/02/17 13:23:42 mohor
// Define missmatch fixed.
//
// Revision 1.11 2002/02/16 14:03:44 mohor
// Registered trimmed. Unused registers removed.
//
// Revision 1.10 2002/02/15 11:08:25 mohor
// File format fixed a bit.
//
// Revision 1.9 2002/02/14 20:19:41 billditt
// Modified for Address Checking,
// addition of eth_addrcheck.v
//
// Revision 1.8 2002/02/12 17:01:19 mohor
// HASH0 and HASH1 registers added.
 
// Revision 1.7 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.6 2001/12/05 15:00:16 mohor
// RX_BD_NUM changed to TX_BD_NUM (holds number of TX descriptors
// instead of the number of RX descriptors).
//
// Revision 1.5 2001/12/05 10:22:19 mohor
// ETH_RX_BD_ADR register deleted. ETH_RX_BD_NUM is used instead.
//
// Revision 1.4 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.3 2001/10/18 12:07:11 mohor
// Status signals changed, Adress decoding changed, interrupt controller
// added.
//
// Revision 1.2 2001/09/24 15:02:56 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.2 2001/08/02 09:25:31 mohor
// Unconnected signals are now connected.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
//
 
`include "eth_defines.v"
`include "timescale.v"
 
 
module eth_registers( DataIn, Address, Rw, Cs, Clk, Reset, DataOut,
r_RecSmall, r_Pad, r_HugEn, r_CrcEn, r_DlyCrcEn,
r_Rst, r_FullD, r_ExDfrEn, r_NoBckof, r_LoopBck, r_IFG,
r_Pro, r_Iam, r_Bro, r_NoPre, r_TxEn, r_RxEn,
TxB_IRQ, TxE_IRQ, RxB_IRQ, RxE_IRQ, Busy_IRQ, TxC_IRQ, RxC_IRQ,
r_IPGT, r_IPGR1, r_IPGR2, r_MinFL, r_MaxFL, r_MaxRet,
r_CollValid, r_TxFlow, r_RxFlow, r_PassAll,
r_MiiMRst, r_MiiNoPre, r_ClkDiv, r_WCtrlData, r_RStat, r_ScanStat,
r_RGAD, r_FIAD, r_CtrlData, NValid_stat, Busy_stat,
LinkFail, r_MAC, WCtrlDataStart, RStatStart,
UpdateMIIRX_DATAReg, Prsd, r_TxBDNum, TX_BD_NUM_Wr, int_o,
r_HASH0, r_HASH1
);
 
parameter Tp = 1;
 
input [31:0] DataIn;
input [7:0] Address;
 
input Rw;
input Cs;
input Clk;
input Reset;
 
input WCtrlDataStart;
input RStatStart;
 
input UpdateMIIRX_DATAReg;
input [15:0] Prsd;
 
output [31:0] DataOut;
reg [31:0] DataOut;
 
output r_RecSmall;
output r_Pad;
output r_HugEn;
output r_CrcEn;
output r_DlyCrcEn;
output r_Rst;
output r_FullD;
output r_ExDfrEn;
output r_NoBckof;
output r_LoopBck;
output r_IFG;
output r_Pro;
output r_Iam;
output r_Bro;
output r_NoPre;
output r_TxEn;
output r_RxEn;
output [31:0] r_HASH0;
output [31:0] r_HASH1;
 
input TxB_IRQ;
input TxE_IRQ;
input RxB_IRQ;
input RxE_IRQ;
input Busy_IRQ;
input TxC_IRQ;
input RxC_IRQ;
 
output [6:0] r_IPGT;
 
output [6:0] r_IPGR1;
 
output [6:0] r_IPGR2;
 
output [15:0] r_MinFL;
output [15:0] r_MaxFL;
 
output [3:0] r_MaxRet;
output [5:0] r_CollValid;
 
output r_TxFlow;
output r_RxFlow;
output r_PassAll;
 
output r_MiiMRst;
output r_MiiNoPre;
output [7:0] r_ClkDiv;
 
output r_WCtrlData;
output r_RStat;
output r_ScanStat;
 
output [4:0] r_RGAD;
output [4:0] r_FIAD;
 
output [15:0]r_CtrlData;
 
 
input NValid_stat;
input Busy_stat;
input LinkFail;
 
output [47:0]r_MAC;
output [7:0] r_TxBDNum;
output TX_BD_NUM_Wr;
output int_o;
 
reg irq_txb;
reg irq_txe;
reg irq_rxb;
reg irq_rxe;
reg irq_busy;
reg irq_txc;
reg irq_rxc;
 
wire Write = Cs & Rw;
wire Read = Cs & ~Rw;
 
wire MODER_Wr = (Address == `ETH_MODER_ADR ) & Write;
wire INT_SOURCE_Wr = (Address == `ETH_INT_SOURCE_ADR ) & Write;
wire INT_MASK_Wr = (Address == `ETH_INT_MASK_ADR ) & Write;
wire IPGT_Wr = (Address == `ETH_IPGT_ADR ) & Write;
wire IPGR1_Wr = (Address == `ETH_IPGR1_ADR ) & Write;
wire IPGR2_Wr = (Address == `ETH_IPGR2_ADR ) & Write;
wire PACKETLEN_Wr = (Address == `ETH_PACKETLEN_ADR ) & Write;
wire COLLCONF_Wr = (Address == `ETH_COLLCONF_ADR ) & Write;
wire CTRLMODER_Wr = (Address == `ETH_CTRLMODER_ADR ) & Write;
wire MIIMODER_Wr = (Address == `ETH_MIIMODER_ADR ) & Write;
wire MIICOMMAND_Wr = (Address == `ETH_MIICOMMAND_ADR ) & Write;
wire MIIADDRESS_Wr = (Address == `ETH_MIIADDRESS_ADR ) & Write;
wire MIITX_DATA_Wr = (Address == `ETH_MIITX_DATA_ADR ) & Write;
wire MIIRX_DATA_Wr = UpdateMIIRX_DATAReg;
wire MIISTATUS_Wr = (Address == `ETH_MIISTATUS_ADR ) & Write;
wire MAC_ADDR0_Wr = (Address == `ETH_MAC_ADDR0_ADR ) & Write;
wire MAC_ADDR1_Wr = (Address == `ETH_MAC_ADDR1_ADR ) & Write;
wire HASH0_Wr = (Address == `ETH_HASH0_ADR ) & Write;
wire HASH1_Wr = (Address == `ETH_HASH1_ADR ) & Write;
assign TX_BD_NUM_Wr = (Address == `ETH_TX_BD_NUM_ADR ) & Write;
 
 
 
wire [31:0] MODEROut;
wire [31:0] INT_SOURCEOut;
wire [31:0] INT_MASKOut;
wire [31:0] IPGTOut;
wire [31:0] IPGR1Out;
wire [31:0] IPGR2Out;
wire [31:0] PACKETLENOut;
wire [31:0] COLLCONFOut;
wire [31:0] CTRLMODEROut;
wire [31:0] MIIMODEROut;
wire [31:0] MIICOMMANDOut;
wire [31:0] MIIADDRESSOut;
wire [31:0] MIITX_DATAOut;
wire [31:0] MIIRX_DATAOut;
wire [31:0] MIISTATUSOut;
wire [31:0] MAC_ADDR0Out;
wire [31:0] MAC_ADDR1Out;
wire [31:0] TX_BD_NUMOut;
wire [31:0] HASH0Out;
wire [31:0] HASH1Out;
 
 
eth_register #(17, `ETH_MODER_DEF) MODER (.DataIn(DataIn[16:0]), .DataOut(MODEROut[16:0]), .Write(MODER_Wr), .Clk(Clk), .Reset(Reset));
assign MODEROut[31:17] = 0;
 
eth_register #(7, `ETH_INT_MASK_DEF) INT_MASK (.DataIn(DataIn[6:0]), .DataOut(INT_MASKOut[6:0]), .Write(INT_MASK_Wr), .Clk(Clk), .Reset(Reset));
assign INT_MASKOut[31:7] = 0;
 
eth_register #(7, `ETH_IPGT_DEF) IPGT (.DataIn(DataIn[6:0]), .DataOut(IPGTOut[6:0]), .Write(IPGT_Wr), .Clk(Clk), .Reset(Reset));
assign IPGTOut[31:7] = 0;
 
eth_register #(7, `ETH_IPGR1_DEF) IPGR1 (.DataIn(DataIn[6:0]), .DataOut(IPGR1Out[6:0]), .Write(IPGR1_Wr), .Clk(Clk), .Reset(Reset));
assign IPGR1Out[31:7] = 0;
 
eth_register #(7, `ETH_IPGR2_DEF) IPGR2 (.DataIn(DataIn[6:0]), .DataOut(IPGR2Out[6:0]), .Write(IPGR2_Wr), .Clk(Clk), .Reset(Reset));
assign IPGR2Out[31:7] = 0;
 
eth_register #(32, `ETH_PACKETLEN_DEF) PACKETLEN (.DataIn(DataIn), .DataOut(PACKETLENOut), .Write(PACKETLEN_Wr), .Clk(Clk), .Reset(Reset));
 
eth_register #(6, `ETH_COLLCONF0_DEF) COLLCONF0 (.DataIn(DataIn[5:0]), .DataOut(COLLCONFOut[5:0]), .Write(COLLCONF_Wr), .Clk(Clk), .Reset(Reset));
eth_register #(4, `ETH_COLLCONF1_DEF) COLLCONF1 (.DataIn(DataIn[19:16]),.DataOut(COLLCONFOut[19:16]), .Write(COLLCONF_Wr), .Clk(Clk), .Reset(Reset));
assign COLLCONFOut[15:6] = 0;
assign COLLCONFOut[31:20] = 0;
 
eth_register #(8, `ETH_TX_BD_NUM_DEF) TX_BD_NUM (.DataIn(DataIn[7:0]), .DataOut(TX_BD_NUMOut[7:0]), .Write(TX_BD_NUM_Wr), .Clk(Clk), .Reset(Reset));
assign TX_BD_NUMOut[31:8] = 24'h0;
 
eth_register #(3, `ETH_CTRLMODER_DEF) CTRLMODER2 (.DataIn(DataIn[2:0]), .DataOut(CTRLMODEROut[2:0]), .Write(CTRLMODER_Wr), .Clk(Clk), .Reset(Reset));
assign CTRLMODEROut[31:3] = 29'h0;
 
eth_register #(11, `ETH_MIIMODER_DEF) MIIMODER (.DataIn(DataIn[10:0]), .DataOut(MIIMODEROut[10:0]), .Write(MIIMODER_Wr), .Clk(Clk), .Reset(Reset));
assign MIIMODEROut[31:11] = 0;
 
eth_register #(1, 0) MIICOMMAND2 (.DataIn(DataIn[2]), .DataOut(MIICOMMANDOut[2]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset | WCtrlDataStart));
eth_register #(1, 0) MIICOMMAND1 (.DataIn(DataIn[1]), .DataOut(MIICOMMANDOut[1]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset | RStatStart));
eth_register #(1, 0) MIICOMMAND0 (.DataIn(DataIn[0]), .DataOut(MIICOMMANDOut[0]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset));
assign MIICOMMANDOut[31:3] = 29'h0;
 
eth_register #(5, `ETH_MIIADDRESS0_DEF) MIIADDRESS0 (.DataIn(DataIn[4:0]), .DataOut(MIIADDRESSOut[4:0]), .Write(MIIADDRESS_Wr), .Clk(Clk), .Reset(Reset));
eth_register #(5, `ETH_MIIADDRESS1_DEF) MIIADDRESS1 (.DataIn(DataIn[12:8]), .DataOut(MIIADDRESSOut[12:8]),.Write(MIIADDRESS_Wr), .Clk(Clk), .Reset(Reset));
assign MIIADDRESSOut[7:5] = 0;
assign MIIADDRESSOut[31:13] = 0;
 
eth_register #(16, `ETH_MIITX_DATA_DEF) MIITX_DATA (.DataIn(DataIn[15:0]), .DataOut(MIITX_DATAOut[15:0]),.Write(MIITX_DATA_Wr), .Clk(Clk), .Reset(Reset));
assign MIITX_DATAOut[31:16] = 0;
 
eth_register #(16, `ETH_MIIRX_DATA_DEF) MIIRX_DATA (.DataIn(Prsd[15:0]), .DataOut(MIIRX_DATAOut[15:0]),.Write(MIIRX_DATA_Wr), .Clk(Clk), .Reset(Reset));
assign MIIRX_DATAOut[31:16] = 0;
 
eth_register #(32, `ETH_MAC_ADDR0_DEF) MAC_ADDR0 (.DataIn(DataIn), .DataOut(MAC_ADDR0Out), .Write(MAC_ADDR0_Wr), .Clk(Clk), .Reset(Reset));
eth_register #(16, `ETH_MAC_ADDR1_DEF) MAC_ADDR1 (.DataIn(DataIn[15:0]), .DataOut(MAC_ADDR1Out[15:0]), .Write(MAC_ADDR1_Wr), .Clk(Clk), .Reset(Reset));
assign MAC_ADDR1Out[31:16] = 0;
 
 
eth_register #(32, `ETH_HASH0_DEF) RXHASH0 (.DataIn(DataIn), .DataOut(HASH0Out), .Write(HASH0_Wr), .Clk(Clk), .Reset(Reset));
eth_register #(32, `ETH_HASH1_DEF) RXHASH1 (.DataIn(DataIn), .DataOut(HASH1Out), .Write(HASH1_Wr), .Clk(Clk), .Reset(Reset));
 
 
reg LinkFailRegister;
wire ResetLinkFailRegister = Address == `ETH_MIISTATUS_ADR & Read;
reg ResetLinkFailRegister_q1;
reg ResetLinkFailRegister_q2;
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
LinkFailRegister <= #Tp 0;
ResetLinkFailRegister_q1 <= #Tp 0;
ResetLinkFailRegister_q2 <= #Tp 0;
end
else
begin
ResetLinkFailRegister_q1 <= #Tp ResetLinkFailRegister;
ResetLinkFailRegister_q2 <= #Tp ResetLinkFailRegister_q1;
if(LinkFail)
LinkFailRegister <= #Tp 1;
if(~ResetLinkFailRegister_q1 & ResetLinkFailRegister_q2)
LinkFailRegister <= #Tp 0;
end
end
 
 
always @ (Address or Read or MODEROut or INT_SOURCEOut or INT_MASKOut or IPGTOut or
IPGR1Out or IPGR2Out or PACKETLENOut or COLLCONFOut or CTRLMODEROut or
MIIMODEROut or MIICOMMANDOut or MIIADDRESSOut or MIITX_DATAOut or
MIIRX_DATAOut or MIISTATUSOut or MAC_ADDR0Out or MAC_ADDR1Out or
TX_BD_NUMOut or HASH0Out or HASH1Out)
begin
if(Read) // read
begin
case(Address)
`ETH_MODER_ADR : DataOut<=MODEROut;
`ETH_INT_SOURCE_ADR : DataOut<=INT_SOURCEOut;
`ETH_INT_MASK_ADR : DataOut<=INT_MASKOut;
`ETH_IPGT_ADR : DataOut<=IPGTOut;
`ETH_IPGR1_ADR : DataOut<=IPGR1Out;
`ETH_IPGR2_ADR : DataOut<=IPGR2Out;
`ETH_PACKETLEN_ADR : DataOut<=PACKETLENOut;
`ETH_COLLCONF_ADR : DataOut<=COLLCONFOut;
`ETH_CTRLMODER_ADR : DataOut<=CTRLMODEROut;
`ETH_MIIMODER_ADR : DataOut<=MIIMODEROut;
`ETH_MIICOMMAND_ADR : DataOut<=MIICOMMANDOut;
`ETH_MIIADDRESS_ADR : DataOut<=MIIADDRESSOut;
`ETH_MIITX_DATA_ADR : DataOut<=MIITX_DATAOut;
`ETH_MIIRX_DATA_ADR : DataOut<=MIIRX_DATAOut;
`ETH_MIISTATUS_ADR : DataOut<=MIISTATUSOut;
`ETH_MAC_ADDR0_ADR : DataOut<=MAC_ADDR0Out;
`ETH_MAC_ADDR1_ADR : DataOut<=MAC_ADDR1Out;
`ETH_TX_BD_NUM_ADR : DataOut<=TX_BD_NUMOut;
`ETH_HASH0_ADR : DataOut<=HASH0Out;
`ETH_HASH1_ADR : DataOut<=HASH1Out;
default: DataOut<=32'h0;
endcase
end
else
DataOut<=32'h0;
end
 
 
assign r_RecSmall = MODEROut[16];
assign r_Pad = MODEROut[15];
assign r_HugEn = MODEROut[14];
assign r_CrcEn = MODEROut[13];
assign r_DlyCrcEn = MODEROut[12];
assign r_Rst = MODEROut[11];
assign r_FullD = MODEROut[10];
assign r_ExDfrEn = MODEROut[9];
assign r_NoBckof = MODEROut[8];
assign r_LoopBck = MODEROut[7];
assign r_IFG = MODEROut[6];
assign r_Pro = MODEROut[5];
assign r_Iam = MODEROut[4];
assign r_Bro = MODEROut[3];
assign r_NoPre = MODEROut[2];
assign r_TxEn = MODEROut[1];
assign r_RxEn = MODEROut[0];
 
assign r_IPGT[6:0] = IPGTOut[6:0];
 
assign r_IPGR1[6:0] = IPGR1Out[6:0];
 
assign r_IPGR2[6:0] = IPGR2Out[6:0];
 
assign r_MinFL[15:0] = PACKETLENOut[31:16];
assign r_MaxFL[15:0] = PACKETLENOut[15:0];
 
assign r_MaxRet[3:0] = COLLCONFOut[19:16];
assign r_CollValid[5:0] = COLLCONFOut[5:0];
 
assign r_TxFlow = CTRLMODEROut[2];
assign r_RxFlow = CTRLMODEROut[1];
assign r_PassAll = CTRLMODEROut[0];
 
assign r_MiiMRst = MIIMODEROut[10];
assign r_MiiNoPre = MIIMODEROut[8];
assign r_ClkDiv[7:0] = MIIMODEROut[7:0];
 
assign r_WCtrlData = MIICOMMANDOut[2];
assign r_RStat = MIICOMMANDOut[1];
assign r_ScanStat = MIICOMMANDOut[0];
 
assign r_RGAD[4:0] = MIIADDRESSOut[12:8];
assign r_FIAD[4:0] = MIIADDRESSOut[4:0];
 
assign r_CtrlData[15:0] = MIITX_DATAOut[15:0];
 
assign MIISTATUSOut[31:10] = 22'h0 ;
assign MIISTATUSOut[9] = NValid_stat ;
assign MIISTATUSOut[8] = Busy_stat ;
assign MIISTATUSOut[7:1]= 7'h0 ;
assign MIISTATUSOut[0] = LinkFailRegister ;
 
assign r_MAC[31:0] = MAC_ADDR0Out[31:0];
assign r_MAC[47:32] = MAC_ADDR1Out[15:0];
assign r_HASH1[31:0] = HASH1Out;
assign r_HASH0[31:0] = HASH0Out;
 
assign r_TxBDNum[7:0] = TX_BD_NUMOut[7:0];
 
 
// Interrupt generation
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_txb <= 1'b0;
else
if(TxB_IRQ)
irq_txb <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[0])
irq_txb <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_txe <= 1'b0;
else
if(TxE_IRQ)
irq_txe <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[1])
irq_txe <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_rxb <= 1'b0;
else
if(RxB_IRQ)
irq_rxb <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[2])
irq_rxb <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_rxe <= 1'b0;
else
if(RxE_IRQ)
irq_rxe <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[3])
irq_rxe <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_busy <= 1'b0;
else
if(Busy_IRQ)
irq_busy <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[4])
irq_busy <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_txc <= 1'b0;
else
if(TxC_IRQ)
irq_txc <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[5])
irq_txc <= #Tp 1'b0;
end
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
irq_rxc <= 1'b0;
else
if(RxC_IRQ)
irq_rxc <= #Tp 1'b1;
else
if(INT_SOURCE_Wr & DataIn[6])
irq_rxc <= #Tp 1'b0;
end
 
// Generating interrupt signal
assign int_o = irq_txb & INT_MASKOut[0] |
irq_txe & INT_MASKOut[1] |
irq_rxb & INT_MASKOut[2] |
irq_rxe & INT_MASKOut[3] |
irq_busy & INT_MASKOut[4] |
irq_txc & INT_MASKOut[5] |
irq_rxc & INT_MASKOut[6] ;
 
// For reading interrupt status
assign INT_SOURCEOut = {26'h0, irq_rxc, irq_txc, irq_busy, irq_rxe, irq_rxb, irq_txe, irq_txb};
 
 
 
endmodule
/rtl/verilog/eth_fifo.v
0,0 → 1,159
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_fifo.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/03/25 13:33:04 mohor
// When clear and read/write are active at the same time, cnt and pointers are
// set to 1.
//
// Revision 1.1 2002/02/05 16:44:39 mohor
// Both rx and tx part are finished. Tested with wb_clk_i between 10 and 200
// MHz. Statuses, overrun, control frame transmission and reception still need
// to be fixed.
//
//
 
`include "eth_defines.v"
`include "timescale.v"
 
module eth_fifo (data_in, data_out, clk, reset, write, read, clear, almost_full, full, almost_empty, empty, cnt);
 
parameter DATA_WIDTH = 32;
parameter DEPTH = 8;
parameter CNT_WIDTH = 4;
 
parameter Tp = 1;
 
input clk;
input reset;
input write;
input read;
input clear;
input [DATA_WIDTH-1:0] data_in;
 
output [DATA_WIDTH-1:0] data_out;
output almost_full;
output full;
output almost_empty;
output empty;
output [CNT_WIDTH-1:0] cnt;
 
`ifdef ETH_FIFO_XILINX
`else
reg [DATA_WIDTH-1:0] fifo [0:DEPTH-1];
`endif
 
reg [CNT_WIDTH-1:0] cnt;
reg [CNT_WIDTH-2:0] read_pointer;
reg [CNT_WIDTH-2:0] write_pointer;
 
 
always @ (posedge clk or posedge reset)
begin
if(reset)
cnt <=#Tp 0;
else
if(clear)
cnt <=#Tp { {(CNT_WIDTH-1){1'b0}}, read^write};
else
if(read ^ write)
if(read)
cnt <=#Tp cnt - 1'b1;
else
cnt <=#Tp cnt + 1'b1;
end
 
always @ (posedge clk or posedge reset)
begin
if(reset)
read_pointer <=#Tp 0;
else
if(clear)
read_pointer <=#Tp { {(CNT_WIDTH-2){1'b0}}, read};
else
if(read & ~empty)
read_pointer <=#Tp read_pointer + 1'b1;
end
 
always @ (posedge clk or posedge reset)
begin
if(reset)
write_pointer <=#Tp 0;
else
if(clear)
write_pointer <=#Tp { {(CNT_WIDTH-2){1'b0}}, write};
else
if(write & ~full)
write_pointer <=#Tp write_pointer + 1'b1;
end
 
assign empty = ~(|cnt);
assign almost_empty = cnt == 1;
assign full = cnt == DEPTH;
assign almost_full = &cnt[CNT_WIDTH-2:0];
 
 
 
`ifdef ETH_FIFO_XILINX
xilinx_dist_ram_16x32 fifo
( .data_out(data_out),
.we(write & ~full),
.data_in(data_in),
.read_address( clear ? {CNT_WIDTH-1{1'b0}} : read_pointer),
.write_address(clear ? {CNT_WIDTH-1{1'b0}} : write_pointer),
.wclk(clk)
);
`else
always @ (posedge clk)
begin
if(write & clear)
fifo[0] <=#Tp data_in;
else
if(write & ~full)
fifo[write_pointer] <=#Tp data_in;
end
assign data_out = clear ? fifo[0] : fifo[read_pointer];
`endif
 
 
endmodule
/rtl/verilog/eth_rxaddrcheck.v
0,0 → 1,194
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxaddrcheck.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/ethmac/ ////
//// ////
//// Author(s): ////
//// - Bill Dittenhofer (billditt@aol.com) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.5 2002/03/02 21:06:32 mohor
// Log info was missing.
//
//
// Revision 1.1 2002/02/08 12:51:54 ditt
// Initial release of the ethernet addresscheck module.
//
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_rxaddrcheck(MRxClk, Reset, RxData, Broadcast ,r_Bro ,r_Pro,
ByteCntEq2, ByteCntEq3, ByteCntEq4, ByteCntEq5,
ByteCntEq6, ByteCntEq7, HASH0, HASH1,
CrcHash, CrcHashGood, StateData, RxEndFrm,
Multicast, MAC, RxAbort
);
 
parameter Tp = 1;
 
input MRxClk;
input Reset;
input [7:0] RxData;
input Broadcast;
input r_Bro;
input r_Pro;
input ByteCntEq2;
input ByteCntEq3;
input ByteCntEq4;
input ByteCntEq5;
input ByteCntEq6;
input ByteCntEq7;
input [31:0] HASH0;
input [31:0] HASH1;
input [5:0] CrcHash;
input CrcHashGood;
input Multicast;
input [47:0] MAC;
input [1:0] StateData;
input RxEndFrm;
output RxAbort;
 
 
wire BroadcastOK;
wire ByteCntEq2;
wire ByteCntEq3;
wire ByteCntEq4;
wire ByteCntEq5;
wire RxAddressInvalid;
wire RxCheckEn;
wire HashBit;
wire [31:0] IntHash;
reg [7:0] ByteHash;
reg MulticastOK;
reg UnicastOK;
reg RxAbort;
reg CrcHashGood_d; // delay HashGood by one cycle
assign RxAddressInvalid = ~(UnicastOK | BroadcastOK | MulticastOK | r_Pro);
assign BroadcastOK = Broadcast & ~r_Bro;
assign RxCheckEn = | StateData;
// Address Error Reported at end of address cycle
// RxAbort clears after one cycle
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
RxAbort <= #Tp 1'b0;
else if(CrcHashGood_d & RxAddressInvalid & RxCheckEn)
RxAbort <= #Tp 1'b1;
else
RxAbort <= #Tp 1'b0;
end
// Hash Address Check, Multicast
 
 
// delay CrcHashGood by 1 cycle
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
CrcHashGood_d <= #Tp 1'b0;
else
CrcHashGood_d <= #Tp CrcHashGood;
end
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
MulticastOK <= #Tp 1'b0;
else if(RxEndFrm | RxAbort)
MulticastOK <= #Tp 1'b0;
else if(CrcHashGood & Multicast)
MulticastOK <= #Tp HashBit;
end
// Address Detection (unicast)
// start with ByteCntEq2 due to delay of addres from RxData
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
UnicastOK <= #Tp 1'b0;
else
if(RxCheckEn & ByteCntEq2)
UnicastOK <= #Tp RxData[7:0] == MAC[47:40];
else
if(RxCheckEn & ByteCntEq3)
UnicastOK <= #Tp ( RxData[7:0] == MAC[39:32]) & UnicastOK;
else
if(RxCheckEn & ByteCntEq4)
UnicastOK <= #Tp ( RxData[7:0] == MAC[31:24]) & UnicastOK;
else
if(RxCheckEn & ByteCntEq5)
UnicastOK <= #Tp ( RxData[7:0] == MAC[23:16]) & UnicastOK;
else
if(RxCheckEn & ByteCntEq6)
UnicastOK <= #Tp ( RxData[7:0] == MAC[15:8]) & UnicastOK;
else
if(RxCheckEn & ByteCntEq7)
UnicastOK <= #Tp ( RxData[7:0] == MAC[7:0]) & UnicastOK;
else
if(RxEndFrm | RxAbort)
UnicastOK <= #Tp 1'b0;
end
assign IntHash = (CrcHash[5])? HASH1 : HASH0;
always@(CrcHash or IntHash)
begin
case(CrcHash[4:3])
2'b00: ByteHash = IntHash[7:0];
2'b01: ByteHash = IntHash[15:8];
2'b10: ByteHash = IntHash[23:16];
2'b11: ByteHash = IntHash[31:24];
endcase
end
assign HashBit = ByteHash[CrcHash[2:0]];
 
 
endmodule
/rtl/verilog/eth_shiftreg.v
0,0 → 1,146
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_shiftreg.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/01 22:28:56 mohor
// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
//
//
 
`include "timescale.v"
 
 
module eth_shiftreg(Clk, Reset, MdcEn_n, Mdi, Fiad, Rgad, CtrlData, WriteOp, ByteSelect,
LatchByte, ShiftedBit, Prsd, LinkFail);
 
 
parameter Tp=1;
 
input Clk; // Input clock (Host clock)
input Reset; // Reset signal
input MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls.
input Mdi; // MII input data
input [4:0] Fiad; // PHY address
input [4:0] Rgad; // Register address (within the selected PHY)
input [15:0]CtrlData; // Control data (data to be written to the PHY)
input WriteOp; // The current operation is a PHY register write operation
input [3:0] ByteSelect; // Byte select
input [1:0] LatchByte; // Byte select for latching (read operation)
 
output ShiftedBit; // Bit shifted out of the shift register
output[15:0]Prsd; // Read Status Data (data read from the PHY)
output LinkFail; // Link Integrity Signal
 
reg [7:0] ShiftReg; // Shift register for shifting the data in and out
reg [15:0]Prsd;
reg LinkFail;
 
 
 
 
// ShiftReg[7:0] :: Shift Register Data
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
ShiftReg[7:0] <= #Tp 8'h0;
Prsd[15:0] <= #Tp 16'h0;
LinkFail <= #Tp 1'b0;
end
else
begin
if(MdcEn_n)
begin
if(|ByteSelect)
begin
case (ByteSelect[3:0])
4'h1 : ShiftReg[7:0] <= #Tp {2'b01, ~WriteOp, WriteOp, Fiad[4:1]};
4'h2 : ShiftReg[7:0] <= #Tp {Fiad[0], Rgad[4:0], 2'b10};
4'h4 : ShiftReg[7:0] <= #Tp CtrlData[15:8];
4'h8 : ShiftReg[7:0] <= #Tp CtrlData[7:0];
default : ShiftReg[7:0] <= #Tp 8'h0;
endcase
end
else
begin
ShiftReg[7:0] <= #Tp {ShiftReg[6:0], Mdi};
if(LatchByte[0])
begin
Prsd[7:0] <= #Tp {ShiftReg[6:0], Mdi};
if(Rgad == 5'h01)
LinkFail <= #Tp ~ShiftReg[2]; // because of shifting
end
else
begin
if(LatchByte[1])
Prsd[15:8] <= #Tp {ShiftReg[6:0], Mdi};
end
end
end
end
end
 
 
assign ShiftedBit = ShiftReg[7];
 
 
endmodule
/rtl/verilog/eth_txethmac.v
0,0 → 1,484
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txethmac.v ////
/// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.6 2002/02/22 12:56:35 mohor
// Retry is not activated when a Tx Underrun occured
//
// Revision 1.5 2002/02/11 09:18:22 mohor
// Tx status is written back to the BD.
//
// Revision 1.4 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/19 18:16:40 mohor
// TxClk changed to MTxClk (as discribed in the documentation).
// Crc changed so only one file can be used instead of two.
//
// Revision 1.2 2001/06/19 10:38:08 mohor
// Minor changes in header.
//
// Revision 1.1 2001/06/19 10:27:58 mohor
// TxEthMAC initial release.
//
//
//
 
`include "timescale.v"
 
 
module eth_txethmac (MTxClk, Reset, TxStartFrm, TxEndFrm, TxUnderRun, TxData, CarrierSense,
Collision, Pad, CrcEn, FullD, HugEn, DlyCrcEn, MinFL, MaxFL, IPGT,
IPGR1, IPGR2, CollValid, MaxRet, NoBckof, ExDfrEn,
MTxD, MTxEn, MTxErr, TxDone, TxRetry, TxAbort, TxUsedData, WillTransmit,
ResetCollision, RetryCnt, StartTxDone, StartTxAbort, MaxCollisionOccured,
LateCollision, StartDefer, StatePreamble, StateData
 
);
 
parameter Tp = 1;
 
 
input MTxClk; // Transmit clock (from PHY)
input Reset; // Reset
input TxStartFrm; // Transmit packet start frame
input TxEndFrm; // Transmit packet end frame
input TxUnderRun; // Transmit packet under-run
input [7:0] TxData; // Transmit packet data byte
input CarrierSense; // Carrier sense (synchronized)
input Collision; // Collision (synchronized)
input Pad; // Pad enable (from register)
input CrcEn; // Crc enable (from register)
input FullD; // Full duplex (from register)
input HugEn; // Huge packets enable (from register)
input DlyCrcEn; // Delayed Crc enabled (from register)
input [15:0] MinFL; // Minimum frame length (from register)
input [15:0] MaxFL; // Maximum frame length (from register)
input [6:0] IPGT; // Back to back transmit inter packet gap parameter (from register)
input [6:0] IPGR1; // Non back to back transmit inter packet gap parameter IPGR1 (from register)
input [6:0] IPGR2; // Non back to back transmit inter packet gap parameter IPGR2 (from register)
input [5:0] CollValid; // Valid collision window (from register)
input [3:0] MaxRet; // Maximum retry number (from register)
input NoBckof; // No backoff (from register)
input ExDfrEn; // Excessive defferal enable (from register)
 
output [3:0] MTxD; // Transmit nibble (to PHY)
output MTxEn; // Transmit enable (to PHY)
output MTxErr; // Transmit error (to PHY)
output TxDone; // Transmit packet done (to RISC)
output TxRetry; // Transmit packet retry (to RISC)
output TxAbort; // Transmit packet abort (to RISC)
output TxUsedData; // Transmit packet used data (to RISC)
output WillTransmit; // Will transmit (to RxEthMAC)
output ResetCollision; // Reset Collision (for synchronizing collision)
output [3:0] RetryCnt; // Latched Retry Counter for tx status purposes
output StartTxDone;
output StartTxAbort;
output MaxCollisionOccured;
output LateCollision;
output StartDefer;
output StatePreamble;
output [1:0] StateData;
 
reg [3:0] MTxD;
reg MTxEn;
reg MTxErr;
reg TxDone;
reg TxRetry;
reg TxAbort;
reg TxUsedData;
reg WillTransmit;
reg ColWindow;
reg StopExcessiveDeferOccured;
reg [3:0] RetryCnt;
reg [3:0] MTxD_d;
reg StatusLatch;
reg PacketFinished_q;
reg PacketFinished;
 
 
wire ExcessiveDeferOccured;
wire StartIPG;
wire StartPreamble;
wire [1:0] StartData;
wire StartFCS;
wire StartJam;
wire StartBackoff;
wire StateDefer;
wire StateIPG;
wire StateIdle;
wire StatePAD;
wire StateFCS;
wire StateJam;
wire StateBackOff;
wire StateSFD;
wire StartTxRetry;
wire UnderRun;
wire TooBig;
wire [31:0] Crc;
wire CrcError;
wire [2:0] DlyCrcCnt;
wire [15:0] NibCnt;
wire NibCntEq7;
wire NibCntEq15;
wire NibbleMinFl;
wire ExcessiveDefer;
wire [15:0] ByteCnt;
wire MaxFrame;
wire RetryMax;
wire RandomEq0;
wire RandomEqByteCnt;
wire PacketFinished_d;
 
 
 
assign ResetCollision = ~(StatePreamble | (|StateData) | StatePAD | StateFCS);
 
assign ExcessiveDeferOccured = TxStartFrm & StateDefer & ExcessiveDefer & ~StopExcessiveDeferOccured;
 
assign StartTxDone = ~Collision & (StateFCS & NibCntEq7 | StateData[1] & TxEndFrm & ~Pad & ~CrcEn);
 
assign UnderRun = StateData[0] & TxUnderRun & ~Collision;
 
assign TooBig = ~Collision & MaxFrame & (StateData[0] & ~TxUnderRun | StateFCS);
 
// assign StartTxRetry = StartJam & (ColWindow & ~RetryMax);
assign StartTxRetry = StartJam & (ColWindow & ~RetryMax) & ~UnderRun;
 
assign LateCollision = StartJam & ~ColWindow & ~UnderRun;
 
assign MaxCollisionOccured = StartJam & ColWindow & RetryMax;
 
assign StateSFD = StatePreamble & NibCntEq15;
 
assign StartTxAbort = TooBig | UnderRun | ExcessiveDeferOccured | LateCollision | MaxCollisionOccured;
 
 
// StopExcessiveDeferOccured
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
StopExcessiveDeferOccured <= #Tp 1'b0;
else
begin
if(~TxStartFrm)
StopExcessiveDeferOccured <= #Tp 1'b0;
else
if(ExcessiveDeferOccured)
StopExcessiveDeferOccured <= #Tp 1'b1;
end
end
 
 
// Collision Window
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
ColWindow <= #Tp 1'b1;
else
begin
if(~Collision & ByteCnt[5:0] == CollValid[5:0] & (StateData[1] | StatePAD & NibCnt[0] | StateFCS & NibCnt[0]))
ColWindow <= #Tp 1'b0;
else
if(StateIdle | StateIPG)
ColWindow <= #Tp 1'b1;
end
end
 
 
// Start Window
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
StatusLatch <= #Tp 1'b0;
else
begin
if(~TxStartFrm)
StatusLatch <= #Tp 1'b0;
else
if(ExcessiveDeferOccured | StateIdle)
StatusLatch <= #Tp 1'b1;
end
end
 
 
// Transmit packet used data
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxUsedData <= #Tp 1'b0;
else
TxUsedData <= #Tp |StartData;
end
 
 
// Transmit packet done
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxDone <= #Tp 1'b0;
else
begin
if(TxStartFrm & ~StatusLatch)
TxDone <= #Tp 1'b0;
else
if(StartTxDone)
TxDone <= #Tp 1'b1;
end
end
 
 
// Transmit packet retry
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxRetry <= #Tp 1'b0;
else
begin
if(TxStartFrm & ~StatusLatch)
TxRetry <= #Tp 1'b0;
else
if(StartTxRetry)
TxRetry <= #Tp 1'b1;
end
end
 
 
// Transmit packet abort
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
TxAbort <= #Tp 1'b0;
else
begin
if(TxStartFrm & ~StatusLatch & ~ExcessiveDeferOccured)
TxAbort <= #Tp 1'b0;
else
if(StartTxAbort)
TxAbort <= #Tp 1'b1;
end
end
 
 
// Retry counter
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
RetryCnt[3:0] <= #Tp 4'h0;
else
begin
if(ExcessiveDeferOccured | UnderRun | TooBig | StartTxDone | TxUnderRun
| StateJam & NibCntEq7 & (~ColWindow | RetryMax))
RetryCnt[3:0] <= #Tp 4'h0;
else
if(StateJam & NibCntEq7 & ColWindow & (RandomEq0 | NoBckof) | StateBackOff & RandomEqByteCnt)
RetryCnt[3:0] <= #Tp RetryCnt[3:0] + 1'b1;
end
end
 
 
assign RetryMax = RetryCnt[3:0] == MaxRet[3:0];
 
 
// Transmit nibble
always @ (StatePreamble or StateData or StateData or StateFCS or StateJam or StateSFD or TxData or
Crc or NibCnt or NibCntEq15)
begin
if(StateData[0])
MTxD_d[3:0] = TxData[3:0]; // Lower nibble
else
if(StateData[1])
MTxD_d[3:0] = TxData[7:4]; // Higher nibble
else
if(StateFCS)
MTxD_d[3:0] = {~Crc[28], ~Crc[29], ~Crc[30], ~Crc[31]}; // Crc
else
if(StateJam)
MTxD_d[3:0] = 4'h9; // Jam pattern
else
if(StatePreamble)
if(NibCntEq15)
MTxD_d[3:0] = 4'hd; // SFD
else
MTxD_d[3:0] = 4'h5; // Preamble
else
MTxD_d[3:0] = 4'h0;
end
 
 
// Transmit Enable
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
MTxEn <= #Tp 1'b0;
else
MTxEn <= #Tp StatePreamble | (|StateData) | StatePAD | StateFCS | StateJam;
end
 
 
// Transmit nibble
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
MTxD[3:0] <= #Tp 4'h0;
else
MTxD[3:0] <= #Tp MTxD_d[3:0];
end
 
 
// Transmit error
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
MTxErr <= #Tp 1'b0;
else
MTxErr <= #Tp TooBig | UnderRun;
end
 
 
// WillTransmit
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
WillTransmit <= #Tp 1'b0;
else
WillTransmit <= #Tp StartPreamble | StatePreamble | (|StateData) | StatePAD | StateFCS | StateJam;
end
 
 
assign PacketFinished_d = StartTxDone | TooBig | UnderRun | LateCollision | MaxCollisionOccured | ExcessiveDeferOccured;
 
 
// Packet finished
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
begin
PacketFinished <= #Tp 1'b0;
PacketFinished_q <= #Tp 1'b0;
end
else
begin
PacketFinished <= #Tp PacketFinished_d;
PacketFinished_q <= #Tp PacketFinished;
end
end
 
 
// Connecting module Counters
eth_txcounters txcounters1 (.StatePreamble(StatePreamble), .StateIPG(StateIPG), .StateData(StateData),
.StatePAD(StatePAD), .StateFCS(StateFCS), .StateJam(StateJam), .StateBackOff(StateBackOff),
.StateDefer(StateDefer), .StateIdle(StateIdle), .StartDefer(StartDefer), .StartIPG(StartIPG),
.StartFCS(StartFCS), .StartJam(StartJam), .TxStartFrm(TxStartFrm), .MTxClk(MTxClk),
.Reset(Reset), .MinFL(MinFL), .MaxFL(MaxFL), .HugEn(HugEn), .ExDfrEn(ExDfrEn),
.PacketFinished_q(PacketFinished_q), .DlyCrcEn(DlyCrcEn), .StartBackoff(StartBackoff),
.StateSFD(StateSFD), .ByteCnt(ByteCnt), .NibCnt(NibCnt), .ExcessiveDefer(ExcessiveDefer),
.NibCntEq7(NibCntEq7), .NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .NibbleMinFl(NibbleMinFl),
.DlyCrcCnt(DlyCrcCnt)
);
 
 
// Connecting module StateM
eth_txstatem txstatem1 (.MTxClk(MTxClk), .Reset(Reset), .ExcessiveDefer(ExcessiveDefer), .CarrierSense(CarrierSense),
.NibCnt(NibCnt[6:0]), .IPGT(IPGT), .IPGR1(IPGR1), .IPGR2(IPGR2), .FullD(FullD),
.TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm), .TxUnderRun(TxUnderRun), .Collision(Collision),
.UnderRun(UnderRun), .StartTxDone(StartTxDone), .TooBig(TooBig), .NibCntEq7(NibCntEq7),
.NibCntEq15(NibCntEq15), .MaxFrame(MaxFrame), .Pad(Pad), .CrcEn(CrcEn),
.NibbleMinFl(NibbleMinFl), .RandomEq0(RandomEq0), .ColWindow(ColWindow), .RetryMax(RetryMax),
.NoBckof(NoBckof), .RandomEqByteCnt(RandomEqByteCnt), .StateIdle(StateIdle),
.StateIPG(StateIPG), .StatePreamble(StatePreamble), .StateData(StateData), .StatePAD(StatePAD),
.StateFCS(StateFCS), .StateJam(StateJam), .StateJam_q(StateJam_q), .StateBackOff(StateBackOff),
.StateDefer(StateDefer), .StartFCS(StartFCS), .StartJam(StartJam), .StartBackoff(StartBackoff),
.StartDefer(StartDefer), .StartPreamble(StartPreamble), .StartData(StartData), .StartIPG(StartIPG)
);
 
 
wire Enable_Crc;
wire [3:0] Data_Crc;
wire Initialize_Crc;
 
assign Enable_Crc = ~StateFCS;
 
assign Data_Crc[0] = StateData[0]? TxData[3] : StateData[1]? TxData[7] : 1'b0;
assign Data_Crc[1] = StateData[0]? TxData[2] : StateData[1]? TxData[6] : 1'b0;
assign Data_Crc[2] = StateData[0]? TxData[1] : StateData[1]? TxData[5] : 1'b0;
assign Data_Crc[3] = StateData[0]? TxData[0] : StateData[1]? TxData[4] : 1'b0;
 
assign Initialize_Crc = StateIdle | StatePreamble | (|DlyCrcCnt);
 
 
// Connecting module Crc
eth_crc txcrc (.Clk(MTxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc),
.Crc(Crc), .CrcError(CrcError)
);
 
 
// Connecting module Random
eth_random random1 (.MTxClk(MTxClk), .Reset(Reset), .StateJam(StateJam), .StateJam_q(StateJam_q), .RetryCnt(RetryCnt),
.NibCnt(NibCnt), .ByteCnt(ByteCnt[9:0]), .RandomEq0(RandomEq0), .RandomEqByteCnt(RandomEqByteCnt));
 
 
 
 
endmodule
/rtl/verilog/eth_register.v
0,0 → 1,98
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_register.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
//
//
//
//
//
//
 
`include "timescale.v"
 
 
module eth_register(DataIn, DataOut, Write, Clk, Reset);
 
parameter WIDTH = 8; // default parameter of the register width
parameter ResetValue = 0;
 
input [WIDTH-1:0] DataIn;
 
input Write;
input Clk;
input Reset;
 
output [WIDTH-1:0] DataOut;
reg [WIDTH-1:0] DataOut;
 
 
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
DataOut<=#1 ResetValue;
else
if(Write) // write
DataOut<=#1 DataIn;
end
 
 
 
endmodule // Register
/rtl/verilog/eth_rxethmac.v
0,0 → 1,356
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxethmac.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.7 2002/02/15 13:44:28 mohor
// RxAbort is an output. No need to have is declared as wire.
//
// Revision 1.6 2002/02/15 11:17:48 mohor
// File format changed.
//
// Revision 1.5 2002/02/14 20:48:43 billditt
// Addition of new module eth_addrcheck.v
//
// Revision 1.4 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.1 2001/06/27 21:26:19 mohor
// Initial release of the RxEthMAC module.
//
//
//
//
//
 
`include "timescale.v"
 
 
module eth_rxethmac (MRxClk, MRxDV, MRxD, Reset, Transmitting, MaxFL, r_IFG, HugEn, DlyCrcEn,
RxData, RxValid, RxStartFrm, RxEndFrm, ByteCnt, ByteCntEq0, ByteCntGreat2,
ByteCntMaxFrame, CrcError, StateIdle, StatePreamble, StateSFD, StateData,
MAC, r_Pro, r_Bro,r_HASH0, r_HASH1, RxAbort
);
 
parameter Tp = 1;
 
 
 
input MRxClk;
input MRxDV;
input [3:0] MRxD;
input Transmitting;
input HugEn;
input DlyCrcEn;
input [15:0] MaxFL;
input r_IFG;
input Reset;
input [47:0] MAC; // Station Address
input r_Bro; // broadcast disable
input r_Pro; // promiscuous enable
input [31:0] r_HASH0; // lower 4 bytes Hash Table
input [31:0] r_HASH1; // upper 4 bytes Hash Table
output [7:0] RxData;
output RxValid;
output RxStartFrm;
output RxEndFrm;
output [15:0] ByteCnt;
output ByteCntEq0;
output ByteCntGreat2;
output ByteCntMaxFrame;
output CrcError;
output StateIdle;
output StatePreamble;
output StateSFD;
output [1:0] StateData;
output RxAbort;
 
reg [7:0] RxData;
reg RxValid;
reg RxStartFrm;
reg RxEndFrm;
reg Broadcast;
reg Multicast;
reg [8:0] CrcHash;
reg CrcHashGood;
reg DelayData;
reg [3:0] LatchedNibble;
reg [7:0] LatchedByte;
reg [7:0] RxData_d;
reg RxValid_d;
reg RxStartFrm_d;
reg RxEndFrm_d;
 
wire MRxDEqD;
wire MRxDEq5;
wire StateDrop;
wire ByteCntEq1;
wire ByteCntEq2;
wire ByteCntEq3;
wire ByteCntEq4;
wire ByteCntEq5;
wire ByteCntEq6;
wire ByteCntEq7;
wire ByteCntSmall7;
wire [31:0] Crc;
wire Enable_Crc;
wire Initialize_Crc;
wire [3:0] Data_Crc;
wire GenerateRxValid;
wire GenerateRxStartFrm;
wire GenerateRxEndFrm;
wire DribbleRxEndFrm;
wire [3:0] DlyCrcCnt;
 
 
assign MRxDEqD = MRxD == 4'hd;
assign MRxDEq5 = MRxD == 4'h5;
 
 
// Rx State Machine module
eth_rxstatem rxstatem1 (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .ByteCntEq0(ByteCntEq0),
.ByteCntGreat2(ByteCntGreat2), .Transmitting(Transmitting), .MRxDEq5(MRxDEq5),
.MRxDEqD(MRxDEqD), .IFGCounterEq24(IFGCounterEq24), .ByteCntMaxFrame(ByteCntMaxFrame),
.StateData(StateData), .StateIdle(StateIdle), .StatePreamble(StatePreamble),
.StateSFD(StateSFD), .StateDrop(StateDrop)
);
 
 
// Rx Counters module
eth_rxcounters rxcounters1 (.MRxClk(MRxClk), .Reset(Reset), .MRxDV(MRxDV), .StateIdle(StateIdle),
.StateSFD(StateSFD), .StateData(StateData), .StateDrop(StateDrop),
.StatePreamble(StatePreamble), .MRxDEqD(MRxDEqD), .DlyCrcEn(DlyCrcEn),
.DlyCrcCnt(DlyCrcCnt), .Transmitting(Transmitting), .MaxFL(MaxFL), .r_IFG(r_IFG),
.HugEn(HugEn), .IFGCounterEq24(IFGCounterEq24), .ByteCntEq0(ByteCntEq0),
.ByteCntEq1(ByteCntEq1), .ByteCntEq2(ByteCntEq2), .ByteCntEq3(ByteCntEq3),
.ByteCntEq4(ByteCntEq4), .ByteCntEq5(ByteCntEq5), .ByteCntEq6(ByteCntEq6),
.ByteCntEq7(ByteCntEq7), .ByteCntGreat2(ByteCntGreat2),
.ByteCntSmall7(ByteCntSmall7), .ByteCntMaxFrame(ByteCntMaxFrame),
.ByteCnt(ByteCnt)
);
 
// Rx Address Check
 
eth_rxaddrcheck rxaddrcheck1
(.MRxClk(MRxClk), .Reset( Reset), .RxData(RxData),
.Broadcast (Broadcast), .r_Bro (r_Bro), .r_Pro(r_Pro),
.ByteCntEq6(ByteCntEq6), .ByteCntEq7(ByteCntEq7), .ByteCntEq2(ByteCntEq2),
.ByteCntEq3(ByteCntEq3), .ByteCntEq4(ByteCntEq4), .ByteCntEq5(ByteCntEq5),
.HASH0(r_HASH0), .HASH1(r_HASH1),
.CrcHash(CrcHash[5:0]), .CrcHashGood(CrcHashGood),.StateData(StateData),
.Multicast(Multicast), .MAC(MAC), .RxAbort(RxAbort),
.RxEndFrm(RxEndFrm)
);
 
 
assign Enable_Crc = MRxDV & (|StateData & ~ByteCntMaxFrame);
assign Initialize_Crc = StateSFD | DlyCrcEn & (|DlyCrcCnt[3:0]) & DlyCrcCnt[3:0] < 4'h9;
 
assign Data_Crc[0] = MRxD[3];
assign Data_Crc[1] = MRxD[2];
assign Data_Crc[2] = MRxD[1];
assign Data_Crc[3] = MRxD[0];
 
 
// Connecting module Crc
eth_crc crcrx (.Clk(MRxClk), .Reset(Reset), .Data(Data_Crc), .Enable(Enable_Crc), .Initialize(Initialize_Crc),
.Crc(Crc), .CrcError(CrcError)
);
 
 
 
// Latching CRC for use in the hash table
 
always @ (posedge MRxClk)
begin
CrcHashGood <= #Tp StateData[0] & ByteCntEq6;
end
 
always @ (posedge MRxClk)
begin
if(Reset | StateIdle)
CrcHash[8:0] <= #Tp 9'h0;
else
if(StateData[0] & ByteCntEq6)
CrcHash[8:0] <= #Tp Crc[31:23];
end
 
 
// Output byte stream
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
begin
RxData_d[7:0] <= #Tp 8'h0;
DelayData <= #Tp 1'b0;
LatchedNibble[3:0] <= #Tp 4'h0;
LatchedByte[7:0] <= #Tp 8'h0;
RxData[7:0] <= #Tp 8'h0;
end
else
begin
LatchedNibble[3:0] <= #Tp MRxD[3:0]; // Latched nibble
LatchedByte[7:0] <= #Tp {MRxD[3:0], LatchedNibble[3:0]}; // Latched byte
DelayData <= #Tp StateData[0];
 
if(GenerateRxValid)
RxData_d[7:0] <= #Tp LatchedByte[7:0] & {8{|StateData}}; // Data goes through only in data state
else
if(~DelayData)
RxData_d[7:0] <= #Tp 8'h0; // Delaying data to be valid for two cycles. Zero when not active.
 
RxData[7:0] <= #Tp RxData_d[7:0]; // Output data byte
end
end
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
Broadcast <= #Tp 1'b0;
else
begin
if(StateData[0] & ~(&LatchedByte[7:0]) & ByteCntSmall7)
Broadcast <= #Tp 1'b0;
else
if(StateData[0] & (&LatchedByte[7:0]) & ByteCntEq1)
Broadcast <= #Tp 1'b1;
else
if(RxAbort | RxEndFrm)
Broadcast <= #Tp 1'b0;
end
end
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
Multicast <= #Tp 1'b0;
else
begin
if(Reset)
Multicast <= #Tp 1'b0;
else
if(StateData[0] & ByteCntEq1 & LatchedByte == 8'h01)
Multicast <= #Tp 1'b1;
else if(RxAbort | RxEndFrm)
Multicast <= #Tp 1'b0;
end
end
 
 
assign GenerateRxValid = StateData[0] & (~ByteCntEq0 | DlyCrcCnt >= 4'h3);
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
begin
RxValid_d <= #Tp 1'b0;
RxValid <= #Tp 1'b0;
end
else
begin
RxValid_d <= #Tp GenerateRxValid;
RxValid <= #Tp RxValid_d;
end
end
 
 
assign GenerateRxStartFrm = StateData[0] & (ByteCntEq1 & ~DlyCrcEn | DlyCrcCnt == 4'h3 & DlyCrcEn);
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
begin
RxStartFrm_d <= #Tp 1'b0;
RxStartFrm <= #Tp 1'b0;
end
else
begin
RxStartFrm_d <= #Tp GenerateRxStartFrm;
RxStartFrm <= #Tp RxStartFrm_d;
end
end
 
 
assign GenerateRxEndFrm = StateData[0] & (~MRxDV & ByteCntGreat2 | ByteCntMaxFrame);
assign DribbleRxEndFrm = StateData[1] & ~MRxDV & ByteCntGreat2;
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
begin
RxEndFrm_d <= #Tp 1'b0;
RxEndFrm <= #Tp 1'b0;
end
else
begin
RxEndFrm_d <= #Tp GenerateRxEndFrm;
RxEndFrm <= #Tp RxEndFrm_d | DribbleRxEndFrm;
end
end
 
 
endmodule
/rtl/verilog/eth_rxcounters.v
0,0 → 1,211
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxcounters.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.4 2002/02/14 20:19:41 billditt
// Modified for Address Checking,
// addition of eth_addrcheck.v
//
// Revision 1.3 2002/01/23 10:28:16 mohor
// Link in the header changed.
//
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.1 2001/06/27 21:26:19 mohor
// Initial release of the RxEthMAC module.
//
//
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_rxcounters (MRxClk, Reset, MRxDV, StateIdle, StateSFD, StateData, StateDrop, StatePreamble,
MRxDEqD, DlyCrcEn, DlyCrcCnt, Transmitting, MaxFL, r_IFG, HugEn, IFGCounterEq24,
ByteCntEq0, ByteCntEq1, ByteCntEq2,ByteCntEq3,ByteCntEq4,ByteCntEq5, ByteCntEq6,
ByteCntEq7, ByteCntGreat2, ByteCntSmall7, ByteCntMaxFrame, ByteCnt
);
 
parameter Tp = 1;
 
input MRxClk;
input Reset;
input MRxDV;
input StateSFD;
input [1:0] StateData;
input MRxDEqD;
input StateIdle;
input StateDrop;
input DlyCrcEn;
input StatePreamble;
input Transmitting;
input HugEn;
input [15:0] MaxFL;
input r_IFG;
 
output IFGCounterEq24; // IFG counter reaches 9600 ns (960 ns)
output [3:0] DlyCrcCnt; // Delayed CRC counter
output ByteCntEq0; // Byte counter = 0
output ByteCntEq1; // Byte counter = 1
output ByteCntEq2; // Byte counter = 2
output ByteCntEq3; // Byte counter = 3
output ByteCntEq4; // Byte counter = 4
output ByteCntEq5; // Byte counter = 5
output ByteCntEq6; // Byte counter = 6
output ByteCntEq7; // Byte counter = 7
output ByteCntGreat2; // Byte counter > 2
output ByteCntSmall7; // Byte counter < 7
output ByteCntMaxFrame; // Byte counter = MaxFL
output [15:0] ByteCnt; // Byte counter
 
wire ResetByteCounter;
wire IncrementByteCounter;
wire ResetIFGCounter;
wire IncrementIFGCounter;
wire ByteCntMax;
 
reg [15:0] ByteCnt;
reg [3:0] DlyCrcCnt;
reg [4:0] IFGCounter;
 
 
 
assign ResetByteCounter = MRxDV & (StateSFD & MRxDEqD | StateData[0] & ByteCntMaxFrame);
 
assign IncrementByteCounter = ~ResetByteCounter & MRxDV &
(StatePreamble | StateSFD | StateIdle & ~Transmitting |
StateData[1] & ~ByteCntMax & ~(DlyCrcEn & |DlyCrcCnt)
);
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ByteCnt[15:0] <= #Tp 11'h0;
else
begin
if(ResetByteCounter)
ByteCnt[15:0] <= #Tp 11'h0;
else
if(IncrementByteCounter)
ByteCnt[15:0] <= #Tp ByteCnt[15:0] + 1'b1;
end
end
 
assign ByteCntEq0 = ByteCnt == 16'h0;
assign ByteCntEq1 = ByteCnt == 16'h1;
assign ByteCntEq2 = ByteCnt == 16'h2;
assign ByteCntEq3 = ByteCnt == 16'h3;
assign ByteCntEq4 = ByteCnt == 16'h4;
assign ByteCntEq5 = ByteCnt == 16'h5;
assign ByteCntEq6 = ByteCnt == 16'h6;
assign ByteCntEq7 = ByteCnt == 16'h7;
assign ByteCntGreat2 = ByteCnt > 16'h2;
assign ByteCntSmall7 = ByteCnt < 16'h7;
assign ByteCntMax = ByteCnt == 16'hffff;
assign ByteCntMaxFrame = ByteCnt == MaxFL[15:0] & ~HugEn;
 
 
 
assign ResetIFGCounter = StateSFD & MRxDV & MRxDEqD | StateDrop;
 
assign IncrementIFGCounter = ~ResetIFGCounter & (StateDrop | StateIdle | StatePreamble | StateSFD) & ~IFGCounterEq24;
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
IFGCounter[4:0] <= #Tp 5'h0;
else
begin
if(ResetIFGCounter)
IFGCounter[4:0] <= #Tp 5'h0;
else
if(IncrementIFGCounter)
IFGCounter[4:0] <= #Tp IFGCounter[4:0] + 1'b1;
end
end
 
 
 
assign IFGCounterEq24 = (IFGCounter[4:0] == 5'h18) | r_IFG; // 24*400 = 9600 ns or r_IFG is set to 1
 
 
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
DlyCrcCnt[3:0] <= #Tp 4'h0;
else
begin
if(DlyCrcCnt[3:0] == 4'h9)
DlyCrcCnt[3:0] <= #Tp 4'h0;
else
if(DlyCrcEn & StateSFD)
DlyCrcCnt[3:0] <= #Tp 4'h1;
else
if(DlyCrcEn & (|DlyCrcCnt[3:0]))
DlyCrcCnt[3:0] <= #Tp DlyCrcCnt[3:0] + 1'b1;
end
end
 
 
endmodule
/rtl/verilog/eth_random.v
0,0 → 1,138
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_random.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/19 18:16:40 mohor
// TxClk changed to MTxClk (as discribed in the documentation).
// Crc changed so only one file can be used instead of two.
//
// Revision 1.2 2001/06/19 10:38:07 mohor
// Minor changes in header.
//
// Revision 1.1 2001/06/19 10:27:57 mohor
// TxEthMAC initial release.
//
//
//
//
 
`include "timescale.v"
 
module eth_random (MTxClk, Reset, StateJam, StateJam_q, RetryCnt, NibCnt, ByteCnt,
RandomEq0, RandomEqByteCnt);
 
parameter Tp = 1;
 
input MTxClk;
input Reset;
input StateJam;
input StateJam_q;
input [3:0] RetryCnt;
input [15:0] NibCnt;
input [9:0] ByteCnt;
output RandomEq0;
output RandomEqByteCnt;
 
wire Feedback;
reg [9:0] x;
wire [9:0] Random;
reg [9:0] RandomLatched;
 
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
x[9:0] <= #Tp 0;
else
x[9:0] <= #Tp {x[8:0], Feedback};
end
 
assign Feedback = x[2] ~^ x[9];
 
assign Random [0] = x[0];
assign Random [1] = (RetryCnt > 1) ? x[1] : 1'b0;
assign Random [2] = (RetryCnt > 2) ? x[2] : 1'b0;
assign Random [3] = (RetryCnt > 3) ? x[3] : 1'b0;
assign Random [4] = (RetryCnt > 4) ? x[4] : 1'b0;
assign Random [5] = (RetryCnt > 5) ? x[5] : 1'b0;
assign Random [6] = (RetryCnt > 6) ? x[6] : 1'b0;
assign Random [7] = (RetryCnt > 7) ? x[7] : 1'b0;
assign Random [8] = (RetryCnt > 8) ? x[8] : 1'b0;
assign Random [9] = (RetryCnt > 9) ? x[9] : 1'b0;
 
 
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
RandomLatched <= #Tp 10'h000;
else
begin
if(StateJam & StateJam_q)
RandomLatched <= #Tp Random;
end
end
 
// Random Number == 0 IEEE 802.3 page 68. If 0 we go to defer and not to backoff.
assign RandomEq0 = RandomLatched == 10'h0;
 
assign RandomEqByteCnt = ByteCnt[9:0] == RandomLatched & (&NibCnt[6:0]);
 
endmodule
/rtl/verilog/eth_receivecontrol.v
0,0 → 1,427
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_receivecontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.1 2001/07/03 12:51:54 mohor
// Initial release of the MAC Control module.
//
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_receivecontrol (MTxClk, MRxClk, TxReset, RxReset, RxData, RxValid, RxStartFrm,
RxEndFrm, RxFlow, ReceiveEnd, MAC, PassAll, DlyCrcEn, TxDoneIn,
TxAbortIn, TxStartFrmOut, ReceivedLengthOK, ReceivedPacketGood,
TxUsedDataOutDetected, Pause, ReceivedPauseFrm
);
 
parameter Tp = 1;
 
 
input MTxClk;
input MRxClk;
input TxReset;
input RxReset;
input [7:0] RxData;
input RxValid;
input RxStartFrm;
input RxEndFrm;
input RxFlow;
input ReceiveEnd;
input [47:0]MAC;
input PassAll;
input DlyCrcEn;
input TxDoneIn;
input TxAbortIn;
input TxStartFrmOut;
input ReceivedLengthOK;
input ReceivedPacketGood;
input TxUsedDataOutDetected;
 
output Pause;
output ReceivedPauseFrm;
 
reg Pause;
reg AddressOK; // Multicast or unicast address detected
reg TypeLengthOK; // Type/Length field contains 0x8808
reg DetectionWindow; // Detection of the PAUSE frame is possible within this window
reg OpCodeOK; // PAUSE opcode detected (0x0001)
reg [2:0] DlyCrcCnt;
reg [4:0] ByteCnt;
reg [15:0] AssembledTimerValue;
reg [15:0] LatchedTimerValue;
reg ReceivedPauseFrm;
reg ReceivedPauseFrmWAddr;
reg PauseTimerEq0_sync1;
reg PauseTimerEq0_sync2;
reg [15:0] PauseTimer;
reg Divider2;
reg [5:0] SlotTimer;
 
wire [47:0] ReservedMulticast; // 0x0180C2000001
wire [15:0] TypeLength; // 0x8808
wire ResetByteCnt; //
wire IncrementByteCnt; //
wire ByteCntEq0; // ByteCnt = 0
wire ByteCntEq1; // ByteCnt = 1
wire ByteCntEq2; // ByteCnt = 2
wire ByteCntEq3; // ByteCnt = 3
wire ByteCntEq4; // ByteCnt = 4
wire ByteCntEq5; // ByteCnt = 5
wire ByteCntEq12; // ByteCnt = 12
wire ByteCntEq13; // ByteCnt = 13
wire ByteCntEq14; // ByteCnt = 14
wire ByteCntEq15; // ByteCnt = 15
wire ByteCntEq16; // ByteCnt = 16
wire ByteCntEq17; // ByteCnt = 17
wire ByteCntEq18; // ByteCnt = 18
wire SetPauseTimer; //
wire DecrementPauseTimer; //
wire PauseTimerEq0; //
wire ResetSlotTimer; //
wire IncrementSlotTimer; //
wire SlotFinished; //
 
 
 
// Reserved multicast address and Type/Length for PAUSE control
assign ReservedMulticast = 48'h0180C2000001;
assign TypeLength = 16'h8808;
 
 
// Address Detection (Multicast or unicast)
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
AddressOK <= #Tp 1'b0;
else
if(DetectionWindow & ByteCntEq0)
AddressOK <= #Tp RxData[7:0] == ReservedMulticast[47:40] | RxData[7:0] == MAC[47:40];
else
if(DetectionWindow & ByteCntEq1)
AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[39:32] | RxData[7:0] == MAC[39:32]) & AddressOK;
else
if(DetectionWindow & ByteCntEq2)
AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[31:24] | RxData[7:0] == MAC[31:24]) & AddressOK;
else
if(DetectionWindow & ByteCntEq3)
AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[23:16] | RxData[7:0] == MAC[23:16]) & AddressOK;
else
if(DetectionWindow & ByteCntEq4)
AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[15:8] | RxData[7:0] == MAC[15:8]) & AddressOK;
else
if(DetectionWindow & ByteCntEq5)
AddressOK <= #Tp (RxData[7:0] == ReservedMulticast[7:0] | RxData[7:0] == MAC[7:0]) & AddressOK;
else
if(ReceiveEnd)
AddressOK <= #Tp 1'b0;
end
 
 
 
// TypeLengthOK (Type/Length Control frame detected)
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
TypeLengthOK <= #Tp 1'b0;
else
if(DetectionWindow & ByteCntEq12)
TypeLengthOK <= #Tp ByteCntEq12 & (RxData[7:0] == TypeLength[15:8]);
else
if(DetectionWindow & ByteCntEq13)
TypeLengthOK <= #Tp ByteCntEq13 & (RxData[7:0] == TypeLength[7:0]) & TypeLengthOK;
else
if(ReceiveEnd)
TypeLengthOK <= #Tp 1'b0;
end
 
 
 
// Latch Control Frame Opcode
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
OpCodeOK <= #Tp 1'b0;
else
if(RxStartFrm)
OpCodeOK <= #Tp 1'b0;
else
begin
if(DetectionWindow & ByteCntEq14)
OpCodeOK <= #Tp ByteCntEq14 & RxData[7:0] == 8'h00;
if(DetectionWindow & ByteCntEq15)
OpCodeOK <= #Tp ByteCntEq15 & RxData[7:0] == 8'h01 & OpCodeOK;
end
end
 
 
// ReceivedPauseFrmWAddr (+Address Check)
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
ReceivedPauseFrmWAddr <= #Tp 1'b0;
else
if(ReceiveEnd)
ReceivedPauseFrmWAddr <= #Tp 1'b0;
else
if(ByteCntEq16 & TypeLengthOK & OpCodeOK & AddressOK)
ReceivedPauseFrmWAddr <= #Tp 1'b1;
end
 
 
 
// Assembling 16-bit timer value from two 8-bit data
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
AssembledTimerValue[15:0] <= #Tp 16'h0;
else
if(RxStartFrm)
AssembledTimerValue[15:0] <= #Tp 16'h0;
else
begin
if(DetectionWindow & ByteCntEq16)
AssembledTimerValue[15:8] <= #Tp RxData[7:0];
if(DetectionWindow & ByteCntEq17)
AssembledTimerValue[7:0] <= #Tp RxData[7:0];
end
end
 
 
// Detection window (while PAUSE detection is possible)
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
DetectionWindow <= #Tp 1'b1;
else
if(ByteCntEq18)
DetectionWindow <= #Tp 1'b0;
else
if(ReceiveEnd)
DetectionWindow <= #Tp 1'b1;
end
 
 
 
// Latching Timer Value
always @ (posedge MRxClk or posedge RxReset )
begin
if(RxReset)
LatchedTimerValue[15:0] <= #Tp 16'h0;
else
if(~PassAll & DetectionWindow & ReceivedPauseFrmWAddr & ByteCntEq18)
LatchedTimerValue[15:0] <= #Tp AssembledTimerValue[15:0];
else
if(ReceiveEnd)
LatchedTimerValue[15:0] <= #Tp 16'h0;
end
 
 
 
// Delayed CEC counter
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
DlyCrcCnt <= #Tp 3'h0;
else
if(RxValid & RxEndFrm)
DlyCrcCnt <= #Tp 3'h0;
else
if(RxValid & ~RxEndFrm & ~DlyCrcCnt[2])
DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1;
end
 
assign ResetByteCnt = RxEndFrm;
assign IncrementByteCnt = RxValid & DetectionWindow & ~ByteCntEq18 & (~DlyCrcEn | DlyCrcEn & DlyCrcCnt[2]);
 
 
// Byte counter
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
ByteCnt[4:0] <= #Tp 5'h0;
else
if(ResetByteCnt)
ByteCnt[4:0] <= #Tp 5'h0;
else
if(IncrementByteCnt)
ByteCnt[4:0] <= #Tp ByteCnt[4:0] + 1'b1;
end
 
 
assign ByteCntEq0 = RxValid & ByteCnt[4:0] == 5'h0;
assign ByteCntEq1 = RxValid & ByteCnt[4:0] == 5'h1;
assign ByteCntEq2 = RxValid & ByteCnt[4:0] == 5'h2;
assign ByteCntEq3 = RxValid & ByteCnt[4:0] == 5'h3;
assign ByteCntEq4 = RxValid & ByteCnt[4:0] == 5'h4;
assign ByteCntEq5 = RxValid & ByteCnt[4:0] == 5'h5;
assign ByteCntEq12 = RxValid & ByteCnt[4:0] == 5'h0C;
assign ByteCntEq13 = RxValid & ByteCnt[4:0] == 5'h0D;
assign ByteCntEq14 = RxValid & ByteCnt[4:0] == 5'h0E;
assign ByteCntEq15 = RxValid & ByteCnt[4:0] == 5'h0F;
assign ByteCntEq16 = RxValid & ByteCnt[4:0] == 5'h10;
assign ByteCntEq17 = RxValid & ByteCnt[4:0] == 5'h11;
assign ByteCntEq18 = RxValid & ByteCnt[4:0] == 5'h12 & DetectionWindow;
 
 
assign SetPauseTimer = ReceiveEnd & ReceivedPauseFrmWAddr & ReceivedPacketGood & ReceivedLengthOK & RxFlow;
assign DecrementPauseTimer = SlotFinished & |PauseTimer;
 
 
// PauseTimer[15:0]
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
PauseTimer[15:0] <= #Tp 16'h0;
else
if(SetPauseTimer)
PauseTimer[15:0] <= #Tp LatchedTimerValue[15:0];
else
if(DecrementPauseTimer)
PauseTimer[15:0] <= #Tp PauseTimer[15:0] - 1'b1;
end
 
assign PauseTimerEq0 = ~(|PauseTimer[15:0]);
 
 
 
// Synchronization of the pause timer
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
begin
PauseTimerEq0_sync1 <= #Tp 1'b1;
PauseTimerEq0_sync2 <= #Tp 1'b1;
end
else
begin
PauseTimerEq0_sync1 <= #Tp PauseTimerEq0;
PauseTimerEq0_sync2 <= #Tp PauseTimerEq0_sync1;
end
end
 
 
// Pause signal generation
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
Pause <= #Tp 1'b0;
else
if((TxDoneIn | TxAbortIn | ~TxUsedDataOutDetected) & ~TxStartFrmOut)
Pause <= #Tp RxFlow & ~PauseTimerEq0_sync2;
end
 
 
// Divider2 is used for incrementing the Slot timer every other clock
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
Divider2 <= #Tp 1'b0;
else
if(|PauseTimer[15:0] & RxFlow)
Divider2 <= #Tp ~Divider2;
else
Divider2 <= #Tp 1'b0;
end
 
 
assign ResetSlotTimer = RxReset;
assign IncrementSlotTimer = Pause & RxFlow & Divider2;
 
 
// SlotTimer
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
SlotTimer[5:0] <= #Tp 6'h0;
else
if(ResetSlotTimer)
SlotTimer[5:0] <= #Tp 6'h0;
else
if(IncrementSlotTimer)
SlotTimer[5:0] <= #Tp SlotTimer[5:0] + 1'b1;
end
 
 
assign SlotFinished = &SlotTimer[5:0] & IncrementSlotTimer; // Slot is 512 bits (64 bytes)
 
 
 
// Pause Frame received
always @ (posedge MRxClk or posedge RxReset)
begin
if(RxReset)
ReceivedPauseFrm <=#Tp 1'b0;
else
if(ByteCntEq16 & TypeLengthOK & OpCodeOK)
ReceivedPauseFrm <=#Tp 1'b1;
else
if(ReceiveEnd)
ReceivedPauseFrm <=#Tp 1'b0;
end
 
 
endmodule
/rtl/verilog/eth_clockgen.v
0,0 → 1,128
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_clockgen.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/01 22:28:55 mohor
// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
//
//
 
`include "timescale.v"
 
module eth_clockgen(Clk, Reset, Divider, MdcEn, MdcEn_n, Mdc);
 
parameter Tp=1;
 
input Clk; // Input clock (Host clock)
input Reset; // Reset signal
input [7:0] Divider; // Divider (input clock will be divided by the Divider[7:0])
 
output Mdc; // Output clock
output MdcEn; // Enable signal is asserted for one Clk period before Mdc rises.
output MdcEn_n; // Enable signal is asserted for one Clk period before Mdc falls.
 
reg Mdc;
reg [7:0] Counter;
 
wire CountEq0;
wire [7:0] CounterPreset;
wire [7:0] TempDivider;
 
 
assign TempDivider[7:0] = (Divider[7:0]<2)? 8'h02 : Divider[7:0]; // If smaller than 2
assign CounterPreset[7:0] = (TempDivider[7:0]>>1) -1; // We are counting half of period
 
 
// Counter counts half period
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
Counter[7:0] <= #Tp 8'h1;
else
begin
if(CountEq0)
begin
Counter[7:0] <= #Tp CounterPreset[7:0];
end
else
Counter[7:0] <= #Tp Counter - 8'h1;
end
end
 
 
// Mdc is asserted every other half period
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
Mdc <= #Tp 1'b0;
else
begin
if(CountEq0)
Mdc <= #Tp ~Mdc;
end
end
 
 
assign CountEq0 = Counter == 8'h0;
assign MdcEn = CountEq0 & ~Mdc;
assign MdcEn_n = CountEq0 & Mdc;
 
endmodule
 
 
/rtl/verilog/eth_miim.v
0,0 → 1,435
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_miim.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.2 2001/08/02 09:25:31 mohor
// Unconnected signals are now connected.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/01 22:28:56 mohor
// This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
//
//
 
`include "timescale.v"
 
 
module eth_miim
(
Clk,
Reset,
Divider,
NoPre,
CtrlData,
Rgad,
Fiad,
WCtrlData,
RStat,
ScanStat,
Mdi,
Mdo,
MdoEn,
Mdc,
Busy,
Prsd,
LinkFail,
Nvalid,
WCtrlDataStart,
RStatStart,
UpdateMIIRX_DATAReg
);
 
 
 
input Clk; // Host Clock
input Reset; // General Reset
input [7:0] Divider; // Divider for the host clock
input [15:0] CtrlData; // Control Data (to be written to the PHY reg.)
input [4:0] Rgad; // Register Address (within the PHY)
input [4:0] Fiad; // PHY Address
input NoPre; // No Preamble (no 32-bit preamble)
input WCtrlData; // Write Control Data operation
input RStat; // Read Status operation
input ScanStat; // Scan Status operation
input Mdi; // MII Management Data In
 
output Mdc; // MII Management Data Clock
output Mdo; // MII Management Data Output
output MdoEn; // MII Management Data Output Enable
output Busy; // Busy Signal
output LinkFail; // Link Integrity Signal
output Nvalid; // Invalid Status (qualifier for the valid scan result)
 
output [15:0] Prsd; // Read Status Data (data read from the PHY)
 
output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register
output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register
output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
 
parameter Tp = 1;
 
 
reg Nvalid;
reg EndBusy_d; // Pre-end Busy signal
reg EndBusy; // End Busy signal (stops the operation in progress)
 
reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle
reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles
reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles
reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected)
reg WCtrlDataStart_q;
reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle
reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles
 
reg RStat_q1; // Read Status operation delayed 1 Clk cycle
reg RStat_q2; // Read Status operation delayed 2 Clk cycles
reg RStat_q3; // Read Status operation delayed 3 Clk cycles
reg RStatStart; // Start Read Status Command (positive edge detected)
reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle
reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles
 
reg ScanStat_q1; // Scan Status operation delayed 1 cycle
reg ScanStat_q2; // Scan Status operation delayed 2 cycles
reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn
 
wire WriteDataOp; // Write Data Operation (positive edge detected)
wire ReadStatusOp; // Read Status Operation (positive edge detected)
wire ScanStatusOp; // Scan Status Operation (positive edge detected)
wire StartOp; // Start Operation (start of any of the preceding operations)
wire EndOp; // End of Operation
 
reg InProgress; // Operation in progress
reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle
reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles
reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles
 
reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress)
reg [6:0] BitCounter; // Bit Counter
 
 
wire MdcFrame; // Frame window for limiting the Mdc
wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises.
wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal
 
 
wire LatchByte1_d2;
wire LatchByte0_d2;
reg LatchByte1_d;
reg LatchByte0_d;
reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register
 
reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
 
 
 
 
 
// Generation of the EndBusy signal. It is used for ending the MII Management operation.
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
EndBusy_d <= #Tp 1'b0;
EndBusy <= #Tp 1'b0;
end
else
begin
EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3;
EndBusy <= #Tp EndBusy_d;
end
end
 
 
// Update MII RX_DATA register
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
UpdateMIIRX_DATAReg <= #Tp 0;
else
if(EndBusy & ~WCtrlDataStart_q)
UpdateMIIRX_DATAReg <= #Tp 1;
else
UpdateMIIRX_DATAReg <= #Tp 0;
end
 
 
 
// Generation of the delayed signals used for positive edge triggering.
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
WCtrlData_q1 <= #Tp 1'b0;
WCtrlData_q2 <= #Tp 1'b0;
WCtrlData_q3 <= #Tp 1'b0;
RStat_q1 <= #Tp 1'b0;
RStat_q2 <= #Tp 1'b0;
RStat_q3 <= #Tp 1'b0;
 
ScanStat_q1 <= #Tp 1'b0;
ScanStat_q2 <= #Tp 1'b0;
SyncStatMdcEn <= #Tp 1'b0;
end
else
begin
WCtrlData_q1 <= #Tp WCtrlData;
WCtrlData_q2 <= #Tp WCtrlData_q1;
WCtrlData_q3 <= #Tp WCtrlData_q2;
 
RStat_q1 <= #Tp RStat;
RStat_q2 <= #Tp RStat_q1;
RStat_q3 <= #Tp RStat_q2;
 
ScanStat_q1 <= #Tp ScanStat;
ScanStat_q2 <= #Tp ScanStat_q1;
if(MdcEn)
SyncStatMdcEn <= #Tp ScanStat_q2;
end
end
 
 
// Generation of the Start Commands (Write Control Data or Read Status)
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
WCtrlDataStart <= #Tp 1'b0;
WCtrlDataStart_q <= #Tp 1'b0;
RStatStart <= #Tp 1'b0;
end
else
begin
if(EndBusy)
begin
WCtrlDataStart <= #Tp 1'b0;
RStatStart <= #Tp 1'b0;
end
else
begin
if(WCtrlData_q2 & ~WCtrlData_q3)
WCtrlDataStart <= #Tp 1'b1;
if(RStat_q2 & ~RStat_q3)
RStatStart <= #Tp 1'b1;
WCtrlDataStart_q <= #Tp WCtrlDataStart;
end
end
end
 
 
// Generation of the Nvalid signal (indicates when the status is invalid)
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
Nvalid <= #Tp 1'b0;
else
begin
if(~InProgress & InProgress_q1)
begin
Nvalid <= #Tp 1'b0;
end
else
begin
if(ScanStat_q2 & ~SyncStatMdcEn)
Nvalid <= #Tp 1'b1;
end
end
end
 
// Signals used for the generation of the Operation signals (positive edge)
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
WCtrlDataStart_q1 <= #Tp 1'b0;
WCtrlDataStart_q2 <= #Tp 1'b0;
 
RStatStart_q1 <= #Tp 1'b0;
RStatStart_q2 <= #Tp 1'b0;
 
InProgress_q1 <= #Tp 1'b0;
InProgress_q2 <= #Tp 1'b0;
InProgress_q3 <= #Tp 1'b0;
 
LatchByte0_d <= #Tp 1'b0;
LatchByte1_d <= #Tp 1'b0;
 
LatchByte <= #Tp 2'b00;
end
else
begin
if(MdcEn)
begin
WCtrlDataStart_q1 <= #Tp WCtrlDataStart;
WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1;
 
RStatStart_q1 <= #Tp RStatStart;
RStatStart_q2 <= #Tp RStatStart_q1;
 
LatchByte[0] <= #Tp LatchByte0_d;
LatchByte[1] <= #Tp LatchByte1_d;
 
LatchByte0_d <= #Tp LatchByte0_d2;
LatchByte1_d <= #Tp LatchByte1_d2;
 
InProgress_q1 <= #Tp InProgress;
InProgress_q2 <= #Tp InProgress_q1;
InProgress_q3 <= #Tp InProgress_q2;
end
end
end
 
 
// Generation of the Operation signals
assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2;
assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2;
assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2;
assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp;
 
// Busy
assign Busy = WCtrlDataStart | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3;
 
 
// Generation of the InProgress signal (indicates when an operation is in progress)
// Generation of the WriteOp signal (indicates when a write is in progress)
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
begin
InProgress <= #Tp 1'b0;
WriteOp <= #Tp 1'b0;
end
else
begin
if(MdcEn)
begin
if(StartOp)
begin
if(~InProgress)
WriteOp <= #Tp WriteDataOp;
InProgress <= #Tp 1'b1;
end
else
begin
if(EndOp)
begin
InProgress <= #Tp 1'b0;
WriteOp <= #Tp 1'b0;
end
end
end
end
end
 
 
 
// Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
BitCounter[6:0] <= #Tp 7'h0;
else
begin
if(MdcEn)
begin
if(InProgress)
begin
if(NoPre & ( BitCounter == 7'h0 ))
BitCounter[6:0] <= #Tp 7'h21;
else
BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1;
end
else
BitCounter[6:0] <= #Tp 7'h0;
end
end
end
 
 
// Operation ends when the Bit Counter reaches 63
assign EndOp = BitCounter==63;
 
assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20)));
assign ByteSelect[1] = InProgress & (BitCounter == 7'h28);
assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30);
assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38);
 
 
// Latch Byte selects which part of Read Status Data is updated from the shift register
assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37;
assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F;
 
 
// Connecting the Clock Generator Module
eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc)
);
 
// Connecting the Shift Register Module
eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad),
.CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte),
.ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail)
);
 
// Connecting the Output Control Module
eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress),
.ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre),
.Mdo(Mdo), .MdoEn(MdoEn)
);
 
endmodule
/rtl/verilog/eth_maccontrol.v
0,0 → 1,249
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_maccontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.1 2001/07/03 12:51:54 mohor
// Initial release of the MAC Control module.
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_maccontrol (MTxClk, MRxClk, TxReset, RxReset, TPauseRq, TxDataIn, TxStartFrmIn, TxUsedDataIn,
TxEndFrmIn, TxDoneIn, TxAbortIn, RxData, RxValid, RxStartFrm, RxEndFrm, ReceiveEnd,
ReceivedPacketGood, ReceivedLengthOK, TxFlow, RxFlow, PassAll, DlyCrcEn, TxPauseTV,
MAC, PadIn, PadOut, CrcEnIn, CrcEnOut, TxDataOut, TxStartFrmOut, TxEndFrmOut,
TxDoneOut, TxAbortOut, TxUsedDataOut, WillSendControlFrame, TxCtrlEndFrm,
ReceivedPauseFrm
);
 
 
parameter Tp = 1;
 
 
input MTxClk; // Transmit clock (from PHY)
input MRxClk; // Receive clock (from PHY)
input TxReset; // Transmit reset
input RxReset; // Receive reset
input TPauseRq; // Transmit control frame (from host)
input [7:0] TxDataIn; // Transmit packet data byte (from host)
input TxStartFrmIn; // Transmit packet start frame input (from host)
input TxUsedDataIn; // Transmit packet used data (from TxEthMAC)
input TxEndFrmIn; // Transmit packet end frame input (from host)
input TxDoneIn; // Transmit packet done (from TxEthMAC)
input TxAbortIn; // Transmit packet abort (input from TxEthMAC)
input PadIn; // Padding (input from registers)
input CrcEnIn; // Crc append (input from registers)
input [7:0] RxData; // Receive Packet Data (from RxEthMAC)
input RxValid; // Received a valid packet
input RxStartFrm; // Receive packet start frame (input from RxEthMAC)
input RxEndFrm; // Receive packet end frame (input from RxEthMAC)
input ReceiveEnd; // End of receiving of the current packet (input from RxEthMAC)
input ReceivedPacketGood; // Received packet is good
input ReceivedLengthOK; // Length of the received packet is OK
input TxFlow; // Tx flow control (from registers)
input RxFlow; // Rx flow control (from registers)
input PassAll; // Pass All received frames (from registers)
input DlyCrcEn; // Delayed CRC enabled (from registers)
input [15:0] TxPauseTV; // Transmit Pause Timer Value (from registers)
input [47:0] MAC; // MAC address (from registers)
 
output [7:0] TxDataOut; // Transmit Packet Data (to TxEthMAC)
output TxStartFrmOut; // Transmit packet start frame (output to TxEthMAC)
output TxEndFrmOut; // Transmit packet end frame (output to TxEthMAC)
output TxDoneOut; // Transmit packet done (to host)
output TxAbortOut; // Transmit packet aborted (to host)
output TxUsedDataOut; // Transmit packet used data (to host)
output PadOut; // Padding (output to TxEthMAC)
output CrcEnOut; // Crc append (output to TxEthMAC)
output WillSendControlFrame;
output TxCtrlEndFrm;
output ReceivedPauseFrm;
 
reg TxUsedDataOutDetected;
reg TxAbortInLatched;
reg TxDoneInLatched;
reg MuxedDone;
reg MuxedAbort;
 
wire Pause;
wire TxCtrlStartFrm;
wire [7:0] ControlData;
wire CtrlMux;
wire SendingCtrlFrm; // Sending Control Frame (enables padding and CRC)
 
 
// Signal TxUsedDataOut was detected (a transfer is already in progress)
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
TxUsedDataOutDetected <= #Tp 1'b0;
else
if(TxDoneIn | TxAbortIn)
TxUsedDataOutDetected <= #Tp 1'b0;
else
if(TxUsedDataOut)
TxUsedDataOutDetected <= #Tp 1'b1;
end
 
 
// Latching variables
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
begin
TxAbortInLatched <= #Tp 1'b0;
TxDoneInLatched <= #Tp 1'b0;
end
else
begin
TxAbortInLatched <= #Tp TxAbortIn;
TxDoneInLatched <= #Tp TxDoneIn;
end
end
 
 
 
// Generating muxed abort signal
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
MuxedAbort <= #Tp 1'b0;
else
if(TxStartFrmIn)
MuxedAbort <= #Tp 1'b0;
else
if(TxAbortIn & ~TxAbortInLatched & TxUsedDataOutDetected)
MuxedAbort <= #Tp 1'b1;
end
 
 
// Generating muxed done signal
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
MuxedDone <= #Tp 1'b0;
else
if(TxStartFrmIn)
MuxedDone <= #Tp 1'b0;
else
if(TxDoneIn & ~TxDoneInLatched & TxUsedDataOutDetected)
MuxedDone <= #Tp 1'b1;
end
 
// TxDoneOut
assign TxDoneOut = CtrlMux? (~TxStartFrmIn & MuxedDone) :
(~TxStartFrmIn & TxDoneIn);
 
// TxAbortOut
assign TxAbortOut = CtrlMux? (~TxStartFrmIn & MuxedAbort) :
(TxAbortIn);
 
// TxUsedDataOut
assign TxUsedDataOut = ~CtrlMux & TxUsedDataIn;
 
// TxStartFrmOut
assign TxStartFrmOut = CtrlMux? TxCtrlStartFrm : (TxStartFrmIn & ~Pause);
 
 
// TxEndFrmOut
assign TxEndFrmOut = CtrlMux? TxCtrlEndFrm : TxEndFrmIn;
 
 
// TxDataOut[7:0]
assign TxDataOut[7:0] = CtrlMux? ControlData[7:0] : TxDataIn[7:0];
 
 
// PadOut
assign PadOut = PadIn | SendingCtrlFrm;
 
 
// CrcEnOut
assign CrcEnOut = CrcEnIn | SendingCtrlFrm;
 
 
 
// Connecting receivecontrol module
eth_receivecontrol receivecontrol1
(
.MTxClk(MTxClk), .MRxClk(MRxClk), .TxReset(TxReset), .RxReset(RxReset), .RxData(RxData),
.RxValid(RxValid), .RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm), .RxFlow(RxFlow),
.ReceiveEnd(ReceiveEnd), .MAC(MAC), .PassAll(PassAll), .DlyCrcEn(DlyCrcEn), .TxDoneIn(TxDoneIn),
.TxAbortIn(TxAbortIn), .TxStartFrmOut(TxStartFrmOut), .ReceivedLengthOK(ReceivedLengthOK),
.ReceivedPacketGood(ReceivedPacketGood), .TxUsedDataOutDetected(TxUsedDataOutDetected),
.Pause(Pause), .ReceivedPauseFrm(ReceivedPauseFrm)
);
 
 
eth_transmitcontrol transmitcontrol1
(
.MTxClk(MTxClk), .TxReset(TxReset), .TxUsedDataIn(TxUsedDataIn), .TxUsedDataOut(TxUsedDataOut),
.TxDoneIn(TxDoneIn), .TxAbortIn(TxAbortIn), .TxStartFrmIn(TxStartFrmIn), .TPauseRq(TPauseRq),
.TxUsedDataOutDetected(TxUsedDataOutDetected), .TxFlow(TxFlow), .DlyCrcEn(DlyCrcEn), .TxPauseTV(TxPauseTV),
.MAC(MAC), .TxCtrlStartFrm(TxCtrlStartFrm), .TxCtrlEndFrm(TxCtrlEndFrm), .SendingCtrlFrm(SendingCtrlFrm),
.CtrlMux(CtrlMux), .ControlData(ControlData), .WillSendControlFrame(WillSendControlFrame)
);
 
 
 
endmodule
/rtl/verilog/eth_transmitcontrol.v
0,0 → 1,294
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_transmitcontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.1 2001/07/03 12:51:54 mohor
// Initial release of the MAC Control module.
//
//
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_transmitcontrol (MTxClk, TxReset, TxUsedDataIn, TxUsedDataOut, TxDoneIn, TxAbortIn,
TxStartFrmIn, TPauseRq, TxUsedDataOutDetected, TxFlow, DlyCrcEn,
TxPauseTV, MAC, TxCtrlStartFrm, TxCtrlEndFrm, SendingCtrlFrm, CtrlMux,
ControlData, WillSendControlFrame
);
 
parameter Tp = 1;
 
 
input MTxClk;
input TxReset;
input TxUsedDataIn;
input TxUsedDataOut;
input TxDoneIn;
input TxAbortIn;
input TxStartFrmIn;
input TPauseRq;
input TxUsedDataOutDetected;
input TxFlow;
input DlyCrcEn;
input [15:0] TxPauseTV;
input [47:0] MAC;
 
output TxCtrlStartFrm;
output TxCtrlEndFrm;
output SendingCtrlFrm;
output CtrlMux;
output [7:0] ControlData;
output WillSendControlFrame;
 
reg SendingCtrlFrm;
reg CtrlMux;
reg WillSendControlFrame;
reg [3:0] DlyCrcCnt;
reg [5:0] ByteCnt;
reg ControlEnd_q;
reg [7:0] MuxedCtrlData;
reg TxCtrlStartFrm;
reg TxCtrlStartFrm_q;
reg TxCtrlEndFrm;
reg [7:0] ControlData;
reg TxUsedDataIn_q;
 
wire IncrementDlyCrcCnt;
wire ResetByteCnt;
wire IncrementByteCnt;
wire ControlEnd;
 
 
// A command for Sending the control frame is active (latched)
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
WillSendControlFrame <= #Tp 1'b0;
else
if(TxCtrlEndFrm & CtrlMux)
WillSendControlFrame <= #Tp 1'b0;
else
if(TPauseRq & TxFlow)
WillSendControlFrame <= #Tp 1'b1;
end
 
 
// Generation of the transmit control packet start frame
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
TxCtrlStartFrm <= #Tp 1'b0;
else
if(TxUsedDataIn_q & CtrlMux)
TxCtrlStartFrm <= #Tp 1'b0;
else
if(WillSendControlFrame & ~TxUsedDataOut & (TxDoneIn | TxAbortIn | TxStartFrmIn | ~TxUsedDataOutDetected))
TxCtrlStartFrm <= #Tp 1'b1;
end
 
 
 
// Generation of the transmit control packet end frame
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
TxCtrlEndFrm <= #Tp 1'b0;
else
if(ControlEnd | ControlEnd_q)
TxCtrlEndFrm <= #Tp 1'b1;
else
TxCtrlEndFrm <= #Tp 1'b0;
end
 
 
// Generation of the multiplexer signal (controls muxes for switching between
// normal and control packets)
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
CtrlMux <= #Tp 1'b0;
else
if(WillSendControlFrame & ~TxUsedDataOut)
CtrlMux <= #Tp 1'b1;
else
if(TxDoneIn)
CtrlMux <= #Tp 1'b0;
end
 
 
 
// Generation of the Sending Control Frame signal (enables padding and CRC)
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
SendingCtrlFrm <= #Tp 1'b0;
else
if(WillSendControlFrame & TxCtrlStartFrm)
SendingCtrlFrm <= #Tp 1'b1;
else
if(TxDoneIn)
SendingCtrlFrm <= #Tp 1'b0;
end
 
 
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
TxUsedDataIn_q <= #Tp 1'b0;
else
TxUsedDataIn_q <= #Tp TxUsedDataIn;
end
 
 
always @ (posedge MTxClk)
begin
ControlEnd_q <= #Tp ControlEnd;
TxCtrlStartFrm_q <= #Tp TxCtrlStartFrm;
end
 
 
assign IncrementDlyCrcCnt = CtrlMux & TxUsedDataIn & ~DlyCrcCnt[2];
 
 
// Delayed CRC counter
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
DlyCrcCnt <= #Tp 4'h0;
else
if(ResetByteCnt)
DlyCrcCnt <= #Tp 4'h0;
else
if(IncrementDlyCrcCnt)
DlyCrcCnt <= #Tp DlyCrcCnt + 1'b1;
end
 
assign ResetByteCnt = TxReset | (~TxCtrlStartFrm & (TxDoneIn | TxAbortIn));
assign IncrementByteCnt = CtrlMux & (TxCtrlStartFrm & ~TxCtrlStartFrm_q & ~TxUsedDataIn | TxUsedDataIn & ~ControlEnd);
 
 
// Byte counter
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
ByteCnt <= #Tp 6'h0;
else
if(ResetByteCnt)
ByteCnt <= #Tp 6'h0;
else
if(IncrementByteCnt & (~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0])))
ByteCnt <= #Tp (ByteCnt[5:0] ) + 1'b1;
end
 
 
assign ControlEnd = ByteCnt[5:0] == 6'h22;
 
 
// Control data generation (goes to the TxEthMAC module)
always @ (ByteCnt or DlyCrcEn or MAC or TxPauseTV or DlyCrcCnt)
begin
case(ByteCnt)
6'h0: if(~DlyCrcEn | DlyCrcEn & (&DlyCrcCnt[1:0]))
MuxedCtrlData[7:0] = 8'h01; // Reserved Multicast Address
else
MuxedCtrlData[7:0] = 8'h0;
6'h2: MuxedCtrlData[7:0] = 8'h80;
6'h4: MuxedCtrlData[7:0] = 8'hC2;
6'h6: MuxedCtrlData[7:0] = 8'h00;
6'h8: MuxedCtrlData[7:0] = 8'h00;
6'hA: MuxedCtrlData[7:0] = 8'h01;
6'hC: MuxedCtrlData[7:0] = MAC[47:40];
6'hE: MuxedCtrlData[7:0] = MAC[39:32];
6'h10: MuxedCtrlData[7:0] = MAC[31:24];
6'h12: MuxedCtrlData[7:0] = MAC[23:16];
6'h14: MuxedCtrlData[7:0] = MAC[15:8];
6'h16: MuxedCtrlData[7:0] = MAC[7:0];
6'h18: MuxedCtrlData[7:0] = 8'h88; // Type/Length
6'h1A: MuxedCtrlData[7:0] = 8'h08;
6'h1C: MuxedCtrlData[7:0] = 8'h00; // Opcode
6'h1E: MuxedCtrlData[7:0] = 8'h01;
6'h20: MuxedCtrlData[7:0] = TxPauseTV[15:8]; // Pause timer value
6'h22: MuxedCtrlData[7:0] = TxPauseTV[7:0];
default: MuxedCtrlData[7:0] = 8'h0;
endcase
end
 
 
// Latched Control data
always @ (posedge MTxClk or posedge TxReset)
begin
if(TxReset)
ControlData[7:0] <= #Tp 8'h0;
else
if(~ByteCnt[0])
ControlData[7:0] <= #Tp MuxedCtrlData[7:0];
end
 
 
 
endmodule
/rtl/verilog/timescale.v
0,0 → 1,50
//////////////////////////////////////////////////////////////////////
//// ////
//// timescale.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 11:36:31 mohor
// Log file added.
//
//
//
 
`timescale 1ns / 1ns
/rtl/verilog/eth_rxstatem.v
0,0 → 1,194
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxstatem.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.4 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.3 2001/10/18 12:07:11 mohor
// Status signals changed, Adress decoding changed, interrupt controller
// added.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.2 2001/07/03 12:55:41 mohor
// Minor changes because of the synthesys warnings.
//
//
// Revision 1.1 2001/06/27 21:26:19 mohor
// Initial release of the RxEthMAC module.
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_rxstatem (MRxClk, Reset, MRxDV, ByteCntEq0, ByteCntGreat2, Transmitting, MRxDEq5, MRxDEqD,
IFGCounterEq24, ByteCntMaxFrame, StateData, StateIdle, StatePreamble, StateSFD,
StateDrop
);
 
parameter Tp = 1;
 
input MRxClk;
input Reset;
input MRxDV;
input ByteCntEq0;
input ByteCntGreat2;
input MRxDEq5;
input Transmitting;
input MRxDEqD;
input IFGCounterEq24;
input ByteCntMaxFrame;
 
output [1:0] StateData;
output StateIdle;
output StateDrop;
output StatePreamble;
output StateSFD;
 
reg StateData0;
reg StateData1;
reg StateIdle;
reg StateDrop;
reg StatePreamble;
reg StateSFD;
 
wire StartIdle;
wire StartDrop;
wire StartData0;
wire StartData1;
wire StartPreamble;
wire StartSFD;
 
 
// Defining the next state
assign StartIdle = ~MRxDV & (StateDrop | StatePreamble | StateSFD | (|StateData) & (ByteCntEq0 | ByteCntGreat2));
 
assign StartPreamble = MRxDV & ~MRxDEq5 & (StateIdle & ~Transmitting);
 
//assign StartSFD = MRxDV & MRxDEq5 & (StateIdle & ~Transmitting);
assign StartSFD = MRxDV & MRxDEq5 & (StateIdle & ~Transmitting | StatePreamble);
 
assign StartData0 = MRxDV & (StateSFD & MRxDEqD & IFGCounterEq24 | StateData1);
 
assign StartData1 = MRxDV & StateData0;
 
assign StartDrop = MRxDV & (StateIdle & Transmitting | StateSFD & ~IFGCounterEq24 & MRxDEqD
| StateData0 & ByteCntMaxFrame
);
 
// Rx State Machine
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
begin
StateIdle <= #Tp 1'b0;
StateDrop <= #Tp 1'b1;
StatePreamble <= #Tp 1'b0;
StateSFD <= #Tp 1'b0;
StateData0 <= #Tp 1'b0;
StateData1 <= #Tp 1'b0;
end
else
begin
if(StartPreamble | StartSFD | StartDrop)
StateIdle <= #Tp 1'b0;
else
if(StartIdle)
StateIdle <= #Tp 1'b1;
 
if(StartIdle)
StateDrop <= #Tp 1'b0;
else
if(StartDrop)
StateDrop <= #Tp 1'b1;
 
if(StartSFD | StartIdle | StartDrop)
StatePreamble <= #Tp 1'b0;
else
if(StartPreamble)
StatePreamble <= #Tp 1'b1;
 
if(StartPreamble | StartIdle | StartData0 | StartDrop)
StateSFD <= #Tp 1'b0;
else
if(StartSFD)
StateSFD <= #Tp 1'b1;
 
if(StartIdle | StartData1 | StartDrop)
StateData0 <= #Tp 1'b0;
else
if(StartData0)
StateData0 <= #Tp 1'b1;
 
if(StartIdle | StartData0 | StartDrop)
StateData1 <= #Tp 1'b0;
else
if(StartData1)
StateData1 <= #Tp 1'b1;
end
end
 
assign StateData[1:0] = {StateData1, StateData0};
 
endmodule
/rtl/verilog/eth_crc.v
0,0 → 1,145
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_crc.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/19 18:16:40 mohor
// TxClk changed to MTxClk (as discribed in the documentation).
// Crc changed so only one file can be used instead of two.
//
// Revision 1.2 2001/06/19 10:38:07 mohor
// Minor changes in header.
//
// Revision 1.1 2001/06/19 10:27:57 mohor
// TxEthMAC initial release.
//
//
//
 
 
`include "timescale.v"
 
module eth_crc (Clk, Reset, Data, Enable, Initialize, Crc, CrcError);
 
 
parameter Tp = 1;
 
input Clk;
input Reset;
input [3:0] Data;
input Enable;
input Initialize;
 
output [31:0] Crc;
output CrcError;
 
reg [31:0] Crc;
 
wire [31:0] CrcNext;
 
 
assign CrcNext[0] = Enable & (Data[0] ^ Crc[28]);
assign CrcNext[1] = Enable & (Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29]);
assign CrcNext[2] = Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30]);
assign CrcNext[3] = Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31]);
assign CrcNext[4] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[0];
assign CrcNext[5] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[1];
assign CrcNext[6] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[ 2];
assign CrcNext[7] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[3];
assign CrcNext[8] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[4];
assign CrcNext[9] = (Enable & (Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30])) ^ Crc[5];
assign CrcNext[10] = (Enable & (Data[3] ^ Data[2] ^ Data[0] ^ Crc[28] ^ Crc[30] ^ Crc[31])) ^ Crc[6];
assign CrcNext[11] = (Enable & (Data[3] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[31])) ^ Crc[7];
assign CrcNext[12] = (Enable & (Data[2] ^ Data[1] ^ Data[0] ^ Crc[28] ^ Crc[29] ^ Crc[30])) ^ Crc[8];
assign CrcNext[13] = (Enable & (Data[3] ^ Data[2] ^ Data[1] ^ Crc[29] ^ Crc[30] ^ Crc[31])) ^ Crc[9];
assign CrcNext[14] = (Enable & (Data[3] ^ Data[2] ^ Crc[30] ^ Crc[31])) ^ Crc[10];
assign CrcNext[15] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[11];
assign CrcNext[16] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[12];
assign CrcNext[17] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[13];
assign CrcNext[18] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[14];
assign CrcNext[19] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[15];
assign CrcNext[20] = Crc[16];
assign CrcNext[21] = Crc[17];
assign CrcNext[22] = (Enable & (Data[0] ^ Crc[28])) ^ Crc[18];
assign CrcNext[23] = (Enable & (Data[1] ^ Data[0] ^ Crc[29] ^ Crc[28])) ^ Crc[19];
assign CrcNext[24] = (Enable & (Data[2] ^ Data[1] ^ Crc[30] ^ Crc[29])) ^ Crc[20];
assign CrcNext[25] = (Enable & (Data[3] ^ Data[2] ^ Crc[31] ^ Crc[30])) ^ Crc[21];
assign CrcNext[26] = (Enable & (Data[3] ^ Data[0] ^ Crc[31] ^ Crc[28])) ^ Crc[22];
assign CrcNext[27] = (Enable & (Data[1] ^ Crc[29])) ^ Crc[23];
assign CrcNext[28] = (Enable & (Data[2] ^ Crc[30])) ^ Crc[24];
assign CrcNext[29] = (Enable & (Data[3] ^ Crc[31])) ^ Crc[25];
assign CrcNext[30] = Crc[26];
assign CrcNext[31] = Crc[27];
 
 
always @ (posedge Clk or posedge Reset)
begin
if (Reset)
Crc <= #1 32'hffffffff;
else
if(Initialize)
Crc <= #Tp 32'hffffffff;
else
Crc <= #Tp CrcNext;
end
 
assign CrcError = Crc[31:0] != 32'hc704dd7b; // CRC not equal to magic number
 
endmodule
/rtl/verilog/eth_txstatem.v
0,0 → 1,277
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txstatem.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// - Novan Hartadi (novan@vlsi.itb.ac.id) ////
//// - Mahmud Galela (mgalela@vlsi.itb.ac.id) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2001/10/19 08:43:51 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.2 2001/09/11 14:17:00 mohor
// Few little NCSIM warnings fixed.
//
// Revision 1.1 2001/08/06 14:44:29 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
// Revision 1.3 2001/06/19 18:16:40 mohor
// TxClk changed to MTxClk (as discribed in the documentation).
// Crc changed so only one file can be used instead of two.
//
// Revision 1.2 2001/06/19 10:38:07 mohor
// Minor changes in header.
//
// Revision 1.1 2001/06/19 10:27:57 mohor
// TxEthMAC initial release.
//
//
//
//
 
 
`include "timescale.v"
 
 
module eth_txstatem (MTxClk, Reset, ExcessiveDefer, CarrierSense, NibCnt, IPGT, IPGR1,
IPGR2, FullD, TxStartFrm, TxEndFrm, TxUnderRun, Collision, UnderRun,
StartTxDone, TooBig, NibCntEq7, NibCntEq15, MaxFrame, Pad, CrcEn,
NibbleMinFl, RandomEq0, ColWindow, RetryMax, NoBckof, RandomEqByteCnt,
StateIdle, StateIPG, StatePreamble, StateData, StatePAD, StateFCS,
StateJam, StateJam_q, StateBackOff, StateDefer, StartFCS, StartJam,
StartBackoff, StartDefer, StartPreamble, StartData, StartIPG
);
 
parameter Tp = 1;
 
input MTxClk;
input Reset;
input ExcessiveDefer;
input CarrierSense;
input [6:0] NibCnt;
input [6:0] IPGT;
input [6:0] IPGR1;
input [6:0] IPGR2;
input FullD;
input TxStartFrm;
input TxEndFrm;
input TxUnderRun;
input Collision;
input UnderRun;
input StartTxDone;
input TooBig;
input NibCntEq7;
input NibCntEq15;
input MaxFrame;
input Pad;
input CrcEn;
input NibbleMinFl;
input RandomEq0;
input ColWindow;
input RetryMax;
input NoBckof;
input RandomEqByteCnt;
 
 
output StateIdle; // Idle state
output StateIPG; // IPG state
output StatePreamble; // Preamble state
output [1:0] StateData; // Data state
output StatePAD; // PAD state
output StateFCS; // FCS state
output StateJam; // Jam state
output StateJam_q; // Delayed Jam state
output StateBackOff; // Backoff state
output StateDefer; // Defer state
 
output StartFCS; // FCS state will be activated in next clock
output StartJam; // Jam state will be activated in next clock
output StartBackoff; // Backoff state will be activated in next clock
output StartDefer; // Defer state will be activated in next clock
output StartPreamble; // Preamble state will be activated in next clock
output [1:0] StartData; // Data state will be activated in next clock
output StartIPG; // IPG state will be activated in next clock
 
wire StartIdle; // Idle state will be activated in next clock
wire StartPAD; // PAD state will be activated in next clock
 
 
reg StateIdle;
reg StateIPG;
reg StatePreamble;
reg [1:0] StateData;
reg StatePAD;
reg StateFCS;
reg StateJam;
reg StateJam_q;
reg StateBackOff;
reg StateDefer;
reg Rule1;
 
 
// Defining the next state
assign StartIPG = StateDefer & ~ExcessiveDefer & ~CarrierSense;
 
assign StartIdle = StateIPG & (Rule1 & NibCnt[6:0] >= IPGT | ~Rule1 & NibCnt[6:0] >= IPGR2);
 
assign StartPreamble = StateIdle & TxStartFrm;
 
assign StartData[0] = ~Collision & (StatePreamble & NibCntEq15 | StateData[1] & ~TxEndFrm);
 
assign StartData[1] = ~Collision & StateData[0] & ~TxUnderRun & ~MaxFrame;
 
assign StartPAD = ~Collision & StateData[1] & TxEndFrm & Pad & ~NibbleMinFl;
 
assign StartFCS = ~Collision & StateData[1] & TxEndFrm & (~Pad & CrcEn | Pad & NibbleMinFl)
| ~Collision & StatePAD & NibbleMinFl;
 
assign StartJam = (Collision | UnderRun) & ((StatePreamble & NibCntEq15) | (|StateData[1:0]) | StatePAD | StateFCS);
 
assign StartBackoff = StateJam & ~RandomEq0 & ColWindow & ~RetryMax & NibCntEq7 & ~NoBckof;
 
assign StartDefer = StateIPG & ~Rule1 & CarrierSense & NibCnt[6:0] <= IPGR1 & NibCnt[6:0] != IPGR2
| StateIdle & ~TxStartFrm & CarrierSense
| StateJam & NibCntEq7 & (NoBckof | RandomEq0 | ~ColWindow | RetryMax)
| StateBackOff & (TxUnderRun | RandomEqByteCnt)
| StartTxDone | TooBig;
 
 
 
// Tx State Machine
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
begin
StateIPG <= #Tp 1'b0;
StateIdle <= #Tp 1'b0;
StatePreamble <= #Tp 1'b0;
StateData[1:0] <= #Tp 2'b0;
StatePAD <= #Tp 1'b0;
StateFCS <= #Tp 1'b0;
StateJam <= #Tp 1'b0;
StateJam_q <= #Tp 1'b0;
StateBackOff <= #Tp 1'b0;
StateDefer <= #Tp 1'b1;
end
else
begin
StateData[1:0] <= #Tp StartData[1:0];
StateJam_q <= #Tp StateJam;
 
if(StartDefer | StartIdle)
StateIPG <= #Tp 1'b0;
else
if(StartIPG)
StateIPG <= #Tp 1'b1;
 
if(StartDefer | StartPreamble)
StateIdle <= #Tp 1'b0;
else
if(StartIdle)
StateIdle <= #Tp 1'b1;
 
if(StartData[0] | StartJam)
StatePreamble <= #Tp 1'b0;
else
if(StartPreamble)
StatePreamble <= #Tp 1'b1;
 
if(StartFCS | StartJam)
StatePAD <= #Tp 1'b0;
else
if(StartPAD)
StatePAD <= #Tp 1'b1;
 
if(StartJam | StartDefer)
StateFCS <= #Tp 1'b0;
else
if(StartFCS)
StateFCS <= #Tp 1'b1;
 
if(StartBackoff | StartDefer)
StateJam <= #Tp 1'b0;
else
if(StartJam)
StateJam <= #Tp 1'b1;
 
if(StartDefer)
StateBackOff <= #Tp 1'b0;
else
if(StartBackoff)
StateBackOff <= #Tp 1'b1;
 
if(StartIPG)
StateDefer <= #Tp 1'b0;
else
if(StartDefer)
StateDefer <= #Tp 1'b1;
end
end
 
 
// This sections defines which interpack gap rule to use
always @ (posedge MTxClk or posedge Reset)
begin
if(Reset)
Rule1 <= #Tp 1'b0;
else
begin
if(StateIdle | StateBackOff)
Rule1 <= #Tp 1'b0;
else
if(StatePreamble | FullD)
Rule1 <= #Tp 1'b1;
end
end
 
 
 
endmodule
/bench/verilog/tb_eth_defines.v
0,0 → 1,194
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.3 2002/07/19 13:57:53 mohor
// Testing environment also includes traffic cop, memory interface and host
// interface.
//
// Revision 1.2 2002/05/03 10:22:17 mohor
// TX_BUF_BASE changed.
//
// Revision 1.1 2002/03/19 12:53:54 mohor
// Some defines that are used in testbench only were moved to tb_eth_defines.v
// file.
//
//
//
//
 
 
//`define EXTERNAL_DMA // Using DMA
 
`define MULTICAST_XFR 0
`define UNICAST_XFR 1
`define BROADCAST_XFR 2
`define UNICAST_WRONG_XFR 3
 
`define ETH_BASE 32'hd0000000
`define ETH_WIDTH 32'h800
`define MEMORY_BASE 32'h2000
`define MEMORY_WIDTH 32'h10000
`define TX_BUF_BASE `MEMORY_BASE
`define RX_BUF_BASE `MEMORY_BASE + 32'h8000
`define TX_BD_BASE `ETH_BASE + 32'h00000400
`define RX_BD_BASE `ETH_BASE + 32'h00000600
 
`define M1_ADDRESSED_S1 ( (m1_wb_adr_i >= `ETH_BASE) & (m1_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) )
`define M1_ADDRESSED_S2 ( (m1_wb_adr_i >= `MEMORY_BASE) & (m1_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) )
`define M2_ADDRESSED_S1 ( (m2_wb_adr_i >= `ETH_BASE) & (m2_wb_adr_i < (`ETH_BASE + `ETH_WIDTH )) )
`define M2_ADDRESSED_S2 ( (m2_wb_adr_i >= `MEMORY_BASE) & (m2_wb_adr_i < (`MEMORY_BASE + `MEMORY_WIDTH)) )
 
 
 
/* Tx BD */
`define ETH_TX_BD_READY 32'h8000 /* Tx BD Ready */
`define ETH_TX_BD_IRQ 32'h4000 /* Tx BD IRQ Enable */
`define ETH_TX_BD_WRAP 32'h2000 /* Tx BD Wrap (last BD) */
`define ETH_TX_BD_PAD 32'h1000 /* Tx BD Pad Enable */
`define ETH_TX_BD_CRC 32'h0800 /* Tx BD CRC Enable */
 
`define ETH_TX_BD_UNDERRUN 32'h0100 /* Tx BD Underrun Status */
`define ETH_TX_BD_RETRY 32'h00F0 /* Tx BD Retry Status */
`define ETH_TX_BD_RETLIM 32'h0008 /* Tx BD Retransmission Limit Status */
`define ETH_TX_BD_LATECOL 32'h0004 /* Tx BD Late Collision Status */
`define ETH_TX_BD_DEFER 32'h0002 /* Tx BD Defer Status */
`define ETH_TX_BD_CARRIER 32'h0001 /* Tx BD Carrier Sense Lost Status */
 
/* Rx BD */
`define ETH_RX_BD_EMPTY 32'h8000 /* Rx BD Empty */
`define ETH_RX_BD_IRQ 32'h4000 /* Rx BD IRQ Enable */
`define ETH_RX_BD_WRAP 32'h2000 /* Rx BD Wrap (last BD) */
 
`define ETH_RX_BD_MISS 32'h0080 /* Rx BD Miss Status */
`define ETH_RX_BD_OVERRUN 32'h0040 /* Rx BD Overrun Status */
`define ETH_RX_BD_INVSIMB 32'h0020 /* Rx BD Invalid Symbol Status */
`define ETH_RX_BD_DRIBBLE 32'h0010 /* Rx BD Dribble Nibble Status */
`define ETH_RX_BD_TOOLONG 32'h0008 /* Rx BD Too Long Status */
`define ETH_RX_BD_SHORT 32'h0004 /* Rx BD Too Short Frame Status */
`define ETH_RX_BD_CRCERR 32'h0002 /* Rx BD CRC Error Status */
`define ETH_RX_BD_LATECOL 32'h0001 /* Rx BD Late Collision Status */
 
 
 
/* Register space */
`define ETH_MODER `ETH_BASE + 32'h00 /* Mode Register */
`define ETH_INT `ETH_BASE + 32'h04 /* Interrupt Source Register */
`define ETH_INT_MASK `ETH_BASE + 32'h08 /* Interrupt Mask Register */
`define ETH_IPGT `ETH_BASE + 32'h0C /* Back to Bak Inter Packet Gap Register */
`define ETH_IPGR1 `ETH_BASE + 32'h10 /* Non Back to Back Inter Packet Gap Register 1 */
`define ETH_IPGR2 `ETH_BASE + 32'h14 /* Non Back to Back Inter Packet Gap Register 2 */
`define ETH_PACKETLEN `ETH_BASE + 32'h18 /* Packet Length Register (min. and max.) */
`define ETH_COLLCONF `ETH_BASE + 32'h1C /* Collision and Retry Configuration Register */
`define ETH_RX_BD_NUM `ETH_BASE + 32'h20 /* Receive Buffer Descriptor Number Register */
`define ETH_CTRLMODER `ETH_BASE + 32'h24 /* Control Module Mode Register */
`define ETH_MIIMODER `ETH_BASE + 32'h28 /* MII Mode Register */
`define ETH_MIICOMMAND `ETH_BASE + 32'h2C /* MII Command Register */
`define ETH_MIIADDRESS `ETH_BASE + 32'h30 /* MII Address Register */
`define ETH_MIITX_DATA `ETH_BASE + 32'h34 /* MII Transmit Data Register */
`define ETH_MIIRX_DATA `ETH_BASE + 32'h38 /* MII Receive Data Register */
`define ETH_MIISTATUS `ETH_BASE + 32'h3C /* MII Status Register */
`define ETH_MAC_ADDR0 `ETH_BASE + 32'h40 /* MAC Individual Address Register 0 */
`define ETH_MAC_ADDR1 `ETH_BASE + 32'h44 /* MAC Individual Address Register 1 */
`define ETH_HASH_ADDR0 `ETH_BASE + 32'h48 /* Hash Register 0 */
`define ETH_HASH_ADDR1 `ETH_BASE + 32'h4C /* Hash Register 1 */
 
/* MODER Register */
`define ETH_MODER_RXEN 32'h00000001 /* Receive Enable */
`define ETH_MODER_TXEN 32'h00000002 /* Transmit Enable */
`define ETH_MODER_NOPRE 32'h00000004 /* No Preamble */
`define ETH_MODER_BRO 32'h00000008 /* Reject Broadcast */
`define ETH_MODER_IAM 32'h00000010 /* Use Individual Hash */
`define ETH_MODER_PRO 32'h00000020 /* Promiscuous (receive all) */
`define ETH_MODER_IFG 32'h00000040 /* Min. IFG not required */
`define ETH_MODER_LOOPBCK 32'h00000080 /* Loop Back */
`define ETH_MODER_NOBCKOF 32'h00000100 /* No Backoff */
`define ETH_MODER_EXDFREN 32'h00000200 /* Excess Defer */
`define ETH_MODER_FULLD 32'h00000400 /* Full Duplex */
`define ETH_MODER_RST 32'h00000800 /* Reset MAC */
`define ETH_MODER_DLYCRCEN 32'h00001000 /* Delayed CRC Enable */
`define ETH_MODER_CRCEN 32'h00002000 /* CRC Enable */
`define ETH_MODER_HUGEN 32'h00004000 /* Huge Enable */
`define ETH_MODER_PAD 32'h00008000 /* Pad Enable */
`define ETH_MODER_RECSMALL 32'h00010000 /* Receive Small */
 
/* Interrupt Source Register */
`define ETH_INT_TXB 32'h00000001 /* Transmit Buffer IRQ */
`define ETH_INT_TXE 32'h00000002 /* Transmit Error IRQ */
`define ETH_INT_RXF 32'h00000004 /* Receive Frame IRQ */
`define ETH_INT_RXE 32'h00000008 /* Receive Error IRQ */
`define ETH_INT_BUSY 32'h00000010 /* Busy IRQ */
`define ETH_INT_TXC 32'h00000020 /* Transmit Control Frame IRQ */
`define ETH_INT_RXC 32'h00000040 /* Received Control Frame IRQ */
 
/* Interrupt Mask Register */
`define ETH_INT_MASK_TXB 32'h00000001 /* Transmit Buffer IRQ Mask */
`define ETH_INT_MASK_TXE 32'h00000002 /* Transmit Error IRQ Mask */
`define ETH_INT_MASK_RXF 32'h00000004 /* Receive Frame IRQ Mask */
`define ETH_INT_MASK_RXE 32'h00000008 /* Receive Error IRQ Mask */
`define ETH_INT_MASK_BUSY 32'h00000010 /* Busy IRQ Mask */
`define ETH_INT_MASK_TXC 32'h00000020 /* Transmit Control Frame IRQ Mask */
`define ETH_INT_MASK_RXC 32'h00000040 /* Received Control Frame IRQ Mask */
 
/* Control Module Mode Register */
`define ETH_CTRLMODER_PASSALL 32'h00000001 /* Pass Control Frames */
`define ETH_CTRLMODER_RXFLOW 32'h00000002 /* Receive Control Flow Enable */
`define ETH_CTRLMODER_TXFLOW 32'h00000004 /* Transmit Control Flow Enable */
 
/* MII Mode Register */
`define ETH_MIIMODER_CLKDIV 32'h000000FF /* Clock Divider */
`define ETH_MIIMODER_NOPRE 32'h00000100 /* No Preamble */
`define ETH_MIIMODER_RST 32'h00000400 /* MIIM Reset */
 
/* MII Command Register */
`define ETH_MIICOMMAND_SCANSTAT 32'h00000001 /* Scan Status */
`define ETH_MIICOMMAND_RSTAT 32'h00000002 /* Read Status */
`define ETH_MIICOMMAND_WCTRLDATA 32'h00000004 /* Write Control Data */
 
/* MII Address Register */
`define ETH_MIIADDRESS_FIAD 32'h0000001F /* PHY Address */
`define ETH_MIIADDRESS_RGAD 32'h00001F00 /* RGAD Address */
 
/* MII Status Register */
`define ETH_MIISTATUS_LINKFAIL 32'h00000001 /* Link Fail */
`define ETH_MIISTATUS_BUSY 32'h00000002 /* MII Busy */
`define ETH_MIISTATUS_NVALID 32'h00000004 /* Data in MII Status Register is invalid */
/bench/verilog/tb_ethernet.v
0,0 → 1,509
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_ethernet.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.2 2002/07/19 14:02:47 mohor
// Clock mrx_clk set to 2.5 MHz.
//
// Revision 1.1 2002/07/19 13:57:53 mohor
// Testing environment also includes traffic cop, memory interface and host
// interface.
//
//
//
//
//
 
 
 
`include "tb_eth_defines.v"
`include "eth_defines.v"
`include "timescale.v"
 
module tb_ethernet();
 
 
parameter Tp = 1;
 
 
reg wb_clk_o;
reg wb_rst_o;
 
reg mtx_clk;
reg mrx_clk;
 
wire [3:0] MTxD;
wire MTxEn;
wire MTxErr;
 
reg [3:0] MRxD; // This goes to PHY
reg MRxDV; // This goes to PHY
reg MRxErr; // This goes to PHY
reg MColl; // This goes to PHY
reg MCrs; // This goes to PHY
 
wire Mdi_I;
wire Mdo_O;
wire Mdo_OE;
wire Mdc_O;
 
integer tx_log;
integer rx_log;
 
reg StartTB;
 
`ifdef ETH_XILINX_RAMB4
reg gsr;
`endif
 
 
integer packet_ready_cnt, send_packet_cnt;
 
 
// Ethernet Slave Interface signals
wire [31:0] eth_sl_wb_adr_i, eth_sl_wb_dat_o, eth_sl_wb_dat_i;
wire [3:0] eth_sl_wb_sel_i;
wire eth_sl_wb_we_i, eth_sl_wb_cyc_i, eth_sl_wb_stb_i, eth_sl_wb_ack_o, eth_sl_wb_err_o;
 
// Memory Slave Interface signals
wire [31:0] mem_sl_wb_adr_i, mem_sl_wb_dat_o, mem_sl_wb_dat_i;
wire [3:0] mem_sl_wb_sel_i;
wire mem_sl_wb_we_i, mem_sl_wb_cyc_i, mem_sl_wb_stb_i, mem_sl_wb_ack_o, mem_sl_wb_err_o;
 
// Ethernet Master Interface signals
wire [31:0] eth_ma_wb_adr_o, eth_ma_wb_dat_i, eth_ma_wb_dat_o;
wire [3:0] eth_ma_wb_sel_o;
wire eth_ma_wb_we_o, eth_ma_wb_cyc_o, eth_ma_wb_stb_o, eth_ma_wb_ack_i, eth_ma_wb_err_i;
 
// Host Master Interface signals
wire [31:0] host_ma_wb_adr_o, host_ma_wb_dat_i, host_ma_wb_dat_o;
wire [3:0] host_ma_wb_sel_o;
wire host_ma_wb_we_o, host_ma_wb_cyc_o, host_ma_wb_stb_o, host_ma_wb_ack_i, host_ma_wb_err_i;
 
 
 
eth_cop i_eth_cop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE MASTER 1 Ethernet Master Interface is connected here
.m1_wb_adr_i(eth_ma_wb_adr_o), .m1_wb_sel_i(eth_ma_wb_sel_o), .m1_wb_we_i (eth_ma_wb_we_o),
.m1_wb_dat_o(eth_ma_wb_dat_i), .m1_wb_dat_i(eth_ma_wb_dat_o), .m1_wb_cyc_i(eth_ma_wb_cyc_o),
.m1_wb_stb_i(eth_ma_wb_stb_o), .m1_wb_ack_o(eth_ma_wb_ack_i), .m1_wb_err_o(eth_ma_wb_err_i),
 
// WISHBONE MASTER 2 Host Interface is connected here
.m2_wb_adr_i(host_ma_wb_adr_o), .m2_wb_sel_i(host_ma_wb_sel_o), .m2_wb_we_i (host_ma_wb_we_o),
.m2_wb_dat_o(host_ma_wb_dat_i), .m2_wb_dat_i(host_ma_wb_dat_o), .m2_wb_cyc_i(host_ma_wb_cyc_o),
.m2_wb_stb_i(host_ma_wb_stb_o), .m2_wb_ack_o(host_ma_wb_ack_i), .m2_wb_err_o(host_ma_wb_err_i),
 
// WISHBONE slave 1 Ethernet Slave Interface is connected here
.s1_wb_adr_o(eth_sl_wb_adr_i), .s1_wb_sel_o(eth_sl_wb_sel_i), .s1_wb_we_o (eth_sl_wb_we_i),
.s1_wb_cyc_o(eth_sl_wb_cyc_i), .s1_wb_stb_o(eth_sl_wb_stb_i), .s1_wb_ack_i(eth_sl_wb_ack_o),
.s1_wb_err_i(eth_sl_wb_err_o), .s1_wb_dat_i(eth_sl_wb_dat_o), .s1_wb_dat_o(eth_sl_wb_dat_i),
 
// WISHBONE slave 2 Memory Interface is connected here
.s2_wb_adr_o(mem_sl_wb_adr_i), .s2_wb_sel_o(mem_sl_wb_sel_i), .s2_wb_we_o (mem_sl_wb_we_i),
.s2_wb_cyc_o(mem_sl_wb_cyc_i), .s2_wb_stb_o(mem_sl_wb_stb_i), .s2_wb_ack_i(mem_sl_wb_ack_o),
.s2_wb_err_i(mem_sl_wb_err_o), .s2_wb_dat_i(mem_sl_wb_dat_o), .s2_wb_dat_o(mem_sl_wb_dat_i)
);
 
 
 
 
// Connecting Ethernet top module
eth_top ethtop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE slave
.wb_adr_i(eth_sl_wb_adr_i[11:2]), .wb_sel_i(eth_sl_wb_sel_i), .wb_we_i(eth_sl_wb_we_i),
.wb_cyc_i(eth_sl_wb_cyc_i), .wb_stb_i(eth_sl_wb_stb_i), .wb_ack_o(eth_sl_wb_ack_o),
.wb_err_o(eth_sl_wb_err_o), .wb_dat_i(eth_sl_wb_dat_i), .wb_dat_o(eth_sl_wb_dat_o),
// WISHBONE master
.m_wb_adr_o(eth_ma_wb_adr_o), .m_wb_sel_o(eth_ma_wb_sel_o), .m_wb_we_o(eth_ma_wb_we_o),
.m_wb_dat_i(eth_ma_wb_dat_i), .m_wb_dat_o(eth_ma_wb_dat_o), .m_wb_cyc_o(eth_ma_wb_cyc_o),
.m_wb_stb_o(eth_ma_wb_stb_o), .m_wb_ack_i(eth_ma_wb_ack_i), .m_wb_err_i(eth_ma_wb_err_i),
 
//TX
.mtx_clk_pad_i(mtx_clk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(mrx_clk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o()
);
 
 
 
// Connecting Memory Interface Module
eth_memory i_eth_memory
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE slave: Memory Interface is connected here
.wb_adr_i(mem_sl_wb_adr_i), .wb_sel_i(mem_sl_wb_sel_i), .wb_we_i (mem_sl_wb_we_i),
.wb_cyc_i(mem_sl_wb_cyc_i), .wb_stb_i(mem_sl_wb_stb_i), .wb_ack_o(mem_sl_wb_ack_o),
.wb_err_o(mem_sl_wb_err_o), .wb_dat_o(mem_sl_wb_dat_o), .wb_dat_i(mem_sl_wb_dat_i)
);
 
 
// Connecting Host Interface
eth_host eth_host
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE master
.wb_adr_o(host_ma_wb_adr_o), .wb_sel_o(host_ma_wb_sel_o), .wb_we_o (host_ma_wb_we_o),
.wb_dat_i(host_ma_wb_dat_i), .wb_dat_o(host_ma_wb_dat_o), .wb_cyc_o(host_ma_wb_cyc_o),
.wb_stb_o(host_ma_wb_stb_o), .wb_ack_i(host_ma_wb_ack_i), .wb_err_i(host_ma_wb_err_i)
);
 
 
 
 
 
// Reset pulse
initial
begin
MCrs=0; // This should come from PHY
MColl=0; // This should come from PHY
MRxD=0; // This should come from PHY
MRxDV=0; // This should come from PHY
MRxErr=0; // This should come from PHY
packet_ready_cnt = 0;
send_packet_cnt = 0;
tx_log = $fopen("ethernet_tx.log");
rx_log = $fopen("ethernet_rx.log");
wb_rst_o = 1'b1;
`ifdef ETH_XILINX_RAMB4
gsr = 1'b0;
#100 gsr = 1'b1;
#100 gsr = 1'b0;
`endif
#100 wb_rst_o = 1'b0;
#100 StartTB = 1'b1;
end
 
`ifdef ETH_XILINX_RAMB4
assign glbl.GSR = gsr;
`endif
 
 
 
// Generating wb_clk_o clock
initial
begin
wb_clk_o=0;
// forever #2.5 wb_clk_o = ~wb_clk_o; // 2*2.5 ns -> 200.0 MHz
// forever #5 wb_clk_o = ~wb_clk_o; // 2*5 ns -> 100.0 MHz
// forever #10 wb_clk_o = ~wb_clk_o; // 2*10 ns -> 50.0 MHz
forever #12.5 wb_clk_o = ~wb_clk_o; // 2*12.5 ns -> 40 MHz
// forever #15 wb_clk_o = ~wb_clk_o; // 2*10 ns -> 33.3 MHz
// forever #20 wb_clk_o = ~wb_clk_o; // 2*20 ns -> 25 MHz
// forever #25 wb_clk_o = ~wb_clk_o; // 2*25 ns -> 20.0 MHz
// forever #31.25 wb_clk_o = ~wb_clk_o; // 2*31.25 ns -> 16.0 MHz
// forever #50 wb_clk_o = ~wb_clk_o; // 2*50 ns -> 10.0 MHz
// forever #55 wb_clk_o = ~wb_clk_o; // 2*55 ns -> 9.1 MHz
end
 
// Generating mtx_clk clock
initial
begin
mtx_clk=0;
// #3 forever #20 mtx_clk = ~mtx_clk; // 2*20 ns -> 25 MHz
#3 forever #200 mtx_clk = ~mtx_clk; // 2*200 ns -> 2.5 MHz
end
 
// Generating mrx_clk clock
initial
begin
mrx_clk=0;
// #16 forever #20 mrx_clk = ~mrx_clk; // 2*20 ns -> 25 MHz
#16 forever #200 mrx_clk = ~mrx_clk; // 2*200 ns -> 2.5 MHz
end
 
reg [31:0] tmp;
initial
begin
wait(StartTB); // Start of testbench
 
eth_host.wb_write(`ETH_MODER, 4'hf, 32'h0); // Reset OFF
eth_host.wb_read(`ETH_MODER, 4'hf, tmp);
 
eth_host.wb_write(32'hd0000000, 4'hf, `ETH_MODER_RXEN | `ETH_MODER_TXEN | `ETH_MODER_PRO |
`ETH_MODER_CRCEN | `ETH_MODER_PAD); // Set MODER register
eth_host.wb_read(32'hd0000000, 4'hf, tmp);
 
initialize_txbd(3);
initialize_rxbd(6);
 
set_packet(16'h34, 8'h1);
set_packet(16'h34, 8'h11);
send_packet;
set_packet(16'h34, 8'h21);
set_packet(16'h34, 8'h31);
send_packet;
 
GetDataOnMRxD(100, `BROADCAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
repeat (100) @(posedge mrx_clk); // Waiting for TxEthMac to finish transmit
 
 
GetDataOnMRxD(70, `BROADCAST_XFR); // LengthRx bytes is comming on MRxD[3:0] signals
 
 
repeat (10000) @(posedge wb_clk_o); // Waiting for TxEthMac to finish transmit
$display("\n\n End of simulation");
$stop;
 
 
 
end
 
 
task initialize_txbd;
input [6:0] txbd_num;
integer i;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<txbd_num; i=i+1) begin
buf_addr = `TX_BUF_BASE + i * 32'h600;
bd_status_addr = `TX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==txbd_num-1)
eth_host.wb_write(bd_status_addr, 4'hf, 32'h00007800); // last BD: + WRAP
else
eth_host.wb_write(bd_status_addr, 4'hf, 32'h00005800); // IRQ + PAD + CRC
 
eth_host.wb_write(bd_ptr_addr, 4'hf, buf_addr); // Initializing BD - pointer
end
endtask // initialize_txbd
 
 
task initialize_rxbd;
input [6:0] rxbd_num;
integer i;
integer bd_status_addr, buf_addr, bd_ptr_addr;
for(i=0; i<rxbd_num; i=i+1) begin
buf_addr = `RX_BUF_BASE + i * 32'h600;
bd_status_addr = `RX_BD_BASE + i * 8;
bd_ptr_addr = bd_status_addr + 4;
// Initializing BD - status
if(i==rxbd_num-1)
eth_host.wb_write(bd_status_addr, 4'hf, 32'h0000e000); // last BD: + WRAP
else
eth_host.wb_write(bd_status_addr, 4'hf, 32'h0000c000); // IRQ + PAD + CRC
 
eth_host.wb_write(bd_ptr_addr, 4'hf, buf_addr); // Initializing BD - pointer
end
endtask // initialize_rxbd
 
 
task set_packet;
input [15:0] len;
input [7:0] start_data;
 
integer i, sd;
integer bd_status_addr, bd_ptr_addr, buffer, bd;
begin
sd = start_data;
bd_status_addr = `TX_BD_BASE + packet_ready_cnt * 8;
bd_ptr_addr = bd_status_addr + 4;
// Reading BD + buffer pointer
eth_host.wb_read(bd_status_addr, 4'hf, bd);
eth_host.wb_read(bd_ptr_addr, 4'hf, buffer);
 
while(bd & `ETH_TX_BD_READY) begin // Buffer is ready. Don't touch !!!
repeat(100) @(posedge wb_clk_o);
i=i+1;
eth_host.wb_read(bd_status_addr, 4'hf, bd);
if(i>1000) begin
$display("(%0t)(%m)Waiting for TxBD ready to clear timeout", $time);
$stop;
end
end
 
// First write might not be word allign.
if(buffer[1:0]==1) begin
eth_host.wb_write(buffer-1, 4'h7, {8'h0, sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2});
sd=sd+3;
i=3;
end
else if(buffer[1:0]==2) begin
eth_host.wb_write(buffer-2, 4'h3, {16'h0, sd[7:0], sd[7:0]+3'h1});
sd=sd+2;
i=2;
end
else if(buffer[1:0]==3) begin
eth_host.wb_write(buffer-3, 4'h1, {24'h0, sd[7:0]});
sd=sd+1;
i=1;
end
else
i=0;
 
 
for(i=i; i<len-4; i=i+4) begin // Last 0-3 bytes are not written
eth_host.wb_write(buffer+i, 4'hf, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, sd[7:0]+3'h3});
sd=sd+4;
end
// Last word
if(len-i==3)
eth_host.wb_write(buffer+i, 4'he, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, 8'h0});
else if(len-i==2)
eth_host.wb_write(buffer+i, 4'hc, {sd[7:0], sd[7:0]+3'h1, 16'h0});
else if(len-i==1)
eth_host.wb_write(buffer+i, 4'h8, {sd[7:0], 24'h0});
else if(len-i==4)
eth_host.wb_write(buffer+i, 4'hf, {sd[7:0], sd[7:0]+3'h1, sd[7:0]+3'h2, sd[7:0]+3'h3});
else
$display("(%0t)(%m) ERROR", $time);
 
// Checking WRAP bit
if(bd & `ETH_TX_BD_WRAP)
packet_ready_cnt = 0;
else
packet_ready_cnt = packet_ready_cnt+1;
 
// Writing len to bd
bd = bd | (len<<16);
eth_host.wb_write(bd_status_addr, 4'hf, bd);
end
endtask // set_packet
 
 
task send_packet;
 
integer bd_status_addr, bd_ptr_addr, buffer, bd;
begin
bd_status_addr = `TX_BD_BASE + send_packet_cnt * 8;
bd_ptr_addr = bd_status_addr + 4;
// Reading BD + buffer pointer
eth_host.wb_read(bd_status_addr, 4'hf, bd);
eth_host.wb_read(bd_ptr_addr, 4'hf, buffer);
 
if(bd & `ETH_TX_BD_WRAP)
send_packet_cnt=0;
else
send_packet_cnt=send_packet_cnt+1;
 
// Setting ETH_TX_BD_READY bit
bd = bd | `ETH_TX_BD_READY;
eth_host.wb_write(bd_status_addr, 4'hf, bd);
end
 
 
endtask // send_packet
 
 
task GetDataOnMRxD;
input [15:0] Len;
input [31:0] TransferType;
integer tt;
 
begin
@ (posedge mrx_clk);
#1MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge mrx_clk);
#1;
end
 
MRxD=4'hd; // SFD
for(tt=1; tt<(Len+1); tt=tt+1)
begin
@ (posedge mrx_clk);
#1;
if(TransferType == `UNICAST_XFR && tt == 1)
MRxD= 4'h0; // Unicast transfer
else if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[3:0]; // Multicast transfer
 
@ (posedge mrx_clk);
#1;
if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[7:4];
end
 
@ (posedge mrx_clk);
#1;
MRxDV=1'b0;
end
endtask // GetDataOnMRxD
 
 
endmodule
/bench/verilog/eth_host.v
0,0 → 1,145
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_host.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
//
 
`include "tb_eth_defines.v"
`include "timescale.v"
 
module eth_host
(
// WISHBONE common
wb_clk_i, wb_rst_i,
// WISHBONE master
wb_adr_o, wb_sel_o, wb_we_o, wb_dat_i, wb_dat_o, wb_cyc_o, wb_stb_o, wb_ack_i, wb_err_i
);
 
parameter Tp=1;
 
input wb_clk_i, wb_rst_i;
 
input [31:0] wb_dat_i;
input wb_ack_i, wb_err_i;
 
output [31:0] wb_adr_o, wb_dat_o;
output [3:0] wb_sel_o;
output wb_cyc_o, wb_stb_o, wb_we_o;
 
reg [31:0] wb_adr_o, wb_dat_o;
reg [3:0] wb_sel_o;
reg wb_cyc_o, wb_stb_o, wb_we_o;
 
integer host_log;
 
// Reset pulse
initial
begin
host_log = $fopen("eth_host.log");
end
 
 
task wb_write;
 
input [31:0] addr;
input [3:0] sel;
input [31:0] data;
 
begin
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = addr;
wb_dat_o = data;
wb_sel_o = sel;
wb_cyc_o = 1;
wb_stb_o = 1;
wb_we_o = 1;
wait(wb_ack_i | wb_err_i);
$fdisplay(host_log, "(%0t)(%m)wb_write (0x%0x) = 0x%0x", $time, wb_adr_o, wb_dat_o);
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = 'hx;
wb_dat_o = 'hx;
wb_sel_o = 'hx;
wb_cyc_o = 0;
wb_stb_o = 0;
wb_we_o = 'hx;
end
endtask
 
 
task wb_read;
 
input [31:0] addr;
input [3:0] sel;
output [31:0] data;
 
begin
@ (posedge wb_clk_i); // Sync. with clock
#1;
wb_adr_o = addr;
wb_sel_o = sel;
wb_cyc_o = 1;
wb_stb_o = 1;
wb_we_o = 0;
wait(wb_ack_i | wb_err_i);
@ (posedge wb_clk_i); // Sync. with clock
data = wb_dat_i;
$fdisplay(host_log, "(%0t)(%m)wb_read (0x%0x) = 0x%0x", $time, wb_adr_o, wb_dat_i);
#1;
wb_adr_o = 'hx;
wb_sel_o = 'hx;
wb_cyc_o = 0;
wb_stb_o = 0;
wb_we_o = 'hx;
end
endtask
 
 
 
endmodule
/bench/verilog/tb_cop.v
0,0 → 1,506
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_cop.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/??????/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
 
 
 
`include "timescale.v"
 
module tb_cop();
 
 
parameter Tp = 1;
 
 
reg wb_clk_o;
reg wb_rst_o;
 
 
// WISHBONE master 1 (input)
reg [31:0] m1_wb_adr_o;
reg [3:0] m1_wb_sel_o;
reg m1_wb_we_o;
wire [31:0] m1_wb_dat_i;
reg [31:0] m1_wb_dat_o;
reg m1_wb_cyc_o;
reg m1_wb_stb_o;
wire m1_wb_ack_i;
wire m1_wb_err_i;
 
// WISHBONE master 2 (input)
reg [31:0] m2_wb_adr_o;
reg [3:0] m2_wb_sel_o;
reg m2_wb_we_o;
wire [31:0] m2_wb_dat_i;
reg [31:0] m2_wb_dat_o;
reg m2_wb_cyc_o;
reg m2_wb_stb_o;
wire m2_wb_ack_i;
wire m2_wb_err_i;
 
// WISHBONE slave 1 (output)
wire [31:0] s1_wb_adr_i;
wire [3:0] s1_wb_sel_i;
wire s1_wb_we_i;
reg [31:0] s1_wb_dat_o;
wire [31:0] s1_wb_dat_i;
wire s1_wb_cyc_i;
wire s1_wb_stb_i;
reg s1_wb_ack_o;
reg s1_wb_err_o;
 
// WISHBONE slave 2 (output)
wire [31:0] s2_wb_adr_i;
wire [3:0] s2_wb_sel_i;
wire s2_wb_we_i;
reg [31:0] s2_wb_dat_o;
wire [31:0] s2_wb_dat_i;
wire s2_wb_cyc_i;
wire s2_wb_stb_i;
reg s2_wb_ack_o;
reg s2_wb_err_o;
 
 
reg Wishbone1Busy;
reg Wishbone2Busy;
 
reg StartTB;
 
eth_cop i_eth_cop
(
// WISHBONE common
.wb_clk_i(wb_clk_o), .wb_rst_i(wb_rst_o),
 
// WISHBONE MASTER 1
.m1_wb_adr_i(m1_wb_adr_o), .m1_wb_sel_i(m1_wb_sel_o), .m1_wb_we_i (m1_wb_we_o), .m1_wb_dat_o(m1_wb_dat_i),
.m1_wb_dat_i(m1_wb_dat_o), .m1_wb_cyc_i(m1_wb_cyc_o), .m1_wb_stb_i(m1_wb_stb_o), .m1_wb_ack_o(m1_wb_ack_i),
.m1_wb_err_o(m1_wb_err_i),
 
// WISHBONE MASTER 2
.m2_wb_adr_i(m2_wb_adr_o), .m2_wb_sel_i(m2_wb_sel_o), .m2_wb_we_i (m2_wb_we_o), .m2_wb_dat_o(m2_wb_dat_i),
.m2_wb_dat_i(m2_wb_dat_o), .m2_wb_cyc_i(m2_wb_cyc_o), .m2_wb_stb_i(m2_wb_stb_o), .m2_wb_ack_o(m2_wb_ack_i),
.m2_wb_err_o(m2_wb_err_i),
 
// WISHBONE slave 1
.s1_wb_adr_o(s1_wb_adr_i), .s1_wb_sel_o(s1_wb_sel_i), .s1_wb_we_o (s1_wb_we_i), .s1_wb_cyc_o(s1_wb_cyc_i),
.s1_wb_stb_o(s1_wb_stb_i), .s1_wb_ack_i(s1_wb_ack_o), .s1_wb_err_i(s1_wb_err_o), .s1_wb_dat_i(s1_wb_dat_o),
.s1_wb_dat_o(s1_wb_dat_i),
// WISHBONE slave 2
.s2_wb_adr_o(s2_wb_adr_i), .s2_wb_sel_o(s2_wb_sel_i), .s2_wb_we_o (s2_wb_we_i), .s2_wb_cyc_o(s2_wb_cyc_i),
.s2_wb_stb_o(s2_wb_stb_i), .s2_wb_ack_i(s2_wb_ack_o), .s2_wb_err_i(s2_wb_err_o), .s2_wb_dat_i(s2_wb_dat_o),
.s2_wb_dat_o(s2_wb_dat_i)
);
 
/*
s1_wb_adr_i m_wb_adr_i
s1_wb_sel_i m_wb_sel_i
s1_wb_we_i m_wb_we_i
s1_wb_dat_o m_wb_dat_o
s1_wb_dat_i m_wb_dat_i
s1_wb_cyc_i m_wb_cyc_i
s1_wb_stb_i m_wb_stb_i
s1_wb_ack_o m_wb_ack_o
s1_wb_err_o m_wb_err_o
*/
 
 
 
initial
begin
s1_wb_ack_o = 0;
s1_wb_err_o = 0;
s1_wb_dat_o = 0;
s2_wb_ack_o = 0;
s2_wb_err_o = 0;
s2_wb_dat_o = 0;
 
// WISHBONE master 1 (input)
m1_wb_adr_o = 0;
m1_wb_sel_o = 0;
m1_wb_we_o = 0;
m1_wb_dat_o = 0;
m1_wb_cyc_o = 0;
m1_wb_stb_o = 0;
 
// WISHBONE master 2 (input)
m2_wb_adr_o = 0;
m2_wb_sel_o = 0;
m2_wb_we_o = 0;
m2_wb_dat_o = 0;
m2_wb_cyc_o = 0;
m2_wb_stb_o = 0;
 
Wishbone1Busy = 1'b0;
Wishbone2Busy = 1'b0;
end
 
 
// Reset pulse
initial
begin
wb_rst_o = 1'b1;
#100 wb_rst_o = 1'b0;
#100 StartTB = 1'b1;
end
 
 
 
// Generating WB_CLK_I clock
always
begin
wb_clk_o = 0;
forever #15 wb_clk_o = ~wb_clk_o; // 2*15 ns -> 33.3 MHz
end
 
 
integer seed_wb1, seed_wb2;
integer jj, kk;
initial
begin
seed_wb1 = 0;
seed_wb2 = 5;
end
 
 
 
 
initial
begin
wait(StartTB); // Start of testbench
fork
begin
for(jj=0; jj<100; jj=jj+1)
begin
if(seed_wb1[3:0]<4)
begin
$display("(%0t) m1 write to eth start (Data = Addr = 0x%0x)", $time, {21'h1a0000, seed_wb1[10:0]}); //0xd0000xxx
Wishbone1Write({21'h1a0000, seed_wb1[10:0]}, {21'h1a0000, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]<=7 && seed_wb1[3:0]>=4)
begin
$display("(%0t) m1 read to eth start (Addr = 0x%0x)", $time, {21'h1a0000, seed_wb1[10:0]});
Wishbone1Read({21'h1a0000, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]<=11 && seed_wb1[3:0]>=8)
begin
$display("(%0t) m1 write to memory start (Data = Addr = 0x%0x)", $time, {21'h000040, seed_wb1[10:0]}); //0x00020xxx
Wishbone1Write({21'h1a0000, seed_wb1[10:0]}, {21'h000040, seed_wb1[10:0]});
end
else
if(seed_wb1[3:0]>=12)
begin
$display("(%0t) m1 read to memory start (Addr = 0x%0x)", $time, {21'h000040, seed_wb1[10:0]});
Wishbone1Read({21'h000040, seed_wb1[10:0]});
end
#1 seed_wb1 = $random(seed_wb1);
$display("seed_wb1[4:0] = 0x%0x", seed_wb1[4:0]);
repeat(seed_wb1[4:0]) @ (posedge wb_clk_o);
end
end
 
begin
for(kk=0; kk<100; kk=kk+1)
begin
if(seed_wb2[3:0]<4)
begin
$display("(%0t) m2 write to eth start (Data = Addr = 0x%0x)", $time, {21'h1a0000, seed_wb2[10:0]}); //0xd0000xxx
Wishbone2Write({21'h1a0000, seed_wb2[10:0]}, {21'h1a0000, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]<=7 && seed_wb2[3:0]>=4)
begin
$display("(%0t) m2 read to eth start (Addr = 0x%0x)", $time, {21'h1a0000, seed_wb2[10:0]});
Wishbone2Read({21'h1a0000, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]<=11 && seed_wb2[3:0]>=8)
begin
$display("(%0t) m2 write to memory start (Data = Addr = 0x%0x)", $time, {21'h000040, seed_wb2[10:0]}); //0x00020xxx
Wishbone2Write({21'h1a0000, seed_wb2[10:0]}, {21'h000040, seed_wb2[10:0]});
end
else
if(seed_wb2[3:0]>=12)
begin
$display("(%0t) m2 read to memory start (Addr = 0x%0x)", $time, {21'h000040, seed_wb2[10:0]});
Wishbone2Read({21'h000040, seed_wb2[10:0]});
end
#1 seed_wb2 = $random(seed_wb2);
$display("seed_wb2[4:0] = 0x%0x", seed_wb2[4:0]);
repeat(seed_wb2[4:0]) @ (posedge wb_clk_o);
end
end
 
 
 
join
 
#10000 $stop;
end
 
 
 
 
 
 
 
task Wishbone1Write;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~Wishbone1Busy);
Wishbone1Busy = 1;
@ (posedge wb_clk_o);
#1;
m1_wb_adr_o = Address;
m1_wb_dat_o = Data;
m1_wb_we_o = 1'b1;
m1_wb_cyc_o = 1'b1;
m1_wb_stb_o = 1'b1;
m1_wb_sel_o = 4'hf;
 
wait(m1_wb_ack_i | m1_wb_err_i); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m1_wb_ack_i)
$display("(%0t) Master1 write cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master1 write cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m1_wb_adr_o = 32'hx;
m1_wb_dat_o = 32'hx;
m1_wb_we_o = 1'bx;
m1_wb_cyc_o = 1'b0;
m1_wb_stb_o = 1'b0;
m1_wb_sel_o = 4'hx;
#5 Wishbone1Busy = 0;
end
endtask
 
 
task Wishbone1Read;
input [31:0] Address;
reg [31:0] Data;
integer ii;
 
begin
wait (~Wishbone1Busy);
Wishbone1Busy = 1;
@ (posedge wb_clk_o);
#1;
m1_wb_adr_o = Address;
m1_wb_we_o = 1'b0;
m1_wb_cyc_o = 1'b1;
m1_wb_stb_o = 1'b1;
m1_wb_sel_o = 4'hf;
 
wait(m1_wb_ack_i | m1_wb_err_i); // waiting for acknowledge response
Data = m1_wb_dat_i;
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m1_wb_ack_i)
$display("(%0t) Master1 read cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master1 read cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m1_wb_adr_o = 32'hx;
m1_wb_dat_o = 32'hx;
m1_wb_we_o = 1'bx;
m1_wb_cyc_o = 1'b0;
m1_wb_stb_o = 1'b0;
m1_wb_sel_o = 4'hx;
#5 Wishbone1Busy = 0;
end
endtask
 
 
 
task Wishbone2Write;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~Wishbone2Busy);
Wishbone2Busy = 1;
@ (posedge wb_clk_o);
#1;
m2_wb_adr_o = Address;
m2_wb_dat_o = Data;
m2_wb_we_o = 1'b1;
m2_wb_cyc_o = 1'b1;
m2_wb_stb_o = 1'b1;
m2_wb_sel_o = 4'hf;
 
wait(m2_wb_ack_i | m2_wb_err_i); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m2_wb_ack_i)
$display("(%0t) Master2 write cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master2 write cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m2_wb_adr_o = 32'hx;
m2_wb_dat_o = 32'hx;
m2_wb_we_o = 1'bx;
m2_wb_cyc_o = 1'b0;
m2_wb_stb_o = 1'b0;
m2_wb_sel_o = 4'hx;
#5 Wishbone2Busy = 0;
end
endtask
 
 
task Wishbone2Read;
input [31:0] Address;
reg [31:0] Data;
integer ii;
 
begin
wait (~Wishbone2Busy);
Wishbone2Busy = 1;
@ (posedge wb_clk_o);
#1;
m2_wb_adr_o = Address;
m2_wb_we_o = 1'b0;
m2_wb_cyc_o = 1'b1;
m2_wb_stb_o = 1'b1;
m2_wb_sel_o = 4'hf;
 
wait(m2_wb_ack_i | m2_wb_err_i); // waiting for acknowledge response
Data = m2_wb_dat_i;
 
// Writing information about the access to the screen
@ (posedge wb_clk_o);
if(m2_wb_ack_i)
$display("(%0t) Master2 read cycle finished ok(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
else
$display("(%0t) Master2 read cycle finished with error(Data: 0x%0x, Addr: 0x%0x)", $time, Data, Address);
 
#1;
m2_wb_adr_o = 32'hx;
m2_wb_dat_o = 32'hx;
m2_wb_we_o = 1'bx;
m2_wb_cyc_o = 1'b0;
m2_wb_stb_o = 1'b0;
m2_wb_sel_o = 4'hx;
#5 Wishbone2Busy = 0;
end
endtask
 
 
 
 
 
 
 
 
integer seed_ack_s1, seed_ack_s2;
integer cnt_s1, cnt_s2;
initial
begin
seed_ack_s1 = 1;
cnt_s1 = 1;
seed_ack_s2 = 2;
cnt_s2 = 32'h88888888;
end
 
// Response from slave 1
always @ (posedge wb_clk_o or posedge wb_rst_o)
begin
#1 seed_ack_s1 = $random(seed_ack_s1);
wait(s1_wb_cyc_i & s1_wb_stb_i);
s1_wb_dat_o = cnt_s1;
repeat(seed_ack_s1[3:0]) @ (posedge wb_clk_o);
#Tp s1_wb_ack_o = 1'b1;
 
if(~s1_wb_we_i)
cnt_s1=cnt_s1+1;
 
@ (posedge wb_clk_o);
#Tp s1_wb_ack_o = 1'b0;
end
 
// Response from slave 2
always @ (posedge wb_clk_o or posedge wb_rst_o)
begin
#1 seed_ack_s2 = $random(seed_ack_s2);
wait(s2_wb_cyc_i & s2_wb_stb_i);
s2_wb_dat_o = cnt_s2;
repeat(seed_ack_s2[3:0]) @ (posedge wb_clk_o);
#Tp s2_wb_ack_o = 1'b1;
 
if(~s1_wb_we_i)
cnt_s2=cnt_s2+1;
 
@ (posedge wb_clk_o);
#Tp s2_wb_ack_o = 1'b0;
end
 
endmodule
 
/bench/verilog/eth_memory.v
0,0 → 1,148
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_memory.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001, 2002 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
//
//
//
//
 
`include "tb_eth_defines.v"
`include "timescale.v"
 
module eth_memory
(
wb_clk_i, wb_rst_i, wb_adr_i, wb_sel_i, wb_we_i, wb_cyc_i,
wb_stb_i, wb_ack_o, wb_err_o, wb_dat_o, wb_dat_i
);
 
parameter Tp=1;
 
input wb_clk_i, wb_rst_i;
input [31:0] wb_adr_i, wb_dat_i;
input [3:0] wb_sel_i;
input wb_we_i, wb_cyc_i, wb_stb_i;
 
output wb_ack_o, wb_err_o;
output [31:0] wb_dat_o;
 
reg wb_ack_o, wb_err_o;
reg [31:0] wb_dat_o;
 
reg [7:0] memory0 [0:65535];
reg [7:0] memory1 [0:65535];
reg [7:0] memory2 [0:65535];
reg [7:0] memory3 [0:65535];
 
integer memory_log;
 
// Reset pulse
initial
begin
memory_log = $fopen("eth_memory.log");
wb_ack_o = 0;
wb_err_o = 0;
end
 
 
always @ (posedge wb_clk_i)
begin
if(wb_cyc_i & wb_stb_i)
begin
repeat(1) @ (posedge wb_clk_i); // Waiting 3 clock cycles before ack is set
begin // (you can add some random function here)
#1;
wb_ack_o = 1'b1;
if(~wb_we_i)
begin
if(wb_adr_i[1:0] == 2'b00) // word access
begin
wb_dat_o[31:24] = memory3[wb_adr_i[17:2]];
wb_dat_o[23:16] = memory2[wb_adr_i[17:2]];
wb_dat_o[15:08] = memory1[wb_adr_i[17:2]];
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
else if(wb_adr_i[1:0] == 2'b10) // half access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = 0;
wb_dat_o[15:08] = memory1[wb_adr_i[17:2]];
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
else if(wb_adr_i[1:0] == 2'b01) // byte access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = memory2[wb_adr_i[17:2]];
wb_dat_o[15:08] = 0;
wb_dat_o[07:00] = 0;
end
else if(wb_adr_i[1:0] == 2'b11) // byte access
begin
wb_dat_o[31:24] = 0;
wb_dat_o[23:16] = 0;
wb_dat_o[15:08] = 0;
wb_dat_o[07:00] = memory0[wb_adr_i[17:2]];
end
 
$fdisplay(memory_log, "(%0t)(%m)wb_read (0x%0x) = 0x%0x", $time, wb_adr_i, wb_dat_o);
end
else
begin
$fdisplay(memory_log, "(%0t)(%m)wb_write (0x%0x) = 0x%0x", $time, wb_adr_i, wb_dat_i);
if(wb_sel_i[0])
memory0[wb_adr_i[17:2]] = wb_dat_i[7:0];
if(wb_sel_i[1])
memory1[wb_adr_i[17:2]] = wb_dat_i[15:8];
if(wb_sel_i[2])
memory2[wb_adr_i[17:2]] = wb_dat_i[23:16];
if(wb_sel_i[3])
memory3[wb_adr_i[17:2]] = wb_dat_i[31:24];
end
end
@ (posedge wb_clk_i);
wb_ack_o <=#Tp 1'b0;
end
end
 
 
 
endmodule
/bench/verilog/tb_eth_top.v
0,0 → 1,1593
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_eth_top.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/projects/ethmac/ ////
//// ////
//// Author(s): ////
//// - Igor Mohor (igorM@opencores.org) ////
//// ////
//// All additional information is avaliable in the Readme.txt ////
//// file. ////
//// ////
//////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2001 Authors ////
//// ////
//// 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 ////
//// ////
//////////////////////////////////////////////////////////////////////
//
// CVS Revision History
//
// $Log: not supported by cvs2svn $
// Revision 1.12 2002/02/26 17:01:09 mohor
// Small fixes for external/internal DMA missmatches.
//
// Revision 1.11 2002/02/16 13:06:59 mohor
// EXTERNAL_DMA used instead of WISHBONE_DMA.
//
// Revision 1.10 2002/02/16 07:22:15 mohor
// Testbench fixed, code simplified, unused signals removed.
//
// Revision 1.9 2002/02/14 20:14:38 billditt
// Added separate tests for Multicast, Unicast, Broadcast
//
// Revision 1.8 2002/02/12 20:24:00 mohor
// HASH0 and HASH1 register read/write added.
//
// Revision 1.7 2002/02/06 14:11:35 mohor
// non-DMA host interface added. Select the right configutation in eth_defines.
//
// Revision 1.6 2001/12/08 12:36:00 mohor
// TX_BD_NUM register added instead of the RB_BD_ADDR.
//
// Revision 1.5 2001/10/19 11:24:04 mohor
// Number of addresses (wb_adr_i) minimized.
//
// Revision 1.4 2001/10/19 08:46:53 mohor
// eth_timescale.v changed to timescale.v This is done because of the
// simulation of the few cores in a one joined project.
//
// Revision 1.3 2001/09/24 14:55:49 mohor
// Defines changed (All precede with ETH_). Small changes because some
// tools generate warnings when two operands are together. Synchronization
// between two clocks domains in eth_wishbonedma.v is changed (due to ASIC
// demands).
//
// Revision 1.2 2001/08/15 14:04:30 mohor
// Signal names changed on the top level for easier pad insertion (ASIC).
//
// Revision 1.1 2001/08/06 14:41:09 mohor
// A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
// Include files fixed to contain no path.
// File names and module names changed ta have a eth_ prologue in the name.
// File eth_timescale.v is used to define timescale
// All pin names on the top module are changed to contain _I, _O or _OE at the end.
// Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
// and Mdo_OE. The bidirectional signal must be created on the top level. This
// is done due to the ASIC tools.
//
// Revision 1.1 2001/07/30 21:46:09 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
 
`include "tb_eth_defines.v"
`include "eth_defines.v"
`include "timescale.v"
 
module tb_eth_top();
 
 
parameter Tp = 1;
 
 
reg WB_CLK_I;
reg WB_RST_I;
reg [31:0] WB_DAT_I;
 
reg [31:0] WB_ADR_I;
reg [3:0] WB_SEL_I;
reg WB_WE_I;
reg WB_CYC_I;
reg WB_STB_I;
 
wire [31:0] WB_DAT_O;
wire WB_ACK_O;
wire WB_ERR_O;
reg [1:0] WB_ACK_I;
 
`ifdef EXTERNAL_DMA
wire [1:0] WB_REQ_O;
wire [1:0] WB_ND_O;
wire WB_RD_O;
`else
// WISHBONE master
wire [31:0] m_wb_adr_o;
wire [3:0] m_wb_sel_o;
wire m_wb_we_o;
reg [31:0] m_wb_dat_i;
wire [31:0] m_wb_dat_o;
wire m_wb_cyc_o;
wire m_wb_stb_o;
reg m_wb_ack_i;
reg m_wb_err_i;
`endif
 
reg MTxClk;
wire [3:0] MTxD;
wire MTxEn;
wire MTxErr;
 
reg MRxClk;
reg [3:0] MRxD;
reg MRxDV;
reg MRxErr;
reg MColl;
reg MCrs;
 
reg Mdi_I;
wire Mdo_O;
wire Mdo_OE;
wire Mdc_O;
 
 
reg [7:0] memory0 [0:65535];
reg [7:0] memory1 [0:65535];
reg [7:0] memory2 [0:65535];
reg [7:0] memory3 [0:65535];
 
reg WishboneBusy;
reg StartTB;
reg [9:0] TxBDIndex;
reg [9:0] RxBDIndex;
 
reg LogEnable;
 
`ifdef EXTERNAL_DMA
`else
integer mcd1;
integer mcd2;
`endif
 
// Connecting Ethernet top module
 
eth_top ethtop
(
// WISHBONE common
.wb_clk_i(WB_CLK_I), .wb_rst_i(WB_RST_I), .wb_dat_i(WB_DAT_I), .wb_dat_o(WB_DAT_O),
 
// WISHBONE slave
.wb_adr_i(WB_ADR_I[11:2]), .wb_sel_i(WB_SEL_I), .wb_we_i(WB_WE_I), .wb_cyc_i(WB_CYC_I),
.wb_stb_i(WB_STB_I), .wb_ack_o(WB_ACK_O), .wb_err_o(WB_ERR_O),
`ifdef EXTERNAL_DMA
.wb_ack_i(WB_ACK_I), .wb_req_o(WB_REQ_O), .wb_nd_o(WB_ND_O), .wb_rd_o(WB_RD_O),
`else
// WISHBONE master
.m_wb_adr_o(m_wb_adr_o), .m_wb_sel_o(m_wb_sel_o), .m_wb_we_o(m_wb_we_o), .m_wb_dat_i(m_wb_dat_i),
.m_wb_dat_o(m_wb_dat_o), .m_wb_cyc_o(m_wb_cyc_o), .m_wb_stb_o(m_wb_stb_o), .m_wb_ack_i(m_wb_ack_i),
.m_wb_err_i(m_wb_err_i),
`endif
 
//TX
.mtx_clk_pad_i(MTxClk), .mtxd_pad_o(MTxD), .mtxen_pad_o(MTxEn), .mtxerr_pad_o(MTxErr),
 
//RX
.mrx_clk_pad_i(MRxClk), .mrxd_pad_i(MRxD), .mrxdv_pad_i(MRxDV), .mrxerr_pad_i(MRxErr),
.mcoll_pad_i(MColl), .mcrs_pad_i(MCrs),
// MIIM
.mdc_pad_o(Mdc_O), .md_pad_i(Mdi_I), .md_pad_o(Mdo_O), .md_padoe_o(Mdo_OE),
.int_o()
);
 
 
 
 
 
 
 
initial
begin
WB_CLK_I = 1'b0;
WB_DAT_I = 32'h0;
WB_ADR_I = 32'h0;
WB_SEL_I = 4'h0;
WB_WE_I = 1'b0;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
 
`ifdef EXTERNAL_DMA
WB_ACK_I = 2'h0;
`else
m_wb_ack_i = 0;
m_wb_err_i = 0;
`endif
MTxClk = 1'b0;
MRxClk = 1'b0;
MRxD = 4'h0;
MRxDV = 1'b0;
MRxErr = 1'b0;
MColl = 1'b0;
MCrs = 1'b0;
Mdi_I = 1'b0;
 
WishboneBusy = 1'b0;
TxBDIndex = 10'h0;
RxBDIndex = 10'h0;
LogEnable = 1'b1;
end
 
 
// Reset pulse
initial
begin
`ifdef EXTERNAL_DMA
`else
mcd1 = $fopen("ethernet_tx.log");
mcd2 = $fopen("ethernet_rx.log");
`endif
WB_RST_I = 1'b1;
#100 WB_RST_I = 1'b0;
#100 StartTB = 1'b1;
end
 
 
 
// Generating WB_CLK_I clock
always
begin
// forever #2.5 WB_CLK_I = ~WB_CLK_I; // 2*2.5 ns -> 200.0 MHz
// forever #5 WB_CLK_I = ~WB_CLK_I; // 2*5 ns -> 100.0 MHz
// forever #10 WB_CLK_I = ~WB_CLK_I; // 2*10 ns -> 50.0 MHz
// forever #15 WB_CLK_I = ~WB_CLK_I; // 2*10 ns -> 33.3 MHz
forever #18 WB_CLK_I = ~WB_CLK_I; // 2*18 ns -> 27.7 MHz
// forever #25 WB_CLK_I = ~WB_CLK_I; // 2*25 ns -> 20.0 MHz
// forever #31.25 WB_CLK_I = ~WB_CLK_I; // 2*31.25 ns -> 16.0 MHz
// forever #50 WB_CLK_I = ~WB_CLK_I; // 2*50 ns -> 10.0 MHz
// forever #55 WB_CLK_I = ~WB_CLK_I; // 2*55 ns -> 9.1 MHz
end
 
// Generating MTxClk clock
always
begin
// #3 forever #20 MTxClk = ~MTxClk; // 2*20 ns -> 25 MHz
#3 forever #200 MTxClk = ~MTxClk; // 2*200 ns -> 2.5 MHz
end
 
// Generating MRxClk clock
always
begin
// #16 forever #20 MRxClk = ~MRxClk; // 2*20 ns -> 25 MHz
// #16 forever #200 MRxClk = ~MRxClk; // 2*200 ns -> 2.5 MHz
#16 forever #62.5 MRxClk = ~MRxClk; // 2*62.5 ns -> 8 MHz // just for testing purposes
end
 
`ifdef EXTERNAL_DMA
initial
begin
wait(StartTB); // Start of testbench
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR<<2}); // r_RxBDAddress = 0x80
WishboneWrite(32'h0002A443, {26'h0, `ETH_MODER_ADR<<2}); // RxEn, Txen, FullD, CrcEn, Pad, DmaEn, r_IFG
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR<<2}); //r_TxFlow = 1
 
SendPacket(16'h0015, 1'b0);
SendPacket(16'h0043, 1'b1); // Control frame
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0045, 1'b0);
SendPacket(16'h0025, 1'b0);
 
ReceivePacket(16'h0012, 1'b1); // Initializes RxBD and then Sends a control packet on the MRxD[3:0] signals.
ReceivePacket(16'h0011, 1'b0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0016, 1'b0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0018, 1'b0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
 
WishboneRead({26'h0, `ETH_MODER_ADR}); // Read from MODER register
 
WishboneRead({24'h04, (8'h0<<2)}); // Read from TxBD register
WishboneRead({24'h04, (8'h1<<2)}); // Read from TxBD register
WishboneRead({24'h04, (8'h2<<2)}); // Read from TxBD register
WishboneRead({24'h04, (8'h3<<2)}); // Read from TxBD register
WishboneRead({24'h04, (8'h4<<2)}); // Read from TxBD register
WishboneRead({22'h01, (10'h80<<2)}); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}); // Read from RxBD register
 
#10000 $stop;
end
 
 
 
 
 
 
 
task WishboneWrite;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_DAT_I = Data;
WB_WE_I = 1'b1;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
 
wait(WB_ACK_O); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge WB_CLK_I);
if(~Address[11] & ~Address[10])
$write("\nWrite to register (Data: 0x%x, Reg. Addr: 0x%0x)", Data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
begin
$write("\nWrite to TxBD (Data: 0x%x, TxBD Addr: 0x%0x)\n", Data, Address);
if(Data[9])
$write("Send Control packet (PAUSE = 0x%0h)\n", Data[31:16]);
end
else
$write("\nWrite to RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", Data, Address);
else
$write("\nWB write ?????????????? Data: 0x%x Addr: 0x%0x", Data, Address);
#1;
WB_ADR_I = 32'hx;
WB_DAT_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
task WishboneRead;
input [31:0] Address;
reg [31:0] Data;
integer ii;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_WE_I = 1'b0;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
 
for(ii=0; (ii<20 & ~WB_ACK_O); ii=ii+1) // Response on the WISHBONE is limited to 20 WB_CLK_I cycles
begin
@ (posedge WB_CLK_I);
Data = WB_DAT_O;
end
 
if(ii==20)
begin
$display("\nERROR: Task WishboneRead(Address=0x%0h): Too late or no appeariance of the WB_ACK_O signal, (Time=%0t)",
Address, $time);
#50 $stop;
end
 
@ (posedge WB_CLK_I);
if(~Address[11] & ~Address[10])
$write("\nRead from register (Data: 0x%x, Reg. Addr: 0x%0x)", Data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
begin
$write("\nRead from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", Data, Address);
end
else
$write("\nRead from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", Data, Address);
else
$write("\nWB read ????????? Data: 0x%x Addr: 0x%0x", Data, Address);
#1;
WB_ADR_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
 
 
task SendPacket;
input [15:0] Length;
input ControlFrame;
reg Wrap;
reg [31:0] TempAddr;
reg [31:0] TempData;
begin
if(TxBDIndex == 3) // Only 4 buffer descriptors are used
Wrap = 1'b1;
else
Wrap = 1'b0;
 
TempAddr = {22'h01, (TxBDIndex<<2)};
TempData = {Length[15:0], 1'b1, 1'b0, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready and Wrap = 1
 
#1;
if(TxBDIndex == 3) // Only 4 buffer descriptors are used
TxBDIndex = 0;
else
TxBDIndex = TxBDIndex + 1;
 
fork
begin
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
end
begin
if(~ControlFrame)
WaitingForTxDMARequest(4'h1, Length); // Delay, DMALength
end
join
end
endtask
 
 
 
task ReceivePacket; // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
input [15:0] LengthRx;
input RxControlFrame;
reg WrapRx;
reg [31:0] TempRxAddr;
reg [31:0] TempRxData;
reg abc;
begin
if(RxBDIndex == 3) // Only 4 buffer descriptors are used
WrapRx = 1'b1;
else
WrapRx = 1'b0;
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex)<<2)};
 
TempRxData = {LengthRx[15:0], 1'b1, 1'b0, WrapRx, 5'h0, RxBDIndex[7:0]}; // Ready and WrapRx = 1 or 0
 
#1;
if(RxBDIndex == 3) // Only 4 buffer descriptors are used
RxBDIndex = 0;
else
RxBDIndex = RxBDIndex + 1;
 
abc=1;
WishboneWrite(TempRxData, TempRxAddr); // Writing status to RxBD
abc=0;
fork
begin
#200;
if(RxControlFrame)
GetControlDataOnMRxD(LengthRx); // LengthRx = PAUSE timer value.
else
GetDataOnMRxD(LengthRx); // LengthRx bytes is comming on MRxD[3:0] signals
end
 
begin
if(RxControlFrame)
WaitingForRxDMARequest(4'h1, 16'h40); // Delay, DMALength = 64 bytes.
else
WaitingForRxDMARequest(4'h1, LengthRx); // Delay, DMALength
end
join
end
endtask
 
 
 
task WaitingForTxDMARequest;
input [3:0] Delay;
input [15:0] DMALength;
integer pp;
reg [7:0]a, b, c, d;
 
for(pp=0; pp*4<DMALength; pp=pp+1)
begin
a = 4*pp[7:0]+3;
b = 4*pp[7:0]+2;
c = 4*pp[7:0]+1;
d = 4*pp[7:0] ;
@ (posedge WB_REQ_O[0]);
repeat(Delay) @(posedge WB_CLK_I);
wait (~WishboneBusy);
WishboneBusy = 1;
#1;
WB_DAT_I = {a, b, c, d};
WB_ADR_I = {22'h02, pp[9:0]};
$display("task WaitingForTxDMARequest: pp=%0d, WB_ADR_I=0x%0h, WB_DAT_I=0x%0h", pp, WB_ADR_I, WB_DAT_I);
 
WB_WE_I = 1'b1;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
WB_ACK_I[0] = 1'b1;
 
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = 32'hx;
WB_DAT_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
WB_ACK_I[0] = 1'b0;
#5 WishboneBusy = 0;
end
endtask
 
 
task WaitingForRxDMARequest;
input [3:0] Delay;
input [15:0] DMALengthRx;
integer rr;
 
for(rr=0; rr*4<DMALengthRx; rr=rr+1)
begin
@ (posedge WB_REQ_O[1]);
repeat(Delay) @(posedge WB_CLK_I);
wait (~WishboneBusy);
WishboneBusy = 1;
#1;
WB_ADR_I = {22'h02, rr[9:0]};
$display("task WaitingForRxDMARequest: rr=%0d, WB_ADR_I=0x%0h, WB_DAT_O=0x%0h", rr, WB_ADR_I, WB_DAT_O);
 
WB_WE_I = 1'b1;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
WB_ACK_I[1] = 1'b1;
 
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
WB_ACK_I[1] = 1'b0;
#5 WishboneBusy = 0;
end
endtask
 
 
 
task GetDataOnMRxD;
input [15:0] Len;
integer tt;
 
begin
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=0; tt<Len; tt=tt+1)
begin
@ (posedge MRxClk);
MRxD=tt[3:0];
@ (posedge MRxClk);
MRxD=tt[7:4];
end
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
 
task GetControlDataOnMRxD;
input [15:0] Timer;
reg [127:0] Packet;
reg [127:0] Data;
reg [31:0] Crc;
integer tt;
 
begin
Packet = 128'h10082C000010_deadbeef0013_8880_0010; // 0180c2000001 + 8808 + 0001
Crc = 32'h6014fe08; // not a correct value
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=0; tt<32; tt=tt+1)
begin
Data = Packet << (tt*4);
@ (posedge MRxClk);
MRxD=Data[127:124];
end
for(tt=0; tt<2; tt=tt+1) // timer
begin
Data[15:0] = Timer << (tt*8);
@ (posedge MRxClk);
MRxD=Data[11:8];
@ (posedge MRxClk);
MRxD=Data[15:12];
end
for(tt=0; tt<42; tt=tt+1) // padding
begin
Data[7:0] = 8'h0;
@ (posedge MRxClk);
MRxD=Data[3:0];
@ (posedge MRxClk);
MRxD=Data[3:0];
end
for(tt=0; tt<4; tt=tt+1) // crc
begin
Data[31:0] = Crc << (tt*8);
@ (posedge MRxClk);
MRxD=Data[27:24];
@ (posedge MRxClk);
MRxD=Data[31:28];
end
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
`else // No EXTERNAL_DMA
 
initial
begin
wait(StartTB); // Start of testbench
// Reset eth MAC core
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
 
InitializeMemory;
 
// Select which test you want to run:
TestTxAndRx;
// TestUnicast;
// TestBroadcast;
// TestMulticast;
end
task TestTxAndRx;
 
integer ii, jj;
integer data_in, bd, pointer;
 
begin
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR<<2}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR<<2}); // r_RxBDAddress = 0x80
 
// WishboneWrite(32'h0000a06b, {26'h0, `ETH_MODER_ADR<<2}); // RxEn, Txen, CrcEn, Pad en, half duplex,
WishboneWrite(32'h0000a46b, {26'h0, `ETH_MODER_ADR<<2}); // RxEn, Txen, CrcEn, Pad en, full duplex,
// WishboneWrite(32'h0001a06b, {26'h0, `ETH_MODER_ADR<<2}); // r_RecSmall, RxEn, Txen, CrcEn, Pad en, half duplex,
// r_IPG, promisc On, reject broadcast
 
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR<<2}); //r_TxFlow = 1
 
WishboneWrite(32'h00000002, {26'h0, `ETH_MAC_ADDR1_ADR<<2}); // MAC = 000203040506
WishboneWrite(32'h03040506, {26'h0, `ETH_MAC_ADDR0_ADR<<2});
 
/*
// Just few reads
WishboneRead({26'h0, `ETH_MODER_ADR<<2}, data_in); // Read from ETH_MODER register
WishboneRead({26'h0, `ETH_TX_BD_NUM_ADR<<2}, data_in); // Read from ETH_TX_BD_NUM_ADR register
WishboneRead({26'h0, `ETH_MAC_ADDR1_ADR<<2}, data_in); // Read from ETH_MAC_ADDR1_ADR register
WishboneRead({26'h0, `ETH_MAC_ADDR0_ADR<<2}, data_in); // Read from ETH_MAC_ADDR0_ADR register
*/
 
 
 
 
for(jj=0; jj<8; jj=jj+4)
begin
WishboneWriteData(`TX_BUF_BASE + jj, 32'hffffffff, 4'hf); // Initializing data to ff
end
 
for(jj=0; jj<8; jj=jj+4)
begin
WishboneWriteData(`RX_BUF_BASE + jj, 32'hffffffff, 4'hf); // Initializing data to ff
end
 
// SendPacketX(16'h0064, 1'b0, 2'h3);
// SendPacketX(16'h0064, 1'b0, 2'h2);
// SendPacketX(16'h0064, 1'b0, 2'h1);
// SendPacketX(16'h0064, 1'b0, 2'h0);
// SendPacket(16'h0064, 1'b0);
// SendPacket(16'h0011, 1'b0);
// SendPacket(16'h0012, 1'b0);
 
fork
begin
SendPacketX(16'h264, 1'b0, 2'h3);
SendPacketX(16'h64, 1'b0, 2'h3);
end
begin
ReceivePacketX(16'h0030, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0035, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0040, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0035, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacketX(16'h0062, 1'b0, `UNICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
end
join
 
fork
begin
wait(tb_eth_top.ethtop.wishbone.TxStatusWrite); // wait until tx status is written
end
begin
wait(tb_eth_top.ethtop.wishbone.RxStatusWrite); // wait until rx status is written
end
join
 
 
/*
SendPacket(16'h0013, 1'b0);
SendPacket(16'h0014, 1'b0);
 
SendPacket(16'h0030, 1'b0);
SendPacket(16'h0031, 1'b0);
SendPacket(16'h0032, 1'b0);
SendPacket(16'h0033, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0045, 1'b0);
SendPacket(16'h0025, 1'b0);
SendPacket(16'h0017, 1'b0);
*/
 
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h3); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h2); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h1); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacketX(16'h0050, 1'b0, `MULTICAST_XFR, 2'h0); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
// ReceivePacket(16'h0050, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0051, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0052, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0053, 1'b0, `BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0054, 1'b0, `UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0055, 1'b0, `MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
// ReceivePacket(16'h0056, 1'b0, `UNICAST_WRONG_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
 
repeat(1000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
// WishboneRead({24'h04, (8'h0<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h1<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h2<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h3<<2)}, RxBD); // Read from TxBD register
// WishboneRead({24'h04, (8'h4<<2)}, RxBD); // Read from TxBD register
 
for(jj=0; jj<3; jj=jj+1) // How many TxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2)<<2)}, bd); // Read from TxBD
$display("\n(%0t)\t\tRead TxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Ready = 0?
begin
WishboneRead({22'h01, ((10'h0+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read TxBD pointer
$display("\t\t\tRead TxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0}+ii, data_in); // Read data from Tx Pointer
$write("\t0x%x", data_in);
end
end
end
 
 
for(jj=0; jj<3; jj=jj+1) // How many RxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2)<<2)}, bd); // Read from RxBD
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Empty = 0?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read RxBD pointer
$display("\t\t\tRead RxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]+4; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0} + ii, data_in); // Read data from Rx Pointer
$write("\t0x%x", data_in);
end
end
end
 
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
 
 
 
#100000 $stop;
end
endtask //TestTxAndRx
 
 
reg [7:0] LateCollisionCounter;
reg EnableCollisionCounter;
// Making a late collision
 
initial
EnableCollisionCounter =0; // Collision = OFF
 
always @ (posedge MTxClk)
begin
if(tb_eth_top.ethtop.wishbone.TxStartFrm)
begin
LateCollisionCounter = 0;
end
else
if(EnableCollisionCounter)
LateCollisionCounter = LateCollisionCounter + 1;
end
 
// Making a late collision
always @ (posedge MTxClk)
begin
if(LateCollisionCounter==0)
MColl = 0;
else
if(LateCollisionCounter==150)
MColl = 1;
else
if(LateCollisionCounter==155)
begin
MColl = 0;
MCrs = 0;
EnableCollisionCounter=0;
LateCollisionCounter=1;
end
end
 
 
// Switching Carrier Sense ON and OFF
always @ (posedge MTxClk)
begin
wait(tb_eth_top.ethtop.wishbone.TxStartFrm);
MCrs=1;
wait(tb_eth_top.ethtop.wishbone.TxEndFrm || !MCrs);
MCrs=0;
end
 
 
task TestUnicast;
 
integer ii, jj;
integer data_in, bd, pointer;
 
begin
$display("\nBegin TestUnicast \n");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
WishboneWrite(32'h0000204b, {26'h0, `ETH_MODER_ADR, 2'h0}); // RxEn, Txen, CrcEn, no Pad, r_IFG, promisc off, broadcast off
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
 
$display("\n This Uniicast packet will be rejected, wrong address in MAC Address Regs\n");
ReceivePacket(16'h0014, 1'b0,`UNICAST_XFR);
WishboneWrite(32'h03040506, {26'h0,`ETH_MAC_ADDR0_ADR ,2'h0}); // Mac Address
WishboneWrite(32'h00000002, {26'h0,`ETH_MAC_ADDR1_ADR ,2'h0}); // Mac Address
$display("\n Set Proper Unicast Address in MAC_ADDRESS regs, resend packet\n");
ReceivePacket(16'h0015, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0016, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0018, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0019, 1'b0,`UNICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h88<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h89<<2)}, data_in); // Read from RxBD register
 
 
for(jj=0; jj<5; jj=jj+1) // How many RxBD do we want to read?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2)<<2)}, bd); // Read from RxBD
$display("\n(%0t)\t\tRead RxBD %0x = 0x%x", $time, jj, bd);
if(~bd[15]) // Empty = 0?
begin
WishboneRead({22'h01, ((10'h80+jj[4:0]*2'h2+1'h1)<<2)}, pointer); // Read RxBD pointer
$display("\t\t\tRead RxBDPointer 0x=%x", pointer);
$write("\t\t\tData:");
for(ii=0; ii<bd[31:16]+4; ii=ii+4)
begin
WishboneReadData({pointer[31:2], 2'h0} + ii, data_in); // Read data from Rx Pointer
$write("\t0x%x", data_in);
end
end
end
 
 
#100000 $stop;
$display("\nEnd TestUnicast \n");
end
endtask //TestUnicast
 
task TestMulticast;
 
integer data_in;
begin
$display("\nBegin TestMulticast \n");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
WishboneWrite(32'h00002043, {26'h0, `ETH_MODER_ADR, 2'h0}); // RxEn, Txen, CrcEn, No Pad, r_IFG, promiscuos off, broadcast enable
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
$display("\n This Multicast packet will be rejected by Hash Filter\n");
ReceivePacket(16'h0014, 1'b0,`MULTICAST_XFR);
WishboneWrite(32'h00400000, {26'h0, `ETH_HASH1_ADR,2'h0}); // set bit 16, multicast hash 36
WishboneRead({26'h0, `ETH_HASH1_ADR, 2'h0}, data_in); // read back
$display("\n Set Hash Filter to accept this Multicast packet, resend packet\n");
ReceivePacket(16'h0015, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0016, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0018, 1'b0,`MULTICAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
$display("\nEnd TestMulticast \n");
#100000 $stop;
end
endtask //TestMulticast
 
 
task TestBroadcast;
 
integer data_in;
 
begin
$display("\n\n\nBegin TestBroadcast");
WishboneWrite(32'h00000800, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 1
WishboneWrite(32'h00000000, {26'h0, `ETH_MODER_ADR, 2'h0}); // r_Rst = 0
WishboneWrite(32'h00000080, {26'h0, `ETH_TX_BD_NUM_ADR, 2'h0}); // r_RxBDAddress = 0x80
 
WishboneWrite(32'h0000A04b, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Reject Broadcast, TxEn, RxEn
WishboneWrite(32'h00000004, {26'h0, `ETH_CTRLMODER_ADR, 2'h0}); // r_TxFlow = 1
 
$display("\nThis Broadcast packet will be rejected, r_BRO = 1");
ReceivePacket(16'h0014, 1'b0,`BROADCAST_XFR);
$display("\nSet r_Bro = 0, resend packet");
WishboneWrite(32'h0000A043, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Accept Broadcast, TxEn, RxEn
ReceivePacket(16'h0015, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
$display("\n This Broadcast packet will be rejected, r_BRO = 1");
WishboneWrite(32'h0000A04b, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Reject Broadcast, TxEn, RxEn
ReceivePacket(16'h0016, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
ReceivePacket(16'h0017, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
$display("\n Set r_Bro = 0, resend packet");
WishboneWrite(32'h0000A043, {26'h0, `ETH_MODER_ADR, 2'h0}); // PadEn, CrcEn, IFG=accept, Accept Broadcast, TxEn, RxEn
ReceivePacket(16'h0018, 1'b0,`BROADCAST_XFR); // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
 
repeat(5000) @ (posedge MRxClk); // Waiting some time for all accesses to finish before reading out the statuses.
 
WishboneRead({26'h0, `ETH_MODER_ADR}, data_in); // Read from MODER register
 
WishboneRead({22'h01, (10'h80<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h81<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h82<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h83<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h84<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h85<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h86<<2)}, data_in); // Read from RxBD register
WishboneRead({22'h01, (10'h87<<2)}, data_in); // Read from RxBD register
 
#100000 $stop;
$display("\nEnd TestBroadcast \n");
end
endtask //TestBroadcast
 
 
always @ (posedge WB_CLK_I)
begin
if(m_wb_cyc_o & m_wb_stb_o) // Add valid address range
begin
repeat(3) @ (posedge WB_CLK_I);
begin
m_wb_ack_i <=#Tp 1'b1;
if(~m_wb_we_o)
begin
#Tp;
if(m_wb_adr_o[1:0] == 2'b00) // word access
begin
m_wb_dat_i[31:24] = memory3[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[23:16] = memory2[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[15:08] = memory1[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
else if(m_wb_adr_o[1:0] == 2'b10) // half access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = 0;
m_wb_dat_i[15:08] = memory1[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
else if(m_wb_adr_o[1:0] == 2'b01) // byte access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = memory2[{m_wb_adr_o[31:2], 2'h0}];
m_wb_dat_i[15:08] = 0;
m_wb_dat_i[07:00] = 0;
end
else if(m_wb_adr_o[1:0] == 2'b11) // byte access
begin
m_wb_dat_i[31:24] = 0;
m_wb_dat_i[23:16] = 0;
m_wb_dat_i[15:08] = 0;
m_wb_dat_i[07:00] = memory0[{m_wb_adr_o[31:2], 2'h0}];
end
 
$fdisplay(mcd1, "(%0t) master read (0x%0x) = 0x%0x", $time, m_wb_adr_o, m_wb_dat_i);
end
else
begin
$fdisplay(mcd2, "(%0t) master write (0x%0x) = 0x%0x", $time, m_wb_adr_o, m_wb_dat_o);
if(m_wb_sel_o[0])
memory0[m_wb_adr_o] = m_wb_dat_o[7:0];
if(m_wb_sel_o[1])
memory1[m_wb_adr_o] = m_wb_dat_o[15:8];
if(m_wb_sel_o[2])
memory2[m_wb_adr_o] = m_wb_dat_o[23:16];
if(m_wb_sel_o[3])
memory3[m_wb_adr_o] = m_wb_dat_o[31:24];
end
end
@ (posedge WB_CLK_I);
m_wb_ack_i <=#Tp 1'b0;
end
end
 
 
 
// Detecting ram_oe and ram_we being active at the same time
always @ (posedge WB_CLK_I)
begin
if(tb_eth_top.ethtop.wishbone.ram_we & tb_eth_top.ethtop.wishbone.ram_oe)
begin
$display("\n\n(%0t)ERROR: ram_we and ram_oe both activated at the same time", $time);
#1000;
$stop;
end
end
 
 
 
 
always @ (posedge WB_CLK_I)
if(tb_eth_top.ethtop.wishbone.RxStatusWrite)
$fdisplay(mcd2, ""); // newline added
 
task WishboneWrite;
input [31:0] Data;
input [31:0] Address;
integer ii;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_DAT_I = Data;
WB_WE_I = 1'b1;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
 
 
wait(WB_ACK_O); // waiting for acknowledge response
 
// Writing information about the access to the screen
@ (posedge WB_CLK_I);
if(LogEnable)
begin
if(~Address[11] & ~Address[10])
$write("\n(%0t) Write to register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, Data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
begin
$write("\n(%0t) Write to TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, Data, Address);
if(Address[9:2] == tb_eth_top.ethtop.r_TxBDNum-2'h2)
$write("(%0t) Send Control packet\n", $time);
end
else
$write("\n(%0t) Write to RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, Data, Address);
else
$write("\n(%0t) WB write ?????????????? Data: 0x%x Addr: 0x%0x", $time, Data, Address);
end
#1;
WB_ADR_I = 32'hx;
WB_DAT_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
task WishboneRead;
input [31:0] Address;
output[31:0] data;
 
begin
wait (~WishboneBusy);
WishboneBusy = 1;
@ (posedge WB_CLK_I);
#1;
WB_ADR_I = Address;
WB_WE_I = 1'b0;
WB_CYC_I = 1'b1;
WB_STB_I = 1'b1;
WB_SEL_I = 4'hf;
#3;
wait(WB_ACK_O); // waiting for acknowledge response
@ (posedge WB_CLK_I);
data = WB_DAT_O;
if(~Address[11] & ~Address[10])
// $write("\n(%0t) Read from register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, WB_DAT_O, Address);
$write("\n(%0t) Read from register (Data: 0x%x, Reg. Addr: 0x%0x)", $time, data, Address);
else
if(~Address[11] & Address[10])
if(Address[9:2] < tb_eth_top.ethtop.r_TxBDNum)
// ; //$write("\n(%0t) Read from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, WB_DAT_O, Address);
; //$write("\n(%0t) Read from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", $time, data, Address);
else
// ;//$write("\n(%0t) Read from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, WB_DAT_O, Address);
;//$write("\n(%0t) Read from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", $time, data, Address);
else
// $write("\n(%0t) WB read ????????? Data: 0x%x Addr: 0x%0x", $time, WB_DAT_O, Address);
$write("\n(%0t) WB read ????????? Data: 0x%x Addr: 0x%0x", $time, data, Address);
#1;
WB_ADR_I = 32'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_SEL_I = 4'hx;
#5 WishboneBusy = 0;
end
endtask
 
 
 
task WishboneReadData;
input [31:0] Address;
output[31:0] data;
 
begin
@ (posedge WB_CLK_I);
data = {memory3[Address], memory2[Address], memory1[Address], memory0[Address]};
#5;
end
endtask
 
 
task WishboneWriteData;
input [31:0] Address;
input [31:0] data;
input [3:0] Select;
 
begin
@ (posedge WB_CLK_I);
if(Select[0])
memory0[Address] = data[7:0];
if(Select[1])
memory1[Address] = data[15:8];
if(Select[2])
memory2[Address] = data[23:16];
if(Select[3])
memory3[Address] = data[31:24];
// $display("\n(%0t) Write data to memory (Data: 0x%x, Addr: 0x%0x)", $time, data, Address);
#5;
end
endtask
 
 
 
 
task SendPacket;
input [15:0] Length;
input ControlFrame;
reg Wrap;
reg [31:0] TempAddr;
reg [31:0] TempData;
reg [31:0] kk;
begin
// if(TxBDIndex == 6) // Only 3 buffer descriptors are used
// Wrap = 1'b1;
// else
Wrap = 1'b0; // At the moment no wrap bit is set
 
 
// Writing data to buffer
for(kk=0; kk<Length; kk=kk+4)
begin
TempAddr = `TX_BUF_BASE + TxBDIndex * 32'h600 + kk;
TempData = {kk[7:0], kk[7:0]+2'h1, kk[7:0]+2'h2, kk[7:0]+2'h3};
WishboneWriteData(TempAddr, TempData, 4'hf); // Writing Data to buffer that is pointed by the BD
end
 
// Writing buffer pointer
TempAddr = {22'h01, ((TxBDIndex*2'h2 + 1'b1)<<2)};
TempData = `TX_BUF_BASE + TxBDIndex * 32'h600; // 1536 bytes is reserved for one frame
WishboneWrite(TempData, TempAddr); // Writing Tx pointer
 
TempAddr = {22'h01, ((TxBDIndex*2'h2)<<2)};
TempData = {Length[15:0], 1'b1, 1'b0, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready and Wrap = 1
 
#1;
// if(TxBDIndex == 6) // Only 4 buffer descriptors are used
// TxBDIndex = 0;
// else
TxBDIndex = TxBDIndex + 1;
 
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
end
endtask
 
 
 
task SendPacketX;
input [15:0] Length;
input ControlFrame;
input [1:0] AddrOffset;
reg Wrap;
reg [31:0] TempAddr;
reg [31:0] TempData;
reg [31:0] kk;
reg [3:0] Select;
begin
Wrap = 1'b0;
 
case(AddrOffset)
2'h0 : Select = 4'hf;
2'h1 : Select = 4'h7;
2'h2 : Select = 4'h3;
2'h3 : Select = 4'h1;
endcase
 
// Writing data to buffer
for(kk=0; kk<Length+4; kk=kk+4) // Length+4 is because we might start up to 3 bytes later
begin
if(kk>0)
Select = 4'hf;
TempAddr = `TX_BUF_BASE + TxBDIndex * 32'h600 + kk;
TempData = {kk[7:0]+3'h1, kk[7:0]+3'h2, kk[7:0]+3'h3, kk[7:0]+3'h4};
WishboneWriteData(TempAddr, TempData, Select); // Writing Data to buffer that is pointed by the BD
end
 
// Writing buffer pointer
TempAddr = {22'h01, ((TxBDIndex*2'h2 + 1'b1)<<2)};
TempData = `TX_BUF_BASE + TxBDIndex * 32'h600 + AddrOffset; // 1536 bytes is reserved for one frame
WishboneWrite(TempData, TempAddr); // Writing Tx pointer
 
TempAddr = {22'h01, ((TxBDIndex*2'h2)<<2)};
TempData = {Length[15:0], 1'b1, 1'b1, Wrap, 3'h0, ControlFrame, 1'b0, TxBDIndex[7:0]}; // Ready, interrupt and Wrap = 1
 
#1;
if(Wrap)
TxBDIndex = 0;
else
TxBDIndex = TxBDIndex + 1;
 
WishboneWrite(TempData, TempAddr); // Writing status to TxBD
end
endtask
 
 
 
task ReceivePacket; // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
input [15:0] LengthRx;
input RxControlFrame;
input [31:0] TransferType; //Broadcast,Unicast,Multicast
reg WrapRx;
reg [31:0] TempRxAddr;
// reg [31:0] TempRxData;
integer TempRxData;
reg abc;
begin
// if(RxBDIndex == 6) // Only 3 buffer descriptors are used
// WrapRx = 1'b1;
// else
WrapRx = 1'b0;
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2 + 1'b1)<<2)};
TempRxData = `RX_BUF_BASE + RxBDIndex * 32'h600; // 1536 bytes is reserved for one frame
WishboneWrite(TempRxData, TempRxAddr); // Writing Rx pointer
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2)<<2)};
TempRxData = {16'h0, 1'b1, 1'b0, WrapRx, 5'h0, RxBDIndex[7:0]}; // Ready and WrapRx = 1 or 0
 
#1;
// if(RxBDIndex == 6) // Only 4 buffer descriptors are used
// RxBDIndex = 0;
// else
RxBDIndex = RxBDIndex + 1;
 
abc=1;
WishboneWrite(TempRxData, TempRxAddr); // Writing status to RxBD
abc=0;
 
begin
#200;
if(RxControlFrame)
GetControlDataOnMRxD(LengthRx); // LengthRx = PAUSE timer value.
else
GetDataOnMRxD(LengthRx, TransferType); // LengthRx bytes is comming on MRxD[3:0] signals
end
 
end
endtask
 
 
task ReceivePacketX; // Initializes RxBD and then generates traffic on the MRxD[3:0] signals.
input [15:0] LengthRx;
input RxControlFrame;
input [31:0] TransferType; //Broadcast,Unicast,Multicast
input [1:0] AddrOffset;
reg WrapRx;
reg [31:0] TempRxAddr;
integer TempRxData;
reg abc;
begin
WrapRx = 1'b0;
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2 + 1'b1)<<2)};
TempRxData = `RX_BUF_BASE + RxBDIndex * 32'h600 + AddrOffset; // 1536 bytes is reserved for one frame
WishboneWrite(TempRxData, TempRxAddr); // Writing Rx pointer
 
TempRxAddr = {22'h01, ((tb_eth_top.ethtop.r_TxBDNum + RxBDIndex*2'h2)<<2)};
TempRxData = {16'h0, 1'b1, 1'b1, WrapRx, 5'h0, RxBDIndex[7:0]}; // Ready, interrupt and WrapRx = 1 or 0
 
#1;
RxBDIndex = RxBDIndex + 1;
 
abc=1;
WishboneWrite(TempRxData, TempRxAddr); // Writing status to RxBD
abc=0;
 
begin
#200;
if(RxControlFrame)
GetControlDataOnMRxD(LengthRx); // LengthRx = PAUSE timer value.
else
GetDataOnMRxD(LengthRx, TransferType); // LengthRx bytes is comming on MRxD[3:0] signals
end
 
end
endtask
 
 
task GetDataOnMRxD;
input [15:0] Len;
input [31:0] TransferType;
integer tt;
 
begin
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=1; tt<(Len+1); tt=tt+1)
begin
@ (posedge MRxClk);
if(TransferType == `UNICAST_XFR && tt == 1)
MRxD= 4'h0; // Unicast transfer
else if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[3:0]; // Multicast transfer
 
@ (posedge MRxClk);
if(TransferType == `BROADCAST_XFR && tt < 7)
MRxD = 4'hf;
else
MRxD=tt[7:4];
end
 
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
 
task GetControlDataOnMRxD;
input [15:0] Timer;
reg [127:0] Packet;
reg [127:0] Data;
reg [31:0] Crc;
integer tt;
 
begin
Packet = 128'h10082C000010_deadbeef0013_8880_0010; // 0180c2000001 + 8808 + 0001
Crc = 32'h6014fe08; // not a correct value
@ (posedge MRxClk);
MRxDV=1'b1;
for(tt=0; tt<15; tt=tt+1)
begin
MRxD=4'h5; // preamble
@ (posedge MRxClk);
end
MRxD=4'hd; // SFD
for(tt=0; tt<32; tt=tt+1)
begin
Data = Packet << (tt*4);
@ (posedge MRxClk);
MRxD=Data[127:124];
end
for(tt=0; tt<2; tt=tt+1) // timer
begin
Data[15:0] = Timer << (tt*8);
@ (posedge MRxClk);
MRxD=Data[11:8];
@ (posedge MRxClk);
MRxD=Data[15:12];
end
for(tt=0; tt<42; tt=tt+1) // padding
begin
Data[7:0] = 8'h0;
@ (posedge MRxClk);
MRxD=Data[3:0];
@ (posedge MRxClk);
MRxD=Data[3:0];
end
for(tt=0; tt<4; tt=tt+1) // crc
begin
Data[31:0] = Crc << (tt*8);
@ (posedge MRxClk);
MRxD=Data[27:24];
@ (posedge MRxClk);
MRxD=Data[31:28];
end
@ (posedge MRxClk);
MRxDV=1'b0;
end
endtask
 
task InitializeMemory;
reg [9:0] mem_addr;
begin
LogEnable = 1'b0;
$display("\n\n(%0t) Initializing Memory...", $time);
for(mem_addr=0; mem_addr<=10'h0ff; mem_addr=mem_addr+1'b1)
WishboneWrite(32'h0, {22'h01, mem_addr<<2}); // Writing status to RxBD
LogEnable = 1'b1;
end
endtask
 
 
`endif
 
 
endmodule
/doc/src/eth_speci.doc Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
doc/src/eth_speci.doc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/Ethernet Datasheet (prl.).doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/src/Ethernet Datasheet (prl.).doc =================================================================== --- doc/src/Ethernet Datasheet (prl.).doc (nonexistent) +++ doc/src/Ethernet Datasheet (prl.).doc (revision 338)
doc/src/Ethernet Datasheet (prl.).doc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/src/ethernet_product_brief.doc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/src/ethernet_product_brief.doc =================================================================== --- doc/src/ethernet_product_brief.doc (nonexistent) +++ doc/src/ethernet_product_brief.doc (revision 338)
doc/src/ethernet_product_brief.doc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/eth_speci.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/eth_speci.pdf =================================================================== --- doc/eth_speci.pdf (nonexistent) +++ doc/eth_speci.pdf (revision 338)
doc/eth_speci.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/Ethernet Datasheet (prl.).pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/Ethernet Datasheet (prl.).pdf =================================================================== --- doc/Ethernet Datasheet (prl.).pdf (nonexistent) +++ doc/Ethernet Datasheet (prl.).pdf (revision 338)
doc/Ethernet Datasheet (prl.).pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: doc/ethernet_product_brief_OC_head.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: doc/ethernet_product_brief_OC_head.pdf =================================================================== --- doc/ethernet_product_brief_OC_head.pdf (nonexistent) +++ doc/ethernet_product_brief_OC_head.pdf (revision 338)
doc/ethernet_product_brief_OC_head.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property

powered by: WebSVN 2.1.0

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