[kmac] Add Main State Machine
This commit adds main state machine at the KMAC top and add
`in_progress` and `in_keyblock` signals for the entropy generation logic
to refresh the entropy.
The entropy logic uses in_progress signal to refresh the LFSR seed.
in_keyblock signal let entropy logic to refresh the entropy everytime it
is consumed, if not in keyblock state, entropy logic gives randome value
and not changed by consumed signal.
Signed-off-by: Eunchan Kim <eunchan@opentitan.org>
diff --git a/hw/ip/kmac/rtl/kmac.sv b/hw/ip/kmac/rtl/kmac.sv
index 3d46a36..c31a9ea 100644
--- a/hw/ip/kmac/rtl/kmac.sv
+++ b/hw/ip/kmac/rtl/kmac.sv
@@ -55,6 +55,26 @@
/////////////////
// Definitions //
/////////////////
+ // This state machine is to track the current process based on SW input and
+ // KMAC operation.
+ typedef enum logic [2:0] {
+ // Idle state
+ KmacIdle,
+
+ // When software writes CmdStart @ KmacIdle and kmac_en, FSM moves to this
+ KmacPrefix,
+
+ // When SHA3 engine processes Key block, FSM moves to here.
+ KmacKeyBlock,
+
+ // Message Feed
+ KmacMsgFeed,
+
+ // Complete and squeeze
+ KmacDigest
+
+ } kmac_st_e;
+ kmac_st_e kmac_st, kmac_st_d;
/////////////
// Signals //
@@ -80,6 +100,12 @@
// Sequence: start --> process(multiple) --> get absorbed event --> {run -->} done
logic sha3_start, sha3_run, sha3_done, sha3_absorbed, unused_sha3_squeeze;
+ // Indicate one block processed
+ logic sha3_block_processed;
+
+ // EStatus for entropy
+ logic entropy_in_progress, entropy_in_keyblock;
+
// KeyMgr interface logic generates event_absorbed from sha3_absorbed.
// It is active only if SW initiates the hashing engine.
logic event_absorbed;
@@ -187,6 +213,7 @@
logic entropy_ready;
entropy_mode_e entropy_mode;
+ logic entropy_fast_process;
// SHA3 Error response
sha3_pkg::err_t sha3_err;
@@ -317,6 +344,7 @@
// Entropy config
assign entropy_ready = reg2hw.cfg.entropy_ready.q;
assign entropy_mode = entropy_mode_e'(reg2hw.cfg.entropy_mode.q);
+ assign entropy_fast_process = reg2hw.cfg.entropy_fast_process.q;
assign hw2reg.cfg.entropy_ready.de = entropy_ready;
assign hw2reg.cfg.entropy_ready.d = 1'b 0; // always clear when ready
@@ -419,6 +447,87 @@
.intr_o (intr_kmac_err_o)
);
+ ///////////////////
+ // State Machine //
+ ///////////////////
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin
+ if (!rst_ni) begin
+ kmac_st <= KmacIdle;
+ end else begin
+ kmac_st <= kmac_st_d;
+ end
+ end
+
+ always_comb begin
+ // Default value
+ kmac_st_d = KmacIdle;
+
+ entropy_in_progress = 1'b 0;
+ entropy_in_keyblock = 1'b 0;
+
+ unique case (kmac_st)
+ KmacIdle: begin
+ if (kmac_cmd == CmdStart) begin
+ // If cSHAKE turned on
+ if (sha3_pkg::CShake == sha3_pkg::sha3_mode_e'(reg2hw.cfg.mode.q)) begin
+ kmac_st_d = KmacPrefix;
+ end else begin
+ // Jump to Msg feed directly
+ kmac_st_d = KmacMsgFeed;
+ end
+ end else begin
+ kmac_st_d = KmacIdle;
+ end
+ end
+
+ KmacPrefix: begin
+ entropy_in_progress =1'b 1;
+ // Wait until SHA3 processes one block
+ if (sha3_block_processed) begin
+ kmac_st_d = (reg2hw.cfg.kmac_en.q) ? KmacKeyBlock : KmacMsgFeed ;
+ end else begin
+ kmac_st_d = KmacPrefix;
+ end
+ end
+
+ KmacKeyBlock: begin
+ entropy_in_progress = 1'b 1;
+ entropy_in_keyblock = 1'b 1;
+ if (sha3_block_processed) begin
+ kmac_st_d = KmacMsgFeed;
+ end else begin
+ kmac_st_d = KmacKeyBlock;
+ end
+ end
+
+ KmacMsgFeed: begin
+ entropy_in_progress = 1'b 1;
+ // If absorbed, move to Digest
+ if (sha3_absorbed) begin
+ kmac_st_d = KmacDigest;
+ end else begin
+ kmac_st_d = KmacMsgFeed;
+ end
+ end
+
+ KmacDigest: begin
+ entropy_in_progress = 1'b 1;
+ // SW can manually run it, wait till done
+ if (sha3_done) begin
+ kmac_st_d = KmacIdle;
+ end else begin
+ kmac_st_d = KmacDigest;
+ end
+ end
+
+ default: begin
+ kmac_st_d = KmacIdle;
+ end
+ endcase
+ end
+ `ASSERT_KNOWN(KmacStKnown_A, kmac_st)
+
///////////////
// Instances //
///////////////
@@ -493,6 +602,8 @@
.absorbed_o (sha3_absorbed),
.squeezing_o (unused_sha3_squeeze),
+ .block_processed_o (sha3_block_processed),
+
.sha3_fsm_o (sha3_fsm),
.state_valid_o (state_valid),
@@ -669,13 +780,14 @@
// Status from internal logic
//// SHA3 engine run indicator
- .in_progress_i (),
+ .in_progress_i (entropy_in_progress),
//// KMAC secret block handling indicator
- .in_keyblock_i (),
+ .in_keyblock_i (entropy_in_keyblock),
// Configuration
.mode_i (entropy_mode),
.entropy_ready_i (entropy_ready),
+ .fast_process_i (entropy_fast_process),
//// Entropy refresh period in clk cycles
.entropy_timer_limit_i (entropy_timer_limit),
@@ -708,6 +820,9 @@
assign unused_refresh_period = {wait_timer_limit, entropy_timer_limit};
assign entropy_err = '{valid: 1'b 0, code: ErrNone, info: '0};
+
+ logic [1:0] unused_entropy_status;
+ assign unused_entropy_status = {entropy_in_keyblock, entropy_in_progress};
end
// Register top
diff --git a/hw/ip/kmac/rtl/kmac_entropy.sv b/hw/ip/kmac/rtl/kmac_entropy.sv
index e3db4a9..f0b9159 100644
--- a/hw/ip/kmac/rtl/kmac_entropy.sv
+++ b/hw/ip/kmac/rtl/kmac_entropy.sv
@@ -31,6 +31,11 @@
//// interface.
input entropy_ready_i,
+ //// Garbage random value when not processing Keyblock, if this config is
+ //// turned on, the logic sending garbage value and never de-assert
+ //// rand_valid_o unless it is not processing KeyBlock.
+ input fast_process_i,
+
//// SW update of seed
input seed_update_i,
input [63:0] seed_data_i,
@@ -288,7 +293,7 @@
rand_valid_o <= 1'b 0;
end else if (rand_valid_set) begin
rand_valid_o <= 1'b 1;
- end else if (rand_valid_clear || rand_consumed_i) begin
+ end else if (rand_valid_clear) begin
rand_valid_o <= 1'b 0;
end
end
@@ -403,7 +408,12 @@
StRandReady: begin
timer_enable = 1'b 1; // If limit is zero, timer won't work
- if (rand_consumed_i) begin
+ if ( (fast_process_i && in_keyblock_i && rand_consumed_i)
+ || (!fast_process_i && rand_consumed_i)) begin
+ // If fast_process is set, don't clear the rand valid, even
+ // consumed. So, the logic does not expand the entropy again.
+ // If fast_process is not set, then every rand_consume signal
+ // triggers rand expansion.
st_d = StRandExpand;
lfsr_en = 1'b 1;
diff --git a/hw/ip/kmac/rtl/sha3.sv b/hw/ip/kmac/rtl/sha3.sv
index 7dfd855..3c85006 100644
--- a/hw/ip/kmac/rtl/sha3.sv
+++ b/hw/ip/kmac/rtl/sha3.sv
@@ -55,6 +55,10 @@
output logic absorbed_o,
output logic squeezing_o,
+ // Indicate of one block processed. KMAC main state tracks the progression
+ // based on this signal.
+ output logic block_processed_o,
+
output sha3_st_e sha3_fsm_o,
// digest output
@@ -130,6 +134,8 @@
// Squeezing output
assign squeezing_o = squeezing;
+ assign block_processed_o = keccak_complete;
+
// State connection
assign state_valid_o = state_valid;
assign state_o = state_guarded;