blob: dc23fbc45f0755e0e95c3b25a74933d6ec98ba1b [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Description: Logic module indicate ongoing activity of after disablement of entropy_src_core
//
// The entropy_src has a great deal of internal state, and when shutting down most of this internal
// state should be cleared. (The two notable exceptions are the health test statistics, which are
// only cleared at the next enable, and the SHA3 conditioning sponge which accumulates unused
// entropy until a seed is generated). There are delays as incoming RNG data is processed, and for
// ease of verification we insist all elements of the data pipeline are cleared consistently. This
// means that once an RNG sample enters the pipeline, that sample should be reflected in the health
// tests. The SHA3 conditioner is also assumed to successfully absorb every 64-bits that enters the
// module.
//
// To acheive this consistency goal the entropy_src delays the clearing of internal data buffers
// and the state machine until:
// 1. Any unprocessed data has been counted at the health checks (regardless of the mode)
// 2. Any RNG data bound for the SHA conditioner has been received at the conditioner.
// 3. Any ongoing SHA processing operations have completed, and the main FSM has been forced
// back to idle.
//
// This block creates a modified version of the enable pulse which:
// 1. Postpones the disable event until any flowing data has passed through the RNG, ESBIT and
// POSTHT FIFOs. If packpressure is encountered at the Precon FIFO, the stalled data can
// be discarded, and so a has a maximum time limit of MaxFifoWait=3 clocks is given for this
// check.
// 2. Once the disable signal is received, the rising edge does not occur until:
// 2a. One clock after the falling edge OR
// 2b. One clock after the SHA engine completes,
// Whichever comes later.
module entropy_src_enable_delay import prim_mubi_pkg::*; (
input logic clk_i,
input logic rst_ni,
input logic enable_i,
// Unconsumed FIFO inputs
input logic esrng_fifo_not_empty_i,
input logic esbit_fifo_not_empty_i,
input logic postht_fifo_not_empty_i,
// SHA3 conditioner inputs
input logic cs_aes_halt_req_i,
input mubi4_t sha3_done_i,
input logic bypass_mode_i,
output logic enable_o
);
// Maximum number of cycles to wait for FIFOs to clear out.
// Set to 3 to allow one cycle for each FIFO in the pipeline.
localparam int MaxFifoWait = 3;
logic suppress_reenable;
logic extend_enable;
logic data_in_flight;
logic [2:0] fifos_not_empty;
// Flops
logic [MaxFifoWait - 1:0] fifo_timer_d, fifo_timer_q;
logic sha3_active_post_en_d, sha3_active_post_en_q;
mubi4_t sha3_done_q;
logic extend_enable_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
sha3_active_post_en_q <= 1'b0;
fifo_timer_q <= '0;
sha3_done_q <= prim_mubi_pkg::MuBi4False;
extend_enable_q <= 1'b0;
end else begin
sha3_active_post_en_q <= sha3_active_post_en_d;
fifo_timer_q <= fifo_timer_d;
sha3_done_q <= sha3_done_i;
extend_enable_q <= extend_enable;
end
end
// Output definition
assign enable_o = (enable_i & ~suppress_reenable) | extend_enable;
// In flight data monitoring.
// The `fifo_timer` is a small shift register to count out the maximum number of cycles to wait
// for the FIFOs to drain. Since this timer is very small (3 cycles), it is implemented as a shift
// register.
assign fifo_timer_d = enable_i ? {MaxFifoWait{1'b1}} : {fifo_timer_q[MaxFifoWait-2:0], 1'b0};
assign fifos_not_empty = {esrng_fifo_not_empty_i, esbit_fifo_not_empty_i,
!bypass_mode_i & postht_fifo_not_empty_i};
assign data_in_flight = |fifo_timer_q && |fifos_not_empty;
// Extend the enable by at least one clock to give the FSM time to receive any last
// Health checks.
assign extend_enable = ((fifo_timer_q[0] | data_in_flight) & ~enable_i);
// Pulse to extend from the falling edge of the incoming enable pulse
// until one cycle after the SHA is done.
assign sha3_active_post_en_d = cs_aes_halt_req_i && !enable_i ? 1'b1 :
mubi4_test_true_strict(sha3_done_q) ? 1'b0 :
sha3_active_post_en_q;
// Force the output to be low until sha3_active_post_en_q falls or
// for one more cycle after the falling each of extend_enable
assign suppress_reenable = sha3_active_post_en_q | extend_enable_q;
endmodule