[otbn,rtl] Avoid a 1-cycle glitch in locking_o

The locking_o signal used to be computed as follows:

  assign locking_o = (state_d == OtbnStateLocked) & ~secure_wipe_running_i;

This used to use state_q, but 48e4bb6 changed to state_d to move it a
cycle earlier. Of course, this doesn't work properly because you end
up with a single cycle "glitch" where locking_o is asserted before the
secure wipe starts.

The problem is that you can't just assert secure_wipe_running_o in the
start/stop controller a cycle earlier because you end up with a
combinational loop (I tried!). This commit switches the start/stop
controller to a sort of req/ack interface where the controller asks to
start a secure wipe and the start/stop controller responds once it's
done.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
diff --git a/hw/ip/otbn/dv/tracer/rtl/otbn_trace_if.sv b/hw/ip/otbn/dv/tracer/rtl/otbn_trace_if.sv
index f024dfc..4fb9cbf 100644
--- a/hw/ip/otbn/dv/tracer/rtl/otbn_trace_if.sv
+++ b/hw/ip/otbn/dv/tracer/rtl/otbn_trace_if.sv
@@ -82,7 +82,8 @@
 
   input logic [1:0][otbn_pkg::SideloadKeyWidth-1:0] sideload_key_shares_i,
 
-  input logic secure_wipe_running
+  input logic start_secure_wipe,
+  input logic secure_wipe_done
 );
   import otbn_pkg::*;
 
@@ -310,16 +311,14 @@
     assign flags_read_data[i_fg] = u_otbn_alu_bignum.flags_q[i_fg];
   end
 
-  // Detect negative edges of the secure wipe signal
-  logic secure_wipe_running_r, secure_wipe_done;
+  logic secure_wipe_running;
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
-      secure_wipe_running_r <= 0;
+      secure_wipe_running <= 0;
     end else begin
-      secure_wipe_running_r <= secure_wipe_running;
+      secure_wipe_running <= start_secure_wipe | (secure_wipe_running & ~secure_wipe_done);
     end
   end
-  assign secure_wipe_done = secure_wipe_running_r & ~secure_wipe_running;
 
 endinterface
 
diff --git a/hw/ip/otbn/dv/tracer/rtl/otbn_tracer.sv b/hw/ip/otbn/dv/tracer/rtl/otbn_tracer.sv
index f0b2cee..95b1e06 100644
--- a/hw/ip/otbn/dv/tracer/rtl/otbn_tracer.sv
+++ b/hw/ip/otbn/dv/tracer/rtl/otbn_tracer.sv
@@ -207,10 +207,10 @@
       end
     end
     if (SecWipeEn) begin
-      if (otbn_trace.secure_wipe_running) begin
-        output_trace(WipeInProgressPrefix, "");
-      end else if (otbn_trace.secure_wipe_done) begin
+      if (otbn_trace.secure_wipe_done) begin
         output_trace(WipeCompletePrefix, "");
+      end else if (otbn_trace.secure_wipe_running) begin
+        output_trace(WipeInProgressPrefix, "");
       end
     end
   endfunction
diff --git a/hw/ip/otbn/rtl/otbn_controller.sv b/hw/ip/otbn/rtl/otbn_controller.sv
index cbaddd8..5233085 100644
--- a/hw/ip/otbn/rtl/otbn_controller.sv
+++ b/hw/ip/otbn/rtl/otbn_controller.sv
@@ -136,8 +136,8 @@
   input  logic rnd_fips_err_i,
 
   // Secure Wipe
-  input  logic secure_wipe_running_i,
   output logic start_secure_wipe_o,
+  input  logic secure_wipe_done_i,
   input  logic sec_wipe_zero_i,
 
   input  logic        state_reset_i,
@@ -285,6 +285,15 @@
 
   logic [4:0] insn_bignum_rd_addr_a_q, insn_bignum_rd_addr_b_q, insn_bignum_wr_addr_q;
 
+  logic secure_wipe_running_q;
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      secure_wipe_running_q <= 1'b0;
+    end else begin
+      secure_wipe_running_q <= start_secure_wipe_o | (secure_wipe_running_q & ~secure_wipe_done_i);
+    end
+  end
+
   // Stall a cycle on loads to allow load data writeback to happen the following cycle. Stall not
   // required on stores as there is no response to deal with.
   assign mem_stall = lsu_load_req_raw;
@@ -310,8 +319,8 @@
   assign executing = (state_q == OtbnStateRun) ||
                      (state_q == OtbnStateStall);
 
-  assign locking_o = (state_d == OtbnStateLocked) & ~secure_wipe_running_i;
-  assign start_secure_wipe_o = executing & (done_complete | err) & ~secure_wipe_running_i;
+  assign locking_o = (state_d == OtbnStateLocked) & ~(start_secure_wipe_o | secure_wipe_running_q);
+  assign start_secure_wipe_o = executing & (done_complete | err) & ~secure_wipe_running_q;
 
   assign jump_or_branch = (insn_valid_i &
                            (insn_dec_shared_i.branch_insn | insn_dec_shared_i.jump_insn));
diff --git a/hw/ip/otbn/rtl/otbn_core.sv b/hw/ip/otbn/rtl/otbn_core.sv
index a2ec496..d7d3341 100644
--- a/hw/ip/otbn/rtl/otbn_core.sv
+++ b/hw/ip/otbn/rtl/otbn_core.sv
@@ -219,7 +219,7 @@
   logic [31:0] insn_cnt;
 
   logic start_secure_wipe;
-  logic secure_wipe_running;
+  logic secure_wipe_done;
 
   logic sec_wipe_wdr_d, sec_wipe_wdr_q;
   logic sec_wipe_wdr_urnd_d, sec_wipe_wdr_urnd_q;
@@ -266,8 +266,8 @@
     .urnd_reseed_ack_i (urnd_reseed_ack),
     .urnd_advance_o    (urnd_advance_start_stop_control),
 
-    .start_secure_wipe_i  (start_secure_wipe),
-    .secure_wipe_running_o(secure_wipe_running),
+    .start_secure_wipe_i (start_secure_wipe),
+    .secure_wipe_done_o  (secure_wipe_done),
     .done_o,
 
     .sec_wipe_wdr_o      (sec_wipe_wdr_d),
@@ -486,9 +486,9 @@
     .rnd_fips_err_i    (rnd_fips_err),
 
     // Secure wipe
-    .secure_wipe_running_i(secure_wipe_running),
-    .start_secure_wipe_o  (start_secure_wipe),
-    .sec_wipe_zero_i      (sec_wipe_zero),
+    .start_secure_wipe_o (start_secure_wipe),
+    .secure_wipe_done_i  (secure_wipe_done),
+    .sec_wipe_zero_i     (sec_wipe_zero),
 
     .state_reset_i(state_reset),
     .insn_cnt_o   (insn_cnt),
diff --git a/hw/ip/otbn/rtl/otbn_start_stop_control.sv b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
index 1757a50..5064ce8 100644
--- a/hw/ip/otbn/rtl/otbn_start_stop_control.sv
+++ b/hw/ip/otbn/rtl/otbn_start_stop_control.sv
@@ -42,7 +42,7 @@
   output logic urnd_advance_o,
 
   input   logic start_secure_wipe_i,
-  output  logic secure_wipe_running_o,
+  output  logic secure_wipe_done_o,
   output  logic done_o,
 
   output logic       sec_wipe_wdr_o,
@@ -103,7 +103,7 @@
     sec_wipe_mod_urnd_o    = 1'b0;
     sec_wipe_zero_o        = 1'b0;
     addr_cnt_inc           = 1'b0;
-    secure_wipe_running_o  = 1'b0;
+    secure_wipe_done_o     = 1'b0;
     state_error_o          = 1'b0;
 
     unique case (state_q)
@@ -142,7 +142,6 @@
         addr_cnt_inc          = 1'b1;
         sec_wipe_wdr_o        = 1'b1;
         sec_wipe_wdr_urnd_o   = 1'b1;
-        secure_wipe_running_o = 1'b1;
         if (addr_cnt_q == 5'b11111) begin
           state_d = OtbnStartStopSecureWipeAccModBaseUrnd;
         end
@@ -151,7 +150,6 @@
       // addr_cnt_q wraps around to 0 when first moving to this state, and we need to
       // supress writes to the zero register and the call stack.
        OtbnStartStopSecureWipeAccModBaseUrnd: begin
-        secure_wipe_running_o = 1'b1;
         urnd_advance_o        = 1'b1;
         addr_cnt_inc          = 1'b1;
         // The first two clock cycles are used to write random data to accumulator and modulus.
@@ -167,7 +165,6 @@
       // Writing zeros to the accumulator, modulus and the registers.
       // Resetting stack
        OtbnStartStopSecureWipeAllZero: begin
-        secure_wipe_running_o = 1'b1;
         sec_wipe_zero_o       = (addr_cnt_q == 5'b00000);
         sec_wipe_wdr_o        = 1'b1;
         sec_wipe_base_o       = (addr_cnt_q > 5'b00001);
@@ -178,6 +175,7 @@
       end
       OtbnStartStopSecureWipeComplete: begin
         urnd_advance_o = 1'b1;
+        secure_wipe_done_o = 1'b1;
         state_d = should_lock_d ? OtbnStartStopStateLocked : OtbnStartStopStateHalt;
       end
       OtbnStartStopStateLocked: begin