blob: 87f6e0624f8f8645e356c335483a26cec48a6937 [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: entropy
// *Module Description: Entropy
//
//############################################################################
`timescale 1ns/1ps
module entropy #(
parameter int EntropyInWidth = 1,
parameter int EntropyRateWidth = 4
) (
input entropy_ack_i,
input [EntropyInWidth-1:0] entropy_i,
input [EntropyRateWidth-1:0] entropy_rate_i,
input clk_src_sys_jen_i, // System Source Clock Jitter Enable
input clk_ast_es_i,
input rst_ast_es_ni,
input clk_src_sys_i,
input rst_src_sys_ni,
input scan_mode_i,
output logic entropy_req_o
);
///////////////////////////////////
// Entropy & Jitter
///////////////////////////////////
// Entropy Enable
logic entropy_enable;
assign entropy_enable = rst_ast_es_ni && clk_src_sys_jen_i;
// Reset De-Assert syncronizer
logic sync1_rst_es_n, sync2_rst_es_n, rst_es_n;
always_ff @( posedge clk_ast_es_i, negedge entropy_enable ) begin
if ( !entropy_enable ) begin
sync1_rst_es_n <= 1'b0;
sync2_rst_es_n <= 1'b0;
end
else begin
sync1_rst_es_n <= 1'b1;
sync2_rst_es_n <= sync1_rst_es_n;
end
end
assign rst_es_n = scan_mode_i ? rst_ast_es_ni : sync2_rst_es_n;
// Entropy Rate
logic [(1<<EntropyRateWidth)-1:0] rate_cnt;
logic [32-1:0] entropy_rate;
logic read_entropy;
always_ff @( posedge clk_ast_es_i, negedge rst_es_n ) begin
if ( !rst_es_n ) rate_cnt <= {(1<<EntropyRateWidth){1'b0}};
else if ( read_entropy ) rate_cnt <= {(1<<EntropyRateWidth){1'b0}};
else rate_cnt <= rate_cnt + 1'b1;
end
assign entropy_rate = (1 << entropy_rate_i);
assign read_entropy = (rate_cnt == entropy_rate[(1 << EntropyRateWidth)-1:0]);
// FIFO RDP/WRP/Level
logic [6-1:0] fifo_cnt; // For 32 1-bit FIFO
logic [5-1:0] fifo_rdp, fifo_wrp; // FIFO read pointer & write pointer
logic [32-1:0] fifo_data; // 32 1-bi FIFOt
logic inc_fifo_cnt, dec_fifo_cnt;
assign inc_fifo_cnt = (fifo_cnt < 6'h20) && entropy_ack_i;
assign dec_fifo_cnt = (fifo_cnt != 6'h00) && read_entropy;
always_ff @( posedge clk_ast_es_i, negedge rst_es_n ) begin
if ( !rst_es_n ) begin
fifo_cnt <= 6'h00;
fifo_rdp <= 5'h00;
fifo_wrp <= 5'h00;
end
else if ( inc_fifo_cnt && dec_fifo_cnt ) begin
fifo_rdp <= fifo_rdp + 1'b1;
fifo_wrp <= fifo_wrp + 1'b1;
end
else if ( inc_fifo_cnt ) begin
fifo_cnt <= fifo_cnt + 1'b1;
fifo_wrp <= fifo_wrp + 1'b1;
end
else if ( dec_fifo_cnt ) begin
fifo_cnt <= fifo_cnt - 1'b1;
fifo_rdp <= fifo_rdp + 1'b1;
end
end
// Request
always_ff @( posedge clk_ast_es_i, negedge rst_es_n ) begin
if ( !rst_es_n )
entropy_req_o <= 1'b0;
else if ( fifo_cnt < 6'h10 )
entropy_req_o <= 1'b1; // Half
else if ( (fifo_cnt == 6'h1f) && inc_fifo_cnt && ~dec_fifo_cnt )
entropy_req_o <= 1'b0; // Full
end
// FIFO Write
always_ff @( posedge clk_ast_es_i, negedge rst_es_n ) begin
if ( !rst_es_n ) fifo_data[32-1:0] <= {32{1'b0}};
else if ( inc_fifo_cnt ) fifo_data[fifo_wrp] <= entropy_i[0];
end
// FIFO Read
wire fifo_entropy_out = fifo_data[fifo_rdp];
// Sync to SYS clock
logic lfsr_data_in;
logic sync1_lfsr_data_in, sync2_lfsr_data_in;
always_ff @( posedge clk_src_sys_i, negedge rst_src_sys_ni ) begin
if ( !rst_src_sys_ni ) begin
sync1_lfsr_data_in <= 1'b0;
sync2_lfsr_data_in <= 1'b0;
end
else begin
sync1_lfsr_data_in <= fifo_entropy_out;
sync2_lfsr_data_in <= sync1_lfsr_data_in;
end
end
assign lfsr_data_in = sync2_lfsr_data_in;
// prim_generic_flop_2sync #(
// .Width ( 1 )
// ) entropy_sync (
// .clk_i ( clk_src_sys_i ),
// .rst_ni ( rst_src_sys_ni ),
// .d_i ( fifo_entropy_out ),
// .q_o ( lfsr_data_in )
// );
// Jitter
// random 0-2000ps (upto +20% of SYS clock)
// jitter = sys_jen ? $urandom_range(2000, 0) : 0;
endmodule // of entropy