Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 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 | // Power Manager Slow FSM |
| 6 | // |
| 7 | |
| 8 | `include "prim_assert.sv" |
| 9 | |
| 10 | module pwrmgr_slow_fsm import pwrmgr_pkg::*; ( |
| 11 | input clk_i, |
| 12 | input rst_ni, |
| 13 | |
| 14 | // sync'ed requests from peripherals |
| 15 | input wakeup_i, |
| 16 | input reset_req_i, |
| 17 | |
| 18 | // interface with fast fsm |
| 19 | output logic req_pwrup_o, |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 20 | output logic pwrup_cause_toggle_o, |
Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 21 | output pwrup_cause_e pwrup_cause_o, |
| 22 | input ack_pwrup_i, |
| 23 | input req_pwrdn_i, |
| 24 | output logic ack_pwrdn_o, |
| 25 | |
| 26 | // low power entry configuration |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 27 | input main_pd_ni, |
Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 28 | input io_clk_en_i, |
| 29 | input core_clk_en_i, |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 30 | input usb_clk_en_lp_i, |
| 31 | input usb_clk_en_active_i, |
Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 32 | |
| 33 | // AST interface |
| 34 | input pwr_ast_rsp_t ast_i, |
| 35 | output pwr_ast_req_t ast_o |
| 36 | ); |
| 37 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 38 | slow_pwr_state_e state_q, state_d; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 39 | |
| 40 | // All signals crossing over to other domain must be flopped |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 41 | pwrup_cause_e cause_q, cause_d; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 42 | logic cause_toggle_q, cause_toggle_d; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 43 | logic req_pwrup_q, req_pwrup_d; |
| 44 | logic ack_pwrdn_q, ack_pwrdn_d; |
Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 45 | |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 46 | // All power signals and signals going to analog logic are flopped to avoid transitional glitches |
| 47 | logic pd_nq, pd_nd; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 48 | logic pwr_clamp_q, pwr_clamp_d; |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 49 | logic pwr_clamp_env_q, pwr_clamp_env_d; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 50 | logic core_clk_en_q, core_clk_en_d; |
| 51 | logic io_clk_en_q, io_clk_en_d; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 52 | logic usb_clk_en_q, usb_clk_en_d; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 53 | |
| 54 | logic all_clks_valid; |
| 55 | logic all_clks_invalid; |
| 56 | |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 57 | // all clocks sources are valid |
Timothy Chen | 43e46a3 | 2020-12-03 10:32:14 -0800 | [diff] [blame] | 58 | // if clocks (usb) not configured to be active, then just bypass check |
Timothy Chen | ea59ad3 | 2021-02-03 17:51:38 -0800 | [diff] [blame] | 59 | assign all_clks_valid = ast_i.core_clk_val & |
| 60 | ast_i.io_clk_val & |
| 61 | (~usb_clk_en_active_i | ast_i.usb_clk_val); |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 62 | |
Timothy Chen | 43e46a3 | 2020-12-03 10:32:14 -0800 | [diff] [blame] | 63 | // if clocks were configured to turn off, make sure val is invalid |
| 64 | // if clocks were not configured to turn off, just bypass the check |
Timothy Chen | ea59ad3 | 2021-02-03 17:51:38 -0800 | [diff] [blame] | 65 | assign all_clks_invalid = (core_clk_en_i | ~ast_i.core_clk_val) & |
| 66 | (io_clk_en_i | ~ast_i.io_clk_val) & |
| 67 | (usb_clk_en_lp_i | ~ast_i.usb_clk_val); |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 68 | |
| 69 | always_ff @(posedge clk_i or negedge rst_ni) begin |
| 70 | if (!rst_ni) begin |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 71 | state_q <= SlowPwrStateReset; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 72 | cause_q <= Por; |
| 73 | cause_toggle_q <= 1'b0; |
Timothy Chen | 72799e9 | 2021-02-09 10:38:44 -0800 | [diff] [blame] | 74 | // pwrmgr resets assuming main power domain is already ready |
| 75 | pd_nq <= 1'b1; |
| 76 | pwr_clamp_q <= 1'b0; |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 77 | pwr_clamp_env_q <= 1'b0; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 78 | core_clk_en_q <= 1'b0; |
| 79 | io_clk_en_q <= 1'b0; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 80 | usb_clk_en_q <= 1'b0; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 81 | req_pwrup_q <= 1'b0; |
| 82 | ack_pwrdn_q <= 1'b0; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 83 | end else begin |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 84 | state_q <= state_d; |
| 85 | cause_q <= cause_d; |
| 86 | cause_toggle_q <= cause_toggle_d; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 87 | pd_nq <= pd_nd; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 88 | pwr_clamp_q <= pwr_clamp_d; |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 89 | pwr_clamp_env_q <= pwr_clamp_env_d; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 90 | core_clk_en_q <= core_clk_en_d; |
| 91 | io_clk_en_q <= io_clk_en_d; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 92 | usb_clk_en_q <= usb_clk_en_d; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 93 | req_pwrup_q <= req_pwrup_d; |
| 94 | ack_pwrdn_q <= ack_pwrdn_d; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 95 | end |
| 96 | end |
| 97 | |
| 98 | always_comb begin |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 99 | state_d = state_q; |
| 100 | cause_d = cause_q; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 101 | pd_nd = pd_nq; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 102 | cause_toggle_d = cause_toggle_q; |
| 103 | pwr_clamp_d = pwr_clamp_q; |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 104 | pwr_clamp_env_d = pwr_clamp_env_q; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 105 | core_clk_en_d = core_clk_en_q; |
| 106 | io_clk_en_d = io_clk_en_q; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 107 | usb_clk_en_d = usb_clk_en_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 108 | |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 109 | req_pwrup_d = req_pwrup_q; |
| 110 | ack_pwrdn_d = ack_pwrdn_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 111 | |
| 112 | unique case(state_q) |
| 113 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 114 | SlowPwrStateReset: begin |
| 115 | state_d = SlowPwrStateMainPowerOn; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 116 | cause_d = Por; |
| 117 | end |
| 118 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 119 | SlowPwrStateLowPower: begin |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 120 | // reset request behaves identically to a wakeup, other than the power-up cause being |
| 121 | // different |
| 122 | if (wakeup_i || reset_req_i) begin |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 123 | state_d = SlowPwrStateMainPowerOn; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 124 | cause_toggle_d = ~cause_toggle_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 125 | cause_d = reset_req_i ? Reset : Wake; |
| 126 | end |
| 127 | end |
| 128 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 129 | SlowPwrStateMainPowerOn: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 130 | pd_nd = 1'b1; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 131 | |
| 132 | if (ast_i.main_pok) begin |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 133 | pwr_clamp_env_d = 1'b0; |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 134 | state_d = SlowPwrStatePwrClampOff; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 135 | end |
| 136 | end |
| 137 | |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 138 | SlowPwrStatePwrClampOff: begin |
| 139 | pwr_clamp_d = 1'b0; |
| 140 | state_d = SlowPwrStateClocksOn; |
| 141 | end |
| 142 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 143 | SlowPwrStateClocksOn: begin |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 144 | core_clk_en_d = 1'b1; |
| 145 | io_clk_en_d = 1'b1; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 146 | usb_clk_en_d = usb_clk_en_active_i; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 147 | |
| 148 | if (all_clks_valid) begin |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 149 | state_d = SlowPwrStateReqPwrUp; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 150 | end |
| 151 | end |
| 152 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 153 | SlowPwrStateReqPwrUp: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 154 | req_pwrup_d = 1'b1; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 155 | |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 156 | // req_pwrdn_i should be 0 here to indicate |
| 157 | // the request from the previous round has definitely completed |
| 158 | if (ack_pwrup_i && !req_pwrdn_i) begin |
| 159 | req_pwrup_d = 1'b0; |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 160 | state_d = SlowPwrStateIdle; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 161 | end |
| 162 | end |
| 163 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 164 | SlowPwrStateIdle: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 165 | // ack_pwrup_i should be 0 here to indicate |
| 166 | // the ack from the previous round has definitively completed |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 167 | usb_clk_en_d = usb_clk_en_active_i; |
| 168 | |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 169 | if (req_pwrdn_i && !ack_pwrup_i) begin |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 170 | state_d = SlowPwrStateAckPwrDn; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 171 | end |
| 172 | end |
| 173 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 174 | SlowPwrStateAckPwrDn: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 175 | ack_pwrdn_d = 1'b1; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 176 | |
| 177 | if (!req_pwrdn_i) begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 178 | ack_pwrdn_d = 1'b0; |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 179 | state_d = SlowPwrStateClocksOff; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 180 | end |
| 181 | end |
| 182 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 183 | SlowPwrStateClocksOff: begin |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 184 | core_clk_en_d = core_clk_en_i; |
| 185 | io_clk_en_d = io_clk_en_i; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 186 | usb_clk_en_d = usb_clk_en_lp_i; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 187 | |
| 188 | if (all_clks_invalid) begin |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 189 | // if main power is turned off, assert early clamp ahead |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 190 | pwr_clamp_env_d = ~main_pd_ni; |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 191 | state_d = SlowPwrStatePwrClampOn; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 192 | end |
| 193 | end |
| 194 | |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 195 | SlowPwrStatePwrClampOn: begin |
| 196 | // if main power is turned off, assert clamp ahead |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 197 | pwr_clamp_d = pwr_clamp_env_q; |
Timothy Chen | 07302ad | 2021-04-13 11:50:31 -0700 | [diff] [blame] | 198 | state_d = SlowPwrStateMainPowerOff; |
| 199 | end |
| 200 | |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 201 | SlowPwrStateMainPowerOff: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 202 | pd_nd = main_pd_ni; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 203 | |
| 204 | // if power is never turned off, proceed directly to low power state |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 205 | if (!ast_i.main_pok | main_pd_ni) begin |
Srikrishna Iyer | d6b71f4 | 2021-01-06 15:33:26 -0800 | [diff] [blame] | 206 | state_d = SlowPwrStateLowPower; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 207 | end |
| 208 | end |
| 209 | |
| 210 | // Very terminal state, kill everything |
| 211 | default: begin |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 212 | pd_nd = 1'b0; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 213 | pwr_clamp_d = 1'b1; |
| 214 | core_clk_en_d = 1'b0; |
| 215 | io_clk_en_d = 1'b0; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 216 | usb_clk_en_d = 1'b0; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 217 | end |
| 218 | |
| 219 | |
| 220 | endcase // unique case (state_q) |
| 221 | end // always_comb |
| 222 | |
| 223 | |
| 224 | assign pwrup_cause_o = cause_q; |
Timothy Chen | 8837fbd | 2020-04-10 17:02:25 -0700 | [diff] [blame] | 225 | assign pwrup_cause_toggle_o = cause_toggle_q; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 226 | assign req_pwrup_o = req_pwrup_q; |
| 227 | assign ack_pwrdn_o = ack_pwrdn_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 228 | |
| 229 | assign ast_o.core_clk_en = core_clk_en_q; |
| 230 | assign ast_o.io_clk_en = io_clk_en_q; |
Timothy Chen | 93ee01e | 2020-09-21 18:01:04 -0700 | [diff] [blame] | 231 | assign ast_o.usb_clk_en = usb_clk_en_q; |
Timothy Chen | 45a1831 | 2020-04-20 18:28:18 -0700 | [diff] [blame] | 232 | assign ast_o.main_pd_n = pd_nq; |
Timothy Chen | 0249a3a | 2021-04-15 11:26:31 -0700 | [diff] [blame] | 233 | assign ast_o.pwr_clamp_env = pwr_clamp_env_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 234 | assign ast_o.pwr_clamp = pwr_clamp_q; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 235 | // This is hardwired to 1 all the time |
| 236 | assign ast_o.slow_clk_en = 1'b1; |
| 237 | |
| 238 | |
| 239 | //////////////////////////// |
| 240 | /// Unused |
| 241 | //////////////////////////// |
| 242 | |
Timothy Chen | ea59ad3 | 2021-02-03 17:51:38 -0800 | [diff] [blame] | 243 | logic unused_slow_clk_val; |
Timothy Chen | 2434383 | 2020-04-09 18:14:37 -0700 | [diff] [blame] | 244 | assign unused_slow_clk_val = ast_i.slow_clk_val; |
Timothy Chen | bc16a17 | 2020-04-07 23:45:23 -0700 | [diff] [blame] | 245 | |
| 246 | |
| 247 | endmodule |