[flash_ctrl] Connect flash / pwrmgr functions
- Connect init / done
- Connect idle
Signed-off-by: Timothy Chen <timothytim@google.com>
[flash_ctrl] update waivers
Signed-off-by: Timothy Chen <timothytim@google.com>
[flash_ctrl] fix typos
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.hjson b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
index f420430..c214965 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.hjson
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.hjson
@@ -36,13 +36,20 @@
package: "flash_ctrl_pkg"
},
- { struct: "pwrmgr_flash",
+ { struct: "edn_entropy",
type: "uni",
- name: "pwrmgr",
+ name: "edn",
act: "rcv",
package: "flash_ctrl_pkg"
},
+ { struct: "pwr_flash",
+ type: "req_rsp",
+ name: "pwrmgr",
+ act: "rsp",
+ package: "pwrmgr_pkg"
+ },
+
],
param_list: [
diff --git a/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv b/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
index e4facd1..b903f01 100644
--- a/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
+++ b/hw/ip/flash_ctrl/dv/tb/flash_ctrl_wrapper.sv
@@ -17,7 +17,8 @@
// OTP interface
input flash_ctrl_pkg::otp_flash_t otp_i,
input flash_ctrl_pkg::lc_flash_req_t lc_i,
- input flash_ctrl_pkg::pwrmgr_flash_t pwrmgr_i,
+ output pwrmgr_pkg::pwr_flash_rsp_t pwrmgr_o,
+ input pwrmgr_pkg::pwr_flash_req_t pwrmgr_i,
input flash_ctrl_pkg::edn_entropy_t edn_i,
// Interrupts
@@ -51,6 +52,7 @@
.otp_i (otp_i),
.lc_i (lc_i),
.pwrmgr_i (pwrmgr_i),
+ .pwrmgr_o (pwrmgr_o),
.edn_i (edn_i),
.clk_i (clk_i),
diff --git a/hw/ip/flash_ctrl/dv/tb/tb.sv b/hw/ip/flash_ctrl/dv/tb/tb.sv
index fa564df..c6b08a1 100644
--- a/hw/ip/flash_ctrl/dv/tb/tb.sv
+++ b/hw/ip/flash_ctrl/dv/tb/tb.sv
@@ -46,7 +46,8 @@
// TODO: create and hook this up to an interface.
.otp_i (flash_ctrl_pkg::OTP_FLASH_DEFAULT),
.lc_i (flash_ctrl_pkg::LC_FLASH_REQ_DEFAULT),
- .pwrmgr_i (flash_ctrl_pkg::PWRMGR_FLASH_DEFAULT),
+ .pwrmgr_o (pwrmgr_pkg::PWR_FLASH_RSP_DEFAULT),
+ .pwrmgr_i (pwrmgr_pkg::PWR_FLASH_REQ_DEFAULT),
.edn_i (flash_ctrl_pkg::EDN_ENTROPY_DEFAULT),
.intr_prog_empty_o (intr_prog_empty),
diff --git a/hw/ip/flash_ctrl/flash_ctrl.core b/hw/ip/flash_ctrl/flash_ctrl.core
index 2280904..b760c47 100644
--- a/hw/ip/flash_ctrl/flash_ctrl.core
+++ b/hw/ip/flash_ctrl/flash_ctrl.core
@@ -14,6 +14,7 @@
- lowrisc:prim:lfsr
- lowrisc:prim:flash
- lowrisc:prim:gf_mult
+ - lowrisc:ip:pwrmgr_pkg
- lowrisc:ip:flash_ctrl_pkg
files:
- rtl/flash_ctrl_reg_top.sv
diff --git a/hw/ip/flash_ctrl/lint/flash_ctrl.waiver b/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
index 25a4d5d..192c86b 100644
--- a/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
+++ b/hw/ip/flash_ctrl/lint/flash_ctrl.waiver
@@ -7,3 +7,14 @@
# All leaf resets have a reset multiplex
waive -rules TERMINAL_STATE -location {flash_ctrl_lcmgr.sv} -regexp {.*StInvalid.*} \
-comment "StInvalid is intended to be a terminal state"
+
+# Remove errors from prim_* modules
+# TBD These should be directly addressed in primgen modules long term
+waive -rules INPUT_NOT_READ -location {prim_flop.sv} -regexp {Input port.*} \
+ -comment "Silience prim related errors"
+
+waive -rules OUTPUT_NOT_DRIVEN -location {prim_flop*.sv} -regexp {.*q_o.*} \
+ -comment "Silience prim related errors"
+
+waive -rules INPUT_NOT_READ -location {prim_flop_2sync.sv} -regexp {Input port.*} \
+ -comment "Silience prim related errors"
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
index aacc643..71c69b1 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl.sv
@@ -24,7 +24,8 @@
input otp_flash_t otp_i,
input lc_flash_req_t lc_i,
output lc_flash_rsp_t lc_o,
- input pwrmgr_flash_t pwrmgr_i,
+ input pwrmgr_pkg::pwr_flash_req_t pwrmgr_i,
+ output pwrmgr_pkg::pwr_flash_rsp_t pwrmgr_o,
input edn_entropy_t edn_i,
// Interrupts
@@ -269,7 +270,8 @@
.clk_i,
.rst_ni,
- .init_i(pwrmgr_i.init),
+ .init_i(pwrmgr_i.flash_init),
+ .init_done_o(pwrmgr_o.flash_done),
.provision_en_i(lc_i.provision_en),
// interface to ctrl arb control ports
@@ -385,9 +387,6 @@
.flash_error_i (flash_mp_error)
);
- // Read FIFO
-
-
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
adapter_rvalid <= 1'b0;
@@ -636,6 +635,23 @@
assign flash_rd_data = flash_i.rd_data;
assign flash_phy_busy = flash_i.init_busy;
+ // Interface to pwrmgr
+ // flash is not idle as long as there is a stateful operation ongoing
+ logic flash_idle_d;
+ assign flash_idle_d = ~(flash_o.req &
+ (flash_o.prog | flash_o.pg_erase | flash_o.bk_erase));
+
+ prim_flop #(
+ .Width(1),
+ .ResetValue(1'b1)
+ ) u_reg_idle (
+ .clk_i,
+ .rst_ni,
+ .d_i(flash_idle_d),
+ .q_o(pwrmgr_o.flash_idle)
+ );
+
+
// Interrupts
// Generate edge triggered signals for sources that are level
logic [3:0] intr_src;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
index 181588d..f14534c 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
@@ -60,7 +60,7 @@
output logic prog_fifo_wvalid_o,
input logic prog_fifo_wready_i,
- // flash phy initilization ongoing
+ // flash phy initialization ongoing
input logic flash_phy_busy_i,
// clear fifo contents
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
index fcf14f0..cd32191 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_lcmgr.sv
@@ -11,6 +11,7 @@
// initialization command
input init_i,
+ output logic init_done_o,
// only access seeds when provisioned
input provision_en_i,
@@ -81,6 +82,7 @@
} state_e;
state_e state_q, state_d;
+ logic init_done_d;
logic validate_q, validate_d;
logic [SeedCntWidth-1:0] seed_cnt_q;
logic [CntWidth-1:0] addr_cnt_q;
@@ -97,9 +99,11 @@
if (!rst_ni) begin
state_q <= StIdle;
validate_q <= 1'b0;
+ init_done_o <= 1'b0;
end else begin
state_q <= state_d;
validate_q <= validate_d;
+ init_done_o <= init_done_d;
end
end
@@ -175,6 +179,19 @@
// rma phase is erase unless we are validating
assign op = seed_phase || validate_q ? FlashOpRead : FlashOpErase;
+ // synchronize inputs
+ logic init_q;
+
+ prim_flop_2sync #(
+ .Width(1),
+ .ResetValue(0)
+ ) u_sync_flash_init (
+ .clk_i,
+ .rst_ni,
+ .d_i(init_i),
+ .q_o(init_q)
+ );
+
always_comb begin
// phases of the hardware interface
@@ -202,15 +219,20 @@
state_d = state_q;
validate_d = validate_q;
+ // init status
+ // flash_ctrl handles its own arbitration between hardware and software.
+ // So once the init kicks off it is safe to ack. The done signal is still
+ // to give a chance to hold off further power up progression in the future
+ // if required.
+ init_done_d = 1'b1;
+
unique case (state_q)
StIdle: begin
+ init_done_d = 1'b0;
phase = PhaseSeed;
- // TBD: provision_en is only a "good" value after otp initilization
- // Need to qualify this statement with some notion that otp init has
- // finished. Since power manager will kick off otp init, it should
- // also be able to kick off flash_init
- if (init_i) begin
+ // provision_en is only a "good" value after otp/lc initialization
+ if (init_q) begin
// if provisioning is not enabled, do not read seeds and skip directly
// to wait state.
state_d = provision_en_i ? StReadSeeds : StWait;
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
index e7f23e1..336f9b6 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_pkg.sv
@@ -282,11 +282,6 @@
logic [BusWidth-1:0] rma_ack_token;
} lc_flash_rsp_t;
- // pwrmgr to flash_ctrl
- typedef struct packed {
- logic init;
- } pwrmgr_flash_t;
-
// place holder for interface to EDN, replace with real one later
typedef struct packed {
logic valid;
@@ -309,10 +304,6 @@
provision_en: 1'b1
};
- parameter pwrmgr_flash_t PWRMGR_FLASH_DEFAULT = '{
- init: 1'b1
- };
-
parameter edn_entropy_t EDN_ENTROPY_DEFAULT = '{
valid: 1'b1,
entropy: '0
diff --git a/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl b/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl
index 0ba5f45..17b1246 100644
--- a/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl
+++ b/hw/ip/pwrmgr/data/pwrmgr.hjson.tpl
@@ -49,9 +49,9 @@
},
{ struct: "pwr_flash",
- type: "uni",
+ type: "req_rsp",
name: "pwr_flash",
- act: "rcv",
+ act: "req",
package: "pwrmgr_pkg",
},
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr.sv b/hw/ip/pwrmgr/rtl/pwrmgr.sv
index e049fc3..d97cb89 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr.sv
@@ -40,7 +40,8 @@
output pwr_lc_req_t pwr_lc_o,
// flash interface
- input pwr_flash_t pwr_flash_i,
+ output pwr_flash_req_t pwr_flash_o,
+ input pwr_flash_rsp_t pwr_flash_i,
// processor interface
input pwr_cpu_t pwr_cpu_i,
@@ -79,6 +80,8 @@
logic low_power_fall_through;
logic low_power_abort;
+ pwr_flash_rsp_t flash_rsp;
+
////////////////////////////
/// clk_slow_i domain declarations
////////////////////////////
@@ -182,7 +185,11 @@
.ast_i(pwr_ast_i),
// peripheral signals
- .peri_i(peri_reqs_raw)
+ .peri_i(peri_reqs_raw),
+
+ // flash handshake
+ .flash_i(pwr_flash_i),
+ .flash_o(flash_rsp)
);
assign hw2reg.cfg_cdc_sync.d = 1'b0;
@@ -291,7 +298,9 @@
.lc_idle_i (pwr_lc_i.lc_idle),
// flash
- .flash_idle_i (pwr_flash_i.flash_idle)
+ .flash_init_o (pwr_flash_o.flash_init),
+ .flash_done_i (flash_rsp.flash_done),
+ .flash_idle_i (flash_rsp.flash_idle)
);
////////////////////////////
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv b/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv
index c4ccd9b..307f5c2 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_cdc.sv
@@ -48,6 +48,8 @@
// peripheral inputs, mixed domains
input pwr_peri_t peri_i,
+ input pwr_flash_rsp_t flash_i,
+ output pwr_flash_rsp_t flash_o,
// AST inputs, unknown domain
input pwr_ast_rsp_t ast_i
@@ -212,7 +214,7 @@
end
end
- prim_flop_2sync # (
+ prim_flop_2sync #(
.Width(HwRstReqs + NumWkups)
) i_ext_req_sync (
.clk_i,
@@ -221,6 +223,27 @@
.q_o(peri_reqs_o)
);
+ // synchronize inputs from flash
+ prim_flop_2sync #(
+ .Width(1),
+ .ResetValue(1'b0)
+ ) u_sync_flash_done (
+ .clk_i,
+ .rst_ni,
+ .d_i(flash_i.flash_done),
+ .q_o(flash_o.flash_done)
+ );
+
+ prim_flop_2sync #(
+ .Width(1),
+ .ResetValue(1'b1)
+ ) u_sync_flash_idle (
+ .clk_i,
+ .rst_ni,
+ .d_i(flash_i.flash_idle),
+ .q_o(flash_o.flash_idle)
+ );
+
endmodule
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
index 8c7028a..b923dd4 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_fsm.sv
@@ -48,6 +48,8 @@
input lc_idle_i,
// flash
+ output logic flash_init_o,
+ input flash_done_i,
input flash_idle_i
);
@@ -58,6 +60,7 @@
StReleaseLcRst,
StOtpInit,
StLcInit,
+ StFlashInit,
StAckPwrUp,
StActive,
StDisClks,
@@ -96,6 +99,7 @@
logic [PowerDomains-1:0] rst_lc_req_d, rst_sys_req_d;
logic otp_init;
logic lc_init;
+ logic flash_init_d;
assign pd_n_rsts_asserted = pwr_rst_i.rst_lc_src_n[PowerDomains-1:1] == '0 &
pwr_rst_i.rst_sys_src_n[PowerDomains-1:1] == '0;
@@ -149,6 +153,7 @@
rst_lc_req_d = rst_lc_req_q;
rst_sys_req_d = rst_sys_req_q;
reset_cause_d = reset_cause_q;
+ flash_init_d = 1'b0;
unique case(state_q)
@@ -186,12 +191,20 @@
lc_init = 1'b1;
if (lc_done_i) begin
- state_d = StAckPwrUp;
-
+ state_d = StFlashInit;
end
end
+ StFlashInit: begin
+ flash_init_d = 1'b1;
+
+ if (flash_done_i) begin
+ state_d = StAckPwrUp;
+ end
+ end
+
+
StAckPwrUp: begin
// only ack the slow_fsm if we actually transitioned through it
ack_pwrup_d = !reset_ongoing_q;
@@ -315,5 +328,15 @@
assign lc_init_o = lc_init;
assign ips_clk_en_o = ip_clk_en_q;
+ prim_flop #(
+ .Width(1),
+ .ResetValue(1'b1)
+ ) u_reg_idle (
+ .clk_i,
+ .rst_ni,
+ .d_i(flash_init_d),
+ .q_o(flash_init_o)
+ );
+
endmodule
diff --git a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
index 98c7d38..6019123 100644
--- a/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
+++ b/hw/ip/pwrmgr/rtl/pwrmgr_pkg.sv
@@ -12,7 +12,7 @@
// variables referenced by other modules / packages
parameter int HwRstReqs = 2; // this needs to be a topgen populated number, or from topcfg?
- parameter int PowerDomains = 2; // this maybe needs to be a topgen populated number, or from topcfg?
+ parameter int PowerDomains = 2; // this needs to be a topgen populated number, or from topcfg?
// variables referenced only by pwrmgr
// pwrmgr_reg_pkg::NumWkups; // should this be coming from top_pkg instead?
@@ -122,11 +122,21 @@
// flash to pwrmgr
typedef struct packed {
+ logic flash_init;
+ } pwr_flash_req_t;
+
+ typedef struct packed {
+ logic flash_done;
logic flash_idle;
- } pwr_flash_t;
+ } pwr_flash_rsp_t;
// default value (for dangling ports)
- parameter pwr_flash_t PWR_FLASH_DEFAULT = '{
+ parameter pwr_flash_req_t PWR_FLASH_REQ_DEFAULT = '{
+ flash_init: 1'b1
+ };
+
+ parameter pwr_flash_rsp_t PWR_FLASH_RSP_DEFAULT = '{
+ flash_done: 1'b1,
flash_idle: 1'b1
};
diff --git a/hw/top_earlgrey/data/top_earlgrey.hjson b/hw/top_earlgrey/data/top_earlgrey.hjson
index 4cced93..7bb98f2 100644
--- a/hw/top_earlgrey/data/top_earlgrey.hjson
+++ b/hw/top_earlgrey/data/top_earlgrey.hjson
@@ -399,7 +399,8 @@
// e.g flash_ctrl0.flash: [flash_phy0.flash_ctrl]
inter_module: {
'connect': {
- 'flash_ctrl.flash': ['eflash.flash_ctrl']
+ 'flash_ctrl.flash': ['eflash.flash_ctrl'],
+ 'pwrmgr.pwr_flash': ['flash_ctrl.pwrmgr'],
'pwrmgr.pwr_rst' : ['rstmgr.pwr'],
'pwrmgr.pwr_clk' : ['clkmgr.pwr'],
}
diff --git a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
index 8253d82..117b1d5 100644
--- a/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
+++ b/hw/top_earlgrey/lint/top_earlgrey_lint_cfgs.hjson
@@ -35,6 +35,12 @@
fusesoc_core: lowrisc:ip:flash_ctrl
import_cfgs: ["{proj_root}/hw/lint/data/common_lint_cfg.hjson"]
rel_path: "hw/ip/flash_ctrl/lint/{tool}"
+ overrides: [
+ {
+ name: design_level
+ value: "top"
+ }
+ ]
},
{ name: gpio
fusesoc_core: lowrisc:ip:gpio