Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: tx_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 : tx_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/19/00 | |
46 | * | |
47 | * Copyright (c) 2002, Sun Microsystems, Inc. | |
48 | * Sun Proprietary and Confidential | |
49 | * | |
50 | * Modification : | |
51 | * | |
52 | * Synthesis Notes by loj: tx_clk belongs to xgmii clock domain. It is | |
53 | * used as DDR selection of txd_image to gtfifo_din. | |
54 | * tx_clk is a clock path which merge with txd_image | |
55 | * which is a data path. Make usre timing is ok. | |
56 | * | |
57 | *************************************************************************/ | |
58 | ||
59 | `include "xmac.h" | |
60 | ||
61 | module tx_mii_gmii ( | |
62 | tx_nbclk, | |
63 | tx_reset_nbclk, | |
64 | hw_reset_txnbclk, | |
65 | tx_output_en_nbclk, | |
66 | mii_mode, | |
67 | gmii_mode, | |
68 | mii_or_gmii_mode, | |
69 | txd_image, | |
70 | txc_image, | |
71 | tx_err_image, | |
72 | ipg_value1, | |
73 | // outputs | |
74 | tx_heart_beat_timer, | |
75 | tx_heart_beat_timer_reg, | |
76 | // gmii outputs // mii pins have been mux with gmii pins. | |
77 | gmii_txd, | |
78 | gmii_tx_en, | |
79 | gmii_tx_err, | |
80 | // loopback path | |
81 | mgmii_txd, | |
82 | mgmii_tx_en, | |
83 | mgmii_tx_err, | |
84 | // internal signals | |
85 | tx_hb_byte0_time, | |
86 | tx_hb_byte1_time, | |
87 | tx_hb_byte2_time, | |
88 | tx_hb_byte3_time, | |
89 | tx_hb_byte4_time, | |
90 | tx_hb_byte5_time, | |
91 | tx_hb_byte6_time, | |
92 | tx_hb_byte7_time | |
93 | ); | |
94 | ||
95 | input tx_nbclk; | |
96 | input tx_reset_nbclk; | |
97 | input hw_reset_txnbclk; | |
98 | input tx_output_en_nbclk; | |
99 | input mii_mode; | |
100 | input gmii_mode; | |
101 | input mii_or_gmii_mode; | |
102 | input [63:0] txd_image; | |
103 | input [7:0] txc_image; | |
104 | input tx_err_image; | |
105 | input [`BYTE] ipg_value1; | |
106 | // outputs | |
107 | output [3:0] tx_heart_beat_timer; // to clock mux | |
108 | output [3:0] tx_heart_beat_timer_reg;// to xmac_slv | |
109 | // gmii outputs // mii pins have been mux with gmii pins. | |
110 | output [`BYTE] gmii_txd; | |
111 | output gmii_tx_en; | |
112 | output gmii_tx_err; | |
113 | // loopback path | |
114 | output [`BYTE] mgmii_txd; | |
115 | output mgmii_tx_en; | |
116 | output mgmii_tx_err; | |
117 | // internal signals | |
118 | output tx_hb_byte0_time; | |
119 | output tx_hb_byte1_time; | |
120 | output tx_hb_byte2_time; | |
121 | output tx_hb_byte3_time; | |
122 | output tx_hb_byte4_time; | |
123 | output tx_hb_byte5_time; | |
124 | output tx_hb_byte6_time; | |
125 | output tx_hb_byte7_time; | |
126 | ||
127 | ||
128 | reg [3:0] mgtfifo_wr_ptr; | |
129 | reg [3:0] mgtfifo_rd_ptr; | |
130 | reg [`BYTE] txd_ilane7; | |
131 | reg [`BYTE] txd_ilane6; | |
132 | reg [`BYTE] txd_ilane5; | |
133 | reg [`BYTE] txd_ilane4; | |
134 | reg [`BYTE] txd_ilane3; | |
135 | reg [`BYTE] txd_ilane2; | |
136 | reg [`BYTE] txd_ilane1; | |
137 | reg [`BYTE] txd_ilane0; | |
138 | ||
139 | reg txc_ilane7; | |
140 | reg txc_ilane6; | |
141 | reg txc_ilane5; | |
142 | reg txc_ilane4; | |
143 | reg txc_ilane3; | |
144 | reg txc_ilane2; | |
145 | reg txc_ilane1; | |
146 | reg txc_ilane0; | |
147 | reg txc_ilane7a; | |
148 | reg txc_ilane6a; | |
149 | reg txc_ilane5a; | |
150 | reg txc_ilane4a; | |
151 | reg txc_ilane3a; | |
152 | reg txc_ilane2a; | |
153 | reg txc_ilane1a; | |
154 | reg txc_ilane0a; | |
155 | ||
156 | ||
157 | wire tx_hb_byte0_time; | |
158 | wire tx_hb_byte1_time; | |
159 | wire tx_hb_byte2_time; | |
160 | wire tx_hb_byte3_time; | |
161 | wire tx_hb_byte4_time; | |
162 | wire tx_hb_byte5_time; | |
163 | wire tx_hb_byte6_time; | |
164 | wire tx_hb_byte7_time; | |
165 | wire [63:0] txd_reg1; | |
166 | wire [7:0] txc_reg1; | |
167 | wire [72:0] mgtfifo_din; | |
168 | wire [72:0] mgtfifo_dout; | |
169 | wire [7:0] mgtfifo_dout_txc = mgtfifo_dout[71:64]; | |
170 | wire tx_det_S; // ipg_done and tx_det_S are level signals. | |
171 | wire mgtfifo_wr_en; | |
172 | wire mgtfifo_rd_en; | |
173 | wire ipg_timer_ce; | |
174 | wire ipg_done; // level signal | |
175 | wire mgtfifo_full_txnbclk; | |
176 | wire mgtfifo_empty_txnbclk; | |
177 | wire mgtfifo_unload_heart_beat; | |
178 | wire adjust_mgtfifo_unload_heart_beat; | |
179 | wire [`BYTE] gmii_txd; | |
180 | wire gmii_tx_en; | |
181 | wire gmii_tx_err; | |
182 | wire [`BYTE] mgmii_txd; | |
183 | wire mgmii_tx_en; | |
184 | wire mgmii_tx_err; | |
185 | wire tx_err_reg1,tx_on_hold,d_hw_reset_txnbclk,ipg_done_lead, | |
186 | tx_en_trail,tx_err_ilane; | |
187 | ||
188 | /************************************************************************** | |
189 | * Pay special attention to this synthesis result. It is timing critical. | |
190 | **************************************************************************/ | |
191 | ||
192 | /* -------------- 1st stage reg: change clock domain --------------- */ | |
193 | ||
194 | xREG3 #(64) txd_reg1_xREG3(.din(txd_image[63:0]), | |
195 | .clk(tx_nbclk), | |
196 | .en(tx_hb_byte1_time), | |
197 | .reset(tx_reset_nbclk), | |
198 | .rst(~mii_or_gmii_mode), | |
199 | .qout(txd_reg1[63:0])); | |
200 | ||
201 | xREG3 #(8) txc_reg1_xREG3(.din(txc_image[7:0]), | |
202 | .clk(tx_nbclk), | |
203 | .en(tx_hb_byte1_time), | |
204 | .reset(tx_reset_nbclk), | |
205 | .rst(~mii_or_gmii_mode), | |
206 | .qout(txc_reg1[7:0])); | |
207 | ||
208 | xREG3 #(1) tx_err_reg1_xREG3(.din(tx_err_image), | |
209 | .clk(tx_nbclk), | |
210 | .en(tx_hb_byte1_time), | |
211 | .reset(tx_reset_nbclk), | |
212 | .rst(~mii_or_gmii_mode), | |
213 | .qout(tx_err_reg1)); | |
214 | ||
215 | assign tx_det_S = txc_reg1[0] & (txd_reg1[`BYTE0] == `S); //txc_reg1[0] == '1' is control | |
216 | assign mgtfifo_din[`BYTE0] = tx_det_S ? 8'h55 : txd_reg1[`BYTE0]; | |
217 | assign mgtfifo_din[63:8] = txd_reg1[63:8]; | |
218 | assign mgtfifo_din[64] = tx_det_S ? 0 : txc_reg1[0]; // lane 0 for SOP | |
219 | assign mgtfifo_din[71:65] = txc_reg1[7:1]; | |
220 | assign mgtfifo_din[72] = tx_err_reg1; | |
221 | ||
222 | // set needs to have higher priority | |
223 | wire reset_tx_on_hold = &txc_reg1; | |
224 | ||
225 | SR_FF tx_on_mgmii_SR_FF(.set(tx_det_S), | |
226 | .rst(reset_tx_on_hold), | |
227 | .clk(tx_nbclk), | |
228 | .reset(tx_reset_nbclk | (~mii_or_gmii_mode)), | |
229 | .qout(tx_on_hold)); | |
230 | ||
231 | wire tx_on = (tx_on_hold | tx_det_S) & ~reset_tx_on_hold; | |
232 | ||
233 | /* --------------- start of txfifo pointer Management --------------- */ | |
234 | ||
235 | assign mgtfifo_wr_en = (~mgtfifo_full_txnbclk) & tx_hb_byte2_time & tx_on ; | |
236 | ||
237 | assign mgtfifo_rd_en = (~mgtfifo_empty_txnbclk) & ipg_done & | |
238 | (mgtfifo_unload_heart_beat | adjust_mgtfifo_unload_heart_beat); | |
239 | ||
240 | assign mgtfifo_full_txnbclk = (mgtfifo_wr_ptr[2] == (!mgtfifo_rd_ptr[2])) && | |
241 | (mgtfifo_wr_ptr[1:0] == mgtfifo_rd_ptr[1:0]); | |
242 | ||
243 | assign mgtfifo_empty_txnbclk = (mgtfifo_wr_ptr[2:0] == mgtfifo_rd_ptr[2:0]); | |
244 | ||
245 | // read pointer | |
246 | always @ (posedge tx_nbclk) | |
247 | if (tx_reset_nbclk) | |
248 | mgtfifo_rd_ptr <= 0; | |
249 | else if (mgtfifo_rd_en) | |
250 | mgtfifo_rd_ptr <= mgtfifo_rd_ptr + 1; | |
251 | else | |
252 | mgtfifo_rd_ptr <= mgtfifo_rd_ptr; | |
253 | ||
254 | // write pointer | |
255 | always @ (posedge tx_nbclk) | |
256 | if (tx_reset_nbclk) | |
257 | mgtfifo_wr_ptr <= 0; | |
258 | else if (mgtfifo_wr_en) | |
259 | mgtfifo_wr_ptr <= mgtfifo_wr_ptr + 1; | |
260 | else | |
261 | mgtfifo_wr_ptr <= mgtfifo_wr_ptr; | |
262 | ||
263 | /* --------------- end of mgtfifo pointer Management ---------------- */ | |
264 | ||
265 | ||
266 | /* --------------- tx_heart_beat_timer -------------------- */ | |
267 | FD1 d_hw_reset_txnbclk_FD1(.D(hw_reset_txnbclk), | |
268 | .CP(tx_nbclk), | |
269 | .Q(d_hw_reset_txnbclk)); | |
270 | ||
271 | wire hw_reset_txnbclk_lead = hw_reset_txnbclk & ~d_hw_reset_txnbclk; | |
272 | ||
273 | reg [3:0] tx_heart_beat_timer; | |
274 | ||
275 | always @ (posedge tx_nbclk) | |
276 | if (hw_reset_txnbclk_lead) | |
277 | tx_heart_beat_timer <= 0; | |
278 | else if (~mii_or_gmii_mode) | |
279 | tx_heart_beat_timer <= 0; | |
280 | else tx_heart_beat_timer <= tx_heart_beat_timer + 1; | |
281 | ||
282 | ||
283 | reg [3:0] tx_heart_beat_timer_reg; | |
284 | always @ (posedge tx_nbclk) | |
285 | tx_heart_beat_timer_reg <= tx_heart_beat_timer; | |
286 | ||
287 | ||
288 | assign tx_hb_byte0_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h0): | |
289 | (tx_heart_beat_timer[3:0] == 4'h0); | |
290 | assign tx_hb_byte1_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h1): | |
291 | (tx_heart_beat_timer[3:0] == 4'h1); | |
292 | assign tx_hb_byte2_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h2): | |
293 | (tx_heart_beat_timer[3:0] == 4'h2); | |
294 | assign tx_hb_byte3_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h3): | |
295 | (tx_heart_beat_timer[3:0] == 4'h3); | |
296 | assign tx_hb_byte4_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h4): | |
297 | (tx_heart_beat_timer[3:0] == 4'h4); | |
298 | assign tx_hb_byte5_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h5): | |
299 | (tx_heart_beat_timer[3:0] == 4'h5); | |
300 | assign tx_hb_byte6_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h6): | |
301 | (tx_heart_beat_timer[3:0] == 4'h6); | |
302 | assign tx_hb_byte7_time = gmii_mode ? (tx_heart_beat_timer[2:0] == 3'h7): | |
303 | (tx_heart_beat_timer[3:0] == 4'h7); | |
304 | ||
305 | ||
306 | // vlint flag_net_has_no_load off | |
307 | // vlint flag_dangling_net_within_module off | |
308 | wire ipg_done_trail; | |
309 | wire tx_en_lead; | |
310 | // vlint flag_dangling_net_within_module on | |
311 | // vlint flag_net_has_no_load on | |
312 | ||
313 | /* --------------- mgtfifo_unload_timer ------------------- */ | |
314 | PlsGen2 ipg_done_lead_PlsGen2 (.sig_in(ipg_done),.clk(tx_nbclk), | |
315 | .lead(ipg_done_lead),.trail(ipg_done_trail)); | |
316 | ||
317 | assign adjust_mgtfifo_unload_heart_beat = ipg_done_lead; | |
318 | ||
319 | reg [3:0] mgtfifo_unload_timer; | |
320 | ||
321 | always @ (posedge tx_nbclk) | |
322 | if (hw_reset_txnbclk_lead) | |
323 | mgtfifo_unload_timer <= 0; | |
324 | else if (adjust_mgtfifo_unload_heart_beat | (~mii_or_gmii_mode)) | |
325 | mgtfifo_unload_timer <= 0; | |
326 | else mgtfifo_unload_timer <= mgtfifo_unload_timer + 1; | |
327 | ||
328 | assign mgtfifo_unload_heart_beat = mii_mode ? | |
329 | (mgtfifo_unload_timer[3:0] == 4'b1111) : | |
330 | (mgtfifo_unload_timer[2:0] == 3'b111) ; | |
331 | ||
332 | /* --------------- ipg timer ------------------------------ */ | |
333 | PlsGen2 tx_en_trail_PlsGen2 (.sig_in(mgmii_tx_en),.clk(tx_nbclk), | |
334 | .lead(tx_en_lead),.trail(tx_en_trail)); | |
335 | ||
336 | // ipg_timer | |
337 | reg [7 :0] ipg_timer; | |
338 | ||
339 | always @ (posedge tx_nbclk) | |
340 | if (tx_reset_nbclk) | |
341 | ipg_timer <= 0; | |
342 | else if (tx_en_trail) // load 12 by ipg value | |
343 | ipg_timer <= (mii_mode ? {ipg_value1[6:0],1'b0} : // 24 tx_nbclk = 12 bytes ipg | |
344 | ipg_value1[7:0]) ; | |
345 | else if (ipg_timer_ce) | |
346 | ipg_timer <= ipg_timer - 1; | |
347 | else // hold | |
348 | ipg_timer <= ipg_timer; | |
349 | ||
350 | assign ipg_timer_ce = |ipg_timer; // level | |
351 | assign ipg_done = ~ipg_timer_ce; // level | |
352 | ||
353 | ||
354 | /* --------------- txd parallel to serial shifter --------- */ | |
355 | always @ (posedge tx_nbclk) | |
356 | if (tx_reset_nbclk) | |
357 | begin | |
358 | txd_ilane7 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
359 | txd_ilane6 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
360 | txd_ilane5 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
361 | txd_ilane4 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
362 | txd_ilane3 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
363 | txd_ilane2 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
364 | txd_ilane1 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
365 | txd_ilane0 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
366 | end | |
367 | else if (mgtfifo_rd_en) // parallel load txd to shifter | |
368 | begin | |
369 | txd_ilane7 <= mgtfifo_dout[`BYTE7]; | |
370 | txd_ilane6 <= mgtfifo_dout[`BYTE6]; | |
371 | txd_ilane5 <= mgtfifo_dout[`BYTE5]; | |
372 | txd_ilane4 <= mgtfifo_dout[`BYTE4]; | |
373 | txd_ilane3 <= mgtfifo_dout[`BYTE3]; | |
374 | txd_ilane2 <= mgtfifo_dout[`BYTE2]; | |
375 | txd_ilane1 <= mgtfifo_dout[`BYTE1]; | |
376 | txd_ilane0 <= mgtfifo_dout[`BYTE0]; | |
377 | end | |
378 | else // shifting all the time | |
379 | begin | |
380 | if (gmii_mode) | |
381 | begin | |
382 | txd_ilane7 <= 8'h55; // pa pattern, see 802.3z pp-35.8 | |
383 | txd_ilane6 <= txd_ilane7; | |
384 | txd_ilane5 <= txd_ilane6; | |
385 | txd_ilane4 <= txd_ilane5; | |
386 | txd_ilane3 <= txd_ilane4; | |
387 | txd_ilane2 <= txd_ilane3; | |
388 | txd_ilane1 <= txd_ilane2; | |
389 | txd_ilane0 <= txd_ilane1; | |
390 | end | |
391 | else // mii_mode | |
392 | begin | |
393 | txd_ilane7[`NIB1] <= 4'h5; // pa pattern, see 802.3z pp-35.8 | |
394 | txd_ilane6[`NIB1] <= txd_ilane7[`NIB0]; | |
395 | txd_ilane5[`NIB1] <= txd_ilane6[`NIB0]; | |
396 | txd_ilane4[`NIB1] <= txd_ilane5[`NIB0]; | |
397 | txd_ilane3[`NIB1] <= txd_ilane4[`NIB0]; | |
398 | txd_ilane2[`NIB1] <= txd_ilane3[`NIB0]; | |
399 | txd_ilane1[`NIB1] <= txd_ilane2[`NIB0]; | |
400 | txd_ilane0[`NIB1] <= txd_ilane1[`NIB0]; | |
401 | // | |
402 | txd_ilane7[`NIB0] <= txd_ilane7[`NIB1]; | |
403 | txd_ilane6[`NIB0] <= txd_ilane6[`NIB1]; | |
404 | txd_ilane5[`NIB0] <= txd_ilane5[`NIB1]; | |
405 | txd_ilane4[`NIB0] <= txd_ilane4[`NIB1]; | |
406 | txd_ilane3[`NIB0] <= txd_ilane3[`NIB1]; | |
407 | txd_ilane2[`NIB0] <= txd_ilane2[`NIB1]; | |
408 | txd_ilane1[`NIB0] <= txd_ilane1[`NIB1]; | |
409 | txd_ilane0[`NIB0] <= txd_ilane0[`NIB1]; | |
410 | end | |
411 | end | |
412 | ||
413 | /* --------------- tx_en parallel to serial shifter ------- */ | |
414 | always @ (posedge tx_nbclk) | |
415 | if (tx_reset_nbclk) | |
416 | begin | |
417 | txc_ilane7 <= 0; | |
418 | txc_ilane6 <= 0; | |
419 | txc_ilane5 <= 0; | |
420 | txc_ilane4 <= 0; | |
421 | txc_ilane3 <= 0; | |
422 | txc_ilane2 <= 0; | |
423 | txc_ilane1 <= 0; | |
424 | txc_ilane0 <= 0; | |
425 | txc_ilane7a <= 0; | |
426 | txc_ilane6a <= 0; | |
427 | txc_ilane5a <= 0; | |
428 | txc_ilane4a <= 0; | |
429 | txc_ilane3a <= 0; | |
430 | txc_ilane2a <= 0; | |
431 | txc_ilane1a <= 0; | |
432 | txc_ilane0a <= 0; | |
433 | end | |
434 | else if (mgtfifo_rd_en) // load txc to shifter | |
435 | begin | |
436 | txc_ilane7 <= mgtfifo_dout_txc[7]; | |
437 | txc_ilane6 <= mgtfifo_dout_txc[6]; | |
438 | txc_ilane5 <= mgtfifo_dout_txc[5]; | |
439 | txc_ilane4 <= mgtfifo_dout_txc[4]; | |
440 | txc_ilane3 <= mgtfifo_dout_txc[3]; | |
441 | txc_ilane2 <= mgtfifo_dout_txc[2]; | |
442 | txc_ilane1 <= mgtfifo_dout_txc[1]; | |
443 | txc_ilane0 <= mgtfifo_dout_txc[0]; | |
444 | // | |
445 | txc_ilane7a <= mgtfifo_dout_txc[7]; | |
446 | txc_ilane6a <= mgtfifo_dout_txc[6]; | |
447 | txc_ilane5a <= mgtfifo_dout_txc[5]; | |
448 | txc_ilane4a <= mgtfifo_dout_txc[4]; | |
449 | txc_ilane3a <= mgtfifo_dout_txc[3]; | |
450 | txc_ilane2a <= mgtfifo_dout_txc[2]; | |
451 | txc_ilane1a <= mgtfifo_dout_txc[1]; | |
452 | txc_ilane0a <= mgtfifo_dout_txc[0]; | |
453 | end | |
454 | else // shifting all the time | |
455 | begin | |
456 | if (gmii_mode) | |
457 | begin | |
458 | txc_ilane7 <= 1; // '1' is control signal | |
459 | txc_ilane6 <= txc_ilane7; | |
460 | txc_ilane5 <= txc_ilane6; | |
461 | txc_ilane4 <= txc_ilane5; | |
462 | txc_ilane3 <= txc_ilane4; | |
463 | txc_ilane2 <= txc_ilane3; | |
464 | txc_ilane1 <= txc_ilane2; | |
465 | txc_ilane0 <= txc_ilane1; | |
466 | end | |
467 | else // mii_mode | |
468 | begin | |
469 | txc_ilane7a <= 1; // '1' is control signal | |
470 | txc_ilane7 <= txc_ilane7a; | |
471 | txc_ilane6a <= txc_ilane7; | |
472 | txc_ilane6 <= txc_ilane6a; | |
473 | txc_ilane5a <= txc_ilane6; | |
474 | txc_ilane5 <= txc_ilane5a; | |
475 | txc_ilane4a <= txc_ilane5; | |
476 | txc_ilane4 <= txc_ilane4a; | |
477 | txc_ilane3a <= txc_ilane4; | |
478 | txc_ilane3 <= txc_ilane3a; | |
479 | txc_ilane2a <= txc_ilane3; | |
480 | txc_ilane2 <= txc_ilane2a; | |
481 | txc_ilane1a <= txc_ilane2; | |
482 | txc_ilane1 <= txc_ilane1a; | |
483 | txc_ilane0a <= txc_ilane1; | |
484 | txc_ilane0 <= txc_ilane0a; | |
485 | end | |
486 | end | |
487 | ||
488 | /* ------- register the mgtfifo output for tx_err --------- */ | |
489 | ||
490 | xREG3 #(1) tx_err_ilane_xREG3(.din(mgtfifo_dout[72]), | |
491 | .clk(tx_nbclk), | |
492 | .en(mgtfifo_rd_en), | |
493 | .reset(tx_reset_nbclk), | |
494 | .rst(~mii_or_gmii_mode), | |
495 | .qout(tx_err_ilane)); | |
496 | ||
497 | /* ------- register the output ---------------------------- */ | |
498 | // gmii_txd, gmii_tx_en, and gmii_tx_err are all sharable | |
499 | // between gmii mode and mii mode of operation. | |
500 | // For mii_mode, just use the gmii_txd[3:0] bit will be fine | |
501 | assign mgmii_txd = txd_ilane0; | |
502 | assign mgmii_tx_en = ~txc_ilane0; | |
503 | assign mgmii_tx_err = tx_err_ilane & mgmii_tx_en; | |
504 | ||
505 | wire reset_gmii_regs = tx_reset_nbclk | (~mii_or_gmii_mode); | |
506 | ||
507 | // mii pins have been mux with gmii pins. | |
508 | wire [`BYTE] gmii_txd_shared = tx_output_en_nbclk ? (gmii_mode ? mgmii_txd[`BYTE] : | |
509 | {mgmii_txd[`NIB0],mgmii_txd[`NIB0]}) : | |
510 | 8'h55 ; | |
511 | ||
512 | RegRst2 #(8) gmii_txd_RegRst2( | |
513 | .clk(tx_nbclk), | |
514 | .reset(reset_gmii_regs), | |
515 | .reset_value(8'h55), | |
516 | .din(gmii_txd_shared), // shared between gmii and mii | |
517 | .qout(gmii_txd[`BYTE])) ; | |
518 | ||
519 | RegRst #(1) gmii_tx_en_RegRst( | |
520 | .clk(tx_nbclk), | |
521 | .reset(reset_gmii_regs), | |
522 | .din(mgmii_tx_en & tx_output_en_nbclk), // shared between gmii and mii | |
523 | .qout(gmii_tx_en)); | |
524 | ||
525 | RegDff #(1) mgmii_tx_err_RegDFF( | |
526 | .din(mgmii_tx_err & tx_output_en_nbclk), // shared between gmii and mii | |
527 | .clk(tx_nbclk), | |
528 | .qout(gmii_tx_err)); | |
529 | ||
530 | /* --------------- instantiation ------------------------------------ */ | |
531 | ||
532 | mgtfifo_memory_model mgtfifo_memory_model( | |
533 | .clk(tx_nbclk), | |
534 | .wp(mgtfifo_wr_ptr[1:0]), | |
535 | .rp(mgtfifo_rd_ptr[1:0]), | |
536 | .we(mgtfifo_wr_en), | |
537 | .din(mgtfifo_din[72:0]), | |
538 | .dout(mgtfifo_dout[72:0])); | |
539 | ||
540 | endmodule // tx_mii_gmii | |
541 | ||
542 | ||
543 | ||
544 | module mgtfifo_memory_model (clk,wp,rp,we,din,dout); | |
545 | input clk; | |
546 | input [1:0] wp,rp; | |
547 | input we; | |
548 | input [72:0] din; | |
549 | output [72:0] dout; | |
550 | /************************************************************************ | |
551 | * It is important to have a 8 deep FIFO so that longer ipg can be used. | |
552 | ************************************************************************/ | |
553 | reg [72:0] mgtfifo_mem [0:3]; | |
554 | ||
555 | always @ (posedge clk) | |
556 | if (we) | |
557 | mgtfifo_mem[wp] <= din; | |
558 | else // hold it | |
559 | mgtfifo_mem[wp] <= mgtfifo_mem[wp]; | |
560 | ||
561 | assign dout = mgtfifo_mem[rp]; | |
562 | ||
563 | endmodule |