Scaling down a 128 bit Xorshift. - PRNG in vhdl

772 views Asked by At

Im trying to figure out a way of generating random values (pseudo random will do) in vhdl using vivado (meaning that I can't use the math_real library).

These random values will determine the number of counts a prescaler will run for which will then in turn generate random timing used for the application.

This means that the values generated do not need to have a very specific value as I can always tweak the speed the prescaler runs at. Generally speaking I am looking for values between 1000 - 10,000, but a bit larger might do as well.

I found following code online which implements a 128 bit xorshift and does seem to work very well. The only problem is that the values are way too large and converting to an integer is pointless as the max value for an unsigned integer is 2^32.

This is the code:

library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;

entity XORSHIFT_128 is
    port (
        CLK : in std_logic;
        RESET : in std_logic;
        OUTPUT : out std_logic_vector(127 downto 0)
    );
end XORSHIFT_128;

architecture Behavioral of XORSHIFT_128 is
    signal STATE : unsigned(127 downto 0) := to_unsigned(1, 128);

begin
    OUTPUT <= std_logic_vector(STATE);

    Update : process(CLK) is
        variable tmp : unsigned(31 downto 0);
    begin
        if(rising_edge(CLK)) then
            if(RESET = '1') then
                STATE <= (others => '0');
            end if;
            tmp := (STATE(127 downto 96) xor (STATE(127 downto 96) sll 11));
            STATE <= STATE(95 downto 0) &
                ((STATE(31 downto 0) xor (STATE(31 downto 0) srl 19)) xor (tmp xor (tmp srl 8)));
        end if;
    end process;
end Behavioral;

For the past couple of hours I have been trying to downscale this 128 bit xorshift PRNG to an 8 bit, 16 bit or even 32 bit PRNG but every time again I get either no output or my simulation (testbench) freezes after one cycle.

I've tried just dividing the value which does work in a way, but the size of the output of the 128 bit xorshift is so large that it makes it a very unwieldy way of going about the situation.

Any ideas or pointers would be very welcome.

2

There are 2 answers

0
sh1 On BEST ANSWER

To reduce the range of your RNG to a smaller power of two range, simply ignore some of the bits. I guess that's something like OUTPUT(15 downto 0) but I don't know VHDL at all.

The remaining bits represent working state for the generator and cannot be eliminated from the design even if you don't use them.

If you mean that the generator uses too many gates, then you'll need to find a different algorithm. Wikipedia gives an example 32-bit xorshift generator in C which you might be able to adapt.

0
bhamadicharef On

Table 3 in the old Xilinx Application Note has the information you need to make such random generator circuit for 8-bit as you mention. https://www.xilinx.com/support/documentation/application_notes/xapp052.pdf