../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: