// Filename: mersenne.v // Author: David Ljung Madison // See License: http://MarginalHacks.com/License // Version: 1.0 // Description: Verilog implementation of the Mersenne Twister, a great // random number generator // // Other implementations at: http://www.math.keio.ac.jp/~matumoto/emt.html // module mersenne; `define MERSENNE_N 624 `define MERSENNE_M 397 `define MERSENNE_MATRIX_A 32'h9908b0df /* constant vector a */ `define MERSENNE_UPPER_MASK 32'h80000000 /* most significant w-r bits */ `define MERSENNE_LOWER_MASK 32'h7fffffff /* least significant r bits */ /* Tempering parameters */ `define TEMPERING_MASK_B 32'h9d2c5680 `define TEMPERING_MASK_C 32'hefc60000 `define TEMPERING_SHIFT_U 11 `define TEMPERING_SHIFT_S 7 `define TEMPERING_SHIFT_T 15 `define TEMPERING_SHIFT_L 18 integer mt [0:`MERSENNE_N]; /* the array for the state vector */ integer mti; task srand; input [31:0] seed; begin // Setting initial seeds to mt[N] using the generator // Line 25 of Table 1 in [KNUTH 1981, The Art of Computer // Programming Vol. 2 (2nd Ed.), pp102] mt[0] = seed; for (mti=1; mti<`MERSENNE_N; mti=mti+1) mt[mti] = (69069 * mt[mti-1]); end endtask task rand; output [31:0] out; integer y; integer kk; begin if (|mti===1'bx || mti>=`MERSENNE_N) begin if (|mti===1'bx) srand(4357); // Default seed for (kk=0; kk<`MERSENNE_N-`MERSENNE_M; kk=kk+1) begin y = (mt[kk]&`MERSENNE_UPPER_MASK)|(mt[kk+1]&`MERSENNE_LOWER_MASK); mt[kk] = mt[kk+`MERSENNE_M] ^ (y >> 1) ^ (y&1 ? `MERSENNE_MATRIX_A : 0); end for (kk=kk; kk<`MERSENNE_N-1; kk=kk+1) begin y = (mt[kk]&`MERSENNE_UPPER_MASK)|(mt[kk+1]&`MERSENNE_LOWER_MASK); mt[kk] = mt[kk+(`MERSENNE_M-`MERSENNE_N)] ^ (y >> 1) ^ (y&1 ? `MERSENNE_MATRIX_A : 0); end y = (mt[`MERSENNE_N-1]&`MERSENNE_UPPER_MASK)|(mt[0]&`MERSENNE_LOWER_MASK); mt[`MERSENNE_N-1] = mt[`MERSENNE_M-1] ^ (y >> 1) ^ (y&1 ? `MERSENNE_MATRIX_A : 0); mti = 0; end y = mt[mti]; mti = mti + 1; y = y ^ (y >> `TEMPERING_SHIFT_U); y = y ^ ((y << `TEMPERING_SHIFT_S) & `TEMPERING_MASK_B); y = y ^ ((y << `TEMPERING_SHIFT_T) & `TEMPERING_MASK_C); y = y ^ (y >> `TEMPERING_SHIFT_L); out = y; end endtask endmodule module top; mersenne r1 (); mersenne r2 (); integer x; integer c; initial begin r1.srand(8833); for (c=0; c<8; c=c+1) begin r1.rand(x); $write("%x ",x); end $write("\n"); end endmodule