| // Copyright lowRISC contributors. | 
 | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 | // | 
 | // Key manager error and fault collection | 
 | // | 
 |  | 
 | `include "prim_assert.sv" | 
 |  | 
 | module keymgr_err | 
 |   import keymgr_pkg::*; | 
 |   import keymgr_reg_pkg::*; | 
 | ( | 
 |   input clk_i, | 
 |   input rst_ni, | 
 |  | 
 |   input invalid_op_i, | 
 |   input disabled_i, | 
 |   input invalid_i, | 
 |   input kmac_input_invalid_i, | 
 |   input shadowed_update_err_i, | 
 |   input kmac_op_err_i, | 
 |   input invalid_kmac_out_i, | 
 |   input sideload_sel_err_i, | 
 |   input kmac_cmd_err_i, | 
 |   input kmac_fsm_err_i, | 
 |   input kmac_done_err_i, | 
 |   input regfile_intg_err_i, | 
 |   input shadowed_storage_err_i, | 
 |   input ctrl_fsm_err_i, | 
 |   input data_fsm_err_i, | 
 |   input op_fsm_err_i, | 
 |   input ecc_err_i, | 
 |   input state_change_err_i, | 
 |   input op_state_cmd_err_i, | 
 |   input cnt_err_i, | 
 |   input reseed_cnt_err_i, | 
 |   input sideload_fsm_err_i, | 
 |  | 
 |   input op_update_i, | 
 |   input op_done_i, | 
 |  | 
 |   // The following outputs are very similar, but have slightly different timing for | 
 |   // for CDIs on sync errors/faults. | 
 |   // Advance operations must go through for all CDIs. | 
 |   // The sync_err/fault outputs register when any CDI completes and helps with | 
 |   // the appropriate behavior on key state change. | 
 |   // The sync error_o/fault_o outputs on the other hand only output when the entire | 
 |   // operation is complete, which could be multiple CDIs. | 
 |   output logic [SyncErrLastIdx-1:0] sync_err_o, | 
 |   output logic [AsyncErrLastIdx-1:0] async_err_o, | 
 |   output logic [SyncFaultLastIdx-1:0] sync_fault_o, | 
 |   output logic [AsyncFaultLastIdx-1:0] async_fault_o, | 
 |   output logic [ErrLastPos-1:0] error_o, | 
 |   output logic [FaultLastPos-1:0] fault_o | 
 | ); | 
 |  | 
 |   // Advance calls are made up of multiple rounds of kmac operations. | 
 |   // Any sync error that occurs is treated as an error of the entire call. | 
 |   // Therefore sync errors that happen before the end of the call must be | 
 |   // latched. | 
 |   logic[SyncErrLastIdx-1:0] sync_err_q, sync_err_d; | 
 |   logic[SyncFaultLastIdx-1:0] sync_fault_q, sync_fault_d; | 
 |  | 
 |   logic err_vld; | 
 |   assign err_vld = op_update_i | op_done_i; | 
 |  | 
 |   // sync errors | 
 |   // When an operation encounters a fault, the operation is always rejected as the FSM | 
 |   // transitions to wipe.  When an operation is ongoing and en drops, it is also rejected. | 
 |   assign sync_err_d[SyncErrInvalidOp] = err_vld & (invalid_op_i | | 
 |                                                    disabled_i | | 
 |                                                    invalid_i | | 
 |                                                    |fault_o); | 
 |   assign sync_err_d[SyncErrInvalidIn] = err_vld & kmac_input_invalid_i; | 
 |  | 
 |   always_ff @(posedge clk_i or negedge rst_ni) begin | 
 |     if (!rst_ni) begin | 
 |       sync_err_q <= '0; | 
 |     end else if (op_done_i) begin | 
 |       sync_err_q <= '0; | 
 |     end else if (op_update_i) begin | 
 |       sync_err_q <= sync_err_d; | 
 |     end | 
 |   end | 
 |   assign sync_err_o = sync_err_q | sync_err_d; | 
 |  | 
 |   // async errors | 
 |   assign async_err_o[AsyncErrShadowUpdate] = shadowed_update_err_i; | 
 |  | 
 |   // sync faults | 
 |   assign sync_fault_d[SyncFaultKmacOp] = err_vld & kmac_op_err_i; | 
 |   assign sync_fault_d[SyncFaultKmacOut] = err_vld & invalid_kmac_out_i; | 
 |   assign sync_fault_d[SyncFaultSideSel] = err_vld & sideload_sel_err_i; | 
 |   always_ff @(posedge clk_i or negedge rst_ni) begin | 
 |     if (!rst_ni) begin | 
 |       sync_fault_q <= '0; | 
 |     end else if (op_done_i) begin | 
 |       sync_fault_q <= '0; | 
 |     end else if (op_update_i) begin | 
 |       sync_fault_q <= sync_fault_d; | 
 |     end | 
 |   end | 
 |   assign sync_fault_o = sync_fault_q | sync_fault_d; | 
 |  | 
 |   // async faults | 
 |   logic [AsyncFaultLastIdx-1:0] async_fault_q, async_fault_d; | 
 |   always_ff @(posedge clk_i or negedge rst_ni) begin | 
 |     if (!rst_ni) begin | 
 |       async_fault_q <= '0; | 
 |     end else begin | 
 |       async_fault_q <= async_fault_o; | 
 |     end | 
 |   end | 
 |   assign async_fault_o = async_fault_q | async_fault_d; | 
 |   assign async_fault_d[AsyncFaultKmacCmd]  = kmac_cmd_err_i; | 
 |   assign async_fault_d[AsyncFaultKmacFsm]  = kmac_fsm_err_i; | 
 |   assign async_fault_d[AsyncFaultKmacDone] = kmac_done_err_i; | 
 |   assign async_fault_d[AsyncFaultRegIntg]  = regfile_intg_err_i; | 
 |   assign async_fault_d[AsyncFaultShadow ]  = shadowed_storage_err_i; | 
 |   assign async_fault_d[AsyncFaultFsmIntg]  = ctrl_fsm_err_i | data_fsm_err_i | op_fsm_err_i; | 
 |   assign async_fault_d[AsyncFaultKeyEcc]   = ecc_err_i; | 
 |  | 
 |   // SEC_CM: CTRL.FSM.CONSISTENCY | 
 |   assign async_fault_d[AsyncFaultFsmChk]   = state_change_err_i | op_state_cmd_err_i; | 
 |   assign async_fault_d[AsyncFaultCntErr ]  = cnt_err_i; | 
 |   assign async_fault_d[AsyncFaultRCntErr]  = reseed_cnt_err_i; | 
 |   assign async_fault_d[AsyncFaultSideErr]  = sideload_fsm_err_i; | 
 |  | 
 |   // certain errors/faults can only happen when there's an actual kmac transaction, | 
 |   // others can happen with or without. | 
 |   assign error_o[ErrInvalidOp]    = op_done_i & sync_err_o[SyncErrInvalidOp]; | 
 |   assign error_o[ErrInvalidIn]    = op_done_i & sync_err_o[SyncErrInvalidIn]; | 
 |   assign error_o[ErrShadowUpdate] = async_err_o[AsyncErrShadowUpdate]; | 
 |  | 
 |   // output to fault code register | 
 |   assign fault_o[FaultKmacOp]     = op_done_i & sync_fault_o[SyncFaultKmacOp]; | 
 |   assign fault_o[FaultKmacOut]    = op_done_i & sync_fault_o[SyncFaultKmacOut]; | 
 |   assign fault_o[FaultSideSel]    = op_done_i & sync_fault_o[SyncFaultSideSel]; | 
 |   assign fault_o[FaultKmacCmd]    = async_fault_o[AsyncFaultKmacCmd]; | 
 |   assign fault_o[FaultKmacFsm]    = async_fault_o[AsyncFaultKmacFsm]; | 
 |   assign fault_o[FaultKmacDone]   = async_fault_o[AsyncFaultKmacDone]; | 
 |   assign fault_o[FaultRegIntg]    = async_fault_o[AsyncFaultRegIntg]; | 
 |   assign fault_o[FaultShadow]     = async_fault_o[AsyncFaultShadow]; | 
 |   assign fault_o[FaultCtrlFsm]    = async_fault_o[AsyncFaultFsmIntg]; | 
 |   assign fault_o[FaultCtrlFsmChk] = async_fault_o[AsyncFaultFsmChk]; | 
 |   assign fault_o[FaultCtrlCnt]    = async_fault_o[AsyncFaultCntErr]; | 
 |   assign fault_o[FaultReseedCnt]  = async_fault_o[AsyncFaultRCntErr]; | 
 |   assign fault_o[FaultSideFsm]    = async_fault_o[AsyncFaultSideErr]; | 
 |   assign fault_o[FaultKeyEcc]     = async_fault_o[AsyncFaultKeyEcc]; | 
 |  | 
 |  | 
 | endmodule // keymgr_err |