blob: 4c3274c1c9ddf4aeeae132694fb5bd70c0081525 [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: entropy distrubution network core module
// - this module will make requests to the CSRNG module
// and return the genbits back to up four requesting
// end points.
//
module edn_core import edn_pkg::*;
#(
parameter int NumEndPoints = 4
) (
input logic clk_i,
input logic rst_ni,
input edn_reg_pkg::edn_reg2hw_t reg2hw,
output edn_reg_pkg::edn_hw2reg_t hw2reg,
// EDN interfaces
input edn_req_t [NumEndPoints-1:0] edn_i,
output edn_rsp_t [NumEndPoints-1:0] edn_o,
// CSRNG Application Interface
output csrng_pkg::csrng_req_t csrng_cmd_o,
input csrng_pkg::csrng_rsp_t csrng_cmd_i,
// Alerts
output logic recov_alert_test_o,
output logic fatal_alert_test_o,
output logic recov_alert_o,
output logic fatal_alert_o,
// Interrupts
output logic intr_edn_cmd_req_done_o,
output logic intr_edn_fatal_err_o
);
import edn_reg_pkg::*;
localparam int RegWidth = 32;
localparam int RescmdFifoWidth = 32;
localparam int RescmdFifoDepth = 13;
localparam int GencmdFifoWidth = 32;
localparam int GencmdFifoDepth = 13;
localparam int OutputFifoWidth = 32;
localparam int OutputFifoDepth = 13;
localparam int CSGenBitsWidth = 128;
localparam int EndPointBusWidth = 32;
localparam int RescmdFifoIdxWidth = $clog2(RescmdFifoDepth);
localparam int FifoRstCopies = 4;
localparam int BootReqCopies = 2;
typedef enum logic [4:0] {
MuBiCheck,
FatalErr,
ReseedCmdErr,
GenCmdErr,
OutputErr,
FifoWrErr,
FifoRdErr,
FifoStErr,
CsrngCmdReq,
CsrngCmdReqValid,
CsrngCmdReqOut,
CsrngCmdReqValidOut,
EnDelay,
IntrStatus,
SendReseedCmd,
SendGenCmd,
OutputClr,
MainFsmEn,
CmdFifoCnt,
CsrngPackerClr,
CsrngFipsEn,
CsrngDataVld,
AckFsmEn,
LastEdnEntry
} edn_enable_e;
localparam int EdnEnableCopies = int'(LastEdnEntry);
// signals
logic event_edn_cmd_req_done;
logic event_edn_fatal_err;
logic [EdnEnableCopies-1:FatalErr] edn_enable_fo;
logic [FifoRstCopies-1:1] cmd_fifo_rst_fo;
logic [BootReqCopies-1:1] boot_req_mode_fo;
logic edn_enable_pfa;
logic cmd_fifo_rst_pfa;
logic packer_arb_valid;
logic packer_arb_ready;
logic [NumEndPoints-1:0] packer_arb_req;
logic [NumEndPoints-1:0] packer_arb_gnt;
logic auto_req_mode_pfe;
logic auto_req_mode_pfa;
logic main_sm_done_pulse;
logic main_sm_busy;
logic capt_gencmd_fifo_cnt;
logic capt_rescmd_fifo_cnt;
logic max_reqs_cnt_zero;
logic max_reqs_cnt_load;
logic max_reqs_between_reseed_load;
logic [31:0] max_reqs_between_reseed_bus;
logic csrng_cmd_ack;
logic csrng_cmd_ack_gated;
logic send_rescmd;
logic cmd_sent;
logic send_gencmd;
logic boot_send_gencmd;
logic sw_cmd_req_load;
logic sw_cmd_valid;
logic [31:0] sw_cmd_req_bus;
logic reseed_cmd_load;
logic [31:0] reseed_cmd_bus;
logic generate_cmd_load;
logic [31:0] generate_cmd_bus;
logic packer_cs_clr;
logic packer_cs_push;
logic [CSGenBitsWidth-1:0] packer_cs_wdata;
logic packer_cs_wready;
logic packer_cs_rvalid;
logic packer_cs_rready;
logic [CSGenBitsWidth-1:0] packer_cs_rdata;
logic boot_req_mode_pfa;
logic boot_wr_cmd_reg;
logic boot_wr_cmd_genfifo;
logic auto_first_ack_wait;
logic auto_req_mode_busy;
logic auto_set_intr_gate;
logic auto_clr_intr_gate;
logic [NumEndPoints-1:0] packer_ep_clr;
logic [NumEndPoints-1:0] packer_ep_ack;
logic [NumEndPoints-1:0] packer_ep_push;
logic [CSGenBitsWidth-1:0] packer_ep_wdata [NumEndPoints];
logic [NumEndPoints-1:0] packer_ep_wready;
logic [NumEndPoints-1:0] packer_ep_rvalid;
logic [NumEndPoints-1:0] packer_ep_rready;
logic edn_ack_sm_err_sum;
logic [NumEndPoints-1:0] edn_ack_sm_err;
logic [EndPointBusWidth-1:0] packer_ep_rdata [NumEndPoints];
// rescmd fifo
logic [RescmdFifoIdxWidth-1:0] sfifo_rescmd_depth;
logic [RescmdFifoWidth-1:0] sfifo_rescmd_rdata;
logic sfifo_rescmd_clr;
logic sfifo_rescmd_push;
logic [RescmdFifoWidth-1:0] sfifo_rescmd_wdata;
logic sfifo_rescmd_pop;
logic sfifo_rescmd_err_sum;
logic [2:0] sfifo_rescmd_err;
logic sfifo_rescmd_full;
logic sfifo_rescmd_not_empty;
// gencmd fifo
logic [GencmdFifoWidth-1:0] sfifo_gencmd_rdata;
logic [$clog2(GencmdFifoDepth)-1:0] sfifo_gencmd_depth;
logic sfifo_gencmd_clr;
logic sfifo_gencmd_push;
logic [GencmdFifoWidth-1:0] sfifo_gencmd_wdata;
logic sfifo_gencmd_pop;
logic sfifo_gencmd_err_sum;
logic [2:0] sfifo_gencmd_err;
logic sfifo_gencmd_full;
logic sfifo_gencmd_not_empty;
// output fifo
logic [OutputFifoWidth-1:0] sfifo_output_rdata;
logic sfifo_output_clr;
logic sfifo_output_push;
logic [OutputFifoWidth-1:0] sfifo_output_wdata;
logic sfifo_output_pop;
logic sfifo_output_full;
logic sfifo_output_err_sum;
logic [2:0] sfifo_output_err;
logic sfifo_output_not_empty;
logic edn_main_sm_err_sum;
logic [8:0] edn_main_sm_state;
logic edn_main_sm_err;
logic [30:0] err_code_test_bit;
logic fifo_write_err_sum;
logic fifo_read_err_sum;
logic fifo_status_err_sum;
logic cs_rdata_capt_vld;
logic edn_bus_cmp_alert;
logic edn_cntr_err_sum;
logic edn_cntr_err;
logic [RegWidth-1:0] max_reqs_cnt;
logic max_reqs_cnt_err;
logic cmd_rdy;
logic [31:0] boot_ins_cmd;
logic [31:0] boot_gen_cmd;
// unused
logic unused_err_code_test_bit;
import prim_mubi_pkg::mubi4_t;
import prim_mubi_pkg::mubi4_test_true_strict;
import prim_mubi_pkg::mubi4_test_invalid;
prim_mubi_pkg::mubi4_t [EdnEnableCopies-1:0] mubi_edn_enable_fanout;
prim_mubi_pkg::mubi4_t [FifoRstCopies-1:0] mubi_cmd_fifo_rst_fanout;
prim_mubi_pkg::mubi4_t [BootReqCopies-1:0] mubi_boot_req_mode_fanout;
prim_mubi_pkg::mubi4_t [1:0] mubi_auto_req_mode_fanout;
// flops
logic [31:0] cs_cmd_req_q, cs_cmd_req_d;
logic cs_cmd_req_vld_q, cs_cmd_req_vld_d;
logic [31:0] cs_cmd_req_out_q, cs_cmd_req_out_d;
logic cs_cmd_req_vld_out_q, cs_cmd_req_vld_out_d;
logic [RescmdFifoIdxWidth-1:0] cmd_fifo_cnt_q, cmd_fifo_cnt_d;
logic send_rescmd_q, send_rescmd_d;
logic send_gencmd_q, send_gencmd_d;
logic csrng_fips_q, csrng_fips_d;
logic [NumEndPoints-1:0] edn_fips_q, edn_fips_d;
logic [63:0] cs_rdata_capt_q, cs_rdata_capt_d;
logic cs_rdata_capt_vld_q, cs_rdata_capt_vld_d;
logic sw_rdy_sts_q, sw_rdy_sts_d;
logic intr_sts_gate_q, intr_sts_gate_d;
logic edn_enable_q, edn_enable_d;
always_ff @(posedge clk_i or negedge rst_ni)
if (!rst_ni) begin
cs_cmd_req_q <= '0;
cs_cmd_req_vld_q <= '0;
cs_cmd_req_out_q <= '0;
cs_cmd_req_vld_out_q <= '0;
cmd_fifo_cnt_q <= '0;
send_rescmd_q <= '0;
send_gencmd_q <= '0;
csrng_fips_q <= '0;
edn_fips_q <= '0;
cs_rdata_capt_q <= '0;
cs_rdata_capt_vld_q <= '0;
sw_rdy_sts_q <= '0;
intr_sts_gate_q <= '0;
edn_enable_q <= '0;
end else begin
cs_cmd_req_q <= cs_cmd_req_d;
cs_cmd_req_vld_q <= cs_cmd_req_vld_d;
cs_cmd_req_out_q <= cs_cmd_req_out_d;
cs_cmd_req_vld_out_q <= cs_cmd_req_vld_out_d;
cmd_fifo_cnt_q <= cmd_fifo_cnt_d;
send_rescmd_q <= send_rescmd_d;
send_gencmd_q <= send_gencmd_d;
csrng_fips_q <= csrng_fips_d;
edn_fips_q <= edn_fips_d;
cs_rdata_capt_q <= cs_rdata_capt_d;
cs_rdata_capt_vld_q <= cs_rdata_capt_vld_d;
sw_rdy_sts_q <= sw_rdy_sts_d;
intr_sts_gate_q <= intr_sts_gate_d;
edn_enable_q <= edn_enable_d;
end
//--------------------------------------------
// instantiate interrupt hardware primitives
//--------------------------------------------
prim_intr_hw #(
.Width(1)
) u_intr_hw_edn_cmd_req_done (
.clk_i (clk_i),
.rst_ni (rst_ni),
.event_intr_i (event_edn_cmd_req_done),
.reg2hw_intr_enable_q_i (reg2hw.intr_enable.edn_cmd_req_done.q),
.reg2hw_intr_test_q_i (reg2hw.intr_test.edn_cmd_req_done.q),
.reg2hw_intr_test_qe_i (reg2hw.intr_test.edn_cmd_req_done.qe),
.reg2hw_intr_state_q_i (reg2hw.intr_state.edn_cmd_req_done.q),
.hw2reg_intr_state_de_o (hw2reg.intr_state.edn_cmd_req_done.de),
.hw2reg_intr_state_d_o (hw2reg.intr_state.edn_cmd_req_done.d),
.intr_o (intr_edn_cmd_req_done_o)
);
prim_intr_hw #(
.Width(1)
) u_intr_hw_edn_fatal_err (
.clk_i (clk_i),
.rst_ni (rst_ni),
.event_intr_i (event_edn_fatal_err),
.reg2hw_intr_enable_q_i (reg2hw.intr_enable.edn_fatal_err.q),
.reg2hw_intr_test_q_i (reg2hw.intr_test.edn_fatal_err.q),
.reg2hw_intr_test_qe_i (reg2hw.intr_test.edn_fatal_err.qe),
.reg2hw_intr_state_q_i (reg2hw.intr_state.edn_fatal_err.q),
.hw2reg_intr_state_de_o (hw2reg.intr_state.edn_fatal_err.de),
.hw2reg_intr_state_d_o (hw2reg.intr_state.edn_fatal_err.d),
.intr_o (intr_edn_fatal_err_o)
);
// interrupt for sw app interface only
assign event_edn_cmd_req_done = csrng_cmd_ack_gated;
// Counter and fsm errors are structural errors and are always
// active regardless of the functional state.
logic fatal_loc_events;
assign fatal_loc_events = edn_cntr_err_sum ||
edn_main_sm_err_sum ||
edn_ack_sm_err_sum;
// set the interrupt sources
assign event_edn_fatal_err = (edn_enable_fo[FatalErr] && (
sfifo_rescmd_err_sum ||
sfifo_gencmd_err_sum ||
sfifo_output_err_sum )) ||
fatal_loc_events;
// set fifo errors that are single instances of source
assign sfifo_rescmd_err_sum = (|sfifo_rescmd_err) ||
err_code_test_bit[0];
assign sfifo_gencmd_err_sum = (|sfifo_gencmd_err) ||
err_code_test_bit[1];
assign sfifo_output_err_sum = (|sfifo_output_err) ||
err_code_test_bit[2];
assign edn_ack_sm_err_sum = (|edn_ack_sm_err) ||
err_code_test_bit[20];
assign edn_main_sm_err_sum = edn_main_sm_err ||
err_code_test_bit[21];
assign edn_cntr_err_sum = edn_cntr_err ||
err_code_test_bit[22];
assign fifo_write_err_sum =
sfifo_rescmd_err[2] ||
sfifo_gencmd_err[2] ||
sfifo_output_err[2] ||
err_code_test_bit[28];
assign fifo_read_err_sum =
sfifo_rescmd_err[1] ||
sfifo_gencmd_err[1] ||
sfifo_output_err[1] ||
err_code_test_bit[29];
assign fifo_status_err_sum =
sfifo_rescmd_err[0] ||
sfifo_gencmd_err[0] ||
sfifo_output_err[0] ||
err_code_test_bit[30];
// set the err code source bits
assign hw2reg.err_code.sfifo_rescmd_err.d = 1'b1;
assign hw2reg.err_code.sfifo_rescmd_err.de = edn_enable_fo[ReseedCmdErr] && sfifo_rescmd_err_sum;
assign hw2reg.err_code.sfifo_gencmd_err.d = 1'b1;
assign hw2reg.err_code.sfifo_gencmd_err.de = edn_enable_fo[GenCmdErr] && sfifo_gencmd_err_sum;
assign hw2reg.err_code.sfifo_output_err.d = 1'b1;
assign hw2reg.err_code.sfifo_output_err.de = edn_enable_fo[OutputErr] && sfifo_output_err_sum;
assign hw2reg.err_code.edn_ack_sm_err.d = 1'b1;
assign hw2reg.err_code.edn_ack_sm_err.de = edn_ack_sm_err_sum;
assign hw2reg.err_code.edn_main_sm_err.d = 1'b1;
assign hw2reg.err_code.edn_main_sm_err.de = edn_main_sm_err_sum;
assign hw2reg.err_code.edn_cntr_err.d = 1'b1;
assign hw2reg.err_code.edn_cntr_err.de = edn_cntr_err_sum;
assign boot_ins_cmd = reg2hw.boot_ins_cmd.q;
assign boot_gen_cmd = reg2hw.boot_gen_cmd.q;
// set the err code type bits
assign hw2reg.err_code.fifo_write_err.d = 1'b1;
assign hw2reg.err_code.fifo_write_err.de = edn_enable_fo[FifoWrErr] && fifo_write_err_sum;
assign hw2reg.err_code.fifo_read_err.d = 1'b1;
assign hw2reg.err_code.fifo_read_err.de = edn_enable_fo[FifoRdErr] && fifo_read_err_sum;
assign hw2reg.err_code.fifo_state_err.d = 1'b1;
assign hw2reg.err_code.fifo_state_err.de = edn_enable_fo[FifoStErr] && fifo_status_err_sum;
// Error forcing
for (genvar i = 0; i < 31; i = i+1) begin : gen_err_code_test_bit
assign err_code_test_bit[i] = (reg2hw.err_code_test.q == i) && reg2hw.err_code_test.qe;
end : gen_err_code_test_bit
// alert - send all interrupt sources to the alert for the fatal case
assign fatal_alert_o = event_edn_fatal_err;
// alert test
assign recov_alert_test_o = {
reg2hw.alert_test.recov_alert.q &&
reg2hw.alert_test.recov_alert.qe
};
assign fatal_alert_test_o = {
reg2hw.alert_test.fatal_alert.q &&
reg2hw.alert_test.fatal_alert.qe
};
// check for illegal enable field states, and set alert if detected
// SEC_CM: CONFIG.MUBI
mubi4_t mubi_edn_enable;
assign mubi_edn_enable = mubi4_t'(reg2hw.ctrl.edn_enable.q);
assign edn_enable_pfa = mubi4_test_invalid(mubi_edn_enable_fanout[MuBiCheck]);
assign hw2reg.recov_alert_sts.edn_enable_field_alert.de = edn_enable_pfa;
assign hw2reg.recov_alert_sts.edn_enable_field_alert.d = edn_enable_pfa;
for (genvar i = int'(FatalErr); i < LastEdnEntry; i = i+1) begin : gen_mubi_en_copies
assign edn_enable_fo[i] = mubi4_test_true_strict(mubi_edn_enable_fanout[i]);
end : gen_mubi_en_copies
prim_mubi4_sync #(
.NumCopies(EdnEnableCopies),
.AsyncOn(0)
) u_prim_mubi4_sync_edn_enable (
.clk_i,
.rst_ni,
.mubi_i(mubi_edn_enable),
.mubi_o(mubi_edn_enable_fanout)
);
// SEC_CM: CONFIG.MUBI
mubi4_t mubi_cmd_fifo_rst;
assign mubi_cmd_fifo_rst = mubi4_t'(reg2hw.ctrl.cmd_fifo_rst.q);
assign cmd_fifo_rst_pfa = mubi4_test_invalid(mubi_cmd_fifo_rst_fanout[0]);
assign hw2reg.recov_alert_sts.cmd_fifo_rst_field_alert.de = cmd_fifo_rst_pfa;
assign hw2reg.recov_alert_sts.cmd_fifo_rst_field_alert.d = cmd_fifo_rst_pfa;
for (genvar i = 1; i < FifoRstCopies; i = i+1) begin : gen_mubi_rst_copies
assign cmd_fifo_rst_fo[i] = mubi4_test_true_strict(mubi_cmd_fifo_rst_fanout[i]);
end : gen_mubi_rst_copies
prim_mubi4_sync #(
.NumCopies(FifoRstCopies),
.AsyncOn(0)
) u_prim_mubi4_sync_cmd_fifo_rst (
.clk_i,
.rst_ni,
.mubi_i(mubi_cmd_fifo_rst),
.mubi_o(mubi_cmd_fifo_rst_fanout)
);
// counter errors
assign edn_cntr_err = max_reqs_cnt_err;
//--------------------------------------------
// sw register interface
//--------------------------------------------
// SEC_CM: CONFIG.MUBI
mubi4_t mubi_auto_req_mode;
assign mubi_auto_req_mode = mubi4_t'(reg2hw.ctrl.auto_req_mode.q);
assign auto_req_mode_pfe = mubi4_test_true_strict(mubi_auto_req_mode_fanout[0]);
assign auto_req_mode_pfa = mubi4_test_invalid(mubi_auto_req_mode_fanout[1]);
assign hw2reg.recov_alert_sts.auto_req_mode_field_alert.de = auto_req_mode_pfa;
assign hw2reg.recov_alert_sts.auto_req_mode_field_alert.d = auto_req_mode_pfa;
prim_mubi4_sync #(
.NumCopies(2),
.AsyncOn(0)
) u_prim_mubi4_sync_auto_req_mode (
.clk_i,
.rst_ni,
.mubi_i(mubi_auto_req_mode),
.mubi_o(mubi_auto_req_mode_fanout)
);
// SW interface connection
// cmd req
assign sw_cmd_req_load = reg2hw.sw_cmd_req.qe & sw_cmd_valid;
assign sw_cmd_req_bus = reg2hw.sw_cmd_req.q;
assign max_reqs_between_reseed_load = reg2hw.max_num_reqs_between_reseeds.qe;
assign max_reqs_between_reseed_bus = reg2hw.max_num_reqs_between_reseeds.q;
assign reseed_cmd_load = reg2hw.reseed_cmd.qe;
assign reseed_cmd_bus = reg2hw.reseed_cmd.q;
assign generate_cmd_load = reg2hw.generate_cmd.qe;
assign generate_cmd_bus = reg2hw.generate_cmd.q;
assign cs_cmd_req_d =
(!edn_enable_fo[CsrngCmdReq]) ? '0 :
boot_wr_cmd_reg ? boot_ins_cmd :
sw_cmd_req_load ? sw_cmd_req_bus :
cs_cmd_req_q;
assign cs_cmd_req_vld_d =
(!edn_enable_fo[CsrngCmdReqValid]) ? '0 :
(sw_cmd_req_load || boot_wr_cmd_reg); // cmd reg write
assign cs_cmd_req_out_d =
(!edn_enable_fo[CsrngCmdReqOut]) ? '0 :
send_rescmd ? sfifo_rescmd_rdata :
(send_gencmd || boot_send_gencmd) ? sfifo_gencmd_rdata :
cs_cmd_req_q;
assign cs_cmd_req_vld_out_d =
(!edn_enable_fo[CsrngCmdReqValidOut]) ? '0 :
(send_rescmd || send_gencmd || (boot_send_gencmd && cmd_sent)) ? 1'b1 :
cs_cmd_req_vld_q;
// receive rdy
assign hw2reg.sw_cmd_sts.cmd_rdy.de = 1'b1;
assign hw2reg.sw_cmd_sts.cmd_rdy.d = cmd_rdy;
assign cmd_rdy = !sw_cmd_req_load && sw_rdy_sts_q;
assign sw_rdy_sts_d =
!edn_enable_q ? 1'b0 :
sw_cmd_req_load ? 1'b0 :
auto_first_ack_wait ? 1'b1 :
main_sm_busy ? 1'b0 :
csrng_cmd_i.csrng_req_ready ? 1'b1 :
sw_rdy_sts_q;
assign edn_enable_d = edn_enable_fo[EnDelay];
// receive cmd ack
assign csrng_cmd_ack = csrng_cmd_i.csrng_rsp_ack;
assign csrng_cmd_ack_gated = csrng_cmd_ack && intr_sts_gate_q;
assign hw2reg.sw_cmd_sts.cmd_sts.de = csrng_cmd_ack_gated;
assign hw2reg.sw_cmd_sts.cmd_sts.d = csrng_cmd_i.csrng_rsp_sts;
assign intr_sts_gate_d =
!edn_enable_fo[IntrStatus] ? 1'b0 :
main_sm_done_pulse ? 1'b1 :
auto_set_intr_gate ? 1'b1 :
auto_clr_intr_gate ? 1'b0 :
intr_sts_gate_q;
// rescmd fifo
prim_fifo_sync #(
.Width(RescmdFifoWidth),
.Pass(0),
.Depth(RescmdFifoDepth)
) u_prim_fifo_sync_rescmd (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (sfifo_rescmd_clr),
.wvalid_i (sfifo_rescmd_push),
.wready_o (),
.wdata_i (sfifo_rescmd_wdata),
.rvalid_o (sfifo_rescmd_not_empty),
.rready_i (sfifo_rescmd_pop),
.rdata_o (sfifo_rescmd_rdata),
.full_o (sfifo_rescmd_full),
.depth_o (sfifo_rescmd_depth),
.err_o ()
);
// feedback cmd back into rescmd fifo
assign send_rescmd_d = send_rescmd;
assign sfifo_rescmd_push =
(send_rescmd_q & edn_enable_fo[SendReseedCmd]) ? 1'b1 :
reseed_cmd_load;
assign sfifo_rescmd_wdata =
auto_req_mode_busy ? cs_cmd_req_out_q :
reseed_cmd_bus;
assign sfifo_rescmd_pop = send_rescmd;
assign sfifo_rescmd_clr = (cmd_fifo_rst_fo[1] || main_sm_done_pulse);
assign sfifo_rescmd_err =
{(sfifo_rescmd_push && sfifo_rescmd_full),
(sfifo_rescmd_pop && !sfifo_rescmd_not_empty),
(sfifo_rescmd_full && !sfifo_rescmd_not_empty)};
// gencmd fifo
prim_fifo_sync #(
.Width(GencmdFifoWidth),
.Pass(0),
.Depth(GencmdFifoDepth)
) u_prim_fifo_sync_gencmd (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (sfifo_gencmd_clr),
.wvalid_i (sfifo_gencmd_push),
.wready_o (),
.wdata_i (sfifo_gencmd_wdata),
.rvalid_o (sfifo_gencmd_not_empty),
.rready_i (sfifo_gencmd_pop),
.rdata_o (sfifo_gencmd_rdata),
.full_o (sfifo_gencmd_full),
.depth_o (sfifo_gencmd_depth),
.err_o ()
);
// feedback cmd back into gencmd fifo
assign send_gencmd_d = send_gencmd;
assign sfifo_gencmd_push =
(boot_wr_cmd_genfifo & edn_enable_fo[SendGenCmd]) ? 1'b1 :
(send_gencmd_q & edn_enable_fo[SendGenCmd]) ? 1'b1 :
generate_cmd_load;
assign sfifo_gencmd_wdata =
boot_wr_cmd_genfifo ? boot_gen_cmd :
auto_req_mode_busy ? cs_cmd_req_out_q :
generate_cmd_bus;
assign sfifo_gencmd_pop = send_gencmd || boot_send_gencmd;
assign sfifo_gencmd_clr = (cmd_fifo_rst_fo[2] || main_sm_done_pulse);
assign sfifo_gencmd_err =
{(sfifo_gencmd_push && sfifo_gencmd_full),
(sfifo_gencmd_pop && !sfifo_gencmd_not_empty),
(sfifo_gencmd_full && !sfifo_gencmd_not_empty)};
// output fifo
prim_fifo_sync #(
.Width(OutputFifoWidth),
.Pass(0),
.Depth(OutputFifoDepth)
) u_prim_fifo_sync_output (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (sfifo_output_clr),
.wvalid_i (sfifo_output_push),
.wready_o (),
.wdata_i (sfifo_output_wdata),
.rvalid_o (sfifo_output_not_empty),
.rready_i (sfifo_output_pop),
.rdata_o (sfifo_output_rdata),
.full_o (sfifo_output_full),
.depth_o (),
.err_o ()
);
// drive outputs
assign csrng_cmd_o.csrng_req_valid = sfifo_output_not_empty;
assign csrng_cmd_o.csrng_req_bus = sfifo_output_rdata;
assign sfifo_output_clr = !edn_enable_fo[OutputClr];
assign sfifo_output_push = cs_cmd_req_vld_out_q;
assign sfifo_output_wdata = cs_cmd_req_out_q;
assign sfifo_output_pop = sfifo_output_not_empty && csrng_cmd_i.csrng_req_ready;
assign sfifo_output_err =
{(sfifo_output_push && sfifo_output_full),
(sfifo_output_pop && !sfifo_output_not_empty),
(sfifo_output_full && !sfifo_output_not_empty)};
// sm to process csrng commands
// SEC_CM: MAIN_SM.FSM.SPARSE
// SEC_CM: MAIN_SM.CTR.LOCAL_ESC
edn_main_sm u_edn_main_sm (
.clk_i (clk_i),
.rst_ni (rst_ni),
.edn_enable_i (edn_enable_fo[MainFsmEn]),
.boot_req_mode_i (boot_req_mode_fo[1]),
.auto_req_mode_i (auto_req_mode_pfe),
.sw_cmd_req_load_i (sw_cmd_req_load),
.sw_cmd_valid_o (sw_cmd_valid),
.boot_wr_cmd_reg_o (boot_wr_cmd_reg),
.boot_wr_cmd_genfifo_o (boot_wr_cmd_genfifo),
.auto_set_intr_gate_o (auto_set_intr_gate),
.auto_clr_intr_gate_o (auto_clr_intr_gate),
.auto_first_ack_wait_o (auto_first_ack_wait),
.main_sm_done_pulse_o (main_sm_done_pulse),
.csrng_cmd_ack_i (csrng_cmd_ack),
.capt_gencmd_fifo_cnt_o (capt_gencmd_fifo_cnt),
.boot_send_gencmd_o (boot_send_gencmd),
.send_gencmd_o (send_gencmd),
.max_reqs_cnt_zero_i (max_reqs_cnt_zero),
.capt_rescmd_fifo_cnt_o (capt_rescmd_fifo_cnt),
.send_rescmd_o (send_rescmd),
.cmd_sent_i (cmd_sent),
.local_escalate_i (fatal_loc_events),
.auto_req_mode_busy_o (auto_req_mode_busy),
.main_sm_busy_o (main_sm_busy),
.main_sm_state_o (edn_main_sm_state),
.main_sm_err_o (edn_main_sm_err)
);
// Maximum requests counter for a generate command
// SEC_CM: CTR.REDUN
prim_count #(
.Width(RegWidth),
.ResetValue({RegWidth{1'b1}})
) u_prim_count_max_reqs_cntr (
.clk_i,
.rst_ni,
.clr_i(1'b0),
.set_i(max_reqs_cnt_load),
.set_cnt_i(max_reqs_between_reseed_bus),
.incr_en_i(1'b0),
.decr_en_i(send_gencmd && cmd_sent), // count down
.step_i(RegWidth'(1)),
.cnt_o(max_reqs_cnt),
.cnt_next_o(),
.err_o(max_reqs_cnt_err)
);
assign max_reqs_cnt_load = (max_reqs_between_reseed_load || // sw initial load
send_rescmd && cmd_sent || // runtime decrement
main_sm_done_pulse); // restore when auto mode done
assign max_reqs_cnt_zero = (max_reqs_cnt == '0);
assign cmd_fifo_cnt_d =
(!edn_enable_fo[CmdFifoCnt]) ? '0 :
(cmd_fifo_rst_fo[3] || main_sm_done_pulse) ? '0 :
capt_gencmd_fifo_cnt ? (sfifo_gencmd_depth) :
capt_rescmd_fifo_cnt ? (sfifo_rescmd_depth) :
(send_gencmd || boot_send_gencmd || send_rescmd)? (cmd_fifo_cnt_q-1) :
cmd_fifo_cnt_q;
assign cmd_sent = (cmd_fifo_cnt_q == RescmdFifoIdxWidth'(1));
// SEC_CM: CONFIG.MUBI
mubi4_t mubi_boot_req_mode;
assign mubi_boot_req_mode = mubi4_t'(reg2hw.ctrl.boot_req_mode.q);
assign boot_req_mode_pfa = mubi4_test_invalid(mubi_boot_req_mode_fanout[0]);
assign hw2reg.recov_alert_sts.boot_req_mode_field_alert.de = boot_req_mode_pfa;
assign hw2reg.recov_alert_sts.boot_req_mode_field_alert.d = boot_req_mode_pfa;
for (genvar i = 1; i < BootReqCopies; i = i+1) begin : gen_mubi_boot_copies
assign boot_req_mode_fo[i] = mubi4_test_true_strict(mubi_boot_req_mode_fanout[i]);
end : gen_mubi_boot_copies
prim_mubi4_sync #(
.NumCopies(BootReqCopies),
.AsyncOn(0)
) u_prim_mubi4_sync_boot_req_mode (
.clk_i,
.rst_ni,
.mubi_i(mubi_boot_req_mode),
.mubi_o(mubi_boot_req_mode_fanout)
);
//--------------------------------------------
// packer arbitration
//--------------------------------------------
prim_arbiter_ppc #(
.EnDataPort(0), // Ignore data port
.N(NumEndPoints), // Number of request ports
.DW(1) // Data width
) u_prim_arbiter_ppc_packer_arb (
.clk_i(clk_i),
.rst_ni(rst_ni),
.req_chk_i(1'b1),
.req_i(packer_arb_req), // N number of reqs
.data_i('{default: 1'b0}),
.gnt_o(packer_arb_gnt), // N number of gnts
.idx_o(), //NC
.valid_o(packer_arb_valid),
.data_o(), // NC
.ready_i(packer_arb_ready)
);
for (genvar i = 0; i < NumEndPoints; i=i+1) begin : gen_arb
assign packer_arb_req[i] = !packer_ep_rvalid[i] && edn_i[i].edn_req;
end
//--------------------------------------------
// csrng interface packer
//--------------------------------------------
prim_packer_fifo #(
.InW(CSGenBitsWidth),
.OutW(CSGenBitsWidth),
.ClearOnRead(1'b0)
) u_prim_packer_fifo_cs (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (packer_cs_clr),
.wvalid_i (packer_cs_push),
.wdata_i (packer_cs_wdata),
.wready_o (packer_cs_wready),
.rvalid_o (packer_cs_rvalid),
.rdata_o (packer_cs_rdata),
.rready_i (packer_cs_rready),
.depth_o ()
);
assign packer_cs_clr = !edn_enable_fo[CsrngPackerClr];
assign packer_cs_push = csrng_cmd_i.genbits_valid;
assign packer_cs_wdata = csrng_cmd_i.genbits_bus;
assign csrng_cmd_o.genbits_ready = packer_cs_wready;
assign packer_cs_rready = packer_arb_valid;
assign packer_arb_ready = packer_cs_rvalid;
assign csrng_fips_d =
!edn_enable_fo[CsrngFipsEn] ? 1'b0 :
(packer_cs_push && packer_cs_wready) ? csrng_cmd_i.genbits_fips :
csrng_fips_q;
//--------------------------------------------
// data path integrity check
// - a counter measure to software genbits bus tampering
// - checks to make sure repeated data sets off
// an alert for sw to handle
//--------------------------------------------
// SEC_CM: CS_RDATA.BUS.CONSISTENCY
// capture a copy of the entropy data
assign cs_rdata_capt_vld = (packer_cs_rvalid && packer_cs_rready);
assign cs_rdata_capt_d = cs_rdata_capt_vld ? packer_cs_rdata[63:0] : cs_rdata_capt_q;
assign cs_rdata_capt_vld_d =
!edn_enable_fo[CsrngDataVld] ? 1'b0 :
cs_rdata_capt_vld ? 1'b1 :
cs_rdata_capt_vld_q;
// continuous compare of the entropy data
assign edn_bus_cmp_alert = cs_rdata_capt_vld && cs_rdata_capt_vld_q &&
(cs_rdata_capt_q == packer_cs_rdata[63:0]);
prim_edge_detector #(
.Width(1),
.ResetValue(0),
.EnSync(0)
) u_prim_edge_detector_recov_alert (
.clk_i,
.rst_ni,
.d_i(edn_bus_cmp_alert),
.q_sync_o(),
.q_posedge_pulse_o(recov_alert_o),
.q_negedge_pulse_o()
);
assign hw2reg.recov_alert_sts.edn_bus_cmp_alert.de = edn_bus_cmp_alert;
assign hw2reg.recov_alert_sts.edn_bus_cmp_alert.d = edn_bus_cmp_alert;
//--------------------------------------------
// end point interface packers generation
//--------------------------------------------
for (genvar i = 0; i < NumEndPoints; i=i+1) begin : gen_ep_blk
prim_packer_fifo #(
.InW(CSGenBitsWidth),
.OutW(EndPointBusWidth),
.ClearOnRead(1'b0)
) u_prim_packer_fifo_ep (
.clk_i (clk_i),
.rst_ni (rst_ni),
.clr_i (packer_ep_clr[i]),
.wvalid_i (packer_ep_push[i]),
.wdata_i (packer_ep_wdata[i]),
.wready_o (packer_ep_wready[i]),
.rvalid_o (packer_ep_rvalid[i]),
.rdata_o (packer_ep_rdata[i]),
.rready_i (packer_ep_rready[i]),
.depth_o ()
);
assign packer_ep_push[i] = packer_arb_valid && packer_ep_wready[i] && packer_arb_gnt[i];
assign packer_ep_wdata[i] = packer_cs_rdata;
// fips indication
assign edn_fips_d[i] = packer_ep_clr[i] ? 1'b0 :
(packer_ep_push[i] && packer_ep_wready[i]) ? csrng_fips_q :
edn_fips_q[i];
assign edn_o[i].edn_fips = edn_fips_q[i];
// gate returned data
assign edn_o[i].edn_ack = packer_ep_ack[i];
assign edn_o[i].edn_bus = packer_ep_rdata[i];
// SEC_CM: ACK_SM.FSM.SPARSE
edn_ack_sm u_edn_ack_sm_ep (
.clk_i (clk_i),
.rst_ni (rst_ni),
.enable_i (edn_enable_fo[AckFsmEn]),
.req_i (edn_i[i].edn_req),
.ack_o (packer_ep_ack[i]),
.fifo_not_empty_i (packer_ep_rvalid[i]),
.fifo_pop_o (packer_ep_rready[i]),
.fifo_clr_o (packer_ep_clr[i]),
.local_escalate_i (fatal_loc_events),
.ack_sm_err_o (edn_ack_sm_err[i])
);
end
// state machine status
assign hw2reg.main_sm_state.de = 1'b1;
assign hw2reg.main_sm_state.d = edn_main_sm_state;
//--------------------------------------------
// unused signals
//--------------------------------------------
assign unused_err_code_test_bit = (|err_code_test_bit[19:3]) || (|err_code_test_bit[27:22]);
endmodule