1 //////////////////////////////////////////////////////////////////////
3 //// eth_receivecontrol.v ////
5 //// This file is part of the Ethernet IP core project ////
6 //// http://www.opencores.org/projects/ethmac/ ////
9 //// - Igor Mohor (igorM@opencores.org) ////
11 //// All additional information is avaliable in the Readme.txt ////
14 //////////////////////////////////////////////////////////////////////
16 //// Copyright (C) 2001 Authors ////
18 //// This source file may be used and distributed without ////
19 //// restriction provided that this copyright statement is not ////
20 //// removed from the file and that any derivative work contains ////
21 //// the original copyright notice and the associated disclaimer. ////
23 //// This source file is free software; you can redistribute it ////
24 //// and/or modify it under the terms of the GNU Lesser General ////
25 //// Public License as published by the Free Software Foundation; ////
26 //// either version 2.1 of the License, or (at your option) any ////
27 //// later version. ////
29 //// This source is distributed in the hope that it will be ////
30 //// useful, but WITHOUT ANY WARRANTY; without even the implied ////
31 //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
32 //// PURPOSE. See the GNU Lesser General Public License for more ////
35 //// You should have received a copy of the GNU Lesser General ////
36 //// Public License along with this source; if not, download it ////
37 //// from http://www.opencores.org/lgpl.shtml ////
39 //////////////////////////////////////////////////////////////////////
41 // CVS Revision History
43 // $Log: eth_receivecontrol.v,v $
44 // Revision 1.5 2003/01/22 13:49:26 tadejm
45 // When control packets were received, they were ignored in some cases.
47 // Revision 1.4 2002/11/22 01:57:06 mohor
48 // Rx Flow control fixed. CF flag added to the RX buffer descriptor. RxAbort
51 // Revision 1.3 2002/01/23 10:28:16 mohor
52 // Link in the header changed.
54 // Revision 1.2 2001/10/19 08:43:51 mohor
55 // eth_timescale.v changed to timescale.v This is done because of the
56 // simulation of the few cores in a one joined project.
58 // Revision 1.1 2001/08/06 14:44:29 mohor
59 // A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
60 // Include files fixed to contain no path.
61 // File names and module names changed ta have a eth_ prologue in the name.
62 // File eth_timescale.v is used to define timescale
63 // All pin names on the top module are changed to contain _I, _O or _OE at the end.
64 // Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
65 // and Mdo_OE. The bidirectional signal must be created on the top level. This
66 // is done due to the ASIC tools.
68 // Revision 1.1 2001/07/30 21:23:42 mohor
69 // Directory structure changed. Files checked and joind together.
71 // Revision 1.1 2001/07/03 12:51:54 mohor
72 // Initial release of the MAC Control module.
80 `include "timescale.v"
83 module eth_receivecontrol (MTxClk
, MRxClk
, TxReset
, RxReset
, RxData
, RxValid
, RxStartFrm
,
84 RxEndFrm
, RxFlow
, ReceiveEnd
, MAC
, DlyCrcEn
, TxDoneIn
,
85 TxAbortIn
, TxStartFrmOut
, ReceivedLengthOK
, ReceivedPacketGood
,
86 TxUsedDataOutDetected
, Pause
, ReceivedPauseFrm
, AddressOK
,
87 RxStatusWriteLatched_sync2
, r_PassAll
, SetPauseTimer
108 input ReceivedLengthOK
;
109 input ReceivedPacketGood
;
110 input TxUsedDataOutDetected
;
111 input RxStatusWriteLatched_sync2
;
115 output ReceivedPauseFrm
;
117 output SetPauseTimer
;
121 reg AddressOK
; // Multicast or unicast address detected
122 reg TypeLengthOK
; // Type/Length field contains 0x8808
123 reg DetectionWindow
; // Detection of the PAUSE frame is possible within this window
124 reg OpCodeOK
; // PAUSE opcode detected (0x0001)
127 reg [15:0] AssembledTimerValue
;
128 reg [15:0] LatchedTimerValue
;
129 reg ReceivedPauseFrm
;
130 reg ReceivedPauseFrmWAddr
;
131 reg PauseTimerEq0_sync1
;
132 reg PauseTimerEq0_sync2
;
133 reg [15:0] PauseTimer
;
137 wire [47:0] ReservedMulticast
; // 0x0180C2000001
138 wire [15:0] TypeLength
; // 0x8808
139 wire ResetByteCnt
; //
140 wire IncrementByteCnt
; //
141 wire ByteCntEq0
; // ByteCnt = 0
142 wire ByteCntEq1
; // ByteCnt = 1
143 wire ByteCntEq2
; // ByteCnt = 2
144 wire ByteCntEq3
; // ByteCnt = 3
145 wire ByteCntEq4
; // ByteCnt = 4
146 wire ByteCntEq5
; // ByteCnt = 5
147 wire ByteCntEq12
; // ByteCnt = 12
148 wire ByteCntEq13
; // ByteCnt = 13
149 wire ByteCntEq14
; // ByteCnt = 14
150 wire ByteCntEq15
; // ByteCnt = 15
151 wire ByteCntEq16
; // ByteCnt = 16
152 wire ByteCntEq17
; // ByteCnt = 17
153 wire ByteCntEq18
; // ByteCnt = 18
154 wire DecrementPauseTimer
; //
155 wire PauseTimerEq0
; //
156 wire ResetSlotTimer
; //
157 wire IncrementSlotTimer
; //
158 wire SlotFinished
; //
162 // Reserved multicast address and Type/Length for PAUSE control
163 assign ReservedMulticast
= 48'h0180C2000001
;
164 assign TypeLength
= 16'h8808
;
167 // Address Detection (Multicast or unicast)
168 always @ (posedge MRxClk
or posedge RxReset
)
171 AddressOK
<= #Tp
1'b0;
173 if(DetectionWindow
& ByteCntEq0
)
174 AddressOK
<= #Tp RxData
[7:0] == ReservedMulticast
[47:40] | RxData
[7:0] == MAC
[47:40];
176 if(DetectionWindow
& ByteCntEq1
)
177 AddressOK
<= #
Tp (RxData
[7:0] == ReservedMulticast
[39:32] | RxData
[7:0] == MAC
[39:32]) & AddressOK
;
179 if(DetectionWindow
& ByteCntEq2
)
180 AddressOK
<= #
Tp (RxData
[7:0] == ReservedMulticast
[31:24] | RxData
[7:0] == MAC
[31:24]) & AddressOK
;
182 if(DetectionWindow
& ByteCntEq3
)
183 AddressOK
<= #
Tp (RxData
[7:0] == ReservedMulticast
[23:16] | RxData
[7:0] == MAC
[23:16]) & AddressOK
;
185 if(DetectionWindow
& ByteCntEq4
)
186 AddressOK
<= #
Tp (RxData
[7:0] == ReservedMulticast
[15:8] | RxData
[7:0] == MAC
[15:8]) & AddressOK
;
188 if(DetectionWindow
& ByteCntEq5
)
189 AddressOK
<= #
Tp (RxData
[7:0] == ReservedMulticast
[7:0] | RxData
[7:0] == MAC
[7:0]) & AddressOK
;
192 AddressOK
<= #Tp
1'b0;
197 // TypeLengthOK (Type/Length Control frame detected)
198 always @ (posedge MRxClk
or posedge RxReset
)
201 TypeLengthOK
<= #Tp
1'b0;
203 if(DetectionWindow
& ByteCntEq12
)
204 TypeLengthOK
<= #Tp ByteCntEq12
& (RxData
[7:0] == TypeLength
[15:8]);
206 if(DetectionWindow
& ByteCntEq13
)
207 TypeLengthOK
<= #Tp ByteCntEq13
& (RxData
[7:0] == TypeLength
[7:0]) & TypeLengthOK
;
210 TypeLengthOK
<= #Tp
1'b0;
215 // Latch Control Frame Opcode
216 always @ (posedge MRxClk
or posedge RxReset
)
219 OpCodeOK
<= #Tp
1'b0;
222 OpCodeOK
<= #Tp
1'b0;
225 if(DetectionWindow
& ByteCntEq14
)
226 OpCodeOK
<= #Tp ByteCntEq14
& RxData
[7:0] == 8'h00
;
228 if(DetectionWindow
& ByteCntEq15
)
229 OpCodeOK
<= #Tp ByteCntEq15
& RxData
[7:0] == 8'h01
& OpCodeOK
;
234 // ReceivedPauseFrmWAddr (+Address Check)
235 always @ (posedge MRxClk
or posedge RxReset
)
238 ReceivedPauseFrmWAddr
<= #Tp
1'b0;
241 ReceivedPauseFrmWAddr
<= #Tp
1'b0;
243 if(ByteCntEq16
& TypeLengthOK
& OpCodeOK
& AddressOK
)
244 ReceivedPauseFrmWAddr
<= #Tp
1'b1;
249 // Assembling 16-bit timer value from two 8-bit data
250 always @ (posedge MRxClk
or posedge RxReset
)
253 AssembledTimerValue
[15:0] <= #Tp
16'h0
;
256 AssembledTimerValue
[15:0] <= #Tp
16'h0
;
259 if(DetectionWindow
& ByteCntEq16
)
260 AssembledTimerValue
[15:8] <= #Tp RxData
[7:0];
261 if(DetectionWindow
& ByteCntEq17
)
262 AssembledTimerValue
[7:0] <= #Tp RxData
[7:0];
267 // Detection window (while PAUSE detection is possible)
268 always @ (posedge MRxClk
or posedge RxReset
)
271 DetectionWindow
<= #Tp
1'b1;
274 DetectionWindow
<= #Tp
1'b0;
277 DetectionWindow
<= #Tp
1'b1;
282 // Latching Timer Value
283 always @ (posedge MRxClk
or posedge RxReset
)
286 LatchedTimerValue
[15:0] <= #Tp
16'h0
;
288 if(DetectionWindow
& ReceivedPauseFrmWAddr
& ByteCntEq18
)
289 LatchedTimerValue
[15:0] <= #Tp AssembledTimerValue
[15:0];
292 LatchedTimerValue
[15:0] <= #Tp
16'h0
;
297 // Delayed CEC counter
298 always @ (posedge MRxClk
or posedge RxReset
)
301 DlyCrcCnt
<= #Tp
3'h0
;
303 if(RxValid
& RxEndFrm
)
304 DlyCrcCnt
<= #Tp
3'h0
;
306 if(RxValid
& ~RxEndFrm
& ~DlyCrcCnt
[2])
307 DlyCrcCnt
<= #Tp DlyCrcCnt
+ 1'b1;
311 assign ResetByteCnt
= RxEndFrm
;
312 assign IncrementByteCnt
= RxValid
& DetectionWindow
& ~ByteCntEq18
& (~DlyCrcEn | DlyCrcEn
& DlyCrcCnt
[2]);
316 always @ (posedge MRxClk
or posedge RxReset
)
319 ByteCnt
[4:0] <= #Tp
5'h0
;
322 ByteCnt
[4:0] <= #Tp
5'h0
;
325 ByteCnt
[4:0] <= #Tp ByteCnt
[4:0] + 1'b1;
329 assign ByteCntEq0
= RxValid
& ByteCnt
[4:0] == 5'h0
;
330 assign ByteCntEq1
= RxValid
& ByteCnt
[4:0] == 5'h1
;
331 assign ByteCntEq2
= RxValid
& ByteCnt
[4:0] == 5'h2
;
332 assign ByteCntEq3
= RxValid
& ByteCnt
[4:0] == 5'h3
;
333 assign ByteCntEq4
= RxValid
& ByteCnt
[4:0] == 5'h4
;
334 assign ByteCntEq5
= RxValid
& ByteCnt
[4:0] == 5'h5
;
335 assign ByteCntEq12
= RxValid
& ByteCnt
[4:0] == 5'h0C
;
336 assign ByteCntEq13
= RxValid
& ByteCnt
[4:0] == 5'h0D
;
337 assign ByteCntEq14
= RxValid
& ByteCnt
[4:0] == 5'h0E
;
338 assign ByteCntEq15
= RxValid
& ByteCnt
[4:0] == 5'h0F
;
339 assign ByteCntEq16
= RxValid
& ByteCnt
[4:0] == 5'h10
;
340 assign ByteCntEq17
= RxValid
& ByteCnt
[4:0] == 5'h11
;
341 assign ByteCntEq18
= RxValid
& ByteCnt
[4:0] == 5'h12
& DetectionWindow
;
344 assign SetPauseTimer
= ReceiveEnd
& ReceivedPauseFrmWAddr
& ReceivedPacketGood
& ReceivedLengthOK
& RxFlow
;
345 assign DecrementPauseTimer
= SlotFinished
& |PauseTimer
;
349 always @ (posedge MRxClk
or posedge RxReset
)
352 PauseTimer
[15:0] <= #Tp
16'h0
;
355 PauseTimer
[15:0] <= #Tp LatchedTimerValue
[15:0];
357 if(DecrementPauseTimer
)
358 PauseTimer
[15:0] <= #Tp PauseTimer
[15:0] - 1'b1;
361 assign PauseTimerEq0
= ~(|PauseTimer
[15:0]);
365 // Synchronization of the pause timer
366 always @ (posedge MTxClk
or posedge TxReset
)
370 PauseTimerEq0_sync1
<= #Tp
1'b1;
371 PauseTimerEq0_sync2
<= #Tp
1'b1;
375 PauseTimerEq0_sync1
<= #Tp PauseTimerEq0
;
376 PauseTimerEq0_sync2
<= #Tp PauseTimerEq0_sync1
;
381 // Pause signal generation
382 always @ (posedge MTxClk
or posedge TxReset
)
387 if((TxDoneIn | TxAbortIn |
~TxUsedDataOutDetected
) & ~TxStartFrmOut
)
388 Pause
<= #Tp RxFlow
& ~PauseTimerEq0_sync2
;
392 // Divider2 is used for incrementing the Slot timer every other clock
393 always @ (posedge MRxClk
or posedge RxReset
)
396 Divider2
<= #Tp
1'b0;
398 if(|PauseTimer
[15:0] & RxFlow
)
399 Divider2
<= #Tp
~Divider2
;
401 Divider2
<= #Tp
1'b0;
405 assign ResetSlotTimer
= RxReset
;
406 assign IncrementSlotTimer
= Pause
& RxFlow
& Divider2
;
410 always @ (posedge MRxClk
or posedge RxReset
)
413 SlotTimer
[5:0] <= #Tp
6'h0
;
416 SlotTimer
[5:0] <= #Tp
6'h0
;
418 if(IncrementSlotTimer
)
419 SlotTimer
[5:0] <= #Tp SlotTimer
[5:0] + 1'b1;
423 assign SlotFinished
= &SlotTimer
[5:0] & IncrementSlotTimer
; // Slot is 512 bits (64 bytes)
427 // Pause Frame received
428 always @ (posedge MRxClk
or posedge RxReset
)
431 ReceivedPauseFrm
<=#Tp
1'b0;
433 if(RxStatusWriteLatched_sync2
& r_PassAll | ReceivedPauseFrm
& (~r_PassAll
))
434 ReceivedPauseFrm
<=#Tp
1'b0;
436 if(ByteCntEq16
& TypeLengthOK
& OpCodeOK
)
437 ReceivedPauseFrm
<=#Tp
1'b1;