Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: xpcs_rx.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 | // **************************************************************** | |
36 | // | |
37 | // Sun Proprietary/Confidential: Internal Use Only | |
38 | // | |
39 | // **************************************************************** | |
40 | // Design: XPCS Receive | |
41 | // Block: XPCS | |
42 | // Author: Carlos Castil | |
43 | // | |
44 | // Module: xpcs_rx | |
45 | // File: xpcs_rx.v | |
46 | // | |
47 | // Description: Logic to deliver receive data to the Vega core | |
48 | // in single clock XGMII, 8 byte wide on a single | |
49 | // clock. | |
50 | // | |
51 | // Revision History | |
52 | // ------------------------------------------------------------ | |
53 | // Ver Date Comments | |
54 | // ------------------------------------------------------------ | |
55 | // 1.0 10/16/02 Created | |
56 | // | |
57 | // **************************************************************** | |
58 | ||
59 | ||
60 | ||
61 | module xpcs_rx ( | |
62 | rx_clk, | |
63 | reset_rxclk, | |
64 | ||
65 | xserdes_rdy, | |
66 | ||
67 | state, | |
68 | ||
69 | csr_xpcs_enable, | |
70 | csr_link_status_rx, | |
71 | csr_tx_test_enable, | |
72 | ||
73 | csr_receive_fault_ref, | |
74 | ||
75 | inc_rx_pkt_count_ref, | |
76 | ||
77 | rx_byte_0, | |
78 | rx_byte_1, | |
79 | rx_byte_2, | |
80 | rx_byte_3, | |
81 | ||
82 | rx_special_0, | |
83 | rx_special_1, | |
84 | rx_special_2, | |
85 | rx_special_3, | |
86 | ||
87 | rx_error_0, | |
88 | rx_error_1, | |
89 | rx_error_2, | |
90 | rx_error_3, | |
91 | ||
92 | rx_xgmii_byte_0, | |
93 | rx_xgmii_byte_1, | |
94 | rx_xgmii_byte_2, | |
95 | rx_xgmii_byte_3, | |
96 | ||
97 | rx_xgmii_special_0, | |
98 | rx_xgmii_special_1, | |
99 | rx_xgmii_special_2, | |
100 | rx_xgmii_special_3 | |
101 | ||
102 | ); | |
103 | ||
104 | input rx_clk; | |
105 | input reset_rxclk; | |
106 | ||
107 | input xserdes_rdy; | |
108 | ||
109 | input csr_xpcs_enable; | |
110 | input csr_link_status_rx; | |
111 | input csr_tx_test_enable; | |
112 | ||
113 | input [7:0] rx_byte_0; | |
114 | input [7:0] rx_byte_1; | |
115 | input [7:0] rx_byte_2; | |
116 | input [7:0] rx_byte_3; | |
117 | ||
118 | input rx_special_0; | |
119 | input rx_special_1; | |
120 | input rx_special_2; | |
121 | input rx_special_3; | |
122 | ||
123 | input rx_error_0; | |
124 | input rx_error_1; | |
125 | input rx_error_2; | |
126 | input rx_error_3; | |
127 | ||
128 | output state; | |
129 | ||
130 | output [7:0] rx_xgmii_byte_0; | |
131 | output [7:0] rx_xgmii_byte_1; | |
132 | output [7:0] rx_xgmii_byte_2; | |
133 | output [7:0] rx_xgmii_byte_3; | |
134 | ||
135 | output rx_xgmii_special_0; | |
136 | output rx_xgmii_special_1; | |
137 | output rx_xgmii_special_2; | |
138 | output rx_xgmii_special_3; | |
139 | ||
140 | output inc_rx_pkt_count_ref; | |
141 | ||
142 | output csr_receive_fault_ref; | |
143 | ||
144 | parameter FAULT = 1'b0; | |
145 | parameter RECEIVE = 1'b1; | |
146 | ||
147 | wire nxt_state; | |
148 | ||
149 | wire serdes_rdy; | |
150 | ||
151 | wire detect_idle_0; | |
152 | wire detect_idle_1; | |
153 | wire detect_idle_2; | |
154 | wire detect_idle_3; | |
155 | ||
156 | // vlint flag_dangling_net_within_module off | |
157 | // vlint flag_net_has_no_load off | |
158 | wire detect_idle; | |
159 | wire detect_sop_pipe; | |
160 | // vlint flag_dangling_net_within_module on | |
161 | // vlint flag_net_has_no_load on | |
162 | ||
163 | reg state; | |
164 | ||
165 | reg [7:0] rx_xgmii_byte_0; | |
166 | reg [7:0] rx_xgmii_byte_1; | |
167 | reg [7:0] rx_xgmii_byte_2; | |
168 | reg [7:0] rx_xgmii_byte_3; | |
169 | ||
170 | reg rx_xgmii_special_0; | |
171 | reg rx_xgmii_special_1; | |
172 | reg rx_xgmii_special_2; | |
173 | reg rx_xgmii_special_3; | |
174 | ||
175 | reg [7:0] rx_byte_pipe_0; | |
176 | reg [7:0] rx_byte_pipe_1; | |
177 | reg [7:0] rx_byte_pipe_2; | |
178 | reg [7:0] rx_byte_pipe_3; | |
179 | ||
180 | reg rx_error_int_0; | |
181 | reg rx_error_int_1; | |
182 | reg rx_error_int_2; | |
183 | reg rx_error_int_3; | |
184 | ||
185 | reg rx_special_pipe_0; | |
186 | reg rx_special_pipe_1; | |
187 | reg rx_special_pipe_2; | |
188 | reg rx_special_pipe_3; | |
189 | ||
190 | wire rx_error_pipe_0; | |
191 | wire rx_error_pipe_1; | |
192 | wire rx_error_pipe_2; | |
193 | wire rx_error_pipe_3; | |
194 | ||
195 | wire detect_eop_0; | |
196 | wire detect_eop_1; | |
197 | wire detect_eop_2; | |
198 | wire detect_eop_3; | |
199 | ||
200 | wire detect_eop; | |
201 | ||
202 | wire detect_seq; | |
203 | ||
204 | wire detect_eop_pipe; | |
205 | ||
206 | wire detect_eop_pipe0; | |
207 | wire detect_eop_pipe1; | |
208 | wire detect_eop_pipe2; | |
209 | wire detect_eop_pipe3; | |
210 | ||
211 | wire xpcs_enable; | |
212 | wire tx_test_enable; | |
213 | ||
214 | /* ********************************************************* */ | |
215 | /* Synchronize */ | |
216 | /* ********************************************************* */ | |
217 | ||
218 | SYNC_CELL u_sync_serdes_rdy ( | |
219 | .D (xserdes_rdy), // unsynchronized | |
220 | .CP (rx_clk), | |
221 | .Q (serdes_rdy)); // synchronized | |
222 | ||
223 | SYNC_CELL u_sync_xpcs_enable ( | |
224 | .D (csr_xpcs_enable), // unsynchronized | |
225 | .CP (rx_clk), | |
226 | .Q (xpcs_enable)); // synchronized | |
227 | ||
228 | SYNC_CELL u_sync_test_enable ( | |
229 | .D (csr_tx_test_enable), // unsynchronized | |
230 | .CP (rx_clk), | |
231 | .Q (tx_test_enable)); // synchronized | |
232 | ||
233 | /* ********************************************************************** */ | |
234 | /* Pipeline to satisfy 48.2.6.1.4 check_end Function */ | |
235 | /* ********************************************************************** */ | |
236 | ||
237 | assign detect_eop_0 = ({rx_error_0,rx_special_0,rx_byte_0} == `XPCS_DEC_END); | |
238 | assign detect_eop_1 = ({rx_error_1,rx_special_1,rx_byte_1} == `XPCS_DEC_END); | |
239 | assign detect_eop_2 = ({rx_error_2,rx_special_2,rx_byte_2} == `XPCS_DEC_END); | |
240 | assign detect_eop_3 = ({rx_error_3,rx_special_3,rx_byte_3} == `XPCS_DEC_END); | |
241 | ||
242 | assign detect_eop = detect_eop_0 | detect_eop_1 | detect_eop_2 | detect_eop_3; | |
243 | ||
244 | always @ (posedge rx_clk) | |
245 | if (reset_rxclk) | |
246 | begin | |
247 | rx_byte_pipe_0 <= 8'h00; | |
248 | rx_byte_pipe_1 <= 8'h00; | |
249 | rx_byte_pipe_2 <= 8'h00; | |
250 | rx_byte_pipe_3 <= 8'h00; | |
251 | end | |
252 | else | |
253 | begin | |
254 | rx_byte_pipe_0 <= rx_byte_0; | |
255 | rx_byte_pipe_1 <= rx_byte_1; | |
256 | rx_byte_pipe_2 <= rx_byte_2; | |
257 | rx_byte_pipe_3 <= rx_byte_3; | |
258 | end | |
259 | ||
260 | always @ (posedge rx_clk) | |
261 | if (reset_rxclk) | |
262 | begin | |
263 | rx_error_int_0 <= 1'b0; | |
264 | rx_error_int_1 <= 1'b0; | |
265 | rx_error_int_2 <= 1'b0; | |
266 | rx_error_int_3 <= 1'b0; | |
267 | end | |
268 | else | |
269 | begin | |
270 | rx_error_int_0 <= rx_error_0; | |
271 | rx_error_int_1 <= rx_error_1; | |
272 | rx_error_int_2 <= rx_error_2; | |
273 | rx_error_int_3 <= rx_error_3; | |
274 | end | |
275 | ||
276 | assign rx_error_pipe_0 = rx_error_int_0 | rx_error_0 & detect_eop_pipe | rx_error_0 & detect_eop; | |
277 | assign rx_error_pipe_1 = rx_error_int_1 | rx_error_1 & detect_eop_pipe | rx_error_1 & detect_eop; | |
278 | assign rx_error_pipe_2 = rx_error_int_2 | rx_error_2 & detect_eop_pipe | rx_error_2 & detect_eop; | |
279 | assign rx_error_pipe_3 = rx_error_int_3 | rx_error_3 & detect_eop_pipe | rx_error_3 & detect_eop; | |
280 | ||
281 | always @ (posedge rx_clk) | |
282 | if (reset_rxclk) | |
283 | begin | |
284 | rx_special_pipe_0 <= 1'b0; | |
285 | rx_special_pipe_1 <= 1'b0; | |
286 | rx_special_pipe_2 <= 1'b0; | |
287 | rx_special_pipe_3 <= 1'b0; | |
288 | end | |
289 | else | |
290 | begin | |
291 | rx_special_pipe_0 <= rx_special_0; | |
292 | rx_special_pipe_1 <= rx_special_1; | |
293 | rx_special_pipe_2 <= rx_special_2; | |
294 | rx_special_pipe_3 <= rx_special_3; | |
295 | end | |
296 | ||
297 | /* ********************************************************************** */ | |
298 | ||
299 | assign detect_eop_pipe0 = ({rx_error_int_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_END); | |
300 | assign detect_eop_pipe1 = ({rx_error_int_1,rx_special_pipe_1,rx_byte_pipe_1} == `XPCS_DEC_END); | |
301 | assign detect_eop_pipe2 = ({rx_error_int_2,rx_special_pipe_2,rx_byte_pipe_2} == `XPCS_DEC_END); | |
302 | assign detect_eop_pipe3 = ({rx_error_int_3,rx_special_pipe_3,rx_byte_pipe_3} == `XPCS_DEC_END); | |
303 | ||
304 | assign detect_idle_0 = ({rx_error_pipe_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_SKP) | | |
305 | ({rx_error_pipe_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_ALG) | | |
306 | ({rx_error_pipe_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_COM); | |
307 | ||
308 | assign detect_idle_1 = ({rx_error_pipe_1,rx_special_pipe_1,rx_byte_pipe_1} == `XPCS_DEC_SKP) | | |
309 | ({rx_error_pipe_1,rx_special_pipe_1,rx_byte_pipe_1} == `XPCS_DEC_ALG) | | |
310 | ({rx_error_pipe_1,rx_special_pipe_1,rx_byte_pipe_1} == `XPCS_DEC_COM); | |
311 | ||
312 | assign detect_idle_2 = ({rx_error_pipe_2,rx_special_pipe_2,rx_byte_pipe_2} == `XPCS_DEC_SKP) | | |
313 | ({rx_error_pipe_2,rx_special_pipe_2,rx_byte_pipe_2} == `XPCS_DEC_ALG) | | |
314 | ({rx_error_pipe_2,rx_special_pipe_2,rx_byte_pipe_2} == `XPCS_DEC_COM); | |
315 | ||
316 | assign detect_idle_3 = ({rx_error_pipe_3,rx_special_pipe_3,rx_byte_pipe_3} == `XPCS_DEC_SKP) | | |
317 | ({rx_error_pipe_3,rx_special_pipe_3,rx_byte_pipe_3} == `XPCS_DEC_ALG) | | |
318 | ({rx_error_pipe_3,rx_special_pipe_3,rx_byte_pipe_3} == `XPCS_DEC_COM); | |
319 | ||
320 | /* 0in req_ack -req $0in_rising_edge(detect_sop_pipe) -ack $0in_rising_edge(detect_eop_pipe) -clock rx_clk -max 7000 */ | |
321 | ||
322 | assign detect_eop_pipe = (detect_eop_pipe0 | detect_eop_pipe1 | detect_eop_pipe2 | detect_eop_pipe3); | |
323 | assign detect_sop_pipe = ({rx_error_pipe_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_SDP); | |
324 | ||
325 | assign detect_idle = (detect_idle_0 | detect_idle_1 | detect_idle_2 | detect_idle_3); | |
326 | assign detect_seq = ({rx_error_pipe_0,rx_special_pipe_0,rx_byte_pipe_0} == `XPCS_DEC_SEQ); | |
327 | ||
328 | assign inc_rx_pkt_count_ref = detect_eop_pipe; | |
329 | ||
330 | assign csr_receive_fault_ref = detect_seq; | |
331 | ||
332 | ||
333 | ||
334 | always @ (posedge rx_clk) | |
335 | if (reset_rxclk) | |
336 | begin | |
337 | rx_xgmii_byte_0 <= 8'h9C; | |
338 | rx_xgmii_byte_1 <= 8'h00; | |
339 | rx_xgmii_byte_2 <= 8'h00; | |
340 | rx_xgmii_byte_3 <= 8'h00; | |
341 | end | |
342 | else | |
343 | begin | |
344 | ||
345 | rx_xgmii_byte_3 <= (state == FAULT) ? 8'h01 : | |
346 | ((state == RECEIVE) & rx_error_pipe_3) & !detect_eop_pipe3 ? 8'hFE : | |
347 | detect_idle_3 & rx_special_pipe_3 & !detect_eop_pipe3 ? 8'h07 : | |
348 | detect_eop_pipe & !detect_eop_pipe3 ? 8'h07 : | |
349 | rx_byte_pipe_3 ; | |
350 | ||
351 | rx_xgmii_byte_2 <= (state == FAULT) ? 8'h00 : | |
352 | ((state == RECEIVE) & rx_error_pipe_2) & !detect_eop_pipe2 ? 8'hFE : | |
353 | detect_idle_2 & rx_special_pipe_2 & !detect_eop_pipe2 ? 8'h07 : | |
354 | (detect_eop_pipe & !(detect_eop_pipe3 | detect_eop_pipe2)) ? 8'h07 : | |
355 | rx_byte_pipe_2 ; | |
356 | ||
357 | rx_xgmii_byte_1 <= (state == FAULT) ? 8'h00 : | |
358 | ((state == RECEIVE) & rx_error_pipe_1) & !detect_eop_pipe1 ? 8'hFE : | |
359 | detect_idle_1 & rx_special_pipe_1 & !detect_eop_pipe1 ? 8'h07 : | |
360 | (detect_eop_pipe & !(detect_eop_pipe3 | detect_eop_pipe2 | detect_eop_pipe1)) ? 8'h07 : | |
361 | rx_byte_pipe_1 ; | |
362 | ||
363 | rx_xgmii_byte_0 <= (state == FAULT) ? 8'h9C : | |
364 | ((state == RECEIVE) & rx_error_pipe_0) & !detect_eop_pipe0 ? 8'hFE : | |
365 | detect_idle_0 & rx_special_pipe_0 & !detect_eop_pipe0 ? 8'h07 : | |
366 | rx_byte_pipe_0 ; | |
367 | end | |
368 | ||
369 | ||
370 | always @ (posedge rx_clk) | |
371 | if (reset_rxclk) | |
372 | begin | |
373 | rx_xgmii_special_0 <= 1'b1; | |
374 | rx_xgmii_special_1 <= 1'b0; | |
375 | rx_xgmii_special_2 <= 1'b0; | |
376 | rx_xgmii_special_3 <= 1'b0; | |
377 | end | |
378 | else | |
379 | begin | |
380 | rx_xgmii_special_3 <= (state == FAULT) ? 1'b0 : rx_special_pipe_3 | ((state == RECEIVE) & rx_error_pipe_3) ; | |
381 | rx_xgmii_special_2 <= (state == FAULT) ? 1'b0 : rx_special_pipe_2 | ((state == RECEIVE) & rx_error_pipe_2) ; | |
382 | rx_xgmii_special_1 <= (state == FAULT) ? 1'b0 : rx_special_pipe_1 | ((state == RECEIVE) & rx_error_pipe_1) ; | |
383 | rx_xgmii_special_0 <= (state == FAULT) ? 1'b1 : rx_special_pipe_0 | ((state == RECEIVE) & rx_error_pipe_0) ; | |
384 | end | |
385 | ||
386 | ||
387 | assign {nxt_state} = receive_fn (reset_rxclk, | |
388 | serdes_rdy, | |
389 | tx_test_enable, | |
390 | xpcs_enable, | |
391 | csr_link_status_rx, | |
392 | detect_eop_pipe, | |
393 | state); | |
394 | ||
395 | ||
396 | function [0:0] receive_fn; | |
397 | ||
398 | input reset; | |
399 | input serdes_rdy; | |
400 | input tx_test_enable; | |
401 | input enable; | |
402 | input link; | |
403 | input eop; | |
404 | input state; | |
405 | ||
406 | reg n_state; | |
407 | ||
408 | begin | |
409 | ||
410 | if (reset) | |
411 | ||
412 | begin | |
413 | n_state = FAULT; | |
414 | end | |
415 | ||
416 | else | |
417 | ||
418 | begin | |
419 | ||
420 | n_state = FAULT; | |
421 | ||
422 | case (state) | |
423 | ||
424 | FAULT : | |
425 | if (link & enable & serdes_rdy & !tx_test_enable) | |
426 | n_state = RECEIVE; | |
427 | else | |
428 | n_state = FAULT; | |
429 | ||
430 | RECEIVE: | |
431 | if (!link | tx_test_enable) | |
432 | n_state = FAULT; | |
433 | else if (!enable & eop) | |
434 | n_state = FAULT; | |
435 | else | |
436 | n_state = RECEIVE; | |
437 | ||
438 | endcase | |
439 | ||
440 | end | |
441 | ||
442 | receive_fn = {n_state}; | |
443 | ||
444 | end | |
445 | ||
446 | endfunction | |
447 | ||
448 | // 0in state -var state -val FAULT -next RECEIVE -clock rx_clk | |
449 | // 0in state -var state -val RECEIVE -next FAULT -clock rx_clk | |
450 | ||
451 | ||
452 | always @ (posedge rx_clk) | |
453 | if (reset_rxclk) | |
454 | state <= 1'b0; | |
455 | else | |
456 | state <= nxt_state; | |
457 | ||
458 | ||
459 | ||
460 | endmodule |