remove debugging code
[debian/gnuradio] / usrp2 / fpga / opencores / ethernet_tri_mode / rtl / verilog / eth_miim.v
1 //////////////////////////////////////////////////////////////////////
2 ////                                                              ////
3 ////  eth_miim.v                                                  ////
4 ////                                                              ////
5 ////  This file is part of the Ethernet IP core project           ////
6 ////  http://www.opencores.org/projects/ethmac/                   ////
7 ////                                                              ////
8 ////  Author(s):                                                  ////
9 ////      - Igor Mohor (igorM@opencores.org)                      ////
10 ////                                                              ////
11 ////  All additional information is avaliable in the Readme.txt   ////
12 ////  file.                                                       ////
13 ////                                                              ////
14 //////////////////////////////////////////////////////////////////////
15 ////                                                              ////
16 //// Copyright (C) 2001 Authors                                   ////
17 ////                                                              ////
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. ////
22 ////                                                              ////
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.                                               ////
28 ////                                                              ////
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 ////
33 //// details.                                                     ////
34 ////                                                              ////
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                     ////
38 ////                                                              ////
39 //////////////////////////////////////////////////////////////////////
40 //
41 // CVS Revision History
42 //
43 // $Log: eth_miim.v,v $
44 // Revision 1.3  2006/01/19 14:07:53  maverickist
45 // verification is complete.
46 //
47 // Revision 1.1.1.1  2005/12/13 01:51:44  Administrator
48 // no message
49 //
50 // Revision 1.4  2005/08/16 12:07:57  Administrator
51 // no message
52 //
53 // Revision 1.3  2005/05/19 07:04:29  Administrator
54 // no message
55 //
56 // Revision 1.2  2005/04/27 15:58:46  Administrator
57 // no message
58 //
59 // Revision 1.1.1.1  2004/12/15 06:38:54  Administrator
60 // no message
61 //
62 // Revision 1.5  2003/05/16 10:08:27  mohor
63 // Busy was set 2 cycles too late. Reported by Dennis Scott.
64 //
65 // Revision 1.4  2002/08/14 18:32:10  mohor
66 // - Busy signal was not set on time when scan status operation was performed
67 // and clock was divided with more than 2.
68 // - Nvalid remains valid two more clocks (was previously cleared too soon).
69 //
70 // Revision 1.3  2002/01/23 10:28:16  mohor
71 // Link in the header changed.
72 //
73 // Revision 1.2  2001/10/19 08:43:51  mohor
74 // eth_timescale.v changed to timescale.v This is done because of the
75 // simulation of the few cores in a one joined project.
76 //
77 // Revision 1.1  2001/08/06 14:44:29  mohor
78 // A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
79 // Include files fixed to contain no path.
80 // File names and module names changed ta have a eth_ prologue in the name.
81 // File eth_timescale.v is used to define timescale
82 // All pin names on the top module are changed to contain _I, _O or _OE at the end.
83 // Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
84 // and Mdo_OE. The bidirectional signal must be created on the top level. This
85 // is done due to the ASIC tools.
86 //
87 // Revision 1.2  2001/08/02 09:25:31  mohor
88 // Unconnected signals are now connected.
89 //
90 // Revision 1.1  2001/07/30 21:23:42  mohor
91 // Directory structure changed. Files checked and joind together.
92 //
93 // Revision 1.3  2001/06/01 22:28:56  mohor
94 // This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
95 //
96 //
97
98 `timescale 1ns/10ps
99
100
101 module eth_miim
102 (
103   Clk,
104   Reset,
105   Divider,
106   NoPre,
107   CtrlData,
108   Rgad,
109   Fiad,
110   WCtrlData,
111   RStat,
112   ScanStat,
113   Mdio,
114   Mdc,
115   Busy,
116   Prsd,
117   LinkFail,
118   Nvalid,
119   WCtrlDataStart,
120   RStatStart,
121   UpdateMIIRX_DATAReg
122 );
123
124
125
126 input         Clk;                // Host Clock
127 input         Reset;              // General Reset
128 input   [7:0] Divider;            // Divider for the host clock
129 input  [15:0] CtrlData;           // Control Data (to be written to the PHY reg.)
130 input   [4:0] Rgad;               // Register Address (within the PHY)
131 input   [4:0] Fiad;               // PHY Address
132 input         NoPre;              // No Preamble (no 32-bit preamble)
133 input         WCtrlData;          // Write Control Data operation
134 input         RStat;              // Read Status operation
135 input         ScanStat;           // Scan Status operation
136 inout         Mdio;                // MII Management Data In
137
138 output        Mdc;                // MII Management Data Clock
139
140 output        Busy;               // Busy Signal
141 output        LinkFail;           // Link Integrity Signal
142 output        Nvalid;             // Invalid Status (qualifier for the valid scan result)
143
144 output [15:0] Prsd;               // Read Status Data (data read from the PHY)
145
146 output        WCtrlDataStart;     // This signals resets the WCTRLDATA bit in the MIIM Command register
147 output        RStatStart;         // This signal resets the RSTAT BIT in the MIIM Command register
148 output        UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
149
150 parameter Tp = 1;
151
152
153 reg           Nvalid;
154 reg           EndBusy_d;          // Pre-end Busy signal
155 reg           EndBusy;            // End Busy signal (stops the operation in progress)
156
157 reg           WCtrlData_q1;       // Write Control Data operation delayed 1 Clk cycle
158 reg           WCtrlData_q2;       // Write Control Data operation delayed 2 Clk cycles
159 reg           WCtrlData_q3;       // Write Control Data operation delayed 3 Clk cycles
160 reg           WCtrlDataStart;     // Start Write Control Data Command (positive edge detected)
161 reg           WCtrlDataStart_q;
162 reg           WCtrlDataStart_q1;  // Start Write Control Data Command delayed 1 Mdc cycle
163 reg           WCtrlDataStart_q2;  // Start Write Control Data Command delayed 2 Mdc cycles
164
165 reg           RStat_q1;           // Read Status operation delayed 1 Clk cycle
166 reg           RStat_q2;           // Read Status operation delayed 2 Clk cycles
167 reg           RStat_q3;           // Read Status operation delayed 3 Clk cycles
168 reg           RStatStart;         // Start Read Status Command (positive edge detected)
169 reg           RStatStart_q1;      // Start Read Status Command delayed 1 Mdc cycle
170 reg           RStatStart_q2;      // Start Read Status Command delayed 2 Mdc cycles
171
172 reg           ScanStat_q1;        // Scan Status operation delayed 1 cycle
173 reg           ScanStat_q2;        // Scan Status operation delayed 2 cycles
174 reg           SyncStatMdcEn;      // Scan Status operation delayed at least cycles and synchronized to MdcEn
175
176 wire          WriteDataOp;        // Write Data Operation (positive edge detected)
177 wire          ReadStatusOp;       // Read Status Operation (positive edge detected)
178 wire          ScanStatusOp;       // Scan Status Operation (positive edge detected)
179 wire          StartOp;            // Start Operation (start of any of the preceding operations)
180 wire          EndOp;              // End of Operation
181
182 reg           InProgress;         // Operation in progress
183 reg           InProgress_q1;      // Operation in progress delayed 1 Mdc cycle
184 reg           InProgress_q2;      // Operation in progress delayed 2 Mdc cycles
185 reg           InProgress_q3;      // Operation in progress delayed 3 Mdc cycles
186
187 reg           WriteOp;            // Write Operation Latch (When asserted, write operation is in progress)
188 reg     [6:0] BitCounter;         // Bit Counter
189
190
191 wire          MdcFrame;           // Frame window for limiting the Mdc
192 wire    [3:0] ByteSelect;         // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
193 wire          MdcEn;              // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises.
194 wire          ShiftedBit;         // This bit is output of the shift register and is connected to the Mdo signal
195
196
197 wire          LatchByte1_d2;
198 wire          LatchByte0_d2;
199 reg           LatchByte1_d;
200 reg           LatchByte0_d;
201 reg     [1:0] LatchByte;          // Latch Byte selects which part of Read Status Data is updated from the shift register
202
203 reg           UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
204
205 wire        Mdo;                // MII Management Data Output
206 wire        MdoEn;              // MII Management Data Output Enable
207 wire            Mdi;
208
209 assign  Mdi=Mdio;
210 assign  Mdio=MdoEn?Mdo:1'bz;
211
212
213
214 // Generation of the EndBusy signal. It is used for ending the MII Management operation.
215 always @ (posedge Clk or posedge Reset)
216 begin
217   if(Reset)
218     begin
219       EndBusy_d <= #Tp 1'b0;
220       EndBusy <= #Tp 1'b0;
221     end
222   else
223     begin
224       EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3;
225       EndBusy   <= #Tp EndBusy_d;
226     end
227 end
228
229
230 // Update MII RX_DATA register
231 always @ (posedge Clk or posedge Reset)
232 begin
233   if(Reset)
234     UpdateMIIRX_DATAReg <= #Tp 0;
235   else
236   if(EndBusy & ~WCtrlDataStart_q)
237     UpdateMIIRX_DATAReg <= #Tp 1;
238   else
239     UpdateMIIRX_DATAReg <= #Tp 0;    
240 end
241
242
243
244 // Generation of the delayed signals used for positive edge triggering.
245 always @ (posedge Clk or posedge Reset)
246 begin
247   if(Reset)
248     begin
249       WCtrlData_q1 <= #Tp 1'b0;
250       WCtrlData_q2 <= #Tp 1'b0;
251       WCtrlData_q3 <= #Tp 1'b0;
252       
253       RStat_q1 <= #Tp 1'b0;
254       RStat_q2 <= #Tp 1'b0;
255       RStat_q3 <= #Tp 1'b0;
256
257       ScanStat_q1  <= #Tp 1'b0;
258       ScanStat_q2  <= #Tp 1'b0;
259       SyncStatMdcEn <= #Tp 1'b0;
260     end
261   else
262     begin
263       WCtrlData_q1 <= #Tp WCtrlData;
264       WCtrlData_q2 <= #Tp WCtrlData_q1;
265       WCtrlData_q3 <= #Tp WCtrlData_q2;
266
267       RStat_q1 <= #Tp RStat;
268       RStat_q2 <= #Tp RStat_q1;
269       RStat_q3 <= #Tp RStat_q2;
270
271       ScanStat_q1  <= #Tp ScanStat;
272       ScanStat_q2  <= #Tp ScanStat_q1;
273       if(MdcEn)
274         SyncStatMdcEn  <= #Tp ScanStat_q2;
275     end
276 end
277
278
279 // Generation of the Start Commands (Write Control Data or Read Status)
280 always @ (posedge Clk or posedge Reset)
281 begin
282   if(Reset)
283     begin
284       WCtrlDataStart <= #Tp 1'b0;
285       WCtrlDataStart_q <= #Tp 1'b0;
286       RStatStart <= #Tp 1'b0;
287     end
288   else
289     begin
290       if(EndBusy)
291         begin
292           WCtrlDataStart <= #Tp 1'b0;
293           RStatStart <= #Tp 1'b0;
294         end
295       else
296         begin
297           if(WCtrlData_q2 & ~WCtrlData_q3)
298             WCtrlDataStart <= #Tp 1'b1;
299           if(RStat_q2 & ~RStat_q3)
300             RStatStart <= #Tp 1'b1;
301           WCtrlDataStart_q <= #Tp WCtrlDataStart;
302         end
303     end
304 end 
305
306
307 // Generation of the Nvalid signal (indicates when the status is invalid)
308 always @ (posedge Clk or posedge Reset)
309 begin
310   if(Reset)
311     Nvalid <= #Tp 1'b0;
312   else
313     begin
314       if(~InProgress_q2 & InProgress_q3)
315         begin
316           Nvalid <= #Tp 1'b0;
317         end
318       else
319         begin
320           if(ScanStat_q2  & ~SyncStatMdcEn)
321             Nvalid <= #Tp 1'b1;
322         end
323     end
324 end 
325
326 // Signals used for the generation of the Operation signals (positive edge)
327 always @ (posedge Clk or posedge Reset)
328 begin
329   if(Reset)
330     begin
331       WCtrlDataStart_q1 <= #Tp 1'b0;
332       WCtrlDataStart_q2 <= #Tp 1'b0;
333
334       RStatStart_q1 <= #Tp 1'b0;
335       RStatStart_q2 <= #Tp 1'b0;
336
337       InProgress_q1 <= #Tp 1'b0;
338       InProgress_q2 <= #Tp 1'b0;
339       InProgress_q3 <= #Tp 1'b0;
340
341           LatchByte0_d <= #Tp 1'b0;
342           LatchByte1_d <= #Tp 1'b0;
343
344           LatchByte <= #Tp 2'b00;
345     end
346   else
347     begin
348       if(MdcEn)
349         begin
350           WCtrlDataStart_q1 <= #Tp WCtrlDataStart;
351           WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1;
352
353           RStatStart_q1 <= #Tp RStatStart;
354           RStatStart_q2 <= #Tp RStatStart_q1;
355
356           LatchByte[0] <= #Tp LatchByte0_d;
357           LatchByte[1] <= #Tp LatchByte1_d;
358
359           LatchByte0_d <= #Tp LatchByte0_d2;
360           LatchByte1_d <= #Tp LatchByte1_d2;
361
362           InProgress_q1 <= #Tp InProgress;
363           InProgress_q2 <= #Tp InProgress_q1;
364           InProgress_q3 <= #Tp InProgress_q2;
365         end
366     end
367 end 
368
369
370 // Generation of the Operation signals
371 assign WriteDataOp  = WCtrlDataStart_q1 & ~WCtrlDataStart_q2;    
372 assign ReadStatusOp = RStatStart_q1     & ~RStatStart_q2;
373 assign ScanStatusOp = SyncStatMdcEn     & ~InProgress & ~InProgress_q1 & ~InProgress_q2;
374 assign StartOp      = WriteDataOp | ReadStatusOp | ScanStatusOp;
375
376 // Busy
377 reg             Busy;
378 always @ (posedge Clk or posedge Reset)
379         if (Reset)
380                 Busy    <=0;
381         else if(WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid)
382                 Busy    <=1;
383         else
384                 Busy    <=0;
385                 
386 //assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid;
387
388
389 // Generation of the InProgress signal (indicates when an operation is in progress)
390 // Generation of the WriteOp signal (indicates when a write is in progress)
391 always @ (posedge Clk or posedge Reset)
392 begin
393   if(Reset)
394     begin
395       InProgress <= #Tp 1'b0;
396       WriteOp <= #Tp 1'b0;
397     end
398   else
399     begin
400       if(MdcEn)
401         begin
402           if(StartOp)
403             begin
404               if(~InProgress)
405                 WriteOp <= #Tp WriteDataOp;
406               InProgress <= #Tp 1'b1;
407             end
408           else
409             begin
410               if(EndOp)
411                 begin
412                   InProgress <= #Tp 1'b0;
413                   WriteOp <= #Tp 1'b0;
414                 end
415             end
416         end
417     end
418 end
419
420
421
422 // Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
423 always @ (posedge Clk or posedge Reset)
424 begin
425   if(Reset)
426     BitCounter[6:0] <= #Tp 7'h0;
427   else
428     begin
429       if(MdcEn)
430         begin
431           if(InProgress)
432             begin
433               if(NoPre & ( BitCounter == 7'h0 ))
434                 BitCounter[6:0] <= #Tp 7'h21;
435               else
436                 BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1;
437             end
438           else
439             BitCounter[6:0] <= #Tp 7'h0;
440         end
441     end
442 end
443
444
445 // Operation ends when the Bit Counter reaches 63
446 assign EndOp = BitCounter==63;
447
448 assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20)));
449 assign ByteSelect[1] = InProgress & (BitCounter == 7'h28);
450 assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30);
451 assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38);
452
453
454 // Latch Byte selects which part of Read Status Data is updated from the shift register
455 assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37;
456 assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F;
457
458
459 // Connecting the Clock Generator Module
460 eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc) 
461                    );
462
463 // Connecting the Shift Register Module
464 eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad), 
465                     .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte), 
466                     .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail)
467                    );
468
469 // Connecting the Output Control Module
470 eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress), 
471                           .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre), 
472                           .Mdo(Mdo), .MdoEn(MdoEn)
473                          );
474
475 endmodule