http://www.markharvey.info

Generating random values in VHDL testbenches

Sometimes it is necessary to use random values as input stimuli when simulating structures such as filters where the random value is used as input noise, or to simulate clock jitter where the random value would be used to modify the clock period.

The IEEE "math_real" VHDL package supplies a function called "UNIFORM" which returns a pseudo-random number (of type REAL) in the range 0 to 1.0.

The UNIFORM function has two seed values (of type POSITIVE) which are updated each time the function is called — these seed values can be initialised as required, otherwise they are initialised as 1 by default.

The following example shows how to generate a random 12bit vector:

LIBRARY ieee;
USE ieee.math_real.ALL;   -- for UNIFORM, TRUNC functions
USE ieee.numeric_std.ALL; -- for TO_UNSIGNED function
.
.
PROCESS
  VARIABLE seed1, seed2: positive;               -- Seed values for random generator
  VARIABLE rand: real;                           -- Random real-number value in range 0 to 1.0
  VARIABLE int_rand: integer;                    -- Random integer value in range 0..4095
  VARIABLE stim: std_logic_vector(11 DOWNTO 0);  -- Random 12-bit stimulus
BEGIN

    UNIFORM(seed1, seed2, rand);                                   -- generate random number
    int_rand := INTEGER(TRUNC(rand*4096.0));                       -- rescale to 0..4096, find integer part
    stim := std_logic_vector(to_unsigned(int_rand, stim'LENGTH));  -- convert to std_logic_vector
.
.



Listing 1: 12-bit random vector

It is also possible to create random time intervals by converting the REAL rnadom number to TIME type. In following listing, a random value is generated, then converted to a TIME type before being used to apply noise to a signal. Note that the UNIFORM function is called twice, the first time to create a random value (rand1) which will be used to define the width of the noise pulse, the second time to create a random value (rand2) which is used to define the interval between the noise pulses:

  PROCESS
    VARIABLE seed1, seed2: positive;    -- Seed values for random generator
    VARIABLE rand1 : real;              -- Random real-number value in range 0 to 1.0
    VARIABLE seed3, seed4: positive;    -- Seed values for random generator
    VARIABLE rand2 : real;              -- Random real-number value in range 0 to 1.0
    VARIABLE width: time;               -- noise pulse width
    VARIABLE interval: time;            -- noise interval
  BEGIN
     
   LOOP
     UNIFORM(seed1, seed2, rand1);
     UNIFORM(seed3, seed4, rand2);
     width := (rand1*0.00000001)*1 sec;
     interval := (rand2*0.0000001)*1 sec;
     
     WAIT FOR width;
     sNoise <= NOT(sNoise);
     WAIT FOR interval;
     sNoise <= NOT(sNoise);
   END LOOP;
   
  END PROCESS;
  
    
   -- mix noise signal onto clean digital input
   DIG_IN <= sDigInClean XOR sNoise;



Listing 2: Random time intervals