blob: 09fe8e55045fce80296cd7f0c8c8829457ff763b [file] [log] [blame]
// 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