|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // KMAC/SHA3 | 
|  |  | 
|  | `include "prim_assert.sv" | 
|  |  | 
|  | module kmac | 
|  | import kmac_pkg::*; | 
|  | import kmac_reg_pkg::*; | 
|  | #( | 
|  | // EnMasking: Enable masking security hardening inside keccak_round | 
|  | // If it is enabled, the result digest will be two set of 1600bit. | 
|  | parameter bit EnMasking = 1, | 
|  |  | 
|  | // In case EnMasking == 0, this defines whether SW can provide a masked key or whether Share 1 of | 
|  | // the SW key is simply ignored. In case EnMasking == 1, this parameter has no meaning, always | 
|  | // both shares of the key provided by SW are used. | 
|  | // This is useful to allow both for area-optimized unmasked designs as well as unmasked designs | 
|  | // having a SW interface fully compatible with the masked design. | 
|  | parameter bit SwKeyMasked = 0, | 
|  |  | 
|  | // Command delay, useful for SCA measurements only. A value of e.g. 40 allows the processor to go | 
|  | // into sleep before KMAC starts operation. If a value > 0 is chosen, the processor can provide | 
|  | // two commands subsquently and then go to sleep. The second command is buffered internally and | 
|  | // will be presented to the hardware SecCmdDelay number of cycles after the first one. | 
|  | parameter int SecCmdDelay = 0, | 
|  |  | 
|  | // Accept SW message when idle and before receiving a START command. Useful for SCA only. | 
|  | parameter bit SecIdleAcceptSwMsg = 1'b0, | 
|  |  | 
|  | parameter lfsr_perm_t RndCnstLfsrPerm = RndCnstLfsrPermDefault, | 
|  | parameter lfsr_seed_t RndCnstLfsrSeed = RndCnstLfsrSeedDefault, | 
|  | parameter lfsr_fwd_perm_t RndCnstLfsrFwdPerm = RndCnstLfsrFwdPermDefault, | 
|  | parameter msg_perm_t  RndCnstMsgPerm  = RndCnstMsgPermDefault, | 
|  |  | 
|  | parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}} | 
|  | ) ( | 
|  | input clk_i, | 
|  | input rst_ni, | 
|  |  | 
|  | input rst_shadowed_ni, | 
|  |  | 
|  | input clk_edn_i, | 
|  | input rst_edn_ni, | 
|  |  | 
|  | input  tlul_pkg::tl_h2d_t tl_i, | 
|  | output tlul_pkg::tl_d2h_t tl_o, | 
|  |  | 
|  | // Alerts | 
|  | input  prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, | 
|  | output prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o, | 
|  |  | 
|  | // KeyMgr sideload (secret key) interface | 
|  | input keymgr_pkg::hw_key_req_t keymgr_key_i, | 
|  |  | 
|  | // KeyMgr KDF data path | 
|  | input  app_req_t [NumAppIntf-1:0] app_i, | 
|  | output app_rsp_t [NumAppIntf-1:0] app_o, | 
|  |  | 
|  | // EDN interface | 
|  | output edn_pkg::edn_req_t entropy_o, | 
|  | input  edn_pkg::edn_rsp_t entropy_i, | 
|  |  | 
|  | // Life cycle | 
|  | input  lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, | 
|  |  | 
|  | // interrupts | 
|  | output logic intr_kmac_done_o, | 
|  | output logic intr_fifo_empty_o, | 
|  | output logic intr_kmac_err_o, | 
|  |  | 
|  | // parameter consistency check with keymgr | 
|  | output logic en_masking_o, | 
|  |  | 
|  | // Idle signal | 
|  | output prim_mubi_pkg::mubi4_t idle_o | 
|  | ); | 
|  |  | 
|  | //////////////// | 
|  | // Parameters // | 
|  | //////////////// | 
|  | localparam int Share = (EnMasking) ? 2 : 1 ; | 
|  | localparam int SwKeyShare = (EnMasking || SwKeyMasked) ? 2 : 1; | 
|  |  | 
|  | ///////////////// | 
|  | // Definitions // | 
|  | ///////////////// | 
|  | // This state machine is to track the current process based on SW input and | 
|  | // KMAC operation. | 
|  | // Encoding generated with: | 
|  | // $ ./util/design/sparse-fsm-encode.py -d 3 -m 6 -n 6 \ | 
|  | //      -s 1966361510 --language=sv | 
|  | // | 
|  | // Hamming distance histogram: | 
|  | // | 
|  | //  0: -- | 
|  | //  1: -- | 
|  | //  2: -- | 
|  | //  3: |||||||||||||||||||| (53.33%) | 
|  | //  4: ||||||||||||||| (40.00%) | 
|  | //  5: || (6.67%) | 
|  | //  6: -- | 
|  | // | 
|  | // Minimum Hamming distance: 3 | 
|  | // Maximum Hamming distance: 5 | 
|  | // Minimum Hamming weight: 2 | 
|  | // Maximum Hamming weight: 5 | 
|  | // | 
|  | localparam int StateWidth = 6; | 
|  | typedef enum logic [StateWidth-1:0] { | 
|  | // Idle state | 
|  | KmacIdle = 6'b001011, | 
|  |  | 
|  | // When software writes CmdStart @ KmacIdle and kmac_en, FSM moves to this | 
|  | KmacPrefix = 6'b000110, | 
|  |  | 
|  | // When SHA3 engine processes Key block, FSM moves to here. | 
|  | KmacKeyBlock = 6'b111110, | 
|  |  | 
|  | // Message Feed | 
|  | KmacMsgFeed = 6'b010101, | 
|  |  | 
|  | // Complete and squeeze | 
|  | KmacDigest = 6'b101101, | 
|  |  | 
|  | // Error | 
|  | KmacTerminalError = 6'b110000 | 
|  |  | 
|  | } kmac_st_e; | 
|  |  | 
|  | kmac_st_e kmac_st, kmac_st_d; | 
|  |  | 
|  | ///////////// | 
|  | // Signals // | 
|  | ///////////// | 
|  | kmac_reg2hw_t reg2hw; | 
|  | kmac_hw2reg_t hw2reg; | 
|  |  | 
|  | // devmode ties to 1 as KMAC should be operated at the beginning for ROM_CTRL. | 
|  | logic devmode; | 
|  | assign devmode = 1'b 1; | 
|  |  | 
|  | // Window | 
|  | typedef enum int { | 
|  | WinState   = 0, | 
|  | WinMsgFifo = 1 | 
|  | } tl_window_e; | 
|  |  | 
|  | tlul_pkg::tl_h2d_t tl_win_h2d[2]; | 
|  | tlul_pkg::tl_d2h_t tl_win_d2h[2]; | 
|  |  | 
|  | // SHA3 core control signals and its response. | 
|  | // Sequence: start --> process(multiple) --> get absorbed event --> {run -->} done | 
|  | logic sha3_start, sha3_run, unused_sha3_squeeze; | 
|  | prim_mubi_pkg::mubi4_t sha3_done; | 
|  | prim_mubi_pkg::mubi4_t sha3_done_d; | 
|  | prim_mubi_pkg::mubi4_t sha3_absorbed; | 
|  |  | 
|  | // Indicate one block processed | 
|  | logic sha3_block_processed; | 
|  |  | 
|  | // EStatus for entropy | 
|  | logic entropy_in_keyblock; | 
|  |  | 
|  | // Application interface logic generates absorbed from sha3_absorbed. | 
|  | // It is active only if SW initiates the hashing engine. | 
|  | prim_mubi_pkg::mubi4_t app_absorbed; | 
|  | logic event_absorbed; | 
|  |  | 
|  | sha3_pkg::sha3_st_e sha3_fsm; | 
|  |  | 
|  | // Prefix: kmac_pkg defines Prefix based on N size and S size. | 
|  | // Then computes left_encode(len(N)) size and left_encode(len(S)) | 
|  | // For given default value 32, 256 bits, the max | 
|  | // encode_string(N) || encode_string(S) is 328. So 11 Prefix registers are | 
|  | // created. | 
|  | logic [sha3_pkg::NSRegisterSize*8-1:0] reg_ns_prefix; | 
|  | logic [sha3_pkg::NSRegisterSize*8-1:0] ns_prefix; | 
|  |  | 
|  | // NumWordsPrefix from kmac_reg_pkg | 
|  | `ASSERT_INIT(PrefixRegSameToPrefixPkg_A, | 
|  | kmac_reg_pkg::NumWordsPrefix*4 == sha3_pkg::NSRegisterSize) | 
|  |  | 
|  | // NumEntriesMsgFifo from kmac_reg_pkg must match calculated MsgFifoDepth | 
|  | // from kmac_pkg. | 
|  | `ASSERT_INIT(NumEntriesRegSameToNumEntriesPkg_A, | 
|  | kmac_reg_pkg::NumEntriesMsgFifo == kmac_pkg::MsgFifoDepth) | 
|  |  | 
|  | // NumBytesMsgFifoEntry from kmac_reg_pkg must match the MsgWidth calculated | 
|  | // in kmac_pkg (although MsgWidth is in bits, so we multiply by 8). | 
|  | `ASSERT_INIT(EntrySizeRegSameToEntrySizePkg_A, | 
|  | kmac_reg_pkg::NumBytesMsgFifoEntry * 8 == kmac_pkg::MsgWidth) | 
|  |  | 
|  | // Output state: this is used to redirect the digest to KeyMgr or Software | 
|  | // depends on the configuration. | 
|  | logic state_valid; | 
|  | logic [sha3_pkg::StateW-1:0] state [Share]; | 
|  |  | 
|  | // state is de-muxed in keymgr interface logic. | 
|  | // the output from keymgr logic goes into staterd module to be visible to SW | 
|  | logic reg_state_valid; | 
|  | logic [sha3_pkg::StateW-1:0] reg_state [Share]; | 
|  |  | 
|  | // SHA3 Entropy interface | 
|  | logic sha3_rand_valid, sha3_rand_early, sha3_rand_consumed; | 
|  | logic [sha3_pkg::StateW/2-1:0] sha3_rand_data; | 
|  | logic sha3_rand_aux; | 
|  |  | 
|  | // FIFO related signals | 
|  | logic msgfifo_empty, msgfifo_full; | 
|  | logic [kmac_pkg::MsgFifoDepthW-1:0] msgfifo_depth; | 
|  |  | 
|  | logic                          msgfifo_valid       ; | 
|  | logic [kmac_pkg::MsgWidth-1:0] msgfifo_data [Share]; | 
|  | logic [kmac_pkg::MsgStrbW-1:0] msgfifo_strb        ; | 
|  | logic                          msgfifo_ready       ; | 
|  |  | 
|  | if (EnMasking) begin : gen_msgfifo_data_masked | 
|  | // In Masked mode, the input message data is split into two shares. | 
|  | // Only concern, however, here is the secret key. So message can be | 
|  | // put into only one share and other is 0. | 
|  | assign msgfifo_data[1] = '0; | 
|  | end | 
|  |  | 
|  | // TL-UL Adapter(MSG_FIFO) signals | 
|  | logic        tlram_req; | 
|  | logic        tlram_gnt; | 
|  | logic        tlram_we; | 
|  | logic [8:0]  tlram_addr;   // NOT_READ | 
|  | logic [31:0] tlram_wdata; | 
|  | logic [31:0] tlram_wmask; | 
|  | logic [31:0] tlram_rdata; | 
|  | logic        tlram_rvalid; | 
|  | logic [1:0]  tlram_rerror; | 
|  | logic [31:0] tlram_wdata_endian; | 
|  | logic [31:0] tlram_wmask_endian; | 
|  |  | 
|  | logic                          sw_msg_valid; | 
|  | logic [kmac_pkg::MsgWidth-1:0] sw_msg_data ; | 
|  | logic [kmac_pkg::MsgWidth-1:0] sw_msg_mask ; | 
|  | logic                          sw_msg_ready; | 
|  |  | 
|  | // KeyMgr interface to MSG_FIFO | 
|  | logic                          mux2fifo_valid; | 
|  | logic [kmac_pkg::MsgWidth-1:0] mux2fifo_data ; | 
|  | logic [kmac_pkg::MsgWidth-1:0] mux2fifo_mask ; | 
|  | logic                          mux2fifo_ready; | 
|  |  | 
|  | // KMAC to SHA3 core | 
|  | logic                          msg_valid       ; | 
|  | logic [kmac_pkg::MsgWidth-1:0] msg_data [Share]; | 
|  | logic [kmac_pkg::MsgWidth-1:0] msg_data_masked [Share]; | 
|  | logic [kmac_pkg::MsgStrbW-1:0] msg_strb        ; | 
|  | logic                          msg_ready       ; | 
|  |  | 
|  | // Process control signals | 
|  | // Process pulse propagates from register to SHA3 engine one by one. | 
|  | // Each module (MSG_FIFO, KMAC core, SHA3 core) generates the process pulse | 
|  | // after flushing internal data to the next module. | 
|  | logic reg2msgfifo_process, msgfifo2kmac_process, kmac2sha3_process; | 
|  |  | 
|  |  | 
|  | // Secret Key signals | 
|  | logic [MaxKeyLen-1:0] sw_key_data_reg [SwKeyShare]; | 
|  | logic [MaxKeyLen-1:0] sw_key_data [Share]; | 
|  | key_len_e             sw_key_len; | 
|  | logic [MaxKeyLen-1:0] key_data [Share]; | 
|  | key_len_e             key_len; | 
|  |  | 
|  | // SHA3 Mode, Strength, KMAC enable for app interface | 
|  | logic                       reg_kmac_en,         app_kmac_en; | 
|  | sha3_pkg::sha3_mode_e       reg_sha3_mode,       app_sha3_mode; | 
|  | sha3_pkg::keccak_strength_e reg_keccak_strength, app_keccak_strength; | 
|  |  | 
|  | // RegIF of enabling unsupported mode & strength | 
|  | logic cfg_en_unsupported_modestrength; | 
|  |  | 
|  | // Indicating AppIntf is active. This signal is used to check SW error | 
|  | logic app_active; | 
|  |  | 
|  | // Command | 
|  | // sw_cmd is the command written by SW | 
|  | // checked_sw_cmd is checked in the kmac_errchk module. | 
|  | //   Invalid command is filtered out in the module. | 
|  | // kmac_cmd is generated in KeyMgr interface. | 
|  | // If SW initiates the KMAC/SHA3, kmac_cmd represents SW command, | 
|  | // if KeyMgr drives the data, kmac_cmd is controled in the state machine | 
|  | // in KeyMgr interface logic. | 
|  | kmac_cmd_e sw_cmd, checked_sw_cmd, kmac_cmd, cmd_q; | 
|  | logic      cmd_update; | 
|  |  | 
|  | // Entropy configurations | 
|  | logic [9:0]  wait_timer_prescaler; | 
|  | logic [15:0] wait_timer_limit; | 
|  | logic        entropy_refresh_req; | 
|  | logic [NumSeedsEntropyLfsr-1:0]       entropy_seed_update; | 
|  | logic [NumSeedsEntropyLfsr-1:0][31:0] entropy_seed_data; | 
|  |  | 
|  | logic [HashCntW-1:0] entropy_hash_threshold; | 
|  | logic [HashCntW-1:0] entropy_hash_cnt; | 
|  | logic                entropy_hash_clr; | 
|  |  | 
|  | logic entropy_ready; | 
|  | entropy_mode_e entropy_mode; | 
|  | logic entropy_fast_process; | 
|  |  | 
|  | prim_mubi_pkg::mubi4_t entropy_configured; | 
|  |  | 
|  | // Message Masking | 
|  | logic msg_mask_en, cfg_msg_mask; | 
|  | logic [MsgWidth-1:0] msg_mask; | 
|  |  | 
|  | // SHA3 Error response | 
|  | sha3_pkg::err_t sha3_err; | 
|  |  | 
|  | // KeyMgr Error response | 
|  | kmac_pkg::err_t app_err; | 
|  |  | 
|  | // Entropy Generator Error | 
|  | kmac_pkg::err_t entropy_err; | 
|  |  | 
|  | // Error checker | 
|  | kmac_pkg::err_t errchecker_err; | 
|  |  | 
|  | // MsgFIFO Error | 
|  | kmac_pkg::err_t msgfifo_err; | 
|  |  | 
|  | logic err_processed; | 
|  |  | 
|  | logic alert_fatal, alert_recov_operation; | 
|  | logic alert_intg_err; | 
|  |  | 
|  | // Life cycle | 
|  | localparam int unsigned NumLcSyncCopies = 6; | 
|  | lc_ctrl_pkg::lc_tx_t [NumLcSyncCopies-1:0] lc_escalate_en_sync; | 
|  | lc_ctrl_pkg::lc_tx_t [NumLcSyncCopies-1:0] lc_escalate_en; | 
|  |  | 
|  | ////////////////////////////////////// | 
|  | // Connecting Register IF to logics // | 
|  | ////////////////////////////////////// | 
|  |  | 
|  | // Function-name N and Customization input string S | 
|  | always_comb begin | 
|  | for (int i = 0 ; i < NumWordsPrefix; i++) begin | 
|  | reg_ns_prefix[32*i+:32] = reg2hw.prefix[i].q; | 
|  | end | 
|  | end | 
|  |  | 
|  | // Create a lint error to reduce the risk of accidentally enabling this feature. | 
|  | `ASSERT_STATIC_LINT_ERROR(KmacSecCmdDelayNonDefault, SecCmdDelay == 0) | 
|  |  | 
|  | if (SecCmdDelay > 0) begin : gen_cmd_delay_buf | 
|  | // Delay and buffer commands for SCA measurements. | 
|  | localparam int unsigned WidthCounter = $clog2(SecCmdDelay+1); | 
|  | logic [WidthCounter-1:0] count_d, count_q; | 
|  | logic                    counting_d, counting_q; | 
|  | logic                    cmd_buf_empty; | 
|  | kmac_cmd_e               cmd_buf_q; | 
|  |  | 
|  | assign cmd_buf_empty = (cmd_buf_q == CmdNone); | 
|  |  | 
|  | // When seeing a write to the cmd register, we start counting. We stop counting once the | 
|  | // counter has expired and the command buffer is empty. | 
|  | assign counting_d = reg2hw.cmd.cmd.qe          ? 1'b1 : | 
|  | cmd_update & cmd_buf_empty ? 1'b0 : counting_q; | 
|  |  | 
|  | // Clear counter upon writes to the cmd register or if the specified delay is reached. | 
|  | assign count_d = reg2hw.cmd.cmd.qe ? '0             : | 
|  | cmd_update        ? '0             : | 
|  | counting_q        ? count_q + 1'b1 : count_q; | 
|  |  | 
|  | // The manual run command cannot be delayed. Software expects this to be triggered immediately | 
|  | // and will poll the status register to wait for the SHA3 engine to return back to the squeeze | 
|  | // state. | 
|  | assign cmd_update = (cmd_q == CmdManualRun)                    ? 1'b1 : | 
|  | (count_q == SecCmdDelay[WidthCounter-1:0]) ? 1'b1 : 1'b0; | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | count_q    <= '0; | 
|  | counting_q <= 1'b0; | 
|  | end else begin | 
|  | count_q    <= count_d; | 
|  | counting_q <= counting_d; | 
|  | end | 
|  | end | 
|  |  | 
|  | // cmd.q is valid while cmd.qe is high, meaning it needs to be registered. We buffer one | 
|  | // additional command such that software can write START followed by PROCESS and then go to | 
|  | // sleep. | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | cmd_q     <= CmdNone; | 
|  | cmd_buf_q <= CmdNone; | 
|  | end else begin | 
|  | if (reg2hw.cmd.cmd.qe && cmd_update) begin | 
|  | // New write & counter expired. | 
|  | cmd_q     <= cmd_buf_q; | 
|  | cmd_buf_q <= kmac_cmd_e'(reg2hw.cmd.cmd.q); | 
|  |  | 
|  | end else if (reg2hw.cmd.cmd.qe) begin | 
|  | // New write. | 
|  | if (counting_q == 1'b0) begin | 
|  | cmd_q     <= kmac_cmd_e'(reg2hw.cmd.cmd.q); | 
|  | end else begin | 
|  | cmd_buf_q <= kmac_cmd_e'(reg2hw.cmd.cmd.q); | 
|  | end | 
|  |  | 
|  | end else if (cmd_update) begin | 
|  | // Counter expired. | 
|  | cmd_q     <= cmd_buf_q; | 
|  | cmd_buf_q <= CmdNone; | 
|  | end | 
|  | end | 
|  | end | 
|  |  | 
|  | end else begin : gen_no_cmd_delay_buf | 
|  | // Directly forward signals from register IF. | 
|  | assign cmd_update = reg2hw.cmd.cmd.qe; | 
|  | assign cmd_q      = kmac_cmd_e'(reg2hw.cmd.cmd.q); | 
|  | end | 
|  |  | 
|  | // Command signals | 
|  | assign sw_cmd = (cmd_update) ? cmd_q : CmdNone; | 
|  | `ASSERT_KNOWN(KmacCmd_A, sw_cmd) | 
|  | always_comb begin | 
|  | sha3_start = 1'b 0; | 
|  | sha3_run = 1'b 0; | 
|  | sha3_done_d = prim_mubi_pkg::MuBi4False; | 
|  | reg2msgfifo_process = 1'b 0; | 
|  |  | 
|  | unique case (kmac_cmd) | 
|  | CmdStart: begin | 
|  | sha3_start = 1'b 1; | 
|  | end | 
|  |  | 
|  | CmdProcess: begin | 
|  | reg2msgfifo_process = 1'b 1; | 
|  | end | 
|  |  | 
|  | CmdManualRun: begin | 
|  | sha3_run = 1'b 1; | 
|  | end | 
|  |  | 
|  | CmdDone: begin | 
|  | sha3_done_d = prim_mubi_pkg::MuBi4True; | 
|  | end | 
|  |  | 
|  | CmdNone: begin | 
|  | // inactive state | 
|  | end | 
|  |  | 
|  | default: begin | 
|  | end | 
|  | endcase | 
|  | end | 
|  |  | 
|  | // Status register ========================================================== | 
|  | // status.squeeze is valid only when SHA3 engine completes the Absorb and not | 
|  | // running the manual keccak rounds. This status is for SW to determine when | 
|  | // to read the STATE values. | 
|  | assign hw2reg.status.sha3_idle.d     = sha3_fsm == sha3_pkg::StIdle; | 
|  | assign hw2reg.status.sha3_absorb.d   = sha3_fsm == sha3_pkg::StAbsorb; | 
|  | assign hw2reg.status.sha3_squeeze.d  = sha3_fsm == sha3_pkg::StSqueeze; | 
|  |  | 
|  | // FIFO related status | 
|  | assign hw2reg.status.fifo_depth.d[MsgFifoDepthW-1:0] = msgfifo_depth; | 
|  | if ($bits(hw2reg.status.fifo_depth.d) != MsgFifoDepthW) begin : gen_fifo_depth_tie | 
|  | assign hw2reg.status.fifo_depth.d[$bits(hw2reg.status.fifo_depth.d)-1:MsgFifoDepthW] = '0; | 
|  | end | 
|  | assign hw2reg.status.fifo_empty.d  = msgfifo_empty; | 
|  | assign hw2reg.status.fifo_full.d   = msgfifo_full; | 
|  |  | 
|  | // Configuration Register | 
|  | logic engine_stable; | 
|  | assign engine_stable = sha3_fsm == sha3_pkg::StIdle; | 
|  |  | 
|  | // SEC_CM: CFG_SHADOWED.CONFIG.REGWEN | 
|  | assign hw2reg.cfg_regwen.d = engine_stable; | 
|  |  | 
|  | // Secret Key | 
|  | // Secret key is defined as external register. So the logic latches when SW | 
|  | // writes to KEY_SHARE0 , KEY_SHARE1 registers. | 
|  | // SEC_CM: SW_KEY.KEY.MASKING | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | sw_key_data_reg[0] <= '0; | 
|  | end else if (engine_stable) begin | 
|  | for (int j = 0 ; j < MaxKeyLen/32 ; j++) begin | 
|  | if (reg2hw.key_share0[j].qe) begin | 
|  | sw_key_data_reg[0][32*j+:32] <= reg2hw.key_share0[j].q; | 
|  | end | 
|  | end // for j | 
|  | end // else if engine_stable | 
|  | end // always_ff | 
|  |  | 
|  | if (EnMasking || SwKeyMasked) begin : gen_key_share1_reg | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | sw_key_data_reg[1] <= '0; | 
|  | end else if (engine_stable) begin | 
|  | for (int j = 0 ; j < MaxKeyLen/32 ; j++) begin | 
|  | if (reg2hw.key_share1[j].qe) begin | 
|  | sw_key_data_reg[1][32*j+:32] <= reg2hw.key_share1[j].q; | 
|  | end | 
|  | end // for j | 
|  | end // else if engine_stable | 
|  | end // always_ff | 
|  | end else begin : gen_no_key_share1_reg | 
|  | logic unused_key_share1; | 
|  | assign unused_key_share1 = ^reg2hw.key_share1; | 
|  | end | 
|  |  | 
|  | if (EnMasking || !SwKeyMasked) begin : gen_key_forward | 
|  | // Forward all available key shares as is. | 
|  | assign sw_key_data = sw_key_data_reg; | 
|  | end else begin : gen_key_unmask | 
|  | // Masking is disabled but the SW still provides the key in two shares. | 
|  | // Unmask the key for processing. | 
|  | assign sw_key_data[0] = sw_key_data_reg[0] ^ sw_key_data_reg[1]; | 
|  | end | 
|  |  | 
|  | assign sw_key_len = key_len_e'(reg2hw.key_len.q); | 
|  |  | 
|  | // Entropy configurations | 
|  | assign wait_timer_prescaler = reg2hw.entropy_period.prescaler.q; | 
|  | assign wait_timer_limit     = reg2hw.entropy_period.wait_timer.q; | 
|  | assign entropy_refresh_req = reg2hw.cmd.entropy_req.q | 
|  | && reg2hw.cmd.entropy_req.qe; | 
|  | for (genvar i = 0; i < NumSeedsEntropyLfsr; i++) begin : gen_entropy_seed | 
|  | assign entropy_seed_update[i] = reg2hw.entropy_seed[i].qe; | 
|  | assign entropy_seed_data[i] = reg2hw.entropy_seed[i].q; | 
|  | end | 
|  |  | 
|  | assign entropy_hash_threshold = reg2hw.entropy_refresh_threshold_shadowed.q; | 
|  | assign hw2reg.entropy_refresh_hash_cnt.de = 1'b 1; | 
|  | assign hw2reg.entropy_refresh_hash_cnt.d  = entropy_hash_cnt; | 
|  |  | 
|  | assign entropy_hash_clr = reg2hw.cmd.hash_cnt_clr.qe | 
|  | && reg2hw.cmd.hash_cnt_clr.q; | 
|  |  | 
|  | // Entropy config | 
|  | assign entropy_ready = reg2hw.cfg_shadowed.entropy_ready.q | 
|  | & reg2hw.cfg_shadowed.entropy_ready.qe; | 
|  | assign entropy_mode  = entropy_mode_e'(reg2hw.cfg_shadowed.entropy_mode.q); | 
|  | assign entropy_fast_process = reg2hw.cfg_shadowed.entropy_fast_process.q; | 
|  |  | 
|  | // msg_mask_en turns on the message LFSR when KMAC is enabled. | 
|  | assign cfg_msg_mask = reg2hw.cfg_shadowed.msg_mask.q; | 
|  | assign msg_mask_en = cfg_msg_mask & msg_valid & msg_ready; | 
|  |  | 
|  | // Enable unsupported mode & strength combination | 
|  | assign cfg_en_unsupported_modestrength = | 
|  | reg2hw.cfg_shadowed.en_unsupported_modestrength.q; | 
|  |  | 
|  | `ASSERT(EntropyReadyLatched_A, $rose(entropy_ready) |=> !entropy_ready) | 
|  |  | 
|  | // Idle control (registered output) | 
|  | // The logic checks idle of SHA3 engine, MSG_FIFO, KMAC_CORE, KEYMGR interface | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | idle_o <= prim_mubi_pkg::MuBi4True; | 
|  | end else if ((sha3_fsm == sha3_pkg::StIdle) && (msgfifo_empty || SecIdleAcceptSwMsg)) begin | 
|  | idle_o <= prim_mubi_pkg::MuBi4True; | 
|  | end else begin | 
|  | idle_o <= prim_mubi_pkg::MuBi4False; | 
|  | end | 
|  | end | 
|  |  | 
|  | // Clear the error processed | 
|  | assign err_processed = reg2hw.cfg_shadowed.err_processed.q | 
|  | & reg2hw.cfg_shadowed.err_processed.qe; | 
|  |  | 
|  | // Make sure the field has latch in reg_top | 
|  | `ASSERT(ErrProcessedLatched_A, $rose(err_processed) |=> !err_processed) | 
|  |  | 
|  | // App mode, strength, kmac_en | 
|  | assign reg_kmac_en         = reg2hw.cfg_shadowed.kmac_en.q; | 
|  | assign reg_sha3_mode       = sha3_pkg::sha3_mode_e'(reg2hw.cfg_shadowed.mode.q); | 
|  | assign reg_keccak_strength = sha3_pkg::keccak_strength_e'(reg2hw.cfg_shadowed.kstrength.q); | 
|  |  | 
|  | /////////////// | 
|  | // Interrupt // | 
|  | /////////////// | 
|  |  | 
|  | logic event_msgfifo_empty, msgfifo_empty_q; | 
|  |  | 
|  | // Hash process absorbed interrupt | 
|  | // Convert mubi4_t to logic to generate interrupts | 
|  | assign event_absorbed = prim_mubi_pkg::mubi4_test_true_strict(app_absorbed); | 
|  |  | 
|  | prim_intr_hw #(.Width(1)) intr_kmac_done ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .event_intr_i           (event_absorbed), | 
|  | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.kmac_done.q), | 
|  | .reg2hw_intr_test_q_i   (reg2hw.intr_test.kmac_done.q), | 
|  | .reg2hw_intr_test_qe_i  (reg2hw.intr_test.kmac_done.qe), | 
|  | .reg2hw_intr_state_q_i  (reg2hw.intr_state.kmac_done.q), | 
|  | .hw2reg_intr_state_de_o (hw2reg.intr_state.kmac_done.de), | 
|  | .hw2reg_intr_state_d_o  (hw2reg.intr_state.kmac_done.d), | 
|  | .intr_o                 (intr_kmac_done_o) | 
|  | ); | 
|  |  | 
|  | `ASSERT(Sha3AbsorbedPulse_A, | 
|  | $rose(prim_mubi_pkg::mubi4_test_true_strict(sha3_absorbed)) |=> | 
|  | prim_mubi_pkg::mubi4_test_false_strict(sha3_absorbed)) | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) msgfifo_empty_q <= 1'b1; | 
|  | else         msgfifo_empty_q <= msgfifo_empty; | 
|  | end | 
|  |  | 
|  | assign event_msgfifo_empty = ~msgfifo_empty_q & msgfifo_empty; | 
|  |  | 
|  | prim_intr_hw #(.Width(1)) intr_fifo_empty ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .event_intr_i           (event_msgfifo_empty), | 
|  | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.fifo_empty.q), | 
|  | .reg2hw_intr_test_q_i   (reg2hw.intr_test.fifo_empty.q), | 
|  | .reg2hw_intr_test_qe_i  (reg2hw.intr_test.fifo_empty.qe), | 
|  | .reg2hw_intr_state_q_i  (reg2hw.intr_state.fifo_empty.q), | 
|  | .hw2reg_intr_state_de_o (hw2reg.intr_state.fifo_empty.de), | 
|  | .hw2reg_intr_state_d_o  (hw2reg.intr_state.fifo_empty.d), | 
|  | .intr_o                 (intr_fifo_empty_o) | 
|  | ); | 
|  |  | 
|  | // Error | 
|  | // As of now, only SHA3 error exists. More error codes will be added. | 
|  |  | 
|  | logic event_error; | 
|  | assign event_error = sha3_err.valid    | app_err.valid | 
|  | | entropy_err.valid | errchecker_err.valid | 
|  | ; | 
|  |  | 
|  | // Assing error code to the register | 
|  | assign hw2reg.err_code.de = event_error; | 
|  |  | 
|  | always_comb begin | 
|  | hw2reg.err_code.d = '0; | 
|  |  | 
|  | priority case (1'b 1) | 
|  | // app_err has the highest priority. If SW issues an incorrect command | 
|  | // while app is in active state, the error from AppIntf is passed | 
|  | // through. | 
|  | app_err.valid: begin | 
|  | hw2reg.err_code.d = {app_err.code, app_err.info}; | 
|  | end | 
|  |  | 
|  | errchecker_err.valid: begin | 
|  | hw2reg.err_code.d = {errchecker_err.code , errchecker_err.info}; | 
|  | end | 
|  |  | 
|  | sha3_err.valid: begin | 
|  | hw2reg.err_code.d = {sha3_err.code , sha3_err.info}; | 
|  | end | 
|  |  | 
|  | entropy_err.valid: begin | 
|  | hw2reg.err_code.d = {entropy_err.code, entropy_err.info}; | 
|  | end | 
|  |  | 
|  | msgfifo_err.valid: begin | 
|  | hw2reg.err_code.d = {msgfifo_err.code, msgfifo_err.info}; | 
|  | end | 
|  |  | 
|  | default: begin | 
|  | hw2reg.err_code.d = '0; | 
|  | end | 
|  | endcase | 
|  | end | 
|  |  | 
|  | // Counter errors | 
|  | logic counter_error, sha3_count_error, key_index_error; | 
|  | logic msgfifo_counter_error; | 
|  | logic kmac_entropy_hash_counter_error; | 
|  | assign counter_error = sha3_count_error | 
|  | | kmac_entropy_hash_counter_error | 
|  | | key_index_error | 
|  | | msgfifo_counter_error; | 
|  |  | 
|  | assign msgfifo_counter_error = msgfifo_err.valid; | 
|  |  | 
|  | // State Errors | 
|  | logic sparse_fsm_error; | 
|  | logic sha3_state_error, kmac_errchk_state_error; | 
|  | logic kmac_core_state_error, kmac_app_state_error; | 
|  | logic kmac_entropy_state_error, kmac_state_error; | 
|  | assign sparse_fsm_error = sha3_state_error | 
|  | | kmac_errchk_state_error | 
|  | | kmac_core_state_error | 
|  | | kmac_app_state_error | 
|  | | kmac_entropy_state_error | 
|  | | kmac_state_error; | 
|  |  | 
|  | // Control Signal Integrity Errors | 
|  | logic control_integrity_error; | 
|  | logic sha3_storage_rst_error; | 
|  | assign control_integrity_error = sha3_storage_rst_error; | 
|  |  | 
|  | prim_intr_hw #(.Width(1)) intr_kmac_err ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .event_intr_i           (event_error), | 
|  | .reg2hw_intr_enable_q_i (reg2hw.intr_enable.kmac_err.q), | 
|  | .reg2hw_intr_test_q_i   (reg2hw.intr_test.kmac_err.q), | 
|  | .reg2hw_intr_test_qe_i  (reg2hw.intr_test.kmac_err.qe), | 
|  | .reg2hw_intr_state_q_i  (reg2hw.intr_state.kmac_err.q), | 
|  | .hw2reg_intr_state_de_o (hw2reg.intr_state.kmac_err.de), | 
|  | .hw2reg_intr_state_d_o  (hw2reg.intr_state.kmac_err.d), | 
|  | .intr_o                 (intr_kmac_err_o) | 
|  | ); | 
|  |  | 
|  | /////////////////// | 
|  | // State Machine // | 
|  | /////////////////// | 
|  |  | 
|  | // State FF | 
|  | `PRIM_FLOP_SPARSE_FSM(u_state_regs, kmac_st_d, kmac_st, kmac_st_e, KmacIdle) | 
|  |  | 
|  | always_comb begin | 
|  | // Default value | 
|  | kmac_st_d = kmac_st; | 
|  |  | 
|  | entropy_in_keyblock = 1'b 0; | 
|  | kmac_state_error = 1'b 0; | 
|  |  | 
|  | unique case (kmac_st) | 
|  | KmacIdle: begin | 
|  | if (kmac_cmd == CmdStart) begin | 
|  | // If cSHAKE turned on | 
|  | if (sha3_pkg::CShake == app_sha3_mode) begin | 
|  | kmac_st_d = KmacPrefix; | 
|  | end else begin | 
|  | // Jump to Msg feed directly | 
|  | kmac_st_d = KmacMsgFeed; | 
|  | end | 
|  | end else begin | 
|  | kmac_st_d = KmacIdle; | 
|  | end | 
|  | end | 
|  |  | 
|  | KmacPrefix: begin | 
|  | // Wait until SHA3 processes one block | 
|  | if (sha3_block_processed) begin | 
|  | kmac_st_d = (app_kmac_en) ? KmacKeyBlock : KmacMsgFeed ; | 
|  | end else begin | 
|  | kmac_st_d = KmacPrefix; | 
|  | end | 
|  | end | 
|  |  | 
|  | KmacKeyBlock: begin | 
|  | entropy_in_keyblock = 1'b 1; | 
|  | if (sha3_block_processed) begin | 
|  | kmac_st_d = KmacMsgFeed; | 
|  | end else begin | 
|  | kmac_st_d = KmacKeyBlock; | 
|  | end | 
|  | end | 
|  |  | 
|  | KmacMsgFeed: begin | 
|  | // If absorbed, move to Digest | 
|  | if (prim_mubi_pkg::mubi4_test_true_strict(sha3_absorbed) && | 
|  | prim_mubi_pkg::mubi4_test_true_strict(sha3_done)) begin | 
|  | // absorbed and done can be asserted at a cycle if Applications have | 
|  | // requested the hash operation. kmac_app FSM issues CmdDone command | 
|  | // if it receives absorbed signal. | 
|  | kmac_st_d = KmacIdle; | 
|  | end else if (prim_mubi_pkg::mubi4_test_true_strict(sha3_absorbed) && | 
|  | prim_mubi_pkg::mubi4_test_false_loose(sha3_done)) begin | 
|  | kmac_st_d = KmacDigest; | 
|  | end else begin | 
|  | kmac_st_d = KmacMsgFeed; | 
|  | end | 
|  | end | 
|  |  | 
|  | KmacDigest: begin | 
|  | // SW can manually run it, wait till done | 
|  | if (prim_mubi_pkg::mubi4_test_true_strict(sha3_done)) begin | 
|  | kmac_st_d = KmacIdle; | 
|  | end else begin | 
|  | kmac_st_d = KmacDigest; | 
|  | end | 
|  | end | 
|  |  | 
|  | KmacTerminalError: begin | 
|  | //this state is terminal | 
|  | kmac_st_d = KmacTerminalError; | 
|  | kmac_state_error = 1'b 1; | 
|  | end | 
|  |  | 
|  | default: begin | 
|  | kmac_st_d = KmacTerminalError; | 
|  | kmac_state_error = 1'b 1; | 
|  | end | 
|  | endcase | 
|  |  | 
|  | // SEC_CM: FSM.GLOBAL_ESC, FSM.LOCAL_ESC | 
|  | // Unconditionally jump into the terminal error state | 
|  | // if the life cycle controller triggers an escalation. | 
|  | if (lc_escalate_en[0] != lc_ctrl_pkg::Off) begin | 
|  | kmac_st_d = KmacTerminalError; | 
|  | end | 
|  | end | 
|  | `ASSERT_KNOWN(KmacStKnown_A, kmac_st) | 
|  |  | 
|  | /////////////// | 
|  | // Instances // | 
|  | /////////////// | 
|  |  | 
|  | // KMAC core | 
|  | kmac_core #( | 
|  | .EnMasking (EnMasking) | 
|  | ) u_kmac_core ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | // from Msg FIFO | 
|  | .fifo_valid_i (msgfifo_valid), | 
|  | .fifo_data_i  (msgfifo_data ), | 
|  | .fifo_strb_i  (msgfifo_strb ), | 
|  | .fifo_ready_o (msgfifo_ready), | 
|  |  | 
|  | // to SHA3 core | 
|  | .msg_valid_o  (msg_valid), | 
|  | .msg_data_o   (msg_data ), | 
|  | .msg_strb_o   (msg_strb ), | 
|  | .msg_ready_i  (msg_ready), | 
|  |  | 
|  | // Configurations | 
|  | .kmac_en_i  (app_kmac_en), | 
|  | .mode_i     (app_sha3_mode), | 
|  | .strength_i (app_keccak_strength), | 
|  |  | 
|  | // Secret key interface | 
|  | .key_data_i (key_data), | 
|  | .key_len_i  (key_len ), | 
|  |  | 
|  | // Controls | 
|  | .start_i   (sha3_start          ), | 
|  | .process_i (msgfifo2kmac_process), | 
|  | .done_i    (sha3_done           ), | 
|  | .process_o (kmac2sha3_process   ), | 
|  |  | 
|  | // LC escalation | 
|  | .lc_escalate_en_i (lc_escalate_en[1]), | 
|  |  | 
|  | // Error detection | 
|  | .sparse_fsm_error_o (kmac_core_state_error), | 
|  | .key_index_error_o  (key_index_error) | 
|  | ); | 
|  |  | 
|  | // SHA3 hashing engine | 
|  |  | 
|  | // msg_data masking | 
|  | if (EnMasking == 1) begin: g_msg_mask | 
|  | logic [MsgWidth-1:0] msg_mask_permuted; | 
|  |  | 
|  | // Permute the LFSR output to avoid same lfsr applied to multiple times | 
|  | always_comb begin | 
|  | msg_mask_permuted = '0; | 
|  | for (int unsigned i = 0 ; i < MsgWidth ; i++) begin | 
|  | // Loop through the MsgPerm constant and swap between the bits | 
|  | msg_mask_permuted[i] = msg_mask[RndCnstMsgPerm[i]]; | 
|  | end | 
|  | end | 
|  |  | 
|  | for (genvar i = 0 ; i < Share ; i++) begin: g_msg_data_mask | 
|  | assign msg_data_masked[i] = msg_data[i] | 
|  | ^ ({MsgWidth{cfg_msg_mask}} & msg_mask_permuted); | 
|  | end : g_msg_data_mask | 
|  | end else begin : g_no_msg_mask | 
|  | assign msg_data_masked[0] = msg_data[0]; | 
|  |  | 
|  | logic unused_msgmask; | 
|  | assign unused_msgmask = ^{msg_mask, cfg_msg_mask, msg_mask_en}; | 
|  | end | 
|  | sha3 #( | 
|  | .EnMasking (EnMasking) | 
|  | ) u_sha3 ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | // MSG_FIFO interface (or from KMAC) | 
|  | .msg_valid_i (msg_valid), | 
|  | .msg_data_i  (msg_data_masked ), | 
|  | .msg_strb_i  (msg_strb ), | 
|  | .msg_ready_o (msg_ready), | 
|  |  | 
|  | // Entropy interface | 
|  | .rand_valid_i    (sha3_rand_valid), | 
|  | .rand_early_i    (sha3_rand_early), | 
|  | .rand_data_i     (sha3_rand_data), | 
|  | .rand_aux_i      (sha3_rand_aux), | 
|  | .rand_consumed_o (sha3_rand_consumed), | 
|  |  | 
|  | // N, S: Used in cSHAKE mode | 
|  | .ns_data_i       (ns_prefix), | 
|  |  | 
|  | // Configurations | 
|  | .mode_i     (app_sha3_mode), | 
|  | .strength_i (app_keccak_strength), | 
|  |  | 
|  | // Controls (CMD register) | 
|  | .start_i    (sha3_start       ), | 
|  | .process_i  (kmac2sha3_process), | 
|  | .run_i      (sha3_run         ), | 
|  | .done_i     (sha3_done        ), | 
|  |  | 
|  | // LC escalation | 
|  | .lc_escalate_en_i (lc_escalate_en[2]), | 
|  |  | 
|  | .absorbed_o  (sha3_absorbed), | 
|  | .squeezing_o (unused_sha3_squeeze), | 
|  |  | 
|  | .block_processed_o (sha3_block_processed), | 
|  |  | 
|  | .sha3_fsm_o (sha3_fsm), | 
|  |  | 
|  | .state_valid_o (state_valid), | 
|  | .state_o       (state), // [Share] | 
|  |  | 
|  | .error_o                    (sha3_err), | 
|  | .sparse_fsm_error_o         (sha3_state_error), | 
|  | .count_error_o              (sha3_count_error), | 
|  | .keccak_storage_rst_error_o (sha3_storage_rst_error) | 
|  | ); | 
|  |  | 
|  | // MSG_FIFO window interface to FIFO interface =============================== | 
|  | // Tie the read path | 
|  | assign tlram_rvalid = 1'b 0; | 
|  | assign tlram_rdata = '0; | 
|  | assign tlram_rerror = '0; | 
|  |  | 
|  | // Convert endian here | 
|  | //    prim_packer always packs to the right(bit0). If the input DWORD is | 
|  | //    big-endian, it needs to be swapped to little-endian to maintain the | 
|  | //    order. Internal SHA3(Keccak) runs in little-endian in contrast to HMAC | 
|  | //    So, no endian-swap after prim_packer. | 
|  | assign tlram_wdata_endian = conv_endian32(tlram_wdata, | 
|  | reg2hw.cfg_shadowed.msg_endianness.q); | 
|  | assign tlram_wmask_endian = conv_endian32(tlram_wmask, | 
|  | reg2hw.cfg_shadowed.msg_endianness.q); | 
|  |  | 
|  | // TL Adapter | 
|  | tlul_adapter_sram #( | 
|  | .SramAw ($clog2(MsgWindowDepth)), | 
|  | .SramDw (MsgWindowWidth), | 
|  | .Outstanding (1), | 
|  | .ByteAccess  (1), | 
|  | .ErrOnRead   (1) | 
|  | ) u_tlul_adapter_msgfifo ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .en_ifetch_i (prim_mubi_pkg::MuBi4False), | 
|  | .tl_i        (tl_win_h2d[WinMsgFifo]), | 
|  | .tl_o        (tl_win_d2h[WinMsgFifo]), | 
|  |  | 
|  | .req_o       (tlram_req), | 
|  | .req_type_o  (), | 
|  | .gnt_i       (tlram_gnt), | 
|  | .we_o        (tlram_we ), | 
|  | .addr_o      (tlram_addr), | 
|  | .wdata_o     (tlram_wdata), | 
|  | .wmask_o     (tlram_wmask), | 
|  | .intg_error_o(           ), | 
|  | .rdata_i     (tlram_rdata), | 
|  | .rvalid_i    (tlram_rvalid), | 
|  | .rerror_i    (tlram_rerror) | 
|  | ); | 
|  |  | 
|  | assign sw_msg_valid = tlram_req & tlram_we ; | 
|  | if (MsgWidth == MsgWindowWidth) begin : gen_sw_msg_samewidth | 
|  | assign sw_msg_data  = tlram_wdata_endian ; | 
|  | assign sw_msg_mask  = tlram_wmask_endian ; | 
|  | end else begin : gen_sw_msg_diff | 
|  | assign sw_msg_data = {{MsgWidth-MsgWindowWidth{1'b0}}, tlram_wdata_endian}; | 
|  | assign sw_msg_mask = {{MsgWidth-MsgWindowWidth{1'b0}}, tlram_wmask_endian}; | 
|  | end | 
|  | assign tlram_gnt    = sw_msg_ready ; | 
|  |  | 
|  | logic unused_tlram_addr; | 
|  | assign unused_tlram_addr = &{1'b0, tlram_addr}; | 
|  |  | 
|  | // Application interface Mux/Demux | 
|  | kmac_app #( | 
|  | .EnMasking(EnMasking), | 
|  | .SecIdleAcceptSwMsg(SecIdleAcceptSwMsg) | 
|  | ) u_app_intf ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | .reg_key_data_i (sw_key_data), | 
|  | .reg_key_len_i  (sw_key_len), | 
|  |  | 
|  | .reg_prefix_i (reg_ns_prefix), | 
|  |  | 
|  | .reg_kmac_en_i         (reg_kmac_en), | 
|  | .reg_sha3_mode_i       (reg_sha3_mode), | 
|  | .reg_keccak_strength_i (reg_keccak_strength), | 
|  |  | 
|  | // data from tl_adapter | 
|  | .sw_valid_i (sw_msg_valid), | 
|  | .sw_data_i  (sw_msg_data), | 
|  | .sw_mask_i  (sw_msg_mask), | 
|  | .sw_ready_o (sw_msg_ready), | 
|  |  | 
|  | // KeyMgr sideloaded key interface | 
|  | .keymgr_key_i, | 
|  |  | 
|  | // Application data in / digest out interface | 
|  | .app_i, | 
|  | .app_o, | 
|  |  | 
|  | // Secret Key output to KMAC Core | 
|  | .key_data_o (key_data), | 
|  | .key_len_o  (key_len), | 
|  |  | 
|  | // to MSG_FIFO | 
|  | .kmac_valid_o (mux2fifo_valid), | 
|  | .kmac_data_o  (mux2fifo_data), | 
|  | .kmac_mask_o  (mux2fifo_mask), | 
|  | .kmac_ready_i (mux2fifo_ready), | 
|  |  | 
|  | // to KMAC Core | 
|  | .kmac_en_o (app_kmac_en), | 
|  |  | 
|  | // to SHA3 Core | 
|  | .sha3_prefix_o     (ns_prefix), | 
|  | .sha3_mode_o       (app_sha3_mode), | 
|  | .keccak_strength_o (app_keccak_strength), | 
|  |  | 
|  | // Keccak state from SHA3 core | 
|  | .keccak_state_valid_i (state_valid), | 
|  | .keccak_state_i       (state), | 
|  |  | 
|  | // to STATE TL Window | 
|  | .reg_state_valid_o    (reg_state_valid), | 
|  | .reg_state_o          (reg_state), | 
|  |  | 
|  | // Configuration: Sideloaded Key | 
|  | .keymgr_key_en_i      (reg2hw.cfg_shadowed.sideload.q), | 
|  |  | 
|  | .absorbed_i (sha3_absorbed), // from SHA3 | 
|  | .absorbed_o (app_absorbed),  // to SW | 
|  |  | 
|  | .app_active_o(app_active), | 
|  |  | 
|  | .error_i         (sha3_err.valid), | 
|  | .err_processed_i (err_processed), | 
|  |  | 
|  | // Command interface | 
|  | .sw_cmd_i (checked_sw_cmd), | 
|  | .cmd_o    (kmac_cmd), | 
|  |  | 
|  | // Status | 
|  | .entropy_ready_i (entropy_configured), | 
|  |  | 
|  | // LC escalation | 
|  | .lc_escalate_en_i (lc_escalate_en[3]), | 
|  |  | 
|  | // Error report | 
|  | .error_o            (app_err), | 
|  | .sparse_fsm_error_o (kmac_app_state_error) | 
|  |  | 
|  | ); | 
|  |  | 
|  | // Message FIFO | 
|  | kmac_msgfifo #( | 
|  | .OutWidth  (kmac_pkg::MsgWidth), | 
|  | .MsgDepth  (kmac_pkg::MsgFifoDepth), | 
|  | .EnMasking (EnMasking) | 
|  | ) u_msgfifo ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | .fifo_valid_i (mux2fifo_valid), | 
|  | .fifo_data_i  (mux2fifo_data), | 
|  | .fifo_mask_i  (mux2fifo_mask), | 
|  | .fifo_ready_o (mux2fifo_ready), | 
|  |  | 
|  | .msg_valid_o (msgfifo_valid), | 
|  | .msg_data_o  (msgfifo_data[0]), | 
|  | .msg_strb_o  (msgfifo_strb), | 
|  | .msg_ready_i (msgfifo_ready), | 
|  |  | 
|  | .fifo_empty_o (msgfifo_empty), // intr and status | 
|  | .fifo_full_o  (msgfifo_full),  // connected to status only | 
|  | .fifo_depth_o (msgfifo_depth), | 
|  |  | 
|  | .clear_i (sha3_done), | 
|  |  | 
|  | .process_i (reg2msgfifo_process ), | 
|  | .process_o (msgfifo2kmac_process), | 
|  |  | 
|  | .err_o (msgfifo_err) | 
|  | ); | 
|  |  | 
|  | logic [sha3_pkg::StateW-1:0] reg_state_tl [Share]; | 
|  | always_comb begin | 
|  | for (int i = 0 ; i < Share; i++) begin | 
|  | reg_state_tl[i] = reg_state_valid ? reg_state[i] : 'b0; | 
|  | end | 
|  | end | 
|  |  | 
|  | // State (Digest) reader | 
|  | kmac_staterd #( | 
|  | .AddrW     (9), // 512B | 
|  | .EnMasking (EnMasking) | 
|  | ) u_staterd ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | .tl_i (tl_win_h2d[WinState]), | 
|  | .tl_o (tl_win_d2h[WinState]), | 
|  |  | 
|  | .state_i (reg_state_tl), | 
|  |  | 
|  | .endian_swap_i (reg2hw.cfg_shadowed.state_endianness.q) | 
|  | ); | 
|  |  | 
|  | // Error checker | 
|  | kmac_errchk #( | 
|  | .EnMasking (EnMasking) | 
|  | ) u_errchk ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | // Configurations | 
|  | .cfg_mode_i    (reg_sha3_mode      ), | 
|  | .cfg_strength_i(reg_keccak_strength), | 
|  |  | 
|  | .kmac_en_i      (reg_kmac_en        ), | 
|  | .cfg_prefix_6B_i(reg_ns_prefix[47:0]), // first 6B of PREFIX | 
|  |  | 
|  | .cfg_en_unsupported_modestrength_i (cfg_en_unsupported_modestrength), | 
|  |  | 
|  | .entropy_ready_pulse_i (entropy_ready), | 
|  |  | 
|  | // SW commands | 
|  | .sw_cmd_i(sw_cmd), | 
|  | .sw_cmd_o(checked_sw_cmd), | 
|  |  | 
|  | // Status from KMAC_APP | 
|  | .app_active_i(app_active), | 
|  |  | 
|  | // Status from SHA3 core | 
|  | .sha3_absorbed_i(sha3_absorbed       ), | 
|  | .keccak_done_i  (sha3_block_processed), | 
|  |  | 
|  | // LC escalation | 
|  | .lc_escalate_en_i (lc_escalate_en[4]), | 
|  |  | 
|  | .err_processed_i (err_processed), | 
|  |  | 
|  | .error_o            (errchecker_err), | 
|  | .sparse_fsm_error_o (kmac_errchk_state_error) | 
|  | ); | 
|  |  | 
|  | // Entropy Generator | 
|  | if (EnMasking == 1) begin : gen_entropy | 
|  |  | 
|  | logic entropy_req, entropy_ack; | 
|  | logic [edn_pkg::ENDPOINT_BUS_WIDTH-1:0] entropy_data; | 
|  | logic unused_entropy_fips; | 
|  |  | 
|  | // Synchronize EDN interface | 
|  | prim_sync_reqack_data #( | 
|  | .Width(edn_pkg::ENDPOINT_BUS_WIDTH), | 
|  | .DataSrc2Dst(1'b0), | 
|  | .DataReg(1'b0) | 
|  | ) u_prim_sync_reqack_data ( | 
|  | .clk_src_i (clk_i), | 
|  | .rst_src_ni(rst_ni), | 
|  | .clk_dst_i (clk_edn_i), | 
|  | .rst_dst_ni(rst_edn_ni), | 
|  | .req_chk_i ((kmac_entropy_state_error == 1'b0) && (entropy_err.valid == 1'b0)), | 
|  | .src_req_i (entropy_req), | 
|  | .src_ack_o (entropy_ack), | 
|  | .dst_req_o (entropy_o.edn_req), | 
|  | .dst_ack_i (entropy_i.edn_ack), | 
|  | .data_i    (entropy_i.edn_bus), | 
|  | .data_o    (entropy_data) | 
|  | ); | 
|  |  | 
|  | // We don't track whether the entropy is pre-FIPS or not inside KMAC. | 
|  | assign unused_entropy_fips = entropy_i.edn_fips; | 
|  |  | 
|  | kmac_entropy #( | 
|  | .RndCnstLfsrPerm(RndCnstLfsrPerm), | 
|  | .RndCnstLfsrSeed(RndCnstLfsrSeed), | 
|  | .RndCnstLfsrFwdPerm(RndCnstLfsrFwdPerm) | 
|  | ) u_entropy ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  |  | 
|  | // EDN interface | 
|  | .entropy_req_o (entropy_req), | 
|  | .entropy_ack_i (entropy_ack), | 
|  | .entropy_data_i(entropy_data), | 
|  |  | 
|  | // Entropy to internal logic (DOM AND) | 
|  | .rand_valid_o    (sha3_rand_valid), | 
|  | .rand_early_o    (sha3_rand_early), | 
|  | .rand_data_o     (sha3_rand_data), | 
|  | .rand_aux_o      (sha3_rand_aux), | 
|  | .rand_consumed_i (sha3_rand_consumed), | 
|  |  | 
|  | // Status from internal logic | 
|  | //// KMAC secret block handling indicator | 
|  | .in_keyblock_i (entropy_in_keyblock), | 
|  |  | 
|  | // Configuration | 
|  | .mode_i          (entropy_mode), | 
|  | .entropy_ready_i (entropy_ready), | 
|  | .fast_process_i  (entropy_fast_process), | 
|  |  | 
|  | //// Entropy refresh period in clk cycles | 
|  | .wait_timer_prescaler_i (wait_timer_prescaler), | 
|  | .wait_timer_limit_i     (wait_timer_limit), | 
|  |  | 
|  | //// Message Masking | 
|  | .msg_mask_en_i (msg_mask_en), | 
|  | .msg_mask_o    (msg_mask), | 
|  |  | 
|  | //// SW update of seed | 
|  | .seed_update_i         (entropy_seed_update), | 
|  | .seed_data_i           (entropy_seed_data), | 
|  | .entropy_refresh_req_i (entropy_refresh_req), | 
|  |  | 
|  | // Status | 
|  | .hash_cnt_o       (entropy_hash_cnt), | 
|  | .hash_cnt_clr_i   (entropy_hash_clr), | 
|  | .hash_threshold_i (entropy_hash_threshold), | 
|  |  | 
|  | .entropy_configured_o (entropy_configured), | 
|  |  | 
|  | // LC escalation | 
|  | .lc_escalate_en_i (lc_escalate_en[5]), | 
|  |  | 
|  | // Error | 
|  | .err_o              (entropy_err), | 
|  | .sparse_fsm_error_o (kmac_entropy_state_error), | 
|  | .count_error_o      (kmac_entropy_hash_counter_error), | 
|  | .err_processed_i    (err_processed) | 
|  | ); | 
|  | end else begin : gen_empty_entropy | 
|  | // If Masking is not used, no need of entropy. Ignore inputs and config; tie output to 0. | 
|  | edn_pkg::edn_rsp_t unused_entropy_input; | 
|  | entropy_mode_e     unused_entropy_mode; | 
|  | logic              unused_entropy_fast_process; | 
|  |  | 
|  | assign unused_entropy_input        = entropy_i; | 
|  | assign unused_entropy_mode         = entropy_mode; | 
|  | assign unused_entropy_fast_process = entropy_fast_process; | 
|  |  | 
|  | assign entropy_o = '{default: '0}; | 
|  |  | 
|  | logic unused_sha3_rand_consumed; | 
|  | assign sha3_rand_valid = 1'b 1; | 
|  | assign sha3_rand_early = 1'b 1; | 
|  | assign sha3_rand_data = '0; | 
|  | assign sha3_rand_aux = '0; | 
|  | assign unused_sha3_rand_consumed = sha3_rand_consumed; | 
|  |  | 
|  | logic [NumSeedsEntropyLfsr-1:0]       unused_seed_update; | 
|  | logic [NumSeedsEntropyLfsr-1:0][31:0] unused_seed_data; | 
|  | logic [31:0] unused_refresh_period; | 
|  | logic unused_entropy_refresh_req; | 
|  | assign unused_seed_data = entropy_seed_data; | 
|  | assign unused_seed_update = entropy_seed_update; | 
|  | assign unused_refresh_period = ^{wait_timer_limit, wait_timer_prescaler}; | 
|  | assign unused_entropy_refresh_req = entropy_refresh_req; | 
|  |  | 
|  | logic unused_entropy_hash; | 
|  | assign unused_entropy_hash = ^{entropy_hash_clr, entropy_hash_threshold}; | 
|  | assign entropy_hash_cnt = '0; | 
|  |  | 
|  | assign entropy_err = '{valid: 1'b 0, code: ErrNone, info: '0}; | 
|  |  | 
|  | assign kmac_entropy_state_error = 1'b 0; | 
|  | assign kmac_entropy_hash_counter_error  = 1'b 0; | 
|  |  | 
|  | logic [1:0] unused_entropy_status; | 
|  | assign unused_entropy_status = entropy_in_keyblock; | 
|  |  | 
|  | // If Masking is off, always entropy configured | 
|  | assign entropy_configured = prim_mubi_pkg::MuBi4True; | 
|  | end | 
|  |  | 
|  | // MUBI4 buf | 
|  | prim_mubi4_sender #( | 
|  | .AsyncOn (0) | 
|  | ) u_sha3_done_sender ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .mubi_i (sha3_done_d), | 
|  | .mubi_o (sha3_done) | 
|  | ); | 
|  |  | 
|  | // Register top | 
|  | logic [NumAlerts-1:0] alert_test, alerts, alerts_q; | 
|  |  | 
|  | logic shadowed_storage_err, shadowed_update_err; | 
|  | kmac_reg_top u_reg ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .rst_shadowed_ni, | 
|  |  | 
|  | .tl_i, | 
|  | .tl_o, | 
|  |  | 
|  | .tl_win_o (tl_win_h2d), | 
|  | .tl_win_i (tl_win_d2h), | 
|  |  | 
|  | .reg2hw, | 
|  | .hw2reg, | 
|  |  | 
|  | // SEC_CM: CFG_SHADOWED.CONFIG.SHADOW | 
|  | .shadowed_storage_err_o (shadowed_storage_err), | 
|  | .shadowed_update_err_o  (shadowed_update_err), | 
|  | // SEC_CM: BUS.INTEGRITY | 
|  | .intg_err_o             (alert_intg_err), | 
|  |  | 
|  | .devmode_i (devmode) | 
|  | ); | 
|  |  | 
|  | logic unused_cfg_shadowed_qe; | 
|  | assign unused_cfg_shadowed_qe = ^{ | 
|  | reg2hw.cfg_shadowed.kmac_en.qe                     , | 
|  | reg2hw.cfg_shadowed.kstrength.qe                   , | 
|  | reg2hw.cfg_shadowed.mode.qe                        , | 
|  | reg2hw.cfg_shadowed.msg_endianness.qe              , | 
|  | reg2hw.cfg_shadowed.state_endianness.qe            , | 
|  | reg2hw.cfg_shadowed.sideload.qe                    , | 
|  | reg2hw.cfg_shadowed.entropy_mode.qe                , | 
|  | reg2hw.cfg_shadowed.entropy_fast_process.qe        , | 
|  | reg2hw.cfg_shadowed.msg_mask.qe                    , | 
|  | reg2hw.cfg_shadowed.en_unsupported_modestrength.qe | 
|  | }; | 
|  |  | 
|  | // Alerts | 
|  | assign alert_test = { | 
|  | reg2hw.alert_test.fatal_fault_err.q | 
|  | & reg2hw.alert_test.fatal_fault_err.qe,    // [1] | 
|  | reg2hw.alert_test.recov_operation_err.q | 
|  | & reg2hw.alert_test.recov_operation_err.qe // [0] | 
|  | }; | 
|  |  | 
|  | assign alerts = { | 
|  | alert_fatal,           // Alerts[1] | 
|  | alert_recov_operation  // Alerts[0] | 
|  | }; | 
|  |  | 
|  | assign alert_recov_operation = shadowed_update_err; | 
|  |  | 
|  | // The recoverable alert is observable via status register until the KMAC operation is restarted | 
|  | // by re-writing the Control Register. | 
|  | logic status_alert_recov_ctrl_update_err; | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | status_alert_recov_ctrl_update_err <= 1'b 0; | 
|  | end else if (alert_recov_operation) begin | 
|  | status_alert_recov_ctrl_update_err <= 1'b 1; | 
|  | end else if (err_processed) begin | 
|  | status_alert_recov_ctrl_update_err <= 1'b 0; | 
|  | end | 
|  | end | 
|  |  | 
|  | assign hw2reg.status.alert_recov_ctrl_update_err.d  = status_alert_recov_ctrl_update_err; | 
|  |  | 
|  | assign alert_fatal = shadowed_storage_err | 
|  | | alert_intg_err | 
|  | | sparse_fsm_error | 
|  | | counter_error | 
|  | | control_integrity_error | 
|  | ; | 
|  |  | 
|  | // Make the fatal alert observable via status register. | 
|  | // Cannot be reset except the hardware reset | 
|  | logic status_alert_fatal_fault; | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | status_alert_fatal_fault <= 1'b 0; | 
|  | end else if (alert_fatal) begin | 
|  | status_alert_fatal_fault <= 1'b 1; | 
|  | end | 
|  | end | 
|  | assign hw2reg.status.alert_fatal_fault.d  = status_alert_fatal_fault; | 
|  |  | 
|  | for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx | 
|  | prim_alert_sender #( | 
|  | .AsyncOn(AlertAsyncOn[i]), | 
|  | .IsFatal(i) | 
|  | ) u_prim_alert_sender ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .alert_test_i  ( alert_test[i] ), | 
|  | .alert_req_i   ( alerts[i]     ), | 
|  | .alert_ack_o   (               ), | 
|  | .alert_state_o (               ), | 
|  | .alert_rx_i    ( alert_rx_i[i] ), | 
|  | .alert_tx_o    ( alert_tx_o[i] ) | 
|  | ); | 
|  | end | 
|  |  | 
|  | // Below assumes NumAlerts == 2 | 
|  | `ASSERT_INIT(NumAlerts2_A, NumAlerts == 2) | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | // break up the combinatorial path for local escalation | 
|  | if (!rst_ni) begin | 
|  | alerts_q[1] <= 1'b0; | 
|  | end else if (alerts[1]) begin | 
|  | // fatal alerts cannot be cleared | 
|  | alerts_q[1] <= 1'b1; | 
|  | end | 
|  | end | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | // break up the combinatorial path for local escalation | 
|  | if (!rst_ni) begin | 
|  | alerts_q[0] <= 1'b0; | 
|  | end else begin | 
|  | // recoverable alerts can be cleared so just latch the value | 
|  | alerts_q[0] <= alerts[0]; | 
|  | end | 
|  | end | 
|  |  | 
|  | // Latched recoverable alert[0] is not used. Rather removing above, | 
|  | // keep alert_q[1:0] and make alert_q[0] unused (lint waive). | 
|  | logic unused_alerts_q0; | 
|  | assign unused_alerts_q0 = alerts_q[0]; | 
|  |  | 
|  | // SEC_CM: LC_ESCALATE_EN.INTERSIG.MUBI, FSM.GLOBAL_ESC, FSM.LOCAL_ESC | 
|  | lc_ctrl_pkg::lc_tx_t alert_to_lc_tx; | 
|  | assign alert_to_lc_tx = lc_ctrl_pkg::lc_tx_bool_to_lc_tx(alerts_q[1]); | 
|  | for (genvar i = 0; i < NumLcSyncCopies; i++) begin : gen_or_alert_lc_sync | 
|  | assign lc_escalate_en[i] = lc_ctrl_pkg::lc_tx_or_hi(alert_to_lc_tx, lc_escalate_en_sync[i]); | 
|  | end | 
|  |  | 
|  | // Synchronize life cycle input | 
|  | prim_lc_sync #( | 
|  | .NumCopies (NumLcSyncCopies) | 
|  | ) u_prim_lc_sync ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .lc_en_i ( lc_escalate_en_i    ), | 
|  | .lc_en_o ( lc_escalate_en_sync ) | 
|  | ); | 
|  |  | 
|  | assign en_masking_o = EnMasking; | 
|  |  | 
|  | //////////////// | 
|  | // Assertions // | 
|  | //////////////// | 
|  |  | 
|  | // Assert known for output values | 
|  | `ASSERT_KNOWN(KmacDone_A, intr_kmac_done_o) | 
|  | `ASSERT_KNOWN(FifoEmpty_A, intr_fifo_empty_o) | 
|  | `ASSERT_KNOWN(KmacErr_A, intr_kmac_err_o) | 
|  | `ASSERT_KNOWN(TlODValidKnown_A, tl_o.d_valid) | 
|  | `ASSERT_KNOWN(TlOAReadyKnown_A, tl_o.a_ready) | 
|  | `ASSERT_KNOWN(AlertKnownO_A, alert_tx_o) | 
|  | `ASSERT_KNOWN(EnMaskingKnown_A, en_masking_o) | 
|  |  | 
|  | // Parameter as desired | 
|  | `ASSERT_INIT(SecretKeyDivideBy32_A, (kmac_pkg::MaxKeyLen % 32) == 0) | 
|  |  | 
|  | // Command input should be sparse | 
|  | `ASSUME(CmdSparse_M, reg2hw.cmd.cmd.qe |-> reg2hw.cmd.cmd.q inside {CmdStart, CmdProcess, | 
|  | CmdManualRun,CmdDone, CmdNone}) | 
|  |  | 
|  | // redundant counter error | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(SentMsgCountCheck_A, u_sha3.u_pad.u_sentmsg_count, | 
|  | alert_tx_o[1]) | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(RoundCountCheck_A, u_sha3.u_keccak.u_round_count, | 
|  | alert_tx_o[1]) | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(KeyIndexCountCheck_A, u_kmac_core.u_key_index_count, | 
|  | alert_tx_o[1]) | 
|  |  | 
|  | // Sparse FSM state error | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(KmacCoreFsmCheck_A, u_kmac_core.u_state_regs, alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(KmacAppFsmCheck_A, u_app_intf.u_state_regs, alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(SHA3FsmCheck_A, u_sha3.u_state_regs, alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(SHA3padFsmCheck_A, u_sha3.u_pad.u_state_regs, alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(KeccackFsmCheck_A, u_sha3.u_keccak.u_state_regs, | 
|  | alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(ErrorCheckFsmCheck_A, u_errchk.u_state_regs, alert_tx_o[1]) | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(KmacFsmCheck_A, u_state_regs, alert_tx_o[1]) | 
|  |  | 
|  | // prim is only instantiated if masking is enabled | 
|  | if (EnMasking == 1) begin : g_testassertion | 
|  | `ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(EntropyFsmCheck_A, gen_entropy.u_entropy.u_state_regs, | 
|  | alert_tx_o[1]) | 
|  |  | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(HashCountCheck_A, gen_entropy.u_entropy.u_hash_count, | 
|  | alert_tx_o[1]) | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT(SeedIdxCountCheck_A, | 
|  | gen_entropy.u_entropy.u_seed_idx_count, | 
|  | alert_tx_o[1]) | 
|  |  | 
|  | // MsgFifo.Packer | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT( | 
|  | PackerCountCheck_A, | 
|  | u_msgfifo.u_packer.g_pos_dupcnt.u_pos, | 
|  | alert_tx_o[1] | 
|  | ) | 
|  |  | 
|  | // MsgFifo.Fifo | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT( | 
|  | MsgFifoWptrCheck_A, | 
|  | u_msgfifo.u_msgfifo.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_wptr, | 
|  | alert_tx_o[1] | 
|  | ) | 
|  | `ASSERT_PRIM_COUNT_ERROR_TRIGGER_ALERT( | 
|  | MsgFifoRptrCheck_A, | 
|  | u_msgfifo.u_msgfifo.gen_normal_fifo.u_fifo_cnt.gen_secure_ptrs.u_rptr, | 
|  | alert_tx_o[1] | 
|  | ) | 
|  | end | 
|  |  | 
|  | // Alert assertions for reg_we onehot check | 
|  | `ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, u_reg, alert_tx_o[1]) | 
|  | endmodule |