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.1 2007-03-20 17:50:56 sithglan
47 // Revision 1.7 2005/03/21 20:07:18 igorm
48 // Some small fixes + some troubles fixed.
50 // Revision 1.6 2005/02/21 12:48:07 igorm
53 // Revision 1.5 2003/05/16 10:08:27 mohor
54 // Busy was set 2 cycles too late. Reported by Dennis Scott.
56 // Revision 1.4 2002/08/14 18:32:10 mohor
57 // - Busy signal was not set on time when scan status operation was performed
58 // and clock was divided with more than 2.
59 // - Nvalid remains valid two more clocks (was previously cleared too soon).
61 // Revision 1.3 2002/01/23 10:28:16 mohor
62 // Link in the header changed.
64 // Revision 1.2 2001/10/19 08:43:51 mohor
65 // eth_timescale.v changed to timescale.v This is done because of the
66 // simulation of the few cores in a one joined project.
68 // Revision 1.1 2001/08/06 14:44:29 mohor
69 // A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
70 // Include files fixed to contain no path.
71 // File names and module names changed ta have a eth_ prologue in the name.
72 // File eth_timescale.v is used to define timescale
73 // All pin names on the top module are changed to contain _I, _O or _OE at the end.
74 // Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
75 // and Mdo_OE. The bidirectional signal must be created on the top level. This
76 // is done due to the ASIC tools.
78 // Revision 1.2 2001/08/02 09:25:31 mohor
79 // Unconnected signals are now connected.
81 // Revision 1.1 2001/07/30 21:23:42 mohor
82 // Directory structure changed. Files checked and joind together.
84 // Revision 1.3 2001/06/01 22:28:56 mohor
85 // This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
89 `include "timescale.v"
119 input Clk; // Host Clock
120 input Reset; // General Reset
121 input [7:0] Divider; // Divider for the host clock
122 input [15:0] CtrlData; // Control Data (to be written to the PHY reg.)
123 input [4:0] Rgad; // Register Address (within the PHY)
124 input [4:0] Fiad; // PHY Address
125 input NoPre; // No Preamble (no 32-bit preamble)
126 input WCtrlData; // Write Control Data operation
127 input RStat; // Read Status operation
128 input ScanStat; // Scan Status operation
129 input Mdi; // MII Management Data In
131 output Mdc; // MII Management Data Clock
132 output Mdo; // MII Management Data Output
133 output MdoEn; // MII Management Data Output Enable
134 output Busy; // Busy Signal
135 output LinkFail; // Link Integrity Signal
136 output Nvalid; // Invalid Status (qualifier for the valid scan result)
138 output [15:0] Prsd; // Read Status Data (data read from the PHY)
140 output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register
141 output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register
142 output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
148 reg EndBusy_d; // Pre-end Busy signal
149 reg EndBusy; // End Busy signal (stops the operation in progress)
151 reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle
152 reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles
153 reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles
154 reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected)
155 reg WCtrlDataStart_q;
156 reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle
157 reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles
159 reg RStat_q1; // Read Status operation delayed 1 Clk cycle
160 reg RStat_q2; // Read Status operation delayed 2 Clk cycles
161 reg RStat_q3; // Read Status operation delayed 3 Clk cycles
162 reg RStatStart; // Start Read Status Command (positive edge detected)
163 reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle
164 reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles
166 reg ScanStat_q1; // Scan Status operation delayed 1 cycle
167 reg ScanStat_q2; // Scan Status operation delayed 2 cycles
168 reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn
170 wire WriteDataOp; // Write Data Operation (positive edge detected)
171 wire ReadStatusOp; // Read Status Operation (positive edge detected)
172 wire ScanStatusOp; // Scan Status Operation (positive edge detected)
173 wire StartOp; // Start Operation (start of any of the preceding operations)
174 wire EndOp; // End of Operation
176 reg InProgress; // Operation in progress
177 reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle
178 reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles
179 reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles
181 reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress)
182 reg [6:0] BitCounter; // Bit Counter
185 wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
186 wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises.
187 wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal
194 reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register
196 reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
202 // Generation of the EndBusy signal. It is used for ending the MII Management operation.
203 always @ (posedge Clk or posedge Reset)
207 EndBusy_d <= #Tp 1'b0;
212 EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3;
213 EndBusy <= #Tp EndBusy_d;
218 // Update MII RX_DATA register
219 always @ (posedge Clk or posedge Reset)
222 UpdateMIIRX_DATAReg <= #Tp 0;
224 if(EndBusy & ~WCtrlDataStart_q)
225 UpdateMIIRX_DATAReg <= #Tp 1;
227 UpdateMIIRX_DATAReg <= #Tp 0;
232 // Generation of the delayed signals used for positive edge triggering.
233 always @ (posedge Clk or posedge Reset)
237 WCtrlData_q1 <= #Tp 1'b0;
238 WCtrlData_q2 <= #Tp 1'b0;
239 WCtrlData_q3 <= #Tp 1'b0;
241 RStat_q1 <= #Tp 1'b0;
242 RStat_q2 <= #Tp 1'b0;
243 RStat_q3 <= #Tp 1'b0;
245 ScanStat_q1 <= #Tp 1'b0;
246 ScanStat_q2 <= #Tp 1'b0;
247 SyncStatMdcEn <= #Tp 1'b0;
251 WCtrlData_q1 <= #Tp WCtrlData;
252 WCtrlData_q2 <= #Tp WCtrlData_q1;
253 WCtrlData_q3 <= #Tp WCtrlData_q2;
255 RStat_q1 <= #Tp RStat;
256 RStat_q2 <= #Tp RStat_q1;
257 RStat_q3 <= #Tp RStat_q2;
259 ScanStat_q1 <= #Tp ScanStat;
260 ScanStat_q2 <= #Tp ScanStat_q1;
262 SyncStatMdcEn <= #Tp ScanStat_q2;
267 // Generation of the Start Commands (Write Control Data or Read Status)
268 always @ (posedge Clk or posedge Reset)
272 WCtrlDataStart <= #Tp 1'b0;
273 WCtrlDataStart_q <= #Tp 1'b0;
274 RStatStart <= #Tp 1'b0;
280 WCtrlDataStart <= #Tp 1'b0;
281 RStatStart <= #Tp 1'b0;
285 if(WCtrlData_q2 & ~WCtrlData_q3)
286 WCtrlDataStart <= #Tp 1'b1;
287 if(RStat_q2 & ~RStat_q3)
288 RStatStart <= #Tp 1'b1;
289 WCtrlDataStart_q <= #Tp WCtrlDataStart;
295 // Generation of the Nvalid signal (indicates when the status is invalid)
296 always @ (posedge Clk or posedge Reset)
302 if(~InProgress_q2 & InProgress_q3)
308 if(ScanStat_q2 & ~SyncStatMdcEn)
314 // Signals used for the generation of the Operation signals (positive edge)
315 always @ (posedge Clk or posedge Reset)
319 WCtrlDataStart_q1 <= #Tp 1'b0;
320 WCtrlDataStart_q2 <= #Tp 1'b0;
322 RStatStart_q1 <= #Tp 1'b0;
323 RStatStart_q2 <= #Tp 1'b0;
325 InProgress_q1 <= #Tp 1'b0;
326 InProgress_q2 <= #Tp 1'b0;
327 InProgress_q3 <= #Tp 1'b0;
329 LatchByte0_d <= #Tp 1'b0;
330 LatchByte1_d <= #Tp 1'b0;
332 LatchByte <= #Tp 2'b00;
338 WCtrlDataStart_q1 <= #Tp WCtrlDataStart;
339 WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1;
341 RStatStart_q1 <= #Tp RStatStart;
342 RStatStart_q2 <= #Tp RStatStart_q1;
344 LatchByte[0] <= #Tp LatchByte0_d;
345 LatchByte[1] <= #Tp LatchByte1_d;
347 LatchByte0_d <= #Tp LatchByte0_d2;
348 LatchByte1_d <= #Tp LatchByte1_d2;
350 InProgress_q1 <= #Tp InProgress;
351 InProgress_q2 <= #Tp InProgress_q1;
352 InProgress_q3 <= #Tp InProgress_q2;
358 // Generation of the Operation signals
359 assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2;
360 assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2;
361 assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2;
362 assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp;
365 assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid;
368 // Generation of the InProgress signal (indicates when an operation is in progress)
369 // Generation of the WriteOp signal (indicates when a write is in progress)
370 always @ (posedge Clk or posedge Reset)
374 InProgress <= #Tp 1'b0;
384 WriteOp <= #Tp WriteDataOp;
385 InProgress <= #Tp 1'b1;
391 InProgress <= #Tp 1'b0;
401 // Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
402 always @ (posedge Clk or posedge Reset)
405 BitCounter[6:0] <= #Tp 7'h0;
412 if(NoPre & ( BitCounter == 7'h0 ))
413 BitCounter[6:0] <= #Tp 7'h21;
415 BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1;
418 BitCounter[6:0] <= #Tp 7'h0;
424 // Operation ends when the Bit Counter reaches 63
425 assign EndOp = BitCounter==63;
427 assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20)));
428 assign ByteSelect[1] = InProgress & (BitCounter == 7'h28);
429 assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30);
430 assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38);
433 // Latch Byte selects which part of Read Status Data is updated from the shift register
434 assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37;
435 assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F;
438 // Connecting the Clock Generator Module
439 eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc)
442 // Connecting the Shift Register Module
443 eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad),
444 .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte),
445 .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail)
448 // Connecting the Output Control Module
449 eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress),
450 .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre),
451 .Mdo(Mdo), .MdoEn(MdoEn)