| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // KMAC Application interface |
| |
| `include "prim_assert.sv" |
| |
| module kmac_app |
| import kmac_pkg::*; |
| #( |
| // App specific configs are defined in kmac_pkg |
| parameter bit EnMasking = 1'b0, |
| localparam int Share = (EnMasking) ? 2 : 1, // derived parameter |
| parameter bit SecIdleAcceptSwMsg = 1'b0 |
| ) ( |
| input clk_i, |
| input rst_ni, |
| |
| // Secret Key from register |
| input [MaxKeyLen-1:0] reg_key_data_i [Share], |
| input key_len_e reg_key_len_i, |
| |
| // Prefix from register |
| input [sha3_pkg::NSRegisterSize*8-1:0] reg_prefix_i, |
| |
| // mode, strength, kmac_en from register |
| input reg_kmac_en_i, |
| input sha3_pkg::sha3_mode_e reg_sha3_mode_i, |
| input sha3_pkg::keccak_strength_e reg_keccak_strength_i, |
| |
| // Data from Software |
| input sw_valid_i, |
| input [MsgWidth-1:0] sw_data_i, |
| input [MsgWidth-1:0] sw_mask_i, |
| output logic sw_ready_o, |
| |
| // KeyMgr Sideload Key interface |
| input keymgr_pkg::hw_key_req_t keymgr_key_i, |
| |
| // Application Message in/ Digest out interface + control signals |
| input app_req_t [NumAppIntf-1:0] app_i, |
| output app_rsp_t [NumAppIntf-1:0] app_o, |
| |
| // to KMAC Core: Secret key |
| output [MaxKeyLen-1:0] key_data_o [Share], |
| output key_len_e key_len_o, |
| |
| // to MSG_FIFO |
| output logic kmac_valid_o, |
| output logic [MsgWidth-1:0] kmac_data_o, |
| output logic [MsgWidth-1:0] kmac_mask_o, |
| input kmac_ready_i, |
| |
| // KMAC Core |
| output logic kmac_en_o, |
| |
| // To Sha3 Core |
| output logic [sha3_pkg::NSRegisterSize*8-1:0] sha3_prefix_o, |
| output sha3_pkg::sha3_mode_e sha3_mode_o, |
| output sha3_pkg::keccak_strength_e keccak_strength_o, |
| |
| // STATE from SHA3 Core |
| input keccak_state_valid_i, |
| input [sha3_pkg::StateW-1:0] keccak_state_i [Share], |
| |
| // to STATE TL-window if Application is not active, the incoming state goes to |
| // register if kdf_en is set, the state value goes to application and the |
| // output to the register is all zero. |
| output logic reg_state_valid_o, |
| output logic [sha3_pkg::StateW-1:0] reg_state_o [Share], |
| |
| // Configurations If key_en is set, the logic uses KeyMgr's sideloaded key as |
| // a secret key rather than register values. This only affects when software |
| // initiates. If App initiates the hash operation and uses KMAC algorithm, it |
| // always uses sideloaded key. |
| input keymgr_key_en_i, |
| |
| // Commands |
| // Command from software |
| input kmac_cmd_e sw_cmd_i, |
| |
| // from SHA3 |
| input absorbed_i, |
| |
| // to KMAC |
| output kmac_cmd_e cmd_o, |
| |
| // to SW |
| output logic absorbed_o, |
| |
| // To status |
| output logic app_active_o, |
| |
| // Error input |
| // This error comes from KMAC/SHA3 engine. |
| // KeyMgr interface delivers the error signal to KeyMgr to drop the current op |
| // and re-initiate. |
| // If error happens, regardless of SW-initiated or KeyMgr-initiated, the error |
| // is reported to the ERR_CODE so that SW can look into. |
| input error_i, |
| |
| // SW sets err_processed bit in CTRL then the logic goes to Idle |
| input err_processed_i, |
| |
| // error_o value is pushed to Error FIFO at KMAC/SHA3 top and reported to SW |
| output kmac_pkg::err_t error_o |
| ); |
| |
| ///////////////// |
| // Definitions // |
| ///////////////// |
| |
| // Digest width is same to the key width `keymgr_pkg::KeyWidth`. |
| localparam int KeyMgrKeyW = $bits(keymgr_key_i.key[0]); |
| |
| localparam key_len_e KeyLen [5] = '{Key128, Key192, Key256, Key384, Key512}; |
| |
| localparam int SelKeySize = (AppKeyW == 128) ? 0 : |
| (AppKeyW == 192) ? 1 : |
| (AppKeyW == 256) ? 2 : |
| (AppKeyW == 384) ? 3 : |
| (AppKeyW == 512) ? 4 : 0 ; |
| localparam int SelDigSize = (AppDigestW == 128) ? 0 : |
| (AppDigestW == 192) ? 1 : |
| (AppDigestW == 256) ? 2 : |
| (AppDigestW == 384) ? 3 : |
| (AppDigestW == 512) ? 4 : 0 ; |
| localparam key_len_e SideloadedKey = KeyLen[SelKeySize]; |
| |
| // Define right_encode(outlen) value here |
| // Look at kmac_pkg::key_len_e for the kinds of key size |
| // |
| // These values should be exactly the same as the key length encodings |
| // in kmac_core.sv, with the only difference being that the byte representing |
| // the byte-length of the encoded value is in the MSB position due to right encoding |
| // instead of in the LSB position (left encoding). |
| localparam int OutLenW = 24; |
| localparam logic [OutLenW-1:0] EncodedOutLen [5]= '{ |
| 24'h 0001_80, // Key128 |
| 24'h 0001_C0, // Key192 |
| 24'h 02_0001, // Key256 |
| 24'h 02_8001, // Key384 |
| 24'h 02_0002 // Key512 |
| }; |
| |
| localparam logic [OutLenW-1:0] EncodedOutLenMask [5] = '{ |
| 24'h 00FFFF, // Key128, |
| 24'h 00FFFF, // Key192 |
| 24'h FFFFFF, // Key256 |
| 24'h FFFFFF, // Key384 |
| 24'h FFFFFF // Key512 |
| }; |
| |
| // Encoding generated with: |
| // $ ./util/design/sparse-fsm-encode.py -d 3 -m 9 -n 10 \ |
| // -s 155490773 --language=sv |
| // |
| // Hamming distance histogram: |
| // |
| // 0: -- |
| // 1: -- |
| // 2: -- |
| // 3: |||||||||| (16.67%) |
| // 4: |||||||||||||||||||| (30.56%) |
| // 5: |||||||||||||||| (25.00%) |
| // 6: ||||||||| (13.89%) |
| // 7: ||||||||| (13.89%) |
| // 8: -- |
| // 9: -- |
| // 10: -- |
| // |
| // Minimum Hamming distance: 3 |
| // Maximum Hamming distance: 7 |
| // Minimum Hamming weight: 2 |
| // Maximum Hamming weight: 9 |
| // |
| localparam int StateWidth = 10; |
| |
| // States |
| typedef enum logic [StateWidth-1:0] { |
| StIdle = 10'b1011011010, |
| |
| // Application operation. |
| // |
| // if start request comes from an App first, until the operation ends by the |
| // requested App, all operations are granted to the specific App. SW |
| // requests and other Apps requests will be ignored. |
| // |
| // App interface does not have control signals. When first data valid occurs |
| // from an App, this logic asserts the start command to the downstream. When |
| // last beat pulse comes, this logic asserts the process to downstream |
| // (after the transaction is accepted regardless of partial writes or not) |
| // When absorbed by SHA3 core, the logic sends digest to the requested App |
| // and right next cycle, it triggers done command to downstream. |
| |
| // In StAppCfg state, it latches the cfg from AppCfg parameter to determine |
| // the kmac_mode, sha3_mode, keccak strength. |
| StAppCfg = 10'b0001010000, |
| |
| StAppMsg = 10'b0001011111, |
| |
| // In StKeyOutLen, this module pushes encoded outlen to the MSG_FIFO. |
| // Assume the length is 256 bit, the data will be 48'h 02_0100 |
| StAppOutLen = 10'b1011001111, |
| StAppProcess = 10'b1000100110, |
| StAppWait = 10'b0010010110, |
| |
| // SW Controlled |
| // If start request comes from SW first, until the operation ends, all |
| // requests from KeyMgr will be discarded. |
| StSw = 10'b0111111111, |
| |
| // Error KeyNotValid |
| // When KeyMgr operates, the secret key is not ready yet. |
| StKeyMgrErrKeyNotValid = 10'b1001110100, |
| |
| StError = 10'b1101011101 |
| } st_e; |
| |
| ///////////// |
| // Signals // |
| ///////////// |
| |
| st_e st, st_d; |
| |
| // app_rsp_t signals |
| // The state machine controls mux selection, which controls the ready signal |
| // the other responses are controled in separate logic. So define the signals |
| // here and merge them to the response. |
| logic app_data_ready, fsm_data_ready; |
| logic app_digest_done, fsm_digest_done_q, fsm_digest_done_d; |
| logic [AppDigestW-1:0] app_digest [2]; |
| |
| // One more slot for value NumAppIntf. It is the value when no app intf is |
| // chosen. |
| localparam int unsigned AppIdxW = $clog2(NumAppIntf); |
| |
| // app_id indicates, which app interface was chosen. various logic use this |
| // value to get the config or return the data. |
| logic [AppIdxW-1:0] app_id, app_id_d; |
| logic clr_appid, set_appid; |
| |
| // Output length |
| logic [OutLenW-1:0] encoded_outlen, encoded_outlen_mask; |
| |
| // state output |
| // Mux selection signal |
| app_mux_sel_e mux_sel; |
| |
| // Error checking logic |
| |
| kmac_pkg::err_t fsm_err, mux_err; |
| |
| //////////////////////////// |
| // Application Mux/ Demux // |
| //////////////////////////// |
| |
| |
| // Processing return data. |
| // sends to only selected app intf. |
| // clear digest right after done to not leak info to other interface |
| always_comb begin |
| for (int unsigned i = 0 ; i < NumAppIntf ; i++) begin |
| if (i == app_id) begin |
| app_o[i] = '{ |
| ready: app_data_ready | fsm_data_ready, |
| done: app_digest_done | fsm_digest_done_q, |
| digest_share0: app_digest[0], |
| digest_share1: app_digest[1], |
| // if fsm asserts done, should be an error case. |
| error: error_i | fsm_digest_done_q |
| }; |
| end else begin |
| app_o[i] = '{ |
| ready: 1'b 0, |
| done: 1'b 0, |
| digest_share0: '0, |
| digest_share1: '0, |
| error: 1'b 0 |
| }; |
| end |
| end // for {i, NumAppIntf, i++} |
| end // aiways_comb |
| |
| // app_id latch |
| always_ff @(posedge clk_i or negedge rst_ni) begin |
| if (!rst_ni) app_id <= AppIdxW'(0) ; // Do not select any |
| else if (clr_appid) app_id <= AppIdxW'(0); |
| else if (set_appid) app_id <= app_id_d; |
| end |
| |
| // app_id selection as of now, app_id uses Priority. The assumption is that |
| // the request normally does not collide. (ROM_CTRL activates very early |
| // stage at the boot sequence) |
| // |
| // If this assumption is not true, consider RR arbiter. |
| |
| // Prep for arbiter |
| logic [NumAppIntf-1:0] app_reqs; |
| logic [NumAppIntf-1:0] unused_app_gnts; |
| logic [$clog2(NumAppIntf)-1:0] arb_idx; |
| logic arb_valid; |
| logic arb_ready; |
| |
| always_comb begin |
| app_reqs = '0; |
| for (int unsigned i = 0 ; i < NumAppIntf ; i++) begin |
| app_reqs[i] = app_i[i].valid; |
| end |
| end |
| |
| prim_arbiter_fixed #( |
| .N (NumAppIntf), |
| .DW(1), |
| .EnDataPort(1'b 0) |
| ) u_appid_arb ( |
| .clk_i, |
| .rst_ni, |
| |
| .req_i (app_reqs), |
| .data_i ('{default:'0}), |
| .gnt_o (unused_app_gnts), |
| .idx_o (arb_idx), |
| |
| .valid_o (arb_valid), |
| .data_o (), // not used |
| .ready_i (arb_ready) |
| ); |
| |
| assign app_id_d = AppIdxW'(arb_idx); |
| assign arb_ready = set_appid; |
| |
| always_ff @(posedge clk_i or negedge rst_ni) begin |
| if (!rst_ni) fsm_digest_done_q <= 1'b 0; |
| else fsm_digest_done_q <= fsm_digest_done_d; |
| end |
| |
| ///////// |
| // FSM // |
| ///////// |
| |
| // State register |
| logic [StateWidth-1:0] st_raw; |
| assign st = st_e'(st_raw); |
| prim_flop #( |
| .Width (StateWidth), |
| .ResetValue (StateWidth'(StIdle)) |
| ) u_state_regs ( |
| .clk_i, |
| .rst_ni, |
| .d_i ( st_d ), |
| .q_o ( st_raw ) |
| ); |
| |
| // Next State & output logic |
| always_comb begin |
| st_d = StIdle; |
| |
| mux_sel = SecIdleAcceptSwMsg ? SelSw : SelNone; |
| |
| // app_id control |
| set_appid = 1'b 0; |
| clr_appid = 1'b 0; |
| |
| // Commands |
| cmd_o = CmdNone; |
| |
| // Software output |
| absorbed_o = 1'b 0; |
| |
| // Error |
| fsm_err = '{valid: 1'b 0, code: ErrNone, info: '0}; |
| |
| // If error happens, FSM asserts data ready but discard incoming msg |
| fsm_data_ready = 1'b 0; |
| fsm_digest_done_d = 1'b 0; |
| |
| unique case (st) |
| StIdle: begin |
| if (arb_valid) begin |
| st_d = StAppCfg; |
| |
| // choose app_id |
| set_appid = 1'b 1; |
| end else if (sw_cmd_i == CmdStart) begin |
| st_d = StSw; |
| // Software initiates the sequence |
| cmd_o = CmdStart; |
| end else begin |
| st_d = StIdle; |
| end |
| end |
| |
| StAppCfg: begin |
| |
| if ((AppCfg[app_id].Mode == AppKMAC) && !keymgr_key_i.valid) begin |
| st_d = StKeyMgrErrKeyNotValid; |
| |
| // As mux_sel is not set to SelApp, app_data_ready is still 0. |
| // This logic won't accept the requests from the selected App. |
| |
| end else begin |
| // As Cfg is stable now, it sends cmd |
| st_d = StAppMsg; |
| |
| // App initiates the data |
| cmd_o = CmdStart; |
| end |
| end |
| |
| StAppMsg: begin |
| mux_sel = SelApp; |
| // Wait until the completion (done) from KeyMgr? |
| // Or absorb completion? |
| if (app_i[app_id].valid && app_o[app_id].ready && app_i[app_id].last) begin |
| if (AppCfg[app_id].Mode == AppKMAC) begin |
| st_d = StAppOutLen; |
| end else begin |
| st_d = StAppProcess; |
| end |
| end else begin |
| st_d = StAppMsg; |
| end |
| end |
| |
| StAppOutLen: begin |
| mux_sel = SelOutLen; |
| |
| if (kmac_valid_o && kmac_ready_i) begin |
| st_d = StAppProcess; |
| end else begin |
| st_d = StAppOutLen; |
| end |
| end |
| |
| StAppProcess: begin |
| cmd_o = CmdProcess; |
| st_d = StAppWait; |
| end |
| |
| StAppWait: begin |
| if (absorbed_i) begin |
| // Send digest to KeyMgr and complete the op |
| st_d = StIdle; |
| cmd_o = CmdDone; |
| |
| clr_appid = 1'b 1; |
| end else begin |
| st_d = StAppWait; |
| end |
| end |
| |
| StSw: begin |
| mux_sel = SelSw; |
| |
| cmd_o = sw_cmd_i; |
| absorbed_o = absorbed_i; |
| |
| if (sw_cmd_i == CmdDone) begin |
| st_d = StIdle; |
| end else begin |
| st_d = StSw; |
| end |
| end |
| |
| StKeyMgrErrKeyNotValid: begin |
| st_d = StError; |
| |
| // As mux_sel is not set to SelApp, app_data_ready is still 0. |
| // This logic won't accept the requests from the selected App. |
| fsm_err.valid = 1'b 1; |
| fsm_err.code = ErrKeyNotValid; |
| fsm_err.info = 24'(app_id); |
| end |
| |
| StError: begin |
| // In this state, the state machine flush out the request |
| st_d = StError; |
| |
| fsm_data_ready = 1'b 1; |
| |
| if (err_processed_i) begin |
| st_d = StIdle; |
| |
| // clear internal variables |
| clr_appid = 1'b 1; |
| end |
| |
| if (app_i[app_id].valid && app_i[app_id].last) begin |
| // Send garbage digest to the app interface to complete transaction |
| fsm_digest_done_d = 1'b 1; |
| end |
| |
| end |
| |
| default: begin |
| st_d = StIdle; |
| end |
| endcase |
| end |
| |
| if (SecIdleAcceptSwMsg != 1'b0) begin : gen_lint_err |
| // Create a lint error to reduce the risk of accidentally enabling this feature. |
| logic sec_idle_accept_sw_msg_dummy; |
| assign sec_idle_accept_sw_msg_dummy = (st == StIdle); |
| end |
| |
| ////////////// |
| // Datapath // |
| ////////////// |
| |
| // Encoded output length |
| assign encoded_outlen = EncodedOutLen[SelDigSize]; |
| assign encoded_outlen_mask = EncodedOutLenMask[SelKeySize]; |
| |
| // Data mux |
| // This is the main part of the KeyMgr interface logic. |
| // The FSM selects KeyMgr interface in a cycle after it receives the first |
| // valid data from KeyMgr. The ready signal to the KeyMgr data interface |
| // represents the MSG_FIFO ready, only when it is in StKeyMgrMsg state. |
| // After KeyMgr sends last beat, the kmac interface (to MSG_FIFO) is switched |
| // to OutLen. OutLen is pre-defined values. See `EncodeOutLen` parameter above. |
| always_comb begin |
| app_data_ready = 1'b 0; |
| sw_ready_o = 1'b 1; |
| |
| kmac_valid_o = 1'b 0; |
| kmac_data_o = '0; |
| kmac_mask_o = '0; |
| |
| unique case (mux_sel) |
| SelApp: begin |
| // app_id is valid at this time |
| kmac_valid_o = app_i[app_id].valid; |
| kmac_data_o = app_i[app_id].data; |
| // Expand strb to bits. prim_packer inside MSG_FIFO accepts the bit masks |
| for (int i = 0 ; i < $bits(app_i[app_id].strb) ; i++) begin |
| kmac_mask_o[8*i+:8] = {8{app_i[app_id].strb[i]}}; |
| end |
| app_data_ready = kmac_ready_i; |
| end |
| |
| SelOutLen: begin |
| // Write encoded output length value |
| kmac_valid_o = 1'b 1; // always write |
| kmac_data_o = MsgWidth'(encoded_outlen); |
| kmac_mask_o = MsgWidth'(encoded_outlen_mask); |
| end |
| |
| SelSw: begin |
| kmac_valid_o = sw_valid_i; |
| kmac_data_o = sw_data_i ; |
| kmac_mask_o = sw_mask_i ; |
| sw_ready_o = kmac_ready_i ; |
| end |
| |
| default: begin // Incl. SelNone |
| kmac_valid_o = 1'b 0; |
| kmac_data_o = '0; |
| kmac_mask_o = '0; |
| end |
| |
| endcase |
| end |
| |
| // Error checking for Mux |
| always_comb begin |
| mux_err = '{valid: 1'b 0, code: ErrNone, info: '0}; |
| |
| if (mux_sel != SelSw && sw_valid_i) begin |
| // If SW writes message into FIFO |
| mux_err = '{ |
| valid: 1'b 1, |
| code: ErrSwPushedMsgFifo, |
| info: 24'({8'h 00, 8'(st), 8'(mux_sel)}) |
| }; |
| end else if (app_active_o && sw_cmd_i != CmdNone) begin |
| // If SW issues command except start |
| mux_err = '{ |
| valid: 1'b 1, |
| code: ErrSwIssuedCmdInAppActive, |
| info: 24'(sw_cmd_i) |
| }; |
| end |
| end |
| |
| // Keccak state Demux |
| // Keccak state --> Register output is enabled when state is in StSw |
| always_comb begin |
| if (mux_sel == SelSw) begin |
| reg_state_valid_o = keccak_state_valid_i; |
| reg_state_o = keccak_state_i; |
| end else begin |
| reg_state_valid_o = 1'b 0; |
| reg_state_o = '{default:'0}; |
| end |
| end |
| |
| // Keccak state --> KeyMgr |
| always_comb begin |
| app_digest_done = 1'b 0; |
| app_digest = '{default:'0}; |
| if (st == StAppWait && absorbed_i) begin |
| // SHA3 engine has calculated the hash. Return the data to KeyMgr |
| app_digest_done = 1'b 1; |
| |
| // digest has always 2 entries. If !EnMasking, second is tied to 0. |
| for (int i = 0 ; i < Share ; i++) begin |
| // Return the portion of state. |
| app_digest[i] = keccak_state_i[i][AppDigestW-1:0]; |
| end |
| end |
| end |
| |
| |
| // Secret Key Mux |
| |
| // Prepare merged key if EnMasking is not set. |
| // Combine share keys into unpacked array for logic below to assign easily. |
| logic [MaxKeyLen-1:0] keymgr_key [Share]; |
| if (EnMasking == 1) begin : g_masked_key |
| for (genvar i = 0; i < Share; i++) begin : gen_key_pad |
| assign keymgr_key[i] = {(MaxKeyLen-KeyMgrKeyW)'(0), keymgr_key_i.key[i]}; |
| end |
| end else begin : g_unmasked_key |
| always_comb begin |
| keymgr_key[0] = '0; |
| for (int i = 0; i < Share; i++) begin |
| keymgr_key[0][KeyMgrKeyW-1:0] ^= keymgr_key_i.key[i]; |
| end |
| end |
| end |
| |
| // Sideloaded key is used when KeyMgr KDF is active or !!CFG.sideload is set |
| always_comb begin |
| if (keymgr_key_en_i || (mux_sel == SelApp)) begin |
| // KeyLen is fixed to the $bits(sideloaded_key) |
| key_len_o = SideloadedKey; |
| end else begin |
| key_len_o = reg_key_len_i; |
| end |
| end |
| |
| for (genvar i = 0 ; i < Share ; i++) begin : g_key_assign |
| assign key_data_o[i] = (keymgr_key_en_i || (mux_sel == SelApp)) |
| ? keymgr_key[i] |
| : reg_key_data_i[i] ; |
| end |
| |
| // Prefix Demux |
| // For SW, always prefix register. |
| // For App intf, check PrefixMode cfg and if 1, use Prefix cfg. |
| always_comb begin |
| sha3_prefix_o = '0; |
| |
| unique case (st) |
| StAppCfg, StAppMsg, StAppOutLen, StAppProcess, StAppWait: begin |
| // Check app intf cfg |
| for (int unsigned i = 0 ; i < NumAppIntf ; i++) begin |
| if (app_id == i) begin |
| if (AppCfg[i].PrefixMode == 1'b 0) begin |
| sha3_prefix_o = reg_prefix_i; |
| end else begin |
| sha3_prefix_o = AppCfg[i].Prefix; |
| end |
| end |
| end |
| end |
| |
| StSw: begin |
| sha3_prefix_o = reg_prefix_i; |
| end |
| |
| default: begin |
| sha3_prefix_o = reg_prefix_i; |
| end |
| endcase |
| end |
| |
| // KMAC en / SHA3 mode / Strength |
| // by default, it uses reg cfg. When app intf reqs come, it uses AppCfg. |
| always_ff @(posedge clk_i or negedge rst_ni) begin |
| if (!rst_ni) begin |
| kmac_en_o <= 1'b 0; |
| sha3_mode_o <= sha3_pkg::Sha3; |
| keccak_strength_o <= sha3_pkg::L256; |
| end else if (clr_appid) begin |
| // As App completed, latch reg value |
| kmac_en_o <= reg_kmac_en_i; |
| sha3_mode_o <= reg_sha3_mode_i; |
| keccak_strength_o <= reg_keccak_strength_i; |
| end else if (set_appid) begin |
| kmac_en_o <= AppCfg[arb_idx].Mode == AppKMAC ? 1'b 1 : 1'b 0; |
| sha3_mode_o <= AppCfg[arb_idx].Mode == AppSHA3 |
| ? sha3_pkg::Sha3 : sha3_pkg::CShake; |
| keccak_strength_o <= AppCfg[arb_idx].Strength ; |
| end else if (st == StIdle) begin |
| kmac_en_o <= reg_kmac_en_i; |
| sha3_mode_o <= reg_sha3_mode_i; |
| keccak_strength_o <= reg_keccak_strength_i; |
| end |
| end |
| |
| // Status |
| assign app_active_o = (st inside {StAppCfg, StAppMsg, StAppOutLen, |
| StAppProcess, StAppWait}); |
| |
| // Error Reporting ========================================================== |
| always_comb begin |
| priority casez ({fsm_err.valid, mux_err.valid}) |
| 2'b ?1: error_o = mux_err; |
| 2'b 10: error_o = fsm_err; |
| default: error_o = '{valid: 1'b0, code: ErrNone, info: '0}; |
| endcase |
| end |
| |
| //////////////// |
| // Assertions // |
| //////////////// |
| |
| // KeyMgr sideload key and the digest should be in the Key Length value |
| `ASSERT_INIT(SideloadKeySameToDigest_A, KeyMgrKeyW <= AppDigestW) |
| `ASSERT_INIT(AppIntfInRange_A, AppDigestW inside {128, 192, 256, 384, 512}) |
| |
| |
| endmodule |