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


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[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] == 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; 


Index
Introduction
Linear Tb
File Io Tb
State Machine Based Tb
Task Based Tb
Self Checking Testbench
Verification Flow
Clock Generator
Simulation
Incremental Compilation
Store And Restore
Event Cycle Simulation
Time Scale And Precision
Stimulus Generation
System Function Random A Myth
Race Condition
Checker
Task And Function
Process Control
Disableing The Block
Watchdog
Compilation N Simulation Switchs
Debugging
About Code Coverage
Testing Stratigies
File Handling
Verilog Semaphore
Finding Testsenarious
Handling Testcase Files
Terimination
Error Injuction
Register Verification
Parameterised Macros
White Gray Black Box
Regression
Tips

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