* nios_env.sh - Cygwin fix, pick up from environment variables installation
[nios2ecos.git] / eth_ocm / eth_miim.v
blob21701278677e6c65c250284e4d0c18eb824654a3
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 //////////////////////////////////////////////////////////////////////
41 // CVS Revision History
43 // $Log: eth_miim.v,v $
44 // Revision 1.7 2005/03/21 20:07:18 igorm
45 // Some small fixes + some troubles fixed.
47 // Revision 1.6 2005/02/21 12:48:07 igorm
48 // Warning fixes.
50 // Revision 1.5 2003/05/16 10:08:27 mohor
51 // Busy was set 2 cycles too late. Reported by Dennis Scott.
53 // Revision 1.4 2002/08/14 18:32:10 mohor
54 // - Busy signal was not set on time when scan status operation was performed
55 // and clock was divided with more than 2.
56 // - Nvalid remains valid two more clocks (was previously cleared too soon).
58 // Revision 1.3 2002/01/23 10:28:16 mohor
59 // Link in the header changed.
61 // Revision 1.2 2001/10/19 08:43:51 mohor
62 // eth_timescale.v changed to timescale.v This is done because of the
63 // simulation of the few cores in a one joined project.
65 // Revision 1.1 2001/08/06 14:44:29 mohor
66 // A define FPGA added to select between Artisan RAM (for ASIC) and Block Ram (For Virtex).
67 // Include files fixed to contain no path.
68 // File names and module names changed ta have a eth_ prologue in the name.
69 // File eth_timescale.v is used to define timescale
70 // All pin names on the top module are changed to contain _I, _O or _OE at the end.
71 // Bidirectional signal MDIO is changed to three signals (Mdc_O, Mdi_I, Mdo_O
72 // and Mdo_OE. The bidirectional signal must be created on the top level. This
73 // is done due to the ASIC tools.
75 // Revision 1.2 2001/08/02 09:25:31 mohor
76 // Unconnected signals are now connected.
78 // Revision 1.1 2001/07/30 21:23:42 mohor
79 // Directory structure changed. Files checked and joind together.
81 // Revision 1.3 2001/06/01 22:28:56 mohor
82 // This files (MIIM) are fully working. They were thoroughly tested. The testbench is not updated.
86 `include "timescale.v"
89 module eth_miim
91 Clk,
92 Reset,
93 Divider,
94 NoPre,
95 CtrlData,
96 Rgad,
97 Fiad,
98 WCtrlData,
99 RStat,
100 ScanStat,
101 Mdi,
102 Mdo,
103 MdoEn,
104 Mdc,
105 Busy,
106 Prsd,
107 LinkFail,
108 Nvalid,
109 WCtrlDataStart,
110 RStatStart,
111 UpdateMIIRX_DATAReg
116 input Clk; // Host Clock
117 input Reset; // General Reset
118 input [7:0] Divider; // Divider for the host clock
119 input [15:0] CtrlData; // Control Data (to be written to the PHY reg.)
120 input [4:0] Rgad; // Register Address (within the PHY)
121 input [4:0] Fiad; // PHY Address
122 input NoPre; // No Preamble (no 32-bit preamble)
123 input WCtrlData; // Write Control Data operation
124 input RStat; // Read Status operation
125 input ScanStat; // Scan Status operation
126 input Mdi; // MII Management Data In
128 output Mdc; // MII Management Data Clock
129 output Mdo; // MII Management Data Output
130 output MdoEn; // MII Management Data Output Enable
131 output Busy; // Busy Signal
132 output LinkFail; // Link Integrity Signal
133 output Nvalid; // Invalid Status (qualifier for the valid scan result)
135 output [15:0] Prsd; // Read Status Data (data read from the PHY)
137 output WCtrlDataStart; // This signals resets the WCTRLDATA bit in the MIIM Command register
138 output RStatStart; // This signal resets the RSTAT BIT in the MIIM Command register
139 output UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
141 parameter Tp = 1;
144 reg Nvalid;
145 reg EndBusy_d; // Pre-end Busy signal
146 reg EndBusy; // End Busy signal (stops the operation in progress)
148 reg WCtrlData_q1; // Write Control Data operation delayed 1 Clk cycle
149 reg WCtrlData_q2; // Write Control Data operation delayed 2 Clk cycles
150 reg WCtrlData_q3; // Write Control Data operation delayed 3 Clk cycles
151 reg WCtrlDataStart; // Start Write Control Data Command (positive edge detected)
152 reg WCtrlDataStart_q;
153 reg WCtrlDataStart_q1; // Start Write Control Data Command delayed 1 Mdc cycle
154 reg WCtrlDataStart_q2; // Start Write Control Data Command delayed 2 Mdc cycles
156 reg RStat_q1; // Read Status operation delayed 1 Clk cycle
157 reg RStat_q2; // Read Status operation delayed 2 Clk cycles
158 reg RStat_q3; // Read Status operation delayed 3 Clk cycles
159 reg RStatStart; // Start Read Status Command (positive edge detected)
160 reg RStatStart_q1; // Start Read Status Command delayed 1 Mdc cycle
161 reg RStatStart_q2; // Start Read Status Command delayed 2 Mdc cycles
163 reg ScanStat_q1; // Scan Status operation delayed 1 cycle
164 reg ScanStat_q2; // Scan Status operation delayed 2 cycles
165 reg SyncStatMdcEn; // Scan Status operation delayed at least cycles and synchronized to MdcEn
167 wire WriteDataOp; // Write Data Operation (positive edge detected)
168 wire ReadStatusOp; // Read Status Operation (positive edge detected)
169 wire ScanStatusOp; // Scan Status Operation (positive edge detected)
170 wire StartOp; // Start Operation (start of any of the preceding operations)
171 wire EndOp; // End of Operation
173 reg InProgress; // Operation in progress
174 reg InProgress_q1; // Operation in progress delayed 1 Mdc cycle
175 reg InProgress_q2; // Operation in progress delayed 2 Mdc cycles
176 reg InProgress_q3; // Operation in progress delayed 3 Mdc cycles
178 reg WriteOp; // Write Operation Latch (When asserted, write operation is in progress)
179 reg [6:0] BitCounter; // Bit Counter
182 wire [3:0] ByteSelect; // Byte Select defines which byte (preamble, data, operation, etc.) is loaded and shifted through the shift register.
183 wire MdcEn; // MII Management Data Clock Enable signal is asserted for one Clk period before Mdc rises.
184 wire ShiftedBit; // This bit is output of the shift register and is connected to the Mdo signal
185 wire MdcEn_n;
187 wire LatchByte1_d2;
188 wire LatchByte0_d2;
189 reg LatchByte1_d;
190 reg LatchByte0_d;
191 reg [1:0] LatchByte; // Latch Byte selects which part of Read Status Data is updated from the shift register
193 reg UpdateMIIRX_DATAReg;// Updates MII RX_DATA register with read data
199 // Generation of the EndBusy signal. It is used for ending the MII Management operation.
200 always @ (posedge Clk or posedge Reset)
201 begin
202 if(Reset)
203 begin
204 EndBusy_d <= #Tp 1'b0;
205 EndBusy <= #Tp 1'b0;
207 else
208 begin
209 EndBusy_d <= #Tp ~InProgress_q2 & InProgress_q3;
210 EndBusy <= #Tp EndBusy_d;
215 // Update MII RX_DATA register
216 always @ (posedge Clk or posedge Reset)
217 begin
218 if(Reset)
219 UpdateMIIRX_DATAReg <= #Tp 0;
220 else
221 if(EndBusy & ~WCtrlDataStart_q)
222 UpdateMIIRX_DATAReg <= #Tp 1;
223 else
224 UpdateMIIRX_DATAReg <= #Tp 0;
229 // Generation of the delayed signals used for positive edge triggering.
230 always @ (posedge Clk or posedge Reset)
231 begin
232 if(Reset)
233 begin
234 WCtrlData_q1 <= #Tp 1'b0;
235 WCtrlData_q2 <= #Tp 1'b0;
236 WCtrlData_q3 <= #Tp 1'b0;
238 RStat_q1 <= #Tp 1'b0;
239 RStat_q2 <= #Tp 1'b0;
240 RStat_q3 <= #Tp 1'b0;
242 ScanStat_q1 <= #Tp 1'b0;
243 ScanStat_q2 <= #Tp 1'b0;
244 SyncStatMdcEn <= #Tp 1'b0;
246 else
247 begin
248 WCtrlData_q1 <= #Tp WCtrlData;
249 WCtrlData_q2 <= #Tp WCtrlData_q1;
250 WCtrlData_q3 <= #Tp WCtrlData_q2;
252 RStat_q1 <= #Tp RStat;
253 RStat_q2 <= #Tp RStat_q1;
254 RStat_q3 <= #Tp RStat_q2;
256 ScanStat_q1 <= #Tp ScanStat;
257 ScanStat_q2 <= #Tp ScanStat_q1;
258 if(MdcEn)
259 SyncStatMdcEn <= #Tp ScanStat_q2;
264 // Generation of the Start Commands (Write Control Data or Read Status)
265 always @ (posedge Clk or posedge Reset)
266 begin
267 if(Reset)
268 begin
269 WCtrlDataStart <= #Tp 1'b0;
270 WCtrlDataStart_q <= #Tp 1'b0;
271 RStatStart <= #Tp 1'b0;
273 else
274 begin
275 if(EndBusy)
276 begin
277 WCtrlDataStart <= #Tp 1'b0;
278 RStatStart <= #Tp 1'b0;
280 else
281 begin
282 if(WCtrlData_q2 & ~WCtrlData_q3)
283 WCtrlDataStart <= #Tp 1'b1;
284 if(RStat_q2 & ~RStat_q3)
285 RStatStart <= #Tp 1'b1;
286 WCtrlDataStart_q <= #Tp WCtrlDataStart;
289 end
292 // Generation of the Nvalid signal (indicates when the status is invalid)
293 always @ (posedge Clk or posedge Reset)
294 begin
295 if(Reset)
296 Nvalid <= #Tp 1'b0;
297 else
298 begin
299 if(~InProgress_q2 & InProgress_q3)
300 begin
301 Nvalid <= #Tp 1'b0;
303 else
304 begin
305 if(ScanStat_q2 & ~SyncStatMdcEn)
306 Nvalid <= #Tp 1'b1;
309 end
311 // Signals used for the generation of the Operation signals (positive edge)
312 always @ (posedge Clk or posedge Reset)
313 begin
314 if(Reset)
315 begin
316 WCtrlDataStart_q1 <= #Tp 1'b0;
317 WCtrlDataStart_q2 <= #Tp 1'b0;
319 RStatStart_q1 <= #Tp 1'b0;
320 RStatStart_q2 <= #Tp 1'b0;
322 InProgress_q1 <= #Tp 1'b0;
323 InProgress_q2 <= #Tp 1'b0;
324 InProgress_q3 <= #Tp 1'b0;
326 LatchByte0_d <= #Tp 1'b0;
327 LatchByte1_d <= #Tp 1'b0;
329 LatchByte <= #Tp 2'b00;
331 else
332 begin
333 if(MdcEn)
334 begin
335 WCtrlDataStart_q1 <= #Tp WCtrlDataStart;
336 WCtrlDataStart_q2 <= #Tp WCtrlDataStart_q1;
338 RStatStart_q1 <= #Tp RStatStart;
339 RStatStart_q2 <= #Tp RStatStart_q1;
341 LatchByte[0] <= #Tp LatchByte0_d;
342 LatchByte[1] <= #Tp LatchByte1_d;
344 LatchByte0_d <= #Tp LatchByte0_d2;
345 LatchByte1_d <= #Tp LatchByte1_d2;
347 InProgress_q1 <= #Tp InProgress;
348 InProgress_q2 <= #Tp InProgress_q1;
349 InProgress_q3 <= #Tp InProgress_q2;
352 end
355 // Generation of the Operation signals
356 assign WriteDataOp = WCtrlDataStart_q1 & ~WCtrlDataStart_q2;
357 assign ReadStatusOp = RStatStart_q1 & ~RStatStart_q2;
358 assign ScanStatusOp = SyncStatMdcEn & ~InProgress & ~InProgress_q1 & ~InProgress_q2;
359 assign StartOp = WriteDataOp | ReadStatusOp | ScanStatusOp;
361 // Busy
362 assign Busy = WCtrlData | WCtrlDataStart | RStat | RStatStart | SyncStatMdcEn | EndBusy | InProgress | InProgress_q3 | Nvalid;
365 // Generation of the InProgress signal (indicates when an operation is in progress)
366 // Generation of the WriteOp signal (indicates when a write is in progress)
367 always @ (posedge Clk or posedge Reset)
368 begin
369 if(Reset)
370 begin
371 InProgress <= #Tp 1'b0;
372 WriteOp <= #Tp 1'b0;
374 else
375 begin
376 if(MdcEn)
377 begin
378 if(StartOp)
379 begin
380 if(~InProgress)
381 WriteOp <= #Tp WriteDataOp;
382 InProgress <= #Tp 1'b1;
384 else
385 begin
386 if(EndOp)
387 begin
388 InProgress <= #Tp 1'b0;
389 WriteOp <= #Tp 1'b0;
398 // Bit Counter counts from 0 to 63 (from 32 to 63 when NoPre is asserted)
399 always @ (posedge Clk or posedge Reset)
400 begin
401 if(Reset)
402 BitCounter[6:0] <= #Tp 7'h0;
403 else
404 begin
405 if(MdcEn)
406 begin
407 if(InProgress)
408 begin
409 if(NoPre & ( BitCounter == 7'h0 ))
410 BitCounter[6:0] <= #Tp 7'h21;
411 else
412 BitCounter[6:0] <= #Tp BitCounter[6:0] + 1'b1;
414 else
415 BitCounter[6:0] <= #Tp 7'h0;
421 // Operation ends when the Bit Counter reaches 63
422 assign EndOp = BitCounter==63;
424 assign ByteSelect[0] = InProgress & ((NoPre & (BitCounter == 7'h0)) | (~NoPre & (BitCounter == 7'h20)));
425 assign ByteSelect[1] = InProgress & (BitCounter == 7'h28);
426 assign ByteSelect[2] = InProgress & WriteOp & (BitCounter == 7'h30);
427 assign ByteSelect[3] = InProgress & WriteOp & (BitCounter == 7'h38);
430 // Latch Byte selects which part of Read Status Data is updated from the shift register
431 assign LatchByte1_d2 = InProgress & ~WriteOp & BitCounter == 7'h37;
432 assign LatchByte0_d2 = InProgress & ~WriteOp & BitCounter == 7'h3F;
435 // Connecting the Clock Generator Module
436 eth_clockgen clkgen(.Clk(Clk), .Reset(Reset), .Divider(Divider[7:0]), .MdcEn(MdcEn), .MdcEn_n(MdcEn_n), .Mdc(Mdc)
439 // Connecting the Shift Register Module
440 eth_shiftreg shftrg(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .Mdi(Mdi), .Fiad(Fiad), .Rgad(Rgad),
441 .CtrlData(CtrlData), .WriteOp(WriteOp), .ByteSelect(ByteSelect), .LatchByte(LatchByte),
442 .ShiftedBit(ShiftedBit), .Prsd(Prsd), .LinkFail(LinkFail)
445 // Connecting the Output Control Module
446 eth_outputcontrol outctrl(.Clk(Clk), .Reset(Reset), .MdcEn_n(MdcEn_n), .InProgress(InProgress),
447 .ShiftedBit(ShiftedBit), .BitCounter(BitCounter), .WriteOp(WriteOp), .NoPre(NoPre),
448 .Mdo(Mdo), .MdoEn(MdoEn)
451 endmodule