Skip to content

Commit

Permalink
[hw,pwrmgr] Ipgen the 'Wait for External Reset' parameter
Browse files Browse the repository at this point in the history
Signed-off-by: Robert Schilling <[email protected]>
  • Loading branch information
Razer6 committed Nov 5, 2024
1 parent 753427d commit e1cdc60
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 231 deletions.
10 changes: 2 additions & 8 deletions hw/ip_templates/pwrmgr/data/pwrmgr.hjson.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,14 @@
]

inter_signal_list: [
% if wait_for_external_reset:
{ struct: "pwr_boot_status",
type: "uni",
name: "boot_status",
act: "req",
package: "pwrmgr_pkg",
},
% endif
{ struct: "pwr_ast",
type: "req_rsp",
name: "pwr_ast",
Expand Down Expand Up @@ -301,14 +303,6 @@

% endfor

{ name: "PwrFsmWaitForExtRst",
desc: "Wait for external reset to complete",
type: "bit",
default: "0",
local: "false",
expose: "true"
},

{ name: "NumRstReqs",
desc: "Number of peripheral reset requets",
type: "int",
Expand Down
6 changes: 6 additions & 0 deletions hw/ip_templates/pwrmgr/data/pwrmgr.tpldesc.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,11 @@
type: "int"
default: "2"
}
{
name: "wait_for_external_reset"
desc: "Wait for external reset requests"
type: "bool"
default: false
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ module tb;
wire clk_lc, rst_lc_n;
wire clk_slow, rst_slow_n;
wire [NUM_MAX_INTERRUPTS-1:0] interrupts;
% if wait_for_external_reset:
wire int_reset_req;
% endif

// interfaces
clk_rst_if clk_rst_if (
Expand Down Expand Up @@ -48,7 +50,9 @@ module tb;
);

assign interrupts[0] = pwrmgr_if.intr_wakeup;
% if wait_for_external_reset:
assign int_reset_req = tb.dut.internal_reset_req;
% endif

pwrmgr_if pwrmgr_if (
.clk,
Expand Down Expand Up @@ -97,8 +101,12 @@ module tb;

.fetch_en_o(pwrmgr_if.fetch_en),
.wakeups_i (pwrmgr_if.wakeups_i),
% if wait_for_external_reset:
// TOOD(#22710): properly cooperate with `pwrmgr_if.rstreqs_i[1]`
.rstreqs_i ({int_reset_req, pwrmgr_if.rstreqs_i[0]}),
% else:
.rstreqs_i (pwrmgr_if.rstreqs_i),
% endif
.ndmreset_req_i(pwrmgr_if.cpu_i.ndmreset_req),

.lc_dft_en_i (pwrmgr_if.lc_dft_en),
Expand Down
2 changes: 2 additions & 0 deletions hw/ip_templates/pwrmgr/pwrmgr_pkg.core.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ filesets:
files_rtl:
depend:
- ${instance_vlnv("lowrisc:ip:pwrmgr_reg")}
% if wait_for_external_reset:
- lowrisc:ip:rom_ctrl_pkg
% endif
files:
- rtl/pwrmgr_pkg.sv
file_type: systemVerilogSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ module pwrmgr
import pwrmgr_pkg::*;
import pwrmgr_reg_pkg::*;
#(
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
parameter bit PwrFsmWaitForExtRst = 0
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}
) (
// Clocks and resets
input clk_slow_i,
Expand Down Expand Up @@ -62,8 +61,9 @@ module pwrmgr
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,

% if wait_for_external_reset:
output pwr_boot_status_t boot_status_o,
% endif
// peripherals wakeup and reset requests
input [NumWkups-1:0] wakeups_i,
input [NumRstReqs-1:0] rstreqs_i,
Expand All @@ -90,11 +90,6 @@ module pwrmgr
output intr_wakeup_o
);

logic internal_reset_req;
logic strap_sampled;
logic ext_reset_req;

////////////////////////////////////////////////////
// Input handling //
////////////////////////////////////////////////////
Expand Down Expand Up @@ -161,25 +156,25 @@ module pwrmgr
// cycles in the fast fsm to generate outputs. However, esc_rst_req_q can be dropped due to
// rst_lc_n, which will cause slow_peri_reqs_masked.rstreqs[ResetEscIdx] to drop.
`ASSERT(PwrmgrSecCmEscToSlowResetReq_A,
esc_rst_req_q |-> ##[1:5] !esc_rst_req_q || slow_peri_reqs_masked.rstreqs[ResetEscIdx],
esc_rst_req_q |-> ${"##"}[1:5] !esc_rst_req_q || slow_peri_reqs_masked.rstreqs[ResetEscIdx],
clk_slow_i, !rst_slow_ni)
`ASSERT(PwrmgrSecCmFsmEscToResetReq_A,
slow_peri_reqs_masked.rstreqs[ResetEscIdx] |->
##[1:4] !slow_peri_reqs_masked.rstreqs[ResetEscIdx] || u_fsm.reset_reqs_i[ResetEscIdx],
${"##"}[1:4] !slow_peri_reqs_masked.rstreqs[ResetEscIdx] || u_fsm.reset_reqs_i[ResetEscIdx],
clk_i, !rst_ni)
`else
`ASSERT(PwrmgrSecCmEscToSlowResetReq_A,
esc_rst_req_d |-> ##[2:3] (
esc_rst_req_d |-> ${"##"}[2:3] (
(!esc_rst_req_d && lc_ctrl_pkg::lc_tx_test_false_loose(fetch_en_o)) ||
slow_peri_reqs_masked.rstreqs[ResetEscIdx]
), clk_slow_i, !rst_slow_ni)
`ASSERT(PwrmgrSlowResetReqToFsmResetReq_A,
slow_peri_reqs_masked.rstreqs[ResetEscIdx] |-> ##1 u_fsm.reset_reqs_i[ResetEscIdx],
slow_peri_reqs_masked.rstreqs[ResetEscIdx] |-> ${"##"}1 u_fsm.reset_reqs_i[ResetEscIdx],
clk_i, !rst_ni)
`endif

`ASSERT(PwrmgrSecCmEscToLCReset_A, u_fsm.reset_reqs_i[ResetEscIdx] &&
u_fsm.state_q == FastPwrStateActive |-> ##4 pwr_rst_o.rst_lc_req == 2'b11,
u_fsm.state_q == FastPwrStateActive |-> ${"##"}4 pwr_rst_o.rst_lc_req == 2'b11,
clk_i, !rst_ni)

always_ff @(posedge clk_lc or negedge rst_lc_n) begin
Expand Down Expand Up @@ -515,8 +510,12 @@ module pwrmgr
{NumDebugRstReqs{1'b1}},
{NumIntRstReqs{1'b1}},
slow_reset_en};

% if wait_for_external_reset:
// TODO(#22711): Make this work also when `rstreqs` is structured differently.
logic strap_sampled;
logic internal_reset_req;
logic ext_reset_req;
assign internal_reset_req =|(
slow_peri_reqs.rstreqs &
{{NumSwRstReq{1'b1}}, // SW driven reset
Expand All @@ -530,6 +529,7 @@ module pwrmgr
// The MSB of `slow_peri_reqs.rstreqs` is the external reset request. We want it to always
// propagate, in order to continue from the Reset Wait state in the fast FSM.
assign ext_reset_req = slow_peri_reqs.rstreqs[NumRstReqs-1];
% endif
for (genvar i = 0; i < NumWkups; i++) begin : gen_wakeup_status
assign hw2reg.wake_status[i].de = 1'b1;
Expand Down Expand Up @@ -602,9 +602,7 @@ module pwrmgr
assign low_power_hint = reg2hw.control.low_power_hint.q == LowPower;
assign low_power_entry = core_sleeping & low_power_hint;

pwrmgr_fsm #(
.PwrFsmWaitForExtRst(PwrFsmWaitForExtRst)
) u_fsm (
pwrmgr_fsm u_fsm (
.clk_i,
.rst_ni,
.clk_slow_i,
Expand Down Expand Up @@ -632,8 +630,10 @@ module pwrmgr
.fall_through_o (low_power_fall_through),
.abort_o (low_power_abort),
.clr_hint_o (clr_hint),
% if wait_for_external_reset:
.int_reset_req_i (internal_reset_req),
.ext_reset_req_i (ext_reset_req),
% endif

// rstmgr
.pwr_rst_o (pwr_rst_o),
Expand Down Expand Up @@ -667,7 +667,11 @@ module pwrmgr

// pinmux and other peripherals
.strap_o,
% if wait_for_external_reset:
.strap_sampled_o (strap_sampled), // to debug monitoring logic
% else:
.strap_sampled_o (),
% endif
.low_power_o
);

Expand Down Expand Up @@ -718,6 +722,7 @@ module pwrmgr
.intr_o (intr_wakeup_o)
);

% if wait_for_external_reset:
////////////////////////////////////////////////////
// Routing sstaus signal outputs for monitoring
////////////////////////////////////////////////////
Expand All @@ -728,6 +733,7 @@ module pwrmgr
assign boot_status_o.clk_status = pwr_clk_i;
assign boot_status_o.light_reset_req = internal_reset_req;
assign boot_status_o.strap_sampled = strap_sampled;
% endif

////////////////////////////
/// Assertions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@

`include "prim_assert.sv"

module pwrmgr_fsm
import pwrmgr_pkg::*;
import pwrmgr_reg_pkg::*;
#(
parameter bit PwrFsmWaitForExtRst = 0
) (
module pwrmgr_fsm import pwrmgr_pkg::*; import pwrmgr_reg_pkg::*;(
input clk_i,
input rst_ni,
input clk_slow_i,
Expand All @@ -38,9 +33,11 @@ module pwrmgr_fsm
output logic abort_o,
output logic clr_hint_o,
output logic clr_cfg_lock_o,
% if wait_for_external_reset:
input logic int_reset_req_i, // internally generated reset request.
// Send to platform to assert reset
input logic ext_reset_req_i, // Internal Req held until ext reset deasserts
% endif

// rstmgr
output pwr_rst_req_t pwr_rst_o,
Expand Down Expand Up @@ -126,8 +123,6 @@ module pwrmgr_fsm
logic otp_init;
logic lc_init;
logic low_power_q, low_power_d;
logic ext_rst_req_d, ext_rst_req_q;
logic ext_rst_pending_q;

assign pd_n_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:OffDomainSelStart] == '0 &
pwr_rst_i.rst_sys_src_n[PowerDomains-1:OffDomainSelStart] == '0;
Expand Down Expand Up @@ -162,34 +157,32 @@ module pwrmgr_fsm
// when the reset cause is something else, it is invalid
assign reset_valid = reset_cause_q == LowPwrEntry ? main_pd_ni | pd_n_rsts_asserted :
reset_cause_q == HwReq ? all_rsts_asserted : 1'b0;
% if wait_for_external_reset:

// Provide the ability to control the reset to OpenTitan RoT from an external source. The logic
// below makes sure that when an internal reset request is generated, it is held high until the
// external SoC reset logic asserts and then deasserts deasserts the external reset signal. The
// pwrmgr fast FSM is held in FastPwrStateResetWait state until the external reset deasserts.
// This ensure that the OT reset exit is synchronized with the rest of the SoC & platform.
if (PwrFsmWaitForExtRst) begin : gen_wait2ext_rst
logic ext_rst_req_d, ext_rst_req_q;
logic ext_rst_pending_q;

assign ext_rst_req_d = ext_reset_req_i;
assign ext_rst_req_d = ext_reset_req_i;

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
ext_rst_pending_q <= 1'b0;
ext_rst_req_q <= 1'b0;
end else begin
ext_rst_req_q <= ext_rst_req_d;
if (ext_rst_pending_q && !ext_rst_req_d && ext_rst_req_q) begin
ext_rst_pending_q <= 1'b0;
ext_rst_req_q <= 1'b0;
end else begin
ext_rst_req_q <= ext_rst_req_d;
if (ext_rst_pending_q && !ext_rst_req_d && ext_rst_req_q) begin
ext_rst_pending_q <= 1'b0;
end else if (int_reset_req_i) begin
ext_rst_pending_q <= 1'b1;
end
end else if (int_reset_req_i) begin
ext_rst_pending_q <= 1'b1;
end
end
end else begin : gen_no_wait2ext_rst
assign ext_rst_pending_q = 1'b0;
assign ext_rst_req_q = 1'b0;
assign ext_rst_req_d = 1'b0;
end : gen_no_wait2ext_rst
end
% endif

always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
Expand Down Expand Up @@ -509,9 +502,12 @@ module pwrmgr_fsm
// cleared before proceeding. This also implies if the system is under a persistent
// glitch, or if someone just turned off the power before pwrmgr turns it off itself,
// we will stay stuck here and perpetually hold the system in reset.
% if wait_for_external_reset:
// Need to hold in reset until external reset deasserts (i.e. ext_rst_pending_q goes low)
if (reset_valid && !reset_reqs_i[ResetMainPwrIdx]
&& !ext_rst_pending_q ) begin
if (reset_valid && !reset_reqs_i[ResetMainPwrIdx] && !ext_rst_pending_q) begin
% else:
if (reset_valid && !reset_reqs_i[ResetMainPwrIdx]) begin
% endif
state_d = FastPwrStateLowPower;
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,18 @@ package pwrmgr_pkg;
typedef struct packed {
logic ndmreset_req;
} pwrmgr_cpu_t;
% if wait_for_external_reset:
typedef struct packed {
lc_ctrl_pkg::lc_tx_t cpu_fetch_en;
rom_ctrl_pkg::pwrmgr_data_t [pwrmgr_reg_pkg::NumRomInputs-1:0] rom_ctrl_status;
logic lc_done;
logic otp_done;
logic strap_sampled;
logic light_reset_req;
pwr_clk_rsp_t clk_status;
lc_ctrl_pkg::lc_tx_t cpu_fetch_en;
rom_ctrl_pkg::pwrmgr_data_t [pwrmgr_reg_pkg::NumRomInputs-1:0] rom_ctrl_status;
logic lc_done;
logic otp_done;
logic strap_sampled;
logic light_reset_req;
pwr_clk_rsp_t clk_status;
} pwr_boot_status_t;
% endif
// exported resets
Expand Down Expand Up @@ -203,7 +205,7 @@ package pwrmgr_pkg;

// fast fsm state enum
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 5 -m 19 -n 12 \
// $ ./util/design/sparse-fsm-encode.py -d 5 -m 19 -n 12 ${"\\"}
// -s 3096160381 --language=sv
//
// Hamming distance histogram:
Expand Down Expand Up @@ -251,7 +253,7 @@ package pwrmgr_pkg;
} fast_pwr_state_e;
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 5 -m 12 -n 10 \
// $ ./util/design/sparse-fsm-encode.py -d 5 -m 12 -n 10 ${"\\"}
// -s 1726685338 --language=sv
//
// Hamming distance histogram:
Expand Down
Loading

0 comments on commit e1cdc60

Please sign in to comment.