[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,