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_ethernettop.v
File deleted
/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/rxethmac.v
File deleted
/trunk/rtl/verilog/rxstatem.v
File deleted
/trunk/rtl/verilog/txethmac.v
File deleted
/trunk/rtl/verilog/macstatus.v
File deleted
/trunk/rtl/verilog/ethregisters.v
File deleted
/trunk/rtl/verilog/transmitcontrol.v
File deleted
/trunk/rtl/verilog/miim.v
File deleted
/trunk/rtl/verilog/outputcontrol.v
File deleted
/trunk/rtl/verilog/crc.v
File deleted
/trunk/rtl/verilog/receivecontrol.v
File deleted
/trunk/rtl/verilog/maccontrol.v
File deleted
/trunk/rtl/verilog/ethdefines.v
File deleted
/trunk/rtl/verilog/counters.v
File deleted
/trunk/rtl/verilog/random.v
File deleted
/trunk/rtl/verilog/shiftreg.v
File deleted
/trunk/rtl/verilog/wishbonedma.v
File deleted
/trunk/rtl/verilog/rxcounters.v
File deleted
/trunk/rtl/verilog/clockgen.v
File deleted
/trunk/rtl/verilog/ethernettop.v
File deleted
/trunk/rtl/verilog/statem.v
File deleted
/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 |