[keymgr] Update keymgr to use prim_edn_req
- also enhance prim_edn_req to perform repetition checks
- keymgr does not need repetition checks, but switch to prim_edn_req
anyways for future proofing in case it is needed.
- update other modules for unused output.
- Turn on repetition check flag only for otbn
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/keymgr/keymgr.core b/hw/ip/keymgr/keymgr.core
index 2fae22c..3051bbd 100644
--- a/hw/ip/keymgr/keymgr.core
+++ b/hw/ip/keymgr/keymgr.core
@@ -10,6 +10,7 @@
depend:
- lowrisc:prim:all
- lowrisc:prim:count
+ - lowrisc:prim:edn_req
- lowrisc:prim:lc_sync
- lowrisc:prim:lfsr
- lowrisc:prim:msb_extend
diff --git a/hw/ip/keymgr/rtl/keymgr_reseed_ctrl.sv b/hw/ip/keymgr/rtl/keymgr_reseed_ctrl.sv
index 581925a..ae54c05 100644
--- a/hw/ip/keymgr/rtl/keymgr_reseed_ctrl.sv
+++ b/hw/ip/keymgr/rtl/keymgr_reseed_ctrl.sv
@@ -32,43 +32,62 @@
output logic cnt_err_o
);
- localparam int unsigned EdnRounds = LfsrWidth / EdnWidth;
- localparam int unsigned EdnCntWidth = prim_util_pkg::vbits(EdnRounds);
- localparam int unsigned LastEdnRound = EdnRounds - 1;
-
- // counter to track number of edn rounds
- logic [EdnCntWidth-1:0] edn_cnt;
- logic edn_txn_done;
+ logic local_req;
+ logic edn_req;
+ logic edn_ack;
+ logic [15:0] reseed_cnt;
logic edn_done;
- logic edn_req, edn_req_d, edn_req_q, edn_ack;
- logic [EdnWidth-1:0] edn_data;
- // This tracks how many edn rounds are required to fill up
- // one required entry.
- assign edn_txn_done = edn_req & edn_ack;
- assign edn_done = (edn_cnt == LastEdnRound[EdnCntWidth-1:0]) & edn_txn_done;
+ assign edn_done = edn_req & edn_ack;
+
+ // An edn request can either come from counter or from external
+ assign local_req = reseed_cnt >= reseed_interval_i;
+
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
- edn_cnt <= '0;
+ edn_req <= '0;
end else if (edn_done) begin
- edn_cnt <= '0;
- end else if (edn_txn_done) begin
- edn_cnt <= edn_cnt - 1'b1;
+ edn_req <= '0;
+ end else if (!edn_req && (reseed_req_i || local_req)) begin
+ // if edn request is not going, make a new request
+ edn_req <= 1'b1;
end
end
- // first activation of edn counter
- logic first_use;
+ assign seed_en_o = edn_ack;
+ assign reseed_ack_o = reseed_req_i & edn_ack;
+
+ prim_edn_req #(
+ .OutWidth(LfsrWidth)
+ ) u_edn_req (
+ .clk_i,
+ .rst_ni,
+ .req_chk_i(1'b1),
+ .req_i(edn_req),
+ .ack_o(edn_ack),
+ .data_o(seed_o),
+ .fips_o(),
+ .err_o(),
+ .clk_edn_i,
+ .rst_edn_ni,
+ .edn_o,
+ .edn_i
+ );
+
+
+ // suppress first reseed count until the first transaction has gone through.
+ // This ensures the first entropy fetch is controlled by software timing and
+ // there is no chance to accidentally pick-up boot time entropy unless intended by software.
+ logic cnt_en;
always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- first_use <= 1'b1;
- end else if (edn_done) begin
- first_use <= 1'b0;
- end
+ if (!rst_ni) begin
+ cnt_en <= '0;
+ end else if (edn_done) begin
+ cnt_en <= 1'b1;
+ end
end
// whenever reseed count reaches reseed_interval, issue a request and wait for ack
- logic [15:0] reseed_cnt;
// SEC_CM: RESEED.CTR.REDUN
prim_count #(
.Width(16),
@@ -80,78 +99,10 @@
.clr_i(edn_done),
.set_i('0),
.set_cnt_i('0),
- .en_i(~edn_req & ~first_use),
+ .en_i(cnt_en),
.step_i(16'h1),
.cnt_o(reseed_cnt),
.err_o(cnt_err_o)
);
- // latch edn request to ensure even if interval is changed in the middle
- // the req/ack protocol is respected
- always_ff @(posedge clk_i or negedge rst_ni) begin
- if (!rst_ni) begin
- edn_req_q <= '0;
- end else if (edn_done) begin
- edn_req_q <= '0;
- end else begin
- edn_req_q <= edn_req_q | edn_req_d;
- end
- end
-
- // An edn request can either come from counter or from external
- assign edn_req_d = reseed_req_i | (~first_use & (reseed_cnt == reseed_interval_i));
- assign edn_req = edn_req_q | edn_req_d;
-
- assign reseed_ack_o = reseed_req_i & edn_done;
- assign seed_en_o = edn_done;
-
- if (EdnRounds == 1) begin : gen_same_width
- assign seed_o = edn_data;
- end else begin : gen_mult_width
- // hold one less transaction in storage
- localparam int DeltaWidth = LfsrWidth-EdnWidth;
- logic [DeltaWidth-1:0] seed_q;
-
- if (DeltaWidth > EdnWidth) begin : gen_greater_width
- always_ff @(posedge clk_i) begin
- if (edn_txn_done) begin
- seed_q <= {seed_q[0 +: DeltaWidth-EdnWidth], edn_data};
- end
- end
- end else begin : gen_double_width
- always_ff @(posedge clk_i) begin
- if (edn_txn_done) begin
- seed_q <= edn_data;
- end
- end
- end
-
- assign seed_o = {seed_q, edn_data};
- end
-
- //req/ack interface to edn
- prim_sync_reqack u_reqack (
- .clk_src_i(clk_i),
- .rst_src_ni(rst_ni),
- .clk_dst_i(clk_edn_i),
- .rst_dst_ni(rst_edn_ni),
- .req_chk_i(1'b1),
- .src_req_i(edn_req),
- .src_ack_o(edn_ack),
- .dst_req_o(edn_o.edn_req),
- .dst_ack_i(edn_i.edn_ack)
- );
-
- // capture the data on edn domain since the ack interface
- // finishes before the source domain is able to see it
- always_ff @(posedge clk_edn_i) begin
- if (edn_o.edn_req && edn_i.edn_ack) begin
- edn_data <= edn_i.edn_bus;
- end
- end
-
-
- logic unused_fips;
- assign unused_fips = edn_i.edn_fips;
-
endmodule // keymgr_reseed_ctrl
diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv
index 64d74ea..574fad9 100644
--- a/hw/ip/kmac/rtl/kmac.sv
+++ b/hw/ip/kmac/rtl/kmac.sv
@@ -1134,6 +1134,7 @@
.ack_o (entropy_ack),
.data_o (entropy_data),
.fips_o (entropy_fips),
+ .err_o (),
// EDN side
.clk_edn_i,
.rst_edn_ni,
diff --git a/hw/ip/otbn/rtl/otbn.sv b/hw/ip/otbn/rtl/otbn.sv
index 5e6f7bf..5b2d61b 100644
--- a/hw/ip/otbn/rtl/otbn.sv
+++ b/hw/ip/otbn/rtl/otbn.sv
@@ -863,7 +863,8 @@
// internal entropy width of 256 bit.
prim_edn_req #(
- .OutWidth(EdnDataWidth)
+ .OutWidth(EdnDataWidth),
+ .RepCheck(1'b1)
) u_prim_edn_rnd_req (
.clk_i,
.rst_ni ( rst_n ),
@@ -872,6 +873,7 @@
.ack_o ( edn_rnd_ack ),
.data_o ( edn_rnd_data ),
.fips_o ( ), // unused
+ .err_o ( ),
.clk_edn_i,
.rst_edn_ni,
.edn_o ( edn_rnd_o ),
@@ -888,6 +890,7 @@
.ack_o ( edn_urnd_ack ),
.data_o ( edn_urnd_data ),
.fips_o ( ), // unused
+ .err_o ( ), // unused
.clk_edn_i,
.rst_edn_ni,
.edn_o ( edn_urnd_o ),
diff --git a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
index b5a76a8..94f1fdc 100644
--- a/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
+++ b/hw/ip/otp_ctrl/rtl/otp_ctrl.sv
@@ -669,6 +669,7 @@
.ack_o ( edn_ack ),
.data_o ( edn_data ),
.fips_o ( ), // unused
+ .err_o ( ), // unused
.clk_edn_i,
.rst_edn_ni,
.edn_o,
diff --git a/hw/ip/prim/rtl/prim_edn_req.sv b/hw/ip/prim/rtl/prim_edn_req.sv
index 430594f..986704c 100644
--- a/hw/ip/prim/rtl/prim_edn_req.sv
+++ b/hw/ip/prim/rtl/prim_edn_req.sv
@@ -17,6 +17,8 @@
import prim_alert_pkg::*;
#(
parameter int OutWidth = 32,
+ // Repetition check for incoming edn data
+ parameter bit RepCheck = 0,
// EDN Request latency checker
//
@@ -37,6 +39,7 @@
output logic ack_o,
output logic [OutWidth-1:0] data_o,
output logic fips_o,
+ output logic err_o, // incoming data failed repetition check
// EDN side
input clk_edn_i,
input rst_edn_ni,
@@ -69,6 +72,31 @@
.data_o ( {word_fips, word_data} )
);
+ if (RepCheck) begin : gen_rep_chk
+ logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] word_data_q;
+ always_ff @(posedge clk_i) begin
+ if (word_ack) begin
+ word_data_q <= word_data;
+ end
+ end
+
+ // do not check until we have received at least the first entry
+ logic chk_rep;
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ chk_rep <= '0;
+ end else if (word_ack) begin
+ chk_rep <= 1'b1;
+ end
+ end
+
+ // whenever a new word is received, check if it is identical to the last
+ // word
+ assign err_o = chk_rep & word_ack & (word_data == word_data_q);
+ end else begin : gen_no_rep_chk // block: gen_rep_chk
+ assign err_o = '0;
+ end
+
prim_packer_fifo #(
.InW(edn_pkg::ENDPOINT_BUS_WIDTH),
.OutW(OutWidth),
diff --git a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
index f622574..7a4cd6e 100644
--- a/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
+++ b/hw/ip/rv_core_ibex/rtl/rv_core_ibex.sv
@@ -773,6 +773,7 @@
.ack_o(edn_ack),
.data_o(edn_data),
.fips_o(edn_fips),
+ .err_o(),
.clk_edn_i,
.rst_edn_ni,
.edn_o,
diff --git a/hw/ip_templates/alert_handler/rtl/alert_handler.sv b/hw/ip_templates/alert_handler/rtl/alert_handler.sv
index 1f6b4d1..7c06fdd 100644
--- a/hw/ip_templates/alert_handler/rtl/alert_handler.sv
+++ b/hw/ip_templates/alert_handler/rtl/alert_handler.sv
@@ -109,6 +109,7 @@
.ack_o ( edn_ack ),
.data_o ( edn_data ),
.fips_o ( ),
+ .err_o ( ),
// EDN side
.clk_edn_i,
.rst_edn_ni,
diff --git a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv
index 1f6b4d1..7c06fdd 100644
--- a/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv
+++ b/hw/top_earlgrey/ip_autogen/alert_handler/rtl/alert_handler.sv
@@ -109,6 +109,7 @@
.ack_o ( edn_ack ),
.data_o ( edn_data ),
.fips_o ( ),
+ .err_o ( ),
// EDN side
.clk_edn_i,
.rst_edn_ni,