123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- //
- // Simple hardware random number generator
- //
- module rng
- #(parameter
- nclocks = 1, // Asynchronous clocks
- width = 32 // Output bus width
- )
- (
- // System clock
- input sys_clk,
- // Output data
- output [width-1:0] q,
- // Randomness inputs
- input [nclocks-1:0] clocks, // Asynchronous clocks
- inout [2:0] rngio // Unconnected pins with pullups
- );
- wire int_clock; // Internal oscillator clock
- // Internal on-chip oscillator
- int_osc int_osc
- (
- .clkout ( int_clock ),
- .oscena ( 1'b1 )
- );
- // De facto RC oscillator using the rngio pins
- assign rngio[0] = rngio[2] ? 1'b0 : 1'bz;
- assign rngio[1] = rngio[0] ? 1'b0 : 1'bz;
- assign rngio[2] = rngio[1] ? 1'b0 : 1'bz;
- wire [nclocks+1:0] sclocks;
- synchronizer #(.width(nclocks+2)) synchro
- (
- .rst_n ( 1'b1 ),
- .clk ( sys_clk ),
- .d ( { clocks, rngio[0], int_clk } ),
- .q ( sclocks )
- );
- // LFSR randomness accumulator
- // See http://users.ece.cmu.edu/~koopman/crc/crc36.html for
- // choice of polynomial.
- localparam poly_width = 33;
- localparam [poly_width:0] poly = 34'h2_0000_009d;
- localparam lsfr_max = width > poly_width ? width-1 : poly_width-1;
- reg [lsfr_max:0] lsfr;
- always @(posedge sys_clk)
- lsfr <= {lsfr[lsfr_max-1:0], ^sclocks} ^
- (lsfr[lsfr_max-1] ? poly : {poly_width{1'b0}});
- assign q = lsfr[lsfr_max:lsfr_max-width+1];
- endmodule // rng
|