[top-level/pwrmgr] Extend chip_sw_pwrmgr_main_power_glitch_reset
Add three groups of assertions to check that:
- the clock valids are deasserted if a power glitch is detected.
- clocks are stopped if their valid is deasserted.
- clocks are running if their valid is asserted.
Enable pwrmgr_ast_sva_if.sv assertions in _vseq file.
Add main_, io_, usb_ clock inputs to pwrmgr_ast_sva_if and
create a binding in tb.sv for that.
Signed-off-by: Abdullah Varici <abdullah.varici@lowrisc.org>
diff --git a/hw/ip/pwrmgr/dv/pwrmgr_sim_cfg.hjson b/hw/ip/pwrmgr/dv/pwrmgr_sim_cfg.hjson
index a3168a2..50f3d42 100644
--- a/hw/ip/pwrmgr/dv/pwrmgr_sim_cfg.hjson
+++ b/hw/ip/pwrmgr/dv/pwrmgr_sim_cfg.hjson
@@ -46,7 +46,7 @@
vcs_cov_excl_files: ["{proj_root}/hw/ip/pwrmgr/dv/cov/pwrmgr_cov_excl.el"]
// Add additional tops for simulation.
sim_tops: ["pwrmgr_bind",
- "pwrmgr_rstmgr_bind",
+ "pwrmgr_unit_bind",
"pwrmgr_cov_bind",
"sec_cm_prim_count_bind",
"sec_cm_prim_sparse_fsm_flop_bind",
diff --git a/hw/ip/pwrmgr/dv/sva/pwrmgr_ast_sva_if.sv b/hw/ip/pwrmgr/dv/sva/pwrmgr_ast_sva_if.sv
index 5834451..281660a 100644
--- a/hw/ip/pwrmgr/dv/sva/pwrmgr_ast_sva_if.sv
+++ b/hw/ip/pwrmgr/dv/sva/pwrmgr_ast_sva_if.sv
@@ -5,9 +5,14 @@
// This has some assertions that check the inputs from ast react according to
// the pwrmgr outputs. The ast inputs are generated by the base sequences, but
// these assertions will also be useful at full chip level.
-interface pwrmgr_ast_sva_if (
+interface pwrmgr_ast_sva_if #(
+ parameter bit CheckClocks = 1'b0
+) (
input logic clk_slow_i,
input logic rst_slow_ni,
+ input logic clk_main_i,
+ input logic clk_io_i,
+ input logic clk_usb_i,
// The pwrmgr outputs.
input pwrmgr_pkg::pwr_ast_req_t pwr_ast_o,
// The pwrmgr inputs.
@@ -50,6 +55,43 @@
`ASSERT(UsbClkHandshakeOff_A, !pwr_ast_o.usb_clk_en |-> `CLK_WAIT_BOUNDS !pwr_ast_i.usb_clk_val,
clk_slow_i, reset_or_disable)
+ if (CheckClocks) begin : gen_check_clock
+ int main_clk_cycles, io_clk_cycles, usb_clk_cycles;
+ always_ff @(posedge clk_main_i) main_clk_cycles++;
+ always_ff @(posedge clk_io_i) io_clk_cycles++;
+ always_ff @(posedge clk_usb_i) usb_clk_cycles++;
+
+ `ASSERT(MainClkStopped_A,
+ $fell(
+ pwr_ast_i.core_clk_val
+ ) |=> ($stable(
+ main_clk_cycles
+ ) throughout (!pwr_ast_i.core_clk_val) [* 1: $]),
+ clk_slow_i, reset_or_disable)
+ `ASSERT(MainClkRun_A, $rose(pwr_ast_i.core_clk_val) |=> !($stable(main_clk_cycles)),
+ clk_slow_i, reset_or_disable)
+
+ `ASSERT(IOClkStopped_A,
+ $fell(
+ pwr_ast_i.io_clk_val
+ ) |=> ($stable(
+ io_clk_cycles
+ ) throughout (!pwr_ast_i.io_clk_val) [* 1: $]),
+ clk_slow_i, reset_or_disable)
+ `ASSERT(IOClkRun_A, $rose(pwr_ast_i.io_clk_val) |=> !($stable(io_clk_cycles)), clk_slow_i,
+ reset_or_disable)
+
+ `ASSERT(USBClkStopped_A,
+ $fell(
+ pwr_ast_i.usb_clk_val
+ ) |=> ($stable(
+ usb_clk_cycles
+ ) throughout (!pwr_ast_i.usb_clk_val) [* 1: $]),
+ clk_slow_i, reset_or_disable)
+ `ASSERT(USBClkRun_A, $rose(pwr_ast_i.usb_clk_val) |=> !($stable(usb_clk_cycles)), clk_slow_i,
+ reset_or_disable)
+ end
+
// Main pd-pok
`ASSERT(MainPdHandshakeOn_A, pwr_ast_o.main_pd_n |-> `PDN_WAIT_BOUNDS pwr_ast_i.main_pok,
clk_slow_i, reset_or_disable)
diff --git a/hw/ip/pwrmgr/dv/sva/pwrmgr_bind.sv b/hw/ip/pwrmgr/dv/sva/pwrmgr_bind.sv
index 2c6bcf0..39e5bc5 100644
--- a/hw/ip/pwrmgr/dv/sva/pwrmgr_bind.sv
+++ b/hw/ip/pwrmgr/dv/sva/pwrmgr_bind.sv
@@ -34,15 +34,6 @@
.usb_clk_en(pwr_ast_o.usb_clk_en)
);
- bind pwrmgr pwrmgr_ast_sva_if pwrmgr_ast_sva_if (
- .clk_slow_i,
- .rst_slow_ni,
- // The pwrmgr outputs.
- .pwr_ast_o,
- // The pwrmgr input.
- .pwr_ast_i
- );
-
bind pwrmgr clkmgr_pwrmgr_sva_if clkmgr_pwrmgr_sva_if (
.clk_i,
.rst_ni,
diff --git a/hw/ip/pwrmgr/dv/sva/pwrmgr_sva.core b/hw/ip/pwrmgr/dv/sva/pwrmgr_sva.core
index e01c431..0d83c52 100644
--- a/hw/ip/pwrmgr/dv/sva/pwrmgr_sva.core
+++ b/hw/ip/pwrmgr/dv/sva/pwrmgr_sva.core
@@ -14,7 +14,7 @@
- lowrisc:dv:pwrmgr_rstmgr_sva_if
files:
- pwrmgr_bind.sv
- - pwrmgr_rstmgr_bind.sv
+ - pwrmgr_unit_bind.sv
- pwrmgr_ast_sva_if.sv
- pwrmgr_clock_enables_sva_if.sv
- pwrmgr_sec_cm_checker_assert.sv
diff --git a/hw/ip/pwrmgr/dv/sva/pwrmgr_rstmgr_bind.sv b/hw/ip/pwrmgr/dv/sva/pwrmgr_unit_bind.sv
similarity index 78%
rename from hw/ip/pwrmgr/dv/sva/pwrmgr_rstmgr_bind.sv
rename to hw/ip/pwrmgr/dv/sva/pwrmgr_unit_bind.sv
index 05b6d6c..b569bc4 100644
--- a/hw/ip/pwrmgr/dv/sva/pwrmgr_rstmgr_bind.sv
+++ b/hw/ip/pwrmgr/dv/sva/pwrmgr_unit_bind.sv
@@ -5,7 +5,7 @@
// This is split off from pwrmgr_bind so that we can instantiate that in chip top, but
// specialize the bind of pwrmgr_rstmgr_sva_if for top_earlgrey, which is needed in order
// to hook up ndm_sys_req because pwrmgr doesn't see it.
-module pwrmgr_rstmgr_bind;
+module pwrmgr_unit_bind;
bind pwrmgr pwrmgr_rstmgr_sva_if pwrmgr_rstmgr_sva_if (
.clk_i,
@@ -31,4 +31,16 @@
.rst_sys_src_n(pwr_rst_i.rst_sys_src_n)
);
+ bind pwrmgr pwrmgr_ast_sva_if #(
+ .CheckClocks(1'b0)
+ ) pwrmgr_ast_sva_if (
+ .clk_slow_i,
+ .rst_slow_ni,
+ // Leave clk_*_i inputs unconnected as they are not used by assertions in unit tests.
+ // The pwrmgr outputs.
+ .pwr_ast_o,
+ // The pwrmgr input.
+ .pwr_ast_i
+ );
+
endmodule
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr.sv b/hw/ip/pwrmgr/rtl/pwrmgr.sv
index c5b40ea..b773ca8 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr.sv
@@ -287,6 +287,15 @@
assign hw2reg.fault_status.main_pd_glitch.de = peri_reqs_masked.rstreqs[ResetMainPwrIdx];
assign hw2reg.fault_status.main_pd_glitch.d = 1'b1;
+ // Check that the clock enables are deasserted in the next slow clock cycle if a power glitch is
+ // detected.
+ `ASSERT(PwrmgrMainPowerGlitchMainClkVld, $rose(hw2reg.fault_status.main_pd_glitch.de)
+ |=> !pwr_clk_o.main_ip_clk_en, clk_slow_i, !rst_slow_ni)
+ `ASSERT(PwrmgrMainPowerGlitchIOClkVld, $rose(hw2reg.fault_status.main_pd_glitch.de)
+ |=> !pwr_clk_o.io_ip_clk_en, clk_slow_i, !rst_slow_ni)
+ `ASSERT(PwrmgrMainPowerGlitchUSBClkVld, $rose(hw2reg.fault_status.main_pd_glitch.de)
+ |=> !pwr_clk_o.usb_ip_clk_en, clk_slow_i, !rst_slow_ni)
+
////////////////////////////
/// alerts
diff --git a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_main_power_glitch_vseq.sv b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_main_power_glitch_vseq.sv
index c91937d..a1ec782 100644
--- a/hw/top_earlgrey/dv/env/seq_lib/chip_sw_main_power_glitch_vseq.sv
+++ b/hw/top_earlgrey/dv/env/seq_lib/chip_sw_main_power_glitch_vseq.sv
@@ -14,7 +14,6 @@
virtual task pre_start();
super.pre_start();
// disable expected assertion error for power glitch test
- $assertoff(0,"pwrmgr_ast_sva_if");
$assertoff(1,"tb.dut.top_earlgrey.pwrmgr_rstmgr_sva_if.MainPwrRstOff_A");
$assertoff(1,"tb.dut.top_earlgrey.pwrmgr_rstmgr_sva_if.MainPwrRstOn_A");
endtask
diff --git a/hw/top_earlgrey/dv/sva/top_earlgrey_bind.sv b/hw/top_earlgrey/dv/sva/top_earlgrey_bind.sv
index f5f7658..1604133 100644
--- a/hw/top_earlgrey/dv/sva/top_earlgrey_bind.sv
+++ b/hw/top_earlgrey/dv/sva/top_earlgrey_bind.sv
@@ -30,4 +30,18 @@
.rst_sys_src_n(u_pwrmgr_aon.pwr_rst_i.rst_sys_src_n)
);
+ bind pwrmgr pwrmgr_ast_sva_if #(
+ .CheckClocks(1'b1)
+ ) pwrmgr_ast_sva_if (
+ .clk_slow_i(u_pwrmgr_aon.clk_slow_i),
+ .rst_slow_ni(u_pwrmgr_aon.rst_slow_ni),
+ .clk_main_i(u_clkmgr_aon.clk_main_i),
+ .clk_io_i(u_clkmgr_aon.clk_io_i),
+ .clk_usb_i(u_clkmgr_aon.clk_usb_i),
+ // The pwrmgr outputs.
+ .pwr_ast_o,
+ // The pwrmgr input.
+ .pwr_ast_i
+ );
+
endmodule