| // 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 |