<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

`include "prim_assert.sv"

/**
 * OTBN random number coordination
 *
 * This module implements the RND, RND_PREFETCH and URND CSRs/WSRs. The EDN (entropy distribution
 * network) provides the bits for random numbers. RND gives direct access to EDN bits. URND provides
 * bits from a PRNG that is seeded with bits from the EDN.
 */

////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE:                                                                                //
//                                   DO NOT USE THIS BLINDLY!                                     //
//                                                                                                //
// This is an initial prototype of the random number functionality in OTBN. Details are still     //
// under discussion and subject to change. It has not yet been verified this provides the         //
// necessary guarantees required for the various uses of random numbers in OTBN software.         //
////////////////////////////////////////////////////////////////////////////////////////////////////

module otbn_rnd import otbn_pkg::*;
#(
  parameter urnd_prng_seed_t       RndCnstUrndPrngSeed      = RndCnstUrndPrngSeedDefault
) (
  input logic clk_i,
  input logic rst_ni,

  input  logic            rnd_wipe_i,
  input  logic            rnd_req_i,
  input  logic            rnd_prefetch_req_i,
  output logic            rnd_valid_o,
  output logic [WLEN-1:0] rnd_data_o,
  output logic            rnd_rep_err_o,
  output logic            rnd_fips_err_o,

  // Request URND PRNG reseed from the EDN
  input  logic            urnd_reseed_req_i,
  // Acknowledge URND PRNG reseed from the EDN
  output logic            urnd_reseed_ack_o,
  // When asserted PRNG state advances. It is permissible to advance the state whilst
  // reseeding.
  input  logic            urnd_advance_i,
  // URND data from PRNG
  output logic [WLEN-1:0] urnd_data_o,
  // URND lockup state detected
  output logic            urnd_all_zero_o,

  // Entropy distribution network (EDN)
  output logic                    edn_rnd_req_o,
  input  logic                    edn_rnd_ack_i,
  input  logic [EdnDataWidth-1:0] edn_rnd_data_i,
  input  logic                    edn_rnd_fips_i,
  input  logic                    edn_rnd_err_i,

  output logic                    edn_urnd_req_o,
  input  logic                    edn_urnd_ack_i,
  input  logic [EdnDataWidth-1:0] edn_urnd_data_i
);

  logic rnd_valid_q, rnd_valid_d;
  logic [WLEN-1:0] rnd_data_q, rnd_data_d;
  logic rnd_fips_d, rnd_fips_q;
  logic rnd_err_d, rnd_err_q;
  logic rnd_data_en;
  logic rnd_req_complete;
  logic edn_rnd_req_complete;
  logic edn_rnd_req_start;

  logic edn_rnd_req_q, edn_rnd_req_d;

  logic rnd_prefetch_pending_d, rnd_prefetch_pending_q;
  logic rnd_req_queued_d, rnd_req_queued_q;
  logic edn_rnd_data_ignore_d, edn_rnd_data_ignore_q;

  ////////////////////////
  // RND Implementation //
  ////////////////////////

  assign rnd_req_complete = rnd_req_i & rnd_valid_o;
  assign edn_rnd_req_complete = edn_rnd_req_o & edn_rnd_ack_i;

  assign rnd_data_en = edn_rnd_req_complete & ~edn_rnd_data_ignore_q;

  // RND becomes valid when EDN request completes and provides new bits. Valid is cleared when OTBN
  // starts a new run (rnd_wipe_i) or when OTBN reads RND (rnd_req_complete).
  assign rnd_valid_d =
      rnd_wipe_i || rnd_req_complete                 ? 1'b0 :
      edn_rnd_req_complete && !edn_rnd_data_ignore_q ? 1'b1 : rnd_valid_q;
  assign rnd_data_d = edn_rnd_data_i;
  assign rnd_fips_d = edn_rnd_fips_i;
  assign rnd_err_d = edn_rnd_err_i;

  // Start an EDN request when there is a prefetch or an attempt at reading RND when RND data is
  // not available. Signalling `edn_rnd_req_start` whilst there is an outstanding request is
  // harmless. However, a prefetch may still be outstanding from the last OTBN run which may have
  // used a different configuration for EDN, CSRNG or the entropy source. At the start of a new
  // OTBN run, RND data is thus always invalidated and outstanding prefetches are marked such that
  // the RND data returned for the first prefetch is thrown away. When throwing away data, we need
  // to keep requesting RND data from EDN if another request got queued in the meantime.
  assign edn_rnd_req_start = (rnd_prefetch_req_i | rnd_req_i | rnd_req_queued_q) & ~rnd_valid_q;

  // Is there a prefetch pending?
  assign rnd_prefetch_pending_d = rnd_prefetch_req_i       ? 1'b1 :
                                  rnd_req_i || rnd_valid_q ? 1'b0 : rnd_prefetch_pending_q;

  // When seeing a wipe with an outstanding prefetch, we are going to ignore the RND data obtained
  // for the first prefetch. Any RND data returned clears the ignore status.
  assign edn_rnd_data_ignore_d =
      rnd_wipe_i && rnd_prefetch_pending_q ? 1'b1 :
      edn_rnd_req_complete                 ? 1'b0 : edn_rnd_data_ignore_q;

  // Don't combine new RND requests with outstanding prefetches for which we are going to ingore
  // the returned data. Cleared upon starting the request without having the ignore bit set.
  assign rnd_req_queued_d =
      edn_rnd_data_ignore_q ? edn_rnd_req_start :
      edn_rnd_req_start     ? 1'b0              : rnd_req_queued_q;

  // Assert `edn_rnd_req_o` when a request is started and keep it asserted until the request is
  // done.
  assign edn_rnd_req_d = (edn_rnd_req_q | edn_rnd_req_start) & ~edn_rnd_req_complete;

  assign edn_rnd_req_o = edn_rnd_req_q;

  always_ff @(posedge clk_i) begin
    if (rnd_data_en) begin
      rnd_data_q <= rnd_data_d;
      rnd_fips_q <= rnd_fips_d;
      rnd_err_q  <= rnd_err_d;
    end
  end

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rnd_valid_q            <= 1'b0;
      rnd_prefetch_pending_q <= 1'b0;
      rnd_req_queued_q       <= 1'b0;
      edn_rnd_req_q          <= 1'b0;
      edn_rnd_data_ignore_q  <= 1'b0;
    end else begin
      rnd_valid_q            <= rnd_valid_d;
      rnd_prefetch_pending_q <= rnd_prefetch_pending_d;
      rnd_req_queued_q       <= rnd_req_queued_d;
      edn_rnd_req_q          <= edn_rnd_req_d;
      edn_rnd_data_ignore_q  <= edn_rnd_data_ignore_d;
    end
  end

  assign rnd_valid_o = rnd_valid_q;
  assign rnd_data_o  = rnd_data_q;

  // SEC_CM: RND.BUS.CONSISTENCY
  // SEC_CM: RND.RNG.DIGEST
  // Detect and forward RND error conditions.
  assign rnd_rep_err_o = rnd_req_complete & rnd_err_q;
  assign rnd_fips_err_o = rnd_req_complete & ~rnd_fips_q;

  /////////////////////////
  // PRNG Implementation //
  /////////////////////////<commit_msg>[otbn,rtl] Get rid of rnd_prefetch_pending_q<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

`include "prim_assert.sv"

/**
 * OTBN random number coordination
 *
 * This module implements the RND, RND_PREFETCH and URND CSRs/WSRs. The EDN (entropy distribution
 * network) provides the bits for random numbers. RND gives direct access to EDN bits. URND provides
 * bits from a PRNG that is seeded with bits from the EDN.
 */

////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTANT NOTE:                                                                                //
//                                   DO NOT USE THIS BLINDLY!                                     //
//                                                                                                //
// This is an initial prototype of the random number functionality in OTBN. Details are still     //
// under discussion and subject to change. It has not yet been verified this provides the         //
// necessary guarantees required for the various uses of random numbers in OTBN software.         //
////////////////////////////////////////////////////////////////////////////////////////////////////

module otbn_rnd import otbn_pkg::*;
#(
  parameter urnd_prng_seed_t       RndCnstUrndPrngSeed      = RndCnstUrndPrngSeedDefault
) (
  input logic clk_i,
  input logic rst_ni,

  input  logic            rnd_wipe_i,
  input  logic            rnd_req_i,
  input  logic            rnd_prefetch_req_i,
  output logic            rnd_valid_o,
  output logic [WLEN-1:0] rnd_data_o,
  output logic            rnd_rep_err_o,
  output logic            rnd_fips_err_o,

  // Request URND PRNG reseed from the EDN
  input  logic            urnd_reseed_req_i,
  // Acknowledge URND PRNG reseed from the EDN
  output logic            urnd_reseed_ack_o,
  // When asserted PRNG state advances. It is permissible to advance the state whilst
  // reseeding.
  input  logic            urnd_advance_i,
  // URND data from PRNG
  output logic [WLEN-1:0] urnd_data_o,
  // URND lockup state detected
  output logic            urnd_all_zero_o,

  // Entropy distribution network (EDN)
  output logic                    edn_rnd_req_o,
  input  logic                    edn_rnd_ack_i,
  input  logic [EdnDataWidth-1:0] edn_rnd_data_i,
  input  logic                    edn_rnd_fips_i,
  input  logic                    edn_rnd_err_i,

  output logic                    edn_urnd_req_o,
  input  logic                    edn_urnd_ack_i,
  input  logic [EdnDataWidth-1:0] edn_urnd_data_i
);

  logic rnd_valid_q, rnd_valid_d;
  logic [WLEN-1:0] rnd_data_q, rnd_data_d;
  logic rnd_fips_d, rnd_fips_q;
  logic rnd_err_d, rnd_err_q;
  logic rnd_data_en;
  logic rnd_req_complete;
  logic edn_rnd_req_complete;
  logic edn_rnd_req_start;

  logic edn_rnd_req_q, edn_rnd_req_d;

  logic rnd_req_queued_d, rnd_req_queued_q;
  logic edn_rnd_data_ignore_d, edn_rnd_data_ignore_q;

  ////////////////////////
  // RND Implementation //
  ////////////////////////

  assign rnd_req_complete = rnd_req_i & rnd_valid_o;
  assign edn_rnd_req_complete = edn_rnd_req_o & edn_rnd_ack_i;

  assign rnd_data_en = edn_rnd_req_complete & ~edn_rnd_data_ignore_q;

  // RND becomes valid when EDN request completes and provides new bits. Valid is cleared when OTBN
  // starts a new run (rnd_wipe_i) or when OTBN reads RND (rnd_req_complete).
  assign rnd_valid_d =
      rnd_wipe_i || rnd_req_complete                 ? 1'b0 :
      edn_rnd_req_complete && !edn_rnd_data_ignore_q ? 1'b1 : rnd_valid_q;
  assign rnd_data_d = edn_rnd_data_i;
  assign rnd_fips_d = edn_rnd_fips_i;
  assign rnd_err_d = edn_rnd_err_i;

  // Start an EDN request when there is a prefetch or an attempt at reading RND when RND data is
  // not available. Signalling `edn_rnd_req_start` whilst there is an outstanding request is
  // harmless. However, a prefetch may still be outstanding from the last OTBN run which may have
  // used a different configuration for EDN, CSRNG or the entropy source. At the start of a new
  // OTBN run, RND data is thus always invalidated and outstanding prefetches are marked such that
  // the RND data returned for the first prefetch is thrown away. When throwing away data, we need
  // to keep requesting RND data from EDN if another request got queued in the meantime.
  assign edn_rnd_req_start = (rnd_prefetch_req_i | rnd_req_i | rnd_req_queued_q) & ~rnd_valid_q;

  // When seeing a wipe with an outstanding request (which must have been a prefetch), we are going
  // to ignore the RND data that comes back from that request. Any RND data returned clears the
  // ignore status.
  assign edn_rnd_data_ignore_d =
      rnd_wipe_i && edn_rnd_req_q ? 1'b1 :
      edn_rnd_req_complete        ? 1'b0 : edn_rnd_data_ignore_q;

  // Don't combine new RND requests with outstanding prefetches for which we are going to ingore
  // the returned data. Cleared upon starting the request without having the ignore bit set.
  assign rnd_req_queued_d =
      edn_rnd_data_ignore_q ? edn_rnd_req_start :
      edn_rnd_req_start     ? 1'b0              : rnd_req_queued_q;

  // Assert `edn_rnd_req_o` when a request is started and keep it asserted until the request is
  // done.
  assign edn_rnd_req_d = (edn_rnd_req_q | edn_rnd_req_start) & ~edn_rnd_req_complete;

  assign edn_rnd_req_o = edn_rnd_req_q;

  always_ff @(posedge clk_i) begin
    if (rnd_data_en) begin
      rnd_data_q <= rnd_data_d;
      rnd_fips_q <= rnd_fips_d;
      rnd_err_q  <= rnd_err_d;
    end
  end

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      rnd_valid_q            <= 1'b0;
      rnd_req_queued_q       <= 1'b0;
      edn_rnd_req_q          <= 1'b0;
      edn_rnd_data_ignore_q  <= 1'b0;
    end else begin
      rnd_valid_q            <= rnd_valid_d;
      rnd_req_queued_q       <= rnd_req_queued_d;
      edn_rnd_req_q          <= edn_rnd_req_d;
      edn_rnd_data_ignore_q  <= edn_rnd_data_ignore_d;
    end
  end

  assign rnd_valid_o = rnd_valid_q;
  assign rnd_data_o  = rnd_data_q;

  // SEC_CM: RND.BUS.CONSISTENCY
  // SEC_CM: RND.RNG.DIGEST
  // Detect and forward RND error conditions.
  assign rnd_rep_err_o = rnd_req_complete & rnd_err_q;
  assign rnd_fips_err_o = rnd_req_complete & ~rnd_fips_q;

  /////////////////////////
  // PRNG Implementation //
  /////////////////////////
{'fraction_non_alphanumeric': 0.10037481259370315, 'fraction_numerical': 0.005247376311844078, 'mean_word_length': 2.1272855133614628, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 19, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4792675', 'n_tokens_mistral': 4683, 'n_tokens_neox': 4533, 'n_words': 1243}