diff --git a/.github/scripts/license_header_check.sh b/.github/scripts/license_header_check.sh index 758834b43..f4bb47405 100755 --- a/.github/scripts/license_header_check.sh +++ b/.github/scripts/license_header_check.sh @@ -78,7 +78,7 @@ exclude_dir='{uvmf*,.git,cmark,caliptra_reg_html,caliptra_top_reg_html,sha256,sh exclude_suffix='*.{tcl,txt,js,htm,html,json,vf,yml,woff,rsp,rdl,bashrc,waiver,cfg,hex,rc,exe,pdf,png,hvp,svg,log}' exclude_regs='*_reg*.{sv,rdl}' exclude_csr='*_csr*.*' -exclude_file='{sglint_waivers,pr_hash,pr_timestamp,.git,.git-comodules,.gitignore,.gitmodules,spyglass_lint.policy,ascent.ctl,clp_mapfile,readme.md,README.md,SECURITY.md,c_sample.c,test_dilithium5,riscv_rev_info,caliptra_tlul_rev_info}' +exclude_file='{sglint_waivers,pr_hash,pr_timestamp,.git,.git-comodules,.gitignore,.gitmodules,spyglass_lint.policy,ascent.ctl,clp_mapfile,readme.md,README.md,SECURITY.md,c_sample.c,test_dilithium5,riscv_rev_info,caliptra_tlul_rev_info,aes_rev_info}' apache_patn='Licensed under the Apache License\|Apache License, Version 2\.0 (the \"License\")' # Recursive find through repository with some major exclusions diff --git a/.github/workflow_metadata/pr_hash b/.github/workflow_metadata/pr_hash index a2d84f442..49d617218 100644 --- a/.github/workflow_metadata/pr_hash +++ b/.github/workflow_metadata/pr_hash @@ -1 +1 @@ -d7522950cee3a6338bddc70db37d2b53d681a16dbab5417c5fede4b899c45ab3998379b3268b2e217f5da423f8c7493c \ No newline at end of file +1cad8694bd690a699ed8a95772494825b142b6cb12db11fa682a9c71e0865c474b066e6f3c1abe35ce52b03edbac73c1 \ No newline at end of file diff --git a/.github/workflow_metadata/pr_timestamp b/.github/workflow_metadata/pr_timestamp index fff69cc13..668c459c4 100644 --- a/.github/workflow_metadata/pr_timestamp +++ b/.github/workflow_metadata/pr_timestamp @@ -1 +1 @@ -1734561364 \ No newline at end of file +1734735334 \ No newline at end of file diff --git a/docs/CaliptraHardwareSpecification.md b/docs/CaliptraHardwareSpecification.md index 6a1d12843..c907ec947 100644 --- a/docs/CaliptraHardwareSpecification.md +++ b/docs/CaliptraHardwareSpecification.md @@ -111,6 +111,7 @@ The following table shows the memory map address ranges for each of the IP block | SHA512 | 6 | 32 KiB | 0x1002_0000 | 0x1002_7FFF | | SHA256 | 10 | 32 KiB | 0x1002_8000 | 0x1002_FFFF | | ML-DSA | 14 | 64 KiB | 0x1003_0000 | 0x1003_FFFF | +| AES | 15 | 4 KiB | 0x1001_1000 | 0x1001_1FFF | #### Peripherals subsystem @@ -1060,7 +1061,7 @@ The ECC architecture inputs and outputs are described in the following table. | r\[383:0\] | output | The signature value of the given priveKey/message. | | s\[383:0\] | output | The signature value of the given priveKey/message. | | r’\[383:0\] | Output | The signature verification result. | -| DH_sharedkey\[383:0\] | output | The generated shared key in the ECDH sharedkey operation. | +| DH_sharedkey\[383:0\] | output | The generated shared key in the ECDH sharedkey operation. | | valid | output | When HIGH, the signal indicates the result is ready. | ### Address map @@ -1312,6 +1313,52 @@ Please refer to the [Adams-bridge specification](https://github.com/chipsallianc ### Address map Address map of ML-DSA accelerator is shown here: [ML-DSA\_reg — clp Reference (chipsalliance.github.io)](https://chipsalliance.github.io/caliptra-rtl/main/internal-regs/?p=clp.mldsa_reg) +## AES + +The AES unit is a cryptographic accelerator that processes requests from the processor to encrypt or decrypt 16-byte data blocks. It supports AES-128/192/256 in various modes, including Electronic Codebook (ECB), Cipher Block Chaining (CBC), Cipher Feedback (CFB) with a fixed segment size of 128 bits (CFB-128), Output Feedback (OFB), Counter (CTR), and Galois/Counter Mode (GCM). + +The AES unit is reused from here, (see [aes](https://github.com/lowRISC/opentitan/tree/master/hw/ip/aes) with a shim to translate from AHB-lite to the tl-ul interface. + +Additional registers have been added to support key vault integration. Keys from the key vault can be loaded into the AES unit to be used for encryption or decryption. + +### Operation + +For more information, see the [AES Programmer's Guide](https://opentitan.org/book/hw/ip/aes/doc/programmers_guide.html). + +### Signal descriptions + +The AES architecture inputs and outputs are described in the following table. + +| Name | Input or output | Description | +| :--------------------------------- | :-------------- | :----------- | +| clk | input | All signal timings are related to the rising edge of clk. | +| reset_n | input | The reset signal is active LOW and resets the core. This is the only active LOW signal. | +| DATA_IN | input | Input block to be encrypted or decrypted. Written in four 32-bit registers. | +| DATA_OUT | output | Output block result of encryption or decryption. Stored in four 32-bit registers. | +| CTRL_SHADOWED.MANUAL_OPERATION | input | Configures the AES core to operation in manual mode. | +| CTRL_SHADOWED.PRNG_RESEED_RATE | input | Configures the rate of reseeding the internal PRNG used for masking. | +| CTRL_SHADOWED.SIDELOAD | input | When asserted, AES core will use the key from the keyvault interface. | +| CTRL_SHADOWED.KEY_LEN | input | Configures the AES key length. Supports 128, 192, and 256-bit keys. | +| CTRL_SHADOWED.MODE | input | Configures the AES block cipher mode. | +| CTRL_SHADOWED.OPERATION | input | Configures the AES core to operate in encryption or decryption modes. | +| TRIGGER.PRNG_RESEED | input | Forces a PRNG reseed. | +| TRIGGER.DATA_OUT_CLEAR | input | Clears the DATA_OUT registers with pseudo-random data. | +| TRIGGER.KEY_IV_DATA_IN_CLEAR | input | Clears the Key, IV, and DATA_INT registers with pseudo-random data. | +| TRIGGER.START | input | Triggers the encryption/decryption of one data block if in manual operation mode. | +| STATUS.ALERT_FATAL_FAULT | output | A fatal fault has ocurred and the AES unit needs to be reset. | +| STATUS.ALERT_RECOV_CTRL_UPDATE_ERR | output | An update error has occurred in the shadowed Control Register.
+ AES operation needs to be restarted by re-writing the Control Register. | +| STATUS.INPUT_READY | output | The AES unit is ready to receive new data input via the DATA_IN registers. | +| STATUS.OUTPUT_VALID | output | The AES unit has alid output data. | +| STATUS.OUTPUT_LOST | output | All previous output data has been fully read by the processor (0) or at least one previous output data block has been lost (1). It has been overwritten by the AES unit before the processor could fully read it. Once set to 1, this flag remains set until AES operation is restarted by re-writing the Control Register. The primary use of this flag is for design verification. This flag is not meaningful if MANUAL_OPERATION=0. | +| STATUS.STALL | output | The AES unit is stalled because there is previous output data that must be read by the processor before the AES unit can overwrite this data. This flag is not meaningful if MANUAL_OPERATION=1. | +| STATUS.IDLE | output | The AES unit is idle. | + + +### Address map + +The AES address map is shown here: [aes\_clp\_reg — clp Reference (chipsalliance.github.io)](https://chipsalliance.github.io/caliptra-rtl/main/internal-regs/?p=clp.aes_clp_reg). + ## PCR vault * Platform Configuration Register (PCR) vault is a register file that stores measurements to be used by the microcontroller. diff --git a/src/aes/config/aes.vf b/src/aes/config/aes.vf index 26a2ec732..41f31e711 100644 --- a/src/aes/config/aes.vf +++ b/src/aes/config/aes.vf @@ -1,11 +1,12 @@ +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl ++incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl +incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl -+incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_ack_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_reg_pkg.sv @@ -23,6 +24,8 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -30,11 +33,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -69,9 +73,28 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -89,4 +112,25 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_shift_rows.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv -${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv \ No newline at end of file +${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv \ No newline at end of file diff --git a/src/aes/config/aes_pkg.vf b/src/aes/config/aes_pkg.vf index bba1db1d0..5a65c2c95 100644 --- a/src/aes/config/aes_pkg.vf +++ b/src/aes/config/aes_pkg.vf @@ -1,9 +1,9 @@ +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl ++incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl +incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl -+incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv @@ -23,6 +23,8 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -30,11 +32,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -69,6 +72,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv \ No newline at end of file diff --git a/src/aes/config/compile.yml b/src/aes/config/compile.yml index 445d407e6..1c60daea0 100644 --- a/src/aes/config/compile.yml +++ b/src/aes/config/compile.yml @@ -16,6 +16,7 @@ provides: [aes] schema_version: 2.4.0 requires: - aes_pkg + - caliptra_tlul_pkg targets: rtl: directories: [$COMPILE_ROOT/rtl] @@ -38,6 +39,27 @@ targets: - $COMPILE_ROOT/rtl/aes_cipher_control.sv - $COMPILE_ROOT/rtl/aes_prng_masking.sv - $COMPILE_ROOT/rtl/aes_key_expand.sv + - $COMPILE_ROOT/rtl/aes_control.sv + - $COMPILE_ROOT/rtl/aes_control_fsm.sv + - $COMPILE_ROOT/rtl/aes_control_fsm_n.sv + - $COMPILE_ROOT/rtl/aes_control_fsm_p.sv + - $COMPILE_ROOT/rtl/aes_core.sv + - $COMPILE_ROOT/rtl/aes_ctr.sv + - $COMPILE_ROOT/rtl/aes_ctr_fsm.sv + - $COMPILE_ROOT/rtl/aes_ctr_fsm_n.sv + - $COMPILE_ROOT/rtl/aes_ctr_fsm_p.sv + - $COMPILE_ROOT/rtl/aes_ctrl_gcm_reg_shadowed.sv + - $COMPILE_ROOT/rtl/aes_ctrl_reg_shadowed.sv + - $COMPILE_ROOT/rtl/aes_ghash.sv + - $COMPILE_ROOT/rtl/aes_prng_clearing.sv + - $COMPILE_ROOT/rtl/aes_reduced_round.sv + - $COMPILE_ROOT/rtl/aes_reg_status.sv + - $COMPILE_ROOT/rtl/aes_reg_top.sv + - $COMPILE_ROOT/rtl/aes_wrap.sv + - $COMPILE_ROOT/rtl/aes.sv + - $COMPILE_ROOT/rtl/aes_clp_reg_pkg.sv + - $COMPILE_ROOT/rtl/aes_clp_reg.sv + - $COMPILE_ROOT/rtl/aes_clp_wrapper.sv tops: [aes_cipher_core] rtl_lint: directories: [] diff --git a/src/aes/data/aes.rdl b/src/aes/data/aes.rdl new file mode 100644 index 000000000..a49e903de --- /dev/null +++ b/src/aes/data/aes.rdl @@ -0,0 +1,308 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +addrmap aes { + reg { + field { + sw = w; + onwrite = woclr; + desc = "Initial Key Registers Share 0. + + The actual initial key corresponds to Initial Key Registers + Share 0 XORed with Initial Key Registers Share 1. Loaded into + the internal Full Key register upon starting + encryption/decryption of the next block. All key registers + (Share 0 and Share 1) must be written at least once when the + key is changed, regardless of key length (write random data + for unused bits). The order in which the registers are + updated does not matter. Can only be updated when the AES + unit is idle. If the AES unit is non-idle, writes to these + registers are ignored. + Upon reset, these registers are cleared with pseudo-random data."; + } KEY_SHARE0[31:0]; + } KEY_SHARE0[8] @ 0x04; + reg { + field { + sw = w; + onwrite = woclr; + desc = "Initial Key Registers Share 1. + + The actual initial key corresponds to Initial Key Registers + Share 0 XORed with Initial Key Registers Share 1. Loaded into + the internal Full Key register upon starting + encryption/decryption of the next block. All key registers + (Share 0 and Share 1) must be written at least once when the + key is changed, regardless of key length (write random data + for unused bits). The order in which the registers are + updated does not matter. Can only be updated when the AES + unit is idle. If the AES unit is non-idle, writes to these + registers are ignored. Upon reset, these registers are + cleared with pseudo-random data."; + } KEY_SHARE1[31:0]; + } KEY_SHARE1[8] @ 0x24; + reg { + field { + sw = rw; + onwrite = woclr; + desc = "Initialization Vector Registers. + + The initialization vector (IV) or initial counter value must + be written to these registers when starting a new message in + CBC or CTR mode (see Control Register), respectively. In CBC + and CTR modes, the AES unit does not start + encryption/decryption with a partially updated IV. Each + register has to be written at least once. The order in which + the registers are written does not matter. If the AES unit is + non-idle, writes to these registers are ignored. Whenever + starting a new message, the corresponding IV value must be + provided by the processor. Once started, the AES unit + automatically updates the contents of these registers. In ECB + mode, the IV registers are not used and do not need to be + configured. Upon reset, these registers are cleared with + pseudo-random data."; + } IV[31:0]; + } IV[4] @ 0x44; + reg { + field { + sw = w; + onwrite = woclr; + desc = "Input Data Registers. + + If MANUAL_OPERATION=0 (see Control Register), the AES unit + automatically starts encryption/decryption after all Input + Data registers have been written. Each register has to be + written at least once. The order in which the registers are + written does not matter. Loaded into the internal State + register upon starting encryption/decryption of the next + block. After that, the processor can update the Input Data + registers (See INPUT_READY field of Status Register). Upon + reset, these registers are cleared with pseudo-random data."; + } DATA_IN[31:0]; + } DATA_IN[4] @ 0x54; + reg { + field { + sw = r; + desc = "Output Data Register. + + Holds the output data produced by the AES unit during the last + encryption/decryption operation. If MANUAL_OPERATION=0 (see + Control Register), the AES unit is stalled when the previous + output data has not yet been read and is about to be + overwritten. Each register has to be read at least once. The + order in which the registers are read does not matter. Upon + reset, these registers are cleared with pseudo-random data."; + } DATA_OUT[31:0]; + } DATA_OUT[4] @ 0x64; + reg { + field { + sw = rw; + onwrite = woclr; + desc = "2-bit one-hot field to select the operation of AES + unit. Invalid input values, i.e., values with multiple + bits set and value 2'b00, are mapped to AES_ENC (2'b01)."; + } OPERATION[1:0]; + field { + sw = rw; + onwrite = woclr; + desc = "6-bit one-hot field to select AES block cipher + mode. Invalid input values, i.e., values with multiple + bits set and value 6'b00_0000, are mapped to AES_NONE + (6'b11_1111)."; + } MODE[7:2]; + field { + sw = rw; + onwrite = woclr; + desc = "3-bit one-hot field to select AES key length. + Invalid input values, i.e., values with multiple bits set, + value 3'b000, and value 3'b010 in case 192-bit keys are + not supported (because disabled at compile time) are + mapped to AES_256 (3'b100)."; + } KEY_LEN[10:8]; + field { + sw = rw; + onwrite = woclr; + desc = "Controls whether the AES unit uses the key + provided by the key manager via key sideload interface (1) + or the key provided by software via Initial Key Registers + KEY_SHARE1_0 - KEY_SHARE1_7 (0)."; + } SIDELOAD[11:11]; + field { + sw = rw; + onwrite = woclr; + desc = "3-bit one-hot field to control the reseeding rate + of the internal pseudo-random number generator (PRNG) used + for masking. Invalid input values, i.e., values with + multiple bits set and value 3'b000 are mapped to the + highest reseeding rate PER_1 (3'b001)."; + } PRNG_RESEED_RATE[14:12]; + field { + sw = rw; + onwrite = woclr; + desc = "Controls whether the AES unit is operated in + normal/automatic mode (0) or fully manual mode (1). In + automatic mode (0), the AES unit automatically i) starts + to encrypt/decrypt when it receives new input data, and + ii) stalls during the last encryption/decryption cycle if + the previous output data has not yet been read. This is + the most efficient mode to operate in. Note that the + corresponding status tracking is automatically cleared + upon a write to the Control Register. In manual mode (1), + the AES unit i) only starts to encrypt/decrypt after + receiving a start trigger (see Trigger Register), and ii) + overwrites previous output data irrespective of whether it + has been read out or not. This mode is useful if software needs full + control over the AES unit."; + } MANUAL_OPERATION[15:15]; + } CTRL_SHADOWED @ 0x74; + reg { + field { + sw = rw; + onwrite = woclr; + desc = "Controls whether providing a new key triggers the reseeding + of internal pseudo-random number generators used for clearing and + masking (1) or not (0)."; + } KEY_TOUCH_FORCES_RESEED[0:0]; + field { + sw = rw; + onwrite = woclr; + desc = "Allow the internal masking PRNG to advance (0) or + force its internal state (1) leading to constant masks. + Setting all masks to constant value can be useful when + performing SCA. To completely disable the masking, the + second key share (KEY_SHARE1_0 - KEY_SHARE1_7) must be + zero as well. In addition, a special seed needs to be + loaded into the masking PRNG using the EDN interface. + Only applicable if both the Masking parameter and the + SecAllowForcingMasks parameter are set to one."; + } FORCE_MASKS[1:1]; + } CTRL_AUX_SHADOWED @ 0x78; + reg { + field { + sw = rw; + onwrite = woclr; + desc = "Auxiliary Control Register configuration enable + bit. If this is cleared to 0, the Auxiliary Control + Register cannot be written anymore."; + } CTRL_AUX_REGWEN[0:0]; + } CTRL_AUX_REGWEN @ 0x7c; + reg { + field { + sw = w; + onwrite = woclr; + desc = "Keep AES unit paused (0) or trigger the + encryption/decryption of one data block (1). This trigger + is cleared to `0` if MANUAL_OPERATION=0 or if MODE=AES_NONE + (see Control Register)."; + } START[0:0]; + field { + sw = w; + onwrite = woclr; + desc = "Keep current values in Initial Key, internal Full + Key and Decryption Key registers, IV registers and Input + Data registers (0) or clear all those registers with + pseudo-random data (1)."; + } KEY_IV_DATA_IN_CLEAR[1:1]; + field { + sw = w; + onwrite = woclr; + desc = "Keep current values in Output Data registers (0) or + clear those registers with pseudo-random data (1)."; + } DATA_OUT_CLEAR[2:2]; + field { + sw = w; + onwrite = woclr; + desc = "Keep continuing with the current states of the + internal pseudo-random number generators used for register + clearing and masking (0) or perform a reseed of the internal + states from the connected entropy source (1). If the + KEY_TOUCH_FORCES_RESEED bit in the Auxiliary Control + Register is set to one, this trigger will automatically get + set after providing a new initial key."; + } PRNG_RESEED[3:3]; + } TRIGGER @ 0x80; + reg { + field { + sw = r; + desc = "The AES unit is idle (1) or busy (0). This flag + is `0` if one of the following operations is currently + running: i) encryption/decryption, ii) register clearing or + iii) PRNG reseeding. This flag is also `0` if an + encryption/decryption is running but the AES unit is + stalled."; + } IDLE[0:0]; + field { + sw = r; + desc = "The AES unit is not stalled (0) or stalled (1) + because there is previous output data that must be read by + the processor before the AES unit can overwrite this data. + This flag is not meaningful if MANUAL_OPERATION=1 (see + Control Register)."; + } STALL[1:1]; + field { + sw = r; + desc = "All previous output data has been fully read by + the processor (0) or at least one previous output data block + has been lost (1). It has been overwritten by the AES unit + before the processor could fully read it. Once set to `1`, + this flag remains set until AES operation is restarted by + re-writing the Control Register. The primary use of this + flag is for design verification. This flag is not + meaningful if MANUAL_OPERATION=0 (see Control Register)."; + } OUTPUT_LOST[2:2]; + field { + sw = r; + desc = "The AES unit has no valid output (0) or has valid output data (1)."; + } OUTPUT_VALID[3:3]; + field { + sw = r; + desc = "The AES unit is ready (1) or not ready (0) to + receive new data input via the DATA_IN registers. If the + present values in the DATA_IN registers have not yet been + loaded into the module this flag is `0` (not ready)."; + } INPUT_READY[4:4]; + field { + sw = r; + desc = "An update error has not occurred (0) or has + occurred (1) in the shadowed Control Register. AES + operation needs to be restarted by re-writing the Control + Register."; + } ALERT_RECOV_CTRL_UPDATE_ERR[5:5]; + field { + sw = r; + desc = "No fatal fault has occurred inside the AES unit + (0). A fatal fault has occurred and the AES unit needs to + be reset (1). Examples for fatal faults include i) storage + errors in the Control Register, ii) if any internal FSM + enters an invalid state, iii) if any sparsely encoded signal + takes on an invalid value, iv) errors in the internal round + counter, v) escalations triggered by the life cycle + controller, and vi) fatal integrity failures on the TL-UL bus."; + } ALERT_FATAL_FAULT[6:6]; + } STATUS @ 0x84; + reg { + field { + sw = rw; + onwrite = woclr; + desc = "6-bit one-hot field to select the phase of the + Galois/Counter Mode (GCM) of operation. Invalid input + values, i.e., values with multiple bits set and value + 6'b00_0000, are mapped to GCM_INIT (6'b00_0001). In case + support for GCM has been disabled at compile time, this + field is not writable and always reads as GCM_INIT + (6'b00_0001)."; + } PHASE[5:0]; + field { + sw = rw; + onwrite = woclr; + desc = "Number of valid bytes of the current input block. + Only the last block in the GCM_AAD and GCM_TEXT phases are + expected to have not all bytes marked as valid. For all + other blocks, the number of valid bytes should be set to 16. + Invalid input values, i.e., the value 5'b0_0000, and all + other values different from 5'b1_0000 in case GCM is not + supported (because disabled at compile time) are mapped to + 5'b1_0000."; + } NUM_VALID_BYTES[10:6]; + } CTRL_GCM_SHADOWED @ 0x88; + }; diff --git a/src/aes/rtl/aes.sv b/src/aes/rtl/aes.sv new file mode 100644 index 000000000..bacfebaee --- /dev/null +++ b/src/aes/rtl/aes.sv @@ -0,0 +1,307 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES top-level wrapper + +`include "caliptra_prim_assert.sv" + +module aes + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AES192Enable = 1, // Can be 0 (disable), or 1 (enable). + parameter bit AESGCMEnable = 1, // Can be 0 (disable), or 1 (enable). + parameter bit SecMasking = 1, // Can be 0 (no masking), or + // 1 (first-order masking) of the cipher + // core. Masking requires the use of a + // masked S-Box, see SecSBoxImpl parameter. + parameter sbox_impl_e SecSBoxImpl = SBoxImplDom, // See aes_pkg.sv + parameter int unsigned SecStartTriggerDelay = 0, // Manual start trigger delay, useful for + // SCA measurements. A value of e.g. 40 + // allows the processor to go into sleep + // before AES starts operation. + parameter bit SecAllowForcingMasks = 0, // Allow forcing masks to constant values using + // FORCE_MASKS bit in Auxiliary Control + // Register. Useful for SCA only. + parameter bit SecSkipPRNGReseeding = 0, // The current SCA setup doesn't provide enough + // resources to implement the infrastucture + // required for PRNG reseeding (CSRNG, EDN). + // To enable SCA resistance evaluations, we + // need to skip reseeding requests. + // Useful for SCA only. + parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}}, + parameter clearing_lfsr_seed_t RndCnstClearingLfsrSeed = RndCnstClearingLfsrSeedDefault, + parameter clearing_lfsr_perm_t RndCnstClearingLfsrPerm = RndCnstClearingLfsrPermDefault, + parameter clearing_lfsr_perm_t RndCnstClearingSharePerm = RndCnstClearingSharePermDefault, + parameter masking_lfsr_seed_t RndCnstMaskingLfsrSeed = RndCnstMaskingLfsrSeedDefault, + parameter masking_lfsr_perm_t RndCnstMaskingLfsrPerm = RndCnstMaskingLfsrPermDefault +) ( + input logic clk_i, + input logic rst_ni, + input logic rst_shadowed_ni, + + // Idle indicator for clock manager + output caliptra_prim_mubi_pkg::mubi4_t idle_o, + + // Life cycle + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + + // Entropy distribution network (EDN) interface + input logic clk_edn_i, + input logic rst_edn_ni, + output edn_pkg::edn_req_t edn_o, + input edn_pkg::edn_rsp_t edn_i, + + // Key manager (keymgr) key sideload interface + input keymgr_pkg::hw_key_req_t keymgr_key_i, + + // Bus interface + input caliptra_tlul_pkg::tl_h2d_t tl_i, + output caliptra_tlul_pkg::tl_d2h_t tl_o, + + // Alerts + input caliptra_prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx_i, + output caliptra_prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx_o +); + + localparam int unsigned EntropyWidth = edn_pkg::ENDPOINT_BUS_WIDTH; + + // Signals + aes_reg2hw_t reg2hw; + aes_hw2reg_t hw2reg; + + logic [NumAlerts-1:0] alert; + lc_ctrl_pkg::lc_tx_t lc_escalate_en; + + logic edn_req_int; + logic edn_req_hold_d, edn_req_hold_q; + logic edn_req; + logic edn_ack; + logic [EntropyWidth-1:0] edn_data; + logic unused_edn_fips; + logic entropy_clearing_req, entropy_masking_req; + logic entropy_clearing_ack, entropy_masking_ack; + + //////////// + // Inputs // + //////////// + + // SEC_CM: BUS.INTEGRITY + // SEC_CM: AUX.CONFIG.SHADOW + // SEC_CM: AUX.CONFIG.REGWEN + // SEC_CM: KEY.SW_UNREADABLE + // SEC_CM: DATA_REG.SW_UNREADABLE + // Register interface + logic intg_err_alert; + logic shadowed_storage_err, shadowed_update_err; + aes_reg_top u_reg ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .tl_i, + .tl_o, + .reg2hw, + .hw2reg, + .shadowed_storage_err_o(shadowed_storage_err), + .shadowed_update_err_o(shadowed_update_err), + .intg_err_o(intg_err_alert) + ); + + // SEC_CM: LC_ESCALATE_EN.INTERSIG.MUBI + // Synchronize life cycle input + caliptra_prim_lc_sync #( + .NumCopies (1) + ) u_caliptra_prim_lc_sync ( + .clk_i, + .rst_ni, + .lc_en_i ( lc_escalate_en_i ), + .lc_en_o ( {lc_escalate_en} ) + ); + + /////////////////// + // EDN Interface // + /////////////////// + + // Internally, we have up to two PRNGs that share the EDN interface for reseeding. Here, we just + // arbitrate the requests. Upsizing of the entropy to the correct width is performed inside the + // PRNGs. + // Reseed operations for the clearing PRNG are initiated by software. Reseed operations for the + // masking PRNG can also be automatically initiated. + assign edn_req_int = entropy_clearing_req | entropy_masking_req; + // Only forward ACK to PRNG currently requesting entropy. Give higher priority to clearing PRNG. + assign entropy_clearing_ack = entropy_clearing_req & edn_ack; + assign entropy_masking_ack = ~entropy_clearing_req & entropy_masking_req & edn_ack; + + // Upon escalation or detection of a fatal alert, an EDN request signal can be dropped before + // getting acknowledged. This is okay with respect to AES as the module will need to be reset + // anyway. However, to not leave EDN in a strange state, we hold the request until it's actually + // acknowledged. + assign edn_req = edn_req_int | edn_req_hold_q; + assign edn_req_hold_d = (edn_req_hold_q | edn_req) & ~edn_ack; + always_ff @(posedge clk_i or negedge rst_ni) begin : edn_req_reg + if (!rst_ni) begin + edn_req_hold_q <= '0; + end else begin + edn_req_hold_q <= edn_req_hold_d; + end + end + + // Synchronize EDN interface + caliptra_prim_sync_reqack_data #( + .Width(EntropyWidth), + .DataSrc2Dst(1'b0), + .DataReg(1'b0) + ) u_caliptra_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 ( 1'b1 ), + .src_req_i ( edn_req ), + .src_ack_o ( edn_ack ), + .dst_req_o ( edn_o.edn_req ), + .dst_ack_i ( edn_i.edn_ack ), + .data_i ( edn_i.edn_bus ), + .data_o ( edn_data ) + ); + // We don't track whether the entropy is pre-FIPS or not inside AES. + assign unused_edn_fips = edn_i.edn_fips; + + ////////// + // Core // + ////////// + + // AES core + aes_core #( + .AES192Enable ( AES192Enable ), + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ), + .SecSBoxImpl ( SecSBoxImpl ), + .SecStartTriggerDelay ( SecStartTriggerDelay ), + .SecAllowForcingMasks ( SecAllowForcingMasks ), + .SecSkipPRNGReseeding ( SecSkipPRNGReseeding ), + .EntropyWidth ( EntropyWidth ), + .RndCnstClearingLfsrSeed ( RndCnstClearingLfsrSeed ), + .RndCnstClearingLfsrPerm ( RndCnstClearingLfsrPerm ), + .RndCnstClearingSharePerm ( RndCnstClearingSharePerm ), + .RndCnstMaskingLfsrSeed ( RndCnstMaskingLfsrSeed ), + .RndCnstMaskingLfsrPerm ( RndCnstMaskingLfsrPerm ) + ) u_aes_core ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .rst_shadowed_ni ( rst_shadowed_ni ), + .entropy_clearing_req_o ( entropy_clearing_req ), + .entropy_clearing_ack_i ( entropy_clearing_ack ), + .entropy_clearing_i ( edn_data ), + .entropy_masking_req_o ( entropy_masking_req ), + .entropy_masking_ack_i ( entropy_masking_ack ), + .entropy_masking_i ( edn_data ), + + .keymgr_key_i ( keymgr_key_i ), + + .lc_escalate_en_i ( lc_escalate_en ), + + .shadowed_storage_err_i ( shadowed_storage_err ), + .shadowed_update_err_i ( shadowed_update_err ), + .intg_err_alert_i ( intg_err_alert ), + .alert_recov_o ( alert[0] ), + .alert_fatal_o ( alert[1] ), + + .reg2hw ( reg2hw ), + .hw2reg ( hw2reg ) + ); + + assign idle_o = caliptra_prim_mubi_pkg::mubi4_bool_to_mubi(reg2hw.status.idle.q); + + //////////// + // Alerts // + //////////// + + logic [NumAlerts-1:0] alert_test; + assign alert_test = { + reg2hw.alert_test.fatal_fault.q & + reg2hw.alert_test.fatal_fault.qe, + reg2hw.alert_test.recov_ctrl_update_err.q & + reg2hw.alert_test.recov_ctrl_update_err.qe + }; + + for (genvar i = 0; i < NumAlerts; i++) begin : gen_alert_tx + caliptra_prim_alert_sender #( + .AsyncOn(AlertAsyncOn[i]), + .IsFatal(i) + ) u_caliptra_prim_alert_sender ( + .clk_i, + .rst_ni, + .alert_test_i ( alert_test[i] ), + .alert_req_i ( alert[i] ), + .alert_ack_o ( ), + .alert_state_o ( ), + .alert_rx_i ( alert_rx_i[i] ), + .alert_tx_o ( alert_tx_o[i] ) + ); + end + + //////////////// + // Assertions // + //////////////// + + // All outputs should have a known value after reset + `CALIPTRA_ASSERT_KNOWN(TlODValidKnown, tl_o.d_valid) + `CALIPTRA_ASSERT_KNOWN(TlOAReadyKnown, tl_o.a_ready) + `CALIPTRA_ASSERT_KNOWN(IdleKnown, idle_o) + `CALIPTRA_ASSERT_KNOWN(EdnReqKnown, edn_o) + `CALIPTRA_ASSERT_KNOWN(AlertTxKnown, alert_tx_o) + + // Alert assertions for sparse FSMs. + for (genvar i = 0; i < Sp2VWidth; i++) begin : gen_control_fsm_svas + if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_control_fsm_svas_p + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesControlFsmCheck_A, + u_aes_core.u_aes_control.gen_fsm[i].gen_fsm_p. + u_aes_control_fsm_i.u_aes_control_fsm.u_state_regs, + alert_tx_o[1]) + end else begin : gen_control_fsm_svas_n + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesControlFsmCheck_A, + u_aes_core.u_aes_control.gen_fsm[i].gen_fsm_n. + u_aes_control_fsm_i.u_aes_control_fsm.u_state_regs, + alert_tx_o[1]) + end + end + + for (genvar i = 0; i < Sp2VWidth; i++) begin : gen_ctr_fsm_svas + if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_ctr_fsm_svas_p + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesCtrFsmCheck_A, + u_aes_core.u_aes_ctr.gen_fsm[i].gen_fsm_p. + u_aes_ctr_fsm_i.u_aes_ctr_fsm.u_state_regs, + alert_tx_o[1]) + end else begin : gen_ctr_fsm_svas_n + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesCtrFsmCheck_A, + u_aes_core.u_aes_ctr.gen_fsm[i].gen_fsm_n. + u_aes_ctr_fsm_i.u_aes_ctr_fsm.u_state_regs, + alert_tx_o[1]) + end + end + + for (genvar i = 0; i < Sp2VWidth; i++) begin : gen_cipher_control_fsm_svas + if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_cipher_control_fsm_svas_p + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesCipherControlFsmCheck_A, + u_aes_core.u_aes_cipher_core.u_aes_cipher_control.gen_fsm[i].gen_fsm_p. + u_aes_cipher_control_fsm_i.u_aes_cipher_control_fsm.u_state_regs, + alert_tx_o[1]) + end else begin : gen_cipher_control_fsm_svas_n + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesCipherControlFsmCheck_A, + u_aes_core.u_aes_cipher_core.u_aes_cipher_control.gen_fsm[i].gen_fsm_n. + u_aes_cipher_control_fsm_i.u_aes_cipher_control_fsm.u_state_regs, + alert_tx_o[1]) + end + end + + if (AESGCMEnable) begin : gen_ghash_fsm_sva + `CALIPTRA_ASSERT_PRIM_FSM_ERROR_TRIGGER_ALERT(AesGhashFsmCheck_A, + u_aes_core.gen_ghash.u_aes_ghash.u_state_regs, + alert_tx_o[1]) + end + + // Alert assertions for reg_we onehot check + `CALIPTRA_ASSERT_PRIM_REG_WE_ONEHOT_ERROR_TRIGGER_ALERT(RegWeOnehotCheck_A, u_reg, alert_tx_o[1]) +endmodule diff --git a/src/aes/rtl/aes_cipher_control.sv b/src/aes/rtl/aes_cipher_control.sv index 2ed922855..d8c9e9c60 100644 --- a/src/aes/rtl/aes_cipher_control.sv +++ b/src/aes/rtl/aes_cipher_control.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -8,12 +8,11 @@ `include "caliptra_prim_assert.sv" -module aes_cipher_control - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_cipher_control import aes_pkg::*; #( - parameter bit SecMasking = 0, - parameter sbox_impl_e SecSBoxImpl = SBoxImplDom + parameter bit CiphOpFwdOnly = 0, + parameter bit SecMasking = 0, + parameter sbox_impl_e SecSBoxImpl = SBoxImplDom ) ( input logic clk_i, input logic rst_ni, @@ -371,8 +370,8 @@ module aes_cipher_control end // Use separate signal for key expand operation, forward round. - assign key_expand_op_o = (dec_key_gen_d == SP2V_HIGH || - dec_key_gen_q == SP2V_HIGH) ? CIPH_FWD : op_i; + assign key_expand_op_o = (dec_key_gen_d == SP2V_HIGH || + dec_key_gen_q == SP2V_HIGH) || CiphOpFwdOnly ? CIPH_FWD : op_i; assign key_expand_round_o = rnd_ctr; // Let the main controller know whate we are doing. diff --git a/src/aes/rtl/aes_cipher_control_fsm.sv b/src/aes/rtl/aes_cipher_control_fsm.sv index 25ec2d837..6de2acbec 100644 --- a/src/aes/rtl/aes_cipher_control_fsm.sv +++ b/src/aes/rtl/aes_cipher_control_fsm.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -8,9 +8,7 @@ `include "caliptra_prim_assert.sv" -module aes_cipher_control_fsm - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_cipher_control_fsm import aes_pkg::*; #( parameter bit SecMasking = 0, parameter sbox_impl_e SecSBoxImpl = SBoxImplDom @@ -187,7 +185,7 @@ module aes_cipher_control_fsm // Make the masking PRNG advance. The current pseudo-random data is used to mask the // input data. - prng_update_o = dec_key_gen_i ? 1'b0 : SecMasking; + prng_update_o = SecMasking; // Init key expand key_expand_clear_o = 1'b1; @@ -234,11 +232,11 @@ module aes_cipher_control_fsm if (key_len_i != AES_256) begin // Advance in sync with KeyExpand. Based on the S-Box implementation, it can take // multiple cycles to finish. Wait for handshake. The DOM S-Boxes consume fresh PRD - // only in the first clock cycle. By requesting the PRNG update in any clock cycle - // other than the last one, the PRD fed into the DOM S-Boxes is guaranteed to be stable. - // This is better in terms of SCA resistance. Request the PRNG update in the first cycle. + // only in the first clock cycle and that PRD is taken from the buffer stage updated + // based on key_full_we_o. The PRNG itself is updated in every clock cycle to increase + // the noise. advance = key_expand_out_req_i & cyc_ctr_expr; - prng_update_o = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking; + prng_update_o = SecMasking; key_expand_en_o = 1'b1; if (advance) begin key_expand_out_ack_o = 1'b1; @@ -249,6 +247,7 @@ module aes_cipher_control_fsm aes_cipher_ctrl_ns = CIPHER_CTRL_ROUND; end end else begin + prng_update_o = SecMasking; state_we_o = ~dec_key_gen_q_i; rnd_ctr_d = rnd_ctr_q + 4'b0001; cyc_ctr_d = 3'd0; @@ -276,12 +275,11 @@ module aes_cipher_control_fsm // Advance in sync with SubBytes and KeyExpand. Based on the S-Box implementation, both can // take multiple cycles to finish. Wait for handshake. The DOM S-Boxes consume fresh PRD - // only in the first clock cycle. By requesting the PRNG update in any clock cycle other - // than the last one, the PRD fed into the DOM S-Boxes is guaranteed to be stable. This is - // better in terms of SCA resistance. Request the PRNG update in the first cycle. Non-DOM - // S-Boxes need fresh PRD in every clock cycle. + // only in the first clock cycle and that PRD is taken from the buffer stages updated + // with state_we_o / based on key_full_we_o. The PRNG itself is updated in every clock + // cycle to increase the noise. advance = key_expand_out_req_i & cyc_ctr_expr & (dec_key_gen_q_i | sub_bytes_out_req_i); - prng_update_o = (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : SecMasking; + prng_update_o = SecMasking; sub_bytes_en_o = ~dec_key_gen_q_i; key_expand_en_o = 1'b1; @@ -358,14 +356,14 @@ module aes_cipher_control_fsm cyc_ctr_d = (SecSBoxImpl == SBoxImplDom) ? (!advance ? cyc_ctr_q + 3'd1 : cyc_ctr_q) : 3'd0; - // The DOM S-Boxes consume fresh PRD only in the first clock cycle. By requesting the PRNG - // update in any clock cycle other than the last one, the PRD fed into the DOM S-Boxes is - // guaranteed to be stable. This is better in terms of SCA resistance. Request the PRNG - // update in the first cycle. We update it only once and in the last cycle for non-DOM - // S-Boxes where otherwise updating the PRNG while being stalled would cause the S-Boxes - // to be re-evaluated, thereby creating additional SCA leakage. + // The DOM S-Boxes consume fresh PRD only in the first clock cycle and that PRD is taken + // from the buffer stages updated with state_we_o / based on key_full_we_o. The PRNG itself + // is updated in every but the last processing clock cycle to increase the noise. Once the + // processing is all done (e.g. if we're just waiting for the PRNG reseeding to finish or + // if we're waiting for out_ready_i), the PRNG is no longer updated to save power. In the + // very last clock cycle, we update the PRNG again to get ready for the next block. prng_update_o = - (SecSBoxImpl == SBoxImplDom) ? cyc_ctr_q == 3'd0 : out_valid_o & out_ready_i; + ((SecSBoxImpl == SBoxImplDom) ? !advance : 1'b0) | (out_valid_o & out_ready_i); if (out_valid_o && out_ready_i) begin sub_bytes_out_ack_o = ~dec_key_gen_q_i; @@ -386,6 +384,9 @@ module aes_cipher_control_fsm // Keep requesting PRNG reseeding until it is acknowledged. prng_reseed_req_o = prng_reseed_q_i & ~prng_reseed_done_q; + // Don't update the cycle counter as we don't need it. + cyc_ctr_d = 3'd0; + // Once we're done, wait for handshake. out_valid_o = prng_reseed_done_q; if (out_valid_o && out_ready_i) begin diff --git a/src/aes/rtl/aes_cipher_control_fsm_n.sv b/src/aes/rtl/aes_cipher_control_fsm_n.sv index 4540e11a7..37e3378d7 100644 --- a/src/aes/rtl/aes_cipher_control_fsm_n.sv +++ b/src/aes/rtl/aes_cipher_control_fsm_n.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -11,9 +11,7 @@ // - inverting these signals between the regular FSM and the caliptra_prim_buf synthesis barriers. // Synthesis tools will then push the inverters into the actual FSM. -module aes_cipher_control_fsm_n - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_cipher_control_fsm_n import aes_pkg::*; #( parameter bit SecMasking = 0, parameter sbox_impl_e SecSBoxImpl = SBoxImplDom diff --git a/src/aes/rtl/aes_cipher_control_fsm_p.sv b/src/aes/rtl/aes_cipher_control_fsm_p.sv index 37607f11f..35fe4b2a9 100644 --- a/src/aes/rtl/aes_cipher_control_fsm_p.sv +++ b/src/aes/rtl/aes_cipher_control_fsm_p.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -7,9 +7,7 @@ // This module contains the AES cipher core control FSM operating on // and producing the positive values of important control signals. -module aes_cipher_control_fsm_p - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_cipher_control_fsm_p import aes_pkg::*; #( parameter bit SecMasking = 0, parameter sbox_impl_e SecSBoxImpl = SBoxImplDom diff --git a/src/aes/rtl/aes_cipher_core.sv b/src/aes/rtl/aes_cipher_core.sv index 6c2fe880f..e6a1fc4e2 100644 --- a/src/aes/rtl/aes_cipher_core.sv +++ b/src/aes/rtl/aes_cipher_core.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -92,11 +92,10 @@ `include "caliptra_prim_assert.sv" -module aes_cipher_core - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_cipher_core import aes_pkg::*; #( parameter bit AES192Enable = 1, + parameter bit CiphOpFwdOnly = 0, parameter bit SecMasking = 1, parameter sbox_impl_e SecSBoxImpl = SBoxImplDom, parameter bit SecAllowForcingMasks = 0, @@ -137,7 +136,8 @@ module aes_cipher_core output logic alert_o, // Pseudo-random data for register clearing - input logic [WidthPRDClearing-1:0] prd_clearing_i [NumShares], + input logic [3:0][3:0][7:0] prd_clearing_state_i [NumShares], + input logic [7:0][31:0] prd_clearing_key_i [NumShares], // Masking PRNG input logic force_masks_i, // Useful for SCA only. @@ -198,6 +198,7 @@ module aes_cipher_core logic [7:0][31:0] key_expand_out [NumShares]; ciph_op_e key_expand_op; sp2v_e key_expand_en; + logic key_expand_prd_we; sp2v_e key_expand_out_req; sp2v_e key_expand_out_ack; logic key_expand_err; @@ -221,27 +222,16 @@ module aes_cipher_core logic sp_enc_err_d, sp_enc_err_q; logic op_err; - // Pseudo-random data for clearing and masking purposes - logic [127:0] prd_clearing_128 [NumShares]; - logic [255:0] prd_clearing_256 [NumShares]; - + // Pseudo-random data for masking purposes logic [WidthPRDMasking-1:0] prd_masking; - logic [3:0][3:0][WidthPRDSBox-1:0] prd_sub_bytes; + logic [3:0][3:0][WidthPRDSBox-1:0] prd_sub_bytes_d; + logic [3:0][3:0][WidthPRDSBox-1:0] prd_sub_bytes_q; logic [WidthPRDKey-1:0] prd_key_expand; logic prd_masking_upd; logic prd_masking_rsd_req; logic prd_masking_rsd_ack; - // Generate clearing signals of appropriate widths. If masking is enabled, the two shares of - // the registers must be cleared with different pseudo-random data. - for (genvar s = 0; s < NumShares; s++) begin : gen_prd_clearing_shares - for (genvar c = 0; c < NumChunksPRDClearing128; c++) begin : gen_prd_clearing_128 - assign prd_clearing_128[s][c * WidthPRDClearing +: WidthPRDClearing] = prd_clearing_i[s]; - end - for (genvar c = 0; c < NumChunksPRDClearing256; c++) begin : gen_prd_clearing_256 - assign prd_clearing_256[s][c * WidthPRDClearing +: WidthPRDClearing] = prd_clearing_i[s]; - end - end + logic [3:0][3:0][7:0] data_in_mask; // op_i is one-hot encoded. Check the provided value and trigger an alert upon detecing invalid // encodings. @@ -258,8 +248,8 @@ module aes_cipher_core unique case (state_sel) STATE_INIT: state_d = state_init_i; STATE_ROUND: state_d = add_round_key_out; - STATE_CLEAR: state_d = prd_clearing_128; - default: state_d = prd_clearing_128; + STATE_CLEAR: state_d = prd_clearing_state_i; + default: state_d = prd_clearing_state_i; endcase end @@ -304,7 +294,6 @@ module aes_cipher_core // - the PRD required by the key expand module (has 4 S-Boxes internally). aes_prng_masking #( .Width ( WidthPRDMasking ), - .ChunkSize ( ChunkSizePRDMasking ), .EntropyWidth ( EntropyWidth ), .SecAllowForcingMasks ( SecAllowForcingMasks ), .SecSkipPRNGReseeding ( SecSkipPRNGReseeding ), @@ -327,21 +316,45 @@ module aes_cipher_core // Extract randomness for key expand module and SubBytes. // // The masking PRNG output has the following shape: - // prd_masking = { prd_key_expand, prd_sub_bytes } - assign prd_key_expand = prd_masking[WidthPRDMasking-1 -: WidthPRDKey]; - assign prd_sub_bytes = prd_masking[WidthPRDData-1 -: WidthPRDData]; + // prd_masking = { prd_key_expand, prd_sub_bytes_d } + assign prd_key_expand = prd_masking[WidthPRDMasking-1 -: WidthPRDKey]; + assign prd_sub_bytes_d = prd_masking[WidthPRDData-1 -: WidthPRDData]; + + // PRD buffering + if (!SecMasking) begin : gen_no_prd_buffer + // The masks are ignored anyway. + assign prd_sub_bytes_q = prd_sub_bytes_d; + + end else begin : gen_prd_buffer + // PRD buffer stage to: + // 1. Make sure the S-Boxes get always presented new data/mask inputs together with fresh PRD + // for remasking. + // 2. Prevent glitches originating from inside the masking PRNG from propagating into the + // masked S-Boxes. + always_ff @(posedge clk_i or negedge rst_ni) begin : prd_sub_bytes_reg + if (!rst_ni) begin + prd_sub_bytes_q <= '0; + end else if (state_we == SP2V_HIGH) begin + prd_sub_bytes_q <= prd_sub_bytes_d; + end + end + end + + // Convert the 3-dimensional prd_sub_bytes_q array to a 1-dimensional packed array for the + // aes_prd_get_lsbs() function used below. + logic [WidthPRDData-1:0] prd_sub_bytes; + assign prd_sub_bytes = prd_sub_bytes_q; // Extract randomness for masking the input data. // // The masking PRNG is used for generating both the PRD for the S-Boxes/SubBytes operation as // well as for the input data masks. When using any of the masked Canright S-Box implementations, // it is important that the SubBytes input masks (generated by the PRNG in Round X-1) and the - // SubBytes output masks (generated by the PRNG in Round X) are independent. Inside the PRNG, - // this is achieved by using multiple, separately re-seeded LFSR chunks and by selecting the - // separate LFSR chunks in alternating fashion. Since the input data masks become the SubBytes - // input masks in the first round, we select the same 8 bit lanes for the input data masks which - // are also used to form the SubBytes output mask for the masked Canright S-Box implementations, - // i.e., the 8 LSBs of the per S-Box PRD. In particular, we have: + // SubBytes output masks (generated by the PRNG in Round X) are independent. This can be achieved + // by using e.g. an unrolled Bivium stream cipher primitive inside the PRNG. Since the input data + // masks become the SubBytes input masks in the first round, we select the same 8 bit lanes for + // the input data masks which are also used to form the SubBytes output mask for the masked + // Canright S-Box implementations, i.e., the 8 LSBs of the per S-Box PRD. In particular, we have: // // prd_masking = { prd_key_expand, ... , sb_prd[4], sb_out_mask[4], sb_prd[0], sb_out_mask[0] } // @@ -351,13 +364,17 @@ module aes_cipher_core // // When using a masked S-Box implementation other than Canright, we still select the 8 LSBs of // the per-S-Box PRD to form the input data mask of the corresponding byte. We do this to - // distribute the input data masks over all LFSR chunks of the masking PRNG. We do the extraction - // on a row basis. + // distribute the input data masks over all output bits the masking PRNG. We do the extraction on + // a row basis. localparam int unsigned WidthPRDRow = 4*WidthPRDSBox; for (genvar i = 0; i < 4; i++) begin : gen_in_mask - assign data_in_mask_o[i] = aes_prd_get_lsbs(prd_masking[i * WidthPRDRow +: WidthPRDRow]); + assign data_in_mask[i] = aes_prd_get_lsbs(prd_sub_bytes[i * WidthPRDRow +: WidthPRDRow]); end + // Rotate the data input masks by 64 bits to ensure the data input masks are independent + // from the PRD fed to the S-Boxes/SubBytes operation. + assign data_in_mask_o = {data_in_mask[1], data_in_mask[0], data_in_mask[3], data_in_mask[2]}; + // Cipher data path aes_sub_bytes #( .SecSBoxImpl ( SecSBoxImpl ) @@ -370,7 +387,7 @@ module aes_cipher_core .op_i ( op_i ), .data_i ( state_q[0] ), .mask_i ( sb_in_mask ), - .prd_i ( prd_sub_bytes ), + .prd_i ( prd_sub_bytes_q ), .data_o ( sub_bytes_out ), .mask_o ( sb_out_mask ), .err_o ( sub_bytes_err ) @@ -420,10 +437,10 @@ module aes_cipher_core always_comb begin : key_full_mux unique case (key_full_sel) KEY_FULL_ENC_INIT: key_full_d = key_init_i; - KEY_FULL_DEC_INIT: key_full_d = key_dec_q; + KEY_FULL_DEC_INIT: key_full_d = !CiphOpFwdOnly ? key_dec_q : prd_clearing_key_i; KEY_FULL_ROUND: key_full_d = key_expand_out; - KEY_FULL_CLEAR: key_full_d = prd_clearing_256; - default: key_full_d = prd_clearing_256; + KEY_FULL_CLEAR: key_full_d = prd_clearing_key_i; + default: key_full_d = prd_clearing_key_i; endcase end @@ -435,24 +452,43 @@ module aes_cipher_core end end - // SEC_CM: KEY.SEC_WIPE - // Decryption Key registers - always_comb begin : key_dec_mux - unique case (key_dec_sel) - KEY_DEC_EXPAND: key_dec_d = key_expand_out; - KEY_DEC_CLEAR: key_dec_d = prd_clearing_256; - default: key_dec_d = prd_clearing_256; - endcase - end + if (!CiphOpFwdOnly) begin : gen_key_dec + // SEC_CM: KEY.SEC_WIPE + // Decryption Key registers + always_comb begin : key_dec_mux + unique case (key_dec_sel) + KEY_DEC_EXPAND: key_dec_d = key_expand_out; + KEY_DEC_CLEAR: key_dec_d = prd_clearing_key_i; + default: key_dec_d = prd_clearing_key_i; + endcase + end - always_ff @(posedge clk_i or negedge rst_ni) begin : key_dec_reg - if (!rst_ni) begin - key_dec_q <= '{default: '0}; - end else if (key_dec_we == SP2V_HIGH) begin - key_dec_q <= key_dec_d; + always_ff @(posedge clk_i or negedge rst_ni) begin : key_dec_reg + if (!rst_ni) begin + key_dec_q <= '{default: '0}; + end else if (key_dec_we == SP2V_HIGH) begin + key_dec_q <= key_dec_d; + end + end + end else begin : gen_no_key_dec + // No Decryption Key registers + assign key_dec_q = '{default: '0}; + assign key_dec_d = key_dec_q; + + // Tie-off unused signals. + logic unused_key_dec; + always_comb begin + unused_key_dec = ^{key_dec_sel, key_dec_we}; + for (int s = 0; s < NumShares; s++) begin + unused_key_dec ^= ^{key_dec_d[s]}; + end end end + // Make sure that whenever the data/mask inputs of the S-Boxes update, the internally buffered + // PRD is updated in sync. + assign key_expand_prd_we = (key_full_we == SP2V_HIGH) ? 1'b1 : 1'b0; + // Key expand data path aes_key_expand #( .AES192Enable ( AES192Enable ), @@ -464,6 +500,7 @@ module aes_cipher_core .cfg_valid_i ( cfg_valid ), .op_i ( key_expand_op ), .en_i ( key_expand_en ), + .prd_we_i ( key_expand_prd_we ), .out_req_o ( key_expand_out_req ), .out_ack_i ( key_expand_out_ack ), .clear_i ( key_expand_clear ), @@ -499,19 +536,31 @@ module aes_cipher_core always_comb begin : round_key_mux unique case (round_key_sel) ROUND_KEY_DIRECT: round_key = key_bytes; - ROUND_KEY_MIXED: round_key = key_mix_columns_out; + ROUND_KEY_MIXED: round_key = !CiphOpFwdOnly ? key_mix_columns_out : key_bytes; default: round_key = key_bytes; endcase end + if (CiphOpFwdOnly) begin : gen_unused_key_mix_columns_out + // Tie-off unused signals. + logic unused_key_mix_columns_out; + always_comb begin + unused_key_mix_columns_out = 1'b0; + for (int s = 0; s < NumShares; s++) begin + unused_key_mix_columns_out ^= ^{key_mix_columns_out[s]}; + end + end + end + ///////////// // Control // ///////////// // Control aes_cipher_control #( - .SecMasking ( SecMasking ), - .SecSBoxImpl ( SecSBoxImpl ) + .CiphOpFwdOnly ( CiphOpFwdOnly ), + .SecMasking ( SecMasking ), + .SecSBoxImpl ( SecSBoxImpl ) ) u_aes_cipher_control ( .clk_i ( clk_i ), .rst_ni ( rst_ni ), @@ -760,7 +809,7 @@ module aes_cipher_core // Signals used for assertions only. logic prd_clearing_equals_output, unused_prd_clearing_equals_output; - assign prd_clearing_equals_output = (prd_clearing_128 == add_round_key_out); + assign prd_clearing_equals_output = (prd_clearing_state_i == add_round_key_out); assign unused_prd_clearing_equals_output = prd_clearing_equals_output; // Ensure that the state register gets cleared with pseudo-random data at the end of the last @@ -791,7 +840,7 @@ module aes_cipher_core sub_bytes_en == SP2V_HIGH && ($past(sub_bytes_en) == SP2V_LOW || ($past(sub_bytes_out_req) == SP2V_HIGH && $past(sub_bytes_out_ack) == SP2V_HIGH)) |=> - $past(prd_sub_bytes) != $past(prd_sub_bytes, NumCyclesPerRound + 1) || + $past(prd_sub_bytes_q) != $past(prd_sub_bytes_q, NumCyclesPerRound + 1) || SecAllowForcingMasks && force_masks_i) // Ensure that the PRNG has been updated between masking the input and starting the first @@ -871,7 +920,7 @@ module aes_cipher_core end for (genvar i = 0; i < 4; i++) begin : gen_unused_prd_masking assign unused_prd_masking[i * WidthPRDRow +: WidthPRDRow] = - aes_prd_concat_bits(data_in_mask_o[i], unused_prd_msbs[i]); + aes_prd_concat_bits(data_in_mask[i], unused_prd_msbs[i]); end assign unused_prd_masking[WidthPRDMasking-1 -: WidthPRDKey] = prd_key_expand; `CALIPTRA_ASSERT(AesMskgPrdExtraction, prd_masking == unused_prd_masking) diff --git a/src/aes/rtl/aes_clp_reg.rdl b/src/aes/rtl/aes_clp_reg.rdl new file mode 100644 index 000000000..7c166359b --- /dev/null +++ b/src/aes/rtl/aes_clp_reg.rdl @@ -0,0 +1,357 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +addrmap aes_clp_reg { + desc="address maps for AES register space"; + + addressing = compact; + lsb0 = true; // lsb0 property is implicit/default. See docs for + // SystemRDL 2.0 sections 9.1 and 13.4 + + default regwidth = 32; // reg property + default accesswidth = 32; // reg property + + default hw = na; + signal {activelow; async; cpuif_reset; field_reset;} reset_b; + signal {activelow; async;} error_reset_b; // Driven by Caliptra pwrgood from SoC + + /* ----------------------- + * Register definitive definitions + * ----------------------- */ + + /* ---- AES Component Name ---- */ + reg { + name = "AES component name register type definition"; + desc = "Two 32-bit read-only registers representing of the name + of AES component."; + + default sw = r; + default hw = w; + field {desc = "Name field";} NAME[32]; + + } AES_NAME[2] @0x00000100; + + /* ---- AES Component Version ---- */ + reg { + name = "AES component version register type definition"; + desc = "Two 32-bit read-only registers representing of the version + of AES component."; + + default sw = r; + default hw = w; + field {desc = "Version field";} VERSION[32]; + + } AES_VERSION[2]; + + /* ---- AES Key Vault Control Reg ---- */ + kv_read_ctrl_reg AES_KV_RD_KEY_CTRL @0x00000600; + kv_status_reg AES_KV_RD_KEY_STATUS; + + + /* ---- Global Interrupt Enable ---- */ + reg global_intr_en_t { + name = "Per-Type Interrupt Enable Register"; + desc = "Dedicated register with one bit for each event type that may produce an interrupt."; + + default hw = na; + default sw = rw; + + // Global enablement (for interrupts of the event types defined for this module) + field {desc = "Global enable bit for all events of type 'Error'"; } error_en = 1'b0; + field {desc = "Global enable bit for all events of type 'Notification'";} notif_en = 1'b0; + }; + + /* ---- Error Interrupt Enable ---- */ + reg error_intr_en_t { + name = "Per-Event Interrupt Enable Register"; + desc = "Dedicated register with one bit for each event that may produce an interrupt."; + + default hw = na; + default sw = rw; + + // Specific enables for the events defined in this + // event type in the instantiating peripheral. + // TODO add error events + field {desc = "Enable bit for Event 0";} error0_en = 1'b0; + field {desc = "Enable bit for Event 1";} error1_en = 1'b0; + field {desc = "Enable bit for Event 2";} error2_en = 1'b0; + field {desc = "Enable bit for Event 3";} error3_en = 1'b0; + }; + + /* ---- Notification Interrupt Enable ---- */ + reg notif_intr_en_t { + name = "Per-Event Interrupt Enable Register"; + desc = "Dedicated register with one bit for each event that may produce an interrupt."; + + default hw = na; + default sw = rw; + + // Specific enables for the events defined in this + // event type in the instantiating peripheral. + field {desc = "Enable bit for Command Done Interrupt";} notif_cmd_done_en = 1'b0; + }; + + /* ---- Error Interrupt Status ---- */ + reg error_intr_t { + name = "Interrupt Status Register type definition"; + desc = "Single bit indicating occurrence of each interrupt event. + Sticky, level assertion, write-1-to-clear."; + + default precedence = hw; + default hw = w; + default hwset = true; + default sw = rw; + default woclr = true; + default level intr; + + field {desc = "Interrupt Event 0 status bit";} error0_sts = 1'b0; + field {desc = "Interrupt Event 1 status bit";} error1_sts = 1'b0; + field {desc = "Interrupt Event 2 status bit";} error2_sts = 1'b0; + field {desc = "Interrupt Event 3 status bit";} error3_sts = 1'b0; + }; + + /* ---- Notification Interrupt Status ---- */ + reg notif_intr_t { + name = "Interrupt Status Register type definition"; + desc = "Single bit indicating occurrence of each interrupt event. + Sticky, level assertion, write-1-to-clear."; + + default precedence = hw; + default hw = w; + default hwset = true; + default sw = rw; + default woclr = true; + default level intr; + + field {desc = "Command Done Interrupt status bit";} notif_cmd_done_sts = 1'b0; + }; + + /* ---- Aggregated Interrupt Status ---- */ + reg global_intr_t { + name = "Interrupt Status Aggregation Register type definition"; + desc = "Single bit indicating occurrence of any interrupt event + of a given type. E.g. Notifications and Errors may drive + to two separate interrupt registers. There may be + multiple sources of Notifications or Errors that are + aggregated into a single interrupt pin for that + respective type. That pin feeds through this register + in order to apply a global enablement of that interrupt + event type. + Nonsticky assertion."; + + default hw = w; + default sw = r; + default nonsticky intr; + + field {desc = "Interrupt Event Aggregation status bit";} agg_sts = 1'b0; + }; + + /* ---- Error Interrupt Trigger ---- */ + reg error_intr_trig_t { + name = "Interrupt Trigger Register type definition"; + desc = "Single bit for each interrupt event allows SW to manually + trigger occurrence of that event. Upon SW write, the trigger bit + will pulse for 1 cycle then clear to 0. The pulse on the + trigger register bit results in the corresponding interrupt + status bit being set to 1."; + + default hw = na; + default sw = rw; + default woset = true; + default singlepulse = true; + + // Instantiate triggers bit-by-bit. + field {desc = "Interrupt Trigger 0 bit";} error0_trig = 1'b0; + field {desc = "Interrupt Trigger 1 bit";} error1_trig = 1'b0; + field {desc = "Interrupt Trigger 2 bit";} error2_trig = 1'b0; + field {desc = "Interrupt Trigger 3 bit";} error3_trig = 1'b0; + }; + + /* ---- Notification Interrupt Trigger ---- */ + reg notif_intr_trig_t { + name = "Interrupt Trigger Register type definition"; + desc = "Single bit for each interrupt event allows SW to manually + trigger occurrence of that event. Upon SW write, the trigger bit + will pulse for 1 cycle then clear to 0. The pulse on the + trigger register bit results in the corresponding interrupt + status bit being set to 1."; + + default hw = na; + default sw = rw; + default woset = true; + default singlepulse = true; + + // Instantiate triggers bit-by-bit. + field {desc = "Interrupt Trigger 0 bit";} notif_cmd_done_trig = 1'b0; + }; + + /* ---- Interrupt Statistics Counter Incrementor ---- */ + reg intr_count_incr_t { + name = "Interrupt Event Count Incrementor"; + desc = "Trigger the event counter to increment based on observing + the rising edge of an interrupt event input from the + Hardware. The same input signal that causes an interrupt + event to be set (sticky) also causes this signal to pulse + for 1 clock cycle, resulting in the event counter + incrementing by 1 for every interrupt event. + This is implemented as a down-counter (1-bit) that will + decrement immediately on being set - resulting in a pulse"; + + default hw = w; + default sw = r; // Has to have some access.... ideally SW wouldn't even see this + default hwset = true; + default decrvalue = 1; + default counter; + + field {desc = "Pulse mirrors interrupt event occurrence";} pulse = 1'b0; + }; + + /* ---- Interrupt Statistics Counter ---- */ + reg intr_count_t { + name = "Interrupt Event Counter"; + desc = "Provides statistics about the number of events that have + occurred. + Will not overflow ('incrsaturate')."; + + default sw = rw; + default hw = na; + default incrvalue = 1; + default incrsaturate = true; + default counter; + + field {desc = "Count field";} cnt[32] = 32'h0; + }; + + + /* ----------------------- + * Register File definitive definition + * ----------------------- */ + + // Notifications are non-error events that occur during normal operation of the module. + // E.g. a completion of a job may produce a notification. + // Error and notification events are separated into separate status/trigger registers + // to allow effective priority allocation by software + regfile intr_block_t { + name = "Interrupt Register Block"; + desc = "Set of registers to implement interrupt functionality"; + + /* ------------------------------------------------- Registers ------------------------------------------------- */ + // First 9 registers are static and always defined // + global_intr_en_t global_intr_en_r; /* 1-bit per event type */ // + error_intr_en_t error_intr_en_r; /* 1-bit per error */ // + notif_intr_en_t notif_intr_en_r; /* 1-bit per notification */ // + global_intr_t error_global_intr_r; /* 1-bit aggregating all error interrupts with global enable */ // + global_intr_t notif_global_intr_r; /* 1-bit aggregating all notification interrupts with global enable */ // + error_intr_t error_internal_intr_r; /* Error pending, SW write 1 to clear */ // + notif_intr_t notif_internal_intr_r; /* Notification pending, SW write 1 to clear */ // + error_intr_trig_t error_intr_trig_r; /* SW sets error bit for interrupt testing */ // + notif_intr_trig_t notif_intr_trig_r; /* SW sets notification bit for interrupt testing */ // + // + // Align this set of registers; number of counters is based on peripheral event requirements // + intr_count_t error0_intr_count_r @0x100; /* Per error */ // + intr_count_t error1_intr_count_r; /* Per error */ // + intr_count_t error2_intr_count_r; /* Per error */ // + intr_count_t error3_intr_count_r; /* Per error */ // + intr_count_t notif_cmd_done_intr_count_r @0x180; /* Per notification */ // + // + // These registers should be treated by SW as reserved, and ignored. // + // Offset at 0x200 gives enough space for 32 Errors and 32 Notifications // + // to be implemented (requiring 2*32 32-bit registers starting at // + // offset 0x100), and still allowing the entire regfile to fit // + // inside a 1024-byte space. // + intr_count_incr_t error0_intr_count_incr_r @0x200; /* Per error count incrementor pulse */ // + intr_count_incr_t error1_intr_count_incr_r; /* Per error count incrementor pulse */ // + intr_count_incr_t error2_intr_count_incr_r; /* Per error count incrementor pulse */ // + intr_count_incr_t error3_intr_count_incr_r; /* Per error count incrementor pulse */ // + intr_count_incr_t notif_cmd_done_intr_count_incr_r; /* Per notification count incrementor pulse */ // + /* ------------------------------------------------------------------------------------------------------------- */ + + /* ---- Reset assignment for Error Events ---- */ + error_internal_intr_r.error0_sts -> resetsignal = error_reset_b; + error_internal_intr_r.error1_sts -> resetsignal = error_reset_b; + error_internal_intr_r.error2_sts -> resetsignal = error_reset_b; + error_internal_intr_r.error3_sts -> resetsignal = error_reset_b; + error0_intr_count_r.cnt -> resetsignal = error_reset_b; + error1_intr_count_r.cnt -> resetsignal = error_reset_b; + error2_intr_count_r.cnt -> resetsignal = error_reset_b; + error3_intr_count_r.cnt -> resetsignal = error_reset_b; + // TODO: Use this same reset for the error incrementor pulse too? + + /* ---- Interrupt Event Dynamic Assignments ---- */ + error_internal_intr_r.error0_sts -> enable = error_intr_en_r.error0_en; + error_internal_intr_r.error1_sts -> enable = error_intr_en_r.error1_en; + error_internal_intr_r.error2_sts -> enable = error_intr_en_r.error2_en; + error_internal_intr_r.error3_sts -> enable = error_intr_en_r.error3_en; + notif_internal_intr_r.notif_cmd_done_sts -> enable = notif_intr_en_r.notif_cmd_done_en; + + error_internal_intr_r.error0_sts -> next = error_intr_trig_r.error0_trig; + error_internal_intr_r.error1_sts -> next = error_intr_trig_r.error1_trig; + error_internal_intr_r.error2_sts -> next = error_intr_trig_r.error2_trig; + error_internal_intr_r.error3_sts -> next = error_intr_trig_r.error3_trig; + notif_internal_intr_r.notif_cmd_done_sts -> next = notif_intr_trig_r.notif_cmd_done_trig; + + // NOTE: hwset for events is implicitly defined as module input + + /* ---- Global Interrupt Dynamic Assignments ---- */ + error_global_intr_r.agg_sts -> enable = global_intr_en_r.error_en; + notif_global_intr_r.agg_sts -> enable = global_intr_en_r.notif_en; + + error_global_intr_r.agg_sts -> next = error_internal_intr_r -> intr; + notif_global_intr_r.agg_sts -> next = notif_internal_intr_r -> intr; + + /* ---- Event Statistics Tracker Assignments ---- */ + // NOTE: This method relies upon a "counter" that is set using the + // same events that trigger an interrupt, then immediately + // self-clearing, which results in a pulse. Must be configured + // to be sensitive to the interrupt trigger events for each event. + // The output pulse is then used to increment the ACTUAL counter + error0_intr_count_incr_r.pulse -> hwset = error_internal_intr_r.error0_sts -> hwset; // \_____ Capture both firmware and hardware triggered events + error0_intr_count_incr_r.pulse -> next = error_internal_intr_r.error0_sts -> next; // / as a pulse to increment the intr_count_r register + error0_intr_count_incr_r.pulse -> we = error_internal_intr_r.error0_sts -> next; // Generate a pulse from SW trigger, if set, or default to use the hwset input + error0_intr_count_incr_r.pulse -> decr = error0_intr_count_incr_r.pulse; // Auto-clear to generate pulse output + error0_intr_count_r.cnt -> incr = error0_intr_count_incr_r.pulse; // Increment coincides with rising edge of interrupt sts bit + + error1_intr_count_incr_r.pulse -> hwset = error_internal_intr_r.error1_sts -> hwset; // \_____ Capture both firmware and hardware triggered events + error1_intr_count_incr_r.pulse -> next = error_internal_intr_r.error1_sts -> next; // / as a pulse to increment the intr_count_r register + error1_intr_count_incr_r.pulse -> we = error_internal_intr_r.error1_sts -> next; // Generate a pulse from SW trigger, if set, or default to use the hwset input + error1_intr_count_incr_r.pulse -> decr = error1_intr_count_incr_r.pulse; // Auto-clear to generate pulse output + error1_intr_count_r.cnt -> incr = error1_intr_count_incr_r.pulse; // Increment coincides with rising edge of interrupt sts bit + + error2_intr_count_incr_r.pulse -> hwset = error_internal_intr_r.error2_sts -> hwset; // \_____ Capture both firmware and hardware triggered events + error2_intr_count_incr_r.pulse -> next = error_internal_intr_r.error2_sts -> next; // / as a pulse to increment the intr_count_r register + error2_intr_count_incr_r.pulse -> we = error_internal_intr_r.error2_sts -> next; // Generate a pulse from SW trigger, if set, or default to use the hwset input + error2_intr_count_incr_r.pulse -> decr = error2_intr_count_incr_r.pulse; // Auto-clear to generate pulse output + error2_intr_count_r.cnt -> incr = error2_intr_count_incr_r.pulse; // Increment coincides with rising edge of interrupt sts bit + + error3_intr_count_incr_r.pulse -> hwset = error_internal_intr_r.error3_sts -> hwset; // \_____ Capture both firmware and hardware triggered events + error3_intr_count_incr_r.pulse -> next = error_internal_intr_r.error3_sts -> next; // / as a pulse to increment the intr_count_r register + error3_intr_count_incr_r.pulse -> we = error_internal_intr_r.error3_sts -> next; // Generate a pulse from SW trigger, if set, or default to use the hwset input + error3_intr_count_incr_r.pulse -> decr = error3_intr_count_incr_r.pulse; // Auto-clear to generate pulse output + error3_intr_count_r.cnt -> incr = error3_intr_count_incr_r.pulse; // Increment coincides with rising edge of interrupt sts bit + + notif_cmd_done_intr_count_incr_r.pulse -> hwset = notif_internal_intr_r.notif_cmd_done_sts -> hwset; // \_____ Capture both firmware and hardware triggered events + notif_cmd_done_intr_count_incr_r.pulse -> next = notif_internal_intr_r.notif_cmd_done_sts -> next; // / as a pulse to increment the intr_count_r register + notif_cmd_done_intr_count_incr_r.pulse -> we = notif_internal_intr_r.notif_cmd_done_sts -> next; // Generate a pulse from SW trigger, if set, or default to use the hwset input + notif_cmd_done_intr_count_incr_r.pulse -> decr = notif_cmd_done_intr_count_incr_r.pulse; // Auto-clear to generate pulse output + notif_cmd_done_intr_count_r.cnt -> incr = notif_cmd_done_intr_count_incr_r.pulse; // Increment coincides with rising edge of interrupt sts bit + + }; + + /* ----------------------- + * Register File instance + * ----------------------- */ + intr_block_t intr_block_rf @0x800; + +}; diff --git a/src/aes/rtl/aes_clp_reg.sv b/src/aes/rtl/aes_clp_reg.sv new file mode 100644 index 000000000..a37e93462 --- /dev/null +++ b/src/aes/rtl/aes_clp_reg.sv @@ -0,0 +1,1457 @@ +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +module aes_clp_reg ( + input wire clk, + input wire rst, + + input wire s_cpuif_req, + input wire s_cpuif_req_is_wr, + input wire [11:0] s_cpuif_addr, + input wire [31:0] s_cpuif_wr_data, + input wire [31:0] s_cpuif_wr_biten, + output wire s_cpuif_req_stall_wr, + output wire s_cpuif_req_stall_rd, + output wire s_cpuif_rd_ack, + output wire s_cpuif_rd_err, + output wire [31:0] s_cpuif_rd_data, + output wire s_cpuif_wr_ack, + output wire s_cpuif_wr_err, + + input aes_clp_reg_pkg::aes_clp_reg__in_t hwif_in, + output aes_clp_reg_pkg::aes_clp_reg__out_t hwif_out + ); + + //-------------------------------------------------------------------------- + // CPU Bus interface logic + //-------------------------------------------------------------------------- + logic cpuif_req; + logic cpuif_req_is_wr; + logic [11:0] cpuif_addr; + logic [31:0] cpuif_wr_data; + logic [31:0] cpuif_wr_biten; + logic cpuif_req_stall_wr; + logic cpuif_req_stall_rd; + + logic cpuif_rd_ack; + logic cpuif_rd_err; + logic [31:0] cpuif_rd_data; + + logic cpuif_wr_ack; + logic cpuif_wr_err; + + assign cpuif_req = s_cpuif_req; + assign cpuif_req_is_wr = s_cpuif_req_is_wr; + assign cpuif_addr = s_cpuif_addr; + assign cpuif_wr_data = s_cpuif_wr_data; + assign cpuif_wr_biten = s_cpuif_wr_biten; + assign s_cpuif_req_stall_wr = cpuif_req_stall_wr; + assign s_cpuif_req_stall_rd = cpuif_req_stall_rd; + assign s_cpuif_rd_ack = cpuif_rd_ack; + assign s_cpuif_rd_err = cpuif_rd_err; + assign s_cpuif_rd_data = cpuif_rd_data; + assign s_cpuif_wr_ack = cpuif_wr_ack; + assign s_cpuif_wr_err = cpuif_wr_err; + + logic cpuif_req_masked; + + // Read & write latencies are balanced. Stalls not required + assign cpuif_req_stall_rd = '0; + assign cpuif_req_stall_wr = '0; + assign cpuif_req_masked = cpuif_req + & !(!cpuif_req_is_wr & cpuif_req_stall_rd) + & !(cpuif_req_is_wr & cpuif_req_stall_wr); + + //-------------------------------------------------------------------------- + // Address Decode + //-------------------------------------------------------------------------- + typedef struct packed{ + logic [2-1:0]AES_NAME; + logic [2-1:0]AES_VERSION; + logic AES_KV_RD_KEY_CTRL; + logic AES_KV_RD_KEY_STATUS; + struct packed{ + logic global_intr_en_r; + logic error_intr_en_r; + logic notif_intr_en_r; + logic error_global_intr_r; + logic notif_global_intr_r; + logic error_internal_intr_r; + logic notif_internal_intr_r; + logic error_intr_trig_r; + logic notif_intr_trig_r; + logic error0_intr_count_r; + logic error1_intr_count_r; + logic error2_intr_count_r; + logic error3_intr_count_r; + logic notif_cmd_done_intr_count_r; + logic error0_intr_count_incr_r; + logic error1_intr_count_incr_r; + logic error2_intr_count_incr_r; + logic error3_intr_count_incr_r; + logic notif_cmd_done_intr_count_incr_r; + } intr_block_rf; + } decoded_reg_strb_t; + decoded_reg_strb_t decoded_reg_strb; + logic decoded_req; + logic decoded_req_is_wr; + logic [31:0] decoded_wr_data; + logic [31:0] decoded_wr_biten; + + always_comb begin + for(int i0=0; i0<2; i0++) begin + decoded_reg_strb.AES_NAME[i0] = cpuif_req_masked & (cpuif_addr == 12'h100 + i0*12'h4); + end + for(int i0=0; i0<2; i0++) begin + decoded_reg_strb.AES_VERSION[i0] = cpuif_req_masked & (cpuif_addr == 12'h108 + i0*12'h4); + end + decoded_reg_strb.AES_KV_RD_KEY_CTRL = cpuif_req_masked & (cpuif_addr == 12'h600); + decoded_reg_strb.AES_KV_RD_KEY_STATUS = cpuif_req_masked & (cpuif_addr == 12'h604); + decoded_reg_strb.intr_block_rf.global_intr_en_r = cpuif_req_masked & (cpuif_addr == 12'h800); + decoded_reg_strb.intr_block_rf.error_intr_en_r = cpuif_req_masked & (cpuif_addr == 12'h804); + decoded_reg_strb.intr_block_rf.notif_intr_en_r = cpuif_req_masked & (cpuif_addr == 12'h808); + decoded_reg_strb.intr_block_rf.error_global_intr_r = cpuif_req_masked & (cpuif_addr == 12'h80c); + decoded_reg_strb.intr_block_rf.notif_global_intr_r = cpuif_req_masked & (cpuif_addr == 12'h810); + decoded_reg_strb.intr_block_rf.error_internal_intr_r = cpuif_req_masked & (cpuif_addr == 12'h814); + decoded_reg_strb.intr_block_rf.notif_internal_intr_r = cpuif_req_masked & (cpuif_addr == 12'h818); + decoded_reg_strb.intr_block_rf.error_intr_trig_r = cpuif_req_masked & (cpuif_addr == 12'h81c); + decoded_reg_strb.intr_block_rf.notif_intr_trig_r = cpuif_req_masked & (cpuif_addr == 12'h820); + decoded_reg_strb.intr_block_rf.error0_intr_count_r = cpuif_req_masked & (cpuif_addr == 12'h900); + decoded_reg_strb.intr_block_rf.error1_intr_count_r = cpuif_req_masked & (cpuif_addr == 12'h904); + decoded_reg_strb.intr_block_rf.error2_intr_count_r = cpuif_req_masked & (cpuif_addr == 12'h908); + decoded_reg_strb.intr_block_rf.error3_intr_count_r = cpuif_req_masked & (cpuif_addr == 12'h90c); + decoded_reg_strb.intr_block_rf.notif_cmd_done_intr_count_r = cpuif_req_masked & (cpuif_addr == 12'h980); + decoded_reg_strb.intr_block_rf.error0_intr_count_incr_r = cpuif_req_masked & (cpuif_addr == 12'ha00); + decoded_reg_strb.intr_block_rf.error1_intr_count_incr_r = cpuif_req_masked & (cpuif_addr == 12'ha04); + decoded_reg_strb.intr_block_rf.error2_intr_count_incr_r = cpuif_req_masked & (cpuif_addr == 12'ha08); + decoded_reg_strb.intr_block_rf.error3_intr_count_incr_r = cpuif_req_masked & (cpuif_addr == 12'ha0c); + decoded_reg_strb.intr_block_rf.notif_cmd_done_intr_count_incr_r = cpuif_req_masked & (cpuif_addr == 12'ha10); + end + + // Pass down signals to next stage + assign decoded_req = cpuif_req_masked; + assign decoded_req_is_wr = cpuif_req_is_wr; + assign decoded_wr_data = cpuif_wr_data; + assign decoded_wr_biten = cpuif_wr_biten; + + //-------------------------------------------------------------------------- + // Field logic + //-------------------------------------------------------------------------- + typedef struct packed{ + struct packed{ + struct packed{ + logic next; + logic load_next; + } read_en; + struct packed{ + logic [4:0] next; + logic load_next; + } read_entry; + struct packed{ + logic next; + logic load_next; + } pcr_hash_extend; + struct packed{ + logic [24:0] next; + logic load_next; + } rsvd; + } AES_KV_RD_KEY_CTRL; + struct packed{ + struct packed{ + logic next; + logic load_next; + } VALID; + } AES_KV_RD_KEY_STATUS; + struct packed{ + struct packed{ + struct packed{ + logic next; + logic load_next; + } error_en; + struct packed{ + logic next; + logic load_next; + } notif_en; + } global_intr_en_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } error0_en; + struct packed{ + logic next; + logic load_next; + } error1_en; + struct packed{ + logic next; + logic load_next; + } error2_en; + struct packed{ + logic next; + logic load_next; + } error3_en; + } error_intr_en_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } notif_cmd_done_en; + } notif_intr_en_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } agg_sts; + } error_global_intr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } agg_sts; + } notif_global_intr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } error0_sts; + struct packed{ + logic next; + logic load_next; + } error1_sts; + struct packed{ + logic next; + logic load_next; + } error2_sts; + struct packed{ + logic next; + logic load_next; + } error3_sts; + } error_internal_intr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } notif_cmd_done_sts; + } notif_internal_intr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } error0_trig; + struct packed{ + logic next; + logic load_next; + } error1_trig; + struct packed{ + logic next; + logic load_next; + } error2_trig; + struct packed{ + logic next; + logic load_next; + } error3_trig; + } error_intr_trig_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + } notif_cmd_done_trig; + } notif_intr_trig_r; + struct packed{ + struct packed{ + logic [31:0] next; + logic load_next; + logic incrthreshold; + logic incrsaturate; + } cnt; + } error0_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] next; + logic load_next; + logic incrthreshold; + logic incrsaturate; + } cnt; + } error1_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] next; + logic load_next; + logic incrthreshold; + logic incrsaturate; + } cnt; + } error2_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] next; + logic load_next; + logic incrthreshold; + logic incrsaturate; + } cnt; + } error3_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] next; + logic load_next; + logic incrthreshold; + logic incrsaturate; + } cnt; + } notif_cmd_done_intr_count_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + logic decrthreshold; + logic underflow; + } pulse; + } error0_intr_count_incr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + logic decrthreshold; + logic underflow; + } pulse; + } error1_intr_count_incr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + logic decrthreshold; + logic underflow; + } pulse; + } error2_intr_count_incr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + logic decrthreshold; + logic underflow; + } pulse; + } error3_intr_count_incr_r; + struct packed{ + struct packed{ + logic next; + logic load_next; + logic decrthreshold; + logic underflow; + } pulse; + } notif_cmd_done_intr_count_incr_r; + } intr_block_rf; + } field_combo_t; + field_combo_t field_combo; + + typedef struct packed{ + struct packed{ + struct packed{ + logic value; + } read_en; + struct packed{ + logic [4:0] value; + } read_entry; + struct packed{ + logic value; + } pcr_hash_extend; + struct packed{ + logic [24:0] value; + } rsvd; + } AES_KV_RD_KEY_CTRL; + struct packed{ + struct packed{ + logic value; + } VALID; + } AES_KV_RD_KEY_STATUS; + struct packed{ + struct packed{ + struct packed{ + logic value; + } error_en; + struct packed{ + logic value; + } notif_en; + } global_intr_en_r; + struct packed{ + struct packed{ + logic value; + } error0_en; + struct packed{ + logic value; + } error1_en; + struct packed{ + logic value; + } error2_en; + struct packed{ + logic value; + } error3_en; + } error_intr_en_r; + struct packed{ + struct packed{ + logic value; + } notif_cmd_done_en; + } notif_intr_en_r; + struct packed{ + struct packed{ + logic value; + } agg_sts; + } error_global_intr_r; + struct packed{ + struct packed{ + logic value; + } agg_sts; + } notif_global_intr_r; + struct packed{ + struct packed{ + logic value; + } error0_sts; + struct packed{ + logic value; + } error1_sts; + struct packed{ + logic value; + } error2_sts; + struct packed{ + logic value; + } error3_sts; + } error_internal_intr_r; + struct packed{ + struct packed{ + logic value; + } notif_cmd_done_sts; + } notif_internal_intr_r; + struct packed{ + struct packed{ + logic value; + } error0_trig; + struct packed{ + logic value; + } error1_trig; + struct packed{ + logic value; + } error2_trig; + struct packed{ + logic value; + } error3_trig; + } error_intr_trig_r; + struct packed{ + struct packed{ + logic value; + } notif_cmd_done_trig; + } notif_intr_trig_r; + struct packed{ + struct packed{ + logic [31:0] value; + } cnt; + } error0_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] value; + } cnt; + } error1_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] value; + } cnt; + } error2_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] value; + } cnt; + } error3_intr_count_r; + struct packed{ + struct packed{ + logic [31:0] value; + } cnt; + } notif_cmd_done_intr_count_r; + struct packed{ + struct packed{ + logic value; + } pulse; + } error0_intr_count_incr_r; + struct packed{ + struct packed{ + logic value; + } pulse; + } error1_intr_count_incr_r; + struct packed{ + struct packed{ + logic value; + } pulse; + } error2_intr_count_incr_r; + struct packed{ + struct packed{ + logic value; + } pulse; + } error3_intr_count_incr_r; + struct packed{ + struct packed{ + logic value; + } pulse; + } notif_cmd_done_intr_count_incr_r; + } intr_block_rf; + } field_storage_t; + field_storage_t field_storage; + + // Field: aes_clp_reg.AES_KV_RD_KEY_CTRL.read_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.AES_KV_RD_KEY_CTRL.read_en.value; + load_next_c = '0; + if(decoded_reg_strb.AES_KV_RD_KEY_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.AES_KV_RD_KEY_CTRL.read_en.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else if(hwif_in.AES_KV_RD_KEY_CTRL.read_en.hwclr) begin // HW Clear + next_c = '0; + load_next_c = '1; + end + field_combo.AES_KV_RD_KEY_CTRL.read_en.next = next_c; + field_combo.AES_KV_RD_KEY_CTRL.read_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.AES_KV_RD_KEY_CTRL.read_en.value <= 1'h0; + end else if(field_combo.AES_KV_RD_KEY_CTRL.read_en.load_next) begin + field_storage.AES_KV_RD_KEY_CTRL.read_en.value <= field_combo.AES_KV_RD_KEY_CTRL.read_en.next; + end + end + assign hwif_out.AES_KV_RD_KEY_CTRL.read_en.value = field_storage.AES_KV_RD_KEY_CTRL.read_en.value; + // Field: aes_clp_reg.AES_KV_RD_KEY_CTRL.read_entry + always_comb begin + automatic logic [4:0] next_c; + automatic logic load_next_c; + next_c = field_storage.AES_KV_RD_KEY_CTRL.read_entry.value; + load_next_c = '0; + if(decoded_reg_strb.AES_KV_RD_KEY_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.AES_KV_RD_KEY_CTRL.read_entry.value & ~decoded_wr_biten[5:1]) | (decoded_wr_data[5:1] & decoded_wr_biten[5:1]); + load_next_c = '1; + end + field_combo.AES_KV_RD_KEY_CTRL.read_entry.next = next_c; + field_combo.AES_KV_RD_KEY_CTRL.read_entry.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.AES_KV_RD_KEY_CTRL.read_entry.value <= 5'h0; + end else if(field_combo.AES_KV_RD_KEY_CTRL.read_entry.load_next) begin + field_storage.AES_KV_RD_KEY_CTRL.read_entry.value <= field_combo.AES_KV_RD_KEY_CTRL.read_entry.next; + end + end + assign hwif_out.AES_KV_RD_KEY_CTRL.read_entry.value = field_storage.AES_KV_RD_KEY_CTRL.read_entry.value; + // Field: aes_clp_reg.AES_KV_RD_KEY_CTRL.pcr_hash_extend + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value; + load_next_c = '0; + if(decoded_reg_strb.AES_KV_RD_KEY_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value & ~decoded_wr_biten[6:6]) | (decoded_wr_data[6:6] & decoded_wr_biten[6:6]); + load_next_c = '1; + end + field_combo.AES_KV_RD_KEY_CTRL.pcr_hash_extend.next = next_c; + field_combo.AES_KV_RD_KEY_CTRL.pcr_hash_extend.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value <= 1'h0; + end else if(field_combo.AES_KV_RD_KEY_CTRL.pcr_hash_extend.load_next) begin + field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value <= field_combo.AES_KV_RD_KEY_CTRL.pcr_hash_extend.next; + end + end + assign hwif_out.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value = field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value; + // Field: aes_clp_reg.AES_KV_RD_KEY_CTRL.rsvd + always_comb begin + automatic logic [24:0] next_c; + automatic logic load_next_c; + next_c = field_storage.AES_KV_RD_KEY_CTRL.rsvd.value; + load_next_c = '0; + if(decoded_reg_strb.AES_KV_RD_KEY_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.AES_KV_RD_KEY_CTRL.rsvd.value & ~decoded_wr_biten[31:7]) | (decoded_wr_data[31:7] & decoded_wr_biten[31:7]); + load_next_c = '1; + end + field_combo.AES_KV_RD_KEY_CTRL.rsvd.next = next_c; + field_combo.AES_KV_RD_KEY_CTRL.rsvd.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.AES_KV_RD_KEY_CTRL.rsvd.value <= 25'h0; + end else if(field_combo.AES_KV_RD_KEY_CTRL.rsvd.load_next) begin + field_storage.AES_KV_RD_KEY_CTRL.rsvd.value <= field_combo.AES_KV_RD_KEY_CTRL.rsvd.next; + end + end + assign hwif_out.AES_KV_RD_KEY_CTRL.rsvd.value = field_storage.AES_KV_RD_KEY_CTRL.rsvd.value; + // Field: aes_clp_reg.AES_KV_RD_KEY_STATUS.VALID + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.AES_KV_RD_KEY_STATUS.VALID.value; + load_next_c = '0; + if(hwif_in.AES_KV_RD_KEY_STATUS.VALID.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(hwif_in.AES_KV_RD_KEY_STATUS.VALID.hwclr) begin // HW Clear + next_c = '0; + load_next_c = '1; + end + field_combo.AES_KV_RD_KEY_STATUS.VALID.next = next_c; + field_combo.AES_KV_RD_KEY_STATUS.VALID.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.AES_KV_RD_KEY_STATUS.VALID.value <= 1'h0; + end else if(field_combo.AES_KV_RD_KEY_STATUS.VALID.load_next) begin + field_storage.AES_KV_RD_KEY_STATUS.VALID.value <= field_combo.AES_KV_RD_KEY_STATUS.VALID.next; + end + end + // Field: aes_clp_reg.intr_block_rf.global_intr_en_r.error_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.global_intr_en_r.error_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.global_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.global_intr_en_r.error_en.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.intr_block_rf.global_intr_en_r.error_en.next = next_c; + field_combo.intr_block_rf.global_intr_en_r.error_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.global_intr_en_r.error_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.global_intr_en_r.error_en.load_next) begin + field_storage.intr_block_rf.global_intr_en_r.error_en.value <= field_combo.intr_block_rf.global_intr_en_r.error_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.global_intr_en_r.notif_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.global_intr_en_r.notif_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.global_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.global_intr_en_r.notif_en.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end + field_combo.intr_block_rf.global_intr_en_r.notif_en.next = next_c; + field_combo.intr_block_rf.global_intr_en_r.notif_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.global_intr_en_r.notif_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.global_intr_en_r.notif_en.load_next) begin + field_storage.intr_block_rf.global_intr_en_r.notif_en.value <= field_combo.intr_block_rf.global_intr_en_r.notif_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_en_r.error0_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_en_r.error0_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error_intr_en_r.error0_en.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_en_r.error0_en.next = next_c; + field_combo.intr_block_rf.error_intr_en_r.error0_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_en_r.error0_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_en_r.error0_en.load_next) begin + field_storage.intr_block_rf.error_intr_en_r.error0_en.value <= field_combo.intr_block_rf.error_intr_en_r.error0_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_en_r.error1_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_en_r.error1_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error_intr_en_r.error1_en.value & ~decoded_wr_biten[1:1]) | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_en_r.error1_en.next = next_c; + field_combo.intr_block_rf.error_intr_en_r.error1_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_en_r.error1_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_en_r.error1_en.load_next) begin + field_storage.intr_block_rf.error_intr_en_r.error1_en.value <= field_combo.intr_block_rf.error_intr_en_r.error1_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_en_r.error2_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_en_r.error2_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error_intr_en_r.error2_en.value & ~decoded_wr_biten[2:2]) | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_en_r.error2_en.next = next_c; + field_combo.intr_block_rf.error_intr_en_r.error2_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_en_r.error2_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_en_r.error2_en.load_next) begin + field_storage.intr_block_rf.error_intr_en_r.error2_en.value <= field_combo.intr_block_rf.error_intr_en_r.error2_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_en_r.error3_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_en_r.error3_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error_intr_en_r.error3_en.value & ~decoded_wr_biten[3:3]) | (decoded_wr_data[3:3] & decoded_wr_biten[3:3]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_en_r.error3_en.next = next_c; + field_combo.intr_block_rf.error_intr_en_r.error3_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_en_r.error3_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_en_r.error3_en.load_next) begin + field_storage.intr_block_rf.error_intr_en_r.error3_en.value <= field_combo.intr_block_rf.error_intr_en_r.error3_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.notif_intr_en_r.notif_cmd_done_en + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.notif_intr_en_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value & ~decoded_wr_biten[0:0]) | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.next = next_c; + field_combo.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value <= 1'h0; + end else if(field_combo.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.load_next) begin + field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value <= field_combo.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_global_intr_r.agg_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_global_intr_r.agg_sts.value; + load_next_c = '0; + + // HW Write + next_c = hwif_out.intr_block_rf.error_internal_intr_r.intr; + load_next_c = '1; + field_combo.intr_block_rf.error_global_intr_r.agg_sts.next = next_c; + field_combo.intr_block_rf.error_global_intr_r.agg_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_global_intr_r.agg_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_global_intr_r.agg_sts.load_next) begin + field_storage.intr_block_rf.error_global_intr_r.agg_sts.value <= field_combo.intr_block_rf.error_global_intr_r.agg_sts.next; + end + end + assign hwif_out.intr_block_rf.error_global_intr_r.intr = + |(field_storage.intr_block_rf.error_global_intr_r.agg_sts.value & field_storage.intr_block_rf.global_intr_en_r.error_en.value); + // Field: aes_clp_reg.intr_block_rf.notif_global_intr_r.agg_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_global_intr_r.agg_sts.value; + load_next_c = '0; + + // HW Write + next_c = hwif_out.intr_block_rf.notif_internal_intr_r.intr; + load_next_c = '1; + field_combo.intr_block_rf.notif_global_intr_r.agg_sts.next = next_c; + field_combo.intr_block_rf.notif_global_intr_r.agg_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_global_intr_r.agg_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.notif_global_intr_r.agg_sts.load_next) begin + field_storage.intr_block_rf.notif_global_intr_r.agg_sts.value <= field_combo.intr_block_rf.notif_global_intr_r.agg_sts.next; + end + end + assign hwif_out.intr_block_rf.notif_global_intr_r.intr = + |(field_storage.intr_block_rf.notif_global_intr_r.agg_sts.value & field_storage.intr_block_rf.global_intr_en_r.notif_en.value); + // Field: aes_clp_reg.intr_block_rf.error_internal_intr_r.error0_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value != '0) begin // stickybit + next_c = field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value | field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error0_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(decoded_reg_strb.intr_block_rf.error_internal_intr_r && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value & ~(decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_internal_intr_r.error0_sts.next = next_c; + field_combo.intr_block_rf.error_internal_intr_r.error0_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_internal_intr_r.error0_sts.load_next) begin + field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value <= field_combo.intr_block_rf.error_internal_intr_r.error0_sts.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_internal_intr_r.error1_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value != '0) begin // stickybit + next_c = field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value | field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error1_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(decoded_reg_strb.intr_block_rf.error_internal_intr_r && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value & ~(decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_internal_intr_r.error1_sts.next = next_c; + field_combo.intr_block_rf.error_internal_intr_r.error1_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_internal_intr_r.error1_sts.load_next) begin + field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value <= field_combo.intr_block_rf.error_internal_intr_r.error1_sts.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_internal_intr_r.error2_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value != '0) begin // stickybit + next_c = field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value | field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error2_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(decoded_reg_strb.intr_block_rf.error_internal_intr_r && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value & ~(decoded_wr_data[2:2] & decoded_wr_biten[2:2]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_internal_intr_r.error2_sts.next = next_c; + field_combo.intr_block_rf.error_internal_intr_r.error2_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_internal_intr_r.error2_sts.load_next) begin + field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value <= field_combo.intr_block_rf.error_internal_intr_r.error2_sts.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_internal_intr_r.error3_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value != '0) begin // stickybit + next_c = field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value | field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error3_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(decoded_reg_strb.intr_block_rf.error_internal_intr_r && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value & ~(decoded_wr_data[3:3] & decoded_wr_biten[3:3]); + load_next_c = '1; + end + field_combo.intr_block_rf.error_internal_intr_r.error3_sts.next = next_c; + field_combo.intr_block_rf.error_internal_intr_r.error3_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_internal_intr_r.error3_sts.load_next) begin + field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value <= field_combo.intr_block_rf.error_internal_intr_r.error3_sts.next; + end + end + assign hwif_out.intr_block_rf.error_internal_intr_r.intr = + |(field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value & field_storage.intr_block_rf.error_intr_en_r.error0_en.value) + || |(field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value & field_storage.intr_block_rf.error_intr_en_r.error1_en.value) + || |(field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value & field_storage.intr_block_rf.error_intr_en_r.error2_en.value) + || |(field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value & field_storage.intr_block_rf.error_intr_en_r.error3_en.value); + // Field: aes_clp_reg.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value; + load_next_c = '0; + if(field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value != '0) begin // stickybit + next_c = field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value | field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end else if(decoded_reg_strb.intr_block_rf.notif_internal_intr_r && decoded_req_is_wr) begin // SW write 1 clear + next_c = field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value & ~(decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end + field_combo.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.next = next_c; + field_combo.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value <= 1'h0; + end else if(field_combo.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.load_next) begin + field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value <= field_combo.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.next; + end + end + assign hwif_out.intr_block_rf.notif_internal_intr_r.intr = + |(field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value & field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value); + // Field: aes_clp_reg.intr_block_rf.error_intr_trig_r.error0_trig + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_trig_r && decoded_req_is_wr) begin // SW write 1 set + next_c = field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else begin // singlepulse clears back to 0 + next_c = '0; + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_trig_r.error0_trig.next = next_c; + field_combo.intr_block_rf.error_intr_trig_r.error0_trig.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_trig_r.error0_trig.load_next) begin + field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value <= field_combo.intr_block_rf.error_intr_trig_r.error0_trig.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_trig_r.error1_trig + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_trig_r && decoded_req_is_wr) begin // SW write 1 set + next_c = field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value | (decoded_wr_data[1:1] & decoded_wr_biten[1:1]); + load_next_c = '1; + end else begin // singlepulse clears back to 0 + next_c = '0; + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_trig_r.error1_trig.next = next_c; + field_combo.intr_block_rf.error_intr_trig_r.error1_trig.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_trig_r.error1_trig.load_next) begin + field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value <= field_combo.intr_block_rf.error_intr_trig_r.error1_trig.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_trig_r.error2_trig + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_trig_r && decoded_req_is_wr) begin // SW write 1 set + next_c = field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value | (decoded_wr_data[2:2] & decoded_wr_biten[2:2]); + load_next_c = '1; + end else begin // singlepulse clears back to 0 + next_c = '0; + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_trig_r.error2_trig.next = next_c; + field_combo.intr_block_rf.error_intr_trig_r.error2_trig.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_trig_r.error2_trig.load_next) begin + field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value <= field_combo.intr_block_rf.error_intr_trig_r.error2_trig.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error_intr_trig_r.error3_trig + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error_intr_trig_r && decoded_req_is_wr) begin // SW write 1 set + next_c = field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value | (decoded_wr_data[3:3] & decoded_wr_biten[3:3]); + load_next_c = '1; + end else begin // singlepulse clears back to 0 + next_c = '0; + load_next_c = '1; + end + field_combo.intr_block_rf.error_intr_trig_r.error3_trig.next = next_c; + field_combo.intr_block_rf.error_intr_trig_r.error3_trig.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value <= 1'h0; + end else if(field_combo.intr_block_rf.error_intr_trig_r.error3_trig.load_next) begin + field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value <= field_combo.intr_block_rf.error_intr_trig_r.error3_trig.next; + end + end + // Field: aes_clp_reg.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.notif_intr_trig_r && decoded_req_is_wr) begin // SW write 1 set + next_c = field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value | (decoded_wr_data[0:0] & decoded_wr_biten[0:0]); + load_next_c = '1; + end else begin // singlepulse clears back to 0 + next_c = '0; + load_next_c = '1; + end + field_combo.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.next = next_c; + field_combo.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value <= 1'h0; + end else if(field_combo.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.load_next) begin + field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value <= field_combo.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error0_intr_count_r.cnt + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error0_intr_count_r.cnt.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error0_intr_count_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error0_intr_count_r.cnt.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + if(field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value) begin // increment + if(((33)'(next_c) + 32'h1) > 32'hffffffff) begin // up-counter saturated + next_c = 32'hffffffff; + end else begin + next_c = next_c + 32'h1; + end + load_next_c = '1; + end + field_combo.intr_block_rf.error0_intr_count_r.cnt.incrthreshold = (field_storage.intr_block_rf.error0_intr_count_r.cnt.value >= 32'hffffffff); + field_combo.intr_block_rf.error0_intr_count_r.cnt.incrsaturate = (field_storage.intr_block_rf.error0_intr_count_r.cnt.value >= 32'hffffffff); + if(next_c > 32'hffffffff) begin + next_c = 32'hffffffff; + load_next_c = '1; + end + field_combo.intr_block_rf.error0_intr_count_r.cnt.next = next_c; + field_combo.intr_block_rf.error0_intr_count_r.cnt.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error0_intr_count_r.cnt.value <= 32'h0; + end else if(field_combo.intr_block_rf.error0_intr_count_r.cnt.load_next) begin + field_storage.intr_block_rf.error0_intr_count_r.cnt.value <= field_combo.intr_block_rf.error0_intr_count_r.cnt.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error1_intr_count_r.cnt + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error1_intr_count_r.cnt.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error1_intr_count_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error1_intr_count_r.cnt.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + if(field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value) begin // increment + if(((33)'(next_c) + 32'h1) > 32'hffffffff) begin // up-counter saturated + next_c = 32'hffffffff; + end else begin + next_c = next_c + 32'h1; + end + load_next_c = '1; + end + field_combo.intr_block_rf.error1_intr_count_r.cnt.incrthreshold = (field_storage.intr_block_rf.error1_intr_count_r.cnt.value >= 32'hffffffff); + field_combo.intr_block_rf.error1_intr_count_r.cnt.incrsaturate = (field_storage.intr_block_rf.error1_intr_count_r.cnt.value >= 32'hffffffff); + if(next_c > 32'hffffffff) begin + next_c = 32'hffffffff; + load_next_c = '1; + end + field_combo.intr_block_rf.error1_intr_count_r.cnt.next = next_c; + field_combo.intr_block_rf.error1_intr_count_r.cnt.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error1_intr_count_r.cnt.value <= 32'h0; + end else if(field_combo.intr_block_rf.error1_intr_count_r.cnt.load_next) begin + field_storage.intr_block_rf.error1_intr_count_r.cnt.value <= field_combo.intr_block_rf.error1_intr_count_r.cnt.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error2_intr_count_r.cnt + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error2_intr_count_r.cnt.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error2_intr_count_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error2_intr_count_r.cnt.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + if(field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value) begin // increment + if(((33)'(next_c) + 32'h1) > 32'hffffffff) begin // up-counter saturated + next_c = 32'hffffffff; + end else begin + next_c = next_c + 32'h1; + end + load_next_c = '1; + end + field_combo.intr_block_rf.error2_intr_count_r.cnt.incrthreshold = (field_storage.intr_block_rf.error2_intr_count_r.cnt.value >= 32'hffffffff); + field_combo.intr_block_rf.error2_intr_count_r.cnt.incrsaturate = (field_storage.intr_block_rf.error2_intr_count_r.cnt.value >= 32'hffffffff); + if(next_c > 32'hffffffff) begin + next_c = 32'hffffffff; + load_next_c = '1; + end + field_combo.intr_block_rf.error2_intr_count_r.cnt.next = next_c; + field_combo.intr_block_rf.error2_intr_count_r.cnt.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error2_intr_count_r.cnt.value <= 32'h0; + end else if(field_combo.intr_block_rf.error2_intr_count_r.cnt.load_next) begin + field_storage.intr_block_rf.error2_intr_count_r.cnt.value <= field_combo.intr_block_rf.error2_intr_count_r.cnt.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error3_intr_count_r.cnt + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error3_intr_count_r.cnt.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.error3_intr_count_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.error3_intr_count_r.cnt.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + if(field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value) begin // increment + if(((33)'(next_c) + 32'h1) > 32'hffffffff) begin // up-counter saturated + next_c = 32'hffffffff; + end else begin + next_c = next_c + 32'h1; + end + load_next_c = '1; + end + field_combo.intr_block_rf.error3_intr_count_r.cnt.incrthreshold = (field_storage.intr_block_rf.error3_intr_count_r.cnt.value >= 32'hffffffff); + field_combo.intr_block_rf.error3_intr_count_r.cnt.incrsaturate = (field_storage.intr_block_rf.error3_intr_count_r.cnt.value >= 32'hffffffff); + if(next_c > 32'hffffffff) begin + next_c = 32'hffffffff; + load_next_c = '1; + end + field_combo.intr_block_rf.error3_intr_count_r.cnt.next = next_c; + field_combo.intr_block_rf.error3_intr_count_r.cnt.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.error_reset_b) begin + if(~hwif_in.error_reset_b) begin + field_storage.intr_block_rf.error3_intr_count_r.cnt.value <= 32'h0; + end else if(field_combo.intr_block_rf.error3_intr_count_r.cnt.load_next) begin + field_storage.intr_block_rf.error3_intr_count_r.cnt.value <= field_combo.intr_block_rf.error3_intr_count_r.cnt.next; + end + end + // Field: aes_clp_reg.intr_block_rf.notif_cmd_done_intr_count_r.cnt + always_comb begin + automatic logic [31:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value; + load_next_c = '0; + if(decoded_reg_strb.intr_block_rf.notif_cmd_done_intr_count_r && decoded_req_is_wr) begin // SW write + next_c = (field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value & ~decoded_wr_biten[31:0]) | (decoded_wr_data[31:0] & decoded_wr_biten[31:0]); + load_next_c = '1; + end + if(field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value) begin // increment + if(((33)'(next_c) + 32'h1) > 32'hffffffff) begin // up-counter saturated + next_c = 32'hffffffff; + end else begin + next_c = next_c + 32'h1; + end + load_next_c = '1; + end + field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.incrthreshold = (field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value >= 32'hffffffff); + field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.incrsaturate = (field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value >= 32'hffffffff); + if(next_c > 32'hffffffff) begin + next_c = 32'hffffffff; + load_next_c = '1; + end + field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.next = next_c; + field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value <= 32'h0; + end else if(field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.load_next) begin + field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value <= field_combo.intr_block_rf.notif_cmd_done_intr_count_r.cnt.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error0_intr_count_incr_r.pulse + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value) begin // HW Write - we + next_c = field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error0_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end + if(field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value) begin // decrement + field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.underflow = (next_c < (1'h1)); + next_c = next_c - 1'h1; + load_next_c = '1; + end else begin + field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.underflow = '0; + end + field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.decrthreshold = (field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value <= 1'd0); + field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.next = next_c; + field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value <= 1'h0; + end else if(field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.load_next) begin + field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value <= field_combo.intr_block_rf.error0_intr_count_incr_r.pulse.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error1_intr_count_incr_r.pulse + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value) begin // HW Write - we + next_c = field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error1_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end + if(field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value) begin // decrement + field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.underflow = (next_c < (1'h1)); + next_c = next_c - 1'h1; + load_next_c = '1; + end else begin + field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.underflow = '0; + end + field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.decrthreshold = (field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value <= 1'd0); + field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.next = next_c; + field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value <= 1'h0; + end else if(field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.load_next) begin + field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value <= field_combo.intr_block_rf.error1_intr_count_incr_r.pulse.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error2_intr_count_incr_r.pulse + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value) begin // HW Write - we + next_c = field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error2_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end + if(field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value) begin // decrement + field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.underflow = (next_c < (1'h1)); + next_c = next_c - 1'h1; + load_next_c = '1; + end else begin + field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.underflow = '0; + end + field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.decrthreshold = (field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value <= 1'd0); + field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.next = next_c; + field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value <= 1'h0; + end else if(field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.load_next) begin + field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value <= field_combo.intr_block_rf.error2_intr_count_incr_r.pulse.next; + end + end + // Field: aes_clp_reg.intr_block_rf.error3_intr_count_incr_r.pulse + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value; + load_next_c = '0; + if(field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value) begin // HW Write - we + next_c = field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.error_internal_intr_r.error3_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end + if(field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value) begin // decrement + field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.underflow = (next_c < (1'h1)); + next_c = next_c - 1'h1; + load_next_c = '1; + end else begin + field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.underflow = '0; + end + field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.decrthreshold = (field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value <= 1'd0); + field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.next = next_c; + field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value <= 1'h0; + end else if(field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.load_next) begin + field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value <= field_combo.intr_block_rf.error3_intr_count_incr_r.pulse.next; + end + end + // Field: aes_clp_reg.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value; + load_next_c = '0; + if(field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value) begin // HW Write - we + next_c = field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value; + load_next_c = '1; + end else if(hwif_in.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.hwset) begin // HW Set + next_c = '1; + load_next_c = '1; + end + if(field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value) begin // decrement + field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.underflow = (next_c < (1'h1)); + next_c = next_c - 1'h1; + load_next_c = '1; + end else begin + field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.underflow = '0; + end + field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.decrthreshold = (field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value <= 1'd0); + field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.next = next_c; + field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value <= 1'h0; + end else if(field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.load_next) begin + field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value <= field_combo.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.next; + end + end + + //-------------------------------------------------------------------------- + // Write response + //-------------------------------------------------------------------------- + assign cpuif_wr_ack = decoded_req & decoded_req_is_wr; + // Writes are always granted with no error response + assign cpuif_wr_err = '0; + + //-------------------------------------------------------------------------- + // Readback + //-------------------------------------------------------------------------- + + logic readback_err; + logic readback_done; + logic [31:0] readback_data; + + // Assign readback values to a flattened array + logic [25-1:0][31:0] readback_array; + for(genvar i0=0; i0<2; i0++) begin + assign readback_array[i0*1 + 0][31:0] = (decoded_reg_strb.AES_NAME[i0] && !decoded_req_is_wr) ? hwif_in.AES_NAME[i0].NAME.next : '0; + end + for(genvar i0=0; i0<2; i0++) begin + assign readback_array[i0*1 + 2][31:0] = (decoded_reg_strb.AES_VERSION[i0] && !decoded_req_is_wr) ? hwif_in.AES_VERSION[i0].VERSION.next : '0; + end + assign readback_array[4][0:0] = (decoded_reg_strb.AES_KV_RD_KEY_CTRL && !decoded_req_is_wr) ? field_storage.AES_KV_RD_KEY_CTRL.read_en.value : '0; + assign readback_array[4][5:1] = (decoded_reg_strb.AES_KV_RD_KEY_CTRL && !decoded_req_is_wr) ? field_storage.AES_KV_RD_KEY_CTRL.read_entry.value : '0; + assign readback_array[4][6:6] = (decoded_reg_strb.AES_KV_RD_KEY_CTRL && !decoded_req_is_wr) ? field_storage.AES_KV_RD_KEY_CTRL.pcr_hash_extend.value : '0; + assign readback_array[4][31:7] = (decoded_reg_strb.AES_KV_RD_KEY_CTRL && !decoded_req_is_wr) ? field_storage.AES_KV_RD_KEY_CTRL.rsvd.value : '0; + assign readback_array[5][0:0] = (decoded_reg_strb.AES_KV_RD_KEY_STATUS && !decoded_req_is_wr) ? hwif_in.AES_KV_RD_KEY_STATUS.READY.next : '0; + assign readback_array[5][1:1] = (decoded_reg_strb.AES_KV_RD_KEY_STATUS && !decoded_req_is_wr) ? field_storage.AES_KV_RD_KEY_STATUS.VALID.value : '0; + assign readback_array[5][9:2] = (decoded_reg_strb.AES_KV_RD_KEY_STATUS && !decoded_req_is_wr) ? hwif_in.AES_KV_RD_KEY_STATUS.ERROR.next : '0; + assign readback_array[5][31:10] = '0; + assign readback_array[6][0:0] = (decoded_reg_strb.intr_block_rf.global_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.global_intr_en_r.error_en.value : '0; + assign readback_array[6][1:1] = (decoded_reg_strb.intr_block_rf.global_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.global_intr_en_r.notif_en.value : '0; + assign readback_array[6][31:2] = '0; + assign readback_array[7][0:0] = (decoded_reg_strb.intr_block_rf.error_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_en_r.error0_en.value : '0; + assign readback_array[7][1:1] = (decoded_reg_strb.intr_block_rf.error_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_en_r.error1_en.value : '0; + assign readback_array[7][2:2] = (decoded_reg_strb.intr_block_rf.error_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_en_r.error2_en.value : '0; + assign readback_array[7][3:3] = (decoded_reg_strb.intr_block_rf.error_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_en_r.error3_en.value : '0; + assign readback_array[7][31:4] = '0; + assign readback_array[8][0:0] = (decoded_reg_strb.intr_block_rf.notif_intr_en_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_intr_en_r.notif_cmd_done_en.value : '0; + assign readback_array[8][31:1] = '0; + assign readback_array[9][0:0] = (decoded_reg_strb.intr_block_rf.error_global_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_global_intr_r.agg_sts.value : '0; + assign readback_array[9][31:1] = '0; + assign readback_array[10][0:0] = (decoded_reg_strb.intr_block_rf.notif_global_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_global_intr_r.agg_sts.value : '0; + assign readback_array[10][31:1] = '0; + assign readback_array[11][0:0] = (decoded_reg_strb.intr_block_rf.error_internal_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_internal_intr_r.error0_sts.value : '0; + assign readback_array[11][1:1] = (decoded_reg_strb.intr_block_rf.error_internal_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_internal_intr_r.error1_sts.value : '0; + assign readback_array[11][2:2] = (decoded_reg_strb.intr_block_rf.error_internal_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_internal_intr_r.error2_sts.value : '0; + assign readback_array[11][3:3] = (decoded_reg_strb.intr_block_rf.error_internal_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_internal_intr_r.error3_sts.value : '0; + assign readback_array[11][31:4] = '0; + assign readback_array[12][0:0] = (decoded_reg_strb.intr_block_rf.notif_internal_intr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.value : '0; + assign readback_array[12][31:1] = '0; + assign readback_array[13][0:0] = (decoded_reg_strb.intr_block_rf.error_intr_trig_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_trig_r.error0_trig.value : '0; + assign readback_array[13][1:1] = (decoded_reg_strb.intr_block_rf.error_intr_trig_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_trig_r.error1_trig.value : '0; + assign readback_array[13][2:2] = (decoded_reg_strb.intr_block_rf.error_intr_trig_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_trig_r.error2_trig.value : '0; + assign readback_array[13][3:3] = (decoded_reg_strb.intr_block_rf.error_intr_trig_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error_intr_trig_r.error3_trig.value : '0; + assign readback_array[13][31:4] = '0; + assign readback_array[14][0:0] = (decoded_reg_strb.intr_block_rf.notif_intr_trig_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_intr_trig_r.notif_cmd_done_trig.value : '0; + assign readback_array[14][31:1] = '0; + assign readback_array[15][31:0] = (decoded_reg_strb.intr_block_rf.error0_intr_count_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error0_intr_count_r.cnt.value : '0; + assign readback_array[16][31:0] = (decoded_reg_strb.intr_block_rf.error1_intr_count_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error1_intr_count_r.cnt.value : '0; + assign readback_array[17][31:0] = (decoded_reg_strb.intr_block_rf.error2_intr_count_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error2_intr_count_r.cnt.value : '0; + assign readback_array[18][31:0] = (decoded_reg_strb.intr_block_rf.error3_intr_count_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error3_intr_count_r.cnt.value : '0; + assign readback_array[19][31:0] = (decoded_reg_strb.intr_block_rf.notif_cmd_done_intr_count_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_cmd_done_intr_count_r.cnt.value : '0; + assign readback_array[20][0:0] = (decoded_reg_strb.intr_block_rf.error0_intr_count_incr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error0_intr_count_incr_r.pulse.value : '0; + assign readback_array[20][31:1] = '0; + assign readback_array[21][0:0] = (decoded_reg_strb.intr_block_rf.error1_intr_count_incr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error1_intr_count_incr_r.pulse.value : '0; + assign readback_array[21][31:1] = '0; + assign readback_array[22][0:0] = (decoded_reg_strb.intr_block_rf.error2_intr_count_incr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error2_intr_count_incr_r.pulse.value : '0; + assign readback_array[22][31:1] = '0; + assign readback_array[23][0:0] = (decoded_reg_strb.intr_block_rf.error3_intr_count_incr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.error3_intr_count_incr_r.pulse.value : '0; + assign readback_array[23][31:1] = '0; + assign readback_array[24][0:0] = (decoded_reg_strb.intr_block_rf.notif_cmd_done_intr_count_incr_r && !decoded_req_is_wr) ? field_storage.intr_block_rf.notif_cmd_done_intr_count_incr_r.pulse.value : '0; + assign readback_array[24][31:1] = '0; + + // Reduce the array + always_comb begin + automatic logic [31:0] readback_data_var; + readback_done = decoded_req & ~decoded_req_is_wr; + readback_err = '0; + readback_data_var = '0; + for(int i=0; i<25; i++) readback_data_var |= readback_array[i]; + readback_data = readback_data_var; + end + + assign cpuif_rd_ack = readback_done; + assign cpuif_rd_data = readback_data; + assign cpuif_rd_err = readback_err; + +`CALIPTRA_ASSERT_KNOWN(ERR_HWIF_IN, hwif_in, clk, !hwif_in.error_reset_b) + +endmodule diff --git a/src/aes/rtl/aes_clp_reg_pkg.sv b/src/aes/rtl/aes_clp_reg_pkg.sv new file mode 100644 index 000000000..92018f9e8 --- /dev/null +++ b/src/aes/rtl/aes_clp_reg_pkg.sv @@ -0,0 +1,157 @@ +// Generated by PeakRDL-regblock - A free and open-source SystemVerilog generator +// https://github.com/SystemRDL/PeakRDL-regblock + +package aes_clp_reg_pkg; + + localparam AES_CLP_REG_DATA_WIDTH = 32; + localparam AES_CLP_REG_MIN_ADDR_WIDTH = 12; + + typedef struct packed{ + logic [31:0] next; + } aes_clp_reg__AES_NAME__NAME__in_t; + + typedef struct packed{ + aes_clp_reg__AES_NAME__NAME__in_t NAME; + } aes_clp_reg__AES_NAME__in_t; + + typedef struct packed{ + logic [31:0] next; + } aes_clp_reg__AES_VERSION__VERSION__in_t; + + typedef struct packed{ + aes_clp_reg__AES_VERSION__VERSION__in_t VERSION; + } aes_clp_reg__AES_VERSION__in_t; + + typedef struct packed{ + logic hwclr; + } kv_read_ctrl_reg__read_en__in_t; + + typedef struct packed{ + kv_read_ctrl_reg__read_en__in_t read_en; + } kv_read_ctrl_reg__in_t; + + typedef struct packed{ + logic next; + } kv_status_reg__READY__in_t; + + typedef struct packed{ + logic hwclr; + logic hwset; + } kv_status_reg__VALID__in_t; + + typedef struct packed{ + logic [7:0] next; + } kv_status_reg__ERROR__in_t; + + typedef struct packed{ + kv_status_reg__READY__in_t READY; + kv_status_reg__VALID__in_t VALID; + kv_status_reg__ERROR__in_t ERROR; + } kv_status_reg__in_t; + + typedef struct packed{ + logic hwset; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error0_sts_enable_528ccada_next_b1018582_resetsignal_939e99d4__in_t; + + typedef struct packed{ + logic hwset; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error1_sts_enable_938cafef_next_f460eb81_resetsignal_939e99d4__in_t; + + typedef struct packed{ + logic hwset; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error2_sts_enable_0dacf7a6_next_4b5b9e74_resetsignal_939e99d4__in_t; + + typedef struct packed{ + logic hwset; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error3_sts_enable_fc3af94b_next_c3125d40_resetsignal_939e99d4__in_t; + + typedef struct packed{ + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error0_sts_enable_528ccada_next_b1018582_resetsignal_939e99d4__in_t error0_sts; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error1_sts_enable_938cafef_next_f460eb81_resetsignal_939e99d4__in_t error1_sts; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error2_sts_enable_0dacf7a6_next_4b5b9e74_resetsignal_939e99d4__in_t error2_sts; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__error3_sts_enable_fc3af94b_next_c3125d40_resetsignal_939e99d4__in_t error3_sts; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__in_t; + + typedef struct packed{ + logic hwset; + } aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__notif_cmd_done_sts_enable_dabe0b8b_next_540fa3b7__in_t; + + typedef struct packed{ + aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__notif_cmd_done_sts_enable_dabe0b8b_next_540fa3b7__in_t notif_cmd_done_sts; + } aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__in_t; + + typedef struct packed{ + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__in_t error_internal_intr_r; + aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__in_t notif_internal_intr_r; + } aes_clp_reg__intr_block_t__in_t; + + typedef struct packed{ + logic reset_b; + logic error_reset_b; + aes_clp_reg__AES_NAME__in_t [2-1:0]AES_NAME; + aes_clp_reg__AES_VERSION__in_t [2-1:0]AES_VERSION; + kv_read_ctrl_reg__in_t AES_KV_RD_KEY_CTRL; + kv_status_reg__in_t AES_KV_RD_KEY_STATUS; + aes_clp_reg__intr_block_t__in_t intr_block_rf; + } aes_clp_reg__in_t; + + typedef struct packed{ + logic value; + } kv_read_ctrl_reg__read_en__out_t; + + typedef struct packed{ + logic [4:0] value; + } kv_read_ctrl_reg__read_entry__out_t; + + typedef struct packed{ + logic value; + } kv_read_ctrl_reg__pcr_hash_extend__out_t; + + typedef struct packed{ + logic [24:0] value; + } kv_read_ctrl_reg__rsvd__out_t; + + typedef struct packed{ + kv_read_ctrl_reg__read_en__out_t read_en; + kv_read_ctrl_reg__read_entry__out_t read_entry; + kv_read_ctrl_reg__pcr_hash_extend__out_t pcr_hash_extend; + kv_read_ctrl_reg__rsvd__out_t rsvd; + } kv_read_ctrl_reg__out_t; + + typedef struct packed{ + logic intr; + } aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a__out_t; + + typedef struct packed{ + logic intr; + } aes_clp_reg__global_intr_t_agg_sts_e6399b4a__out_t; + + typedef struct packed{ + logic intr; + } aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__out_t; + + typedef struct packed{ + logic intr; + } aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__out_t; + + typedef struct packed{ + aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a__out_t error_global_intr_r; + aes_clp_reg__global_intr_t_agg_sts_e6399b4a__out_t notif_global_intr_r; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378__out_t error_internal_intr_r; + aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e__out_t notif_internal_intr_r; + } aes_clp_reg__intr_block_t__out_t; + + typedef struct packed{ + kv_read_ctrl_reg__out_t AES_KV_RD_KEY_CTRL; + aes_clp_reg__intr_block_t__out_t intr_block_rf; + } aes_clp_reg__out_t; + + typedef enum logic [31:0] { + kv_status_reg__ERROR__kv_error_e__SUCCESS = 'h0, + kv_status_reg__ERROR__kv_error_e__KV_READ_FAIL = 'h1, + kv_status_reg__ERROR__kv_error_e__KV_WRITE_FAIL = 'h2 + } kv_status_reg__ERROR__kv_error_e_e; + + localparam AES_CLP_REG_ADDR_WIDTH = 32'd12; + +endpackage \ No newline at end of file diff --git a/src/aes/rtl/aes_clp_reg_uvm.sv b/src/aes/rtl/aes_clp_reg_uvm.sv new file mode 100644 index 000000000..3c0fa1194 --- /dev/null +++ b/src/aes/rtl/aes_clp_reg_uvm.sv @@ -0,0 +1,944 @@ + +// This file was autogenerated by PeakRDL-uvm +package aes_clp_reg_uvm; + `include "uvm_macros.svh" + import uvm_pkg::*; + `include "aes_clp_reg_covergroups.svh" + // Reg - aes_clp_reg::AES_NAME + class aes_clp_reg__AES_NAME extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__AES_NAME_bit_cg NAME_bit_cg[32]; + aes_clp_reg__AES_NAME_fld_cg fld_cg; + rand uvm_reg_field NAME; + + function new(string name = "aes_clp_reg__AES_NAME"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.NAME = new("NAME"); + this.NAME.configure(this, 32, 0, "RO", 1, 'h0, 0, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(NAME_bit_cg[bt]) NAME_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__AES_NAME + + // Reg - aes_clp_reg::AES_VERSION + class aes_clp_reg__AES_VERSION extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__AES_VERSION_bit_cg VERSION_bit_cg[32]; + aes_clp_reg__AES_VERSION_fld_cg fld_cg; + rand uvm_reg_field VERSION; + + function new(string name = "aes_clp_reg__AES_VERSION"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.VERSION = new("VERSION"); + this.VERSION.configure(this, 32, 0, "RO", 1, 'h0, 0, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(VERSION_bit_cg[bt]) VERSION_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__AES_VERSION + + // Reg - kv_read_ctrl_reg + class kv_read_ctrl_reg extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + kv_read_ctrl_reg_bit_cg read_en_bit_cg[1]; + kv_read_ctrl_reg_bit_cg read_entry_bit_cg[5]; + kv_read_ctrl_reg_bit_cg pcr_hash_extend_bit_cg[1]; + kv_read_ctrl_reg_bit_cg rsvd_bit_cg[25]; + kv_read_ctrl_reg_fld_cg fld_cg; + rand uvm_reg_field read_en; + rand uvm_reg_field read_entry; + rand uvm_reg_field pcr_hash_extend; + rand uvm_reg_field rsvd; + + function new(string name = "kv_read_ctrl_reg"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.read_en = new("read_en"); + this.read_en.configure(this, 1, 0, "RW", 1, 'h0, 1, 1, 0); + this.read_entry = new("read_entry"); + this.read_entry.configure(this, 5, 1, "RW", 0, 'h0, 1, 1, 0); + this.pcr_hash_extend = new("pcr_hash_extend"); + this.pcr_hash_extend.configure(this, 1, 6, "RW", 0, 'h0, 1, 1, 0); + this.rsvd = new("rsvd"); + this.rsvd.configure(this, 25, 7, "RW", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(read_en_bit_cg[bt]) read_en_bit_cg[bt] = new(); + foreach(read_entry_bit_cg[bt]) read_entry_bit_cg[bt] = new(); + foreach(pcr_hash_extend_bit_cg[bt]) pcr_hash_extend_bit_cg[bt] = new(); + foreach(rsvd_bit_cg[bt]) rsvd_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : kv_read_ctrl_reg + + // Reg - kv_status_reg + class kv_status_reg extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + kv_status_reg_bit_cg READY_bit_cg[1]; + kv_status_reg_bit_cg VALID_bit_cg[1]; + kv_status_reg_bit_cg ERROR_bit_cg[8]; + kv_status_reg_fld_cg fld_cg; + rand uvm_reg_field READY; + rand uvm_reg_field VALID; + rand uvm_reg_field ERROR; + + function new(string name = "kv_status_reg"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.READY = new("READY"); + this.READY.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + this.VALID = new("VALID"); + this.VALID.configure(this, 1, 1, "RO", 1, 'h0, 1, 1, 0); + this.ERROR = new("ERROR"); + this.ERROR.configure(this, 8, 2, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(READY_bit_cg[bt]) READY_bit_cg[bt] = new(); + foreach(VALID_bit_cg[bt]) VALID_bit_cg[bt] = new(); + foreach(ERROR_bit_cg[bt]) ERROR_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : kv_status_reg + + // Reg - aes_clp_reg::global_intr_en_t + class aes_clp_reg__global_intr_en_t extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__global_intr_en_t_bit_cg error_en_bit_cg[1]; + aes_clp_reg__global_intr_en_t_bit_cg notif_en_bit_cg[1]; + aes_clp_reg__global_intr_en_t_fld_cg fld_cg; + rand uvm_reg_field error_en; + rand uvm_reg_field notif_en; + + function new(string name = "aes_clp_reg__global_intr_en_t"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.error_en = new("error_en"); + this.error_en.configure(this, 1, 0, "RW", 0, 'h0, 1, 1, 0); + this.notif_en = new("notif_en"); + this.notif_en.configure(this, 1, 1, "RW", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(error_en_bit_cg[bt]) error_en_bit_cg[bt] = new(); + foreach(notif_en_bit_cg[bt]) notif_en_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__global_intr_en_t + + // Reg - aes_clp_reg::error_intr_en_t + class aes_clp_reg__error_intr_en_t extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__error_intr_en_t_bit_cg error0_en_bit_cg[1]; + aes_clp_reg__error_intr_en_t_bit_cg error1_en_bit_cg[1]; + aes_clp_reg__error_intr_en_t_bit_cg error2_en_bit_cg[1]; + aes_clp_reg__error_intr_en_t_bit_cg error3_en_bit_cg[1]; + aes_clp_reg__error_intr_en_t_fld_cg fld_cg; + rand uvm_reg_field error0_en; + rand uvm_reg_field error1_en; + rand uvm_reg_field error2_en; + rand uvm_reg_field error3_en; + + function new(string name = "aes_clp_reg__error_intr_en_t"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.error0_en = new("error0_en"); + this.error0_en.configure(this, 1, 0, "RW", 0, 'h0, 1, 1, 0); + this.error1_en = new("error1_en"); + this.error1_en.configure(this, 1, 1, "RW", 0, 'h0, 1, 1, 0); + this.error2_en = new("error2_en"); + this.error2_en.configure(this, 1, 2, "RW", 0, 'h0, 1, 1, 0); + this.error3_en = new("error3_en"); + this.error3_en.configure(this, 1, 3, "RW", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(error0_en_bit_cg[bt]) error0_en_bit_cg[bt] = new(); + foreach(error1_en_bit_cg[bt]) error1_en_bit_cg[bt] = new(); + foreach(error2_en_bit_cg[bt]) error2_en_bit_cg[bt] = new(); + foreach(error3_en_bit_cg[bt]) error3_en_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__error_intr_en_t + + // Reg - aes_clp_reg::notif_intr_en_t + class aes_clp_reg__notif_intr_en_t extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__notif_intr_en_t_bit_cg notif_cmd_done_en_bit_cg[1]; + aes_clp_reg__notif_intr_en_t_fld_cg fld_cg; + rand uvm_reg_field notif_cmd_done_en; + + function new(string name = "aes_clp_reg__notif_intr_en_t"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.notif_cmd_done_en = new("notif_cmd_done_en"); + this.notif_cmd_done_en.configure(this, 1, 0, "RW", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(notif_cmd_done_en_bit_cg[bt]) notif_cmd_done_en_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__notif_intr_en_t + + // Reg - aes_clp_reg::global_intr_t_agg_sts_dd3dcf0a + class aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a_bit_cg agg_sts_bit_cg[1]; + aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a_fld_cg fld_cg; + rand uvm_reg_field agg_sts; + + function new(string name = "aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.agg_sts = new("agg_sts"); + this.agg_sts.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(agg_sts_bit_cg[bt]) agg_sts_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a + + // Reg - aes_clp_reg::global_intr_t_agg_sts_e6399b4a + class aes_clp_reg__global_intr_t_agg_sts_e6399b4a extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__global_intr_t_agg_sts_e6399b4a_bit_cg agg_sts_bit_cg[1]; + aes_clp_reg__global_intr_t_agg_sts_e6399b4a_fld_cg fld_cg; + rand uvm_reg_field agg_sts; + + function new(string name = "aes_clp_reg__global_intr_t_agg_sts_e6399b4a"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.agg_sts = new("agg_sts"); + this.agg_sts.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(agg_sts_bit_cg[bt]) agg_sts_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__global_intr_t_agg_sts_e6399b4a + + // Reg - aes_clp_reg::error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378 + class aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378_bit_cg error0_sts_bit_cg[1]; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378_bit_cg error1_sts_bit_cg[1]; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378_bit_cg error2_sts_bit_cg[1]; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378_bit_cg error3_sts_bit_cg[1]; + aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378_fld_cg fld_cg; + rand uvm_reg_field error0_sts; + rand uvm_reg_field error1_sts; + rand uvm_reg_field error2_sts; + rand uvm_reg_field error3_sts; + + function new(string name = "aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.error0_sts = new("error0_sts"); + this.error0_sts.configure(this, 1, 0, "W1C", 1, 'h0, 1, 1, 0); + this.error1_sts = new("error1_sts"); + this.error1_sts.configure(this, 1, 1, "W1C", 1, 'h0, 1, 1, 0); + this.error2_sts = new("error2_sts"); + this.error2_sts.configure(this, 1, 2, "W1C", 1, 'h0, 1, 1, 0); + this.error3_sts = new("error3_sts"); + this.error3_sts.configure(this, 1, 3, "W1C", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(error0_sts_bit_cg[bt]) error0_sts_bit_cg[bt] = new(); + foreach(error1_sts_bit_cg[bt]) error1_sts_bit_cg[bt] = new(); + foreach(error2_sts_bit_cg[bt]) error2_sts_bit_cg[bt] = new(); + foreach(error3_sts_bit_cg[bt]) error3_sts_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378 + + // Reg - aes_clp_reg::notif_intr_t_notif_cmd_done_sts_1c68637e + class aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e_bit_cg notif_cmd_done_sts_bit_cg[1]; + aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e_fld_cg fld_cg; + rand uvm_reg_field notif_cmd_done_sts; + + function new(string name = "aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.notif_cmd_done_sts = new("notif_cmd_done_sts"); + this.notif_cmd_done_sts.configure(this, 1, 0, "W1C", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(notif_cmd_done_sts_bit_cg[bt]) notif_cmd_done_sts_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e + + // Reg - aes_clp_reg::error_intr_trig_t + class aes_clp_reg__error_intr_trig_t extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__error_intr_trig_t_bit_cg error0_trig_bit_cg[1]; + aes_clp_reg__error_intr_trig_t_bit_cg error1_trig_bit_cg[1]; + aes_clp_reg__error_intr_trig_t_bit_cg error2_trig_bit_cg[1]; + aes_clp_reg__error_intr_trig_t_bit_cg error3_trig_bit_cg[1]; + aes_clp_reg__error_intr_trig_t_fld_cg fld_cg; + rand uvm_reg_field error0_trig; + rand uvm_reg_field error1_trig; + rand uvm_reg_field error2_trig; + rand uvm_reg_field error3_trig; + + function new(string name = "aes_clp_reg__error_intr_trig_t"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.error0_trig = new("error0_trig"); + this.error0_trig.configure(this, 1, 0, "W1S", 0, 'h0, 1, 1, 0); + this.error1_trig = new("error1_trig"); + this.error1_trig.configure(this, 1, 1, "W1S", 0, 'h0, 1, 1, 0); + this.error2_trig = new("error2_trig"); + this.error2_trig.configure(this, 1, 2, "W1S", 0, 'h0, 1, 1, 0); + this.error3_trig = new("error3_trig"); + this.error3_trig.configure(this, 1, 3, "W1S", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(error0_trig_bit_cg[bt]) error0_trig_bit_cg[bt] = new(); + foreach(error1_trig_bit_cg[bt]) error1_trig_bit_cg[bt] = new(); + foreach(error2_trig_bit_cg[bt]) error2_trig_bit_cg[bt] = new(); + foreach(error3_trig_bit_cg[bt]) error3_trig_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__error_intr_trig_t + + // Reg - aes_clp_reg::notif_intr_trig_t + class aes_clp_reg__notif_intr_trig_t extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__notif_intr_trig_t_bit_cg notif_cmd_done_trig_bit_cg[1]; + aes_clp_reg__notif_intr_trig_t_fld_cg fld_cg; + rand uvm_reg_field notif_cmd_done_trig; + + function new(string name = "aes_clp_reg__notif_intr_trig_t"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.notif_cmd_done_trig = new("notif_cmd_done_trig"); + this.notif_cmd_done_trig.configure(this, 1, 0, "W1S", 0, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(notif_cmd_done_trig_bit_cg[bt]) notif_cmd_done_trig_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__notif_intr_trig_t + + // Reg - aes_clp_reg::intr_count_t_cnt_35ace267 + class aes_clp_reg__intr_count_t_cnt_35ace267 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_t_cnt_35ace267_bit_cg cnt_bit_cg[32]; + aes_clp_reg__intr_count_t_cnt_35ace267_fld_cg fld_cg; + rand uvm_reg_field cnt; + + function new(string name = "aes_clp_reg__intr_count_t_cnt_35ace267"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.cnt = new("cnt"); + this.cnt.configure(this, 32, 0, "RW", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(cnt_bit_cg[bt]) cnt_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_t_cnt_35ace267 + + // Reg - aes_clp_reg::intr_count_t_cnt_73c42c28 + class aes_clp_reg__intr_count_t_cnt_73c42c28 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_t_cnt_73c42c28_bit_cg cnt_bit_cg[32]; + aes_clp_reg__intr_count_t_cnt_73c42c28_fld_cg fld_cg; + rand uvm_reg_field cnt; + + function new(string name = "aes_clp_reg__intr_count_t_cnt_73c42c28"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.cnt = new("cnt"); + this.cnt.configure(this, 32, 0, "RW", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(cnt_bit_cg[bt]) cnt_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_t_cnt_73c42c28 + + // Reg - aes_clp_reg::intr_count_t_cnt_d8af96ff + class aes_clp_reg__intr_count_t_cnt_d8af96ff extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_t_cnt_d8af96ff_bit_cg cnt_bit_cg[32]; + aes_clp_reg__intr_count_t_cnt_d8af96ff_fld_cg fld_cg; + rand uvm_reg_field cnt; + + function new(string name = "aes_clp_reg__intr_count_t_cnt_d8af96ff"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.cnt = new("cnt"); + this.cnt.configure(this, 32, 0, "RW", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(cnt_bit_cg[bt]) cnt_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_t_cnt_d8af96ff + + // Reg - aes_clp_reg::intr_count_t_cnt_9bd7f809 + class aes_clp_reg__intr_count_t_cnt_9bd7f809 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_t_cnt_9bd7f809_bit_cg cnt_bit_cg[32]; + aes_clp_reg__intr_count_t_cnt_9bd7f809_fld_cg fld_cg; + rand uvm_reg_field cnt; + + function new(string name = "aes_clp_reg__intr_count_t_cnt_9bd7f809"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.cnt = new("cnt"); + this.cnt.configure(this, 32, 0, "RW", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(cnt_bit_cg[bt]) cnt_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_t_cnt_9bd7f809 + + // Reg - aes_clp_reg::intr_count_t_cnt_be67d6d5 + class aes_clp_reg__intr_count_t_cnt_be67d6d5 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_t_cnt_be67d6d5_bit_cg cnt_bit_cg[32]; + aes_clp_reg__intr_count_t_cnt_be67d6d5_fld_cg fld_cg; + rand uvm_reg_field cnt; + + function new(string name = "aes_clp_reg__intr_count_t_cnt_be67d6d5"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.cnt = new("cnt"); + this.cnt.configure(this, 32, 0, "RW", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(cnt_bit_cg[bt]) cnt_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_t_cnt_be67d6d5 + + // Reg - aes_clp_reg::intr_count_incr_t_pulse_37026c97 + class aes_clp_reg__intr_count_incr_t_pulse_37026c97 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_incr_t_pulse_37026c97_bit_cg pulse_bit_cg[1]; + aes_clp_reg__intr_count_incr_t_pulse_37026c97_fld_cg fld_cg; + rand uvm_reg_field pulse; + + function new(string name = "aes_clp_reg__intr_count_incr_t_pulse_37026c97"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.pulse = new("pulse"); + this.pulse.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(pulse_bit_cg[bt]) pulse_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_incr_t_pulse_37026c97 + + // Reg - aes_clp_reg::intr_count_incr_t_pulse_d860d977 + class aes_clp_reg__intr_count_incr_t_pulse_d860d977 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_incr_t_pulse_d860d977_bit_cg pulse_bit_cg[1]; + aes_clp_reg__intr_count_incr_t_pulse_d860d977_fld_cg fld_cg; + rand uvm_reg_field pulse; + + function new(string name = "aes_clp_reg__intr_count_incr_t_pulse_d860d977"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.pulse = new("pulse"); + this.pulse.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(pulse_bit_cg[bt]) pulse_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_incr_t_pulse_d860d977 + + // Reg - aes_clp_reg::intr_count_incr_t_pulse_87b45fe7 + class aes_clp_reg__intr_count_incr_t_pulse_87b45fe7 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_incr_t_pulse_87b45fe7_bit_cg pulse_bit_cg[1]; + aes_clp_reg__intr_count_incr_t_pulse_87b45fe7_fld_cg fld_cg; + rand uvm_reg_field pulse; + + function new(string name = "aes_clp_reg__intr_count_incr_t_pulse_87b45fe7"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.pulse = new("pulse"); + this.pulse.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(pulse_bit_cg[bt]) pulse_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_incr_t_pulse_87b45fe7 + + // Reg - aes_clp_reg::intr_count_incr_t_pulse_c1689ee6 + class aes_clp_reg__intr_count_incr_t_pulse_c1689ee6 extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_incr_t_pulse_c1689ee6_bit_cg pulse_bit_cg[1]; + aes_clp_reg__intr_count_incr_t_pulse_c1689ee6_fld_cg fld_cg; + rand uvm_reg_field pulse; + + function new(string name = "aes_clp_reg__intr_count_incr_t_pulse_c1689ee6"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.pulse = new("pulse"); + this.pulse.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(pulse_bit_cg[bt]) pulse_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_incr_t_pulse_c1689ee6 + + // Reg - aes_clp_reg::intr_count_incr_t_pulse_6173128e + class aes_clp_reg__intr_count_incr_t_pulse_6173128e extends uvm_reg; + protected uvm_reg_data_t m_current; + protected uvm_reg_data_t m_data; + protected bit m_is_read; + + aes_clp_reg__intr_count_incr_t_pulse_6173128e_bit_cg pulse_bit_cg[1]; + aes_clp_reg__intr_count_incr_t_pulse_6173128e_fld_cg fld_cg; + rand uvm_reg_field pulse; + + function new(string name = "aes_clp_reg__intr_count_incr_t_pulse_6173128e"); + super.new(name, 32, build_coverage(UVM_CVR_ALL)); + endfunction : new + extern virtual function void sample_values(); + extern protected virtual function void sample(uvm_reg_data_t data, + uvm_reg_data_t byte_en, + bit is_read, + uvm_reg_map map); + + virtual function void build(); + this.pulse = new("pulse"); + this.pulse.configure(this, 1, 0, "RO", 1, 'h0, 1, 1, 0); + if (has_coverage(UVM_CVR_REG_BITS)) begin + foreach(pulse_bit_cg[bt]) pulse_bit_cg[bt] = new(); + end + if (has_coverage(UVM_CVR_FIELD_VALS)) + fld_cg = new(); + endfunction : build + endclass : aes_clp_reg__intr_count_incr_t_pulse_6173128e + + // Regfile - aes_clp_reg::intr_block_t + class aes_clp_reg__intr_block_t extends uvm_reg_block; + rand aes_clp_reg__global_intr_en_t global_intr_en_r; + rand aes_clp_reg__error_intr_en_t error_intr_en_r; + rand aes_clp_reg__notif_intr_en_t notif_intr_en_r; + rand aes_clp_reg__global_intr_t_agg_sts_dd3dcf0a error_global_intr_r; + rand aes_clp_reg__global_intr_t_agg_sts_e6399b4a notif_global_intr_r; + rand aes_clp_reg__error_intr_t_error0_sts_28545624_error1_sts_40e0d3e1_error2_sts_b1cf2205_error3_sts_74a35378 error_internal_intr_r; + rand aes_clp_reg__notif_intr_t_notif_cmd_done_sts_1c68637e notif_internal_intr_r; + rand aes_clp_reg__error_intr_trig_t error_intr_trig_r; + rand aes_clp_reg__notif_intr_trig_t notif_intr_trig_r; + rand aes_clp_reg__intr_count_t_cnt_35ace267 error0_intr_count_r; + rand aes_clp_reg__intr_count_t_cnt_73c42c28 error1_intr_count_r; + rand aes_clp_reg__intr_count_t_cnt_d8af96ff error2_intr_count_r; + rand aes_clp_reg__intr_count_t_cnt_9bd7f809 error3_intr_count_r; + rand aes_clp_reg__intr_count_t_cnt_be67d6d5 notif_cmd_done_intr_count_r; + rand aes_clp_reg__intr_count_incr_t_pulse_37026c97 error0_intr_count_incr_r; + rand aes_clp_reg__intr_count_incr_t_pulse_d860d977 error1_intr_count_incr_r; + rand aes_clp_reg__intr_count_incr_t_pulse_87b45fe7 error2_intr_count_incr_r; + rand aes_clp_reg__intr_count_incr_t_pulse_c1689ee6 error3_intr_count_incr_r; + rand aes_clp_reg__intr_count_incr_t_pulse_6173128e notif_cmd_done_intr_count_incr_r; + + function new(string name = "aes_clp_reg__intr_block_t"); + super.new(name); + endfunction : new + + virtual function void build(); + this.default_map = create_map("reg_map", 0, 4, UVM_NO_ENDIAN); + this.global_intr_en_r = new("global_intr_en_r"); + this.global_intr_en_r.configure(this); + + this.global_intr_en_r.build(); + this.default_map.add_reg(this.global_intr_en_r, 'h0); + this.error_intr_en_r = new("error_intr_en_r"); + this.error_intr_en_r.configure(this); + + this.error_intr_en_r.build(); + this.default_map.add_reg(this.error_intr_en_r, 'h4); + this.notif_intr_en_r = new("notif_intr_en_r"); + this.notif_intr_en_r.configure(this); + + this.notif_intr_en_r.build(); + this.default_map.add_reg(this.notif_intr_en_r, 'h8); + this.error_global_intr_r = new("error_global_intr_r"); + this.error_global_intr_r.configure(this); + + this.error_global_intr_r.build(); + this.default_map.add_reg(this.error_global_intr_r, 'hc); + this.notif_global_intr_r = new("notif_global_intr_r"); + this.notif_global_intr_r.configure(this); + + this.notif_global_intr_r.build(); + this.default_map.add_reg(this.notif_global_intr_r, 'h10); + this.error_internal_intr_r = new("error_internal_intr_r"); + this.error_internal_intr_r.configure(this); + + this.error_internal_intr_r.build(); + this.default_map.add_reg(this.error_internal_intr_r, 'h14); + this.notif_internal_intr_r = new("notif_internal_intr_r"); + this.notif_internal_intr_r.configure(this); + + this.notif_internal_intr_r.build(); + this.default_map.add_reg(this.notif_internal_intr_r, 'h18); + this.error_intr_trig_r = new("error_intr_trig_r"); + this.error_intr_trig_r.configure(this); + + this.error_intr_trig_r.build(); + this.default_map.add_reg(this.error_intr_trig_r, 'h1c); + this.notif_intr_trig_r = new("notif_intr_trig_r"); + this.notif_intr_trig_r.configure(this); + + this.notif_intr_trig_r.build(); + this.default_map.add_reg(this.notif_intr_trig_r, 'h20); + this.error0_intr_count_r = new("error0_intr_count_r"); + this.error0_intr_count_r.configure(this); + + this.error0_intr_count_r.build(); + this.default_map.add_reg(this.error0_intr_count_r, 'h100); + this.error1_intr_count_r = new("error1_intr_count_r"); + this.error1_intr_count_r.configure(this); + + this.error1_intr_count_r.build(); + this.default_map.add_reg(this.error1_intr_count_r, 'h104); + this.error2_intr_count_r = new("error2_intr_count_r"); + this.error2_intr_count_r.configure(this); + + this.error2_intr_count_r.build(); + this.default_map.add_reg(this.error2_intr_count_r, 'h108); + this.error3_intr_count_r = new("error3_intr_count_r"); + this.error3_intr_count_r.configure(this); + + this.error3_intr_count_r.build(); + this.default_map.add_reg(this.error3_intr_count_r, 'h10c); + this.notif_cmd_done_intr_count_r = new("notif_cmd_done_intr_count_r"); + this.notif_cmd_done_intr_count_r.configure(this); + + this.notif_cmd_done_intr_count_r.build(); + this.default_map.add_reg(this.notif_cmd_done_intr_count_r, 'h180); + this.error0_intr_count_incr_r = new("error0_intr_count_incr_r"); + this.error0_intr_count_incr_r.configure(this); + + this.error0_intr_count_incr_r.build(); + this.default_map.add_reg(this.error0_intr_count_incr_r, 'h200); + this.error1_intr_count_incr_r = new("error1_intr_count_incr_r"); + this.error1_intr_count_incr_r.configure(this); + + this.error1_intr_count_incr_r.build(); + this.default_map.add_reg(this.error1_intr_count_incr_r, 'h204); + this.error2_intr_count_incr_r = new("error2_intr_count_incr_r"); + this.error2_intr_count_incr_r.configure(this); + + this.error2_intr_count_incr_r.build(); + this.default_map.add_reg(this.error2_intr_count_incr_r, 'h208); + this.error3_intr_count_incr_r = new("error3_intr_count_incr_r"); + this.error3_intr_count_incr_r.configure(this); + + this.error3_intr_count_incr_r.build(); + this.default_map.add_reg(this.error3_intr_count_incr_r, 'h20c); + this.notif_cmd_done_intr_count_incr_r = new("notif_cmd_done_intr_count_incr_r"); + this.notif_cmd_done_intr_count_incr_r.configure(this); + + this.notif_cmd_done_intr_count_incr_r.build(); + this.default_map.add_reg(this.notif_cmd_done_intr_count_incr_r, 'h210); + endfunction : build + endclass : aes_clp_reg__intr_block_t + + // Addrmap - aes_clp_reg + class aes_clp_reg extends uvm_reg_block; + rand aes_clp_reg__AES_NAME AES_NAME[2]; + rand aes_clp_reg__AES_VERSION AES_VERSION[2]; + rand kv_read_ctrl_reg AES_KV_RD_KEY_CTRL; + rand kv_status_reg AES_KV_RD_KEY_STATUS; + rand aes_clp_reg__intr_block_t intr_block_rf; + + function new(string name = "aes_clp_reg"); + super.new(name); + endfunction : new + + virtual function void build(); + this.default_map = create_map("reg_map", 0, 4, UVM_NO_ENDIAN); + foreach(this.AES_NAME[i0]) begin + this.AES_NAME[i0] = new($sformatf("AES_NAME[%0d]", i0)); + this.AES_NAME[i0].configure(this); + + this.AES_NAME[i0].build(); + this.default_map.add_reg(this.AES_NAME[i0], 'h100 + i0*'h4); + end + foreach(this.AES_VERSION[i0]) begin + this.AES_VERSION[i0] = new($sformatf("AES_VERSION[%0d]", i0)); + this.AES_VERSION[i0].configure(this); + + this.AES_VERSION[i0].build(); + this.default_map.add_reg(this.AES_VERSION[i0], 'h108 + i0*'h4); + end + this.AES_KV_RD_KEY_CTRL = new("AES_KV_RD_KEY_CTRL"); + this.AES_KV_RD_KEY_CTRL.configure(this); + + this.AES_KV_RD_KEY_CTRL.build(); + this.default_map.add_reg(this.AES_KV_RD_KEY_CTRL, 'h600); + this.AES_KV_RD_KEY_STATUS = new("AES_KV_RD_KEY_STATUS"); + this.AES_KV_RD_KEY_STATUS.configure(this); + + this.AES_KV_RD_KEY_STATUS.build(); + this.default_map.add_reg(this.AES_KV_RD_KEY_STATUS, 'h604); + this.intr_block_rf = new("intr_block_rf"); + this.intr_block_rf.configure(this); + this.intr_block_rf.build(); + this.default_map.add_submap(this.intr_block_rf.default_map, 'h800); + endfunction : build + endclass : aes_clp_reg + + `include "aes_clp_reg_sample.svh" +endpackage: aes_clp_reg_uvm diff --git a/src/aes/rtl/aes_clp_wrapper.sv b/src/aes/rtl/aes_clp_wrapper.sv new file mode 100644 index 000000000..faea7efd5 --- /dev/null +++ b/src/aes/rtl/aes_clp_wrapper.sv @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//====================================================================== +// +// aes_clp_wrapper.sv +// -------- +// Wrapper for instantiation aes engine +// +// +// +//====================================================================== + +module aes_clp_wrapper + import kv_defines_pkg::*; + import aes_clp_reg_pkg::*; + #( + parameter AHB_DATA_WIDTH = 32, + parameter AHB_ADDR_WIDTH = 32 +) +( + // Clock and reset. + input wire clk, + input wire reset_n, + input wire cptra_pwrgood, + + input logic [AHB_ADDR_WIDTH-1:0] haddr_i, + input logic [AHB_DATA_WIDTH-1:0] hwdata_i, + input logic hsel_i, + input logic hwrite_i, + input logic hready_i, + input logic [1:0] htrans_i, + input logic [2:0] hsize_i, + + output logic hresp_o, + output logic hreadyout_o, + output logic [AHB_DATA_WIDTH-1:0] hrdata_o, + + // kv interface + output kv_read_t kv_read, + input kv_rd_resp_t kv_rd_resp, + + output logic busy_o, + + // Interrupt + output logic error_intr, + output logic notif_intr, + input logic debugUnlock_or_scan_mode_switch +); + +caliptra_tlul_pkg::tl_h2d_t adapter_to_aes_tl; +caliptra_tlul_pkg::tl_d2h_t aes_to_adapter_tl; + +logic ahb_dv; +logic ahb_hold; +logic ahb_write; +logic ahb_err; +logic [AHB_ADDR_WIDTH-1 : 0] ahb_addr; +logic [31 : 0] ahb_wdata; +logic [31 : 0] ahb_rdata; + +logic clp_reg_dv; +logic clp_reg_write; +logic [31 : 0] clp_reg_rdata; +logic [31 : 0] clp_reg_wdata; +logic [caliptra_tlul_pkg::TL_AW-1 : 0] clp_reg_addr; + +aes_clp_reg_pkg::aes_clp_reg__in_t hwif_in; +aes_clp_reg_pkg::aes_clp_reg__out_t hwif_out; + +caliptra_prim_mubi_pkg::mubi4_t aes_idle; + +kv_read_ctrl_reg_t kv_key_read_ctrl_reg; +kv_error_code_e kv_key_error; +logic kv_key_ready, kv_key_done; + +logic kv_key_write_en; +logic [2:0] kv_key_write_offset; +logic [31:0] kv_key_write_data; + +edn_pkg::edn_req_t edn_req; + +keymgr_pkg::hw_key_req_t keymgr_key; + +assign busy_o = caliptra_prim_mubi_pkg::mubi4_test_false_loose(aes_idle); + +//AHB interface +ahb_slv_sif #( + .AHB_ADDR_WIDTH(AHB_ADDR_WIDTH), + .AHB_DATA_WIDTH(AHB_DATA_WIDTH), + .CLIENT_DATA_WIDTH(32) +) ahb_slv_sif_inst +( + //AMBA AHB Lite INF + .hclk(clk), + .hreset_n(reset_n), + .haddr_i(haddr_i), + .hwdata_i(hwdata_i), + .hsel_i(hsel_i), + .hwrite_i(hwrite_i), + .hready_i(hready_i), + .htrans_i(htrans_i), + .hsize_i(hsize_i), + + .hresp_o(hresp_o), + .hreadyout_o(hreadyout_o), + .hrdata_o(hrdata_o), + + + //COMPONENT INF + .dv(ahb_dv), + .hld(ahb_hold), + .err(ahb_err), + .write(ahb_write), + .wdata(ahb_wdata), + .addr(ahb_addr), + + .rdata(ahb_rdata) +); + +//TLUL Adapter +caliptra_tlul_adapter_vh +caliptra_tlul_adapter_vh_inst +( + .clk_i(clk), + .rst_ni(reset_n), + + .tl_o(adapter_to_aes_tl), + .tl_i(aes_to_adapter_tl), + + // Valid-Hold device interface (VH to TLUL). + .dv_i(ahb_dv), + .hld_o(ahb_hold), + .addr_i({ {caliptra_tlul_pkg::TL_AW-AHB_ADDR_WIDTH{1'b0}}, ahb_addr }), + .write_i(ahb_write), + .wdata_i(ahb_wdata), + .wstrb_i('1), + .size_i(3'b010), + .rdata_o(ahb_rdata), + .error_o(ahb_err), + .last_i('0), + .user_i('0), + .id_i('0), + + // Valid-Hold host interface (VH to internal registers). The signals from the VH device interface + // are routed to the VH host interface for every internal access, see the `internal_access` signal. + .int_dv_o(clp_reg_dv), + .int_hld_i('0), + .int_addr_o(clp_reg_addr), + .int_write_o(clp_reg_write), + .int_wdata_o(clp_reg_wdata), + .int_wstrb_o(), + .int_size_o(), + .int_rdata_i(clp_reg_rdata), + .int_error_i('0), + .int_last_o(), + .int_user_o(), + .int_id_o() +); + +//Internal register block +aes_clp_reg aes_clp_reg_inst ( + .clk(clk), + .rst(1'b0), + + .s_cpuif_req (clp_reg_dv), + .s_cpuif_req_is_wr (clp_reg_write), + .s_cpuif_addr (clp_reg_addr[AES_CLP_REG_MIN_ADDR_WIDTH-1:0]), + .s_cpuif_wr_data (clp_reg_wdata), + .s_cpuif_wr_biten ('1), + .s_cpuif_req_stall_wr(), + .s_cpuif_req_stall_rd(), + .s_cpuif_rd_ack (), + .s_cpuif_rd_err (), + .s_cpuif_rd_data (clp_reg_rdata), + .s_cpuif_wr_ack (), + .s_cpuif_wr_err (), + + .hwif_in (hwif_in), + .hwif_out(hwif_out) +); + +edn_pkg::edn_rsp_t edn_i; + +assign edn_i = '{edn_ack:edn_req.edn_req, edn_fips:0, edn_bus:'0}; //FIXME + +//AES Engine +aes +aes_inst ( + .clk_i(clk), + .rst_ni(reset_n), + .rst_shadowed_ni(reset_n), //FIXME + + .idle_o(aes_idle), + + // Life cycle + .lc_escalate_en_i(lc_ctrl_pkg::Off), + + // Entropy distribution network (EDN) interface + .clk_edn_i(clk), + .rst_edn_ni(reset_n), + .edn_o(edn_req), + .edn_i(edn_i), //FIXME + + // Key manager (keymgr) key sideload interface + .keymgr_key_i(keymgr_key), //FIXME + + // Bus interface + .tl_i(adapter_to_aes_tl), + .tl_o(aes_to_adapter_tl), + + // Alerts + .alert_rx_i({caliptra_prim_alert_pkg::ALERT_RX_DEFAULT, caliptra_prim_alert_pkg::ALERT_RX_DEFAULT}), + .alert_tx_o() +); + +always_comb begin + hwif_in.error_reset_b = cptra_pwrgood; + hwif_in.reset_b = reset_n; + hwif_in.AES_NAME[0].NAME.next = '0; //FIXME + hwif_in.AES_NAME[1].NAME.next = '0; //FIXME + hwif_in.AES_VERSION[0].VERSION.next = '0; //FIXME + hwif_in.AES_VERSION[1].VERSION.next = '0; //FIXME + + //set ready when keyvault isn't busy + hwif_in.AES_KV_RD_KEY_STATUS.READY.next = kv_key_ready; + //set error code + hwif_in.AES_KV_RD_KEY_STATUS.ERROR.next = kv_key_error; + //set valid when fsm is done + hwif_in.AES_KV_RD_KEY_STATUS.VALID.hwset = kv_key_done; + //clear valid when new request is made + hwif_in.AES_KV_RD_KEY_STATUS.VALID.hwclr = kv_key_read_ctrl_reg.read_en; + //clear enable when busy + hwif_in.AES_KV_RD_KEY_CTRL.read_en.hwclr = ~kv_key_ready; + + hwif_in.intr_block_rf.notif_internal_intr_r.notif_cmd_done_sts.hwset = '0; //FIXME + hwif_in.intr_block_rf.error_internal_intr_r.error0_sts.hwset = 1'b0; // TODO + hwif_in.intr_block_rf.error_internal_intr_r.error1_sts.hwset = 1'b0; // TODO + hwif_in.intr_block_rf.error_internal_intr_r.error2_sts.hwset = 1'b0; // TODO + hwif_in.intr_block_rf.error_internal_intr_r.error3_sts.hwset = 1'b0; // TODO +end + +//keyault FSM +//keyvault control reg macros for assigning to struct +`CALIPTRA_KV_READ_CTRL_REG2STRUCT(kv_key_read_ctrl_reg, AES_KV_RD_KEY_CTRL) + +//Read Key +kv_read_client #( + .DATA_WIDTH(keymgr_pkg::KeyWidth), + .PAD(0) +) +aes_key_kv_read +( + .clk(clk), + .rst_b(reset_n), + .zeroize('0), //FIXME needed? + + //client control register + .read_ctrl_reg(kv_key_read_ctrl_reg), + + //interface with kv + .kv_read(kv_read), + .kv_resp(kv_rd_resp), + + //interface with client + .write_en(kv_key_write_en), + .write_offset(kv_key_write_offset), + .write_data(kv_key_write_data), + + .error_code(kv_key_error), + .kv_ready(kv_key_ready), + .read_done(kv_key_done) +); + +logic [(keymgr_pkg::KeyWidth/32)-1:0][31:0] kv_key_reg; + +//load keyvault key into local reg +genvar g_dword; +generate + for (g_dword = 0; g_dword < keymgr_pkg::KeyWidth/32; g_dword++) begin + always_ff @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + kv_key_reg[g_dword] <= '0; + end else if (kv_key_read_ctrl_reg.read_en || (kv_key_error == KV_READ_FAIL)) begin + kv_key_reg[g_dword] <= '0; + end else if (kv_key_write_en && (kv_key_write_offset == g_dword)) begin + kv_key_reg[g_dword] <= kv_key_write_data; + end + end + end +endgenerate + +//Drive keymgr interface into AES +always_ff @(posedge clk or negedge reset_n) begin + if (~reset_n) begin + keymgr_key.valid <= '0; + keymgr_key.key <= '0; + end + else if (kv_key_read_ctrl_reg.read_en) begin //new request, invalidate old key + keymgr_key.valid <= '0; + keymgr_key.key[0] <= '0; //FIXME drive from kv + keymgr_key.key[1] <= '0; + end + else if (kv_key_done) begin //key is copied, drive valid to aes + keymgr_key.valid <= '1; + keymgr_key.key[0] <= kv_key_reg; + keymgr_key.key[1] <= '0; + end +end + + +endmodule \ No newline at end of file diff --git a/src/aes/rtl/aes_control.sv b/src/aes/rtl/aes_control.sv new file mode 100644 index 000000000..577ebe50d --- /dev/null +++ b/src/aes/rtl/aes_control.sv @@ -0,0 +1,638 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES main control +// +// This module controls the interplay of input/output registers and the AES cipher core. + +`include "caliptra_prim_assert.sv" + +module aes_control + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AESGCMEnable = 0, + parameter bit SecMasking = 0, + parameter int unsigned SecStartTriggerDelay = 0 +) ( + input logic clk_i, + input logic rst_ni, + + // Main control signals + input logic ctrl_qe_i, + output logic ctrl_we_o, + input logic ctrl_phase_i, + input logic ctrl_err_storage_i, + input aes_op_e op_i, + input aes_mode_e mode_i, + input ciph_op_e cipher_op_i, + input logic sideload_i, + input prs_rate_e prng_reseed_rate_i, + input logic manual_operation_i, + input logic key_touch_forces_reseed_i, + input logic ctrl_gcm_qe_i, + output logic ctrl_gcm_we_o, + input gcm_phase_e gcm_phase_i, + input logic start_i, + input logic key_iv_data_in_clear_i, + input logic data_out_clear_i, + input logic prng_reseed_i, + input logic mux_sel_err_i, + input logic sp_enc_err_i, + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + input logic alert_fatal_i, + output logic alert_o, + + // I/O register read/write enables + input logic key_sideload_valid_i, + input logic [NumRegsKey-1:0] key_init_qe_i [NumSharesKey], + input logic [NumRegsIv-1:0] iv_qe_i, + input logic [NumRegsData-1:0] data_in_qe_i, + input logic [NumRegsData-1:0] data_out_re_i, + output logic data_in_we_o, + output data_out_sel_e data_out_sel_o, + output sp2v_e data_out_we_o, + + // Previous input data register + output dip_sel_e data_in_prev_sel_o, + output sp2v_e data_in_prev_we_o, + + // Cipher I/O muxes + output si_sel_e state_in_sel_o, + output add_si_sel_e add_state_in_sel_o, + output add_so_sel_e add_state_out_sel_o, + + // Counter + output sp2v_e ctr_inc32_o, + output sp2v_e ctr_incr_o, + input sp2v_e ctr_ready_i, + input sp2v_e [NumSlicesCtr-1:0] ctr_we_i, + + // Cipher core control and sync + output sp2v_e cipher_in_valid_o, + input sp2v_e cipher_in_ready_i, + input sp2v_e cipher_out_valid_i, + output sp2v_e cipher_out_ready_o, + output sp2v_e cipher_crypt_o, + input sp2v_e cipher_crypt_i, + output sp2v_e cipher_dec_key_gen_o, + input sp2v_e cipher_dec_key_gen_i, + output logic cipher_prng_reseed_o, + input logic cipher_prng_reseed_i, + output logic cipher_key_clear_o, + input logic cipher_key_clear_i, + output logic cipher_data_out_clear_o, + input logic cipher_data_out_clear_i, + + // GHASH control and sync + output sp2v_e ghash_in_valid_o, + input sp2v_e ghash_in_ready_i, + input sp2v_e ghash_out_valid_i, + output sp2v_e ghash_out_ready_o, + output sp2v_e ghash_load_hash_subkey_o, + + // Initial key registers + output key_init_sel_e key_init_sel_o, + output sp2v_e [NumRegsKey-1:0] key_init_we_o [NumSharesKey], + + // IV registers + output iv_sel_e iv_sel_o, + output sp2v_e [NumSlicesCtr-1:0] iv_we_o, + + // Pseudo-random number generator interface + output logic prng_update_o, + output logic prng_reseed_req_o, + input logic prng_reseed_ack_i, + + // Trigger register + output logic start_o, + output logic start_we_o, + output logic key_iv_data_in_clear_o, + output logic key_iv_data_in_clear_we_o, + output logic data_out_clear_o, + output logic data_out_clear_we_o, + output logic prng_reseed_o, + output logic prng_reseed_we_o, + + // Status register + output logic idle_o, + output logic idle_we_o, + output logic stall_o, + output logic stall_we_o, + input logic output_lost_i, + output logic output_lost_o, + output logic output_lost_we_o, + output logic output_valid_o, + output logic output_valid_we_o, + output logic input_ready_o, + output logic input_ready_we_o +); + + // Optional delay of manual start trigger + logic start_trigger; + + // Create a lint error to reduce the risk of accidentally enabling this feature. + `CALIPTRA_ASSERT_STATIC_LINT_ERROR(AesSecStartTriggerDelayNonDefault, SecStartTriggerDelay == 0) + + if (SecStartTriggerDelay > 0) begin : gen_start_delay + // Delay the manual start trigger input for SCA measurements. + localparam int unsigned WidthCounter = $clog2(SecStartTriggerDelay+1); + logic [WidthCounter-1:0] count_d, count_q; + + // Clear counter when input goes low. Keep value if the specified delay is reached. + assign count_d = !start_i ? '0 : + start_trigger ? count_q : count_q + 1'b1; + assign start_trigger = (count_q == SecStartTriggerDelay[WidthCounter-1:0]) ? 1'b1 : 1'b0; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + count_q <= '0; + end else begin + count_q <= count_d; + end + end + + end else begin : gen_no_start_delay + // Directly forward the manual start trigger input. + assign start_trigger = start_i; + end + + // Signals + sp2v_e ctr_ready; + sp2v_e [NumSlicesCtr-1:0] ctr_we; + sp2v_e cipher_in_ready; + sp2v_e cipher_out_valid; + sp2v_e cipher_crypt; + sp2v_e cipher_dec_key_gen; + sp2v_e ghash_in_ready; + sp2v_e ghash_out_valid; + logic mux_sel_err; + logic mr_err; + logic sp_enc_err; + + // Sparsified FSM signals. These are needed for connecting the individual bits of the Sp2V + // signals to the single-rail FSMs. + logic [Sp2VWidth-1:0] sp_data_out_we; + logic [Sp2VWidth-1:0] sp_data_in_prev_we; + logic [Sp2VWidth-1:0] sp_ctr_inc32; + logic [Sp2VWidth-1:0] sp_ctr_incr; + logic [Sp2VWidth-1:0] sp_ctr_ready; + logic [Sp2VWidth-1:0] sp_cipher_in_valid; + logic [Sp2VWidth-1:0] sp_cipher_in_ready; + logic [Sp2VWidth-1:0] sp_cipher_out_valid; + logic [Sp2VWidth-1:0] sp_cipher_out_ready; + logic [Sp2VWidth-1:0] sp_in_cipher_crypt; + logic [Sp2VWidth-1:0] sp_out_cipher_crypt; + logic [Sp2VWidth-1:0] sp_in_cipher_dec_key_gen; + logic [Sp2VWidth-1:0] sp_out_cipher_dec_key_gen; + logic [Sp2VWidth-1:0] sp_ghash_in_valid; + logic [Sp2VWidth-1:0] sp_ghash_in_ready; + logic [Sp2VWidth-1:0] sp_ghash_out_valid; + logic [Sp2VWidth-1:0] sp_ghash_out_ready; + logic [Sp2VWidth-1:0] sp_ghash_load_hash_subkey; + + // Multi-rail signals. These are outputs of the single-rail FSMs and need combining. + logic [Sp2VWidth-1:0] mr_ctrl_we; + logic [Sp2VWidth-1:0] mr_ctrl_gcm_we; + logic [Sp2VWidth-1:0] mr_alert; + logic [Sp2VWidth-1:0] mr_data_in_we; + data_out_sel_e [Sp2VWidth-1:0] mr_data_out_sel; + dip_sel_e [Sp2VWidth-1:0] mr_data_in_prev_sel; + si_sel_e [Sp2VWidth-1:0] mr_state_in_sel; + add_si_sel_e [Sp2VWidth-1:0] mr_add_state_in_sel; + add_so_sel_e [Sp2VWidth-1:0] mr_add_state_out_sel; + logic [Sp2VWidth-1:0] mr_cipher_prng_reseed; + logic [Sp2VWidth-1:0] mr_cipher_key_clear; + logic [Sp2VWidth-1:0] mr_cipher_data_out_clear; + key_init_sel_e [Sp2VWidth-1:0] mr_key_init_sel; + iv_sel_e [Sp2VWidth-1:0] mr_iv_sel; + logic [Sp2VWidth-1:0] mr_prng_update; + logic [Sp2VWidth-1:0] mr_prng_reseed_req; + logic [Sp2VWidth-1:0] mr_start_we; + logic [Sp2VWidth-1:0] mr_key_iv_data_in_clear_we; + logic [Sp2VWidth-1:0] mr_data_out_clear_we; + logic [Sp2VWidth-1:0] mr_prng_reseed; + logic [Sp2VWidth-1:0] mr_prng_reseed_we; + logic [Sp2VWidth-1:0] mr_idle; + logic [Sp2VWidth-1:0] mr_idle_we; + logic [Sp2VWidth-1:0] mr_stall; + logic [Sp2VWidth-1:0] mr_stall_we; + logic [Sp2VWidth-1:0] mr_output_lost; + logic [Sp2VWidth-1:0] mr_output_lost_we; + logic [Sp2VWidth-1:0] mr_output_valid; + logic [Sp2VWidth-1:0] mr_output_valid_we; + logic [Sp2VWidth-1:0] mr_input_ready; + logic [Sp2VWidth-1:0] mr_input_ready_we; + + // To ease interfacing with the individual FSM rails, some signals need to be converted to packed + // arrays. + logic [Sp2VWidth-1:0][NumSharesKey-1:0][NumRegsKey-1:0] int_key_init_we; + logic [NumSharesKey-1:0][NumRegsKey-1:0][Sp2VWidth-1:0] log_key_init_we; + logic [NumSharesKey-1:0][NumRegsKey-1:0] int_key_init_qe; + for (genvar s = 0; s < NumSharesKey; s++) begin : gen_conv_key_init_wqe_shares + for (genvar i = 0; i < NumRegsKey; i++) begin : gen_conv_key_init_wqe_regs + assign int_key_init_qe[s][i] = key_init_qe_i[s][i]; + for (genvar j = 0; j < Sp2VWidth; j++) begin : gen_conv_key_init_wqe_log + assign log_key_init_we[s][i][j] = int_key_init_we[j][s][i]; + end + assign key_init_we_o[s][i] = sp2v_e'(log_key_init_we[s][i]); + end + end + logic [Sp2VWidth-1:0][NumSlicesCtr-1:0] int_ctr_we; + logic [NumSlicesCtr-1:0][Sp2VWidth-1:0] log_ctr_we; + logic [Sp2VWidth-1:0][NumSlicesCtr-1:0] int_iv_we; + logic [NumSlicesCtr-1:0][Sp2VWidth-1:0] log_iv_we; + for (genvar i = 0; i < NumSlicesCtr; i++) begin : gen_conv_ctr_iv_we_slices + assign log_ctr_we[i] = {ctr_we[i]}; + for (genvar j = 0; j < Sp2VWidth; j++) begin : gen_conv_ctr_iv_we_log + assign int_ctr_we[j][i] = log_ctr_we[i][j]; + assign log_iv_we[i][j] = int_iv_we[j][i]; + end + assign iv_we_o[i] = sp2v_e'(log_iv_we[i]); + end + + ///////// + // FSM // + ///////// + + // Convert sp2v_e signals to sparsified inputs. + assign sp_ctr_ready = {ctr_ready}; + assign sp_cipher_in_ready = {cipher_in_ready}; + assign sp_cipher_out_valid = {cipher_out_valid}; + assign sp_in_cipher_crypt = {cipher_crypt}; + assign sp_in_cipher_dec_key_gen = {cipher_dec_key_gen}; + assign sp_ghash_in_ready = {ghash_in_ready}; + assign sp_ghash_out_valid = {ghash_out_valid}; + + // SEC_CM: MAIN.FSM.REDUN + // For every bit in the Sp2V signals, one separate rail is instantiated. The inputs and outputs + // of every rail are buffered to prevent aggressive synthesis optimizations. + for (genvar i = 0; i < Sp2VWidth; i++) begin : gen_fsm + if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_fsm_p + aes_control_fsm_p #( + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ) + ) u_aes_control_fsm_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .ctrl_qe_i ( ctrl_qe_i ), + .ctrl_we_o ( mr_ctrl_we[i] ), // AND-combine + .ctrl_phase_i ( ctrl_phase_i ), + .ctrl_err_storage_i ( ctrl_err_storage_i ), + .op_i ( op_i ), + .mode_i ( mode_i ), + .cipher_op_i ( cipher_op_i ), + .sideload_i ( sideload_i ), + .prng_reseed_rate_i ( prng_reseed_rate_i ), + .manual_operation_i ( manual_operation_i ), + .key_touch_forces_reseed_i ( key_touch_forces_reseed_i ), + .ctrl_gcm_qe_i ( ctrl_gcm_qe_i ), + .ctrl_gcm_we_o ( mr_ctrl_gcm_we[i] ), // AND-combine + .gcm_phase_i ( gcm_phase_i ), + .start_i ( start_trigger ), + .key_iv_data_in_clear_i ( key_iv_data_in_clear_i ), + .data_out_clear_i ( data_out_clear_i ), + .prng_reseed_i ( prng_reseed_i ), + .mux_sel_err_i ( mux_sel_err ), + .sp_enc_err_i ( sp_enc_err ), + .lc_escalate_en_i ( lc_escalate_en_i ), + .alert_fatal_i ( alert_fatal_i ), + .alert_o ( mr_alert[i] ), // OR-combine + + .key_sideload_valid_i ( key_sideload_valid_i ), + .key_init_qe_i ( int_key_init_qe ), + .iv_qe_i ( iv_qe_i ), + .data_in_qe_i ( data_in_qe_i ), + .data_out_re_i ( data_out_re_i ), + .data_in_we_o ( mr_data_in_we[i] ), // AND-combine + .data_out_sel_o ( mr_data_out_sel[i] ), // OR-combine + .data_out_we_o ( sp_data_out_we[i] ), // Sparsified + + .data_in_prev_sel_o ( mr_data_in_prev_sel[i] ), // OR-combine + .data_in_prev_we_o ( sp_data_in_prev_we[i] ), // Sparsified + + .state_in_sel_o ( mr_state_in_sel[i] ), // OR-combine + .add_state_in_sel_o ( mr_add_state_in_sel[i] ), // OR-combine + .add_state_out_sel_o ( mr_add_state_out_sel[i] ), // OR-combine + + .ctr_inc32_o ( sp_ctr_inc32[i] ), // Sparsified + .ctr_incr_o ( sp_ctr_incr[i] ), // Sparsified + .ctr_ready_i ( sp_ctr_ready[i] ), // Sparsified + .ctr_we_i ( int_ctr_we[i] ), // Sparsified + + .cipher_in_valid_o ( sp_cipher_in_valid[i] ), // Sparsified + .cipher_in_ready_i ( sp_cipher_in_ready[i] ), // Sparsified + .cipher_out_valid_i ( sp_cipher_out_valid[i] ), // Sparsified + .cipher_out_ready_o ( sp_cipher_out_ready[i] ), // Sparsified + .cipher_crypt_o ( sp_out_cipher_crypt[i] ), // Sparsified + .cipher_crypt_i ( sp_in_cipher_crypt[i] ), // Sparsified + .cipher_dec_key_gen_o ( sp_out_cipher_dec_key_gen[i] ), // Sparsified + .cipher_dec_key_gen_i ( sp_in_cipher_dec_key_gen[i] ), // Sparsified + .cipher_prng_reseed_o ( mr_cipher_prng_reseed[i] ), // OR-combine + .cipher_prng_reseed_i ( cipher_prng_reseed_i ), + .cipher_key_clear_o ( mr_cipher_key_clear[i] ), // OR-combine + .cipher_key_clear_i ( cipher_key_clear_i ), + .cipher_data_out_clear_o ( mr_cipher_data_out_clear[i] ), // OR-combine + .cipher_data_out_clear_i ( cipher_data_out_clear_i ), + + .ghash_in_valid_o ( sp_ghash_in_valid[i] ), // Sparsified + .ghash_in_ready_i ( sp_ghash_in_ready[i] ), // Sparsified + .ghash_out_valid_i ( sp_ghash_out_valid[i] ), // Sparsified + .ghash_out_ready_o ( sp_ghash_out_ready[i] ), // Sparsified + .ghash_load_hash_subkey_o ( sp_ghash_load_hash_subkey[i] ), // Sparsified + + .key_init_sel_o ( mr_key_init_sel[i] ), // OR-combine + .key_init_we_o ( int_key_init_we[i] ), // Sparsified + + .iv_sel_o ( mr_iv_sel[i] ), // OR-combine + .iv_we_o ( int_iv_we[i] ), // Sparsified + + .prng_update_o ( mr_prng_update[i] ), // OR-combine + .prng_reseed_req_o ( mr_prng_reseed_req[i] ), // OR-combine + .prng_reseed_ack_i ( prng_reseed_ack_i ), + + .start_we_o ( mr_start_we[i] ), // OR-combine + .key_iv_data_in_clear_we_o ( mr_key_iv_data_in_clear_we[i] ), // AND-combine + .data_out_clear_we_o ( mr_data_out_clear_we[i] ), // AND-combine + .prng_reseed_o ( mr_prng_reseed[i] ), // OR-combine + .prng_reseed_we_o ( mr_prng_reseed_we[i] ), // OR-combine + + .idle_o ( mr_idle[i] ), // AND-combine + .idle_we_o ( mr_idle_we[i] ), // AND-combine + .stall_o ( mr_stall[i] ), // AND-combine + .stall_we_o ( mr_stall_we[i] ), // AND-combine + .output_lost_i ( output_lost_i ), // AND-combine + .output_lost_o ( mr_output_lost[i] ), // AND-combine + .output_lost_we_o ( mr_output_lost_we[i] ), // AND-combine + .output_valid_o ( mr_output_valid[i] ), // AND-combine + .output_valid_we_o ( mr_output_valid_we[i] ), // AND-combine + .input_ready_o ( mr_input_ready[i] ), // AND-combine + .input_ready_we_o ( mr_input_ready_we[i] ) // AND-combine + ); + end else begin : gen_fsm_n + aes_control_fsm_n #( + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ) + ) u_aes_control_fsm_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .ctrl_qe_i ( ctrl_qe_i ), + .ctrl_we_o ( mr_ctrl_we[i] ), // AND-combine + .ctrl_phase_i ( ctrl_phase_i ), + .ctrl_err_storage_i ( ctrl_err_storage_i ), + .op_i ( op_i ), + .mode_i ( mode_i ), + .cipher_op_i ( cipher_op_i ), + .sideload_i ( sideload_i ), + .prng_reseed_rate_i ( prng_reseed_rate_i ), + .manual_operation_i ( manual_operation_i ), + .key_touch_forces_reseed_i ( key_touch_forces_reseed_i ), + .ctrl_gcm_qe_i ( ctrl_gcm_qe_i ), + .ctrl_gcm_we_o ( mr_ctrl_gcm_we[i] ), // AND-combine + .gcm_phase_i ( gcm_phase_i ), + .start_i ( start_trigger ), + .key_iv_data_in_clear_i ( key_iv_data_in_clear_i ), + .data_out_clear_i ( data_out_clear_i ), + .prng_reseed_i ( prng_reseed_i ), + .mux_sel_err_i ( mux_sel_err ), + .sp_enc_err_i ( sp_enc_err ), + .lc_escalate_en_i ( lc_escalate_en_i ), + .alert_fatal_i ( alert_fatal_i ), + .alert_o ( mr_alert[i] ), // OR-combine + + .key_sideload_valid_i ( key_sideload_valid_i ), + .key_init_qe_i ( int_key_init_qe ), + .iv_qe_i ( iv_qe_i ), + .data_in_qe_i ( data_in_qe_i ), + .data_out_re_i ( data_out_re_i ), + .data_in_we_o ( mr_data_in_we[i] ), // AND-combine + .data_out_sel_o ( mr_data_out_sel[i] ), // OR-combine + .data_out_we_no ( sp_data_out_we[i] ), // Sparsified + + .data_in_prev_sel_o ( mr_data_in_prev_sel[i] ), // OR-combine + .data_in_prev_we_no ( sp_data_in_prev_we[i] ), // Sparsified + + .state_in_sel_o ( mr_state_in_sel[i] ), // OR-combine + .add_state_in_sel_o ( mr_add_state_in_sel[i] ), // OR-combine + .add_state_out_sel_o ( mr_add_state_out_sel[i] ), // OR-combine + + .ctr_inc32_no ( sp_ctr_inc32[i] ), // Sparsified + .ctr_incr_no ( sp_ctr_incr[i] ), // Sparsified + .ctr_ready_ni ( sp_ctr_ready[i] ), // Sparsified + .ctr_we_ni ( int_ctr_we[i] ), // Sparsified + + .cipher_in_valid_no ( sp_cipher_in_valid[i] ), // Sparsified + .cipher_in_ready_ni ( sp_cipher_in_ready[i] ), // Sparsified + .cipher_out_valid_ni ( sp_cipher_out_valid[i] ), // Sparsified + .cipher_out_ready_no ( sp_cipher_out_ready[i] ), // Sparsified + .cipher_crypt_no ( sp_out_cipher_crypt[i] ), // Sparsified + .cipher_crypt_ni ( sp_in_cipher_crypt[i] ), // Sparsified + .cipher_dec_key_gen_no ( sp_out_cipher_dec_key_gen[i] ), // Sparsified + .cipher_dec_key_gen_ni ( sp_in_cipher_dec_key_gen[i] ), // Sparsified + .cipher_prng_reseed_o ( mr_cipher_prng_reseed[i] ), // OR-combine + .cipher_prng_reseed_i ( cipher_prng_reseed_i ), + .cipher_key_clear_o ( mr_cipher_key_clear[i] ), // OR-combine + .cipher_key_clear_i ( cipher_key_clear_i ), + .cipher_data_out_clear_o ( mr_cipher_data_out_clear[i] ), // OR-combine + .cipher_data_out_clear_i ( cipher_data_out_clear_i ), + + .ghash_in_valid_no ( sp_ghash_in_valid[i] ), // Sparsified + .ghash_in_ready_ni ( sp_ghash_in_ready[i] ), // Sparsified + .ghash_out_valid_ni ( sp_ghash_out_valid[i] ), // Sparsified + .ghash_out_ready_no ( sp_ghash_out_ready[i] ), // Sparsified + .ghash_load_hash_subkey_no ( sp_ghash_load_hash_subkey[i] ), // Sparsified + + .key_init_sel_o ( mr_key_init_sel[i] ), // OR-combine + .key_init_we_no ( int_key_init_we[i] ), // Sparsified + + .iv_sel_o ( mr_iv_sel[i] ), // OR-combine + .iv_we_no ( int_iv_we[i] ), // Sparsified + + .prng_update_o ( mr_prng_update[i] ), // OR-combine + .prng_reseed_req_o ( mr_prng_reseed_req[i] ), // OR-combine + .prng_reseed_ack_i ( prng_reseed_ack_i ), + + .start_we_o ( mr_start_we[i] ), // OR-combine + .key_iv_data_in_clear_we_o ( mr_key_iv_data_in_clear_we[i] ), // AND-combine + .data_out_clear_we_o ( mr_data_out_clear_we[i] ), // AND-combine + .prng_reseed_o ( mr_prng_reseed[i] ), // OR-combine + .prng_reseed_we_o ( mr_prng_reseed_we[i] ), // OR-combine + + .idle_o ( mr_idle[i] ), // AND-combine + .idle_we_o ( mr_idle_we[i] ), // AND-combine + .stall_o ( mr_stall[i] ), // AND-combine + .stall_we_o ( mr_stall_we[i] ), // AND-combine + .output_lost_i ( output_lost_i ), // AND-combine + .output_lost_o ( mr_output_lost[i] ), // AND-combine + .output_lost_we_o ( mr_output_lost_we[i] ), // AND-combine + .output_valid_o ( mr_output_valid[i] ), // AND-combine + .output_valid_we_o ( mr_output_valid_we[i] ), // AND-combine + .input_ready_o ( mr_input_ready[i] ), // AND-combine + .input_ready_we_o ( mr_input_ready_we[i] ) // AND-combine + ); + end + end + + // Convert sparsified outputs to sp2v_e type. + assign data_out_we_o = sp2v_e'(sp_data_out_we); + assign data_in_prev_we_o = sp2v_e'(sp_data_in_prev_we); + assign ctr_inc32_o = sp2v_e'(sp_ctr_inc32); + assign ctr_incr_o = sp2v_e'(sp_ctr_incr); + assign cipher_in_valid_o = sp2v_e'(sp_cipher_in_valid); + assign cipher_out_ready_o = sp2v_e'(sp_cipher_out_ready); + assign cipher_crypt_o = sp2v_e'(sp_out_cipher_crypt); + assign cipher_dec_key_gen_o = sp2v_e'(sp_out_cipher_dec_key_gen); + assign ghash_in_valid_o = sp2v_e'(sp_ghash_in_valid); + assign ghash_out_ready_o = sp2v_e'(sp_ghash_out_ready); + assign ghash_load_hash_subkey_o = sp2v_e'(sp_ghash_load_hash_subkey); + + // Combine single-bit FSM outputs. + // OR: One bit is sufficient to drive the corresponding output bit high. + assign alert_o = |mr_alert; + assign cipher_prng_reseed_o = |mr_cipher_prng_reseed; + assign cipher_key_clear_o = |mr_cipher_key_clear; + assign cipher_data_out_clear_o = |mr_cipher_data_out_clear; + assign prng_update_o = |mr_prng_update; + assign prng_reseed_req_o = |mr_prng_reseed_req; + assign start_we_o = |mr_start_we; + assign prng_reseed_o = |mr_prng_reseed; + assign prng_reseed_we_o = |mr_prng_reseed_we; + + // AND: Only if all bits are high, the corresponding action should be triggered. + assign ctrl_we_o = &mr_ctrl_we; + assign ctrl_gcm_we_o = &mr_ctrl_gcm_we; + assign data_in_we_o = &mr_data_in_we; + assign key_iv_data_in_clear_we_o = &mr_key_iv_data_in_clear_we; + assign data_out_clear_we_o = &mr_data_out_clear_we; + assign idle_o = &mr_idle; + assign idle_we_o = &mr_idle_we; + assign stall_o = &mr_stall; + assign stall_we_o = &mr_stall_we; + assign output_lost_o = &mr_output_lost; + assign output_lost_we_o = &mr_output_lost_we; + assign output_valid_o = &mr_output_valid; + assign output_valid_we_o = &mr_output_valid_we; + assign input_ready_o = &mr_input_ready; + assign input_ready_we_o = &mr_input_ready_we; + + // Combine multi-bit, sparse FSM outputs. We simply OR them together. If the FSMs don't provide + // the same outputs, two cases are possible: + // - An invalid encoding results: A downstream checker will fire, see mux_sel_err_i. + // - A valid encoding results: The outputs are compared below to cover this case, see mr_err; + always_comb begin : combine_sparse_signals + data_out_sel_o = data_out_sel_e'({DataOutSelWidth{1'b0}}); + data_in_prev_sel_o = dip_sel_e'({DIPSelWidth{1'b0}}); + state_in_sel_o = si_sel_e'({SISelWidth{1'b0}}); + add_state_in_sel_o = add_si_sel_e'({AddSISelWidth{1'b0}}); + add_state_out_sel_o = add_so_sel_e'({AddSOSelWidth{1'b0}}); + key_init_sel_o = key_init_sel_e'({KeyInitSelWidth{1'b0}}); + iv_sel_o = iv_sel_e'({IVSelWidth{1'b0}}); + mr_err = 1'b0; + + for (int i = 0; i < Sp2VWidth; i++) begin + data_out_sel_o = data_out_sel_e'({data_out_sel_o} | {mr_data_out_sel[i]}); + data_in_prev_sel_o = dip_sel_e'({data_in_prev_sel_o} | {mr_data_in_prev_sel[i]}); + state_in_sel_o = si_sel_e'({state_in_sel_o} | {mr_state_in_sel[i]}); + add_state_in_sel_o = add_si_sel_e'({add_state_in_sel_o} | {mr_add_state_in_sel[i]}); + add_state_out_sel_o = add_so_sel_e'({add_state_out_sel_o} | {mr_add_state_out_sel[i]}); + key_init_sel_o = key_init_sel_e'({key_init_sel_o} | {mr_key_init_sel[i]}); + iv_sel_o = iv_sel_e'({iv_sel_o} | {mr_iv_sel[i]}); + end + + for (int i = 0; i < Sp2VWidth; i++) begin + if (data_out_sel_o != mr_data_out_sel[i] || + data_in_prev_sel_o != mr_data_in_prev_sel[i] || + state_in_sel_o != mr_state_in_sel[i] || + add_state_in_sel_o != mr_add_state_in_sel[i] || + add_state_out_sel_o != mr_add_state_out_sel[i] || + key_init_sel_o != mr_key_init_sel[i] || + iv_sel_o != mr_iv_sel[i]) begin + mr_err = 1'b1; + end + end + end + + // Collect errors in mux selector signals. + assign mux_sel_err = mux_sel_err_i | mr_err; + + ////////////////////////////// + // Sparsely Encoded Signals // + ////////////////////////////// + + // SEC_CM: CTRL.SPARSE + // We use sparse encodings for various critical signals and must ensure that: + // 1. The synthesis tool doesn't optimize away the sparse encoding. + // 2. The sparsely encoded signal is always valid. More precisely, an alert or SVA is triggered + // if a sparse signal takes on an invalid value. + // 3. The alert signal remains asserted until reset even if the sparse signal becomes valid again + // This is achieved by driving the control FSM into the terminal error state whenever any + // sparsely encoded signal becomes invalid. + // + // If any sparsely encoded signal becomes invalid, the controller further immediately de-asserts + // data_out_we_o and other write-enable signals to prevent any data from being released. + + // We use vectors of sparsely encoded signals to reduce code duplication. + localparam int unsigned NumSp2VSig = 7 + NumSlicesCtr; + sp2v_e [NumSp2VSig-1:0] sp2v_sig; + sp2v_e [NumSp2VSig-1:0] sp2v_sig_chk; + logic [NumSp2VSig-1:0][Sp2VWidth-1:0] sp2v_sig_chk_raw; + logic [NumSp2VSig-1:0] sp2v_sig_err; + + assign sp2v_sig[0] = cipher_in_ready_i; + assign sp2v_sig[1] = cipher_out_valid_i; + assign sp2v_sig[2] = cipher_crypt_i; + assign sp2v_sig[3] = cipher_dec_key_gen_i; + assign sp2v_sig[4] = ghash_in_ready_i; + assign sp2v_sig[5] = ghash_out_valid_i; + assign sp2v_sig[6] = ctr_ready_i; + for (genvar i = 0; i < NumSlicesCtr; i++) begin : gen_use_ctr_we_i + assign sp2v_sig[7+i] = ctr_we_i[i]; + end + + // All signals inside sp2v_sig are driven and consumed by multi-rail FSMs. + localparam bit [NumSp2VSig-1:0] Sp2VEnSecBuf = '0; + + // Individually check sparsely encoded signals. + for (genvar i = 0; i < NumSp2VSig; i++) begin : gen_sel_buf_chk + aes_sel_buf_chk #( + .Num ( Sp2VNum ), + .Width ( Sp2VWidth ), + .EnSecBuf ( Sp2VEnSecBuf[i] ) + ) u_aes_sp2v_sig_buf_chk_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( sp2v_sig[i] ), + .sel_o ( sp2v_sig_chk_raw[i] ), + .err_o ( sp2v_sig_err[i] ) + ); + assign sp2v_sig_chk[i] = sp2v_e'(sp2v_sig_chk_raw[i]); + end + + assign cipher_in_ready = sp2v_sig_chk[0]; + assign cipher_out_valid = sp2v_sig_chk[1]; + assign cipher_crypt = sp2v_sig_chk[2]; + assign cipher_dec_key_gen = sp2v_sig_chk[3]; + assign ghash_in_ready = sp2v_sig_chk[4]; + assign ghash_out_valid = sp2v_sig_chk[5]; + assign ctr_ready = sp2v_sig_chk[6]; + for (genvar i = 0; i < NumSlicesCtr; i++) begin : gen_ctr_we + assign ctr_we[i] = sp2v_sig_chk[7+i]; + end + + // Collect encoding errors. + // We instantiate the checker modules as close as possible to where the sparsely encoded signals + // are used. Here, we collect also encoding errors detected in other places of the core. + assign sp_enc_err = |sp2v_sig_err | sp_enc_err_i; + + ////////////////////// + // Trigger Register // + ////////////////////// + // Most triggers are only ever cleared by control. + assign start_o = 1'b0; + assign key_iv_data_in_clear_o = 1'b0; + assign data_out_clear_o = 1'b0; + +endmodule diff --git a/src/aes/rtl/aes_control_fsm.sv b/src/aes/rtl/aes_control_fsm.sv new file mode 100644 index 000000000..4b9ad8df0 --- /dev/null +++ b/src/aes/rtl/aes_control_fsm.sv @@ -0,0 +1,1136 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES main control FSM +// +// This module contains the main control FSM handling the interplay of input/output registers and +// the AES cipher core. + +`include "caliptra_prim_assert.sv" + +module aes_control_fsm + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AESGCMEnable = 0, + parameter bit SecMasking = 0 +) ( + input logic clk_i, + input logic rst_ni, + + // Main control signals + input logic ctrl_qe_i, + output logic ctrl_we_o, + input logic ctrl_phase_i, + input logic ctrl_err_storage_i, + input aes_op_e op_i, + input aes_mode_e mode_i, + input ciph_op_e cipher_op_i, + input logic sideload_i, + input prs_rate_e prng_reseed_rate_i, + input logic manual_operation_i, + input logic key_touch_forces_reseed_i, + input logic ctrl_gcm_qe_i, + output logic ctrl_gcm_we_o, + input gcm_phase_e gcm_phase_i, + input logic start_i, + input logic key_iv_data_in_clear_i, + input logic data_out_clear_i, + input logic prng_reseed_i, + input logic mux_sel_err_i, + input logic sp_enc_err_i, + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + input logic alert_fatal_i, + output logic alert_o, + + // I/O register read/write enables + input logic key_sideload_valid_i, + input logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe_i, + input logic [NumRegsIv-1:0] iv_qe_i, + input logic [NumRegsData-1:0] data_in_qe_i, + input logic [NumRegsData-1:0] data_out_re_i, + output logic data_in_we_o, + output data_out_sel_e data_out_sel_o, + output logic data_out_we_o, // Sparsify + + // Previous input data register + output dip_sel_e data_in_prev_sel_o, + output logic data_in_prev_we_o, // Sparsify + + // Cipher I/O muxes + output si_sel_e state_in_sel_o, + output add_si_sel_e add_state_in_sel_o, + output add_so_sel_e add_state_out_sel_o, + + // Counter + output logic ctr_inc32_o, // Sparsify + output logic ctr_incr_o, // Sparsify + input logic ctr_ready_i, // Sparsify + input logic [NumSlicesCtr-1:0] ctr_we_i, // Sparsify + + // Cipher core control and sync + output logic cipher_in_valid_o, // Sparsify + input logic cipher_in_ready_i, // Sparsify + input logic cipher_out_valid_i, // Sparsify + output logic cipher_out_ready_o, // Sparsify + output logic cipher_crypt_o, // Sparsify + input logic cipher_crypt_i, // Sparsify + output logic cipher_dec_key_gen_o, // Sparsify + input logic cipher_dec_key_gen_i, // Sparsify + output logic cipher_prng_reseed_o, + input logic cipher_prng_reseed_i, + output logic cipher_key_clear_o, + input logic cipher_key_clear_i, + output logic cipher_data_out_clear_o, + input logic cipher_data_out_clear_i, + + // GHASH control and sync + output logic ghash_in_valid_o, // Sparsify + input logic ghash_in_ready_i, // Sparsify + input logic ghash_out_valid_i, // Sparsify + output logic ghash_out_ready_o, // Sparsify + output logic ghash_load_hash_subkey_o, // Sparsify + + // Initial key registers + output key_init_sel_e key_init_sel_o, + output logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we_o, // Sparsify + + // IV registers + output iv_sel_e iv_sel_o, + output logic [NumSlicesCtr-1:0] iv_we_o, // Sparsify + + // Pseudo-random number generator interface + output logic prng_update_o, + output logic prng_reseed_req_o, + input logic prng_reseed_ack_i, + + // Trigger register + output logic start_we_o, + output logic key_iv_data_in_clear_we_o, + output logic data_out_clear_we_o, + output logic prng_reseed_o, + output logic prng_reseed_we_o, + + // Status register + output logic idle_o, + output logic idle_we_o, + output logic stall_o, + output logic stall_we_o, + input logic output_lost_i, + output logic output_lost_o, + output logic output_lost_we_o, + output logic output_valid_o, + output logic output_valid_we_o, + output logic input_ready_o, + output logic input_ready_we_o +); + + // Signals + aes_ctrl_e aes_ctrl_ns, aes_ctrl_cs; + logic prng_reseed_done_d, prng_reseed_done_q; + + logic key_init_clear; + logic key_init_new; + logic key_init_new_pulse; + logic key_init_load; + logic key_init_arm; + logic key_init_ready; + logic key_sideload; + + logic [NumSlicesCtr-1:0] iv_qe; + logic iv_clear; + logic iv_load; + logic iv_arm; + logic iv_ready; + + logic [NumRegsData-1:0] data_in_new_d, data_in_new_q; + logic data_in_new; + logic data_in_load; + + logic [NumRegsData-1:0] data_out_read_d, data_out_read_q; + logic data_out_read; + logic output_valid_q; + + logic cfg_valid; + logic no_alert; + logic cipher_op_err; + logic start_common, start_ecb, start_cbc, start_cfb, start_ofb, start_ctr; + logic start; + logic start_core; + logic finish; + logic crypt; + logic cipher_out_done; + logic doing_cbc_enc, doing_cbc_dec; + logic doing_cfb_enc, doing_cfb_dec; + logic doing_ofb; + logic doing_ctr; + logic ctrl_we_q; + logic clear_in_out_status; + logic clear_on_fatal; + + logic start_we; + logic key_iv_data_in_clear_we; + logic data_out_clear_we; + logic prng_reseed_we; + + logic idle; + logic idle_we; + logic stall; + logic stall_we; + logic output_lost; + logic output_lost_we; + logic output_valid; + logic output_valid_we; + logic input_ready; + logic input_ready_we; + + logic gcm_init, gcm_restore, gcm_aad, gcm_txt, gcm_save, gcm_tag; + logic start_common_gcm, start_gcm; + logic start_gcm_init, start_gcm_hash_subkey, start_gcm_s; + logic start_gcm_restore, start_gcm_aad, start_gcm_txt, start_gcm_save; + logic start_gcm_tag; + logic doing_gcm_hsk, doing_gcm_s, doing_gcm_txt; + logic hash_subkey_ready_d, hash_subkey_ready_q; + logic s_ready_d, s_ready_q; + logic doing_gcm_restore_d, doing_gcm_restore_q; + logic doing_gcm_aad_d, doing_gcm_aad_q; + logic doing_gcm_tag_d, doing_gcm_tag_q; + logic doing_gcm_save_d, doing_gcm_save_q; + logic ghash_out_done; + logic ghash_idle; + + logic block_ctr_expr; + logic block_ctr_decr; + + // Software updates IV in chunks of 32 bits, the counter updates SliceSizeCtr bits at a time. + // Convert word write enable to internal half-word write enable. + assign iv_qe = {iv_qe_i[3], iv_qe_i[3], iv_qe_i[2], iv_qe_i[2], + iv_qe_i[1], iv_qe_i[1], iv_qe_i[0], iv_qe_i[0]}; + + // The cipher core is only ever allowed to start or finish if the control register holds a valid + // configuration and if no fatal alert condition occured. + assign cfg_valid = ~((mode_i == AES_NONE) | ctrl_err_storage_i); + assign no_alert = ~alert_fatal_i; + + // cipher_op_i is obtained from the configuration of the control register with additional logic. + assign cipher_op_err = ~(cipher_op_i == CIPH_FWD || cipher_op_i == CIPH_INV); + + // Check common start conditions. These are needed for any mode, unless we are running in + // manual mode. + assign start_common = key_init_ready & data_in_new & + // If key sideload is enabled, we only start if the key is valid. + (sideload_i ? key_sideload_valid_i : 1'b1); + + // Check mode-specific start conditions. If the IV (and counter) is needed, we only start if + // also the IV (and counter) is ready. + assign start_ecb = (mode_i == AES_ECB); + assign start_cbc = (mode_i == AES_CBC) & iv_ready; + assign start_cfb = (mode_i == AES_CFB) & iv_ready; + assign start_ofb = (mode_i == AES_OFB) & iv_ready; + assign start_ctr = (mode_i == AES_CTR) & iv_ready & ctr_ready_i; + + // For the initial GCM phase, we need key and IV but then encrypt two blocks. The input data + // is not required. + assign gcm_init = (mode_i == AES_GCM) & (gcm_phase_i == GCM_INIT); + assign start_common_gcm = key_init_ready & (sideload_i ? key_sideload_valid_i : 1'b1); + assign start_gcm_hash_subkey = gcm_init & ~hash_subkey_ready_q & iv_ready & ctr_ready_i; + assign start_gcm_s = gcm_init & ~s_ready_q & iv_ready & ctr_ready_i; + assign start_gcm_init = (start_gcm_hash_subkey | start_gcm_s) & start_common_gcm; + + // For the restore phase of GCM, we need key, IV and input data. + assign gcm_restore = (mode_i == AES_GCM) & (gcm_phase_i == GCM_RESTORE); + assign start_gcm_restore = gcm_restore & iv_ready & ctr_ready_i & data_in_new & start_common_gcm; + + // For the AAD and ciphertext/plaintext phases of GCM, we need key, IV and input data. But for + // the AAD phase, only the input data is really used and marked as used. + assign gcm_aad = (mode_i == AES_GCM) & (gcm_phase_i == GCM_AAD); + assign gcm_txt = (mode_i == AES_GCM) & (gcm_phase_i == GCM_TEXT); + assign start_gcm_aad = gcm_aad & iv_ready & ctr_ready_i & data_in_new; + assign start_gcm_txt = gcm_txt & iv_ready & ctr_ready_i & data_in_new; + assign start_gcm = start_gcm_aad | start_gcm_txt; + + // For the save phase of GCM, we need no inputs. + assign gcm_save = (mode_i == AES_GCM) & (gcm_phase_i == GCM_SAVE); + assign start_gcm_save = gcm_save & hash_subkey_ready_q & s_ready_q; + + // For the tag phase of GCM, we just need the input data. + assign gcm_tag = (mode_i == AES_GCM) & (gcm_phase_i == GCM_TAG); + assign start_gcm_tag = gcm_tag & data_in_new; + + // The GHASH block is idle whenever it's ready to receive inputs and where not about to start + // a GCM related operation. + assign ghash_idle = ghash_in_ready_i & ~(start_gcm_init | start_gcm | start_gcm_tag); + + // In GCM, the counter performs inc32() instead of inc128(), i.e., the counter wraps at 32 bits. + assign ctr_inc32_o = (mode_i == AES_GCM); + + // If set to start manually, we just wait for the trigger. Otherwise, check common as well as + // mode-specific start conditions. + assign start = cfg_valid & no_alert & + // Manual operation has priority. + (manual_operation_i ? start_i : + // Check start conditions for automatic operation. + ((start_ecb | + start_cbc | + start_cfb | + start_ofb | + start_ctr | + start_gcm) & start_common) | + start_gcm_init | + start_gcm_restore | + start_gcm_save | + start_gcm_tag); + + // If not set to overwrite data, we wait for any previous output data to be read. data_out_read + // synchronously clears output_valid_q, unless new output data is written in the exact same + // clock cycle. + assign finish = cfg_valid & no_alert & + // Manual operation has priority. + (manual_operation_i ? 1'b1 : + // Make sure previous output data has been read. + (~output_valid_q | data_out_read)); + + // Helper signals for FSM + assign crypt = cipher_crypt_o | cipher_crypt_i; + + assign doing_cbc_enc = (mode_i == AES_CBC && op_i == AES_ENC) & crypt; + assign doing_cbc_dec = (mode_i == AES_CBC && op_i == AES_DEC) & crypt; + assign doing_cfb_enc = (mode_i == AES_CFB && op_i == AES_ENC) & crypt; + assign doing_cfb_dec = (mode_i == AES_CFB && op_i == AES_DEC) & crypt; + assign doing_ofb = (mode_i == AES_OFB) & crypt; + assign doing_ctr = (mode_i == AES_CTR) & crypt; + assign doing_gcm_hsk = gcm_init & ~hash_subkey_ready_q & crypt; + assign doing_gcm_s = gcm_init & hash_subkey_ready_q & crypt; + assign doing_gcm_txt = gcm_txt & crypt; + + // FSM + always_comb begin : aes_ctrl_fsm + + // Previous input data register control + data_in_prev_sel_o = DIP_CLEAR; + data_in_prev_we_o = 1'b0; + + // Cipher I/O mux control + state_in_sel_o = SI_DATA; + add_state_in_sel_o = ADD_SI_ZERO; + add_state_out_sel_o = ADD_SO_ZERO; + + // Counter control + ctr_incr_o = 1'b0; + + // Cipher core control + cipher_in_valid_o = 1'b0; + cipher_out_ready_o = 1'b0; + cipher_out_done = 1'b0; + cipher_crypt_o = 1'b0; + cipher_dec_key_gen_o = 1'b0; + cipher_prng_reseed_o = 1'b0; + cipher_key_clear_o = 1'b0; + cipher_data_out_clear_o = 1'b0; + + // GHASH control + ghash_in_valid_o = 1'b0; + ghash_out_ready_o = 1'b0; + ghash_out_done = 1'b0; + ghash_load_hash_subkey_o = ~hash_subkey_ready_q; + + // Initial key registers + key_init_sel_o = sideload_i ? KEY_INIT_KEYMGR : KEY_INIT_INPUT; + key_init_we_o = {NumSharesKey * NumRegsKey{1'b0}}; + + // IV registers + iv_sel_o = IV_INPUT; + iv_we_o = {NumSlicesCtr{1'b0}}; + + // Control registers + ctrl_we_o = 1'b0; + ctrl_gcm_we_o = 1'b0; + + // Alert + alert_o = 1'b0; + + // Pseudo-random number generator control + prng_update_o = 1'b0; + prng_reseed_req_o = 1'b0; + + // Trigger register control + start_we = 1'b0; + key_iv_data_in_clear_we = 1'b0; + data_out_clear_we = 1'b0; + prng_reseed_we = 1'b0; + + // Status register + idle = 1'b0; + idle_we = 1'b0; + stall = 1'b0; + stall_we = 1'b0; + + // Key, data I/O register control + data_in_load = 1'b0; + data_in_we_o = 1'b0; + data_out_sel_o = DATA_OUT_CIPHER; + data_out_we_o = 1'b0; + + // Register status tracker control + key_init_clear = 1'b0; + key_init_load = 1'b0; + key_init_arm = 1'b0; + iv_clear = 1'b0; + iv_load = 1'b0; + iv_arm = 1'b0; + + // Block counter + block_ctr_decr = 1'b0; + + // FSM + aes_ctrl_ns = aes_ctrl_cs; + start_core = 1'b0; + prng_reseed_done_d = prng_reseed_done_q | prng_reseed_ack_i; + hash_subkey_ready_d = hash_subkey_ready_q; + s_ready_d = s_ready_q; + doing_gcm_restore_d = doing_gcm_restore_q; + doing_gcm_aad_d = doing_gcm_aad_q; + doing_gcm_tag_d = doing_gcm_tag_q; + doing_gcm_save_d = doing_gcm_save_q; + + unique case (aes_ctrl_cs) + + CTRL_IDLE: begin + // The core is about to start encryption/decryption or another action. + start_core = start | key_iv_data_in_clear_i | data_out_clear_i | prng_reseed_i; + + // Update status register. A write to the main control register (if sideload is enabled) + // or writing the last key register can initiate a PRNG reseed operation via trigger + // register. To avoid that subsequent writes to the main control, key or IV registers + // collide with the start of the reseed operation, de-assert the idle bit. The GHASH block + // may still be busy while the cipher core is actually idle. + idle = ~(start_core | (prng_reseed_o & prng_reseed_we_o)) & ghash_idle; + idle_we = 1'b1; + + // Clear the start trigger when seeing invalid configurations or performing automatic + // operation. + start_we = start_i & ((mode_i == AES_NONE) | ~manual_operation_i); + + if (!start_core) begin + // Initial key and IV updates are ignored if the core is about to start. If key sideload + // is enabled, software writes to the initial key registers are ignored. + key_init_we_o = sideload_i ? {NumSharesKey * NumRegsKey{key_sideload}} : key_init_qe_i; + iv_we_o = iv_qe; + + // Updates to the main and GCM control registers are only allowed if the core is not + // about to start and there isn't a storage error. A storage error is unrecoverable and + // requires a reset. + ctrl_we_o = !ctrl_err_storage_i ? ctrl_qe_i : 1'b0; + ctrl_gcm_we_o = !ctrl_err_storage_i ? ctrl_gcm_qe_i : 1'b0; + + // Control register updates clear all register status trackers. + key_init_clear = ctrl_we_o; + iv_clear = ctrl_we_o; + end + + if (prng_reseed_i) begin + // PRNG reseeding has highest priority. + if (!SecMasking) begin + prng_reseed_done_d = 1'b0; + aes_ctrl_ns = CTRL_PRNG_RESEED; + end else begin + // In case masking is enabled, also the masking PRNG inside the cipher core needs to + // be reseeded. + cipher_prng_reseed_o = 1'b1; + + // Perform handshake. + cipher_in_valid_o = 1'b1; + if (cipher_in_ready_i) begin + prng_reseed_done_d = 1'b0; + aes_ctrl_ns = CTRL_PRNG_RESEED; + end + end + + end else if (key_iv_data_in_clear_i || data_out_clear_i) begin + // To clear registers, we update the PRNG and then wait for the GHASH block. + prng_update_o = 1'b1; + + // To clear the output data registers, we re-use the muxing resources of the cipher + // core. To clear all key material, some key registers inside the cipher core need to + // be cleared. + cipher_key_clear_o = key_iv_data_in_clear_i; + cipher_data_out_clear_o = data_out_clear_i; + + // We have work for the cipher core, perform handshake. + cipher_in_valid_o = 1'b1; + if (cipher_in_ready_i) begin + aes_ctrl_ns = CTRL_GHASH_READY; + end + + end else if (start_gcm_restore || start_gcm_aad || start_gcm_tag) begin + // We don't have work for the AES cipher core but for the GHASH block only. Load the + // input data into the previous input data register such that it can be loaded into + // the GHASH block in unmasked form. + data_in_prev_sel_o = DIP_DATA_IN; + data_in_prev_we_o = 1'b1; + + // Advance to the loading state where the input data is marked as used. + doing_gcm_restore_d = start_gcm_restore; + doing_gcm_aad_d = start_gcm_aad; + doing_gcm_tag_d = start_gcm_tag; + start_we = 1'b1; + aes_ctrl_ns = CTRL_LOAD; + + end else if (start_gcm_save) begin + // We don't have work for the AES cipher core but for the GHASH block only. Update the + // PRNG (to clear the internal state after saving it) and advance. + prng_update_o = 1'b1; + doing_gcm_save_d = 1'b1; + start_we = 1'b1; + aes_ctrl_ns = CTRL_GHASH_READY; + + end else if (start) begin + // Signal that we want to start encryption/decryption. + cipher_crypt_o = 1'b1; + + // Signal if the cipher core shall reseed the masking PRNG. + cipher_prng_reseed_o = block_ctr_expr; + + // We got a new initial key, but want to do decryption. The cipher core must first + // generate the start key for decryption. + cipher_dec_key_gen_o = (cipher_op_i == CIPH_INV) ? key_init_new : 1'b0; + + // Previous input data register control + data_in_prev_sel_o = doing_cbc_dec ? DIP_DATA_IN : + doing_cfb_enc ? DIP_DATA_IN : + doing_cfb_dec ? DIP_DATA_IN : + doing_ofb ? DIP_DATA_IN : + doing_ctr ? DIP_DATA_IN : + doing_gcm_txt ? DIP_DATA_IN : DIP_CLEAR; + data_in_prev_we_o = doing_cbc_dec | + doing_cfb_enc | + doing_cfb_dec | + doing_ofb | + doing_ctr | + doing_gcm_txt; + + // State input mux control + state_in_sel_o = doing_cfb_enc ? SI_ZERO : + doing_cfb_dec ? SI_ZERO : + doing_ofb ? SI_ZERO : + doing_ctr ? SI_ZERO : + doing_gcm_hsk ? SI_ZERO : + doing_gcm_s ? SI_ZERO : + doing_gcm_txt ? SI_ZERO : SI_DATA; + + // State input addition mux control + add_state_in_sel_o = doing_cbc_enc ? ADD_SI_IV : + doing_cfb_enc ? ADD_SI_IV : + doing_cfb_dec ? ADD_SI_IV : + doing_ofb ? ADD_SI_IV : + doing_ctr ? ADD_SI_IV : + doing_gcm_s ? ADD_SI_IV : + doing_gcm_txt ? ADD_SI_IV : ADD_SI_ZERO; + + // We have work for the cipher core, perform handshake. + cipher_in_valid_o = 1'b1; + if (cipher_in_ready_i) begin + // Do not yet clear a possible start trigger if we are just starting the generation of + // the start key for decryption. + start_we = ~cipher_dec_key_gen_o; + aes_ctrl_ns = CTRL_LOAD; + end + end + end + + CTRL_LOAD: begin + // Signal that we have used the current key, IV, data input to register status tracking. + key_init_load = cipher_dec_key_gen_i; // This key is no longer "new", but still clean. + key_init_arm = ~cipher_dec_key_gen_i; // The key is still "new", prevent partial updates. + iv_load = ~cipher_dec_key_gen_i & (doing_cbc_enc | + doing_cbc_dec | + doing_cfb_enc | + doing_cfb_dec | + doing_ofb | + doing_ctr | + doing_gcm_hsk | + doing_gcm_s | + doing_gcm_txt); + data_in_load = ~cipher_dec_key_gen_i; + + // Trigger counter increment. + ctr_incr_o = doing_ctr | doing_gcm_hsk | doing_gcm_s | doing_gcm_txt; + + // Unless we are just generating the start key for decryption, we must update the PRNG. + // Fresh pseudo-random data is used to: + // - clear the state in the final cipher round, + // - clear any other registers in the CLEAR_I/CO states. + prng_update_o = !cipher_dec_key_gen_i; + + // Unless we are just generating the start key for decryption, we may need to interface + // the GHASH block as well + aes_ctrl_ns = !cipher_dec_key_gen_i ? CTRL_GHASH_READY : CTRL_FINISH; + end + + CTRL_GHASH_READY: begin + // IV control in case of ongoing encryption/decryption + // - CTR: IV registers are updated by counter during cipher operation + iv_sel_o = doing_ctr || + doing_gcm_hsk || + doing_gcm_s || + doing_gcm_txt ? IV_CTR : IV_INPUT; + iv_we_o = doing_ctr || + doing_gcm_hsk || + doing_gcm_s || + doing_gcm_txt ? ctr_we_i : {NumSlicesCtr{1'b0}}; + + // Ongoing encryption/decryption operations have the highest priority. The clear triggers + // might for example have become asserted after the handshake with the cipher core. + if (cipher_crypt_i) begin + if (doing_gcm_hsk || doing_gcm_s || doing_gcm_txt) begin + // We actually have some work for the GHASH block. Make sure it's ready before we move. + // We send the valid in a following clock cycle. Doing this check here, allows to + // decouple the valid from the ready. + if (ghash_in_ready_i) begin + aes_ctrl_ns = CTRL_FINISH; + end + end else begin + // We're not actually using the GHASH block and don't need to check it's status. + aes_ctrl_ns = CTRL_FINISH; + end + + end else if (doing_gcm_restore_q) begin + // Pass the previously saved GHASH state to the GHASH block. We're done after the input + // handshake. + ghash_in_valid_o = 1'b1; + if (ghash_in_ready_i) begin + doing_gcm_restore_d = 1'b0; + aes_ctrl_ns = CTRL_IDLE; + end + + end else if (doing_gcm_aad_q) begin + // Pass the AAD to the GHASH block. We're done after the input handshake. + ghash_in_valid_o = 1'b1; + if (ghash_in_ready_i) begin + doing_gcm_aad_d = 1'b0; + aes_ctrl_ns = CTRL_IDLE; + end + + end else if (doing_gcm_save_q) begin + // Perform the handshake with the GHASH block and then wait for the GHASH block to output + // the state. + ghash_in_valid_o = 1'b1; + if (ghash_in_ready_i) begin + aes_ctrl_ns = CTRL_FINISH; + end + + end else if (doing_gcm_tag_q) begin + // Pass the AAD and text length to the GHASH block and wait for the final authentication + // tag afterwards. + ghash_in_valid_o = 1'b1; + if (ghash_in_ready_i) begin + aes_ctrl_ns = CTRL_FINISH; + end + + end else if (key_iv_data_in_clear_i || data_out_clear_i || + cipher_key_clear_i || cipher_data_out_clear_i) begin + // We actually have some work for the GHASH block. Make sure it's ready before we move. + // We send the valid in a following clock cycle. Doing this check here, allows to + // decouple the valid from the ready. + if (ghash_in_ready_i) begin + aes_ctrl_ns = CTRL_CLEAR_I; + end + end else begin + // Another write to the trigger register must have overwritten the trigger bits that + // actually caused us to enter this state. Just return. + aes_ctrl_ns = CTRL_IDLE; + end + end + + CTRL_PRNG_RESEED: begin + // Request a reseed of the clearing PRNG. + prng_reseed_req_o = ~prng_reseed_done_q; + + if (!SecMasking) begin + if (prng_reseed_done_q) begin + // Clear the trigger and return. + prng_reseed_we = 1'b1; + prng_reseed_done_d = 1'b0; + aes_ctrl_ns = CTRL_IDLE; + end + + end else begin + // In case masking is used, we must also wait for the cipher core to reseed the internal + // masking PRNG. Perform handshake. + cipher_out_ready_o = prng_reseed_done_q; + if (cipher_out_ready_o && cipher_out_valid_i) begin + // Clear the trigger and return. + prng_reseed_we = 1'b1; + prng_reseed_done_d = 1'b0; + aes_ctrl_ns = CTRL_IDLE; + end + end + end + + CTRL_FINISH: begin + // Wait for cipher core to finish. + + if (cipher_dec_key_gen_i) begin + // We are ready. + cipher_out_ready_o = 1'b1; + if (cipher_out_valid_i) begin + block_ctr_decr = 1'b1; + aes_ctrl_ns = CTRL_IDLE; + end + end else if (doing_gcm_save_q || doing_gcm_tag_q) begin + // Handshake signals: We are ready once the output data registers can be written. Don't + // let data propagate in case of mux selector or sparsely encoded signals taking on + // invalid values. + ghash_out_ready_o = finish; + ghash_out_done = finish & ghash_out_valid_i & + ~mux_sel_err_i & ~sp_enc_err_i & ~cipher_op_err; + + // Signal if the GHASH block is stalled (because previous output has not yet been read). + stall = ~finish & ghash_out_valid_i; + stall_we = 1'b1; + + // Forward the GHASH output instead of the cipher core output. + data_out_sel_o = DATA_OUT_GHASH; + + // Proceed upon successful handshake. Mark hash subkey and s as not ready, the GHASH + // block clears those registers after the handshake. + if (ghash_out_done) begin + doing_gcm_save_d = 1'b0; + doing_gcm_tag_d = 1'b0; + hash_subkey_ready_d = 1'b0; + s_ready_d = 1'b0; + data_out_we_o = 1'b1; + aes_ctrl_ns = CTRL_IDLE; + end + + end else begin + // Handshake signals: We are ready once the output data registers can be written. Don't + // let data propagate in case of mux selector or sparsely encoded signals taking on + // invalid values. + cipher_out_ready_o = finish; + cipher_out_done = finish & cipher_out_valid_i & + ~mux_sel_err_i & ~sp_enc_err_i & ~cipher_op_err; + + // Signal if the cipher core is stalled (because previous output has not yet been read). + stall = ~finish & cipher_out_valid_i; + stall_we = 1'b1; + + // State out addition mux control + add_state_out_sel_o = doing_cbc_dec ? ADD_SO_IV : + doing_cfb_enc ? ADD_SO_DIP : + doing_cfb_dec ? ADD_SO_DIP : + doing_ofb ? ADD_SO_DIP : + doing_ctr ? ADD_SO_DIP : + doing_gcm_txt ? ADD_SO_DIP : ADD_SO_ZERO; + + // IV control + // - CBC/CFB/OFB: IV registers are only updated when cipher finishes. + // - CTR/GCM: IV registers are updated by counter during cipher operation. + // The same holds when we're computing the hash subkey for GCM. + iv_sel_o = doing_cbc_enc ? IV_DATA_OUT : + doing_cbc_dec ? IV_DATA_IN_PREV : + doing_cfb_enc ? IV_DATA_OUT : + doing_cfb_dec ? IV_DATA_IN_PREV : + doing_ofb ? IV_DATA_OUT_RAW : + doing_ctr ? IV_CTR : + doing_gcm_hsk ? IV_CTR : + doing_gcm_s ? IV_CTR : + doing_gcm_txt ? IV_CTR : IV_INPUT; + iv_we_o = doing_cbc_enc || + doing_cbc_dec || + doing_cfb_enc || + doing_cfb_dec || + doing_ofb ? {NumSlicesCtr{cipher_out_done}} : + doing_ctr ? ctr_we_i : + doing_gcm_hsk ? ctr_we_i : + doing_gcm_s ? ctr_we_i : + doing_gcm_txt ? ctr_we_i : {NumSlicesCtr{1'b0}}; + + // Arm the IV status tracker: After finishing, the IV registers can be written again + // by software. We need to make sure software does not partially update the IV. + iv_arm = (doing_cbc_enc | + doing_cbc_dec | + doing_cfb_enc | + doing_cfb_dec | + doing_ofb | + doing_ctr | + doing_gcm_hsk | + doing_gcm_s | + doing_gcm_txt) & cipher_out_done; + + // Proceed upon successful handshake. When initializing GHASH for GCM, don't write to the + // cipher output to the output data registers but forward it to the GHASH block and + // mark the hash subkey or S as ready. + if (cipher_out_done) begin + block_ctr_decr = 1'b1; + data_out_we_o = doing_gcm_hsk | + doing_gcm_s ? 1'b0 : 1'b1; + ghash_in_valid_o = doing_gcm_hsk | + doing_gcm_s | + doing_gcm_txt ? 1'b1 : 1'b0; + hash_subkey_ready_d = doing_gcm_hsk ? 1'b1 : hash_subkey_ready_q; + s_ready_d = doing_gcm_s ? 1'b1 : s_ready_q; + aes_ctrl_ns = CTRL_IDLE; + end + end + end + + CTRL_CLEAR_I: begin + // Clear input registers such as Initial Key, IV and input data registers. + if (key_iv_data_in_clear_i) begin + // Initial Key + key_init_sel_o = KEY_INIT_CLEAR; + key_init_we_o = {NumSharesKey * NumRegsKey{1'b1}}; + key_init_clear = 1'b1; + + // IV + iv_sel_o = IV_CLEAR; + iv_we_o = {NumSlicesCtr{1'b1}}; + iv_clear = 1'b1; + + // Input data + data_in_we_o = 1'b1; + data_in_prev_sel_o = DIP_CLEAR; + data_in_prev_we_o = 1'b1; + end + aes_ctrl_ns = CTRL_CLEAR_CO; + end + + CTRL_CLEAR_CO: begin + // Wait for cipher core to clear internal Full Key and Decryption Key registers and/or + // the state register and clear output data registers afterwards. + + // Perform handshake with cipher core. + cipher_out_ready_o = 1'b1; + if (cipher_out_valid_i) begin + + // Full Key and Decryption Key registers are cleared by the cipher core. + // key_iv_data_in_clear_i is acknowledged by the cipher core with cipher_key_clear_i. + if (cipher_key_clear_i) begin + // Clear the trigger bit. + key_iv_data_in_clear_we = 1'b1; + + // The GHASH block can now clear it's internal registers. + ghash_in_valid_o = 1'b1; + end + + // To clear the output data registers, we re-use the muxing resources of the cipher core. + // data_out_clear_i is acknowledged by the cipher core with cipher_data_out_clear_i. + if (cipher_data_out_clear_i) begin + // Clear output data and the trigger bit. Don't release data from cipher core in case + // of mux selector or sparsely encoded signals taking on invalid values. + data_out_we_o = ~mux_sel_err_i & ~sp_enc_err_i & ~cipher_op_err; + data_out_clear_we = 1'b1; + end + + aes_ctrl_ns = CTRL_IDLE; + end + end + + CTRL_ERROR: begin + // SEC_CM: MAIN.FSM.GLOBAL_ESC + // SEC_CM: MAIN.FSM.LOCAL_ESC + // Terminal error state + alert_o = 1'b1; + end + + // We should never get here. If we do (e.g. via a malicious glitch), error out immediately. + default: begin + aes_ctrl_ns = CTRL_ERROR; + alert_o = 1'b1; + end + endcase + + // Unconditionally jump into the terminal error state in case a mux selector or a sparsely + // encoded signal becomes invalid, or if the life cycle controller triggers an escalation. + if (mux_sel_err_i || sp_enc_err_i || cipher_op_err || + lc_ctrl_pkg::lc_tx_test_true_loose(lc_escalate_en_i)) begin + aes_ctrl_ns = CTRL_ERROR; + end + end + + // SEC_CM: MAIN.FSM.SPARSE + `CALIPTRA_PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_ctrl_ns, aes_ctrl_cs, aes_ctrl_e, CTRL_IDLE) + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm + if (!rst_ni) begin + prng_reseed_done_q <= 1'b0; + end else begin + prng_reseed_done_q <= prng_reseed_done_d; + end + end + + if (AESGCMEnable) begin : gen_reg_fsm_gcm + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_fsm_gcm + if (!rst_ni) begin + hash_subkey_ready_q <= 1'b0; + s_ready_q <= 1'b0; + doing_gcm_restore_q <= 1'b0; + doing_gcm_aad_q <= 1'b0; + doing_gcm_save_q <= 1'b0; + doing_gcm_tag_q <= 1'b0; + end else begin + hash_subkey_ready_q <= hash_subkey_ready_d; + s_ready_q <= s_ready_d; + doing_gcm_restore_q <= doing_gcm_restore_d; + doing_gcm_aad_q <= doing_gcm_aad_d; + doing_gcm_save_q <= doing_gcm_save_d; + doing_gcm_tag_q <= doing_gcm_tag_d; + end + end + end else begin : gen_no_reg_fsm_gcm + // GCM is simply not supported. + assign hash_subkey_ready_q = 1'b0; + assign s_ready_q = 1'b0; + assign doing_gcm_restore_q = 1'b0; + assign doing_gcm_aad_q = 1'b0; + assign doing_gcm_save_q = 1'b0; + assign doing_gcm_tag_q = 1'b0; + + // Tie-off unused signals. + logic unused_gcm_d; + assign unused_gcm_d = ^{hash_subkey_ready_d, + s_ready_d, + doing_gcm_restore_d, + doing_gcm_aad_d, + doing_gcm_save_d, + doing_gcm_tag_d}; + end + + ///////////////////// + // Status Tracking // + ///////////////////// + + // We only take a new sideload key if sideload is enabled, if the provided sideload key is marked + // as valid, and after the control register has been written for the second time. After that + // point we don't update the key anymore, as we don't have a notion of when it actually changes. + // This would be required to trigger decryption key generation for ECB/CBC decryption. + // To update the sideload key, software has to: + // 1) wait unitl AES is idle, + // 2) wait for the key manager to provide the new key, + // 3) start a new message by writing the control register and providing the IV (if needed). + assign key_sideload = sideload_i & key_sideload_valid_i & ctrl_we_q & ~ctrl_phase_i; + + // We only use clean initial keys. Either software/counter has updated + // - all initial key registers, or + // - none of the initial key registers but the registers were updated in the past. + aes_reg_status #( + .Width ( $bits(key_init_we_o) ) + ) u_reg_status_key_init ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .we_i ( key_init_we_o ), + .use_i ( key_init_load ), + .clear_i ( key_init_clear ), + .arm_i ( key_init_arm ), + .new_o ( key_init_new ), + .new_pulse_o ( key_init_new_pulse ), + .clean_o ( key_init_ready ) + ); + + // We only use clean and unused IVs. Either software/counter has updated + // - all IV registers, or + // - none of the IV registers but the registers were updated in the past + // and this particular IV has not yet been used. + aes_reg_status #( + .Width ( $bits(iv_we_o) ) + ) u_reg_status_iv ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .we_i ( iv_we_o ), + .use_i ( iv_load ), + .clear_i ( iv_clear ), + .arm_i ( iv_arm ), + .new_o ( iv_ready ), + .new_pulse_o ( ), + .clean_o ( ) + ); + + // Input and output data register status tracking detects if: + // - A complete new data input block is available, and + // - An output data block has been read completely. + // The status tracking needs to be cleared upon writes to the control register. The clearing is + // applied one cycle later here to avoid zero-latency loops. This additional delay is not + // relevant as if we are about to start encryption/decryption, we anyway don't allow writes + // to the control register. + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_ctrl_we + if (!rst_ni) begin + ctrl_we_q <= 1'b0; + end else begin + ctrl_we_q <= ctrl_we_o; + end + end + assign clear_in_out_status = ctrl_we_q; + + // Collect writes to data input registers. Cleared if: + // - data is loaded into cipher core, + // - clearing data input registers with random data (all data_in_qe_i bits high in next cycle), + // - clearing the status tracking. + assign data_in_new_d = data_in_load || &data_in_qe_i || clear_in_out_status ? '0 : + data_in_new_q | data_in_qe_i; + assign data_in_new = &data_in_new_d; + + // Collect reads of data output registers. data_out_read is high for one clock cycle only and + // clears output_valid_q unless new output is written in the exact same cycle. Cleared if: + // - clearing data ouput registers with random data, + // - clearing the status tracking. + assign data_out_read_d = &data_out_read_q || clear_in_out_status ? '0 : + data_out_read_q | data_out_re_i; + assign data_out_read = &data_out_read_d; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_edge_detection + if (!rst_ni) begin + data_in_new_q <= '0; + data_out_read_q <= '0; + end else begin + data_in_new_q <= data_in_new_d; + data_out_read_q <= data_out_read_d; + end + end + + // Status register bits for data input and output + // Cleared to 1 if: + // - data is loaded into cipher core, + // - clearing data input registers with random data, + // - clearing the status tracking. + assign input_ready = ~data_in_new; + assign input_ready_we = data_in_new | data_in_load | data_in_we_o | clear_in_out_status; + + // Cleared if: + // - all data output registers have been read (unless new output is written in the same cycle), + // - clearing data ouput registers with random data, + // - clearing the status tracking. + assign output_valid = data_out_we_o & ~data_out_clear_we; + assign output_valid_we = data_out_we_o | data_out_read | data_out_clear_we | + clear_in_out_status; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_output_valid + if (!rst_ni) begin + output_valid_q <= '0; + end else if (output_valid_we) begin + output_valid_q <= output_valid; + end + end + + // Output lost status register bit + // Cleared when updating the Control Register. Set when overwriting previous output data that has + // not yet been read. + assign output_lost = ctrl_we_o ? 1'b0 : + output_lost_i ? 1'b1 : output_valid_q & ~data_out_read; + assign output_lost_we = ctrl_we_o | data_out_we_o; + + // Should fatal alerts clear the status and trigger register? + assign clear_on_fatal = ClearStatusOnFatalAlert ? alert_fatal_i : 1'b0; + + ///////////////////// + // Status Register // + ///////////////////// + assign idle_o = clear_on_fatal ? 1'b0 : idle; + assign idle_we_o = clear_on_fatal ? 1'b1 : idle_we; + assign stall_o = clear_on_fatal ? 1'b0 : stall; + assign stall_we_o = clear_on_fatal ? 1'b1 : stall_we; + assign output_lost_o = clear_on_fatal ? 1'b0 : output_lost; + assign output_lost_we_o = clear_on_fatal ? 1'b1 : output_lost_we; + assign output_valid_o = clear_on_fatal ? 1'b0 : output_valid; + assign output_valid_we_o = clear_on_fatal ? 1'b1 : output_valid_we; + assign input_ready_o = clear_on_fatal ? 1'b0 : input_ready; + assign input_ready_we_o = clear_on_fatal ? 1'b1 : input_ready_we; + + ////////////////////// + // Trigger Register // + ////////////////////// + // Most triggers are only ever cleared by control. Fatal alerts clear all bits in the trigger + // register. + assign start_we_o = clear_on_fatal ? 1'b1 : start_we; + assign key_iv_data_in_clear_we_o = clear_on_fatal ? 1'b1 : key_iv_data_in_clear_we; + assign data_out_clear_we_o = clear_on_fatal ? 1'b1 : data_out_clear_we; + + // If configured, trigger the reseeding of the PRNGs used for clearing and masking purposes after + // the key has been updated. + assign prng_reseed_o = clear_on_fatal ? 1'b0 : + key_init_new_pulse ? 1'b1 : 1'b0; + assign prng_reseed_we_o = clear_on_fatal ? 1'b1 : + key_init_new_pulse ? key_touch_forces_reseed_i : prng_reseed_we; + + //////////////////////////// + // PRNG Reseeding Counter // + //////////////////////////// + // Count the number of blocks since the start of the message to determine when the masking PRNG + // inside the cipher core needs to be reseeded. + if (SecMasking) begin : gen_block_ctr + logic block_ctr_set; + logic [BlockCtrWidth-1:0] block_ctr_d, block_ctr_q; + logic [BlockCtrWidth-1:0] block_ctr_set_val, block_ctr_decr_val; + + assign block_ctr_expr = block_ctr_q == '0; + assign block_ctr_set = ctrl_we_q | (block_ctr_decr & (block_ctr_expr | cipher_prng_reseed_i)); + + assign block_ctr_set_val = prng_reseed_rate_i == PER_1 ? '0 : + prng_reseed_rate_i == PER_64 ? BlockCtrWidth'(63) : + prng_reseed_rate_i == PER_8K ? BlockCtrWidth'(8191) : '0; + + assign block_ctr_decr_val = block_ctr_q - BlockCtrWidth'(1); + + assign block_ctr_d = block_ctr_set ? block_ctr_set_val : + block_ctr_decr ? block_ctr_decr_val : block_ctr_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_block_ctr + if (!rst_ni) begin + block_ctr_q <= '0; + end else begin + block_ctr_q <= block_ctr_d; + end + end + + end else begin : gen_no_block_ctr + assign block_ctr_expr = 1'b0; + + // Tie off unused signals. + logic unused_block_ctr_decr; + prs_rate_e unused_prng_reseed_rate; + logic unused_cipher_prng_reseed; + assign unused_block_ctr_decr = block_ctr_decr; + assign unused_prng_reseed_rate = prng_reseed_rate_i; + assign unused_cipher_prng_reseed = cipher_prng_reseed_i; + end + + //////////////// + // Assertions // + //////////////// + + // Create a lint error to reduce the risk of accidentally disabling the masking. + `CALIPTRA_ASSERT_STATIC_LINT_ERROR(AesControlFsmSecMaskingNonDefault, SecMasking == 1) + + // Selectors must be known/valid + `CALIPTRA_ASSERT(AesModeValid, !ctrl_err_storage_i |-> mode_i inside { + AES_ECB, + AES_CBC, + AES_CFB, + AES_OFB, + AES_CTR, + AES_GCM, + AES_NONE + }) + `CALIPTRA_ASSERT(AesOpValid, !ctrl_err_storage_i |-> op_i inside { + AES_ENC, + AES_DEC + }) + `CALIPTRA_ASSERT(AesCiphOpValid, !cipher_op_err |-> cipher_op_i inside { + CIPH_FWD, + CIPH_INV + }) + `CALIPTRA_ASSERT(AesControlStateValid, !alert_o |-> aes_ctrl_cs inside { + CTRL_IDLE, + CTRL_LOAD, + CTRL_GHASH_READY, + CTRL_PRNG_RESEED, + CTRL_FINISH, + CTRL_CLEAR_I, + CTRL_CLEAR_CO + }) + + // Check parameters + `CALIPTRA_ASSERT_INIT(AesNumSlicesCtr, NumSlicesCtr == 8) + +endmodule diff --git a/src/aes/rtl/aes_control_fsm_n.sv b/src/aes/rtl/aes_control_fsm_n.sv new file mode 100644 index 000000000..e2b2d7cd6 --- /dev/null +++ b/src/aes/rtl/aes_control_fsm_n.sv @@ -0,0 +1,626 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES main control FSM +// +// This module contains the main control FSM handling the interplay of input/output registers and +// the AES cipher core. This version operates on and produces the negated values of important +// control signals. This is achieved by: +// - instantiating the regular main control FSM operating on and producing the positive values of +// these signals, and +// - inverting these signals between the regular FSM and the caliptra_prim_buf synthesis barriers. +// Synthesis tools will then push the inverters into the actual FSM. + +`include "caliptra_prim_assert.sv" + +module aes_control_fsm_n + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AESGCMEnable = 0, + parameter bit SecMasking = 0 +) ( + input logic clk_i, + input logic rst_ni, + + // Main control signals + input logic ctrl_qe_i, + output logic ctrl_we_o, + input logic ctrl_phase_i, + input logic ctrl_err_storage_i, + input aes_op_e op_i, + input aes_mode_e mode_i, + input ciph_op_e cipher_op_i, + input logic sideload_i, + input prs_rate_e prng_reseed_rate_i, + input logic manual_operation_i, + input logic key_touch_forces_reseed_i, + input logic ctrl_gcm_qe_i, + output logic ctrl_gcm_we_o, + input gcm_phase_e gcm_phase_i, + input logic start_i, + input logic key_iv_data_in_clear_i, + input logic data_out_clear_i, + input logic prng_reseed_i, + input logic mux_sel_err_i, + input logic sp_enc_err_i, + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + input logic alert_fatal_i, + output logic alert_o, + + // I/O register read/write enables + input logic key_sideload_valid_i, + input logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe_i, + input logic [NumRegsIv-1:0] iv_qe_i, + input logic [NumRegsData-1:0] data_in_qe_i, + input logic [NumRegsData-1:0] data_out_re_i, + output logic data_in_we_o, + output data_out_sel_e data_out_sel_o, + output logic data_out_we_no, // Sparsify + + // Previous input data register + output dip_sel_e data_in_prev_sel_o, + output logic data_in_prev_we_no, // Sparsify + + // Cipher I/O muxes + output si_sel_e state_in_sel_o, + output add_si_sel_e add_state_in_sel_o, + output add_so_sel_e add_state_out_sel_o, + + // Counter + output logic ctr_inc32_no, // Sparsify + output logic ctr_incr_no, // Sparsify + input logic ctr_ready_ni, // Sparsify + input logic [NumSlicesCtr-1:0] ctr_we_ni, // Sparsify + + // Cipher core control and sync + output logic cipher_in_valid_no, // Sparsify + input logic cipher_in_ready_ni, // Sparsify + input logic cipher_out_valid_ni, // Sparsify + output logic cipher_out_ready_no, // Sparsify + output logic cipher_crypt_no, // Sparsify + input logic cipher_crypt_ni, // Sparsify + output logic cipher_dec_key_gen_no, // Sparsify + input logic cipher_dec_key_gen_ni, // Sparsify + output logic cipher_prng_reseed_o, + input logic cipher_prng_reseed_i, + output logic cipher_key_clear_o, + input logic cipher_key_clear_i, + output logic cipher_data_out_clear_o, + input logic cipher_data_out_clear_i, + + // GHASH control and sync + output logic ghash_in_valid_no, // Sparsify + input logic ghash_in_ready_ni, // Sparsify + input logic ghash_out_valid_ni, // Sparsify + output logic ghash_out_ready_no, // Sparsify + output logic ghash_load_hash_subkey_no, // Sparsify + + // Initial key registers + output key_init_sel_e key_init_sel_o, + output logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we_no, // Sparsify + + // IV registers + output iv_sel_e iv_sel_o, + output logic [NumSlicesCtr-1:0] iv_we_no, // Sparsify + + // Pseudo-random number generator interface + output logic prng_update_o, + output logic prng_reseed_req_o, + input logic prng_reseed_ack_i, + + // Trigger register + output logic start_we_o, + output logic key_iv_data_in_clear_we_o, + output logic data_out_clear_we_o, + output logic prng_reseed_o, + output logic prng_reseed_we_o, + + // Status register + output logic idle_o, + output logic idle_we_o, + output logic stall_o, + output logic stall_we_o, + input logic output_lost_i, + output logic output_lost_o, + output logic output_lost_we_o, + output logic output_valid_o, + output logic output_valid_we_o, + output logic input_ready_o, + output logic input_ready_we_o +); + + ///////////////////// + // Input Buffering // + ///////////////////// + + localparam int NumInBufBits = $bits({ + ctrl_qe_i, + ctrl_phase_i, + ctrl_err_storage_i, + op_i, + mode_i, + cipher_op_i, + sideload_i, + prng_reseed_rate_i, + manual_operation_i, + key_touch_forces_reseed_i, + ctrl_gcm_qe_i, + gcm_phase_i, + start_i, + key_iv_data_in_clear_i, + data_out_clear_i, + prng_reseed_i, + mux_sel_err_i, + sp_enc_err_i, + lc_escalate_en_i, + alert_fatal_i, + key_sideload_valid_i, + key_init_qe_i, + iv_qe_i, + data_in_qe_i, + data_out_re_i, + ctr_ready_ni, + ctr_we_ni, + cipher_in_ready_ni, + cipher_out_valid_ni, + cipher_crypt_ni, + cipher_dec_key_gen_ni, + cipher_prng_reseed_i, + cipher_key_clear_i, + cipher_data_out_clear_i, + ghash_in_ready_ni, + ghash_out_valid_ni, + prng_reseed_ack_i, + output_lost_i + }); + + logic [NumInBufBits-1:0] in, in_buf; + + assign in = { + ctrl_qe_i, + ctrl_phase_i, + ctrl_err_storage_i, + op_i, + mode_i, + cipher_op_i, + sideload_i, + prng_reseed_rate_i, + manual_operation_i, + key_touch_forces_reseed_i, + ctrl_gcm_qe_i, + gcm_phase_i, + start_i, + key_iv_data_in_clear_i, + data_out_clear_i, + prng_reseed_i, + mux_sel_err_i, + sp_enc_err_i, + lc_escalate_en_i, + alert_fatal_i, + key_sideload_valid_i, + key_init_qe_i, + iv_qe_i, + data_in_qe_i, + data_out_re_i, + ctr_ready_ni, + ctr_we_ni, + cipher_in_ready_ni, + cipher_out_valid_ni, + cipher_crypt_ni, + cipher_dec_key_gen_ni, + cipher_prng_reseed_i, + cipher_key_clear_i, + cipher_data_out_clear_i, + ghash_in_ready_ni, + ghash_out_valid_ni, + prng_reseed_ack_i, + output_lost_i + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumInBufBits) + ) u_caliptra_prim_buf_in ( + .in_i(in), + .out_o(in_buf) + ); + + logic ctrl_qe; + logic ctrl_phase; + logic ctrl_err_storage; + aes_op_e op; + aes_mode_e mode; + ciph_op_e cipher_op; + logic [$bits(cipher_op)-1:0] cipher_op_raw; + logic sideload; + prs_rate_e prng_reseed_rate; + logic manual_operation; + logic key_touch_forces_reseed; + logic ctrl_gcm_qe; + gcm_phase_e gcm_phase; + logic [$bits(gcm_phase)-1:0] gcm_phase_raw; + logic start; + logic key_iv_data_in_clear; + logic data_out_clear; + logic prng_reseed_in_buf; + logic mux_sel_err; + logic sp_enc_err; + lc_ctrl_pkg::lc_tx_t lc_escalate_en; + logic alert_fatal; + logic key_sideload_valid; + logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe; + logic [NumRegsIv-1:0] iv_qe; + logic [NumRegsData-1:0] data_in_qe; + logic [NumRegsData-1:0] data_out_re; + logic ctr_ready_n; + logic [NumSlicesCtr-1:0] ctr_we_n; + logic cipher_in_ready_n; + logic cipher_out_valid_n; + logic cipher_crypt_in_buf_n; + logic cipher_dec_key_gen_in_buf_n; + logic cipher_prng_reseed_in_buf; + logic cipher_key_clear_in_buf; + logic cipher_data_out_clear_in_buf; + logic ghash_in_ready_n; + logic ghash_out_valid_n; + logic prng_reseed_ack; + logic output_lost_in_buf; + + assign {ctrl_qe, + ctrl_phase, + ctrl_err_storage, + op, + mode, + cipher_op_raw, + sideload, + prng_reseed_rate, + manual_operation, + key_touch_forces_reseed, + ctrl_gcm_qe, + gcm_phase_raw, + start, + key_iv_data_in_clear, + data_out_clear, + prng_reseed_in_buf, + mux_sel_err, + sp_enc_err, + lc_escalate_en, + alert_fatal, + key_sideload_valid, + key_init_qe, + iv_qe, + data_in_qe, + data_out_re, + ctr_ready_n, + ctr_we_n, + cipher_in_ready_n, + cipher_out_valid_n, + cipher_crypt_in_buf_n, + cipher_dec_key_gen_in_buf_n, + cipher_prng_reseed_in_buf, + cipher_key_clear_in_buf, + cipher_data_out_clear_in_buf, + ghash_in_ready_n, + ghash_out_valid_n, + prng_reseed_ack, + output_lost_in_buf} = in_buf; + + assign cipher_op = ciph_op_e'(cipher_op_raw); + assign gcm_phase = gcm_phase_e'(gcm_phase_raw); + + // Intermediate output signals + logic ctrl_we; + logic ctrl_gcm_we; + logic alert; + logic data_in_we; + data_out_sel_e data_out_sel; + logic data_out_we; + dip_sel_e data_in_prev_sel; + logic data_in_prev_we; + si_sel_e state_in_sel; + add_si_sel_e add_state_in_sel; + add_so_sel_e add_state_out_sel; + logic ctr_inc32; + logic ctr_incr; + logic cipher_in_valid; + logic cipher_out_ready; + logic cipher_crypt_out_buf; + logic cipher_dec_key_gen_out_buf; + logic cipher_prng_reseed_out_buf; + logic cipher_key_clear_out_buf; + logic cipher_data_out_clear_out_buf; + logic ghash_in_valid; + logic ghash_out_ready; + logic ghash_load_hash_subkey; + key_init_sel_e key_init_sel; + logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we; + iv_sel_e iv_sel; + logic [NumSlicesCtr-1:0] iv_we; + logic prng_update; + logic prng_reseed_req; + logic start_we; + logic key_iv_data_in_clear_we; + logic data_out_clear_we; + logic prng_reseed_out_buf; + logic prng_reseed_we; + logic idle; + logic idle_we; + logic stall; + logic stall_we; + logic output_lost_out_buf; + logic output_lost_we; + logic output_valid; + logic output_valid_we; + logic input_ready; + logic input_ready_we; + + ///////////////// + // Regular FSM // + ///////////////// + + // The regular FSM operates on and produces the positive values of important control signals. + // Invert *_n input signals here to get the positive values for the regular FSM. To obtain the + // negated outputs, important output signals are inverted further below. Thanks to the caliptra_prim_buf + // synthesis optimization barriers, tools will push the inverters into the regular FSM. + aes_control_fsm #( + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ) + ) u_aes_control_fsm ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .ctrl_qe_i ( ctrl_qe ), + .ctrl_we_o ( ctrl_we ), + .ctrl_phase_i ( ctrl_phase ), + .ctrl_err_storage_i ( ctrl_err_storage ), + .op_i ( op ), + .mode_i ( mode ), + .cipher_op_i ( cipher_op ), + .sideload_i ( sideload ), + .prng_reseed_rate_i ( prng_reseed_rate ), + .manual_operation_i ( manual_operation ), + .key_touch_forces_reseed_i ( key_touch_forces_reseed ), + .ctrl_gcm_qe_i ( ctrl_gcm_qe ), + .ctrl_gcm_we_o ( ctrl_gcm_we ), + .gcm_phase_i ( gcm_phase ), + .start_i ( start ), + .key_iv_data_in_clear_i ( key_iv_data_in_clear ), + .data_out_clear_i ( data_out_clear ), + .prng_reseed_i ( prng_reseed_in_buf ), + .mux_sel_err_i ( mux_sel_err ), + .sp_enc_err_i ( sp_enc_err ), + .lc_escalate_en_i ( lc_escalate_en ), + .alert_fatal_i ( alert_fatal ), + .alert_o ( alert ), + + .key_sideload_valid_i ( key_sideload_valid ), + .key_init_qe_i ( key_init_qe ), + .iv_qe_i ( iv_qe ), + .data_in_qe_i ( data_in_qe ), + .data_out_re_i ( data_out_re ), + .data_in_we_o ( data_in_we ), + .data_out_sel_o ( data_out_sel ), + .data_out_we_o ( data_out_we ), // Invert below for _n output. + + .data_in_prev_sel_o ( data_in_prev_sel ), + .data_in_prev_we_o ( data_in_prev_we ), // Invert below for _n output. + + .state_in_sel_o ( state_in_sel ), + .add_state_in_sel_o ( add_state_in_sel ), + .add_state_out_sel_o ( add_state_out_sel ), + + .ctr_inc32_o ( ctr_inc32 ), // Invert below for _n output. + .ctr_incr_o ( ctr_incr ), // Invert below for _n output. + .ctr_ready_i ( ~ctr_ready_n ), // Invert for regular FSM. + .ctr_we_i ( ~ctr_we_n ), // Invert for regular FSM. + + .cipher_in_valid_o ( cipher_in_valid ), // Invert below for _n output. + .cipher_in_ready_i ( ~cipher_in_ready_n ), // Invert for regular FSM. + .cipher_out_valid_i ( ~cipher_out_valid_n ), // Invert for regular FSM. + .cipher_out_ready_o ( cipher_out_ready ), // Invert below for _n output. + .cipher_crypt_o ( cipher_crypt_out_buf ), // Invert below for _n output. + .cipher_crypt_i ( ~cipher_crypt_in_buf_n ), // Invert for regular FSM. + .cipher_dec_key_gen_o ( cipher_dec_key_gen_out_buf ), // Invert below for _n output. + .cipher_dec_key_gen_i ( ~cipher_dec_key_gen_in_buf_n ), // Invert for regular FSM. + .cipher_prng_reseed_o ( cipher_prng_reseed_out_buf ), + .cipher_prng_reseed_i ( cipher_prng_reseed_in_buf ), + .cipher_key_clear_o ( cipher_key_clear_out_buf ), + .cipher_key_clear_i ( cipher_key_clear_in_buf ), + .cipher_data_out_clear_o ( cipher_data_out_clear_out_buf ), + .cipher_data_out_clear_i ( cipher_data_out_clear_in_buf ), + + .ghash_in_valid_o ( ghash_in_valid ), // Invert below for _n output. + .ghash_in_ready_i ( ~ghash_in_ready_n ), // Invert for regular FSM. + .ghash_out_valid_i ( ~ghash_out_valid_n ), // Invert for regular FSM. + .ghash_out_ready_o ( ghash_out_ready ), // Invert below for _n output. + .ghash_load_hash_subkey_o ( ghash_load_hash_subkey ), // Invert below for _n output. + + .key_init_sel_o ( key_init_sel ), + .key_init_we_o ( key_init_we ), // Invert below for _n output. + + .iv_sel_o ( iv_sel ), + .iv_we_o ( iv_we ), // Invert below for _n output. + + .prng_update_o ( prng_update ), + .prng_reseed_req_o ( prng_reseed_req ), + .prng_reseed_ack_i ( prng_reseed_ack ), + + .start_we_o ( start_we ), + .key_iv_data_in_clear_we_o ( key_iv_data_in_clear_we ), + .data_out_clear_we_o ( data_out_clear_we ), + .prng_reseed_o ( prng_reseed_out_buf ), + .prng_reseed_we_o ( prng_reseed_we ), + + .idle_o ( idle ), + .idle_we_o ( idle_we ), + .stall_o ( stall ), + .stall_we_o ( stall_we ), + .output_lost_i ( output_lost_in_buf ), + .output_lost_o ( output_lost_out_buf ), + .output_lost_we_o ( output_lost_we ), + .output_valid_o ( output_valid ), + .output_valid_we_o ( output_valid_we ), + .input_ready_o ( input_ready ), + .input_ready_we_o ( input_ready_we ) + ); + + ////////////////////// + // Output Buffering // + ////////////////////// + + localparam int NumOutBufBits = $bits({ + ctrl_we_o, + ctrl_gcm_we_o, + alert_o, + data_in_we_o, + data_out_sel_o, + data_out_we_no, + data_in_prev_sel_o, + data_in_prev_we_no, + state_in_sel_o, + add_state_in_sel_o, + add_state_out_sel_o, + ctr_inc32_no, + ctr_incr_no, + cipher_in_valid_no, + cipher_out_ready_no, + cipher_crypt_no, + cipher_dec_key_gen_no, + cipher_prng_reseed_o, + cipher_key_clear_o, + cipher_data_out_clear_o, + ghash_in_valid_no, + ghash_out_ready_no, + ghash_load_hash_subkey_no, + key_init_sel_o, + key_init_we_no, + iv_sel_o, + iv_we_no, + prng_update_o, + prng_reseed_req_o, + start_we_o, + key_iv_data_in_clear_we_o, + data_out_clear_we_o, + prng_reseed_o, + prng_reseed_we_o, + idle_o, + idle_we_o, + stall_o, + stall_we_o, + output_lost_o, + output_lost_we_o, + output_valid_o, + output_valid_we_o, + input_ready_o, + input_ready_we_o + }); + + logic [NumOutBufBits-1:0] out, out_buf; + + // Important output control signals need to be inverted here. Synthesis tools will push the + // inverters back into the regular FSM. + assign out = { + ctrl_we, + ctrl_gcm_we, + alert, + data_in_we, + data_out_sel, + ~data_out_we, + data_in_prev_sel, + ~data_in_prev_we, + state_in_sel, + add_state_in_sel, + add_state_out_sel, + ~ctr_inc32, + ~ctr_incr, + ~cipher_in_valid, + ~cipher_out_ready, + ~cipher_crypt_out_buf, + ~cipher_dec_key_gen_out_buf, + cipher_prng_reseed_out_buf, + cipher_key_clear_out_buf, + cipher_data_out_clear_out_buf, + ~ghash_in_valid, + ~ghash_out_ready, + ~ghash_load_hash_subkey, + key_init_sel, + ~key_init_we, + iv_sel, + ~iv_we, + prng_update, + prng_reseed_req, + start_we, + key_iv_data_in_clear_we, + data_out_clear_we, + prng_reseed_out_buf, + prng_reseed_we, + idle, + idle_we, + stall, + stall_we, + output_lost_out_buf, + output_lost_we, + output_valid, + output_valid_we, + input_ready, + input_ready_we + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumOutBufBits) + ) u_caliptra_prim_buf_out ( + .in_i(out), + .out_o(out_buf) + ); + + assign {ctrl_we_o, + ctrl_gcm_we_o, + alert_o, + data_in_we_o, + data_out_sel_o, + data_out_we_no, + data_in_prev_sel_o, + data_in_prev_we_no, + state_in_sel_o, + add_state_in_sel_o, + add_state_out_sel_o, + ctr_inc32_no, + ctr_incr_no, + cipher_in_valid_no, + cipher_out_ready_no, + cipher_crypt_no, + cipher_dec_key_gen_no, + cipher_prng_reseed_o, + cipher_key_clear_o, + cipher_data_out_clear_o, + ghash_in_valid_no, + ghash_out_ready_no, + ghash_load_hash_subkey_no, + key_init_sel_o, + key_init_we_no, + iv_sel_o, + iv_we_no, + prng_update_o, + prng_reseed_req_o, + start_we_o, + key_iv_data_in_clear_we_o, + data_out_clear_we_o, + prng_reseed_o, + prng_reseed_we_o, + idle_o, + idle_we_o, + stall_o, + stall_we_o, + output_lost_o, + output_lost_we_o, + output_valid_o, + output_valid_we_o, + input_ready_o, + input_ready_we_o} = out_buf; + +endmodule diff --git a/src/aes/rtl/aes_control_fsm_p.sv b/src/aes/rtl/aes_control_fsm_p.sv new file mode 100644 index 000000000..4ad0ecb65 --- /dev/null +++ b/src/aes/rtl/aes_control_fsm_p.sv @@ -0,0 +1,616 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES main control FSM +// +// This module contains the main control FSM handling the interplay of input/output registers and +// the AES cipher core. This version operates on and produces the positive values of important +// control signals. + +`include "caliptra_prim_assert.sv" + +module aes_control_fsm_p + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AESGCMEnable = 0, + parameter bit SecMasking = 0 +) ( + input logic clk_i, + input logic rst_ni, + + // Main control signals + input logic ctrl_qe_i, + output logic ctrl_we_o, + input logic ctrl_phase_i, + input logic ctrl_err_storage_i, + input aes_op_e op_i, + input aes_mode_e mode_i, + input ciph_op_e cipher_op_i, + input logic sideload_i, + input prs_rate_e prng_reseed_rate_i, + input logic manual_operation_i, + input logic key_touch_forces_reseed_i, + input logic ctrl_gcm_qe_i, + output logic ctrl_gcm_we_o, + input gcm_phase_e gcm_phase_i, + input logic start_i, + input logic key_iv_data_in_clear_i, + input logic data_out_clear_i, + input logic prng_reseed_i, + input logic mux_sel_err_i, + input logic sp_enc_err_i, + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + input logic alert_fatal_i, + output logic alert_o, + + // I/O register read/write enables + input logic key_sideload_valid_i, + input logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe_i, + input logic [NumRegsIv-1:0] iv_qe_i, + input logic [NumRegsData-1:0] data_in_qe_i, + input logic [NumRegsData-1:0] data_out_re_i, + output logic data_in_we_o, + output data_out_sel_e data_out_sel_o, + output logic data_out_we_o, // Sparsify + + // Previous input data register + output dip_sel_e data_in_prev_sel_o, + output logic data_in_prev_we_o, // Sparsify + + // Cipher I/O muxes + output si_sel_e state_in_sel_o, + output add_si_sel_e add_state_in_sel_o, + output add_so_sel_e add_state_out_sel_o, + + // Counter + output logic ctr_inc32_o, // Sparsify + output logic ctr_incr_o, // Sparsify + input logic ctr_ready_i, // Sparsify + input logic [NumSlicesCtr-1:0] ctr_we_i, // Sparsify + + // Cipher core control and sync + output logic cipher_in_valid_o, // Sparsify + input logic cipher_in_ready_i, // Sparsify + input logic cipher_out_valid_i, // Sparsify + output logic cipher_out_ready_o, // Sparsify + output logic cipher_crypt_o, // Sparsify + input logic cipher_crypt_i, // Sparsify + output logic cipher_dec_key_gen_o, // Sparsify + input logic cipher_dec_key_gen_i, // Sparsify + output logic cipher_prng_reseed_o, + input logic cipher_prng_reseed_i, + output logic cipher_key_clear_o, + input logic cipher_key_clear_i, + output logic cipher_data_out_clear_o, + input logic cipher_data_out_clear_i, + + // GHASH control and sync + output logic ghash_in_valid_o, // Sparsify + input logic ghash_in_ready_i, // Sparsify + input logic ghash_out_valid_i, // Sparsify + output logic ghash_out_ready_o, // Sparsify + output logic ghash_load_hash_subkey_o, // Sparsify + + // Initial key registers + output key_init_sel_e key_init_sel_o, + output logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we_o, // Sparsify + + // IV registers + output iv_sel_e iv_sel_o, + output logic [NumSlicesCtr-1:0] iv_we_o, // Sparsify + + // Pseudo-random number generator interface + output logic prng_update_o, + output logic prng_reseed_req_o, + input logic prng_reseed_ack_i, + + // Trigger register + output logic start_we_o, + output logic key_iv_data_in_clear_we_o, + output logic data_out_clear_we_o, + output logic prng_reseed_o, + output logic prng_reseed_we_o, + + // Status register + output logic idle_o, + output logic idle_we_o, + output logic stall_o, + output logic stall_we_o, + input logic output_lost_i, + output logic output_lost_o, + output logic output_lost_we_o, + output logic output_valid_o, + output logic output_valid_we_o, + output logic input_ready_o, + output logic input_ready_we_o +); + + ///////////////////// + // Input Buffering // + ///////////////////// + + localparam int NumInBufBits = $bits({ + ctrl_qe_i, + ctrl_phase_i, + ctrl_err_storage_i, + op_i, + mode_i, + cipher_op_i, + sideload_i, + prng_reseed_rate_i, + manual_operation_i, + key_touch_forces_reseed_i, + ctrl_gcm_qe_i, + gcm_phase_i, + start_i, + key_iv_data_in_clear_i, + data_out_clear_i, + prng_reseed_i, + mux_sel_err_i, + sp_enc_err_i, + lc_escalate_en_i, + alert_fatal_i, + key_sideload_valid_i, + key_init_qe_i, + iv_qe_i, + data_in_qe_i, + data_out_re_i, + ctr_ready_i, + ctr_we_i, + cipher_in_ready_i, + cipher_out_valid_i, + cipher_crypt_i, + cipher_dec_key_gen_i, + cipher_prng_reseed_i, + cipher_key_clear_i, + cipher_data_out_clear_i, + ghash_in_ready_i, + ghash_out_valid_i, + prng_reseed_ack_i, + output_lost_i + }); + + logic [NumInBufBits-1:0] in, in_buf; + + assign in = { + ctrl_qe_i, + ctrl_phase_i, + ctrl_err_storage_i, + op_i, + mode_i, + cipher_op_i, + sideload_i, + prng_reseed_rate_i, + manual_operation_i, + key_touch_forces_reseed_i, + ctrl_gcm_qe_i, + gcm_phase_i, + start_i, + key_iv_data_in_clear_i, + data_out_clear_i, + prng_reseed_i, + mux_sel_err_i, + sp_enc_err_i, + lc_escalate_en_i, + alert_fatal_i, + key_sideload_valid_i, + key_init_qe_i, + iv_qe_i, + data_in_qe_i, + data_out_re_i, + ctr_ready_i, + ctr_we_i, + cipher_in_ready_i, + cipher_out_valid_i, + cipher_crypt_i, + cipher_dec_key_gen_i, + cipher_prng_reseed_i, + cipher_key_clear_i, + cipher_data_out_clear_i, + ghash_in_ready_i, + ghash_out_valid_i, + prng_reseed_ack_i, + output_lost_i + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumInBufBits) + ) u_caliptra_prim_buf_in ( + .in_i(in), + .out_o(in_buf) + ); + + logic ctrl_qe; + logic ctrl_phase; + logic ctrl_err_storage; + aes_op_e op; + aes_mode_e mode; + ciph_op_e cipher_op; + logic [$bits(cipher_op)-1:0] cipher_op_raw; + logic sideload; + prs_rate_e prng_reseed_rate; + logic manual_operation; + logic key_touch_forces_reseed; + logic ctrl_gcm_qe; + gcm_phase_e gcm_phase; + logic [$bits(gcm_phase)-1:0] gcm_phase_raw; + logic start; + logic key_iv_data_in_clear; + logic data_out_clear; + logic prng_reseed_in_buf; + logic mux_sel_err; + logic sp_enc_err; + lc_ctrl_pkg::lc_tx_t lc_escalate_en; + logic alert_fatal; + logic key_sideload_valid; + logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_qe; + logic [NumRegsIv-1:0] iv_qe; + logic [NumRegsData-1:0] data_in_qe; + logic [NumRegsData-1:0] data_out_re; + logic ctr_ready; + logic [NumSlicesCtr-1:0] ctr_we; + logic cipher_in_ready; + logic cipher_out_valid; + logic cipher_crypt_in_buf; + logic cipher_dec_key_gen_in_buf; + logic cipher_prng_reseed_in_buf; + logic cipher_key_clear_in_buf; + logic cipher_data_out_clear_in_buf; + logic ghash_in_ready; + logic ghash_out_valid; + logic prng_reseed_ack; + logic output_lost_in_buf; + + assign {ctrl_qe, + ctrl_phase, + ctrl_err_storage, + op, + mode, + cipher_op_raw, + sideload, + prng_reseed_rate, + manual_operation, + key_touch_forces_reseed, + ctrl_gcm_qe, + gcm_phase_raw, + start, + key_iv_data_in_clear, + data_out_clear, + prng_reseed_in_buf, + mux_sel_err, + sp_enc_err, + lc_escalate_en, + alert_fatal, + key_sideload_valid, + key_init_qe, + iv_qe, + data_in_qe, + data_out_re, + ctr_ready, + ctr_we, + cipher_in_ready, + cipher_out_valid, + cipher_crypt_in_buf, + cipher_dec_key_gen_in_buf, + cipher_prng_reseed_in_buf, + cipher_key_clear_in_buf, + cipher_data_out_clear_in_buf, + ghash_in_ready, + ghash_out_valid, + prng_reseed_ack, + output_lost_in_buf} = in_buf; + + assign cipher_op = ciph_op_e'(cipher_op_raw); + assign gcm_phase = gcm_phase_e'(gcm_phase_raw); + + // Intermediate output signals + logic ctrl_we; + logic ctrl_gcm_we; + logic alert; + logic data_in_we; + data_out_sel_e data_out_sel; + logic data_out_we; + dip_sel_e data_in_prev_sel; + logic data_in_prev_we; + si_sel_e state_in_sel; + add_si_sel_e add_state_in_sel; + add_so_sel_e add_state_out_sel; + logic ctr_inc32; + logic ctr_incr; + logic cipher_in_valid; + logic cipher_out_ready; + logic cipher_crypt_out_buf; + logic cipher_dec_key_gen_out_buf; + logic cipher_prng_reseed_out_buf; + logic cipher_key_clear_out_buf; + logic cipher_data_out_clear_out_buf; + logic ghash_in_valid; + logic ghash_out_ready; + logic ghash_load_hash_subkey; + key_init_sel_e key_init_sel; + logic [NumSharesKey-1:0][NumRegsKey-1:0] key_init_we; + iv_sel_e iv_sel; + logic [NumSlicesCtr-1:0] iv_we; + logic prng_update; + logic prng_reseed_req; + logic start_we; + logic key_iv_data_in_clear_we; + logic data_out_clear_we; + logic prng_reseed_out_buf; + logic prng_reseed_we; + logic idle; + logic idle_we; + logic stall; + logic stall_we; + logic output_lost_out_buf; + logic output_lost_we; + logic output_valid; + logic output_valid_we; + logic input_ready; + logic input_ready_we; + + ///////////////// + // Regular FSM // + ///////////////// + + aes_control_fsm #( + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ) + ) u_aes_control_fsm ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .ctrl_qe_i ( ctrl_qe ), + .ctrl_we_o ( ctrl_we ), + .ctrl_phase_i ( ctrl_phase ), + .ctrl_err_storage_i ( ctrl_err_storage ), + .op_i ( op ), + .mode_i ( mode ), + .cipher_op_i ( cipher_op ), + .sideload_i ( sideload ), + .prng_reseed_rate_i ( prng_reseed_rate ), + .manual_operation_i ( manual_operation ), + .key_touch_forces_reseed_i ( key_touch_forces_reseed ), + .ctrl_gcm_qe_i ( ctrl_gcm_qe ), + .ctrl_gcm_we_o ( ctrl_gcm_we ), + .gcm_phase_i ( gcm_phase ), + .start_i ( start ), + .key_iv_data_in_clear_i ( key_iv_data_in_clear ), + .data_out_clear_i ( data_out_clear ), + .prng_reseed_i ( prng_reseed_in_buf ), + .mux_sel_err_i ( mux_sel_err ), + .sp_enc_err_i ( sp_enc_err ), + .lc_escalate_en_i ( lc_escalate_en ), + .alert_fatal_i ( alert_fatal ), + .alert_o ( alert ), + + .key_sideload_valid_i ( key_sideload_valid ), + .key_init_qe_i ( key_init_qe ), + .iv_qe_i ( iv_qe ), + .data_in_qe_i ( data_in_qe ), + .data_out_re_i ( data_out_re ), + .data_in_we_o ( data_in_we ), + .data_out_sel_o ( data_out_sel ), + .data_out_we_o ( data_out_we ), + + .data_in_prev_sel_o ( data_in_prev_sel ), + .data_in_prev_we_o ( data_in_prev_we ), + + .state_in_sel_o ( state_in_sel ), + .add_state_in_sel_o ( add_state_in_sel ), + .add_state_out_sel_o ( add_state_out_sel ), + + .ctr_inc32_o ( ctr_inc32 ), + .ctr_incr_o ( ctr_incr ), + .ctr_ready_i ( ctr_ready ), + .ctr_we_i ( ctr_we ), + + .cipher_in_valid_o ( cipher_in_valid ), + .cipher_in_ready_i ( cipher_in_ready ), + .cipher_out_valid_i ( cipher_out_valid ), + .cipher_out_ready_o ( cipher_out_ready ), + .cipher_crypt_o ( cipher_crypt_out_buf ), + .cipher_crypt_i ( cipher_crypt_in_buf ), + .cipher_dec_key_gen_o ( cipher_dec_key_gen_out_buf ), + .cipher_dec_key_gen_i ( cipher_dec_key_gen_in_buf ), + .cipher_prng_reseed_o ( cipher_prng_reseed_out_buf ), + .cipher_prng_reseed_i ( cipher_prng_reseed_in_buf ), + .cipher_key_clear_o ( cipher_key_clear_out_buf ), + .cipher_key_clear_i ( cipher_key_clear_in_buf ), + .cipher_data_out_clear_o ( cipher_data_out_clear_out_buf ), + .cipher_data_out_clear_i ( cipher_data_out_clear_in_buf ), + + .ghash_in_valid_o ( ghash_in_valid ), + .ghash_in_ready_i ( ghash_in_ready ), + .ghash_out_valid_i ( ghash_out_valid ), + .ghash_out_ready_o ( ghash_out_ready ), + .ghash_load_hash_subkey_o ( ghash_load_hash_subkey ), + + .key_init_sel_o ( key_init_sel ), + .key_init_we_o ( key_init_we ), + + .iv_sel_o ( iv_sel ), + .iv_we_o ( iv_we ), + + .prng_update_o ( prng_update ), + .prng_reseed_req_o ( prng_reseed_req ), + .prng_reseed_ack_i ( prng_reseed_ack ), + + .start_we_o ( start_we ), + .key_iv_data_in_clear_we_o ( key_iv_data_in_clear_we ), + .data_out_clear_we_o ( data_out_clear_we ), + .prng_reseed_o ( prng_reseed_out_buf ), + .prng_reseed_we_o ( prng_reseed_we ), + + .idle_o ( idle ), + .idle_we_o ( idle_we ), + .stall_o ( stall ), + .stall_we_o ( stall_we ), + .output_lost_i ( output_lost_in_buf ), + .output_lost_o ( output_lost_out_buf ), + .output_lost_we_o ( output_lost_we ), + .output_valid_o ( output_valid ), + .output_valid_we_o ( output_valid_we ), + .input_ready_o ( input_ready ), + .input_ready_we_o ( input_ready_we ) + ); + + ////////////////////// + // Output Buffering // + ////////////////////// + + localparam int NumOutBufBits = $bits({ + ctrl_we_o, + ctrl_gcm_we_o, + alert_o, + data_in_we_o, + data_out_sel_o, + data_out_we_o, + data_in_prev_sel_o, + data_in_prev_we_o, + state_in_sel_o, + add_state_in_sel_o, + add_state_out_sel_o, + ctr_inc32_o, + ctr_incr_o, + cipher_in_valid_o, + cipher_out_ready_o, + cipher_crypt_o, + cipher_dec_key_gen_o, + cipher_prng_reseed_o, + cipher_key_clear_o, + cipher_data_out_clear_o, + ghash_in_valid_o, + ghash_out_ready_o, + ghash_load_hash_subkey_o, + key_init_sel_o, + key_init_we_o, + iv_sel_o, + iv_we_o, + prng_update_o, + prng_reseed_req_o, + start_we_o, + key_iv_data_in_clear_we_o, + data_out_clear_we_o, + prng_reseed_o, + prng_reseed_we_o, + idle_o, + idle_we_o, + stall_o, + stall_we_o, + output_lost_o, + output_lost_we_o, + output_valid_o, + output_valid_we_o, + input_ready_o, + input_ready_we_o + }); + + logic [NumOutBufBits-1:0] out, out_buf; + + assign out = { + ctrl_we, + ctrl_gcm_we, + alert, + data_in_we, + data_out_sel, + data_out_we, + data_in_prev_sel, + data_in_prev_we, + state_in_sel, + add_state_in_sel, + add_state_out_sel, + ctr_inc32, + ctr_incr, + cipher_in_valid, + cipher_out_ready, + cipher_crypt_out_buf, + cipher_dec_key_gen_out_buf, + cipher_prng_reseed_out_buf, + cipher_key_clear_out_buf, + cipher_data_out_clear_out_buf, + ghash_in_valid, + ghash_out_ready, + ghash_load_hash_subkey, + key_init_sel, + key_init_we, + iv_sel, + iv_we, + prng_update, + prng_reseed_req, + start_we, + key_iv_data_in_clear_we, + data_out_clear_we, + prng_reseed_out_buf, + prng_reseed_we, + idle, + idle_we, + stall, + stall_we, + output_lost_out_buf, + output_lost_we, + output_valid, + output_valid_we, + input_ready, + input_ready_we + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumOutBufBits) + ) u_caliptra_prim_buf_out ( + .in_i(out), + .out_o(out_buf) + ); + + assign {ctrl_we_o, + ctrl_gcm_we_o, + alert_o, + data_in_we_o, + data_out_sel_o, + data_out_we_o, + data_in_prev_sel_o, + data_in_prev_we_o, + state_in_sel_o, + add_state_in_sel_o, + add_state_out_sel_o, + ctr_inc32_o, + ctr_incr_o, + cipher_in_valid_o, + cipher_out_ready_o, + cipher_crypt_o, + cipher_dec_key_gen_o, + cipher_prng_reseed_o, + cipher_key_clear_o, + cipher_data_out_clear_o, + ghash_in_valid_o, + ghash_out_ready_o, + ghash_load_hash_subkey_o, + key_init_sel_o, + key_init_we_o, + iv_sel_o, + iv_we_o, + prng_update_o, + prng_reseed_req_o, + start_we_o, + key_iv_data_in_clear_we_o, + data_out_clear_we_o, + prng_reseed_o, + prng_reseed_we_o, + idle_o, + idle_we_o, + stall_o, + stall_we_o, + output_lost_o, + output_lost_we_o, + output_valid_o, + output_valid_we_o, + input_ready_o, + input_ready_we_o} = out_buf; + +endmodule diff --git a/src/aes/rtl/aes_core.sv b/src/aes/rtl/aes_core.sv new file mode 100644 index 000000000..7b0487d47 --- /dev/null +++ b/src/aes/rtl/aes_core.sv @@ -0,0 +1,1137 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES core implementation + +`include "caliptra_prim_assert.sv" + +module aes_core + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AES192Enable = 1, + parameter bit AESGCMEnable = 1, + parameter bit SecMasking = 1, + parameter sbox_impl_e SecSBoxImpl = SBoxImplDom, + parameter int unsigned SecStartTriggerDelay = 0, + parameter bit SecAllowForcingMasks = 0, + parameter bit SecSkipPRNGReseeding = 0, + parameter int unsigned EntropyWidth = edn_pkg::ENDPOINT_BUS_WIDTH, + + localparam int NumShares = SecMasking ? 2 : 1, // derived parameter + + parameter clearing_lfsr_seed_t RndCnstClearingLfsrSeed = RndCnstClearingLfsrSeedDefault, + parameter clearing_lfsr_perm_t RndCnstClearingLfsrPerm = RndCnstClearingLfsrPermDefault, + parameter clearing_lfsr_perm_t RndCnstClearingSharePerm = RndCnstClearingSharePermDefault, + parameter masking_lfsr_seed_t RndCnstMaskingLfsrSeed = RndCnstMaskingLfsrSeedDefault, + parameter masking_lfsr_perm_t RndCnstMaskingLfsrPerm = RndCnstMaskingLfsrPermDefault +) ( + input logic clk_i, + input logic rst_ni, + input logic rst_shadowed_ni, + + // Entropy request interfaces for clearing and masking PRNGs + output logic entropy_clearing_req_o, + input logic entropy_clearing_ack_i, + input logic [EntropyWidth-1:0] entropy_clearing_i, + output logic entropy_masking_req_o, + input logic entropy_masking_ack_i, + input logic [EntropyWidth-1:0] entropy_masking_i, + + // Key manager (keymgr) key sideload interface + input keymgr_pkg::hw_key_req_t keymgr_key_i, + + // Life cycle + input lc_ctrl_pkg::lc_tx_t lc_escalate_en_i, + + // Alerts + input logic shadowed_storage_err_i, + input logic shadowed_update_err_i, + input logic intg_err_alert_i, + output logic alert_recov_o, + output logic alert_fatal_o, + + // Bus Interface + input aes_reg2hw_t reg2hw, + output aes_hw2reg_t hw2reg +); + + // Signals + logic ctrl_qe; + logic ctrl_we; + logic ctrl_phase; + aes_op_e aes_op_q; + aes_mode_e aes_mode_q; + ciph_op_e cipher_op; + ciph_op_e cipher_op_buf; + key_len_e key_len_q; + logic sideload_q; + prs_rate_e prng_reseed_rate_q; + logic manual_operation_q; + logic ctrl_reg_err_update; + logic ctrl_reg_err_storage; + logic ctrl_gcm_qe; + logic ctrl_gcm_we; + gcm_phase_e gcm_phase_q; + logic [4:0] num_valid_bytes_q; + logic ctrl_gcm_reg_err_update; + logic ctrl_gcm_reg_err_storage; + logic ctrl_err_update; + logic ctrl_err_storage; + logic ctrl_err_storage_d; + logic ctrl_err_storage_q; + logic ctrl_alert; + logic key_touch_forces_reseed; + logic force_masks; + logic mux_sel_err; + logic sp_enc_err_d, sp_enc_err_q; + logic clear_on_fatal; + + logic [3:0][3:0][7:0] state_in; + logic [SISelWidth-1:0] state_in_sel_raw; + si_sel_e state_in_sel_ctrl; + si_sel_e state_in_sel; + logic state_in_sel_err; + logic [3:0][3:0][7:0] add_state_in; + logic [AddSISelWidth-1:0] add_state_in_sel_raw; + add_si_sel_e add_state_in_sel_ctrl; + add_si_sel_e add_state_in_sel; + logic add_state_in_sel_err; + + logic [3:0][3:0][7:0] state_mask; + logic [3:0][3:0][7:0] state_init [NumShares]; + logic [3:0][3:0][7:0] state_done [NumShares]; + logic [3:0][3:0][7:0] state_out; + + logic [NumRegsKey-1:0][31:0] key_init [NumSharesKey]; + logic [NumRegsKey-1:0] key_init_qe [NumSharesKey]; + logic [NumRegsKey-1:0] key_init_qe_buf [NumSharesKey]; + logic [NumRegsKey-1:0][31:0] key_init_d [NumSharesKey]; + logic [NumRegsKey-1:0][31:0] key_init_q [NumSharesKey]; + logic [NumRegsKey-1:0][31:0] key_init_cipher [NumShares]; + sp2v_e [NumRegsKey-1:0] key_init_we_ctrl [NumSharesKey]; + sp2v_e [NumRegsKey-1:0] key_init_we [NumSharesKey]; + logic [KeyInitSelWidth-1:0] key_init_sel_raw; + key_init_sel_e key_init_sel_ctrl; + key_init_sel_e key_init_sel; + logic key_init_sel_err; + logic [NumRegsKey-1:0][31:0] key_sideload [NumSharesKey]; + + logic [NumRegsIv-1:0][31:0] iv; + logic [NumRegsIv-1:0] iv_qe; + logic [NumRegsIv-1:0] iv_qe_buf; + logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] iv_d; + logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] iv_q; + sp2v_e [NumSlicesCtr-1:0] iv_we_ctrl; + sp2v_e [NumSlicesCtr-1:0] iv_we; + logic [IVSelWidth-1:0] iv_sel_raw; + iv_sel_e iv_sel_ctrl; + iv_sel_e iv_sel; + logic iv_sel_err; + + logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] ctr; + sp2v_e [NumSlicesCtr-1:0] ctr_we; + sp2v_e ctr_inc32; + sp2v_e ctr_incr; + sp2v_e ctr_ready; + logic ctr_alert; + + logic [NumRegsData-1:0][31:0] data_in_prev_d; + logic [NumRegsData-1:0][31:0] data_in_prev_q; + sp2v_e data_in_prev_we_ctrl; + sp2v_e data_in_prev_we; + logic [DIPSelWidth-1:0] data_in_prev_sel_raw; + dip_sel_e data_in_prev_sel_ctrl; + dip_sel_e data_in_prev_sel; + logic data_in_prev_sel_err; + + logic [NumRegsData-1:0][31:0] data_in; + logic [NumRegsData-1:0] data_in_qe; + logic [NumRegsData-1:0] data_in_qe_buf; + logic data_in_we; + + logic [3:0][3:0][7:0] add_state_out; + logic [AddSOSelWidth-1:0] add_state_out_sel_raw; + add_so_sel_e add_state_out_sel_ctrl; + add_so_sel_e add_state_out_sel; + logic add_state_out_sel_err; + + logic [NumRegsData-1:0][31:0] data_out; + logic [NumRegsData-1:0][31:0] data_out_d; + logic [NumRegsData-1:0][31:0] data_out_q; + sp2v_e data_out_we_ctrl; + sp2v_e data_out_we; + logic [NumRegsData-1:0] data_out_re; + logic [NumRegsData-1:0] data_out_re_buf; + logic [DataOutSelWidth-1:0] data_out_sel_raw; + data_out_sel_e data_out_sel_ctrl; + data_out_sel_e data_out_sel; + logic data_out_sel_err; + + sp2v_e cipher_in_valid; + sp2v_e cipher_in_ready; + sp2v_e cipher_out_valid; + sp2v_e cipher_out_ready; + sp2v_e cipher_crypt; + sp2v_e cipher_crypt_busy; + sp2v_e cipher_dec_key_gen; + sp2v_e cipher_dec_key_gen_busy; + logic cipher_prng_reseed; + logic cipher_prng_reseed_busy; + logic cipher_key_clear; + logic cipher_key_clear_busy; + logic cipher_data_out_clear; + logic cipher_data_out_clear_busy; + logic cipher_alert; + + sp2v_e ghash_in_valid; + sp2v_e ghash_in_ready; + sp2v_e ghash_out_valid; + sp2v_e ghash_out_ready; + sp2v_e ghash_load_hash_subkey; + logic ghash_first_block; + logic ghash_alert; + + // Pseudo-random data for clearing purposes + logic [WidthPRDClearing-1:0] prd_clearing [NumSharesKey]; + logic prd_clearing_update; + logic prd_clearing_rsd_req; + logic prd_clearing_rsd_ack; + logic [127:0] prd_clearing_128 [NumShares]; + logic [255:0] prd_clearing_256 [NumShares]; + logic [3:0][31:0] prd_clearing_data; + logic [255:0] prd_clearing_key_init [NumSharesKey]; + logic [3:0][3:0][7:0] prd_clearing_state [NumShares]; + logic [7:0][31:0] prd_clearing_key [NumShares]; + + // Unused signals + logic [NumRegsData-1:0][31:0] unused_data_out_q; + + // The clearing PRNG provides pseudo-random data for register clearing purposes. + aes_prng_clearing #( + .Width ( WidthPRDClearing ), + .EntropyWidth ( EntropyWidth ), + .SecSkipPRNGReseeding ( SecSkipPRNGReseeding ), + .RndCnstLfsrSeed ( RndCnstClearingLfsrSeed ), + .RndCnstLfsrPerm ( RndCnstClearingLfsrPerm ), + .RndCnstSharePerm ( RndCnstClearingSharePerm ) + ) u_aes_prng_clearing ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .data_update_i ( prd_clearing_update ), + .data_o ( prd_clearing ), + .reseed_req_i ( prd_clearing_rsd_req ), + .reseed_ack_o ( prd_clearing_rsd_ack ), + + .entropy_req_o ( entropy_clearing_req_o ), + .entropy_ack_i ( entropy_clearing_ack_i ), + .entropy_i ( entropy_clearing_i ) + ); + + // Generate clearing signals of appropriate widths. + // Different shares need to be cleared with different pseudo-random data. + for (genvar s = 0; s < NumShares; s++) begin : gen_prd_clearing_shares + for (genvar c = 0; c < NumChunksPRDClearing128; c++) begin : gen_prd_clearing_128 + assign prd_clearing_128[s][c * WidthPRDClearing +: WidthPRDClearing] = prd_clearing[s]; + end + for (genvar c = 0; c < NumChunksPRDClearing256; c++) begin : gen_prd_clearing_256 + assign prd_clearing_256[s][c * WidthPRDClearing +: WidthPRDClearing] = prd_clearing[s]; + end + end + // The data registers are always unmasked. + assign prd_clearing_data = prd_clearing_128[0]; + // The initial key is always provided in two shares. The two shares of the initial key register + // need to be cleared with different pseudo-random data. + for (genvar s = 0; s < NumSharesKey; s++) begin : gen_prd_clearing_key_init_shares + for (genvar c = 0; c < NumChunksPRDClearing256; c++) begin : gen_prd_clearing_key_init + assign prd_clearing_key_init[s][c * WidthPRDClearing +: WidthPRDClearing] = prd_clearing[s]; + end + end + // The cipher core uses multiple packed dimensions internally but the number of bits remain the + // same. Since some tools fail to peform the `conversion` on input ports, we do it here. + assign prd_clearing_state = prd_clearing_128; + assign prd_clearing_key = prd_clearing_256; + + //////////// + // Inputs // + //////////// + + always_comb begin : key_init_get + for (int i = 0; i < NumRegsKey; i++) begin + key_init[0][i] = reg2hw.key_share0[i].q; + key_init_qe[0][i] = reg2hw.key_share0[i].qe; + key_init[1][i] = reg2hw.key_share1[i].q; + key_init_qe[1][i] = reg2hw.key_share1[i].qe; + end + end + + caliptra_prim_sec_anchor_buf #( + .Width ( NumSharesKey * NumRegsKey ) + ) u_caliptra_prim_buf_key_init_qe ( + .in_i ( {key_init_qe[1], key_init_qe[0]} ), + .out_o ( {key_init_qe_buf[1], key_init_qe_buf[0]} ) + ); + + always_comb begin : key_sideload_get + for (int s = 0; s < NumSharesKey; s++) begin + for (int i = 0; i < NumRegsKey; i++) begin + key_sideload[s][i] = keymgr_key_i.key[s][i * 32 +: 32]; + end + end + end + + always_comb begin : iv_get + for (int i = 0; i < NumRegsIv; i++) begin + iv[i] = reg2hw.iv[i].q; + iv_qe[i] = reg2hw.iv[i].qe; + end + end + + caliptra_prim_sec_anchor_buf #( + .Width ( NumRegsIv ) + ) u_caliptra_prim_buf_iv_qe ( + .in_i ( iv_qe ), + .out_o ( iv_qe_buf ) + ); + + always_comb begin : data_in_get + for (int i = 0; i < NumRegsData; i++) begin + data_in[i] = reg2hw.data_in[i].q; + data_in_qe[i] = reg2hw.data_in[i].qe; + end + end + + caliptra_prim_sec_anchor_buf #( + .Width ( NumRegsData ) + ) u_caliptra_prim_buf_data_in_qe ( + .in_i ( data_in_qe ), + .out_o ( data_in_qe_buf ) + ); + + always_comb begin : data_out_get + for (int i = 0; i < NumRegsData; i++) begin + // data_out is actually hwo, but we need hrw for hwre + unused_data_out_q[i] = reg2hw.data_out[i].q; + data_out_re[i] = reg2hw.data_out[i].re; + end + end + + caliptra_prim_sec_anchor_buf #( + .Width ( NumRegsData ) + ) u_caliptra_prim_buf_data_out_re ( + .in_i ( data_out_re ), + .out_o ( data_out_re_buf ) + ); + + ////////////////////// + // Key, IV and Data // + ////////////////////// + + // SEC_CM: KEY.SEC_WIPE + // SEC_CM: KEY.SIDELOAD + // Initial Key registers + always_comb begin : key_init_mux + unique case (key_init_sel) + KEY_INIT_INPUT: key_init_d = key_init; + KEY_INIT_KEYMGR: key_init_d = key_sideload; + KEY_INIT_CLEAR: key_init_d = prd_clearing_key_init; + default: key_init_d = prd_clearing_key_init; + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : key_init_reg + if (!rst_ni) begin + key_init_q <= '{default: '0}; + end else begin + for (int s = 0; s < NumSharesKey; s++) begin + for (int i = 0; i < NumRegsKey; i++) begin + if (key_init_we[s][i] == SP2V_HIGH) begin + key_init_q[s][i] <= key_init_d[s][i]; + end + end + end + end + end + + // SEC_CM: IV.CONFIG.SEC_WIPE + // IV registers + always_comb begin : iv_mux + unique case (iv_sel) + IV_INPUT: iv_d = iv; + IV_DATA_OUT: iv_d = data_out_d; + IV_DATA_OUT_RAW: iv_d = aes_transpose(state_out); + IV_DATA_IN_PREV: iv_d = data_in_prev_q; + IV_CTR: iv_d = ctr; + IV_CLEAR: iv_d = prd_clearing_data; + default: iv_d = prd_clearing_data; + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : iv_reg + if (!rst_ni) begin + iv_q <= '0; + end else begin + for (int i = 0; i < NumSlicesCtr; i++) begin + if (iv_we[i] == SP2V_HIGH) begin + iv_q[i] <= iv_d[i]; + end + end + end + end + + // SEC_CM: DATA_REG.SEC_WIPE + // Previous input data register + always_comb begin : data_in_prev_mux + unique case (data_in_prev_sel) + DIP_DATA_IN: data_in_prev_d = data_in; + DIP_CLEAR: data_in_prev_d = prd_clearing_data; + default: data_in_prev_d = prd_clearing_data; + endcase + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : data_in_prev_reg + if (!rst_ni) begin + data_in_prev_q <= '0; + end else if (data_in_prev_we == SP2V_HIGH) begin + data_in_prev_q <= data_in_prev_d; + end + end + + ///////////// + // Counter // + ///////////// + + aes_ctr u_aes_ctr ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .inc32_i ( ctr_inc32 ), + .incr_i ( ctr_incr ), + .ready_o ( ctr_ready ), + .alert_o ( ctr_alert ), + + .ctr_i ( iv_q ), + .ctr_o ( ctr ), + .ctr_we_o ( ctr_we ) + ); + + ///////////////// + // Cipher Core // + ///////////////// + + // Cipher core operation + assign cipher_op = (aes_mode_q == AES_ECB && aes_op_q == AES_ENC) ? CIPH_FWD : + (aes_mode_q == AES_ECB && aes_op_q == AES_DEC) ? CIPH_INV : + (aes_mode_q == AES_CBC && aes_op_q == AES_ENC) ? CIPH_FWD : + (aes_mode_q == AES_CBC && aes_op_q == AES_DEC) ? CIPH_INV : + (aes_mode_q == AES_CFB) ? CIPH_FWD : + (aes_mode_q == AES_OFB) ? CIPH_FWD : + (aes_mode_q == AES_CTR) ? CIPH_FWD : + (aes_mode_q == AES_GCM) ? CIPH_FWD : CIPH_FWD; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + logic [$bits(ciph_op_e)-1:0] cipher_op_raw; + caliptra_prim_buf #( + .Width($bits(ciph_op_e)) + ) u_caliptra_prim_buf_op ( + .in_i(cipher_op), + .out_o(cipher_op_raw) + ); + assign cipher_op_buf = ciph_op_e'(cipher_op_raw); + + // Convert input data/IV to state format (every word corresponds to one state column). + // Mux for state input + always_comb begin : state_in_mux + unique case (state_in_sel) + SI_ZERO: state_in = '0; + SI_DATA: state_in = aes_transpose(data_in); + default: state_in = '0; + endcase + end + + // Mux for addition to state input + always_comb begin : add_state_in_mux + unique case (add_state_in_sel) + ADD_SI_ZERO: add_state_in = '0; + ADD_SI_IV: add_state_in = aes_transpose(iv_q); + default: add_state_in = '0; + endcase + end + + if (!SecMasking) begin : gen_state_init_unmasked + assign state_init[0] = state_in ^ add_state_in; + + logic [3:0][3:0][7:0] unused_state_mask; + assign unused_state_mask = state_mask; + + end else begin : gen_state_init_masked + assign state_init[0] = (state_in ^ add_state_in) ^ state_mask; // Masked data share + assign state_init[1] = state_mask; // Mask share + end + + if (!SecMasking) begin : gen_key_init_unmasked + // Combine the two key shares for the unmasked cipher core. This causes SCA leakage of the key + // and thus should be avoided. + assign key_init_cipher[0] = key_init_q[0] ^ key_init_q[1]; + + end else begin : gen_key_init_masked + // Forward the masked key share and the mask share to the masked cipher core. + assign key_init_cipher = key_init_q; + end + + // SEC_CM: KEY.MASKING + // Cipher core + aes_cipher_core #( + .AES192Enable ( AES192Enable ), + .SecMasking ( SecMasking ), + .SecSBoxImpl ( SecSBoxImpl ), + .SecAllowForcingMasks ( SecAllowForcingMasks ), + .SecSkipPRNGReseeding ( SecSkipPRNGReseeding ), + .RndCnstMaskingLfsrSeed ( RndCnstMaskingLfsrSeed ), + .RndCnstMaskingLfsrPerm ( RndCnstMaskingLfsrPerm ) + ) u_aes_cipher_core ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .in_valid_i ( cipher_in_valid ), + .in_ready_o ( cipher_in_ready ), + + .out_valid_o ( cipher_out_valid ), + .out_ready_i ( cipher_out_ready ), + + .cfg_valid_i ( ~ctrl_err_storage ), // Used for gating assertions only. + .op_i ( cipher_op_buf ), + .key_len_i ( key_len_q ), + .crypt_i ( cipher_crypt ), + .crypt_o ( cipher_crypt_busy ), + .dec_key_gen_i ( cipher_dec_key_gen ), + .dec_key_gen_o ( cipher_dec_key_gen_busy ), + .prng_reseed_i ( cipher_prng_reseed ), + .prng_reseed_o ( cipher_prng_reseed_busy ), + .key_clear_i ( cipher_key_clear ), + .key_clear_o ( cipher_key_clear_busy ), + .data_out_clear_i ( cipher_data_out_clear ), + .data_out_clear_o ( cipher_data_out_clear_busy ), + .alert_fatal_i ( alert_fatal_o ), + .alert_o ( cipher_alert ), + + .prd_clearing_state_i ( prd_clearing_state ), + .prd_clearing_key_i ( prd_clearing_key ), + + .force_masks_i ( force_masks ), + .data_in_mask_o ( state_mask ), + .entropy_req_o ( entropy_masking_req_o ), + .entropy_ack_i ( entropy_masking_ack_i ), + .entropy_i ( entropy_masking_i ), + + .state_init_i ( state_init ), + .key_init_i ( key_init_cipher ), + .state_o ( state_done ) + ); + + if (!SecMasking) begin : gen_state_out_unmasked + assign state_out = state_done[0]; + end else begin : gen_state_out_masked + // Unmask the cipher core output. This might get reworked in the future when masking the + // counter and feedback path through the IV regs. + + // Only unmask the final cipher core output. Unmasking intermediate output data causes + // additional SCA leakage and thus has to be avoided. Forward PRD instead of a determinsitic + // value to avoid leaking the cipher core output when it becomes valid. Don't unmask the hash + // subkey in case of GCM. + logic [3:0][3:0][7:0] state_done_muxed [NumShares]; + for (genvar s = 0; s < NumShares; s++) begin : gen_state_done_muxed + assign state_done_muxed[s] = ((cipher_out_valid == SP2V_HIGH) && + !(aes_mode_q == AES_GCM && + gcm_phase_q == GCM_INIT)) ? state_done[s] : prd_clearing_state[s]; + end + + // Avoid aggressive synthesis optimizations. + logic [3:0][3:0][7:0] state_done_buf [NumShares]; + caliptra_prim_buf #( + .Width ( 128 * NumShares ) + ) u_caliptra_prim_state_done_muxed ( + .in_i ( {state_done_muxed[1], state_done_muxed[0]} ), + .out_o ( {state_done_buf[1], state_done_buf[0]} ) + ); + + // Unmask the cipher core output. + assign state_out = state_done_buf[0] ^ state_done_buf[1]; + end + + // Mux for addition to state output + always_comb begin : add_state_out_mux + unique case (add_state_out_sel) + ADD_SO_ZERO: add_state_out = '0; + ADD_SO_IV: add_state_out = aes_transpose(iv_q); + ADD_SO_DIP: add_state_out = aes_transpose(data_in_prev_q); + default: add_state_out = '0; + endcase + end + + // Convert output state to output data format (every column corresponds to one output word). + assign data_out = aes_transpose(state_out ^ add_state_out); + + /////////// + // GHASH // + /////////// + + if (AESGCMEnable) begin : gen_ghash + logic [3:0][3:0][7:0] ghash_state_out; + + logic ghash_clear; + assign ghash_clear = cipher_key_clear | cipher_key_clear_busy; + + // The number of cycles must be a power of two and ideally matches the minimum latency of the + // cipher core which is 56 clock cycles (masked) or 12 clock cycles (unmasked) for AES-128. + localparam int unsigned GhashGFMultCycles = (SecSBoxImpl == SBoxImplDom) ? 32 : 8; + + // The actual GHASH module. + aes_ghash #( + .SecMasking ( SecMasking ), + .GFMultCycles ( GhashGFMultCycles ) + ) u_aes_ghash ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .in_valid_i ( ghash_in_valid ), + .in_ready_o ( ghash_in_ready ), + + .out_valid_o ( ghash_out_valid ), + .out_ready_i ( ghash_out_ready ), + + .op_i ( aes_op_q ), + .gcm_phase_i ( gcm_phase_q ), + .num_valid_bytes_i ( num_valid_bytes_q ), + .load_hash_subkey_i ( ghash_load_hash_subkey ), + .clear_i ( ghash_clear ), + .first_block_o ( ghash_first_block ), + .alert_fatal_i ( alert_fatal_o ), + .alert_o ( ghash_alert ), + + .data_in_prev_i ( data_in_prev_q ), + .data_out_i ( data_out_d ), + .cipher_state_done_i ( state_done ), + .ghash_state_done_o ( ghash_state_out ) + ); + + // Mux for output data registers + always_comb begin : data_out_mux + unique case (data_out_sel) + DATA_OUT_CIPHER: data_out_d = data_out; + DATA_OUT_GHASH: data_out_d = ghash_state_out; + default: data_out_d = ghash_state_out; + endcase + end + + end else begin : gen_no_ghash + // GHASH isn't there and thus generates no back pressure / alerts / output to be muxed. + assign ghash_in_ready = SP2V_HIGH; + assign ghash_out_valid = SP2V_HIGH; + assign ghash_first_block = 1'b0; + assign ghash_alert = 1'b0; + assign data_out_d = data_out; + + // Tie-off unused signals. + sp2v_e unused_ghash_in_valid; + sp2v_e unused_ghash_out_ready; + sp2v_e unused_ghash_load_hash_subkey; + logic [4:0] unused_num_valid_bytes; + data_out_sel_e unused_data_out_sel; + assign unused_ghash_in_valid = ghash_in_valid; + assign unused_ghash_out_ready = ghash_out_ready; + assign unused_ghash_load_hash_subkey = ghash_load_hash_subkey; + assign unused_num_valid_bytes = num_valid_bytes_q; + assign unused_data_out_sel = data_out_sel; + end + + /////////////////////// + // Control Registers // + /////////////////////// + + // Shadowed register primitve + aes_ctrl_reg_shadowed #( + .AES192Enable ( AES192Enable ), + .AESGCMEnable ( AESGCMEnable ) + ) u_ctrl_reg_shadowed ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .rst_shadowed_ni ( rst_shadowed_ni ), + .qe_o ( ctrl_qe ), + .we_i ( ctrl_we ), + .phase_o ( ctrl_phase ), + .operation_o ( aes_op_q ), + .mode_o ( aes_mode_q ), + .key_len_o ( key_len_q ), + .sideload_o ( sideload_q ), + .prng_reseed_rate_o ( prng_reseed_rate_q ), + .manual_operation_o ( manual_operation_q ), + .err_update_o ( ctrl_reg_err_update ), + .err_storage_o ( ctrl_reg_err_storage ), + .reg2hw_ctrl_i ( reg2hw.ctrl_shadowed ), + .hw2reg_ctrl_o ( hw2reg.ctrl_shadowed ) + ); + + // Auxiliary control register signals + assign key_touch_forces_reseed = reg2hw.ctrl_aux_shadowed.key_touch_forces_reseed.q; + assign force_masks = reg2hw.ctrl_aux_shadowed.force_masks.q; + + // GCM control register + aes_ctrl_gcm_reg_shadowed #( + .AESGCMEnable ( AESGCMEnable ) + ) u_ctrl_gcm_reg_shadowed ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .rst_shadowed_ni ( rst_shadowed_ni ), + .qe_o ( ctrl_gcm_qe ), + .we_i ( ctrl_gcm_we ), + .first_block_i ( ghash_first_block ), + .gcm_phase_o ( gcm_phase_q ), + .num_valid_bytes_o ( num_valid_bytes_q ), + .err_update_o ( ctrl_gcm_reg_err_update ), + .err_storage_o ( ctrl_gcm_reg_err_storage ), + .reg2hw_ctrl_gcm_i ( reg2hw.ctrl_gcm_shadowed ), + .hw2reg_ctrl_gcm_o ( hw2reg.ctrl_gcm_shadowed ) + ); + + ///////////// + // Control // + ///////////// + + // Control + aes_control #( + .AESGCMEnable ( AESGCMEnable ), + .SecMasking ( SecMasking ), + .SecStartTriggerDelay ( SecStartTriggerDelay ) + ) u_aes_control ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .ctrl_qe_i ( ctrl_qe ), + .ctrl_we_o ( ctrl_we ), + .ctrl_phase_i ( ctrl_phase ), + .ctrl_err_storage_i ( ctrl_err_storage ), + .op_i ( aes_op_q ), + .mode_i ( aes_mode_q ), + .cipher_op_i ( cipher_op_buf ), + .sideload_i ( sideload_q ), + .prng_reseed_rate_i ( prng_reseed_rate_q ), + .manual_operation_i ( manual_operation_q ), + .key_touch_forces_reseed_i ( key_touch_forces_reseed ), + .ctrl_gcm_qe_i ( ctrl_gcm_qe ), + .ctrl_gcm_we_o ( ctrl_gcm_we ), + .gcm_phase_i ( gcm_phase_q ), + .start_i ( reg2hw.trigger.start.q ), + .key_iv_data_in_clear_i ( reg2hw.trigger.key_iv_data_in_clear.q ), + .data_out_clear_i ( reg2hw.trigger.data_out_clear.q ), + .prng_reseed_i ( reg2hw.trigger.prng_reseed.q ), + .mux_sel_err_i ( mux_sel_err ), + .sp_enc_err_i ( sp_enc_err_q ), + .lc_escalate_en_i ( lc_escalate_en_i ), + .alert_fatal_i ( alert_fatal_o ), + .alert_o ( ctrl_alert ), + + .key_sideload_valid_i ( keymgr_key_i.valid ), + .key_init_qe_i ( key_init_qe_buf ), + .iv_qe_i ( iv_qe_buf ), + .data_in_qe_i ( data_in_qe_buf ), + .data_out_re_i ( data_out_re_buf ), + .data_in_we_o ( data_in_we ), + .data_out_sel_o ( data_out_sel_ctrl ), + .data_out_we_o ( data_out_we_ctrl ), + + .data_in_prev_sel_o ( data_in_prev_sel_ctrl ), + .data_in_prev_we_o ( data_in_prev_we_ctrl ), + + .state_in_sel_o ( state_in_sel_ctrl ), + .add_state_in_sel_o ( add_state_in_sel_ctrl ), + .add_state_out_sel_o ( add_state_out_sel_ctrl ), + + .ctr_inc32_o ( ctr_inc32 ), + .ctr_incr_o ( ctr_incr ), + .ctr_ready_i ( ctr_ready ), + .ctr_we_i ( ctr_we ), + + .cipher_in_valid_o ( cipher_in_valid ), + .cipher_in_ready_i ( cipher_in_ready ), + .cipher_out_valid_i ( cipher_out_valid ), + .cipher_out_ready_o ( cipher_out_ready ), + .cipher_crypt_o ( cipher_crypt ), + .cipher_crypt_i ( cipher_crypt_busy ), + .cipher_dec_key_gen_o ( cipher_dec_key_gen ), + .cipher_dec_key_gen_i ( cipher_dec_key_gen_busy ), + .cipher_prng_reseed_o ( cipher_prng_reseed ), + .cipher_prng_reseed_i ( cipher_prng_reseed_busy ), + .cipher_key_clear_o ( cipher_key_clear ), + .cipher_key_clear_i ( cipher_key_clear_busy ), + .cipher_data_out_clear_o ( cipher_data_out_clear ), + .cipher_data_out_clear_i ( cipher_data_out_clear_busy ), + + .ghash_in_valid_o ( ghash_in_valid ), + .ghash_in_ready_i ( ghash_in_ready ), + .ghash_out_valid_i ( ghash_out_valid ), + .ghash_out_ready_o ( ghash_out_ready ), + .ghash_load_hash_subkey_o ( ghash_load_hash_subkey ), + + .key_init_sel_o ( key_init_sel_ctrl ), + .key_init_we_o ( key_init_we_ctrl ), + .iv_sel_o ( iv_sel_ctrl ), + .iv_we_o ( iv_we_ctrl ), + + .prng_update_o ( prd_clearing_update ), + .prng_reseed_req_o ( prd_clearing_rsd_req ), + .prng_reseed_ack_i ( prd_clearing_rsd_ack ), + + .start_o ( hw2reg.trigger.start.d ), + .start_we_o ( hw2reg.trigger.start.de ), + .key_iv_data_in_clear_o ( hw2reg.trigger.key_iv_data_in_clear.d ), + .key_iv_data_in_clear_we_o ( hw2reg.trigger.key_iv_data_in_clear.de ), + .data_out_clear_o ( hw2reg.trigger.data_out_clear.d ), + .data_out_clear_we_o ( hw2reg.trigger.data_out_clear.de ), + .prng_reseed_o ( hw2reg.trigger.prng_reseed.d ), + .prng_reseed_we_o ( hw2reg.trigger.prng_reseed.de ), + + .idle_o ( hw2reg.status.idle.d ), + .idle_we_o ( hw2reg.status.idle.de ), + .stall_o ( hw2reg.status.stall.d ), + .stall_we_o ( hw2reg.status.stall.de ), + .output_lost_i ( reg2hw.status.output_lost.q ), + .output_lost_o ( hw2reg.status.output_lost.d ), + .output_lost_we_o ( hw2reg.status.output_lost.de ), + .output_valid_o ( hw2reg.status.output_valid.d ), + .output_valid_we_o ( hw2reg.status.output_valid.de ), + .input_ready_o ( hw2reg.status.input_ready.d ), + .input_ready_we_o ( hw2reg.status.input_ready.de ) + ); + + // SEC_CM: DATA_REG.SEC_WIPE + // Input data register clear + always_comb begin : data_in_reg_clear + for (int i = 0; i < NumRegsData; i++) begin + hw2reg.data_in[i].d = prd_clearing_data[i]; + hw2reg.data_in[i].de = data_in_we; + end + end + + /////////////// + // Selectors // + /////////////// + + // We use sparse encodings for these mux selector signals and must ensure that: + // 1. The synthesis tool doesn't optimize away the sparse encoding. + // 2. The selector signal is always valid. More precisely, an alert or SVA is triggered if a + // selector signal takes on an invalid value. + // 3. The alert signal remains asserted until reset even if the selector signal becomes valid + // again. This is achieved by driving the control FSM into the terminal error state whenever + // any mux selector signal becomes invalid. + // + // If any mux selector signal becomes invalid, the control FSM further prevents any data from + // being released from the cipher core by de-asserting the write enable of the output data + // registers. + + aes_sel_buf_chk #( + .Num ( DIPSelNum ), + .Width ( DIPSelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_data_in_prev_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( data_in_prev_sel_ctrl ), + .sel_o ( data_in_prev_sel_raw ), + .err_o ( data_in_prev_sel_err ) + ); + assign data_in_prev_sel = dip_sel_e'(data_in_prev_sel_raw); + + aes_sel_buf_chk #( + .Num ( SISelNum ), + .Width ( SISelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_state_in_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( state_in_sel_ctrl ), + .sel_o ( state_in_sel_raw ), + .err_o ( state_in_sel_err ) + ); + assign state_in_sel = si_sel_e'(state_in_sel_raw); + + aes_sel_buf_chk #( + .Num ( AddSISelNum ), + .Width ( AddSISelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_add_state_in_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( add_state_in_sel_ctrl ), + .sel_o ( add_state_in_sel_raw ), + .err_o ( add_state_in_sel_err ) + ); + assign add_state_in_sel = add_si_sel_e'(add_state_in_sel_raw); + + aes_sel_buf_chk #( + .Num ( AddSOSelNum ), + .Width ( AddSOSelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_add_state_out_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( add_state_out_sel_ctrl ), + .sel_o ( add_state_out_sel_raw ), + .err_o ( add_state_out_sel_err ) + ); + assign add_state_out_sel = add_so_sel_e'(add_state_out_sel_raw); + + aes_sel_buf_chk #( + .Num ( KeyInitSelNum ), + .Width ( KeyInitSelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_key_init_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( key_init_sel_ctrl ), + .sel_o ( key_init_sel_raw ), + .err_o ( key_init_sel_err ) + ); + assign key_init_sel = key_init_sel_e'(key_init_sel_raw); + + aes_sel_buf_chk #( + .Num ( IVSelNum ), + .Width ( IVSelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_iv_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( iv_sel_ctrl ), + .sel_o ( iv_sel_raw ), + .err_o ( iv_sel_err ) + ); + assign iv_sel = iv_sel_e'(iv_sel_raw); + + aes_sel_buf_chk #( + .Num ( DataOutSelNum ), + .Width ( DataOutSelWidth ), + .EnSecBuf ( 1'b1 ) + ) u_aes_data_out_sel_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( data_out_sel_ctrl ), + .sel_o ( data_out_sel_raw ), + .err_o ( data_out_sel_err ) + ); + assign data_out_sel = data_out_sel_e'(data_out_sel_raw); + + // Signal invalid mux selector signals to control FSM which will lock up and trigger an alert. + assign mux_sel_err = data_in_prev_sel_err | state_in_sel_err | add_state_in_sel_err | + add_state_out_sel_err | key_init_sel_err | iv_sel_err | data_out_sel_err; + + ////////////////////////////// + // Sparsely Encoded Signals // + ////////////////////////////// + + // We use sparse encodings for various critical signals and must ensure that: + // 1. The synthesis tool doesn't optimize away the sparse encoding. + // 2. The sparsely encoded signal is always valid. More precisely, an alert or SVA is triggered + // if a sparse signal takes on an invalid value. + // 3. The alert signal remains asserted until reset even if the sparse signal becomes valid again + // This is achieved by driving the control FSM into the terminal error state whenever any + // sparsely encoded signal becomes invalid. + // + // If any sparsely encoded signal becomes invalid, the core controller further immediately + // de-asserts the data_out_we_o signal to prevent any data from being released. + + // We use vectors of sparsely encoded signals to reduce code duplication. + localparam int unsigned NumSp2VSig = NumSharesKey * NumRegsKey + NumSlicesCtr + 2; + sp2v_e [NumSp2VSig-1:0] sp2v_sig; + sp2v_e [NumSp2VSig-1:0] sp2v_sig_chk; + logic [NumSp2VSig-1:0][Sp2VWidth-1:0] sp2v_sig_chk_raw; + logic [NumSp2VSig-1:0] sp2v_sig_err; + + for (genvar s = 0; s < NumSharesKey; s++) begin : gen_use_key_init_we_ctrl_shares + for (genvar i = 0; i < NumRegsKey; i++) begin : gen_use_key_init_we_ctrl + assign sp2v_sig[s * NumRegsKey + i] = key_init_we_ctrl[s][i]; + end + end + for (genvar i = 0; i < NumSlicesCtr; i++) begin : gen_use_iv_we_ctrl + assign sp2v_sig[NumSharesKey * NumRegsKey + i] = iv_we_ctrl[i]; + end + assign sp2v_sig[NumSharesKey * NumRegsKey + NumSlicesCtr + 0] = data_in_prev_we_ctrl; + assign sp2v_sig[NumSharesKey * NumRegsKey + NumSlicesCtr + 1] = data_out_we_ctrl; + + // All signals inside sp2v_sig are eventually converted to single-rail signals. + localparam bit [NumSp2VSig-1:0] Sp2VEnSecBuf = {NumSp2VSig{1'b1}}; + + // Individually check sparsely encoded signals. + for (genvar i = 0; i < NumSp2VSig; i++) begin : gen_sel_buf_chk + aes_sel_buf_chk #( + .Num ( Sp2VNum ), + .Width ( Sp2VWidth ), + .EnSecBuf ( Sp2VEnSecBuf[i] ) + ) u_aes_sp2v_sig_buf_chk_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( sp2v_sig[i] ), + .sel_o ( sp2v_sig_chk_raw[i] ), + .err_o ( sp2v_sig_err[i] ) + ); + assign sp2v_sig_chk[i] = sp2v_e'(sp2v_sig_chk_raw[i]); + end + + for (genvar s = 0; s < NumSharesKey; s++) begin : gen_key_init_we_shares + for (genvar i = 0; i < NumRegsKey; i++) begin : gen_key_init_we + assign key_init_we[s][i] = sp2v_sig_chk[s * NumRegsKey + i]; + end + end + for (genvar i = 0; i < NumSlicesCtr; i++) begin : gen_iv_we + assign iv_we[i] = sp2v_sig_chk[NumSharesKey * NumRegsKey + i]; + end + assign data_in_prev_we = sp2v_sig_chk[NumSharesKey * NumRegsKey + NumSlicesCtr + 0]; + assign data_out_we = sp2v_sig_chk[NumSharesKey * NumRegsKey + NumSlicesCtr + 1]; + + // Collect encoding errors. + // We instantiate the checker modules as close as possible to where the sparsely encoded signals + // are used. Here, we collect also encoding errors detected in other places of the core. + assign sp_enc_err_d = |sp2v_sig_err; + + // We need to register the collected error signal to avoid circular loops in the core controller + // related to iv_we and data_out_we. + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_sp_enc_err + if (!rst_ni) begin + sp_enc_err_q <= 1'b0; + end else if (sp_enc_err_d) begin + sp_enc_err_q <= 1'b1; + end + end + + ///////////// + // Outputs // + ///////////// + + always_ff @(posedge clk_i or negedge rst_ni) begin : data_out_reg + if (!rst_ni) begin + data_out_q <= '0; + end else if (data_out_we == SP2V_HIGH) begin + data_out_q <= data_out_d; + end + end + + always_comb begin : key_reg_put + for (int i = 0; i < NumRegsKey; i++) begin + hw2reg.key_share0[i].d = key_init_q[0][i]; + hw2reg.key_share1[i].d = key_init_q[1][i]; + end + end + + always_comb begin : iv_reg_put + for (int i = 0; i < NumRegsIv; i++) begin + // Software updates IV in chunks of 32 bits. Internally, the counter updates SliceSizeCtr + // bits at a time. + hw2reg.iv[i].d = {iv_q[2 * i + 1], iv_q[2 * i]}; + end + end + + always_comb begin : data_out_put + for (int i = 0; i < NumRegsData; i++) begin + hw2reg.data_out[i].d = data_out_q[i]; + end + end + + //////////// + // Alerts // + //////////// + + // Should fatal alerts clear the status register? + assign clear_on_fatal = ClearStatusOnFatalAlert ? alert_fatal_o : 1'b0; + + // Recoverable alert conditions are signaled as a single alert event. + assign ctrl_err_update = ctrl_reg_err_update | shadowed_update_err_i | ctrl_gcm_reg_err_update; + assign alert_recov_o = ctrl_err_update; + + // The recoverable alert is observable via status register until the AES operation is restarted + // by re-writing the Control Register. Fatal alerts clear all other bits in the status register. + assign hw2reg.status.alert_recov_ctrl_update_err.d = ctrl_err_update & ~clear_on_fatal; + assign hw2reg.status.alert_recov_ctrl_update_err.de = ctrl_err_update | ctrl_we | clear_on_fatal; + + // Fatal alert conditions need to remain asserted until reset. + assign ctrl_err_storage_d = + ctrl_reg_err_storage | shadowed_storage_err_i | ctrl_gcm_reg_err_storage; + always_ff @(posedge clk_i or negedge rst_ni) begin : ctrl_err_storage_reg + if (!rst_ni) begin + ctrl_err_storage_q <= 1'b0; + end else if (ctrl_err_storage_d) begin + ctrl_err_storage_q <= 1'b1; + end + end + assign ctrl_err_storage = ctrl_err_storage_d | ctrl_err_storage_q; + + // Collect fatal alert signals. + assign alert_fatal_o = ctrl_err_storage | + ctr_alert | + cipher_alert | + ghash_alert | + ctrl_alert | + intg_err_alert_i; + + // Make the fatal alert observable via status register. + assign hw2reg.status.alert_fatal_fault.d = alert_fatal_o; + assign hw2reg.status.alert_fatal_fault.de = alert_fatal_o; + + // Unused alert signals + logic unused_alert_signals; + assign unused_alert_signals = ^reg2hw.alert_test; + + // Unused inputs + logic unused_idle; + assign unused_idle = reg2hw.status.idle.q; + + //////////////// + // Assertions // + //////////////// + + // Create a lint error to reduce the risk of accidentally disabling the masking. + `CALIPTRA_ASSERT_STATIC_LINT_ERROR(AesCoreSecMaskingNonDefault, SecMasking == 1) + + // Selectors must be known/valid + `CALIPTRA_ASSERT(AesModeValid, !ctrl_err_storage |-> aes_mode_q inside { + AES_ECB, + AES_CBC, + AES_CFB, + AES_OFB, + AES_CTR, + AES_GCM, + AES_NONE + }) + `CALIPTRA_ASSERT(AesOpValid, !ctrl_err_storage |-> aes_op_q inside { + AES_ENC, + AES_DEC + }) + + // Check parameters + `CALIPTRA_ASSERT_INIT(AesNumSlicesCtr, NumSlicesCtr == 8) + + // Signals used for assertions only. + logic [3:0][31:0] state_done_transposed, unused_state_done_transposed; + if (!SecMasking) begin : gen_state_done_transposed_unmasked + assign state_done_transposed = aes_transpose(state_done[0]); + end else begin : gen_state_done_transposed_masked + assign state_done_transposed = aes_transpose(state_done[0] ^ state_done[1]); + end + assign unused_state_done_transposed = state_done_transposed; + + // Ensure that upon local escalation of any of the FSMs, no intermediate state is released from + // the cipher core into the software readable output data or IV registers. + `CALIPTRA_ASSERT(AesSecCmDataRegLocalEscDataOut, $changed(data_out_q) && alert_fatal_o && + ($past(cipher_crypt, 2) == SP2V_HIGH || $past(cipher_crypt_busy, 2) == SP2V_HIGH) |=> + ($past(data_out_q) != $past(state_done_transposed, 2)) && + ($past(data_out_q) != $past(state_done_transposed, 2) ^ $past(iv_q, 2)) && + ($past(data_out_q) != $past(state_done_transposed, 2) ^ $past(data_in_prev_q, 2))) + + `CALIPTRA_ASSERT(AesSecCmDataRegLocalEscIv, $changed(iv_q) && alert_fatal_o && + ($past(cipher_crypt, 2) == SP2V_HIGH || $past(cipher_crypt_busy, 2) == SP2V_HIGH) |=> + ($past(iv_q) != $past(state_done_transposed, 2)) && + ($past(iv_q) != $past(state_done_transposed, 2) ^ $past(iv_q, 2)) && + ($past(iv_q) != $past(state_done_transposed, 2) ^ $past(data_in_prev_q, 2))) + +endmodule diff --git a/src/aes/rtl/aes_ctr.sv b/src/aes/rtl/aes_ctr.sv new file mode 100644 index 000000000..f07b55a33 --- /dev/null +++ b/src/aes/rtl/aes_ctr.sv @@ -0,0 +1,217 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES counter for CTR mode +// +// This module uses one counter with a width of SliceSizeCtr to iteratively increment the 128-bit +// counter value. + +module aes_ctr import aes_pkg::*; +( + input logic clk_i, + input logic rst_ni, + + input sp2v_e inc32_i, + input sp2v_e incr_i, + output sp2v_e ready_o, + output logic alert_o, + + input logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] ctr_i, + output logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] ctr_o, + output sp2v_e [NumSlicesCtr-1:0] ctr_we_o +); + + // Reverse byte order - unrelated to NumSlicesCtr and SliceSizeCtr + function automatic logic [15:0][7:0] aes_rev_order_byte(logic [15:0][7:0] in); + logic [15:0][7:0] out; + for (int i = 0; i < 16; i++) begin + out[i] = in[15-i]; + end + return out; + endfunction + + // Reverse sp2v order + function automatic sp2v_e [NumSlicesCtr-1:0] aes_rev_order_sp2v(sp2v_e [NumSlicesCtr-1:0] in); + sp2v_e [NumSlicesCtr-1:0] out; + for (int i = 0; i < NumSlicesCtr; i++) begin + out[i] = in[NumSlicesCtr - 1 - i]; + end + return out; + endfunction + + // Signals + logic [SliceIdxWidth-1:0] ctr_slice_idx; + + logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] ctr_i_rev; // 8 times 2 bytes + logic [NumSlicesCtr-1:0][SliceSizeCtr-1:0] ctr_o_rev; // 8 times 2 bytes + sp2v_e [NumSlicesCtr-1:0] ctr_we_o_rev; + sp2v_e ctr_we; + + logic [SliceSizeCtr-1:0] ctr_i_slice; + logic [SliceSizeCtr-1:0] ctr_o_slice; + + sp2v_e inc32; + logic inc32_err; + sp2v_e incr; + logic incr_err; + logic sp_enc_err; + logic mr_err; + + // Sparsified FSM signals. These are needed for connecting the individual bits of the Sp2V + // signals to the single-rail FSMs. + logic [Sp2VWidth-1:0] sp_inc32; + logic [Sp2VWidth-1:0] sp_incr; + logic [Sp2VWidth-1:0] sp_ready; + logic [Sp2VWidth-1:0] sp_ctr_we; + + // Multi-rail signals. These are outputs of the single-rail FSMs and need combining. + logic [Sp2VWidth-1:0] mr_alert; + logic [Sp2VWidth-1:0][SliceIdxWidth-1:0] mr_ctr_slice_idx; + logic [Sp2VWidth-1:0] [SliceSizeCtr-1:0] mr_ctr_o_slice; + + //////////// + // Inputs // + //////////// + + // Reverse byte order + assign ctr_i_rev = aes_rev_order_byte(ctr_i); + + // SEC_CM: CTRL.SPARSE + // Check sparsely encoded inc32 and incr signals. + logic [Sp2VWidth-1:0] inc32_raw; + aes_sel_buf_chk #( + .Num ( Sp2VNum ), + .Width ( Sp2VWidth ), + .EnSecBuf ( 1'b0 ) + ) u_aes_inc32_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( inc32_i ), + .sel_o ( inc32_raw ), + .err_o ( inc32_err ) + ); + assign inc32 = sp2v_e'(inc32_raw); + + logic [Sp2VWidth-1:0] incr_raw; + aes_sel_buf_chk #( + .Num ( Sp2VNum ), + .Width ( Sp2VWidth ), + .EnSecBuf ( 1'b0 ) + ) u_aes_incr_buf_chk ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .sel_i ( incr_i ), + .sel_o ( incr_raw ), + .err_o ( incr_err ) + ); + assign incr = sp2v_e'(incr_raw); + + // Collect encoding errors. + assign sp_enc_err = inc32_err | incr_err; + + ///////////// + // Counter // + ///////////// + + // We do SliceSizeCtr bits at a time. + assign ctr_i_slice = ctr_i_rev[ctr_slice_idx]; + + ///////// + // FSM // + ///////// + + // Convert sp2v_e signals to sparsified inputs. + assign sp_inc32 = {inc32}; + assign sp_incr = {incr}; + + // SEC_CM: CTR.FSM.REDUN + // For every bit in the Sp2V signals, one separate rail is instantiated. The inputs and outputs + // of every rail are buffered to prevent aggressive synthesis optimizations. + for (genvar i = 0; i < Sp2VWidth; i++) begin : gen_fsm + if (SP2V_LOGIC_HIGH[i] == 1'b1) begin : gen_fsm_p + aes_ctr_fsm_p u_aes_ctr_fsm_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .inc32_i ( sp_inc32[i] ), // Sparsified + .incr_i ( sp_incr[i] ), // Sparsified + .ready_o ( sp_ready[i] ), // Sparsified + .sp_enc_err_i ( sp_enc_err ), + .mr_err_i ( mr_err ), + .alert_o ( mr_alert[i] ), // OR-combine + + .ctr_slice_idx_o ( mr_ctr_slice_idx[i] ), // OR-combine + .ctr_slice_i ( ctr_i_slice ), + .ctr_slice_o ( mr_ctr_o_slice[i] ), // OR-combine + .ctr_we_o ( sp_ctr_we[i] ) // Sparsified + ); + end else begin : gen_fsm_n + aes_ctr_fsm_n u_aes_ctr_fsm_i ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .inc32_ni ( sp_inc32[i] ), // Sparsified + .incr_ni ( sp_incr[i] ), // Sparsified + .ready_no ( sp_ready[i] ), // Sparsified + .sp_enc_err_i ( sp_enc_err ), + .mr_err_i ( mr_err ), + .alert_o ( mr_alert[i] ), // OR-combine + + .ctr_slice_idx_o ( mr_ctr_slice_idx[i] ), // OR-combine + .ctr_slice_i ( ctr_i_slice ), + .ctr_slice_o ( mr_ctr_o_slice[i] ), // OR-combine + .ctr_we_no ( sp_ctr_we[i] ) // Sparsified + ); + end + end + + // Convert sparsified outputs to sp2v_e type. + assign ready_o = sp2v_e'(sp_ready); + assign ctr_we = sp2v_e'(sp_ctr_we); + + // Combine single-bit FSM outputs. + // OR: One bit is sufficient to drive the corresponding output bit high. + assign alert_o = |mr_alert; + + // Combine multi-bit FSM outputs. We simply OR them together and compare the values + // to detect errors. + always_comb begin : combine_sparse_signals + ctr_slice_idx = '0; + ctr_o_slice = '0; + mr_err = 1'b0; + + for (int i = 0; i < Sp2VWidth; i++) begin + ctr_slice_idx |= mr_ctr_slice_idx[i]; + ctr_o_slice |= mr_ctr_o_slice[i]; + end + + for (int i = 0; i < Sp2VWidth; i++) begin + if (ctr_slice_idx != mr_ctr_slice_idx[i] || + ctr_o_slice != mr_ctr_o_slice[i]) begin + mr_err = 1'b1; + end + end + end + + ///////////// + // Outputs // + ///////////// + + // Combine input and counter output. + always_comb begin + ctr_o_rev = ctr_i_rev; + ctr_o_rev[ctr_slice_idx] = ctr_o_slice; + end + + // Generate the sliced write enable. + always_comb begin + ctr_we_o_rev = {NumSlicesCtr{SP2V_LOW}}; + ctr_we_o_rev[ctr_slice_idx] = ctr_we; + end + + // Reverse byte and bit order. + assign ctr_o = aes_rev_order_byte(ctr_o_rev); + assign ctr_we_o = aes_rev_order_sp2v(ctr_we_o_rev); + +endmodule diff --git a/src/aes/rtl/aes_ctr_fsm.sv b/src/aes/rtl/aes_ctr_fsm.sv new file mode 100644 index 000000000..e09644d3a --- /dev/null +++ b/src/aes/rtl/aes_ctr_fsm.sv @@ -0,0 +1,130 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES counter FSM for CTR mode + +`include "caliptra_prim_assert.sv" + +module aes_ctr_fsm import aes_pkg::*; +( + input logic clk_i, + input logic rst_ni, + + input logic inc32_i, // Sparsify using multi-rail. + input logic incr_i, // Sparsify using multi-rail. + output logic ready_o, // Sparsify using multi-rail. + input logic sp_enc_err_i, + input logic mr_err_i, + output logic alert_o, + + output logic [SliceIdxWidth-1:0] ctr_slice_idx_o, + input logic [SliceSizeCtr-1:0] ctr_slice_i, + output logic [SliceSizeCtr-1:0] ctr_slice_o, + output logic ctr_we_o // Sparsify using multi-rail. +); + + // Signals + aes_ctr_e aes_ctr_ns, aes_ctr_cs; + logic [SliceIdxWidth-1:0] ctr_slice_idx_d, ctr_slice_idx_q; + logic [SliceIdxWidth-1:0] ctr_slice_idx_max; + logic ctr_carry_d, ctr_carry_q; + + logic [SliceSizeCtr:0] ctr_value; + + ///////////// + // Counter // + ///////////// + + // We do SliceSizeCtr bits at a time. + assign ctr_value = ctr_slice_i + {{(SliceSizeCtr-1){1'b0}}, ctr_carry_q}; + assign ctr_slice_o = ctr_value[SliceSizeCtr-1:0]; + + // Perform either inc128() or inc32() for GCM. + assign ctr_slice_idx_max = inc32_i ? SliceIdxWidth'(SliceIdxMaxInc32) : {SliceIdxWidth{1'b1}}; + + ///////////// + // Control // + ///////////// + + // FSM + always_comb begin : aes_ctr_fsm_comb + + // Outputs + ready_o = 1'b0; + ctr_we_o = 1'b0; + alert_o = 1'b0; + + // FSM + aes_ctr_ns = aes_ctr_cs; + ctr_slice_idx_d = ctr_slice_idx_q; + ctr_carry_d = ctr_carry_q; + + unique case (aes_ctr_cs) + CTR_IDLE: begin + ready_o = 1'b1; + if (incr_i == 1'b1) begin + // Initialize slice index and carry bit. + ctr_slice_idx_d = '0; + ctr_carry_d = 1'b1; + aes_ctr_ns = CTR_INCR; + end + end + + CTR_INCR: begin + // Increment slice index. + ctr_slice_idx_d = ctr_slice_idx_q + SliceIdxWidth'(1); + ctr_carry_d = ctr_slice_idx_q >= ctr_slice_idx_max ? 1'b0 : ctr_value[SliceSizeCtr]; + ctr_we_o = 1'b1; + + if (ctr_slice_idx_q == {SliceIdxWidth{1'b1}}) begin + aes_ctr_ns = CTR_IDLE; + end + end + + CTR_ERROR: begin + // SEC_CM: CTR.FSM.LOCAL_ESC + // Terminal error state + alert_o = 1'b1; + end + + // We should never get here. If we do (e.g. via a malicious + // glitch), error out immediately. + default: begin + aes_ctr_ns = CTR_ERROR; + alert_o = 1'b1; + end + endcase + + // Unconditionally jump into the terminal error state in case an error is detected. + if (sp_enc_err_i || mr_err_i) begin + aes_ctr_ns = CTR_ERROR; + end + end + + // Registers + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + ctr_slice_idx_q <= '0; + ctr_carry_q <= '0; + end else begin + ctr_slice_idx_q <= ctr_slice_idx_d; + ctr_carry_q <= ctr_carry_d; + end + end + + // SEC_CM: CTR.FSM.SPARSE + `CALIPTRA_PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_ctr_ns, aes_ctr_cs, aes_ctr_e, CTR_IDLE) + + // Forward slice index. + assign ctr_slice_idx_o = ctr_slice_idx_q; + + //////////////// + // Assertions // + //////////////// + `CALIPTRA_ASSERT(AesCtrStateValid, !alert_o |-> aes_ctr_cs inside { + CTR_IDLE, + CTR_INCR + }) + +endmodule diff --git a/src/aes/rtl/aes_ctr_fsm_n.sv b/src/aes/rtl/aes_ctr_fsm_n.sv new file mode 100644 index 000000000..8df0ae738 --- /dev/null +++ b/src/aes/rtl/aes_ctr_fsm_n.sv @@ -0,0 +1,146 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES counter FSM for CTR mode +// +// This module contains the AES counter FSM operating on and producing the negated values of +// important control signals. This is achieved by: +// - instantiating the regular AES counter FSM operating on and producing the positive values of +// these signals, and +// - inverting these signals between the regular FSM and the caliptra_prim_buf synthesis barriers. +// Synthesis tools will then push the inverters into the actual FSM. + +module aes_ctr_fsm_n import aes_pkg::*; +( + input logic clk_i, + input logic rst_ni, + + input logic inc32_ni, // Sparsify using multi-rail. + input logic incr_ni, // Sparsify using multi-rail. + output logic ready_no, // Sparsify using multi-rail. + input logic sp_enc_err_i, + input logic mr_err_i, + output logic alert_o, + + output logic [SliceIdxWidth-1:0] ctr_slice_idx_o, + input logic [SliceSizeCtr-1:0] ctr_slice_i, + output logic [SliceSizeCtr-1:0] ctr_slice_o, + output logic ctr_we_no // Sparsify using multi-rail. +); + + ///////////////////// + // Input Buffering // + ///////////////////// + + localparam int NumInBufBits = $bits({ + inc32_ni, + incr_ni, + sp_enc_err_i, + mr_err_i, + ctr_slice_i + }); + + logic [NumInBufBits-1:0] in, in_buf; + + assign in = { + inc32_ni, + incr_ni, + sp_enc_err_i, + mr_err_i, + ctr_slice_i + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumInBufBits) + ) u_caliptra_prim_buf_in ( + .in_i(in), + .out_o(in_buf) + ); + + logic inc32_n; + logic incr_n; + logic sp_enc_err; + logic mr_err; + logic [SliceSizeCtr-1:0] ctr_i_slice; + + assign {inc32_n, + incr_n, + sp_enc_err, + mr_err, + ctr_i_slice} = in_buf; + + // Intermediate output signals + logic ready; + logic alert; + logic [SliceIdxWidth-1:0] ctr_slice_idx; + logic [SliceSizeCtr-1:0] ctr_o_slice; + logic ctr_we; + + ///////////////// + // Regular FSM // + ///////////////// + + // The regular FSM operates on and produces the positive values of important control signals. + // Invert *_n input signals here to get the positive values for the regular FSM. To obtain the + // negated outputs, important output signals are inverted further below. Thanks to the caliptra_prim_buf + // synthesis optimization barriers, tools will push the inverters into the regular FSM. + aes_ctr_fsm u_aes_ctr_fsm ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .inc32_i ( ~inc32_n ), // Invert for regular FSM. + .incr_i ( ~incr_n ), // Invert for regular FSM. + .ready_o ( ready ), // Invert below for negated output. + .sp_enc_err_i ( sp_enc_err ), + .mr_err_i ( mr_err ), + .alert_o ( alert ), + + .ctr_slice_idx_o ( ctr_slice_idx ), + .ctr_slice_i ( ctr_i_slice ), + .ctr_slice_o ( ctr_o_slice ), + .ctr_we_o ( ctr_we ) // Invert below for negated output. + ); + + ////////////////////// + // Output Buffering // + ////////////////////// + + localparam int NumOutBufBits = $bits({ + ready_no, + alert_o, + ctr_slice_idx_o, + ctr_slice_o, + ctr_we_no + }); + + logic [NumOutBufBits-1:0] out, out_buf; + + // Important output control signals need to be inverted here. Synthesis tools will push the + // inverters back into the regular FSM. + assign out = { + ~ready, + alert, + ctr_slice_idx, + ctr_o_slice, + ~ctr_we + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumOutBufBits) + ) u_caliptra_prim_buf_out ( + .in_i(out), + .out_o(out_buf) + ); + + assign {ready_no, + alert_o, + ctr_slice_idx_o, + ctr_slice_o, + ctr_we_no} = out_buf; + +endmodule diff --git a/src/aes/rtl/aes_ctr_fsm_p.sv b/src/aes/rtl/aes_ctr_fsm_p.sv new file mode 100644 index 000000000..cfa0f383a --- /dev/null +++ b/src/aes/rtl/aes_ctr_fsm_p.sv @@ -0,0 +1,136 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES counter FSM for CTR mode +// +// This module contains the AES counter FSM operating on and producing the positive values of +// important control signals. + +module aes_ctr_fsm_p import aes_pkg::*; +( + input logic clk_i, + input logic rst_ni, + + input logic inc32_i, // Sparsify + input logic incr_i, // Sparsify + output logic ready_o, // Sparsify + input logic sp_enc_err_i, + input logic mr_err_i, + output logic alert_o, + + output logic [SliceIdxWidth-1:0] ctr_slice_idx_o, + input logic [SliceSizeCtr-1:0] ctr_slice_i, + output logic [SliceSizeCtr-1:0] ctr_slice_o, + output logic ctr_we_o // Sparsify +); + + ///////////////////// + // Input Buffering // + ///////////////////// + + localparam int NumInBufBits = $bits({ + inc32_i, + incr_i, + sp_enc_err_i, + mr_err_i, + ctr_slice_i + }); + + logic [NumInBufBits-1:0] in, in_buf; + + assign in = { + inc32_i, + incr_i, + sp_enc_err_i, + mr_err_i, + ctr_slice_i + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumInBufBits) + ) u_caliptra_prim_buf_in ( + .in_i(in), + .out_o(in_buf) + ); + + logic inc32; + logic incr; + logic sp_enc_err; + logic mr_err; + logic [SliceSizeCtr-1:0] ctr_i_slice; + + assign {inc32, + incr, + sp_enc_err, + mr_err, + ctr_i_slice} = in_buf; + + // Intermediate output signals + logic ready; + logic alert; + logic [SliceIdxWidth-1:0] ctr_slice_idx; + logic [SliceSizeCtr-1:0] ctr_o_slice; + logic ctr_we; + + ///////////////// + // Regular FSM // + ///////////////// + + aes_ctr_fsm u_aes_ctr_fsm ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + + .inc32_i ( inc32 ), + .incr_i ( incr ), + .ready_o ( ready ), + .sp_enc_err_i ( sp_enc_err ), + .mr_err_i ( mr_err ), + .alert_o ( alert ), + + .ctr_slice_idx_o ( ctr_slice_idx ), + .ctr_slice_i ( ctr_i_slice ), + .ctr_slice_o ( ctr_o_slice ), + .ctr_we_o ( ctr_we ) + ); + + ////////////////////// + // Output Buffering // + ////////////////////// + + localparam int NumOutBufBits = $bits({ + ready_o, + alert_o, + ctr_slice_idx_o, + ctr_slice_o, + ctr_we_o + }); + + logic [NumOutBufBits-1:0] out, out_buf; + + assign out = { + ready, + alert, + ctr_slice_idx, + ctr_o_slice, + ctr_we + }; + + // This primitive is used to place a size-only constraint on the + // buffers to act as a synthesis optimization barrier. + caliptra_prim_buf #( + .Width(NumOutBufBits) + ) u_caliptra_prim_buf_out ( + .in_i(out), + .out_o(out_buf) + ); + + assign {ready_o, + alert_o, + ctr_slice_idx_o, + ctr_slice_o, + ctr_we_o} = out_buf; + +endmodule diff --git a/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv b/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv new file mode 100644 index 000000000..289b2d225 --- /dev/null +++ b/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv @@ -0,0 +1,201 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES Galois/Counter Mode (GCM) shadowed control register +// +// This module implements the shadowed AES GCM control register. The main differences compared +// to implementing the register as part of the auto-generated aes_reg_top.sv are: +// +// 1. The hardware can block updates to the GCM control register from software. +// Whenever the module is busy, GCM control register writes are ignored. +// 2. Invalid values written by software are resolved to valid configurations. + +`include "caliptra_prim_assert.sv" + +module aes_ctrl_gcm_reg_shadowed + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AESGCMEnable = 1 +) ( + input logic clk_i, + input logic rst_ni, + input logic rst_shadowed_ni, + // Main control + output logic qe_o, // software wants to write + input logic we_i, // hardware grants software write + input logic first_block_i, + output gcm_phase_e gcm_phase_o, + output logic [4:0] num_valid_bytes_o, + + // Alerts + output logic err_update_o, + output logic err_storage_o, + + // Bus interface + input aes_reg2hw_ctrl_gcm_shadowed_reg_t reg2hw_ctrl_gcm_i, + output aes_hw2reg_ctrl_gcm_shadowed_reg_t hw2reg_ctrl_gcm_o +); + + // Signals + logic err_update_gcm_phase; + logic err_update_num_valid_bytes; + logic err_storage_gcm_phase; + logic err_storage_num_valid_bytes; + + // Get and forward write enable. Writes are only allowed if the module is idle. + assign qe_o = reg2hw_ctrl_gcm_i.phase.qe & reg2hw_ctrl_gcm_i.num_valid_bytes.qe; + + if (AESGCMEnable) begin : gen_ctrl_gcm_reg_shadowed + ctrl_gcm_reg_t ctrl_gcm_wd; + gcm_phase_e gcm_phase_reg_if, gcm_phase; + logic [4:0] num_valid_bytes; + + // Get and resolve values from register interface. + assign gcm_phase_reg_if = gcm_phase_e'(reg2hw_ctrl_gcm_i.phase.q); + always_comb begin : gcm_phase_get + // Resolve unsupported input values. + unique case (gcm_phase_reg_if) + GCM_INIT: gcm_phase = GCM_INIT; + GCM_RESTORE: gcm_phase = GCM_RESTORE; + GCM_AAD: gcm_phase = GCM_AAD; + GCM_TEXT: gcm_phase = GCM_TEXT; + GCM_SAVE: gcm_phase = GCM_SAVE; + GCM_TAG: gcm_phase = GCM_TAG; + default: gcm_phase = GCM_INIT; // Unsupported values are mapped to GCM_INIT. + endcase + + // Only a subset of next phase transitions are allowed. + unique case (gcm_phase_o) + GCM_INIT: begin + gcm_phase = gcm_phase == GCM_RESTORE || + gcm_phase == GCM_AAD || + gcm_phase == GCM_TEXT || + gcm_phase == GCM_TAG ? gcm_phase : gcm_phase_o; + end + + GCM_RESTORE: begin + gcm_phase = gcm_phase == GCM_INIT || + gcm_phase == GCM_AAD || + gcm_phase == GCM_TEXT ? gcm_phase : gcm_phase_o; + end + + GCM_AAD: begin + gcm_phase = gcm_phase == GCM_INIT || + gcm_phase == GCM_TEXT || + gcm_phase == GCM_SAVE && !first_block_i || + gcm_phase == GCM_TAG ? gcm_phase : gcm_phase_o; + end + + GCM_TEXT: begin + gcm_phase = gcm_phase == GCM_INIT || + gcm_phase == GCM_SAVE && !first_block_i || + gcm_phase == GCM_TAG ? gcm_phase : gcm_phase_o; + end + + GCM_SAVE: begin + gcm_phase = gcm_phase == GCM_INIT ? gcm_phase : gcm_phase_o; + end + + GCM_TAG: begin + gcm_phase = gcm_phase == GCM_INIT ? gcm_phase : gcm_phase_o; + end + + default: begin + gcm_phase = gcm_phase_o; // If we end up in an unspported value (which should never + // happen), keep it. + end + endcase + end + assign ctrl_gcm_wd.phase = gcm_phase; + + assign num_valid_bytes = reg2hw_ctrl_gcm_i.num_valid_bytes.q; + // Unsupported values are mapped to 16. + assign ctrl_gcm_wd.num_valid_bytes = + ((num_valid_bytes == 5'd0) || (num_valid_bytes > 5'd16)) ? 5'd16 : num_valid_bytes; + + // SEC_CM: GCM.CONFIG.SHADOW + // Instantiate one shadowed register primitive per field. An update error in a field should + // only prevent the update of the affected field. + caliptra_prim_subreg_shadow #( + .DW ($bits(gcm_phase_e)), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_GCM_SHADOWED_PHASE_RESVAL) + ) u_ctrl_gcm_reg_shadowed_phase ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_gcm_i.phase.re), + .we (we_i), + .wd ({ctrl_gcm_wd.phase}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_gcm_o.phase.d), + .qs (), + .ds (), + .phase (), + .err_update (err_update_gcm_phase), + .err_storage(err_storage_gcm_phase) + ); + + caliptra_prim_subreg_shadow #( + .DW (5), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_RESVAL) + ) u_ctrl_gcm_reg_shadowed_num_valid_bytes ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_gcm_i.num_valid_bytes.re), + .we (we_i), + .wd ({ctrl_gcm_wd.num_valid_bytes}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_gcm_o.num_valid_bytes.d), + .qs (), + .ds (), + .phase (), + .err_update (err_update_num_valid_bytes), + .err_storage(err_storage_num_valid_bytes) + ); + end else begin : gen_no_ctrl_gcm_reg_shadowed + // Tie off unused inputs. + logic unused_ctrl_gcm; + assign unused_ctrl_gcm = ^{reg2hw_ctrl_gcm_i.phase.re, + reg2hw_ctrl_gcm_i.phase.q, + reg2hw_ctrl_gcm_i.num_valid_bytes.re, + reg2hw_ctrl_gcm_i.num_valid_bytes.q}; + logic unused_we; + assign unused_we = we_i; + + logic unused_clk; + logic unused_rst; + logic unused_rst_shadowed; + assign unused_clk = clk_i; + assign unused_rst = rst_ni; + assign unused_rst_shadowed = rst_shadowed_ni; + + // Tie off control signals. + assign hw2reg_ctrl_gcm_o.phase.d = {GCM_INIT}; + assign hw2reg_ctrl_gcm_o.num_valid_bytes.d = 5'd16; + + // Tie off error signals. + assign err_update_gcm_phase = 1'b0; + assign err_update_num_valid_bytes = 1'b0; + assign err_storage_gcm_phase = 1'b0; + assign err_storage_num_valid_bytes = 1'b0; + end + + // Collect alerts. + assign err_update_o = err_update_gcm_phase | err_update_num_valid_bytes; + assign err_storage_o = err_storage_gcm_phase | err_storage_num_valid_bytes; + + // Generate shorter references. + // Doing that here as opposed to in aes_core avoids several Verilator lint errors. + assign gcm_phase_o = gcm_phase_e'(hw2reg_ctrl_gcm_o.phase.d); + assign num_valid_bytes_o = hw2reg_ctrl_gcm_o.num_valid_bytes.d; + +endmodule diff --git a/src/aes/rtl/aes_ctrl_reg_shadowed.sv b/src/aes/rtl/aes_ctrl_reg_shadowed.sv new file mode 100644 index 000000000..17f019a20 --- /dev/null +++ b/src/aes/rtl/aes_ctrl_reg_shadowed.sv @@ -0,0 +1,277 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES shadowed control register +// +// This module implements the AES shadowed control register. The main differences compared +// to implementing the register as part of the auto-generated aes_reg_top.sv are: +// +// 1. The hardware can block updates to the control register from software. +// Whenever the module is busy, control register writes are ignored. +// 2. Invalid values written by software are resolved to valid configurations. + +`include "caliptra_prim_assert.sv" + +module aes_ctrl_reg_shadowed + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit AES192Enable = 1, + parameter bit AESGCMEnable = 1 +) ( + input logic clk_i, + input logic rst_ni, + input logic rst_shadowed_ni, + // Main control + output logic qe_o, // software wants to write + input logic we_i, // hardware grants software write + output logic phase_o, + output aes_op_e operation_o, + output aes_mode_e mode_o, + output key_len_e key_len_o, + output logic sideload_o, + output prs_rate_e prng_reseed_rate_o, + output logic manual_operation_o, + + // Alerts + output logic err_update_o, + output logic err_storage_o, + + // Bus interface + input aes_reg2hw_ctrl_shadowed_reg_t reg2hw_ctrl_i, + output aes_hw2reg_ctrl_shadowed_reg_t hw2reg_ctrl_o +); + + // Signals + ctrl_reg_t ctrl_wd; + aes_op_e op; + aes_mode_e mode; + key_len_e key_len; + prs_rate_e prng_reseed_rate; + logic phase_operation; + logic phase_mode; + logic phase_key_len; + logic phase_key_sideload; + logic phase_prng_reseed_rate; + logic phase_manual_operation; + logic err_update_operation; + logic err_update_mode; + logic err_update_key_len; + logic err_update_sideload; + logic err_update_prng_reseed_rate; + logic err_update_manual_operation; + logic err_storage_operation; + logic err_storage_mode; + logic err_storage_key_len; + logic err_storage_sideload; + logic err_storage_prng_reseed_rate; + logic err_storage_manual_operation; + + // Get and forward write enable. Writes are only allowed if the module is idle. + assign qe_o = reg2hw_ctrl_i.operation.qe & reg2hw_ctrl_i.mode.qe & + reg2hw_ctrl_i.key_len.qe & reg2hw_ctrl_i.sideload.qe & + reg2hw_ctrl_i.prng_reseed_rate.qe & reg2hw_ctrl_i.manual_operation.qe; + + // Get and resolve values from register interface. + assign op = aes_op_e'(reg2hw_ctrl_i.operation.q); + always_comb begin : operation_get + unique case (op) + AES_ENC: ctrl_wd.operation = AES_ENC; + AES_DEC: ctrl_wd.operation = AES_DEC; + default: ctrl_wd.operation = AES_ENC; // unsupported values are mapped to AES_ENC + endcase + end + + assign mode = aes_mode_e'(reg2hw_ctrl_i.mode.q); + always_comb begin : mode_get + unique case (mode) + AES_ECB: ctrl_wd.mode = AES_ECB; + AES_CBC: ctrl_wd.mode = AES_CBC; + AES_CFB: ctrl_wd.mode = AES_CFB; + AES_OFB: ctrl_wd.mode = AES_OFB; + AES_CTR: ctrl_wd.mode = AES_CTR; + AES_GCM: ctrl_wd.mode = AESGCMEnable ? AES_GCM : AES_NONE; + default: ctrl_wd.mode = AES_NONE; // unsupported values are mapped to AES_NONE + endcase + end + + assign key_len = key_len_e'(reg2hw_ctrl_i.key_len.q); + always_comb begin : key_len_get + unique case (key_len) + AES_128: ctrl_wd.key_len = AES_128; + AES_256: ctrl_wd.key_len = AES_256; + AES_192: ctrl_wd.key_len = AES192Enable ? AES_192 : AES_256; + default: ctrl_wd.key_len = AES_256; // unsupported values are mapped to AES_256 + endcase + end + + assign ctrl_wd.sideload = reg2hw_ctrl_i.sideload.q; + + assign prng_reseed_rate = prs_rate_e'(reg2hw_ctrl_i.prng_reseed_rate.q); + always_comb begin : prng_reseed_rate_get + unique case (prng_reseed_rate) + PER_1: ctrl_wd.prng_reseed_rate = PER_1; + PER_64: ctrl_wd.prng_reseed_rate = PER_64; + PER_8K: ctrl_wd.prng_reseed_rate = PER_8K; + default: ctrl_wd.prng_reseed_rate = PER_1; // unsupported values are mapped to PER_1. + endcase + end + + assign ctrl_wd.manual_operation = reg2hw_ctrl_i.manual_operation.q; + + // SEC_CM: MAIN.CONFIG.SHADOW + // Instantiate one shadowed register primitive per field. An update error in a field should + // only prevent the update of the affected field. + caliptra_prim_subreg_shadow #( + .DW ($bits(aes_op_e)), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_OPERATION_RESVAL) + ) u_ctrl_reg_shadowed_operation ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.operation.re), + .we (we_i), + .wd ({ctrl_wd.operation}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.operation.d), + .qs (), + .ds (), + .phase (phase_operation), + .err_update (err_update_operation), + .err_storage(err_storage_operation) + ); + + caliptra_prim_subreg_shadow #( + .DW ($bits(aes_mode_e)), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_MODE_RESVAL) + ) u_ctrl_reg_shadowed_mode ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.mode.re), + .we (we_i), + .wd ({ctrl_wd.mode}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.mode.d), + .qs (), + .ds (), + .phase (phase_mode), + .err_update (err_update_mode), + .err_storage(err_storage_mode) + ); + + caliptra_prim_subreg_shadow #( + .DW ($bits(key_len_e)), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_KEY_LEN_RESVAL) + ) u_ctrl_reg_shadowed_key_len ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.key_len.re), + .we (we_i), + .wd ({ctrl_wd.key_len}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.key_len.d), + .qs (), + .ds (), + .phase (phase_key_len), + .err_update (err_update_key_len), + .err_storage(err_storage_key_len) + ); + + caliptra_prim_subreg_shadow #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_SIDELOAD_RESVAL) + ) u_ctrl_reg_shadowed_sideload ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.sideload.re), + .we (we_i), + .wd (ctrl_wd.sideload), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.sideload.d), + .qs (), + .ds (), + .phase (phase_key_sideload), + .err_update (err_update_sideload), + .err_storage(err_storage_sideload) + ); + + caliptra_prim_subreg_shadow #( + .DW ($bits(prs_rate_e)), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_PRNG_RESEED_RATE_RESVAL) + ) u_ctrl_reg_shadowed_prng_reseed_rate ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.prng_reseed_rate.re), + .we (we_i), + .wd ({ctrl_wd.prng_reseed_rate}), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.prng_reseed_rate.d), + .qs (), + .ds (), + .phase (phase_prng_reseed_rate), + .err_update (err_update_prng_reseed_rate), + .err_storage(err_storage_prng_reseed_rate) + ); + + caliptra_prim_subreg_shadow #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (AES_CTRL_SHADOWED_MANUAL_OPERATION_RESVAL) + ) u_ctrl_reg_shadowed_manual_operation ( + .clk_i, + .rst_ni, + .rst_shadowed_ni, + .re (reg2hw_ctrl_i.manual_operation.re), + .we (we_i), + .wd (ctrl_wd.manual_operation), + .de (1'b0), + .d ('0), + .qe (), + .q (hw2reg_ctrl_o.manual_operation.d), + .qs (), + .ds (), + .phase (phase_manual_operation), + .err_update (err_update_manual_operation), + .err_storage(err_storage_manual_operation) + ); + + // Collect phase signals. + assign phase_o = phase_operation | phase_mode | phase_key_len | phase_key_sideload | + phase_prng_reseed_rate | phase_manual_operation; + + // Collect alerts. + assign err_update_o = err_update_operation | err_update_mode | err_update_key_len | + err_update_sideload | err_update_prng_reseed_rate | err_update_manual_operation; + assign err_storage_o = err_storage_operation | err_storage_mode | err_storage_key_len | + err_storage_sideload | err_storage_prng_reseed_rate | err_storage_manual_operation; + + // Generate shorter references. + // Doing that here as opposed to in aes_core avoids several Verilator lint errors. + assign operation_o = aes_op_e'(hw2reg_ctrl_o.operation.d); + assign mode_o = aes_mode_e'(hw2reg_ctrl_o.mode.d); + assign key_len_o = key_len_e'(hw2reg_ctrl_o.key_len.d); + assign sideload_o = hw2reg_ctrl_o.sideload.d; + assign prng_reseed_rate_o = prs_rate_e'(hw2reg_ctrl_o.prng_reseed_rate.d); + assign manual_operation_o = hw2reg_ctrl_o.manual_operation.d; + +endmodule diff --git a/src/aes/rtl/aes_ghash.sv b/src/aes/rtl/aes_ghash.sv new file mode 100644 index 000000000..0250131ab --- /dev/null +++ b/src/aes/rtl/aes_ghash.sv @@ -0,0 +1,705 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES GHASH implementation for AES-GCM +// +// This module implements the GHASH core including hash state and hash key register required for +// AES-GCM. +// +// Details on the data formats +// --------------------------- +// +// The aes_core as well as the aes_cipher_core modules use 4-dimensional SystemVerilog arrays to +// represent AES states: +// +// logic [3:0][3:0][7:0] state_q [NumShares]; +// +// The fourth dimension (unpacked) corresponds to the different shares. The first element holds the +// (masked) data share whereas the other elements hold the masks (masked implementation only). +// The three packed dimensions correspond to the 128-bit state matrix per share. This +// implementation uses the same encoding as the Advanced Encryption Standard (AES) FIPS Publication +// 197 available at https://www.nist.gov/publications/advanced-encryption-standard-aes (see Section +// 3.4). An input sequence of 16 bytes (128-bit, left most byte is the first one) +// +// B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 +// +// is mapped to the state matrix as +// +// [ B0 B4 B8 B12 ] +// [ B1 B5 B9 B13 ] +// [ B2 B6 B10 B14 ] +// [ B3 B7 B11 B15 ] . +// +// In contrast, this implementation of the GHASH module uses 2-dimensional SystemVerilog arrays +// to represent bit strings: +// +// logic [127:0] hash_subkey_q [NumShares]; +// +// The second dimension (unpacked) corresponds to the different shares. The first element holds +// the (masked) data share whereas the other elements hold the masks (masked implementation only). +// The unpacked dimension corresponds to the 128-bit bit string per share. This implementation +// uses the same encoding as Recommendation for Block Cipher Modes of Operation: Galois/Counter +// Mode (GCM) and GMAC NIST Special Publication 800-38D available at +// https://csrc.nist.gov/pubs/sp/800/38/d/final (See Section 6.1) and as Advanced Encryption +// Standard (AES) FIPS Publication 197 available at +// https://www.nist.gov/publications/advanced-encryption-standard-aes (see Section 3.3). An input +// sequence of 128 bits (left most bit is the first one) +// +// b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 b10 b11 ... b125 b126 b127 +// +// is mapped to Bytes as follows +// +// B0 = {b0 b1 b2 b3 b4 b5 b6 b7 } +// B1 = {b8 b9 b10 b11 b12 b13 b14 b15 } +// . +// B15 = {b120 b121 b122 b123 b124 b125 b126 b127} . +// +// Internally, this is mapped to the 128-bit packed dimension of the SystemVerilog array as follows +// +// /-------- Byte 0 --------\ ... /-------- Byte 15 -------\ +// 128'b{ b0, b1, b2, ... b5, b6, b7, b8, b9, ..., b119, b120, ... b126, b127 } +// +// meaning the hexadecimal representations of these values can directly be compared with test vector +// data found in The Galois/Counter Mode of Operation (GCM) available at +// https://csrc.nist.rip/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf (See +// Appendix B). +// +// However, when interfacing the GF(2^128) multiplier, the bit order has to reversed to obtain +// packed 128-bit SystemVerilog arrays with the MSB left and the LSB right, i.e., +// +// 128'b{ b127, b126, ... b1, b0 } . +// +// The final authentication tag is put out via Data Out registers and uses again the above format +// +// MSB LSB +// - DATA_OUT_0 32'h{ B3 B2 B1 B0 } +// - DATA_OUT_1 32'h{ B7 B6 B5 B4 } +// - DATA_OUT_2 32'h{ B11 B10 B9 B8 } +// - DATA_OUT_3 32'h{ B15 B14 B13 B12 } +// +// Or in terms of bits +// MSB LSB +// - DATA_OUT_0 32'h = 32'h{ b24 b25 b26 b27 b28 b29 b30 b31 ... b0 b1 b2 b3 b4 b5 b6 b7 } +// - ... + +`include "caliptra_prim_assert.sv" + +module aes_ghash + import aes_pkg::*; + import aes_reg_pkg::*; +#( + parameter bit SecMasking = 1, + parameter int unsigned GFMultCycles = 32, + + localparam int NumShares = SecMasking ? 2 : 1 // derived parameter +) ( + input logic clk_i, + input logic rst_ni, + + // Input handshake signals + input sp2v_e in_valid_i, + output sp2v_e in_ready_o, + + // Output handshake signals + output sp2v_e out_valid_o, + input sp2v_e out_ready_i, + + // Control signals + input aes_op_e op_i, + input gcm_phase_e gcm_phase_i, + input logic [4:0] num_valid_bytes_i, + input sp2v_e load_hash_subkey_i, + input logic clear_i, + output logic first_block_o, + input logic alert_fatal_i, + output logic alert_o, + + // I/O data signals + input logic [GCMDegree-1:0] data_in_prev_i, // Ciphertext for decryption + // or AAD + input logic [NumRegsData-1:0][31:0] data_out_i, // Ciphertext for encryption + input logic [3:0][3:0][7:0] cipher_state_done_i [NumShares], // Masked cipher core output + output logic [NumRegsData-1:0][31:0] ghash_state_done_o +); + + // Signals + logic [GCMDegree-1:0] s_d; + logic [GCMDegree-1:0] s_q; + sp2v_e s_we; + logic [GCMDegree-1:0] corr_d [2]; + logic [GCMDegree-1:0] corr_q [2]; + sp2v_e corr_we; + logic [15:0][7:0] ghash_in; + logic [15:0][7:0] ghash_in_valid; + ghash_in_sel_e ghash_in_sel; + ghash_add_in_sel_e ghash_add_in_sel [2]; + logic [GCMDegree-1:0] ghash_state_d [NumShares]; + logic [GCMDegree-1:0] ghash_state_q [NumShares]; + logic [GCMDegree-1:0] ghash_state_restore [NumShares]; + logic [GCMDegree-1:0] ghash_state_add [NumShares]; + sp2v_e ghash_state_we [2]; + ghash_state_sel_e ghash_state_sel; + logic [GCMDegree-1:0] ghash_state_mult [NumShares]; + logic [GCMDegree-1:0] hash_subkey_d [NumShares]; + logic [GCMDegree-1:0] hash_subkey_q [NumShares]; + sp2v_e hash_subkey_we; + gf_mult_in_sel_e gf_mult1_in_sel; + logic [1:0] gf_mult_req; + logic [1:0] gf_mult_ack; + aes_ghash_e aes_ghash_ns, aes_ghash_cs; + logic first_block_d; + logic first_block_q; + logic final_add_d; + logic final_add_q; + logic advance; + + ////////////////////////////////// + // Input Data Format Conversion // + ////////////////////////////////// + // Covert the input data to the internal data format. + logic [GCMDegree-1:0] cipher_state_done [NumShares]; + logic [GCMDegree-1:0] data_in_prev; + logic [GCMDegree-1:0] data_out; + always_comb begin : data_in_conversion + for (int s = 0; s < NumShares; s++) begin + cipher_state_done[s] = aes_state_to_ghash_vec(cipher_state_done_i[s]); + end + data_in_prev = aes_state_to_ghash_vec(aes_transpose(data_in_prev_i)); + data_out = aes_state_to_ghash_vec(aes_transpose(data_out_i)); + end + + //////////////////// + // S = AES_K(J_0) // + //////////////////// + // The initial counter block J_0 encrypted using the encryption key K. For the unmasked + // implementation this is only used at the very end. + // + // For the masked implementaion, the shares of S are used multiple times in the form of + // correction terms throughout the entire computation (see separate section below for details). + // In addition, Share 1 of S only is again used at the very end. + // + // These registers can be cleared with pseudo-random data by loading the output of the cipher + // core after having cleared the internal state of the cipher core. + if (SecMasking) begin : gen_s1 + // Save Share 1 of S for later usage. + assign s_d = cipher_state_done[1]; + + end else begin : gen_s0 + // S comes in unmasked, simply save it. + assign s_d = cipher_state_done[0]; + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : s_reg + if (!rst_ni) begin + s_q <= '0; + end else if (s_we == SP2V_HIGH) begin + s_q <= s_d; + end + end + + ////////////////////// + // Correction Terms // + ////////////////////// + // For the masked implementation, three correction terms based on the Shares of S as well as on + // the Shares of the sub hashkey need to be added to various intermediate results. Two of these + // correction terms are added repeatedly. These are thus stored in dedicated registers. A third + // correction term is used only once, it is computed on demand. The following terms are needed: + // + // 1. (S0 * H0) + S0 -- Used for every block, computed during the initialization phase. + // 2. S0 * H1 -- Used for every block except for the first one, computed during the + // initialization phase. + // 3. S1 * H1 -- Used only for the first block and computed on demand. + // + // where S0 or S1 is Share 0 or Share 1 of S, respectively. Similarly, H0 or H1 is Share 0 or + // Share 1 of the hash subkey, respectively. + // + // These register can be cleared after pushing some pseudo-random data through the multipliers. + if (SecMasking) begin : gen_corr_terms + assign corr_d[0] = ghash_state_mult[0] ^ ghash_state_q[0]; + assign corr_d[1] = ghash_state_mult[1]; + + always_ff @(posedge clk_i or negedge rst_ni) begin : corr_reg + if (!rst_ni) begin + corr_q <= '{default: '0}; + end else if (corr_we == SP2V_HIGH) begin + corr_q <= corr_d; + end + end + end + + ///////////////// + // GHASH Input // + ///////////////// + // Select the ciphertext for encryption / decryption or S for the final authentication tag. + always_comb begin : ghash_in_mux + unique case (ghash_in_sel) + GHASH_IN_DATA_IN_PREV: ghash_in = data_in_prev; + GHASH_IN_DATA_OUT: ghash_in = data_out; + GHASH_IN_S: ghash_in = s_q; + default: ghash_in = data_out; + endcase + end + + // Mask invalid bytes. The least significant byte is mapped to Position 15 internally. See + // the section "Details on the data formats" in the header for details. + always_comb begin + for (int unsigned i = 0; i < 16; i++) begin + ghash_in_valid[15-i] = num_valid_bytes_i > i[4:0] ? ghash_in[15-i] : 8'b0; + end + end + + ///////////////// + // GHASH State // + ///////////////// + // Add the GHASH input or correction terms (masked implementation only) to the current state. + if (SecMasking) begin : gen_masked_add + logic [GCMDegree-1:0] add_in [NumShares]; + + // Depending on the which phase we are in, we either add the GHASH input, or some correction + // term to the GHASH state. The selection may vary between the two shares. + always_comb begin : add_in_mux0 + unique case (ghash_add_in_sel[0]) + ADD_IN_GHASH_IN: add_in[0] = ghash_in_valid; + ADD_IN_CORR_A: add_in[0] = corr_q[0]; + ADD_IN_CORR_B: add_in[0] = ghash_state_q[1]; + default: add_in[0] = ghash_in_valid; + endcase + end + + always_comb begin : add_in_mux1 + unique case (ghash_add_in_sel[1]) + ADD_IN_GHASH_IN: add_in[1] = ghash_in_valid; + ADD_IN_CORR_A: add_in[1] = corr_q[1]; + ADD_IN_CORR_B: add_in[1] = ghash_state_mult[1]; + default: add_in[1] = ghash_in_valid; + endcase + end + + // Perform the addition on a per-share basis. + for (genvar s = 0; s < NumShares; s++) begin : gen_state_add + assign ghash_state_add[s] = ghash_state_q[s] ^ add_in[s]; + end + + end else begin : gen_unmasked_add + + // Simply add the GHASH input to the current state. + assign ghash_state_add[0] = ghash_state_q[0] ^ ghash_in_valid; + end + + // For restoring a GHASH state, we overwrite Share 0 of the initialized GHASH state with the + // previously saved GHASH state in unmasked form. Share 1 is left untouched. This is identical to + // subtracing Share 1 of S which will be added again at the very end. To save muxing resources, + // Share 1 of the state multiplexer below is identical to the default. + // + // For the unmasked implementation, we add the previously saved GHASH state to the GHASH state + // previously initialized with S. S is then substracted again seperately. Doing this allows + // saving one multiplexer input. + if (SecMasking) begin : gen_ghash_state_restore_masked + assign ghash_state_restore[0] = data_in_prev; + assign ghash_state_restore[1] = ghash_state_add[1]; + end else begin : gen_ghash_state_restore_unmasked + assign ghash_state_restore[0] = ghash_state_add[0]; + end + + // We initialize the state with S. In case of the unmasked implementation, S has to be + // substracted in a second step to reach the required zero state. Doing it this way allows saving + // one multiplexer input. + always_comb begin : ghash_state_mux + unique case (ghash_state_sel) + GHASH_STATE_RESTORE: ghash_state_d = ghash_state_restore; + GHASH_STATE_INIT: ghash_state_d = cipher_state_done; + GHASH_STATE_ADD: ghash_state_d = ghash_state_add; + GHASH_STATE_MULT: ghash_state_d = ghash_state_mult; + default: ghash_state_d = ghash_state_add; + endcase + end + + // This register can be cleared with pseudo-random data by adding the output of the cipher core + // to the current state after having cleared the internal state of the cipher core. + for (genvar s = 0; s < NumShares; s++) begin : gen_ghash_state_reg_shares + always_ff @(posedge clk_i or negedge rst_ni) begin : ghash_state_reg + if (!rst_ni) begin + ghash_state_q[s] <= '0; + end else if (ghash_state_we[s] == SP2V_HIGH) begin + ghash_state_q[s] <= ghash_state_d[s]; + end + end + end + + ///////////////// + // Hash Subkey // + ///////////////// + // This register can be cleared with pseudo-random data by loading the output of the cipher + // core after having cleared the internal state of the cipher core. + assign hash_subkey_d = cipher_state_done; + always_ff @(posedge clk_i or negedge rst_ni) begin : hash_subkey_reg + if (!rst_ni) begin + hash_subkey_q <= '{default: '0}; + end else if (hash_subkey_we == SP2V_HIGH) begin + hash_subkey_q <= hash_subkey_d; + end + end + + ////////////////////////// + // GF(2^128) Multiplier // + ////////////////////////// + logic [GCMDegree-1:0] gf_mult_op_a[NumShares]; + logic [GCMDegree-1:0] gf_mult_prod[NumShares]; + + // The first multiplier has no muxes on the operand inputs. + assign gf_mult_op_a[0] = ghash_state_q[0]; + + if (SecMasking) begin : gen_gf_mult_s1_mux + // The second multiplier is used to multiply Share 0, Share 1 (first block only) of + // the state, and also Share 1 of S with Share 1 of the hash subkey. + always_comb begin : gf_mult1_in_mux + unique case (gf_mult1_in_sel) + MULT_IN_STATE0: gf_mult_op_a[1] = ghash_state_q[0]; + MULT_IN_STATE1: gf_mult_op_a[1] = ghash_state_q[1]; + MULT_IN_S1: gf_mult_op_a[1] = s_q; + default: gf_mult_op_a[1] = ghash_state_q[0]; + endcase + end + end + + for (genvar s = 0; s < NumShares; s++) begin : gen_gf_mult + caliptra_prim_gf_mult #( + .Width (GCMDegree), + .StagesPerCycle(GCMDegree / GFMultCycles), + .IPoly (GCMIPoly) + ) u_gf_mult ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .req_i(gf_mult_req[s]), + .ack_o(gf_mult_ack[s]), + + .operand_a_i(aes_ghash_reverse_bit_order(gf_mult_op_a[s])), // The A input is scanned. + .operand_b_i(aes_ghash_reverse_bit_order(hash_subkey_q[s])), // The B input is not scanned. + + .prod_o(gf_mult_prod[s]) + ); + assign ghash_state_mult[s] = aes_ghash_reverse_bit_order(gf_mult_prod[s]); + end + + if (!SecMasking) begin : gen_tie_offs + // Tie-off datapath signals unused for the unmasked implementation. + logic [GCMDegree-1:0] unused_corr_q [2]; + sp2v_e unused_corr_we; + assign corr_d = '{default: '0}; + assign corr_q = corr_d; + assign unused_corr_q = corr_q; + assign unused_corr_we = corr_we; + + logic unused_ghash_add_in_sel; + assign unused_ghash_add_in_sel = ^{{ghash_add_in_sel[0]}, {ghash_add_in_sel[1]}}; + + sp2v_e unused_ghash_state_we; + assign unused_ghash_state_we = ghash_state_we[1]; + + gf_mult_in_sel_e unused_gf_mult1_in_sel; + assign unused_gf_mult1_in_sel = gf_mult1_in_sel; + + logic unused_gf_mult_req; + assign unused_gf_mult_req = gf_mult_req[1]; + assign gf_mult_ack[1] = 1'b1; + end + + ///////////////// + // Control FSM // + ///////////////// + + always_comb begin : aes_ghash_fsm + + // Handshake signals + in_ready_o = SP2V_LOW; + out_valid_o = SP2V_LOW; + + // Data path + s_we = SP2V_LOW; + corr_we = SP2V_LOW; + + ghash_in_sel = GHASH_IN_DATA_OUT; + + ghash_add_in_sel[0] = ADD_IN_GHASH_IN; + ghash_add_in_sel[1] = ADD_IN_GHASH_IN; + + ghash_state_sel = GHASH_STATE_ADD; + ghash_state_we[0] = SP2V_LOW; + ghash_state_we[1] = SP2V_LOW; + + hash_subkey_we = SP2V_LOW; + + gf_mult1_in_sel = MULT_IN_STATE0; + gf_mult_req = '0; + + // FSM + aes_ghash_ns = aes_ghash_cs; + first_block_d = first_block_q; + final_add_d = final_add_q; + advance = 1'b0; + + // Alert + alert_o = 1'b0; + + unique case (aes_ghash_cs) + GHASH_IDLE: begin + in_ready_o = SP2V_HIGH; + if (in_valid_i == SP2V_HIGH) begin + if (clear_i) begin + // Clearing has highest priority. In case of the masked implementation, we clear the + // state using the initial state (the cipher core output, for which both shares are + // random at this point). For the unmasked implementation, we use the unmasked cipher + // core output. + s_we = SP2V_HIGH; + ghash_state_sel = SecMasking ? GHASH_STATE_INIT : GHASH_STATE_ADD; + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + hash_subkey_we = SP2V_HIGH; + first_block_d = 1'b1; + final_add_d = 1'b0; + + // In case of the masked implementation, also the correction terms need to be cleared. + // This can be done by using the multipliers. + aes_ghash_ns = SecMasking ? GHASH_MASKED_INIT : aes_ghash_cs; + + end else if (gcm_phase_i == GCM_INIT) begin + if (load_hash_subkey_i == SP2V_HIGH) begin + + // Load the hash subkey. + hash_subkey_we = SP2V_HIGH; + end else begin + + // Load S and initialize the state with S. + s_we = SP2V_HIGH; + ghash_state_sel = GHASH_STATE_INIT; + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + first_block_d = 1'b1; + + // We have now all pre-requisites to compute the correction terms for the masked + // implementation. For the unmasked implementation, we now have to subtract S again + // from the state. Doing it this way allows saving one multiplexer input. + aes_ghash_ns = SecMasking ? GHASH_MASKED_INIT : GHASH_ADD_S; + end + + end else if (gcm_phase_i == GCM_RESTORE) begin + // Restore a previously loaded GHASH state. We overwrite the Share 0 of the GHASH + // state and leave Share 1 untouched. For the masked implementation, this is equal to + // subtracting Share 1 of S. It is only added at the very end (or when saving the GHASH + // state). + ghash_state_sel = GHASH_STATE_RESTORE; + ghash_state_we[0] = SP2V_HIGH; + first_block_d = 1'b0; + + // For the unmasked implementation, the previously restored GHASH state is added to the + // GHASH state initialized with S, meaning S needs to be subtracted again to continue. + ghash_in_sel = !SecMasking ? GHASH_IN_DATA_IN_PREV : GHASH_IN_DATA_OUT; + aes_ghash_ns = !SecMasking ? GHASH_ADD_S : GHASH_IDLE; + + end else if (gcm_phase_i == GCM_AAD || + gcm_phase_i == GCM_TEXT || + gcm_phase_i == GCM_TAG) begin + // Select the proper input for the addition. + ghash_in_sel = + (gcm_phase_i == GCM_AAD) ? GHASH_IN_DATA_IN_PREV : + (gcm_phase_i == GCM_TEXT && op_i == AES_DEC) ? GHASH_IN_DATA_IN_PREV : + (gcm_phase_i == GCM_TEXT && op_i == AES_ENC) ? GHASH_IN_DATA_OUT : + (gcm_phase_i == GCM_TAG) ? GHASH_IN_DATA_IN_PREV : + GHASH_IN_DATA_OUT; + + // Add the current input to the GHASH state to start the multiplication afterwards. + // Only for the first block both shares of the GHASH state need to be updated. + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = first_block_q ? SP2V_HIGH : SP2V_LOW; + + // Start the multiplication. In case masking is enabled and we've already done the + // first block, we have to do one more addtion first. + aes_ghash_ns = + SecMasking && !first_block_q ? GHASH_MASKED_ADD_STATE_SHARES : GHASH_MULT; + + end else if (gcm_phase_i == GCM_SAVE) begin + // Get ready to output the current GHASH state. + + // For the masked implementation, first unmask the GHASH state and then add Share 1 of + // S. For the unmasked implementation, add S directly. + final_add_d = 1'b1; + aes_ghash_ns = SecMasking ? GHASH_MASKED_ADD_STATE_SHARES : GHASH_ADD_S; + + end else begin + // Handshake without a valid command. We should never get here. If we do (e.g. via a + // malicious glitch), error out immediately. + aes_ghash_ns = GHASH_ERROR; + end + end + end + + GHASH_MASKED_INIT: begin + // Compute repeatedly used correction terms (masked implementation only). We need: + // + // 1. (S0 * H0) + S0 + // 2. S0 * H1 + // + // S0 and S1 have been loaded into the GHASH state registers previsously. + gf_mult1_in_sel = MULT_IN_STATE0; + gf_mult_req = 2'b11; + if (&gf_mult_ack) begin + corr_we = SP2V_HIGH; + aes_ghash_ns = GHASH_IDLE; + end + end + + GHASH_MASKED_ADD_STATE_SHARES: begin + // Add both shares of the GHASH state and store the result in Share 0. + ghash_add_in_sel[0] = ADD_IN_CORR_B; + ghash_state_sel = GHASH_STATE_ADD; + ghash_state_we[0] = SP2V_HIGH; + + // We need to add Share 1 of S next, in case we're saving the context or producing the + // final authentication tag. + final_add_d = 1'b0; + aes_ghash_ns = ((gcm_phase_i == GCM_SAVE) || + (gcm_phase_i == GCM_TAG)) && final_add_q ? GHASH_ADD_S : GHASH_MULT; + end + + GHASH_MULT: begin + // Perform the multiplication and update the state. + gf_mult1_in_sel = first_block_q ? MULT_IN_STATE1 : MULT_IN_STATE0; + gf_mult_req = 2'b11; + if (&gf_mult_ack) begin + ghash_state_sel = GHASH_STATE_MULT; + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + first_block_d = SecMasking ? first_block_q : 1'b0; + aes_ghash_ns = SecMasking ? GHASH_MASKED_ADD_CORR : + (gcm_phase_i == GCM_TAG) ? GHASH_ADD_S : GHASH_IDLE; + end + end + + GHASH_MASKED_ADD_CORR: begin + // Add the proper correction terms to both state shares. + ghash_add_in_sel[0] = ADD_IN_CORR_A; + ghash_add_in_sel[1] = ADD_IN_CORR_A; + + if (first_block_q) begin + // When doing the first block only, we need to compute another correction term using the + // second multiplier only, i.e., S1 * H1. + ghash_add_in_sel[1] = ADD_IN_CORR_B; + gf_mult1_in_sel = MULT_IN_S1; + gf_mult_req[1] = 1'b1; + if (gf_mult_ack[1]) begin + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + first_block_d = 1'b0; + advance = 1'b1; + end + end else begin + // We don't have to do another multiplication. + advance = 1'b1; + + // Note: Share 0 of the state now depends on Share 0 of the hash subkey. Thus, we don't + // forward it to the second multiplier as this may lead to undesirable SCA leakage in the + // multiplier. + gf_mult1_in_sel = MULT_IN_S1; + + // Add the previously computed correction terms. + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + end + + // In case we're producing the final authentication tag, we have to unmask the state next. + if (advance) begin + if (gcm_phase_i == GCM_TAG) begin + final_add_d = 1'b1; + aes_ghash_ns = GHASH_MASKED_ADD_STATE_SHARES; + end else begin + aes_ghash_ns = GHASH_IDLE; + end + end + end + + GHASH_ADD_S: begin + // Add S to the GHASH state and then get ready to output the final tag or return to the + // idle state in case this state has been reached as part of an initialization or state + // restore operation. + ghash_in_sel = GHASH_IN_S; + ghash_state_we[0] = SP2V_HIGH; + aes_ghash_ns = ((gcm_phase_i == GCM_INIT) || + (gcm_phase_i == GCM_RESTORE)) ? GHASH_IDLE : GHASH_OUT; + end + + GHASH_OUT: begin + // Perform output handshake and clear all internal state with pseudo-random data. + out_valid_o = SP2V_HIGH; + if (out_ready_i == SP2V_HIGH) begin + s_we = SP2V_HIGH; + ghash_state_sel = SecMasking ? GHASH_STATE_INIT : GHASH_STATE_ADD; + ghash_state_we[0] = SP2V_HIGH; + ghash_state_we[1] = SP2V_HIGH; + hash_subkey_we = SP2V_HIGH; + aes_ghash_ns = SecMasking ? GHASH_MASKED_INIT : GHASH_IDLE; + end + end + + GHASH_ERROR: begin + // Terminal error state + alert_o = 1'b1; + end + + // We should never get here. If we do (e.g. via a malicious glitch), error out immediately. + default: begin + aes_ghash_ns = GHASH_ERROR; + alert_o = 1'b1; + end + endcase + + // Unconditionally jump into the terminal error state if a fatal alert has been triggered. + if (alert_fatal_i) begin + aes_ghash_ns = GHASH_ERROR; + end + end + + // SEC_CM: GHASH.FSM.SPARSE + `CALIPTRA_PRIM_FLOP_SPARSE_FSM(u_state_regs, aes_ghash_ns, + aes_ghash_cs, aes_ghash_e, GHASH_IDLE) + + always_ff @(posedge clk_i or negedge rst_ni) begin : fsm_reg + if (!rst_ni) begin + first_block_q <= 1'b0; + end else begin + first_block_q <= first_block_d; + end + end + + if (SecMasking) begin : gen_fsm_reg_masked + always_ff @(posedge clk_i or negedge rst_ni) begin : fsm_reg_masked + if (!rst_ni) begin + final_add_q <= 1'b0; + end else begin + final_add_q <= final_add_d; + end + end + end else begin : gen_no_fsm_reg + // Tie-off unused FSM signals. + logic unused_final_add_d; + assign final_add_q = 1'b0; + assign unused_final_add_d = final_add_d; + + logic unused_advance; + assign unused_advance = advance; + end + + ///////////// + // Outputs // + ///////////// + + // Moving to GCM_SAVE is only allowed after having done the first block. + assign first_block_o = first_block_q; + + // Covert the output data from the internal data format to the output format. + always_comb begin : data_out_conversion + ghash_state_done_o = aes_transpose(aes_state_to_ghash_vec(ghash_state_q[0])); + end + +endmodule diff --git a/src/aes/rtl/aes_key_expand.sv b/src/aes/rtl/aes_key_expand.sv index 3b94592f1..57692e3ef 100644 --- a/src/aes/rtl/aes_key_expand.sv +++ b/src/aes/rtl/aes_key_expand.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -6,9 +6,7 @@ `include "caliptra_prim_assert.sv" -module aes_key_expand - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_key_expand import aes_pkg::*; #( parameter bit AES192Enable = 1, parameter bit SecMasking = 0, @@ -21,6 +19,7 @@ module aes_key_expand input logic cfg_valid_i, input ciph_op_e op_i, input sp2v_e en_i, + input logic prd_we_i, output sp2v_e out_req_o, input sp2v_e out_ack_i, input logic clear_i, @@ -49,6 +48,7 @@ module aes_key_expand logic [31:0] rot_word_in [NumShares]; logic [31:0] rot_word_out [NumShares]; logic use_rot_word; + logic prd_we, prd_we_force, prd_we_inhibit; logic [31:0] sub_word_in, sub_word_out; logic [3:0] sub_word_out_req; logic [31:0] sw_in_mask, sw_out_mask; @@ -207,17 +207,54 @@ module aes_key_expand assign sw_in_mask = use_rot_word ? rot_word_out[1] : rot_word_in[1]; end + // Make sure that whenever the data/mask inputs of the S-Boxes update, the buffered PRD is + // updated in sync. There are two special cases we need to handle here: + // - For AES-256, the initial round is short (no round key computation). But the data/mask inputs + // are updated either way. Thus, we need to force a PRD update as well. + // - For AES-192 in FWD mode, the data/mask inputs aren't updated in Round 1, 4, 7 and 10. Thus, + // we need to inhibit PRD updates triggred at the end of Round 0, 3, 6 and 9. + assign prd_we_force = (key_len_i == AES_256) & (rnd == 0); + assign prd_we_inhibit = (key_len_i == AES_192) & (op_i == CIPH_FWD) & + (rnd == 0 || rnd == 3 || rnd == 6 || rnd == 9); + assign prd_we = (prd_we_i & ~prd_we_inhibit) | prd_we_force; + + // PRD buffering + logic [WidthPRDKey-1:0] prd_q; + + if (!SecMasking) begin : gen_no_prd_buffer + // The masks are ignored anyway. + assign prd_q = prd_i; + + // Tie-off unused signals. + logic unused_prd_we; + assign unused_prd_we = prd_we; + + end else begin : gen_prd_buffer + // PRD buffer stage to: + // 1. Make sure the S-Boxes get always presented new data/mask inputs together with fresh PRD + // for remasking. + // 2. Prevent glitches originating from inside the masking PRNG from propagating into the + // masked S-Boxes. + always_ff @(posedge clk_i or negedge rst_ni) begin : prd_reg + if (!rst_ni) begin + prd_q <= '0; + end else if (prd_we) begin + prd_q <= prd_i; + end + end + end + // SubWord - individually substitute bytes. // Every DOM S-Box instance consumes 28 bits of randomness but itself produces 20 bits for use in - // another S-Box instance. For other S-Box implementations, only the bits corresponding to prd_i + // another S-Box instance. For other S-Box implementations, only the bits corresponding to prd_q // are used. Other bits are ignored and tied to 0. logic [3:0][WidthPRDSBox+19:0] in_prd; logic [3:0] [19:0] out_prd; for (genvar i = 0; i < 4; i++) begin : gen_sbox // Rotate the randomness produced by the S-Boxes. The LSBs are taken from the masking PRNG - // (prd_i) whereas the MSBs are produced by the other S-Box instances. - assign in_prd[i] = {out_prd[aes_rot_int(i,4)], prd_i[WidthPRDSBox*i +: WidthPRDSBox]}; + // (prd_q) whereas the MSBs are produced by the other S-Box instances. + assign in_prd[i] = {out_prd[aes_rot_int(i,4)], prd_q[WidthPRDSBox*i +: WidthPRDSBox]}; aes_sbox #( .SecSBoxImpl ( SecSBoxImpl ) diff --git a/src/aes/rtl/aes_mix_columns.sv b/src/aes/rtl/aes_mix_columns.sv index 35ad8c235..d2c555907 100644 --- a/src/aes/rtl/aes_mix_columns.sv +++ b/src/aes/rtl/aes_mix_columns.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -10,7 +10,6 @@ module aes_mix_columns ( output logic [3:0][3:0][7:0] data_o ); - import aes_reg_pkg::*; import aes_pkg::*; // Transpose to operate on columns diff --git a/src/aes/rtl/aes_mix_single_column.sv b/src/aes/rtl/aes_mix_single_column.sv index 23c2ac67c..6b7cfd1f5 100644 --- a/src/aes/rtl/aes_mix_single_column.sv +++ b/src/aes/rtl/aes_mix_single_column.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -13,7 +13,6 @@ module aes_mix_single_column ( output logic [3:0][7:0] data_o ); - import aes_reg_pkg::*; import aes_pkg::*; logic [3:0][7:0] x; diff --git a/src/aes/rtl/aes_pkg.sv b/src/aes/rtl/aes_pkg.sv index 1ec439032..5afbb1a62 100644 --- a/src/aes/rtl/aes_pkg.sv +++ b/src/aes/rtl/aes_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -19,6 +19,9 @@ parameter int unsigned SliceSizeCtr = 16; parameter int unsigned NumSlicesCtr = aes_reg_pkg::NumRegsIv * 32 / SliceSizeCtr; parameter int unsigned SliceIdxWidth = caliptra_prim_util_pkg::vbits(NumSlicesCtr); +// In GCM, the counter performs inc32() instead of inc128(), i.e., the counter wraps at 32 bits. +parameter int unsigned SliceIdxMaxInc32 = 32 / SliceSizeCtr - 1; + // Widths of signals carrying pseudo-random data for clearing parameter int unsigned WidthPRDClearing = 64; parameter int unsigned NumChunksPRDClearing128 = 128/WidthPRDClearing; @@ -32,8 +35,6 @@ parameter int unsigned WidthPRDData = 16*WidthPRDSBox; // 16 S-Boxes for the parameter int unsigned WidthPRDKey = 4*WidthPRDSBox; // 4 S-Boxes for the key expand parameter int unsigned WidthPRDMasking = WidthPRDData + WidthPRDKey; -parameter int unsigned ChunkSizePRDMasking = WidthPRDMasking/5; - // Clearing PRNG default LFSR seed and permutation // These LFSR parameters have been generated with // $ util/design/gen-lfsr-seed.py --width 64 --seed 31468618 --prefix "Clearing" @@ -51,15 +52,12 @@ parameter clearing_lfsr_perm_t RndCnstClearingSharePermDefault = { 256'h9736b95ac3f3b5205caf8dc536aad73605d393c8dd94476e830e97891d4828d0 }; -// Masking PRNG default LFSR seed and permutation -// We use a single seed that is split down into chunks internally. +// Masking PRNG default state seed and output permutation +// The output width is 160 bits (WidthPRDMasking = WidthPRDSBox * (16 + 4)). // These LFSR parameters have been generated with // $ util/design/gen-lfsr-seed.py --width 160 --seed 31468618 --prefix "Masking" parameter int MaskingLfsrWidth = 160; // = WidthPRDMasking = WidthPRDSBox * (16 + 4) -typedef logic [MaskingLfsrWidth-1:0] masking_lfsr_seed_t; typedef logic [MaskingLfsrWidth-1:0][$clog2(MaskingLfsrWidth)-1:0] masking_lfsr_perm_t; -parameter masking_lfsr_seed_t RndCnstMaskingLfsrSeedDefault = - 160'hc132b5723c5a4cf4743b3c7c32d580f74f1713a; parameter masking_lfsr_perm_t RndCnstMaskingLfsrPermDefault = { 256'h17261943423e4c5c03872194050c7e5f8497081d96666d406f4b606473303469, 256'h8e7c721c8832471f59919e0b128f067b25622768462e554d8970815d490d7f44, @@ -67,6 +65,15 @@ parameter masking_lfsr_perm_t RndCnstMaskingLfsrPermDefault = { 256'h4f785b772b352f6550613c58130a8b104a3f28019c9a380233956b00563a512c, 256'h808d419d63982a16995e0e3b57826a36718a9329452492533d83115a75316e15 }; +// The state width is 177 bits (Bivium) but the primitive expects a 288-bit seed (Trivium). +// These LFSR parameters have been generated with +// $ util/design/gen-lfsr-seed.py --width 288 --seed 31468618 --prefix "Masking" +parameter int MaskingPrngStateWidth = 288; +typedef logic [MaskingPrngStateWidth-1:0] masking_lfsr_seed_t; +parameter masking_lfsr_seed_t RndCnstMaskingLfsrSeedDefault = { + 32'h758a4420, + 256'h31e1c461_6ea343ec_153282a3_0c132b57_23c5a4cf_4743b3c7_c32d580f_74f1713a +}; typedef enum logic [31:0] { SBoxImplLut, // Unmasked LUT-based S-Box @@ -79,12 +86,26 @@ typedef enum logic [31:0] { // see aes_sbox_canright_dom.sv } sbox_impl_e; +// GF(2^128) irreducible, field-generating polynomial for AES-GCM +// See Section "6.3 Multiplication Operation on Blocks" of +// https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf on Page 11: +// "Let R be the bit string 11100001 || 0^120." +// And further on Page 12: +// "The reduction modulus is the polynomial of degree 128 that corresponds to R || 1" +// Or in other words: x^128 + x^7 + x^2 + x + 1 +// The MSB gets clipped off below. +parameter int unsigned GCMDegree = 128; +parameter bit [GCMDegree-1:0] GCMIPoly = GCMDegree'(1'b1) << 7 | + GCMDegree'(1'b1) << 2 | + GCMDegree'(1'b1) << 1 | + GCMDegree'(1'b1) << 0; // Parameters used for controlgroups in the coverage parameter int AES_OP_WIDTH = 2; parameter int AES_MODE_WIDTH = 6; parameter int AES_KEYLEN_WIDTH = 3; parameter int AES_PRNGRESEEDRATE_WIDTH = 3; +parameter int AES_GCMPHASE_WIDTH = 6; // SEC_CM: MAIN.CONFIG.SPARSE typedef enum logic [AES_OP_WIDTH-1:0] { @@ -99,9 +120,11 @@ typedef enum logic [AES_MODE_WIDTH-1:0] { AES_CFB = 6'b00_0100, AES_OFB = 6'b00_1000, AES_CTR = 6'b01_0000, - AES_NONE = 6'b10_0000 + AES_GCM = 6'b10_0000, + AES_NONE = 6'b11_1111 } aes_mode_e; +// SEC_CM: MAIN.CONFIG.SPARSE typedef enum logic [AES_OP_WIDTH-1:0] { CIPH_FWD = 2'b01, CIPH_INV = 2'b10 @@ -122,6 +145,16 @@ typedef enum logic [AES_PRNGRESEEDRATE_WIDTH-1:0] { } prs_rate_e; parameter int unsigned BlockCtrWidth = 13; +// SEC_CM: GCM.CONFIG.SPARSE +typedef enum logic [AES_GCMPHASE_WIDTH-1:0] { + GCM_INIT = 6'b00_0001, + GCM_RESTORE = 6'b00_0010, + GCM_AAD = 6'b00_0100, + GCM_TEXT = 6'b00_1000, + GCM_SAVE = 6'b01_0000, + GCM_TAG = 6'b10_0000 +} gcm_phase_e; + typedef struct packed { logic [31:7] unused; logic alert_fatal_fault; @@ -216,7 +249,7 @@ typedef struct packed { typedef enum logic [CtrlStateWidth-1:0] { CTRL_IDLE = 6'b001001, CTRL_LOAD = 6'b100011, - CTRL_PRNG_UPDATE = 6'b111101, + CTRL_GHASH_READY = 6'b111101, CTRL_PRNG_RESEED = 6'b010000, CTRL_FINISH = 6'b100100, CTRL_CLEAR_I = 6'b111010, @@ -224,6 +257,37 @@ typedef struct packed { CTRL_ERROR = 6'b010111 } aes_ctrl_e; +// Encoding generated with: +// $ ./util/design/sparse-fsm-encode.py -d 3 -m 8 -n 6 \ +// -s 31468618 --language=sv +// +// Hamming distance histogram: +// +// 0: -- +// 1: -- +// 2: -- +// 3: |||||||||||||||||||| (57.14%) +// 4: ||||||||||||||| (42.86%) +// 5: -- +// 6: -- +// +// Minimum Hamming distance: 3 +// Maximum Hamming distance: 4 +// Minimum Hamming weight: 1 +// Maximum Hamming weight: 5 +// +localparam int GhashStateWidth = 6; +typedef enum logic [GhashStateWidth-1:0] { + GHASH_IDLE = 6'b101001, + GHASH_MULT = 6'b010000, + GHASH_ADD_S = 6'b111110, + GHASH_OUT = 6'b011101, + GHASH_ERROR = 6'b110011, + GHASH_MASKED_INIT = 6'b001010, + GHASH_MASKED_ADD_STATE_SHARES = 6'b000111, + GHASH_MASKED_ADD_CORR = 6'b100100 +} aes_ghash_e; + // Generic, sparse mux selector encodings // Encoding generated with: @@ -295,6 +359,35 @@ typedef enum logic [Mux4SelWidth-1:0] { MUX4_SEL_3 = 5'b10111 } mux4_sel_e; +// Encoding generated with: +// $ ./util/design/sparse-fsm-encode.py -d 3 -m 5 -n 6 \ +// -s 31468618 --language=sv +// +// Hamming distance histogram: +// +// 0: -- +// 1: -- +// 2: -- +// 3: |||||||||||||||||||| (50.00%) +// 4: |||||||||||||||| (40.00%) +// 5: |||| (10.00%) +// 6: -- +// +// Minimum Hamming distance: 3 +// Maximum Hamming distance: 5 +// Minimum Hamming weight: 1 +// Maximum Hamming weight: 5 +// +localparam int Mux5SelWidth = 6; +typedef enum logic [Mux5SelWidth-1:0] { + MUX5_SEL_0 = 6'b110000, + MUX5_SEL_1 = 6'b001000, + MUX5_SEL_2 = 6'b000011, + MUX5_SEL_3 = 6'b011101, + MUX5_SEL_4 = 6'b111110 +} mux5_sel_e; + + // $ ./sparse-fsm-encode.py -d 3 -m 6 -n 6 \ // -s 31468618 --language=sv // @@ -419,6 +512,46 @@ typedef enum logic [AddSOSelWidth-1:0] { ADD_SO_DIP = MUX3_SEL_2 } add_so_sel_e; +parameter int GHashInSelNum = 3; +parameter int GHashInSelWidth = Mux3SelWidth; +typedef enum logic [GHashInSelWidth-1:0] { + GHASH_IN_DATA_IN_PREV = MUX3_SEL_0, + GHASH_IN_DATA_OUT = MUX3_SEL_1, + GHASH_IN_S = MUX3_SEL_2 +} ghash_in_sel_e; + +parameter int GHashAddInSelNum = 3; +parameter int GHashAddInSelWidth = Mux3SelWidth; +typedef enum logic [GHashAddInSelWidth-1:0] { + ADD_IN_GHASH_IN = MUX3_SEL_0, + ADD_IN_CORR_A = MUX3_SEL_1, + ADD_IN_CORR_B = MUX3_SEL_2 +} ghash_add_in_sel_e; + +parameter int GHashStateSelNum = 4; +parameter int GHashStateSelWidth = Mux4SelWidth; +typedef enum logic [GHashStateSelWidth-1:0] { + GHASH_STATE_RESTORE = MUX4_SEL_0, + GHASH_STATE_INIT = MUX4_SEL_1, + GHASH_STATE_ADD = MUX4_SEL_2, + GHASH_STATE_MULT = MUX4_SEL_3 +} ghash_state_sel_e; + +parameter int GFMultS1SelNum = 3; +parameter int GFMultS1SelWidth = Mux3SelWidth; +typedef enum logic [GFMultS1SelWidth-1:0] { + MULT_IN_STATE0 = MUX3_SEL_0, + MULT_IN_STATE1 = MUX3_SEL_1, + MULT_IN_S1 = MUX3_SEL_2 +} gf_mult_in_sel_e; + +parameter int DataOutSelNum = 2; +parameter int DataOutSelWidth = Mux2SelWidth; +typedef enum logic [DataOutSelWidth-1:0] { + DATA_OUT_CIPHER = MUX2_SEL_0, + DATA_OUT_GHASH = MUX2_SEL_1 +} data_out_sel_e; + // Sparse two-value signal type sp2v_e parameter int Sp2VNum = 2; parameter int Sp2VWidth = Mux2SelWidth; @@ -449,6 +582,12 @@ parameter ctrl_reg_t CTRL_RESET = '{ operation: aes_op_e'(aes_reg_pkg::AES_CTRL_SHADOWED_OPERATION_RESVAL) }; +// GCM control register type +typedef struct packed { + logic [4:0] num_valid_bytes; + gcm_phase_e phase; +} ctrl_gcm_reg_t; + // Multiplication by {02} (i.e. x) on GF(2^8) // with field generating polynomial {01}{1b} (9'h11b) // Sometimes also denoted by xtime(). @@ -509,6 +648,28 @@ function automatic logic [3:0][3:0][7:0] aes_transpose(logic [3:0][3:0][7:0] in) return transpose; endfunction +// Convert AES byte state matrix to internal GHASH bit vector representation. +function automatic logic [127:0] aes_state_to_ghash_vec(logic [3:0][3:0][7:0] in); + logic [127:0] out; + logic [15:0][7:0] byte_vec; + for (int i = 0; i < 4; i++) begin + for (int j = 0; j < 4; j++) begin + byte_vec[15 - 4*i - j] = in[j][i]; + end + end + out = byte_vec; + return out; +endfunction + +// Convert internal GHASH bit vector representation to simple bit vector. +function automatic logic [127:0] aes_ghash_reverse_bit_order(logic [127:0] in); + logic [127:0] out; + for (int i = 0; i < 128; i++) begin + out[i] = in[127-i]; + end + return out; +endfunction + // Extract single column from state matrix function automatic logic [3:0][7:0] aes_col_get(logic [3:0][3:0][7:0] in, logic [1:0] idx); logic [3:0][7:0] out; @@ -550,12 +711,11 @@ endfunction // The masking PRNG is used for generating both the PRD for the S-Boxes/SubBytes operation as // well as for the input data masks. When using any of the masked Canright S-Box implementations, // it is important that the SubBytes input masks (generated by the PRNG in Round X-1) and the -// SubBytes output masks (generated by the PRNG in Round X) are independent. Inside the PRNG, -// this is achieved by using multiple, separately re-seeded LFSR chunks and by selecting the -// separate LFSR chunks in alternating fashion. Since the input data masks become the SubBytes -// input masks in the first round, we select the same 8 bit lanes for the input data masks which -// are also used to form the SubBytes output mask for the masked Canright S-Box implementations, -// i.e., the 8 LSBs of the per S-Box PRD. In particular, we have: +// SubBytes output masks (generated by the PRNG in Round X) are independent. This can be achieved +// by using e.g. an unrolled Bivium stream cipher primitive inside the PRNG. Since the input data +// masks become the SubBytes input masks in the first round, we select the same 8 bit lanes for the +// input data masks which are also used to form the SubBytes output mask for the masked Canright +// S-Box implementations, i.e., the 8 LSBs of the per S-Box PRD. In particular, we have: // // prng_output = { prd_key_expand, ... , sb_prd[4], sb_out_mask[4], sb_prd[0], sb_out_mask[0] } // @@ -565,7 +725,7 @@ endfunction // // When using a masked S-Box implementation other than Canright, we still select the 8 LSBs of // the per-S-Box PRD to form the input data mask of the corresponding byte. We do this to -// distribute the input data masks over all LFSR chunks of the masking PRNG. +// distribute the input data masks over all output bits the masking PRNG. // For one row of the state matrix, extract the 8 LSBs of the per-S-Box PRD from the PRNG output. // These bits are used as: diff --git a/src/aes/rtl/aes_prng_clearing.sv b/src/aes/rtl/aes_prng_clearing.sv new file mode 100644 index 000000000..c65631286 --- /dev/null +++ b/src/aes/rtl/aes_prng_clearing.sv @@ -0,0 +1,165 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES low-bandwidth pseudo-random number generator for register clearing +// +// This module uses an LFSR followed by an aligned permutation, a non-linear layer (PRINCE S-Boxes) +// and another permutation to generate pseudo-random data for the AES module for clearing +// registers (secure wipe). The LFSR can be reseeded using an external interface. + +`include "caliptra_prim_assert.sv" + +module aes_prng_clearing import aes_pkg::*; +#( + parameter int unsigned Width = 64, // At the moment we just support a width of 64. + parameter int unsigned EntropyWidth = edn_pkg::ENDPOINT_BUS_WIDTH, + parameter bit SecSkipPRNGReseeding = 0, // The current SCA setup doesn't provide + // sufficient resources to implement the + // infrastructure required for PRNG reseeding. + // To enable SCA resistance evaluations, we + // need to skip reseeding requests. + parameter clearing_lfsr_seed_t RndCnstLfsrSeed = RndCnstClearingLfsrSeedDefault, + parameter clearing_lfsr_perm_t RndCnstLfsrPerm = RndCnstClearingLfsrPermDefault, + parameter clearing_lfsr_perm_t RndCnstSharePerm = RndCnstClearingSharePermDefault +) ( + input logic clk_i, + input logic rst_ni, + + // Connections to AES internals, PRNG consumers + input logic data_update_i, + output logic [Width-1:0] data_o [NumSharesKey], + input logic reseed_req_i, + output logic reseed_ack_o, + + // Connections to outer world, LFSR re-seed + output logic entropy_req_o, + input logic entropy_ack_i, + input logic [EntropyWidth-1:0] entropy_i +); + + logic seed_valid; + logic seed_en; + logic [Width-1:0] seed; + logic lfsr_en; + logic [Width-1:0] lfsr_state; + + // The data requests are fed from an LFSR. Reseed requests take precedence internally to the + // LFSR. If there is an outstanding reseed request, the PRNG can keep updating and providing + // pseudo-random data (using the old seed). If the reseeding is taking place, the LFSR will + // provide fresh pseudo-random data (the new seed) in the next cycle anyway. This means the PRNG + // is always ready to provide new pseudo-random data. + + // In the current SCA setup, we don't have sufficient resources to implement the infrastructure + // required for PRNG reseeding (CSRNG, EDN, etc.). Therefore, we skip any reseeding requests if + // the SecSkipPRNGReseeding parameter is set. Performing the reseeding without proper entropy + // provided from CSRNG would result in quickly repeating, fully deterministic PRNG output, + // which prevents meaningful SCA resistance evaluations. + + // Create a lint error to reduce the risk of accidentally enabling this feature. + `CALIPTRA_ASSERT_STATIC_LINT_ERROR(AesSecSkipPRNGReseedingNonDefault, SecSkipPRNGReseeding == 0) + + // LFSR control + assign lfsr_en = data_update_i; + assign seed_en = SecSkipPRNGReseeding ? 1'b0 : seed_valid; + + // Width adaption for reseeding interface. We get EntropyWidth bits at a time. + if (Width/2 == EntropyWidth) begin : gen_buffer + // We buffer the first EntropyWidth bits. + logic [EntropyWidth-1:0] buffer_d, buffer_q; + logic buffer_valid_d, buffer_valid_q; + + // Stop requesting entropy once we have reseeded the LFSR. + assign entropy_req_o = SecSkipPRNGReseeding ? 1'b0 : reseed_req_i; + assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : seed_valid; + + // Buffer + assign buffer_valid_d = entropy_req_o && entropy_ack_i ? ~buffer_valid_q : buffer_valid_q; + + // Only update the buffer upon receiving the first EntropyWidth bits. + assign buffer_d = entropy_req_o && entropy_ack_i && !buffer_valid_q ? entropy_i : buffer_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_buffer + if (!rst_ni) begin + buffer_q <= '0; + buffer_valid_q <= 1'b0; + end else begin + buffer_q <= buffer_d; + buffer_valid_q <= buffer_valid_d; + end + end + + assign seed = {buffer_q, entropy_i}; + assign seed_valid = buffer_valid_q & entropy_req_o & entropy_ack_i; + + end else begin : gen_packer + // Upsizing of entropy input to correct width for LFSR reseeding. + + // Stop requesting entropy once the desired amount is available. + assign entropy_req_o = SecSkipPRNGReseeding ? 1'b0 : reseed_req_i & ~seed_valid; + assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : seed_valid; + + caliptra_prim_packer_fifo #( + .InW ( EntropyWidth ), + .OutW ( Width ), + .ClearOnRead ( 1'b0 ) + ) u_caliptra_prim_packer_fifo ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .clr_i ( 1'b0 ), // Not needed. + .wvalid_i ( entropy_ack_i ), + .wdata_i ( entropy_i ), + .wready_o ( ), // Not needed, we're always ready to sink data at this point. + .rvalid_o ( seed_valid ), + .rdata_o ( seed ), + .rready_i ( 1'b1 ), // We're always ready to receive the packed output word. + .depth_o ( ) // Not needed. + ); + end + + // LFSR instance + caliptra_prim_lfsr #( + .LfsrType ( "GAL_XOR" ), + .LfsrDw ( Width ), + .StateOutDw ( Width ), + .DefaultSeed ( RndCnstLfsrSeed ), + .StatePermEn ( 1'b1 ), + .StatePerm ( RndCnstLfsrPerm ), + .NonLinearOut ( 1'b1 ) + ) u_lfsr ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .seed_en_i ( seed_en ), + .seed_i ( seed ), + .lfsr_en_i ( lfsr_en ), + .entropy_i ( '0 ), + .state_o ( lfsr_state ) + ); + assign data_o[0] = lfsr_state; + + // A seperate permutation is applied to obtain the pseudo-random data for clearing the second + // share of registers (e.g. key registers or state registers in case masking is enabled). + for (genvar i = 0; i < Width; i++) begin : gen_share_perm + assign data_o[1][i] = lfsr_state[RndCnstSharePerm[i]]; + end + + // Width must be 64. + `CALIPTRA_ASSERT_INIT(AesPrngWidth, Width == 64) + +// the code below is not meant to be synthesized, +// but it is intended to be used in simulation and FPV +`ifndef SYNTHESIS + // Check that the supplied permutation is valid. + logic [Width-1:0] share_perm_test, unused_share_perm_test; + initial begin : p_share_perm_check + share_perm_test = '0; + for (int k = 0; k < Width; k++) begin + share_perm_test[RndCnstSharePerm[k]] = 1'b1; + end + unused_share_perm_test = share_perm_test; + // All bit positions must be marked with 1. + `CALIPTRA_ASSERT_I(SharePermutationCheck_A, &share_perm_test) + end +`endif + +endmodule diff --git a/src/aes/rtl/aes_prng_masking.sv b/src/aes/rtl/aes_prng_masking.sv index 56439e71a..6e15f4519 100644 --- a/src/aes/rtl/aes_prng_masking.sv +++ b/src/aes/rtl/aes_prng_masking.sv @@ -1,31 +1,18 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // // AES high-bandwidth pseudo-random number generator for masking // -// This module uses multiple parallel LFSRs each one of them followed by an aligned permutation, a -// non-linear layer (PRINCE S-Boxes) and another permutation layer spanning across all LFSRs to -// generate pseudo-random data for masking the AES cipher core. The LFSRs can be reseeded using an -// external interface. - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// IMPORTANT NOTE: // -// DO NOT USE THIS BLINDLY! // -// // -// It has not yet been verified that this initial implementation produces pseudo-random numbers // -// of sufficient quality in terms of uniformity and independence, and that it is indeed suitable // -// for masking purposes. // -/////////////////////////////////////////////////////////////////////////////////////////////////// +// This module uses a stream cipher primitive followed by a linear permutation layer to generate +// pseudo-random data for masking the AES cipher core. The stream cipher primitive can be reseeded +// using an external interface. `include "caliptra_prim_assert.sv" -module aes_prng_masking - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_prng_masking import aes_pkg::*; #( - parameter int unsigned Width = WidthPRDMasking, // Must be divisble by ChunkSize and 8 - parameter int unsigned ChunkSize = ChunkSizePRDMasking, // Width of the LFSR primitives + parameter int unsigned Width = WidthPRDMasking, parameter int unsigned EntropyWidth = edn_pkg::ENDPOINT_BUS_WIDTH, parameter bit SecAllowForcingMasks = 0, // Allow forcing masks to constant values using // force_masks_i. Useful for SCA only. @@ -35,8 +22,6 @@ module aes_prng_masking // To enable SCA resistance evaluations, we // need to skip reseeding requests. - localparam int unsigned NumChunks = Width/ChunkSize, // derived parameter - parameter masking_lfsr_seed_t RndCnstLfsrSeed = RndCnstMaskingLfsrSeedDefault, parameter masking_lfsr_perm_t RndCnstLfsrPerm = RndCnstMaskingLfsrPermDefault ) ( @@ -57,22 +42,21 @@ module aes_prng_masking input logic [EntropyWidth-1:0] entropy_i ); - logic [NumChunks-1:0] prng_seed_en; - logic [NumChunks-1:0][ChunkSize-1:0] prng_seed; - logic prng_en; - logic [NumChunks-1:0][ChunkSize-1:0] prng_state, perm; - logic [Width-1:0] prng_b, perm_b; - logic phase_q; + logic prng_seed_en; + logic prng_seed_done; + logic [Width-1:0] prng_key; + logic prng_err; ///////////// // Control // ///////////// - // The data requests are fed from the LFSRs. Reseed requests take precedence internally to the - // LFSRs. If there is an outstanding reseed request, the PRNG can keep updating and providing - // pseudo-random data (using the old seed). If the reseeding is taking place, the LFSRs will - // provide fresh pseudo-random data (the new seed) in the next cycle anyway. This means the - // PRNG is always ready to provide new pseudo-random data. + // The data requests are fed from a stream cipher primitive that is reseeded in chunks of + // EntropyWidth bits. Internally, the primitive generates the output based on the current state. + // If there is an outstanding reseed request, the PRNG can keep updating and providing + // pseudo-random data (using the current state of the primitive). When reseeding a chunk without + // requesting a PRNG update, the current output might change or not, depending on the Width and + // current chunk index. // In the current SCA setup, we don't have sufficient resources to implement the infrastructure // required for PRNG reseeding (CSRNG, EDN, etc.). Therefore, we skip any reseeding requests if @@ -88,133 +72,66 @@ module aes_prng_masking assign unused_force_masks = force_masks_i; end - // PRNG control - assign prng_en = (SecAllowForcingMasks && force_masks_i) ? 1'b0 : data_update_i; - // Create a lint error to reduce the risk of accidentally enabling this feature. `CALIPTRA_ASSERT_STATIC_LINT_ERROR(AesSecSkipPRNGReseedingNonDefault, SecSkipPRNGReseeding == 0) - // Width adaption for reseeding interface. We get EntropyWidth bits at a time. - if (ChunkSize == EntropyWidth) begin : gen_counter - // We can reseed chunk by chunk as we get fresh entropy. Need to keep track of which chunk to - // reseed next. - localparam int unsigned ChunkIdxWidth = caliptra_prim_util_pkg::vbits(NumChunks); - logic [ChunkIdxWidth-1:0] chunk_idx_d, chunk_idx_q; - logic prng_reseed_done; - - // Stop requesting entropy once every chunk got reseeded. - assign entropy_req_o = SecSkipPRNGReseeding ? 1'b0 : reseed_req_i; - assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : prng_reseed_done; - - // Counter - assign prng_reseed_done = - (chunk_idx_q == ChunkIdxWidth'(NumChunks - 1)) & entropy_req_o & entropy_ack_i; - assign chunk_idx_d = prng_reseed_done ? '0 : - entropy_req_o && entropy_ack_i ? chunk_idx_q + ChunkIdxWidth'(1) : chunk_idx_q; - - always_ff @(posedge clk_i or negedge rst_ni) begin : reg_chunk_idx - if (!rst_ni) begin - chunk_idx_q <= '0; - end else begin - chunk_idx_q <= chunk_idx_d; - end - end - - // The entropy input is forwarded to all chunks, we just control the seed enable. - for (genvar c = 0; c < NumChunks; c++) begin : gen_seeds - assign prng_seed[c] = entropy_i; - assign prng_seed_en[c] = (c == chunk_idx_q) ? entropy_req_o & entropy_ack_i : 1'b0; - end - - end else begin : gen_packer - // Upsizing of entropy input to correct width for reseeding the full PRNG in one shot. - logic [Width-1:0] seed; - logic seed_valid; - - // Stop requesting entropy once the desired amount is available. - assign entropy_req_o = SecSkipPRNGReseeding ? 1'b0 : reseed_req_i & ~seed_valid; - assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : seed_valid; - - caliptra_prim_packer_fifo #( - .InW ( EntropyWidth ), - .OutW ( Width ), - .ClearOnRead ( 1'b0 ) - ) u_caliptra_prim_packer_fifo ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .clr_i ( 1'b0 ), // Not needed. - .wvalid_i ( entropy_ack_i ), - .wdata_i ( entropy_i ), - .wready_o ( ), // Not needed, we're always ready to sink data at this point. - .rvalid_o ( seed_valid ), - .rdata_o ( seed ), - .rready_i ( 1'b1 ), // We're always ready to receive the packed output word. - .depth_o ( ) // Not needed. - ); - - // Extract chunk seeds. All chunks get reseeded together. - for (genvar c = 0; c < NumChunks; c++) begin : gen_seeds - assign prng_seed[c] = seed[c * ChunkSize +: ChunkSize]; - assign prng_seed_en[c] = SecSkipPRNGReseeding ? 1'b0 : seed_valid; - end - end - - /////////// - // LFSRs // - /////////// - - // We use multiple LFSR instances each having a width of ChunkSize. - for (genvar c = 0; c < NumChunks; c++) begin : gen_lfsrs - caliptra_prim_lfsr #( - .LfsrType ( "GAL_XOR" ), - .LfsrDw ( ChunkSize ), - .StateOutDw ( ChunkSize ), - .DefaultSeed ( RndCnstLfsrSeed[c * ChunkSize +: ChunkSize] ), - .StatePermEn ( 1'b0 ), - .NonLinearOut ( 1'b1 ) - ) u_lfsr_chunk ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .seed_en_i ( prng_seed_en[c] ), - .seed_i ( prng_seed[c] ), - .lfsr_en_i ( prng_en ), - .entropy_i ( '0 ), - .state_o ( prng_state[c] ) - ); + if (SecSkipPRNGReseeding == 1) begin : gen_unused_prng_seed_done + logic unused_prng_seed_done; + assign unused_prng_seed_done = prng_seed_done; end - // Add a permutation layer spanning across all LFSRs to break linear shift patterns. - assign prng_b = prng_state; + // Reseed interface handling + assign prng_seed_en = SecSkipPRNGReseeding ? 1'b0 : reseed_req_i; + assign reseed_ack_o = SecSkipPRNGReseeding ? reseed_req_i : prng_seed_done; + + //////////////////////////////////// + // Bivium Stream Cipher Primitive // + //////////////////////////////////// + caliptra_prim_trivium #( + .BiviumVariant (1), + .OutputWidth (Width), + .StrictLockupProtection(!SecAllowForcingMasks), + .SeedType (caliptra_prim_trivium_pkg::SeedTypeStatePartial), + .PartialSeedWidth (EntropyWidth), + .RndCnstTriviumLfsrSeed(RndCnstLfsrSeed) + ) u_caliptra_prim_bivium ( + .clk_i (clk_i), + .rst_ni(rst_ni), + + .en_i (data_update_i), + .allow_lockup_i (SecAllowForcingMasks & force_masks_i), + .seed_en_i (prng_seed_en), + .seed_done_o (prng_seed_done), + .seed_req_o (entropy_req_o), + .seed_ack_i (entropy_ack_i), + .seed_key_i ('0), // Not used. + .seed_iv_i ('0), // Not used. + .seed_state_full_i ('0), // Not used. + .seed_state_partial_i(entropy_i), + + .key_o(prng_key), + .err_o(prng_err) + ); + + // Add a permutation layer to obfuscate the output of stream cipher primitive. for (genvar b = 0; b < Width; b++) begin : gen_perm - assign perm_b[b] = prng_b[RndCnstLfsrPerm[b]]; + assign data_o[b] = prng_key[RndCnstLfsrPerm[b]]; end - assign perm = perm_b; - - ///////////// - // Outputs // - ///////////// - // To achieve independence of input and output masks (the output mask of round X is the input - // mask of round X+1), we assign the scrambled chunks to the output data in alternating fashion. - assign data_o = phase_q ? {perm[0], perm[NumChunks-1:1]} : perm; - - always_ff @(posedge clk_i or negedge rst_ni) begin : reg_phase - if (!rst_ni) begin - phase_q <= '0; - end else if (prng_en) begin - phase_q <= ~phase_q; - end - end + // At the moment, the PRNG error output is ignored. This signal is asserted only if the stream + // cipher primitive enters an all-zero state. Depending on the value of the SecAllowForcingMasks + // parameter, the primitive behaves differently: + // - If SecAllowForcingMasks == 0 or if SecAllowForcingMasks == 1 and force_masks_i == 0, the + // primitive is automatically reset to the default value defined by a secret netlist constant. + // - If SecAllowForcingMasks == 1 and force_masks_i == 1, the primitive keeps the all-zero value. + // This may be required to switch off the masking for evaluating the SCA resistance. + logic unused_prng_err; + assign unused_prng_err = prng_err; ///////////////// // Asssertions // ///////////////// - // Width must be divisible by ChunkSize - `CALIPTRA_ASSERT_INIT(AesPrngMaskingWidthByChunk, Width % ChunkSize == 0) - // Width must be divisible by 8 - `CALIPTRA_ASSERT_INIT(AesPrngMaskingWidthBy8, Width % 8 == 0) - // the code below is not meant to be synthesized, // but it is intended to be used in simulation and FPV `ifndef SYNTHESIS diff --git a/src/aes/rtl/aes_reduced_round.sv b/src/aes/rtl/aes_reduced_round.sv new file mode 100644 index 000000000..c56cdf4f1 --- /dev/null +++ b/src/aes/rtl/aes_reduced_round.sv @@ -0,0 +1,80 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// AES reduced round data path +// This module is useful for formal masking verification using e.g. Alma. +// For details, see hw/ip/aes/pre_sca/alma/README.md . + +module aes_reduced_round import aes_pkg::*; +#( + parameter sbox_impl_e SecSBoxImpl = SBoxImplDom +) ( + input logic clk_i, + input logic rst_ni, + input sp2v_e en_i, + output sp2v_e out_req_o, + input sp2v_e out_ack_i, + input ciph_op_e op_i, + input logic [3:0][3:0][7:0] data_i, + input logic [3:0][3:0][7:0] mask_i, + input logic [3:0][3:0][WidthPRDSBox-1:0] prd_i, + output logic [3:0][3:0][7:0] data_o, + output logic [3:0][3:0][7:0] mask_o, + output logic err_o +); + + localparam int NumShares = 2; + + // Signals + logic [3:0][3:0][7:0] sub_bytes_out; + logic [3:0][3:0][7:0] sb_out_mask; + logic [3:0][3:0][7:0] shift_rows_in [NumShares]; + logic [3:0][3:0][7:0] shift_rows_out [NumShares]; + logic [3:0][3:0][7:0] mix_columns_out [NumShares]; + + // A single reduced (no AddKey) round of the cipher data path + aes_sub_bytes #( + .SecSBoxImpl ( SecSBoxImpl ) + ) u_aes_sub_bytes ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .en_i ( en_i ), + .out_req_o ( out_req_o ), + .out_ack_i ( out_ack_i ), + .op_i ( op_i ), + .data_i ( data_i ), + .mask_i ( mask_i ), + .prd_i ( prd_i ), + .data_o ( sub_bytes_out ), + .mask_o ( sb_out_mask ), + .err_o ( err_o ) + ); + + for (genvar s = 0; s < NumShares; s++) begin : gen_shares_shift_mix + if (s == 0) begin : gen_shift_in_data + // The (masked) data share + assign shift_rows_in[s] = sub_bytes_out; + end else begin : gen_shift_in_mask + // The mask share + assign shift_rows_in[s] = sb_out_mask; + end + + aes_shift_rows u_aes_shift_rows ( + .op_i ( op_i ), + .data_i ( shift_rows_in[s] ), + .data_o ( shift_rows_out[s] ) + ); + + aes_mix_columns u_aes_mix_columns ( + .op_i ( op_i ), + .data_i ( shift_rows_out[s] ), + .data_o ( mix_columns_out[s] ) + ); + end + + // Outputs + assign data_o = mix_columns_out[0]; + assign mask_o = mix_columns_out[1]; + +endmodule diff --git a/src/aes/rtl/aes_reg_pkg.sv b/src/aes/rtl/aes_reg_pkg.sv index d3b3d4b7d..eb30c11d2 100644 --- a/src/aes/rtl/aes_reg_pkg.sv +++ b/src/aes/rtl/aes_reg_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -23,11 +23,11 @@ package aes_reg_pkg; struct packed { logic q; logic qe; - } recov_ctrl_update_err; + } fatal_fault; struct packed { logic q; logic qe; - } fatal_fault; + } recov_ctrl_update_err; } aes_reg2hw_alert_test_reg_t; typedef struct packed { @@ -57,20 +57,15 @@ package aes_reg_pkg; typedef struct packed { struct packed { - logic [1:0] q; - logic qe; - logic re; - } operation; - struct packed { - logic [5:0] q; + logic q; logic qe; logic re; - } mode; + } manual_operation; struct packed { logic [2:0] q; logic qe; logic re; - } key_len; + } prng_reseed_rate; struct packed { logic q; logic qe; @@ -80,47 +75,65 @@ package aes_reg_pkg; logic [2:0] q; logic qe; logic re; - } prng_reseed_rate; + } key_len; struct packed { - logic q; + logic [5:0] q; logic qe; logic re; - } manual_operation; + } mode; + struct packed { + logic [1:0] q; + logic qe; + logic re; + } operation; } aes_reg2hw_ctrl_shadowed_reg_t; typedef struct packed { struct packed { logic q; - } key_touch_forces_reseed; + } force_masks; struct packed { logic q; - } force_masks; + } key_touch_forces_reseed; } aes_reg2hw_ctrl_aux_shadowed_reg_t; typedef struct packed { struct packed { logic q; - } start; + } prng_reseed; struct packed { logic q; - } key_iv_data_in_clear; + } data_out_clear; struct packed { logic q; - } data_out_clear; + } key_iv_data_in_clear; struct packed { logic q; - } prng_reseed; + } start; } aes_reg2hw_trigger_reg_t; typedef struct packed { struct packed { logic q; - } idle; + } output_lost; struct packed { logic q; - } output_lost; + } idle; } aes_reg2hw_status_reg_t; + typedef struct packed { + struct packed { + logic [4:0] q; + logic qe; + logic re; + } num_valid_bytes; + struct packed { + logic [5:0] q; + logic qe; + logic re; + } phase; + } aes_reg2hw_ctrl_gcm_shadowed_reg_t; + typedef struct packed { logic [31:0] d; } aes_hw2reg_key_share0_mreg_t; @@ -213,30 +226,41 @@ package aes_reg_pkg; } alert_fatal_fault; } aes_hw2reg_status_reg_t; + typedef struct packed { + struct packed { + logic [5:0] d; + } phase; + struct packed { + logic [4:0] d; + } num_valid_bytes; + } aes_hw2reg_ctrl_gcm_shadowed_reg_t; + // Register -> HW type typedef struct packed { - aes_reg2hw_alert_test_reg_t alert_test; // [957:954] - aes_reg2hw_key_share0_mreg_t [7:0] key_share0; // [953:690] - aes_reg2hw_key_share1_mreg_t [7:0] key_share1; // [689:426] - aes_reg2hw_iv_mreg_t [3:0] iv; // [425:294] - aes_reg2hw_data_in_mreg_t [3:0] data_in; // [293:162] - aes_reg2hw_data_out_mreg_t [3:0] data_out; // [161:30] - aes_reg2hw_ctrl_shadowed_reg_t ctrl_shadowed; // [29:8] - aes_reg2hw_ctrl_aux_shadowed_reg_t ctrl_aux_shadowed; // [7:6] - aes_reg2hw_trigger_reg_t trigger; // [5:2] - aes_reg2hw_status_reg_t status; // [1:0] + aes_reg2hw_alert_test_reg_t alert_test; // [970:967] + aes_reg2hw_key_share0_mreg_t [7:0] key_share0; // [966:703] + aes_reg2hw_key_share1_mreg_t [7:0] key_share1; // [702:439] + aes_reg2hw_iv_mreg_t [3:0] iv; // [438:307] + aes_reg2hw_data_in_mreg_t [3:0] data_in; // [306:175] + aes_reg2hw_data_out_mreg_t [3:0] data_out; // [174:43] + aes_reg2hw_ctrl_shadowed_reg_t ctrl_shadowed; // [42:21] + aes_reg2hw_ctrl_aux_shadowed_reg_t ctrl_aux_shadowed; // [20:19] + aes_reg2hw_trigger_reg_t trigger; // [18:15] + aes_reg2hw_status_reg_t status; // [14:13] + aes_reg2hw_ctrl_gcm_shadowed_reg_t ctrl_gcm_shadowed; // [12:0] } aes_reg2hw_t; // HW -> register type typedef struct packed { - aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [937:682] - aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [681:426] - aes_hw2reg_iv_mreg_t [3:0] iv; // [425:298] - aes_hw2reg_data_in_mreg_t [3:0] data_in; // [297:166] - aes_hw2reg_data_out_mreg_t [3:0] data_out; // [165:38] - aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [37:22] - aes_hw2reg_trigger_reg_t trigger; // [21:14] - aes_hw2reg_status_reg_t status; // [13:0] + aes_hw2reg_key_share0_mreg_t [7:0] key_share0; // [948:693] + aes_hw2reg_key_share1_mreg_t [7:0] key_share1; // [692:437] + aes_hw2reg_iv_mreg_t [3:0] iv; // [436:309] + aes_hw2reg_data_in_mreg_t [3:0] data_in; // [308:177] + aes_hw2reg_data_out_mreg_t [3:0] data_out; // [176:49] + aes_hw2reg_ctrl_shadowed_reg_t ctrl_shadowed; // [48:33] + aes_hw2reg_trigger_reg_t trigger; // [32:25] + aes_hw2reg_status_reg_t status; // [24:11] + aes_hw2reg_ctrl_gcm_shadowed_reg_t ctrl_gcm_shadowed; // [10:0] } aes_hw2reg_t; // Register offsets @@ -274,6 +298,7 @@ package aes_reg_pkg; parameter logic [BlockAw-1:0] AES_CTRL_AUX_REGWEN_OFFSET = 8'h 7c; parameter logic [BlockAw-1:0] AES_TRIGGER_OFFSET = 8'h 80; parameter logic [BlockAw-1:0] AES_STATUS_OFFSET = 8'h 84; + parameter logic [BlockAw-1:0] AES_CTRL_GCM_SHADOWED_OFFSET = 8'h 88; // Reset values for hwext registers and their fields parameter logic [1:0] AES_ALERT_TEST_RESVAL = 2'h 0; @@ -327,13 +352,16 @@ package aes_reg_pkg; parameter logic [31:0] AES_DATA_OUT_2_DATA_OUT_2_RESVAL = 32'h 0; parameter logic [31:0] AES_DATA_OUT_3_RESVAL = 32'h 0; parameter logic [31:0] AES_DATA_OUT_3_DATA_OUT_3_RESVAL = 32'h 0; - parameter logic [15:0] AES_CTRL_SHADOWED_RESVAL = 16'h 1181; + parameter logic [15:0] AES_CTRL_SHADOWED_RESVAL = 16'h 11fd; parameter logic [1:0] AES_CTRL_SHADOWED_OPERATION_RESVAL = 2'h 1; - parameter logic [5:0] AES_CTRL_SHADOWED_MODE_RESVAL = 6'h 20; + parameter logic [5:0] AES_CTRL_SHADOWED_MODE_RESVAL = 6'h 3f; parameter logic [2:0] AES_CTRL_SHADOWED_KEY_LEN_RESVAL = 3'h 1; parameter logic [0:0] AES_CTRL_SHADOWED_SIDELOAD_RESVAL = 1'h 0; parameter logic [2:0] AES_CTRL_SHADOWED_PRNG_RESEED_RATE_RESVAL = 3'h 1; parameter logic [0:0] AES_CTRL_SHADOWED_MANUAL_OPERATION_RESVAL = 1'h 0; + parameter logic [10:0] AES_CTRL_GCM_SHADOWED_RESVAL = 11'h 401; + parameter logic [5:0] AES_CTRL_GCM_SHADOWED_PHASE_RESVAL = 6'h 1; + parameter logic [4:0] AES_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_RESVAL = 5'h 10; // Register index typedef enum logic [31:0] { @@ -370,11 +398,12 @@ package aes_reg_pkg; AES_CTRL_AUX_SHADOWED, AES_CTRL_AUX_REGWEN, AES_TRIGGER, - AES_STATUS + AES_STATUS, + AES_CTRL_GCM_SHADOWED } aes_id_e; // Register width information to check illegal writes - parameter logic [3:0] AES_PERMIT [34] = '{ + parameter logic [3:0] AES_PERMIT [35] = '{ 4'b 0001, // index[ 0] AES_ALERT_TEST 4'b 1111, // index[ 1] AES_KEY_SHARE0_0 4'b 1111, // index[ 2] AES_KEY_SHARE0_1 @@ -408,7 +437,8 @@ package aes_reg_pkg; 4'b 0001, // index[30] AES_CTRL_AUX_SHADOWED 4'b 0001, // index[31] AES_CTRL_AUX_REGWEN 4'b 0001, // index[32] AES_TRIGGER - 4'b 0001 // index[33] AES_STATUS + 4'b 0001, // index[33] AES_STATUS + 4'b 0011 // index[34] AES_CTRL_GCM_SHADOWED }; endpackage diff --git a/src/aes/rtl/aes_reg_status.sv b/src/aes/rtl/aes_reg_status.sv new file mode 100644 index 000000000..f608e8464 --- /dev/null +++ b/src/aes/rtl/aes_reg_status.sv @@ -0,0 +1,79 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES reg status +// +// This module tracks the collective status of multiple registers. + +module aes_reg_status #( + parameter int Width = 1 +) ( + input logic clk_i, + input logic rst_ni, + + input logic [Width-1:0] we_i, + input logic use_i, + input logic clear_i, + input logic arm_i, + output logic new_o, + output logic new_pulse_o, + output logic clean_o +); + + logic [Width-1:0] we_d, we_q; + logic armed_d, armed_q; + logic all_written; + logic none_written; + logic new_d, new_q; + logic clean_d, clean_q; + + // Collect write operations. Upon clear or use, we start over. If armed, the next write will + // restart the tracking. + assign we_d = (clear_i || use_i) ? '0 : + (armed_q && |we_i) ? we_i : (we_q | we_i); + assign armed_d = (clear_i || use_i) ? 1'b0 : + (armed_q && |we_i) ? 1'b0 : armed_q | arm_i; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_ops + if (!rst_ni) begin + we_q <= '0; + armed_q <= 1'b0; + end else begin + we_q <= we_d; + armed_q <= armed_d; + end + end + + // Status tracking + assign all_written = &we_d; + assign none_written = ~|we_d; + + // We have a complete new value if all registers have been written at least once. + assign new_d = (clear_i || use_i) ? 1'b0 : all_written; + + // We have a clean value, if either: + // - all registers have been written at least once, or + // - no registers have been written but the value was clean previsously. + // A value is NOT clean, if either: + // - we get a clear or reset, or + // - some but not all registers have been written. + assign clean_d = clear_i ? 1'b0 : + all_written ? 1'b1 : + none_written ? clean_q : 1'b0; + + always_ff @(posedge clk_i or negedge rst_ni) begin : reg_status + if (!rst_ni) begin + new_q <= 1'b0; + clean_q <= 1'b0; + end else begin + new_q <= new_d; + clean_q <= clean_d; + end + end + + assign new_o = new_q; + assign new_pulse_o = new_d & ~new_q; + assign clean_o = clean_q; + +endmodule diff --git a/src/aes/rtl/aes_reg_top.sv b/src/aes/rtl/aes_reg_top.sv new file mode 100644 index 000000000..f449c5666 --- /dev/null +++ b/src/aes/rtl/aes_reg_top.sv @@ -0,0 +1,1947 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Register Top module auto-generated by `reggen` + +`include "caliptra_prim_assert.sv" + +module aes_reg_top ( + input clk_i, + input rst_ni, + input rst_shadowed_ni, + input caliptra_tlul_pkg::tl_h2d_t tl_i, + output caliptra_tlul_pkg::tl_d2h_t tl_o, + // To HW + output aes_reg_pkg::aes_reg2hw_t reg2hw, // Write + input aes_reg_pkg::aes_hw2reg_t hw2reg, // Read + + output logic shadowed_storage_err_o, + output logic shadowed_update_err_o, + + // Integrity check errors + output logic intg_err_o +); + + import aes_reg_pkg::* ; + + localparam int AW = 8; + localparam int DW = 32; + localparam int DBW = DW/8; // Byte Width + + // register signals + logic reg_we; + logic reg_re; + logic [AW-1:0] reg_addr; + logic [DW-1:0] reg_wdata; + logic [DBW-1:0] reg_be; + logic [DW-1:0] reg_rdata; + logic reg_error; + + logic addrmiss, wr_err; + + logic [DW-1:0] reg_rdata_next; + logic reg_busy; + + caliptra_tlul_pkg::tl_h2d_t tl_reg_h2d; + caliptra_tlul_pkg::tl_d2h_t tl_reg_d2h; + + + // incoming payload check + logic intg_err; + caliptra_tlul_cmd_intg_chk u_chk ( + .tl_i(tl_i), + .err_o(intg_err) + ); + + // also check for spurious write enables + logic reg_we_err; + logic [34:0] reg_we_check; + caliptra_prim_reg_we_check #( + .OneHotWidth(35) + ) u_caliptra_prim_reg_we_check ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .oh_i (reg_we_check), + .en_i (reg_we && !addrmiss), + .err_o (reg_we_err) + ); + + logic err_q; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + err_q <= '0; + end else if (intg_err || reg_we_err) begin + err_q <= 1'b1; + end + end + + // integrity error output is permanent and should be used for alert generation + // register errors are transactional + assign intg_err_o = err_q | intg_err | reg_we_err; + + // outgoing integrity generation + caliptra_tlul_pkg::tl_d2h_t tl_o_pre; + caliptra_tlul_rsp_intg_gen #( + .EnableRspIntgGen(1), + .EnableDataIntgGen(1) + ) u_rsp_intg_gen ( + .tl_i(tl_o_pre), + .tl_o(tl_o) + ); + + assign tl_reg_h2d = tl_i; + assign tl_o_pre = tl_reg_d2h; + + caliptra_tlul_adapter_reg #( + .RegAw(AW), + .RegDw(DW), + .EnableDataIntgGen(0) + ) u_reg_if ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + .tl_i (tl_reg_h2d), + .tl_o (tl_reg_d2h), + + .en_ifetch_i(caliptra_prim_mubi_pkg::MuBi4False), + .intg_error_o(), + + .we_o (reg_we), + .re_o (reg_re), + .addr_o (reg_addr), + .wdata_o (reg_wdata), + .be_o (reg_be), + .busy_i (reg_busy), + .rdata_i (reg_rdata), + .error_i (reg_error) + ); + + // cdc oversampling signals + + assign reg_rdata = reg_rdata_next ; + assign reg_error = addrmiss | wr_err | intg_err; + + // Define SW related signals + // Format: __{wd|we|qs} + // or _{wd|we|qs} if field == 1 or 0 + logic alert_test_we; + logic alert_test_recov_ctrl_update_err_wd; + logic alert_test_fatal_fault_wd; + logic key_share0_0_we; + logic [31:0] key_share0_0_wd; + logic key_share0_1_we; + logic [31:0] key_share0_1_wd; + logic key_share0_2_we; + logic [31:0] key_share0_2_wd; + logic key_share0_3_we; + logic [31:0] key_share0_3_wd; + logic key_share0_4_we; + logic [31:0] key_share0_4_wd; + logic key_share0_5_we; + logic [31:0] key_share0_5_wd; + logic key_share0_6_we; + logic [31:0] key_share0_6_wd; + logic key_share0_7_we; + logic [31:0] key_share0_7_wd; + logic key_share1_0_we; + logic [31:0] key_share1_0_wd; + logic key_share1_1_we; + logic [31:0] key_share1_1_wd; + logic key_share1_2_we; + logic [31:0] key_share1_2_wd; + logic key_share1_3_we; + logic [31:0] key_share1_3_wd; + logic key_share1_4_we; + logic [31:0] key_share1_4_wd; + logic key_share1_5_we; + logic [31:0] key_share1_5_wd; + logic key_share1_6_we; + logic [31:0] key_share1_6_wd; + logic key_share1_7_we; + logic [31:0] key_share1_7_wd; + logic iv_0_re; + logic iv_0_we; + logic [31:0] iv_0_qs; + logic [31:0] iv_0_wd; + logic iv_1_re; + logic iv_1_we; + logic [31:0] iv_1_qs; + logic [31:0] iv_1_wd; + logic iv_2_re; + logic iv_2_we; + logic [31:0] iv_2_qs; + logic [31:0] iv_2_wd; + logic iv_3_re; + logic iv_3_we; + logic [31:0] iv_3_qs; + logic [31:0] iv_3_wd; + logic data_in_0_we; + logic [31:0] data_in_0_wd; + logic data_in_1_we; + logic [31:0] data_in_1_wd; + logic data_in_2_we; + logic [31:0] data_in_2_wd; + logic data_in_3_we; + logic [31:0] data_in_3_wd; + logic data_out_0_re; + logic [31:0] data_out_0_qs; + logic data_out_1_re; + logic [31:0] data_out_1_qs; + logic data_out_2_re; + logic [31:0] data_out_2_qs; + logic data_out_3_re; + logic [31:0] data_out_3_qs; + logic ctrl_shadowed_re; + logic ctrl_shadowed_we; + logic [1:0] ctrl_shadowed_operation_qs; + logic [1:0] ctrl_shadowed_operation_wd; + logic [5:0] ctrl_shadowed_mode_qs; + logic [5:0] ctrl_shadowed_mode_wd; + logic [2:0] ctrl_shadowed_key_len_qs; + logic [2:0] ctrl_shadowed_key_len_wd; + logic ctrl_shadowed_sideload_qs; + logic ctrl_shadowed_sideload_wd; + logic [2:0] ctrl_shadowed_prng_reseed_rate_qs; + logic [2:0] ctrl_shadowed_prng_reseed_rate_wd; + logic ctrl_shadowed_manual_operation_qs; + logic ctrl_shadowed_manual_operation_wd; + logic ctrl_aux_shadowed_re; + logic ctrl_aux_shadowed_we; + logic ctrl_aux_shadowed_key_touch_forces_reseed_qs; + logic ctrl_aux_shadowed_key_touch_forces_reseed_wd; + logic ctrl_aux_shadowed_key_touch_forces_reseed_storage_err; + logic ctrl_aux_shadowed_key_touch_forces_reseed_update_err; + logic ctrl_aux_shadowed_force_masks_qs; + logic ctrl_aux_shadowed_force_masks_wd; + logic ctrl_aux_shadowed_force_masks_storage_err; + logic ctrl_aux_shadowed_force_masks_update_err; + logic ctrl_aux_regwen_we; + logic ctrl_aux_regwen_qs; + logic ctrl_aux_regwen_wd; + logic trigger_we; + logic trigger_start_wd; + logic trigger_key_iv_data_in_clear_wd; + logic trigger_data_out_clear_wd; + logic trigger_prng_reseed_wd; + logic status_idle_qs; + logic status_stall_qs; + logic status_output_lost_qs; + logic status_output_valid_qs; + logic status_input_ready_qs; + logic status_alert_recov_ctrl_update_err_qs; + logic status_alert_fatal_fault_qs; + logic ctrl_gcm_shadowed_re; + logic ctrl_gcm_shadowed_we; + logic [5:0] ctrl_gcm_shadowed_phase_qs; + logic [5:0] ctrl_gcm_shadowed_phase_wd; + logic [4:0] ctrl_gcm_shadowed_num_valid_bytes_qs; + logic [4:0] ctrl_gcm_shadowed_num_valid_bytes_wd; + + // Register instances + // R[alert_test]: V(True) + logic alert_test_qe; + logic [1:0] alert_test_flds_we; + assign alert_test_qe = &alert_test_flds_we; + // F[recov_ctrl_update_err]: 0:0 + caliptra_prim_subreg_ext #( + .DW (1) + ) u_alert_test_recov_ctrl_update_err ( + .re (1'b0), + .we (alert_test_we), + .wd (alert_test_recov_ctrl_update_err_wd), + .d ('0), + .qre (), + .qe (alert_test_flds_we[0]), + .q (reg2hw.alert_test.recov_ctrl_update_err.q), + .ds (), + .qs () + ); + assign reg2hw.alert_test.recov_ctrl_update_err.qe = alert_test_qe; + + // F[fatal_fault]: 1:1 + caliptra_prim_subreg_ext #( + .DW (1) + ) u_alert_test_fatal_fault ( + .re (1'b0), + .we (alert_test_we), + .wd (alert_test_fatal_fault_wd), + .d ('0), + .qre (), + .qe (alert_test_flds_we[1]), + .q (reg2hw.alert_test.fatal_fault.q), + .ds (), + .qs () + ); + assign reg2hw.alert_test.fatal_fault.qe = alert_test_qe; + + + // Subregister 0 of Multireg key_share0 + // R[key_share0_0]: V(True) + logic key_share0_0_qe; + logic [0:0] key_share0_0_flds_we; + assign key_share0_0_qe = &key_share0_0_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_0 ( + .re (1'b0), + .we (key_share0_0_we), + .wd (key_share0_0_wd), + .d (hw2reg.key_share0[0].d), + .qre (), + .qe (key_share0_0_flds_we[0]), + .q (reg2hw.key_share0[0].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[0].qe = key_share0_0_qe; + + + // Subregister 1 of Multireg key_share0 + // R[key_share0_1]: V(True) + logic key_share0_1_qe; + logic [0:0] key_share0_1_flds_we; + assign key_share0_1_qe = &key_share0_1_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_1 ( + .re (1'b0), + .we (key_share0_1_we), + .wd (key_share0_1_wd), + .d (hw2reg.key_share0[1].d), + .qre (), + .qe (key_share0_1_flds_we[0]), + .q (reg2hw.key_share0[1].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[1].qe = key_share0_1_qe; + + + // Subregister 2 of Multireg key_share0 + // R[key_share0_2]: V(True) + logic key_share0_2_qe; + logic [0:0] key_share0_2_flds_we; + assign key_share0_2_qe = &key_share0_2_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_2 ( + .re (1'b0), + .we (key_share0_2_we), + .wd (key_share0_2_wd), + .d (hw2reg.key_share0[2].d), + .qre (), + .qe (key_share0_2_flds_we[0]), + .q (reg2hw.key_share0[2].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[2].qe = key_share0_2_qe; + + + // Subregister 3 of Multireg key_share0 + // R[key_share0_3]: V(True) + logic key_share0_3_qe; + logic [0:0] key_share0_3_flds_we; + assign key_share0_3_qe = &key_share0_3_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_3 ( + .re (1'b0), + .we (key_share0_3_we), + .wd (key_share0_3_wd), + .d (hw2reg.key_share0[3].d), + .qre (), + .qe (key_share0_3_flds_we[0]), + .q (reg2hw.key_share0[3].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[3].qe = key_share0_3_qe; + + + // Subregister 4 of Multireg key_share0 + // R[key_share0_4]: V(True) + logic key_share0_4_qe; + logic [0:0] key_share0_4_flds_we; + assign key_share0_4_qe = &key_share0_4_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_4 ( + .re (1'b0), + .we (key_share0_4_we), + .wd (key_share0_4_wd), + .d (hw2reg.key_share0[4].d), + .qre (), + .qe (key_share0_4_flds_we[0]), + .q (reg2hw.key_share0[4].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[4].qe = key_share0_4_qe; + + + // Subregister 5 of Multireg key_share0 + // R[key_share0_5]: V(True) + logic key_share0_5_qe; + logic [0:0] key_share0_5_flds_we; + assign key_share0_5_qe = &key_share0_5_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_5 ( + .re (1'b0), + .we (key_share0_5_we), + .wd (key_share0_5_wd), + .d (hw2reg.key_share0[5].d), + .qre (), + .qe (key_share0_5_flds_we[0]), + .q (reg2hw.key_share0[5].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[5].qe = key_share0_5_qe; + + + // Subregister 6 of Multireg key_share0 + // R[key_share0_6]: V(True) + logic key_share0_6_qe; + logic [0:0] key_share0_6_flds_we; + assign key_share0_6_qe = &key_share0_6_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_6 ( + .re (1'b0), + .we (key_share0_6_we), + .wd (key_share0_6_wd), + .d (hw2reg.key_share0[6].d), + .qre (), + .qe (key_share0_6_flds_we[0]), + .q (reg2hw.key_share0[6].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[6].qe = key_share0_6_qe; + + + // Subregister 7 of Multireg key_share0 + // R[key_share0_7]: V(True) + logic key_share0_7_qe; + logic [0:0] key_share0_7_flds_we; + assign key_share0_7_qe = &key_share0_7_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share0_7 ( + .re (1'b0), + .we (key_share0_7_we), + .wd (key_share0_7_wd), + .d (hw2reg.key_share0[7].d), + .qre (), + .qe (key_share0_7_flds_we[0]), + .q (reg2hw.key_share0[7].q), + .ds (), + .qs () + ); + assign reg2hw.key_share0[7].qe = key_share0_7_qe; + + + // Subregister 0 of Multireg key_share1 + // R[key_share1_0]: V(True) + logic key_share1_0_qe; + logic [0:0] key_share1_0_flds_we; + assign key_share1_0_qe = &key_share1_0_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_0 ( + .re (1'b0), + .we (key_share1_0_we), + .wd (key_share1_0_wd), + .d (hw2reg.key_share1[0].d), + .qre (), + .qe (key_share1_0_flds_we[0]), + .q (reg2hw.key_share1[0].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[0].qe = key_share1_0_qe; + + + // Subregister 1 of Multireg key_share1 + // R[key_share1_1]: V(True) + logic key_share1_1_qe; + logic [0:0] key_share1_1_flds_we; + assign key_share1_1_qe = &key_share1_1_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_1 ( + .re (1'b0), + .we (key_share1_1_we), + .wd (key_share1_1_wd), + .d (hw2reg.key_share1[1].d), + .qre (), + .qe (key_share1_1_flds_we[0]), + .q (reg2hw.key_share1[1].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[1].qe = key_share1_1_qe; + + + // Subregister 2 of Multireg key_share1 + // R[key_share1_2]: V(True) + logic key_share1_2_qe; + logic [0:0] key_share1_2_flds_we; + assign key_share1_2_qe = &key_share1_2_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_2 ( + .re (1'b0), + .we (key_share1_2_we), + .wd (key_share1_2_wd), + .d (hw2reg.key_share1[2].d), + .qre (), + .qe (key_share1_2_flds_we[0]), + .q (reg2hw.key_share1[2].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[2].qe = key_share1_2_qe; + + + // Subregister 3 of Multireg key_share1 + // R[key_share1_3]: V(True) + logic key_share1_3_qe; + logic [0:0] key_share1_3_flds_we; + assign key_share1_3_qe = &key_share1_3_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_3 ( + .re (1'b0), + .we (key_share1_3_we), + .wd (key_share1_3_wd), + .d (hw2reg.key_share1[3].d), + .qre (), + .qe (key_share1_3_flds_we[0]), + .q (reg2hw.key_share1[3].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[3].qe = key_share1_3_qe; + + + // Subregister 4 of Multireg key_share1 + // R[key_share1_4]: V(True) + logic key_share1_4_qe; + logic [0:0] key_share1_4_flds_we; + assign key_share1_4_qe = &key_share1_4_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_4 ( + .re (1'b0), + .we (key_share1_4_we), + .wd (key_share1_4_wd), + .d (hw2reg.key_share1[4].d), + .qre (), + .qe (key_share1_4_flds_we[0]), + .q (reg2hw.key_share1[4].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[4].qe = key_share1_4_qe; + + + // Subregister 5 of Multireg key_share1 + // R[key_share1_5]: V(True) + logic key_share1_5_qe; + logic [0:0] key_share1_5_flds_we; + assign key_share1_5_qe = &key_share1_5_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_5 ( + .re (1'b0), + .we (key_share1_5_we), + .wd (key_share1_5_wd), + .d (hw2reg.key_share1[5].d), + .qre (), + .qe (key_share1_5_flds_we[0]), + .q (reg2hw.key_share1[5].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[5].qe = key_share1_5_qe; + + + // Subregister 6 of Multireg key_share1 + // R[key_share1_6]: V(True) + logic key_share1_6_qe; + logic [0:0] key_share1_6_flds_we; + assign key_share1_6_qe = &key_share1_6_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_6 ( + .re (1'b0), + .we (key_share1_6_we), + .wd (key_share1_6_wd), + .d (hw2reg.key_share1[6].d), + .qre (), + .qe (key_share1_6_flds_we[0]), + .q (reg2hw.key_share1[6].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[6].qe = key_share1_6_qe; + + + // Subregister 7 of Multireg key_share1 + // R[key_share1_7]: V(True) + logic key_share1_7_qe; + logic [0:0] key_share1_7_flds_we; + assign key_share1_7_qe = &key_share1_7_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_key_share1_7 ( + .re (1'b0), + .we (key_share1_7_we), + .wd (key_share1_7_wd), + .d (hw2reg.key_share1[7].d), + .qre (), + .qe (key_share1_7_flds_we[0]), + .q (reg2hw.key_share1[7].q), + .ds (), + .qs () + ); + assign reg2hw.key_share1[7].qe = key_share1_7_qe; + + + // Subregister 0 of Multireg iv + // R[iv_0]: V(True) + logic iv_0_qe; + logic [0:0] iv_0_flds_we; + assign iv_0_qe = &iv_0_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_iv_0 ( + .re (iv_0_re), + .we (iv_0_we), + .wd (iv_0_wd), + .d (hw2reg.iv[0].d), + .qre (), + .qe (iv_0_flds_we[0]), + .q (reg2hw.iv[0].q), + .ds (), + .qs (iv_0_qs) + ); + assign reg2hw.iv[0].qe = iv_0_qe; + + + // Subregister 1 of Multireg iv + // R[iv_1]: V(True) + logic iv_1_qe; + logic [0:0] iv_1_flds_we; + assign iv_1_qe = &iv_1_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_iv_1 ( + .re (iv_1_re), + .we (iv_1_we), + .wd (iv_1_wd), + .d (hw2reg.iv[1].d), + .qre (), + .qe (iv_1_flds_we[0]), + .q (reg2hw.iv[1].q), + .ds (), + .qs (iv_1_qs) + ); + assign reg2hw.iv[1].qe = iv_1_qe; + + + // Subregister 2 of Multireg iv + // R[iv_2]: V(True) + logic iv_2_qe; + logic [0:0] iv_2_flds_we; + assign iv_2_qe = &iv_2_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_iv_2 ( + .re (iv_2_re), + .we (iv_2_we), + .wd (iv_2_wd), + .d (hw2reg.iv[2].d), + .qre (), + .qe (iv_2_flds_we[0]), + .q (reg2hw.iv[2].q), + .ds (), + .qs (iv_2_qs) + ); + assign reg2hw.iv[2].qe = iv_2_qe; + + + // Subregister 3 of Multireg iv + // R[iv_3]: V(True) + logic iv_3_qe; + logic [0:0] iv_3_flds_we; + assign iv_3_qe = &iv_3_flds_we; + caliptra_prim_subreg_ext #( + .DW (32) + ) u_iv_3 ( + .re (iv_3_re), + .we (iv_3_we), + .wd (iv_3_wd), + .d (hw2reg.iv[3].d), + .qre (), + .qe (iv_3_flds_we[0]), + .q (reg2hw.iv[3].q), + .ds (), + .qs (iv_3_qs) + ); + assign reg2hw.iv[3].qe = iv_3_qe; + + + // Subregister 0 of Multireg data_in + // R[data_in_0]: V(False) + logic data_in_0_qe; + logic [0:0] data_in_0_flds_we; + caliptra_prim_flop #( + .Width(1), + .ResetValue(0) + ) u_data_in0_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&data_in_0_flds_we), + .q_o(data_in_0_qe) + ); + caliptra_prim_subreg #( + .DW (32), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_data_in_0 ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (data_in_0_we), + .wd (data_in_0_wd), + + // from internal hardware + .de (hw2reg.data_in[0].de), + .d (hw2reg.data_in[0].d), + + // to internal hardware + .qe (data_in_0_flds_we[0]), + .q (reg2hw.data_in[0].q), + .ds (), + + // to register interface (read) + .qs () + ); + assign reg2hw.data_in[0].qe = data_in_0_qe; + + + // Subregister 1 of Multireg data_in + // R[data_in_1]: V(False) + logic data_in_1_qe; + logic [0:0] data_in_1_flds_we; + caliptra_prim_flop #( + .Width(1), + .ResetValue(0) + ) u_data_in1_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&data_in_1_flds_we), + .q_o(data_in_1_qe) + ); + caliptra_prim_subreg #( + .DW (32), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_data_in_1 ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (data_in_1_we), + .wd (data_in_1_wd), + + // from internal hardware + .de (hw2reg.data_in[1].de), + .d (hw2reg.data_in[1].d), + + // to internal hardware + .qe (data_in_1_flds_we[0]), + .q (reg2hw.data_in[1].q), + .ds (), + + // to register interface (read) + .qs () + ); + assign reg2hw.data_in[1].qe = data_in_1_qe; + + + // Subregister 2 of Multireg data_in + // R[data_in_2]: V(False) + logic data_in_2_qe; + logic [0:0] data_in_2_flds_we; + caliptra_prim_flop #( + .Width(1), + .ResetValue(0) + ) u_data_in2_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&data_in_2_flds_we), + .q_o(data_in_2_qe) + ); + caliptra_prim_subreg #( + .DW (32), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_data_in_2 ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (data_in_2_we), + .wd (data_in_2_wd), + + // from internal hardware + .de (hw2reg.data_in[2].de), + .d (hw2reg.data_in[2].d), + + // to internal hardware + .qe (data_in_2_flds_we[0]), + .q (reg2hw.data_in[2].q), + .ds (), + + // to register interface (read) + .qs () + ); + assign reg2hw.data_in[2].qe = data_in_2_qe; + + + // Subregister 3 of Multireg data_in + // R[data_in_3]: V(False) + logic data_in_3_qe; + logic [0:0] data_in_3_flds_we; + caliptra_prim_flop #( + .Width(1), + .ResetValue(0) + ) u_data_in3_qe ( + .clk_i(clk_i), + .rst_ni(rst_ni), + .d_i(&data_in_3_flds_we), + .q_o(data_in_3_qe) + ); + caliptra_prim_subreg #( + .DW (32), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (32'h0), + .Mubi (1'b0) + ) u_data_in_3 ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (data_in_3_we), + .wd (data_in_3_wd), + + // from internal hardware + .de (hw2reg.data_in[3].de), + .d (hw2reg.data_in[3].d), + + // to internal hardware + .qe (data_in_3_flds_we[0]), + .q (reg2hw.data_in[3].q), + .ds (), + + // to register interface (read) + .qs () + ); + assign reg2hw.data_in[3].qe = data_in_3_qe; + + + // Subregister 0 of Multireg data_out + // R[data_out_0]: V(True) + caliptra_prim_subreg_ext #( + .DW (32) + ) u_data_out_0 ( + .re (data_out_0_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.data_out[0].d), + .qre (reg2hw.data_out[0].re), + .qe (), + .q (reg2hw.data_out[0].q), + .ds (), + .qs (data_out_0_qs) + ); + + + // Subregister 1 of Multireg data_out + // R[data_out_1]: V(True) + caliptra_prim_subreg_ext #( + .DW (32) + ) u_data_out_1 ( + .re (data_out_1_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.data_out[1].d), + .qre (reg2hw.data_out[1].re), + .qe (), + .q (reg2hw.data_out[1].q), + .ds (), + .qs (data_out_1_qs) + ); + + + // Subregister 2 of Multireg data_out + // R[data_out_2]: V(True) + caliptra_prim_subreg_ext #( + .DW (32) + ) u_data_out_2 ( + .re (data_out_2_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.data_out[2].d), + .qre (reg2hw.data_out[2].re), + .qe (), + .q (reg2hw.data_out[2].q), + .ds (), + .qs (data_out_2_qs) + ); + + + // Subregister 3 of Multireg data_out + // R[data_out_3]: V(True) + caliptra_prim_subreg_ext #( + .DW (32) + ) u_data_out_3 ( + .re (data_out_3_re), + .we (1'b0), + .wd ('0), + .d (hw2reg.data_out[3].d), + .qre (reg2hw.data_out[3].re), + .qe (), + .q (reg2hw.data_out[3].q), + .ds (), + .qs (data_out_3_qs) + ); + + + // R[ctrl_shadowed]: V(True) + logic ctrl_shadowed_qe; + logic [5:0] ctrl_shadowed_flds_we; + assign ctrl_shadowed_qe = &ctrl_shadowed_flds_we; + // F[operation]: 1:0 + caliptra_prim_subreg_ext #( + .DW (2) + ) u_ctrl_shadowed_operation ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_operation_wd), + .d (hw2reg.ctrl_shadowed.operation.d), + .qre (reg2hw.ctrl_shadowed.operation.re), + .qe (ctrl_shadowed_flds_we[0]), + .q (reg2hw.ctrl_shadowed.operation.q), + .ds (), + .qs (ctrl_shadowed_operation_qs) + ); + assign reg2hw.ctrl_shadowed.operation.qe = ctrl_shadowed_qe; + + // F[mode]: 7:2 + caliptra_prim_subreg_ext #( + .DW (6) + ) u_ctrl_shadowed_mode ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_mode_wd), + .d (hw2reg.ctrl_shadowed.mode.d), + .qre (reg2hw.ctrl_shadowed.mode.re), + .qe (ctrl_shadowed_flds_we[1]), + .q (reg2hw.ctrl_shadowed.mode.q), + .ds (), + .qs (ctrl_shadowed_mode_qs) + ); + assign reg2hw.ctrl_shadowed.mode.qe = ctrl_shadowed_qe; + + // F[key_len]: 10:8 + caliptra_prim_subreg_ext #( + .DW (3) + ) u_ctrl_shadowed_key_len ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_key_len_wd), + .d (hw2reg.ctrl_shadowed.key_len.d), + .qre (reg2hw.ctrl_shadowed.key_len.re), + .qe (ctrl_shadowed_flds_we[2]), + .q (reg2hw.ctrl_shadowed.key_len.q), + .ds (), + .qs (ctrl_shadowed_key_len_qs) + ); + assign reg2hw.ctrl_shadowed.key_len.qe = ctrl_shadowed_qe; + + // F[sideload]: 11:11 + caliptra_prim_subreg_ext #( + .DW (1) + ) u_ctrl_shadowed_sideload ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_sideload_wd), + .d (hw2reg.ctrl_shadowed.sideload.d), + .qre (reg2hw.ctrl_shadowed.sideload.re), + .qe (ctrl_shadowed_flds_we[3]), + .q (reg2hw.ctrl_shadowed.sideload.q), + .ds (), + .qs (ctrl_shadowed_sideload_qs) + ); + assign reg2hw.ctrl_shadowed.sideload.qe = ctrl_shadowed_qe; + + // F[prng_reseed_rate]: 14:12 + caliptra_prim_subreg_ext #( + .DW (3) + ) u_ctrl_shadowed_prng_reseed_rate ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_prng_reseed_rate_wd), + .d (hw2reg.ctrl_shadowed.prng_reseed_rate.d), + .qre (reg2hw.ctrl_shadowed.prng_reseed_rate.re), + .qe (ctrl_shadowed_flds_we[4]), + .q (reg2hw.ctrl_shadowed.prng_reseed_rate.q), + .ds (), + .qs (ctrl_shadowed_prng_reseed_rate_qs) + ); + assign reg2hw.ctrl_shadowed.prng_reseed_rate.qe = ctrl_shadowed_qe; + + // F[manual_operation]: 15:15 + caliptra_prim_subreg_ext #( + .DW (1) + ) u_ctrl_shadowed_manual_operation ( + .re (ctrl_shadowed_re), + .we (ctrl_shadowed_we), + .wd (ctrl_shadowed_manual_operation_wd), + .d (hw2reg.ctrl_shadowed.manual_operation.d), + .qre (reg2hw.ctrl_shadowed.manual_operation.re), + .qe (ctrl_shadowed_flds_we[5]), + .q (reg2hw.ctrl_shadowed.manual_operation.q), + .ds (), + .qs (ctrl_shadowed_manual_operation_qs) + ); + assign reg2hw.ctrl_shadowed.manual_operation.qe = ctrl_shadowed_qe; + + + // R[ctrl_aux_shadowed]: V(False) + // Create REGWEN-gated WE signal + logic ctrl_aux_shadowed_gated_we; + assign ctrl_aux_shadowed_gated_we = ctrl_aux_shadowed_we & ctrl_aux_regwen_qs; + // F[key_touch_forces_reseed]: 0:0 + caliptra_prim_subreg_shadow #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_ctrl_aux_shadowed_key_touch_forces_reseed ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .rst_shadowed_ni (rst_shadowed_ni), + + // from register interface + .re (ctrl_aux_shadowed_re), + .we (ctrl_aux_shadowed_gated_we), + .wd (ctrl_aux_shadowed_key_touch_forces_reseed_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.ctrl_aux_shadowed.key_touch_forces_reseed.q), + .ds (), + + // to register interface (read) + .qs (ctrl_aux_shadowed_key_touch_forces_reseed_qs), + + // Shadow register phase. Relevant for hwext only. + .phase (), + + // Shadow register error conditions + .err_update (ctrl_aux_shadowed_key_touch_forces_reseed_update_err), + .err_storage (ctrl_aux_shadowed_key_touch_forces_reseed_storage_err) + ); + + // F[force_masks]: 1:1 + caliptra_prim_subreg_shadow #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRW), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_ctrl_aux_shadowed_force_masks ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .rst_shadowed_ni (rst_shadowed_ni), + + // from register interface + .re (ctrl_aux_shadowed_re), + .we (ctrl_aux_shadowed_gated_we), + .wd (ctrl_aux_shadowed_force_masks_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (reg2hw.ctrl_aux_shadowed.force_masks.q), + .ds (), + + // to register interface (read) + .qs (ctrl_aux_shadowed_force_masks_qs), + + // Shadow register phase. Relevant for hwext only. + .phase (), + + // Shadow register error conditions + .err_update (ctrl_aux_shadowed_force_masks_update_err), + .err_storage (ctrl_aux_shadowed_force_masks_storage_err) + ); + + + // R[ctrl_aux_regwen]: V(False) + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessW0C), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_ctrl_aux_regwen ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (ctrl_aux_regwen_we), + .wd (ctrl_aux_regwen_wd), + + // from internal hardware + .de (1'b0), + .d ('0), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (ctrl_aux_regwen_qs) + ); + + + // R[trigger]: V(False) + // F[start]: 0:0 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_trigger_start ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (trigger_we), + .wd (trigger_start_wd), + + // from internal hardware + .de (hw2reg.trigger.start.de), + .d (hw2reg.trigger.start.d), + + // to internal hardware + .qe (), + .q (reg2hw.trigger.start.q), + .ds (), + + // to register interface (read) + .qs () + ); + + // F[key_iv_data_in_clear]: 1:1 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_trigger_key_iv_data_in_clear ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (trigger_we), + .wd (trigger_key_iv_data_in_clear_wd), + + // from internal hardware + .de (hw2reg.trigger.key_iv_data_in_clear.de), + .d (hw2reg.trigger.key_iv_data_in_clear.d), + + // to internal hardware + .qe (), + .q (reg2hw.trigger.key_iv_data_in_clear.q), + .ds (), + + // to register interface (read) + .qs () + ); + + // F[data_out_clear]: 2:2 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_trigger_data_out_clear ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (trigger_we), + .wd (trigger_data_out_clear_wd), + + // from internal hardware + .de (hw2reg.trigger.data_out_clear.de), + .d (hw2reg.trigger.data_out_clear.d), + + // to internal hardware + .qe (), + .q (reg2hw.trigger.data_out_clear.q), + .ds (), + + // to register interface (read) + .qs () + ); + + // F[prng_reseed]: 3:3 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessWO), + .RESVAL (1'h1), + .Mubi (1'b0) + ) u_trigger_prng_reseed ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (trigger_we), + .wd (trigger_prng_reseed_wd), + + // from internal hardware + .de (hw2reg.trigger.prng_reseed.de), + .d (hw2reg.trigger.prng_reseed.d), + + // to internal hardware + .qe (), + .q (reg2hw.trigger.prng_reseed.q), + .ds (), + + // to register interface (read) + .qs () + ); + + + // R[status]: V(False) + // F[idle]: 0:0 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_idle ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.idle.de), + .d (hw2reg.status.idle.d), + + // to internal hardware + .qe (), + .q (reg2hw.status.idle.q), + .ds (), + + // to register interface (read) + .qs (status_idle_qs) + ); + + // F[stall]: 1:1 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_stall ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.stall.de), + .d (hw2reg.status.stall.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (status_stall_qs) + ); + + // F[output_lost]: 2:2 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_output_lost ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.output_lost.de), + .d (hw2reg.status.output_lost.d), + + // to internal hardware + .qe (), + .q (reg2hw.status.output_lost.q), + .ds (), + + // to register interface (read) + .qs (status_output_lost_qs) + ); + + // F[output_valid]: 3:3 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_output_valid ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.output_valid.de), + .d (hw2reg.status.output_valid.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (status_output_valid_qs) + ); + + // F[input_ready]: 4:4 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_input_ready ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.input_ready.de), + .d (hw2reg.status.input_ready.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (status_input_ready_qs) + ); + + // F[alert_recov_ctrl_update_err]: 5:5 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_alert_recov_ctrl_update_err ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.alert_recov_ctrl_update_err.de), + .d (hw2reg.status.alert_recov_ctrl_update_err.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (status_alert_recov_ctrl_update_err_qs) + ); + + // F[alert_fatal_fault]: 6:6 + caliptra_prim_subreg #( + .DW (1), + .SwAccess(caliptra_prim_subreg_pkg::SwAccessRO), + .RESVAL (1'h0), + .Mubi (1'b0) + ) u_status_alert_fatal_fault ( + .clk_i (clk_i), + .rst_ni (rst_ni), + + // from register interface + .we (1'b0), + .wd ('0), + + // from internal hardware + .de (hw2reg.status.alert_fatal_fault.de), + .d (hw2reg.status.alert_fatal_fault.d), + + // to internal hardware + .qe (), + .q (), + .ds (), + + // to register interface (read) + .qs (status_alert_fatal_fault_qs) + ); + + + // R[ctrl_gcm_shadowed]: V(True) + logic ctrl_gcm_shadowed_qe; + logic [1:0] ctrl_gcm_shadowed_flds_we; + assign ctrl_gcm_shadowed_qe = &ctrl_gcm_shadowed_flds_we; + // F[phase]: 5:0 + caliptra_prim_subreg_ext #( + .DW (6) + ) u_ctrl_gcm_shadowed_phase ( + .re (ctrl_gcm_shadowed_re), + .we (ctrl_gcm_shadowed_we), + .wd (ctrl_gcm_shadowed_phase_wd), + .d (hw2reg.ctrl_gcm_shadowed.phase.d), + .qre (reg2hw.ctrl_gcm_shadowed.phase.re), + .qe (ctrl_gcm_shadowed_flds_we[0]), + .q (reg2hw.ctrl_gcm_shadowed.phase.q), + .ds (), + .qs (ctrl_gcm_shadowed_phase_qs) + ); + assign reg2hw.ctrl_gcm_shadowed.phase.qe = ctrl_gcm_shadowed_qe; + + // F[num_valid_bytes]: 10:6 + caliptra_prim_subreg_ext #( + .DW (5) + ) u_ctrl_gcm_shadowed_num_valid_bytes ( + .re (ctrl_gcm_shadowed_re), + .we (ctrl_gcm_shadowed_we), + .wd (ctrl_gcm_shadowed_num_valid_bytes_wd), + .d (hw2reg.ctrl_gcm_shadowed.num_valid_bytes.d), + .qre (reg2hw.ctrl_gcm_shadowed.num_valid_bytes.re), + .qe (ctrl_gcm_shadowed_flds_we[1]), + .q (reg2hw.ctrl_gcm_shadowed.num_valid_bytes.q), + .ds (), + .qs (ctrl_gcm_shadowed_num_valid_bytes_qs) + ); + assign reg2hw.ctrl_gcm_shadowed.num_valid_bytes.qe = ctrl_gcm_shadowed_qe; + + + + logic [34:0] addr_hit; + always_comb begin + addr_hit = '0; + addr_hit[ 0] = (reg_addr == AES_ALERT_TEST_OFFSET); + addr_hit[ 1] = (reg_addr == AES_KEY_SHARE0_0_OFFSET); + addr_hit[ 2] = (reg_addr == AES_KEY_SHARE0_1_OFFSET); + addr_hit[ 3] = (reg_addr == AES_KEY_SHARE0_2_OFFSET); + addr_hit[ 4] = (reg_addr == AES_KEY_SHARE0_3_OFFSET); + addr_hit[ 5] = (reg_addr == AES_KEY_SHARE0_4_OFFSET); + addr_hit[ 6] = (reg_addr == AES_KEY_SHARE0_5_OFFSET); + addr_hit[ 7] = (reg_addr == AES_KEY_SHARE0_6_OFFSET); + addr_hit[ 8] = (reg_addr == AES_KEY_SHARE0_7_OFFSET); + addr_hit[ 9] = (reg_addr == AES_KEY_SHARE1_0_OFFSET); + addr_hit[10] = (reg_addr == AES_KEY_SHARE1_1_OFFSET); + addr_hit[11] = (reg_addr == AES_KEY_SHARE1_2_OFFSET); + addr_hit[12] = (reg_addr == AES_KEY_SHARE1_3_OFFSET); + addr_hit[13] = (reg_addr == AES_KEY_SHARE1_4_OFFSET); + addr_hit[14] = (reg_addr == AES_KEY_SHARE1_5_OFFSET); + addr_hit[15] = (reg_addr == AES_KEY_SHARE1_6_OFFSET); + addr_hit[16] = (reg_addr == AES_KEY_SHARE1_7_OFFSET); + addr_hit[17] = (reg_addr == AES_IV_0_OFFSET); + addr_hit[18] = (reg_addr == AES_IV_1_OFFSET); + addr_hit[19] = (reg_addr == AES_IV_2_OFFSET); + addr_hit[20] = (reg_addr == AES_IV_3_OFFSET); + addr_hit[21] = (reg_addr == AES_DATA_IN_0_OFFSET); + addr_hit[22] = (reg_addr == AES_DATA_IN_1_OFFSET); + addr_hit[23] = (reg_addr == AES_DATA_IN_2_OFFSET); + addr_hit[24] = (reg_addr == AES_DATA_IN_3_OFFSET); + addr_hit[25] = (reg_addr == AES_DATA_OUT_0_OFFSET); + addr_hit[26] = (reg_addr == AES_DATA_OUT_1_OFFSET); + addr_hit[27] = (reg_addr == AES_DATA_OUT_2_OFFSET); + addr_hit[28] = (reg_addr == AES_DATA_OUT_3_OFFSET); + addr_hit[29] = (reg_addr == AES_CTRL_SHADOWED_OFFSET); + addr_hit[30] = (reg_addr == AES_CTRL_AUX_SHADOWED_OFFSET); + addr_hit[31] = (reg_addr == AES_CTRL_AUX_REGWEN_OFFSET); + addr_hit[32] = (reg_addr == AES_TRIGGER_OFFSET); + addr_hit[33] = (reg_addr == AES_STATUS_OFFSET); + addr_hit[34] = (reg_addr == AES_CTRL_GCM_SHADOWED_OFFSET); + end + + assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ; + + // Check sub-word write is permitted + always_comb begin + wr_err = (reg_we & + ((addr_hit[ 0] & (|(AES_PERMIT[ 0] & ~reg_be))) | + (addr_hit[ 1] & (|(AES_PERMIT[ 1] & ~reg_be))) | + (addr_hit[ 2] & (|(AES_PERMIT[ 2] & ~reg_be))) | + (addr_hit[ 3] & (|(AES_PERMIT[ 3] & ~reg_be))) | + (addr_hit[ 4] & (|(AES_PERMIT[ 4] & ~reg_be))) | + (addr_hit[ 5] & (|(AES_PERMIT[ 5] & ~reg_be))) | + (addr_hit[ 6] & (|(AES_PERMIT[ 6] & ~reg_be))) | + (addr_hit[ 7] & (|(AES_PERMIT[ 7] & ~reg_be))) | + (addr_hit[ 8] & (|(AES_PERMIT[ 8] & ~reg_be))) | + (addr_hit[ 9] & (|(AES_PERMIT[ 9] & ~reg_be))) | + (addr_hit[10] & (|(AES_PERMIT[10] & ~reg_be))) | + (addr_hit[11] & (|(AES_PERMIT[11] & ~reg_be))) | + (addr_hit[12] & (|(AES_PERMIT[12] & ~reg_be))) | + (addr_hit[13] & (|(AES_PERMIT[13] & ~reg_be))) | + (addr_hit[14] & (|(AES_PERMIT[14] & ~reg_be))) | + (addr_hit[15] & (|(AES_PERMIT[15] & ~reg_be))) | + (addr_hit[16] & (|(AES_PERMIT[16] & ~reg_be))) | + (addr_hit[17] & (|(AES_PERMIT[17] & ~reg_be))) | + (addr_hit[18] & (|(AES_PERMIT[18] & ~reg_be))) | + (addr_hit[19] & (|(AES_PERMIT[19] & ~reg_be))) | + (addr_hit[20] & (|(AES_PERMIT[20] & ~reg_be))) | + (addr_hit[21] & (|(AES_PERMIT[21] & ~reg_be))) | + (addr_hit[22] & (|(AES_PERMIT[22] & ~reg_be))) | + (addr_hit[23] & (|(AES_PERMIT[23] & ~reg_be))) | + (addr_hit[24] & (|(AES_PERMIT[24] & ~reg_be))) | + (addr_hit[25] & (|(AES_PERMIT[25] & ~reg_be))) | + (addr_hit[26] & (|(AES_PERMIT[26] & ~reg_be))) | + (addr_hit[27] & (|(AES_PERMIT[27] & ~reg_be))) | + (addr_hit[28] & (|(AES_PERMIT[28] & ~reg_be))) | + (addr_hit[29] & (|(AES_PERMIT[29] & ~reg_be))) | + (addr_hit[30] & (|(AES_PERMIT[30] & ~reg_be))) | + (addr_hit[31] & (|(AES_PERMIT[31] & ~reg_be))) | + (addr_hit[32] & (|(AES_PERMIT[32] & ~reg_be))) | + (addr_hit[33] & (|(AES_PERMIT[33] & ~reg_be))) | + (addr_hit[34] & (|(AES_PERMIT[34] & ~reg_be))))); + end + + // Generate write-enables + assign alert_test_we = addr_hit[0] & reg_we & !reg_error; + + assign alert_test_recov_ctrl_update_err_wd = reg_wdata[0]; + + assign alert_test_fatal_fault_wd = reg_wdata[1]; + assign key_share0_0_we = addr_hit[1] & reg_we & !reg_error; + + assign key_share0_0_wd = reg_wdata[31:0]; + assign key_share0_1_we = addr_hit[2] & reg_we & !reg_error; + + assign key_share0_1_wd = reg_wdata[31:0]; + assign key_share0_2_we = addr_hit[3] & reg_we & !reg_error; + + assign key_share0_2_wd = reg_wdata[31:0]; + assign key_share0_3_we = addr_hit[4] & reg_we & !reg_error; + + assign key_share0_3_wd = reg_wdata[31:0]; + assign key_share0_4_we = addr_hit[5] & reg_we & !reg_error; + + assign key_share0_4_wd = reg_wdata[31:0]; + assign key_share0_5_we = addr_hit[6] & reg_we & !reg_error; + + assign key_share0_5_wd = reg_wdata[31:0]; + assign key_share0_6_we = addr_hit[7] & reg_we & !reg_error; + + assign key_share0_6_wd = reg_wdata[31:0]; + assign key_share0_7_we = addr_hit[8] & reg_we & !reg_error; + + assign key_share0_7_wd = reg_wdata[31:0]; + assign key_share1_0_we = addr_hit[9] & reg_we & !reg_error; + + assign key_share1_0_wd = reg_wdata[31:0]; + assign key_share1_1_we = addr_hit[10] & reg_we & !reg_error; + + assign key_share1_1_wd = reg_wdata[31:0]; + assign key_share1_2_we = addr_hit[11] & reg_we & !reg_error; + + assign key_share1_2_wd = reg_wdata[31:0]; + assign key_share1_3_we = addr_hit[12] & reg_we & !reg_error; + + assign key_share1_3_wd = reg_wdata[31:0]; + assign key_share1_4_we = addr_hit[13] & reg_we & !reg_error; + + assign key_share1_4_wd = reg_wdata[31:0]; + assign key_share1_5_we = addr_hit[14] & reg_we & !reg_error; + + assign key_share1_5_wd = reg_wdata[31:0]; + assign key_share1_6_we = addr_hit[15] & reg_we & !reg_error; + + assign key_share1_6_wd = reg_wdata[31:0]; + assign key_share1_7_we = addr_hit[16] & reg_we & !reg_error; + + assign key_share1_7_wd = reg_wdata[31:0]; + assign iv_0_re = addr_hit[17] & reg_re & !reg_error; + assign iv_0_we = addr_hit[17] & reg_we & !reg_error; + + assign iv_0_wd = reg_wdata[31:0]; + assign iv_1_re = addr_hit[18] & reg_re & !reg_error; + assign iv_1_we = addr_hit[18] & reg_we & !reg_error; + + assign iv_1_wd = reg_wdata[31:0]; + assign iv_2_re = addr_hit[19] & reg_re & !reg_error; + assign iv_2_we = addr_hit[19] & reg_we & !reg_error; + + assign iv_2_wd = reg_wdata[31:0]; + assign iv_3_re = addr_hit[20] & reg_re & !reg_error; + assign iv_3_we = addr_hit[20] & reg_we & !reg_error; + + assign iv_3_wd = reg_wdata[31:0]; + assign data_in_0_we = addr_hit[21] & reg_we & !reg_error; + + assign data_in_0_wd = reg_wdata[31:0]; + assign data_in_1_we = addr_hit[22] & reg_we & !reg_error; + + assign data_in_1_wd = reg_wdata[31:0]; + assign data_in_2_we = addr_hit[23] & reg_we & !reg_error; + + assign data_in_2_wd = reg_wdata[31:0]; + assign data_in_3_we = addr_hit[24] & reg_we & !reg_error; + + assign data_in_3_wd = reg_wdata[31:0]; + assign data_out_0_re = addr_hit[25] & reg_re & !reg_error; + assign data_out_1_re = addr_hit[26] & reg_re & !reg_error; + assign data_out_2_re = addr_hit[27] & reg_re & !reg_error; + assign data_out_3_re = addr_hit[28] & reg_re & !reg_error; + assign ctrl_shadowed_re = addr_hit[29] & reg_re & !reg_error; + assign ctrl_shadowed_we = addr_hit[29] & reg_we & !reg_error; + + assign ctrl_shadowed_operation_wd = reg_wdata[1:0]; + + assign ctrl_shadowed_mode_wd = reg_wdata[7:2]; + + assign ctrl_shadowed_key_len_wd = reg_wdata[10:8]; + + assign ctrl_shadowed_sideload_wd = reg_wdata[11]; + + assign ctrl_shadowed_prng_reseed_rate_wd = reg_wdata[14:12]; + + assign ctrl_shadowed_manual_operation_wd = reg_wdata[15]; + assign ctrl_aux_shadowed_re = addr_hit[30] & reg_re & !reg_error; + assign ctrl_aux_shadowed_we = addr_hit[30] & reg_we & !reg_error; + + assign ctrl_aux_shadowed_key_touch_forces_reseed_wd = reg_wdata[0]; + + assign ctrl_aux_shadowed_force_masks_wd = reg_wdata[1]; + assign ctrl_aux_regwen_we = addr_hit[31] & reg_we & !reg_error; + + assign ctrl_aux_regwen_wd = reg_wdata[0]; + assign trigger_we = addr_hit[32] & reg_we & !reg_error; + + assign trigger_start_wd = reg_wdata[0]; + + assign trigger_key_iv_data_in_clear_wd = reg_wdata[1]; + + assign trigger_data_out_clear_wd = reg_wdata[2]; + + assign trigger_prng_reseed_wd = reg_wdata[3]; + assign ctrl_gcm_shadowed_re = addr_hit[34] & reg_re & !reg_error; + assign ctrl_gcm_shadowed_we = addr_hit[34] & reg_we & !reg_error; + + assign ctrl_gcm_shadowed_phase_wd = reg_wdata[5:0]; + + assign ctrl_gcm_shadowed_num_valid_bytes_wd = reg_wdata[10:6]; + + // Assign write-enables to checker logic vector. + always_comb begin + reg_we_check = '0; + reg_we_check[0] = alert_test_we; + reg_we_check[1] = key_share0_0_we; + reg_we_check[2] = key_share0_1_we; + reg_we_check[3] = key_share0_2_we; + reg_we_check[4] = key_share0_3_we; + reg_we_check[5] = key_share0_4_we; + reg_we_check[6] = key_share0_5_we; + reg_we_check[7] = key_share0_6_we; + reg_we_check[8] = key_share0_7_we; + reg_we_check[9] = key_share1_0_we; + reg_we_check[10] = key_share1_1_we; + reg_we_check[11] = key_share1_2_we; + reg_we_check[12] = key_share1_3_we; + reg_we_check[13] = key_share1_4_we; + reg_we_check[14] = key_share1_5_we; + reg_we_check[15] = key_share1_6_we; + reg_we_check[16] = key_share1_7_we; + reg_we_check[17] = iv_0_we; + reg_we_check[18] = iv_1_we; + reg_we_check[19] = iv_2_we; + reg_we_check[20] = iv_3_we; + reg_we_check[21] = data_in_0_we; + reg_we_check[22] = data_in_1_we; + reg_we_check[23] = data_in_2_we; + reg_we_check[24] = data_in_3_we; + reg_we_check[25] = 1'b0; + reg_we_check[26] = 1'b0; + reg_we_check[27] = 1'b0; + reg_we_check[28] = 1'b0; + reg_we_check[29] = ctrl_shadowed_we; + reg_we_check[30] = ctrl_aux_shadowed_gated_we; + reg_we_check[31] = ctrl_aux_regwen_we; + reg_we_check[32] = trigger_we; + reg_we_check[33] = 1'b0; + reg_we_check[34] = ctrl_gcm_shadowed_we; + end + + // Read data return + always_comb begin + reg_rdata_next = '0; + unique case (1'b1) + addr_hit[0]: begin + reg_rdata_next[0] = '0; + reg_rdata_next[1] = '0; + end + + addr_hit[1]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[2]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[3]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[4]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[5]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[6]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[7]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[8]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[9]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[10]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[11]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[12]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[13]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[14]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[15]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[16]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[17]: begin + reg_rdata_next[31:0] = iv_0_qs; + end + + addr_hit[18]: begin + reg_rdata_next[31:0] = iv_1_qs; + end + + addr_hit[19]: begin + reg_rdata_next[31:0] = iv_2_qs; + end + + addr_hit[20]: begin + reg_rdata_next[31:0] = iv_3_qs; + end + + addr_hit[21]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[22]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[23]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[24]: begin + reg_rdata_next[31:0] = '0; + end + + addr_hit[25]: begin + reg_rdata_next[31:0] = data_out_0_qs; + end + + addr_hit[26]: begin + reg_rdata_next[31:0] = data_out_1_qs; + end + + addr_hit[27]: begin + reg_rdata_next[31:0] = data_out_2_qs; + end + + addr_hit[28]: begin + reg_rdata_next[31:0] = data_out_3_qs; + end + + addr_hit[29]: begin + reg_rdata_next[1:0] = ctrl_shadowed_operation_qs; + reg_rdata_next[7:2] = ctrl_shadowed_mode_qs; + reg_rdata_next[10:8] = ctrl_shadowed_key_len_qs; + reg_rdata_next[11] = ctrl_shadowed_sideload_qs; + reg_rdata_next[14:12] = ctrl_shadowed_prng_reseed_rate_qs; + reg_rdata_next[15] = ctrl_shadowed_manual_operation_qs; + end + + addr_hit[30]: begin + reg_rdata_next[0] = ctrl_aux_shadowed_key_touch_forces_reseed_qs; + reg_rdata_next[1] = ctrl_aux_shadowed_force_masks_qs; + end + + addr_hit[31]: begin + reg_rdata_next[0] = ctrl_aux_regwen_qs; + end + + addr_hit[32]: begin + reg_rdata_next[0] = '0; + reg_rdata_next[1] = '0; + reg_rdata_next[2] = '0; + reg_rdata_next[3] = '0; + end + + addr_hit[33]: begin + reg_rdata_next[0] = status_idle_qs; + reg_rdata_next[1] = status_stall_qs; + reg_rdata_next[2] = status_output_lost_qs; + reg_rdata_next[3] = status_output_valid_qs; + reg_rdata_next[4] = status_input_ready_qs; + reg_rdata_next[5] = status_alert_recov_ctrl_update_err_qs; + reg_rdata_next[6] = status_alert_fatal_fault_qs; + end + + addr_hit[34]: begin + reg_rdata_next[5:0] = ctrl_gcm_shadowed_phase_qs; + reg_rdata_next[10:6] = ctrl_gcm_shadowed_num_valid_bytes_qs; + end + + default: begin + reg_rdata_next = '1; + end + endcase + end + + // shadow busy + logic shadow_busy; + logic rst_done; + logic shadow_rst_done; + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + rst_done <= '0; + end else begin + rst_done <= 1'b1; + end + end + + always_ff @(posedge clk_i or negedge rst_shadowed_ni) begin + if (!rst_shadowed_ni) begin + shadow_rst_done <= '0; + end else begin + shadow_rst_done <= 1'b1; + end + end + + // both shadow and normal resets have been released + assign shadow_busy = ~(rst_done & shadow_rst_done); + + // Collect up storage and update errors + assign shadowed_storage_err_o = |{ + ctrl_aux_shadowed_key_touch_forces_reseed_storage_err, + ctrl_aux_shadowed_force_masks_storage_err + }; + assign shadowed_update_err_o = |{ + ctrl_aux_shadowed_key_touch_forces_reseed_update_err, + ctrl_aux_shadowed_force_masks_update_err + }; + + // register busy + assign reg_busy = shadow_busy; + + // Unused signal tieoff + + // wdata / byte enable are not always fully used + // add a blanket unused statement to handle lint waivers + logic unused_wdata; + logic unused_be; + assign unused_wdata = ^reg_wdata; + assign unused_be = ^reg_be; + + // Assertions for Register Interface + `CALIPTRA_ASSERT_PULSE(wePulse, reg_we, clk_i, !rst_ni) + `CALIPTRA_ASSERT_PULSE(rePulse, reg_re, clk_i, !rst_ni) + + `CALIPTRA_ASSERT(reAfterRv, $rose(reg_re || reg_we) |=> tl_o_pre.d_valid, clk_i, !rst_ni) + + `CALIPTRA_ASSERT(en2addrHit, (reg_we || reg_re) |-> $onehot0(addr_hit), clk_i, !rst_ni) + + // this is formulated as an assumption such that the FPV testbenches do disprove this + // property by mistake + //`ASSUME(reqParity, tl_reg_h2d.a_valid |-> tl_reg_h2d.a_user.chk_en == caliptra_tlul_pkg::CheckDis) + +endmodule diff --git a/src/aes/rtl/aes_rev_info b/src/aes/rtl/aes_rev_info new file mode 100644 index 000000000..6c07c38b2 --- /dev/null +++ b/src/aes/rtl/aes_rev_info @@ -0,0 +1,12 @@ +commit e9437d6dc68b9884e2a76571d70edf17ba8ed72d +Author: Andrea Caforio +Date: Fri Dec 13 13:39:43 2024 +0100 + + [aes, pre-dv] Remove test vector redundancies + + Firstly, this commit removes some redundant instructions in the test + vector sequences, e.g., unnecessary writes to the `CTRL_GCM` register. + Secondly, some redundant polls for the `IDLE` bit in the `STATUS` + register are replaced with polls for the `INPUT_READY` bit. + + Signed-off-by: Andrea Caforio diff --git a/src/aes/rtl/aes_sbox.sv b/src/aes/rtl/aes_sbox.sv index 1464dd184..66be52651 100644 --- a/src/aes/rtl/aes_sbox.sv +++ b/src/aes/rtl/aes_sbox.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -6,9 +6,7 @@ `include "caliptra_prim_assert.sv" -module aes_sbox - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_sbox import aes_pkg::*; #( parameter sbox_impl_e SecSBoxImpl = SBoxImplLut ) ( diff --git a/src/aes/rtl/aes_sbox_canright.sv b/src/aes/rtl/aes_sbox_canright.sv index f43b2dbca..232a59f08 100644 --- a/src/aes/rtl/aes_sbox_canright.sv +++ b/src/aes/rtl/aes_sbox_canright.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -13,7 +13,6 @@ module aes_sbox_canright ( output logic [7:0] data_o ); - import aes_reg_pkg::*; import aes_pkg::*; import aes_sbox_canright_pkg::*; diff --git a/src/aes/rtl/aes_sbox_canright_masked.sv b/src/aes/rtl/aes_sbox_canright_masked.sv index 254b0da96..6bb9be5bf 100644 --- a/src/aes/rtl/aes_sbox_canright_masked.sv +++ b/src/aes/rtl/aes_sbox_canright_masked.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -40,7 +40,6 @@ module aes_masked_inverse_gf2p4 ( output logic [3:0] b_inv ); - import aes_reg_pkg::*; import aes_pkg::*; import aes_sbox_canright_pkg::*; diff --git a/src/aes/rtl/aes_sbox_canright_masked_noreuse.sv b/src/aes/rtl/aes_sbox_canright_masked_noreuse.sv index 02475cb7b..ba8184c68 100644 --- a/src/aes/rtl/aes_sbox_canright_masked_noreuse.sv +++ b/src/aes/rtl/aes_sbox_canright_masked_noreuse.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -39,7 +39,6 @@ module aes_masked_inverse_gf2p4_noreuse ( output logic [3:0] b_inv ); - import aes_reg_pkg::*; import aes_pkg::*; import aes_sbox_canright_pkg::*; diff --git a/src/aes/rtl/aes_sbox_canright_pkg.sv b/src/aes/rtl/aes_sbox_canright_pkg.sv index c5f8f810c..d520fc92d 100644 --- a/src/aes/rtl/aes_sbox_canright_pkg.sv +++ b/src/aes/rtl/aes_sbox_canright_pkg.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // diff --git a/src/aes/rtl/aes_sbox_dom.sv b/src/aes/rtl/aes_sbox_dom.sv index 9e2d92e4d..973d8b088 100644 --- a/src/aes/rtl/aes_sbox_dom.sv +++ b/src/aes/rtl/aes_sbox_dom.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -47,7 +47,7 @@ typedef struct packed { logic [3:0] prd_2; logic [7:0] prd_3; logic [7:0] prd_4; -} prd_in_t; +} aes_sbox_dom_prd_in_t; // Packed struct for pseudo-random data (PRD) output. Stages 2 and 3 produce 8 bits each. Stage 1 // produces just 4 bits. @@ -55,7 +55,7 @@ typedef struct packed { logic [3:0] prd_1; logic [7:0] prd_2; logic [7:0] prd_3; -} prd_out_t; +} aes_sbox_dom_prd_out_t; // DOM-indep GF(2^N) multiplier, first-order masked. // Computes (a_q ^ b_q) = (a_x ^ b_x) * (a_y ^ b_y), i.e. q = x * y using first-order @@ -531,7 +531,7 @@ module aes_dom_dep_mul_gf2pn #( end else begin : gen_not_pre_dom_indep // This DOM-dep multiplier is not directly followed by an un-pipelined DOM-indep multiplier. As - // a result, the the d_y and _D_y_z0 parts of d_b can be summed up prior to the multiplication + // a result, the d_y and _D_y_z0 parts of d_b can be summed up prior to the multiplication // with input x which allows saving 2 GF multipliers. // Sum up d_y and _D_y_z0. @@ -795,16 +795,16 @@ endmodule module aes_dom_inverse_gf2p8 #( parameter bit PipelineMul = 1'b1 ) ( - input logic clk_i, - input logic rst_ni, - input logic [3:0] we_i, - input logic [7:0] a_y, // input data masked by b_y - input logic [7:0] b_y, // input mask - input prd_in_t prd_i, // pseudo-random data, e.g. for intermediate masks - output logic [7:0] a_y_inv, // output data masked by b_y_inv - output logic [7:0] b_y_inv, // output mask - output prd_out_t prd_o // pseudo-random data, e.g. for use in another S-Box instance -); + input logic clk_i, + input logic rst_ni, + input logic [3:0] we_i, + input logic [7:0] a_y, // input data masked by b_y + input logic [7:0] b_y, // input mask + input aes_sbox_dom_prd_in_t prd_i, // pseudo-random data, e.g. for intermediate masks + output logic [7:0] a_y_inv, // output data masked by b_y_inv + output logic [7:0] b_y_inv, // output mask + output aes_sbox_dom_prd_out_t prd_o // pseudo-random data, e.g. for use in another S-Box +); // instance import aes_sbox_canright_pkg::*; @@ -1000,16 +1000,14 @@ module aes_sbox_dom output logic [19:0] prd_o // PRD for usage in Stages 2 - 4 of other S-Box instances ); - import aes_reg_pkg::*; import aes_pkg::*; import aes_sbox_canright_pkg::*; - logic [7:0] in_data_basis_x, out_data_basis_x; - logic [7:0] in_mask_basis_x, out_mask_basis_x; - logic [3:0] we; - logic [7:0] prd1_d, prd1_q; - prd_in_t in_prd; - prd_out_t out_prd; + logic [7:0] in_data_basis_x, out_data_basis_x; + logic [7:0] in_mask_basis_x, out_mask_basis_x; + logic [3:0] we; + aes_sbox_dom_prd_in_t in_prd; + aes_sbox_dom_prd_out_t out_prd; // Convert data to normal basis X. assign in_data_basis_x = (op_i == CIPH_FWD) ? aes_mvm(data_i, A2X) : @@ -1068,19 +1066,9 @@ module aes_sbox_dom assign we[2] = en_i & count_q == 3'd2; assign we[3] = en_i & count_q == 3'd3; - // Buffer and forward PRD for the individual stages. We get 8 bits from the PRNG for usage in the - // first cycle. Stages 2, 3 and 4 are driven by other S-Box instances. - assign prd1_d = we[0] ? prd_i[7:0] : prd1_q; - caliptra_prim_flop #( - .Width ( 8 ), - .ResetValue ( '0 ) - ) u_caliptra_prim_flop_prd1_q ( - .clk_i ( clk_i ), - .rst_ni ( rst_ni ), - .d_i ( prd1_d ), - .q_o ( prd1_q ) - ); - assign in_prd = '{prd_1: prd1_d, + // PRD forwarding for the individual stages. We get 8 bits from the PRNG for usage in Stage 1. + // Stages 2, 3 and 4 are driven by other S-Box instances. + assign in_prd = '{prd_1: prd_i[7:0], prd_2: prd_i[11:8], prd_3: prd_i[19:12], prd_4: prd_i[27:20]}; diff --git a/src/aes/rtl/aes_sbox_lut.sv b/src/aes/rtl/aes_sbox_lut.sv index 4861537a3..94064a3a8 100644 --- a/src/aes/rtl/aes_sbox_lut.sv +++ b/src/aes/rtl/aes_sbox_lut.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -10,7 +10,6 @@ module aes_sbox_lut ( output logic [7:0] data_o ); - import aes_reg_pkg::*; import aes_pkg::*; // Define the LUTs diff --git a/src/aes/rtl/aes_sel_buf_chk.sv b/src/aes/rtl/aes_sel_buf_chk.sv index 86423c778..335eeb60e 100644 --- a/src/aes/rtl/aes_sel_buf_chk.sv +++ b/src/aes/rtl/aes_sel_buf_chk.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -23,7 +23,6 @@ module aes_sel_buf_chk #( output logic err_o ); - import aes_reg_pkg::*; import aes_pkg::*; // Tie off unused inputs. diff --git a/src/aes/rtl/aes_shift_rows.sv b/src/aes/rtl/aes_shift_rows.sv index 537a03fcc..e8df6f0e2 100644 --- a/src/aes/rtl/aes_shift_rows.sv +++ b/src/aes/rtl/aes_shift_rows.sv @@ -1,4 +1,4 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // @@ -10,7 +10,6 @@ module aes_shift_rows ( output logic [3:0][3:0][7:0] data_o ); - import aes_reg_pkg::*; import aes_pkg::*; // Row 0 is left untouched diff --git a/src/aes/rtl/aes_sub_bytes.sv b/src/aes/rtl/aes_sub_bytes.sv index b948b4358..11e7254d9 100644 --- a/src/aes/rtl/aes_sub_bytes.sv +++ b/src/aes/rtl/aes_sub_bytes.sv @@ -1,12 +1,10 @@ -// Copyright lowRISC contributors. +// Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 // // AES SubBytes -module aes_sub_bytes - import aes_reg_pkg::*; - import aes_pkg::*; +module aes_sub_bytes import aes_pkg::*; #( parameter sbox_impl_e SecSBoxImpl = SBoxImplDom ) ( diff --git a/src/aes/rtl/aes_wrap.sv b/src/aes/rtl/aes_wrap.sv new file mode 100644 index 000000000..28a438188 --- /dev/null +++ b/src/aes/rtl/aes_wrap.sv @@ -0,0 +1,581 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// AES wrapper for FI experiments + +module aes_wrap + import aes_pkg::*; +#( + parameter bit AES192Enable = 1, // Can be 0 (disable), or 1 (enable). + parameter bit SecMasking = 1, // Can be 0 (no masking), or + // 1 (first-order masking) of the cipher + // core. Masking requires the use of a + // masked S-Box, see SBoxImpl parameter. + // Note: currently, constant masks are + // used, this is of course not secure. + parameter sbox_impl_e SecSBoxImpl = SBoxImplDom // See aes_pkg.sv +) ( + input logic clk_i, + input logic rst_ni, + + input logic [127:0] aes_input, + input logic [255:0] aes_key, + output logic [127:0] aes_output, + + output logic alert_recov_o, + output logic alert_fatal_o, + + output logic test_done_o +); + + localparam logic SIDELOAD = 1'b1; + localparam aes_mode_e AES_MODE = AES_ECB; + + import aes_reg_pkg::*; + import caliptra_tlul_pkg::*; + + logic unused_idle; + logic [31:0] unused_wdata; + logic edn_req; + keymgr_pkg::hw_key_req_t keymgr_key; + tl_h2d_t h2d, h2d_intg; // req + tl_d2h_t d2h; // rsp + caliptra_prim_alert_pkg::alert_rx_t [NumAlerts-1:0] alert_rx; + caliptra_prim_alert_pkg::alert_tx_t [NumAlerts-1:0] alert_tx; + + // Sideload interface - allows for quicker simulation. + assign keymgr_key.valid = 1'b1; + assign keymgr_key.key[0][255:0] = aes_key; + assign keymgr_key.key[1][255:0] = '0; + + // Alert receivers + assign alert_rx[0].ping_p = 1'b0; + assign alert_rx[0].ping_n = 1'b1; + assign alert_rx[0].ack_p = 1'b0; + assign alert_rx[0].ack_n = 1'b1; + assign alert_rx[1].ping_p = 1'b0; + assign alert_rx[1].ping_n = 1'b1; + assign alert_rx[1].ack_p = 1'b0; + assign alert_rx[1].ack_n = 1'b1; + + // Alert transceivers + assign alert_recov_o = alert_tx[0].alert_p | ~alert_tx[0].alert_n; + assign alert_fatal_o = alert_tx[1].alert_p | ~alert_tx[1].alert_n; + + // Command integrity generation + caliptra_tlul_cmd_intg_gen caliptra_tlul_cmd_intg_gen ( + .tl_i(h2d), + .tl_o(h2d_intg) + ); + + // Data integrity generation + caliptra_prim_secded_inv_39_32_enc u_data_gen ( + .data_i (h2d.a_data), + .data_o ({h2d_intg.a_user.data_intg, unused_wdata}) + ); + + // DUT + aes #( + .AES192Enable(AES192Enable), + .SecMasking(SecMasking), + .SecSBoxImpl(SecSBoxImpl) + ) aes ( + .clk_i (clk_i), + .rst_ni (rst_ni), + .rst_shadowed_ni (rst_ni), + .idle_o (unused_idle), + .lc_escalate_en_i(lc_ctrl_pkg::Off), + .clk_edn_i (clk_i), + .rst_edn_ni (rst_ni), + .edn_o (edn_req), + .edn_i ({edn_req, 1'b1, 32'h12345678}), + .keymgr_key_i (keymgr_key), + .tl_i (h2d_intg), + .tl_o (d2h), + .alert_rx_i (alert_rx), + .alert_tx_o (alert_tx) + ); + + // FSM + localparam int StateWidth = BlockAw; + typedef enum logic [StateWidth-1:0] { + IDLE, + W_KEY_SHARE0_0, + W_KEY_SHARE0_1, + W_KEY_SHARE0_2, + W_KEY_SHARE0_3, + W_KEY_SHARE0_4, + W_KEY_SHARE0_5, + W_KEY_SHARE0_6, + W_KEY_SHARE0_7, + W_KEY_SHARE1_0, + W_KEY_SHARE1_1, + W_KEY_SHARE1_2, + W_KEY_SHARE1_3, + W_KEY_SHARE1_4, + W_KEY_SHARE1_5, + W_KEY_SHARE1_6, + W_KEY_SHARE1_7, + W_IV_0, + W_IV_1, + W_IV_2, + W_IV_3, + W_DATA_IN_0, + W_DATA_IN_1, + W_DATA_IN_2, + W_DATA_IN_3, + R_DATA_OUT_0, + R_DATA_OUT_1, + R_DATA_OUT_2, + R_DATA_OUT_3, + W_CTRL_SHADOWED, + W_CTRL_AUX_SHADOWED, + W_TRIGGER_OFFSET, + R_STATUS, + FINISH + } aes_wrap_ctrl_e; + aes_wrap_ctrl_e aes_wrap_ctrl_ns, aes_wrap_ctrl_cs; + logic [31:0] count_d, count_q; + logic [127:0] data_out_d, data_out_q; + + always_comb begin : aes_wrap_fsm + // TL-UL + h2d.a_valid = 1'b0; + h2d.a_opcode = PutFullData; + h2d.a_param = 3'h0; // static + h2d.a_size = 2'h2; // static + h2d.a_source = 8'h0; // static + h2d.a_address = 32'hAAAAAAA8; + h2d.a_mask = 4'hF; // static + h2d.a_data = 32'h55555555; + h2d.a_user.rsvd = '0; // static + h2d.a_user.instr_type = caliptra_prim_mubi_pkg::MuBi4False; // static (Data) + h2d.a_user.cmd_intg = '0; // will be driven by tlul_cmd_intg_gen + h2d.a_user.data_intg = '0; // will be driven by caliptra_prim_secded_enc + h2d.d_ready = 1'b1; // static + + // FSM + aes_wrap_ctrl_ns = aes_wrap_ctrl_cs; + count_d = count_q + 32'h1; + data_out_d = data_out_q; + test_done_o = 1'b0; + + unique case (aes_wrap_ctrl_cs) + + IDLE: begin + // Poll the status register until the DUT has finished initialization and becomes idle. + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_STATUS_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + if (d2h.d_data[0] == 1'b1) begin + // Once the DUT is idle, we can start the configuration sequence and clear the counter. + aes_wrap_ctrl_ns = W_CTRL_AUX_SHADOWED; + count_d = 32'h0; + end + end + end + + W_CTRL_AUX_SHADOWED: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_CTRL_AUX_SHADOWED_OFFSET}; + h2d.a_data = 32'h0; + + // We can't do back to back transactions. De-assert valid while receiving response. + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + end + + // The shadow reg needs to be written twice. + if (count_q >= 32'h3 && d2h.d_valid) begin + aes_wrap_ctrl_ns = W_CTRL_SHADOWED; + end + end + + W_CTRL_SHADOWED: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_CTRL_SHADOWED_OFFSET}; + h2d.a_data = {18'h0, 1'b0 ,1'b0, SIDELOAD, AES_128, AES_MODE, AES_ENC}; + + // We can't do back to back transactions. De-assert valid while receiving response. + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + end + + // The shadow reg needs to be written twice. + if (count_q >= 32'h7 && d2h.d_valid) begin + aes_wrap_ctrl_ns = SIDELOAD == 1'b1 ? + (AES_MODE == AES_ECB ? W_DATA_IN_0 : W_IV_0) : W_KEY_SHARE0_0; + end + end + + W_KEY_SHARE0_0: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_0_OFFSET}; + h2d.a_data = aes_key[31:0]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_1; + end + end + + W_KEY_SHARE0_1: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_1_OFFSET}; + h2d.a_data = aes_key[63:32]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_2; + end + end + + W_KEY_SHARE0_2: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_2_OFFSET}; + h2d.a_data = aes_key[95:64]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_3; + end + end + + W_KEY_SHARE0_3: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_3_OFFSET}; + h2d.a_data = aes_key[127:96]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_4; + end + end + + W_KEY_SHARE0_4: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_4_OFFSET}; + h2d.a_data = aes_key[159:128]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_5; + end + end + + W_KEY_SHARE0_5: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_5_OFFSET}; + h2d.a_data = aes_key[195:160]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_6; + end + end + + W_KEY_SHARE0_6: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_6_OFFSET}; + h2d.a_data = aes_key[227:196]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE0_7; + end + end + + W_KEY_SHARE0_7: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE0_7_OFFSET}; + h2d.a_data = aes_key[255:228]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_0; + end + end + + W_KEY_SHARE1_0: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_0_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_1; + end + end + + W_KEY_SHARE1_1: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_1_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_2; + end + end + + W_KEY_SHARE1_2: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_2_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_3; + end + end + + W_KEY_SHARE1_3: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_3_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_4; + end + end + + W_KEY_SHARE1_4: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_4_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_5; + end + end + + W_KEY_SHARE1_5: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_5_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_6; + end + end + + W_KEY_SHARE1_6: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_6_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_KEY_SHARE1_7; + end + end + + W_KEY_SHARE1_7: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_KEY_SHARE1_7_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = AES_MODE == AES_ECB ? W_DATA_IN_0 : W_IV_0; + end + end + + W_IV_0: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_IV_0_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_IV_1; + end + end + + W_IV_1: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_IV_1_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_IV_2; + end + end + + W_IV_2: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_IV_2_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_IV_3; + end + end + + W_IV_3: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_IV_3_OFFSET}; + h2d.a_data = '0; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_DATA_IN_0; + end + end + + W_DATA_IN_0: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_IN_0_OFFSET}; + h2d.a_data = aes_input[31:0]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_DATA_IN_1; + end + end + + W_DATA_IN_1: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_IN_1_OFFSET}; + h2d.a_data = aes_input[63:32]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_DATA_IN_2; + end + end + + W_DATA_IN_2: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_IN_2_OFFSET}; + h2d.a_data = aes_input[95:64]; + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = W_DATA_IN_3; + end + end + + W_DATA_IN_3: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = PutFullData; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_IN_3_OFFSET}; + h2d.a_data = aes_input[127:96]; + if (d2h.d_valid) begin + // Clear the counter to serve as a reference for the experiments. + h2d.a_valid = 1'b0; + aes_wrap_ctrl_ns = R_STATUS; + count_d = '0; + end + end + + R_STATUS: begin + // After providing the last data word, the DUT will start. Poll the status register until + // the DUT is idle and has valid output data. + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_STATUS_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + if ((d2h.d_data[0] == 1'b1) && (d2h.d_data[3] == 1'b1)) begin + aes_wrap_ctrl_ns = R_DATA_OUT_0; + end + end + end + + R_DATA_OUT_0: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_OUT_0_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + data_out_d[31:0] = d2h.d_data; + aes_wrap_ctrl_ns = R_DATA_OUT_1; + end + end + + R_DATA_OUT_1: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_OUT_1_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + data_out_d[63:32] = d2h.d_data; + aes_wrap_ctrl_ns = R_DATA_OUT_2; + end + end + + R_DATA_OUT_2: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_OUT_2_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + data_out_d[95:64] = d2h.d_data; + aes_wrap_ctrl_ns = R_DATA_OUT_3; + end + end + + R_DATA_OUT_3: begin + h2d.a_valid = 1'b1; + h2d.a_opcode = Get; + h2d.a_address = {{{32-BlockAw}{1'b0}}, AES_DATA_OUT_3_OFFSET}; + + if (d2h.d_valid) begin + h2d.a_valid = 1'b0; + data_out_d[127:96] = d2h.d_data; + aes_wrap_ctrl_ns = FINISH; + end + end + + FINISH: begin + // Just signal end of simulation. + test_done_o = 1'b1; + end + + default: begin + aes_wrap_ctrl_ns = FINISH; + end + endcase // aes_wrap_ctrl_cs + + // We can't handle TL-UL errors. Abort. + if (d2h.d_valid && d2h.d_error) begin + aes_wrap_ctrl_ns = FINISH; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : fsm_reg + if (!rst_ni) begin + aes_wrap_ctrl_cs <= IDLE; + count_q <= 32'b0; + end else begin + aes_wrap_ctrl_cs <= aes_wrap_ctrl_ns; + count_q <= count_d; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin : data_out_reg + if (!rst_ni) begin + data_out_q <= '0; + end else begin + data_out_q <= data_out_d; + end + end + assign aes_output = data_out_q; + +endmodule diff --git a/src/axi/config/axi_dma.vf b/src/axi/config/axi_dma.vf index f71cf6b19..863063a4c 100644 --- a/src/axi/config/axi_dma.vf +++ b/src/axi/config/axi_dma.vf @@ -1,9 +1,9 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl ${CALIPTRA_ROOT}/src/integration/rtl/config_defines.svh ${CALIPTRA_ROOT}/src/integration/rtl/caliptra_reg_defines.svh @@ -18,6 +18,11 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv +${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv +${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv +${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -25,14 +30,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv -${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv -${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -67,6 +70,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv diff --git a/src/caliptra_prim/config/caliptra_prim.vf b/src/caliptra_prim/config/caliptra_prim.vf index d4366d742..cfb57d8bd 100644 --- a/src/caliptra_prim/config/caliptra_prim.vf +++ b/src/caliptra_prim/config/caliptra_prim.vf @@ -16,6 +16,7 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -23,10 +24,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -60,4 +63,13 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_fifo_sync.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv \ No newline at end of file +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv \ No newline at end of file diff --git a/src/caliptra_prim/config/caliptra_prim_pkg.vf b/src/caliptra_prim/config/caliptra_prim_pkg.vf index b3a1e93ff..282886c80 100644 --- a/src/caliptra_prim/config/caliptra_prim_pkg.vf +++ b/src/caliptra_prim/config/caliptra_prim_pkg.vf @@ -6,4 +6,6 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv \ No newline at end of file +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv \ No newline at end of file diff --git a/src/caliptra_prim/config/compile.yml b/src/caliptra_prim/config/compile.yml index 70fac1887..fbcdee8a6 100644 --- a/src/caliptra_prim/config/compile.yml +++ b/src/caliptra_prim/config/compile.yml @@ -12,16 +12,9 @@ targets: - $COMPILE_ROOT/rtl/caliptra_prim_cipher_pkg.sv - $COMPILE_ROOT/rtl/caliptra_prim_pkg.sv - $COMPILE_ROOT/rtl/caliptra_prim_sparse_fsm_pkg.sv - tb: - directories: [$COMPILE_ROOT/rtl] - files: - - $COMPILE_ROOT/rtl/caliptra_prim_util_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_alert_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_subreg_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_mubi_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_cipher_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_pkg.sv - - $COMPILE_ROOT/rtl/caliptra_prim_sparse_fsm_pkg.sv + - $COMPILE_ROOT/rtl/caliptra_prim_trivium_pkg.sv + - $COMPILE_ROOT/rtl/caliptra_prim_secded_pkg.sv + - $COMPILE_ROOT/rtl/keymgr_pkg.sv --- provides: [caliptra_prim] schema_version: 2.4.0 @@ -71,4 +64,13 @@ targets: - $COMPILE_ROOT/rtl/caliptra_prim_sum_tree.sv - $COMPILE_ROOT/rtl/caliptra_prim_subreg_ext.sv - $COMPILE_ROOT/rtl/caliptra_prim_edge_detector.sv + - $COMPILE_ROOT/rtl/caliptra_prim_trivium.sv + - $COMPILE_ROOT/rtl/caliptra_prim_subreg_shadow.sv + - $COMPILE_ROOT/rtl/caliptra_prim_sync_reqack_data.sv + - $COMPILE_ROOT/rtl/caliptra_prim_sync_reqack.sv + - $COMPILE_ROOT/rtl/caliptra_prim_secded_inv_39_32_enc.sv + - $COMPILE_ROOT/rtl/caliptra_prim_secded_inv_39_32_dec.sv + - $COMPILE_ROOT/rtl/caliptra_prim_secded_inv_64_57_enc.sv + - $COMPILE_ROOT/rtl/caliptra_prim_secded_inv_64_57_dec.sv + - $COMPILE_ROOT/rtl/caliptra_prim_gf_mult.sv tops: [caliptra_prim] diff --git a/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv b/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv new file mode 100644 index 000000000..72d42d43c --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv @@ -0,0 +1,171 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// This module performs a the multiplication of two operands in Galois field GF(2^Width) modulo the +// provided irreducible polynomial using a parallel Mastrovito multipler [3]. To cut long paths +// potentially occurring for large data widths, the implementation provides a parameter +// StagesPerCycle to decompose the multiplication into Width/StagesPerCycle iterative steps +// (Digit-Serial/Parallel Multiplier [4]). +// +// Note that this module is not pipelined and produces an output sample every Width/StagesPerCycle +// cycles. +// +// References: +// +// [1] Patel, "Parallel Multiplier Designs for the Galois/Counter Mode of Operation", +// https://pdfs.semanticscholar.org/1246/a9ad98dc0421ccfc945e6529c886f23e848d.pdf +// [2] Wagner, "The Laws of Cryptography: The Finite Field GF(2^8)", +// http://www.cs.utsa.edu/~wagner/laws/FFM.html +// +// [3]: Mastrovito, "VLSI Designs for Multiplication over Finite Fields GF(2^m)", +// https://link.springer.com/chapter/10.1007/3-540-51083-4_67 +// [4]: Song et al., "Efficient Finite Field Serial/Parallel Multiplication", +// https://ieeexplore.ieee.org/document/542803 + + +`include "caliptra_prim_assert.sv" + +module caliptra_prim_gf_mult #( + parameter int Width = 32, + parameter int StagesPerCycle = Width, + + // The field-generating, irreducible polynomial of degree Width. + // Can for example be a Conway polynomial, see + // http://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol/CP2.html + // For Width = 33, the Conway polynomial has bits 32, 15, 9, 7, 4, 3, 0 set to one. + parameter logic[Width-1:0] IPoly = Width'(1'b1) << 15 | + Width'(1'b1) << 9 | + Width'(1'b1) << 7 | + Width'(1'b1) << 4 | + Width'(1'b1) << 3 | + Width'(1'b1) << 0 +) ( + input clk_i, + input rst_ni, + input req_i, + input [Width-1:0] operand_a_i, + input [Width-1:0] operand_b_i, + output logic ack_o, + output logic [Width-1:0] prod_o +); + + `CALIPTRA_ASSERT_INIT(IntegerLoops_A, (Width % StagesPerCycle) == 0) + `CALIPTRA_ASSERT_INIT(StagePow2_A, $onehot(StagesPerCycle)) + + localparam int Loops = Width / StagesPerCycle; + localparam int CntWidth = (Loops == 1) ? 1 : $clog2(Loops); + + // reformat operand_b_i + logic [Loops-1:0][StagesPerCycle-1:0] reformat_data; + + // this slice of operand bits used during each loop + logic [StagesPerCycle-1:0] op_i_slice; + + // the matrix is made up of a series of GF(2^Width) * x + logic [StagesPerCycle-1:0][Width-1:0] matrix; + + // since the matrix generation is not done in one go, we must remember + // where it last left off + logic [Width-1:0] vector; + + // this variable tracks which loop we are currently operating + logic [CntWidth-1:0] cnt; + + // this variable tracks the first loop through the multiply + logic first; + + // intermediate prod held between loops + logic [Width-1:0] prod_q, prod_d; + + // select current slice + assign reformat_data = operand_b_i; + assign op_i_slice = reformat_data[cnt]; + + assign first = cnt == 0; + + if (StagesPerCycle == Width) begin : gen_all_combo + + assign ack_o = 1'b1; + assign cnt = '0; + assign prod_q = '0; + assign vector = '0; + + end else begin : gen_decomposed + + // multiply is done + assign ack_o = int'(cnt) == (Loops - 1); + + // advance the stage count and also advance the bit position count + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + cnt <= '0; + end else if (req_i && ack_o) begin + cnt <= '0; + end else if (req_i && int'(cnt) < (Loops - 1)) begin + cnt <= cnt + 1'b1; + end + end + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + prod_q <= '0; + vector <= '0; + end else if (ack_o) begin + prod_q <= '0; + vector <= '0; + end else if (req_i) begin + prod_q <= prod_d; + vector <= matrix[StagesPerCycle-1]; + end + end + end + + + assign matrix = first ? gen_matrix(operand_a_i, 1'b1) : gen_matrix(vector, 1'b0); + assign prod_d = prod_q ^ gf_mult(matrix, op_i_slice); + + // The output is not toggled until it is ready + assign prod_o = ack_o ? prod_d : operand_a_i; + + + // GF(2^Width) * x + function automatic logic [Width-1:0] gf_mult2( + logic [Width-1:0] operand + ); + logic [Width-1:0] mult_out; + mult_out = operand[Width-1] ? (operand << 1) ^ IPoly : (operand << 1); + return mult_out; + endfunction + + // Matrix generate step + function automatic logic [StagesPerCycle-1:0][Width-1:0] gen_matrix( + logic [Width-1:0] seed, + logic init + ); + logic [StagesPerCycle-1:0][Width-1:0] matrix_out; + + matrix_out[0] = init ? seed : gf_mult2(seed); + matrix_out[StagesPerCycle-1:1] = '0; + for (int i = 1; i < StagesPerCycle; i++) begin + matrix_out[i] = gf_mult2(matrix_out[i-1]); + end + return matrix_out; + endfunction + + // Galois multiply step + function automatic logic [Width-1:0] gf_mult( + logic [StagesPerCycle-1:0][Width-1:0] matrix_, + logic [StagesPerCycle-1:0] operand + ); + logic [Width-1:0] mult_out; + logic [Width-1:0] add_vector; + mult_out = '0; + for (int i = 0; i < StagesPerCycle; i++) begin + add_vector = operand[i] ? matrix_[i] : '0; + mult_out = mult_out ^ add_vector; + end + return mult_out; + endfunction // gf_mult + +endmodule // caliptra_prim_gf_mult diff --git a/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv new file mode 100644 index 000000000..677c17452 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv @@ -0,0 +1,62 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED decoder generated by util/design/secded_gen.py + +module caliptra_prim_secded_inv_39_32_dec ( + input [38:0] data_i, + output logic [31:0] data_o, + output logic [6:0] syndrome_o, + output logic [1:0] err_o +); + + always_comb begin : p_encode + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 39'h2A00000000) & 39'h012606BD25); + syndrome_o[1] = ^((data_i ^ 39'h2A00000000) & 39'h02DEBA8050); + syndrome_o[2] = ^((data_i ^ 39'h2A00000000) & 39'h04413D89AA); + syndrome_o[3] = ^((data_i ^ 39'h2A00000000) & 39'h0831234ED1); + syndrome_o[4] = ^((data_i ^ 39'h2A00000000) & 39'h10C2C1323B); + syndrome_o[5] = ^((data_i ^ 39'h2A00000000) & 39'h202DCC624C); + syndrome_o[6] = ^((data_i ^ 39'h2A00000000) & 39'h4098505586); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h19) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'h54) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h61) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h34) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h1a) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'h15) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h2a) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h38) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h49) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'hd) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h51) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h31) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h68) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'h7) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h1c) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'hb) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h25) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h26) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h46) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'he) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h70) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h32) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h2c) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h13) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h23) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h62) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h4a) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h29) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h16) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h52) ^ data_i[31]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + end +endmodule : caliptra_prim_secded_inv_39_32_dec diff --git a/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv new file mode 100644 index 000000000..1cbd66a7e --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv @@ -0,0 +1,24 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED encoder generated by util/design/secded_gen.py + +module caliptra_prim_secded_inv_39_32_enc ( + input [31:0] data_i, + output logic [38:0] data_o +); + + always_comb begin : p_encode + data_o = 39'(data_i); + data_o[32] = ^(data_o & 39'h002606BD25); + data_o[33] = ^(data_o & 39'h00DEBA8050); + data_o[34] = ^(data_o & 39'h00413D89AA); + data_o[35] = ^(data_o & 39'h0031234ED1); + data_o[36] = ^(data_o & 39'h00C2C1323B); + data_o[37] = ^(data_o & 39'h002DCC624C); + data_o[38] = ^(data_o & 39'h0098505586); + data_o ^= 39'h2A00000000; + end + +endmodule : caliptra_prim_secded_inv_39_32_enc diff --git a/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv new file mode 100644 index 000000000..28fad1dc4 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv @@ -0,0 +1,87 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED decoder generated by util/design/secded_gen.py + +module caliptra_prim_secded_inv_64_57_dec ( + input [63:0] data_i, + output logic [56:0] data_o, + output logic [6:0] syndrome_o, + output logic [1:0] err_o +); + + always_comb begin : p_encode + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 64'h5400000000000000) & 64'h0303FFF800007FFF); + syndrome_o[1] = ^((data_i ^ 64'h5400000000000000) & 64'h057C1FF801FF801F); + syndrome_o[2] = ^((data_i ^ 64'h5400000000000000) & 64'h09BDE1F87E0781E1); + syndrome_o[3] = ^((data_i ^ 64'h5400000000000000) & 64'h11DEEE3B8E388E22); + syndrome_o[4] = ^((data_i ^ 64'h5400000000000000) & 64'h21EF76CDB2C93244); + syndrome_o[5] = ^((data_i ^ 64'h5400000000000000) & 64'h41F7BB56D5525488); + syndrome_o[6] = ^((data_i ^ 64'h5400000000000000) & 64'h81FBDDA769A46910); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h43) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'hd) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h15) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h25) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h19) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h29) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'h49) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h31) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h51) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h61) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'he) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h16) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'h26) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h46) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h1a) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h2a) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'h4a) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h32) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h52) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h62) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h1c) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h2c) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h4c) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h34) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h54) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h64) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h38) ^ data_i[31]; + data_o[32] = (syndrome_o == 7'h58) ^ data_i[32]; + data_o[33] = (syndrome_o == 7'h68) ^ data_i[33]; + data_o[34] = (syndrome_o == 7'h70) ^ data_i[34]; + data_o[35] = (syndrome_o == 7'h1f) ^ data_i[35]; + data_o[36] = (syndrome_o == 7'h2f) ^ data_i[36]; + data_o[37] = (syndrome_o == 7'h4f) ^ data_i[37]; + data_o[38] = (syndrome_o == 7'h37) ^ data_i[38]; + data_o[39] = (syndrome_o == 7'h57) ^ data_i[39]; + data_o[40] = (syndrome_o == 7'h67) ^ data_i[40]; + data_o[41] = (syndrome_o == 7'h3b) ^ data_i[41]; + data_o[42] = (syndrome_o == 7'h5b) ^ data_i[42]; + data_o[43] = (syndrome_o == 7'h6b) ^ data_i[43]; + data_o[44] = (syndrome_o == 7'h73) ^ data_i[44]; + data_o[45] = (syndrome_o == 7'h3d) ^ data_i[45]; + data_o[46] = (syndrome_o == 7'h5d) ^ data_i[46]; + data_o[47] = (syndrome_o == 7'h6d) ^ data_i[47]; + data_o[48] = (syndrome_o == 7'h75) ^ data_i[48]; + data_o[49] = (syndrome_o == 7'h79) ^ data_i[49]; + data_o[50] = (syndrome_o == 7'h3e) ^ data_i[50]; + data_o[51] = (syndrome_o == 7'h5e) ^ data_i[51]; + data_o[52] = (syndrome_o == 7'h6e) ^ data_i[52]; + data_o[53] = (syndrome_o == 7'h76) ^ data_i[53]; + data_o[54] = (syndrome_o == 7'h7a) ^ data_i[54]; + data_o[55] = (syndrome_o == 7'h7c) ^ data_i[55]; + data_o[56] = (syndrome_o == 7'h7f) ^ data_i[56]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + end +endmodule : caliptra_prim_secded_inv_64_57_dec diff --git a/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv new file mode 100644 index 000000000..b491a4204 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv @@ -0,0 +1,24 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED encoder generated by util/design/secded_gen.py + +module caliptra_prim_secded_inv_64_57_enc ( + input [56:0] data_i, + output logic [63:0] data_o +); + + always_comb begin : p_encode + data_o = 64'(data_i); + data_o[57] = ^(data_o & 64'h0103FFF800007FFF); + data_o[58] = ^(data_o & 64'h017C1FF801FF801F); + data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1); + data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22); + data_o[61] = ^(data_o & 64'h01EF76CDB2C93244); + data_o[62] = ^(data_o & 64'h01F7BB56D5525488); + data_o[63] = ^(data_o & 64'h01FBDDA769A46910); + data_o ^= 64'h5400000000000000; + end + +endmodule : caliptra_prim_secded_inv_64_57_enc diff --git a/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv b/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv new file mode 100644 index 000000000..885402984 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv @@ -0,0 +1,1787 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// SECDED package generated by +// util/design/secded_gen.py from util/design/data/secded_cfg.hjson + +package caliptra_prim_secded_pkg; + + typedef enum logic [31:0] { + SecdedNone, + Secded_22_16, + Secded_28_22, + Secded_39_32, + Secded_64_57, + Secded_72_64, + SecdedHamming_22_16, + SecdedHamming_39_32, + SecdedHamming_72_64, + SecdedHamming_76_68, + SecdedInv_22_16, + SecdedInv_28_22, + SecdedInv_39_32, + SecdedInv_64_57, + SecdedInv_72_64, + SecdedInvHamming_22_16, + SecdedInvHamming_39_32, + SecdedInvHamming_72_64, + SecdedInvHamming_76_68 + } caliptra_prim_secded_e; + + function automatic int get_ecc_data_width(caliptra_prim_secded_e ecc_type); + case (ecc_type) + Secded_22_16: return 16; + Secded_28_22: return 22; + Secded_39_32: return 32; + Secded_64_57: return 57; + Secded_72_64: return 64; + SecdedHamming_22_16: return 16; + SecdedHamming_39_32: return 32; + SecdedHamming_72_64: return 64; + SecdedHamming_76_68: return 68; + SecdedInv_22_16: return 16; + SecdedInv_28_22: return 22; + SecdedInv_39_32: return 32; + SecdedInv_64_57: return 57; + SecdedInv_72_64: return 64; + SecdedInvHamming_22_16: return 16; + SecdedInvHamming_39_32: return 32; + SecdedInvHamming_72_64: return 64; + SecdedInvHamming_76_68: return 68; + // Return a non-zero width to avoid VCS compile issues + default: return 32; + endcase + endfunction + + function automatic int get_ecc_parity_width(caliptra_prim_secded_e ecc_type); + case (ecc_type) + Secded_22_16: return 6; + Secded_28_22: return 6; + Secded_39_32: return 7; + Secded_64_57: return 7; + Secded_72_64: return 8; + SecdedHamming_22_16: return 6; + SecdedHamming_39_32: return 7; + SecdedHamming_72_64: return 8; + SecdedHamming_76_68: return 8; + SecdedInv_22_16: return 6; + SecdedInv_28_22: return 6; + SecdedInv_39_32: return 7; + SecdedInv_64_57: return 7; + SecdedInv_72_64: return 8; + SecdedInvHamming_22_16: return 6; + SecdedInvHamming_39_32: return 7; + SecdedInvHamming_72_64: return 8; + SecdedInvHamming_76_68: return 8; + default: return 0; + endcase + endfunction + + parameter logic [5:0] Secded2216ZeroEcc = 6'h0; + parameter logic [21:0] Secded2216ZeroWord = 22'h0; + + typedef struct packed { + logic [15:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_22_16_t; + + parameter logic [5:0] Secded2822ZeroEcc = 6'h0; + parameter logic [27:0] Secded2822ZeroWord = 28'h0; + + typedef struct packed { + logic [21:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_28_22_t; + + parameter logic [6:0] Secded3932ZeroEcc = 7'h0; + parameter logic [38:0] Secded3932ZeroWord = 39'h0; + + typedef struct packed { + logic [31:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_39_32_t; + + parameter logic [6:0] Secded6457ZeroEcc = 7'h0; + parameter logic [63:0] Secded6457ZeroWord = 64'h0; + + typedef struct packed { + logic [56:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_64_57_t; + + parameter logic [7:0] Secded7264ZeroEcc = 8'h0; + parameter logic [71:0] Secded7264ZeroWord = 72'h0; + + typedef struct packed { + logic [63:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_72_64_t; + + parameter logic [5:0] SecdedHamming2216ZeroEcc = 6'h0; + parameter logic [21:0] SecdedHamming2216ZeroWord = 22'h0; + + typedef struct packed { + logic [15:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_hamming_22_16_t; + + parameter logic [6:0] SecdedHamming3932ZeroEcc = 7'h0; + parameter logic [38:0] SecdedHamming3932ZeroWord = 39'h0; + + typedef struct packed { + logic [31:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_hamming_39_32_t; + + parameter logic [7:0] SecdedHamming7264ZeroEcc = 8'h0; + parameter logic [71:0] SecdedHamming7264ZeroWord = 72'h0; + + typedef struct packed { + logic [63:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_hamming_72_64_t; + + parameter logic [7:0] SecdedHamming7668ZeroEcc = 8'h0; + parameter logic [75:0] SecdedHamming7668ZeroWord = 76'h0; + + typedef struct packed { + logic [67:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_hamming_76_68_t; + + parameter logic [5:0] SecdedInv2216ZeroEcc = 6'h2A; + parameter logic [21:0] SecdedInv2216ZeroWord = 22'h2A0000; + + typedef struct packed { + logic [15:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_inv_22_16_t; + + parameter logic [5:0] SecdedInv2822ZeroEcc = 6'h2A; + parameter logic [27:0] SecdedInv2822ZeroWord = 28'hA800000; + + typedef struct packed { + logic [21:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_inv_28_22_t; + + parameter logic [6:0] SecdedInv3932ZeroEcc = 7'h2A; + parameter logic [38:0] SecdedInv3932ZeroWord = 39'h2A00000000; + + typedef struct packed { + logic [31:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_inv_39_32_t; + + parameter logic [6:0] SecdedInv6457ZeroEcc = 7'h2A; + parameter logic [63:0] SecdedInv6457ZeroWord = 64'h5400000000000000; + + typedef struct packed { + logic [56:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_inv_64_57_t; + + parameter logic [7:0] SecdedInv7264ZeroEcc = 8'hAA; + parameter logic [71:0] SecdedInv7264ZeroWord = 72'hAA0000000000000000; + + typedef struct packed { + logic [63:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_inv_72_64_t; + + parameter logic [5:0] SecdedInvHamming2216ZeroEcc = 6'h2A; + parameter logic [21:0] SecdedInvHamming2216ZeroWord = 22'h2A0000; + + typedef struct packed { + logic [15:0] data; + logic [5:0] syndrome; + logic [1:0] err; + } secded_inv_hamming_22_16_t; + + parameter logic [6:0] SecdedInvHamming3932ZeroEcc = 7'h2A; + parameter logic [38:0] SecdedInvHamming3932ZeroWord = 39'h2A00000000; + + typedef struct packed { + logic [31:0] data; + logic [6:0] syndrome; + logic [1:0] err; + } secded_inv_hamming_39_32_t; + + parameter logic [7:0] SecdedInvHamming7264ZeroEcc = 8'hAA; + parameter logic [71:0] SecdedInvHamming7264ZeroWord = 72'hAA0000000000000000; + + typedef struct packed { + logic [63:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_inv_hamming_72_64_t; + + parameter logic [7:0] SecdedInvHamming7668ZeroEcc = 8'hAA; + parameter logic [75:0] SecdedInvHamming7668ZeroWord = 76'hAA00000000000000000; + + typedef struct packed { + logic [67:0] data; + logic [7:0] syndrome; + logic [1:0] err; + } secded_inv_hamming_76_68_t; + + function automatic logic [21:0] + caliptra_prim_secded_22_16_enc (logic [15:0] data_i); + logic [21:0] data_o; + data_o = 22'(data_i); + data_o[16] = ^(data_o & 22'h00496E); + data_o[17] = ^(data_o & 22'h00F20B); + data_o[18] = ^(data_o & 22'h008ED8); + data_o[19] = ^(data_o & 22'h007714); + data_o[20] = ^(data_o & 22'h00ACA5); + data_o[21] = ^(data_o & 22'h0011F3); + return data_o; + endfunction + + function automatic secded_22_16_t + caliptra_prim_secded_22_16_dec (logic [21:0] data_i); + logic [15:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_22_16_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 22'h01496E); + syndrome_o[1] = ^(data_i & 22'h02F20B); + syndrome_o[2] = ^(data_i & 22'h048ED8); + syndrome_o[3] = ^(data_i & 22'h087714); + syndrome_o[4] = ^(data_i & 22'h10ACA5); + syndrome_o[5] = ^(data_i & 22'h2011F3); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h32) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'h23) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h19) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h7) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'h2c) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h31) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h25) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h34) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h29) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'he) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'h1c) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h15) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h2a) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'hb) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h16) ^ data_i[15]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [27:0] + caliptra_prim_secded_28_22_enc (logic [21:0] data_i); + logic [27:0] data_o; + data_o = 28'(data_i); + data_o[22] = ^(data_o & 28'h03003FF); + data_o[23] = ^(data_o & 28'h010FC0F); + data_o[24] = ^(data_o & 28'h0271C71); + data_o[25] = ^(data_o & 28'h03B6592); + data_o[26] = ^(data_o & 28'h03DAAA4); + data_o[27] = ^(data_o & 28'h03ED348); + return data_o; + endfunction + + function automatic secded_28_22_t + caliptra_prim_secded_28_22_dec (logic [27:0] data_i); + logic [21:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_28_22_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 28'h07003FF); + syndrome_o[1] = ^(data_i & 28'h090FC0F); + syndrome_o[2] = ^(data_i & 28'h1271C71); + syndrome_o[3] = ^(data_i & 28'h23B6592); + syndrome_o[4] = ^(data_i & 28'h43DAAA4); + syndrome_o[5] = ^(data_i & 28'h83ED348); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'hd) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h15) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h25) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h19) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h29) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'h31) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'he) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h16) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h26) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'h2a) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h32) ^ data_i[15]; + data_o[16] = (syndrome_o == 6'h1c) ^ data_i[16]; + data_o[17] = (syndrome_o == 6'h2c) ^ data_i[17]; + data_o[18] = (syndrome_o == 6'h34) ^ data_i[18]; + data_o[19] = (syndrome_o == 6'h38) ^ data_i[19]; + data_o[20] = (syndrome_o == 6'h3b) ^ data_i[20]; + data_o[21] = (syndrome_o == 6'h3d) ^ data_i[21]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [38:0] + caliptra_prim_secded_39_32_enc (logic [31:0] data_i); + logic [38:0] data_o; + data_o = 39'(data_i); + data_o[32] = ^(data_o & 39'h002606BD25); + data_o[33] = ^(data_o & 39'h00DEBA8050); + data_o[34] = ^(data_o & 39'h00413D89AA); + data_o[35] = ^(data_o & 39'h0031234ED1); + data_o[36] = ^(data_o & 39'h00C2C1323B); + data_o[37] = ^(data_o & 39'h002DCC624C); + data_o[38] = ^(data_o & 39'h0098505586); + return data_o; + endfunction + + function automatic secded_39_32_t + caliptra_prim_secded_39_32_dec (logic [38:0] data_i); + logic [31:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_39_32_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 39'h012606BD25); + syndrome_o[1] = ^(data_i & 39'h02DEBA8050); + syndrome_o[2] = ^(data_i & 39'h04413D89AA); + syndrome_o[3] = ^(data_i & 39'h0831234ED1); + syndrome_o[4] = ^(data_i & 39'h10C2C1323B); + syndrome_o[5] = ^(data_i & 39'h202DCC624C); + syndrome_o[6] = ^(data_i & 39'h4098505586); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h19) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'h54) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h61) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h34) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h1a) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'h15) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h2a) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h38) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h49) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'hd) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h51) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h31) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h68) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'h7) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h1c) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'hb) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h25) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h26) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h46) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'he) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h70) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h32) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h2c) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h13) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h23) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h62) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h4a) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h29) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h16) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h52) ^ data_i[31]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [63:0] + caliptra_prim_secded_64_57_enc (logic [56:0] data_i); + logic [63:0] data_o; + data_o = 64'(data_i); + data_o[57] = ^(data_o & 64'h0103FFF800007FFF); + data_o[58] = ^(data_o & 64'h017C1FF801FF801F); + data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1); + data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22); + data_o[61] = ^(data_o & 64'h01EF76CDB2C93244); + data_o[62] = ^(data_o & 64'h01F7BB56D5525488); + data_o[63] = ^(data_o & 64'h01FBDDA769A46910); + return data_o; + endfunction + + function automatic secded_64_57_t + caliptra_prim_secded_64_57_dec (logic [63:0] data_i); + logic [56:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_64_57_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 64'h0303FFF800007FFF); + syndrome_o[1] = ^(data_i & 64'h057C1FF801FF801F); + syndrome_o[2] = ^(data_i & 64'h09BDE1F87E0781E1); + syndrome_o[3] = ^(data_i & 64'h11DEEE3B8E388E22); + syndrome_o[4] = ^(data_i & 64'h21EF76CDB2C93244); + syndrome_o[5] = ^(data_i & 64'h41F7BB56D5525488); + syndrome_o[6] = ^(data_i & 64'h81FBDDA769A46910); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h43) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'hd) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h15) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h25) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h19) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h29) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'h49) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h31) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h51) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h61) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'he) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h16) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'h26) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h46) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h1a) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h2a) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'h4a) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h32) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h52) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h62) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h1c) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h2c) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h4c) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h34) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h54) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h64) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h38) ^ data_i[31]; + data_o[32] = (syndrome_o == 7'h58) ^ data_i[32]; + data_o[33] = (syndrome_o == 7'h68) ^ data_i[33]; + data_o[34] = (syndrome_o == 7'h70) ^ data_i[34]; + data_o[35] = (syndrome_o == 7'h1f) ^ data_i[35]; + data_o[36] = (syndrome_o == 7'h2f) ^ data_i[36]; + data_o[37] = (syndrome_o == 7'h4f) ^ data_i[37]; + data_o[38] = (syndrome_o == 7'h37) ^ data_i[38]; + data_o[39] = (syndrome_o == 7'h57) ^ data_i[39]; + data_o[40] = (syndrome_o == 7'h67) ^ data_i[40]; + data_o[41] = (syndrome_o == 7'h3b) ^ data_i[41]; + data_o[42] = (syndrome_o == 7'h5b) ^ data_i[42]; + data_o[43] = (syndrome_o == 7'h6b) ^ data_i[43]; + data_o[44] = (syndrome_o == 7'h73) ^ data_i[44]; + data_o[45] = (syndrome_o == 7'h3d) ^ data_i[45]; + data_o[46] = (syndrome_o == 7'h5d) ^ data_i[46]; + data_o[47] = (syndrome_o == 7'h6d) ^ data_i[47]; + data_o[48] = (syndrome_o == 7'h75) ^ data_i[48]; + data_o[49] = (syndrome_o == 7'h79) ^ data_i[49]; + data_o[50] = (syndrome_o == 7'h3e) ^ data_i[50]; + data_o[51] = (syndrome_o == 7'h5e) ^ data_i[51]; + data_o[52] = (syndrome_o == 7'h6e) ^ data_i[52]; + data_o[53] = (syndrome_o == 7'h76) ^ data_i[53]; + data_o[54] = (syndrome_o == 7'h7a) ^ data_i[54]; + data_o[55] = (syndrome_o == 7'h7c) ^ data_i[55]; + data_o[56] = (syndrome_o == 7'h7f) ^ data_i[56]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [71:0] + caliptra_prim_secded_72_64_enc (logic [63:0] data_i); + logic [71:0] data_o; + data_o = 72'(data_i); + data_o[64] = ^(data_o & 72'h00B9000000001FFFFF); + data_o[65] = ^(data_o & 72'h005E00000FFFE0003F); + data_o[66] = ^(data_o & 72'h0067003FF003E007C1); + data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842); + data_o[68] = ^(data_o & 72'h00B671C711C4438884); + data_o[69] = ^(data_o & 72'h00B5B65926488C9108); + data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210); + data_o[71] = ^(data_o & 72'h007AED348D221A4420); + return data_o; + endfunction + + function automatic secded_72_64_t + caliptra_prim_secded_72_64_dec (logic [71:0] data_i); + logic [63:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_72_64_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 72'h01B9000000001FFFFF); + syndrome_o[1] = ^(data_i & 72'h025E00000FFFE0003F); + syndrome_o[2] = ^(data_i & 72'h0467003FF003E007C1); + syndrome_o[3] = ^(data_i & 72'h08CD0FC0F03C207842); + syndrome_o[4] = ^(data_i & 72'h10B671C711C4438884); + syndrome_o[5] = ^(data_i & 72'h20B5B65926488C9108); + syndrome_o[6] = ^(data_i & 72'h40CBDAAA4A91152210); + syndrome_o[7] = ^(data_i & 72'h807AED348D221A4420); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h43) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h83) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'hd) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h15) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h25) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h45) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h85) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h19) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h29) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h49) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h89) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h31) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h51) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h91) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h61) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'ha1) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'hc1) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'he) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h16) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h26) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h46) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h86) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'h1a) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'h2a) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'h4a) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'h8a) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'h32) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'h52) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'h92) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'h62) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha2) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'hc2) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'h1c) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'h2c) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'h4c) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'h8c) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'h34) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'h54) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'h94) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'h64) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'ha4) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hc4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'h38) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'h58) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'h98) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'h68) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'ha8) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hc8) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'h70) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hb0) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hd0) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'he0) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'h6d) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hd6) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'h3e) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hcb) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hb3) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hb5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hce) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'h79) ^ data_i[63]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [21:0] + caliptra_prim_secded_hamming_22_16_enc (logic [15:0] data_i); + logic [21:0] data_o; + data_o = 22'(data_i); + data_o[16] = ^(data_o & 22'h00AD5B); + data_o[17] = ^(data_o & 22'h00366D); + data_o[18] = ^(data_o & 22'h00C78E); + data_o[19] = ^(data_o & 22'h0007F0); + data_o[20] = ^(data_o & 22'h00F800); + data_o[21] = ^(data_o & 22'h1FFFFF); + return data_o; + endfunction + + function automatic secded_hamming_22_16_t + caliptra_prim_secded_hamming_22_16_dec (logic [21:0] data_i); + logic [15:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_hamming_22_16_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 22'h01AD5B); + syndrome_o[1] = ^(data_i & 22'h02366D); + syndrome_o[2] = ^(data_i & 22'h04C78E); + syndrome_o[3] = ^(data_i & 22'h0807F0); + syndrome_o[4] = ^(data_i & 22'h10F800); + syndrome_o[5] = ^(data_i & 22'h3FFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h23) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'h25) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h26) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h27) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'h29) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h2a) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h2b) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h2c) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h2d) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'h2e) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'h2f) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h31) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h32) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h33) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'h34) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h35) ^ data_i[15]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[5]; + err_o[1] = |syndrome_o[4:0] & ~syndrome_o[5]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [38:0] + caliptra_prim_secded_hamming_39_32_enc (logic [31:0] data_i); + logic [38:0] data_o; + data_o = 39'(data_i); + data_o[32] = ^(data_o & 39'h0056AAAD5B); + data_o[33] = ^(data_o & 39'h009B33366D); + data_o[34] = ^(data_o & 39'h00E3C3C78E); + data_o[35] = ^(data_o & 39'h0003FC07F0); + data_o[36] = ^(data_o & 39'h0003FFF800); + data_o[37] = ^(data_o & 39'h00FC000000); + data_o[38] = ^(data_o & 39'h3FFFFFFFFF); + return data_o; + endfunction + + function automatic secded_hamming_39_32_t + caliptra_prim_secded_hamming_39_32_dec (logic [38:0] data_i); + logic [31:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_hamming_39_32_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 39'h0156AAAD5B); + syndrome_o[1] = ^(data_i & 39'h029B33366D); + syndrome_o[2] = ^(data_i & 39'h04E3C3C78E); + syndrome_o[3] = ^(data_i & 39'h0803FC07F0); + syndrome_o[4] = ^(data_i & 39'h1003FFF800); + syndrome_o[5] = ^(data_i & 39'h20FC000000); + syndrome_o[6] = ^(data_i & 39'h7FFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h43) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'h45) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h46) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h47) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h49) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'h4a) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h4b) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h4d) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h4e) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h4f) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'h51) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h52) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h53) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h54) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'h55) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h56) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'h57) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h58) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h59) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h5a) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'h5b) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h5c) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h5d) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h5e) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h5f) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h61) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h62) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h63) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h64) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h65) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h66) ^ data_i[31]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[6]; + err_o[1] = |syndrome_o[5:0] & ~syndrome_o[6]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [71:0] + caliptra_prim_secded_hamming_72_64_enc (logic [63:0] data_i); + logic [71:0] data_o; + data_o = 72'(data_i); + data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B); + data_o[65] = ^(data_o & 72'h00CD9999999B33366D); + data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E); + data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0); + data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800); + data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000); + data_o[70] = ^(data_o & 72'h00FE00000000000000); + data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF); + return data_o; + endfunction + + function automatic secded_hamming_72_64_t + caliptra_prim_secded_hamming_72_64_dec (logic [71:0] data_i); + logic [63:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_hamming_72_64_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 72'h01AB55555556AAAD5B); + syndrome_o[1] = ^(data_i & 72'h02CD9999999B33366D); + syndrome_o[2] = ^(data_i & 72'h04F1E1E1E1E3C3C78E); + syndrome_o[3] = ^(data_i & 72'h0801FE01FE03FC07F0); + syndrome_o[4] = ^(data_i & 72'h1001FFFE0003FFF800); + syndrome_o[5] = ^(data_i & 72'h2001FFFFFFFC000000); + syndrome_o[6] = ^(data_i & 72'h40FE00000000000000); + syndrome_o[7] = ^(data_i & 72'hFFFFFFFFFFFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h83) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'h85) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h86) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h87) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h89) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h8a) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'h8b) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h8c) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h8d) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h8e) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h8f) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h91) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h92) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h93) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h94) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h95) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h96) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h97) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h98) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'h99) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'h9a) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'h9b) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h9c) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h9d) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h9e) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h9f) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'ha1) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'ha2) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'ha3) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'ha4) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'ha5) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'ha6) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'ha7) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'ha8) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha9) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'haa) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'hab) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'hac) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'had) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'hae) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'haf) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'hb0) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'hb1) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'hb2) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'hb3) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hb4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'hb5) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'hb6) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'hb7) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'hb8) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'hb9) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hba) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'hbb) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hbc) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hbd) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'hbe) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'hbf) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hc1) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'hc2) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hc3) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hc4) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hc5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hc6) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'hc7) ^ data_i[63]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[7]; + err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [75:0] + caliptra_prim_secded_hamming_76_68_enc (logic [67:0] data_i); + logic [75:0] data_o; + data_o = 76'(data_i); + data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B); + data_o[69] = ^(data_o & 76'h00CCD9999999B33366D); + data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E); + data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0); + data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800); + data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000); + data_o[74] = ^(data_o & 76'h00FFE00000000000000); + data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF); + return data_o; + endfunction + + function automatic secded_hamming_76_68_t + caliptra_prim_secded_hamming_76_68_dec (logic [75:0] data_i); + logic [67:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_hamming_76_68_t dec; + + // Syndrome calculation + syndrome_o[0] = ^(data_i & 76'h01AAB55555556AAAD5B); + syndrome_o[1] = ^(data_i & 76'h02CCD9999999B33366D); + syndrome_o[2] = ^(data_i & 76'h040F1E1E1E1E3C3C78E); + syndrome_o[3] = ^(data_i & 76'h08F01FE01FE03FC07F0); + syndrome_o[4] = ^(data_i & 76'h10001FFFE0003FFF800); + syndrome_o[5] = ^(data_i & 76'h20001FFFFFFFC000000); + syndrome_o[6] = ^(data_i & 76'h40FFE00000000000000); + syndrome_o[7] = ^(data_i & 76'hFFFFFFFFFFFFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h83) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'h85) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h86) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h87) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h89) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h8a) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'h8b) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h8c) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h8d) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h8e) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h8f) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h91) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h92) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h93) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h94) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h95) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h96) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h97) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h98) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'h99) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'h9a) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'h9b) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h9c) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h9d) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h9e) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h9f) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'ha1) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'ha2) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'ha3) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'ha4) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'ha5) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'ha6) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'ha7) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'ha8) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha9) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'haa) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'hab) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'hac) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'had) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'hae) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'haf) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'hb0) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'hb1) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'hb2) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'hb3) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hb4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'hb5) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'hb6) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'hb7) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'hb8) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'hb9) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hba) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'hbb) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hbc) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hbd) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'hbe) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'hbf) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hc1) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'hc2) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hc3) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hc4) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hc5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hc6) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'hc7) ^ data_i[63]; + data_o[64] = (syndrome_o == 8'hc8) ^ data_i[64]; + data_o[65] = (syndrome_o == 8'hc9) ^ data_i[65]; + data_o[66] = (syndrome_o == 8'hca) ^ data_i[66]; + data_o[67] = (syndrome_o == 8'hcb) ^ data_i[67]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[7]; + err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [21:0] + caliptra_prim_secded_inv_22_16_enc (logic [15:0] data_i); + logic [21:0] data_o; + data_o = 22'(data_i); + data_o[16] = ^(data_o & 22'h00496E); + data_o[17] = ^(data_o & 22'h00F20B); + data_o[18] = ^(data_o & 22'h008ED8); + data_o[19] = ^(data_o & 22'h007714); + data_o[20] = ^(data_o & 22'h00ACA5); + data_o[21] = ^(data_o & 22'h0011F3); + data_o ^= 22'h2A0000; + return data_o; + endfunction + + function automatic secded_inv_22_16_t + caliptra_prim_secded_inv_22_16_dec (logic [21:0] data_i); + logic [15:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_22_16_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 22'h2A0000) & 22'h01496E); + syndrome_o[1] = ^((data_i ^ 22'h2A0000) & 22'h02F20B); + syndrome_o[2] = ^((data_i ^ 22'h2A0000) & 22'h048ED8); + syndrome_o[3] = ^((data_i ^ 22'h2A0000) & 22'h087714); + syndrome_o[4] = ^((data_i ^ 22'h2A0000) & 22'h10ACA5); + syndrome_o[5] = ^((data_i ^ 22'h2A0000) & 22'h2011F3); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h32) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'h23) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h19) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h7) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'h2c) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h31) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h25) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h34) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h29) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'he) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'h1c) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h15) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h2a) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'hb) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h16) ^ data_i[15]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [27:0] + caliptra_prim_secded_inv_28_22_enc (logic [21:0] data_i); + logic [27:0] data_o; + data_o = 28'(data_i); + data_o[22] = ^(data_o & 28'h03003FF); + data_o[23] = ^(data_o & 28'h010FC0F); + data_o[24] = ^(data_o & 28'h0271C71); + data_o[25] = ^(data_o & 28'h03B6592); + data_o[26] = ^(data_o & 28'h03DAAA4); + data_o[27] = ^(data_o & 28'h03ED348); + data_o ^= 28'hA800000; + return data_o; + endfunction + + function automatic secded_inv_28_22_t + caliptra_prim_secded_inv_28_22_dec (logic [27:0] data_i); + logic [21:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_28_22_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 28'hA800000) & 28'h07003FF); + syndrome_o[1] = ^((data_i ^ 28'hA800000) & 28'h090FC0F); + syndrome_o[2] = ^((data_i ^ 28'hA800000) & 28'h1271C71); + syndrome_o[3] = ^((data_i ^ 28'hA800000) & 28'h23B6592); + syndrome_o[4] = ^((data_i ^ 28'hA800000) & 28'h43DAAA4); + syndrome_o[5] = ^((data_i ^ 28'hA800000) & 28'h83ED348); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'hd) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h15) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h25) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h19) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h29) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'h31) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'he) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h16) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h26) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h1a) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'h2a) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h32) ^ data_i[15]; + data_o[16] = (syndrome_o == 6'h1c) ^ data_i[16]; + data_o[17] = (syndrome_o == 6'h2c) ^ data_i[17]; + data_o[18] = (syndrome_o == 6'h34) ^ data_i[18]; + data_o[19] = (syndrome_o == 6'h38) ^ data_i[19]; + data_o[20] = (syndrome_o == 6'h3b) ^ data_i[20]; + data_o[21] = (syndrome_o == 6'h3d) ^ data_i[21]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [38:0] + caliptra_prim_secded_inv_39_32_enc (logic [31:0] data_i); + logic [38:0] data_o; + data_o = 39'(data_i); + data_o[32] = ^(data_o & 39'h002606BD25); + data_o[33] = ^(data_o & 39'h00DEBA8050); + data_o[34] = ^(data_o & 39'h00413D89AA); + data_o[35] = ^(data_o & 39'h0031234ED1); + data_o[36] = ^(data_o & 39'h00C2C1323B); + data_o[37] = ^(data_o & 39'h002DCC624C); + data_o[38] = ^(data_o & 39'h0098505586); + data_o ^= 39'h2A00000000; + return data_o; + endfunction + + function automatic secded_inv_39_32_t + caliptra_prim_secded_inv_39_32_dec (logic [38:0] data_i); + logic [31:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_39_32_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 39'h2A00000000) & 39'h012606BD25); + syndrome_o[1] = ^((data_i ^ 39'h2A00000000) & 39'h02DEBA8050); + syndrome_o[2] = ^((data_i ^ 39'h2A00000000) & 39'h04413D89AA); + syndrome_o[3] = ^((data_i ^ 39'h2A00000000) & 39'h0831234ED1); + syndrome_o[4] = ^((data_i ^ 39'h2A00000000) & 39'h10C2C1323B); + syndrome_o[5] = ^((data_i ^ 39'h2A00000000) & 39'h202DCC624C); + syndrome_o[6] = ^((data_i ^ 39'h2A00000000) & 39'h4098505586); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h19) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'h54) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h61) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h34) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h1a) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'h15) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h2a) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h38) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h49) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'hd) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h51) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h31) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h68) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'h7) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h1c) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'hb) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h25) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h26) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h46) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'he) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h70) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h32) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h2c) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h13) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h23) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h62) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h4a) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h29) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h16) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h52) ^ data_i[31]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [63:0] + caliptra_prim_secded_inv_64_57_enc (logic [56:0] data_i); + logic [63:0] data_o; + data_o = 64'(data_i); + data_o[57] = ^(data_o & 64'h0103FFF800007FFF); + data_o[58] = ^(data_o & 64'h017C1FF801FF801F); + data_o[59] = ^(data_o & 64'h01BDE1F87E0781E1); + data_o[60] = ^(data_o & 64'h01DEEE3B8E388E22); + data_o[61] = ^(data_o & 64'h01EF76CDB2C93244); + data_o[62] = ^(data_o & 64'h01F7BB56D5525488); + data_o[63] = ^(data_o & 64'h01FBDDA769A46910); + data_o ^= 64'h5400000000000000; + return data_o; + endfunction + + function automatic secded_inv_64_57_t + caliptra_prim_secded_inv_64_57_dec (logic [63:0] data_i); + logic [56:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_64_57_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 64'h5400000000000000) & 64'h0303FFF800007FFF); + syndrome_o[1] = ^((data_i ^ 64'h5400000000000000) & 64'h057C1FF801FF801F); + syndrome_o[2] = ^((data_i ^ 64'h5400000000000000) & 64'h09BDE1F87E0781E1); + syndrome_o[3] = ^((data_i ^ 64'h5400000000000000) & 64'h11DEEE3B8E388E22); + syndrome_o[4] = ^((data_i ^ 64'h5400000000000000) & 64'h21EF76CDB2C93244); + syndrome_o[5] = ^((data_i ^ 64'h5400000000000000) & 64'h41F7BB56D5525488); + syndrome_o[6] = ^((data_i ^ 64'h5400000000000000) & 64'h81FBDDA769A46910); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h43) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'hd) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h15) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h25) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h45) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h19) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h29) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'h49) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h31) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h51) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h61) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'he) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h16) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'h26) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h46) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h1a) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h2a) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'h4a) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h32) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h52) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h62) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h1c) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h2c) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h4c) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h34) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h54) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h64) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h38) ^ data_i[31]; + data_o[32] = (syndrome_o == 7'h58) ^ data_i[32]; + data_o[33] = (syndrome_o == 7'h68) ^ data_i[33]; + data_o[34] = (syndrome_o == 7'h70) ^ data_i[34]; + data_o[35] = (syndrome_o == 7'h1f) ^ data_i[35]; + data_o[36] = (syndrome_o == 7'h2f) ^ data_i[36]; + data_o[37] = (syndrome_o == 7'h4f) ^ data_i[37]; + data_o[38] = (syndrome_o == 7'h37) ^ data_i[38]; + data_o[39] = (syndrome_o == 7'h57) ^ data_i[39]; + data_o[40] = (syndrome_o == 7'h67) ^ data_i[40]; + data_o[41] = (syndrome_o == 7'h3b) ^ data_i[41]; + data_o[42] = (syndrome_o == 7'h5b) ^ data_i[42]; + data_o[43] = (syndrome_o == 7'h6b) ^ data_i[43]; + data_o[44] = (syndrome_o == 7'h73) ^ data_i[44]; + data_o[45] = (syndrome_o == 7'h3d) ^ data_i[45]; + data_o[46] = (syndrome_o == 7'h5d) ^ data_i[46]; + data_o[47] = (syndrome_o == 7'h6d) ^ data_i[47]; + data_o[48] = (syndrome_o == 7'h75) ^ data_i[48]; + data_o[49] = (syndrome_o == 7'h79) ^ data_i[49]; + data_o[50] = (syndrome_o == 7'h3e) ^ data_i[50]; + data_o[51] = (syndrome_o == 7'h5e) ^ data_i[51]; + data_o[52] = (syndrome_o == 7'h6e) ^ data_i[52]; + data_o[53] = (syndrome_o == 7'h76) ^ data_i[53]; + data_o[54] = (syndrome_o == 7'h7a) ^ data_i[54]; + data_o[55] = (syndrome_o == 7'h7c) ^ data_i[55]; + data_o[56] = (syndrome_o == 7'h7f) ^ data_i[56]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [71:0] + caliptra_prim_secded_inv_72_64_enc (logic [63:0] data_i); + logic [71:0] data_o; + data_o = 72'(data_i); + data_o[64] = ^(data_o & 72'h00B9000000001FFFFF); + data_o[65] = ^(data_o & 72'h005E00000FFFE0003F); + data_o[66] = ^(data_o & 72'h0067003FF003E007C1); + data_o[67] = ^(data_o & 72'h00CD0FC0F03C207842); + data_o[68] = ^(data_o & 72'h00B671C711C4438884); + data_o[69] = ^(data_o & 72'h00B5B65926488C9108); + data_o[70] = ^(data_o & 72'h00CBDAAA4A91152210); + data_o[71] = ^(data_o & 72'h007AED348D221A4420); + data_o ^= 72'hAA0000000000000000; + return data_o; + endfunction + + function automatic secded_inv_72_64_t + caliptra_prim_secded_inv_72_64_dec (logic [71:0] data_i); + logic [63:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_72_64_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 72'hAA0000000000000000) & 72'h01B9000000001FFFFF); + syndrome_o[1] = ^((data_i ^ 72'hAA0000000000000000) & 72'h025E00000FFFE0003F); + syndrome_o[2] = ^((data_i ^ 72'hAA0000000000000000) & 72'h0467003FF003E007C1); + syndrome_o[3] = ^((data_i ^ 72'hAA0000000000000000) & 72'h08CD0FC0F03C207842); + syndrome_o[4] = ^((data_i ^ 72'hAA0000000000000000) & 72'h10B671C711C4438884); + syndrome_o[5] = ^((data_i ^ 72'hAA0000000000000000) & 72'h20B5B65926488C9108); + syndrome_o[6] = ^((data_i ^ 72'hAA0000000000000000) & 72'h40CBDAAA4A91152210); + syndrome_o[7] = ^((data_i ^ 72'hAA0000000000000000) & 72'h807AED348D221A4420); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h7) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'hb) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h13) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h23) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h43) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h83) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'hd) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h15) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h25) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h45) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h85) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h19) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h29) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h49) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h89) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h31) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h51) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h91) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h61) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'ha1) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'hc1) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'he) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h16) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h26) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h46) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h86) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'h1a) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'h2a) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'h4a) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'h8a) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'h32) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'h52) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'h92) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'h62) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha2) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'hc2) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'h1c) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'h2c) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'h4c) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'h8c) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'h34) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'h54) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'h94) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'h64) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'ha4) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hc4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'h38) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'h58) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'h98) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'h68) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'ha8) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hc8) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'h70) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hb0) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hd0) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'he0) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'h6d) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hd6) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'h3e) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hcb) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hb3) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hb5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hce) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'h79) ^ data_i[63]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = ^syndrome_o; + err_o[1] = ~err_o[0] & (|syndrome_o); + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [21:0] + caliptra_prim_secded_inv_hamming_22_16_enc (logic [15:0] data_i); + logic [21:0] data_o; + data_o = 22'(data_i); + data_o[16] = ^(data_o & 22'h00AD5B); + data_o[17] = ^(data_o & 22'h00366D); + data_o[18] = ^(data_o & 22'h00C78E); + data_o[19] = ^(data_o & 22'h0007F0); + data_o[20] = ^(data_o & 22'h00F800); + data_o[21] = ^(data_o & 22'h1FFFFF); + data_o ^= 22'h2A0000; + return data_o; + endfunction + + function automatic secded_inv_hamming_22_16_t + caliptra_prim_secded_inv_hamming_22_16_dec (logic [21:0] data_i); + logic [15:0] data_o; + logic [5:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_hamming_22_16_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 22'h2A0000) & 22'h01AD5B); + syndrome_o[1] = ^((data_i ^ 22'h2A0000) & 22'h02366D); + syndrome_o[2] = ^((data_i ^ 22'h2A0000) & 22'h04C78E); + syndrome_o[3] = ^((data_i ^ 22'h2A0000) & 22'h0807F0); + syndrome_o[4] = ^((data_i ^ 22'h2A0000) & 22'h10F800); + syndrome_o[5] = ^((data_i ^ 22'h2A0000) & 22'h3FFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 6'h23) ^ data_i[0]; + data_o[1] = (syndrome_o == 6'h25) ^ data_i[1]; + data_o[2] = (syndrome_o == 6'h26) ^ data_i[2]; + data_o[3] = (syndrome_o == 6'h27) ^ data_i[3]; + data_o[4] = (syndrome_o == 6'h29) ^ data_i[4]; + data_o[5] = (syndrome_o == 6'h2a) ^ data_i[5]; + data_o[6] = (syndrome_o == 6'h2b) ^ data_i[6]; + data_o[7] = (syndrome_o == 6'h2c) ^ data_i[7]; + data_o[8] = (syndrome_o == 6'h2d) ^ data_i[8]; + data_o[9] = (syndrome_o == 6'h2e) ^ data_i[9]; + data_o[10] = (syndrome_o == 6'h2f) ^ data_i[10]; + data_o[11] = (syndrome_o == 6'h31) ^ data_i[11]; + data_o[12] = (syndrome_o == 6'h32) ^ data_i[12]; + data_o[13] = (syndrome_o == 6'h33) ^ data_i[13]; + data_o[14] = (syndrome_o == 6'h34) ^ data_i[14]; + data_o[15] = (syndrome_o == 6'h35) ^ data_i[15]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[5]; + err_o[1] = |syndrome_o[4:0] & ~syndrome_o[5]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [38:0] + caliptra_prim_secded_inv_hamming_39_32_enc (logic [31:0] data_i); + logic [38:0] data_o; + data_o = 39'(data_i); + data_o[32] = ^(data_o & 39'h0056AAAD5B); + data_o[33] = ^(data_o & 39'h009B33366D); + data_o[34] = ^(data_o & 39'h00E3C3C78E); + data_o[35] = ^(data_o & 39'h0003FC07F0); + data_o[36] = ^(data_o & 39'h0003FFF800); + data_o[37] = ^(data_o & 39'h00FC000000); + data_o[38] = ^(data_o & 39'h3FFFFFFFFF); + data_o ^= 39'h2A00000000; + return data_o; + endfunction + + function automatic secded_inv_hamming_39_32_t + caliptra_prim_secded_inv_hamming_39_32_dec (logic [38:0] data_i); + logic [31:0] data_o; + logic [6:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_hamming_39_32_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 39'h2A00000000) & 39'h0156AAAD5B); + syndrome_o[1] = ^((data_i ^ 39'h2A00000000) & 39'h029B33366D); + syndrome_o[2] = ^((data_i ^ 39'h2A00000000) & 39'h04E3C3C78E); + syndrome_o[3] = ^((data_i ^ 39'h2A00000000) & 39'h0803FC07F0); + syndrome_o[4] = ^((data_i ^ 39'h2A00000000) & 39'h1003FFF800); + syndrome_o[5] = ^((data_i ^ 39'h2A00000000) & 39'h20FC000000); + syndrome_o[6] = ^((data_i ^ 39'h2A00000000) & 39'h7FFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 7'h43) ^ data_i[0]; + data_o[1] = (syndrome_o == 7'h45) ^ data_i[1]; + data_o[2] = (syndrome_o == 7'h46) ^ data_i[2]; + data_o[3] = (syndrome_o == 7'h47) ^ data_i[3]; + data_o[4] = (syndrome_o == 7'h49) ^ data_i[4]; + data_o[5] = (syndrome_o == 7'h4a) ^ data_i[5]; + data_o[6] = (syndrome_o == 7'h4b) ^ data_i[6]; + data_o[7] = (syndrome_o == 7'h4c) ^ data_i[7]; + data_o[8] = (syndrome_o == 7'h4d) ^ data_i[8]; + data_o[9] = (syndrome_o == 7'h4e) ^ data_i[9]; + data_o[10] = (syndrome_o == 7'h4f) ^ data_i[10]; + data_o[11] = (syndrome_o == 7'h51) ^ data_i[11]; + data_o[12] = (syndrome_o == 7'h52) ^ data_i[12]; + data_o[13] = (syndrome_o == 7'h53) ^ data_i[13]; + data_o[14] = (syndrome_o == 7'h54) ^ data_i[14]; + data_o[15] = (syndrome_o == 7'h55) ^ data_i[15]; + data_o[16] = (syndrome_o == 7'h56) ^ data_i[16]; + data_o[17] = (syndrome_o == 7'h57) ^ data_i[17]; + data_o[18] = (syndrome_o == 7'h58) ^ data_i[18]; + data_o[19] = (syndrome_o == 7'h59) ^ data_i[19]; + data_o[20] = (syndrome_o == 7'h5a) ^ data_i[20]; + data_o[21] = (syndrome_o == 7'h5b) ^ data_i[21]; + data_o[22] = (syndrome_o == 7'h5c) ^ data_i[22]; + data_o[23] = (syndrome_o == 7'h5d) ^ data_i[23]; + data_o[24] = (syndrome_o == 7'h5e) ^ data_i[24]; + data_o[25] = (syndrome_o == 7'h5f) ^ data_i[25]; + data_o[26] = (syndrome_o == 7'h61) ^ data_i[26]; + data_o[27] = (syndrome_o == 7'h62) ^ data_i[27]; + data_o[28] = (syndrome_o == 7'h63) ^ data_i[28]; + data_o[29] = (syndrome_o == 7'h64) ^ data_i[29]; + data_o[30] = (syndrome_o == 7'h65) ^ data_i[30]; + data_o[31] = (syndrome_o == 7'h66) ^ data_i[31]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[6]; + err_o[1] = |syndrome_o[5:0] & ~syndrome_o[6]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [71:0] + caliptra_prim_secded_inv_hamming_72_64_enc (logic [63:0] data_i); + logic [71:0] data_o; + data_o = 72'(data_i); + data_o[64] = ^(data_o & 72'h00AB55555556AAAD5B); + data_o[65] = ^(data_o & 72'h00CD9999999B33366D); + data_o[66] = ^(data_o & 72'h00F1E1E1E1E3C3C78E); + data_o[67] = ^(data_o & 72'h0001FE01FE03FC07F0); + data_o[68] = ^(data_o & 72'h0001FFFE0003FFF800); + data_o[69] = ^(data_o & 72'h0001FFFFFFFC000000); + data_o[70] = ^(data_o & 72'h00FE00000000000000); + data_o[71] = ^(data_o & 72'h7FFFFFFFFFFFFFFFFF); + data_o ^= 72'hAA0000000000000000; + return data_o; + endfunction + + function automatic secded_inv_hamming_72_64_t + caliptra_prim_secded_inv_hamming_72_64_dec (logic [71:0] data_i); + logic [63:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_hamming_72_64_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 72'hAA0000000000000000) & 72'h01AB55555556AAAD5B); + syndrome_o[1] = ^((data_i ^ 72'hAA0000000000000000) & 72'h02CD9999999B33366D); + syndrome_o[2] = ^((data_i ^ 72'hAA0000000000000000) & 72'h04F1E1E1E1E3C3C78E); + syndrome_o[3] = ^((data_i ^ 72'hAA0000000000000000) & 72'h0801FE01FE03FC07F0); + syndrome_o[4] = ^((data_i ^ 72'hAA0000000000000000) & 72'h1001FFFE0003FFF800); + syndrome_o[5] = ^((data_i ^ 72'hAA0000000000000000) & 72'h2001FFFFFFFC000000); + syndrome_o[6] = ^((data_i ^ 72'hAA0000000000000000) & 72'h40FE00000000000000); + syndrome_o[7] = ^((data_i ^ 72'hAA0000000000000000) & 72'hFFFFFFFFFFFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h83) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'h85) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h86) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h87) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h89) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h8a) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'h8b) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h8c) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h8d) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h8e) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h8f) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h91) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h92) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h93) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h94) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h95) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h96) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h97) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h98) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'h99) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'h9a) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'h9b) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h9c) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h9d) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h9e) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h9f) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'ha1) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'ha2) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'ha3) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'ha4) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'ha5) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'ha6) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'ha7) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'ha8) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha9) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'haa) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'hab) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'hac) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'had) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'hae) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'haf) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'hb0) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'hb1) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'hb2) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'hb3) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hb4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'hb5) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'hb6) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'hb7) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'hb8) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'hb9) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hba) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'hbb) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hbc) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hbd) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'hbe) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'hbf) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hc1) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'hc2) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hc3) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hc4) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hc5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hc6) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'hc7) ^ data_i[63]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[7]; + err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + function automatic logic [75:0] + caliptra_prim_secded_inv_hamming_76_68_enc (logic [67:0] data_i); + logic [75:0] data_o; + data_o = 76'(data_i); + data_o[68] = ^(data_o & 76'h00AAB55555556AAAD5B); + data_o[69] = ^(data_o & 76'h00CCD9999999B33366D); + data_o[70] = ^(data_o & 76'h000F1E1E1E1E3C3C78E); + data_o[71] = ^(data_o & 76'h00F01FE01FE03FC07F0); + data_o[72] = ^(data_o & 76'h00001FFFE0003FFF800); + data_o[73] = ^(data_o & 76'h00001FFFFFFFC000000); + data_o[74] = ^(data_o & 76'h00FFE00000000000000); + data_o[75] = ^(data_o & 76'h7FFFFFFFFFFFFFFFFFF); + data_o ^= 76'hAA00000000000000000; + return data_o; + endfunction + + function automatic secded_inv_hamming_76_68_t + caliptra_prim_secded_inv_hamming_76_68_dec (logic [75:0] data_i); + logic [67:0] data_o; + logic [7:0] syndrome_o; + logic [1:0] err_o; + + secded_inv_hamming_76_68_t dec; + + // Syndrome calculation + syndrome_o[0] = ^((data_i ^ 76'hAA00000000000000000) & 76'h01AAB55555556AAAD5B); + syndrome_o[1] = ^((data_i ^ 76'hAA00000000000000000) & 76'h02CCD9999999B33366D); + syndrome_o[2] = ^((data_i ^ 76'hAA00000000000000000) & 76'h040F1E1E1E1E3C3C78E); + syndrome_o[3] = ^((data_i ^ 76'hAA00000000000000000) & 76'h08F01FE01FE03FC07F0); + syndrome_o[4] = ^((data_i ^ 76'hAA00000000000000000) & 76'h10001FFFE0003FFF800); + syndrome_o[5] = ^((data_i ^ 76'hAA00000000000000000) & 76'h20001FFFFFFFC000000); + syndrome_o[6] = ^((data_i ^ 76'hAA00000000000000000) & 76'h40FFE00000000000000); + syndrome_o[7] = ^((data_i ^ 76'hAA00000000000000000) & 76'hFFFFFFFFFFFFFFFFFFF); + + // Corrected output calculation + data_o[0] = (syndrome_o == 8'h83) ^ data_i[0]; + data_o[1] = (syndrome_o == 8'h85) ^ data_i[1]; + data_o[2] = (syndrome_o == 8'h86) ^ data_i[2]; + data_o[3] = (syndrome_o == 8'h87) ^ data_i[3]; + data_o[4] = (syndrome_o == 8'h89) ^ data_i[4]; + data_o[5] = (syndrome_o == 8'h8a) ^ data_i[5]; + data_o[6] = (syndrome_o == 8'h8b) ^ data_i[6]; + data_o[7] = (syndrome_o == 8'h8c) ^ data_i[7]; + data_o[8] = (syndrome_o == 8'h8d) ^ data_i[8]; + data_o[9] = (syndrome_o == 8'h8e) ^ data_i[9]; + data_o[10] = (syndrome_o == 8'h8f) ^ data_i[10]; + data_o[11] = (syndrome_o == 8'h91) ^ data_i[11]; + data_o[12] = (syndrome_o == 8'h92) ^ data_i[12]; + data_o[13] = (syndrome_o == 8'h93) ^ data_i[13]; + data_o[14] = (syndrome_o == 8'h94) ^ data_i[14]; + data_o[15] = (syndrome_o == 8'h95) ^ data_i[15]; + data_o[16] = (syndrome_o == 8'h96) ^ data_i[16]; + data_o[17] = (syndrome_o == 8'h97) ^ data_i[17]; + data_o[18] = (syndrome_o == 8'h98) ^ data_i[18]; + data_o[19] = (syndrome_o == 8'h99) ^ data_i[19]; + data_o[20] = (syndrome_o == 8'h9a) ^ data_i[20]; + data_o[21] = (syndrome_o == 8'h9b) ^ data_i[21]; + data_o[22] = (syndrome_o == 8'h9c) ^ data_i[22]; + data_o[23] = (syndrome_o == 8'h9d) ^ data_i[23]; + data_o[24] = (syndrome_o == 8'h9e) ^ data_i[24]; + data_o[25] = (syndrome_o == 8'h9f) ^ data_i[25]; + data_o[26] = (syndrome_o == 8'ha1) ^ data_i[26]; + data_o[27] = (syndrome_o == 8'ha2) ^ data_i[27]; + data_o[28] = (syndrome_o == 8'ha3) ^ data_i[28]; + data_o[29] = (syndrome_o == 8'ha4) ^ data_i[29]; + data_o[30] = (syndrome_o == 8'ha5) ^ data_i[30]; + data_o[31] = (syndrome_o == 8'ha6) ^ data_i[31]; + data_o[32] = (syndrome_o == 8'ha7) ^ data_i[32]; + data_o[33] = (syndrome_o == 8'ha8) ^ data_i[33]; + data_o[34] = (syndrome_o == 8'ha9) ^ data_i[34]; + data_o[35] = (syndrome_o == 8'haa) ^ data_i[35]; + data_o[36] = (syndrome_o == 8'hab) ^ data_i[36]; + data_o[37] = (syndrome_o == 8'hac) ^ data_i[37]; + data_o[38] = (syndrome_o == 8'had) ^ data_i[38]; + data_o[39] = (syndrome_o == 8'hae) ^ data_i[39]; + data_o[40] = (syndrome_o == 8'haf) ^ data_i[40]; + data_o[41] = (syndrome_o == 8'hb0) ^ data_i[41]; + data_o[42] = (syndrome_o == 8'hb1) ^ data_i[42]; + data_o[43] = (syndrome_o == 8'hb2) ^ data_i[43]; + data_o[44] = (syndrome_o == 8'hb3) ^ data_i[44]; + data_o[45] = (syndrome_o == 8'hb4) ^ data_i[45]; + data_o[46] = (syndrome_o == 8'hb5) ^ data_i[46]; + data_o[47] = (syndrome_o == 8'hb6) ^ data_i[47]; + data_o[48] = (syndrome_o == 8'hb7) ^ data_i[48]; + data_o[49] = (syndrome_o == 8'hb8) ^ data_i[49]; + data_o[50] = (syndrome_o == 8'hb9) ^ data_i[50]; + data_o[51] = (syndrome_o == 8'hba) ^ data_i[51]; + data_o[52] = (syndrome_o == 8'hbb) ^ data_i[52]; + data_o[53] = (syndrome_o == 8'hbc) ^ data_i[53]; + data_o[54] = (syndrome_o == 8'hbd) ^ data_i[54]; + data_o[55] = (syndrome_o == 8'hbe) ^ data_i[55]; + data_o[56] = (syndrome_o == 8'hbf) ^ data_i[56]; + data_o[57] = (syndrome_o == 8'hc1) ^ data_i[57]; + data_o[58] = (syndrome_o == 8'hc2) ^ data_i[58]; + data_o[59] = (syndrome_o == 8'hc3) ^ data_i[59]; + data_o[60] = (syndrome_o == 8'hc4) ^ data_i[60]; + data_o[61] = (syndrome_o == 8'hc5) ^ data_i[61]; + data_o[62] = (syndrome_o == 8'hc6) ^ data_i[62]; + data_o[63] = (syndrome_o == 8'hc7) ^ data_i[63]; + data_o[64] = (syndrome_o == 8'hc8) ^ data_i[64]; + data_o[65] = (syndrome_o == 8'hc9) ^ data_i[65]; + data_o[66] = (syndrome_o == 8'hca) ^ data_i[66]; + data_o[67] = (syndrome_o == 8'hcb) ^ data_i[67]; + + // err_o calc. bit0: single error, bit1: double error + err_o[0] = syndrome_o[7]; + err_o[1] = |syndrome_o[6:0] & ~syndrome_o[7]; + + dec.data = data_o; + dec.syndrome = syndrome_o; + dec.err = err_o; + return dec; + + endfunction + + +endpackage diff --git a/src/caliptra_prim/rtl/caliptra_prim_subreg.sv b/src/caliptra_prim/rtl/caliptra_prim_subreg.sv index 8bb91d955..53511f1a1 100644 --- a/src/caliptra_prim/rtl/caliptra_prim_subreg.sv +++ b/src/caliptra_prim/rtl/caliptra_prim_subreg.sv @@ -9,7 +9,8 @@ module caliptra_prim_subreg #( parameter int DW = 32, parameter sw_access_e SwAccess = SwAccessRW, - parameter logic [DW-1:0] RESVAL = '0 // reset value + parameter logic [DW-1:0] RESVAL = '0 , // reset value + parameter bit Mubi = 1'b0 ) ( input clk_i, input rst_ni, @@ -39,7 +40,8 @@ module caliptra_prim_subreg caliptra_prim_subreg_arb #( .DW ( DW ), - .SwAccess ( SwAccess ) + .SwAccess ( SwAccess ), + .Mubi ( Mubi ) ) wr_en_data_arb ( .we, .wd, @@ -61,6 +63,13 @@ module caliptra_prim_subreg // feed back out for consolidation assign ds = wr_en ? wr_data : qs; assign qe = wr_en; - assign qs = q; + + if (SwAccess == SwAccessRC) begin : gen_rc + // In case of a SW RC colliding with a HW write, SW gets the value written by HW + // but the register is cleared to 0. See #5416 for a discussion. + assign qs = de && we ? d : q; + end else begin : gen_no_rc + assign qs = q; + end endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_subreg_arb.sv b/src/caliptra_prim/rtl/caliptra_prim_subreg_arb.sv index d660a5465..be3f5b978 100644 --- a/src/caliptra_prim/rtl/caliptra_prim_subreg_arb.sv +++ b/src/caliptra_prim/rtl/caliptra_prim_subreg_arb.sv @@ -8,7 +8,8 @@ module caliptra_prim_subreg_arb import caliptra_prim_subreg_pkg::*; #( parameter int DW = 32, - parameter sw_access_e SwAccess = SwAccessRW + parameter sw_access_e SwAccess = SwAccessRW, + parameter bit Mubi = 1'b0 ) ( // From SW: valid for RW, WO, W1C, W1S, W0C, RC. // In case of RC, top connects read pulse to we. @@ -26,13 +27,18 @@ module caliptra_prim_subreg_arb output logic wr_en, output logic [DW-1:0] wr_data ); + import caliptra_prim_mubi_pkg::*; if (SwAccess inside {SwAccessRW, SwAccessWO}) begin : gen_w assign wr_en = we | de; assign wr_data = (we == 1'b1) ? wd : d; // SW higher priority // Unused q - Prevent lint errors. logic [DW-1:0] unused_q; + //VCS coverage off + // pragma coverage off assign unused_q = q; + //VCS coverage on + // pragma coverage on end else if (SwAccess == SwAccessRO) begin : gen_ro assign wr_en = de; assign wr_data = d; @@ -40,32 +46,128 @@ module caliptra_prim_subreg_arb logic unused_we; logic [DW-1:0] unused_wd; logic [DW-1:0] unused_q; + //VCS coverage off + // pragma coverage off assign unused_we = we; assign unused_wd = wd; assign unused_q = q; + //VCS coverage on + // pragma coverage on end else if (SwAccess == SwAccessW1S) begin : gen_w1s // If SwAccess is W1S, then assume hw tries to clear. // So, give a chance HW to clear when SW tries to set. // If both try to set/clr at the same bit pos, SW wins. assign wr_en = we | de; - assign wr_data = (de ? d : q) | (we ? wd : '0); + if (Mubi) begin : gen_mubi + if (DW == 4) begin : gen_mubi4 + assign wr_data = caliptra_prim_mubi_pkg::mubi4_or_hi(caliptra_prim_mubi_pkg::mubi4_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi4_t'(wd) : + caliptra_prim_mubi_pkg::MuBi4False)); + end else if (DW == 8) begin : gen_mubi8 + assign wr_data = caliptra_prim_mubi_pkg::mubi8_or_hi(caliptra_prim_mubi_pkg::mubi8_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi8_t'(wd) : + caliptra_prim_mubi_pkg::MuBi8False)); + end else if (DW == 12) begin : gen_mubi12 + assign wr_data = caliptra_prim_mubi_pkg::mubi12_or_hi(caliptra_prim_mubi_pkg::mubi12_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi12_t'(wd) : + caliptra_prim_mubi_pkg::MuBi12False)); + end else if (DW == 16) begin : gen_mubi16 + assign wr_data = caliptra_prim_mubi_pkg::mubi16_or_hi(caliptra_prim_mubi_pkg::mubi16_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi16_t'(wd) : + caliptra_prim_mubi_pkg::MuBi16False)); + end else begin : gen_invalid_mubi + $error("%m: Invalid width for MuBi"); + end + end else begin : gen_non_mubi + assign wr_data = (de ? d : q) | (we ? wd : '0); + end end else if (SwAccess == SwAccessW1C) begin : gen_w1c // If SwAccess is W1C, then assume hw tries to set. // So, give a chance HW to set when SW tries to clear. // If both try to set/clr at the same bit pos, SW wins. assign wr_en = we | de; - assign wr_data = (de ? d : q) & (we ? ~wd : '1); + if (Mubi) begin : gen_mubi + if (DW == 4) begin : gen_mubi4 + assign wr_data = caliptra_prim_mubi_pkg::mubi4_and_hi(caliptra_prim_mubi_pkg::mubi4_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi4_t'(~wd) : + caliptra_prim_mubi_pkg::MuBi4True)); + end else if (DW == 8) begin : gen_mubi8 + assign wr_data = caliptra_prim_mubi_pkg::mubi8_and_hi(caliptra_prim_mubi_pkg::mubi8_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi8_t'(~wd) : + caliptra_prim_mubi_pkg::MuBi8True)); + end else if (DW == 12) begin : gen_mubi12 + assign wr_data = caliptra_prim_mubi_pkg::mubi12_and_hi(caliptra_prim_mubi_pkg::mubi12_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi12_t'(~wd) : + caliptra_prim_mubi_pkg::MuBi12True)); + end else if (DW == 16) begin : gen_mubi16 + assign wr_data = caliptra_prim_mubi_pkg::mubi16_and_hi(caliptra_prim_mubi_pkg::mubi16_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi16_t'(~wd) : + caliptra_prim_mubi_pkg::MuBi16True)); + end else begin : gen_invalid_mubi + $error("%m: Invalid width for MuBi"); + end + end else begin : gen_non_mubi + assign wr_data = (de ? d : q) & (we ? ~wd : '1); + end end else if (SwAccess == SwAccessW0C) begin : gen_w0c assign wr_en = we | de; - assign wr_data = (de ? d : q) & (we ? wd : '1); + if (Mubi) begin : gen_mubi + if (DW == 4) begin : gen_mubi4 + assign wr_data = caliptra_prim_mubi_pkg::mubi4_and_hi(caliptra_prim_mubi_pkg::mubi4_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi4_t'(wd) : + caliptra_prim_mubi_pkg::MuBi4True)); + end else if (DW == 8) begin : gen_mubi8 + assign wr_data = caliptra_prim_mubi_pkg::mubi8_and_hi(caliptra_prim_mubi_pkg::mubi8_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi8_t'(wd) : + caliptra_prim_mubi_pkg::MuBi8True)); + end else if (DW == 12) begin : gen_mubi12 + assign wr_data = caliptra_prim_mubi_pkg::mubi12_and_hi(caliptra_prim_mubi_pkg::mubi12_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi12_t'(wd) : + caliptra_prim_mubi_pkg::MuBi12True)); + end else if (DW == 16) begin : gen_mubi16 + assign wr_data = caliptra_prim_mubi_pkg::mubi16_and_hi(caliptra_prim_mubi_pkg::mubi16_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi16_t'(wd) : + caliptra_prim_mubi_pkg::MuBi16True)); + end else begin : gen_invalid_mubi + $error("%m: Invalid width for MuBi"); + end + end else begin : gen_non_mubi + assign wr_data = (de ? d : q) & (we ? wd : '1); + end end else if (SwAccess == SwAccessRC) begin : gen_rc // This swtype is not recommended but exists for compatibility. // WARN: we signal is actually read signal not write enable. assign wr_en = we | de; - assign wr_data = (de ? d : q) & (we ? '0 : '1); + if (Mubi) begin : gen_mubi + if (DW == 4) begin : gen_mubi4 + assign wr_data = caliptra_prim_mubi_pkg::mubi4_and_hi(caliptra_prim_mubi_pkg::mubi4_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::MuBi4False : + caliptra_prim_mubi_pkg::MuBi4True)); + end else if (DW == 8) begin : gen_mubi8 + assign wr_data = caliptra_prim_mubi_pkg::mubi8_and_hi(caliptra_prim_mubi_pkg::mubi8_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::MuBi8False : + caliptra_prim_mubi_pkg::MuBi8True)); + end else if (DW == 12) begin : gen_mubi12 + assign wr_data = caliptra_prim_mubi_pkg::mubi12_and_hi(caliptra_prim_mubi_pkg::mubi12_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::MuBi12False : + caliptra_prim_mubi_pkg::MuBi12True)); + end else if (DW == 16) begin : gen_mubi16 + assign wr_data = caliptra_prim_mubi_pkg::mubi16_and_hi(caliptra_prim_mubi_pkg::mubi16_t'(de ? d : q), + (we ? caliptra_prim_mubi_pkg::mubi16_t'(wd) : + caliptra_prim_mubi_pkg::MuBi16True)); + end else begin : gen_invalid_mubi + $error("%m: Invalid width for MuBi"); + end + end else begin : gen_non_mubi + assign wr_data = (de ? d : q) & (we ? '0 : '1); + end // Unused wd - Prevent lint errors. logic [DW-1:0] unused_wd; + //VCS coverage off + // pragma coverage off assign unused_wd = wd; + //VCS coverage on + // pragma coverage on end else begin : gen_hw assign wr_en = de; assign wr_data = d; @@ -73,9 +175,13 @@ module caliptra_prim_subreg_arb logic unused_we; logic [DW-1:0] unused_wd; logic [DW-1:0] unused_q; + //VCS coverage off + // pragma coverage off assign unused_we = we; assign unused_wd = wd; assign unused_q = q; + //VCS coverage on + // pragma coverage on end endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv b/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv new file mode 100644 index 000000000..e4b8553ee --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv @@ -0,0 +1,196 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// Shadowed register slice conforming to Comportibility guide. + +`include "caliptra_prim_assert.sv" + +module caliptra_prim_subreg_shadow + import caliptra_prim_subreg_pkg::*; +#( + parameter int DW = 32, + parameter sw_access_e SwAccess = SwAccessRW, + parameter logic [DW-1:0] RESVAL = '0, // reset value + parameter bit Mubi = 1'b0 +) ( + input clk_i, + input rst_ni, + input rst_shadowed_ni, + + // From SW: valid for RW, WO, W1C, W1S, W0C, RC. + // SW reads clear phase unless SwAccess is RO. + input re, + // In case of RC, top connects read pulse to we. + input we, + input [DW-1:0] wd, + + // From HW: valid for HRW, HWO. + input de, + input [DW-1:0] d, + + // Output to HW and Reg Read + output logic qe, + output logic [DW-1:0] q, + output logic [DW-1:0] ds, + output logic [DW-1:0] qs, + + // Phase output to HW + output logic phase, + + // Error conditions + output logic err_update, + output logic err_storage +); + + // Since the shadow register works with the 1's complement value, + // we need to invert the polarity of the SW access if it is either "W1S" or "W0C". + // W1C is forbidden since the W0S complement is not implemented. + `CALIPTRA_ASSERT_INIT(CheckSwAccessIsLegal_A, + SwAccess inside {SwAccessRW, SwAccessRO, SwAccessWO, SwAccessW1S, SwAccessW0C}) + localparam sw_access_e InvertedSwAccess = (SwAccess == SwAccessW1S) ? SwAccessW0C : + (SwAccess == SwAccessW0C) ? SwAccessW1S : SwAccess; + + // For the staging register, we set the SwAccess to RW in case of W1S and W0C in + // order to always capture the data value on the first write operation - no matter + // whether the data value will actually have an effect. That way, we can still capture + // inconsistent double writes which would otherwise be ignored due to the data value filtering + // effect that W1S and W0C can have. + localparam sw_access_e StagedSwAccess = (SwAccess == SwAccessW1S) ? SwAccessRW : + (SwAccess == SwAccessW0C) ? SwAccessRW : SwAccess; + + // Subreg control signals + logic phase_clear; + logic phase_q; + logic staged_we, shadow_we, committed_we; + logic staged_de, shadow_de, committed_de; + + // Subreg status and data signals + logic committed_qe; + logic [DW-1:0] staged_q, shadow_q, committed_q; + logic [DW-1:0] committed_qs; + + // Effective write enable and write data signals. + // These depend on we, de and wd, d, q as well as SwAccess. + logic wr_en; + logic [DW-1:0] wr_data; + + caliptra_prim_subreg_arb #( + .DW ( DW ), + .SwAccess ( SwAccess ) + ) wr_en_data_arb ( + .we ( we ), + .wd ( wd ), + .de ( de ), + .d ( d ), + .q ( q ), + .wr_en ( wr_en ), + .wr_data ( wr_data ) + ); + + // Phase clearing: + // - SW reads clear phase unless SwAccess is RO. + // - In case of RO, SW should not interfere with update process. + assign phase_clear = (SwAccess == SwAccessRO) ? 1'b0 : re; + + // Phase tracker: + // - Reads from SW clear the phase back to 0. + // - Writes have priority (can come from SW or HW). + always_ff @(posedge clk_i or negedge rst_ni) begin : phase_reg + if (!rst_ni) begin + phase_q <= 1'b0; + end else if (wr_en && !err_storage) begin + phase_q <= ~phase_q; + end else if (phase_clear || err_storage) begin + phase_q <= 1'b0; + end + end + + // The staged register: + // - Holds the 1's complement value. + // - Written in Phase 0. + // - Once storage error occurs, do not allow any further update until reset + assign staged_we = we & ~phase_q & ~err_storage; + assign staged_de = de & ~phase_q & ~err_storage; + caliptra_prim_subreg #( + .DW ( DW ), + .SwAccess ( StagedSwAccess ), + .RESVAL ( ~RESVAL ) + ) staged_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .we ( staged_we ), + .wd ( ~wr_data ), + .de ( staged_de ), + .d ( ~d ), + .qe ( ), + .q ( staged_q ), + .ds ( ), + .qs ( ) + ); + + // The shadow register: + // - Holds the 1's complement value. + // - Written in Phase 1. + // - Writes are ignored in case of update errors. + // - Gets the value from the staged register. + // - Once storage error occurs, do not allow any further update until reset + assign shadow_we = we & phase_q & ~err_update & ~err_storage; + assign shadow_de = de & phase_q & ~err_update & ~err_storage; + caliptra_prim_subreg #( + .DW ( DW ), + .SwAccess ( InvertedSwAccess ), + .RESVAL ( ~RESVAL ) + ) shadow_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_shadowed_ni ), + .we ( shadow_we ), + .wd ( staged_q ), + .de ( shadow_de ), + .d ( staged_q ), + .qe ( ), + .q ( shadow_q ), + .ds ( ), + .qs ( ) + ); + + // The committed register: + // - Written in Phase 1. + // - Writes are ignored in case of update errors. + assign committed_we = shadow_we; + assign committed_de = shadow_de; + caliptra_prim_subreg #( + .DW ( DW ), + .SwAccess ( SwAccess ), + .RESVAL ( RESVAL ) + ) committed_reg ( + .clk_i ( clk_i ), + .rst_ni ( rst_ni ), + .we ( committed_we ), + .wd ( wr_data ), + .de ( committed_de ), + .d ( d ), + .qe ( committed_qe ), + .q ( committed_q ), + .ds ( ds ), + .qs ( committed_qs ) + ); + + // Output phase for hwext. + assign phase = phase_q; + + // Error detection - all bits must match. + assign err_update = (~staged_q != wr_data) ? phase_q & wr_en : 1'b0; + assign err_storage = (~shadow_q != committed_q); + + // Remaining output assignments + assign qe = committed_qe; + assign q = committed_q; + assign qs = committed_qs; + + // caliptra_prim_subreg_shadow does not support multi-bit software access yet + `CALIPTRA_ASSERT_NEVER(MubiIsNotYetSupported_A, Mubi) + logic unused_mubi; + assign unused_mubi = Mubi; + +endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv b/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv new file mode 100644 index 000000000..ae7c0e7f8 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv @@ -0,0 +1,404 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// REQ/ACK synchronizer +// +// This module synchronizes a REQ/ACK handshake across a clock domain crossing. +// Both domains will see a handshake with the duration of one clock cycle. +// +// Notes: +// - Once asserted, the source (SRC) domain is not allowed to de-assert REQ without ACK. +// - The destination (DST) domain is not allowed to send an ACK without a REQ. +// - When resetting one domain, also the other domain needs to be reset with both resets being +// active at the same time. +// - This module works both when syncing from a faster to a slower clock domain and vice versa. +// - Internally, this module uses a non-return-to-zero (NRZ), two-phase handshake protocol by +// default. Assuming the DST domain responds with an ACK immediately, the latency from asserting +// the REQ in the SRC domain is: +// - 1 source + 2 destination clock cycles until the handshake is performed in the DST domain, +// - 1 source + 2 destination + 1 destination + 2 source clock cycles until the handshake is +// performed in the SRC domain. +// - Optionally, the module can also use a return-to-zero (RZ), four-phase handshake protocol. +// That one has lower throughput, but it is safe to reset either domain in isolation, since the +// two FSMs cannot get out of sync due to persistent EVEN/ODD states. The handshake latencies +// are the same as for the NRZ protocol, but the throughput is half that of the NRZ protocol +// since the signals neet to return to zero first, causing two round-trips through the +// synchronizers instead of just one. +// +// For further information, see Section 8.2.4 in H. Kaeslin, "Top-Down Digital VLSI Design: From +// Architecture to Gate-Level Circuits and FPGAs", 2015. + +`include "caliptra_prim_assert.sv" + +module caliptra_prim_sync_reqack #( + parameter bit EnRstChks = 1'b0, // Enable reset-related assertion checks, disabled by default. + parameter bit EnRzHs = 1'b0 // By Default, the faster NRZ handshake protocol + // (EnRzHs = 0) is used. Enable the RZ handshake protocol + // if the FSMs need to be partial-reset-safe. +) ( + input clk_src_i, // REQ side, SRC domain + input rst_src_ni, // REQ side, SRC domain + input clk_dst_i, // ACK side, DST domain + input rst_dst_ni, // ACK side, DST domain + + input logic req_chk_i, // Used for gating assertions. Drive to 1 during normal operation. + + input logic src_req_i, // REQ side, SRC domain + output logic src_ack_o, // REQ side, SRC domain + output logic dst_req_o, // ACK side, DST domain + input logic dst_ack_i // ACK side, DST domain +); + + // req_chk_i is used for gating assertions only. + logic unused_req_chk; + assign unused_req_chk = req_chk_i; + + if (EnRzHs) begin : gen_rz_hs_protocol + ////////////////// + // RZ protocol // + ////////////////// + + // Types + typedef enum logic { + LoSt, HiSt + } rz_fsm_e; + + // Signals + rz_fsm_e src_fsm_d, src_fsm_q; + rz_fsm_e dst_fsm_d, dst_fsm_q; + logic src_ack, dst_ack; + logic src_req, dst_req; + + // REQ-side FSM (SRC domain) + always_comb begin : src_fsm + src_fsm_d = src_fsm_q; + src_ack_o = 1'b0; + src_req = 1'b0; + + unique case (src_fsm_q) + LoSt: begin + // Wait for the ack to go back to zero before starting + // a new transaction. + if (!src_ack && src_req_i) begin + src_fsm_d = HiSt; + end + end + HiSt: begin + src_req = 1'b1; + // Forward the acknowledgement. + src_ack_o = src_ack; + // If request drops out, we go back to LoSt. + // If DST side asserts ack, we also go back to LoSt. + if (!src_req_i || src_ack) begin + src_fsm_d = LoSt; + end + end + //VCS coverage off + // pragma coverage off + default: ; + //VCS coverage on + // pragma coverage on + endcase + end + + // Move ACK over to SRC domain. + caliptra_prim_flop_2sync #( + .Width(1) + ) ack_sync ( + .clk_i (clk_src_i), + .rst_ni (rst_src_ni), + .d_i (dst_ack), + .q_o (src_ack) + ); + + // Registers + always_ff @(posedge clk_src_i or negedge rst_src_ni) begin + if (!rst_src_ni) begin + src_fsm_q <= LoSt; + end else begin + src_fsm_q <= src_fsm_d; + end + end + + // ACK-side FSM (DST domain) + always_comb begin : dst_fsm + dst_fsm_d = dst_fsm_q; + dst_req_o = 1'b0; + dst_ack = 1'b0; + + unique case (dst_fsm_q) + LoSt: begin + if (dst_req) begin + // Forward the request. + dst_req_o = 1'b1; + // Wait for the request and acknowledge to be asserted + // before responding to the SRC side. + if (dst_ack_i) begin + dst_fsm_d = HiSt; + end + end + end + HiSt: begin + dst_ack = 1'b1; + // Wait for the request to drop back to zero. + if (!dst_req) begin + dst_fsm_d = LoSt; + end + end + //VCS coverage off + // pragma coverage off + default: ; + //VCS coverage on + // pragma coverage on + endcase + end + + // Move REQ over to DST domain. + caliptra_prim_flop_2sync #( + .Width(1) + ) req_sync ( + .clk_i (clk_dst_i), + .rst_ni (rst_dst_ni), + .d_i (src_req), + .q_o (dst_req) + ); + + // Registers + always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin + if (!rst_dst_ni) begin + dst_fsm_q <= LoSt; + end else begin + dst_fsm_q <= dst_fsm_d; + end + end + + end else begin : gen_nrz_hs_protocol + ////////////////// + // NRZ protocol // + ////////////////// + + // Types + typedef enum logic { + EVEN, ODD + } sync_reqack_fsm_e; + + // Signals + sync_reqack_fsm_e src_fsm_ns, src_fsm_cs; + sync_reqack_fsm_e dst_fsm_ns, dst_fsm_cs; + + logic src_req_d, src_req_q, src_ack; + logic dst_ack_d, dst_ack_q, dst_req; + logic src_handshake, dst_handshake; + + assign src_handshake = src_req_i & src_ack_o; + assign dst_handshake = dst_req_o & dst_ack_i; + + // Move REQ over to DST domain. + caliptra_prim_flop_2sync #( + .Width(1) + ) req_sync ( + .clk_i (clk_dst_i), + .rst_ni (rst_dst_ni), + .d_i (src_req_q), + .q_o (dst_req) + ); + + // Move ACK over to SRC domain. + caliptra_prim_flop_2sync #( + .Width(1) + ) ack_sync ( + .clk_i (clk_src_i), + .rst_ni (rst_src_ni), + .d_i (dst_ack_q), + .q_o (src_ack) + ); + + // REQ-side FSM (SRC domain) + always_comb begin : src_fsm + src_fsm_ns = src_fsm_cs; + + // By default, we keep the internal REQ value and don't ACK. + src_req_d = src_req_q; + src_ack_o = 1'b0; + + unique case (src_fsm_cs) + + EVEN: begin + // Simply forward REQ and ACK. + src_req_d = src_req_i; + src_ack_o = src_ack; + + // The handshake is done for exactly 1 clock cycle. + if (src_handshake) begin + src_fsm_ns = ODD; + end + end + + ODD: begin + // Internal REQ and ACK have inverted meaning now. If src_req_i is high again, this + // signals a new transaction. + src_req_d = ~src_req_i; + src_ack_o = ~src_ack; + + // The handshake is done for exactly 1 clock cycle. + if (src_handshake) begin + src_fsm_ns = EVEN; + end + end + + //VCS coverage off + // pragma coverage off + + default: ; + + //VCS coverage on + // pragma coverage on + + endcase + end + + // ACK-side FSM (DST domain) + always_comb begin : dst_fsm + dst_fsm_ns = dst_fsm_cs; + + // By default, we don't REQ and keep the internal ACK. + dst_req_o = 1'b0; + dst_ack_d = dst_ack_q; + + unique case (dst_fsm_cs) + + EVEN: begin + // Simply forward REQ and ACK. + dst_req_o = dst_req; + dst_ack_d = dst_ack_i; + + // The handshake is done for exactly 1 clock cycle. + if (dst_handshake) begin + dst_fsm_ns = ODD; + end + end + + ODD: begin + // Internal REQ and ACK have inverted meaning now. If dst_req goes low, this signals a new + // transaction. + dst_req_o = ~dst_req; + dst_ack_d = ~dst_ack_i; + + // The handshake is done for exactly 1 clock cycle. + if (dst_handshake) begin + dst_fsm_ns = EVEN; + end + end + + //VCS coverage off + // pragma coverage off + + default: ; + + //VCS coverage on + // pragma coverage on + + endcase + end + + // Registers + always_ff @(posedge clk_src_i or negedge rst_src_ni) begin + if (!rst_src_ni) begin + src_fsm_cs <= EVEN; + src_req_q <= 1'b0; + end else begin + src_fsm_cs <= src_fsm_ns; + src_req_q <= src_req_d; + end + end + always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin + if (!rst_dst_ni) begin + dst_fsm_cs <= EVEN; + dst_ack_q <= 1'b0; + end else begin + dst_fsm_cs <= dst_fsm_ns; + dst_ack_q <= dst_ack_d; + end + end + end + + //////////////// + // Assertions // + //////////////// + + `ifdef INC_ASSERT + //VCS coverage off + // pragma coverage off + + logic effective_rst_n; + assign effective_rst_n = rst_src_ni && rst_dst_ni; + + logic chk_flag; + always_ff @(posedge clk_src_i or negedge effective_rst_n) begin + if (!effective_rst_n) begin + chk_flag <= '0; + end else if (src_req_i && !chk_flag) begin + chk_flag <= 1'b1; + end + end + //VCS coverage on + // pragma coverage on + + // SRC domain can only de-assert REQ after receiving ACK. + `CALIPTRA_ASSERT(SyncReqAckHoldReq, $fell(src_req_i) && req_chk_i && chk_flag |-> + $fell(src_ack_o), clk_src_i, !rst_src_ni || !rst_dst_ni || !req_chk_i || !chk_flag) + `endif + + // DST domain cannot assert ACK without REQ. + `CALIPTRA_ASSERT(SyncReqAckAckNeedsReq, dst_ack_i |-> + dst_req_o, clk_dst_i, !rst_src_ni || !rst_dst_ni) + + if (EnRstChks) begin : gen_assert_en_rst_chks + `ifdef INC_ASSERT + + //VCS coverage off + // pragma coverage off + // This assertion is written very oddly because it is difficult to reliably catch + // when rst drops. + // The problem is that reset assertion in the design is often associated with clocks + // stopping, this means things like rise / fell don't work correctly since there are + // no clocks. + // As a result of this, we end up detecting way past the interest point (whenever + // clocks are restored) and falsely assert an error. + // The code below instead tries to use asynchronous flags to determine when and if + // the two domains are properly reset. + logic src_reset_flag; + always_ff @(posedge clk_src_i or negedge rst_src_ni) begin + if (!rst_src_ni) begin + src_reset_flag <= '0; + end else if(src_req_i) begin + src_reset_flag <= 1'b1; + end + end + + logic dst_reset_flag; + always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin + if (!rst_dst_ni) begin + dst_reset_flag <= '0; + end else if (dst_req_o) begin + dst_reset_flag <= 1'b1; + end + end + //VCS coverage on + // pragma coverage on + + // Always reset both domains. Both resets need to be active at the same time. + `CALIPTRA_ASSERT(SyncReqAckRstSrc, $fell(rst_src_ni) |-> + (!src_reset_flag throughout !dst_reset_flag[->1]), + clk_src_i, 0) + `CALIPTRA_ASSERT(SyncReqAckRstDst, $fell(rst_dst_ni) |-> + (!dst_reset_flag throughout !src_reset_flag[->1]), + clk_dst_i, 0) + + `endif + + + end + +endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv b/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv new file mode 100644 index 000000000..10f236d94 --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv @@ -0,0 +1,178 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// REQ/ACK synchronizer with associated data. +// +// This module synchronizes a REQ/ACK handshake with associated data across a clock domain +// crossing (CDC). Both domains will see a handshake with the duration of one clock cycle. By +// default, the data itself is not registered. The main purpose of feeding the data through this +// module to have an anchor point for waiving CDC violations. If the data is configured to flow +// from the destination (DST) to the source (SRC) domain, an additional register stage can be +// inserted for data buffering. +// +// Under the hood, this module uses a caliptra_prim_sync_reqack primitive for synchronizing the +// REQ/ACK handshake. See caliptra_prim_sync_reqack.sv for more details. + +`include "caliptra_prim_assert.sv" + +module caliptra_prim_sync_reqack_data #( + parameter int unsigned Width = 1, + parameter bit EnRstChks = 1'b0, // Enable reset-related assertion checks, disabled by + // default. + parameter bit DataSrc2Dst = 1'b1, // Direction of data flow: 1'b1 = SRC to DST, + // 1'b0 = DST to SRC + parameter bit DataReg = 1'b0, // Enable optional register stage for data, + // only usable with DataSrc2Dst == 1'b0. + parameter bit EnRzHs = 1'b0 // By Default, we the faster NRZ handshake protocol + // (EnRzHs = 0) is used. Enable the RZ handshake + // protocol if the FSMs need to be partial-reset-safe. +) ( + input clk_src_i, // REQ side, SRC domain + input rst_src_ni, // REQ side, SRC domain + input clk_dst_i, // ACK side, DST domain + input rst_dst_ni, // ACK side, DST domain + + input logic req_chk_i, // Used for gating assertions. Drive to 1 during normal operation. + + input logic src_req_i, // REQ side, SRC domain + output logic src_ack_o, // REQ side, SRC domain + output logic dst_req_o, // ACK side, DST domain + input logic dst_ack_i, // ACK side, DST domain + + input logic [Width-1:0] data_i, + output logic [Width-1:0] data_o +); + + //////////////////////////////////// + // REQ/ACK synchronizer primitive // + //////////////////////////////////// + caliptra_prim_sync_reqack #( + .EnRstChks(EnRstChks), + .EnRzHs(EnRzHs) + ) u_caliptra_prim_sync_reqack ( + .clk_src_i, + .rst_src_ni, + .clk_dst_i, + .rst_dst_ni, + + .req_chk_i, + + .src_req_i, + .src_ack_o, + .dst_req_o, + .dst_ack_i + ); + + ///////////////////////// + // Data register stage // + ///////////////////////// + // Optional - Only relevant if the data flows from DST to SRC. In this case, it must be ensured + // that the data remains stable until the ACK becomes visible in the SRC domain. + // + // Note that for larger data widths, it is recommended to adjust the data sender to hold the data + // stable until the next REQ in order to save the cost of this register stage. + if (DataSrc2Dst == 1'b0 && DataReg == 1'b1) begin : gen_data_reg + logic data_we; + logic [Width-1:0] data_d, data_q; + + // Sample the data when seing the REQ/ACK handshake in the DST domain. + assign data_we = dst_req_o & dst_ack_i; + assign data_d = data_i; + always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin + if (!rst_dst_ni) begin + data_q <= '0; + end else if (data_we) begin + data_q <= data_d; + end + end + assign data_o = data_q; + + end else begin : gen_no_data_reg + // Just feed through the data. + assign data_o = data_i; + end + + //////////////// + // Assertions // + //////////////// + if (DataSrc2Dst == 1'b1) begin : gen_assert_data_src2dst +`ifdef INC_CALIPTRA_ASSERT + //VCS coverage off + // pragma coverage off + logic effective_rst_n; + assign effective_rst_n = rst_src_ni && rst_dst_ni; + + logic chk_flag_d, chk_flag_q; + assign chk_flag_d = src_req_i && !chk_flag_q ? 1'b1 : chk_flag_q; + + always_ff @(posedge clk_src_i or negedge effective_rst_n) begin + if (!effective_rst_n) begin + chk_flag_q <= '0; + end else begin + chk_flag_q <= chk_flag_d; + end + end + //VCS coverage on + // pragma coverage on + + // SRC domain cannot change data while waiting for ACK. + `CALIPTRA_ASSERT(SyncReqAckDataHoldSrc2Dst, !$stable(data_i) && chk_flag_q |-> + (!src_req_i || (src_req_i && src_ack_o)), + clk_src_i, !rst_src_ni || !rst_dst_ni || !chk_flag_q) + + // Register stage cannot be used. + `CALIPTRA_ASSERT_INIT(SyncReqAckDataReg, DataSrc2Dst && !DataReg) +`endif + end else if (DataSrc2Dst == 1'b0 && DataReg == 1'b0) begin : gen_assert_data_dst2src + // DST domain shall not change data while waiting for SRC domain to latch it (together with + // receiving ACK). It takes 2 SRC cycles for ACK to cross over from DST to SRC, and 1 SRC cycle + // for the next REQ to cross over from SRC to DST. + // + // Denote the src clock where REQ & ACK as time zero. The data flowing through the CDC could be + // corrupted if data_o was not stable over the previous 2 clock cycles (so we want to check time + // points -2, -1 and 0). Moreover, the DST domain cannot know that it is allowed to change value + // until at least one more SRC cycle (the time taken for REQ to cross back from SRC to DST). + // + // To make this assertion, we will sample at each of 4 time points (-2, -1, 0 and +1), asserting + // that data_o is equal at each of these times. Note this won't detect glitches at intermediate + // timepoints. + // + // The SVAs below are designed not to consume time, which means that they can be disabled with + // an $assertoff(..) and won't linger to fail later. This wouldn't work properly if we used + // something like |=> instead of the $past(...) function. That means that we have to trigger at + // the "end" of the window. To make sure we don't miss a situation where the value changed at + // time -1 (causing corruption), but reset was asserted between time 0 and 1, we split the + // assertion into two pieces. The first (SyncReqAckDataHoldDst2SrcA) checks that data doesn't + // change in a way that could cause data corruption. The second (SyncReqAckDataHoldDst2SrcB) + // checks that the DST side doesn't do anything that it shouldn't know is safe. +`ifdef INC_CALIPTRA_ASSERT + //VCS coverage off + // pragma coverage off + logic effective_rst_n; + assign effective_rst_n = rst_src_ni && rst_dst_ni; + + logic chk_flag_d, chk_flag_q; + assign chk_flag_d = src_req_i && !chk_flag_q ? 1'b1 : chk_flag_q; + + always_ff @(posedge clk_src_i or negedge effective_rst_n) begin + if (!effective_rst_n) begin + chk_flag_q <= '0; + end else begin + chk_flag_q <= chk_flag_d; + end + end + //VCS coverage on + // pragma coverage on + + `CALIPTRA_ASSERT(SyncReqAckDataHoldDst2SrcA, + chk_flag_q && src_req_i && src_ack_o |-> + $past(data_o, 2) == data_o && $past(data_o) == data_o, + clk_src_i, !rst_src_ni || !rst_dst_ni || !chk_flag_q) + `CALIPTRA_ASSERT(SyncReqAckDataHoldDst2SrcB, + chk_flag_q && $past(src_req_i && src_ack_o) |-> $past(data_o) == data_o, + clk_src_i, !rst_src_ni || !rst_dst_ni || !chk_flag_q) +`endif + end + +endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_trivium.sv b/src/caliptra_prim/rtl/caliptra_prim_trivium.sv new file mode 100644 index 000000000..c00cf88bc --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_trivium.sv @@ -0,0 +1,317 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +// Trivium and Bivium stream cipher primitives +// +// This module implements the Trivium [1] and its reduced variant Bivium [2] (more precisely +// Bivium B) stream cipher primitives. Internally, they use 3 (Trivium) or 2 (Bivium) non-linear +// feedback shift registers (NFSRs). The number of output bits produced per update can flexibly +// be tuned using the OutputWidth parameter to match the needs of integrators. Up to an output +// width of 64 bits, the critical path stays unchanged. For output widths above 64 bits, the +// critical path starts to increase. The asymptotic area of the two primitives is 30 GE / output +// bit (Trivium) and 20 GE / output bit (Bivium). For a thorough analysis of the two primitives +// including security evaluation, as well as area and critical path figures, refer to [3]. +// +// As thoroughly analyzed in [3], these primitives are suitable to be used as pseudo-random +// number generators for masking countermeasures in hardware. +// +// This implementation supports three different reseeding interfaces which can be selected using +// the SeedType parameter: +// 1. SeedTypeKeyIv: 2 x 80 bits for key and IV need to be provided. Before the key stream becomes +// usable, the primitive needs to be updated 1152 / OutputWidth (Trivium) or +// 708 / OutputWidth (Bivium) times. These initial updates are performed automatically by the +// primitives. Once the reseeding and the following initialization are done, this is indicated +// with the seed_done_o output. +// 2. SeedTypeStateFull: The full 288-bit (Trivium) or 177-bit (Bivium) state is reseeded in one +// shot. +// 3. SeedTypeStatePartial: PartialSeedWidth bits at a time are injected into the state. The +// primitive latches the seed_en_i signal and keeps requesting entropy until every +// PartialSeedWidth-wide part of the state has been overwritten once. +// To enable updating the primitive and using the key stream during the reseed operation, the +// number of output bits produced per update (OutputWidth) should be greater than the width of +// the smallest NFSR in the primitve (MinNfsrWidth = 84). Thanks to the strong diffusion +// properties of the primitives, the majority of state and key stream bits change after +// reseeding the first state part and performing the first couple of updates if OutputWidth is +// chosen sufficiently large. For Bivium, a quick evaluation hints that for OutputWidth equal +// to 84, the key stream seems usable after 3 updates and most state bits seem to change after +// 5 updates. For OutputWidth equal to 160, the key stream seems usable after only 2 updates and +// most state bits seem to change after 3 updates. +// If the next PartialSeedWidth bits of entropy arrive after having done at least one update +// but the new entropy hasn't sufficiently diffused yet into the state, there is a risk that +// previously injected entropy bits are partially or completely overwritten. It is the job of +// the integrator to ensure sufficiently many updates are performed between reseeding state +// parts. In practice, this should be relatively simple as there is typically a minimal latency +// between receiving entropy bits, e.g., due to clock domain crossings in the system. +// Independently of the chosen OutputWidth parameter, it's always safe to reseed the primitive +// while it's completely idle. +// +// For details, see the following specifications and papers: +// [1] De Canniere, "Trivium Specifications" available at +// https://www.ecrypt.eu.org/stream/p3ciphers/trivium/trivium_p3.pdf +// [2] Raddum "Cryptanalytic Results on Trivium" available at +// https://www.ecrypt.eu.org/stream/papersdir/2006/039.ps +// [3] Cassiers, "Randomness Generation for Secure Hardware Masking - Unrolled Trivium to the +// Rescue" available at https://eprint.iacr.org/2023/1134 + +`include "caliptra_prim_assert.sv" + +module caliptra_prim_trivium import caliptra_prim_trivium_pkg::*; +#( + parameter bit BiviumVariant = 0, // 0: Trivium, 1: Bivium + parameter int unsigned OutputWidth = 64, // Number of output bits generated per update. + parameter bit StrictLockupProtection = 1, // Upon entering an all zero state, 1: always + // restore to the default seed, or 0: allow + // to keep the all zero state if requested by + // allow_lockup_i. + parameter seed_type_e SeedType = SeedTypeStateFull, // Reseeding inteface selection, see + // caliptra_prim_trivium_pkg.sv for possible values. + parameter int unsigned PartialSeedWidth = PartialSeedWidthDefault, + + // derived parameter + localparam int unsigned StateWidth = BiviumVariant ? BiviumStateWidth : TriviumStateWidth, + + parameter trivium_lfsr_seed_t RndCnstTriviumLfsrSeed = RndCnstTriviumLfsrSeedDefault, + + // derived parameter + localparam logic [StateWidth-1:0] StateSeed = RndCnstTriviumLfsrSeed[StateWidth-1:0] +) ( + input logic clk_i, + input logic rst_ni, + + input logic en_i, // Update the primitive. + input logic allow_lockup_i, // Allow locking up in all zero state. + // Only taken into account if + // LockupParameter = 0 + input logic seed_en_i, // Start reseeding (pulse or level). + output logic seed_done_o, // Reseeding is done (pulse). + output logic seed_req_o, // Seed REQ handshake signal + input logic seed_ack_i, // Seed ACK handshake signal + input logic [KeyIvWidth-1:0] seed_key_i, // Seed input for SeedTypeKeyIV + input logic [KeyIvWidth-1:0] seed_iv_i, // Seed input for SeedTypeKeyIV + input logic [StateWidth-1:0] seed_state_full_i, // Seed input for SeedTypeStateFull + input logic [PartialSeedWidth-1:0] seed_state_partial_i, // Seed input for SeedTypeStatePartial + + output logic [OutputWidth-1:0] key_o, // Key stream output + output logic err_o // The primitive entered an all zero state and may have + // locked up or entered the default state defined by + // RndCnstTriviumLfsrSeed depending on the + // StrictLockupProtection parameter and the allow_lockup_i + // signal. +); + + localparam int unsigned LastStatePartFractional = StateWidth % PartialSeedWidth != 0 ? 1 : 0; + localparam int unsigned NumStateParts = StateWidth / PartialSeedWidth + LastStatePartFractional; + localparam int unsigned NumBitsLastPart = StateWidth - (NumStateParts - 1) * PartialSeedWidth; + localparam int unsigned LastStatePart = NumStateParts - 1; + // Width of the variable determining which state part to overwrite with the next partial seed. + localparam int unsigned StateIdxWidth = caliptra_prim_util_pkg::vbits(NumStateParts); + + logic [StateWidth-1:0] state_d, state_q; + logic [StateWidth-1:0] state_update, state_seed; + logic seed_req_d, seed_req_q; + logic unused_seed; + logic update, update_init, wr_en_seed; + logic [StateIdxWidth-1:0] state_idx_d, state_idx_q; + logic last_state_part; + logic lockup, restore; + + assign update = en_i | update_init; + assign wr_en_seed = seed_req_o & seed_ack_i; + assign lockup = ~(|state_q); + assign err_o = lockup; + + ////////////////////////////////////////////////// + // Regular state updating and output generation // + ////////////////////////////////////////////////// + + // The current key stream depends on the current state only. + if (BiviumVariant) begin : gen_update_and_output_bivium + always_comb begin + state_update = state_q; + for (int unsigned i = 0; i < OutputWidth; i++) begin + key_o[i] = bivium_generate_key_stream(state_update); + state_update = bivium_update_state(state_update); + end + end + end else begin : gen_update_and_output_trivium + always_comb begin + state_update = state_q; + for (int unsigned i = 0; i < OutputWidth; i++) begin + key_o[i] = trivium_generate_key_stream(state_update); + state_update = trivium_update_state(state_update); + end + end + end + + /////////////// + // Reseeding // + /////////////// + + if (SeedType == SeedTypeKeyIv) begin : gen_seed_type_key_iv + if (BiviumVariant) begin : gen_seed_type_key_iv_bivium + assign state_seed = bivium_seed_key_iv(seed_key_i, seed_iv_i); + end else begin : gen_seed_type_key_iv_trivium + assign state_seed = trivium_seed_key_iv(seed_key_i, seed_iv_i); + end + + end else if (SeedType == SeedTypeStateFull) begin : gen_seed_type_state_full + assign state_seed = seed_state_full_i; + + end else begin : gen_seed_type_state_partial + // If the primitive is idle and an update is not currently being requested (update = 1'b0), the + // parts not currently being reseeded remain constant, i.e., the update function above doesn't + // modify the state. This is required to put the primitive into a known state e.g. for known + // answer testing. + // If the primitive is busy and an update is requested, the update function always modifies + // the state (but the part currently being reseeded is solely determined by the new seed). + // Otherwise the primitive could potentially produce the same key stream output twice in a row. + always_comb begin + state_seed = !update ? state_q : state_update; + // The last part may be shorter than PartialSeedWidth. + if (last_state_part) begin + state_seed[StateWidth - 1 -: NumBitsLastPart] = seed_state_partial_i[NumBitsLastPart-1:0]; + end else begin + state_seed[state_idx_q * PartialSeedWidth +: PartialSeedWidth] = seed_state_partial_i; + end + end + end + + ///////////////////////////////// + // State register and updating // + ///////////////////////////////// + + // The lockup protection can optionally be disabled at run time. This may be required to put the + // primitive into an all zero state, e.g., to switch off masking countermeasures for analysis if + // the primitive is used for generating masks. However, the err_o bit always signals this + // condition to the outside. + assign restore = lockup & (StrictLockupProtection | ~allow_lockup_i); + assign state_d = restore ? StateSeed : + wr_en_seed ? state_seed : + update ? state_update : state_q; + + always_ff @(posedge clk_i or negedge rst_ni) begin : state_reg + if (!rst_ni) begin + state_q <= StateSeed; + end else begin + state_q <= state_d; + end + end + + // Latch the seed enable signal and keep the request high until the last request is acknowledged. + assign seed_req_d = (seed_en_i | seed_req_q) & (~seed_ack_i | ~last_state_part); + always_ff @(posedge clk_i or negedge rst_ni) begin : seed_req_reg + if (!rst_ni) begin + seed_req_q <= 1'b0; + end else begin + seed_req_q <= seed_req_d; + end + end + assign seed_req_o = seed_en_i | seed_req_q; + + if (SeedType == SeedTypeKeyIv) begin : gen_key_iv_seed_handling + // After receiving key and IV, the entire state needs to be updated 4 times before the key + // stream becomes usable. Depending on OutputWidth, a different number of initial updates are + // required for this. [3] + localparam int unsigned NumInitUpdatesFractional = (StateWidth * 4) % OutputWidth != 0 ? 1 : 0; + localparam int unsigned NumInitUpdates = + (StateWidth * 4) / OutputWidth + NumInitUpdatesFractional; + localparam int unsigned LastInitUpdate = NumInitUpdates - 1; + localparam int unsigned InitUpdatesCtrWidth = caliptra_prim_util_pkg::vbits(NumInitUpdates); + + logic [InitUpdatesCtrWidth-1:0] init_update_ctr_d, init_update_ctr_q; + logic init_update_d, init_update_q; + logic last_init_update; + + // Count the number of initial updates done. + assign init_update_ctr_d = wr_en_seed ? '0 : + init_update_q ? init_update_ctr_q + 1'b1 : init_update_ctr_q; + always_ff @(posedge clk_i or negedge rst_ni) begin : init_update_ctr_reg + if (!rst_ni) begin + init_update_ctr_q <= '0; + end else begin + init_update_ctr_q <= init_update_ctr_d; + end + end + + // Track whether we're currently doing the initial updates. + assign last_init_update = init_update_ctr_q == LastInitUpdate[InitUpdatesCtrWidth-1:0]; + assign init_update_d = wr_en_seed ? 1'b1 : + last_init_update ? 1'b0 : init_update_q; + always_ff @(posedge clk_i or negedge rst_ni) begin : init_update_reg + if (!rst_ni) begin + init_update_q <= 1'b0; + end else begin + init_update_q <= init_update_d; + end + end + assign update_init = init_update_q; + + // We're done after performing the initial updates. + assign seed_done_o = init_update_q & last_init_update; + + // Tie off unused signals. + assign state_idx_d = '0; + assign state_idx_q = '0; + assign last_state_part = 1'b0; + assign unused_seed = ^{seed_state_full_i, + seed_state_partial_i, + state_idx_d, + state_idx_q, + last_state_part}; + + end else if (SeedType == SeedTypeStateFull) begin : gen_full_seed_handling + + // Only one handshake is required. + assign seed_done_o = seed_req_o & seed_ack_i; + + // Tie off unused signals. + assign update_init = 1'b0; + assign state_idx_d = '0; + assign state_idx_q = '0; + assign last_state_part = 1'b1; + assign unused_seed = ^{seed_key_i, + seed_iv_i, + seed_state_partial_i, + state_idx_d, + state_idx_q, + last_state_part}; + + end else begin : gen_partial_seed_handling + + // Seed PartialSeedWidth bits of the state at a time. Track the part idx using a counter. The + // counter is reset when seeding the last part. + assign last_state_part = state_idx_q == LastStatePart[StateIdxWidth-1:0]; + assign state_idx_d = wr_en_seed & last_state_part ? '0 : + wr_en_seed & ~last_state_part ? state_idx_q + 1'b1 : state_idx_q; + always_ff @(posedge clk_i or negedge rst_ni) begin : state_idx_reg + if (!rst_ni) begin + state_idx_q <= '0; + end else begin + state_idx_q <= state_idx_d; + end + end + + // We're done upon receiving the last state part. + assign seed_done_o = seed_req_o & seed_ack_i & last_state_part; + + // Tie off unused signals. + assign update_init = 1'b0; + assign unused_seed = ^{seed_key_i, + seed_iv_i, + seed_state_full_i}; + end + + ///////////////// + // Asssertions // + ///////////////// + + // While performing a partial reseed of the state, the primitive can be updated. However, this + // should only be done if the number of produced bits per update / shift amount per update is + // greater than the width of the smallest NFSR (= 84) inside the primitve. Otherwise, there is a + // risk of overwriting the previously provided partial seed which reduces the amount of fresh + // entropy injected per full reseed operation. + `CALIPTRA_ASSERT(PrimTriviumPartialStateSeedWhileUpdate_A, + (SeedType == SeedTypeStatePartial) && seed_req_o && en_i |-> OutputWidth >= MinNfsrWidth) + +endmodule diff --git a/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv b/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv new file mode 100644 index 000000000..9ee8170ca --- /dev/null +++ b/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv @@ -0,0 +1,159 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +package caliptra_prim_trivium_pkg; + + typedef enum logic [31:0] { + SeedTypeKeyIv, // 2 * 80 bits for key and IV, requires advancing the primitive + // 1152/OutputWidth (Trivium) or 708/OutputWidth (Bivium) times + // before the key stream becomes usable. + SeedTypeStateFull, // Seed the full state + SeedTypeStatePartial // Seed PartialSeedWidth bits of the state at a time. + } seed_type_e; + + parameter int unsigned KeyIvWidth = 80; + parameter int unsigned PartialSeedWidthDefault = 32; + parameter int unsigned MinNfsrWidth = 84; + + // These LFSR parameters have been generated with + // $ ./util/design/gen-lfsr-seed.py --width 288 --seed 31468618 --prefix "Trivium" + parameter int TriviumLfsrWidth = 288; + typedef logic [TriviumLfsrWidth-1:0] trivium_lfsr_seed_t; + parameter trivium_lfsr_seed_t RndCnstTriviumLfsrSeedDefault = { + 32'h758a4420, + 256'h31e1c461_6ea343ec_153282a3_0c132b57_23c5a4cf_4743b3c7_c32d580f_74f1713a + }; + + ///////////// + // Trivium // + ///////////// + + parameter int unsigned TriviumMaxNfsrWidth = 111; + parameter int TriviumStateWidth = TriviumLfsrWidth; + + function automatic logic [TriviumStateWidth-1:0] trivium_update_state( + logic [TriviumStateWidth-1:0] in + ); + logic [TriviumStateWidth-1:0] out; + logic mul_90_91, mul_174_175, mul_285_286; + logic add_65_92, add_161_176, add_242_287; + + // First state part intermediate results + mul_90_91 = in[90] & in[91]; + add_65_92 = in[65] ^ in[92]; + + // Second state part intermediate results + mul_174_175 = in[174] & in[175]; + add_161_176 = in[161] ^ in[176]; + + // Third state part intermediate results + mul_285_286 = in[285] & in[286]; + add_242_287 = in[242] ^ in[287]; + + // Updates - feedback part + out[0] = in[68] ^ (mul_285_286 ^ add_242_287); + out[93] = in[170] ^ (add_65_92 ^ mul_90_91); + out[177] = in[263] ^ (mul_174_175 ^ add_161_176); + + // Updates - shift part + out[92:1] = in[91:0]; + out[176:94] = in[175:93]; + out[287:178] = in[286:177]; + + return out; + endfunction + + function automatic logic trivium_generate_key_stream( + logic [TriviumStateWidth-1:0] state + ); + logic key; + logic add_65_92, add_161_176, add_242_287; + logic unused_state; + + add_65_92 = state[65] ^ state[92]; + add_161_176 = state[161] ^ state[176]; + add_242_287 = state[242] ^ state[287]; + key = add_161_176 ^ add_65_92 ^ add_242_287; + + unused_state = ^{state[286:243], + state[241:177], + state[175:162], + state[160:93], + state[91:66], + state[64:0]}; + return key; + endfunction + + function automatic logic [TriviumStateWidth-1:0] trivium_seed_key_iv( + logic [KeyIvWidth-1:0] key, + logic [KeyIvWidth-1:0] iv + ); + logic [TriviumStateWidth-1:0] state; + // [287:285] [284:173] [172:93] [92:80] [79:0] + state = {3'b111, 112'b0, iv, 13'b0, key}; + return state; + endfunction + + //////////// + // Bivium // + //////////// + + parameter int unsigned BiviumMaxNfsrWidth = 93; + parameter int BiviumStateWidth = 177; + + function automatic logic [BiviumStateWidth-1:0] bivium_update_state( + logic [BiviumStateWidth-1:0] in + ); + logic [BiviumStateWidth-1:0] out; + logic mul_90_91, mul_174_175; + logic add_65_92, add_161_176; + + // First state half intermediate results + mul_90_91 = in[90] & in[91]; + add_65_92 = in[65] ^ in[92]; + + // Second state half intermediate results + mul_174_175 = in[174] & in[175]; + add_161_176 = in[161] ^ in[176]; + + // Updates - feedback part + out[0] = in[68] ^ (mul_174_175 ^ add_161_176); + out[93] = in[170] ^ add_65_92 ^ mul_90_91; + + // Updates - shift part + out[92:1] = in[91:0]; + out[176:94] = in[175:93]; + + return out; + endfunction + + function automatic logic bivium_generate_key_stream( + logic [BiviumStateWidth-1:0] state + ); + logic key; + logic add_65_92, add_161_176; + logic unused_state; + + add_65_92 = state[65] ^ state[92]; + add_161_176 = state[161] ^ state[176]; + key = add_161_176 ^ add_65_92; + + unused_state = ^{state[175:162], + state[160:93], + state[91:66], + state[64:0]}; + return key; + endfunction + + function automatic logic [BiviumStateWidth-1:0] bivium_seed_key_iv( + logic [KeyIvWidth-1:0] key, + logic [KeyIvWidth-1:0] iv + ); + logic [BiviumStateWidth-1:0] state; + // [176:173] [172:93] [92:80] [79:0] + state = {4'b0, iv, 13'b0, key}; + return state; + endfunction + +endpackage diff --git a/src/caliptra_prim/rtl/keymgr_pkg.sv b/src/caliptra_prim/rtl/keymgr_pkg.sv new file mode 100644 index 000000000..560a023df --- /dev/null +++ b/src/caliptra_prim/rtl/keymgr_pkg.sv @@ -0,0 +1,19 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 +// +// key manager package +// + +package keymgr_pkg; + + parameter int KeyWidth = 256; + parameter int Shares = 2; // number of key shares + + // Key connection to various symmetric modules + typedef struct packed { + logic valid; + logic [Shares-1:0][KeyWidth-1:0] key; + } hw_key_req_t; + +endpackage : keymgr_pkg diff --git a/src/csrng/config/csrng.vf b/src/csrng/config/csrng.vf index 8a9a7a9be..96bd2c10a 100644 --- a/src/csrng/config/csrng.vf +++ b/src/csrng/config/csrng.vf @@ -1,12 +1,13 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/csrng/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/integration/rtl/config_defines.svh ${CALIPTRA_ROOT}/src/integration/rtl/caliptra_reg_defines.svh ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_sva.svh @@ -20,16 +21,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_ack_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_reg_pkg.sv @@ -40,6 +31,19 @@ ${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cdc_rand_delay.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_flop_2sync.sv @@ -71,10 +75,29 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -93,6 +116,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/csrng/config/csrng_tb.vf b/src/csrng/config/csrng_tb.vf index 641cb6454..be2cdc188 100644 --- a/src/csrng/config/csrng_tb.vf +++ b/src/csrng/config/csrng_tb.vf @@ -1,12 +1,13 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/csrng/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl +incdir+${CALIPTRA_ROOT}/src/csrng/tb ${CALIPTRA_ROOT}/src/integration/rtl/config_defines.svh ${CALIPTRA_ROOT}/src/integration/rtl/caliptra_reg_defines.svh @@ -21,16 +22,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_ack_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_reg_pkg.sv @@ -41,6 +32,19 @@ ${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cdc_rand_delay.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_flop_2sync.sv @@ -72,10 +76,29 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -94,6 +117,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/csrng/rtl/csrng_block_encrypt.sv b/src/csrng/rtl/csrng_block_encrypt.sv index 73c890149..caa73f88d 100644 --- a/src/csrng/rtl/csrng_block_encrypt.sv +++ b/src/csrng/rtl/csrng_block_encrypt.sv @@ -57,16 +57,12 @@ module csrng_block_encrypt import csrng_pkg::*; #( logic [BlkLen-1:0] cipher_data_out; logic aes_cipher_core_enable; - logic [aes_pkg::WidthPRDClearing-1:0] prd_clearing [NumShares]; - logic [3:0][3:0][7:0] state_init[NumShares]; logic [7:0][31:0] key_init[NumShares]; logic [3:0][3:0][7:0] state_done[NumShares]; logic [3:0][3:0][7:0] state_out; - assign prd_clearing[0] = '0; - assign state_init[0] = aes_pkg::aes_transpose({<<8{block_encrypt_v_i}}); assign key_init[0] = {<<8{block_encrypt_key_i}}; @@ -94,42 +90,48 @@ module csrng_block_encrypt import csrng_pkg::*; #( // SEC_CM: AES_CIPHER.DATA_REG.LOCAL_ESC aes_cipher_core #( - .AES192Enable ( 1'b0 ), // AES192Enable disabled - .SecMasking ( 1'b0 ), // Masking disable - .SecSBoxImpl ( SBoxImpl ) + .AES192Enable ( 1'b0 ), // AES192Enable disabled + .CiphOpFwdOnly ( 1'b1 ), // Forward operation only + .SecMasking ( 1'b0 ), // Masking disable + .SecSBoxImpl ( SBoxImpl ) ) u_aes_cipher_core ( .clk_i (clk_i), .rst_ni (rst_ni), - .cfg_valid_i ( 1'b1 ), - .in_valid_i ( cipher_in_valid ), - .in_ready_o ( cipher_in_ready ), - .out_valid_o ( cipher_out_valid ), - .out_ready_i ( cipher_out_ready ), - .op_i ( aes_pkg::CIPH_FWD ), - .key_len_i ( aes_pkg::AES_256 ), - .crypt_i ( aes_pkg::SP2V_HIGH ), // Enable - .crypt_o ( cipher_crypt_busy ), - .alert_fatal_i ( 1'b0 ), - .alert_o ( block_encrypt_aes_cipher_sm_err_o), - .dec_key_gen_i ( aes_pkg::SP2V_LOW ), // Disable - .dec_key_gen_o ( ), - .prng_reseed_i ( 1'b0 ), // Disable - .prng_reseed_o ( ), - .key_clear_i ( 1'b0 ), // Disable - .key_clear_o ( ), - .data_out_clear_i ( 1'b0 ), // Disable - .data_out_clear_o ( ), - .prd_clearing_i ( prd_clearing ), - .force_masks_i ( 1'b0 ), - .data_in_mask_o ( ), - .entropy_req_o ( ), - .entropy_ack_i ( 1'b0 ), - .entropy_i ( '0 ), - - .state_init_i ( state_init ), - .key_init_i ( key_init ), - .state_o ( state_done ) + .cfg_valid_i ( 1'b1 ), + .in_valid_i ( cipher_in_valid ), + .in_ready_o ( cipher_in_ready ), + .out_valid_o ( cipher_out_valid ), + .out_ready_i ( cipher_out_ready ), + .op_i ( aes_pkg::CIPH_FWD ), + .key_len_i ( aes_pkg::AES_256 ), + .crypt_i ( aes_pkg::SP2V_HIGH ), // Enable + .crypt_o ( cipher_crypt_busy ), + .alert_fatal_i ( 1'b0 ), + .alert_o ( block_encrypt_aes_cipher_sm_err_o), + .dec_key_gen_i ( aes_pkg::SP2V_LOW ), // Disable + .dec_key_gen_o ( ), + .prng_reseed_i ( 1'b0 ), // Disable + .prng_reseed_o ( ), + .key_clear_i ( 1'b0 ), // Disable + .key_clear_o ( ), + .data_out_clear_i ( 1'b0 ), // Disable + .data_out_clear_o ( ), + .prd_clearing_state_i ( state_init ), // Providing this value allows synthesis + // to perform optimizations. We don't + // care about SCA leakage in this context. + .prd_clearing_key_i ( key_init ), // This input is not used. Providing this + // value allows synthesis to perform + // optimizations. + .force_masks_i ( 1'b0 ), + .data_in_mask_o ( ), + .entropy_req_o ( ), + .entropy_ack_i ( 1'b0 ), + .entropy_i ( '0 ), + + .state_init_i ( state_init ), + .key_init_i ( key_init ), + .state_o ( state_done ) ); diff --git a/src/ecc/rtl/ecc_reg.sv b/src/ecc/rtl/ecc_reg.sv index ca160dd10..2e2a54a8b 100644 --- a/src/ecc/rtl/ecc_reg.sv +++ b/src/ecc/rtl/ecc_reg.sv @@ -354,7 +354,11 @@ module ecc_reg ( logic load_next; } ecc_seed_dest_valid; struct packed{ - logic [20:0] next; + logic next; + logic load_next; + } aes_key_dest_valid; + struct packed{ + logic [19:0] next; logic load_next; } rsvd; } ecc_kv_wr_pkey_ctrl; @@ -595,7 +599,10 @@ module ecc_reg ( logic value; } ecc_seed_dest_valid; struct packed{ - logic [20:0] value; + logic value; + } aes_key_dest_valid; + struct packed{ + logic [19:0] value; } rsvd; } ecc_kv_wr_pkey_ctrl; struct packed{ @@ -1473,14 +1480,35 @@ module ecc_reg ( end end assign hwif_out.ecc_kv_wr_pkey_ctrl.ecc_seed_dest_valid.value = field_storage.ecc_kv_wr_pkey_ctrl.ecc_seed_dest_valid.value; + // Field: ecc_reg.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value; + load_next_c = '0; + if(decoded_reg_strb.ecc_kv_wr_pkey_ctrl && decoded_req_is_wr) begin // SW write + next_c = (field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value & ~decoded_wr_biten[11:11]) | (decoded_wr_data[11:11] & decoded_wr_biten[11:11]); + load_next_c = '1; + end + field_combo.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.next = next_c; + field_combo.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value <= 1'h0; + end else if(field_combo.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.load_next) begin + field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value <= field_combo.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.next; + end + end + assign hwif_out.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value = field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value; // Field: ecc_reg.ecc_kv_wr_pkey_ctrl.rsvd always_comb begin - automatic logic [20:0] next_c; + automatic logic [19:0] next_c; automatic logic load_next_c; next_c = field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value; load_next_c = '0; if(decoded_reg_strb.ecc_kv_wr_pkey_ctrl && decoded_req_is_wr) begin // SW write - next_c = (field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value & ~decoded_wr_biten[31:11]) | (decoded_wr_data[31:11] & decoded_wr_biten[31:11]); + next_c = (field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value & ~decoded_wr_biten[31:12]) | (decoded_wr_data[31:12] & decoded_wr_biten[31:12]); load_next_c = '1; end field_combo.ecc_kv_wr_pkey_ctrl.rsvd.next = next_c; @@ -1488,7 +1516,7 @@ module ecc_reg ( end always_ff @(posedge clk or negedge hwif_in.reset_b) begin if(~hwif_in.reset_b) begin - field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value <= 21'h0; + field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value <= 20'h0; end else if(field_combo.ecc_kv_wr_pkey_ctrl.rsvd.load_next) begin field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value <= field_combo.ecc_kv_wr_pkey_ctrl.rsvd.next; end @@ -1944,7 +1972,8 @@ module ecc_reg ( assign readback_array[93][8:8] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.mldsa_seed_dest_valid.value : '0; assign readback_array[93][9:9] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.ecc_pkey_dest_valid.value : '0; assign readback_array[93][10:10] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.ecc_seed_dest_valid.value : '0; - assign readback_array[93][31:11] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value : '0; + assign readback_array[93][11:11] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.aes_key_dest_valid.value : '0; + assign readback_array[93][31:12] = (decoded_reg_strb.ecc_kv_wr_pkey_ctrl && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_ctrl.rsvd.value : '0; assign readback_array[94][0:0] = (decoded_reg_strb.ecc_kv_wr_pkey_status && !decoded_req_is_wr) ? hwif_in.ecc_kv_wr_pkey_status.READY.next : '0; assign readback_array[94][1:1] = (decoded_reg_strb.ecc_kv_wr_pkey_status && !decoded_req_is_wr) ? field_storage.ecc_kv_wr_pkey_status.VALID.value : '0; assign readback_array[94][9:2] = (decoded_reg_strb.ecc_kv_wr_pkey_status && !decoded_req_is_wr) ? hwif_in.ecc_kv_wr_pkey_status.ERROR.next : '0; diff --git a/src/ecc/rtl/ecc_reg_pkg.sv b/src/ecc/rtl/ecc_reg_pkg.sv index daab24775..aed140e1b 100644 --- a/src/ecc/rtl/ecc_reg_pkg.sv +++ b/src/ecc/rtl/ecc_reg_pkg.sv @@ -411,7 +411,11 @@ package ecc_reg_pkg; } kv_write_ctrl_reg__ecc_seed_dest_valid__out_t; typedef struct packed{ - logic [20:0] value; + logic value; + } kv_write_ctrl_reg__aes_key_dest_valid__out_t; + + typedef struct packed{ + logic [19:0] value; } kv_write_ctrl_reg__rsvd__out_t; typedef struct packed{ @@ -422,6 +426,7 @@ package ecc_reg_pkg; kv_write_ctrl_reg__mldsa_seed_dest_valid__out_t mldsa_seed_dest_valid; kv_write_ctrl_reg__ecc_pkey_dest_valid__out_t ecc_pkey_dest_valid; kv_write_ctrl_reg__ecc_seed_dest_valid__out_t ecc_seed_dest_valid; + kv_write_ctrl_reg__aes_key_dest_valid__out_t aes_key_dest_valid; kv_write_ctrl_reg__rsvd__out_t rsvd; } kv_write_ctrl_reg__out_t; diff --git a/src/ecc/rtl/ecc_reg_uvm.sv b/src/ecc/rtl/ecc_reg_uvm.sv index 91005d1f0..e14d4070a 100644 --- a/src/ecc/rtl/ecc_reg_uvm.sv +++ b/src/ecc/rtl/ecc_reg_uvm.sv @@ -602,7 +602,8 @@ package ecc_reg_uvm; kv_write_ctrl_reg_bit_cg mldsa_seed_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_pkey_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_seed_dest_valid_bit_cg[1]; - kv_write_ctrl_reg_bit_cg rsvd_bit_cg[21]; + kv_write_ctrl_reg_bit_cg aes_key_dest_valid_bit_cg[1]; + kv_write_ctrl_reg_bit_cg rsvd_bit_cg[20]; kv_write_ctrl_reg_fld_cg fld_cg; rand uvm_reg_field write_en; rand uvm_reg_field write_entry; @@ -611,6 +612,7 @@ package ecc_reg_uvm; rand uvm_reg_field mldsa_seed_dest_valid; rand uvm_reg_field ecc_pkey_dest_valid; rand uvm_reg_field ecc_seed_dest_valid; + rand uvm_reg_field aes_key_dest_valid; rand uvm_reg_field rsvd; function new(string name = "kv_write_ctrl_reg"); @@ -637,8 +639,10 @@ package ecc_reg_uvm; this.ecc_pkey_dest_valid.configure(this, 1, 9, "RW", 0, 'h0, 1, 1, 0); this.ecc_seed_dest_valid = new("ecc_seed_dest_valid"); this.ecc_seed_dest_valid.configure(this, 1, 10, "RW", 0, 'h0, 1, 1, 0); + this.aes_key_dest_valid = new("aes_key_dest_valid"); + this.aes_key_dest_valid.configure(this, 1, 11, "RW", 0, 'h0, 1, 1, 0); this.rsvd = new("rsvd"); - this.rsvd.configure(this, 21, 11, "RW", 0, 'h0, 1, 1, 0); + this.rsvd.configure(this, 20, 12, "RW", 0, 'h0, 1, 1, 0); if (has_coverage(UVM_CVR_REG_BITS)) begin foreach(write_en_bit_cg[bt]) write_en_bit_cg[bt] = new(); foreach(write_entry_bit_cg[bt]) write_entry_bit_cg[bt] = new(); @@ -647,6 +651,7 @@ package ecc_reg_uvm; foreach(mldsa_seed_dest_valid_bit_cg[bt]) mldsa_seed_dest_valid_bit_cg[bt] = new(); foreach(ecc_pkey_dest_valid_bit_cg[bt]) ecc_pkey_dest_valid_bit_cg[bt] = new(); foreach(ecc_seed_dest_valid_bit_cg[bt]) ecc_seed_dest_valid_bit_cg[bt] = new(); + foreach(aes_key_dest_valid_bit_cg[bt]) aes_key_dest_valid_bit_cg[bt] = new(); foreach(rsvd_bit_cg[bt]) rsvd_bit_cg[bt] = new(); end if (has_coverage(UVM_CVR_FIELD_VALS)) diff --git a/src/entropy_src/config/entropy_src.vf b/src/entropy_src/config/entropy_src.vf index 497d5bd48..ab88cfcab 100644 --- a/src/entropy_src/config/entropy_src.vf +++ b/src/entropy_src/config/entropy_src.vf @@ -1,10 +1,10 @@ +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb +incdir+${CALIPTRA_ROOT}/src/kmac/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_ack_sm_pkg.sv @@ -23,6 +23,9 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/entropy_src/tb/physical_rng.sv +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv +${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -30,12 +33,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/entropy_src/tb/physical_rng.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv -${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_round.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_2share.sv ${CALIPTRA_ROOT}/src/kmac/rtl/sha3pad.sv @@ -74,6 +77,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_reg_top.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_bucket_ht.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_cntr_reg.sv diff --git a/src/entropy_src/config/entropy_src_tb.vf b/src/entropy_src/config/entropy_src_tb.vf index 789a04464..a966d1bed 100644 --- a/src/entropy_src/config/entropy_src_tb.vf +++ b/src/entropy_src/config/entropy_src_tb.vf @@ -1,10 +1,10 @@ +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb +incdir+${CALIPTRA_ROOT}/src/kmac/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_ack_sm_pkg.sv @@ -23,6 +23,9 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_icg.sv ${CALIPTRA_ROOT}/src/libs/rtl/clk_gate.sv ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v +${CALIPTRA_ROOT}/src/entropy_src/tb/physical_rng.sv +${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv +${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -30,12 +33,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/entropy_src/tb/physical_rng.sv -${CALIPTRA_ROOT}/src/libs/rtl/ahb_to_reg_adapter.sv -${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_round.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_2share.sv ${CALIPTRA_ROOT}/src/kmac/rtl/sha3pad.sv @@ -74,6 +77,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_reg_top.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_bucket_ht.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_cntr_reg.sv diff --git a/src/hmac/rtl/hmac_reg.sv b/src/hmac/rtl/hmac_reg.sv index ce1815342..09eb0dd69 100644 --- a/src/hmac/rtl/hmac_reg.sv +++ b/src/hmac/rtl/hmac_reg.sv @@ -294,7 +294,11 @@ module hmac_reg ( logic load_next; } ecc_seed_dest_valid; struct packed{ - logic [20:0] next; + logic next; + logic load_next; + } aes_key_dest_valid; + struct packed{ + logic [19:0] next; logic load_next; } rsvd; } HMAC512_KV_WR_CTRL; @@ -585,7 +589,10 @@ module hmac_reg ( logic value; } ecc_seed_dest_valid; struct packed{ - logic [20:0] value; + logic value; + } aes_key_dest_valid; + struct packed{ + logic [19:0] value; } rsvd; } HMAC512_KV_WR_CTRL; struct packed{ @@ -1334,14 +1341,35 @@ module hmac_reg ( end end assign hwif_out.HMAC512_KV_WR_CTRL.ecc_seed_dest_valid.value = field_storage.HMAC512_KV_WR_CTRL.ecc_seed_dest_valid.value; + // Field: hmac_reg.HMAC512_KV_WR_CTRL.aes_key_dest_valid + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value; + load_next_c = '0; + if(decoded_reg_strb.HMAC512_KV_WR_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value & ~decoded_wr_biten[11:11]) | (decoded_wr_data[11:11] & decoded_wr_biten[11:11]); + load_next_c = '1; + end + field_combo.HMAC512_KV_WR_CTRL.aes_key_dest_valid.next = next_c; + field_combo.HMAC512_KV_WR_CTRL.aes_key_dest_valid.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value <= 1'h0; + end else if(field_combo.HMAC512_KV_WR_CTRL.aes_key_dest_valid.load_next) begin + field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value <= field_combo.HMAC512_KV_WR_CTRL.aes_key_dest_valid.next; + end + end + assign hwif_out.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value = field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value; // Field: hmac_reg.HMAC512_KV_WR_CTRL.rsvd always_comb begin - automatic logic [20:0] next_c; + automatic logic [19:0] next_c; automatic logic load_next_c; next_c = field_storage.HMAC512_KV_WR_CTRL.rsvd.value; load_next_c = '0; if(decoded_reg_strb.HMAC512_KV_WR_CTRL && decoded_req_is_wr) begin // SW write - next_c = (field_storage.HMAC512_KV_WR_CTRL.rsvd.value & ~decoded_wr_biten[31:11]) | (decoded_wr_data[31:11] & decoded_wr_biten[31:11]); + next_c = (field_storage.HMAC512_KV_WR_CTRL.rsvd.value & ~decoded_wr_biten[31:12]) | (decoded_wr_data[31:12] & decoded_wr_biten[31:12]); load_next_c = '1; end field_combo.HMAC512_KV_WR_CTRL.rsvd.next = next_c; @@ -1349,7 +1377,7 @@ module hmac_reg ( end always_ff @(posedge clk or negedge hwif_in.reset_b) begin if(~hwif_in.reset_b) begin - field_storage.HMAC512_KV_WR_CTRL.rsvd.value <= 21'h0; + field_storage.HMAC512_KV_WR_CTRL.rsvd.value <= 20'h0; end else if(field_combo.HMAC512_KV_WR_CTRL.rsvd.load_next) begin field_storage.HMAC512_KV_WR_CTRL.rsvd.value <= field_combo.HMAC512_KV_WR_CTRL.rsvd.next; end @@ -2192,7 +2220,8 @@ module hmac_reg ( assign readback_array[25][8:8] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.mldsa_seed_dest_valid.value : '0; assign readback_array[25][9:9] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.ecc_pkey_dest_valid.value : '0; assign readback_array[25][10:10] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.ecc_seed_dest_valid.value : '0; - assign readback_array[25][31:11] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.rsvd.value : '0; + assign readback_array[25][11:11] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.aes_key_dest_valid.value : '0; + assign readback_array[25][31:12] = (decoded_reg_strb.HMAC512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_CTRL.rsvd.value : '0; assign readback_array[26][0:0] = (decoded_reg_strb.HMAC512_KV_WR_STATUS && !decoded_req_is_wr) ? hwif_in.HMAC512_KV_WR_STATUS.READY.next : '0; assign readback_array[26][1:1] = (decoded_reg_strb.HMAC512_KV_WR_STATUS && !decoded_req_is_wr) ? field_storage.HMAC512_KV_WR_STATUS.VALID.value : '0; assign readback_array[26][9:2] = (decoded_reg_strb.HMAC512_KV_WR_STATUS && !decoded_req_is_wr) ? hwif_in.HMAC512_KV_WR_STATUS.ERROR.next : '0; diff --git a/src/hmac/rtl/hmac_reg_pkg.sv b/src/hmac/rtl/hmac_reg_pkg.sv index 9d541620f..67ba3ced8 100644 --- a/src/hmac/rtl/hmac_reg_pkg.sv +++ b/src/hmac/rtl/hmac_reg_pkg.sv @@ -288,7 +288,11 @@ package hmac_reg_pkg; } kv_write_ctrl_reg__ecc_seed_dest_valid__out_t; typedef struct packed{ - logic [20:0] value; + logic value; + } kv_write_ctrl_reg__aes_key_dest_valid__out_t; + + typedef struct packed{ + logic [19:0] value; } kv_write_ctrl_reg__rsvd__out_t; typedef struct packed{ @@ -299,6 +303,7 @@ package hmac_reg_pkg; kv_write_ctrl_reg__mldsa_seed_dest_valid__out_t mldsa_seed_dest_valid; kv_write_ctrl_reg__ecc_pkey_dest_valid__out_t ecc_pkey_dest_valid; kv_write_ctrl_reg__ecc_seed_dest_valid__out_t ecc_seed_dest_valid; + kv_write_ctrl_reg__aes_key_dest_valid__out_t aes_key_dest_valid; kv_write_ctrl_reg__rsvd__out_t rsvd; } kv_write_ctrl_reg__out_t; diff --git a/src/hmac/rtl/hmac_reg_uvm.sv b/src/hmac/rtl/hmac_reg_uvm.sv index 2ab8d42dc..49a029811 100644 --- a/src/hmac/rtl/hmac_reg_uvm.sv +++ b/src/hmac/rtl/hmac_reg_uvm.sv @@ -372,7 +372,8 @@ package hmac_reg_uvm; kv_write_ctrl_reg_bit_cg mldsa_seed_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_pkey_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_seed_dest_valid_bit_cg[1]; - kv_write_ctrl_reg_bit_cg rsvd_bit_cg[21]; + kv_write_ctrl_reg_bit_cg aes_key_dest_valid_bit_cg[1]; + kv_write_ctrl_reg_bit_cg rsvd_bit_cg[20]; kv_write_ctrl_reg_fld_cg fld_cg; rand uvm_reg_field write_en; rand uvm_reg_field write_entry; @@ -381,6 +382,7 @@ package hmac_reg_uvm; rand uvm_reg_field mldsa_seed_dest_valid; rand uvm_reg_field ecc_pkey_dest_valid; rand uvm_reg_field ecc_seed_dest_valid; + rand uvm_reg_field aes_key_dest_valid; rand uvm_reg_field rsvd; function new(string name = "kv_write_ctrl_reg"); @@ -407,8 +409,10 @@ package hmac_reg_uvm; this.ecc_pkey_dest_valid.configure(this, 1, 9, "RW", 0, 'h0, 1, 1, 0); this.ecc_seed_dest_valid = new("ecc_seed_dest_valid"); this.ecc_seed_dest_valid.configure(this, 1, 10, "RW", 0, 'h0, 1, 1, 0); + this.aes_key_dest_valid = new("aes_key_dest_valid"); + this.aes_key_dest_valid.configure(this, 1, 11, "RW", 0, 'h0, 1, 1, 0); this.rsvd = new("rsvd"); - this.rsvd.configure(this, 21, 11, "RW", 0, 'h0, 1, 1, 0); + this.rsvd.configure(this, 20, 12, "RW", 0, 'h0, 1, 1, 0); if (has_coverage(UVM_CVR_REG_BITS)) begin foreach(write_en_bit_cg[bt]) write_en_bit_cg[bt] = new(); foreach(write_entry_bit_cg[bt]) write_entry_bit_cg[bt] = new(); @@ -417,6 +421,7 @@ package hmac_reg_uvm; foreach(mldsa_seed_dest_valid_bit_cg[bt]) mldsa_seed_dest_valid_bit_cg[bt] = new(); foreach(ecc_pkey_dest_valid_bit_cg[bt]) ecc_pkey_dest_valid_bit_cg[bt] = new(); foreach(ecc_seed_dest_valid_bit_cg[bt]) ecc_seed_dest_valid_bit_cg[bt] = new(); + foreach(aes_key_dest_valid_bit_cg[bt]) aes_key_dest_valid_bit_cg[bt] = new(); foreach(rsvd_bit_cg[bt]) rsvd_bit_cg[bt] = new(); end if (has_coverage(UVM_CVR_FIELD_VALS)) diff --git a/src/integration/config/caliptra_top.vf b/src/integration/config/caliptra_top.vf index 05d0cf9c7..8976fdc4b 100644 --- a/src/integration/config/caliptra_top.vf +++ b/src/integration/config/caliptra_top.vf @@ -13,8 +13,6 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb @@ -41,10 +39,13 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/sig_decode_z/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/pk_decode/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/power2round/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/integration/rtl/config_defines.svh ${CALIPTRA_ROOT}/src/integration/rtl/caliptra_reg_defines.svh ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_sva.svh @@ -111,16 +112,6 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl/ntt_defines_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl/norm_check_defines_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv @@ -370,6 +361,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -404,6 +408,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -444,6 +457,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -462,6 +485,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/config/caliptra_top_tb.vf b/src/integration/config/caliptra_top_tb.vf index 017b7373a..e7e62af9f 100644 --- a/src/integration/config/caliptra_top_tb.vf +++ b/src/integration/config/caliptra_top_tb.vf @@ -14,8 +14,6 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb @@ -51,10 +49,13 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/sig_decode_z/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/pk_decode/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/power2round/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_defines_pkg.sv ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_macros.svh ${CALIPTRA_ROOT}/src/doe/rtl/doe_defines_pkg.sv @@ -122,16 +123,6 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_sparse_fsm_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl/ntt_defines_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl/norm_check_defines_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv @@ -407,6 +398,19 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/mldsa_top/rtl/mldsa_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg_pkg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -441,6 +445,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -481,6 +494,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -499,6 +522,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/config/caliptra_top_tb_pkg.vf b/src/integration/config/caliptra_top_tb_pkg.vf index ffbfae1d3..90826dbb2 100644 --- a/src/integration/config/caliptra_top_tb_pkg.vf +++ b/src/integration/config/caliptra_top_tb_pkg.vf @@ -14,8 +14,6 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb @@ -51,10 +49,13 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/sig_decode_z/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/pk_decode/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/power2round/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_defines_pkg.sv ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_macros.svh ${CALIPTRA_ROOT}/src/doe/rtl/doe_defines_pkg.sv @@ -122,16 +123,6 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_sparse_fsm_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl/ntt_defines_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl/norm_check_defines_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv @@ -406,6 +397,19 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/mldsa_top/rtl/mldsa_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg_pkg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -440,6 +444,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -480,6 +493,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -498,6 +521,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/config/caliptra_top_trng_tb.vf b/src/integration/config/caliptra_top_trng_tb.vf index 017b7373a..e7e62af9f 100644 --- a/src/integration/config/caliptra_top_trng_tb.vf +++ b/src/integration/config/caliptra_top_trng_tb.vf @@ -14,8 +14,6 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/rtl +incdir+${CALIPTRA_ROOT}/src/entropy_src/tb @@ -51,10 +49,13 @@ +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/sig_decode_z/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/pk_decode/rtl +incdir+${CALIPTRA_ROOT}/submodules/adams-bridge/src/power2round/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_defines_pkg.sv ${CALIPTRA_ROOT}/src/keyvault/rtl/kv_macros.svh ${CALIPTRA_ROOT}/src/doe/rtl/doe_defines_pkg.sv @@ -122,16 +123,6 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/abr_prim/rtl/abr_prim_sparse_fsm_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/ntt_top/rtl/ntt_defines_pkg.sv ${CALIPTRA_ROOT}/submodules/adams-bridge/src/norm_check/rtl/norm_check_defines_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/entropy_src/rtl/entropy_src_main_sm_pkg.sv @@ -407,6 +398,19 @@ ${CALIPTRA_ROOT}/submodules/adams-bridge/src/mldsa_top/rtl/mldsa_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg_pkg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv_reg.sv ${CALIPTRA_ROOT}/src/datavault/rtl/dv.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -441,6 +445,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -481,6 +494,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -499,6 +522,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/config/compile.yml b/src/integration/config/compile.yml index 4d5a8bad4..95fdfc955 100644 --- a/src/integration/config/compile.yml +++ b/src/integration/config/compile.yml @@ -36,6 +36,7 @@ requires: - soc_ifc_top - entropy_src - csrng + - aes targets: rtl: directories: [$COMPILE_ROOT/rtl] diff --git a/src/integration/rtl/caliptra_reg.h b/src/integration/rtl/caliptra_reg.h index 08ea3a46b..cb3fbb122 100644 --- a/src/integration/rtl/caliptra_reg.h +++ b/src/integration/rtl/caliptra_reg.h @@ -496,8 +496,10 @@ #define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_PKEY_DEST_VALID_MASK (0x200) #define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_SEED_DEST_VALID_LOW (10) #define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_SEED_DEST_VALID_MASK (0x400) -#define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_LOW (11) -#define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_MASK (0xfffff800) +#define ECC_REG_ECC_KV_WR_PKEY_CTRL_AES_KEY_DEST_VALID_LOW (11) +#define ECC_REG_ECC_KV_WR_PKEY_CTRL_AES_KEY_DEST_VALID_MASK (0x800) +#define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_LOW (12) +#define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_MASK (0xfffff000) #define CLP_ECC_REG_ECC_KV_WR_PKEY_STATUS (0x10008614) #define ECC_REG_ECC_KV_WR_PKEY_STATUS (0x614) #define ECC_REG_ECC_KV_WR_PKEY_STATUS_READY_LOW (0) @@ -790,8 +792,10 @@ #define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_PKEY_DEST_VALID_MASK (0x200) #define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_SEED_DEST_VALID_LOW (10) #define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_SEED_DEST_VALID_MASK (0x400) -#define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_LOW (11) -#define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_MASK (0xfffff800) +#define HMAC_REG_HMAC512_KV_WR_CTRL_AES_KEY_DEST_VALID_LOW (11) +#define HMAC_REG_HMAC512_KV_WR_CTRL_AES_KEY_DEST_VALID_MASK (0x800) +#define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_LOW (12) +#define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_MASK (0xfffff000) #define CLP_HMAC_REG_HMAC512_KV_WR_STATUS (0x10010614) #define HMAC_REG_HMAC512_KV_WR_STATUS (0x614) #define HMAC_REG_HMAC512_KV_WR_STATUS_READY_LOW (0) @@ -887,6 +891,233 @@ #define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (0xa10) #define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_LOW (0) #define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_MASK (0x1) +#define CLP_AES_REG_BASE_ADDR (0x10011000) +#define CLP_AES_REG_KEY_SHARE0_0 (0x10011004) +#define AES_REG_KEY_SHARE0_0 (0x4) +#define CLP_AES_REG_KEY_SHARE0_1 (0x10011008) +#define AES_REG_KEY_SHARE0_1 (0x8) +#define CLP_AES_REG_KEY_SHARE0_2 (0x1001100c) +#define AES_REG_KEY_SHARE0_2 (0xc) +#define CLP_AES_REG_KEY_SHARE0_3 (0x10011010) +#define AES_REG_KEY_SHARE0_3 (0x10) +#define CLP_AES_REG_KEY_SHARE0_4 (0x10011014) +#define AES_REG_KEY_SHARE0_4 (0x14) +#define CLP_AES_REG_KEY_SHARE0_5 (0x10011018) +#define AES_REG_KEY_SHARE0_5 (0x18) +#define CLP_AES_REG_KEY_SHARE0_6 (0x1001101c) +#define AES_REG_KEY_SHARE0_6 (0x1c) +#define CLP_AES_REG_KEY_SHARE0_7 (0x10011020) +#define AES_REG_KEY_SHARE0_7 (0x20) +#define CLP_AES_REG_KEY_SHARE1_0 (0x10011024) +#define AES_REG_KEY_SHARE1_0 (0x24) +#define CLP_AES_REG_KEY_SHARE1_1 (0x10011028) +#define AES_REG_KEY_SHARE1_1 (0x28) +#define CLP_AES_REG_KEY_SHARE1_2 (0x1001102c) +#define AES_REG_KEY_SHARE1_2 (0x2c) +#define CLP_AES_REG_KEY_SHARE1_3 (0x10011030) +#define AES_REG_KEY_SHARE1_3 (0x30) +#define CLP_AES_REG_KEY_SHARE1_4 (0x10011034) +#define AES_REG_KEY_SHARE1_4 (0x34) +#define CLP_AES_REG_KEY_SHARE1_5 (0x10011038) +#define AES_REG_KEY_SHARE1_5 (0x38) +#define CLP_AES_REG_KEY_SHARE1_6 (0x1001103c) +#define AES_REG_KEY_SHARE1_6 (0x3c) +#define CLP_AES_REG_KEY_SHARE1_7 (0x10011040) +#define AES_REG_KEY_SHARE1_7 (0x40) +#define CLP_AES_REG_IV_0 (0x10011044) +#define AES_REG_IV_0 (0x44) +#define CLP_AES_REG_IV_1 (0x10011048) +#define AES_REG_IV_1 (0x48) +#define CLP_AES_REG_IV_2 (0x1001104c) +#define AES_REG_IV_2 (0x4c) +#define CLP_AES_REG_IV_3 (0x10011050) +#define AES_REG_IV_3 (0x50) +#define CLP_AES_REG_DATA_IN_0 (0x10011054) +#define AES_REG_DATA_IN_0 (0x54) +#define CLP_AES_REG_DATA_IN_1 (0x10011058) +#define AES_REG_DATA_IN_1 (0x58) +#define CLP_AES_REG_DATA_IN_2 (0x1001105c) +#define AES_REG_DATA_IN_2 (0x5c) +#define CLP_AES_REG_DATA_IN_3 (0x10011060) +#define AES_REG_DATA_IN_3 (0x60) +#define CLP_AES_REG_DATA_OUT_0 (0x10011064) +#define AES_REG_DATA_OUT_0 (0x64) +#define CLP_AES_REG_DATA_OUT_1 (0x10011068) +#define AES_REG_DATA_OUT_1 (0x68) +#define CLP_AES_REG_DATA_OUT_2 (0x1001106c) +#define AES_REG_DATA_OUT_2 (0x6c) +#define CLP_AES_REG_DATA_OUT_3 (0x10011070) +#define AES_REG_DATA_OUT_3 (0x70) +#define CLP_AES_REG_CTRL_SHADOWED (0x10011074) +#define AES_REG_CTRL_SHADOWED (0x74) +#define AES_REG_CTRL_SHADOWED_OPERATION_LOW (0) +#define AES_REG_CTRL_SHADOWED_OPERATION_MASK (0x3) +#define AES_REG_CTRL_SHADOWED_MODE_LOW (2) +#define AES_REG_CTRL_SHADOWED_MODE_MASK (0xfc) +#define AES_REG_CTRL_SHADOWED_KEY_LEN_LOW (8) +#define AES_REG_CTRL_SHADOWED_KEY_LEN_MASK (0x700) +#define AES_REG_CTRL_SHADOWED_SIDELOAD_LOW (11) +#define AES_REG_CTRL_SHADOWED_SIDELOAD_MASK (0x800) +#define AES_REG_CTRL_SHADOWED_PRNG_RESEED_RATE_LOW (12) +#define AES_REG_CTRL_SHADOWED_PRNG_RESEED_RATE_MASK (0x7000) +#define AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_LOW (15) +#define AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_MASK (0x8000) +#define CLP_AES_REG_CTRL_AUX_SHADOWED (0x10011078) +#define AES_REG_CTRL_AUX_SHADOWED (0x78) +#define AES_REG_CTRL_AUX_SHADOWED_KEY_TOUCH_FORCES_RESEED_LOW (0) +#define AES_REG_CTRL_AUX_SHADOWED_KEY_TOUCH_FORCES_RESEED_MASK (0x1) +#define AES_REG_CTRL_AUX_SHADOWED_FORCE_MASKS_LOW (1) +#define AES_REG_CTRL_AUX_SHADOWED_FORCE_MASKS_MASK (0x2) +#define CLP_AES_REG_CTRL_AUX_REGWEN (0x1001107c) +#define AES_REG_CTRL_AUX_REGWEN (0x7c) +#define AES_REG_CTRL_AUX_REGWEN_CTRL_AUX_REGWEN_LOW (0) +#define AES_REG_CTRL_AUX_REGWEN_CTRL_AUX_REGWEN_MASK (0x1) +#define CLP_AES_REG_TRIGGER (0x10011080) +#define AES_REG_TRIGGER (0x80) +#define AES_REG_TRIGGER_START_LOW (0) +#define AES_REG_TRIGGER_START_MASK (0x1) +#define AES_REG_TRIGGER_KEY_IV_DATA_IN_CLEAR_LOW (1) +#define AES_REG_TRIGGER_KEY_IV_DATA_IN_CLEAR_MASK (0x2) +#define AES_REG_TRIGGER_DATA_OUT_CLEAR_LOW (2) +#define AES_REG_TRIGGER_DATA_OUT_CLEAR_MASK (0x4) +#define AES_REG_TRIGGER_PRNG_RESEED_LOW (3) +#define AES_REG_TRIGGER_PRNG_RESEED_MASK (0x8) +#define CLP_AES_REG_STATUS (0x10011084) +#define AES_REG_STATUS (0x84) +#define AES_REG_STATUS_IDLE_LOW (0) +#define AES_REG_STATUS_IDLE_MASK (0x1) +#define AES_REG_STATUS_STALL_LOW (1) +#define AES_REG_STATUS_STALL_MASK (0x2) +#define AES_REG_STATUS_OUTPUT_LOST_LOW (2) +#define AES_REG_STATUS_OUTPUT_LOST_MASK (0x4) +#define AES_REG_STATUS_OUTPUT_VALID_LOW (3) +#define AES_REG_STATUS_OUTPUT_VALID_MASK (0x8) +#define AES_REG_STATUS_INPUT_READY_LOW (4) +#define AES_REG_STATUS_INPUT_READY_MASK (0x10) +#define AES_REG_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_LOW (5) +#define AES_REG_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_MASK (0x20) +#define AES_REG_STATUS_ALERT_FATAL_FAULT_LOW (6) +#define AES_REG_STATUS_ALERT_FATAL_FAULT_MASK (0x40) +#define CLP_AES_REG_CTRL_GCM_SHADOWED (0x10011088) +#define AES_REG_CTRL_GCM_SHADOWED (0x88) +#define AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW (0) +#define AES_REG_CTRL_GCM_SHADOWED_PHASE_MASK (0x3f) +#define AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW (6) +#define AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_MASK (0x7c0) +#define CLP_AES_CLP_REG_BASE_ADDR (0x10011100) +#define CLP_AES_CLP_REG_AES_NAME_0 (0x10011200) +#define AES_CLP_REG_AES_NAME_0 (0x100) +#define CLP_AES_CLP_REG_AES_NAME_1 (0x10011204) +#define AES_CLP_REG_AES_NAME_1 (0x104) +#define CLP_AES_CLP_REG_AES_VERSION_0 (0x10011208) +#define AES_CLP_REG_AES_VERSION_0 (0x108) +#define CLP_AES_CLP_REG_AES_VERSION_1 (0x1001120c) +#define AES_CLP_REG_AES_VERSION_1 (0x10c) +#define CLP_AES_CLP_REG_AES_KV_RD_KEY_CTRL (0x10011700) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL (0x600) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_EN_LOW (0) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_EN_MASK (0x1) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_LOW (1) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_MASK (0x3e) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_PCR_HASH_EXTEND_LOW (6) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_PCR_HASH_EXTEND_MASK (0x40) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_RSVD_LOW (7) +#define AES_CLP_REG_AES_KV_RD_KEY_CTRL_RSVD_MASK (0xffffff80) +#define CLP_AES_CLP_REG_AES_KV_RD_KEY_STATUS (0x10011704) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS (0x604) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_READY_LOW (0) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_READY_MASK (0x1) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_VALID_LOW (1) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_VALID_MASK (0x2) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_ERROR_LOW (2) +#define AES_CLP_REG_AES_KV_RD_KEY_STATUS_ERROR_MASK (0x3fc) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_START (0x10011900) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R (0x10011900) +#define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R (0x800) +#define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_MASK (0x1) +#define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_LOW (1) +#define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_MASK (0x2) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R (0x10011904) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R (0x804) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR0_EN_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR0_EN_MASK (0x1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR1_EN_LOW (1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR1_EN_MASK (0x2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR2_EN_LOW (2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR2_EN_MASK (0x4) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR3_EN_LOW (3) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR3_EN_MASK (0x8) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R (0x10011908) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R (0x808) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_CMD_DONE_EN_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_CMD_DONE_EN_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R (0x1001190c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R (0x80c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R_AGG_STS_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R_AGG_STS_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R (0x10011910) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R (0x810) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R_AGG_STS_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R_AGG_STS_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R (0x10011914) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R (0x814) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR0_STS_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR0_STS_MASK (0x1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR1_STS_LOW (1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR1_STS_MASK (0x2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR2_STS_LOW (2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR2_STS_MASK (0x4) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR3_STS_LOW (3) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR3_STS_MASK (0x8) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R (0x10011918) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R (0x818) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R (0x1001191c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R (0x81c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR0_TRIG_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR0_TRIG_MASK (0x1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR1_TRIG_LOW (1) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR1_TRIG_MASK (0x2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR2_TRIG_LOW (2) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR2_TRIG_MASK (0x4) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR3_TRIG_LOW (3) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR3_TRIG_MASK (0x8) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R (0x10011920) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R (0x820) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R_NOTIF_CMD_DONE_TRIG_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R_NOTIF_CMD_DONE_TRIG_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_R (0x10011a00) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_R (0x900) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_R (0x10011a04) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_R (0x904) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_R (0x10011a08) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_R (0x908) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_R (0x10011a0c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_R (0x90c) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_R (0x10011a80) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_R (0x980) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R (0x10011b00) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R (0xa00) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R_PULSE_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R_PULSE_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R (0x10011b04) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R (0xa04) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R_PULSE_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R_PULSE_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R (0x10011b08) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R (0xa08) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R_PULSE_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R_PULSE_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R (0x10011b0c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R (0xa0c) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R_PULSE_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R_PULSE_MASK (0x1) +#define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (0x10011b10) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (0xa10) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_LOW (0) +#define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_MASK (0x1) #define CLP_KV_REG_BASE_ADDR (0x10018000) #define CLP_KV_REG_KEY_CTRL_0 (0x10018000) #define KV_REG_KEY_CTRL_0 (0x0) @@ -3979,8 +4210,10 @@ #define SHA512_REG_SHA512_KV_WR_CTRL_ECC_PKEY_DEST_VALID_MASK (0x200) #define SHA512_REG_SHA512_KV_WR_CTRL_ECC_SEED_DEST_VALID_LOW (10) #define SHA512_REG_SHA512_KV_WR_CTRL_ECC_SEED_DEST_VALID_MASK (0x400) -#define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_LOW (11) -#define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_MASK (0xfffff800) +#define SHA512_REG_SHA512_KV_WR_CTRL_AES_KEY_DEST_VALID_LOW (11) +#define SHA512_REG_SHA512_KV_WR_CTRL_AES_KEY_DEST_VALID_MASK (0x800) +#define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_LOW (12) +#define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_MASK (0xfffff000) #define CLP_SHA512_REG_SHA512_KV_WR_STATUS (0x1002060c) #define SHA512_REG_SHA512_KV_WR_STATUS (0x60c) #define SHA512_REG_SHA512_KV_WR_STATUS_READY_LOW (0) diff --git a/src/integration/rtl/caliptra_reg.rdl b/src/integration/rtl/caliptra_reg.rdl index a47deccff..9a3e00e29 100644 --- a/src/integration/rtl/caliptra_reg.rdl +++ b/src/integration/rtl/caliptra_reg.rdl @@ -22,6 +22,10 @@ addrmap clp { hmac_reg hmac_reg @ 0x1001_0000; + aes aes_reg @ 0x1001_1000; + + aes_clp_reg aes_clp_reg @ 0x1001_1100; + kv_reg kv_reg @ 0x1001_8000; pv_reg pv_reg @ 0x1001_A000; diff --git a/src/integration/rtl/caliptra_reg_defines.svh b/src/integration/rtl/caliptra_reg_defines.svh index b8fd3dae6..ce971d488 100644 --- a/src/integration/rtl/caliptra_reg_defines.svh +++ b/src/integration/rtl/caliptra_reg_defines.svh @@ -496,8 +496,10 @@ `define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_PKEY_DEST_VALID_MASK (32'h200) `define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_SEED_DEST_VALID_LOW (10) `define ECC_REG_ECC_KV_WR_PKEY_CTRL_ECC_SEED_DEST_VALID_MASK (32'h400) -`define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_LOW (11) -`define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_MASK (32'hfffff800) +`define ECC_REG_ECC_KV_WR_PKEY_CTRL_AES_KEY_DEST_VALID_LOW (11) +`define ECC_REG_ECC_KV_WR_PKEY_CTRL_AES_KEY_DEST_VALID_MASK (32'h800) +`define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_LOW (12) +`define ECC_REG_ECC_KV_WR_PKEY_CTRL_RSVD_MASK (32'hfffff000) `define CLP_ECC_REG_ECC_KV_WR_PKEY_STATUS (32'h10008614) `define ECC_REG_ECC_KV_WR_PKEY_STATUS (32'h614) `define ECC_REG_ECC_KV_WR_PKEY_STATUS_READY_LOW (0) @@ -790,8 +792,10 @@ `define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_PKEY_DEST_VALID_MASK (32'h200) `define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_SEED_DEST_VALID_LOW (10) `define HMAC_REG_HMAC512_KV_WR_CTRL_ECC_SEED_DEST_VALID_MASK (32'h400) -`define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_LOW (11) -`define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_MASK (32'hfffff800) +`define HMAC_REG_HMAC512_KV_WR_CTRL_AES_KEY_DEST_VALID_LOW (11) +`define HMAC_REG_HMAC512_KV_WR_CTRL_AES_KEY_DEST_VALID_MASK (32'h800) +`define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_LOW (12) +`define HMAC_REG_HMAC512_KV_WR_CTRL_RSVD_MASK (32'hfffff000) `define CLP_HMAC_REG_HMAC512_KV_WR_STATUS (32'h10010614) `define HMAC_REG_HMAC512_KV_WR_STATUS (32'h614) `define HMAC_REG_HMAC512_KV_WR_STATUS_READY_LOW (0) @@ -887,6 +891,233 @@ `define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (32'ha10) `define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_LOW (0) `define HMAC_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) +`define CLP_AES_REG_BASE_ADDR (32'h10011000) +`define CLP_AES_REG_KEY_SHARE0_0 (32'h10011004) +`define AES_REG_KEY_SHARE0_0 (32'h4) +`define CLP_AES_REG_KEY_SHARE0_1 (32'h10011008) +`define AES_REG_KEY_SHARE0_1 (32'h8) +`define CLP_AES_REG_KEY_SHARE0_2 (32'h1001100c) +`define AES_REG_KEY_SHARE0_2 (32'hc) +`define CLP_AES_REG_KEY_SHARE0_3 (32'h10011010) +`define AES_REG_KEY_SHARE0_3 (32'h10) +`define CLP_AES_REG_KEY_SHARE0_4 (32'h10011014) +`define AES_REG_KEY_SHARE0_4 (32'h14) +`define CLP_AES_REG_KEY_SHARE0_5 (32'h10011018) +`define AES_REG_KEY_SHARE0_5 (32'h18) +`define CLP_AES_REG_KEY_SHARE0_6 (32'h1001101c) +`define AES_REG_KEY_SHARE0_6 (32'h1c) +`define CLP_AES_REG_KEY_SHARE0_7 (32'h10011020) +`define AES_REG_KEY_SHARE0_7 (32'h20) +`define CLP_AES_REG_KEY_SHARE1_0 (32'h10011024) +`define AES_REG_KEY_SHARE1_0 (32'h24) +`define CLP_AES_REG_KEY_SHARE1_1 (32'h10011028) +`define AES_REG_KEY_SHARE1_1 (32'h28) +`define CLP_AES_REG_KEY_SHARE1_2 (32'h1001102c) +`define AES_REG_KEY_SHARE1_2 (32'h2c) +`define CLP_AES_REG_KEY_SHARE1_3 (32'h10011030) +`define AES_REG_KEY_SHARE1_3 (32'h30) +`define CLP_AES_REG_KEY_SHARE1_4 (32'h10011034) +`define AES_REG_KEY_SHARE1_4 (32'h34) +`define CLP_AES_REG_KEY_SHARE1_5 (32'h10011038) +`define AES_REG_KEY_SHARE1_5 (32'h38) +`define CLP_AES_REG_KEY_SHARE1_6 (32'h1001103c) +`define AES_REG_KEY_SHARE1_6 (32'h3c) +`define CLP_AES_REG_KEY_SHARE1_7 (32'h10011040) +`define AES_REG_KEY_SHARE1_7 (32'h40) +`define CLP_AES_REG_IV_0 (32'h10011044) +`define AES_REG_IV_0 (32'h44) +`define CLP_AES_REG_IV_1 (32'h10011048) +`define AES_REG_IV_1 (32'h48) +`define CLP_AES_REG_IV_2 (32'h1001104c) +`define AES_REG_IV_2 (32'h4c) +`define CLP_AES_REG_IV_3 (32'h10011050) +`define AES_REG_IV_3 (32'h50) +`define CLP_AES_REG_DATA_IN_0 (32'h10011054) +`define AES_REG_DATA_IN_0 (32'h54) +`define CLP_AES_REG_DATA_IN_1 (32'h10011058) +`define AES_REG_DATA_IN_1 (32'h58) +`define CLP_AES_REG_DATA_IN_2 (32'h1001105c) +`define AES_REG_DATA_IN_2 (32'h5c) +`define CLP_AES_REG_DATA_IN_3 (32'h10011060) +`define AES_REG_DATA_IN_3 (32'h60) +`define CLP_AES_REG_DATA_OUT_0 (32'h10011064) +`define AES_REG_DATA_OUT_0 (32'h64) +`define CLP_AES_REG_DATA_OUT_1 (32'h10011068) +`define AES_REG_DATA_OUT_1 (32'h68) +`define CLP_AES_REG_DATA_OUT_2 (32'h1001106c) +`define AES_REG_DATA_OUT_2 (32'h6c) +`define CLP_AES_REG_DATA_OUT_3 (32'h10011070) +`define AES_REG_DATA_OUT_3 (32'h70) +`define CLP_AES_REG_CTRL_SHADOWED (32'h10011074) +`define AES_REG_CTRL_SHADOWED (32'h74) +`define AES_REG_CTRL_SHADOWED_OPERATION_LOW (0) +`define AES_REG_CTRL_SHADOWED_OPERATION_MASK (32'h3) +`define AES_REG_CTRL_SHADOWED_MODE_LOW (2) +`define AES_REG_CTRL_SHADOWED_MODE_MASK (32'hfc) +`define AES_REG_CTRL_SHADOWED_KEY_LEN_LOW (8) +`define AES_REG_CTRL_SHADOWED_KEY_LEN_MASK (32'h700) +`define AES_REG_CTRL_SHADOWED_SIDELOAD_LOW (11) +`define AES_REG_CTRL_SHADOWED_SIDELOAD_MASK (32'h800) +`define AES_REG_CTRL_SHADOWED_PRNG_RESEED_RATE_LOW (12) +`define AES_REG_CTRL_SHADOWED_PRNG_RESEED_RATE_MASK (32'h7000) +`define AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_LOW (15) +`define AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_MASK (32'h8000) +`define CLP_AES_REG_CTRL_AUX_SHADOWED (32'h10011078) +`define AES_REG_CTRL_AUX_SHADOWED (32'h78) +`define AES_REG_CTRL_AUX_SHADOWED_KEY_TOUCH_FORCES_RESEED_LOW (0) +`define AES_REG_CTRL_AUX_SHADOWED_KEY_TOUCH_FORCES_RESEED_MASK (32'h1) +`define AES_REG_CTRL_AUX_SHADOWED_FORCE_MASKS_LOW (1) +`define AES_REG_CTRL_AUX_SHADOWED_FORCE_MASKS_MASK (32'h2) +`define CLP_AES_REG_CTRL_AUX_REGWEN (32'h1001107c) +`define AES_REG_CTRL_AUX_REGWEN (32'h7c) +`define AES_REG_CTRL_AUX_REGWEN_CTRL_AUX_REGWEN_LOW (0) +`define AES_REG_CTRL_AUX_REGWEN_CTRL_AUX_REGWEN_MASK (32'h1) +`define CLP_AES_REG_TRIGGER (32'h10011080) +`define AES_REG_TRIGGER (32'h80) +`define AES_REG_TRIGGER_START_LOW (0) +`define AES_REG_TRIGGER_START_MASK (32'h1) +`define AES_REG_TRIGGER_KEY_IV_DATA_IN_CLEAR_LOW (1) +`define AES_REG_TRIGGER_KEY_IV_DATA_IN_CLEAR_MASK (32'h2) +`define AES_REG_TRIGGER_DATA_OUT_CLEAR_LOW (2) +`define AES_REG_TRIGGER_DATA_OUT_CLEAR_MASK (32'h4) +`define AES_REG_TRIGGER_PRNG_RESEED_LOW (3) +`define AES_REG_TRIGGER_PRNG_RESEED_MASK (32'h8) +`define CLP_AES_REG_STATUS (32'h10011084) +`define AES_REG_STATUS (32'h84) +`define AES_REG_STATUS_IDLE_LOW (0) +`define AES_REG_STATUS_IDLE_MASK (32'h1) +`define AES_REG_STATUS_STALL_LOW (1) +`define AES_REG_STATUS_STALL_MASK (32'h2) +`define AES_REG_STATUS_OUTPUT_LOST_LOW (2) +`define AES_REG_STATUS_OUTPUT_LOST_MASK (32'h4) +`define AES_REG_STATUS_OUTPUT_VALID_LOW (3) +`define AES_REG_STATUS_OUTPUT_VALID_MASK (32'h8) +`define AES_REG_STATUS_INPUT_READY_LOW (4) +`define AES_REG_STATUS_INPUT_READY_MASK (32'h10) +`define AES_REG_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_LOW (5) +`define AES_REG_STATUS_ALERT_RECOV_CTRL_UPDATE_ERR_MASK (32'h20) +`define AES_REG_STATUS_ALERT_FATAL_FAULT_LOW (6) +`define AES_REG_STATUS_ALERT_FATAL_FAULT_MASK (32'h40) +`define CLP_AES_REG_CTRL_GCM_SHADOWED (32'h10011088) +`define AES_REG_CTRL_GCM_SHADOWED (32'h88) +`define AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW (0) +`define AES_REG_CTRL_GCM_SHADOWED_PHASE_MASK (32'h3f) +`define AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW (6) +`define AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_MASK (32'h7c0) +`define CLP_AES_CLP_REG_BASE_ADDR (32'h10011100) +`define CLP_AES_CLP_REG_AES_NAME_0 (32'h10011200) +`define AES_CLP_REG_AES_NAME_0 (32'h100) +`define CLP_AES_CLP_REG_AES_NAME_1 (32'h10011204) +`define AES_CLP_REG_AES_NAME_1 (32'h104) +`define CLP_AES_CLP_REG_AES_VERSION_0 (32'h10011208) +`define AES_CLP_REG_AES_VERSION_0 (32'h108) +`define CLP_AES_CLP_REG_AES_VERSION_1 (32'h1001120c) +`define AES_CLP_REG_AES_VERSION_1 (32'h10c) +`define CLP_AES_CLP_REG_AES_KV_RD_KEY_CTRL (32'h10011700) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL (32'h600) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_EN_LOW (0) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_EN_MASK (32'h1) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_LOW (1) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_MASK (32'h3e) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_PCR_HASH_EXTEND_LOW (6) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_PCR_HASH_EXTEND_MASK (32'h40) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_RSVD_LOW (7) +`define AES_CLP_REG_AES_KV_RD_KEY_CTRL_RSVD_MASK (32'hffffff80) +`define CLP_AES_CLP_REG_AES_KV_RD_KEY_STATUS (32'h10011704) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS (32'h604) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_READY_LOW (0) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_READY_MASK (32'h1) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_VALID_LOW (1) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_VALID_MASK (32'h2) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_ERROR_LOW (2) +`define AES_CLP_REG_AES_KV_RD_KEY_STATUS_ERROR_MASK (32'h3fc) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_START (32'h10011900) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R (32'h10011900) +`define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R (32'h800) +`define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_ERROR_EN_MASK (32'h1) +`define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_LOW (1) +`define AES_CLP_REG_INTR_BLOCK_RF_GLOBAL_INTR_EN_R_NOTIF_EN_MASK (32'h2) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R (32'h10011904) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R (32'h804) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR0_EN_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR0_EN_MASK (32'h1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR1_EN_LOW (1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR1_EN_MASK (32'h2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR2_EN_LOW (2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR2_EN_MASK (32'h4) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR3_EN_LOW (3) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_EN_R_ERROR3_EN_MASK (32'h8) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R (32'h10011908) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R (32'h808) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_CMD_DONE_EN_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_EN_R_NOTIF_CMD_DONE_EN_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R (32'h1001190c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R (32'h80c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R_AGG_STS_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_GLOBAL_INTR_R_AGG_STS_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R (32'h10011910) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R (32'h810) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R_AGG_STS_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_GLOBAL_INTR_R_AGG_STS_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R (32'h10011914) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R (32'h814) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR0_STS_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR0_STS_MASK (32'h1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR1_STS_LOW (1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR1_STS_MASK (32'h2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR2_STS_LOW (2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR2_STS_MASK (32'h4) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR3_STS_LOW (3) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR3_STS_MASK (32'h8) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R (32'h10011918) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R (32'h818) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R (32'h1001191c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R (32'h81c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR0_TRIG_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR0_TRIG_MASK (32'h1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR1_TRIG_LOW (1) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR1_TRIG_MASK (32'h2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR2_TRIG_LOW (2) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR2_TRIG_MASK (32'h4) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR3_TRIG_LOW (3) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR_INTR_TRIG_R_ERROR3_TRIG_MASK (32'h8) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R (32'h10011920) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R (32'h820) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R_NOTIF_CMD_DONE_TRIG_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_INTR_TRIG_R_NOTIF_CMD_DONE_TRIG_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_R (32'h10011a00) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_R (32'h900) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_R (32'h10011a04) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_R (32'h904) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_R (32'h10011a08) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_R (32'h908) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_R (32'h10011a0c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_R (32'h90c) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_R (32'h10011a80) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_R (32'h980) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R (32'h10011b00) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R (32'ha00) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R_PULSE_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR0_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R (32'h10011b04) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R (32'ha04) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R_PULSE_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR1_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R (32'h10011b08) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R (32'ha08) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R_PULSE_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR2_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R (32'h10011b0c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R (32'ha0c) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R_PULSE_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_ERROR3_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) +`define CLP_AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (32'h10011b10) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R (32'ha10) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_LOW (0) +`define AES_CLP_REG_INTR_BLOCK_RF_NOTIF_CMD_DONE_INTR_COUNT_INCR_R_PULSE_MASK (32'h1) `define CLP_KV_REG_BASE_ADDR (32'h10018000) `define CLP_KV_REG_KEY_CTRL_0 (32'h10018000) `define KV_REG_KEY_CTRL_0 (32'h0) @@ -3979,8 +4210,10 @@ `define SHA512_REG_SHA512_KV_WR_CTRL_ECC_PKEY_DEST_VALID_MASK (32'h200) `define SHA512_REG_SHA512_KV_WR_CTRL_ECC_SEED_DEST_VALID_LOW (10) `define SHA512_REG_SHA512_KV_WR_CTRL_ECC_SEED_DEST_VALID_MASK (32'h400) -`define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_LOW (11) -`define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_MASK (32'hfffff800) +`define SHA512_REG_SHA512_KV_WR_CTRL_AES_KEY_DEST_VALID_LOW (11) +`define SHA512_REG_SHA512_KV_WR_CTRL_AES_KEY_DEST_VALID_MASK (32'h800) +`define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_LOW (12) +`define SHA512_REG_SHA512_KV_WR_CTRL_RSVD_MASK (32'hfffff000) `define CLP_SHA512_REG_SHA512_KV_WR_STATUS (32'h1002060c) `define SHA512_REG_SHA512_KV_WR_STATUS (32'h60c) `define SHA512_REG_SHA512_KV_WR_STATUS_READY_LOW (0) diff --git a/src/integration/rtl/caliptra_top.sv b/src/integration/rtl/caliptra_top.sv index ada582afa..92df68128 100755 --- a/src/integration/rtl/caliptra_top.sv +++ b/src/integration/rtl/caliptra_top.sv @@ -281,7 +281,7 @@ module caliptra_top logic lsu_addr_ph, lsu_data_ph, lsu_sel; logic ic_addr_ph, ic_data_ph, ic_sel; - logic hmac_busy, ecc_busy, doe_busy; + logic hmac_busy, ecc_busy, doe_busy, aes_busy; logic crypto_error; always_comb crypto_error = (hmac_busy & ecc_busy) | @@ -366,6 +366,7 @@ end always_comb ahb_lite_resp_disable[`CALIPTRA_SLAVE_SEL_CSRNG] = 1'b0; always_comb ahb_lite_resp_disable[`CALIPTRA_SLAVE_SEL_ENTROPY_SRC] = 1'b0; always_comb ahb_lite_resp_disable[`CALIPTRA_SLAVE_SEL_MLDSA] = 1'b0; + always_comb ahb_lite_resp_disable[`CALIPTRA_SLAVE_SEL_AES] = 1'b0; //=========================================================================- // RTL instance @@ -991,6 +992,37 @@ mldsa_top #( .notif_intr (mldsa_notif_intr) ); +aes_clp_wrapper #( + .AHB_DATA_WIDTH(`CALIPTRA_AHB_HDATA_SIZE), + .AHB_ADDR_WIDTH(`CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_AES)) +) aes_inst ( + .clk(clk_cg), + .reset_n(cptra_noncore_rst_b), + .cptra_pwrgood(cptra_pwrgood), + + .haddr_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].haddr[`CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_AES)-1:0]), + .hwdata_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hwdata), + .hsel_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hsel), + .hwrite_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hwrite), + .hready_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hready), + .htrans_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].htrans), + .hsize_i (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hsize), + .hresp_o (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hresp), + .hreadyout_o (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hreadyout), + .hrdata_o (responder_inst[`CALIPTRA_SLAVE_SEL_AES].hrdata), + + // kv interface + .kv_read(kv_read[5]), + .kv_rd_resp(kv_rd_resp[5]), + + .busy_o(aes_busy), + + // Interrupt + .error_intr(), + .notif_intr(), + .debugUnlock_or_scan_mode_switch(debug_lock_or_scan_mode_switch) +); + kv #( .AHB_ADDR_WIDTH(`CALIPTRA_SLAVE_ADDR_WIDTH(`CALIPTRA_SLAVE_SEL_KV)), .AHB_DATA_WIDTH(`CALIPTRA_AHB_HDATA_SIZE) diff --git a/src/integration/rtl/config_defines.svh b/src/integration/rtl/config_defines.svh index a4030d31b..c82c9c6a4 100755 --- a/src/integration/rtl/config_defines.svh +++ b/src/integration/rtl/config_defines.svh @@ -20,7 +20,7 @@ // Uncomment to enable Caliptra Internal TRNG //`define CALIPTRA_INTERNAL_TRNG - `define CALIPTRA_AHB_SLAVES_NUM 5'd15 // Number of slaves AHB + `define CALIPTRA_AHB_SLAVES_NUM 5'd16 // Number of slaves AHB `define CALIPTRA_AHB_MASTERS_NUM 4'd1 // Number of masters AHB `define CALIPTRA_AHB_HADDR_SIZE 32 // bit-width AHB address haddr `define CALIPTRA_AHB_HDATA_SIZE 64 // bit-width AHB data @@ -34,9 +34,9 @@ `define CALIPTRA_SOC_SEC_STATE_WIDTH 3 // AHB Address Map - `define CALIPTRA_SLAVE_NAMES {"MLDSA", "ENTROPY_SRC", "CSRNG" , "IMEM" , "SHA256" , "VEER_ICCM_DMA" , "VEER_DCCM_DMA" , "SOC_IFC" , "SHA512" , "DATAVAULT" , "PCRVAULT" , "KEYVAULT" , "HMAC" , "ECC" , "DOE_CTRL"} /* Array of names for peripherals */ - `define CALIPTRA_SLAVE_BASE_ADDR { 32'h1003_0000, 32'h2000_3000, 32'h2000_2000, 32'h0000_0000, 32'h1002_8000, 32'h4000_0000 , 32'h5000_0000 , 32'h3000_0000, 32'h1002_0000, 32'h1001_C000, 32'h1001_A000, 32'h1001_8000, 32'h1001_0000, 32'h1000_8000, 32'h1000_0000} /* Array with slave base address */ - `define CALIPTRA_SLAVE_MASK_ADDR { 32'h1003_FFFF, 32'h2000_3FFF, 32'h2000_2FFF, 32'h0000_BFFF, 32'h1002_FFFF, 32'h4001_FFFF , 32'h5001_FFFF , 32'h3003_FFFF, 32'h1002_7FFF, 32'h1001_DFFF, 32'h1001_BFFF, 32'h1001_9FFF, 32'h1001_0FFF, 32'h1000_FFFF, 32'h1000_7FFF} /* Array with slave offset address */ + `define CALIPTRA_SLAVE_NAMES {"AES" , "MLDSA" , "ENTROPY_SRC", "CSRNG" , "IMEM" , "SHA256" , "VEER_ICCM_DMA", "VEER_DCCM_DMA", "SOC_IFC" , "SHA512" , "DATAVAULT" , "PCRVAULT" , "KEYVAULT" , "HMAC" , "ECC" , "DOE_CTRL" } /* Array of names for peripherals */ + `define CALIPTRA_SLAVE_BASE_ADDR {32'h1001_1000, 32'h1003_0000, 32'h2000_3000, 32'h2000_2000, 32'h0000_0000, 32'h1002_8000, 32'h4000_0000 , 32'h5000_0000 , 32'h3000_0000, 32'h1002_0000, 32'h1001_C000, 32'h1001_A000, 32'h1001_8000, 32'h1001_0000, 32'h1000_8000, 32'h1000_0000} /* Array with slave base address */ + `define CALIPTRA_SLAVE_MASK_ADDR {32'h1001_1FFF, 32'h1003_FFFF, 32'h2000_3FFF, 32'h2000_2FFF, 32'h0000_BFFF, 32'h1002_FFFF, 32'h4001_FFFF , 32'h5001_FFFF , 32'h3003_FFFF, 32'h1002_7FFF, 32'h1001_DFFF, 32'h1001_BFFF, 32'h1001_9FFF, 32'h1001_0FFF, 32'h1000_FFFF, 32'h1000_7FFF} /* Array with slave offset address */ `define CALIPTRA_SLAVE_ADDR_MASK (`CALIPTRA_SLAVE_BASE_ADDR ^ `CALIPTRA_SLAVE_MASK_ADDR) /* Array indicating meaningful address bits for each slave */ `define CALIPTRA_SLAVE_ADDR_WIDTH(n) $clog2((`CALIPTRA_SLAVE_ADDR_MASK >> (`CALIPTRA_AHB_HADDR_SIZE*n)) & {`CALIPTRA_AHB_HADDR_SIZE{1'b1}}) /* Decode address width for each slave from assigned BASE/MASK address */ `define CALIPTRA_SLAVE_SEL_DOE 0 @@ -54,6 +54,7 @@ `define CALIPTRA_SLAVE_SEL_CSRNG 12 `define CALIPTRA_SLAVE_SEL_ENTROPY_SRC 13 `define CALIPTRA_SLAVE_SEL_MLDSA 14 + `define CALIPTRA_SLAVE_SEL_AES 15 // Interrupt Assignments // NOTE Vector 0 is reserved by VeeR diff --git a/src/integration/stimulus/L0_regression.yml b/src/integration/stimulus/L0_regression.yml index 01230ede4..25cc59721 100644 --- a/src/integration/stimulus/L0_regression.yml +++ b/src/integration/stimulus/L0_regression.yml @@ -25,6 +25,7 @@ contents: - ../test_suites/smoke_test_ecc/smoke_test_ecc.yml - ../test_suites/smoke_test_hmac/smoke_test_hmac.yml #- ../test_suites/smoke_test_mldsa/smoke_test_mldsa.yml //TODO: Add after updating submodule + - ../test_suites/smoke_test_aes/smoke_test_aes.yml - ../test_suites/smoke_test_kv/smoke_test_kv.yml - ../test_suites/smoke_test_sram_ecc/smoke_test_sram_ecc.yml - ../test_suites/smoke_test_ras/smoke_test_ras.yml diff --git a/src/integration/test_suites/libs/aes/aes.c b/src/integration/test_suites/libs/aes/aes.c index 7226fcc25..230301c78 100644 --- a/src/integration/test_suites/libs/aes/aes.c +++ b/src/integration/test_suites/libs/aes/aes.c @@ -12,4 +12,265 @@ // See the License for the specific language governing permissions and // limitations under the License. // +#include "caliptra_defines.h" +#include "printf.h" +#include "aes.h" +#include +#include +//"0388dace60b6a392f328c2b971b2fe78" + +void hex_to_uint32_array(const char *hex_str, uint32_t *array, uint32_t *array_size) { + int len = strlen(hex_str); + const uint32_t index[] = {1,0,3,2,5,4,7,6}; + if (len % 8 != 0) { + VPRINTF(HIGH, "Error: Hex string length must be a multiple of 8.\n"); + return; + } + + *array_size = len / 8; + for (int i = 0; i < *array_size; i++) { + uint32_t value = 0x00000000; + for (int j = 0; j < 8; j++) { + char c = hex_str[i * 8 + j]; + uint32_t digit; + + if (c >= '0' && c <= '9') { + digit = c - '0'; + } else if (c >= 'a' && c <= 'f') { + digit = c - 'a' + 10; + } else if (c >= 'A' && c <= 'F') { + digit = c - 'A' + 10; + } else { + VPRINTF(HIGH, "Error: Invalid hex character: %c\n", c); + return; + } + value |= digit << (4 * index[j]); + } + array[i] = value; + } +} + +void aes_wait_idle(){ + while((lsu_read_32(CLP_AES_REG_STATUS) & AES_REG_STATUS_IDLE_MASK) == 0); +} + + +void aes_flow(aes_op_e op, aes_mode_e mode, aes_key_len_e key_len, aes_flow_t aes_input){ + uint8_t fail_cmd = 0x1; + uint32_t ciphertext[4]; + uint32_t tag[4]; + uint32_t partial_text_len = aes_input.text_len%16; + uint32_t partial_aad_len = aes_input.aad_len%16; + uint32_t num_blocks_text = (partial_text_len == 0) ? aes_input.text_len/16 : aes_input.text_len/16 +1; + uint32_t num_blocks_aad = (partial_aad_len == 0) ? aes_input.aad_len/16 : aes_input.aad_len/16 + 1; + uint32_t length; + uint32_t num_bytes; + uint32_t masked = 0; + + // wait for AES to be idle + aes_wait_idle(); + + uint32_t aes_ctrl = + ((op << AES_REG_CTRL_SHADOWED_OPERATION_LOW) & AES_REG_CTRL_SHADOWED_OPERATION_MASK) | + ((mode << AES_REG_CTRL_SHADOWED_MODE_LOW) & AES_REG_CTRL_SHADOWED_MODE_MASK) | + ((key_len << AES_REG_CTRL_SHADOWED_KEY_LEN_LOW) & AES_REG_CTRL_SHADOWED_KEY_LEN_MASK) | + (0x0 << AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_LOW) | + (aes_input.key.kv_intf << AES_REG_CTRL_SHADOWED_SIDELOAD_LOW); + + VPRINTF(LOW, "Write AES CTRL with value 0x%x\n", aes_ctrl); + + //write shadowed ctrl twice + lsu_write_32(CLP_AES_REG_CTRL_SHADOWED, aes_ctrl); + lsu_write_32(CLP_AES_REG_CTRL_SHADOWED, aes_ctrl); + + + if (mode == AES_GCM) { + aes_wait_idle(); + + //If GCM set CTRL_GCM to GCM_INIT + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_INIT << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (16 << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_INIT << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (16 << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + } + + aes_wait_idle(); + + //Write the key + if (aes_input.key.kv_intf){ + // Wait for KV read logic to be idle + while((lsu_read_32(CLP_AES_CLP_REG_AES_KV_RD_KEY_STATUS) & AES_CLP_REG_AES_KV_RD_KEY_STATUS_READY_MASK) == 0); + + // Program KEY Read + lsu_write_32(CLP_AES_CLP_REG_AES_KV_RD_KEY_CTRL, AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_EN_MASK | + ((aes_input.key.kv_id << AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_LOW) & AES_CLP_REG_AES_KV_RD_KEY_CTRL_READ_ENTRY_MASK)); + + // Check that AES key is loaded + while((lsu_read_32(CLP_AES_CLP_REG_AES_KV_RD_KEY_STATUS) & AES_CLP_REG_AES_KV_RD_KEY_STATUS_VALID_MASK) == 0); + } + else{ + // Load key from hw_data and write to AES + VPRINTF(LOW, "Load Key data to AES\n"); + for (int j = 0; j < 8; j++) { + lsu_write_32(CLP_AES_REG_KEY_SHARE0_0 + j * 4, aes_input.key.key_share0[j]); + lsu_write_32(CLP_AES_REG_KEY_SHARE1_0 + j * 4, aes_input.key.key_share1[j]); + } + } + + aes_wait_idle(); + + // Write IV + VPRINTF(LOW, "Write AES IV\n"); + for (int j = 0; j < 4; j++) { + lsu_write_32((CLP_AES_REG_IV_0 + j * 4), aes_input.iv[j]); + } + + //If GCM set CTRL_GCM to GCM_AAD + if ((mode == AES_GCM) && (aes_input.aad_len > 0)) { + + // Write AAD to REG_DATA_IN + // Check INPUT_READY between blocks + for (int i = 0; i < num_blocks_aad; i++) { + if ((i==0) || ((i==(num_blocks_aad-1)) && (partial_aad_len > 0))) { + num_bytes = ((i==(num_blocks_aad-1)) && (partial_aad_len > 0)) ? partial_aad_len : 16; + + aes_wait_idle(); + + VPRINTF(LOW, "Write GCM_AAD Phase, NUM_BYTES 0x%x\n", num_bytes); + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_AAD << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (num_bytes << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_AAD << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (num_bytes << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + } + + // Wait for INPUT_READY + while((lsu_read_32(CLP_AES_REG_STATUS) & AES_REG_STATUS_INPUT_READY_MASK) == 0); + + VPRINTF(LOW, "Write AES AAD Block %d\n", i); + for (int j = 0; j < 4; j++) { + VPRINTF(HIGH, "Write In Data: 0x%x\n", aes_input.aad[j+i*4]); + lsu_write_32((CLP_AES_REG_DATA_IN_0 + j * 4), aes_input.aad[j+i*4]); + } + } + } + + // Wait for IDLE + //aes_wait_idle(); + + if (aes_input.text_len > 0) { + // For Data Block I=0,...,N-1 + for (int i = 0; i < num_blocks_text; i++) { + + //Check if first block or a partial last block + if ((mode == AES_GCM) && ((i == 0) || ((i == num_blocks_text-1) && (partial_text_len > 0)))) { + //Set num bytes for the last block (could be first also) + num_bytes = ((i == num_blocks_text-1) && (partial_text_len > 0)) ? partial_text_len : 16; + + // Wait for IDLE + aes_wait_idle(); + + //set CTRL_GCM to GCM_TEXT + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_TEXT << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (num_bytes << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_TEXT << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (num_bytes << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + } + + // Wait for INPUT_READY + while((lsu_read_32(CLP_AES_REG_STATUS) & AES_REG_STATUS_INPUT_READY_MASK) == 0); + + // Write Input Data Block. + VPRINTF(LOW, "Write AES Input Data Block %d\n", i); + for (int j = 0; j < 4; j++) { + lsu_write_32((CLP_AES_REG_DATA_IN_0 + j * 4), aes_input.plaintext[j+i*4]); + } + + // Wait for OUTPUT_VALID bit + while((lsu_read_32(CLP_AES_REG_STATUS) & AES_REG_STATUS_OUTPUT_VALID_MASK) == 0); + + // Read Output Data Block I + for (int j = 0; j < 4; j++) { + ciphertext[j] = lsu_read_32(CLP_AES_REG_DATA_OUT_0 + j * 4); + VPRINTF(LOW, "CIPHERTEXT: 0x%x\n", ciphertext[j]); + + //byte mask + uint32_t mask = (masked == 0) ? 0xffffffff : 0x00000000; + //this is the last block, and the partial is inside this dword + if ((i == num_blocks_text-1) && (partial_text_len > 0) && (partial_text_len >= j*4) && (partial_text_len < (j+1)*4)) { + mask = (1 << (partial_text_len%4)*8) - 1; + masked = 0x1; + } + + if ((ciphertext[j] & mask) != (aes_input.ciphertext[j+i*4] & mask)) { + VPRINTF(FATAL, "At offset [%d], output data mismatch!\n", j); + VPRINTF(FATAL, "Actual data: 0x%x\n", ciphertext[j] & mask); + VPRINTF(FATAL, "Expected data: 0x%x\n", aes_input.ciphertext[j+i*4] & mask); + VPRINTF(FATAL,"%c", fail_cmd); + while(1); + } + } + } + } + + // Wait for IDLE + aes_wait_idle(); + + if (mode == AES_GCM) { + // If GCM set CTRL_GCM to GCM_TAG + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_TAG << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (16 << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + lsu_write_32(CLP_AES_REG_CTRL_GCM_SHADOWED, (GCM_TAG << AES_REG_CTRL_GCM_SHADOWED_PHASE_LOW) | + (16 << AES_REG_CTRL_GCM_SHADOWED_NUM_VALID_BYTES_LOW)); + + //Write Input Data Block containing length of AAD and length of ciphertext + //compute length of AAD + length = aes_input.aad_len << 3; //convert length from bytes to bits + length = ((length<<24) & 0xff000000) | //swap the bytes + ((length<< 8) & 0x00ff0000) | + ((length>> 8) & 0x0000ff00) | + ((length>>24) & 0x000000ff); + + VPRINTF(HIGH, "Write AAD Length: 0x%x\n", length); + lsu_write_32(CLP_AES_REG_DATA_IN_0, 0); + lsu_write_32(CLP_AES_REG_DATA_IN_1, length); + + //compute length of text + length = aes_input.text_len << 3; //convert length from bytes to bits + length = ((length<<24) & 0xff000000) | //swap the bytes + ((length<< 8) & 0x00ff0000) | + ((length>> 8) & 0x0000ff00) | + ((length>>24) & 0x000000ff); + + VPRINTF(HIGH, "Write Text Length: 0x%x\n", length); + lsu_write_32(CLP_AES_REG_DATA_IN_2, 0); + lsu_write_32(CLP_AES_REG_DATA_IN_3, length); + + // Wait for OUTPUT_VALID bit + while ((lsu_read_32(CLP_AES_REG_STATUS) & AES_REG_STATUS_OUTPUT_VALID_MASK) == 0); + + //compare output data to expected tag + // Read Output Data Block I + for (int j = 0; j < 4; j++) { + tag[j] = lsu_read_32(CLP_AES_REG_DATA_OUT_0 + j * 4); + VPRINTF(LOW, "TAG: 0x%x\n", tag[j]); + if (tag[j] != aes_input.tag[j]) { + VPRINTF(FATAL,"At offset [%d], tag data mismatch!\n", j); + VPRINTF(FATAL,"Actual data: 0x%x\n", tag[j]); + VPRINTF(FATAL,"Expected data: 0x%x\n", aes_input.tag[j]); + VPRINTF(FATAL,"%c", fail_cmd); + while(1); + } + } + } + + // Disable autostart. Note the control register is shadowed and thus needs to be written twice. + aes_ctrl = 0x1 << AES_REG_CTRL_SHADOWED_MANUAL_OPERATION_LOW; + lsu_write_32(CLP_AES_REG_CTRL_SHADOWED, aes_ctrl); + lsu_write_32(CLP_AES_REG_CTRL_SHADOWED, aes_ctrl); + + // Clear all key, IV, Input Data and Output Data registers. + lsu_write_32(CLP_AES_REG_TRIGGER, (0x1 << AES_REG_TRIGGER_KEY_IV_DATA_IN_CLEAR_LOW) | + (0x1 << AES_REG_TRIGGER_DATA_OUT_CLEAR_LOW)); + +} \ No newline at end of file diff --git a/src/integration/test_suites/libs/aes/aes.h b/src/integration/test_suites/libs/aes/aes.h index 1fdbd3026..8ecd7e94b 100644 --- a/src/integration/test_suites/libs/aes/aes.h +++ b/src/integration/test_suites/libs/aes/aes.h @@ -16,4 +16,64 @@ #ifndef AES_H #define AES_H +#include "caliptra_defines.h" +#include "caliptra_reg.h" +#include "riscv_hw_if.h" + +typedef uint8_t BOOL; +#define FALSE 0u +#define TRUE 1u + +typedef enum { + AES_ECB = (1 << 0), + AES_CBC = (1 << 1), + AES_CFB = (1 << 2), + AES_OFB = (1 << 3), + AEC_CTR = (1 << 4), + AES_GCM = (1 << 5) +} aes_mode_e; + +typedef enum { + AES_ENC = (1 << 0), + AES_DEC = (1 << 1) +} aes_op_e; + +typedef enum { + AES_128 = (1 << 0), + AES_192 = (1 << 1), + AES_256 = (1 << 2) +} aes_key_len_e; + +typedef enum { + GCM_INIT = (1 << 0), + GCM_RESTORE = (1 << 1), + GCM_AAD = (1 << 2), + GCM_TEXT = (1 << 3), + GCM_SAVE = (1 << 4), + GCM_TAG = (1 << 5) +} gcm_phase_e; + +typedef struct { + BOOL kv_intf; + uint8_t kv_id; + uint32_t key_share0[8]; + uint32_t key_share1[8]; +} aes_key_t; + +typedef struct { + aes_key_t key; + uint32_t *iv; + uint32_t text_len; + uint32_t *plaintext; + uint32_t *ciphertext; + uint32_t aad_len; + uint32_t *aad; + uint32_t *tag; +} aes_flow_t; + +void hex_to_uint32_array(const char *hex_str, uint32_t *array, uint32_t *array_size); +void aes_wait_idle(); +void aes_flow(aes_op_e op, aes_mode_e mode, aes_key_len_e key_len, aes_flow_t aes_input); +void aes_zeroize(); + #endif diff --git a/src/integration/test_suites/smoke_test_aes/caliptra_isr.h b/src/integration/test_suites/smoke_test_aes/caliptra_isr.h new file mode 100644 index 000000000..fbef8d0e9 --- /dev/null +++ b/src/integration/test_suites/smoke_test_aes/caliptra_isr.h @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// --------------------------------------------------------------------- +// File: caliptra_isr.h +// Description: +// Provides function declarations for use by external test files, so +// that the ISR functionality may behave like a library. +// TODO: +// This header file includes inline function definitions for event and +// test specific interrupt service behavior, so it should be copied and +// modified for each test. +// --------------------------------------------------------------------- + +#ifndef CALIPTRA_ISR_H + #define CALIPTRA_ISR_H + +#define EN_ISR_PRINTS 1 + +#include "caliptra_defines.h" +#include +#include "printf.h" + +/* --------------- symbols/typedefs --------------- */ +typedef struct { + uint32_t doe_error; + uint32_t doe_notif; + uint32_t ecc_error; + uint32_t ecc_notif; + uint32_t hmac_error; + uint32_t hmac_notif; + uint32_t kv_error; + uint32_t kv_notif; + uint32_t sha512_error; + uint32_t sha512_notif; + uint32_t sha256_error; + uint32_t sha256_notif; + uint32_t soc_ifc_error; + uint32_t soc_ifc_notif; + uint32_t sha512_acc_error; + uint32_t sha512_acc_notif; + uint32_t mldsa_error; + uint32_t mldsa_notif; + uint32_t axi_dma_error; + uint32_t axi_dma_notif; +} caliptra_intr_received_s; +extern volatile caliptra_intr_received_s cptra_intr_rcv; + +////////////////////////////////////////////////////////////////////////////// +// Function Declarations +// + +// Performs all the CSR setup to configure and enable vectored external interrupts +void init_interrupts(void); + +// These inline functions are used to insert event-specific functionality into the +// otherwise generic ISR that gets laid down by the parameterized macro "nonstd_veer_isr" +inline void service_doe_error_intr() {return;} +inline void service_doe_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.doe_notif |= DOE_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad doe_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_ecc_error_intr() {return;} +inline void service_ecc_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.ecc_notif |= ECC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad ecc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_hmac_error_intr() {return;} +inline void service_hmac_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.hmac_notif |= HMAC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad hmac_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_kv_error_intr() {return;} +inline void service_kv_notif_intr() {return;} +inline void service_sha512_error_intr() {return;} +inline void service_sha512_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha512_notif |= SHA512_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha512_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_sha256_error_intr() {return;} +inline void service_sha256_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha256_notif |= SHA256_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha256_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + + +inline void service_soc_ifc_error_intr() { + uint32_t * reg = (uint32_t *) (CLP_SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INTERNAL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_INV_DEV_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_CMD_FAIL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_BAD_FUSE_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_ICCM_BLOCKED_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK; + cptra_intr_rcv.soc_ifc_error |= SOC_IFC_REG_INTR_BLOCK_RF_ERROR_INTERNAL_INTR_R_ERROR_MBOX_ECC_UNC_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad soc_ifc_error_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_soc_ifc_notif_intr () { + uint32_t * reg = (uint32_t *) (CLP_SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_AVAIL_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_MBOX_ECC_COR_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_DEBUG_LOCKED_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SCAN_MODE_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_SOC_REQ_LOCK_STS_MASK; + } + if (sts & SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK) { + *reg = SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK; + cptra_intr_rcv.soc_ifc_notif |= SOC_IFC_REG_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_GEN_IN_TOGGLE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad soc_ifc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_sha512_acc_error_intr() {return;} +inline void service_sha512_acc_notif_intr() { + uint32_t * reg = (uint32_t *) (CLP_SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R); + uint32_t sts = *reg; + /* Write 1 to Clear the pending interrupt */ + if (sts & SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK) { + *reg = SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + cptra_intr_rcv.sha512_acc_notif |= SHA512_ACC_CSR_INTR_BLOCK_RF_NOTIF_INTERNAL_INTR_R_NOTIF_CMD_DONE_STS_MASK; + } + if (sts == 0) { + VPRINTF(ERROR,"bad sha512_acc_notif_intr sts:%x\n", sts); + SEND_STDOUT_CTRL(0x1); + while(1); + } +} + +inline void service_mldsa_error_intr() {return;} +inline void service_mldsa_notif_intr() {return;} +inline void service_axi_dma_error_intr() {return;} +inline void service_axi_dma_notif_intr() {return;} + + +#endif //CALIPTRA_ISR_H diff --git a/src/integration/test_suites/smoke_test_aes/smoke_test_aes.c b/src/integration/test_suites/smoke_test_aes/smoke_test_aes.c new file mode 100644 index 000000000..63a15b521 --- /dev/null +++ b/src/integration/test_suites/smoke_test_aes/smoke_test_aes.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#include "caliptra_defines.h" +#include "caliptra_isr.h" +#include "riscv_hw_if.h" +#include "riscv-csr.h" +#include "printf.h" +#include "aes.h" + +volatile uint32_t* stdout = (uint32_t *)STDOUT; +volatile uint32_t intr_count = 0; +#ifdef CPT_VERBOSITY + enum printf_verbosity verbosity_g = CPT_VERBOSITY; +#else + enum printf_verbosity verbosity_g = LOW; +#endif + +volatile caliptra_intr_received_s cptra_intr_rcv = {0}; + +/* +//CASE1 +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = +Ciphertext = +AAD = +Tag = 530f8afbc74536b9a963b4f1c4cb738b +//CASE2 +Cipher = AES-256-GCM +Key = 0000000000000000000000000000000000000000000000000000000000000000 +IV = 000000000000000000000000 +Plaintext = 00000000000000000000000000000000 +Ciphertext = cea7403d4d606b6e074ec5d3baf39d18 +AAD = +Tag = d0d1c8a799996bf0265b98b5d48ab919 +//CASE3 +Cipher = AES-256-GCM +Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 76fc6ece0f4e1768cddf8853bb2d551b +//CASE4 +Cipher = AES-128-GCM +Key = feffe9928665731c6d6a8f9467308308 +IV = cafebabefacedbaddecaf888 +Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39 +Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091 +AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2 +Tag = 5bc94fbc3221a5db94fae95ae7121a47 +*/ + +void main() { + + aes_flow_t aes_input; + aes_op_e op = AES_ENC; + aes_mode_e mode = AES_GCM; + aes_key_len_e key_len; + + const char key_str1[] = "0000000000000000000000000000000000000000000000000000000000000000"; + const char key_str2[] = "0000000000000000000000000000000000000000000000000000000000000000"; + const char key_str3[] = "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308"; + const char key_str4[] = "feffe9928665731c6d6a8f9467308308"; + uint32_t key[8]; + uint32_t key_size; + + const char iv_str1[] = "000000000000000000000000"; + const char iv_str2[] = "000000000000000000000000"; + const char iv_str3[] = "cafebabefacedbaddecaf888"; + const char iv_str4[] = "cafebabefacedbaddecaf888"; + uint32_t iv[4]; + uint32_t iv_length; + + const char plaintext_str1[] = ""; + const char plaintext_str2[] = "00000000000000000000000000000000"; + const char plaintext_str3[] = "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; + const char plaintext_str4[] = "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39"; + uint32_t plaintext[32]; //arbitrary length here + uint32_t plaintext_length; + + const char ciphertext_str1[] = ""; + const char ciphertext_str2[] = "cea7403d4d606b6e074ec5d3baf39d18"; + const char ciphertext_str3[] = "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662"; + const char ciphertext_str4[] = "42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091"; + uint32_t ciphertext[32]; //arbitrary length here + uint32_t ciphertext_length; + + const char aad_str1[] = ""; + const char aad_str2[] = ""; + const char aad_str3[] = "feedfacedeadbeeffeedfacedeadbeefabaddad2"; + const char aad_str4[] = "feedfacedeadbeeffeedfacedeadbeefabaddad2"; + uint32_t aad[32]; //arbitrary length here + uint32_t aad_length; + + const char tag_str1[] = "530f8afbc74536b9a963b4f1c4cb738b"; + const char tag_str2[] = "d0d1c8a799996bf0265b98b5d48ab919"; + const char tag_str3[] = "76fc6ece0f4e1768cddf8853bb2d551b"; + const char tag_str4[] = "5bc94fbc3221a5db94fae95ae7121a47"; + uint32_t tag[4]; + uint32_t tag_length; + + aes_key_t aes_key; + + // Entry message + VPRINTF(LOW, "----------------------------------\n"); + VPRINTF(LOW, " AES-GCM smoke test !!\n" ); + VPRINTF(LOW, "----------------------------------\n"); + + //CASE1 + VPRINTF(LOW, "Test Case 1\n"); + hex_to_uint32_array(key_str1, key, &key_size); + key_len = key_size == 8 ? AES_256 : + key_size == 4 ? AES_128 : AES_192; + hex_to_uint32_array(iv_str1, iv, &iv_length); + hex_to_uint32_array(plaintext_str1, plaintext, &plaintext_length); + hex_to_uint32_array(ciphertext_str1, ciphertext, &ciphertext_length); + hex_to_uint32_array(aad_str1, aad, &aad_length); + hex_to_uint32_array(tag_str1, tag, &tag_length); + + aes_key.kv_intf = FALSE; + for (int i = 0; i < 8; i++) { + aes_key.key_share0[i] = key[i]; + aes_key.key_share1[i] = 0x00000000; + } + + aes_input.key = aes_key; + aes_input.text_len = plaintext_length*4; //convert length to bytes + aes_input.plaintext = plaintext; + aes_input.ciphertext = ciphertext; + aes_input.aad_len = aad_length*4; //convert length to bytes + aes_input.aad = aad; + aes_input.tag = tag; + aes_input.iv = iv; + + aes_flow(op, mode, key_len, aes_input); + + //CASE2 + VPRINTF(LOW, "Test Case 2\n"); + hex_to_uint32_array(key_str2, key, &key_size); + key_len = key_size == 8 ? AES_256 : + key_size == 4 ? AES_128 : AES_192; + hex_to_uint32_array(iv_str2, iv, &iv_length); + hex_to_uint32_array(plaintext_str2, plaintext, &plaintext_length); + hex_to_uint32_array(ciphertext_str2, ciphertext, &ciphertext_length); + hex_to_uint32_array(aad_str2, aad, &aad_length); + hex_to_uint32_array(tag_str2, tag, &tag_length); + + aes_key.kv_intf = FALSE; + for (int i = 0; i < 8; i++) { + aes_key.key_share0[i] = key[i]; + aes_key.key_share1[i] = 0x00000000; + } + + aes_input.key = aes_key; + aes_input.text_len = plaintext_length*4; //convert length to bytes + aes_input.plaintext = plaintext; + aes_input.ciphertext = ciphertext; + aes_input.aad_len = aad_length*4; //convert length to bytes + aes_input.aad = aad; + aes_input.tag = tag; + aes_input.iv = iv; + + aes_flow(op, mode, key_len, aes_input); + + //CASE3 + VPRINTF(LOW, "Test Case 3\n"); + hex_to_uint32_array(key_str3, key, &key_size); + key_len = key_size == 8 ? AES_256 : + key_size == 4 ? AES_128 : AES_192; + hex_to_uint32_array(iv_str3, iv, &iv_length); + hex_to_uint32_array(plaintext_str3, plaintext, &plaintext_length); + hex_to_uint32_array(ciphertext_str3, ciphertext, &ciphertext_length); + hex_to_uint32_array(aad_str3, aad, &aad_length); + hex_to_uint32_array(tag_str3, tag, &tag_length); + + aes_key.kv_intf = FALSE; + for (int i = 0; i < 8; i++) { + aes_key.key_share0[i] = key[i]; + aes_key.key_share1[i] = 0x00000000; + } + + aes_input.key = aes_key; + aes_input.text_len = plaintext_length*4; //convert length to bytes + aes_input.plaintext = plaintext; + aes_input.ciphertext = ciphertext; + aes_input.aad_len = aad_length*4; //convert length to bytes + aes_input.aad = aad; + aes_input.tag = tag; + aes_input.iv = iv; + + aes_flow(op, mode, key_len, aes_input); + + //CASE4 + VPRINTF(LOW, "Test Case 4\n"); + hex_to_uint32_array(key_str4, key, &key_size); + key_len = key_size == 8 ? AES_256 : + key_size == 4 ? AES_128 : AES_192; + hex_to_uint32_array(iv_str4, iv, &iv_length); + hex_to_uint32_array(plaintext_str4, plaintext, &plaintext_length); + hex_to_uint32_array(ciphertext_str4, ciphertext, &ciphertext_length); + hex_to_uint32_array(aad_str4, aad, &aad_length); + hex_to_uint32_array(tag_str4, tag, &tag_length); + + aes_key.kv_intf = FALSE; + for (int i = 0; i < 8; i++) { + aes_key.key_share0[i] = key[i]; + aes_key.key_share1[i] = 0x00000000; + } + + aes_input.key = aes_key; + aes_input.text_len = plaintext_length*4; //convert length to bytes + aes_input.plaintext = plaintext; + aes_input.ciphertext = ciphertext; + aes_input.aad_len = aad_length*4; //convert length to bytes + aes_input.aad = aad; + aes_input.tag = tag; + aes_input.iv = iv; + + aes_flow(op, mode, key_len, aes_input); + + SEND_STDOUT_CTRL( 0xff); + while(1); + +} \ No newline at end of file diff --git a/src/integration/test_suites/smoke_test_aes/smoke_test_aes.yml b/src/integration/test_suites/smoke_test_aes/smoke_test_aes.yml new file mode 100755 index 000000000..2550c1d27 --- /dev/null +++ b/src/integration/test_suites/smoke_test_aes/smoke_test_aes.yml @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +--- +seed: 1 +testname: smoke_test_aes diff --git a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top.vf b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top.vf index cb0d8fe6b..0d1245234 100644 --- a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top.vf +++ b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top.vf @@ -23,8 +23,6 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl @@ -67,6 +65,8 @@ +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/uvmf_template_output/project_benches/caliptra_top/tb/tests +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/uvmf_template_output/project_benches/caliptra_top/tb/testbench +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/../tb ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -93,6 +93,7 @@ +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${UVM_HOME}/src/uvm_pkg.sv ${QUESTA_MVC_HOME}/include/questa_mvc_svapi.svh ${QUESTA_MVC_HOME}/questa_mvc_src/sv/mvc_pkg.sv @@ -155,16 +156,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv @@ -288,6 +279,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -322,6 +326,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -596,6 +609,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -614,6 +637,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_itrng.vf b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_itrng.vf index cb0d8fe6b..0d1245234 100644 --- a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_itrng.vf +++ b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_itrng.vf @@ -23,8 +23,6 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl @@ -67,6 +65,8 @@ +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/uvmf_template_output/project_benches/caliptra_top/tb/tests +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/uvmf_template_output/project_benches/caliptra_top/tb/testbench +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/../tb ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -93,6 +93,7 @@ +incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/edn/rtl +incdir+${CALIPTRA_ROOT}/src/aes/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_tlul/rtl ${UVM_HOME}/src/uvm_pkg.sv ${QUESTA_MVC_HOME}/include/questa_mvc_svapi.svh ${QUESTA_MVC_HOME}/questa_mvc_src/sv/mvc_pkg.sv @@ -155,16 +156,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv @@ -288,6 +279,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -322,6 +326,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv @@ -596,6 +609,16 @@ ${CALIPTRA_ROOT}/src/edn/rtl/edn_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_pkg.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_vh.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_adapter_reg.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_cmd_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_gen.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_rsp_intg_chk.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_dec.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_data_integ_enc.sv +${CALIPTRA_ROOT}/src/caliptra_tlul/rtl/caliptra_tlul_err.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_sbox_canright_masked.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_core.sv @@ -614,6 +637,27 @@ ${CALIPTRA_ROOT}/src/aes/rtl/aes_mix_single_column.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_cipher_control.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_masking.sv ${CALIPTRA_ROOT}/src/aes/rtl/aes_key_expand.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_control_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_core.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_n.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctr_fsm_p.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_gcm_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ctrl_reg_shadowed.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_ghash.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_prng_clearing.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reduced_round.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_status.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_reg_top.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_wrap.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg_pkg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_reg.sv +${CALIPTRA_ROOT}/src/aes/rtl/aes_clp_wrapper.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_core.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_main_sm.sv ${CALIPTRA_ROOT}/src/csrng/rtl/csrng_ctr_drbg_upd.sv diff --git a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_vip.vf b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_vip.vf index 59475fda4..1c840c016 100644 --- a/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_vip.vf +++ b/src/integration/uvmf_caliptra_top/config/uvmf_caliptra_top_vip.vf @@ -23,8 +23,6 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl @@ -41,6 +39,8 @@ +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers +incdir+${CALIPTRA_ROOT}/src/integration/uvmf_caliptra_top/uvmf_template_output/verification_ip/environment_packages/caliptra_top_env_pkg ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -106,16 +106,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv @@ -159,6 +149,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -193,6 +196,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv diff --git a/src/keyvault/rtl/kv_def.rdl b/src/keyvault/rtl/kv_def.rdl index 7a9cd9490..0bae882b5 100644 --- a/src/keyvault/rtl/kv_def.rdl +++ b/src/keyvault/rtl/kv_def.rdl @@ -66,6 +66,7 @@ field {desc = "MLDSA_SEED is a valid destination";} mldsa_seed_dest_valid = 0; field {desc = "ECC PKEY is a valid destination";} ecc_pkey_dest_valid = 0; field {desc = "ECC SEED is a valid destination";} ecc_seed_dest_valid = 0; - field {desc = "Reserved field";} rsvd[21] = 0; + field {desc = "AES KEY is a valid destination";} aes_key_dest_valid = 0; + field {desc = "Reserved field";} rsvd[20] = 0; }; diff --git a/src/keyvault/rtl/kv_defines_pkg.sv b/src/keyvault/rtl/kv_defines_pkg.sv index 71f6b4642..7c76aec36 100644 --- a/src/keyvault/rtl/kv_defines_pkg.sv +++ b/src/keyvault/rtl/kv_defines_pkg.sv @@ -23,7 +23,7 @@ parameter KV_ADDR_W = 13; parameter KV_DATA_W = 32; parameter KV_ENTRY_ADDR_W = $clog2(KV_NUM_KEYS); parameter KV_ENTRY_SIZE_W = $clog2(KV_NUM_DWORDS); -parameter KV_NUM_READ=5; +parameter KV_NUM_READ=6; parameter KV_NUM_WRITE=4; parameter KV_ENTRY_FOR_SIGNING = 7; diff --git a/src/keyvault/rtl/kv_macros.svh b/src/keyvault/rtl/kv_macros.svh index c5c2a7ec9..597fad306 100644 --- a/src/keyvault/rtl/kv_macros.svh +++ b/src/keyvault/rtl/kv_macros.svh @@ -24,6 +24,7 @@ assign struct_name.write_dest_vld[1] = ``hwif_name.``ctrl_reg_name.hmac_block_de assign struct_name.write_dest_vld[2] = ``hwif_name.``ctrl_reg_name.mldsa_seed_dest_valid.value;\ assign struct_name.write_dest_vld[3] = ``hwif_name.``ctrl_reg_name.ecc_pkey_dest_valid.value;\ assign struct_name.write_dest_vld[4] = ``hwif_name.``ctrl_reg_name.ecc_seed_dest_valid.value;\ +assign struct_name.write_dest_vld[5] = ``hwif_name.``ctrl_reg_name.aes_key_dest_valid.value;\ assign struct_name.write_entry = ``hwif_name.``ctrl_reg_name.write_entry.value;\ assign struct_name.write_en = ``hwif_name.``ctrl_reg_name.write_en.value; diff --git a/src/keyvault/rtl/kv_reg.rdl b/src/keyvault/rtl/kv_reg.rdl index 52caf6af2..c833f14b2 100644 --- a/src/keyvault/rtl/kv_reg.rdl +++ b/src/keyvault/rtl/kv_reg.rdl @@ -41,7 +41,7 @@ addrmap kv_reg { [br]dest_valid[2] = mldsa_seed_dest_valid [br]dest_valid[3] = ecc_pkey_dest_valid [br]dest_valid[4] = ecc_seed_dest_valid - [br]dest_valid[5] = rsvd + [br]dest_valid[5] = aes_key_dest_valid [br]dest_valid[6] = rsvd [br]dest_valid[7] = rsvd"; sw=r; hw=rw; we=true; hwclr; resetsignal = hard_reset_b;} dest_valid[8]=0; diff --git a/src/kmac/config/kmac.vf b/src/kmac/config/kmac.vf index 21bfb92e0..161d6d408 100644 --- a/src/kmac/config/kmac.vf +++ b/src/kmac/config/kmac.vf @@ -1,6 +1,7 @@ ++incdir+${CALIPTRA_ROOT}/src/kmac/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl +incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl -+incdir+${CALIPTRA_ROOT}/src/kmac/rtl +${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv @@ -8,10 +9,12 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv -${CALIPTRA_ROOT}/src/kmac/rtl/sha3_pkg.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_round.sv ${CALIPTRA_ROOT}/src/kmac/rtl/keccak_2share.sv ${CALIPTRA_ROOT}/src/kmac/rtl/sha3pad.sv diff --git a/src/lc_ctrl/config/compile.yml b/src/lc_ctrl/config/compile.yml index eff0a412e..efd791094 100644 --- a/src/lc_ctrl/config/compile.yml +++ b/src/lc_ctrl/config/compile.yml @@ -10,9 +10,3 @@ targets: - $COMPILE_ROOT/rtl/lc_ctrl_reg_pkg.sv - $COMPILE_ROOT/rtl/lc_ctrl_state_pkg.sv - $COMPILE_ROOT/rtl/lc_ctrl_pkg.sv - tb: - directories: [$COMPILE_ROOT/rtl] - files: - - $COMPILE_ROOT/rtl/lc_ctrl_reg_pkg.sv - - $COMPILE_ROOT/rtl/lc_ctrl_state_pkg.sv - - $COMPILE_ROOT/rtl/lc_ctrl_pkg.sv diff --git a/src/lc_ctrl/config/lc_ctrl_pkg.vf b/src/lc_ctrl/config/lc_ctrl_pkg.vf index e41a7f442..8c2f460d8 100644 --- a/src/lc_ctrl/config/lc_ctrl_pkg.vf +++ b/src/lc_ctrl/config/lc_ctrl_pkg.vf @@ -7,7 +7,9 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv \ No newline at end of file diff --git a/src/libs/rtl/ahb_slv_sif.sv b/src/libs/rtl/ahb_slv_sif.sv index 972b58381..88e2c10e9 100644 --- a/src/libs/rtl/ahb_slv_sif.sv +++ b/src/libs/rtl/ahb_slv_sif.sv @@ -138,7 +138,7 @@ always_comb begin : response_block if (err & ~err_f) begin hreadyout_o = 1'b0; hresp_o = H_ERROR; - end else if (hld) begin + end else if (dv & hld) begin hreadyout_o = 1'b0; hresp_o = H_OKAY; end else if (err_f) begin diff --git a/src/sha512/rtl/sha512_reg.sv b/src/sha512/rtl/sha512_reg.sv index 4c33285f8..36d3e1989 100644 --- a/src/sha512/rtl/sha512_reg.sv +++ b/src/sha512/rtl/sha512_reg.sv @@ -258,7 +258,11 @@ module sha512_reg ( logic load_next; } ecc_seed_dest_valid; struct packed{ - logic [20:0] next; + logic next; + logic load_next; + } aes_key_dest_valid; + struct packed{ + logic [19:0] next; logic load_next; } rsvd; } SHA512_KV_WR_CTRL; @@ -544,7 +548,10 @@ module sha512_reg ( logic value; } ecc_seed_dest_valid; struct packed{ - logic [20:0] value; + logic value; + } aes_key_dest_valid; + struct packed{ + logic [19:0] value; } rsvd; } SHA512_KV_WR_CTRL; struct packed{ @@ -1161,14 +1168,35 @@ module sha512_reg ( end end assign hwif_out.SHA512_KV_WR_CTRL.ecc_seed_dest_valid.value = field_storage.SHA512_KV_WR_CTRL.ecc_seed_dest_valid.value; + // Field: sha512_reg.SHA512_KV_WR_CTRL.aes_key_dest_valid + always_comb begin + automatic logic [0:0] next_c; + automatic logic load_next_c; + next_c = field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value; + load_next_c = '0; + if(decoded_reg_strb.SHA512_KV_WR_CTRL && decoded_req_is_wr) begin // SW write + next_c = (field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value & ~decoded_wr_biten[11:11]) | (decoded_wr_data[11:11] & decoded_wr_biten[11:11]); + load_next_c = '1; + end + field_combo.SHA512_KV_WR_CTRL.aes_key_dest_valid.next = next_c; + field_combo.SHA512_KV_WR_CTRL.aes_key_dest_valid.load_next = load_next_c; + end + always_ff @(posedge clk or negedge hwif_in.reset_b) begin + if(~hwif_in.reset_b) begin + field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value <= 1'h0; + end else if(field_combo.SHA512_KV_WR_CTRL.aes_key_dest_valid.load_next) begin + field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value <= field_combo.SHA512_KV_WR_CTRL.aes_key_dest_valid.next; + end + end + assign hwif_out.SHA512_KV_WR_CTRL.aes_key_dest_valid.value = field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value; // Field: sha512_reg.SHA512_KV_WR_CTRL.rsvd always_comb begin - automatic logic [20:0] next_c; + automatic logic [19:0] next_c; automatic logic load_next_c; next_c = field_storage.SHA512_KV_WR_CTRL.rsvd.value; load_next_c = '0; if(decoded_reg_strb.SHA512_KV_WR_CTRL && decoded_req_is_wr) begin // SW write - next_c = (field_storage.SHA512_KV_WR_CTRL.rsvd.value & ~decoded_wr_biten[31:11]) | (decoded_wr_data[31:11] & decoded_wr_biten[31:11]); + next_c = (field_storage.SHA512_KV_WR_CTRL.rsvd.value & ~decoded_wr_biten[31:12]) | (decoded_wr_data[31:12] & decoded_wr_biten[31:12]); load_next_c = '1; end field_combo.SHA512_KV_WR_CTRL.rsvd.next = next_c; @@ -1176,7 +1204,7 @@ module sha512_reg ( end always_ff @(posedge clk or negedge hwif_in.reset_b) begin if(~hwif_in.reset_b) begin - field_storage.SHA512_KV_WR_CTRL.rsvd.value <= 21'h0; + field_storage.SHA512_KV_WR_CTRL.rsvd.value <= 20'h0; end else if(field_combo.SHA512_KV_WR_CTRL.rsvd.load_next) begin field_storage.SHA512_KV_WR_CTRL.rsvd.value <= field_combo.SHA512_KV_WR_CTRL.rsvd.next; end @@ -2106,7 +2134,8 @@ module sha512_reg ( assign readback_array[23][8:8] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.mldsa_seed_dest_valid.value : '0; assign readback_array[23][9:9] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.ecc_pkey_dest_valid.value : '0; assign readback_array[23][10:10] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.ecc_seed_dest_valid.value : '0; - assign readback_array[23][31:11] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.rsvd.value : '0; + assign readback_array[23][11:11] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.aes_key_dest_valid.value : '0; + assign readback_array[23][31:12] = (decoded_reg_strb.SHA512_KV_WR_CTRL && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_CTRL.rsvd.value : '0; assign readback_array[24][0:0] = (decoded_reg_strb.SHA512_KV_WR_STATUS && !decoded_req_is_wr) ? hwif_in.SHA512_KV_WR_STATUS.READY.next : '0; assign readback_array[24][1:1] = (decoded_reg_strb.SHA512_KV_WR_STATUS && !decoded_req_is_wr) ? field_storage.SHA512_KV_WR_STATUS.VALID.value : '0; assign readback_array[24][9:2] = (decoded_reg_strb.SHA512_KV_WR_STATUS && !decoded_req_is_wr) ? hwif_in.SHA512_KV_WR_STATUS.ERROR.next : '0; diff --git a/src/sha512/rtl/sha512_reg_pkg.sv b/src/sha512/rtl/sha512_reg_pkg.sv index 87d9e3830..e66bc885a 100644 --- a/src/sha512/rtl/sha512_reg_pkg.sv +++ b/src/sha512/rtl/sha512_reg_pkg.sv @@ -277,7 +277,11 @@ package sha512_reg_pkg; } kv_write_ctrl_reg__ecc_seed_dest_valid__out_t; typedef struct packed{ - logic [20:0] value; + logic value; + } kv_write_ctrl_reg__aes_key_dest_valid__out_t; + + typedef struct packed{ + logic [19:0] value; } kv_write_ctrl_reg__rsvd__out_t; typedef struct packed{ @@ -288,6 +292,7 @@ package sha512_reg_pkg; kv_write_ctrl_reg__mldsa_seed_dest_valid__out_t mldsa_seed_dest_valid; kv_write_ctrl_reg__ecc_pkey_dest_valid__out_t ecc_pkey_dest_valid; kv_write_ctrl_reg__ecc_seed_dest_valid__out_t ecc_seed_dest_valid; + kv_write_ctrl_reg__aes_key_dest_valid__out_t aes_key_dest_valid; kv_write_ctrl_reg__rsvd__out_t rsvd; } kv_write_ctrl_reg__out_t; diff --git a/src/sha512/rtl/sha512_reg_uvm.sv b/src/sha512/rtl/sha512_reg_uvm.sv index 6aee142a8..0b55fbce6 100644 --- a/src/sha512/rtl/sha512_reg_uvm.sv +++ b/src/sha512/rtl/sha512_reg_uvm.sv @@ -312,7 +312,8 @@ package sha512_reg_uvm; kv_write_ctrl_reg_bit_cg mldsa_seed_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_pkey_dest_valid_bit_cg[1]; kv_write_ctrl_reg_bit_cg ecc_seed_dest_valid_bit_cg[1]; - kv_write_ctrl_reg_bit_cg rsvd_bit_cg[21]; + kv_write_ctrl_reg_bit_cg aes_key_dest_valid_bit_cg[1]; + kv_write_ctrl_reg_bit_cg rsvd_bit_cg[20]; kv_write_ctrl_reg_fld_cg fld_cg; rand uvm_reg_field write_en; rand uvm_reg_field write_entry; @@ -321,6 +322,7 @@ package sha512_reg_uvm; rand uvm_reg_field mldsa_seed_dest_valid; rand uvm_reg_field ecc_pkey_dest_valid; rand uvm_reg_field ecc_seed_dest_valid; + rand uvm_reg_field aes_key_dest_valid; rand uvm_reg_field rsvd; function new(string name = "kv_write_ctrl_reg"); @@ -347,8 +349,10 @@ package sha512_reg_uvm; this.ecc_pkey_dest_valid.configure(this, 1, 9, "RW", 0, 'h0, 1, 1, 0); this.ecc_seed_dest_valid = new("ecc_seed_dest_valid"); this.ecc_seed_dest_valid.configure(this, 1, 10, "RW", 0, 'h0, 1, 1, 0); + this.aes_key_dest_valid = new("aes_key_dest_valid"); + this.aes_key_dest_valid.configure(this, 1, 11, "RW", 0, 'h0, 1, 1, 0); this.rsvd = new("rsvd"); - this.rsvd.configure(this, 21, 11, "RW", 0, 'h0, 1, 1, 0); + this.rsvd.configure(this, 20, 12, "RW", 0, 'h0, 1, 1, 0); if (has_coverage(UVM_CVR_REG_BITS)) begin foreach(write_en_bit_cg[bt]) write_en_bit_cg[bt] = new(); foreach(write_entry_bit_cg[bt]) write_entry_bit_cg[bt] = new(); @@ -357,6 +361,7 @@ package sha512_reg_uvm; foreach(mldsa_seed_dest_valid_bit_cg[bt]) mldsa_seed_dest_valid_bit_cg[bt] = new(); foreach(ecc_pkey_dest_valid_bit_cg[bt]) ecc_pkey_dest_valid_bit_cg[bt] = new(); foreach(ecc_seed_dest_valid_bit_cg[bt]) ecc_seed_dest_valid_bit_cg[bt] = new(); + foreach(aes_key_dest_valid_bit_cg[bt]) aes_key_dest_valid_bit_cg[bt] = new(); foreach(rsvd_bit_cg[bt]) rsvd_bit_cg[bt] = new(); end if (has_coverage(UVM_CVR_FIELD_VALS)) diff --git a/src/soc_ifc/config/soc_ifc_tb.vf b/src/soc_ifc/config/soc_ifc_tb.vf index 8c79918fb..fa4b37f7d 100644 --- a/src/soc_ifc/config/soc_ifc_tb.vf +++ b/src/soc_ifc/config/soc_ifc_tb.vf @@ -3,12 +3,12 @@ +incdir+${CALIPTRA_ROOT}/src/axi/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/coverage -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/tb ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -31,16 +31,6 @@ ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/coverage/soc_ifc_cov_if.sv ${CALIPTRA_ROOT}/src/soc_ifc/coverage/soc_ifc_cov_bind.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/common_defines.sv @@ -59,6 +49,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -93,6 +96,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_reg_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_reg.sv diff --git a/src/soc_ifc/config/soc_ifc_top.vf b/src/soc_ifc/config/soc_ifc_top.vf index fcc93a0c9..d549efc50 100644 --- a/src/soc_ifc/config/soc_ifc_top.vf +++ b/src/soc_ifc/config/soc_ifc_top.vf @@ -1,12 +1,12 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/soc_ifc/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -25,16 +25,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh @@ -51,6 +41,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -85,6 +88,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv diff --git a/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc.vf b/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc.vf index 18e96e77b..b890c40e4 100644 --- a/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc.vf +++ b/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc.vf @@ -23,8 +23,6 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl @@ -45,6 +43,8 @@ +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/project_benches/soc_ifc/tb/sequences +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/project_benches/soc_ifc/tb/tests +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/project_benches/soc_ifc/tb/testbench ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -110,16 +110,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv @@ -169,6 +159,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -203,6 +206,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv diff --git a/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc_vip.vf b/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc_vip.vf index 2ce15aaba..bd6e59922 100644 --- a/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc_vip.vf +++ b/src/soc_ifc/uvmf_soc_ifc/config/uvmf_soc_ifc_vip.vf @@ -23,8 +23,6 @@ +incdir+${CALIPTRA_ROOT}/src/integration/rtl +incdir+${CALIPTRA_ROOT}/src/libs/rtl +incdir+${CALIPTRA_ROOT}/src/axi/rtl -+incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl -+incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl +incdir+${CALIPTRA_ROOT}/src/keyvault/rtl +incdir+${CALIPTRA_ROOT}/src/pcrvault/rtl @@ -40,6 +38,8 @@ +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/interface_packages/mbox_sram_pkg/src +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg +incdir+${CALIPTRA_ROOT}/src/soc_ifc/uvmf_soc_ifc/uvmf_template_output/verification_ip/environment_packages/soc_ifc_env_pkg/registers ++incdir+${CALIPTRA_ROOT}/src/caliptra_prim/rtl ++incdir+${CALIPTRA_ROOT}/src/lc_ctrl/rtl +incdir+${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl +incdir+${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include +incdir+${CALIPTRA_ROOT}/src/sha512/rtl @@ -105,16 +105,6 @@ ${CALIPTRA_ROOT}/src/libs/rtl/caliptra_2ff_sync.sv ${CALIPTRA_ROOT}/src/libs/rtl/skidbuffer.v ${CALIPTRA_ROOT}/src/axi/rtl/axi_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_if.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv -${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv -${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/soc_ifc_reg_pkg.sv ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/el2_pdef.vh ${CALIPTRA_ROOT}/src/riscv_core/veer_el2/rtl/include/el2_def.sv @@ -157,6 +147,19 @@ ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_rd.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_wr.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub_arb.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_sub.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_util_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_alert_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_mubi_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_cipher_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sparse_fsm_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_pkg.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/keymgr_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_reg_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_state_pkg.sv +${CALIPTRA_ROOT}/src/lc_ctrl/rtl/lc_ctrl_pkg.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop_en.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_flop.sv ${CALIPTRA_ROOT}/src/caliptra_prim_generic/rtl/caliptra_prim_generic_buf.sv @@ -191,6 +194,15 @@ ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_arbiter_ppc.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sum_tree.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_ext.sv ${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_edge_detector.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_trivium.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_subreg_shadow.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack_data.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_sync_reqack.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_39_32_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_enc.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_secded_inv_64_57_dec.sv +${CALIPTRA_ROOT}/src/caliptra_prim/rtl/caliptra_prim_gf_mult.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/mbox_csr_pkg.sv ${CALIPTRA_ROOT}/src/soc_ifc/rtl/sha512_acc_csr_pkg.sv ${CALIPTRA_ROOT}/src/axi/rtl/axi_dma_req_if.sv diff --git a/tools/scripts/reg_doc_gen.sh b/tools/scripts/reg_doc_gen.sh index f9b737eda..41c97de83 100755 --- a/tools/scripts/reg_doc_gen.sh +++ b/tools/scripts/reg_doc_gen.sh @@ -29,11 +29,13 @@ src/axi/rtl/axi_dma_reg.rdl \ src/soc_ifc/rtl/soc_ifc_reg.rdl \ src/hmac/rtl/hmac_reg.rdl \ src/doe/rtl/doe_reg.rdl \ -src/keyvault/rtl/kv_def.rdl \ src/entropy_src/data/entropy_src.rdl \ src/csrng/data/csrng.rdl \ src/spi_host/data/spi_host.rdl \ -src/uart/data/uart.rdl +src/uart/data/uart.rdl \ +src/aes/data/aes.rdl \ +src/aes/rtl/aes_clp_reg.rdl \ +src/keyvault/rtl/kv_def.rdl python3 tools/scripts/reg_doc_gen.py \ src/soc_ifc/rtl/caliptra_top_reg.rdl \ diff --git a/tools/scripts/reg_gen.sh b/tools/scripts/reg_gen.sh index de5587d5c..50ae36141 100755 --- a/tools/scripts/reg_gen.sh +++ b/tools/scripts/reg_gen.sh @@ -26,3 +26,4 @@ python3 tools/scripts/reg_gen.py $CALIPTRA_ROOT/src/soc_ifc/rtl/soc_ifc_reg.rdl python3 tools/scripts/reg_gen.py $CALIPTRA_ROOT/src/hmac/rtl/hmac_reg.rdl python3 tools/scripts/reg_gen.py $CALIPTRA_ROOT/src/doe/rtl/doe_reg.rdl python3 tools/scripts/reg_gen.py $CALIPTRA_ROOT/src/axi/rtl/axi_dma_reg.rdl +python3 tools/scripts/reg_gen.py $CALIPTRA_ROOT/src/aes/rtl/aes_clp_reg.rdl