Search code examples
randomvhdl

Random number generator in VHDL


I'm designing a test bench and I need to create a random sequence of bits for one of the system's inputs which is normally controlled by the user. I also want this sequence of bits not being in the same order every time I run the simulation.

I cannot use a PRNG since its initial state will be predefined meaning it while produce the same numbers every time. I also used the uniform function but I had the same issue.

RAND_GEN : process(clk) is
    variable seed1, seed2 : positive := 1;
    variable re           : real;
begin
    if rising_edge(clk) then
        uniform(seed1, seed2, re);
        if (re < 0.5) then
            rand_bit <= '0';
        else
            rand_bit <= '1';
        end if;
    end if;
end process;

Is there any alternatives for this problem?


Solution

  • Testing with randomly generated inputs is a powerful tehnique and is the technique commonly used to verify ICs these days. Normally, you would run a test with a known, per-determined seed, whereas you want to be able to generate a varying seed. So, you absolutely MUST record this seed when you run the test and provide a mechanism to run a test using this seed. Otherwise, when you find a bug, you will not be able to test whether you've fixed it. You might find it more useful to a a fixed set of tests with a smaller number of manually-generated seeds.

    You could use the linux date command with the %s format specifier, which outputs the number of seconds since 1/1/1970 and redirect that to a file.

    date +%s >! seed.txt
    

    Then read the file, eg:

    RAND_GEN : process(clk) is
        variable seed1, seed2 : positive := 1;
        variable re           : real;
        file F: TEXT;
        variable L: LINE;
        variable seed_RNG : boolean := false;
    begin
        if not seed_RNG then
            file_open(F, "seed.txt", READ_MODE);
            readline (F, L);
            read (L, seed1);  -- or seed2
            file_close(F);
            report "seed1 = " & integer'image(seed1);
            seed_RNG := true;
        end if;
        if rising_edge(clk) then    
            uniform(seed1, seed2, re);
            if (re < 0.5) then
                rand_bit <= '0';
            else
                rand_bit <= '1';
            end if;
        end if;
    end process;