/* =============================================================== (C) 2005 Robert Finch All rights reserved. rob@birdcomputer.ca rand.v Random number generator. This source code is free for use and modification for non-commercial or evaluation purposes, provided this copyright statement and disclaimer remains present in the file. If you do modify the code, please state the origin and note that you have modified the code. NO WARRANTY. THIS Work, IS PROVIDEDED "AS IS" WITH NO WARRANTIES OF ANY KIND, WHETHER EXPRESS OR IMPLIED. The user must assume the entire risk of using the Work. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES WHATSOEVER RELATING TO THE USE OF THIS WORK, OR YOUR RELATIONSHIP WITH THE AUTHOR. IN ADDITION, IN NO EVENT DOES THE AUTHOR AUTHORIZE YOU TO USE THE WORK IN APPLICATIONS OR SYSTEMS WHERE THE WORK'S FAILURE TO PERFORM CAN REASONABLY BE EXPECTED TO RESULT IN A SIGNIFICANT PHYSICAL INJURY, OR IN LOSS OF LIFE. ANY SUCH USE BY YOU IS ENTIRELY AT YOUR OWN RISK, AND YOU AGREE TO HOLD THE AUTHOR AND CONTRIBUTORS HARMLESS FROM ANY CLAIMS OR LOSSES RELATING TO SUCH UNAUTHORIZED USE. This little peripheral uses a 52 bit LFSR to generate random numbers. Only the lower 32 bits of the LFSR are seedable allowing 2^32 different start values; this also prevents a lockup value from being written to the LFSR. The random number shouldn't be read more often than every 32 clock cycles to prevent the appearance of interrelated values. (The values shift over one bit every clock cycle so the same bits are present for 32 clock cycles). However if you just need X bits, the register can be read every X clock cycles. Use: To read, write a zero into the command register then read back the value from the value registers. Note: a new value will appear in the value register only after the command register is written. If performing partial word writes (eg eight or sixteen bit updates), the generator should be stopped first, then restarted after all bytes have been written. This can be done by writing to the command register. To stop the LFSR write a one to the command register To seed the generator, write a value to the value register. Reg Name Description 0 VAL read/write byte addressable via byte selects 1 CMD write bit 31 - 1 = stop LFSR, 0 = free run LFSR writing to the command register causes a snapshot of the LFSR to be taken read bit 31 = stop status, 1=stopped, 0=running [30: 0] = LFSR value (same as reg #0) +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |WISHBONE Datasheet |WISHBONE SoC Architecture Specification, Revision B.3 | |Description: Specifications: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |General Description: random number generator +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported Cycles: SLAVE,READ/WRITE | SLAVE,BLOCK READ/WRITE | SLAVE,RMW +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Data port, size: 32 bit |Data port, granularity: 32 bit |Data port, maximum operand size: 32 bit |Data transfer ordering: Undefined |Data transfer sequencing: Undefined +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Clock frequency constraints: none +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Supported signal list and Signal Name WISHBONE equiv. |cross reference to equivalent ack_o ACK_O |WISHBONE signals adr_i ADR_I() | clk_i CLK_I | dat_i(31:0) DAT_I() | dat_o(31:0) DAT_O() | cyc_i CYC_I | stb_i STB_I | we_i WE_I | +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |Special requirements: +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 63 LUTs / 49 slices / 243 MHz =============================================================== */ module rand( input rst_i, // reset input clk_i, // system clock input cyc_i, // cycle valid input stb_i, // circuit select (chip select) output ack_o, // transfer acknowledge input we_i, // write registers input adr_i, // register address input [31:0] dat_i, // data input output reg [31:0] dat_o, // data output output vol_o ); reg [51:0] lfsr; reg [31:0] hold; reg stop; assign vol_o = cyc_i & stb_i; assign ack_o = cyc_i & stb_i; always @(posedge clk_i) if (rst_i) begin lfsr <= 0; stop <= 0; end else if (ack_o & we_i) begin case (adr_i) 1'd0: begin lfsr[31:0] <= dat_i; lfsr[51:32] <= 20'b0; end 1'd1: begin stop <= dat_i[0]; hold <= lfsr[31:0]; end endcase end else if (!stop) lfsr <= {lfsr[50:0],~(lfsr[51]^lfsr[48])}; always @(adr_i,hold,stop) begin dat_o[31:1] = hold[30:0]; dat_o[0] = adr_i ? stop : hold[31]; end endmodule