Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | // ========== Copyright Header Begin ========================================== |
2 | // | |
3 | // OpenSPARC T2 Processor File: ccu_csr.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 | `define PLL_REG 40'h8300000000 | |
36 | `define RNGCTL_REG 40'h8300000020 | |
37 | `define RNGDAT_REG 40'h8300000030 | |
38 | ||
39 | ||
40 | // POLYNOMIAL DEFINITION | |
41 | // x64 + x61 + x57 + x56 + x52 + x51 + x50 + x48 + x47 + | |
42 | // x46 + x43 + x42 + x41 + x39 + x38 + x37 + x35 + x32 + | |
43 | // x28 + x25 + x22 + x21 + x17 + x15 + x13 + x12 + x11 + | |
44 | // x7 + x5 + x + 1 | |
45 | ||
46 | // poly coeffecients starting with x^63 going down to x^0 (x^64 tap is always 1) | |
47 | `define RNGCRC_POLY 64'b00100011000111011_100111011101001_000100100110001010111_00010100011 | |
48 | // default values - currently set to 62 | |
49 | `define DEFAULT_RNG_WAIT_VAL 16'h003E | |
50 | ||
51 | // FIELD DEFINITION | |
52 | `define PLL_DIV1 5:0 | |
53 | `define PLL_DIV2 11:6 | |
54 | `define PLL_DIV3 17:12 | |
55 | `define PLL_DIV4 24:18 | |
56 | `define ST_PHASE_HI 25 | |
57 | `define ST_DELAY_CMP 27:26 | |
58 | `define SERDES_DTM1 28 | |
59 | `define SERDES_DTM2 29 | |
60 | `define ALIGN_SHIFT 31:30 | |
61 | `define CHANGE 32 | |
62 | `define PLL_CHAR_IN 33 | |
63 | `define ST_DELAY_DR 35:34 | |
64 | `define PLL_CLAMP_FLTR 36 | |
65 | `define PLL_RES 63:37 | |
66 | ||
67 | `define RNG_RES 63:25 | |
68 | `define RNG_WAIT_CNT 24:9 | |
69 | `define RNG_BYPASS 8 | |
70 | `define RNG_VCOCTRL_SEL 7:6 | |
71 | `define RNG_ANLG_SEL 5:4 | |
72 | `define RNG_CTL4 3 | |
73 | `define RNG_CTL3 2 | |
74 | `define RNG_CTL2 1 | |
75 | `define RNG_CTL1 0 | |
76 | ||
77 | ||
78 | // STATE DEFINITION | |
79 | `define CCUCSR_IDLE 3'b000 | |
80 | `define CCUCSR_WRITE 3'b001 | |
81 | `define CCUCSR_READ 3'b010 | |
82 | `define CCUCSR_READ_SUCCESS 3'b011 | |
83 | `define CCUCSR_READ_PROB 3'b100 | |
84 | ||
85 | `timescale 1 ns / 10 ps | |
86 | ||
87 | module ccu_csr ( | |
88 | // ucb connectivity side | |
89 | io_clk, | |
90 | ||
91 | wr_req_vld, | |
92 | addr_in, | |
93 | data_in, | |
94 | req_accepted, | |
95 | ||
96 | rd_req_vld, | |
97 | thr_id_in, | |
98 | buf_id_in, | |
99 | ||
100 | rack_busy, | |
101 | ||
102 | data_out, | |
103 | thr_id_out, | |
104 | buf_id_out, | |
105 | rd_ack_vld, | |
106 | rd_nack_vld, | |
107 | ||
108 | int_busy, | |
109 | dev_id, | |
110 | int_vld, | |
111 | ||
112 | // other block connectivity | |
113 | rst_n, | |
114 | wmr_protect, | |
115 | rng_data_in, | |
116 | // RNG outputs | |
117 | rng_ctl1, | |
118 | rng_ctl2, | |
119 | rng_ctl3, | |
120 | rng_bypass, | |
121 | rng_vcoctrl_sel, | |
122 | rng_anlg_sel, | |
123 | // PLL outputs | |
124 | pll_div1, | |
125 | pll_div2, | |
126 | pll_div3, | |
127 | pll_div4, | |
128 | st_phase_hi, | |
129 | st_delay_cmp, | |
130 | st_delay_dr, | |
131 | serdes_dtm1, | |
132 | serdes_dtm2, | |
133 | change, | |
134 | align_shift, | |
135 | pll_clamp_fltr, | |
136 | pll_char_in | |
137 | ); | |
138 | ||
139 | // ***************************************** | |
140 | // PORT DECLARATION | |
141 | // ***************************************** | |
142 | ||
143 | // ucb connectivity side | |
144 | // ------------------------ | |
145 | input io_clk; | |
146 | ||
147 | // CSR Write case: | |
148 | input wr_req_vld; // when signal is asserted, following are valid to Local Unit | |
149 | input [39:0] addr_in; // Based on addr_in Local Unit will update the CSR info accordingly | |
150 | input [63:0] data_in; // Write command to invalid address should be discarded silently | |
151 | output req_accepted; // CSR Reg Block will assert a 1 clock pulse to indicate acceptance | |
152 | ||
153 | ||
154 | // CSR read case: | |
155 | input rd_req_vld; // when signal is asserted, following are valid to Local Unit | |
156 | // input [39:0] addr_in; // Based on addr_in Local Unit will read the CSR info accordingly | |
157 | input [5:0] thr_id_in; | |
158 | input [1:0] buf_id_in; | |
159 | input rack_busy; // until deasserted, CSR reg Block should NOT assert rd_ack_vld/"rd_nack_vld | |
160 | ||
161 | // output req_accepted; // CSR Reg Block will assert a 1 clock pulse to indicate acceptance | |
162 | output [63:0] data_out; | |
163 | output [5:0] thr_id_out; | |
164 | output [1:0] buf_id_out; | |
165 | output rd_ack_vld; // CSR Reg Block asserts this to send return data to CSR Interface logic | |
166 | output rd_nack_vld; // if not valid, Reg Block asserts this along with thr_id_in and buf_id_in | |
167 | ||
168 | ||
169 | // Interrupts : // unused stuff for now | |
170 | output int_busy; | |
171 | output [5:0] dev_id; // When Local Unit needs to send intr to NCU, there should be set | |
172 | output int_vld; // asserted indicates a valid interrupt to NCU, and asserts only when int_busy is 0. | |
173 | ||
174 | ||
175 | // other block connectivity | |
176 | // ------------------------ | |
177 | input rst_n; | |
178 | input wmr_protect; | |
179 | input rng_data_in; | |
180 | ||
181 | // PLL_REG fields | |
182 | output [5:0] pll_div1; | |
183 | output [5:0] pll_div2; | |
184 | output [5:0] pll_div3; | |
185 | output [6:0] pll_div4; | |
186 | ||
187 | output pll_char_in; | |
188 | output change; | |
189 | output [1:0] align_shift; | |
190 | output serdes_dtm2; | |
191 | output serdes_dtm1; | |
192 | output [1:0] st_delay_cmp; | |
193 | output [1:0] st_delay_dr; | |
194 | output st_phase_hi; | |
195 | output pll_clamp_fltr; | |
196 | ||
197 | ||
198 | // RNG_CTL fields | |
199 | output rng_ctl1; | |
200 | output rng_ctl2; | |
201 | output rng_ctl3; | |
202 | output rng_bypass; | |
203 | output [1:0] rng_vcoctrl_sel; | |
204 | output [1:0] rng_anlg_sel; | |
205 | ||
206 | ||
207 | // ***************************************** | |
208 | // WIRE/REG DECLARATION | |
209 | // ***************************************** | |
210 | ||
211 | // ucb connectivity side | |
212 | wire io_clk; | |
213 | ||
214 | wire wr_req_vld; | |
215 | wire [39:0] addr_in; | |
216 | wire [63:0] data_in; | |
217 | reg req_accepted; | |
218 | ||
219 | wire rd_req_vld; | |
220 | wire [5:0] thr_id_in; | |
221 | wire [1:0] buf_id_in; | |
222 | wire rack_busy; | |
223 | ||
224 | reg [63:0] data_out; | |
225 | // reg [5:0] thr_id_out; | |
226 | // reg [1:0] buf_id_out; | |
227 | wire [5:0] thr_id_out; | |
228 | wire [1:0] buf_id_out; | |
229 | reg rd_ack_vld; | |
230 | reg rd_nack_vld; | |
231 | ||
232 | wire int_busy; | |
233 | wire [5:0] dev_id; | |
234 | wire int_vld; | |
235 | ||
236 | ||
237 | wire rst_n; | |
238 | wire wmr_protect; | |
239 | wire rng_data_in; | |
240 | // PLL_REG fields | |
241 | wire [5:0] pll_div1; | |
242 | wire [5:0] pll_div2; | |
243 | wire [5:0] pll_div3; | |
244 | wire [6:0] pll_div4; | |
245 | ||
246 | wire pll_char_in; | |
247 | wire change; | |
248 | wire [1:0] align_shift; | |
249 | wire serdes_dtm2; | |
250 | wire serdes_dtm1; | |
251 | wire [1:0] st_delay_cmp; | |
252 | wire [1:0] st_delay_dr; | |
253 | wire st_phase_hi; | |
254 | wire pll_clamp_fltr; | |
255 | ||
256 | ||
257 | // RNG_CTL fields | |
258 | wire rng_ctl1; | |
259 | wire rng_ctl2; | |
260 | wire rng_ctl3; | |
261 | wire rng_bypass; | |
262 | wire [1:0] rng_vcoctrl_sel; | |
263 | wire [1:0] rng_anlg_sel; | |
264 | wire [15:0] rng_wait_cnt; | |
265 | ||
266 | // --------------------------------- | |
267 | // internal wire/reg stuff | |
268 | // --------------------------------- | |
269 | ||
270 | wire rng_data_in_gated; | |
271 | ||
272 | // for instantiated flops | |
273 | wire [63:0] pll_r; | |
274 | wire [63:0] rngctl_r; | |
275 | wire [63:0] rngdat_r; | |
276 | wire rng_ctl4; | |
277 | wire [2:0] state; | |
278 | ||
279 | wire rng_data_synced; | |
280 | ||
281 | wire pll_match ; | |
282 | wire rngctl_match ; | |
283 | wire rngdat_match ; | |
284 | wire pll_wr_en; | |
285 | wire rngctl_wr_en; | |
286 | // wire rngdat_wr_en; | |
287 | ||
288 | wire pll_rd_en; | |
289 | wire rngctl_rd_en; | |
290 | wire rngdat_rd_en; | |
291 | ||
292 | wire wr_ok; | |
293 | wire rd_ok; | |
294 | wire rd_nok; | |
295 | ||
296 | wire l1clk; | |
297 | ||
298 | wire rng_busy; | |
299 | wire rng_cnt_reached; | |
300 | reg [15:0] rng_cnt; | |
301 | ||
302 | wire [63:0] lfsr_in; | |
303 | reg [63:0] lfsr_data; | |
304 | wire [63:0] msb_sel; // pick out msb based on poly coeff | |
305 | wire [63:0] poly; // given in decreasing powers of x | |
306 | wire lfsr_fdbk; | |
307 | ||
308 | wire [63:0] lfsr_data_muxed; | |
309 | wire [15:0] max_cnt; | |
310 | ||
311 | wire rng_wait_done; | |
312 | reg rng_cnt_reached_q1; | |
313 | // *********************************************************** | |
314 | // Unused outputs | |
315 | // *********************************************************** | |
316 | ||
317 | assign int_vld = 1'b0; | |
318 | assign int_busy = 1'b0; | |
319 | assign dev_id = 6'b0_0000; | |
320 | ||
321 | // *********************************************************** | |
322 | // CSR Fields | |
323 | // *********************************************************** | |
324 | ||
325 | assign pll_div1 = pll_r[`PLL_DIV1]; | |
326 | assign pll_div2 = pll_r[`PLL_DIV2]; | |
327 | assign pll_div3 = pll_r[`PLL_DIV3]; | |
328 | assign pll_div4 = pll_r[`PLL_DIV4]; | |
329 | assign st_phase_hi = pll_r[`ST_PHASE_HI]; | |
330 | assign st_delay_cmp = pll_r[`ST_DELAY_CMP]; | |
331 | assign serdes_dtm1 = pll_r[`SERDES_DTM1]; | |
332 | assign serdes_dtm2 = pll_r[`SERDES_DTM2]; | |
333 | assign align_shift = pll_r[`ALIGN_SHIFT]; | |
334 | assign change = pll_r[`CHANGE]; | |
335 | assign pll_char_in = pll_r[`PLL_CHAR_IN]; | |
336 | assign st_delay_dr = pll_r[`ST_DELAY_DR]; // late addition | |
337 | assign pll_clamp_fltr = pll_r[`PLL_CLAMP_FLTR]; // late addition | |
338 | ||
339 | assign rng_ctl1 = rngctl_r[`RNG_CTL1]; | |
340 | assign rng_ctl2 = rngctl_r[`RNG_CTL2]; | |
341 | assign rng_ctl3 = rngctl_r[`RNG_CTL3]; | |
342 | assign rng_ctl4 = rngctl_r[`RNG_CTL4]; | |
343 | assign rng_anlg_sel = rngctl_r[`RNG_ANLG_SEL]; | |
344 | assign rng_vcoctrl_sel = rngctl_r[`RNG_VCOCTRL_SEL]; | |
345 | assign rng_bypass = rngctl_r[`RNG_BYPASS]; | |
346 | assign rng_wait_cnt = rngctl_r[`RNG_WAIT_CNT]; | |
347 | ||
348 | // address decodes & read/write enables | |
349 | ||
350 | assign pll_match = (addr_in == `PLL_REG); | |
351 | assign rngctl_match = (addr_in == `RNGCTL_REG); | |
352 | assign rngdat_match = (addr_in == `RNGDAT_REG); | |
353 | ||
354 | assign pll_wr_en = wr_req_vld & pll_match; | |
355 | assign rngctl_wr_en = wr_req_vld & rngctl_match; | |
356 | // assign rngdat_wr_en = wr_req_vld & rngdat_match; | |
357 | ||
358 | assign pll_rd_en = rd_req_vld & pll_match; | |
359 | assign rngctl_rd_en = rd_req_vld & rngctl_match; | |
360 | assign rngdat_rd_en = rd_req_vld & rngdat_match; | |
361 | ||
362 | ||
363 | // write success -- has no effect on acknowledge | |
364 | assign wr_ok = (pll_wr_en | rngctl_wr_en | wr_req_vld); | |
365 | ||
366 | // read success | |
367 | assign rd_ok = (pll_rd_en | rngctl_rd_en | rngdat_rd_en ); | |
368 | ||
369 | // read no success | |
370 | assign rd_nok = rd_req_vld & ~(pll_match | rngctl_match | rngdat_match); | |
371 | ||
372 | ||
373 | // *********************************************************** | |
374 | // CSR Write implementation: | |
375 | // *********************************************************** | |
376 | // reg updates | |
377 | ||
378 | wire rst_gated_n; | |
379 | assign rst_gated_n = rst_n | wmr_protect; | |
380 | ||
381 | ||
382 | // WARM RESET PROTECTED FLOPS | |
383 | /* commented out to replace with instantiated flops | |
384 | ||
385 | always @(posedge l1clk or negedge rst_gated_n) begin | |
386 | if (!rst_gated_n) begin | |
387 | // pll default values | |
388 | `PLL_DIV1 <= 6'h01; // /2 of sysclk 00_0001 | |
389 | `PLL_DIV2 <= 6'h07; // x8 of sysclk/2 00_0111 | |
390 | `PLL_DIV3 <= 6'h00; // no post-division 00_0000 | |
391 | `PLL_DIV4 <= 7'h04; // divide by 2 00_0010_0 | |
392 | `ST_PHASE_HI <= 1'b0; 0 | |
393 | `ST_DELAY_A <= 2'b0; 00 | |
394 | `SERDES_DTM1 <= 1'b0; 0 | |
395 | `SERDES_DTM2 <= 1'b0; 0 | |
396 | `ALIGN_SHIFT <= 2'b0; 00 | |
397 | `CHANGE <= 1'b1; 1 | |
398 | `PLL_CHAR_IN <= 1'b0; 0 | |
399 | `PLL_RES <= 30'b0; 00_0000_0000_0000_0000 | |
400 | end else begin | |
401 | pll_r <= (!wmr_protect && pll_wr_en)?data_in:pll_r; | |
402 | end | |
403 | end | |
404 | */ | |
405 | ||
406 | wire rst_gated; | |
407 | assign rst_gated = ~rst_gated_n; | |
408 | ||
409 | wire [63:0] pll_r_tmp; | |
410 | wire [63:0] pll_r_in; | |
411 | wire [63:0] pll_r_pre_in; | |
412 | ||
413 | wire [5:0] mask_div1; | |
414 | wire [5:0] mask_div2; | |
415 | wire [5:0] mask_div3; | |
416 | wire [6:0] mask_div4; | |
417 | ||
418 | // mask bits help to set to 1 during reset where needed | |
419 | // (aka use default values) | |
420 | assign mask_div1 = 6'b00_0001; | |
421 | assign mask_div2 = 6'b00_0111; | |
422 | assign mask_div3 = 6'b00_0001; | |
423 | assign mask_div4 = 7'b00_0100_0; | |
424 | ||
425 | assign pll_r_pre_in = (!wmr_protect && pll_wr_en)?data_in:pll_r; | |
426 | ||
427 | // invert inputs where needed | |
428 | assign pll_r_in = pll_r_pre_in ^ {31'b0, 1'b1, 7'b0, mask_div4, mask_div3, mask_div2, mask_div1}; | |
429 | ||
430 | ccu_msff_arst_4x_64 pll_r_bank64 ( | |
431 | .q (pll_r_tmp), .reset_n (rst_gated_n), .d (pll_r_in), .l1clk (l1clk), | |
432 | .si (1'b0), .siclk (1'b0), .soclk (1'b0), .so () | |
433 | ); | |
434 | ||
435 | assign pll_r[`PLL_DIV1 ] = pll_r_tmp[`PLL_DIV1 ] ^ mask_div1; | |
436 | assign pll_r[`PLL_DIV2 ] = pll_r_tmp[`PLL_DIV2 ] ^ mask_div2; | |
437 | assign pll_r[`PLL_DIV3 ] = pll_r_tmp[`PLL_DIV3 ] ^ mask_div3; | |
438 | assign pll_r[`PLL_DIV4 ] = pll_r_tmp[`PLL_DIV4 ] ^ mask_div4; | |
439 | assign pll_r[`ST_PHASE_HI ] = pll_r_tmp[`ST_PHASE_HI ]; | |
440 | assign pll_r[`ST_DELAY_CMP] = pll_r_tmp[`ST_DELAY_CMP]; // from `st_delay_a | |
441 | assign pll_r[`SERDES_DTM1 ] = pll_r_tmp[`SERDES_DTM1 ]; | |
442 | assign pll_r[`SERDES_DTM2 ] = pll_r_tmp[`SERDES_DTM2 ]; | |
443 | assign pll_r[`ALIGN_SHIFT ] = pll_r_tmp[`ALIGN_SHIFT ]; | |
444 | assign pll_r[`CHANGE ] = ~pll_r_tmp[`CHANGE ]; // bit is 1 by default | |
445 | assign pll_r[`PLL_CHAR_IN ] = pll_r_tmp[`PLL_CHAR_IN ]; | |
446 | assign pll_r[`ST_DELAY_DR ] = pll_r_tmp[`ST_DELAY_DR ]; // late addition | |
447 | assign pll_r[`PLL_CLAMP_FLTR] = pll_r_tmp[`PLL_CLAMP_FLTR]; // late addition | |
448 | assign pll_r[`PLL_RES ] = pll_r_tmp[`PLL_RES ]; | |
449 | ||
450 | ||
451 | // NOT WARM RESET PROTECTED | |
452 | /* commented out to replace with instantiated flops | |
453 | ||
454 | always @(posedge l1clk or negedge rst_n) begin | |
455 | if (!rst_n) begin | |
456 | // rng default values | |
457 | `RNG_RES <= 55'b0; | |
458 | `RNG_BYPASS <= 1'b0; | |
459 | `RNG_VCOCTRL_SEL <= 2'b0; | |
460 | `RNG_ANLG_SEL <= 2'b0; | |
461 | `RNG_CTL4 <= 1'b0; | |
462 | `RNG_CTL3 <= 1'b1; | |
463 | `RNG_CTL2 <= 1'b1; | |
464 | `RNG_CTL1 <= 1'b1; | |
465 | end else begin | |
466 | rngctl_r <= (rngctl_wr_en)?data_in:rngctl_r; | |
467 | end | |
468 | end | |
469 | */ | |
470 | ||
471 | wire [63:0] rngctl_r_in; | |
472 | wire [63:0] rngctl_r_tmp; | |
473 | wire [63:0] rngctl_r_pre_in; | |
474 | ||
475 | wire rst; | |
476 | assign rst = ~rst_n; | |
477 | ||
478 | assign rngctl_r_pre_in = (rngctl_wr_en)?data_in:rngctl_r; | |
479 | assign rngctl_r_in = rngctl_r_pre_in ^ | |
480 | {39'b0,`DEFAULT_RNG_WAIT_VAL,9'b0_0000_1111}; // invert mask bits | |
481 | ||
482 | ccu_msff_arst_4x_64 rngctl_r_bank64 ( | |
483 | .q (rngctl_r_tmp), .reset_n (rst_n), .d (rngctl_r_in), .l1clk (l1clk), | |
484 | .si (1'b0), .siclk (1'b0), .soclk (1'b0), .so () | |
485 | ); | |
486 | ||
487 | // inversion needed when asynchronously resetting to 1 is desired | |
488 | assign rngctl_r[`RNG_RES] = rngctl_r_tmp[`RNG_RES]; | |
489 | assign rngctl_r[`RNG_WAIT_CNT] = rngctl_r_tmp[`RNG_WAIT_CNT] ^ `DEFAULT_RNG_WAIT_VAL; | |
490 | assign rngctl_r[`RNG_BYPASS] = rngctl_r_tmp[`RNG_BYPASS]; | |
491 | assign rngctl_r[`RNG_VCOCTRL_SEL] = rngctl_r_tmp[`RNG_VCOCTRL_SEL]; | |
492 | assign rngctl_r[`RNG_ANLG_SEL] = rngctl_r_tmp[`RNG_ANLG_SEL]; | |
493 | assign rngctl_r[`RNG_CTL4] = ~rngctl_r_tmp[`RNG_CTL4]; | |
494 | assign rngctl_r[`RNG_CTL3] = ~rngctl_r_tmp[`RNG_CTL3]; | |
495 | assign rngctl_r[`RNG_CTL2] = ~rngctl_r_tmp[`RNG_CTL2]; | |
496 | assign rngctl_r[`RNG_CTL1] = ~rngctl_r_tmp[`RNG_CTL1]; | |
497 | ||
498 | ||
499 | // *********************************************************** | |
500 | // CSR read implementation: | |
501 | // *********************************************************** | |
502 | // reg reads | |
503 | always @(posedge l1clk) begin | |
504 | if (pll_rd_en) data_out <= pll_r; | |
505 | else if (rngctl_rd_en) data_out <= rngctl_r; | |
506 | else if (rngdat_rd_en && rng_wait_done) data_out <= rngdat_r; | |
507 | else data_out <= data_out; | |
508 | end | |
509 | ||
510 | // thread and dev id reads | |
511 | ||
512 | ||
513 | assign thr_id_out[5:0] = thr_id_in[5:0]; | |
514 | assign buf_id_out[1:0] = buf_id_in[1:0]; | |
515 | ||
516 | ||
517 | // *********************************************************** | |
518 | // CSR read/write acknowledgement: | |
519 | // *********************************************************** | |
520 | // finally settled for a simpler moore machine design | |
521 | // | |
522 | // state outputs | |
523 | always @(state) begin | |
524 | case (state) | |
525 | `CCUCSR_IDLE: begin | |
526 | req_accepted = 1'b0; | |
527 | rd_ack_vld = 1'b0; | |
528 | rd_nack_vld = 1'b0; | |
529 | end | |
530 | `CCUCSR_WRITE: begin | |
531 | req_accepted = 1'b1; | |
532 | rd_ack_vld = 1'b0; | |
533 | rd_nack_vld = 1'b0; | |
534 | end | |
535 | `CCUCSR_READ: begin | |
536 | req_accepted = 1'b0; | |
537 | rd_ack_vld = 1'b0; | |
538 | rd_nack_vld = 1'b0; | |
539 | end | |
540 | `CCUCSR_READ_PROB: begin | |
541 | req_accepted = 1'b1; | |
542 | rd_ack_vld = 1'b0; | |
543 | rd_nack_vld = 1'b1; | |
544 | end | |
545 | `CCUCSR_READ_SUCCESS: begin | |
546 | req_accepted = 1'b1; | |
547 | rd_ack_vld = 1'b1; | |
548 | rd_nack_vld = 1'b0; | |
549 | end | |
550 | default: begin | |
551 | req_accepted = 1'b0; | |
552 | rd_ack_vld = 1'b0; | |
553 | rd_nack_vld = 1'b0; | |
554 | end | |
555 | endcase | |
556 | end | |
557 | ||
558 | ||
559 | reg [2:0] state_in; | |
560 | always @(wr_ok or rd_req_vld or rack_busy or rng_busy or rd_ok or rd_nok or state) begin | |
561 | case (state) | |
562 | ||
563 | `CCUCSR_IDLE: begin | |
564 | if (wr_ok) | |
565 | state_in = `CCUCSR_WRITE; | |
566 | else if (rd_req_vld) | |
567 | state_in = `CCUCSR_READ; | |
568 | else | |
569 | state_in = `CCUCSR_IDLE; | |
570 | end | |
571 | ||
572 | `CCUCSR_WRITE: state_in = `CCUCSR_IDLE; // always return to idle | |
573 | ||
574 | `CCUCSR_READ: begin | |
575 | if (rack_busy || rng_busy) // handles special rng read | |
576 | state_in = `CCUCSR_READ; | |
577 | else if (rd_ok) | |
578 | state_in = `CCUCSR_READ_SUCCESS; | |
579 | else if (rd_nok) | |
580 | state_in = `CCUCSR_READ_PROB; | |
581 | else | |
582 | state_in = `CCUCSR_READ; | |
583 | end | |
584 | ||
585 | `CCUCSR_READ_PROB: state_in = `CCUCSR_IDLE; // always return to idle | |
586 | ||
587 | `CCUCSR_READ_SUCCESS: state_in = `CCUCSR_IDLE; // always return to idle | |
588 | ||
589 | default: state_in = `CCUCSR_IDLE; | |
590 | endcase | |
591 | end | |
592 | ||
593 | ||
594 | ccu_msff_arst_4x_3 state_bank3 ( | |
595 | .q(state), | |
596 | .so(), | |
597 | .d(state_in), | |
598 | .l1clk(l1clk), | |
599 | .si(1'b0), | |
600 | .siclk(1'b0), | |
601 | .soclk(1'b0), | |
602 | .reset_n (rst_n) | |
603 | ); | |
604 | ||
605 | ||
606 | // *********************************************************** | |
607 | // rng read mode for diagnostics | |
608 | // *********************************************************** | |
609 | // | |
610 | ||
611 | assign rng_cnt_reached = (rng_cnt == max_cnt); | |
612 | // assign rng_busy = rngdat_rd_en & rng_ctl4 & ~rng_cnt_reached; | |
613 | assign rng_busy = rngdat_rd_en & ~rng_wait_done; | |
614 | assign max_cnt = (rng_ctl4) ? rng_wait_cnt : 16'd62; // + 2 cycles for states | |
615 | ||
616 | // convert rng_cnt_reached to a pulse | |
617 | assign rng_wait_done = ~rng_cnt_reached_q1 & rng_cnt_reached; | |
618 | ||
619 | always @(posedge l1clk) begin | |
620 | if (!rst_n) | |
621 | rng_cnt_reached_q1 <= 1'b0; | |
622 | else | |
623 | rng_cnt_reached_q1 <= rng_cnt_reached; | |
624 | end | |
625 | ||
626 | ||
627 | // count up to max_cnt and hold till "idle" | |
628 | always @(posedge l1clk) begin | |
629 | if (!rst_n) | |
630 | rng_cnt <= 16'h0000; | |
631 | else begin | |
632 | if (state == `CCUCSR_IDLE) | |
633 | rng_cnt <= 16'h0000; | |
634 | else begin | |
635 | if (rng_cnt == max_cnt) | |
636 | rng_cnt <= max_cnt; | |
637 | else | |
638 | rng_cnt <= rng_cnt + 16'h0001; | |
639 | end | |
640 | end | |
641 | end | |
642 | ||
643 | // *********************************************** | |
644 | // synchronizer flop (for rngdata) | |
645 | // *********************************************** | |
646 | ||
647 | assign rng_data_in_gated = (rng_ctl1 | rng_ctl2 | rng_ctl3) & rng_data_in; | |
648 | ||
649 | cl_a1_clksyncff_4x rng_data_syncff ( | |
650 | .l1clk (l1clk), .d (rng_data_in_gated), .q(rng_data_synced), | |
651 | .si(1'b0), .siclk(1'b0), .soclk (1'b0), .so() | |
652 | ); | |
653 | ||
654 | // *********************************************************** | |
655 | // LFSR implementation & update register | |
656 | // *********************************************************** | |
657 | ||
658 | // load serial shift reg/LFSR | |
659 | assign poly = `RNGCRC_POLY ; // [a63..a0] for a63.x^63 + ... a0.x^0, a64=1 | |
660 | // added xor for quicker entropy building; (ctl4==0) -> shift reg, period. | |
661 | assign lfsr_fdbk = rng_ctl4 & (lfsr_data[63] ^ rng_data_synced); | |
662 | assign msb_sel = {64{lfsr_fdbk}} & `RNGCRC_POLY; | |
663 | ||
664 | // flush with one's when a read is successful & (ctl4==1) | |
665 | // need to break next statement into 2 pieces to fix shift-reg bug | |
666 | // assign lfsr_in[63:0] = ((state == `CCUCSR_READ_SUCCESS) && rng_ctl4) ? | |
667 | // 64'hFFFF_FFFF_FFFF_FFFF : {lfsr_data[62:0],1'b0} ^ msb_sel[63:0]; | |
668 | assign lfsr_in[63:1] = ((state == `CCUCSR_READ_SUCCESS) && rng_ctl4) ? | |
669 | 63'h7FFF_FFFF_FFFF_FFFF : lfsr_data[62:0] ^ msb_sel[63:1]; | |
670 | assign lfsr_in[0] = (rng_ctl4 == 1'b0) ? rng_data_synced : | |
671 | ((state == `CCUCSR_READ_SUCCESS) && rng_ctl4) ? 1'b1 : msb_sel[0]; | |
672 | ||
673 | // convert to sync reset for convenience | |
674 | always @(posedge l1clk) begin | |
675 | if (!rst_n) begin | |
676 | lfsr_data <= 64'hFFFF_FFFF_FFFF_FFFF; | |
677 | end else begin | |
678 | lfsr_data <= lfsr_in; | |
679 | end | |
680 | end | |
681 | ||
682 | // update rngdat_r register when done waiting | |
683 | assign lfsr_data_muxed = (rng_wait_done) ? lfsr_data: rngdat_r; | |
684 | ||
685 | // always @(posedge l1clk) rngdat_r <= lfsr_data_muxed; | |
686 | // do not flop in this stage | |
687 | assign rngdat_r = lfsr_data_muxed; | |
688 | ||
689 | // *********************************************************** | |
690 | // L1 header - io clk | |
691 | // *********************************************************** | |
692 | // | |
693 | cl_a1_l1hdr_8x header_io ( | |
694 | .l2clk(io_clk), | |
695 | .l1clk(l1clk), | |
696 | .pce(1'b1), | |
697 | .se(1'b0), | |
698 | .pce_ov(1'b0), | |
699 | .stop(1'b0) | |
700 | ); | |
701 | ||
702 | ||
703 | ||
704 | endmodule | |
705 | ||
706 |