[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/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));