Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / xdeferral.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: xdeferral.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 : xdeferral.v
40 * Author Name : John Lo
41 * Description :
42 * Parent Module: tx_xmac
43 * Child Module: none
44 * Interface Mod:
45 * Date Created : 6/8/00
46 *
47 * Copyright (c) 2002, Sun Microsystems, Inc.
48 * Sun Proprietary and Confidential
49 *
50 * Modification :
51 *
52 * Synthesis Notes:
53 *
54 *************************************************************************/
55
56`include "xmac.h"
57
58module xdeferral (
59 tx_clk,
60 tx_reset,
61 mii_mode,
62 gmii_mode,
63 tx_byte_count_en,
64 tx_en_8bit,
65 stretch_mode,
66 stretch_constant,
67 stretch_ratio,
68 ipg_value,
69 tx_on_half, // to modify last_byte_position
70 add_crc, // cond1 plus !no_crc -> add 4 crc bytes
71 eop_txclk,
72 last_byte_position,
73 var_min_ipg_en,
74 pa_time,
75 back2back_swap_reg1,
76 set_back2back,
77// outputs
78 tx_swap,
79 ipg_done,
80 final_ipg_clks,
81 // internal observation
82 full_case_last_byte_position,
83 adjust2crc_full_case_last_byte_position,
84 adjust2crc_full_case_last_byte_position_is_3_or_7,
85 stretch_full_case_last_byte_position,
86 stretch_clks,
87 stretch_bytes,
88 stretch_1_more_clk,
89 B_eop,
90 minus_4bytes,
91 no_wasted_BW // no wasted band width (bytes).
92 );
93
94 input tx_clk;
95 input tx_reset;
96 // vlint flag_input_port_not_connected off
97 input mii_mode;
98 input gmii_mode;
99 // vlint flag_input_port_not_connected on
100 input tx_byte_count_en;
101 input [7:0] tx_en_8bit;
102 input stretch_mode;
103 input [2:0] stretch_constant;
104 input [4:0] stretch_ratio;
105 input [2:0] ipg_value;
106 input tx_on_half; // to modify last_byte_position
107 input add_crc; // cond1 plus !no_crc -> add 4 crc bytes
108 input eop_txclk;
109 input [2:0] last_byte_position;
110 input var_min_ipg_en;
111 input pa_time;
112 input back2back_swap_reg1;
113 input set_back2back;
114// outputs
115 output tx_swap;
116 output ipg_done;
117 output [`BYTE] final_ipg_clks;
118 // internal observation
119 output [2:0] full_case_last_byte_position;
120 output [2:0] adjust2crc_full_case_last_byte_position;
121 output adjust2crc_full_case_last_byte_position_is_3_or_7;
122 output [3:0] stretch_full_case_last_byte_position;
123 output [`BYTE] stretch_clks;
124 output [2:0] stretch_bytes;
125 output stretch_1_more_clk;
126 output B_eop;
127 output minus_4bytes;
128 output no_wasted_BW; // no wasted band width (bytes).
129
130
131 // vlint flag_dangling_net_within_module off
132 // vlint flag_net_has_no_load off
133 // vlint flag_input_port_not_connected off
134 wire mii_mode;
135 wire gmii_mode;
136 // vlint flag_input_port_not_connected on
137 // vlint flag_net_has_no_load on
138 // vlint flag_dangling_net_within_module on
139
140
141/* ------------- start of stretch mode logic ---------------------- */
142 // This implementation enable the residue bits to be available for
143 // next coming packet ipg extension calculation.
144
145 reg [4:0] addend_stretch_byte_count;
146 wire [4:0] new_stretch_byte_count;
147 reg [4:0] nx_stretch_byte_count;
148 wire [4:0] stretch_byte_count;
149 reg stretch_1byte;
150
151// addend selection mux
152always @ (tx_en_8bit or tx_byte_count_en or stretch_mode)
153 if (tx_byte_count_en & stretch_mode)
154 casex (tx_en_8bit) // synopsys parallel_case full_case
155 8'b1xxxxxxx: addend_stretch_byte_count = 8;
156 8'b01xxxxxx: addend_stretch_byte_count = 7;
157 8'b001xxxxx: addend_stretch_byte_count = 6;
158 8'b0001xxxx: addend_stretch_byte_count = 5;
159 8'b00001xxx: addend_stretch_byte_count = 4;
160 8'b000001xx: addend_stretch_byte_count = 3;
161 8'b0000001x: addend_stretch_byte_count = 2;
162 8'b00000001: addend_stretch_byte_count = 1;
163 8'b00000000: addend_stretch_byte_count = 0;
164 default: addend_stretch_byte_count = 0;
165 endcase // casex(tx_en_8bit)
166 else addend_stretch_byte_count = 0;
167
168// adder
169 assign new_stretch_byte_count =
170 (stretch_byte_count + addend_stretch_byte_count);
171
172// subtractor
173 // The stretch_ratio in octet should not be bigger than data path width.
174always @ (new_stretch_byte_count or stretch_ratio)
175 if ((new_stretch_byte_count >= stretch_ratio))
176 begin
177 // Since it exceeds stretch_ratio, one more byte is added (stretched)
178 // to IPG (stretch_1byte=1).
179 // The purpose of subtract stretch_ratio is to get the residue
180 // byte count for next round calculation.
181 nx_stretch_byte_count = new_stretch_byte_count - stretch_ratio;
182 stretch_1byte = 1; // add one byte per stretch_ratio
183 end
184 else
185 begin
186 nx_stretch_byte_count = new_stretch_byte_count;
187 stretch_1byte = 0;
188 end
189
190RegRst #(5) stretch_byte_count_RegRst(
191 .clk(tx_clk),
192 .reset(tx_reset | (~stretch_mode) | (pa_time & ~set_back2back)),
193 .din(nx_stretch_byte_count),
194 .qout(stretch_byte_count));
195
196// stretch_size counter
197 wire [10:0] stretch_size;
198 wire [10:0] nx_stretch_size;
199
200 assign nx_stretch_size = stretch_1byte ? (stretch_size + 1) :
201 stretch_size;
202
203RegRst2 #(11) stretch_size_RegRst2(
204 .clk(tx_clk),
205 .reset(tx_reset | (~stretch_mode) | pa_time),
206 .reset_value({8'b0,stretch_constant[2:0]}),
207 .din(nx_stretch_size),
208 .qout(stretch_size));
209
210wire [`BYTE] stretch_clks = nx_stretch_size[10:3];
211wire [2:0] stretch_bytes = nx_stretch_size[2:0];
212
213/* ------------- end of stretch mode logic ------------------------ */
214
215/* ------------------- credit management logic ------------------- */
216 // add_crc is valid only at eop_txclk time
217 // For cond2 and cond3 runt packets, the eop is always at the 3rd
218 // byte of A side then add fcs to make 64 bytes to meet min pkt size.
219 // tx_on_half takes care of cond2 and cond3 caes.
220 // add_crc takes care of cond1 and normal cases.
221 // add_crc = ~no_crc | add_fcs;
222
223 // \\ originai implementation. Before modifying for stretch_mode.
224 // wire [2:0] full_case_last_byte_position = tx_on_half ? 3'h3:
225 // last_byte_position[2:0];
226
227 wire [2:0] org_full_case_last_byte_position = tx_on_half ? 3'h3:
228 last_byte_position[2:0];
229
230 wire [3:0] stretch_full_case_last_byte_position =
231 {1'b0,org_full_case_last_byte_position[2:0]} +
232 {1'b0,stretch_bytes[2:0]};
233
234xMUX_2to1 #(3) full_case_last_byte_positio_xMUX_2to1(
235 .din0(org_full_case_last_byte_position[2:0]),
236 .din1(stretch_full_case_last_byte_position[2:0]),
237 .sel(stretch_mode),
238 .dout(full_case_last_byte_position[2:0]));
239
240 wire [2:0] adjust2crc_full_case_last_byte_position = add_crc ?
241 (full_case_last_byte_position[2:0] + `FOUR_CRC_BYTES) :
242 full_case_last_byte_position[2:0] ;
243
244 wire adjust2crc_full_case_last_byte_position_is_3_or_7 =
245 (&adjust2crc_full_case_last_byte_position[`MERGE_A_B]);
246
247
248 wire [1:0] pos_credit = (3 -
249 adjust2crc_full_case_last_byte_position[`MERGE_A_B]);
250
251 wire [1:0] neg_credit = (1 +
252 adjust2crc_full_case_last_byte_position[`MERGE_A_B]);
253
254 wire no_wasted_BW = adjust2crc_full_case_last_byte_position_is_3_or_7 &
255 (ipg_value[2:0] == 3'h3);
256
257
258 // By default or when var_min_ipg_en == 0, the xdeferral logic will
259 // generate more than 12 bytes ipg (always minus_4bytes == 0) at
260 // the end of each packet.
261 //
262 // In var_min_ipg_en == 1 mode.
263 // When the current_credit is negative at the eop_txclk time, the
264 // minus_4bytes == 0, this will make the logic default to not subtract
265 // 4 bytes ipg. The end results of ipg shown in the waveform should
266 // be longer than min_ipg (12 bytes). Vise versa.
267
268 reg [4:0] current_credit;
269 wire minus_4bytes = eop_txclk &
270 (current_credit >= `CREDIT_BIAS) &
271 (~no_wasted_BW) &
272 var_min_ipg_en ;
273
274 wire [4:0] net_credit = minus_4bytes ?
275 current_credit - {3'b0,neg_credit[1:0]} :
276 current_credit + {3'b0,pos_credit[1:0]} ;
277
278always @ (posedge tx_clk)
279 if (tx_reset)
280 current_credit <= `CREDIT_BIAS;
281 else if (eop_txclk)
282 current_credit <= net_credit;
283 else
284 current_credit <= current_credit; // hold
285
286// synopsys translate_off
287// diag purpose
288always @ (/*AUTOSENSE*/`CREDIT_BIAS or current_credit or gmii_mode
289 or mii_mode or stretch_mode or tx_reset)
290 if ( stretch_mode & (!tx_reset) & ~(mii_mode | gmii_mode) & ((current_credit < (`CREDIT_BIAS - 3)) | (current_credit > (`CREDIT_BIAS + 3))))
291 $display("\n (* ERROR: at sim time = %d, in xdeferral.v, current credit is wrong => current_credit = %h *) \n", $time, current_credit);
292 else ;
293// synopsys translate_on
294/* ------------------- end of credit management logic ------------ */
295
296
297/* ------------------- ipg_timer logic ---------------------------- */
298
299 // final_ipg_value is the tx_clk number which is 4 bytes in granularity.
300 // @ eop_txclk only
301 wire [2:0] final_ipg_value = ipg_value[2:0] - {2'b0,minus_4bytes};
302
303// synopsys translate_off
304// diag purpose
305always @ (/*AUTOSENSE*/final_ipg_value or gmii_mode or mii_mode
306 or stretch_mode or tx_reset)
307 if ( stretch_mode & (!tx_reset) & ~(mii_mode | gmii_mode) & (final_ipg_value < 2))
308 $display("\n (* ERROR: at sim time = %d, in xdeferral.v, final_ipg_value less than 2 clk (less than 8 byte times), final_ipg_value = %h *) \n", $time, final_ipg_value);
309 else ;
310// synopsys translate_on
311
312 reg temp_tx_swap;
313 reg set_tx_swap;
314 reg [`BYTE] ipg_timer;
315 reg [2:0] rounded_ipg_clks;
316 wire ipg_timer_ce = (|ipg_timer[`BYTE]);
317 wire ipg_done = ~ipg_timer_ce;
318
319 // It has to use nx_ipg_extension_count. Since eop_txclk and
320 // inc_ipg_extension_count can happen at the same time.
321 wire stretch_1_more_clk = stretch_mode &
322 stretch_full_case_last_byte_position[3];
323
324 wire [`BYTE] final_ipg_clks = {5'b0,rounded_ipg_clks[2:0]} +
325 stretch_clks[`BYTE] +
326 {7'b0,stretch_1_more_clk};
327
328always @ (posedge tx_clk)
329if (tx_reset)
330 begin
331 temp_tx_swap <= 0 ;
332 ipg_timer <= 0 ;
333 end
334else if (eop_txclk) // load final_ipg_value at eop time.
335 begin
336 temp_tx_swap <= set_tx_swap ;
337 ipg_timer <= final_ipg_clks;
338 end
339else if (ipg_timer_ce)
340 begin
341 temp_tx_swap <= temp_tx_swap ; // hold
342 ipg_timer <= ipg_timer - 1 ; // 8 byte time per txclk
343 end
344else // hold
345 begin
346 temp_tx_swap <= temp_tx_swap ; // hold
347 ipg_timer <= ipg_timer ;
348 end
349
350xREG #(1) tx_swap_xREG(.din(temp_tx_swap),
351 .clk(tx_clk),
352 .en(pa_time),
353 .reset(tx_reset),
354 .qout(tx_swap));
355
356 wire B_eop = full_case_last_byte_position[2]; // eop byte is in byte 4~7.
357
358always @ (/*AUTOSENSE*/B_eop or add_crc or back2back_swap_reg1
359 or eop_txclk or final_ipg_value)
360 if (eop_txclk)
361 casex (final_ipg_value) // synopsys parallel_case full_case
362 3'h2: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
363 2'b00: begin // eop in A side
364 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd1 : 3'd0;
365 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1; // flip
366 end
367 2'b01: begin // eop in B side
368 rounded_ipg_clks = 3'd1;
369 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0; // flip
370 end
371 2'b10: begin // eop in A side
372 rounded_ipg_clks = 3'd1;
373 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0; // flip
374 end
375 2'b11: begin // eop in B side
376 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
377 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1; // flip
378 end
379 endcase
380
381 3'h3: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
382 2'b00: begin // eop in A side
383 rounded_ipg_clks = 3'd1;
384 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0; // flip
385 end
386 2'b01: begin // eop in B side
387 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
388 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1; // flip
389 end
390 2'b10: begin // eop in A side
391 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
392 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1; // flip
393 end
394 2'b11: begin // eop in B side
395 rounded_ipg_clks = 3'd2;
396 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0; // flip
397 end
398 endcase
399
400 3'h4: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
401 2'b00: begin // eop in A side
402 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
403 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
404 end
405 2'b01: begin // eop in B side
406 rounded_ipg_clks = 3'd2;
407 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
408 end
409 2'b10: begin // eop in A side
410 rounded_ipg_clks = 3'd2;
411 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
412 end
413 2'b11: begin // eop in B side
414 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd3 : 3'd2;
415 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
416 end
417 endcase
418
419 3'h5: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
420 2'b00: begin // eop in A side
421 rounded_ipg_clks = 3'd2;
422 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
423 end
424 2'b01: begin // eop in B side
425 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd3 : 3'd2;
426 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
427 end
428 2'b10: begin // eop in A side
429 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd3 : 3'd2;
430 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
431 end
432 2'b11: begin // eop in B side
433 rounded_ipg_clks = 3'd3;
434 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
435 end
436 endcase
437
438 3'h6: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
439 2'b00: begin // eop in A side
440 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd3 : 3'd2;
441 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
442 end
443 2'b01: begin // eop in B side
444 rounded_ipg_clks = 3'd3;
445 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
446 end
447 2'b10: begin // eop in A side
448 rounded_ipg_clks = 3'd3;
449 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
450 end
451 2'b11: begin // eop in B side
452 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd4 : 3'd3;
453 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
454 end
455 endcase
456
457 3'h7: casex ({add_crc,B_eop}) // synopsys parallel_case full_case
458 2'b00: begin // eop in A side
459 rounded_ipg_clks = 3'd3;
460 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
461 end
462 2'b01: begin // eop in B side
463 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd4 : 3'd3;
464 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
465 end
466 2'b10: begin // eop in A side
467 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd4 : 3'd3;
468 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
469 end
470 2'b11: begin // eop in B side
471 rounded_ipg_clks = 3'd4;
472 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
473 end
474 endcase
475
476 default: // default to final_ipg_value = 3
477 begin
478 casex ({add_crc,B_eop}) // synopsys parallel_case full_case
479 2'b00: begin // eop in A side
480 rounded_ipg_clks = 3'd1;
481 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
482 end
483 2'b01: begin // eop in B side
484 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
485 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
486 end
487 2'b10: begin // eop in A side
488 rounded_ipg_clks = {2'b0,back2back_swap_reg1} ? 3'd2 : 3'd1;
489 set_tx_swap = back2back_swap_reg1 ? 1'b0 : 1'b1;
490 end
491 2'b11: begin // eop in B side
492 rounded_ipg_clks = 3'd2;
493 set_tx_swap = back2back_swap_reg1 ? 1'b1 : 1'b0;
494 end
495 endcase // casex({add_crc,B_eop})
496 end // case: endcase...
497 endcase // casex(final_ipg_value)
498 else begin
499 rounded_ipg_clks = 3'd2;
500 set_tx_swap = 1'b0;
501 end // else: !if(eop_txclk)
502
503
504/* ------------------- end of ipg_timer logic --------------------- */
505
506endmodule // xdeferral