../src/lowrisc_top_earlgrey_clkmgr_0.1/rtl/autogen/clkmgr.sv Cov: 100%
1: // 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: // ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
6: // PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
7: // Copyright lowRISC contributors.
8: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
9: // SPDX-License-Identifier: Apache-2.0
10: //
11: // The overall clock manager
12:
13: `include "prim_assert.sv"
14:
15:
16:
17: module clkmgr import clkmgr_pkg::*; (
18: // Primary module control clocks and resets
19: // This drives the register interface
20: input clk_i,
21: input rst_ni,
22:
23: // System clocks and resets
24: // These are the source clocks for the system
25: input clk_main_i,
26: input rst_main_ni,
27: input clk_io_i,
28: input rst_io_ni,
29: input clk_usb_i,
30: input rst_usb_ni,
31: input clk_aon_i,
32:
33: // Bus Interface
34: input tlul_pkg::tl_h2d_t tl_i,
35: output tlul_pkg::tl_d2h_t tl_o,
36:
37: // pwrmgr interface
38: input pwrmgr_pkg::pwr_clk_req_t pwr_i,
39: output pwrmgr_pkg::pwr_clk_rsp_t pwr_o,
40:
41: // dft interface
42: input clk_dft_t dft_i,
43:
44: // idle hints
45: input clk_hint_status_t status_i,
46:
47: // clock output interface
48: output clkmgr_out_t clocks_o
49:
50: );
51:
52: ////////////////////////////////////////////////////
53: // Register Interface
54: ////////////////////////////////////////////////////
55:
56: clkmgr_reg_pkg::clkmgr_reg2hw_t reg2hw;
57: clkmgr_reg_pkg::clkmgr_hw2reg_t hw2reg;
58:
59: clkmgr_reg_top i_reg (
60: .clk_i,
61: .rst_ni,
62: .tl_i,
63: .tl_o,
64: .reg2hw,
65: .hw2reg,
66: .devmode_i(1'b1)
67: );
68:
69:
70: ////////////////////////////////////////////////////
71: // Root gating
72: ////////////////////////////////////////////////////
73:
74: // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
75: // if the clkmgr is always on, can use por synced directly
76: // if not, then need to generate something ahead of lc/sys
77:
78: logic async_roots_en;
79: logic roots_en_q2, roots_en_q1, roots_en_d;
80: logic clk_main_root;
81: logic clk_main_en;
82: logic clk_io_root;
83: logic clk_io_en;
84: logic clk_usb_root;
85: logic clk_usb_en;
86:
87: prim_clock_gating_sync i_main_cg (
88: .clk_i(clk_main_i),
89: .rst_ni(rst_main_ni),
90: .test_en_i(dft_i.test_en),
91: .async_en_i(pwr_i.ip_clk_en),
92: .en_o(clk_main_en),
93: .clk_o(clk_main_root)
94: );
95: prim_clock_gating_sync i_io_cg (
96: .clk_i(clk_io_i),
97: .rst_ni(rst_io_ni),
98: .test_en_i(dft_i.test_en),
99: .async_en_i(pwr_i.ip_clk_en),
100: .en_o(clk_io_en),
101: .clk_o(clk_io_root)
102: );
103: prim_clock_gating_sync i_usb_cg (
104: .clk_i(clk_usb_i),
105: .rst_ni(rst_usb_ni),
106: .test_en_i(dft_i.test_en),
107: .async_en_i(pwr_i.ip_clk_en),
108: .en_o(clk_usb_en),
109: .clk_o(clk_usb_root)
110: );
111:
112: // an async OR of all the synchronized enables
113: assign async_roots_en =
114: clk_main_en |
115: clk_io_en |
116: clk_usb_en;
117:
118: // Sync the OR back into clkmgr domain for feedback to pwrmgr.
119: // Since the signal is combo / converged on the other side, de-bounce
120: // the signal prior to output
121: prim_flop_2sync #(
122: .Width(1)
123: ) i_roots_en_sync (
124: .clk_i,
125: .rst_ni,
126: .d(async_roots_en),
127: .q(roots_en_d)
128: );
129:
130: always_ff @(posedge clk_i or negedge rst_ni) begin
131: if (!rst_ni) begin
132: roots_en_q1 <= 1'b0;
133: roots_en_q2 <= 1'b0;
134: end else begin
135: roots_en_q1 <= roots_en_d;
136:
137: if (roots_en_q1 == roots_en_d) begin
138: roots_en_q2 <= roots_en_q1;
139: end
140: end
141: end
142:
143: assign pwr_o.roots_en = roots_en_q2;
144:
145: ////////////////////////////////////////////////////
146: // Clocks with only root gate
147: ////////////////////////////////////////////////////
148: assign clocks_o.clk_main_infra = clk_main_root;
149: assign clocks_o.clk_io_infra = clk_io_root;
150: assign clocks_o.clk_io_secure = clk_io_root;
151: assign clocks_o.clk_main_secure = clk_main_root;
152: assign clocks_o.clk_io_timers = clk_io_root;
153: assign clocks_o.clk_proc_main = clk_main_root;
154:
155: ////////////////////////////////////////////////////
156: // Software direct control group
157: ////////////////////////////////////////////////////
158:
159: // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
160: // if the clkmgr is always on, can use por synced directly
161: // if not, then need to generate something ahead of lc/sys
162: logic clk_io_peri_sw_en;
163: logic clk_usb_peri_sw_en;
164:
165: prim_flop_2sync #(
166: .Width(1)
167: ) i_clk_io_peri_sw_en_sync (
168: .clk_i(clk_io_i),
169: .rst_ni(rst_io_ni),
170: .d(reg2hw.clk_enables.clk_io_peri_en.q),
171: .q(clk_io_peri_sw_en)
172: );
173:
174: prim_clock_gating i_clk_io_peri_cg (
175: .clk_i(clk_io_i),
176: .en_i(clk_io_peri_sw_en & clk_io_en),
177: .test_en_i(dft_i.test_en),
178: .clk_o(clocks_o.clk_io_peri)
179: );
180:
181: prim_flop_2sync #(
182: .Width(1)
183: ) i_clk_usb_peri_sw_en_sync (
184: .clk_i(clk_usb_i),
185: .rst_ni(rst_usb_ni),
186: .d(reg2hw.clk_enables.clk_usb_peri_en.q),
187: .q(clk_usb_peri_sw_en)
188: );
189:
190: prim_clock_gating i_clk_usb_peri_cg (
191: .clk_i(clk_usb_i),
192: .en_i(clk_usb_peri_sw_en & clk_usb_en),
193: .test_en_i(dft_i.test_en),
194: .clk_o(clocks_o.clk_usb_peri)
195: );
196:
197:
198: ////////////////////////////////////////////////////
199: // Software hint group
200: // The idle hint feedback is assumed to be synchronous to the
201: // clock target
202: ////////////////////////////////////////////////////
203:
204: // the rst_ni connection below is incorrect, need to find a proper reset in the sequence to use
205: // if the clkmgr is always on, can use por synced directly
206: // if not, then need to generate something ahead of lc/sys
207:
208: logic clk_main_aes_hint;
209: logic clk_main_aes_en;
210: logic clk_main_hmac_hint;
211: logic clk_main_hmac_en;
212:
213: assign clk_main_aes_en = clk_main_aes_hint | ~status_i.idle[0];
214:
215: prim_flop_2sync #(
216: .Width(1)
217: ) i_clk_main_aes_hint_sync (
218: .clk_i(clk_main_i),
219: .rst_ni(rst_main_ni),
220: .d(reg2hw.clk_hints.clk_main_aes_hint.q),
221: .q(clk_main_aes_hint)
222: );
223:
224: prim_clock_gating i_clk_main_aes_cg (
225: .clk_i(clk_main_i),
226: .en_i(clk_main_aes_en & clk_main_en),
227: .test_en_i(dft_i.test_en),
228: .clk_o(clocks_o.clk_main_aes)
229: );
230:
231: assign clk_main_hmac_en = clk_main_hmac_hint | ~status_i.idle[1];
232:
233: prim_flop_2sync #(
234: .Width(1)
235: ) i_clk_main_hmac_hint_sync (
236: .clk_i(clk_main_i),
237: .rst_ni(rst_main_ni),
238: .d(reg2hw.clk_hints.clk_main_hmac_hint.q),
239: .q(clk_main_hmac_hint)
240: );
241:
242: prim_clock_gating i_clk_main_hmac_cg (
243: .clk_i(clk_main_i),
244: .en_i(clk_main_hmac_en & clk_main_en),
245: .test_en_i(dft_i.test_en),
246: .clk_o(clocks_o.clk_main_hmac)
247: );
248:
249:
250: // state readback
251: assign hw2reg.clk_hints_status.clk_main_aes_val.de = 1'b1;
252: assign hw2reg.clk_hints_status.clk_main_aes_val.d = clk_main_aes_en;
253: assign hw2reg.clk_hints_status.clk_main_hmac_val.de = 1'b1;
254: assign hw2reg.clk_hints_status.clk_main_hmac_val.d = clk_main_hmac_en;
255:
256:
257: ////////////////////////////////////////////////////
258: // Assertions
259: ////////////////////////////////////////////////////
260:
261:
262: endmodule // rstmgr
263: