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:

  1. library ieee;
  2.  use ieee.math_real.all;    -- for uniform & trunc functions
  3.  use ieee.numeric_std.all;  -- for to_unsigned function
  4. .
  5. .
  6. process
  7.   variable seed1, seed2: positive;  -- seed values for random generator
  8.   variable rand: real;              -- random real-number value in range 0 to 1.0
  9.   variable int_rand: integer;       -- random integer value in range 0..4095
  10.   variable stim: std_logic_vector(11 downto 0);  -- random 12-bit stimulus
  11. begin
  12.     uniform(seed1, seed2, rand);              -- generate random number
  13.     -- rescale to 0..4096, find integer part
  14.     int_rand := integer(trunc(rand*4096.0));
  15.     -- convert to std_logic_vector
  16.     stim := std_logic_vector(to_unsigned(int_rand, stim'length));
  17.     .
  18.     .

It is also possible to create random time intervals by converting the REAL random 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:

  1. process
  2.   variable seed1, seed2: positive;    -- seed values for random generator
  3.   variable rand1 : real;              -- random real-number value, range 0 - 1.0
  4.   variable seed3, seed4: positive;    -- seed values for random generator
  5.   variable rand2 : real;              -- random real-number value, range 0 - 1.0
  6.   variable width: time;               -- noise pulse width
  7.   variable interval: time;            -- noise interval
  8. begin
  9.   loop
  10.     uniform(seed1, seed2, rand1);
  11.     uniform(seed3, seed4, rand2);
  12.     width := (rand1*0.00000001)*1 sec;
  13.     interval := (rand2*0.0000001)*1 sec;
  15.     wait for width;
  16.     noise_sig <= not(noise_sig);
  17.     wait for interval;
  18.     noise_sig <= not(noise_sig);
  19.   end loop;
  20. end process;
  21. -- mix noise signal onto clean digital input
  22. dig_in <= sdiginclean xor noise_sig;