Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / design / sys / iop / ccu / rtl / ccu_core.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ccu_core.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`timescale 1 ps/ 1 ps
36
37`define CCU_ALIGN_CNT 5'h08
38`define CCU_CSR_RST_CNT 6'h36
39
40module ccu_core (
41 l1clk,
42 rst_ccu_,
43 aligned,
44 pll_arst_l,
45 pll_div2,
46 pll_div3,
47 pll_div4,
48 pll_div4_msb,
49 io2x_phase_180,
50 io_phase_180,
51 io_phase_0,
52 ccu_sys_cmp_sync_en,
53 shift_amt,
54 ccu_cmp_sys_sync_en,
55 ratio,
56// ccu_vco_aligned,
57 pll_div3_lat,
58 pll_div4_lat,
59 csr_rst_n,
60 serdes_dtm1,
61 serdes_dtm2,
62 io_div,
63 io2x_div,
64 ccu_dbg1_serdes_dtm,
65 ccu_mio_serdes_dtm,
66 ccu_io2x_sync_en,
67 ccu_pre_dr_sync_en,
68 ccu_dr_sync_en,
69 tcu_atpg_mode,
70 scan_in,
71 aclk,
72 bclk,
73 scan_out,
74 rng_arst_l,
75 ccu_serdes_dtm_lat,
76 rng_ctl1,
77 rng_ctl2,
78 rng_ctl3 ,
79 rng_ch_sel,
80 ccu_cmp_io_sync_en,
81 ccu_io_cmp_sync_en,
82 ccu_rst_sync_stable,
83 aligned_rst_n,
84 dr_shift_amt
85);
86
87// port declarations
88
89input l1clk;
90input rst_ccu_;
91input aligned;
92input pll_arst_l;
93input [5:0] pll_div2;
94input [5:0] pll_div3;
95input [6:0] pll_div4;
96input io2x_phase_180;
97input io_phase_180;
98input io_phase_0;
99output ccu_sys_cmp_sync_en;
100input serdes_dtm1;
101input serdes_dtm2;
102output [4:0] io_div;
103output [4:0] io2x_div;
104output ccu_cmp_sys_sync_en;
105output aligned_rst_n;
106output [4:0] ratio;
107// output ccu_vco_aligned;
108output [5:0] pll_div3_lat;
109output [6:0] pll_div4_lat;
110output csr_rst_n;
111output ccu_dbg1_serdes_dtm;
112output ccu_mio_serdes_dtm;
113output ccu_io2x_sync_en;
114input ccu_pre_dr_sync_en;
115output ccu_dr_sync_en;
116input tcu_atpg_mode;
117input scan_in;
118input aclk;
119input bclk;
120output scan_out;
121output rng_arst_l;
122output ccu_serdes_dtm_lat;
123input rng_ctl1;
124input rng_ctl2;
125input rng_ctl3;
126output [1:0] rng_ch_sel;
127output ccu_cmp_io_sync_en;
128output ccu_io_cmp_sync_en;
129output ccu_rst_sync_stable;
130output [4:0] shift_amt;
131output pll_div4_msb;
132output [4:0] dr_shift_amt;
133
134// external wire/reg declarations
135
136wire l1clk;
137wire rst_ccu_;
138wire aligned;
139wire pll_arst_l;
140wire [5:0] pll_div2;
141wire [5:0] pll_div3;
142wire [6:0] pll_div4;
143wire io2x_phase_180;
144wire io_phase_180;
145wire io_phase_0;
146wire serdes_dtm1;
147wire serdes_dtm2;
148wire [4:0] io_div;
149wire [4:0] io2x_div;
150wire ccu_sys_cmp_sync_en;
151wire ccu_cmp_sys_sync_en;
152wire aligned_rst_n;
153wire [4:0] ratio;
154// wire ccu_vco_aligned;
155wire [5:0] pll_div3_lat;
156wire [6:0] pll_div4_lat;
157wire csr_rst_n;
158wire ccu_dbg1_serdes_dtm;
159wire ccu_mio_serdes_dtm;
160wire ccu_io2x_sync_en;
161wire ccu_dr_sync_en;
162wire tcu_atpg_mode;
163wire scan_in;
164wire aclk;
165wire bclk;
166wire scan_out;
167wire rng_arst_l;
168wire ccu_serdes_dtm_lat;
169wire rng_ctl1;
170wire rng_ctl2;
171wire rng_ctl3;
172wire [1:0] rng_ch_sel;
173wire ccu_cmp_io_sync_en;
174wire ccu_io_cmp_sync_en;
175// reg ccu_rst_sync_stable; // for inferred flops
176reg [4:0] shift_amt;
177wire pll_div4_msb;
178wire [4:0] dr_shift_amt;
179
180// internal wire/reg declarations
181
182wire csr_rst;
183reg aligned_rst_q1_n;
184// reg [4:0] csr_rst_cnt; // for inferred flops
185wire [5:0] pll_div2_lat;
186wire gclk_rst_n;
187// reg [4:0] align_pulse_cnt; // for inferred flops
188
189// for instantiated flops
190wire [5:0] csr_rst_cnt;
191wire [4:0] align_pulse_cnt;
192wire ccu_rst_sync_stable;
193
194
195wire rst_ccu;
196wire ccu_rst_sync_stable_in;
197wire [5:0] csr_rst_cnt_in;
198
199
200wire [4:0] align_pulse_cnt_in;
201wire unused;
202
203// wire rst_ccu_gated;
204// wire rst_ccu_n_gated;
205wire csr_rst_n_gated;
206wire csr_rst_gated;
207
208wire io_phase_180_q1;
209wire io_phase_0_q1;
210
211wire serdes_dtm1_lat;
212wire serdes_dtm2_lat;
213
214reg aligned_rst_q2_n;
215reg aligned_rst_q3_n;
216
217wire gclk_rst ;
218wire gclk_rst_n_gated ;
219wire gclk_rst_gated ;
220
221
222assign gclk_rst = ~gclk_rst_n;
223assign gclk_rst_n_gated = tcu_atpg_mode | gclk_rst_n;
224assign gclk_rst_gated = ~gclk_rst_n_gated;
225
226// assign rst_ccu_gated = ~tcu_atpg_mode & rst_ccu;
227// assign rst_ccu_n_gated = tcu_atpg_mode | rst_ccu_;
228
229assign csr_rst_gated = ~tcu_atpg_mode & csr_rst;
230assign csr_rst_n_gated = tcu_atpg_mode | csr_rst_n;
231
232assign dr_shift_amt = shift_amt;
233
234assign csr_rst = ~csr_rst_n;
235assign ccu_serdes_dtm_lat = serdes_dtm1_lat | serdes_dtm2_lat;
236
237// clear rng during por_ or wmr_ with frequency change
238assign rng_arst_l = rst_ccu_;
239
240assign scan_out = scan_in;
241
242assign ccu_mio_serdes_dtm = serdes_dtm1_lat;
243assign ccu_dbg1_serdes_dtm = serdes_dtm1_lat;
244
245
246// ***********************************************
247// synchronizer flop
248// ***********************************************
249
250wire pre_gclk_rst_n;
251
252assign gclk_rst_n = rst_ccu_ & pre_gclk_rst_n;
253
254cl_a1_clksyncff_4x bf_sync1 (
255 .l1clk (l1clk), .d (rst_ccu_), .q(pre_gclk_rst_n),
256 .si(1'b0), .siclk(1'b0), .soclk (1'b0), .so()
257);
258
259
260// ***********************************************
261// now generate reset aligned w/aligned pulse
262// ***********************************************
263
264// BEGIN_ECO POST TAPEOUT - N2 BUG
265wire gclk_rst_n_eco;
266wire aligned_hold;
267wire aligned_hold_q;
268
269assign aligned_hold = aligned | aligned_hold_q;
270
271my_msff_arst_4x gclk_rst_hold_eco (
272 .d ( aligned_hold ), .q ( aligned_hold_q ), .reset ( gclk_rst ), .l1clk ( l1clk ),
273 .si(1'b0), .siclk(1'b0), .soclk (1'b0), .so()
274);
275// END_ECO POST TAPEOUT
276
277always @( posedge l1clk) begin
278 if ( !gclk_rst_n ) begin // POST TAPEOUT ECO
279 aligned_rst_q1_n <= 1'b0; // internal
280 aligned_rst_q2_n <= 1'b0; // additional pipe stage
281 aligned_rst_q3_n <= 1'b0; // external
282 end else begin
283 aligned_rst_q1_n <= aligned & aligned_hold_q; // POST TAPEOUT ECO
284 aligned_rst_q2_n <= aligned_rst_q1_n;
285 aligned_rst_q3_n <= aligned_rst_q3_n |
286 (aligned_rst_q2_n & (~aligned_rst_q1_n));
287
288 end
289end
290
291assign aligned_rst_n = aligned_rst_q3_n;
292
293// ***********************************************
294// generate delayd rst signal for csr stuff
295// ***********************************************
296assign csr_rst_n = (csr_rst_cnt==`CCU_CSR_RST_CNT)? 1'b1: 1'b0;
297
298assign csr_rst_cnt_in[5:0] = (csr_rst_cnt == `CCU_CSR_RST_CNT) ? csr_rst_cnt[5:0] : (csr_rst_cnt + 6'b1) ;
299
300wire aligned_hold_q_gated = aligned_hold_q | tcu_atpg_mode; // POST TAPEOUT ECO
301
302ccu_msff_arst_4x_6 rst_cnt_bank6 (
303 .q(csr_rst_cnt),
304 .so(),
305 .si (1'b0),
306 .d(csr_rst_cnt_in),
307 .l1clk(l1clk),
308 .siclk (aclk),
309 .soclk (bclk),
310 .reset_n (aligned_hold_q_gated) // POST TAPEOUT ECO - changed from gclk_rst_n_gated
311);
312
313
314// ***********************************************
315// latch in divider value similar to pll's
316// ***********************************************
317
318assign pll_div4_msb = pll_div4_lat[4]; // ccu only needs bit 4 of 6:0
319assign pll_div4_lat[6] = pll_div4[6]; // this is purely for maintaining 7 inputs to pll
320
321ccu_blatch_4x_6 pll_div2_bnk6 (
322 .latout (pll_div2_lat), .d(pll_div2), .l1clk(pll_arst_l),
323 .so(), .si (1'b0), .siclk (1'b0), .soclk (1'b0)
324);
325
326ccu_blatch_4x_6 pll_div3_bnk6 (
327 .latout (pll_div3_lat), .d(pll_div3), .l1clk(pll_arst_l),
328 .so(), .si (1'b0), .siclk (1'b0), .soclk (1'b0)
329);
330
331ccu_blatch_4x_6 pll_div4_bnk6 (
332 .latout (pll_div4_lat[5:0]), .d(pll_div4[5:0]),
333 .l1clk(pll_arst_l), .so(), .si (1'b0), .siclk (1'b0), .soclk (1'b0)
334);
335
336ccu_blatch_4x_1 serdes_dtm1_bnk1 (
337 .latout (serdes_dtm1_lat), .d(serdes_dtm1), .l1clk(pll_arst_l),
338 .so(), .si (1'b0), .siclk (1'b0), .soclk (1'b0)
339);
340
341ccu_blatch_4x_1 serdes_dtm1_bnk2 (
342 .latout (serdes_dtm2_lat), .d(serdes_dtm2), .l1clk(pll_arst_l),
343 .so(), .si (1'b0), .siclk (1'b0), .soclk (1'b0)
344);
345
346
347// ***********************************************
348// align shift value
349// ***********************************************
350always @ (pll_div2_lat) begin
351 case (pll_div2_lat)
352 6'h07: shift_amt = 5'h02;
353 6'h08: shift_amt = 5'h03;
354 6'h09: shift_amt = 5'h04;
355 6'h0A: shift_amt = 5'h05;
356 6'h0B: shift_amt = 5'h06;
357 6'h0C: shift_amt = 5'h07;
358 6'h0D: shift_amt = 5'h08;
359 6'h0E: shift_amt = 5'h09;
360 6'h0F: shift_amt = 5'h0A;
361 6'h10: shift_amt = 5'h0B;
362 6'h11: shift_amt = 5'h0C;
363 6'h12: shift_amt = 5'h0D;
364 6'h13: shift_amt = 5'h0E;
365 6'h14: shift_amt = 5'h0F;
366 6'h15: shift_amt = 5'h10;
367 default: shift_amt = 5'h02;
368 endcase
369end
370
371// assign ccu_vco_aligned = aligned;
372
373// count align cycles, repeat after CCU_ALIGN_CNT
374assign align_pulse_cnt_in = (aligned == 1'b1) ?
375 ((align_pulse_cnt == `CCU_ALIGN_CNT) ? 5'b0 : (align_pulse_cnt + 5'b1) ) :
376 align_pulse_cnt;
377
378ccu_msff_arst_4x_5 align_pulse_cnt_bank5 (
379 .q(align_pulse_cnt),
380 .si(1'b0),
381 .so(),
382 .d(align_pulse_cnt_in),
383 .l1clk(l1clk),
384 .siclk (aclk),
385 .soclk (bclk),
386 .reset_n (csr_rst_n_gated)
387);
388
389
390// generate ccu_rst_sync_stable signal after CCU_ALIGN_CNT
391// ref_clk (= 2 * CCU_ALIGN_CNT sys_clk cycles)
392
393assign ccu_rst_sync_stable_in = (align_pulse_cnt == `CCU_ALIGN_CNT) ? 1'b1 : ccu_rst_sync_stable;
394assign rst_ccu = ~rst_ccu_;
395
396my_msff_arst_4x ccu_rst_sync_stable_ff (
397 .q(ccu_rst_sync_stable),
398 .so(),
399 .d(ccu_rst_sync_stable_in),
400 .l1clk(l1clk),
401 .si(1'b0),
402 .siclk(aclk),
403 .soclk(bclk),
404 .reset(csr_rst_gated) // .reset(csr_rst)
405);
406
407
408// generate cmp->dr ratio
409//
410// normal mode: always cmp multiplier/4, range [2.00,5.50]x
411// use lsb to determine fractional parts
412// 00 => .00
413// 01 => .25
414// 10 => .50
415// 11 => .75
416// d3=2, pll_div4/2 is true ratio
417//
418// func: assign ratio[4:0] = pll_div2_lat[4:0];
419// dtm: (pll_div2+1)/2 = ratio
420
421
422// shift io-cmp & cmp-io sync pulses by a cycle in functional mode
423my_msff_arst_4x sync1_shift (
424 .q(io_phase_180_q1), .so(), .d(io_phase_180), .l1clk(l1clk),
425 .si(1'b0), .siclk(aclk), .soclk(bclk), .reset(gclk_rst_gated)
426);
427
428my_msff_arst_4x sync2_shift (
429 .q(io_phase_0_q1), .so(), .d(io_phase_0), .l1clk(l1clk),
430 .si(1'b0), .siclk(aclk), .soclk(bclk), .reset(gclk_rst_gated)
431);
432
433my_msff_arst_4x sys_cmp_sync_shift1 (
434 .q(ccu_pre_sys_cmp_sync_en ), .so(), .d(aligned), .l1clk(l1clk),
435 .si(1'b0), .siclk(aclk), .soclk(bclk), .reset(gclk_rst_gated)
436);
437
438
439// take care of dtm mode
440wire ccu_dr_sync_en_q2;
441wire ccu_dr_sync_en_q1;
442wire ccu_pre_cmp_io_sync_en;
443wire ccu_pre_io_cmp_sync_en;
444wire ccu_pre_io2x_sync_en;
445
446assign ratio[4:0] = ccu_serdes_dtm_lat? pll_div2_lat[4:0] : pll_div4_lat[4:0];
447assign io_div = ccu_serdes_dtm_lat? pll_div2_lat[4:0] : 5'b00011;
448assign io2x_div = ccu_serdes_dtm_lat? pll_div2_lat[4:0] : 5'b00001;
449
450assign ccu_pre_io2x_sync_en = ccu_serdes_dtm_lat?ccu_dr_sync_en_q1:io2x_phase_180; // removed inversion
451assign ccu_pre_cmp_io_sync_en = ccu_serdes_dtm_lat?ccu_dr_sync_en_q1:io_phase_180_q1;
452// FREEZE FEATURE BEGIN
453// assign ccu_pre_io_cmp_sync_en=ccu_serdes_dtm_lat?ccu_dr_sync_en_q1:io_phase_0_q1;
454assign ccu_pre_io_cmp_sync_en = io_phase_0_q1;
455// FREEZE FEATURE END
456assign ccu_cmp_sys_sync_en = ccu_sys_cmp_sync_en; // unaffected by dtm
457
458
459// account for # delay in pre-grid driver
460//
461
462
463assign ccu_dr_sync_en = ccu_dr_sync_en_q2; // shift twice needed here
464
465
466my_msff_arst_4x dr_sync_shift1 (
467 .q(ccu_dr_sync_en_q1), .so(), .d(ccu_pre_dr_sync_en), .l1clk(l1clk),
468 .si(1'b0), .siclk(aclk), .soclk(bclk), .reset(gclk_rst_gated)
469);
470
471my_msff_arst_4x dr_sync_shift2 (
472 .q(ccu_dr_sync_en_q2), .so(), .d(ccu_dr_sync_en_q1), .l1clk(l1clk),
473 .si(1'b0), .siclk(aclk), .soclk(bclk), .reset(gclk_rst_gated)
474);
475
476
477// finally, shift all sync pulses by single cycle to compensate
478// for race-thru in cluster header
479ccu_msff_arst_4x_4 all_sync_shift (
480 .l1clk(l1clk),
481 .q({ccu_sys_cmp_sync_en,ccu_io2x_sync_en,
482 ccu_io_cmp_sync_en,ccu_cmp_io_sync_en}),
483 .d({ccu_pre_sys_cmp_sync_en,ccu_pre_io2x_sync_en,
484 ccu_pre_io_cmp_sync_en,ccu_pre_cmp_io_sync_en}),
485 .reset_n(gclk_rst_n_gated) ,
486 .si(1'b0), .siclk(aclk), .soclk(bclk), .so()
487);
488
489// rng channel encoding
490// =====================
491// ctl3 ctl2 ctl1 ch_sel[1:0]
492// 0 0 0 11 - really don't care
493// 0 0 1 00 - select ch1
494// 0 1 0 01 - select ch2
495// 1 0 0 10 - select ch3
496// 1 0 1 11 - select all ch
497// 1 1 0 11 - select all ch
498// 1 1 1 11 - select all ch
499// 0 1 1 11 - select all ch
500
501// a = ctl3, b = ctl2, c = ctl1
502// ch0 = b + ac + !a!c
503// ch1 = a + bc + !b!c
504assign rng_ch_sel[0] = rng_ctl2 | (rng_ctl3 & rng_ctl1) | (~rng_ctl3 & ~rng_ctl1);
505assign rng_ch_sel[1] = rng_ctl3 | (rng_ctl2 & rng_ctl1) | (~rng_ctl2 & ~rng_ctl1);
506
507
508endmodule
509