|HOME |ABOUT |ARTICLES |ACK |FEEDBACK |TOC |LINKS |BLOG |JOBS |


Tutorials



VERILOG CRV


Constrained Random Stimulus Generation In Verilog:



Verilog has system function $random, which can be used to generate random input vectors. With this approach,we can generate values which we wouldnt 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;
$display($time," read_write = %d ; data = %d ; address = %d;",read_write,data,address);
end
#10 $finish;
end


endmodule


RESULT:

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




$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 = %0d;",address);

endmodule

RESULT:

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




We have seen how to generate random numbers.But the numbers randge from - (2**32 -1) to 2 **32. Most of the time, the requirement is dont 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 meaning less. In verilog there are no constructs to constraint randomization. Following 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 = %0d",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 bitvector. 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 = %0d;add_2 = %0d;add_1 = %0d",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 = 4
add_3 = 1;add_2 = 2;add_1 = 4
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 = %0d",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 = %0d",add);
end
end
endmodule

RESULT:

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




All the random numbers generated above are 32 bit vectors, which is not always the same requirement. 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 to some number. For example, Ethernet packet is always in multiples of 8bits. Look at the following example. It generates a random number which is multiple of 3 and 5.

$random * 3 will give random numbers which are multiples of 3. But if the number after multiplication needs more than 32 bit to reprasent, then the results may be wrong.



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

initial
begin
repeat(5)
begin
num_1 =( $random / 3)*3;
num_2 =( $random / 5)*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 examples show that the random numbers are integers only. In verilog there is no special construct to generate a random real number.The following method shows generation of random real numbers.



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 interms of sign, exponential and mantissa, use $bitstoreal() as shown in example below. For positive numbers use sgn = 0 and for negative numbers use sgn = 1 .


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






Some times it is required to generate random numbers without repetition. The random numbers should be unique. For example,to generate 10 random numbers between 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 returned by $random system function should be deterministic, i.e when ever we run with simulator it should return values in same sequence. Otherwise the bug found today cant be found return. For this purpose it has one 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.



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 user is not giving explicitly seed. The following example shows that seed = 0 and implicit seed are having same sequence.It means that the imlicity 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 same series of values with 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. In the following example, when ever the seed is changed to 2, the sequence 8-1-0-5-0-8-6-7-11-6......... is followed. Check out in any tool you will see the same sequence.


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 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 table, then rest of the sequence has to follow sequence in table.

Table is as follows 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(32'hFFFF_FFFF). 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 chaining 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 zero 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 . It's interisting to know that some how the sequence is able to enter this chaining which is formed with seed=0 and there is no seed value 1 in this chaining and my simulation hanged. So aborted the simulation and partial results show that the initial seed = 1 enters the chaing 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 genrator 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 randomizes 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. Following 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(seed) } %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 = 973;num_21 = 1064;num_22 = 961;num_23 = 988;num_24 = 999;num_25 = 1015



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 index only. Try out rest of them and see that results is same for all the bits.



EXAMPLE:
module Tb();
integer num;
integer num_2,num_3,num_4,num_11,num_12,num_13;
initial
begin
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[2] == 0 )
num_2 = num_2 + 1;
if(num[3] == 0)
num_3 = num_3 + 1;
if(num[4] == 0)
num_4 = num_4 + 1;
if(num[11] == 0)
num_11 = num_11 + 1;
if(num[12] == 0)
num_12 = num_12 + 1;
if(num[13] == 0)
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 = 2975




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. Other wise distribution is distributed on all the variables as overall variables which mightnot be our requirement.. 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;
}


In Verilog 1995 standard every simulator has its own random number generation algorithm. But in Verilog 2001 a standard is 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 following example, both the statements_1 and statement_2 are scheduled to execute at same simulation time. The order of execution is not not known. Some simulators take statement_1 as the first statement to execute and some other statement_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 and a testbench without a racecondition on $random calls is not easy to build.

Look at the following 2 examples. I just changed the order of statements, the results are reversed.
@edes

EXAMPLE:new
module Tb();

initial
$display("staement 2 :::%d",$random);

initial
$display("staement 1 :::%d",$random);

endmodule


staement 2 ::: 303379748
staement 1 :::-1064739199


EXAMPLE:
module Tb();

initial
$display("staement 1 :::%d",$random);

initial
$display("staement 2 :::%d",$random);

endmodule


staement 1 ::: 303379748
staement 2 :::-1064739199

Index
Constrained Random Verification
Verilog Crv
Systemverilog Crv
Randomizing Objects
Random Variables
Randomization Methods
Checker
Constraint Block
Inline Constraint
Global Constraint
Constraint Mode
External Constraints
Randomization Controlability
Static Constraint
Constraint Expression
Variable Ordering
Constraint Solver Speed
Randcase
Randsequence
Random Stability
Array Randomization
Constraint Guards
Titbits

Report a Bug or Comment on This section - Your input is what keeps Testbench.in improving with time!





<< PREVIOUS PAGE

TOP

NEXT PAGE >>

copyright © 2007-2017 :: all rights reserved www.testbench.in::Disclaimer