blob: aa05c4372ec04968dc0981189c82714b2299d5e3 [file] [log] [blame]
Timothy Chen3525aa82020-04-23 23:23:18 -07001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4//
5// The overall clock manager
6
7`include "prim_assert.sv"
8
9<%
10clks_attr = cfg['clocks']
11srcs = clks_attr['srcs']
12%>
13
14module clkmgr import clkmgr_pkg::*; (
Timothy Chen33b3b9d2020-05-08 10:14:17 -070015 // Primary module control clocks and resets
16 // This drives the register interface
Timothy Chen3525aa82020-04-23 23:23:18 -070017 input clk_i,
18 input rst_ni,
Timothy Chen33b3b9d2020-05-08 10:14:17 -070019
20 // System clocks and resets
21 // These are the source clocks for the system
Timothy Chen3525aa82020-04-23 23:23:18 -070022% for src in srcs:
23 input clk_${src['name']}_i,
Timothy Chen33b3b9d2020-05-08 10:14:17 -070024 % if src['aon'] == 'no':
Timothy Chen3525aa82020-04-23 23:23:18 -070025 input rst_${src['name']}_ni,
Timothy Chen33b3b9d2020-05-08 10:14:17 -070026 % endif
Timothy Chen3525aa82020-04-23 23:23:18 -070027% endfor
28
Timothy Chenb63f3b82020-06-30 17:10:57 -070029 // Resets for derived clocks
30 // clocks are derived locally
31% for src in div_srcs:
32 input rst_${src['name']}_ni,
33% endfor
34
Timothy Chen3525aa82020-04-23 23:23:18 -070035 // Bus Interface
36 input tlul_pkg::tl_h2d_t tl_i,
37 output tlul_pkg::tl_d2h_t tl_o,
38
39 // pwrmgr interface
40 input pwrmgr_pkg::pwr_clk_req_t pwr_i,
41 output pwrmgr_pkg::pwr_clk_rsp_t pwr_o,
42
43 // dft interface
Timothy Chen5649c2a2021-02-08 18:32:22 -080044 input lc_ctrl_pkg::lc_tx_t scanmode_i,
Timothy Chen3525aa82020-04-23 23:23:18 -070045
46 // idle hints
Timothy Chenc8f30042020-09-25 16:59:47 -070047 input [${len(hint_clks)-1}:0] idle_i,
Timothy Chen3525aa82020-04-23 23:23:18 -070048
Timothy Chen33c90782021-01-06 17:38:48 -080049 // clock bypass control
50 input lc_ctrl_pkg::lc_tx_t ast_clk_bypass_ack_i,
51 output lc_ctrl_pkg::lc_tx_t lc_clk_bypass_ack_o,
52
Timothy Chen5649c2a2021-02-08 18:32:22 -080053 // jittery enable
54 output logic jitter_en_o,
55
Timothy Chen3525aa82020-04-23 23:23:18 -070056 // clock output interface
Timothy Chen4c8905e2020-08-26 10:34:33 -070057% for intf in export_clks:
58 output clkmgr_${intf}_out_t clocks_${intf}_o,
59% endfor
Timothy Chen3525aa82020-04-23 23:23:18 -070060 output clkmgr_out_t clocks_o
61
62);
63
64 ////////////////////////////////////////////////////
65 // Register Interface
66 ////////////////////////////////////////////////////
67
68 clkmgr_reg_pkg::clkmgr_reg2hw_t reg2hw;
69 clkmgr_reg_pkg::clkmgr_hw2reg_t hw2reg;
70
Weicai Yang9f6311f2020-06-09 16:04:35 -070071 clkmgr_reg_top u_reg (
Timothy Chen3525aa82020-04-23 23:23:18 -070072 .clk_i,
73 .rst_ni,
74 .tl_i,
75 .tl_o,
76 .reg2hw,
77 .hw2reg,
Timothy Chen8ec347f2021-03-02 11:52:17 -080078 .intg_err_o(),
Timothy Chen3525aa82020-04-23 23:23:18 -070079 .devmode_i(1'b1)
80 );
81
Timothy Chenb63f3b82020-06-30 17:10:57 -070082 ////////////////////////////////////////////////////
83 // Divided clocks
84 ////////////////////////////////////////////////////
Timothy Chen33c90782021-01-06 17:38:48 -080085
86 lc_ctrl_pkg::lc_tx_t step_down_req;
87 logic [${len(div_srcs)-1}:0] step_down_acks;
88
89 prim_lc_sync u_rcv (
90 .clk_i,
91 .rst_ni,
92 .lc_en_i(ast_clk_bypass_ack_i),
93 .lc_en_o(step_down_req)
94 );
95
Timothy Chenb63f3b82020-06-30 17:10:57 -070096% for src in div_srcs:
97 logic clk_${src['name']}_i;
98% endfor
99
100% for src in div_srcs:
Timothy Chen5649c2a2021-02-08 18:32:22 -0800101
102 lc_ctrl_pkg::lc_tx_t ${src['name']}_div_scanmode;
103 prim_lc_sync #(
104 .NumCopies(1),
105 .AsyncOn(0)
106 ) u_${src['name']}_div_scanmode_sync (
Timothy Chen7a0289c2021-02-19 16:33:44 -0800107 .clk_i(1'b0), //unused
108 .rst_ni(1'b1), //unused
Timothy Chen5649c2a2021-02-08 18:32:22 -0800109 .lc_en_i(scanmode_i),
110 .lc_en_o(${src['name']}_div_scanmode)
111 );
112
Timothy Chenced60b22020-08-20 10:35:00 -0700113 prim_clock_div #(
114 .Divisor(${src['div']})
Timothy Chena1af4ec2021-03-05 13:57:00 -0800115 ) u_no_scan_${src['name']}_div (
Timothy Chenced60b22020-08-20 10:35:00 -0700116 .clk_i(clk_${src['src']}_i),
117 .rst_ni(rst_${src['src']}_ni),
Timothy Chen33c90782021-01-06 17:38:48 -0800118 .step_down_req_i(step_down_req == lc_ctrl_pkg::On),
119 .step_down_ack_o(step_down_acks[${loop.index}]),
Timothy Chen5649c2a2021-02-08 18:32:22 -0800120 .test_en_i(${src['name']}_div_scanmode == lc_ctrl_pkg::On),
Timothy Chenced60b22020-08-20 10:35:00 -0700121 .clk_o(clk_${src['name']}_i)
122 );
Timothy Chenb63f3b82020-06-30 17:10:57 -0700123% endfor
124
Timothy Chen33c90782021-01-06 17:38:48 -0800125 prim_lc_sender u_send (
126 .clk_i,
127 .rst_ni,
128 .lc_en_i(&step_down_acks ? lc_ctrl_pkg::On : lc_ctrl_pkg::Off),
129 .lc_en_o(lc_clk_bypass_ack_o)
130 );
Timothy Chenb63f3b82020-06-30 17:10:57 -0700131
Timothy Chen3525aa82020-04-23 23:23:18 -0700132 ////////////////////////////////////////////////////
Timothy Chen00cad632020-06-29 15:29:42 -0700133 // Feed through clocks
134 // Feed through clocks do not actually need to be in clkmgr, as they are
135 // completely untouched. The only reason they are here is for easier
136 // bundling management purposes through clocks_o
137 ////////////////////////////////////////////////////
138% for k,v in ft_clks.items():
Timothy Chen11c848e2020-11-03 12:03:28 -0800139 prim_clock_buf u_${k}_buf (
140 .clk_i(clk_${v}_i),
141 .clk_o(clocks_o.${k})
142 );
Timothy Chen00cad632020-06-29 15:29:42 -0700143% endfor
144
Timothy Chen00cad632020-06-29 15:29:42 -0700145 ////////////////////////////////////////////////////
Timothy Chen3525aa82020-04-23 23:23:18 -0700146 // Root gating
147 ////////////////////////////////////////////////////
148
Timothy Chena5f9e422020-09-01 18:05:03 -0700149 logic wait_enable;
150 logic wait_disable;
151 logic en_status_d;
152 logic dis_status_d;
153 logic [1:0] en_status_q;
154 logic [1:0] dis_status_q;
155 logic clk_status;
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700156% for src in rg_srcs:
157 logic clk_${src}_root;
158 logic clk_${src}_en;
Timothy Chen3525aa82020-04-23 23:23:18 -0700159% endfor
160
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700161% for src in rg_srcs:
Timothy Chen5649c2a2021-02-08 18:32:22 -0800162 lc_ctrl_pkg::lc_tx_t ${src}_scanmode;
163 prim_lc_sync #(
164 .NumCopies(1),
165 .AsyncOn(0)
166 ) u_${src}_scanmode_sync (
Timothy Chen7a0289c2021-02-19 16:33:44 -0800167 .clk_i(1'b0), //unused
168 .rst_ni(1'b1), //unused
Timothy Chen5649c2a2021-02-08 18:32:22 -0800169 .lc_en_i(scanmode_i),
170 .lc_en_o(${src}_scanmode)
171 );
172
Timothy Chenced60b22020-08-20 10:35:00 -0700173 prim_clock_gating_sync u_${src}_cg (
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700174 .clk_i(clk_${src}_i),
175 .rst_ni(rst_${src}_ni),
Timothy Chen5649c2a2021-02-08 18:32:22 -0800176 .test_en_i(${src}_scanmode == lc_ctrl_pkg::On),
Timothy Chen3525aa82020-04-23 23:23:18 -0700177 .async_en_i(pwr_i.ip_clk_en),
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700178 .en_o(clk_${src}_en),
179 .clk_o(clk_${src}_root)
Timothy Chen3525aa82020-04-23 23:23:18 -0700180 );
181% endfor
182
Timothy Chena5f9e422020-09-01 18:05:03 -0700183 // an async AND of all the synchronized enables
184 // return feedback to pwrmgr only when all clocks are enabled
185 assign wait_enable =
186% for src in rg_srcs:
187 % if loop.last:
188 clk_${src}_en;
189 % else:
190 clk_${src}_en &
191 % endif
192% endfor
193
Timothy Chen3525aa82020-04-23 23:23:18 -0700194 // an async OR of all the synchronized enables
Timothy Chena5f9e422020-09-01 18:05:03 -0700195 // return feedback to pwrmgr only when all clocks are disabled
196 assign wait_disable =
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700197% for src in rg_srcs:
Timothy Chen3525aa82020-04-23 23:23:18 -0700198 % if loop.last:
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700199 clk_${src}_en;
Timothy Chen3525aa82020-04-23 23:23:18 -0700200 % else:
Timothy Chen33b3b9d2020-05-08 10:14:17 -0700201 clk_${src}_en |
Timothy Chen3525aa82020-04-23 23:23:18 -0700202 % endif
203% endfor
204
Timothy Chena5f9e422020-09-01 18:05:03 -0700205 // Sync clkmgr domain for feedback to pwrmgr.
Timothy Chen3525aa82020-04-23 23:23:18 -0700206 // Since the signal is combo / converged on the other side, de-bounce
207 // the signal prior to output
208 prim_flop_2sync #(
209 .Width(1)
Timothy Chena5f9e422020-09-01 18:05:03 -0700210 ) u_roots_en_status_sync (
Timothy Chen3525aa82020-04-23 23:23:18 -0700211 .clk_i,
212 .rst_ni,
Timothy Chena5f9e422020-09-01 18:05:03 -0700213 .d_i(wait_enable),
214 .q_o(en_status_d)
215 );
216
217 prim_flop_2sync #(
218 .Width(1)
219 ) u_roots_or_sync (
220 .clk_i,
221 .rst_ni,
222 .d_i(wait_disable),
223 .q_o(dis_status_d)
Timothy Chen3525aa82020-04-23 23:23:18 -0700224 );
225
226 always_ff @(posedge clk_i or negedge rst_ni) begin
227 if (!rst_ni) begin
Timothy Chena5f9e422020-09-01 18:05:03 -0700228 en_status_q <= '0;
229 dis_status_q <= '0;
230 clk_status <= '0;
Timothy Chen3525aa82020-04-23 23:23:18 -0700231 end else begin
Timothy Chena5f9e422020-09-01 18:05:03 -0700232 en_status_q <= {en_status_q[0], en_status_d};
233 dis_status_q <= {dis_status_q[0], dis_status_d};
Timothy Chen3525aa82020-04-23 23:23:18 -0700234
Timothy Chena5f9e422020-09-01 18:05:03 -0700235 if (&en_status_q) begin
236 clk_status <= 1'b1;
237 end else if (|dis_status_q == '0) begin
238 clk_status <= 1'b0;
Timothy Chen3525aa82020-04-23 23:23:18 -0700239 end
240 end
241 end
242
Timothy Chena5f9e422020-09-01 18:05:03 -0700243 assign pwr_o.clk_status = clk_status;
Timothy Chen3525aa82020-04-23 23:23:18 -0700244
245 ////////////////////////////////////////////////////
246 // Clocks with only root gate
247 ////////////////////////////////////////////////////
248% for k,v in rg_clks.items():
249 assign clocks_o.${k} = clk_${v}_root;
250% endfor
251
252 ////////////////////////////////////////////////////
253 // Software direct control group
254 ////////////////////////////////////////////////////
255
Timothy Chen110fa292020-04-28 17:00:15 -0700256% for k in sw_clks:
257 logic ${k}_sw_en;
258% endfor
Timothy Chen3525aa82020-04-23 23:23:18 -0700259
260% for k,v in sw_clks.items():
Timothy Chen110fa292020-04-28 17:00:15 -0700261 prim_flop_2sync #(
262 .Width(1)
Timothy Chenced60b22020-08-20 10:35:00 -0700263 ) u_${k}_sw_en_sync (
Timothy Chen110fa292020-04-28 17:00:15 -0700264 .clk_i(clk_${v}_i),
Timothy Chen3525aa82020-04-23 23:23:18 -0700265 .rst_ni(rst_${v}_ni),
Scott Johnson204d98d2020-07-17 12:06:05 -0700266 .d_i(reg2hw.clk_enables.${k}_en.q),
267 .q_o(${k}_sw_en)
Timothy Chen110fa292020-04-28 17:00:15 -0700268 );
269
Timothy Chen5649c2a2021-02-08 18:32:22 -0800270 lc_ctrl_pkg::lc_tx_t ${k}_scanmode;
271 prim_lc_sync #(
272 .NumCopies(1),
273 .AsyncOn(0)
274 ) u_${k}_scanmode_sync (
Timothy Chen7a0289c2021-02-19 16:33:44 -0800275 .clk_i(1'b0), //unused
276 .rst_ni(1'b1), //unused
Timothy Chen5649c2a2021-02-08 18:32:22 -0800277 .lc_en_i(scanmode_i),
278 .lc_en_o(${k}_scanmode)
279 );
280
Timothy Chen11c848e2020-11-03 12:03:28 -0800281 prim_clock_gating #(
282 .NoFpgaGate(1'b1)
283 ) u_${k}_cg (
Timothy Chen1366af72020-11-03 09:53:03 -0800284 .clk_i(clk_${v}_root),
Timothy Chen110fa292020-04-28 17:00:15 -0700285 .en_i(${k}_sw_en & clk_${v}_en),
Timothy Chen5649c2a2021-02-08 18:32:22 -0800286 .test_en_i(${k}_scanmode == lc_ctrl_pkg::On),
Timothy Chen3525aa82020-04-23 23:23:18 -0700287 .clk_o(clocks_o.${k})
288 );
Timothy Chen110fa292020-04-28 17:00:15 -0700289
Timothy Chen3525aa82020-04-23 23:23:18 -0700290% endfor
291
292 ////////////////////////////////////////////////////
293 // Software hint group
294 // The idle hint feedback is assumed to be synchronous to the
295 // clock target
296 ////////////////////////////////////////////////////
297
Timothy Chen3525aa82020-04-23 23:23:18 -0700298% for k in hint_clks:
299 logic ${k}_hint;
300 logic ${k}_en;
301% endfor
302
303% for k,v in hint_clks.items():
Timothy Chenc8f30042020-09-25 16:59:47 -0700304 assign ${k}_en = ${k}_hint | ~idle_i[${v["name"].capitalize()}];
Timothy Chen3525aa82020-04-23 23:23:18 -0700305
306 prim_flop_2sync #(
307 .Width(1)
Timothy Chenced60b22020-08-20 10:35:00 -0700308 ) u_${k}_hint_sync (
Timothy Chenc8f30042020-09-25 16:59:47 -0700309 .clk_i(clk_${v["src"]}_i),
310 .rst_ni(rst_${v["src"]}_ni),
Scott Johnson204d98d2020-07-17 12:06:05 -0700311 .d_i(reg2hw.clk_hints.${k}_hint.q),
312 .q_o(${k}_hint)
Timothy Chen3525aa82020-04-23 23:23:18 -0700313 );
314
Timothy Chen5649c2a2021-02-08 18:32:22 -0800315 lc_ctrl_pkg::lc_tx_t ${k}_scanmode;
316 prim_lc_sync #(
317 .NumCopies(1),
318 .AsyncOn(0)
319 ) u_${k}_scanmode_sync (
Timothy Chen7a0289c2021-02-19 16:33:44 -0800320 .clk_i(1'b0), //unused
321 .rst_ni(1'b1), //unused
Timothy Chen5649c2a2021-02-08 18:32:22 -0800322 .lc_en_i(scanmode_i),
323 .lc_en_o(${k}_scanmode)
324 );
325
Timothy Chen11c848e2020-11-03 12:03:28 -0800326 prim_clock_gating #(
327 .NoFpgaGate(1'b1)
328 ) u_${k}_cg (
Timothy Chen1366af72020-11-03 09:53:03 -0800329 .clk_i(clk_${v["src"]}_root),
Timothy Chenc8f30042020-09-25 16:59:47 -0700330 .en_i(${k}_en & clk_${v["src"]}_en),
Timothy Chen5649c2a2021-02-08 18:32:22 -0800331 .test_en_i(${k}_scanmode == lc_ctrl_pkg::On),
Timothy Chen3525aa82020-04-23 23:23:18 -0700332 .clk_o(clocks_o.${k})
333 );
334
335% endfor
336
337 // state readback
338% for k,v in hint_clks.items():
339 assign hw2reg.clk_hints_status.${k}_val.de = 1'b1;
340 assign hw2reg.clk_hints_status.${k}_val.d = ${k}_en;
341% endfor
342
Timothy Chen5649c2a2021-02-08 18:32:22 -0800343 assign jitter_en_o = reg2hw.jitter_enable.q;
344
Timothy Chen4c8905e2020-08-26 10:34:33 -0700345 ////////////////////////////////////////////////////
346 // Exported clocks
347 ////////////////////////////////////////////////////
348
349% for intf, eps in export_clks.items():
350 % for ep, clks in eps.items():
351 % for clk in clks:
352 assign clocks_${intf}_o.clk_${intf}_${ep}_${clk} = clocks_o.clk_${clk};
353 % endfor
354 % endfor
355% endfor
Timothy Chen3525aa82020-04-23 23:23:18 -0700356
357 ////////////////////////////////////////////////////
358 // Assertions
359 ////////////////////////////////////////////////////
360
Timothy Chen8be91862020-11-02 13:40:09 -0800361 `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
362 `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
363% for intf in export_clks:
364 `ASSERT_KNOWN(ExportClocksKownO_A, clocks_${intf}_o)
365% endfor
366 `ASSERT_KNOWN(ClocksKownO_A, clocks_o)
Timothy Chen3525aa82020-04-23 23:23:18 -0700367
Timothy Chenced60b22020-08-20 10:35:00 -0700368endmodule // clkmgr