| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | //// Simple hardware random number generator//module rng#(parameter  nclocks = 1,	// Asynchronous clocks  width = 32	// Output bus width  )   (    // System reset and clock    input		   rst_n,    input		   sys_clk,    input		   read_stb,    input		   latch_stb,    output		   ready,    output reg [width-1:0] q,     // Randomness inputs    input [nclocks-1:0]    clocks, // Random input synchronized to sys_clk    (* keep = 1 *) inout [2:0] rngio	// Unconnected pins with pullups    );   // Number of internal oscillators   localparam n_osc = 2;   wire [n_osc:1]	   osc;   wire [n_osc:1]	   osc_s;   //   // Latch control and enable logic   //   reg [n_osc:1]	   osc_q;   reg [n_osc:1]	   osc_e; // Edge detected   typedef enum logic [2:0] {	st_starting,		// Powering up oscillators	st_started,		// Oscillators running	st_strobed,		// Starting strobe received	st_latch,		// Ending strobe received, latch output data	st_ready,		// Output data available	st_stopped		// Data available, powered down due to idle   } state_t;   state_t state = st_starting;   // Number of ticks before shutting down   localparam shutdown_ticks_lg2 = 1;   reg [shutdown_ticks_lg2-1:0] shutdown_tmr;   assign ready   = (state == st_ready) | (state == st_stopped);   wire   running = (state != st_stopped);   wire [width-1:0] random_data;   always @(posedge sys_clk or negedge rst_n)     if (~rst_n)       begin	  state <= st_starting;	  osc_q <= 'b0;	  osc_e <= 'b0;       end     else       begin	  osc_q        <= ~osc_s;	  osc_e        <= 'b0;	  shutdown_tmr <= 'b0;	  case (state)	    st_starting: begin	       osc_e <= osc_e | (osc_s & osc_q);	       if (&osc_e)		 state <= st_started;	    end	    st_started: begin	       if (latch_stb)		 state <= st_strobed;	    end	    st_strobed: begin	       if (latch_stb)		 state <= st_latch;	    end	    st_latch: begin	       // Wait here if read_stb is still active from previous read	       if (~read_stb)		 begin		    q <= random_data;		    state <= st_ready;		 end	    end	    st_ready: begin	       shutdown_tmr <= shutdown_tmr + latch_stb;	       // If shutdown_tmr is nonzero, then we have had at least	       // one latch_stb already while waiting here, and so we	       // can use that data immediately.	       if (read_stb)		 state <= |shutdown_tmr ? st_latch :			  latch_stb ? st_strobed : st_started;	       else if (latch_stb & &shutdown_tmr)		 state <= st_stopped;	    end	    st_stopped: begin	       // Data is available, but haven't been consumed for	       // a long time, so we have shut down the ring oscillators.	       // When a read happens, start them up again.	       if (read_stb)		 state <= st_starting;	    end	  endcase // case (state)       end // else: !if(~rst_n)   //   // Internal oscillators: allow them to be stopped to save power   // if we have had multiple ticks with no data accesses.   //   // Internal on-chip oscillator   int_osc int_osc     (      .clkout ( osc[1] ),      .oscena ( running )      );   // Ring oscillator using the rngio pins   assign rngio[0] = ~rngio[2] & running;   assign rngio[1] = ~rngio[0] & running;   assign rngio[2] = ~rngio[1] & running;   assign osc[2] = rngio[0];   synchronizer #(.width(n_osc)) synchro     (      .rst_n ( 1'b1 ),      .clk ( sys_clk ),      .d ( osc ),      .q ( osc_s )      );   // 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;   wire			lsfr_input = ^{osc_s, clocks};   reg [lsfr_max:0]	lsfr;   always @(posedge sys_clk)     lsfr <= ({lsfr[lsfr_max-1:0], lsfr_input} ^	      {{(lsfr_max+1){lsfr[poly_width-1]}} & poly});   assign random_data = lsfr[width-1:0];endmodule // rng
 |