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

Subversion Repositories ethmac

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 14 to Rev 15
    Reverse comparison

Rev 14 → Rev 15

/trunk/bench/verilog/tb_eth_top.v
0,0 → 1,625
//////////////////////////////////////////////////////////////////////
//// ////
//// tb_eth_top.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.1 2001/07/30 21:46:09 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
 
`include "eth_defines.v"
`include "eth_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;
reg [1:0] WB_ACK_I;
 
wire [31:0] WB_DAT_O;
wire WB_ACK_O;
wire WB_ERR_O;
wire [1:0] WB_REQ_O;
wire [1:0] WB_ND_O;
wire WB_RD_O;
 
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 GSR;
 
reg WishboneBusy;
reg StartTB;
reg [9:0] TxBDIndex;
reg [9:0] RxBDIndex;
 
 
 
// 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), .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), .WB_REQ_O(WB_REQ_O),
.WB_ACK_I(WB_ACK_I), .WB_ND_O(WB_ND_O), .WB_RD_O(WB_RD_O),
 
//TX
.MTxClk_I(MTxClk), .MTxD_O(MTxD), .MTxEn_O(MTxEn), .MTxErr_O(MTxErr),
 
//RX
.MRxClk_I(MRxClk), .MRxD_I(MRxD), .MRxDV_I(MRxDV), .MRxErr_I(MRxErr), .MColl_I(MColl), .MCrs_I(MCrs),
// MIIM
.Mdc_O(Mdc_O), .Mdi_I(Mdi_I), .Mdo_O(Mdo_O), .Mdo_OE(Mdo_OE)
);
 
 
 
 
 
 
 
initial
begin
WB_CLK_I = 1'b0;
WB_DAT_I = 32'hx;
WB_ADR_I = 32'hx;
WB_SEL_I = 4'hx;
WB_WE_I = 1'bx;
WB_CYC_I = 1'b0;
WB_STB_I = 1'b0;
WB_ACK_I = 2'h0;
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;
end
 
 
// Reset pulse
initial
begin
GSR = 1'b0;
WB_RST_I = 1'b0;
#100 WB_RST_I = 1'b1;
GSR = 1'b1;
#100 WB_RST_I = 1'b0;
GSR = 1'b0;
#100 StartTB = 1'b1;
end
 
 
assign glbl.GSR = GSR;
 
 
 
// Generating WB_CLK_I clock
always
begin
// 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 #100 WB_CLK_I = ~WB_CLK_I;
end
 
// Generating MTxClk clock
always
begin
#3 forever #20 MTxClk = ~MTxClk; // 2*20 ns -> 25 MHz
// #3 forever #200 MTxClk = ~MTxClk;
end
 
// Generating MRxClk clock
always
begin
#16 forever #20 MRxClk = ~MRxClk; // 2*20 ns -> 25 MHz
// #16 forever #250 MRxClk = ~MRxClk;
end
 
 
 
initial
begin
wait(StartTB); // Start of testbench
WishboneWrite(32'h00000800, {`ETHERNET_SPACE, `REG_SPACE, 6'h0, `MODER_ADR<<2}); // r_Rst = 1
WishboneWrite(32'h00000000, {`ETHERNET_SPACE, `REG_SPACE, 6'h0, `MODER_ADR<<2}); // r_Rst = 0
WishboneWrite(32'h00000080, {`ETHERNET_SPACE, `REG_SPACE, 6'h0, `RX_BD_ADR_ADR<<2});// r_RxBDAddress = 0x80
WishboneWrite(32'h0002A443, {`ETHERNET_SPACE, `REG_SPACE, 6'h0, `MODER_ADR<<2}); // RxEn, Txen, FullD, CrcEn, Pad, DmaEn, r_IFG
WishboneWrite(32'h00000004, {`ETHERNET_SPACE, `REG_SPACE, 6'h0, `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({`ETHERNET_SPACE, `REG_SPACE, 6'h0, `MODER_ADR<<2}); // Read from MODER register
 
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h0<<2)}); // Read from TxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h1<<2)}); // Read from TxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h2<<2)}); // Read from TxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h3<<2)}); // Read from TxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h4<<2)}); // Read from TxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h80<<2)}); // Read from RxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h81<<2)}); // Read from RxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h82<<2)}); // Read from RxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (10'h83<<2)}); // Read from RxBD register
WishboneRead({`ETHERNET_SPACE, `BD_SPACE, 2'h0, (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;
 
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);
end
 
if(ii==20)
begin
$display("\nERROR: Task WishboneWrite(Data=0x%0h, Address=0x%0h): Too late or no appeariance of the WB_ACK_O signal, (Time=%0t)",
Data, Address, $time);
#50 $stop;
end
 
@ (posedge WB_CLK_I);
if(Address[31:16] == `ETHERNET_SPACE)
if(Address[15:12] == `REG_SPACE)
$write("\nWrite to register (Data: 0x%x, Reg. Addr: 0x%0x)", Data, Address[9:2]);
else
if(Address[15:12] == `BD_SPACE)
if(Address[9:2] < tb_eth_top.ethtop.r_RxBDAddress)
begin
$write("\nWrite to TxBD (Data: 0x%x, TxBD Addr: 0x%0x)\n", Data, Address[9:2]);
if(Data[13])
$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[9:2]);
else
$write("\nWB write Data: 0x%x Addr: 0x%0x", Data, Address);
else
$write("\nWARNING !!! WB write to non-ethernet space (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[31:16] == `ETHERNET_SPACE)
if(Address[15:12] == `REG_SPACE)
$write("\nRead from register (Data: 0x%x, Reg. Addr: 0x%0x)", Data, Address[9:2]);
else
if(Address[15:12] == `BD_SPACE)
if(Address[9:2] < tb_eth_top.ethtop.r_RxBDAddress)
begin
$write("\nRead from TxBD (Data: 0x%x, TxBD Addr: 0x%0x)", Data, Address[9:2]);
end
else
$write("\nRead from RxBD (Data: 0x%x, RxBD Addr: 0x%0x)", Data, Address[9:2]);
else
$write("\nWB read Data: 0x%x Addr: 0x%0x", Data, Address);
else
$write("\nWARNING !!! WB read to non-ethernet space (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 = {`ETHERNET_SPACE, `BD_SPACE, 2'h0, (TxBDIndex<<2)};
TempData = {Length[15:0], 1'b1, Wrap, ControlFrame, 5'h0, 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 = {`ETHERNET_SPACE, `BD_SPACE, 2'h0, ((tb_eth_top.ethtop.r_RxBDAddress + RxBDIndex)<<2)};
 
TempRxData = {LengthRx[15:0], 1'b1, WrapRx, 6'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 = {`ETHERNET_SPACE, `TX_DATA, pp[11: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 = {`ETHERNET_SPACE, `RX_DATA, rr[11: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
 
 
 
endmodule
/trunk/rtl/verilog/eth_shiftreg.v
0,0 → 1,129
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_shiftreg.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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[1]; // 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
/trunk/rtl/verilog/eth_rxethmac.v
0,0 → 1,303
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxethmac.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_timescale.v"
 
 
module eth_rxethmac (MRxClk, MRxDV, MRxD, Reset, Transmitting, MaxFL, r_IFG, HugEn, DlyCrcEn,
RxData, RxValid, RxStartFrm, RxEndFrm, CrcHash, CrcHashGood, Broadcast,
Multicast, ByteCnt, ByteCntEq0, ByteCntGreat2, ByteCntMaxFrame,
CrcError, StateIdle, StatePreamble, StateSFD, StateData
);
 
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;
 
output [7:0] RxData;
output RxValid;
output RxStartFrm;
output RxEndFrm;
output [8:0] CrcHash;
output CrcHashGood;
output Broadcast;
output Multicast;
output [15:0] ByteCnt;
output ByteCntEq0;
output ByteCntGreat2;
output ByteCntMaxFrame;
output CrcError;
output StateIdle;
output StatePreamble;
output StateSFD;
output [1:0] StateData;
 
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 ByteCntEq6;
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), .ByteCntEq6(ByteCntEq6), .ByteCntGreat2(ByteCntGreat2),
.ByteCntSmall7(ByteCntSmall7), .ByteCntMaxFrame(ByteCntMaxFrame),
.ByteCnt(ByteCnt)
);
 
 
 
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;
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)
Multicast <= #Tp LatchedByte[0];
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
/trunk/rtl/verilog/eth_rxcounters.v
0,0 → 1,180
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxcounters.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_timescale.v"
 
 
module eth_rxcounters (MRxClk, Reset, MRxDV, StateIdle, StateSFD, StateData, StateDrop, StatePreamble,
MRxDEqD, DlyCrcEn, DlyCrcCnt, Transmitting, MaxFL, r_IFG, HugEn, IFGCounterEq24,
ByteCntEq0, ByteCntEq1, ByteCntEq6, 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 ByteCntEq6; // Byte counter = 6
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 ByteCntEq6 = ByteCnt == 16'h6;
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
/trunk/rtl/verilog/eth_defines.v
0,0 → 1,106
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_defines.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
`define FPGA // Core is going to be implemented in FPGA and contains FPGA specific elements
// Should be cleared for the ASIC implementation
 
 
// Address is {`ETHERNET_SPACE, REG_SPACE, 12'hx}
`define ETHERNET_SPACE 16'hf000 // Ethernet space is allocated from 0xF0000000 to 0xF000FFFF
`define REG_SPACE 4'h0 // Register space is allocated to 0xF0000000
`define BD_SPACE 4'h1 // Buffer descriptor space is allocated to 0xF0001000
`define TX_DATA 4'h2 // Tx data is written to address 0xF0002000. Since DMA is used, TX_DATA is not used in equations.
`define RX_DATA 4'h3 // Rx data is read from address 0xF0003000. Since DMA is used, RX_DATA is not used in equations.
 
 
`define PACKET_SEND_ADR 32'h20 // Packet for TX are written to the address 0x20
 
`define MODER_ADR 6'h0
`define INT_SOURCE_ADR 6'h1
`define INT_MASK_ADR 6'h2
`define IPGT_ADR 6'h3
`define IPGR1_ADR 6'h4
`define IPGR2_ADR 6'h5
`define PACKETLEN_ADR 6'h6
`define COLLCONF_ADR 6'h7
`define RX_BD_ADR_ADR 6'h8
`define CTRLMODER_ADR 6'hA
`define MIIMODER_ADR 6'hB
`define MIICOMMAND_ADR 6'hC
`define MIIADDRESS_ADR 6'hD
`define MIITX_DATA_ADR 6'hE
`define MIIRX_DATA_ADR 6'hF
`define MIISTATUS_ADR 6'h10
`define MAC_ADDR0_ADR 6'h11
`define MAC_ADDR1_ADR 6'h12
 
 
 
`define MODER_DEF 32'h0000A000
`define INT_SOURCE_DEF 32'h00000000
`define INT_MASK_DEF 32'h00000000
`define IPGT_DEF 32'h00000012
`define IPGR1_DEF 32'h0000000C
`define IPGR2_DEF 32'h00000012
`define PACKETLEN_DEF 32'h003C0600
`define COLLCONF_DEF 32'h000F0040
`define CTRLMODER_DEF 32'h00000000
`define MIIMODER_DEF 32'h00000064
`define MIICOMMAND_DEF 32'h00000000
`define MIIADDRESS_DEF 32'h00000000
`define MIITX_DATA_DEF 32'h00000000
`define MIIRX_DATA_DEF 32'h00000000
`define MIISTATUS_DEF 32'h00000000
`define MAC_ADDR0_DEF 32'h00000000
`define MAC_ADDR1_DEF 32'h00000000
 
`define RX_BD_ADR_DEF 8'h0
/trunk/rtl/verilog/eth_txethmac.v
0,0 → 1,454
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txethmac.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
);
 
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)
 
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 StartDefer;
wire StartIPG;
wire StartPreamble;
wire [1:0] StartData;
wire StartFCS;
wire StartJam;
wire StartBackoff;
wire StateDefer;
wire StateIPG;
wire StateIdle;
wire StatePreamble;
wire [1:0] StateData;
wire StatePAD;
wire StateFCS;
wire StateJam;
wire StateBackOff;
wire StateSFD;
wire StartTxRetry;
wire StartTxDone;
wire LateCollision;
wire MaxCollisionOccured;
wire UnderRun;
wire TooBig;
wire StartTxAbort;
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 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
/trunk/rtl/verilog/eth_txcounters.v
0,0 → 1,198
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txcounters.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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<<1) -1);
 
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
/trunk/rtl/verilog/eth_random.v
0,0 → 1,124
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_random.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
/trunk/rtl/verilog/eth_receivecontrol.v
0,0 → 1,413
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_receivecontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
/trunk/rtl/verilog/eth_register.v
0,0 → 1,81
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_register.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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 $
//
//
//
//
//
//
 
`include "eth_timescale.v"
 
 
module eth_register(DataIn, DataOut, Write, Clk, Reset, Default);
 
parameter WIDTH = 8; // default parameter of the register width
 
input [WIDTH-1:0] DataIn;
 
input Write;
input Clk;
input Reset;
input [WIDTH-1:0] Default;
 
output [WIDTH-1:0] DataOut;
reg [WIDTH-1:0] DataOut;
 
 
 
always @ (posedge Clk or posedge Reset)
begin
if(Reset)
DataOut<=#1 Default;
else
if(Write) // write
DataOut<=#1 DataIn;
end
 
 
 
endmodule // Register
/trunk/rtl/verilog/eth_clockgen.v
0,0 → 1,114
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_clockgen.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
 
 
/trunk/rtl/verilog/eth_miim.v
0,0 → 1,421
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_miim.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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/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 "eth_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
/trunk/rtl/verilog/eth_wishbonedma.v
0,0 → 1,1816
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_wishbonedma.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
 
`include "eth_defines.v"
`include "eth_timescale.v"
 
 
module eth_wishbonedma
(
 
// 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_REQ_O, WB_ACK_I, WB_ND_O, WB_RD_O,
 
//TX
MTxClk, TxStartFrm, TxEndFrm, TxUsedData, TxData, StatusIzTxEthMACModula,
TxRetry, TxAbort, TxUnderRun, TxDone, TPauseRq, TxPauseTV, PerPacketCrcEn,
PerPacketPad,
 
//RX
MRxClk, RxData, RxValid, RxStartFrm, RxEndFrm,
// Register
r_TxEn, r_RxEn, r_RxBDAddress, r_DmaEn, RX_BD_ADR_Wr,
 
WillSendControlFrame, TxCtrlEndFrm
 
);
 
 
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
 
// WISHBONE slave
input [31:0] 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
 
// DMA
input [1:0] WB_ACK_I; // DMA acknowledge input
output [1:0] WB_REQ_O; // DMA request output
output [1:0] WB_ND_O; // DMA force new descriptor output
output WB_RD_O; // DMA restart descriptor output
 
// Tx
input MTxClk; // Transmit clock (from PHY)
input TxUsedData; // Transmit packet used data
input [15:0] StatusIzTxEthMACModula;
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; //
 
//Register
input r_TxEn; // Transmit enable
input r_RxEn; // Receive enable
input [7:0] r_RxBDAddress; // Receive buffer descriptor address
input r_DmaEn; // DMA enable
input RX_BD_ADR_Wr; // RxBDAddress written
 
reg WB_REQ_O_RX;
reg WB_ND_O_TX; // New descriptor
reg WB_RD_O; // Restart descriptor
 
reg TxStartFrm;
reg TxEndFrm;
reg [7:0] TxData;
 
reg TxUnderRun;
reg TPauseRq;
reg TxPauseRq;
 
reg RxStartFrm_wb;
reg [31:0] RxData_wb;
reg RxDataValid_wb;
reg RxEndFrm_wb;
 
reg [7:0] BDAddress; // BD address for access from MAC side
reg BDRead_q;
 
reg TxBDRead;
reg TxDataRead;
reg TxStatusWrite;
 
reg [1:0] TxValidBytesLatched;
reg TxEndFrm_wbLatched;
 
reg [15:0] TxLength;
reg [15:0] TxStatus;
 
reg [15:0] RxStatus;
 
reg TxStartFrm_wb;
reg TxRetry_wb;
reg GetNewTxData_wb;
reg TxDone_wb;
reg TxAbort_wb;
 
 
reg TxStartFrmRequest;
reg [31:0] TxDataLatched_wb;
 
reg RxStatusWriteOccured;
 
reg TxRestart_wb_q;
reg TxDone_wb_q;
reg TxAbort_wb_q;
reg RxBDReady;
reg TxBDReady;
 
reg RxBDRead;
reg RxStatusWrite;
reg WbWriteError;
 
reg [31:0] TxDataLatched;
reg [1:0] TxByteCnt;
reg LastWord;
reg GetNewTxData;
reg TxRetryLatched;
 
reg Div2;
reg Flop;
 
reg BlockingTxStatusWrite;
reg TxStatusWriteOccured;
reg BlockingTxBDRead;
 
reg GetNewTxData_wb_latched;
 
reg NewTxDataAvaliable_wb;
 
reg TxBDAccessed;
 
reg [7:0] TxBDAddress;
reg [7:0] RxBDAddress;
 
reg GotDataSync1;
reg GotDataSync2;
reg GotDataSync3;
reg GotData;
reg SyncGetNewTxData_wb1;
reg SyncGetNewTxData_wb2;
reg SyncGetNewTxData_wb3;
reg TxDoneSync1;
reg TxDoneSync2;
reg TxDoneSync3;
reg TxRetrySync1;
reg TxRetrySync2;
reg TxRetrySync3;
reg TxAbortSync1;
reg TxAbortSync2;
reg TxAbortSync3;
 
reg TxAbort_q;
reg TxDone_q;
reg TxRetry_q;
reg TxUsedData_q;
 
reg [31:0] RxDataLatched2;
reg [15:0] RxDataLatched1;
reg [1:0] RxValidBytes;
reg [1:0] RxByteCnt;
reg LastByteIn;
reg ShiftWillEnd;
 
reg StartShifting;
reg Shifting_wb_Sync1;
reg Shifting_wb_Sync2;
reg LatchNow_wb;
 
reg ShiftEndedSync1;
reg ShiftEndedSync2;
reg ShiftEndedSync3;
reg ShiftEnded;
 
reg RxStartFrmSync1;
reg RxStartFrmSync2;
reg RxStartFrmSync3;
 
reg DMACycleFinishedTx_q;
reg DataNotAvaliable;
 
reg ClearTxBDReadySync1;
reg ClearTxBDReadySync2;
reg ClearTxBDReady;
 
reg TxCtrlEndFrm_wbSync1;
reg TxCtrlEndFrm_wbSync2;
reg TxCtrlEndFrm_wb;
 
wire [15:0] TxPauseTV;
wire ResetDataNotAvaliable;
wire SetDataNotAvaliable;
wire DWord; // Only 32-bit accesses are valid
wire BDWe; // BD Write Enable for access from WISHBONE side
wire BDRead; // BD Read access from WISHBONE side
wire [31:0] BDDataIn; // BD data in
wire [31:0] BDDataOut; // BD data out
 
wire TxEndFrm_wb;
 
wire DMACycleFinishedTx;
wire BDStatusWrite;
 
wire TxEn;
wire RxEn;
wire TxRestartPulse;
wire TxDonePulse;
wire TxAbortPulse;
 
wire StartRxBDRead;
wire ResetRxBDRead;
wire StartRxStatusWrite;
 
wire ResetShifting_wb;
wire StartShifting_wb;
wire DMACycleFinishedRx;
 
wire [31:0] WB_BDDataOut;
 
wire StartTxBDRead;
wire StartTxDataRead;
wire ResetTxDataRead;
wire StartTxStatusWrite;
wire ResetTxStatusWrite;
wire WrapTxStatusBit;
wire WrapRxStatusBit;
 
wire [1:0] TxValidBytes;
 
wire [7:0] TempTxBDAddress;
wire [7:0] TempRxBDAddress;
 
wire [15:0] RxLength;
wire [15:0] NewRxStatus;
 
wire SetGotData;
wire ResetGotData;
wire GotDataEvaluate;
wire ResetSyncGetNewTxData_wb;
wire ResetTxDoneSync;
wire ResetTxRetrySync;
wire ResetTxAbortSync;
wire SetSyncGetNewTxData_wb;
 
wire SetTxDoneSync;
wire SetTxRetrySync;
wire SetTxAbortSync;
wire ResetShiftEnded;
wire ResetRxStartFrmSync1;
wire StartShiftEnded;
wire StartRxStartFrmSync1;
 
wire SetClearTxBDReady;
wire ResetClearTxBDReady;
 
wire AccessToBD;
 
wire ResetTxCtrlEndFrm_wb;
wire SetTxCtrlEndFrm_wb;
assign AccessToBD = WB_ADR_I[15:12] == `BD_SPACE;
assign DWord = &WB_SEL_I;
assign BDWe = DWord & WB_CYC_I & WB_STB_I & WB_WE_I & AccessToBD;
assign BDRead = DWord & WB_CYC_I & WB_STB_I & ~WB_WE_I & AccessToBD;
assign WB_ACK_O = BDWe | BDRead & BDRead_q; // ACK is delayed one clock because of BLOCKRAM properties when performing read
 
`ifdef FPGA
// Xilinx BlockRAM for storing Tx and Rx buffer descriptors
RAMB4_S16_S16 RAM1 ( .DIA(WB_DAT_I[15:0]), .DOA(WB_BDDataOut[15:0]), .ADDRA(WB_ADR_I[9:2]),
.WEA(BDWe), .CLKA(WB_CLK_I), .ENA(1'b1),
.RSTA(WB_RST_I), .DIB(BDDataIn[15:0]), .DOB(BDDataOut[15:0]),
.ADDRB(BDAddress[7:0]), .WEB(BDStatusWrite), .CLKB(~WB_CLK_I),
.ENB(1'b1), .RSTB(WB_RST_I) );
RAMB4_S16_S16 RAM2 ( .DIA(WB_DAT_I[31:16]), .DOA(WB_BDDataOut[31:16]), .ADDRA(WB_ADR_I[9:2]),
.WEA(BDWe), .CLKA(WB_CLK_I), .ENA(1'b1),
.RSTA(WB_RST_I), .DIB(BDDataIn[31:16]), .DOB(BDDataOut[31:16]),
.ADDRB(BDAddress[7:0]), .WEB(BDStatusWrite), .CLKB(~WB_CLK_I),
.ENB(1'b1), .RSTB(WB_RST_I) );
`else
// Artisan RAM (ASIC implementation) for storing Tx and Rx buffer descriptors
// Size will be reduced before implementation to 256 x 32
wire [63:32] qa_dummy;
wire [63:32] qb_dummy;
art_hddp_8192x64 RAM1 ( .qa({qa_dummy[63:32], WB_BDDataOut[31:0]}), .clka(WB_CLK_I),
.cena(1'b0), .wena(~BDWe),
.aa({5'h0, WB_ADR_I[9:2]}), .da({32'h0, WB_DAT_I[31:0]}),
.oena(1'b0),
.qb({qb_dummy[63:32], BDDataOut[31:0]}), .clkb(~WB_CLK_I),
.cenb(1'b0), .wenb(~BDStatusWrite),
.ab({5'h0, BDAddress[7:0]}), .db({32'h0, BDDataIn[31:0]}),
.oenb(1'b0)
);
`endif
 
 
// WB_CLK_I is divided by 2. This signal is used for enabling tx and rx operations sequentially
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
Div2 <=#Tp 1'h0;
else
Div2 <=#Tp ~Div2;
end
 
 
// Tx_En and Rx_En select who can access the BD memory (Tx or Rx)
assign TxEn = Div2 & r_TxEn;
assign RxEn = ~Div2 & r_RxEn;
 
 
// Changes for tx occur every second clock. Flop is used for this manner.
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
Flop <=#Tp 1'b0;
else
if(TxDone | TxAbort | TxRetry_q)
Flop <=#Tp 1'b0;
else
if(TxUsedData)
Flop <=#Tp ~Flop;
end
 
 
// Latching READY status of the Tx buffer descriptor
always @ (negedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxBDReady <=#Tp 1'b0;
else
if(TxEn & TxBDRead)
TxBDReady <=#Tp BDDataOut[15]; // TxBDReady is sampled only once at the beginning
else
if(TxDone & ~TxDone_q | TxAbort & ~TxAbort_q | TxRetry & ~TxRetry_q | ClearTxBDReady | TxPauseRq)
TxBDReady <=#Tp 1'b0;
end
 
 
// Latching READY status of the Tx buffer descriptor
always @ (negedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
begin
TxPauseRq <=#Tp 1'b0;
end
else
if(TxEn & TxBDRead)
begin
TxPauseRq <=#Tp BDDataOut[13]; // Tx PAUSE request
end
else
TxPauseRq <=#Tp 1'b0;
end
 
 
assign TxPauseTV[15:0] = TxLength[15:0];
 
// Reading the Tx buffer descriptor
assign StartTxBDRead = TxEn & ~BlockingTxBDRead & (TxRetry_wb | TxStatusWriteOccured);
 
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxBDRead <=#Tp 1'b1;
else
if(StartTxBDRead)
TxBDRead <=#Tp 1'b1;
else
if(StartTxDataRead | TxPauseRq)
TxBDRead <=#Tp 1'b0;
end
 
 
 
// Requesting data (DMA)
assign StartTxDataRead = TxBDRead & TxBDReady & ~TxPauseRq | GetNewTxData_wb;
assign ResetTxDataRead = DMACycleFinishedTx | TxRestartPulse | TxAbortPulse | TxDonePulse;
 
 
// Reading data
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDataRead <=#Tp 1'b0;
else
if(StartTxDataRead)
TxDataRead <=#Tp 1'b1;
else
if(ResetTxDataRead)
TxDataRead <=#Tp 1'b0;
end
 
// Requesting tx data from the DMA
assign WB_REQ_O[0] = TxDataRead & r_DmaEn;
assign DMACycleFinishedTx = WB_REQ_O[0] & WB_ACK_I[0] & TxBDReady;
 
 
// Writing status back to the Tx buffer descriptor
assign StartTxStatusWrite = TxEn & ~BlockingTxStatusWrite & (TxDone_wb | TxAbort_wb | TxCtrlEndFrm_wb);
assign ResetTxStatusWrite = TxStatusWrite;
 
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxStatusWrite <=#Tp 1'b0;
else
if(StartTxStatusWrite)
TxStatusWrite <=#Tp 1'b1;
else
if(ResetTxStatusWrite)
TxStatusWrite <=#Tp 1'b0;
end
 
 
// Status writing must occur only once. Meanwhile it is blocked.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
BlockingTxStatusWrite <=#Tp 1'b0;
else
if(StartTxStatusWrite)
BlockingTxStatusWrite <=#Tp 1'b1;
else
if(~TxDone_wb & ~TxAbort_wb)
BlockingTxStatusWrite <=#Tp 1'b0;
end
 
 
// After a tx status write is finished, a new tx buffer descriptor is read. Signal must be
// latched because new BD read doesn't occur immediately.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxStatusWriteOccured <=#Tp 1'b0;
else
if(StartTxStatusWrite)
TxStatusWriteOccured <=#Tp 1'b1;
else
if(StartTxBDRead)
TxStatusWriteOccured <=#Tp 1'b0;
end
 
 
// TxBDRead state is activated only once.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
BlockingTxBDRead <=#Tp 1'b0;
else
if(StartTxBDRead)
BlockingTxBDRead <=#Tp 1'b1;
else
if(TxStartFrm_wb | TxCtrlEndFrm_wb)
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 WB_RST_I)
begin
if(WB_RST_I)
TxStatus <=#Tp 16'h0;
else
if(TxBDRead & ~TxEn)
TxStatus <=#Tp BDDataOut[15:0];
end
 
 
//Latching length from the buffer descriptor;
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxLength <=#Tp 16'h0;
else
if(TxBDRead & ~TxEn)
TxLength <=#Tp BDDataOut[31:16];
else
if(GetNewTxData_wb & ~WillSendControlFrame)
begin
if(TxLength > 4)
TxLength <=#Tp TxLength - 4; // Length is subtracted at the data request
else
TxLength <=#Tp 16'h0;
end
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 WB_RST_I)
begin
if(WB_RST_I)
RxStatus <=#Tp 16'h0;
else
if(RxBDRead & ~RxEn)
RxStatus <=#Tp BDDataOut[15:0];
end
 
 
// Signal GetNewTxData_wb that requests new data from the DMA must be latched since the DMA response
// might be delayed.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
GetNewTxData_wb_latched <=#Tp 1'b0;
else
if(GetNewTxData_wb)
GetNewTxData_wb_latched <=#Tp 1'b1;
else
if(DMACycleFinishedTx)
GetNewTxData_wb_latched <=#Tp 1'b0;
end
 
 
// New tx data is avaliable after the DMA access is finished
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
NewTxDataAvaliable_wb <=#Tp 1'b0;
else
if(DMACycleFinishedTx & GetNewTxData_wb_latched)
NewTxDataAvaliable_wb <=#Tp 1'b1;
else
if(NewTxDataAvaliable_wb)
NewTxDataAvaliable_wb <=#Tp 1'b0;
end
 
 
// Tx Buffer descriptor is only read at the beginning. This signal is used for generation of the
// TxStartFrm_wb signal.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxBDAccessed <=#Tp 1'b0;
else
if(TxBDRead)
TxBDAccessed <=#Tp 1'b1;
else
if(TxStartFrm_wb)
TxBDAccessed <=#Tp 1'b0;
end
 
 
// TxStartFrm_wb: indicator of the start frame (synchronized to WB_CLK_I)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxStartFrm_wb <=#Tp 1'b0;
else
if(DMACycleFinishedTx & TxBDAccessed & ~TxStartFrm_wb)
TxStartFrm_wb <=#Tp 1'b1;
else
if(TxStartFrm_wb)
TxStartFrm_wb <=#Tp 1'b0;
end
 
 
// TxEndFrm_wb: indicator of the end of frame
assign TxEndFrm_wb = (TxLength <= 4) & TxUsedData;
 
 
// Input latch of the end-of-frame indicator
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxEndFrm_wbLatched <=#Tp 1'b0;
else
if(TxEndFrm_wb)
TxEndFrm_wbLatched <=#Tp 1'b1;
else
if(TxRestartPulse | TxDonePulse | TxAbortPulse)
TxEndFrm_wbLatched <=#Tp 1'b0;
end
 
 
// Marks which bytes are valid within the word.
assign TxValidBytes = (TxLength >= 4)? 2'b0 : TxLength[1:0];
 
 
// Latching valid bytes
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxValidBytesLatched <=#Tp 2'h0;
else
if(TxEndFrm_wb & ~TxEndFrm_wbLatched)
TxValidBytesLatched <=#Tp TxValidBytes;
if(TxRestartPulse | TxDonePulse | TxAbortPulse)
TxValidBytesLatched <=#Tp 2'h0;
end
 
 
// Input Tx data latch
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDataLatched_wb <=#Tp 32'h0;
else
if(DMACycleFinishedTx)
TxDataLatched_wb <=#Tp WB_DAT_I;
end
 
 
// TxStartFrmRequest is set when a new frame is avaliable or when new data of the same frame is avaliable)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxStartFrmRequest <=#Tp 1'b0;
else
if(TxStartFrm_wb | NewTxDataAvaliable_wb)
TxStartFrmRequest <=#Tp TxStartFrm_wb;
end
 
 
// Bit 14 is used as a wrap bit. When active it indicates the last buffer descriptor in a row. After
// using this descriptor, first BD will be used again.
assign WrapTxStatusBit = TxStatus[14];
assign WrapRxStatusBit = RxStatus[14];
assign PerPacketCrcEn = RxStatus[13] & RxStatus[12];
assign PerPacketPad = RxStatus[11];
 
 
// Temporary Tx and Rx buffer descriptor address
assign TempTxBDAddress[7:0] = {8{ TxStatusWrite & ~WrapTxStatusBit}} & (TxBDAddress + 1) ; // Tx BD increment or wrap (last BD)
assign TempRxBDAddress[7:0] = {8{ WrapRxStatusBit}} & (r_RxBDAddress) | // Using first Rx BD
{8{~WrapRxStatusBit}} & (RxBDAddress + 1) ; // Using next Rx BD (incremenrement address)
 
 
// Latching Tx buffer descriptor address
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxBDAddress <=#Tp 8'h0;
else
if(TxStatusWrite)
TxBDAddress <=#Tp TempTxBDAddress;
end
 
 
// Latching Rx buffer descriptor address
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxBDAddress <=#Tp 8'h0;
else
if(RX_BD_ADR_Wr) // When r_RxBDAddress is updated, RxBDAddress is also
RxBDAddress <=#Tp WB_DAT_I[7:0];
else
if(RxStatusWrite)
RxBDAddress <=#Tp TempRxBDAddress;
end
 
 
// Selecting Tx or Rx buffer descriptor address
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
BDAddress <=#Tp 8'h0;
else
if(TxEn)
BDAddress <=#Tp TxBDAddress;
else
BDAddress <=#Tp RxBDAddress;
end
 
 
assign RxLength[15:0] = 16'h1399;
assign NewRxStatus[15:0] = {1'b0, WbWriteError, RxStatus[13:0]};
 
 
assign BDDataIn = TxStatusWrite ? {TxLength[15:0], StatusIzTxEthMACModula} : {RxLength, NewRxStatus};
assign BDStatusWrite = TxStatusWrite | RxStatusWrite;
 
 
 
// Generating delayed signals
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
begin
TxRestart_wb_q <=#Tp 1'b0;
TxDone_wb_q <=#Tp 1'b0;
TxAbort_wb_q <=#Tp 1'b0;
BDRead_q <=#Tp 1'b0;
DMACycleFinishedTx_q <=#Tp 1'b0;
end
else
begin
TxRestart_wb_q <=#Tp TxRetry_wb;
TxDone_wb_q <=#Tp TxDone_wb;
TxAbort_wb_q <=#Tp TxAbort_wb;
BDRead_q <=#Tp BDRead;
DMACycleFinishedTx_q <=#Tp DMACycleFinishedTx;
end
end
 
 
// Signals used for various purposes
assign TxRestartPulse = TxRetry_wb & ~TxRestart_wb_q;
assign TxDonePulse = TxDone_wb & ~TxDone_wb_q;
assign TxAbortPulse = TxAbort_wb & ~TxAbort_wb_q;
 
 
// Next descriptor for Tx DMA channel
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
WB_ND_O_TX <=#Tp 1'b0;
else
if(TxDonePulse | TxAbortPulse)
WB_ND_O_TX <=#Tp 1'b1;
else
if(WB_ND_O_TX)
WB_ND_O_TX <=#Tp 1'b0;
end
 
 
// Force next descriptor on DMA channel 0 (Tx)
assign WB_ND_O[0] = WB_ND_O_TX;
 
 
 
// Restart descriptor for DMA channel 0 (Tx)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
WB_RD_O <=#Tp 1'b0;
else
if(TxRestartPulse)
WB_RD_O <=#Tp 1'b1;
else
if(WB_RD_O)
WB_RD_O <=#Tp 1'b0;
end
 
 
assign SetClearTxBDReady = ~TxUsedData & TxUsedData_q;
assign ResetClearTxBDReady = ClearTxBDReady | WB_RST_I;
 
 
always @ (posedge SetClearTxBDReady or posedge ResetClearTxBDReady)
begin
if(ResetClearTxBDReady)
ClearTxBDReadySync1 <=#Tp 1'b0;
else
ClearTxBDReadySync1 <=#Tp 1'b1;
end
 
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
ClearTxBDReadySync2 <=#Tp 1'b0;
else
if(ClearTxBDReadySync1 & ~ClearTxBDReady)
ClearTxBDReadySync2 <=#Tp 1'b1;
else
ClearTxBDReadySync2 <=#Tp 1'b0;
end
 
 
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
ClearTxBDReady <=#Tp 1'b0;
else
if(ClearTxBDReadySync2 & ~ClearTxBDReady)
ClearTxBDReady <=#Tp 1'b1;
else
ClearTxBDReady <=#Tp 1'b0;
end
 
 
 
// Latching and synchronizing the Tx pause request signal
 
wire ResetTPauseRq;
wire SetTPauseRq;
reg TPauseRqSync1;
reg TPauseRqSync2;
 
assign ResetTPauseRq = TPauseRqSync2 | WB_RST_I;
assign SetTPauseRq = TxPauseRq;
 
 
// Sync stage 1
always @ (posedge SetTPauseRq or posedge ResetTPauseRq)
begin
if(ResetTPauseRq)
TPauseRqSync1 <=#Tp 1'b0;
else
TPauseRqSync1 <=#Tp 1'b1;
end
 
// Sync stage 2
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TPauseRqSync2 <=#Tp 1'b0;
else
if(TPauseRqSync1 & ~TPauseRq)
TPauseRqSync2 <=#Tp 1'b1;
else
TPauseRqSync2 <=#Tp 1'b0;
end
 
 
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TPauseRq <=#Tp 1'b0;
else
if(TPauseRq )
TPauseRq <=#Tp 1'b0;
else
if(TPauseRqSync2)
TPauseRq <=#Tp 1'b1;
end
 
 
 
// Generating delayed signals
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
begin
TxAbort_q <=#Tp 1'b0;
TxDone_q <=#Tp 1'b0;
TxRetry_q <=#Tp 1'b0;
TxUsedData_q <=#Tp 1'b0;
end
else
begin
TxAbort_q <=#Tp TxAbort;
TxDone_q <=#Tp TxDone;
TxRetry_q <=#Tp TxRetry;
TxUsedData_q <=#Tp TxUsedData;
end
end
 
 
 
// Sinchronizing and evaluating tx data
assign SetGotData = (TxStartFrm_wb | NewTxDataAvaliable_wb & ~TxAbort_wb & ~TxRetry_wb) & ~WB_CLK_I;
assign ResetGotData = GotDataSync3 & ~TxStartFrm_wb | WB_RST_I;
 
 
// Sync stage 1
always @ (posedge SetGotData or posedge ResetGotData)
begin
if(ResetGotData)
GotDataSync1 <=#Tp 1'b0;
else
GotDataSync1 <=#Tp 1'b1;
end
 
 
// Sync stage 2
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
GotDataSync2 <=#Tp 1'b0;
else
if(GotDataSync1 & ~GotData)
GotDataSync2 <=#Tp 1'b1;
else
GotDataSync2 <=#Tp 1'b0;
end
 
 
// Sync stage 3
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
GotDataSync3 <=#Tp 1'b0;
else
if(GotDataSync2 & ~GotData)
GotDataSync3 <=#Tp 1'b1;
else
GotDataSync3 <=#Tp 1'b0;
end
 
 
 
// Evaluating data. If abort or retry occured meanwhile than data is ignored.
assign GotDataEvaluate = GotDataSync3 & ~GotData & (~TxRetry & ~TxAbort | (TxRetry | TxAbort) & (TxStartFrmRequest | TxStartFrm));
 
 
// Indication of good data
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
GotData <=#Tp 1'b0;
else
if(GotDataEvaluate)
GotData <=#Tp 1'b1;
else
GotData <=#Tp 1'b0;
end
 
 
// Tx start frame generation
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxStartFrm <=#Tp 1'b0;
else
if(TxUsedData_q | TxAbort & ~TxAbort_q | TxRetry & ~TxRetry_q)
TxStartFrm <=#Tp 1'b0;
else
if(TxBDReady & GotData & TxStartFrmRequest)
TxStartFrm <=#Tp 1'b1;
end
 
 
// Indication of the last word
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
LastWord <=#Tp 1'b0;
else
if((TxEndFrm | TxAbort | TxRetry) & Flop)
LastWord <=#Tp 1'b0;
else
if(TxUsedData & Flop & TxByteCnt == 2'h3)
LastWord <=#Tp TxEndFrm_wbLatched;
end
 
 
// Tx end frame generation
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxEndFrm <=#Tp 1'b0;
else
if(Flop & TxEndFrm | TxAbort | TxRetry_q)
TxEndFrm <=#Tp 1'b0;
else
if(Flop & LastWord)
begin
case (TxValidBytesLatched)
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 WB_RST_I)
begin
if(WB_RST_I)
TxData <=#Tp 8'h0;
else
if(GotData & ~TxStartFrm & ~TxUsedData)
TxData <=#Tp TxDataLatched_wb[7:0];
else
if(TxUsedData & Flop)
begin
case(TxByteCnt)
0 : TxData <=#Tp TxDataLatched[7:0];
1 : TxData <=#Tp TxDataLatched[15:8];
2 : TxData <=#Tp TxDataLatched[23:16];
3 : TxData <=#Tp TxDataLatched[31:24];
endcase
end
end
 
 
// Latching tx data
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDataLatched[31:0] <=#Tp 32'h0;
else
if(GotData & ~TxUsedData & ~TxStartFrm)
TxDataLatched[31:0] <=#Tp TxDataLatched_wb[31:0];
else
if(TxUsedData & Flop & TxByteCnt == 2'h3)
TxDataLatched[31:0] <=#Tp TxDataLatched_wb[31:0];
end
 
 
// Generation of the DataNotAvaliable signal which is used for the generation of the TxUnderRun signal
assign ResetDataNotAvaliable = DMACycleFinishedTx_q | WB_RST_I;
assign SetDataNotAvaliable = GotData & ~TxUsedData & ~TxStartFrm | TxUsedData & Flop & TxByteCnt == 2'h3;
 
always @ (posedge MTxClk or posedge ResetDataNotAvaliable)
begin
if(ResetDataNotAvaliable)
DataNotAvaliable <=#Tp 1'b0;
else
if(SetDataNotAvaliable) // data is latched here
DataNotAvaliable <=#Tp 1'b1;
end
 
 
// Tx under run
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxUnderRun <=#Tp 1'b0;
else
if(TxAbort & ~TxAbort_q)
TxUnderRun <=#Tp 1'b0;
else
if(TxUsedData & Flop & TxByteCnt == 2'h3 & ~LastWord & DataNotAvaliable)
TxUnderRun <=#Tp 1'b1;
end
 
 
 
// Tx Byte counter
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxByteCnt <=#Tp 2'h0;
else
if(TxAbort_q | TxRetry_q)
TxByteCnt <=#Tp 2'h0;
else
if(TxStartFrm & ~TxUsedData)
TxByteCnt <=#Tp 2'h1;
else
if(TxUsedData & Flop)
TxByteCnt <=#Tp TxByteCnt + 1;
end
 
 
// Generation of the GetNewTxData signal
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
GetNewTxData <=#Tp 1'b0;
else
if(GetNewTxData)
GetNewTxData <=#Tp 1'b0;
else
if(TxBDReady & GotData & ~(TxStartFrm | TxUsedData))
GetNewTxData <=#Tp 1'b1;
else
if(TxUsedData & ~TxEndFrm_wbLatched & TxByteCnt == 2'h3)
GetNewTxData <=#Tp ~LastWord;
end
 
 
// TxRetryLatched
always @ (posedge MTxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
TxRetryLatched <=#Tp 1'b0;
else
if(TxStartFrm)
TxRetryLatched <=#Tp 1'b0;
else
if(TxRetry)
TxRetryLatched <=#Tp 1'b1;
end
 
 
 
// Synchronizing request for a new tx data
assign ResetSyncGetNewTxData_wb = SyncGetNewTxData_wb3 | TxAbort_wb | TxRetry_wb | WB_RST_I;
assign SetSyncGetNewTxData_wb = GetNewTxData;
 
 
// Sync. stage 1
always @ (posedge SetSyncGetNewTxData_wb or posedge ResetSyncGetNewTxData_wb)
begin
if(ResetSyncGetNewTxData_wb)
SyncGetNewTxData_wb1 <=#Tp 1'b0;
else
SyncGetNewTxData_wb1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
SyncGetNewTxData_wb2 <=#Tp 1'b0;
else
if(SyncGetNewTxData_wb1 & ~GetNewTxData_wb & ~TxAbort_wb & ~TxRetry_wb)
SyncGetNewTxData_wb2 <=#Tp 1'b1;
else
SyncGetNewTxData_wb2 <=#Tp 1'b0;
end
 
 
// Sync. stage 3
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
SyncGetNewTxData_wb3 <=#Tp 1'b0;
else
if(SyncGetNewTxData_wb2 & ~GetNewTxData_wb & ~TxAbort_wb & ~TxRetry_wb)
SyncGetNewTxData_wb3 <=#Tp 1'b1;
else
SyncGetNewTxData_wb3 <=#Tp 1'b0;
end
 
 
// Synchronized request for a new tx data
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
GetNewTxData_wb <=#Tp 1'b0;
else
if(GetNewTxData_wb)
GetNewTxData_wb <=#Tp 1'b0;
else
if(SyncGetNewTxData_wb3 & ~GetNewTxData_wb & ~TxAbort_wb & ~TxRetry_wb)
GetNewTxData_wb <=#Tp 1'b1;
end
 
 
// Synchronizine transmit done signal
assign ResetTxDoneSync = TxDoneSync3 | WB_RST_I;
assign SetTxDoneSync = TxDone;
 
 
// Sync stage 1
always @ (posedge SetTxDoneSync or posedge ResetTxDoneSync )
begin
if(ResetTxDoneSync)
TxDoneSync1 <=#Tp 1'b0;
else
TxDoneSync1 <=#Tp 1'b1;
end
 
 
// Sync stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDoneSync2 <=#Tp 1'b0;
else
if(TxDoneSync1 & ~TxDone_wb)
TxDoneSync2 <=#Tp 1'b1;
else
TxDoneSync2 <=#Tp 1'b0;
end
 
 
// Sync stage 3
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDoneSync3 <=#Tp 1'b0;
else
if(TxDoneSync2 & ~TxDone_wb)
TxDoneSync3 <=#Tp 1'b1;
else
TxDoneSync3 <=#Tp 1'b0;
end
 
 
// Syncronized signal TxDone_wb (sync. to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxDone_wb <=#Tp 1'b0;
else
if(TxStartFrm_wb | WillSendControlFrame)
TxDone_wb <=#Tp 1'b0;
else
if(TxDoneSync3 & ~TxStartFrmRequest)
TxDone_wb <=#Tp 1'b1;
end
 
 
// Synchronizing transmit control end frame signal
assign ResetTxCtrlEndFrm_wb = TxCtrlEndFrm_wb | WB_RST_I;
assign SetTxCtrlEndFrm_wb = TxCtrlEndFrm;
 
 
// Sync stage 1
always @ (posedge SetTxCtrlEndFrm_wb or posedge ResetTxCtrlEndFrm_wb)
begin
if(ResetTxCtrlEndFrm_wb)
TxCtrlEndFrm_wbSync1 <=#Tp 1'b0;
else
TxCtrlEndFrm_wbSync1 <=#Tp 1'b1;
end
 
 
// Sync stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxCtrlEndFrm_wbSync2 <=#Tp 1'b0;
else
if(TxCtrlEndFrm_wbSync1 & ~TxCtrlEndFrm_wb)
TxCtrlEndFrm_wbSync2 <=#Tp 1'b1;
else
TxCtrlEndFrm_wbSync2 <=#Tp 1'b0;
end
 
 
// Synchronized Tx control end frame
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxCtrlEndFrm_wb <=#Tp 1'b0;
else
if(TxCtrlEndFrm_wbSync2 & ~TxCtrlEndFrm_wb)
TxCtrlEndFrm_wb <=#Tp 1'b1;
else
if(StartTxStatusWrite)
TxCtrlEndFrm_wb <=#Tp 1'b0;
end
 
 
// Synchronizing TxRetry signal
assign ResetTxRetrySync = TxRetrySync3 | WB_RST_I;
assign SetTxRetrySync = TxRetryLatched;
 
 
// Sync. stage 1
always @ (posedge SetTxRetrySync or posedge ResetTxRetrySync)
begin
if(ResetTxRetrySync)
TxRetrySync1 <=#Tp 1'b0;
else
TxRetrySync1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxRetrySync2 <=#Tp 1'b0;
else
if(TxRetrySync1 & ~TxRetry_wb)
TxRetrySync2 <=#Tp 1'b1;
else
TxRetrySync2 <=#Tp 1'b0;
end
 
 
// Sync. stage 3
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxRetrySync3 <=#Tp 1'b0;
else
if(TxRetrySync2 & ~TxRetry_wb)
TxRetrySync3 <=#Tp 1'b1;
else
TxRetrySync3 <=#Tp 1'b0;
end
 
 
// Synchronized signal TxRetry_wb (synchronized to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxRetry_wb <=#Tp 1'b0;
else
if(TxStartFrm_wb | WillSendControlFrame)
TxRetry_wb <=#Tp 1'b0;
else
if(TxRetrySync3)
TxRetry_wb <=#Tp 1'b1;
end
 
 
// Synchronizing TxAbort signal
assign ResetTxAbortSync = TxAbortSync3 | WB_RST_I;
assign SetTxAbortSync = TxAbort;
 
 
// Sync. stage 1
always @ (posedge SetTxAbortSync or posedge ResetTxAbortSync)
begin
if(ResetTxAbortSync)
TxAbortSync1 <=#Tp 1'b0;
else
TxAbortSync1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxAbortSync2 <=#Tp 1'b0;
else
if(TxAbortSync1 & ~TxAbort_wb)
TxAbortSync2 <=#Tp 1'b1;
else
TxAbortSync2 <=#Tp 1'b0;
end
 
 
// Sync. stage 3
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxAbortSync3 <=#Tp 1'b0;
else
if(TxAbortSync2 & ~TxAbort_wb)
TxAbortSync3 <=#Tp 1'b1;
else
TxAbortSync3 <=#Tp 1'b0;
end
 
 
// Synchronized TxAbort_wb signal (synchronized to WISHBONE clock)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
TxAbort_wb <=#Tp 1'b0;
else
if(TxStartFrm_wb)
TxAbort_wb <=#Tp 1'b0;
else
if(TxAbortSync3 & ~TxStartFrmRequest)
TxAbort_wb <=#Tp 1'b1;
end
 
 
// Reading of the next receive buffer descriptor starts after reception status is
// written to the previous one.
assign StartRxBDRead = RxEn & RxStatusWriteOccured;
assign ResetRxBDRead = RxBDRead & RxBDReady; // Rx BD is read until READY bit is set.
 
 
// Latching READY status of the Rx buffer descriptor
always @ (negedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxBDReady <=#Tp 1'b0;
else
if(RxEn & RxBDRead)
RxBDReady <=#Tp BDDataOut[15];
else
if(RxStatusWrite)
RxBDReady <=#Tp 1'b0;
end
 
 
// Reading the Rx buffer descriptor
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxBDRead <=#Tp 1'b1;
else
if(StartRxBDRead)
RxBDRead <=#Tp 1'b1;
else
if(ResetRxBDRead)
RxBDRead <=#Tp 1'b0;
end
 
 
// Reception status is written back to the buffer descriptor after the end of frame is detected.
//assign StartRxStatusWrite = RxEn & RxEndFrm_wb;
assign StartRxStatusWrite = RxEn & RxEndFrm_wb;
 
 
// Writing status back to the Rx buffer descriptor
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxStatusWrite <=#Tp 1'b0;
else
if(StartRxStatusWrite)
RxStatusWrite <=#Tp 1'b1;
else
RxStatusWrite <=#Tp 1'b0;
end
 
 
// Forcing next descriptor on DMA channel 1 (Rx)
assign WB_ND_O[1] = RxStatusWrite;
 
 
// Latched status that a status write occured.
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxStatusWriteOccured <=#Tp 1'b0;
else
if(StartRxStatusWrite)
RxStatusWriteOccured <=#Tp 1'b1;
else
if(StartRxBDRead)
RxStatusWriteOccured <=#Tp 1'b0;
end
 
 
 
// Generation of the synchronized signal ShiftEnded that indicates end of reception
assign ResetShiftEnded = ShiftEndedSync3 | WB_RST_I;
assign StartShiftEnded = RxEndFrm_wb;
 
 
// Sync. stage 1
always @ (posedge StartShiftEnded or posedge ResetShiftEnded)
begin
if(ResetShiftEnded)
ShiftEndedSync1 <=#Tp 1'b0;
else
ShiftEndedSync1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
ShiftEndedSync2 <=#Tp 1'b0;
else
if(ShiftEndedSync1 & ~ShiftEnded)
ShiftEndedSync2 <=#Tp 1'b1;
else
ShiftEndedSync2 <=#Tp 1'b0;
end
 
 
// Sync. stage 3
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
ShiftEndedSync3 <=#Tp 1'b0;
else
if(ShiftEndedSync2 & ~ShiftEnded)
ShiftEndedSync3 <=#Tp 1'b1;
else
ShiftEndedSync3 <=#Tp 1'b0;
end
 
 
 
// Synchronized signal ShiftEnded
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
ShiftEnded <=#Tp 1'b0;
else
if(ShiftEndedSync3 & ~ShiftEnded)
ShiftEnded <=#Tp 1'b1;
else
ShiftEnded <=#Tp 1'b0;
end
 
 
// Indicating that last byte is being reveived
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
LastByteIn <=#Tp 1'b0;
else
if(ShiftWillEnd & (&RxByteCnt))
LastByteIn <=#Tp 1'b0;
else
if(RxValid & RxBDReady & RxEndFrm & ~(&RxByteCnt))
LastByteIn <=#Tp 1'b1;
end
 
 
// Indicating that data reception will end
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
ShiftWillEnd <=#Tp 1'b0;
else
if(ShiftEnded)
ShiftWillEnd <=#Tp 1'b0;
else
if(LastByteIn & (&RxByteCnt) | RxValid & RxEndFrm & (&RxByteCnt))
ShiftWillEnd <=#Tp 1'b1;
end
 
 
// Receive byte counter
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
RxByteCnt <=#Tp 2'h0;
else
if(ShiftEnded)
RxByteCnt <=#Tp 2'h0;
else
if(RxValid & RxBDReady | LastByteIn)
RxByteCnt <=#Tp RxByteCnt + 1;
end
 
 
// Indicates how many bytes are valid within the last word
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
RxValidBytes <=#Tp 2'h1;
else
if(ShiftEnded)
RxValidBytes <=#Tp 2'h1;
else
if(RxValid & ~LastByteIn & ~RxStartFrm)
RxValidBytes <=#Tp RxValidBytes + 1;
end
 
 
// There is a maximum 3 MRxClk delay between RxDataLatched2 and RxData_wb. In the meantime data
// is stored to the RxDataLatched1.
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
RxDataLatched1 <=#Tp 16'h0;
else
if(RxValid & RxBDReady & ~LastByteIn & RxByteCnt == 2'h0)
RxDataLatched1[7:0] <=#Tp RxData;
else
if(RxValid & RxBDReady & ~LastByteIn & RxByteCnt == 2'h1)
RxDataLatched1[15:8] <=#Tp RxData;
end
 
 
// Latching incoming data to buffer
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
RxDataLatched2 <=#Tp 32'h0;
else
if(RxValid & RxBDReady & ~LastByteIn & RxByteCnt == 2'h2)
RxDataLatched2[23:0] <=#Tp {RxData,RxDataLatched1};
else
if(RxValid & RxBDReady & ~LastByteIn & RxByteCnt == 2'h3)
RxDataLatched2[31:24] <=#Tp RxData;
end
 
 
// Indicating start of the reception process
always @ (posedge MRxClk or posedge WB_RST_I)
begin
if(WB_RST_I)
StartShifting <=#Tp 1'b0;
else
if((RxValid & RxBDReady & ~RxStartFrm & (&RxByteCnt)) | (ShiftWillEnd & LastByteIn & (&RxByteCnt)))
StartShifting <=#Tp 1'b1;
else
StartShifting <=#Tp 1'b0;
end
 
 
// Synchronizing Rx start frame to the WISHBONE clock
assign ResetRxStartFrmSync1 = RxStartFrmSync3 | WB_RST_I;
assign StartRxStartFrmSync1 = RxStartFrm & RxBDReady;
 
 
// Sync. stage 1
always @ (posedge StartRxStartFrmSync1 or posedge ResetRxStartFrmSync1)
begin
if(ResetRxStartFrmSync1)
RxStartFrmSync1 <=#Tp 1'b0;
else
RxStartFrmSync1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxStartFrmSync2 <=#Tp 1'b0;
else
if(RxStartFrmSync1 & ~RxStartFrm_wb)
RxStartFrmSync2 <=#Tp 1'b1;
else
RxStartFrmSync2 <=#Tp 1'b0;
end
 
 
// Sync. stage 3
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxStartFrmSync3 <=#Tp 1'b0;
else
if(RxStartFrmSync2 & ~RxStartFrm_wb)
RxStartFrmSync3 <=#Tp 1'b1;
else
RxStartFrmSync3 <=#Tp 1'b0;
end
 
 
// Generating synchronized Rx start frame
always @ ( posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxStartFrm_wb <=#Tp 1'b0;
else
if(RxStartFrmSync3 & ~RxStartFrm_wb)
RxStartFrm_wb <=#Tp 1'b1;
else
RxStartFrm_wb <=#Tp 1'b0;
end
 
 
//Synchronizing signal for latching data that will be written to the WISHBONE
assign ResetShifting_wb = LatchNow_wb | WB_RST_I;
assign StartShifting_wb = StartShifting;
 
 
// Sync. stage 1
always @ (posedge StartShifting_wb or posedge ResetShifting_wb)
begin
if(ResetShifting_wb)
Shifting_wb_Sync1 <=#Tp 1'b0;
else
Shifting_wb_Sync1 <=#Tp 1'b1;
end
 
 
// Sync. stage 2
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
Shifting_wb_Sync2 <=#Tp 1'b0;
else
if(Shifting_wb_Sync1 & ~RxDataValid_wb)
Shifting_wb_Sync2 <=#Tp 1'b1;
else
Shifting_wb_Sync2 <=#Tp 1'b0;
end
 
 
// Generating synchronized signal that will latch data for writing to the WISHBONE
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
LatchNow_wb <=#Tp 1'b0;
else
if(Shifting_wb_Sync2 & ~RxDataValid_wb)
LatchNow_wb <=#Tp 1'b1;
else
LatchNow_wb <=#Tp 1'b0;
end
 
 
// Indicating that valid data is avaliable
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxDataValid_wb <=#Tp 1'b0;
else
if(LatchNow_wb & ~RxDataValid_wb)
RxDataValid_wb <=#Tp 1'b1;
else
if(RxDataValid_wb)
RxDataValid_wb <=#Tp 1'b0;
end
 
 
// Forcing next descriptor in the DMA (Channel 1 is used for rx)
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
WB_REQ_O_RX <=#Tp 1'b0;
else
if(LatchNow_wb & ~RxDataValid_wb)
WB_REQ_O_RX <=#Tp 1'b1;
else
if(DMACycleFinishedRx)
WB_REQ_O_RX <=#Tp 1'b0;
end
 
 
assign WB_REQ_O[1] = WB_REQ_O_RX & r_DmaEn;
assign DMACycleFinishedRx = WB_REQ_O[1] & WB_ACK_I[1];
 
 
// WbWriteError is generated when the previous word is not written to the wishbone on time
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
WbWriteError <=#Tp 1'b0;
else
if(LatchNow_wb & ~RxDataValid_wb)
begin
if(WB_REQ_O[1] & ~WB_ACK_I[1])
WbWriteError <=#Tp 1'b1;
end
else
if(RxStartFrm_wb)
WbWriteError <=#Tp 1'b0;
end
 
 
// Assembling data that will be written to the WISHBONE
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxData_wb <=#Tp 32'h0;
else
if(LatchNow_wb & ~RxDataValid_wb & ~ShiftWillEnd)
RxData_wb <=#Tp RxDataLatched2;
else
if(LatchNow_wb & ~RxDataValid_wb & ShiftWillEnd)
case(RxValidBytes)
0 : RxData_wb <=#Tp {RxDataLatched2[31:16], RxDataLatched1[15:0]};
1 : RxData_wb <=#Tp {24'h0, RxDataLatched1[7:0]};
2 : RxData_wb <=#Tp {16'h0, RxDataLatched1[15:0]};
3 : RxData_wb <=#Tp {8'h0, RxDataLatched2[23:16], RxDataLatched1[15:0]};
endcase
end
 
 
// Selecting the data for the WISHBONE
assign WB_DAT_O[31:0] = BDRead? WB_BDDataOut : RxData_wb;
 
 
// Generation of the end-of-frame signal
always @ (posedge WB_CLK_I or posedge WB_RST_I)
begin
if(WB_RST_I)
RxEndFrm_wb <=#Tp 1'b0;
else
if(LatchNow_wb & ~RxDataValid_wb & ShiftWillEnd)
RxEndFrm_wb <=#Tp 1'b1;
else
if(StartRxStatusWrite)
RxEndFrm_wb <=#Tp 1'b0;
end
 
endmodule
/trunk/rtl/verilog/eth_outputcontrol.v
0,0 → 1,130
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_outputcontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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 )); // igor !!! ali je tu res <46. To je veljalo, ko sem imel se >31 in napako 32 preamble bitov
 
 
// 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
/trunk/rtl/verilog/eth_maccontrol.v
0,0 → 1,235
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_maccontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
/trunk/rtl/verilog/eth_top.v
0,0 → 1,505
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_top.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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/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 "eth_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,
WB_REQ_O, WB_ACK_I, WB_ND_O, WB_RD_O,
 
//TX
MTxClk_I, MTxD_O, MTxEn_O, MTxErr_O,
 
//RX
MRxClk_I, MRxD_I, MRxDV_I, MRxErr_I, MColl_I, MCrs_I,
// MIIM
Mdc_O, Mdi_I, Mdo_O, Mdo_OE
);
 
 
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 [31:0] 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
 
// DMA
input [1:0] WB_ACK_I; // DMA acknowledge input
output [1:0] WB_REQ_O; // DMA request output
output [1:0] WB_ND_O; // DMA force new descriptor output
output WB_RD_O; // DMA restart descriptor output
 
// Tx
input MTxClk_I; // Transmit clock (from PHY)
output [3:0] MTxD_O; // Transmit nibble (to PHY)
output MTxEn_O; // Transmit enable (to PHY)
output MTxErr_O; // Transmit error (to PHY)
 
// Rx
input MRxClk_I; // Receive clock (from PHY)
input [3:0] MRxD_I; // Receive nibble (from PHY)
input MRxDV_I; // Receive data valid (from PHY)
input MRxErr_I; // Receive data error (from PHY)
 
// Common Tx and Rx
input MColl_I; // Collision (from PHY)
input MCrs_I; // Carrier sense (from PHY)
 
// MII Management interface
input Mdi_I; // MII data input (from I/O cell)
output Mdc_O; // MII Management data clock (to PHY)
output Mdo_O; // MII data output (to I/O cell)
output Mdo_OE; // MII data output enable (to I/O cell)
 
 
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;
 
 
 
 
// 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(Mdi_I), .Mdo(Mdo_O),
.MdoEn(Mdo_OE), .Mdc(Mdc_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_DmaEn; // DMA enable
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 [47:0] r_MAC; // MAC address
 
wire [7:0] r_RxBDAddress; // Receive buffer descriptor base address
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 RX_BD_ADR_Wr; // Write enable that writes RX_BD_ADR 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 EthAddMatch;
wire WB_STB_I_eth;
wire WB_CYC_I_eth;
 
wire DWord;
wire RegAck;
wire BDAck;
wire [31:0] DMA_WB_DAT_O; // WB_DAT_O that comes from the WishboneDMA module
 
 
 
assign EthAddMatch = WB_ADR_I[31:16] == `ETHERNET_SPACE;
assign WB_STB_I_eth = WB_STB_I & EthAddMatch;
assign WB_CYC_I_eth = WB_STB_I & EthAddMatch;
 
assign WB_ERR_O = WB_STB_I & WB_CYC_I & EthAddMatch & ~DWord;
assign DWord = &WB_SEL_I;
assign RegCs = WB_STB_I & WB_CYC_I & DWord & EthAddMatch & (WB_ADR_I[15:12] == `REG_SPACE);
assign RegAck = RegCs;
assign WB_ACK_O = RegAck | BDAck;
 
 
// Selecting the WISHBONE output data
assign WB_DAT_O[31:0] = (RegCs & ~WB_WE_I)? RegDataOut : DMA_WB_DAT_O;
 
 
// Connecting Ethernet registers
eth_registers ethreg1
(
.DataIn(WB_DAT_I), .Address(WB_ADR_I[7:2]), .Rw(WB_WE_I),
.Cs(RegCs), .Clk(WB_CLK_I), .Reset(WB_RST_I),
.DataOut(RegDataOut), .r_DmaEn(r_DmaEn), .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_Iam(),
.r_Bro(), .r_NoPre(r_NoPre), .r_TxEn(r_TxEn),
.r_RxEn(r_RxEn), .Busy_IRQ(), .RxF_IRQ(),
.RxB_IRQ(), .TxE_IRQ(), .TxB_IRQ(),
.Busy_MASK(), .RxF_MASK(), .RxB_MASK(),
.TxE_MASK(), .TxB_MASK(), .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_RxBDAddress(r_RxBDAddress), .RX_BD_ADR_Wr(RX_BD_ADR_Wr)
);
 
 
 
wire [7:0] RxData;
wire RxValid;
wire RxStartFrm;
wire RxEndFrm;
 
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;
 
// Connecting MACControl
eth_maccontrol maccontrol1
(
.MTxClk(MTxClk_I), .TPauseRq(TPauseRq),
.TxPauseTV(TxPauseTV), .TxDataIn(TxData),
.TxStartFrmIn(TxStartFrm), .TxEndFrmIn(TxEndFrm),
.TxUsedDataIn(TxUsedDataIn), .TxDoneIn(TxDoneIn),
.TxAbortIn(TxAbortIn), .MRxClk(MRxClk_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_O : MRxDV_I & RxEnSync;
 
// Muxed MII Receive Error
assign MRxErr_Lb = r_LoopBck? MTxErr_O : MRxErr_I & RxEnSync;
 
// Muxed MII Receive Data
assign MRxD_Lb[3:0] = r_LoopBck? MTxD_O[3:0] : MRxD_I[3:0];
 
 
 
// Connecting TxEthMAC
eth_txethmac txethmac1
(
.MTxClk(MTxClk_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_O), .MTxD(MTxD_O),
.MTxErr(MTxErr_O), .TxUsedData(TxUsedDataIn), .TxDone(TxDoneIn),
.TxRetry(TxRetry), .TxAbort(TxAbortIn), .WillTransmit(WillTransmit),
.ResetCollision(ResetCollision)
);
 
 
 
 
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(MRxClk_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), .CrcHash(), .CrcHashGood(),
.Broadcast(), .Multicast(), .ByteCnt(RxByteCnt),
.ByteCntEq0(RxByteCntEq0), .ByteCntGreat2(RxByteCntGreat2), .ByteCntMaxFrame(RxByteCntMaxFrame),
.CrcError(RxCrcError), .StateIdle(RxStateIdle), .StatePreamble(RxStatePreamble),
.StateSFD(RxStateSFD), .StateData(RxStateData)
);
 
 
// MII Carrier Sense Synchronization
always @ (posedge MTxClk_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_I;
CarrierSense_Tx2 <= #Tp CarrierSense_Tx1;
end
end
 
assign TxCarrierSense = ~r_FullD & CarrierSense_Tx2;
 
 
// MII Collision Synchronization
always @ (posedge MTxClk_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_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 MRxClk_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_I;
RxCarrierSense <= #Tp CarrierSense_Rx1;
end
end
 
 
// Delayed WillTransmit
always @ (posedge MRxClk_I)
begin
WillTransmit_q <= #Tp WillTransmit;
WillTransmit_q2 <= #Tp WillTransmit_q;
end
 
 
assign Transmitting = ~r_FullD & WillTransmit_q2;
 
 
 
// Synchronized Receive Enable
always @ (posedge MRxClk_I or posedge r_Rst)
begin
if(r_Rst)
RxEnSync <= #Tp 1'b0;
else
if(~RxCarrierSense | RxCarrierSense & Transmitting)
RxEnSync <= #Tp r_RxEn;
end
 
 
 
 
// Connecting WishboneDMA module
eth_wishbonedma wbdma
(
.WB_CLK_I(WB_CLK_I), .WB_RST_I(WB_RST_I), .WB_DAT_I(WB_DAT_I),
.WB_DAT_O(DMA_WB_DAT_O),
 
// WISHBONE slave
.WB_ADR_I(WB_ADR_I), .WB_SEL_I(WB_SEL_I), .WB_WE_I(WB_WE_I),
.WB_CYC_I(WB_CYC_I_eth), .WB_STB_I(WB_STB_I_eth), .WB_ACK_O(BDAck),
.WB_REQ_O(WB_REQ_O), .WB_ACK_I(WB_ACK_I), .WB_ND_O(WB_ND_O),
.WB_RD_O(WB_RD_O),
 
//TX
.MTxClk(MTxClk_I), .TxStartFrm(TxStartFrm), .TxEndFrm(TxEndFrm),
.TxUsedData(TxUsedData), .TxData(TxData), .StatusIzTxEthMACModula(16'h0),
.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_RxBDAddress(r_RxBDAddress),
.r_DmaEn(r_DmaEn), .RX_BD_ADR_Wr(RX_BD_ADR_Wr),
 
//RX
.MRxClk(MRxClk_I), .RxData(RxData), .RxValid(RxValid),
.RxStartFrm(RxStartFrm), .RxEndFrm(RxEndFrm)
);
 
 
 
// Connecting MacStatus module
eth_macstatus macstatus1
(
.MRxClk(MRxClk_I), .Reset(r_Rst), .TransmitEnd(),
.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)
);
 
 
endmodule
/trunk/rtl/verilog/eth_transmitcontrol.v
0,0 → 1,277
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_transmitcontrol.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
/trunk/rtl/verilog/eth_macstatus.v
0,0 → 1,180
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_macstatus.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.1 2001/07/30 21:23:42 mohor
// Directory structure changed. Files checked and joind together.
//
//
//
//
//
 
`include "eth_timescale.v"
 
 
module eth_macstatus(
MRxClk, Reset, ReceivedLengthOK, ReceiveEnd, TransmitEnd, ReceivedPacketGood, RxCrcError,
MRxErr, MRxDV, RxStateSFD, RxStateData, RxStatePreamble, RxStateIdle, Transmitting,
RxByteCnt, RxByteCntEq0, RxByteCntGreat2, RxByteCntMaxFrame, ReceivedPauseFrm
);
 
 
 
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;
 
output ReceivedLengthOK;
output ReceiveEnd;
output ReceivedPacketGood;
output TransmitEnd;
 
reg ReceiveEnd;
 
reg LatchedCrcError;
reg LatchedMRxErr;
reg PreloadRxStatus;
reg [15:0] LatchedRxByteCnt;
 
wire TakeSample;
 
 
// Crc error
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedCrcError <=#Tp 1'b0;
else
begin
if(RxStateSFD)
LatchedCrcError <=#Tp 1'b0;
else
if(RxStateData[0])
LatchedCrcError <=#Tp RxCrcError & ~RxByteCntEq0;
end
end
 
 
// LatchedMRxErr
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedMRxErr <=#Tp 1'b0;
else
if(~MRxErr & MRxDV & RxStateIdle & ~Transmitting)
LatchedMRxErr <=#Tp 1'b0;
else
if(MRxErr & MRxDV & (RxStatePreamble | RxStateSFD | |RxStateData | RxStateIdle & ~Transmitting))
LatchedMRxErr <=#Tp 1'b1;
end
 
 
// ReceivedPacketGood
assign ReceivedPacketGood = ~LatchedCrcError & ~LatchedMRxErr;
 
 
// ReceivedLengthOK
assign ReceivedLengthOK = LatchedRxByteCnt[15:0] > 63 & LatchedRxByteCnt[15:0] < 1519;
 
 
 
// LatchedRxByteCnt[15:0]
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
LatchedRxByteCnt[15:0] <=#Tp 16'h0;
else
begin
if(RxStateSFD)
LatchedRxByteCnt[15:0] <=#Tp RxByteCnt[15:0];
else
if(RxStateData[0])
LatchedRxByteCnt[15:0] <=#Tp RxByteCnt[15:0];
end
end
 
 
 
// Time to take a sample
assign TakeSample = |RxStateData & ~MRxDV & RxByteCntGreat2 |
RxStateData[0] & MRxDV & RxByteCntMaxFrame;
 
 
// PreloadRxStatus
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
PreloadRxStatus <=#Tp 1'b0;
else
PreloadRxStatus <=#Tp TakeSample;
end
 
 
 
// ReceiveEnd
always @ (posedge MRxClk or posedge Reset)
begin
if(Reset)
ReceiveEnd <=#Tp 1'b0;
else
ReceiveEnd <=#Tp PreloadRxStatus;
end
 
 
endmodule
/trunk/rtl/verilog/eth_timescale.v
0,0 → 1,180
`timescale 1ns / 1ns
/trunk/rtl/verilog/eth_crc.v
0,0 → 1,131
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_crc.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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
/trunk/rtl/verilog/eth_registers.v
0,0 → 1,380
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_registers.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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/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 "eth_timescale.v"
 
 
module eth_registers( DataIn, Address, Rw, Cs, Clk, Reset, DataOut, r_DmaEn,
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, Busy_IRQ, RxF_IRQ,
RxB_IRQ, TxE_IRQ, TxB_IRQ, Busy_MASK, RxF_MASK, RxB_MASK, TxE_MASK,
TxB_MASK, 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_RxBDAddress, RX_BD_ADR_Wr
);
 
parameter Tp = 1;
 
input [31:0] DataIn;
input [5: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_DmaEn;
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 Busy_IRQ;
output RxF_IRQ;
output RxB_IRQ;
output TxE_IRQ;
output TxB_IRQ;
 
output Busy_MASK;
output RxF_MASK;
output RxB_MASK;
output TxE_MASK;
output TxB_MASK;
 
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_RxBDAddress;
 
output RX_BD_ADR_Wr;
 
 
 
wire Write = Cs & Rw;
wire Read = Cs & ~Rw;
 
wire MODER_Wr = (Address == `MODER_ADR) & Write;
wire INT_SOURCE_Wr = (Address == `INT_SOURCE_ADR) & Write;
wire INT_MASK_Wr = (Address == `INT_MASK_ADR) & Write;
wire IPGT_Wr = (Address == `IPGT_ADR) & Write;
wire IPGR1_Wr = (Address == `IPGR1_ADR) & Write;
wire IPGR2_Wr = (Address == `IPGR2_ADR) & Write;
wire PACKETLEN_Wr = (Address == `PACKETLEN_ADR) & Write;
wire COLLCONF_Wr = (Address == `COLLCONF_ADR) & Write;
 
wire CTRLMODER_Wr = (Address == `CTRLMODER_ADR) & Write;
wire MIIMODER_Wr = (Address == `MIIMODER_ADR) & Write;
wire MIICOMMAND_Wr = (Address == `MIICOMMAND_ADR) & Write;
wire MIIADDRESS_Wr = (Address == `MIIADDRESS_ADR) & Write;
wire MIITX_DATA_Wr = (Address == `MIITX_DATA_ADR) & Write;
wire MIIRX_DATA_Wr = UpdateMIIRX_DATAReg;
wire MIISTATUS_Wr = (Address == `MIISTATUS_ADR) & Write;
wire MAC_ADDR0_Wr = (Address == `MAC_ADDR0_ADR) & Write;
wire MAC_ADDR1_Wr = (Address == `MAC_ADDR1_ADR) & Write;
assign RX_BD_ADR_Wr = (Address == `RX_BD_ADR_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] RX_BD_ADROut;
 
eth_register #(32) MODER (.DataIn(DataIn), .DataOut(MODEROut), .Write(MODER_Wr), .Clk(Clk), .Reset(Reset), .Default(`MODER_DEF));
eth_register #(32) INT_SOURCE (.DataIn(DataIn), .DataOut(INT_SOURCEOut), .Write(INT_SOURCE_Wr), .Clk(Clk), .Reset(Reset), .Default(`INT_SOURCE_DEF));
eth_register #(32) INT_MASK (.DataIn(DataIn), .DataOut(INT_MASKOut), .Write(INT_MASK_Wr), .Clk(Clk), .Reset(Reset), .Default(`INT_MASK_DEF));
eth_register #(32) IPGT (.DataIn(DataIn), .DataOut(IPGTOut), .Write(IPGT_Wr), .Clk(Clk), .Reset(Reset), .Default(`IPGT_DEF));
eth_register #(32) IPGR1 (.DataIn(DataIn), .DataOut(IPGR1Out), .Write(IPGR1_Wr), .Clk(Clk), .Reset(Reset), .Default(`IPGR1_DEF));
eth_register #(32) IPGR2 (.DataIn(DataIn), .DataOut(IPGR2Out), .Write(IPGR2_Wr), .Clk(Clk), .Reset(Reset), .Default(`IPGR2_DEF));
eth_register #(32) PACKETLEN (.DataIn(DataIn), .DataOut(PACKETLENOut), .Write(PACKETLEN_Wr), .Clk(Clk), .Reset(Reset), .Default(`PACKETLEN_DEF));
eth_register #(32) COLLCONF (.DataIn(DataIn), .DataOut(COLLCONFOut), .Write(COLLCONF_Wr), .Clk(Clk), .Reset(Reset), .Default(`COLLCONF_DEF));
 
// CTRLMODER registers
wire [31:0] DefaultCtrlModer = `CTRLMODER_DEF;
assign CTRLMODEROut[31:3] = 29'h0;
eth_register #(3) CTRLMODER2 (.DataIn(DataIn[2:0]), .DataOut(CTRLMODEROut[2:0]), .Write(CTRLMODER_Wr), .Clk(Clk), .Reset(Reset), .Default(DefaultCtrlModer[2:0]));
// End: CTRLMODER registers
 
 
 
 
 
eth_register #(32) MIIMODER (.DataIn(DataIn), .DataOut(MIIMODEROut), .Write(MIIMODER_Wr), .Clk(Clk), .Reset(Reset), .Default(`MIIMODER_DEF));
 
assign MIICOMMANDOut[31:3] = 29'h0;
eth_register #(1) MIICOMMAND2 (.DataIn(DataIn[2]), .DataOut(MIICOMMANDOut[2]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset | WCtrlDataStart), .Default(1'b0));
eth_register #(1) MIICOMMAND1 (.DataIn(DataIn[1]), .DataOut(MIICOMMANDOut[1]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset | RStatStart), .Default(1'b0));
eth_register #(1) MIICOMMAND0 (.DataIn(DataIn[0]), .DataOut(MIICOMMANDOut[0]), .Write(MIICOMMAND_Wr), .Clk(Clk), .Reset(Reset), .Default(1'b0));
 
eth_register #(32) MIIADDRESS (.DataIn(DataIn), .DataOut(MIIADDRESSOut), .Write(MIIADDRESS_Wr), .Clk(Clk), .Reset(Reset), .Default(`MIIADDRESS_DEF));
eth_register #(32) MIITX_DATA (.DataIn(DataIn), .DataOut(MIITX_DATAOut), .Write(MIITX_DATA_Wr), .Clk(Clk), .Reset(Reset), .Default(`MIITX_DATA_DEF));
eth_register #(32) MIIRX_DATA (.DataIn({16'h0, Prsd}), .DataOut(MIIRX_DATAOut), .Write(MIIRX_DATA_Wr), .Clk(Clk), .Reset(Reset), .Default(`MIIRX_DATA_DEF));
//eth_register #(32) MIISTATUS (.DataIn(DataIn), .DataOut(MIISTATUSOut), .Write(MIISTATUS_Wr), .Clk(Clk), .Reset(Reset), .Default(`MIISTATUS_DEF));
eth_register #(32) MAC_ADDR0 (.DataIn(DataIn), .DataOut(MAC_ADDR0Out), .Write(MAC_ADDR0_Wr), .Clk(Clk), .Reset(Reset), .Default(`MAC_ADDR0_DEF));
eth_register #(32) MAC_ADDR1 (.DataIn(DataIn), .DataOut(MAC_ADDR1Out), .Write(MAC_ADDR1_Wr), .Clk(Clk), .Reset(Reset), .Default(`MAC_ADDR1_DEF));
 
assign RX_BD_ADROut[31:8] = 24'h0;
eth_register #(8) RX_BD_ADR (.DataIn(DataIn[7:0]), .DataOut(RX_BD_ADROut[7:0]), .Write(RX_BD_ADR_Wr), .Clk(Clk), .Reset(Reset), .Default(`RX_BD_ADR_DEF));
 
 
reg LinkFailRegister;
wire ResetLinkFailRegister = Address == `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
RX_BD_ADROut)
begin
if(Read) // read
begin
case(Address)
`MODER_ADR : DataOut<=MODEROut;
`INT_SOURCE_ADR : DataOut<=INT_SOURCEOut;
`INT_MASK_ADR : DataOut<=INT_MASKOut;
`IPGT_ADR : DataOut<=IPGTOut;
`IPGR1_ADR : DataOut<=IPGR1Out;
`IPGR2_ADR : DataOut<=IPGR2Out;
`PACKETLEN_ADR : DataOut<=PACKETLENOut;
`COLLCONF_ADR : DataOut<=COLLCONFOut;
`CTRLMODER_ADR : DataOut<=CTRLMODEROut;
`MIIMODER_ADR : DataOut<=MIIMODEROut;
`MIICOMMAND_ADR : DataOut<=MIICOMMANDOut;
`MIIADDRESS_ADR : DataOut<=MIIADDRESSOut;
`MIITX_DATA_ADR : DataOut<=MIITX_DATAOut;
`MIIRX_DATA_ADR : DataOut<=MIIRX_DATAOut;
`MIISTATUS_ADR : DataOut<=MIISTATUSOut;
`MAC_ADDR0_ADR : DataOut<=MAC_ADDR0Out;
`MAC_ADDR1_ADR : DataOut<=MAC_ADDR1Out;
`RX_BD_ADR_ADR : DataOut<=RX_BD_ADROut;
default: DataOut<=32'h0;
endcase
end
else
DataOut<=32'h0;
end
 
 
assign r_DmaEn = MODEROut[17];
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 Busy_IRQ = INT_SOURCEOut[4];
assign RxF_IRQ = INT_SOURCEOut[3];
assign RxB_IRQ = INT_SOURCEOut[2];
assign TxE_IRQ = INT_SOURCEOut[1];
assign TxB_IRQ = INT_SOURCEOut[0];
 
assign Busy_MASK = INT_MASKOut[4];
assign RxF_MASK = INT_MASKOut[3];
assign RxB_MASK = INT_MASKOut[2];
assign TxE_MASK = INT_MASKOut[1];
assign TxB_MASK = INT_MASKOut[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:3]= 5'h0 ;
assign MIISTATUSOut[2] = 1'b0;
assign MIISTATUSOut[1] = 1'b0;
assign MIISTATUSOut[0] = LinkFailRegister ;
 
assign r_MAC[31:0] = MAC_ADDR0Out[31:0];
assign r_MAC[47:32] = MAC_ADDR1Out[15:0];
 
assign r_RxBDAddress[7:0] = RX_BD_ADROut[7:0];
 
 
endmodule
/trunk/rtl/verilog/eth_rxstatem.v
0,0 → 1,172
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_rxstatem.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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 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
/trunk/rtl/verilog/eth_txstatem.v
0,0 → 1,260
//////////////////////////////////////////////////////////////////////
//// ////
//// eth_txstatem.v ////
//// ////
//// This file is part of the Ethernet IP core project ////
//// http://www.opencores.org/cores/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.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 "eth_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

powered by: WebSVN 2.1.0

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