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;
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;
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

thanx for writing such a good post,, this is one of the best material i have found on this subject,
ReplyDeletethank you very much much, this helped me a lot.
ReplyDeleteThis 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.
ReplyDeletethis 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.
@Chris: Thanks a lot.I got your point.
ReplyDeleteI 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".
Have you fixed the random program?
ReplyDeletethank you very much for the post, but I wonder if you correct the mistake, is this code the new corrected program?
ReplyDeletein this code the 13th line is showing error in modelsim... the line is
ReplyDeletevariable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
plese rectify it and tell me the right answer...
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
ReplyDeletecan 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?
Just by copy and pasting your generator I get an error: Unexpected EOF. I somehow don't see what's wrong.
ReplyDeleteA minor bug: The "end process;" line in the main module should be followed by "end;".
ReplyDelete