Tutorials SYSTEM FUNCTION RANDOM A MYTH

Verilog has system function \$random ,which can be used to generate random input vectors. With this approach, we can generate values which we wouldn't have got, if listed manually. In this topic I would like to discuss what natural things happening behind \$random and how we use it in different manners.

EXAMPLE:
module Tb_mem();
reg clock;
reg read_write;
reg [31:0] data;
reg [31:0] address;

initial
begin
clock = 0;
forever
#10 clock = ~clock;
end

initial
begin
repeat(5)@(negedge clock)
begin read_write = \$random ; data = \$random;address = \$random; end
\$finish;
end

initial
\$monitor(\$time,"read_write = %d ; data = %d ; address = %d;",read_write,data,address);

endmodule

RESULT:

20read_write = 0 ; data = 3230228097 ; address = 2223298057;
40read_write = 1 ; data = 112818957 ; address = 1189058957;
60read_write = 1 ; data = 2302104082 ; address = 15983361;
80read_write = 1 ; data = 992211318 ; address = 512609597;

\$random() system function returns a new 32-bit random number each time it is called. The random number is a signed integer; it can be positive or negative. The following example demonstrates random generation of signed numbers.

EXAMPLE:
module Tb();
integer address;

initial
begin
repeat(5)
#1 address = \$random;
end

initial
\$monitor("address = %d;",address);

endmodule

RESULT:

address = 303379748;
address = -1064739199;
address = -2071669239;
address = -1309649309;
address = 112818957;

We have seen how to generate random numbers. But the numbers range from - (2**32 -1) to 2 **32. Most of the time, the requirement don't need this range. For example, take a memory. The address starts from 0 to some 1k or 1m.Generating a random address which DUT is not supporting is meaningless. In verilog there are no constructs to constraint randomization. Fallowing example demonstrated how to generate random number between 0 to 10.Using % operation, the remainder of any number is always between 0 to 10.

EXAMPLE:
module Tb();
integer add_1;

initial
begin
repeat(5)
begin
#1;
add_1 = \$random % 10;
end
end

initial
\$monitor("add_1 = %d",add_1);

endmodule

RESULT:

add_1 = 8;
add_1 = 4294967287;
add_1 = 4294967295;
add_1 = 9;
add_1 = 9;

OOPS!...... The results are not what is expected. The reason is \$random generates negative numbers also. The following example demonstrates proper way of generating a random number between 0 to 10. Concatenation operator returns only bit vector. Bit vectors are unsigned, so the results are correct as we expected. Verilog also has \$unsigned systemtask to convert signed numbers to signed number. This can also be used to meet the requirements. The following example shows the usage of concatenation operator and \$unsigned.

EXAMPLE:
module Tb();
integer add_2;
reg [31:0] add_1;
integer add_3;

initial
begin
repeat(5)
begin
#1;
add_1 = \$random % 10;
add_2 = {\$random} %10 ;
add_3 = \$unsigned(\$random) %10 ;
end
end

initial
\$monitor("add_3 = %d;add_2 = %d;add_1 = %d",add_3,add_2,add_1);

endmodule

RESULT:

add_3 = 7;add_2 = 7;add_1 = 8
add_3 = 7;add_2 = 7;add_1 = 4294967287
add_3 = 1;add_2 = 2;add_1 = 4294967295
add_3 = 7;add_2 = 8;add_1 = 9
add_3 = 9;add_2 = 2;add_1 = 9

The above example shows the generation of numbers from 0 to N.Some specification require the range to start from non Zero number. MIN + {\$random} % (MAX - MIN ) will generate random numbers between MIN and MAX.

EXAMPLE:
module Tb();
integer add;

initial
begin
repeat(5)
begin
#1;
add = 40 + {\$random} % (50 - 40) ;
\$display("add = %d",add);
end
end
endmodule

RESULT:

add = 48
add = 47
add = 47
add = 47
add = 47

Now how to generate a random number between two ranges? The number should be between MIN1 and MAX1 or MIN2 and MAX2.The following example show how to generate this specification.

EXAMPLE:
module Tb();
integer add;

initial
begin
repeat(5)
begin
#1;
if(\$random % 2)
add = 40 + {\$random} % (50 - 40) ;
else
add = 90 + {\$random} % (100 - 90) ;
\$display("add = %d",add);
end
end
endmodule

RESULT:

add = 97
add = 47
add = 47
add = 42
add = 49

All the random number generates above generate numbers of 32 vector. Not always the requirements are 32 bit .For example, to generate a 5 bit and 45 bit vector random number, the following method can be used.

EXAMPLE:
module Tb();
reg [4:0] add_1;
reg [44:0] add_2;

initial
begin
repeat(5)
begin
add_1 = \$random ;
add_2 = {\$random,\$random};
\$display("add_1 = %b,add_2 = %b ",add_1,add_2);
end
end
endmodule

RESULTS:

add_1 = 00100,add_2 = 111101000000110000100100001001101011000001001
add_1 = 00011,add_2 = 110110000110101000110110111111001100110001101
add_1 = 00101,add_2 = 100100001001000000000111100111110001100000001
add_1 = 01101,add_2 = 100010111011000011110100011011100110100111101
add_1 = 01101,add_2 = 101111000110001111100111111011110100111111001

Some protocols require a random number which is multiple some number. For example, Ethernet packet is always in multiples of 8bits,and PCIExpress packets are multiples of 4byts .Look at the following example. It generates a random number which is multiple of 3 and 5.

EXAMPLE:
module Tb();
integer num_1,num_2,tmp;

initial
begin
repeat(5)
begin
#1;
tmp = {\$random} / 3;
num_1 = (tmp) * 3;
tmp = {\$random} / 3;
num_2 = (tmp) * 5;
\$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule

RESULT:

num_1 = 303379746,num_2 = -1064739195
num_1 = -2071669239,num_2 = -1309649305
num_1 = 112818957,num_2 = 1189058955
num_1 = -1295874969,num_2 = -1992863210
num_1 = 15983361,num_2 = 114806025

All the above example show that the random numbers are integers only. In verilog there is not special construct to generate a random real number. The following method shows the generation of random real number.

EXAMPLE:
module Tb();

integer num_1,num_2,num_3;
real r_num;

initial
begin
repeat(5)
begin
#1;
num_1 = \$random;
num_2 = \$random;
num_3 = \$random;
r_num = num_1 + ((10)**(-(num_2)))*(num_3);
\$display("r_num = %e",r_num);
end
end
endmodule

RESULT:

r_num = -2.071669e+03
r_num = 2641.189059e+013
r_num = 976361.598336e+01
r_num = 57645.126096e+02
r_num = 24589.097015e+0

To generate random real number , system function \$bitstoreal can also be used.

EXAMPLE:
module Tb();

real r_num;

initial
begin
repeat(5)
begin
#1;
r_num = \$bitstoreal({\$random,\$random});
\$display("r_num = %e",r_num);
end
end
endmodule

RESULTS:

r_num = 1.466745e-221
r_num = -6.841798e-287
r_num = 2.874848e-276
r_num = -3.516622e-64
r_num = 4.531144e-304

If you want more control over randomizing real numbers in terms of sign, exponential and mantissa, use \$bitstoreal() as shown in example below. For positive numbers, use sgn = 0 etc.

EXAMPLE:
module Tb();
reg sgn;
reg [10:0] exp;
reg [51:0] man;
real r_num;

initial
begin
repeat(5)
begin
sgn = \$random;
exp = \$random;
man = \$random;
r_num = \$bitstoreal({sgn,exp,man});
\$display("r_num = %e",r_num);
end
end
endmodule
RESULTS:

r_num = 3.649952e+193
r_num = -1.414950e-73
r_num = -3.910319e-149
r_num = -4.280878e-196
r_num = -4.327791e+273

Sometimes it is required to generate random numbers without repetition. The random numbers should be unique. For example, to generate 10 random numbers b/w 0 to 9 without repetition, the following logic can be used.

EXAMPLE:
module Tb();
integer num,i,j,index;
integer arr[9:0];
reg ind[9:0];
reg got;

initial
begin
index=0;
for(i=0;i<10;i=i+1)
begin
arr[i] = i;
ind[i] = 1;
end

for(j = 0;j<10 ;j=j+1)
begin
got = 0;
while(got == 0)
begin
index = { \$random() } % 10;
if(ind[index] == 1)
begin
ind[index] = 0;
got = 1;
num = arr[index];
end
end
\$write("| num=%2d |",num);
end

end
endmodule

RESULT:

| num= 8 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 || num= 6 || num= 4 || num= 0 || num= 3 |

Random number system function has a argument called seed. The seed parameter controls the numbers that \$random returns such that different seeds generate different random streams. The seed parameter shall be either a reg, an integer, or a time variable. The seed value should be assigned to this variable prior to calling \$random. For each system function, the seed parameter is an in-out parameter; that is, a value is passed to the function
and a different value is returned.

EXAMPLE:
module Tb();
integer num,seed,i,j;

initial
begin
for(j = 0;j<4 ;j=j+1)
begin
seed = j;
\$display(" seed is %d",seed);
for(i = 0;i < 10; i=i+1)
begin
num = { \$random(seed) } % 10;
\$write("| num=%2d |",num);
end
\$display(" ");
end
end
endmodule

RESULT:

seed is 0
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |
seed is 1
| num= 8 || num= 8 || num= 2 || num= 2 || num= 6 || num= 3 || num= 8 || num= 5 || num= 5 || num= 5 |
seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |
seed is 3
| num= 8 || num= 2 || num= 2 || num= 3 || num= 8 || num= 6 || num= 1 || num= 4 || num= 3 || num= 9 |

The \$random function has its own implicit variable as seed when the used is not giving explicitly giving seed. The following example shows that seed = 0 and implicit seed are having same sequence. It means that the implicitly taken seed is also 0.

EXAMPLE:
module Tb();
integer num,seed,i,j;

initial
begin
seed = 0;

for(j = 0;j<2 ;j=j+1)
begin
if(j ==0)
\$display(" seed is %d",seed);
else
\$display(" No seed is given ");

for(i = 0;i < 10; i=i+1)
begin
if( j == 0)
num = { \$random(seed) } % 10;
else
num = { \$random() } % 10;
\$write("| num=%2d |",num);
end
\$display(" ");
end
end
endmodule

RESULT:

seed is 0
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |
No seed is given
| num= 8 || num= 7 || num= 7 || num= 7 || num= 7 || num= 7 || num= 5 || num= 2 || num= 1 || num= 9 |

The system functions shall always return the same value given the same seed. This facilitates debugging by making the operation of the system repeatable. The argument for the seed parameter should be an integer variable that is initialized by the user and only updated by the system function. This ensures the desired distribution is achieved.

EXAMPLE:
module Tb();
integer num,seed,i,j;

initial
begin
for(j = 0;j<4 ;j=j+1)
begin
seed = 2;
\$display(" seed is %d",seed);
for(i = 0;i < 10; i=i+1)
begin
num = { \$random(seed) } % 10;
\$write("| num=%2d |",num);
end
\$display(" ");
end
end
endmodule

RESULT:

seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |
seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |
seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |
seed is 2
| num= 8 || num= 1 || num= 0 || num= 5 || num= 0 || num= 8 || num= 6 || num= 7 || num= 1 || num= 6 |

Seed is inout port. Random number system function returns a random number and also returns a random number to seed inout argument also. The results of the following example demonstrates how the seed value is getting changed.

EXAMPLE:
module Tb();
integer num,seed,i,j;

initial
begin
seed = 0;
for(j = 0;j<10 ;j=j+1)
begin
num = { \$random(seed) } % 10;
\$write("| num=%2d |",num);
\$display(" seed is %d ",seed);
end
end
endmodule

RESULT:

| num= 8 | seed is -1844104698
| num= 7 | seed is 1082744015
| num= 7 | seed is 75814084
| num= 7 | seed is 837833973
| num= 7 | seed is -2034665166
| num= 7 | seed is -958425333
| num= 5 | seed is 851608272
| num= 2 | seed is 154620049
| num= 1 | seed is -2131500770
| num= 9 | seed is -2032678137

From the above results we can make a table of seed values and return values of \$random. If a seed is taken from the table, then rest of the sequence has to follow sequence in table.

Table is as falows for initial seed 0;

| num= 8 | seed is -1844104698
| num= 7 | seed is 1082744015
| num= 7 | seed is 75814084
| num= 7 | seed is 837833973
| num= 7 | seed is -2034665166
| num= 7 | seed is -958425333
| num= 5 | seed is 851608272
| num= 2 | seed is 154620049
| num= 1 | seed is -2131500770
| num= 9 | seed is -2032678137
.
.
.
.
.
table goes on........

In the following example, the seed is 837833973, which is the 4 th seed from the above table.

EXAMPLE:
module Tb();
integer num,seed,i,j;

initial
begin
seed = 837833973;
for(j = 0;j<10 ;j=j+1)
begin
num = { \$random(seed) } % 10;
\$write("| num=%2d |",num);
\$display(" seed is %d ",seed);
end
end
endmodule

RESULTS:

| num= 7 | seed is -2034665166
| num= 7 | seed is -958425333
| num= 5 | seed is 851608272
| num= 2 | seed is 154620049
| num= 1 | seed is -2131500770
| num= 9 | seed is -2032678137
| num= 8 | seed is -1155272804
| num= 7 | seed is -1634874387
| num= 9 | seed is -153856566
| num= 2 | seed is -970066749

From the above example we can come to conclusion that \$random is not giving a random number. It is randomizing seed and returning corresponding number for that seed.

Total possible seed values are 4294967295. Is it possible for \$random to generate all the seeds? . Lets say ,if the seed gets repeated after 10 iterations, then after the 10 iterations, same values are repeated. So \$random is circulating inside a chain of 10 numbers.

The following example demonstrates how \$random misses many seeds. I tried to display the seeds between 0 to 20 in the chain formed by initial seed of 0. Results show that total possible seeds are 4294967295 , and number of seeds possible in seed chain are 4030768279 , so we are missing some seeds. Look at the seeds between 0 to 20. Seed == 1 is missing.

EXAMPLE:

module Tb();
integer num,seed,j;
reg [0:31] i;

initial
begin
i = 0;
seed = 1;
while (seed != 0)
begin
if(i == 0)
seed = 0;
i = i + 1;
num = \$random(seed);
if(seed < 20 && seed > 0)
\$display(" seed is %d after values %d ",seed,i);
end
\$display(" seed is one after this number of random numbers %0d total numbers available are %d",i,{32'hffff_ffff});
end
endmodule

RESULTS:

seed is 10 after values 93137101
seed is 17 after values 307298440
seed is 2 after values 410139893
seed is 12 after values 483530075
seed is 19 after values 592243262
seed is 3 after values 720224974
seed is 11 after values 1342230278
seed is 15 after values 2032553666
seed is 7 after values 2266624778
seed is 13 after values 2362534380
seed is 5 after values 2512466932
seed is 9 after values 2575033104
seed is 16 after values 2988686279
seed is 4 after values 3173376451
seed is 6 after values 3483433473
seed is 8 after values 3547878575
seed is 14 after values 3663208793
seed is 18 after values 3930700709
seed is zero after this number of random numbers 4030768279 total numbers available are 4294967295

Now I tried to simulate with seed== 1 . Its interesting to know that some how the sequence is able to enter this chain which is formed with seed==0 and there is no seed value 1 in this chain and my simulation hanged. So aborted the simulation and parter results show that the initial seed = 1 with enter the chain formed by seed 0.

EXAMPLE:
module Tb();
integer num,seed,j;
reg [0:31] i;

initial
begin
i = 0;
seed = 0;
while (seed != 1)
begin
if(i == 0)
seed = 1;
i = i + 1;
num = \$random(seed);
if(seed < 20 && seed > 0)
\$display(" seed is %d after values %d ",seed,i);
end
\$display(" seed is one after this number of random numbers %0d total numbers available are %d",i,{32'hffff_ffff});
end
endmodule

RESULTS:

seed is 10 after values 357336117
seed is 17 after values 571497456
seed is 2 after values 674338909
seed is 12 after values 747729091
seed is 19 after values 856442278
seed is 3 after values 984423990
seed is 11 after values 1606429294
seed is 15 after values 2296752682
seed is 7 after values 2530823794
seed is 13 after values 2626733396
seed is 5 after values 2776665948
seed is 9 after values 2839232120
seed is 16 after values 3252885295
seed is 4 after values 3437575467
seed is 6 after values 3747632489
seed is 8 after values 3812077591
seed is 14 after values 3927407809
seed is 18 after values 4194899725
seed is 10 after values 357336117
seed is 17 after values 571497456
seed is 2 after values 674338909
seed is 12 after values 747729091
seed is 19 after values 856442278
seed is 3 after values 984423990

Verilog also has other system functions to generate random numbers. Each of these functions returns a pseudo-random number whose characteristics are described by the function name.
Following are the Verilog random number generator system functions:

\$random
\$dist_chi_square
\$dist_erlang
\$dist_exponential
\$dist_normal
\$dist_poisson
\$dist_t
\$dist_uniform

All parameters to the system functions are integer values. For the exponential , Poisson , chi-square , t , and erlang functions, the parameters mean, degree of freedom, and k_stage must be greater than 0 .

\$dist_uniform(seed, min, max) is similar to min + {\$random(seed)}%(max-min+1),the difference is that in \$dist_uniform,the distribution is uniform. \$dist_uniform returns a number between min and max. In the \$dist_uniform function, the start and end parameters are integer inputs that bound the values returned. The start value should be smaller than the end value.

The mean parameter, used by \$dist_normal, \$dist_exponential, \$dist_poisson, and \$dist_erlang, is an integer input that causes the average value returned by the function to approach the value specified. The standard deviation parameter used with the \$dist_normal function is an integer input that helps determine the shape of the density function. Larger numbers for standard deviation spread the returned values over a wider range.

The degree of freedom parameter used with the \$dist_chi_square and \$dist_t functions is an integer input that helps determine the shape of the density function. Larger numbers spread the returned values over a wider range.

EXAMPLE:
module Tb();
integer num_1,num_2,seed;

initial
begin
seed = 10;
repeat(5)
begin
#1;
num_1 = \$dist_uniform(seed,20,25);
num_2 = \$dist_uniform(seed,50,55);
\$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule

RESULTS:

num_1 = 20,num_2 = 50
num_1 = 23,num_2 = 55
num_1 = 22,num_2 = 54
num_1 = 25,num_2 = 51
num_1 = 23,num_2 = 55

As I discussed \$random changes its seed , Lets see whether \$dist_uniform is also doing the same.

EXAMPLE:

module Tb();
integer num_1,num_2,seedd,seedr;

initial
begin
seedd = 10;
seedr = 10;
repeat(5)
begin
#1;
num_1 = \$dist_uniform(seedd,20,25);
num_2 = 20 + ({\$random(seedr)} % 6);
\$display("num_1 = %d,num_2 = %d,seedd = %d seedr = %d",num_1,num_2,seedd,seedr);
end
end
endmodule
RESULTS:

num_1 = 20,num_2 = 22,seedd = 690691 seedr = 690691
num_1 = 20,num_2 = 20,seedd = 460696424 seedr = 460696424
num_1 = 23,num_2 = 22,seedd = -1571386807 seedr = -1571386807
num_1 = 25,num_2 = 21,seedd = -291802762 seedr = -291802762
num_1 = 22,num_2 = 23,seedd = 1756551551 seedr = 1756551551

Look at the results... Its interesting to note that \$random and \$dist_uniform have same seed sequence flow also.

As I mentioned ,\$dist_uniform(seed, min, max) is similar to min + {\$random(seed)}%(max-min+1). "similar" means they have some common functionality. \$dist_uniform is having uniform distribution, \$random for that range, is also uniformly distributed. Fallowing example ,demonstrates that \$dist_uniform and \$random are uniformly distributed.

EXAMPLE:
module Tb();
integer num,seed;
integer num_20,num_21,num_22,num_23,num_24,num_25;

initial
begin
seed = 10;
num_20 = 0;num_21 = 0;num_22 = 0;num_23 = 0;num_24 = 0;num_25 =0;

repeat(6000)
begin

num = \$dist_uniform(seed,20,25);
if(num == 20 )
num_20 = num_20 + 1;
if(num == 21)
num_21 = num_21 + 1;
if(num == 22)
num_22 = num_22 + 1;
if(num == 23)
num_23 = num_23 + 1;
if(num == 24)
num_24 = num_24 + 1;
if(num == 25)
num_25 = num_25 + 1;

end
\$display("num_20 = %0d;num_21 = %0d;num_22 = %0d;num_23 = %0d;num_24 = %0d;num_25 = %0d",num_20,num_21,num_22,num_23,num_24,num_25);
end
endmodule

RESULTS:

num_20 = 1014;num_21 = 983;num_22 = 946;num_23 = 1023;num_24 = 1014;num_25 = 1020

EXAMPLE:
module Tb();
integer num;
integer num_20,num_21,num_22,num_23,num_24,num_25;

initial
begin
seed = 10;
num_20 = 0;num_21 = 0;num_22 = 0;num_23 = 0;num_24 = 0;num_25 =0;

repeat(6000)
begin

num = 20 +( {\$random() } %6 );
if(num == 20 )
num_20 = num_20 + 1;
if(num == 21)
num_21 = num_21 + 1;
if(num == 22)
num_22 = num_22 + 1;
if(num == 23)
num_23 = num_23 + 1;
if(num == 24)
num_24 = num_24 + 1;
if(num == 25)
num_25 = num_25 + 1;

end
\$display("num_20 = %0d;num_21 = %0d;num_22 = %0d;num_23 = %0d;num_24 = %0d;num_25 = %0d",num_20,num_21,num_22,num_23,num_24,num_25);
end
endmodule
RESULTS:

num_20 = 996;num_21 = 999;num_22 = 959;num_23 = 996;num_24 = 1002;num_25 = 1048

As I mentioned ,\$dist_uniform(seed, min, max) is similar to min + {\$random(seed)}%(max-min+1). "similar" means they have some difference. The difference is that they generate different sequence.

EXAMPLE:
module Tb();
integer num_1,num_2,seedd,seedr;

initial
begin
seedd = 10;
seedr = 10;
repeat(5)
begin
#1;
num_1 = \$dist_uniform(seedd,20,25);
num_2 = 20 + ({\$random(seedr)} % 6);
\$display("num_1 = %d,num_2 = %d",num_1,num_2);
end
end
endmodule
RESULTS:

num_1 = 20,num_2 = 22
num_1 = 20,num_2 = 20
num_1 = 23,num_2 = 22
num_1 = 25,num_2 = 21
num_1 = 22,num_2 = 23

Till now what we have seen is \$random has uniform distribution over integer values. It means that distribution should be uniform across all the bits in 32 bit vector also. The following example shows that bits positions 2,3,4,11,12,13 have equal probability of getting 0. For demonstration I showed some indexes only. Try out rest of them and see that results is same for all the bis.

EXAMPLE:
module Tb();
integer num;
integer num_2,num_3,num_4,num_11,num_12,num_13;

initial
begin
seed = 10;
num_2 = 0;num_3 = 0;num_4 = 0;num_11 = 0;num_12 = 0;num_13 =0;

repeat(6000)
begin

num = \$random();
if(num == 0 )
num_2 = num_2 + 1;
if(num == 0)
num_3 = num_3 + 1;
if(num == 0)
num_4 = num_4 + 1;
if(num == 0)
num_11 = num_11 + 1;
if(num == 0)
num_12 = num_12 + 1;
if(num == 1)
num_13 = num_13 + 1;

end
\$display("num_2 = %0d;num_3 = %0d;num_4 = %0d;num_11 = %0d;num_12 = %0d;num_13 = %0d",num_2,num_3,num_4,num_11,num_12,num_13);
end
endmodule

RESULTS:

num_2 = 3012;num_3 = 2964;num_4 = 3065;num_11 = 3001;num_12 = 2964;num_13 = 3025

The distribution is uniform for system function \$random. Suppose if the requirement is to generate random numbers for more than one variable, and all the variables should have uniform distribution, then use different seeds for each variable. Otherwise distribution is distributed on all the variables as overall. But for lower bits, the distribution is same as shown in example.

EXAMPLE:
module Tb();
integer seed;
reg [1:0] var_1,var_2,var3,var4;
integer num_2,num_3,num_1,num_0;
integer cou_2,cou_3,cou_1,cou_0;

initial
begin
seed = 10;
num_2 = 0;num_3= 0;num_1= 0;num_0= 0;
cou_2= 0;cou_3= 0;cou_1= 0;cou_0= 0;

repeat(40000)
begin

var_1 = \$random();
var3 = \$random();
var4 = \$random();
var_2 = \$random();
if(var_1 == 0 )
num_0 = num_0 + 1;
if(var_1 == 1 )
num_1 = num_1 + 1;
if(var_1 == 2 )
num_2 = num_2 + 1;
if(var_1 == 3 )
num_3 = num_3 + 1;

if(var_2 == 0 )
cou_0 = cou_0 + 1;
if(var_2 == 1 )
cou_1 = cou_1 + 1;
if(var_2 == 2 )
cou_2 = cou_2 + 1;
if(var_2 == 3 )
cou_3 = cou_3 + 1;
end
\$display("num_2 = %0d;num_3= %0d;num_1= %0d;num_0= %0d;",num_2,num_3,num_1,num_0);
\$display("cou_2= %0d;cou_3= %0d;cou_1= %0d;cou_0= %0d;",cou_2,cou_3,cou_1,cou_0);
end
endmodule

RESULTS:

num_2 = 9984;num_3= 10059;num_1= 10002;num_0= 9955;
cou_2= 10060;cou_3= 9934;cou_1= 10072;cou_0= 9934;

Use system time as seed, so the same TB simulated at different times have different random sequences and there is more probability of finding bugs. The following is c code useful in PLI to get system time in to verilog.

#include <stdio.h>
#include <time.h>
char *get_time_string(int mode24);
int get_systime() {
time_t seconds;
seconds = time (NULL);
return seconds;
}

Verilog 1995, every simulator has its own random number generation algorithm. Verilog 2001 , The standard made that every simulator has to follow same algorithm. So the same random number sequence can seen on different simulators for same seed.

Don't expect that the same sequence is generated on all the simulators. They are only following same algorithm. The reason is, race condition. Look at the following example, both the statements num_1 and num_2 are scheduled to execute at same simulation time. The order of execution is not known. Some simulators take num_1 as the first statement to execute and some other num_2 .If the TB is built without any race condition to \$random function calls, then the same random sequence can be generated on different simulators.

EXAMPLE:
initial
# 10 num_1 = \$random;

initial
#10 num_2 = \$random;

 << PREVIOUS PAGE TOP NEXT PAGE >> copyright © 2007-2017 :: all rights reserved www.testbench.in::Disclaimer