Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / niu / rtl / pcs_sequence_detect.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: pcs_sequence_detect.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// @(#)pcs_sequence_detect.v 1.1G
36/**********************************************************************/
37/* Project Name : CASSINI */
38/* Module Name : PCS Sequence Detection */
39/* Description : This block detects all ordered sets which could */
40/* come over the receive data bus. As a result, it */
41/* generates flags indicating which ordered sets */
42/* were received. These outputs are used by the Link */
43/* Configuration block to determine link status. */
44/* It also captures the partner's configuration */
45/* registers in order to compare them with previous */
46/* copies it has received. It counts the number of */
47/* sequential and identical Config registers */
48/* it has received (not comparing their ack bits), */
49/* and counts the number of Config registers with */
50/* the ack bit set plus good data characters it has */
51/* received sequentially. These flags are also used */
52/* by the Link Configuration block. The outputs are */
53/* passed out synchronous to the rxclk, so the */
54/* blocks which use the outputs must synchronize */
55/* them to the local clock domain if necessary. */
56/* */
57/* This block also detects whether word synchroniz- */
58/* ation has been achieved. The main output from it */
59/* is the loss_sync signal. Loss of signal indicated */
60/* by the optics will put the state machine in loss */
61/* of sync state. Then the state machine will try */
62/* to reacquire sync. Link Configuration will be */
63/* triggered upon loss_sync. */
64/* */
65/* Assumptions : none. */
66/* */
67/* Parent module : pcs.v */
68/* Child modules : none. */
69/* Author Name : Linda Chen */
70/* Date Created : 10/15/96 */
71/* */
72/* Copyright (c) 1994, Sun Microsystems, Inc. */
73/* Sun Proprietary and Confidential */
74/* */
75/* Modifications : */
76/* 7/22/97 : removed flag for got_Cnack_rx to restart autoneg */
77/* : add check for unaligned commas for sync state machine */
78/* : allow any d following k28.5 to be considered an idle */
79/* 11/1/97 : add got3_config0_rx flag for aneg restart */
80/* : add check for dec_err and disp_err to cause aneg */
81/* restart during aneg */
82/* : stay in loss of sync if signal_detect is in FAIL */
83/* 11/17/97: reset Cnack_cnt and CorData_cnt counters if got idle*/
84/* : updated got_none_err to allow undefined idles */
85/* 11/24/97: removed signal_detect_rx_d because it no longer */
86/* : drives any nets. */
87/* 12/8/98 : changed word_sync sm to only look at commas, not */
88/* : care if it is k28.5 specifically */
89/* 12/8/98 : changed crs to trigger on carrier detect which */
90/* : looks for 2 or more bit difference with K28.5 */
91/* 1/17/02 : added LT_TM related logic */
92/* Synthesis Notes : none yet */
93/**********************************************************************/
94
95`include "pcs_define.h"
96
97module pcs_sequence_detect (
98 rxclk,reset_pci, // inputs
99 kchar_p,disp_err_p,dec_err_p,rx_8bdata_p,odd_rx,signal_detect,
100 got_d_linkconf_p,nxt_crs_mask,
101 link_up_tx,comma_p,k285w1_p,
102
103 good3_Cnack_rx,good3_CorData_rx, // outputs
104 got_C_rx,CorData_err_rx,nxt_crs_rx,crs_rx,
105 loss_sync_rx,reset_rx,link_partner_rx,
106 seq_state_rx,word_state_rx,got3_config0_rx);
107
108input rxclk; // Rx Clk 125 MHz
109input reset_pci; // hw and sw reset OR'ed, needs sync from PCI
110input kchar_p; // this marks a K char
111input disp_err_p; // marks a code which had a disparity error
112input dec_err_p; // marks a code which was not a valid code
113input [7:0] rx_8bdata_p; // the 8 bit decoded data
114input odd_rx; // indicates alignment to word boundary
115input signal_detect; // input from optics which indicates light ok
116input got_d_linkconf_p; // flags special data character
117input nxt_crs_mask; // used to deassert crs_rx early for IPG
118input link_up_tx; // used to clear cnt_CorData
119input comma_p; // received a comma character
120input k285w1_p; // within one bit of k28.5
121
122output good3_Cnack_rx; // flag to link config, got 3 C's
123output good3_CorData_rx; // flag to link config, got 3 C's or data
124output got_C_rx; // flag to indicate currently receiving C chars
125output CorData_err_rx; // flag to indicate not receiving C or data
126output nxt_crs_rx; // unmasked crs_rx one cycle before crs_rx
127output crs_rx; // post-masked crs_rx due out with rx_dv
128output loss_sync_rx; // flag which indicates word synchronization
129output reset_rx; // synchronized here, to be used by rx_ctrl
130output [15:0] link_partner_rx; // same as cfg_old, link partner ability
131output [1:0] seq_state_rx; // state bits to slave for diagnostic
132output [2:0] word_state_rx; // state bits to slave for diagnostic
133output got3_config0_rx; // used in conjunction with good3_Cnack_rx
134 // to restart aneg
135
136wire reset_rx; // synchronized version of reset to rxclk
137wire got_k285; // special symbol K28.5 detected
138wire clr_got_C, // control for special symbol detect registers
139 clr_got_I;
140wire set_got_C, // used to set got_C reg
141 set_got_I, // used to set got_I reg
142 got_none_err; // used in clearing got_C/I regs
143wire got_I, nxt_got_C,
144 nxt_got_I;
145wire [15:0] cfg_new, cfg_old; // used for config reg compare for link config
146wire [7:0] cfg_new_lsb, // pipeline of config registers, used to
147 cfg_new_msb, // compare sequential config register contents
148 cfg_old_msb,
149 cfg_old_lsb;
150wire Cnack_same, // compare of config regs disregarding ack bit
151 Cwack_same; // compare of config regs, all bits
152wire [1:0] Cnack_cnt, // counter for number of sequential and
153 nxt_Cnack_cnt, // identical Config regs
154 CorData_cnt,
155 nxt_CorData_cnt;
156wire good3_Cnack, // flags for when counters reach 3
157 good3_CorData;
158wire load_config; // load signal for config reg pipeline
159wire compare_config; // asserted when ok to compare Config regs
160wire two_kchar_err; // flag for two Kchar in a row error
161wire CorData_err_loc; // local version of CorData_err, not delayed
162
163wire [1:0] seq_state_rx, nxt_seq_state_rx;
164wire [2:0] word_state_rx, nxt_word_state_rx;
165
166wire [15:0] link_partner_rx; // same as cfg_new, link partner ability reg
167wire clr_crs_rx,set_crs_rx, // signals used for carrier sense rx activity
168 crs_rx_p,nxt_crs_rx,
169 masked_nxt_crs_rx;
170wire carrier_detect; // 2+ bit difference to k28.5 detected
171
172/*
173** Signals Specific to Word Synchronization
174*/
175wire [1:0] nxt_sync_cnt, // counter for number of good commas received
176 sync_cnt;
177wire loss_sync_loc; // local version of loss_sync, not delayed
178wire invalid; // error flag used to determine loss of sync
179wire sync_cnt_eq3; // flag which marks receipt of 3 good commas
180wire clr_sync_cnt; // clear signal for good comma counter
181wire inc_sync_cnt; // increment signal for good comma counter
182wire signal_detect_rx; // delayed version of signal detect from optics
183
184parameter CHECK_K285 = 2'h0, // sequence detect state machine
185 CHECK_D_CHAR = 2'h1,
186 CONFIG_LOAD_LSB = 2'h2,
187 CONFIG_LOAD_MSB = 2'h3;
188
189parameter LOSS_SYNC = 3'h0, // word synchronization state machine
190 IN_SYNC = 3'h1,
191 ONE_INVALID = 3'h2,
192 TWO_INVALID = 3'h3,
193 THREE_INVALID = 3'h4;
194
195assign got_k285 = kchar_p & rx_8bdata_p[`PCS_K285_CHAR],
196 clr_got_C = set_got_I | got_none_err,
197 clr_got_I = set_got_C | got_none_err,
198 nxt_got_C = (clr_got_C | reset_rx) ? 1'h0 : (set_got_C) ? 1'h1 :
199 got_C_rx,
200 nxt_got_I = (clr_got_I | reset_rx) ? 1'h0 : (set_got_I) ?
201 1'h1 : got_I,
202 cfg_new_msb = rx_8bdata_p,
203 link_partner_rx = {cfg_new_lsb,cfg_old_msb},
204 cfg_new = {cfg_new_msb,cfg_new_lsb},
205 cfg_old = {cfg_old_msb,cfg_old_lsb},
206 Cnack_same = (cfg_old[13:0] == cfg_new[13:0])
207 & (cfg_old[15] == cfg_new[15]),
208 Cwack_same = Cnack_same & cfg_old[14] & cfg_new[14],
209 nxt_Cnack_cnt = (reset_rx | (compare_config & !Cnack_same) | got_I) ?
210 2'h0 : (good3_Cnack) ? 2'h3 : (compare_config & Cnack_same) ?
211 Cnack_cnt + 1'h1 : Cnack_cnt,
212 nxt_CorData_cnt = (reset_rx | (compare_config & ~Cwack_same) | link_up_tx) ?
213 2'h0 : (good3_CorData) ? 2'h3 : (compare_config & Cwack_same) ?
214 CorData_cnt + 1'h1 : CorData_cnt,
215 good3_Cnack = Cnack_cnt == 2'h3,
216 good3_CorData = CorData_cnt == 2'h3,
217 CorData_err_loc = !(got_C_rx | got_I),
218 crs_rx_p = (reset_rx | clr_crs_rx) ? 1'h0 : (set_crs_rx) ? 1'h1 :
219 nxt_crs_rx,
220 masked_nxt_crs_rx = nxt_crs_rx & ~nxt_crs_mask,
221 got3_config0_rx = good3_Cnack & (cfg_old == 16'h0),
222 carrier_detect = ~odd_rx & ~k285w1_p;
223
224
225/*
226** Call of function sequence_detect_fn
227*/
228assign {set_got_C,set_got_I,got_none_err,
229 load_config,compare_config,two_kchar_err,
230 clr_crs_rx,set_crs_rx,nxt_seq_state_rx }
231 = sequence_detect_fn(reset_rx,odd_rx,
232 got_k285,got_d_linkconf_p,
233 dec_err_p,disp_err_p,carrier_detect,kchar_p,seq_state_rx);
234
235/*
236** Sequence Detect state machine
237*/
238function [9:0] sequence_detect_fn;
239 input reset;
240 input odd;
241 input got_k285;
242 input got_d_linkconf;
243 input dec_err;
244 input disp_err;
245 input carrier_detect;
246 input kchar;
247 input [1:0] state;
248
249 reg set_got_C; // control signals for special char detect
250 reg set_got_I;
251 reg got_none_err; // illegal & unrecognizable sequence
252 reg load_config; // load config regs in pipeline
253 reg compare_config; // ok to compare config regs
254 reg two_kchar_err; // illegal sequence
255 reg clr_crs_rx; // turn off carrier sense
256 reg set_crs_rx; // turn on carrier sense
257 reg [1:0] n_state; // next state
258
259 begin
260 set_got_C = 1'h0;
261 set_got_I = 1'h0;
262 got_none_err = 1'h0;
263 load_config = 1'h0;
264 compare_config = 1'h0;
265 two_kchar_err = 1'h0;
266 clr_crs_rx = 1'h0;
267 set_crs_rx = 1'h0;
268 n_state = 2'h0;
269
270 case (state) // synopsys parallel_case full_case
271 CHECK_K285 : // 0
272 if (reset)
273 n_state = CHECK_K285;
274 else if (!odd & got_k285)
275 begin
276 n_state = CHECK_D_CHAR;
277 clr_crs_rx = 1'h1;
278 end
279 else
280 begin
281 got_none_err = 1'h1;
282 n_state = CHECK_K285;
283 set_crs_rx = carrier_detect;
284 end
285 CHECK_D_CHAR : // 1
286 begin
287 set_got_C = got_d_linkconf & ~disp_err;
288 set_got_I = ~dec_err & ~got_d_linkconf & ~disp_err ;
289 got_none_err = disp_err | dec_err;
290 two_kchar_err = kchar;
291 if (got_d_linkconf)
292 n_state = CONFIG_LOAD_LSB;
293 else
294 n_state = CHECK_K285;
295 end
296 CONFIG_LOAD_LSB : // 2
297 begin
298 if (dec_err | disp_err)
299 got_none_err = 1'h1;
300 else
301 load_config = 1'h1;
302 n_state = CONFIG_LOAD_MSB;
303 end
304 CONFIG_LOAD_MSB : // 3
305 begin
306 if (dec_err | disp_err)
307 got_none_err = 1'h1;
308 else
309 begin
310 load_config = 1'h1;
311 compare_config = 1'h1;
312 end
313 n_state = CHECK_K285;
314 end
315 default: n_state = CHECK_K285;
316 endcase
317
318 sequence_detect_fn = {set_got_C,set_got_I,
319 got_none_err,load_config,compare_config,
320 two_kchar_err,clr_crs_rx,set_crs_rx,n_state };
321 end
322endfunction
323
324RREG #(2) r_seq_state (seq_state_rx, rxclk, reset_rx, nxt_seq_state_rx);
325REG #(1) r_nxt_crs_rx (nxt_crs_rx, rxclk, crs_rx_p);
326REG #(1) r_crs_rx (crs_rx, rxclk, masked_nxt_crs_rx);
327REG #(2) r_Cnack_cnt (Cnack_cnt, rxclk, nxt_Cnack_cnt);
328REG #(2) r_CorData_cnt (CorData_cnt, rxclk, nxt_CorData_cnt);
329REG #(1) r_got_C (got_C_rx, rxclk, nxt_got_C);
330REG #(1) r_got_I (got_I, rxclk, nxt_got_I);
331REG #(1) r_good3_Cnack_rx(good3_Cnack_rx, rxclk, good3_Cnack); // unglitch
332REG #(1) r_good3_CorData_rx(good3_CorData_rx, rxclk, good3_CorData); // unglitch
333REG #(1) r_CorData_err_rx(CorData_err_rx, rxclk, CorData_err_loc); // unglitch
334SRREG #(8) r_cfg_old_lsb (cfg_old_lsb,rxclk,load_config,reset_rx,cfg_old_msb);
335SRREG #(8) r_cfg_old_msb (cfg_old_msb,rxclk,load_config,reset_rx,cfg_new_lsb);
336SRREG #(8) r_cfg_new_lsb (cfg_new_lsb,rxclk,load_config,reset_rx,cfg_new_msb);
337
338// SYNCREG (qout, clk, din);
339SYNCREG r_reset_rx(.qout(reset_rx),.clk(rxclk),.din(reset_pci));
340
341/*
342** Word Synchronization Logic
343*/
344
345assign nxt_sync_cnt = (reset_rx|clr_sync_cnt)? 2'h0 : (inc_sync_cnt) ?
346 sync_cnt + 1'h1 : sync_cnt,
347// no_signal = !signal_detect_rx & signal_detect_rx_d,
348// need to conform to the spec, so restart on ~signal_detect instead of one shot
349 invalid = dec_err_p | two_kchar_err | disp_err_p | (comma_p & odd_rx),
350 sync_cnt_eq3 = sync_cnt == 2'h3;
351
352
353/*
354** Call of function word synchronization
355*/
356assign {loss_sync_loc,inc_sync_cnt,clr_sync_cnt,nxt_word_state_rx}
357 = word_synchronization_fn(reset_rx,
358 comma_p,odd_rx,
359 invalid,sync_cnt_eq3,word_state_rx);
360
361/*
362** Word Synchronization state machine
363*/
364function [5:0] word_synchronization_fn;
365 input reset;
366 input got_comma; // to determine if there is a comma
367 input odd; //
368 input invalid; // invalid transmission word detected
369 input sync_cnt_eq3; // found 3 commas with no errors
370 input [2:0] state;
371
372 reg loss_sync; // indicates word sync status
373 reg inc_sync_cnt; // increment word sync counter
374 reg clr_sync_cnt; // clear word sync counter
375 reg [2:0] n_state; // next state
376
377 begin
378 loss_sync = 1'h0;
379 inc_sync_cnt = 1'h0;
380 clr_sync_cnt = 1'h0;
381 n_state = LOSS_SYNC;
382
383 case (state) // synopsys parallel_case full_case
384 LOSS_SYNC : // 0 // being in this state triggers link config
385 begin
386 loss_sync = 1'h1;
387 if (reset)
388 n_state = LOSS_SYNC;
389 else if (invalid)
390 clr_sync_cnt = 1'h1;
391 else if (sync_cnt_eq3) // got 3 good ordered sets with commas
392 n_state = IN_SYNC;
393 else if (got_comma & ~odd) // accum good
394 inc_sync_cnt = 1'h1;
395 end
396 IN_SYNC : // 1
397 if (invalid)
398 n_state = ONE_INVALID;
399 else
400 n_state = IN_SYNC;
401 ONE_INVALID : // 2
402 if (invalid)
403 n_state = TWO_INVALID;
404 else
405 n_state = IN_SYNC;
406 TWO_INVALID : // 3
407 if (invalid)
408 n_state = THREE_INVALID;
409 else
410 n_state = ONE_INVALID;
411 THREE_INVALID : // 4
412 if (invalid)
413 begin
414 n_state = LOSS_SYNC;
415 clr_sync_cnt = 1'h1; // reset good comma counter
416 end
417 else
418 n_state = TWO_INVALID;
419 default: n_state = LOSS_SYNC;
420 endcase
421
422 word_synchronization_fn = {loss_sync,inc_sync_cnt,clr_sync_cnt,n_state};
423
424 end
425endfunction
426
427RREG #(3) r_word_state (word_state_rx, rxclk, reset_rx|(~signal_detect_rx),
428 nxt_word_state_rx);
429REG #(2) r_sync_cnt (sync_cnt, rxclk, nxt_sync_cnt);
430SYNCREG r_signal_det_rx (signal_detect_rx, rxclk, signal_detect);
431REG #(1) r_loss_sync_rx (loss_sync_rx, rxclk, loss_sync_loc);
432
433endmodule
434
435