rng.sv 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. //
  2. // Simple hardware random number generator
  3. //
  4. module rng
  5. #(parameter
  6. nclocks = 1, // Asynchronous clocks
  7. width = 32 // Output bus width
  8. )
  9. (
  10. // System clock
  11. input sys_clk,
  12. // Output data
  13. output [width-1:0] q,
  14. // Randomness inputs
  15. input [nclocks-1:0] clocks, // Asynchronous clocks
  16. inout [2:0] rngio // Unconnected pins with pullups
  17. );
  18. wire int_clock; // Internal oscillator clock
  19. // Internal on-chip oscillator
  20. int_osc int_osc
  21. (
  22. .clkout ( int_clock ),
  23. .oscena ( 1'b1 )
  24. );
  25. // De facto RC oscillator using the rngio pins
  26. assign rngio[0] = rngio[2] ? 1'b0 : 1'bz;
  27. assign rngio[1] = rngio[0] ? 1'b0 : 1'bz;
  28. assign rngio[2] = rngio[1] ? 1'b0 : 1'bz;
  29. wire [nclocks+1:0] sclocks;
  30. synchronizer #(.width(nclocks+2)) synchro
  31. (
  32. .rst_n ( 1'b1 ),
  33. .clk ( sys_clk ),
  34. .d ( { clocks, rngio[0], int_clk } ),
  35. .q ( sclocks )
  36. );
  37. // LFSR randomness accumulator
  38. // See http://users.ece.cmu.edu/~koopman/crc/crc36.html for
  39. // choice of polynomial.
  40. localparam poly_width = 33;
  41. localparam [poly_width:0] poly = 34'h2_0000_009d;
  42. localparam lsfr_max = width > poly_width ? width-1 : poly_width-1;
  43. reg [lsfr_max:0] lsfr;
  44. always @(posedge sys_clk)
  45. lsfr <= {lsfr[lsfr_max-1:0], ^sclocks} ^
  46. (lsfr[lsfr_max-1] ? poly : {poly_width{1'b0}});
  47. assign q = lsfr[lsfr_max:lsfr_max-width+1];
  48. endmodule // rng