|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // sha3_pkg | 
|  |  | 
|  | package sha3_pkg; | 
|  |  | 
|  | // StateW represents the width of Keccak state variable. | 
|  | // As Sha3 assume the state value as 1600, this shouldn't be modified. | 
|  | // Note that keccak_round is flexible. It can have any values defined in SHA3 | 
|  | // specification. But sha3pad logic assumes the value as 1600. | 
|  | parameter int StateW = 1600; | 
|  |  | 
|  | // Function Name (N) and Customzation String (S) shall be | 
|  | // smaller than 2**256 bits and integer divisiable by 8. | 
|  | parameter int FnWidth = 32;  // up to 32bit Function Name | 
|  | parameter int CsWidth = 256; // up to 256bit Customization Input | 
|  |  | 
|  | // Calculate left_encode(len( X )) bit size. | 
|  | // Assume the enc_8(n) is always 1 (up to 255 byte of len(S) size) | 
|  | // e.g) 248bit --> two bytes , 256bit --> three bytes | 
|  | //  round8bit(clog2(X+1))/8 | 
|  |  | 
|  | parameter int MaxFnEncodeSize = ($clog2(FnWidth+1) + 8 - 1) / 8 + 1; | 
|  | parameter int MaxCsEncodeSize = ($clog2(CsWidth+1) + 8 - 1) / 8 + 1; | 
|  |  | 
|  | parameter int NSRegisterSizePre = FnWidth/8       + CsWidth/8 | 
|  | + MaxFnEncodeSize + MaxCsEncodeSize; | 
|  | // Round up to 32bit word base | 
|  | parameter int NSRegisterSize = ((NSRegisterSizePre + 4 - 1 ) / 4) * 4; | 
|  |  | 
|  | // Prefix represents bytepad(encode_string(N) || encode_string(S), 168 or 136) | 
|  | // +2 represents left_encoding(168 or 136) which could be either: | 
|  | // 10000000 || 00010101 // 168 | 
|  | // 10000000 || 00010001 // 136 | 
|  | parameter int PrefixSize = NSRegisterSize + 2; | 
|  |  | 
|  | // index width for `N` and `S` | 
|  | parameter int PrefixIndexW = $clog2(PrefixSize/64); | 
|  |  | 
|  | // Datapath width in KMAC, this also affects the output of MSG_FIFO | 
|  | // This is assumed as 64 in KMAC design. If this value is changed, some parts | 
|  | // of the KMAC design need to be changed. | 
|  | // | 
|  | // 1. keccak_round logic datapath. Keccak round logic assumes MsgWidth | 
|  | //    divides 1600 keccak state `Width`. Choose the value accordingly. | 
|  | // 2. sha3pad module has fixed width mux for funcpad logic. If MsgWidth is | 
|  | //    changed, the logic also need to be revised. | 
|  | // 3. kmac core logic also has fixed size mux for appeding output length. | 
|  | //    Revise the case statement to fit into revised MsgWidth value. | 
|  | parameter int MsgWidth = 64; | 
|  | parameter int MsgStrbW = MsgWidth / 8; | 
|  |  | 
|  | // Keccak module supports SHA3, SHAKE, cSHAKE function. | 
|  | // This mode determines if the module uses encoded N and S or not. | 
|  | // Also it chooses the padding value. | 
|  | // | 
|  | //    mode   |  little-endian | 
|  | //    -------|---------------- | 
|  | //    Sha3   |  2'b   10 | 
|  | //    Shake  |  4'b 1111 | 
|  | //    CShake |  2'b   00 | 
|  | // | 
|  | // Please remind that if input strings N and S are empty, SW shall | 
|  | // choose SHAKE even for cSHAKE operation. | 
|  | typedef enum logic[1:0] { | 
|  | Sha3   = 2'b 00, | 
|  | Shake  = 2'b 10, | 
|  | CShake = 2'b 11 | 
|  | } sha3_mode_e; | 
|  |  | 
|  | // keccak_strength_e determines the security strength against collision attack | 
|  | // This value decides the _rate_ and _capacity_ of the keccak states. | 
|  | // It affects the sha3pad module too. the padding module implements | 
|  | // `bytepad(X,168)` for L128, `bytepad(X,136)` for L256 in cSHAKE | 
|  | typedef enum logic [2:0] { | 
|  | L128 = 3'b 000, // rate: 1344 bit / capacity:  256 bit Keccak[ 256](, 128) | 
|  | L224 = 3'b 001, // rate: 1152 bit / capacity:  448 bit Keccak[ 448](, 224) | 
|  | L256 = 3'b 010, // rate: 1088 bit / capacity:  512 bit Keccak[ 512](, 256) | 
|  | L384 = 3'b 011, // rate:  832 bit / capacity:  768 bit Keccak[ 768](, 384) | 
|  | L512 = 3'b 100  // rate:  576 bit / capacity: 1024 bit Keccak[1024](, 512) | 
|  | } keccak_strength_e; | 
|  |  | 
|  | parameter int unsigned KeccakRate [5] = '{ | 
|  | 1344/MsgWidth,  // 21 depth := (1600 - 128*2) | 
|  | 1152/MsgWidth,  // 18 depth := (1600 - 224*2) | 
|  | 1088/MsgWidth,  // 17 depth := (1600 - 256*2) | 
|  | 832/MsgWidth,  // 13 depth := (1600 - 384*2) | 
|  | 576/MsgWidth   //  9 depth := (1600 - 512*2) | 
|  | }; | 
|  |  | 
|  | parameter int unsigned MaxBlockSize = KeccakRate[0]; | 
|  |  | 
|  | parameter int unsigned KeccakEntries = 1600/MsgWidth; | 
|  | parameter int unsigned KeccakMsgAddrW = $clog2(KeccakEntries); | 
|  |  | 
|  | parameter int unsigned KeccakCountW = $clog2(KeccakEntries+1); | 
|  |  | 
|  | // SHA3 core state. This state value is used in sha3core module | 
|  | // and also in KMAC top module and the register interface for sw to track the | 
|  | // sha3 status. | 
|  | // Encoding generated with: | 
|  | // $ ./util/design/sparse-fsm-encode.py -d 3 -m 7 -n 6 \ | 
|  | //      -s 4082450958 --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: 4 | 
|  | // | 
|  | localparam int StateWidth = 6; | 
|  | typedef enum logic [StateWidth-1:0] { | 
|  | StIdle_sparse = 6'b101100, | 
|  |  | 
|  | // Absorb stage receives the message bitstream and computes the keccak | 
|  | // rounds. This internal operation is mainly done inside sha3pad module | 
|  | // not sha3core. The core module and this state machine observe the status | 
|  | // of the process and mainly waits until all the sponge absorbing is | 
|  | // completed. The main indicator is `absorbed` signal. | 
|  | StAbsorb_sparse = 6'b100001, | 
|  |  | 
|  | // TODO: Implement StAbort later after context-switching discussion. | 
|  | // Abort stage can be moved from StAbsorb stage. It basically holds the | 
|  | // keccak round operation and opens up the internal state variable to the | 
|  | // software. This stage is for the software to pause current operation and | 
|  | // store the internal state elsewhere then initiates new KMAC/SHA3 process. | 
|  | // StAbort only can be moved to _StFlush_. | 
|  | //StAbort_sparse = 6'b011101, | 
|  |  | 
|  | // Squeeze stage allows the software to read the internal state. | 
|  | // If `EnMasking`, it opens the read permission of two share of the state. | 
|  | // The squeezing in SHA3 specification describes the software to read up to | 
|  | // the rate of SHA3 algorithm but this logic opens up the entire 1600 bits | 
|  | // of the state (3200bits if `EnMasking`). | 
|  | StSqueeze_sparse = 6'b001011, | 
|  |  | 
|  | // ManualRun stage initiaties the keccak round and waits the completion. | 
|  | // This state is moved from Squeeze state by writing 1 to manual_run CSR. | 
|  | // When keccak round is completed, it goes back to Squeeze state. | 
|  | StManualRun_sparse = 6'b010000, | 
|  |  | 
|  | // Flush stage, the core clears out the internal variables and also | 
|  | // submodules' variables too. Then moves back to Idle state. | 
|  | StFlush_sparse =  6'b000110, | 
|  |  | 
|  | StTerminalError_sparse = 6'b111010 | 
|  | } sha3_st_sparse_e; | 
|  |  | 
|  | localparam int StateWidthLogic = 3; | 
|  | typedef enum logic [StateWidthLogic-1:0] { | 
|  | StIdle, | 
|  | StAbsorb, | 
|  | //StAbort, | 
|  | StSqueeze, | 
|  | StManualRun, | 
|  | StFlush, | 
|  | StError | 
|  | } sha3_st_e; | 
|  |  | 
|  | function automatic sha3_st_e sparse2logic(sha3_st_sparse_e st); | 
|  | unique case (st) | 
|  | StIdle_sparse      : return StIdle; | 
|  | StAbsorb_sparse    : return StAbsorb; | 
|  | //StAbort_sparse   : return StAbort; | 
|  | StSqueeze_sparse   : return StSqueeze; | 
|  | StManualRun_sparse : return StManualRun; | 
|  | StFlush_sparse     : return StFlush; | 
|  | default            : return StError; | 
|  | endcase | 
|  | endfunction : sparse2logic | 
|  |  | 
|  | ////////////////// | 
|  | // Error Report // | 
|  | ////////////////// | 
|  | typedef enum logic [7:0] { | 
|  | ErrNone = 8'h 00, | 
|  |  | 
|  | // ErrSha3SwControl occurs when software sent wrong flow signal. | 
|  | // e.g) Sw set `process_i` without `start_i`. The state machine ignores | 
|  | //      the signal and report through the error FIFO. | 
|  | ErrSha3SwControl = 8'h 80 | 
|  | } err_code_e; | 
|  |  | 
|  | typedef struct packed { | 
|  | logic        valid; | 
|  | err_code_e   code; // Type of error | 
|  | logic [23:0] info; // Additional Debug info | 
|  | } err_t; | 
|  |  | 
|  |  | 
|  | /////////////// | 
|  | // Functions // | 
|  | /////////////// | 
|  |  | 
|  | // Bytepading function | 
|  | // `encode_bytepad_len` represents the first two bytes of bytepad() | 
|  | // It depends on the block size. We can reuse KeccakRate | 
|  | // 10000000 || 00010101 // 168 | 
|  | // 10000000 || 00010001 // 136 | 
|  | function automatic logic [15:0] encode_bytepad_len(keccak_strength_e kstrength); | 
|  | logic [15:0] result; | 
|  | unique case (kstrength) | 
|  | L128: result = 16'h A801; // cSHAKE128 | 
|  | L224: result = 16'h 9001; // not used | 
|  | L256: result = 16'h 8801; // cSHAKE256 | 
|  | L384: result = 16'h 6801; // not used | 
|  | L512: result = 16'h 4801; // not used | 
|  |  | 
|  | default: result = 16'h 0000; | 
|  | endcase | 
|  | return result; | 
|  | endfunction : encode_bytepad_len | 
|  |  | 
|  |  | 
|  | endpackage : sha3_pkg |