| // Copyright lowRISC contributors. |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| // SPDX-License-Identifier: Apache-2.0 |
| // |
| // Description: csrng state data base module |
| // |
| // This is the container for accessing the current |
| // working state for a given drbg instance. |
| |
| `include "prim_assert.sv" |
| |
| module csrng_state_db import csrng_pkg::*; #( |
| parameter int NApps = 4, |
| parameter int StateId = 4, |
| parameter int BlkLen = 128, |
| parameter int KeyLen = 256, |
| parameter int CtrLen = 32, |
| parameter int Cmd = 3 |
| ) ( |
| input logic clk_i, |
| input logic rst_ni, |
| |
| // read interface |
| input logic state_db_enable_i, |
| input logic [StateId-1:0] state_db_rd_inst_id_i, |
| output logic [KeyLen-1:0] state_db_rd_key_o, |
| output logic [BlkLen-1:0] state_db_rd_v_o, |
| output logic [CtrLen-1:0] state_db_rd_res_ctr_o, |
| output logic state_db_rd_inst_st_o, |
| output logic state_db_rd_fips_o, |
| // write interface |
| input logic state_db_wr_req_i, |
| output logic state_db_wr_req_rdy_o, |
| input logic [StateId-1:0] state_db_wr_inst_id_i, |
| input logic state_db_wr_fips_i, |
| input logic [Cmd-1:0] state_db_wr_ccmd_i, |
| input logic [KeyLen-1:0] state_db_wr_key_i, |
| input logic [BlkLen-1:0] state_db_wr_v_i, |
| input logic [CtrLen-1:0] state_db_wr_res_ctr_i, |
| input logic state_db_wr_sts_i, |
| // status interface |
| input logic state_db_is_dump_en_i, |
| input logic state_db_reg_rd_sel_i, |
| input logic state_db_reg_rd_id_pulse_i, |
| input logic [StateId-1:0] state_db_reg_rd_id_i, |
| output logic [31:0] state_db_reg_rd_val_o, |
| output logic state_db_sts_ack_o, |
| output logic state_db_sts_sts_o, |
| output logic [StateId-1:0] state_db_sts_id_o |
| ); |
| |
| localparam int InternalStateWidth = 2+KeyLen+BlkLen+CtrLen; |
| localparam int RegInternalStateWidth = 30+InternalStateWidth; |
| localparam int RegW = 32; |
| localparam int StateWidth = 1+1+KeyLen+BlkLen+CtrLen+StateId+1; |
| |
| logic [StateId-1:0] state_db_id; |
| logic [KeyLen-1:0] state_db_key; |
| logic [BlkLen-1:0] state_db_v; |
| logic [CtrLen-1:0] state_db_rc; |
| logic state_db_fips; |
| logic state_db_inst_st; |
| logic state_db_sts; |
| logic state_db_write; |
| logic instance_status; |
| logic [NApps-1:0] int_st_out_sel; |
| logic [NApps-1:0] int_st_dump_sel; |
| logic [InternalStateWidth-1:0] internal_states_out[NApps]; |
| logic [InternalStateWidth-1:0] internal_states_dump[NApps]; |
| logic [RegInternalStateWidth-1:0] internal_state_diag; |
| logic reg_rd_ptr_inc; |
| |
| // flops |
| logic state_db_sts_ack_q, state_db_sts_ack_d; |
| logic state_db_sts_sts_q, state_db_sts_sts_d; |
| logic [StateId-1:0] state_db_sts_id_q, state_db_sts_id_d; |
| logic [StateId-1:0] reg_rd_ptr_q, reg_rd_ptr_d; |
| logic [StateId-1:0] int_st_dump_id_q, int_st_dump_id_d; |
| |
| always_ff @(posedge clk_i or negedge rst_ni) |
| if (!rst_ni) begin |
| state_db_sts_ack_q <= '0; |
| state_db_sts_sts_q <= '0; |
| state_db_sts_id_q <= '0; |
| reg_rd_ptr_q <= '0; |
| int_st_dump_id_q <= '0; |
| end else begin |
| state_db_sts_ack_q <= state_db_sts_ack_d; |
| state_db_sts_sts_q <= state_db_sts_sts_d; |
| state_db_sts_id_q <= state_db_sts_id_d; |
| reg_rd_ptr_q <= reg_rd_ptr_d; |
| int_st_dump_id_q <= int_st_dump_id_d; |
| end |
| |
| // flops - no reset |
| logic [InternalStateWidth-1:0] internal_states_q[NApps], internal_states_d[NApps]; |
| logic [InternalStateWidth-1:0] internal_state_pl_q, internal_state_pl_d; |
| logic [InternalStateWidth-1:0] internal_state_pl_dump_q, internal_state_pl_dump_d; |
| |
| |
| // no reset on state |
| always_ff @(posedge clk_i) |
| begin |
| internal_states_q <= internal_states_d; |
| internal_state_pl_q <= internal_state_pl_d; |
| internal_state_pl_dump_q <= internal_state_pl_dump_d; |
| end |
| |
| |
| //-------------------------------------------- |
| // internal state read logic |
| //-------------------------------------------- |
| for (genvar rd = 0; rd < NApps; rd = rd+1) begin : gen_state_rd |
| assign int_st_out_sel[rd] = (state_db_rd_inst_id_i == rd); |
| assign int_st_dump_sel[rd] = (int_st_dump_id_q == rd); |
| assign internal_states_out[rd] = int_st_out_sel[rd] ? internal_states_q[rd] : '0; |
| assign internal_states_dump[rd] = int_st_dump_sel[rd] ? internal_states_q[rd] : '0; |
| end |
| |
| // since only one of the internal states is active at a time, a |
| // logical "or" is made of all of the buses into one |
| always_comb begin |
| internal_state_pl_d = '0; |
| internal_state_pl_dump_d = '0; |
| for (int i = 0; i < NApps; i = i+1) begin |
| internal_state_pl_d |= internal_states_out[i]; |
| internal_state_pl_dump_d |= internal_states_dump[i]; |
| end |
| end |
| |
| assign {state_db_rd_fips_o,state_db_rd_inst_st_o, |
| state_db_rd_key_o,state_db_rd_v_o, |
| state_db_rd_res_ctr_o} = internal_state_pl_q; |
| |
| |
| // using a copy of the internal state pipeline version for better timing |
| assign internal_state_diag = {30'b0,internal_state_pl_dump_q}; |
| |
| |
| // Register access of internal state |
| assign state_db_reg_rd_val_o = |
| (reg_rd_ptr_q == 4'h0) ? internal_state_diag[RegW-1:0] : |
| (reg_rd_ptr_q == 4'h1) ? internal_state_diag[2*RegW-1:RegW] : |
| (reg_rd_ptr_q == 4'h2) ? internal_state_diag[3*RegW-1:2*RegW] : |
| (reg_rd_ptr_q == 4'h3) ? internal_state_diag[4*RegW-1:3*RegW] : |
| (reg_rd_ptr_q == 4'h4) ? internal_state_diag[5*RegW-1:4*RegW] : |
| (reg_rd_ptr_q == 4'h5) ? internal_state_diag[6*RegW-1:5*RegW] : |
| (reg_rd_ptr_q == 4'h6) ? internal_state_diag[7*RegW-1:6*RegW] : |
| (reg_rd_ptr_q == 4'h7) ? internal_state_diag[8*RegW-1:7*RegW] : |
| (reg_rd_ptr_q == 4'h8) ? internal_state_diag[9*RegW-1:8*RegW] : |
| (reg_rd_ptr_q == 4'h9) ? internal_state_diag[10*RegW-1:9*RegW] : |
| (reg_rd_ptr_q == 4'ha) ? internal_state_diag[11*RegW-1:10*RegW] : |
| (reg_rd_ptr_q == 4'hb) ? internal_state_diag[12*RegW-1:11*RegW] : |
| (reg_rd_ptr_q == 4'hc) ? internal_state_diag[13*RegW-1:12*RegW] : |
| (reg_rd_ptr_q == 4'hd) ? internal_state_diag[14*RegW-1:13*RegW] : |
| '0; |
| |
| // selects 32b fields from the internal state to be read out for diagnostics |
| assign reg_rd_ptr_inc = state_db_reg_rd_sel_i; |
| |
| assign reg_rd_ptr_d = |
| (!state_db_enable_i) ? 4'hf : |
| (!state_db_is_dump_en_i) ? 4'hf : |
| (reg_rd_ptr_q == 4'he) ? '0 : |
| state_db_reg_rd_id_pulse_i ? '0 : |
| reg_rd_ptr_inc ? (reg_rd_ptr_q+1) : |
| reg_rd_ptr_q; |
| |
| |
| assign int_st_dump_id_d = |
| (!state_db_enable_i) ? '0 : |
| state_db_reg_rd_id_pulse_i ? state_db_reg_rd_id_i : |
| int_st_dump_id_q; |
| |
| //-------------------------------------------- |
| // write state logic |
| //-------------------------------------------- |
| |
| for (genvar wr = 0; wr < NApps; wr = wr+1) begin : gen_state_wr |
| |
| assign internal_states_d[wr] = !state_db_enable_i ? '0 : // better timing |
| (state_db_write && (state_db_id == wr)) ? |
| {state_db_fips,state_db_inst_st,state_db_key, |
| state_db_v,state_db_rc} : internal_states_q[wr]; |
| end : gen_state_wr |
| |
| |
| assign {state_db_fips,state_db_inst_st, |
| state_db_key, |
| state_db_v,state_db_rc, |
| state_db_id,state_db_sts} = {StateWidth{state_db_enable_i}} & |
| {state_db_wr_fips_i,instance_status, |
| state_db_wr_key_i, |
| state_db_wr_v_i,state_db_wr_res_ctr_i, |
| state_db_wr_inst_id_i,state_db_wr_sts_i}; |
| |
| assign instance_status = |
| (state_db_wr_ccmd_i == INS) || |
| (state_db_wr_ccmd_i == RES) || |
| (state_db_wr_ccmd_i == GENU) || |
| (state_db_wr_ccmd_i == UPD); |
| |
| |
| assign state_db_write = state_db_enable_i && state_db_wr_req_i; |
| |
| assign state_db_sts_ack_d = |
| state_db_write; |
| |
| assign state_db_sts_sts_d = |
| state_db_sts; |
| |
| assign state_db_sts_id_d = |
| state_db_id; |
| |
| assign state_db_sts_ack_o = state_db_sts_ack_q; |
| assign state_db_sts_sts_o = state_db_sts_sts_q; |
| assign state_db_sts_id_o = state_db_sts_id_q; |
| assign state_db_wr_req_rdy_o = 1'b1; |
| |
| |
| // Assertions |
| `ASSERT_KNOWN(IntStOutSelOneHot_A, $onehot(int_st_out_sel)) |
| |
| endmodule |