// // 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. The x^poly_width term in the polynomial // is implicit. localparam poly_width = 33; localparam [poly_width-1:0] poly = 33'h0_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_max+1){lsfr[poly_width-1]}} & poly}; assign q = lsfr[width-1:0]; endmodule // rng