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