1 //////////////////////////////////////////////////////////////////////
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_miim.v,v $
44 // Revision 1.3 2006/01/19 14:07:53 maverickist
45 // verification is complete.
47 // Revision 1.1.1.1 2005/12/13 01:51:44 Administrator
50 // Revision 1.4 2005/08/16 12:07:57 Administrator
53 // Revision 1.3 2005/05/19 07:04:29 Administrator
56 // Revision 1.2 2005/04/27 15:58:46 Administrator
59 // Revision 1.1.1.1 2004/12/15 06:38:54 Administrator
62 // Revision 1.5 2003/05/16 10:08:27 mohor
63 // Busy was set 2 cycles too late. Reported by Dennis Scott.
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).
70 // Revision 1.3 2002/01/23 10:28:16 mohor
71 // Link in the header changed.
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.
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.
87 // Revision 1.2 2001/08/02 09:25:31 mohor
88 // Unconnected signals are now connected.
90 // Revision 1.1 2001/07/30 21:23:42 mohor
91 // Directory structure changed. Files checked and joind together.
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.
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
138 output Mdc; // MII Management Data Clock
140 output Busy; // Busy Signal
141 output LinkFail; // Link Integrity Signal
142 output Nvalid; // Invalid Status (qualifier for the valid scan result)
144 output [15:0] Prsd; // Read Status Data (data read from the PHY)
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
154 reg EndBusy_d; // Pre-end Busy signal
155 reg EndBusy; // End Busy signal (stops the operation in progress)
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
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
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
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
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
187 reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress)
188 reg [6:0] BitCounter; // Bit Counter
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
201 reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register
203 reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
205 wire Mdo; // MII Management Data Output
206 wire MdoEn; // MII Management Data Output Enable
210 assign Mdio=MdoEn?Mdo:1'bz;
214 // Generation of the EndBusy signal. It is used for ending the MII Management operation.
215 always @ (posedge Clk or posedge Reset)
219 EndBusy_d <= #Tp 1'b0;
224 EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3;
225 EndBusy <= #Tp EndBusy_d;
230 // Update MII RX_DATA register
231 always @ (posedge Clk or posedge Reset)
234 UpdateMIIRX_DATAReg <= #Tp 0;
236 if(EndBusy & ~WCtrlDataStart_q)
237 UpdateMIIRX_DATAReg <= #Tp 1;
239 UpdateMIIRX_DATAReg <= #Tp 0;
244 // Generation of the delayed signals used for positive edge triggering.
245 always @ (posedge Clk or posedge Reset)
249 WCtrlData_q1 <= #Tp 1'b0;
250 WCtrlData_q2 <= #Tp 1'b0;
251 WCtrlData_q3 <= #Tp 1'b0;
253 RStat_q1 <= #Tp 1'b0;
254 RStat_q2 <= #Tp 1'b0;
255 RStat_q3 <= #Tp 1'b0;
257 ScanStat_q1 <= #Tp 1'b0;
258 ScanStat_q2 <= #Tp 1'b0;
259 SyncStatMdcEn <= #Tp 1'b0;
263 WCtrlData_q1 <= #Tp WCtrlData;
264 WCtrlData_q2 <= #Tp WCtrlData_q1;
265 WCtrlData_q3 <= #Tp WCtrlData_q2;
267 RStat_q1 <= #Tp RStat;
268 RStat_q2 <= #Tp RStat_q1;
269 RStat_q3 <= #Tp RStat_q2;
271 ScanStat_q1 <= #Tp ScanStat;
272 ScanStat_q2 <= #Tp ScanStat_q1;
274 SyncStatMdcEn <= #Tp ScanStat_q2;
279 // Generation of the Start Commands (Write Control Data or Read Status)
280 always @ (posedge Clk or posedge Reset)
284 WCtrlDataStart <= #Tp 1'b0;
285 WCtrlDataStart_q <= #Tp 1'b0;
286 RStatStart <= #Tp 1'b0;
292 WCtrlDataStart <= #Tp 1'b0;
293 RStatStart <= #Tp 1'b0;
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;
307 // Generation of the Nvalid signal (indicates when the status is invalid)
308 always @ (posedge Clk or posedge Reset)
314 if(~InProgress_q2 & InProgress_q3)
320 if(ScanStat_q2 & ~SyncStatMdcEn)
326 // Signals used for the generation of the Operation signals (positive edge)
327 always @ (posedge Clk or posedge Reset)
331 WCtrlDataStart_q1 <= #Tp 1'b0;
332 WCtrlDataStart_q2 <= #Tp 1'b0;
334 RStatStart_q1 <= #Tp 1'b0;
335 RStatStart_q2 <= #Tp 1'b0;
337 InProgress_q1 <= #Tp 1'b0;
338 InProgress_q2 <= #Tp 1'b0;
339 InProgress_q3 <= #Tp 1'b0;
341 LatchByte0_d <= #Tp 1'b0;
342 LatchByte1_d <= #Tp 1'b0;
344 LatchByte <= #Tp 2'b00;
350 WCtrlDataStart_q1 <= #Tp WCtrlDataStart;
351 WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1;
353 RStatStart_q1 <= #Tp RStatStart;
354 RStatStart_q2 <= #Tp RStatStart_q1;
356 LatchByte[0] <= #Tp LatchByte0_d;
357 LatchByte[1] <= #Tp LatchByte1_d;
359 LatchByte0_d <= #Tp LatchByte0_d2;
360 LatchByte1_d <= #Tp LatchByte1_d2;
362 InProgress_q1 <= #Tp InProgress;
363 InProgress_q2 <= #Tp InProgress_q1;
364 InProgress_q3 <= #Tp InProgress_q2;
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;
378 always @ (posedge Clk or posedge Reset)
381 else if(WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid)
386 //assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid;
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)
395 InProgress <= #Tp 1'b0;
405 WriteOp <= #Tp WriteDataOp;
406 InProgress <= #Tp 1'b1;
412 InProgress <= #Tp 1'b0;
422 // Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
423 always @ (posedge Clk or posedge Reset)
426 BitCounter[6:0] <= #Tp 7'h0;
433 if(NoPre & ( BitCounter == 7'h0 ))
434 BitCounter[6:0] <= #Tp 7'h21;
436 BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1;
439 BitCounter[6:0] <= #Tp 7'h0;
445 // Operation ends when the Bit Counter reaches 63
446 assign EndOp = BitCounter==63;
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);
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;
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)
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)
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)