@@ -113,7 +113,7 @@ module otbn_core
113113 logic [31 : 0 ] insn_fetch_resp_data;
114114 logic insn_fetch_resp_clear;
115115 logic insn_fetch_err;
116- logic insn_addr_err;
116+ logic insn_addr_err_d, insn_addr_err;
117117
118118 rf_predec_bignum_t rf_predec_bignum;
119119 alu_predec_bignum_t alu_predec_bignum;
@@ -156,7 +156,7 @@ module otbn_core
156156 logic rf_base_rd_commit;
157157 logic rf_base_call_stack_sw_err;
158158 logic rf_base_call_stack_hw_err;
159- logic rf_base_intg_err;
159+ logic rf_base_intg_err_d, rf_base_intg_err;
160160 logic rf_base_spurious_we_err;
161161 logic rf_base_sec_wipe_err;
162162
@@ -175,7 +175,7 @@ module otbn_core
175175
176176 logic [BaseIntgWidth- 1 : 0 ] lsu_base_rdata;
177177 logic [ExtWLEN- 1 : 0 ] lsu_bignum_rdata;
178- logic lsu_rdata_err;
178+ logic lsu_rdata_err_d, lsu_rdata_err;
179179
180180 logic [WdrAw- 1 : 0 ] rf_bignum_wr_addr;
181181 logic [WdrAw- 1 : 0 ] rf_bignum_wr_addr_ctrl;
@@ -241,7 +241,7 @@ module otbn_core
241241 logic urnd_advance;
242242 logic urnd_advance_start_stop_control;
243243 logic [WLEN - 1 : 0 ] urnd_data;
244- logic urnd_all_zero;
244+ logic urnd_all_zero_d, urnd_all_zero;
245245
246246 logic controller_start;
247247
@@ -281,7 +281,7 @@ module otbn_core
281281 logic start_stop_fatal_error;
282282 logic rf_bignum_predec_error, alu_bignum_predec_error, ispr_predec_error, mac_bignum_predec_error;
283283 logic controller_predec_error;
284- logic rd_predec_error, predec_error;
284+ logic rd_predec_error, predec_error_d, predec_error;
285285
286286 logic req_sec_wipe_urnd_keys_q;
287287
@@ -361,7 +361,7 @@ module otbn_core
361361 .insn_fetch_resp_data_o (insn_fetch_resp_data),
362362 .insn_fetch_resp_clear_i (insn_fetch_resp_clear),
363363 .insn_fetch_err_o (insn_fetch_err),
364- .insn_addr_err_o (insn_addr_err ),
364+ .insn_addr_err_o (insn_addr_err_d ),
365365
366366 .rf_predec_bignum_o (rf_predec_bignum),
367367 .alu_predec_bignum_o (alu_predec_bignum),
@@ -416,7 +416,7 @@ module otbn_core
416416 rf_predec_bignum.rf_ren_b,
417417 ispr_predec_bignum.ispr_rd_en} & ~ insn_valid;
418418
419- assign predec_error =
419+ assign predec_error_d =
420420 ((alu_bignum_predec_error | mac_bignum_predec_error | controller_predec_error) & insn_valid) |
421421 rf_bignum_predec_error |
422422 ispr_predec_error |
@@ -589,10 +589,103 @@ module otbn_core
589589 controller_err_bits.bad_internal_state,
590590 controller_err_bits.reg_intg_violation} ;
591591
592- logic non_controller_reg_intg_violation;
593- assign non_controller_reg_intg_violation =
594- |{ alu_bignum_reg_intg_violation_err, mac_bignum_reg_intg_violation_err, rf_base_intg_err} ;
595-
592+ logic non_controller_reg_intg_violation_d, non_controller_reg_intg_violation;
593+ assign non_controller_reg_intg_violation_d =
594+ |{ alu_bignum_reg_intg_violation_err, mac_bignum_reg_intg_violation_err, rf_base_intg_err_d} ;
595+
596+ // //////////////////////////////////////////////////////////////
597+ // Register local escalation signals for timinig optimization //
598+ // //////////////////////////////////////////////////////////////
599+ // Signals contributing to the local controller escalation signal directly factor into the
600+ // insn_executing signal inside the otbn_controller.sv. This then drives various commit signals
601+ // as well as the DMEM request signal (lsu_load_req_o). By cutting these escalation signals,
602+ // these paths are shortened which results in better timing/area results. Signals contributing to
603+ // the start/stop escalation are also cut to synchronize the escalation such that transitioning
604+ // into LOCKED and the start of wiping activities happen at the same time. The error bits are
605+ // also updated delayed to have the same behaviour as without a cut.
606+ //
607+ // Registered signals:
608+ // - urnd_all_zero: Is high when the local PRNG is all zero and locks up.
609+ // Potentially timing critical.
610+ // - predec_error: Generated by checking all the registered, predecoded signals with decoded
611+ // signals and combining these.
612+ // Potentially timing critical.
613+ // - lsu_rdata_err: DMEM ECC errors of data read from DMEM.
614+ // Timing critical because source is in memory.
615+ // - insn_addr_err: Is asserted when the prefetched address does not match the requested
616+ // address. Depends on insn_fetch_req_addr_o and prefetch_ignore_errs_o from
617+ // the controller which factor in lots of combinatorial signals. Especially
618+ // the prefetch_ignore_errs_o depends on the internal error which depends on
619+ // many internal error signals.
620+ // Very likely timing critical.
621+ // - rf_base_intg_err: ECC errors triggered with in the base register file. The control signals
622+ // for the base register file are not predecoded.
623+ // So this is likely timing critical.
624+ // - non_controller_reg_intg_violation: Based on alu_bignum_reg_intg_violation_err,
625+ // mac_bignum_reg_intg_violation_err and rf_base_intg_err.
626+ // The former two are generated by checking the ECC of the
627+ // MOD / ACC values. The checks depends on the actual
628+ // ALU / MAC datapath outputs.
629+ // **Highly** timing critical.
630+ //
631+ // Not registered signals:
632+ // - escalate_en_i: This must NOT be not cut. It stems from the system wide escalation
633+ // control mechanism and such a global escalation must be as fast as
634+ // possible.
635+ // - start_stop_fatal_error: The error signal of the start stop FSM. Based on EDN urnd ack
636+ // signal and internal state checking. This error is not cut to
637+ // synchronize the escalation of the controller and start/stop
638+ // control.
639+ // - controller_fatal_err: The error signal of the controller towards the start/stop logic.
640+ // This error is not cut to synchronize the escalation of the
641+ // controller and start/stop control.
642+ // - rf_base_spurious_we_err: This error is already registered at the source.
643+ // - insn_fetch_err: IMEM ECC errors, not computed on the IMEM output but on a flopped
644+ // signal.
645+ //
646+ // Security considerations:
647+ // With the registering, the reaction to escalation sources is delayed by one cycle. Any faulty
648+ // instruction therefore still commits and updates registers or the memory. This does not affect
649+ // security because:
650+ // - While executing a program, the IMEM and DMEM are locked and cannot be read by Ibex.
651+ // - They become readable once the execution finishes without a fatal error. In addition, only a
652+ // part of the DMEM is readable by Ibex.
653+ // - If a fatal error occurs OTBN locks up and none of the memories become readable again.
654+ // - SCA and FI combined attacks are out of scope. As of this, any leakage due to FI attacks is
655+ // considered unusable because the OpenTitan chip scraps itself when too many FI attacks were
656+ // detected.
657+ // - When escalating, OTBN asserts locking_o and therefore any memory reads are killed
658+ // immediately. This handles the case where the final instruction is targeted. An error during
659+ // the final instruction does not prevent the OTBN of going into IDLE and thus the memories are
660+ // theoretically unlocked for one cycle. However, OTBN will escalate immediately and also kill
661+ // any read requests. The memories are therefore never readable except maybe some glitching
662+ // activities on the port. However, assuming a single fault per execution, when targeting the
663+ // last instruction, any program should have run correctly up to this point and thus should not
664+ // expose any secrets in the readable DMEM section. Additionally, converting the ECALL
665+ // instruction into a meaningful memory instruction is infeasible with only 1 fault. Also, a
666+ // BN.SID instruction takes two cycles to execute and therefore only a SW instruction could
667+ // be performed.
668+
669+ // TODO: Does this need a prim_flop or is a regular flop sufficient?
670+ // We drop the _q suffix for the registered signals such that DV and tracing can stay the same
671+ // whether there is a cut or not.
672+ always_ff @ (posedge clk_i or negedge rst_ni) begin
673+ if (! rst_ni) begin
674+ urnd_all_zero <= '0 ;
675+ predec_error <= '0 ;
676+ rf_base_intg_err <= '0 ;
677+ lsu_rdata_err <= '0 ;
678+ non_controller_reg_intg_violation <= '0 ;
679+ insn_addr_err <= '0 ;
680+ end else begin
681+ urnd_all_zero <= urnd_all_zero_d;
682+ predec_error <= predec_error_d;
683+ rf_base_intg_err <= rf_base_intg_err_d;
684+ lsu_rdata_err <= lsu_rdata_err_d;
685+ non_controller_reg_intg_violation <= non_controller_reg_intg_violation_d;
686+ insn_addr_err <= insn_addr_err_d;
687+ end
688+ end
596689
597690 // Generate an err_bits output by combining errors from all the blocks in otbn_core
598691 assign err_bits_d = '{
@@ -633,11 +726,12 @@ module otbn_core
633726
634727 // Pass an "escalation" signal down to the controller by ORing in error signals from the other
635728 // modules in otbn_core. Note that each error signal except escalate_en_i that appears here also
636- // appears somewhere in err_bits_o above (checked in ErrBitsIfControllerEscalate_A)
729+ // appears somewhere in err_bits_o above (checked in ErrBitsIfControllerEscalate_A).
730+ // The error rf_base_intg_err is already factored into non_controller_reg_intg_violation.
637731 assign controller_fatal_escalate_en =
638732 mubi4_or_hi (escalate_en_i,
639733 mubi4_bool_to_mubi (|{ start_stop_fatal_error, urnd_all_zero, predec_error,
640- rf_base_intg_err, rf_base_spurious_we_err, lsu_rdata_err,
734+ rf_base_spurious_we_err, lsu_rdata_err,
641735 insn_fetch_err, non_controller_reg_intg_violation,
642736 insn_addr_err} ));
643737
@@ -684,7 +778,7 @@ module otbn_core
684778
685779 .lsu_base_rdata_o (lsu_base_rdata),
686780 .lsu_bignum_rdata_o (lsu_bignum_rdata),
687- .lsu_rdata_err_o (lsu_rdata_err )
781+ .lsu_rdata_err_o (lsu_rdata_err_d )
688782 );
689783
690784 // Base Instruction Subset =======================================================================
@@ -716,7 +810,7 @@ module otbn_core
716810
717811 .call_stack_sw_err_o (rf_base_call_stack_sw_err),
718812 .call_stack_hw_err_o (rf_base_call_stack_hw_err),
719- .intg_err_o (rf_base_intg_err ),
813+ .intg_err_o (rf_base_intg_err_d ),
720814 .spurious_we_err_o (rf_base_spurious_we_err),
721815 .sec_wipe_err_o (rf_base_sec_wipe_err)
722816 );
@@ -910,7 +1004,7 @@ module otbn_core
9101004 .urnd_reseed_ack_o (urnd_reseed_ack),
9111005 .urnd_advance_i (urnd_advance),
9121006 .urnd_data_o (urnd_data),
913- .urnd_all_zero_o (urnd_all_zero ),
1007+ .urnd_all_zero_o (urnd_all_zero_d ),
9141008
9151009 .edn_rnd_req_o,
9161010 .edn_rnd_ack_i,
0 commit comments