blob: 4149ac07465ca94fc5794b8a7073c48fdeeb1c57 [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: csrng app cmd request state machine module
//
// - handles all app cmd requests from all requesting interfaces
module csrng_main_sm import csrng_pkg::*; #() (
input logic clk_i,
input logic rst_ni,
input logic enable_i,
input logic acmd_avail_i,
output logic acmd_accept_o,
input logic [2:0] acmd_i,
input logic acmd_eop_i,
input logic ctr_drbg_cmd_req_rdy_i,
input logic flag0_i,
output logic cmd_entropy_req_o,
input logic cmd_entropy_avail_i,
output logic instant_req_o,
output logic reseed_req_o,
output logic generate_req_o,
output logic update_req_o,
output logic uninstant_req_o,
output logic clr_adata_packer_o,
input logic cmd_complete_i,
input logic local_escalate_i,
output logic [MainSmStateWidth-1:0] main_sm_state_o,
output logic main_sm_alert_o,
output logic main_sm_err_o
);
main_sm_state_e state_d, state_q;
`PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, main_sm_state_e, MainSmIdle)
assign main_sm_state_o = {state_q};
always_comb begin
state_d = state_q;
acmd_accept_o = 1'b0;
cmd_entropy_req_o = 1'b0;
instant_req_o = 1'b0;
reseed_req_o = 1'b0;
generate_req_o = 1'b0;
update_req_o = 1'b0;
uninstant_req_o = 1'b0;
clr_adata_packer_o = 1'b0;
main_sm_alert_o = 1'b0;
main_sm_err_o = 1'b0;
if (state_q == MainSmError) begin
// In case we are in the Error state we must ignore the local escalate and enable signals.
main_sm_err_o = 1'b1;
end else if (local_escalate_i) begin
// In case local escalate is high we must transition to the error state.
state_d = MainSmError;
end else if (!enable_i && state_q inside {MainSmIdle, MainSmParseCmd, MainSmInstantPrep,
MainSmInstantReq, MainSmReseedPrep, MainSmReseedReq,
MainSmGeneratePrep, MainSmGenerateReq,
MainSmUpdatePrep, MainSmUpdateReq,
MainSmUninstantPrep, MainSmUninstantReq,
MainSmClrAData, MainSmCmdCompWait}) begin
// In case the module is disabled and we are in a legal state we must go into idle state.
state_d = MainSmIdle;
end else begin
// Otherwise do the state machine as normal.
unique case (state_q)
MainSmIdle: begin
// Because of the if statement above we won't leave idle if enable is low.
if (ctr_drbg_cmd_req_rdy_i) begin
// Signal the arbiter to grant this request.
if (acmd_avail_i) begin
acmd_accept_o = 1'b1;
state_d = MainSmParseCmd;
end
end
end
MainSmParseCmd: begin
if (ctr_drbg_cmd_req_rdy_i) begin
if (acmd_i == INS) begin
if (acmd_eop_i) begin
state_d = MainSmInstantPrep;
end
end else if (acmd_i == RES) begin
if (acmd_eop_i) begin
state_d = MainSmReseedPrep;
end
end else if (acmd_i == GEN) begin
if (acmd_eop_i) begin
state_d = MainSmGeneratePrep;
end
end else if (acmd_i == UPD) begin
if (acmd_eop_i) begin
state_d = MainSmUpdatePrep;
end
end else if (acmd_i == UNI) begin
if (acmd_eop_i) begin
state_d = MainSmUninstantPrep;
end
end else begin
// Command was not supported.
main_sm_alert_o = 1'b1;
end
end
end
MainSmInstantPrep: begin
if (flag0_i) begin
// Assumes all adata is present now.
state_d = MainSmInstantReq;
end else begin
// Delay one clock to fix timing issue.
cmd_entropy_req_o = 1'b1;
if (cmd_entropy_avail_i) begin
state_d = MainSmInstantReq;
end
end
end
MainSmInstantReq: begin
instant_req_o = 1'b1;
state_d = MainSmClrAData;
end
MainSmReseedPrep: begin
if (flag0_i) begin
// Assumes all adata is present now.
state_d = MainSmReseedReq;
end else begin
// Delay one clock to fix timing issue.
cmd_entropy_req_o = 1'b1;
if (cmd_entropy_avail_i) begin
state_d = MainSmReseedReq;
end
end
end
MainSmReseedReq: begin
reseed_req_o = 1'b1;
state_d = MainSmClrAData;
end
MainSmGeneratePrep: begin
// Assumes all adata is present now.
state_d = MainSmGenerateReq;
end
MainSmGenerateReq: begin
generate_req_o = 1'b1;
state_d = MainSmClrAData;
end
MainSmUpdatePrep: begin
// Assumes all adata is present now.
state_d = MainSmUpdateReq;
end
MainSmUpdateReq: begin
update_req_o = 1'b1;
state_d = MainSmClrAData;
end
MainSmUninstantPrep: begin
// Assumes all adata is present now.
state_d = MainSmUninstantReq;
end
MainSmUninstantReq: begin
uninstant_req_o = 1'b1;
state_d = MainSmClrAData;
end
MainSmClrAData: begin
clr_adata_packer_o = 1'b1;
state_d = MainSmCmdCompWait;
end
MainSmCmdCompWait: begin
if (cmd_complete_i) begin
state_d = MainSmIdle;
end
end
// Error: The error state is now covered by the if statement above.
default: begin
state_d = MainSmError;
main_sm_err_o = 1'b1;
end
endcase
end
end
// Make sure that the state machine has a stable error state. This means that after the error
// state is entered it will not exit it unless a reset signal is received.
`ASSERT(CsrngMainErrorStStable_A, state_q == MainSmError |=> $stable(state_q))
// If in error state, the error output must be high.
`ASSERT(CsrngMainErrorOutput_A, state_q == MainSmError |-> main_sm_err_o)
endmodule