blob: 6f5679ca526085ef1f783920d1c27c0b1f73865e [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: edn csrng application request state machine module
//
// does hardware-based csrng app interface command requests
module edn_main_sm import edn_pkg::*; #(
localparam int StateWidth = 9
) (
input logic clk_i,
input logic rst_ni,
input logic edn_enable_i,
input logic boot_req_mode_i,
input logic auto_req_mode_i,
input logic sw_cmd_req_load_i,
output logic sw_cmd_valid_o,
output logic boot_wr_cmd_reg_o,
output logic boot_wr_cmd_genfifo_o,
output logic auto_set_intr_gate_o,
output logic auto_clr_intr_gate_o,
output logic auto_first_ack_wait_o,
output logic main_sm_done_pulse_o,
input logic csrng_cmd_ack_i,
output logic capt_gencmd_fifo_cnt_o,
output logic boot_send_gencmd_o,
output logic send_gencmd_o,
input logic max_reqs_cnt_zero_i,
output logic capt_rescmd_fifo_cnt_o,
output logic send_rescmd_o,
input logic cmd_sent_i,
input logic local_escalate_i,
output logic auto_req_mode_busy_o,
output logic main_sm_busy_o,
output logic [StateWidth-1:0] main_sm_state_o,
output logic main_sm_err_o
);
//
// Hamming distance histogram:
//
// 0: --
// 1: --
// 2: --
// 3: ||||||||||| (17.54%)
// 4: |||||||||||||||||||| (29.82%)
// 5: ||||||||||||||||| (26.32%)
// 6: ||||||||||| (17.54%)
// 7: ||||| (7.60%)
// 8: (1.17%)
// 9: --
//
// Minimum Hamming distance: 3
// Maximum Hamming distance: 8
// Minimum Hamming weight: 2
// Maximum Hamming weight: 7
//
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;
assign main_sm_busy_o = (state_q != Idle) && (state_q != BootPulse) &&
(state_q != BootDone) && (state_q != SWPortMode);
always_comb begin
state_d = state_q;
boot_wr_cmd_reg_o = 1'b0;
boot_wr_cmd_genfifo_o = 1'b0;
boot_send_gencmd_o = 1'b0;
auto_set_intr_gate_o = 1'b0;
auto_clr_intr_gate_o = 1'b0;
auto_first_ack_wait_o = 1'b0;
auto_req_mode_busy_o = 1'b0;
capt_gencmd_fifo_cnt_o = 1'b0;
send_gencmd_o = 1'b0;
capt_rescmd_fifo_cnt_o = 1'b0;
send_rescmd_o = 1'b0;
main_sm_done_pulse_o = 1'b0;
main_sm_err_o = 1'b0;
sw_cmd_valid_o = 1'b1;
unique case (state_q)
Idle: begin
if (boot_req_mode_i && edn_enable_i) begin
state_d = BootLoadIns;
end else if (auto_req_mode_i && edn_enable_i) begin
state_d = AutoLoadIns;
end else if (edn_enable_i) begin
main_sm_done_pulse_o = 1'b1;
state_d = SWPortMode;
end
end
BootLoadIns: begin
boot_wr_cmd_reg_o = 1'b1;
state_d = BootLoadGen;
end
BootLoadGen: begin
boot_wr_cmd_genfifo_o = 1'b1;
state_d = BootInsAckWait;
end
BootInsAckWait: begin
if (csrng_cmd_ack_i) begin
state_d = BootCaptGenCnt;
end
end
BootCaptGenCnt: begin
capt_gencmd_fifo_cnt_o = 1'b1;
state_d = BootSendGenCmd;
end
BootSendGenCmd: begin
boot_send_gencmd_o = 1'b1;
if (cmd_sent_i) begin
state_d = BootGenAckWait;
end
end
BootGenAckWait: begin
if (csrng_cmd_ack_i) begin
state_d = BootPulse;
end
end
BootPulse: begin
main_sm_done_pulse_o = 1'b1;
state_d = BootDone;
end
BootDone: begin
end
//-----------------------------------
AutoLoadIns: begin
auto_set_intr_gate_o = 1'b1;
auto_first_ack_wait_o = 1'b1;
if (sw_cmd_req_load_i) begin
state_d = AutoFirstAckWait;
end
end
AutoFirstAckWait: begin
auto_first_ack_wait_o = 1'b1;
if (csrng_cmd_ack_i) begin
auto_clr_intr_gate_o = 1'b1;
state_d = AutoDispatch;
end
end
AutoAckWait: begin
sw_cmd_valid_o = 1'b0;
auto_req_mode_busy_o = 1'b1;
if (csrng_cmd_ack_i) begin
state_d = AutoDispatch;
end
end
AutoDispatch: begin
auto_req_mode_busy_o = 1'b1;
sw_cmd_valid_o = 1'b0;
if (!auto_req_mode_i) begin
main_sm_done_pulse_o = 1'b1;
state_d = Idle;
end else begin
if (max_reqs_cnt_zero_i) begin
state_d = AutoCaptReseedCnt;
end else begin
state_d = AutoCaptGenCnt;
end
end
end
AutoCaptGenCnt: begin
sw_cmd_valid_o = 1'b0;
auto_req_mode_busy_o = 1'b1;
capt_gencmd_fifo_cnt_o = 1'b1;
state_d = AutoSendGenCmd;
end
AutoSendGenCmd: begin
sw_cmd_valid_o = 1'b0;
auto_req_mode_busy_o = 1'b1;
send_gencmd_o = 1'b1;
if (cmd_sent_i) begin
state_d = AutoAckWait;
end
end
AutoCaptReseedCnt: begin
sw_cmd_valid_o = 1'b0;
auto_req_mode_busy_o = 1'b1;
capt_rescmd_fifo_cnt_o = 1'b1;
state_d = AutoSendReseedCmd;
end
AutoSendReseedCmd: begin
sw_cmd_valid_o = 1'b0;
auto_req_mode_busy_o = 1'b1;
send_rescmd_o = 1'b1;
if (cmd_sent_i) begin
state_d = AutoAckWait;
end
end
SWPortMode: begin
end
Error: begin
main_sm_err_o = 1'b1;
end
default: begin
state_d = Error;
main_sm_err_o = 1'b1;
end
endcase
if (local_escalate_i) begin
state_d = Error;
// Tie off outputs, except for main_sm_err_o.
boot_wr_cmd_reg_o = 1'b0;
boot_wr_cmd_genfifo_o = 1'b0;
boot_send_gencmd_o = 1'b0;
auto_set_intr_gate_o = 1'b0;
auto_clr_intr_gate_o = 1'b0;
auto_first_ack_wait_o = 1'b0;
auto_req_mode_busy_o = 1'b0;
capt_gencmd_fifo_cnt_o = 1'b0;
send_gencmd_o = 1'b0;
capt_rescmd_fifo_cnt_o = 1'b0;
send_rescmd_o = 1'b0;
main_sm_done_pulse_o = 1'b0;
end else if (!edn_enable_i && state_q inside {BootLoadIns, BootLoadGen, BootInsAckWait,
BootCaptGenCnt, BootSendGenCmd, BootGenAckWait,
BootPulse, BootDone, AutoLoadIns,
AutoFirstAckWait, AutoAckWait, AutoDispatch,
AutoCaptGenCnt, AutoSendGenCmd,
AutoCaptReseedCnt, AutoSendReseedCmd, SWPortMode
}) begin
// Only go to idle if the state is legal and not Idle or Error.
// Even when disabled, illegal states must result in a transition to Error.
state_d = Idle;
// Tie off outputs, except for main_sm_err_o.
boot_wr_cmd_reg_o = 1'b0;
boot_wr_cmd_genfifo_o = 1'b0;
boot_send_gencmd_o = 1'b0;
auto_set_intr_gate_o = 1'b0;
auto_clr_intr_gate_o = 1'b0;
auto_first_ack_wait_o = 1'b0;
auto_req_mode_busy_o = 1'b0;
capt_gencmd_fifo_cnt_o = 1'b0;
send_gencmd_o = 1'b0;
capt_rescmd_fifo_cnt_o = 1'b0;
send_rescmd_o = 1'b0;
main_sm_done_pulse_o = 1'b0;
end
end
// The `local_escalate_i` includes `main_sm_err_o`.
// The following assertion ensures the Error state is stable until reset.
// With `FpvSecCm` prefix, this assertion will added to weekly FPV sec_cm regression.
`ASSERT(FpvSecCmErrorStEscalate_A, state_q == Error |-> local_escalate_i)
// This assertion does not have `FpvSecCm` prefix because the sec_cm FPV environment will
// blackbox the `prim_sparse_fsm` `state_q` output.
`ASSERT(ErrorStStable_A, state_q == Error |=> $stable(state_q))
endmodule