blob: 375fa354db11b77b3b5d650e401bc6cd043980a6 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//############################################################################
// *Name: rng
// *Module Description: Random (bit/s) Generator
//############################################################################
module rng #(
parameter int EntropyStreams = 4
) (
input clk_i, // Non-Jittery Clock (TLUL)
input rst_ni, // Non-Jittery Reset (TLUL)
input clk_ast_rng_i, // Jittery Clock (RNG)
input rst_ast_rng_ni, // Jittery Reset (RNG)
input rng_en_i, // RNG Enable
input rng_fips_i, // RNG FIPS Enable
input scan_mode_i, // Scan Mode
output logic [EntropyStreams-1:0] rng_b_o, // RNG Bus/Bits Output
output logic rng_val_o // RNG Bus/Bits Valid
);
///////////////////////////////////////
// RNG Bus using LFSR
///////////////////////////////////////
logic rst_n;
logic[32-1:0] lfsr_val;
assign rst_n = scan_mode_i ? rst_ni : rst_ni && rng_en_i;
always_ff @(posedge clk_i, negedge rst_n ) begin
if ( !rst_n ) begin
lfsr_val <= 32'h0000_0001;
end else if ( lfsr_val == {32{1'b1}} ) begin // Skip one problematic value
lfsr_val <= {{31{1'b1}}, 1'b0};
end else begin
lfsr_val[31:1] <= lfsr_val[30:0];
lfsr_val[0] <= !(lfsr_val[31] ^ lfsr_val[21] ^ lfsr_val[1] ^ lfsr_val[0]);
end
end
logic srate_rng_val;
logic [12-1:0] srate_cnt, srate_value;
logic [EntropyStreams-1:0] rng_b;
assign srate_value = 12'd120;
always_ff @( posedge clk_i, negedge rst_n ) begin
if ( !rst_n ) begin
srate_cnt <= 12'h000;
srate_rng_val <= 1'b0;
end else if ( srate_cnt == srate_value ) begin
srate_cnt <= 12'h000;
srate_rng_val <= 1'b1;
end else begin
srate_cnt <= srate_cnt + 1'b1;
srate_rng_val <= 1'b0;
end
end
always_ff @( posedge clk_i, negedge rst_n ) begin
if ( !rst_n ) begin
rng_b <= {EntropyStreams{1'b0}};
end else if ( srate_rng_val ) begin
rng_b <= lfsr_val[EntropyStreams-1:0];
end
end
////////////////////////////////////////
// Sychronize Bus & Valid to RNG Clock
////////////////////////////////////////
logic sync_rng_val;
prim_pulse_sync u_rng_val_pulse_sync (
// source clock domain
.clk_src_i ( clk_i ),
.rst_src_ni ( rst_n ),
.src_pulse_i ( srate_rng_val ),
// destination clock domain
.clk_dst_i ( clk_ast_rng_i ),
.rst_dst_ni ( rst_ast_rng_ni ),
.dst_pulse_o ( sync_rng_val )
);
always_ff @( posedge clk_ast_rng_i, negedge rst_ast_rng_ni ) begin
if (!rst_ast_rng_ni ) begin
rng_b_o <= {EntropyStreams{1'b0}};
rng_val_o <= 1'b0;
end else if ( sync_rng_val ) begin
rng_b_o <= rng_b[EntropyStreams-1:0];
rng_val_o <= 1'b1;
end else begin
rng_val_o <= 1'b0;
end
end
endmodule : rng