[keymgr] Drop sw_binding_en during normal transactions
- Address #4564
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/keymgr/data/keymgr.hjson b/hw/ip/keymgr/data/keymgr.hjson
index 04af7ff..73bedad 100644
--- a/hw/ip/keymgr/data/keymgr.hjson
+++ b/hw/ip/keymgr/data/keymgr.hjson
@@ -358,7 +358,9 @@
{ name: "SW_BINDING_EN",
desc: "Register write enable for SOFTWARE_BINDING",
swaccess: "rw0c",
- hwaccess: "hwo",
+ hwaccess: "hrw",
+ hwext: "true",
+ hwqe: "true",
fields: [
{ bits: "0",
name: "EN",
@@ -376,7 +378,7 @@
{ multireg: {
cname: "KEYMGR",
name: "SW_BINDING",
- regwen: "SW_BINDING_EN",
+ regwen: "CFGEN",
desc: '''
Software binding input to key manager.
This register is lockable and shared between key manager stages.
diff --git a/hw/ip/keymgr/rtl/keymgr.sv b/hw/ip/keymgr/rtl/keymgr.sv
index cecbd43..292538e 100644
--- a/hw/ip/keymgr/rtl/keymgr.sv
+++ b/hw/ip/keymgr/rtl/keymgr.sv
@@ -218,7 +218,9 @@
assign hw2reg.working_state.de = 1'b1;
// key manager registers cannot be changed once an operation starts
- keymgr_cfg_en u_cfgen (
+ keymgr_cfg_en #(
+ .NonInitClr(1'b1) // clear has effect even when non-init
+ ) u_cfgen (
.clk_i,
.rst_ni,
.init_i(init),
@@ -228,9 +230,33 @@
.out_o(hw2reg.cfgen.d)
);
- // we can only unlock on a successful advance call
- assign hw2reg.sw_binding_en.d = reg2hw.control.operation.q == OpAdvance;
- assign hw2reg.sw_binding_en.de = sw_binding_unlock;
+
+ logic sw_binding_set;
+ logic sw_binding_clr;
+ logic sw_binding_en;
+
+ // set on a successful advance
+ assign sw_binding_set = reg2hw.control.operation.q == OpAdvance &
+ sw_binding_unlock;
+
+ // this is w0c
+ assign sw_binding_clr = reg2hw.sw_binding_en.qe & ~reg2hw.sw_binding_en.q;
+
+ // software clears the enable
+ // hardware restores it upon successful advance
+ keymgr_cfg_en #(
+ .NonInitClr(1'b0) // clear has no effect until init
+ ) u_sw_binding_en (
+ .clk_i,
+ .rst_ni,
+ .init_i(init),
+ .en_i(lc_keymgr_en[KeyMgrEnSwBindingEn] == lc_ctrl_pkg::On),
+ .set_i(sw_binding_set),
+ .clr_i(sw_binding_clr),
+ .out_o(sw_binding_en)
+ );
+
+ assign hw2reg.sw_binding_en.d = sw_binding_en & hw2reg.cfgen.d;
/////////////////////////////////////
// Key Manager Input Construction
diff --git a/hw/ip/keymgr/rtl/keymgr_cfg_en.sv b/hw/ip/keymgr/rtl/keymgr_cfg_en.sv
index a819e97..9066f5c 100644
--- a/hw/ip/keymgr/rtl/keymgr_cfg_en.sv
+++ b/hw/ip/keymgr/rtl/keymgr_cfg_en.sv
@@ -7,7 +7,10 @@
`include "prim_assert.sv"
-module keymgr_cfg_en (
+module keymgr_cfg_en #(
+ // controls whether clear has an effect on output value during non-init
+ parameter bit NonInitClr = 1'b1
+) (
input clk_i,
input rst_ni,
input init_i,
@@ -20,9 +23,19 @@
logic out_q;
logic init_q;
+ logic vld_clr;
+ logic vld_set;
+ logic vld_dis;
+
+ assign vld_clr = init_q && clr_i;
+ assign vld_set = init_q && set_i;
+ assign vld_dis = init_q && !en_i;
+
// the same cycle where clear is asserted should already block future
// configuration
- assign out_o = ~clr_i & out_q & en_i;
+ logic out_clr;
+ assign out_clr = NonInitClr ? clr_i : vld_clr;
+ assign out_o = ~out_clr & out_q & en_i;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@@ -38,11 +51,11 @@
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
out_q <= 1'b1;
- end else if (init_q && !en_i) begin
+ end else if (vld_dis) begin
out_q <= 1'b0;
- end else if (init_q && set_i) begin
+ end else if (vld_set) begin
out_q <= 1'b1;
- end else if (init_q && clr_i) begin
+ end else if (vld_clr) begin
out_q <= 1'b0;
end
end
diff --git a/hw/ip/keymgr/rtl/keymgr_pkg.sv b/hw/ip/keymgr/rtl/keymgr_pkg.sv
index 8fed228..ead7815 100644
--- a/hw/ip/keymgr/rtl/keymgr_pkg.sv
+++ b/hw/ip/keymgr/rtl/keymgr_pkg.sv
@@ -186,6 +186,7 @@
typedef enum logic [1:0] {
KeyMgrEnCtrl,
KeyMgrEnCfgEn,
+ KeyMgrEnSwBindingEn,
KeyMgrEnLast
} keymgr_lc_en_usage_e;
diff --git a/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv b/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
index 947ed83..594779d 100644
--- a/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
+++ b/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
@@ -60,6 +60,11 @@
} keymgr_reg2hw_reseed_interval_reg_t;
typedef struct packed {
+ logic q;
+ logic qe;
+ } keymgr_reg2hw_sw_binding_en_reg_t;
+
+ typedef struct packed {
logic [31:0] q;
} keymgr_reg2hw_sw_binding_mreg_t;
@@ -117,7 +122,6 @@
typedef struct packed {
logic d;
- logic de;
} keymgr_hw2reg_sw_binding_en_reg_t;
typedef struct packed {
@@ -164,13 +168,14 @@
// Register to internal design logic //
///////////////////////////////////////
typedef struct packed {
- keymgr_reg2hw_intr_state_reg_t intr_state; // [418:418]
- keymgr_reg2hw_intr_enable_reg_t intr_enable; // [417:417]
- keymgr_reg2hw_intr_test_reg_t intr_test; // [416:415]
- keymgr_reg2hw_alert_test_reg_t alert_test; // [414:411]
- keymgr_reg2hw_control_reg_t control; // [410:405]
- keymgr_reg2hw_sideload_clear_reg_t sideload_clear; // [404:404]
- keymgr_reg2hw_reseed_interval_reg_t reseed_interval; // [403:388]
+ keymgr_reg2hw_intr_state_reg_t intr_state; // [420:420]
+ keymgr_reg2hw_intr_enable_reg_t intr_enable; // [419:419]
+ keymgr_reg2hw_intr_test_reg_t intr_test; // [418:417]
+ keymgr_reg2hw_alert_test_reg_t alert_test; // [416:413]
+ keymgr_reg2hw_control_reg_t control; // [412:407]
+ keymgr_reg2hw_sideload_clear_reg_t sideload_clear; // [406:406]
+ keymgr_reg2hw_reseed_interval_reg_t reseed_interval; // [405:390]
+ keymgr_reg2hw_sw_binding_en_reg_t sw_binding_en; // [389:388]
keymgr_reg2hw_sw_binding_mreg_t [3:0] sw_binding; // [387:260]
keymgr_reg2hw_salt_mreg_t [3:0] salt; // [259:132]
keymgr_reg2hw_key_version_mreg_t [0:0] key_version; // [131:100]
@@ -184,10 +189,10 @@
// Internal design logic to register //
///////////////////////////////////////
typedef struct packed {
- keymgr_hw2reg_intr_state_reg_t intr_state; // [549:548]
- keymgr_hw2reg_cfgen_reg_t cfgen; // [547:547]
- keymgr_hw2reg_control_reg_t control; // [546:545]
- keymgr_hw2reg_sw_binding_en_reg_t sw_binding_en; // [544:543]
+ keymgr_hw2reg_intr_state_reg_t intr_state; // [548:547]
+ keymgr_hw2reg_cfgen_reg_t cfgen; // [546:546]
+ keymgr_hw2reg_control_reg_t control; // [545:544]
+ keymgr_hw2reg_sw_binding_en_reg_t sw_binding_en; // [543:543]
keymgr_hw2reg_sw_share0_output_mreg_t [7:0] sw_share0_output; // [542:279]
keymgr_hw2reg_sw_share1_output_mreg_t [7:0] sw_share1_output; // [278:15]
keymgr_hw2reg_working_state_reg_t working_state; // [14:11]
diff --git a/hw/ip/keymgr/rtl/keymgr_reg_top.sv b/hw/ip/keymgr/rtl/keymgr_reg_top.sv
index 28fba8d..c162830 100644
--- a/hw/ip/keymgr/rtl/keymgr_reg_top.sv
+++ b/hw/ip/keymgr/rtl/keymgr_reg_top.sv
@@ -103,6 +103,7 @@
logic sw_binding_en_qs;
logic sw_binding_en_wd;
logic sw_binding_en_we;
+ logic sw_binding_en_re;
logic [31:0] sw_binding_0_qs;
logic [31:0] sw_binding_0_wd;
logic sw_binding_0_we;
@@ -466,29 +467,18 @@
);
- // R[sw_binding_en]: V(False)
+ // R[sw_binding_en]: V(True)
- prim_subreg #(
- .DW (1),
- .SWACCESS("W0C"),
- .RESVAL (1'h1)
+ prim_subreg_ext #(
+ .DW (1)
) u_sw_binding_en (
- .clk_i (clk_i ),
- .rst_ni (rst_ni ),
-
- // from register interface
+ .re (sw_binding_en_re),
.we (sw_binding_en_we),
.wd (sw_binding_en_wd),
-
- // from internal hardware
- .de (hw2reg.sw_binding_en.de),
- .d (hw2reg.sw_binding_en.d ),
-
- // to internal hardware
- .qe (),
- .q (),
-
- // to register interface (read)
+ .d (hw2reg.sw_binding_en.d),
+ .qre (),
+ .qe (reg2hw.sw_binding_en.qe),
+ .q (reg2hw.sw_binding_en.q ),
.qs (sw_binding_en_qs)
);
@@ -506,7 +496,7 @@
.rst_ni (rst_ni ),
// from register interface (qualified with register enable)
- .we (sw_binding_0_we & sw_binding_en_qs),
+ .we (sw_binding_0_we & cfgen_qs),
.wd (sw_binding_0_wd),
// from internal hardware
@@ -533,7 +523,7 @@
.rst_ni (rst_ni ),
// from register interface (qualified with register enable)
- .we (sw_binding_1_we & sw_binding_en_qs),
+ .we (sw_binding_1_we & cfgen_qs),
.wd (sw_binding_1_wd),
// from internal hardware
@@ -560,7 +550,7 @@
.rst_ni (rst_ni ),
// from register interface (qualified with register enable)
- .we (sw_binding_2_we & sw_binding_en_qs),
+ .we (sw_binding_2_we & cfgen_qs),
.wd (sw_binding_2_wd),
// from internal hardware
@@ -587,7 +577,7 @@
.rst_ni (rst_ni ),
// from register interface (qualified with register enable)
- .we (sw_binding_3_we & sw_binding_en_qs),
+ .we (sw_binding_3_we & cfgen_qs),
.wd (sw_binding_3_wd),
// from internal hardware
@@ -1633,6 +1623,7 @@
assign sw_binding_en_we = addr_hit[8] & reg_we & ~wr_err;
assign sw_binding_en_wd = reg_wdata[0];
+ assign sw_binding_en_re = addr_hit[8] && reg_re;
assign sw_binding_0_we = addr_hit[9] & reg_we & ~wr_err;
assign sw_binding_0_wd = reg_wdata[31:0];