Contact me for VHDL projects or assignments

Friday, March 26, 2010

Random Number Generator in VHDL

     In some designs you may need a Random Number Generator for generating random numbers.In C and other high level languages you have library functions for this kind of functions.In VHDL this is achieved by designing a pseudo random sequence generator (PRSG) of suitable length. The PRSG I have coded, will look like this:

 
     The sequence generated by PRSG is not theoretically  random,but for most practical applications the sequence can be considered as random.Because the period of the sequence is (2^n - 1).Where n is the number of shift registers used in the design.For 32 bit design the period is 4294967295.This is large enough for most of the practical applications.

   The module is written in a generic way.That means the value of 'n' can be specified at the time of compilation.
Below is the code:
 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity random is
    generic ( width : integer :=  32 );
port (
      clk : in std_logic;
      random_num : out std_logic_vector (width-1 downto 0)   --output vector           
    );
end random;

architecture Behavioral of random is
begin
process(clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
variable temp : std_logic := '0';
begin
if(rising_edge(clk)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
end if;
random_num <= rand_temp;
end process;

     The test bench for the code is given below:

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY testbench IS
END testbench;

ARCHITECTURE behavior OF testbench IS
   --Input and Output definitions.
   signal clk : std_logic := '0';
   signal random_num : std_logic_vector(3 downto 0);
   -- Clock period definitions
   constant clk_period : time := 1 ns;
BEGIN
        -- Instantiate the Unit Under Test (UUT)
   uut: entity work.random generic map (width => 4) PORT MAP (
          clk => clk,
          random_num => random_num
        );
   -- Clock process definitions
   clk_process :process
   begin
                clk <= '0';
                wait for clk_period/2;
                clk <= '1';
                wait for clk_period/2;
   end process;

END;

The simulated waveform is shown below.

The code is synthesizable.The RTL schematic of the design is given below:
   The above test bench program passes the value '4' to the main code in  a generic manner so  that the output generated by the code is 4 bit in size.For more information about usage of Generics in VHDL,you can see this article.You can change the size of the output as you want by editing the following lines:
 --change the value shown in RED colours.It should be (width -1).
              signal random_num : std_logic_vector(3 downto 0);  
 --change the value shown in RED colours.It should be equal to 'width' of the output vector.
              uut: entity work.random generic map (width => 4) PORT MAP

10 comments:

  1. thanx for writing such a good post,, this is one of the best material i have found on this subject,

    ReplyDelete
  2. thank you very much much, this helped me a lot.

    ReplyDelete
  3. This post is unfortunantly wrong. The "taps", or xor'd values are not arbitrary, but rather carefully selected. If expressed as a polynomial, the tap locations would form a monic, irreducible polynomial.
    this is very obvious if you try to make a 31 element sequence. You will end up with a 21 element sequence instead.

    why? because the polynomial x^5 + x^4 + 1 is not irreducible. It can be factored as (x^2 + x + 1)(x^3 + x + 1), where coefficients are in GF2.

    with an FPGA, you can even see that this does NOT work with some of the longer sequence generators, as the sequence won't be nearly long enough, and will repeat more frequently than expected.

    you should take the tap values from some of the other sites on google. Keep in mind that there are actually a large number of irreducible polynomials, but not every polynomial is irreducible. what this means is that an arbitrary selection of taps may result in shorter sequences.


    for test purposes, I prefer polynomials that have only a few taps, and where the lowest tap is relatively high. this allows for a simple to code multi-bit shift.

    ReplyDelete
  4. @Chris: Thanks a lot.I got your point.
    I checked the code with 32 bit width, and the seq seems to repeat after 2^21 clock cycles.
    After checking with other articles on PRNG I will soon upload a new program which takes care of the "taps".

    ReplyDelete
  5. Have you fixed the random program?

    ReplyDelete
  6. thank you very much for the post, but I wonder if you correct the mistake, is this code the new corrected program?

    ReplyDelete
  7. in this code the 13th line is showing error in modelsim... the line is
    variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
    plese rectify it and tell me the right answer...

    ReplyDelete
  8. Sorry for writing my question anywhere but can you tell me if I am having 1024 member array of 64 bit length and with each clock I want to excess 4 member out of it
    can you tell me what i can do for that?
    Someone said me to use rom
    Can you tell me how to use it?

    And i need to generate real random number also that is varying from 0 to 1 can you tell me how can i do it?

    ReplyDelete
  9. Just by copy and pasting your generator I get an error: Unexpected EOF. I somehow don't see what's wrong.

    ReplyDelete
  10. A minor bug: The "end process;" line in the main module should be followed by "end;".

    ReplyDelete

Related Posts with Thumbnails

Download this article as PDF