../src/lowrisc_ip_rstmgr_0.1/rtl/rstmgr.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: // This module is the overall reset manager wrapper
6: // TODO: This module is only a draft implementation that covers most of the rstmgr
7: // functoinality but is incomplete
8:
9: `include "prim_assert.sv"
10:
11: // This top level controller is fairly hardcoded right now, but will be switched to a template
12: module rstmgr import rstmgr_pkg::*; (
13: // Primary module clocks
14: input clk_i,
15: input rst_ni,
16: input clk_main_i,
17: input clk_io_i,
18: input clk_usb_i,
19: input clk_aon_i,
20:
21: // Bus Interface
22: input tlul_pkg::tl_h2d_t tl_i,
23: output tlul_pkg::tl_d2h_t tl_o,
24:
25: // pwrmgr interface
26: input pwrmgr_pkg::pwr_rst_req_t pwr_i,
27: output pwrmgr_pkg::pwr_rst_rsp_t pwr_o,
28:
29: // ast interface
30: input rstmgr_ast_t ast_i,
31:
32: // cpu related inputs
33: input rstmgr_cpu_t cpu_i,
34:
35: // peripheral reset requests
36: input rstmgr_peri_t peri_i,
37:
38: // Interface to alert handler
39: // always on resets
40: output rstmgr_out_t resets_o
41:
42: );
43:
44: // receive POR and stretch
45: // The por is at first stretched and synced on clk_aon
46: rstmgr_por i_por (
47: .clk_i(clk_aon_i),
48: .rst_ni,
49: .pok_i(ast_i.vcc_pok & ast_i.alw_pok),
50: .rst_no(resets_o.rst_por_aon_n)
51: );
52:
53: // POR usage for the clkmgr
54: prim_flop_2sync #(
55: .Width(1),
56: .ResetValue(0)
57: ) i_por_sync (
58: .clk_i(clk_main_i),
59: .rst_ni(resets_o.rst_por_aon_n),
60: .d(1'b1),
61: .q(resets_o.rst_por_n)
62: );
63:
64: prim_flop_2sync #(
65: .Width(1),
66: .ResetValue(0)
67: ) i_por_io_sync (
68: .clk_i(clk_io_i),
69: .rst_ni(resets_o.rst_por_aon_n),
70: .d(1'b1),
71: .q(resets_o.rst_por_io_n)
72: );
73:
74: prim_flop_2sync #(
75: .Width(1),
76: .ResetValue(0)
77: ) i_por_usb_sync (
78: .clk_i(clk_usb_i),
79: .rst_ni(resets_o.rst_por_aon_n),
80: .d(1'b1),
81: .q(resets_o.rst_por_usb_n)
82: );
83:
84: ////////////////////////////////////////////////////
85: // Register Interface //
86: ////////////////////////////////////////////////////
87:
88: rstmgr_reg_pkg::rstmgr_reg2hw_t reg2hw;
89: rstmgr_reg_pkg::rstmgr_hw2reg_t hw2reg;
90:
91: rstmgr_reg_top i_reg (
92: .clk_i,
93: .rst_ni(resets_o.rst_por_aon_n),
94: .tl_i,
95: .tl_o,
96: .reg2hw,
97: .hw2reg,
98: .devmode_i(1'b1)
99: );
100:
101: ////////////////////////////////////////////////////
102: // Input handling //
103: ////////////////////////////////////////////////////
104:
105: logic ndmreset_req_q;
106: logic ndm_req_valid;
107:
108: prim_flop_2sync #(
109: .Width(1),
110: .ResetValue(0)
111: ) i_sync (
112: .clk_i,
113: .rst_ni(resets_o.rst_por_aon_n),
114: .d(cpu_i.ndmreset_req),
115: .q(ndmreset_req_q)
116: );
117:
118: assign ndm_req_valid = ndmreset_req_q & (pwr_i.reset_cause == pwrmgr_pkg::ResetNone);
119:
120: ////////////////////////////////////////////////////
121: // Source resets in the system //
122: // These are hardcoded and not directly used. //
123: // Instead they act as async reset roots. //
124: ////////////////////////////////////////////////////
125: logic [PowerDomains-1:0] rst_lc_src_n;
126: logic [PowerDomains-1:0] rst_sys_src_n;
127:
128: // The two source reset modules are chained together. The output of one is fed into the
129: // the second. This ensures that if upstream resets for any reason, the associated downstream
130: // reset will also reset.
131:
132: // lc reset sources
133: rstmgr_ctrl #(
134: .PowerDomains(PowerDomains)
135: ) i_lc_src (
136: .clk_i(clk_i),
137: .rst_ni(resets_o.rst_por_aon_n),
138: .rst_req_i(pwr_i.rst_lc_req),
139: .rst_parent_ni({PowerDomains{1'b1}}),
140: .rst_no(rst_lc_src_n)
141: );
142:
143: // sys reset sources
144: rstmgr_ctrl #(
145: .PowerDomains(PowerDomains)
146: ) i_sys_src (
147: .clk_i(clk_i),
148: .rst_ni(resets_o.rst_por_aon_n),
149: .rst_req_i(pwr_i.rst_sys_req | {PowerDomains{ndm_req_valid}}),
150: .rst_parent_ni(rst_lc_src_n),
151: .rst_no(rst_sys_src_n)
152: );
153:
154: assign pwr_o.rst_lc_src_n = rst_lc_src_n;
155: assign pwr_o.rst_sys_src_n = rst_sys_src_n;
156:
157: ////////////////////////////////////////////////////
158: // leaf reset in the system //
159: // These should all be generated //
160: ////////////////////////////////////////////////////
161:
162: prim_flop_2sync #(
163: .Width(1),
164: .ResetValue(0)
165: ) i_lc (
166: .clk_i(clk_io_i),
167: .rst_ni(rst_lc_src_n[ALWAYS_ON_SEL]),
168: .d(1'b1),
169: .q(resets_o.rst_lc_n)
170: );
171:
172: prim_flop_2sync #(
173: .Width(1),
174: .ResetValue(0)
175: ) i_sys (
176: .clk_i(clk_main_i),
177: .rst_ni(rst_sys_src_n[ALWAYS_ON_SEL]),
178: .d(1'b1),
179: .q(resets_o.rst_sys_n)
180: );
181:
182: prim_flop_2sync #(
183: .Width(1),
184: .ResetValue(0)
185: ) i_sys_io (
186: .clk_i(clk_io_i),
187: .rst_ni(rst_sys_src_n[ALWAYS_ON_SEL]),
188: .d(1'b1),
189: .q(resets_o.rst_sys_io_n)
190: );
191:
192: prim_flop_2sync #(
193: .Width(1),
194: .ResetValue(0)
195: ) i_spi_device (
196: .clk_i(clk_io_i),
197: .rst_ni(rst_sys_src_n[ALWAYS_ON_SEL]),
198: .d(reg2hw.rst_spi_device_n.q),
199: .q(resets_o.rst_spi_device_n)
200: );
201:
202: prim_flop_2sync #(
203: .Width(1),
204: .ResetValue(0)
205: ) i_usb (
206: .clk_i(clk_usb_i),
207: .rst_ni(rst_sys_src_n[ALWAYS_ON_SEL]),
208: .d(reg2hw.rst_usb_n.q),
209: .q(resets_o.rst_usb_n)
210: );
211:
212: ////////////////////////////////////////////////////
213: // Reset info construction //
214: ////////////////////////////////////////////////////
215:
216: logic [ResetReasons-1:0] rst_reqs;
217: logic rst_hw_req;
218: logic rst_low_power;
219:
220: assign rst_hw_req = pwr_i.reset_cause == pwrmgr_pkg::HwReq;
221: assign rst_low_power = pwr_i.reset_cause == pwrmgr_pkg::LowPwrEntry;
222:
223: assign rst_reqs = {
224: ndm_req_valid,
225: rst_hw_req ? peri_i.rst_reqs : ExtResetReasons'(0),
226: rst_low_power
227: };
228:
229: rstmgr_info #(
230: .Reasons(ResetReasons)
231: ) i_info (
232: .clk_i,
233: .rst_ni(resets_o.rst_por_aon_n),
234: .rst_cpu_ni(cpu_i.rst_cpu_n),
235: .rst_req_i(rst_reqs),
236: .wr_i(reg2hw.reset_info.qe),
237: .data_i(reg2hw.reset_info.q),
238: .rst_reasons_o(hw2reg.reset_info)
239: );
240:
241: ////////////////////////////////////////////////////
242: // Assertions //
243: ////////////////////////////////////////////////////
244:
245: // when upstream resets, downstream must also reset
246:
247: endmodule // rstmgr
248: