blob: 8763812a009a82548ca7ca64a076d9e6b9ffe672 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Power Manager
//
`include "prim_assert.sv"
module pwrmgr
import pwrmgr_pkg::*;
import pwrmgr_reg_pkg::*;
#(
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}
) (
// Clocks and resets
input clk_slow_i,
input clk_i,
input rst_slow_ni,
input rst_ni,
input rst_main_ni,
input clk_lc_i,
input rst_lc_ni,
input clk_esc_i,
input rst_esc_ni,
// Bus Interface
input tlul_pkg::tl_h2d_t tl_i,
output tlul_pkg::tl_d2h_t tl_o,
// Alerts
input prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i,
output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o,
// AST interface
input pwr_ast_rsp_t pwr_ast_i,
output pwr_ast_req_t pwr_ast_o,
// rstmgr interface
input pwr_rst_rsp_t pwr_rst_i,
output pwr_rst_req_t pwr_rst_o,
// clkmgr interface
output pwr_clk_req_t pwr_clk_o,
input pwr_clk_rsp_t pwr_clk_i,
// otp interface
input pwr_otp_rsp_t pwr_otp_i,
output pwr_otp_req_t pwr_otp_o,
// life cycle interface
input pwr_lc_rsp_t pwr_lc_i,
output pwr_lc_req_t pwr_lc_o,
// flash interface
input pwr_flash_t pwr_flash_i,
// processor interface
input pwr_cpu_t pwr_cpu_i,
// SEC_CM: LC_CTRL.INTERSIG.MUBI
output lc_ctrl_pkg::lc_tx_t fetch_en_o,
input lc_ctrl_pkg::lc_tx_t lc_hw_debug_en_i,
input lc_ctrl_pkg::lc_tx_t lc_dft_en_i,
// peripherals wakeup and reset requests
input [NumWkups-1:0] wakeups_i,
input [NumRstReqs-1:0] rstreqs_i,
// cpu related inputs
input ndmreset_req_i,
// pinmux and other peripherals
output logic strap_o,
output logic low_power_o,
// rom_ctrl interface
// SEC_CM: ROM_CTRL.INTERSIG.MUBI
input rom_ctrl_pkg::pwrmgr_data_t rom_ctrl_i,
// software issued reset request
// SEC_CM: RSTMGR.INTERSIG.MUBI
input prim_mubi_pkg::mubi4_t sw_rst_req_i,
// escalation interface
input prim_esc_pkg::esc_tx_t esc_rst_tx_i,
output prim_esc_pkg::esc_rx_t esc_rst_rx_o,
output intr_wakeup_o
);
////////////////////////////////////////////////////
// Input handling //
////////////////////////////////////////////////////
logic ndmreset_req_q;
logic ndm_req_valid;
prim_flop_2sync #(
.Width(1),
.ResetValue('0)
) u_ndm_sync (
.clk_i,
.rst_ni,
.d_i(ndmreset_req_i),
.q_o(ndmreset_req_q)
);
assign ndm_req_valid = ndmreset_req_q;
////////////////////////////
/// escalation detections
////////////////////////////
logic clk_lc;
logic rst_lc_n;
assign clk_lc = clk_lc_i;
assign rst_lc_n = rst_lc_ni;
logic clk_esc;
logic rst_esc_n;
prim_clock_buf #(
.NoFpgaBuf(1'b1)
) u_esc_clk_buf (
.clk_i(clk_esc_i),
.clk_o(clk_esc)
);
prim_clock_buf #(
.NoFpgaBuf(1'b1)
) u_esc_rst_buf (
.clk_i(rst_esc_ni),
.clk_o(rst_esc_n)
);
logic esc_rst_req_d, esc_rst_req_q;
prim_esc_receiver #(
.N_ESC_SEV (alert_handler_reg_pkg::N_ESC_SEV),
.PING_CNT_DW (alert_handler_reg_pkg::PING_CNT_DW)
) u_esc_rx (
.clk_i(clk_esc),
.rst_ni(rst_esc_n),
.esc_req_o(esc_rst_req_d),
.esc_rx_o(esc_rst_rx_o),
.esc_tx_i(esc_rst_tx_i)
);
// These assertions use formal to approve that once esc_rst_req is latched, we always expect to
// see the pwr_rst_o to latch.
`ifdef SIMULATION
// In simulation mode, the prim_cdc_rand_delay module inserts a random one cycle delay to the
// two flop synchronizers.
// This assertion also adds a two-cycle buffer to handle the scenario where the escalation request
// yields to a pending low power reset request.
`ASSERT(PwrmgrSecCmEscToFsmResetReq_A, esc_rst_req_d |-> ##[1:5] (u_fsm.reset_reqs_i > 0),
clk_slow_i, !rst_slow_ni)
`else
`ASSERT(PwrmgrSecCmEscToFsmResetReq_A, esc_rst_req_d |-> ##3 u_fsm.reset_reqs_i[ResetEscIdx],
clk_slow_i, !rst_slow_ni)
`endif
`ASSERT(PwrmgrSecCmEscToLCReset_A, u_fsm.reset_reqs_i[ResetEscIdx] &&
u_fsm.state_q == FastPwrStateActive |-> ##[0:2] pwr_rst_o.rst_lc_req == 2'b11,
clk_slow_i, !rst_slow_ni)
always_ff @(posedge clk_lc or negedge rst_lc_n) begin
if (!rst_lc_n) begin
esc_rst_req_q <= '0;
end else if (esc_rst_req_d) begin
// once latched, do not clear until reset
esc_rst_req_q <= 1'b1;
end
end
localparam int EscTimeOutCnt = 128;
logic esc_timeout;
// SEC_CM: ESC_RX.CLK.BKGN_CHK, ESC_RX.CLK.LOCAL_ESC
prim_clock_timeout #(
.TimeOutCnt(EscTimeOutCnt)
) u_esc_timeout (
.clk_chk_i(clk_esc),
.rst_chk_ni(rst_esc_n),
.clk_i,
.rst_ni,
// if any ip clock enable is turned on, then the escalation
// clocks are also enabled.
.en_i(|pwr_clk_o),
.timeout_o(esc_timeout)
);
////////////////////////////
/// async declarations
////////////////////////////
pwr_peri_t peri_reqs_raw;
logic slow_rst_req;
assign peri_reqs_raw.wakeups = wakeups_i;
assign peri_reqs_raw.rstreqs[NumRstReqs-1:0] = rstreqs_i;
assign peri_reqs_raw.rstreqs[ResetMainPwrIdx] = slow_rst_req;
// SEC_CM: ESC_RX.CLK.LOCAL_ESC, CTRL_FLOW.GLOBAL_ESC
assign peri_reqs_raw.rstreqs[ResetEscIdx] = esc_rst_req_q | esc_timeout;
assign peri_reqs_raw.rstreqs[ResetNdmIdx] = ndm_req_valid;
////////////////////////////
/// Software reset request
////////////////////////////
logic sw_rst_req;
prim_buf #(
.Width(1)
) u_sw_req_buf (
.in_i(prim_mubi_pkg::mubi4_test_true_strict(sw_rst_req_i)),
.out_o(sw_rst_req)
);
assign peri_reqs_raw.rstreqs[ResetSwReqIdx] = sw_rst_req;
////////////////////////////
/// clk_i domain declarations
////////////////////////////
pwrmgr_reg2hw_t reg2hw;
pwrmgr_hw2reg_t hw2reg;
pwr_peri_t peri_reqs_masked;
logic req_pwrup;
logic ack_pwrup;
logic req_pwrdn;
logic ack_pwrdn;
logic fsm_invalid;
logic clr_slow_req;
logic usb_ip_clk_en;
logic usb_ip_clk_status;
pwrup_cause_e pwrup_cause;
logic low_power_fall_through;
logic low_power_abort;
pwr_flash_t flash_rsp;
pwr_otp_rsp_t otp_rsp;
prim_mubi_pkg::mubi4_t rom_ctrl_done;
prim_mubi_pkg::mubi4_t rom_ctrl_good;
logic core_sleeping;
////////////////////////////
/// clk_slow_i domain declarations
////////////////////////////
// Captured signals
// These signals, though on clk_i domain, are safe for clk_slow_i to use
logic [NumWkups-1:0] slow_wakeup_en;
logic [NumRstReqs-1:0] slow_reset_en;
pwr_ast_rsp_t slow_ast;
pwr_peri_t slow_peri_reqs, slow_peri_reqs_masked;
pwrup_cause_e slow_pwrup_cause;
logic slow_pwrup_cause_toggle;
logic slow_req_pwrup;
logic slow_ack_pwrup;
logic slow_req_pwrdn;
logic slow_ack_pwrdn;
logic slow_fsm_invalid;
logic slow_main_pd_n;
logic slow_io_clk_en;
logic slow_core_clk_en;
logic slow_usb_clk_en_lp;
logic slow_usb_clk_en_active;
logic slow_clr_req;
logic slow_usb_ip_clk_en;
logic slow_usb_ip_clk_status;
////////////////////////////
/// Register module
////////////////////////////
logic [NumAlerts-1:0] alert_test, alerts;
logic low_power_hint;
logic lowpwr_cfg_wen;
logic clr_hint;
logic wkup;
logic clr_cfg_lock;
logic reg_intg_err;
// SEC_CM: BUS.INTEGRITY
// SEC_CM: CTRL.CONFIG.REGWEN, WAKEUP.CONFIG.REGWEN, RESET.CONFIG.REGWEN
pwrmgr_reg_top u_reg (
.clk_i,
.rst_ni,
.clk_lc_i (clk_lc ),
.rst_lc_ni (rst_lc_n),
.tl_i,
.tl_o,
.reg2hw,
.hw2reg,
.intg_err_o (reg_intg_err),
.devmode_i (1'b1)
);
// whenever low power entry begins, wipe the hint
assign hw2reg.control.low_power_hint.d = 1'b0;
assign hw2reg.control.low_power_hint.de = clr_hint;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
lowpwr_cfg_wen <= 1'b1;
end else if (!lowpwr_cfg_wen && (clr_cfg_lock || wkup)) begin
lowpwr_cfg_wen <= 1'b1;
end else if (low_power_hint) begin
lowpwr_cfg_wen <= 1'b0;
end
end
assign hw2reg.ctrl_cfg_regwen.d = lowpwr_cfg_wen;
assign hw2reg.fault_status.reg_intg_err.de = reg_intg_err;
assign hw2reg.fault_status.reg_intg_err.d = 1'b1;
assign hw2reg.fault_status.esc_timeout.de = esc_timeout;
assign hw2reg.fault_status.esc_timeout.d = 1'b1;
// The main power domain glitch automatically causes a reset, so regsitering
// an alert is functionally pointless. However, if an attacker somehow manages/
// to silence the reset, this gives us one potential back-up path through alert_handler.
// Allow capture of main_pd fault status whenever the system is live.
assign hw2reg.fault_status.main_pd_glitch.de = pwr_clk_o.main_ip_clk_en;
assign hw2reg.fault_status.main_pd_glitch.d = peri_reqs_masked.rstreqs[ResetMainPwrIdx] |
reg2hw.fault_status.main_pd_glitch.q;
`ASSERT(GlitchStatusPersist_A, $rose(reg2hw.fault_status.main_pd_glitch.q) |->
reg2hw.fault_status.main_pd_glitch.q until !rst_lc_ni)
////////////////////////////
/// alerts
////////////////////////////
// the logic below assumes there is only one alert, so make an
// explicit assertion check for it.
`ASSERT_INIT(AlertNumCheck_A, NumAlerts == 1)
assign alert_test = {
reg2hw.alert_test.q &
reg2hw.alert_test.qe
};
assign alerts[0] = reg2hw.fault_status.reg_intg_err.q |
reg2hw.fault_status.esc_timeout.q |
reg2hw.fault_status.main_pd_glitch.q;
for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx
prim_alert_sender #(
.AsyncOn(AlertAsyncOn[i]),
.IsFatal(1'b1)
) u_prim_alert_sender (
.clk_i ( clk_lc ),
.rst_ni ( rst_lc_n ),
.alert_test_i ( alert_test[i] ),
.alert_req_i ( alerts[i] ),
.alert_ack_o ( ),
.alert_state_o ( ),
.alert_rx_i ( alert_rx_i[i] ),
.alert_tx_o ( alert_tx_o[i] )
);
end
////////////////////////////
/// cdc handling
////////////////////////////
pwrmgr_cdc u_cdc (
.clk_i,
.rst_ni,
.clk_slow_i,
.rst_slow_ni,
// slow domain signals
.slow_req_pwrup_i(slow_req_pwrup),
.slow_ack_pwrdn_i(slow_ack_pwrdn),
.slow_fsm_invalid_i(slow_fsm_invalid),
.slow_pwrup_cause_toggle_i(slow_pwrup_cause_toggle),
.slow_pwrup_cause_i(slow_pwrup_cause),
.slow_wakeup_en_o(slow_wakeup_en),
.slow_reset_en_o(slow_reset_en),
.slow_main_pd_no(slow_main_pd_n),
.slow_io_clk_en_o(slow_io_clk_en),
.slow_core_clk_en_o(slow_core_clk_en),
.slow_usb_clk_en_lp_o(slow_usb_clk_en_lp),
.slow_usb_clk_en_active_o(slow_usb_clk_en_active),
.slow_req_pwrdn_o(slow_req_pwrdn),
.slow_ack_pwrup_o(slow_ack_pwrup),
.slow_ast_o(slow_ast),
.slow_peri_reqs_o(slow_peri_reqs),
.slow_peri_reqs_masked_i(slow_peri_reqs_masked),
.slow_clr_req_o(slow_clr_req),
.slow_usb_ip_clk_en_i(slow_usb_ip_clk_en),
.slow_usb_ip_clk_status_o(slow_usb_ip_clk_status),
// fast domain signals
.req_pwrdn_i(req_pwrdn),
.ack_pwrup_i(ack_pwrup),
.cfg_cdc_sync_i(reg2hw.cfg_cdc_sync.qe & reg2hw.cfg_cdc_sync.q),
.cdc_sync_done_o(hw2reg.cfg_cdc_sync.de),
.wakeup_en_i(reg2hw.wakeup_en),
.reset_en_i(reg2hw.reset_en),
.main_pd_ni(reg2hw.control.main_pd_n.q),
.io_clk_en_i(reg2hw.control.io_clk_en.q),
.core_clk_en_i(reg2hw.control.core_clk_en.q),
.usb_clk_en_lp_i(reg2hw.control.usb_clk_en_lp.q),
.usb_clk_en_active_i(reg2hw.control.usb_clk_en_active.q),
.ack_pwrdn_o(ack_pwrdn),
.fsm_invalid_o(fsm_invalid),
.req_pwrup_o(req_pwrup),
.pwrup_cause_o(pwrup_cause),
.peri_reqs_o(peri_reqs_masked),
.clr_slow_req_i(clr_slow_req),
.usb_ip_clk_en_o(usb_ip_clk_en),
.usb_ip_clk_status_i(usb_ip_clk_status),
// AST signals
.ast_i(pwr_ast_i),
// peripheral signals
.peri_i(peri_reqs_raw),
// flash handshake
.flash_i(pwr_flash_i),
.flash_o(flash_rsp),
// OTP signals
.otp_i(pwr_otp_i),
.otp_o(otp_rsp),
// rom_ctrl signals
.rom_ctrl_done_i(rom_ctrl_i.done),
.rom_ctrl_done_o(rom_ctrl_done),
// core sleeping
.core_sleeping_i(pwr_cpu_i.core_sleeping),
.core_sleeping_o(core_sleeping)
);
// rom_ctrl_i.good is not synchronized as it acts as a "payload" signal
// to "done". Good is only observed if "done" is high.
assign rom_ctrl_good = rom_ctrl_i.good;
assign hw2reg.cfg_cdc_sync.d = 1'b0;
////////////////////////////
/// Wakup and reset capture
////////////////////////////
// reset and wakeup requests are captured into the slow clock domain and then
// fanned out to other domains as necessary. This ensures there is not a huge
// time gap between when the slow clk domain sees the signal vs when the fast
// clock domains see it. This creates redundant syncing but keeps the time
// scale approximately the same across all domains.
//
// This also implies that these signals must be at least 1 clk_slow pulse long
//
// Since resets are not latched inside pwrmgr, there exists a corner case where
// non-always-on reset requests may get wiped out by a graceful low power entry
// It's not clear if this is really an issue at the moment, but something to keep
// in mind if future changes are needed.
//
// Latching the reset requests is not difficult, but the bigger question is who
// should clear it and when that should happen. If the clearing does not work
// correctly, it is possible for the device to end up in a permanent reset loop,
// and that would be very undesirable.
assign slow_peri_reqs_masked.wakeups = slow_peri_reqs.wakeups & slow_wakeup_en;
// msb is software request
// the internal requests include escalation and internal requests
// the lsbs are the software enabled peripheral requests.
assign slow_peri_reqs_masked.rstreqs = slow_peri_reqs.rstreqs &
{{NumSwRstReq{1'b1}},
{NumDebugRstReqs{1'b1}},
{NumIntRstReqs{1'b1}},
slow_reset_en};
for (genvar i = 0; i < NumWkups; i++) begin : gen_wakeup_status
assign hw2reg.wake_status[i].de = 1'b1;
assign hw2reg.wake_status[i].d = peri_reqs_masked.wakeups[i];
end
for (genvar i = 0; i < NumRstReqs; i++) begin : gen_reset_status
assign hw2reg.reset_status[i].de = 1'b1;
assign hw2reg.reset_status[i].d = peri_reqs_masked.rstreqs[i];
end
assign hw2reg.escalate_reset_status.de = 1'b1;
assign hw2reg.escalate_reset_status.d = peri_reqs_masked.rstreqs[NumRstReqs];
////////////////////////////
/// clk_slow FSM
////////////////////////////
pwrmgr_slow_fsm u_slow_fsm (
.clk_i (clk_slow_i),
.rst_ni (rst_slow_ni),
.rst_main_ni (rst_main_ni),
.wakeup_i (|slow_peri_reqs_masked.wakeups),
.reset_req_i (|slow_peri_reqs_masked.rstreqs),
.ast_i (slow_ast),
.req_pwrup_o (slow_req_pwrup),
.pwrup_cause_o (slow_pwrup_cause),
.pwrup_cause_toggle_o (slow_pwrup_cause_toggle),
.ack_pwrup_i (slow_ack_pwrup),
.req_pwrdn_i (slow_req_pwrdn),
.ack_pwrdn_o (slow_ack_pwrdn),
.rst_req_o (slow_rst_req),
.fsm_invalid_o (slow_fsm_invalid),
.clr_req_i (slow_clr_req),
.usb_ip_clk_en_o (slow_usb_ip_clk_en),
.usb_ip_clk_status_i (slow_usb_ip_clk_status),
.main_pd_ni (slow_main_pd_n),
.io_clk_en_i (slow_io_clk_en),
.core_clk_en_i (slow_core_clk_en),
.usb_clk_en_lp_i (slow_usb_clk_en_lp),
.usb_clk_en_active_i (slow_usb_clk_en_active),
// outputs to AST - These are on the slow clock domain
// TBD - need to check this with partners
.ast_o (pwr_ast_o)
);
////////////////////////////
/// clk FSM
////////////////////////////
assign low_power_hint = reg2hw.control.low_power_hint.q == LowPower;
pwrmgr_fsm u_fsm (
.clk_i,
.rst_ni,
.clk_slow_i,
.rst_slow_ni,
// interface with slow_fsm
.req_pwrup_i (req_pwrup),
.pwrup_cause_i (pwrup_cause), // por, wake or reset request
.ack_pwrup_o (ack_pwrup),
.req_pwrdn_o (req_pwrdn),
.ack_pwrdn_i (ack_pwrdn),
.low_power_entry_i (core_sleeping & low_power_hint),
.reset_reqs_i (peri_reqs_masked.rstreqs),
.fsm_invalid_i (fsm_invalid),
.clr_slow_req_o (clr_slow_req),
.usb_ip_clk_en_i (usb_ip_clk_en),
.usb_ip_clk_status_o (usb_ip_clk_status),
// cfg
.main_pd_ni (reg2hw.control.main_pd_n.q),
// consumed in pwrmgr
.wkup_o (wkup),
.clr_cfg_lock_o (clr_cfg_lock),
.fall_through_o (low_power_fall_through),
.abort_o (low_power_abort),
.clr_hint_o (clr_hint),
// rstmgr
.pwr_rst_o (pwr_rst_o),
.pwr_rst_i (pwr_rst_i),
// clkmgr
.ips_clk_en_o (pwr_clk_o),
.clk_en_status_i (pwr_clk_i),
// otp
.otp_init_o (pwr_otp_o.otp_init),
.otp_done_i (otp_rsp.otp_done),
.otp_idle_i (otp_rsp.otp_idle),
// lc
.lc_init_o (pwr_lc_o.lc_init),
.lc_done_i (pwr_lc_i.lc_done),
.lc_idle_i (pwr_lc_i.lc_idle),
.lc_dft_en_i,
.lc_hw_debug_en_i,
// flash
.flash_idle_i (flash_rsp.flash_idle),
// rom_ctrl
.rom_ctrl_done_i (rom_ctrl_done),
.rom_ctrl_good_i (rom_ctrl_good),
// processing element
.fetch_en_o,
// pinmux and other peripherals
.strap_o,
.low_power_o
);
////////////////////////////
/// Wakeup Info Capture
////////////////////////////
logic wake_info_wen;
logic [TotalWakeWidth-1:0] wake_info_data;
assign wake_info_wen = reg2hw.wake_info.abort.qe |
reg2hw.wake_info.fall_through.qe |
reg2hw.wake_info.reasons.qe;
assign wake_info_data = {reg2hw.wake_info.abort.q,
reg2hw.wake_info.fall_through.q,
reg2hw.wake_info.reasons.q};
pwrmgr_wake_info i_wake_info (
.clk_i,
.rst_ni,
.wr_i (wake_info_wen),
.data_i (wake_info_data),
.start_capture_i (low_power_o),
.record_dis_i (reg2hw.wake_info_capture_dis.q),
.wakeups_i (peri_reqs_masked.wakeups),
.fall_through_i (low_power_fall_through),
.abort_i (low_power_abort),
.info_o (hw2reg.wake_info)
);
////////////////////////////
/// Interrupts
////////////////////////////
// This interrupt is asserted whenever the fast FSM transitions
// into active state. However, it does not assert during POR
prim_intr_hw #(.Width(1)) intr_wakeup (
.clk_i,
.rst_ni,
.event_intr_i (wkup),
.reg2hw_intr_enable_q_i (reg2hw.intr_enable.q),
.reg2hw_intr_test_q_i (reg2hw.intr_test.q),
.reg2hw_intr_test_qe_i (reg2hw.intr_test.qe),
.reg2hw_intr_state_q_i (reg2hw.intr_state.q),
.hw2reg_intr_state_de_o (hw2reg.intr_state.de),
.hw2reg_intr_state_d_o (hw2reg.intr_state.d),
.intr_o (intr_wakeup_o)
);
////////////////////////////
/// Assertions
////////////////////////////
`ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid )
`ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready )
`ASSERT_KNOWN(AlertsKnownO_A, alert_tx_o )
`ASSERT_KNOWN(AstKnownO_A, pwr_ast_o )
`ASSERT_KNOWN(RstKnownO_A, pwr_rst_o )
`ASSERT_KNOWN(ClkKnownO_A, pwr_clk_o )
`ASSERT_KNOWN(OtpKnownO_A, pwr_otp_o )
`ASSERT_KNOWN(LcKnownO_A, pwr_lc_o )
`ASSERT_KNOWN(IntrKnownO_A, intr_wakeup_o )
// EscTimeOutCnt also sets the required clock ratios between escalator and local clock
// Ie, clk_lc cannot be so slow that the timeout count is reached
`ifdef INC_ASSERT
//VCS coverage off
// pragma coverage off
logic effective_rst_n;
assign effective_rst_n = clk_lc_i && rst_ni;
logic [31:0] cnt;
always_ff @(posedge clk_i or negedge effective_rst_n) begin
if (!effective_rst_n) begin
cnt <= '0;
end else begin
cnt <= cnt + 1'b1;
end
end
//VCS coverage on
// pragma coverage on
`ASSERT(ClkRatio_A, cnt < EscTimeOutCnt)
`endif
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ERR(FsmCheck_A, u_fsm.u_state_regs,
pwr_rst_o.rst_lc_req && pwr_rst_o.rst_sys_req)
`ASSERT_PRIM_FSM_ERROR_TRIGGER_ERR(SlowFsmCheck_A, u_slow_fsm.u_state_regs,
pwr_ast_o.pwr_clamp && !pwr_ast_o.main_pd_n, 0, 2,
clk_slow_i, !rst_slow_ni)
// Alert assertions for reg_we onehot check
`ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, u_reg, alert_tx_o[0])
endmodule // pwrmgr