blob: 21f25e455e76852a502471e0aa26c8f22e6c1ef0 [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::*; #(
localparam int StateWidth = 8
) (
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 [StateWidth-1:0] main_sm_state_o,
output logic main_sm_err_o
);
// Encoding generated with:
// $ ./util/design/sparse-fsm-encode.py -d 3 -m 15 -n 8 \
// -s 1300573258 --language=sv
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: |||||||||||||||||| (32.38%)
// 4: |||||||||||||||||||| (35.24%)
// 5: |||||||| (15.24%)
// 6: |||||| (11.43%)
// 7: ||| (5.71%)
// 8: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 7
// Minimum Hamming weight: 1
// Maximum Hamming weight: 7
//
typedef enum logic [StateWidth-1:0] {
Idle = 8'b01001110, // idle
ParseCmd = 8'b10111011, // parse the cmd
InstantPrep = 8'b11000001, // instantiate prep
InstantReq = 8'b01010100, // instantiate request (takes adata or entropy)
ReseedPrep = 8'b11011101, // reseed prep
ReseedReq = 8'b01011011, // reseed request (takes adata and entropy and Key,V,RC)
GeneratePrep = 8'b11101111, // generate request (takes adata? and Key,V,RC)
GenerateReq = 8'b00100100, // generate request (takes adata? and Key,V,RC)
UpdatePrep = 8'b00110001, // update prep
UpdateReq = 8'b10010000, // update request (takes adata and Key,V,RC)
UninstantPrep = 8'b11110110, // uninstantiate prep
UninstantReq = 8'b01100011, // uninstantiate request
ClrAData = 8'b00000010, // clear out the additional data packer fifo
CmdCompWait = 8'b10111100, // wait for command to complete
Error = 8'b01111000 // error state, results in fatal alert
} state_e;
state_e state_d, state_q;
`PRIM_FLOP_SPARSE_FSM(u_state_regs, state_d, state_q, state_e, Idle)
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_err_o = 1'b0;
unique case (state_q)
Idle: begin
if (enable_i) begin
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 = ParseCmd;
end
end
end
end
ParseCmd: begin
if (enable_i) begin
if (ctr_drbg_cmd_req_rdy_i) begin
if (acmd_i == INS) begin
if (acmd_eop_i) begin
state_d = InstantPrep;
end
end else if (acmd_i == RES) begin
if (acmd_eop_i) begin
state_d = ReseedPrep;
end
end else if (acmd_i == GEN) begin
if (acmd_eop_i) begin
state_d = GeneratePrep;
end
end else if (acmd_i == UPD) begin
if (acmd_eop_i) begin
state_d = UpdatePrep;
end
end else if (acmd_i == UNI) begin
if (acmd_eop_i) begin
state_d = UninstantPrep;
end
end
end
end
end
InstantPrep: begin
if (!enable_i) begin
state_d = Idle;
end else begin
if (flag0_i) begin
// assumes all adata is present now
state_d = InstantReq;
end else begin
// delay one clock to fix timing issue
cmd_entropy_req_o = 1'b1;
if (cmd_entropy_avail_i) begin
state_d = InstantReq;
end
end
end
end
InstantReq: begin
if (!enable_i) begin
state_d = Idle;
end else begin
instant_req_o = 1'b1;
state_d = ClrAData;
end
end
ReseedPrep: begin
if (!enable_i) begin
state_d = Idle;
end else begin
if (flag0_i) begin
// assumes all adata is present now
state_d = ReseedReq;
end else begin
// delay one clock to fix timing issue
cmd_entropy_req_o = 1'b1;
if (cmd_entropy_avail_i) begin
state_d = ReseedReq;
end
end
end
end
ReseedReq: begin
if (!enable_i) begin
state_d = Idle;
end else begin
reseed_req_o = 1'b1;
state_d = ClrAData;
end
end
GeneratePrep: begin
if (!enable_i) begin
state_d = Idle;
end else begin
// assumes all adata is present now
state_d = GenerateReq;
end
end
GenerateReq: begin
if (!enable_i) begin
state_d = Idle;
end else begin
generate_req_o = 1'b1;
state_d = ClrAData;
end
end
UpdatePrep: begin
if (!enable_i) begin
state_d = Idle;
end else begin
// assumes all adata is present now
state_d = UpdateReq;
end
end
UpdateReq: begin
if (!enable_i) begin
state_d = Idle;
end else begin
update_req_o = 1'b1;
state_d = ClrAData;
end
end
UninstantPrep: begin
if (!enable_i) begin
state_d = Idle;
end else begin
// assumes all adata is present now
state_d = UninstantReq;
end
end
UninstantReq: begin
if (!enable_i) begin
state_d = Idle;
end else begin
uninstant_req_o = 1'b1;
state_d = ClrAData;
end
end
ClrAData: begin
if (!enable_i) begin
state_d = Idle;
end else begin
clr_adata_packer_o = 1'b1;
state_d = CmdCompWait;
end
end
CmdCompWait: begin
if (!enable_i) begin
state_d = Idle;
end else begin
if (cmd_complete_i) begin
state_d = Idle;
end
end
end
Error: begin
main_sm_err_o = 1'b1;
end
default: state_d = Error;
endcase
if (local_escalate_i) begin
state_d = Error;
end
end
endmodule