Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / rx_mii_gmii.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: rx_mii_gmii.v
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35/*%W% %G%*/
36
37/*************************************************************************
38 *
39 * File Name : rx_mii_gmii
40 * Author Name : John Lo
41 * Description : txmac gmii interface logic
42 * Parent Module: xmac
43 * Child Module:
44 * Interface Mod:
45 * Date Created : 9/22/00
46 *
47 * Copyright (c) 2002, Sun Microsystems, Inc.
48 * Sun Proprietary and Confidential
49 *
50 * Modification :
51 *
52 * Synthesis Notes by loj: from hold_rxc -> g2x_rxc, hold_rxd -> g2x_rxd
53 * are signal changing clk domain. They are
54 * placed here to be able to close to each
55 * other to meet timing when synthesis/layout
56 * time comes.
57 *
58 *************************************************************************/
59
60`include "xmac.h"
61
62module rx_mii_gmii (
63 rx_nbclk,
64 rx_reset_nbclk,
65 hw_reset_rxnbclk,
66 rxfifo_full_nbclk,
67 rx_enable_nbclk,
68 // mgmii loopback signals
69 mgmii_txd,
70 mgmii_tx_en,
71 mgmii_tx_err,
72 mii_mode,
73 gmii_mode,
74 mii_or_gmii_mode,
75 loopback,
76 // rx gmii signals
77 gmii_rxd,
78 gmii_rx_dv,
79 gmii_rx_err,
80// outputs
81 inc_align_err_count_nbclk,
82 rx_heart_beat_timer,
83 rx_heart_beat_timer_reg,
84 hold_rxd,
85 hold_rx_dv,
86 hold_rx_err,
87 mgrlm_state
88 );
89
90 input rx_nbclk;
91 input rx_reset_nbclk;
92 input hw_reset_rxnbclk;
93 input rxfifo_full_nbclk;
94 input rx_enable_nbclk;
95 // mgmii loopback signals
96 input [`BYTE] mgmii_txd;
97 input mgmii_tx_en;
98 input mgmii_tx_err;
99 input mii_mode;
100 input gmii_mode;
101 input mii_or_gmii_mode;
102 input loopback;
103 // gmii signals
104 input [`BYTE] gmii_rxd;
105 input gmii_rx_dv;
106 input gmii_rx_err;
107// outputs
108 output inc_align_err_count_nbclk;
109 output [3:0] rx_heart_beat_timer; // to clock mux
110 output [3:0] rx_heart_beat_timer_reg;
111 output [63:0] hold_rxd;
112 output [7:0] hold_rx_dv;
113 output hold_rx_err;
114 output mgrlm_state;
115
116 reg [`BYTE] rxd_ilane7; // internal lane
117 reg [`BYTE] rxd_ilane6; // internal lane
118 reg [`BYTE] rxd_ilane5; // internal lane
119 reg [`BYTE] rxd_ilane4; // internal lane
120 reg [`BYTE] rxd_ilane3; // internal lane
121 reg [`BYTE] rxd_ilane2; // internal lane
122 reg [`BYTE] rxd_ilane1; // internal lane
123 reg [`BYTE] rxd_ilane0; // internal lane
124 reg [`NIB] rxd_ilaneX; // internal lane
125 reg rx_dv_ilane7;
126 reg rx_dv_ilane6;
127 reg rx_dv_ilane5;
128 reg rx_dv_ilane4;
129 reg rx_dv_ilane3;
130 reg rx_dv_ilane2;
131 reg rx_dv_ilane1;
132 reg rx_dv_ilane0;
133 reg rx_dv_ilane7a;
134 reg rx_dv_ilane6a;
135 reg rx_dv_ilane5a;
136 reg rx_dv_ilane4a;
137 reg rx_dv_ilane3a;
138 reg rx_dv_ilane2a;
139 reg rx_dv_ilane1a;
140 reg rx_dv_ilane0a;
141 reg rx_dv_ilaneX;
142 reg rx_err_ilane7;
143 reg rx_err_ilane6;
144 reg rx_err_ilane5;
145 reg rx_err_ilane4;
146 reg rx_err_ilane3;
147 reg rx_err_ilane2;
148 reg rx_err_ilane1;
149 reg rx_err_ilane0;
150 reg rx_err_ilane7a;
151 reg rx_err_ilane6a;
152 reg rx_err_ilane5a;
153 reg rx_err_ilane4a;
154 reg rx_err_ilane3a;
155 reg rx_err_ilane2a;
156 reg rx_err_ilane1a;
157 reg rx_err_ilane0a;
158 wire load_ok_state;
159
160// S = 8'hFB, T = 8'hFD, E = 8'hFE, I = 8'h07
161// in 802.3z pp-36A.2 shows PA => FB 55 55 55 55 55 55 D5 (big endian format)
162// ^
163// detect SFD logic
164// sfd is send out by rising edge clk.
165
166 wire rx_det_sfd;
167 wire rx_det_eop_lv;
168 wire adjust_rx_heart_beat; // should be a pulse
169 wire rx_heart_beat;
170 wire hw_reset_rxnbclk_lead;
171 wire d_hw_reset_rxnbclk;
172 wire [`BYTE] g_rxd;
173 wire g_rx_err;
174 wire g_rx_err_lv;
175 wire mg_rx_dv_trail;
176 wire [`BYTE] mg_rxd;
177 wire mg_rx_dv;
178 wire mg_rx_err;
179 wire [`BYTE] mg_rxd_mux;
180 wire mg_rx_dv_mux;
181 wire mg_rx_err_mux;
182 wire rx_dv_ilane0_lead,rx_dv_ilaneX_lead,sfd_win;
183
184
185 // vlint flag_net_has_no_load off
186 // vlint flag_dangling_net_within_module off
187 wire rx_dv_ilane0_trail;
188 wire rx_dv_ilaneX_trail;
189 wire mg_rx_dv_lead;
190 // vlint flag_dangling_net_within_module on
191 // vlint flag_net_has_no_load on
192
193/* ------------ sfd qulification logic -------------------------- */
194
195PlsGen2 rx_dv_ilane0_PlsGen2(.sig_in(rx_dv_ilane0),.clk(rx_nbclk),
196 .lead (rx_dv_ilane0_lead),
197 .trail (rx_dv_ilane0_trail));
198
199PlsGen2 rx_dv_ilaneX_PlsGen2(.sig_in(rx_dv_ilaneX),.clk(rx_nbclk),
200 .lead (rx_dv_ilaneX_lead),
201 .trail (rx_dv_ilaneX_trail));
202
203 wire set_sfd_win = gmii_mode ? rx_dv_ilane0_lead :
204 rx_dv_ilaneX_lead ;
205
206
207SRFF sfd_win_SRFF(.reset(rx_reset_nbclk),.clk(rx_nbclk),
208 .iSet(set_sfd_win),
209 .iRst(rx_det_sfd),
210 .oQ(sfd_win));
211
212/* ---------- Data path ----------------------------------------- */
213
214
215RegDff #(8) g_rxd_RegDff (.din(gmii_rxd), .clk(rx_nbclk),.qout(g_rxd));
216RegDff #(1) mg_rx_dv_RegDff (.din(gmii_rx_dv), .clk(rx_nbclk),.qout(mg_rx_dv));
217RegDff #(1) mg_rx_err_RegDff(.din(gmii_rx_err),.clk(rx_nbclk),.qout(g_rx_err));
218
219// Mainly to take care of the rx_err happend in pa time
220RS_FF g_rx_err_lv_RS_FF (.set(g_rx_err),
221 .rst(mg_rx_dv_trail),
222 .clk(rx_nbclk),
223 .reset(rx_reset_nbclk),
224 .qout(g_rx_err_lv));
225
226PlsGen2 mg_rx_dv_trail_PlsGen2(.sig_in(mg_rx_dv),
227 .clk(rx_nbclk),
228 .lead(mg_rx_dv_lead),
229 .trail(mg_rx_dv_trail));
230
231 assign mg_rx_err = mg_rx_dv & (g_rx_err | g_rx_err_lv);
232 assign mg_rxd = gmii_mode? g_rxd : {4'h0,g_rxd[`NIB]};
233 assign mg_rxd_mux = loopback ? mgmii_txd : mg_rxd;
234 assign mg_rx_dv_mux = loopback ? mgmii_tx_en : mg_rx_dv;
235 assign mg_rx_err_mux= loopback ? mgmii_tx_err : mg_rx_err;
236
237
238/* ---------- 1st stage: serial to paralle shifter --------------- */
239// rxd serial shifter
240// rxd shifting is achieved by using `NIB0 to `NIB1.
241// It is different from rx_dv which requires rx_dv_ilane?a.
242
243always @ (posedge rx_nbclk)
244 if (gmii_mode)
245 begin
246 rxd_ilane7 <= mg_rxd_mux[`BYTE];
247 rxd_ilane6 <= rxd_ilane7;
248 rxd_ilane5 <= rxd_ilane6;
249 rxd_ilane4 <= rxd_ilane5;
250 rxd_ilane3 <= rxd_ilane4;
251 rxd_ilane2 <= rxd_ilane3;
252 rxd_ilane1 <= rxd_ilane2;
253 rxd_ilane0 <= rxd_ilane1;
254 rxd_ilaneX <= 0;
255 end
256 else // 10/100M mode; mii_mode
257 begin // rxd nibble shifting is achieved by using `NIB0 to `NIB1.
258 rxd_ilane7[`NIB0] <= mg_rxd_mux[`NIB];
259 rxd_ilane7[`NIB1] <= rxd_ilane7[`NIB0];
260 rxd_ilane6[`NIB0] <= rxd_ilane7[`NIB1];
261 rxd_ilane6[`NIB1] <= rxd_ilane6[`NIB0];
262 rxd_ilane5[`NIB0] <= rxd_ilane6[`NIB1];
263 rxd_ilane5[`NIB1] <= rxd_ilane5[`NIB0];
264 rxd_ilane4[`NIB0] <= rxd_ilane5[`NIB1];
265 rxd_ilane4[`NIB1] <= rxd_ilane4[`NIB0];
266 rxd_ilane3[`NIB0] <= rxd_ilane4[`NIB1];
267 rxd_ilane3[`NIB1] <= rxd_ilane3[`NIB0];
268 rxd_ilane2[`NIB0] <= rxd_ilane3[`NIB1];
269 rxd_ilane2[`NIB1] <= rxd_ilane2[`NIB0];
270 rxd_ilane1[`NIB0] <= rxd_ilane2[`NIB1];
271 rxd_ilane1[`NIB1] <= rxd_ilane1[`NIB0];
272 rxd_ilane0[`NIB0] <= rxd_ilane1[`NIB1];
273 rxd_ilane0[`NIB1] <= rxd_ilane0[`NIB0];
274 rxd_ilaneX[`NIB] <= rxd_ilane0[`NIB1];
275 end
276
277// rx_dv serial shifter
278always @ (posedge rx_nbclk)
279 if (gmii_mode)
280 begin
281 rx_dv_ilane7 <= mg_rx_dv_mux;
282 rx_dv_ilane6 <= rx_dv_ilane7;
283 rx_dv_ilane5 <= rx_dv_ilane6;
284 rx_dv_ilane4 <= rx_dv_ilane5;
285 rx_dv_ilane3 <= rx_dv_ilane4;
286 rx_dv_ilane2 <= rx_dv_ilane3;
287 rx_dv_ilane1 <= rx_dv_ilane2;
288 rx_dv_ilane0 <= rx_dv_ilane1;
289 //
290 rx_dv_ilane7a <= 0;
291 rx_dv_ilane6a <= 0;
292 rx_dv_ilane5a <= 0;
293 rx_dv_ilane4a <= 0;
294 rx_dv_ilane3a <= 0;
295 rx_dv_ilane2a <= 0;
296 rx_dv_ilane1a <= 0;
297 rx_dv_ilane0a <= 0;
298 rx_dv_ilaneX <= 0; // laneX
299 end
300 else // mii_mode; 10/100Mhz mode
301 begin
302 rx_dv_ilane7a <= mg_rx_dv_mux ;
303 rx_dv_ilane7 <= rx_dv_ilane7a;
304 rx_dv_ilane6a <= rx_dv_ilane7 ;
305 rx_dv_ilane6 <= rx_dv_ilane6a;
306 rx_dv_ilane5a <= rx_dv_ilane6 ;
307 rx_dv_ilane5 <= rx_dv_ilane5a;
308 rx_dv_ilane4a <= rx_dv_ilane5 ;
309 rx_dv_ilane4 <= rx_dv_ilane4a;
310 rx_dv_ilane3a <= rx_dv_ilane4 ;
311 rx_dv_ilane3 <= rx_dv_ilane3a;
312 rx_dv_ilane2a <= rx_dv_ilane3 ;
313 rx_dv_ilane2 <= rx_dv_ilane2a;
314 rx_dv_ilane1a <= rx_dv_ilane2 ;
315 rx_dv_ilane1 <= rx_dv_ilane1a;
316 rx_dv_ilane0a <= rx_dv_ilane1 ;
317 rx_dv_ilane0 <= rx_dv_ilane0a;
318 rx_dv_ilaneX <= rx_dv_ilane0 ; // laneX
319 end
320
321// rx_err serial shifter
322always @ (posedge rx_nbclk)
323 if (gmii_mode)
324 begin // gmii_mode
325 rx_err_ilane7 <= mg_rx_err_mux;
326 rx_err_ilane6 <= rx_err_ilane7;
327 rx_err_ilane5 <= rx_err_ilane6;
328 rx_err_ilane4 <= rx_err_ilane5;
329 rx_err_ilane3 <= rx_err_ilane4;
330 rx_err_ilane2 <= rx_err_ilane3;
331 rx_err_ilane1 <= rx_err_ilane2;
332 rx_err_ilane0 <= rx_err_ilane1;
333 //
334 rx_err_ilane7a <= 0;
335 rx_err_ilane6a <= 0;
336 rx_err_ilane5a <= 0;
337 rx_err_ilane4a <= 0;
338 rx_err_ilane3a <= 0;
339 rx_err_ilane2a <= 0;
340 rx_err_ilane1a <= 0;
341 rx_err_ilane0a <= 0;
342 end
343 else
344 begin // mii_mode
345 rx_err_ilane7a <= mg_rx_err_mux ;
346 rx_err_ilane7 <= rx_err_ilane7a;
347 rx_err_ilane6a <= rx_err_ilane7 ;
348 rx_err_ilane6 <= rx_err_ilane6a;
349 rx_err_ilane5a <= rx_err_ilane6 ;
350 rx_err_ilane5 <= rx_err_ilane5a;
351 rx_err_ilane4a <= rx_err_ilane5 ;
352 rx_err_ilane4 <= rx_err_ilane4a;
353 rx_err_ilane3a <= rx_err_ilane4 ;
354 rx_err_ilane3 <= rx_err_ilane3a;
355 rx_err_ilane2a <= rx_err_ilane3 ;
356 rx_err_ilane2 <= rx_err_ilane2a;
357 rx_err_ilane1a <= rx_err_ilane2 ;
358 rx_err_ilane1 <= rx_err_ilane1a;
359 rx_err_ilane0a <= rx_err_ilane1 ;
360 rx_err_ilane0 <= rx_err_ilane0a;
361 end
362
363/* --- end of 1st stage: serial to paralle shifter --------------- */
364
365 wire [63:0] parallel_rxd = gmii_mode ?
366 (
367 load_ok_state ?
368 {rxd_ilane7,
369 rxd_ilane6,
370 rxd_ilane5,
371 rxd_ilane4,
372 rxd_ilane3,
373 rxd_ilane2,
374 rxd_ilane1,
375 rxd_ilane0} : 0
376 ) :
377 (
378 load_ok_state ?
379 {rxd_ilane7[`NIB0], // nibble swap
380 rxd_ilane7[`NIB1], // nibble swap
381 rxd_ilane6[`NIB0], // nibble swap
382 rxd_ilane6[`NIB1], // nibble swap
383 rxd_ilane5[`NIB0], // nibble swap
384 rxd_ilane5[`NIB1], // nibble swap
385 rxd_ilane4[`NIB0], // nibble swap
386 rxd_ilane4[`NIB1], // nibble swap
387 rxd_ilane3[`NIB0], // nibble swap
388 rxd_ilane3[`NIB1], // nibble swap
389 rxd_ilane2[`NIB0], // nibble swap
390 rxd_ilane2[`NIB1], // nibble swap
391 rxd_ilane1[`NIB0], // nibble swap
392 rxd_ilane1[`NIB1], // nibble swap
393 rxd_ilane0[`NIB0], // nibble swap
394 rxd_ilane0[`NIB1]} : 0
395 );
396
397 wire [`BYTE] parallel_rx_dv = load_ok_state ?
398 {rx_dv_ilane7,
399 rx_dv_ilane6,
400 rx_dv_ilane5,
401 rx_dv_ilane4,
402 rx_dv_ilane3,
403 rx_dv_ilane2,
404 rx_dv_ilane1,
405 rx_dv_ilane0} : 0;
406
407 wire parallel_rx_err = load_ok_state ?
408 (rx_err_ilane7 |
409 rx_err_ilane6 |
410 rx_err_ilane5 |
411 rx_err_ilane4 |
412 rx_err_ilane3 |
413 rx_err_ilane2 |
414 rx_err_ilane1 |
415 rx_err_ilane0 ) : 0;
416
417 wire inc_align_err_count_nbclk = load_ok_state & rx_heart_beat & mii_mode ?
418 ((rx_dv_ilane7 != rx_dv_ilane7a) |
419 (rx_dv_ilane6 != rx_dv_ilane6a) |
420 (rx_dv_ilane5 != rx_dv_ilane5a) |
421 (rx_dv_ilane4 != rx_dv_ilane4a) |
422 (rx_dv_ilane3 != rx_dv_ilane3a) |
423 (rx_dv_ilane2 != rx_dv_ilane2a) |
424 (rx_dv_ilane1 != rx_dv_ilane1a) |
425 (rx_dv_ilane0 != rx_dv_ilane0a) ) : 0;
426
427/* ---------- 2nd stage to hold the data: change clock domain --- */
428 wire [63:0] hold_rxd;
429 wire [7:0] hold_rx_dv;
430 wire hold_rx_err;
431
432xREG3 #(64) hold_rxd_xREG3(.din(parallel_rxd[63:0]),
433 .clk(rx_nbclk),
434 .en(rx_heart_beat),
435 .reset(rx_reset_nbclk),
436 .rst(rxfifo_full_nbclk),
437 .qout(hold_rxd[63:0]));
438
439xREG3 #(8) hold_rx_dv_xREG3(.din(parallel_rx_dv),
440 .clk(rx_nbclk),
441 .en(rx_heart_beat),
442 .reset(rx_reset_nbclk),
443 .rst(rxfifo_full_nbclk),
444 .qout(hold_rx_dv[7:0]));
445
446xREG3 #(1) hold_rx_err_xREG3(.din(parallel_rx_err),
447 .clk(rx_nbclk),
448 .en(rx_heart_beat),
449 .reset(rx_reset_nbclk),
450 .rst(rxfifo_full_nbclk),
451 .qout(hold_rx_err));
452
453
454/* ---------- control logic ------------------------------------- */
455
456// sfd detection: maybe a pulse assign
457// load_ok_state = (grlm_state == PAYLOAD)
458
459 assign rx_det_sfd = gmii_mode ? // a pulse
460 ((rxd_ilane0[`BYTE0] == `SFD_GMII) & // SFD_GMII == 'hD5
461 sfd_win) : // mii_mode
462 (({rxd_ilaneX[`NIB],rxd_ilane0[`NIB1]} == `SFD_MII) & // SFD_MII == 'h5D
463 sfd_win) ; // grlm_state NOT in PAYLOAD state
464
465// eop detection: it is a level
466
467 assign rx_det_eop_lv = ~(rx_dv_ilane0 &
468 rx_dv_ilane1 &
469 rx_dv_ilane2 &
470 rx_dv_ilane3 &
471 rx_dv_ilane4 &
472 rx_dv_ilane5 &
473 rx_dv_ilane6 &
474 rx_dv_ilane7);
475
476
477//PlsGen rx_det_eop_lead_PlsGen(.reset(rx_reset_nbclk),
478// .clk(rx_nbclk),
479// .iSigIn(rx_det_eop_lv),
480// .oPlsOut(rx_det_eop_lead));
481
482
483/* --------------- rx_heart_beat timer -------------------- */
484FD1 d_hw_reset_rxnbclk_FD1(.D(hw_reset_rxnbclk),
485 .CP(rx_nbclk),
486 .Q(d_hw_reset_rxnbclk));
487
488 assign hw_reset_rxnbclk_lead = hw_reset_rxnbclk & ~d_hw_reset_rxnbclk;
489
490 reg [3:0] rx_heart_beat_timer;
491
492always @ (posedge rx_nbclk)
493 if (hw_reset_rxnbclk_lead)
494 rx_heart_beat_timer <= 0;
495 else if (adjust_rx_heart_beat | (~mii_or_gmii_mode))
496 rx_heart_beat_timer <= 0;
497 else rx_heart_beat_timer <= rx_heart_beat_timer + 1;
498
499 reg [3:0] rx_heart_beat_timer_reg;
500always @ (posedge rx_nbclk)
501 rx_heart_beat_timer_reg <= rx_heart_beat_timer;
502
503
504 assign rx_heart_beat = mii_mode ?
505 (rx_heart_beat_timer[3:0] == 4'b0) :
506 (rx_heart_beat_timer[2:0] == 3'b0) ;// load time
507
508
509/* --------------- instantiation -------------------------- */
510mgrlm_sm mgrlm_sm(
511 .rx_nbclk(rx_nbclk),
512 .rx_reset_nbclk(rx_reset_nbclk),
513 .rx_enable_nbclk(rx_enable_nbclk),
514 .rx_det_sfd(rx_det_sfd), // ipg_done and rx_det_S are level signals.
515 .rx_det_eop_lv(rx_det_eop_lv), // rx_det_sfd is level signals.
516 .rx_heart_beat(rx_heart_beat),
517 .rxfifo_full_nbclk(rxfifo_full_nbclk),
518 // outputs
519 .load_ok_state(load_ok_state),
520 .adjust_rx_heart_beat(adjust_rx_heart_beat), // should be a pulse
521 .mgrlm_state(mgrlm_state)
522 );
523
524endmodule // rx_mii_gmii