---------------------------------------------------------------------------- -- prng.vhd -- Pseudo Random Generators -- Version 1.0 -- -- Copyright (C) 2014 H.Poetzl -- -- This program is free software: you can redistribute it and/or -- modify it under the terms of the GNU General Public License -- as published by the Free Software Foundation, either version -- 2 of the License, or (at your option) any later version. ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.ALL; use work.vivado_pkg.ALL; -- Vivado Attributes entity rng_sr is generic ( K : integer ); port ( clk : in std_logic; ce : in std_logic; din : in std_logic; dout : out std_logic ); end entity; architecture RTL of rng_sr is attribute KEEP_HIERARCHY of RTL : architecture is "TRUE"; signal bits : std_logic_vector (0 to K); begin bits(0) <= din; process (clk) begin if rising_edge(clk) then if ce = '1' then bits(1 to K) <= bits(0 to K - 1); end if; end if; end process; dout <= bits(K); end RTL; library IEEE; use IEEE.std_logic_1164.ALL; use IEEE.std_logic_textio.ALL; use IEEE.numeric_std.ALL; use work.vivado_pkg.ALL; -- Vivado Attributes use std.textio.ALL; -- Text Input/Output entity dpram is generic ( DATA_WIDTH : positive := 1; ADDR_WIDTH : positive := 8; INIT_FILE : string := "NONE.bin" ); port ( -- writing port clka : in std_logic; wea : in std_logic; addra : in std_logic_vector (ADDR_WIDTH-1 downto 0); dina : in std_logic_vector (DATA_WIDTH-1 downto 0); -- reading port clkb : in std_logic; addrb : in std_logic_vector (ADDR_WIDTH-1 downto 0); doutb : out std_logic_vector (DATA_WIDTH-1 downto 0) := (others =>'0') ); end entity; architecture RTL of dpram is type mem is array (2 ** ADDR_WIDTH - 1 downto 0) of std_logic_vector (DATA_WIDTH - 1 downto 0); function dpram_init_f ( file_name : string; addr_width : positive; data_width : positive ) return mem is file init_file : text is in file_name; variable line_v : line; variable index_v : natural := 0; variable temp_v : mem := (others => (others => '0')); begin while not endfile(init_file) and index_v < 2 ** ADDR_WIDTH loop readline(init_file, line_v); read(line_v, temp_v(index_v)); index_v := index_v + 1; end loop; return temp_v; end function; signal RAM : mem := dpram_init_f(file_name => INIT_FILE, addr_width => ADDR_WIDTH, data_width => DATA_WIDTH); signal d2 : std_logic_vector (DATA_WIDTH-1 downto 0) := (others => '0'); begin process (clka) -- write begin if rising_edge(clka) then if wea = '1' then RAM(to_integer(unsigned(addra))) <= dina; end if; end if; end process; -- read process (clkb) begin if rising_edge(clkb) then doutb <= RAM(to_integer(unsigned(addrb))); end if; end process; end RTL; library IEEE; use IEEE.std_logic_1164.ALL; use IEEE.numeric_std.ALL; use work.vivado_pkg.ALL; -- Vivado Attributes entity prng32 is port( clk : in std_logic; ce : in std_logic; mode : in std_logic; s_in : in std_logic; s_out : out std_logic; rng : out std_logic_vector (31 downto 0) ); end prng32; ---------------------------------------------------------------------------- -- LFSR RNG (Fibonacci) -- (32,22,2,1,0) -- Version 1.0 -- ---------------------------------------------------------------------------- architecture LFSR_FIB of prng32 is signal fb : std_logic; signal sr : std_logic_vector (31 downto 0) := ( others => '1' ); begin prng : process (clk) begin if rising_edge(clk) then if ce = '1' then if mode = '1' then s_out <= sr(31); sr <= sr(30 downto 0) & s_in; else fb <= sr(31) xor sr(21) xor sr(1) xor sr(0); sr <= sr(30 downto 0) & fb; end if; end if; end if; end process; rng <= sr; end LFSR_FIB; ---------------------------------------------------------------------------- -- LFSR RNG (Galois) -- (32,31,29,1,0) -- Version 1.0 -- ---------------------------------------------------------------------------- architecture LFSR_GAL of prng32 is signal fb : std_logic_vector (31 downto 0); signal sr : std_logic_vector (31 downto 0) := ( others => '1' ); begin prng : process (clk) begin if rising_edge(clk) then if ce = '1' then if mode = '1' then s_out <= sr(31); sr <= sr(30 downto 0) & s_in; else fb <= (31 => sr(0), 30 => sr(0), 28 => sr(0), 0 => sr(0), others => '0'); sr <= ('0' & sr(31 downto 1)) xor fb; end if; end if; end if; end process; rng <= sr; end LFSR_GAL; ---------------------------------------------------------------------------- -- LUT-SR RNG -- (n,r,t,k,s) = (1024,32,5,32,1c48) -- Version 1.0 -- -- Design by David B. Thomas and Wayne Luk -- -- FPGA-Optimised Uniform Random Number -- Generators using LUTs and Shift Registers ---------------------------------------------------------------------------- architecture LUT_SR of prng32 is signal sr_out : std_logic_vector (31 downto 0); signal r_out : std_logic_vector (31 downto 0) := ( others => '1' ); begin rng(0) <= r_out(6); rng(16) <= r_out(23); rng(1) <= r_out(10); rng(17) <= r_out(9); rng(2) <= r_out(26); rng(18) <= r_out(21); rng(3) <= r_out(14); rng(19) <= r_out(19); rng(4) <= r_out(2); rng(20) <= r_out(20); rng(5) <= r_out(30); rng(21) <= r_out(25); rng(6) <= r_out(0); rng(22) <= r_out(18); rng(7) <= r_out(22); rng(23) <= r_out(17); rng(8) <= r_out(24); rng(24) <= r_out(31); rng(9) <= r_out(27); rng(25) <= r_out(1); rng(10) <= r_out(29); rng(26) <= r_out(4); rng(11) <= r_out(13); rng(27) <= r_out(16); rng(12) <= r_out(8); rng(28) <= r_out(12); rng(13) <= r_out(28); rng(29) <= r_out(5); rng(14) <= r_out(7); rng(30) <= r_out(11); rng(15) <= r_out(3); rng(31) <= r_out(15); s_out <= sr_out(23); sr_00 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(1), dout => sr_out(0)); sr_01 : entity work.rng_sr generic map ( K => 30 ) port map ( clk => clk, ce => ce, din => r_out(2), dout => sr_out(1)); sr_02 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(3), dout => sr_out(2)); sr_03 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(4), dout => sr_out(3)); sr_04 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(5), dout => sr_out(4)); sr_05 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(6), dout => sr_out(5)); sr_06 : entity work.rng_sr generic map ( K => 31 ) port map ( clk => clk, ce => ce, din => r_out(7), dout => sr_out(6)); sr_07 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(8), dout => sr_out(7)); sr_08 : entity work.rng_sr generic map ( K => 26 ) port map ( clk => clk, ce => ce, din => r_out(9), dout => sr_out(8)); sr_09 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(10), dout => sr_out(9)); sr_10 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(11), dout => sr_out(10)); sr_11 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(12), dout => sr_out(11)); sr_12 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(13), dout => sr_out(12)); sr_13 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(14), dout => sr_out(13)); sr_14 : entity work.rng_sr generic map ( K => 21 ) port map ( clk => clk, ce => ce, din => r_out(15), dout => sr_out(14)); sr_15 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(16), dout => sr_out(15)); sr_16 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(17), dout => sr_out(16)); sr_17 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(18), dout => sr_out(17)); sr_18 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(19), dout => sr_out(18)); sr_19 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(20), dout => sr_out(19)); sr_20 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(21), dout => sr_out(20)); sr_21 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(22), dout => sr_out(21)); sr_22 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(23), dout => sr_out(22)); sr_23 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(24), dout => sr_out(23)); sr_24 : entity work.rng_sr generic map ( K => 29 ) port map ( clk => clk, ce => ce, din => r_out(25), dout => sr_out(24)); sr_25 : entity work.rng_sr generic map ( K => 30 ) port map ( clk => clk, ce => ce, din => r_out(26), dout => sr_out(25)); sr_26 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(27), dout => sr_out(26)); sr_27 : entity work.rng_sr generic map ( K => 29 ) port map ( clk => clk, ce => ce, din => r_out(28), dout => sr_out(27)); sr_28 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(29), dout => sr_out(28)); sr_29 : entity work.rng_sr generic map ( K => 28 ) port map ( clk => clk, ce => ce, din => r_out(30), dout => sr_out(29)); sr_30 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(31), dout => sr_out(30)); sr_31 : entity work.rng_sr generic map ( K => 32 ) port map ( clk => clk, ce => ce, din => r_out(0), dout => sr_out(31)); regs : process (clk) begin if rising_edge(clk) then if ce = '1' then r_out(0) <= (mode and sr_out(0)) or ((not mode) and ('0' xor sr_out(16) xor sr_out(0) xor sr_out(12) xor sr_out(27))); r_out(1) <= (mode and sr_out(1)) or ((not mode) and ('0' xor sr_out(16) xor sr_out(12) xor sr_out(20) xor sr_out(24) xor sr_out(1))); r_out(2) <= (mode and sr_out(2)) or ((not mode) and ('0' xor sr_out(2) xor sr_out(15) xor sr_out(0) xor sr_out(11) xor sr_out(1))); r_out(3) <= (mode and sr_out(3)) or ((not mode) and ('0' xor sr_out(3) xor sr_out(2) xor sr_out(4) xor sr_out(5) xor sr_out(25))); r_out(4) <= (mode and sr_out(4)) or ((not mode) and ('0' xor sr_out(7) xor sr_out(19) xor sr_out(4) xor sr_out(23) xor sr_out(26))); r_out(5) <= (mode and sr_out(5)) or ((not mode) and ('0' xor sr_out(10) xor sr_out(3) xor sr_out(0) xor sr_out(5) xor sr_out(6))); r_out(6) <= (mode and sr_out(6)) or ((not mode) and ('0' xor sr_out(3) xor sr_out(9) xor sr_out(11) xor sr_out(20) xor sr_out(6))); r_out(7) <= (mode and sr_out(7)) or ((not mode) and ('0' xor sr_out(7) xor sr_out(22) xor sr_out(24) xor sr_out(28) xor sr_out(14))); r_out(8) <= (mode and sr_out(8)) or ((not mode) and ('0' xor sr_out(7) xor sr_out(16) xor sr_out(18) xor sr_out(8))); r_out(9) <= (mode and sr_out(9)) or ((not mode) and ('0' xor sr_out(9) xor sr_out(0) xor sr_out(18) xor sr_out(23) xor sr_out(13))); r_out(10) <= (mode and sr_out(10)) or ((not mode) and ('0' xor sr_out(10) xor sr_out(9) xor sr_out(21) xor sr_out(29) xor sr_out(28))); r_out(11) <= (mode and sr_out(11)) or ((not mode) and ('0' xor sr_out(3) xor sr_out(15) xor sr_out(11) xor sr_out(6))); r_out(12) <= (mode and sr_out(12)) or ((not mode) and ('0' xor sr_out(18) xor sr_out(12) xor sr_out(26) xor sr_out(24) xor sr_out(6))); r_out(13) <= (mode and sr_out(13)) or ((not mode) and ('0' xor sr_out(4) xor sr_out(31) xor sr_out(8) xor sr_out(13) xor sr_out(30))); r_out(14) <= (mode and sr_out(14)) or ((not mode) and ('0' xor sr_out(15) xor sr_out(30) xor sr_out(5) xor sr_out(14) xor sr_out(27))); r_out(15) <= (mode and sr_out(15)) or ((not mode) and ('0' xor sr_out(15) xor sr_out(4) xor sr_out(22) xor sr_out(8) xor sr_out(26))); r_out(16) <= (mode and sr_out(16)) or ((not mode) and ('0' xor sr_out(16) xor sr_out(2) xor sr_out(9) xor sr_out(26) xor sr_out(14))); r_out(17) <= (mode and sr_out(17)) or ((not mode) and ('0' xor sr_out(17) xor sr_out(19) xor sr_out(12) xor sr_out(31) xor sr_out(8))); r_out(18) <= (mode and sr_out(18)) or ((not mode) and ('0' xor sr_out(21) xor sr_out(18) xor sr_out(20) xor sr_out(5) xor sr_out(14))); r_out(19) <= (mode and sr_out(19)) or ((not mode) and ('0' xor sr_out(19) xor sr_out(4) xor sr_out(25) xor sr_out(1))); r_out(20) <= (mode and sr_out(20)) or ((not mode) and ('0' xor sr_out(10) xor sr_out(17) xor sr_out(2) xor sr_out(20) xor sr_out(1))); r_out(21) <= (mode and sr_out(21)) or ((not mode) and ('0' xor sr_out(17) xor sr_out(16) xor sr_out(21) xor sr_out(11) xor sr_out(25))); r_out(22) <= (mode and sr_out(22)) or ((not mode) and ('0' xor sr_out(17) xor sr_out(2) xor sr_out(22) xor sr_out(8) xor sr_out(28))); r_out(23) <= (mode and s_in) or ((not mode) and ('0' xor sr_out(0) xor sr_out(21) xor sr_out(23) xor sr_out(29))); r_out(24) <= (mode and sr_out(24)) or ((not mode) and ('0' xor sr_out(11) xor sr_out(24) xor sr_out(13) xor sr_out(6) xor sr_out(27))); r_out(25) <= (mode and sr_out(25)) or ((not mode) and ('0' xor sr_out(7) xor sr_out(22) xor sr_out(12) xor sr_out(30) xor sr_out(25))); r_out(26) <= (mode and sr_out(26)) or ((not mode) and ('0' xor sr_out(10) xor sr_out(21) xor sr_out(18) xor sr_out(22) xor sr_out(26))); r_out(27) <= (mode and sr_out(27)) or ((not mode) and ('0' xor sr_out(17) xor sr_out(29) xor sr_out(13) xor sr_out(5) xor sr_out(27))); r_out(28) <= (mode and sr_out(28)) or ((not mode) and ('0' xor sr_out(10) xor sr_out(19) xor sr_out(15) xor sr_out(28) xor sr_out(14))); r_out(29) <= (mode and sr_out(29)) or ((not mode) and ('0' xor sr_out(23) xor sr_out(31) xor sr_out(29) xor sr_out(20) xor sr_out(30))); r_out(30) <= (mode and sr_out(30)) or ((not mode) and ('0' xor sr_out(9) xor sr_out(31) xor sr_out(30) xor sr_out(25) xor sr_out(28))); r_out(31) <= (mode and sr_out(31)) or ((not mode) and ('0' xor sr_out(31) xor sr_out(29) xor sr_out(24) xor sr_out(13) xor sr_out(1))); end if; end if; end process; end LUT_SR; ---------------------------------------------------------------------------- -- MT32 RNG -- Version 1.0 -- -- Design based on the Mersenne Twister 19937 -- by Makoto Matsumoto and Takuji Nishimura. ---------------------------------------------------------------------------- architecture MT32 of prng32 is constant M : integer := 397; constant N : integer := 623; constant N_c : std_logic_vector(9 downto 0) := std_logic_vector(to_unsigned(N, 10)); signal wr_cnt : unsigned (9 downto 0) := (others => '1'); signal kk_cnt : unsigned (9 downto 0) := (others => '0'); signal kp_cnt : unsigned (9 downto 0) := (0 => '1', others => '0'); signal km_cnt : unsigned (9 downto 0) := to_unsigned(M, 10); signal mt_kk31 : std_logic_vector(0 downto 0); signal mt_kk_s : std_logic_vector(31 downto 0); signal mt_km : std_logic_vector(31 downto 0); signal mt_kp : std_logic_vector(30 downto 0); signal ena : std_logic; signal wea : std_logic; -- signal wea_s : std_logic_vector(0 downto 0); signal xor1_s : std_logic_vector(31 downto 0); signal xor2_s : std_logic_vector(31 downto 0); signal xor3_s : std_logic_vector(31 downto 0); signal y_s : std_logic_vector(31 downto 0); signal mag01_s : std_logic_vector(31 downto 0); begin -- wea_s(0) <= wea; -- wonderful VHDL ena <= ce; xor1_s <= mt_kk_s xor (x"00" & "000" & mt_kk_s(31 downto 11)); xor2_s <= xor1_s xor (xor1_s(24 downto 0) & "0000000" and x"9D2C5680"); xor3_s <= xor2_s xor (xor2_s(16 downto 0) & x"000" & "000" and x"EFC60000"); rng <= xor3_s xor x"0000" & "00" & xor3_s(31 downto 18); y_s <= mt_kk31(0) & mt_kp(30 downto 0); mag01_s <= x"00000000" when y_s(0) = '0' else x"9908B0DF"; mt_kk_s <= mt_km xor ('0' & y_s(31 downto 1)) xor mag01_s; dpram_inst0 : entity work.dpram generic map ( DATA_WIDTH => 1, ADDR_WIDTH => 10, INIT_FILE => "mt32_624x1.ini" ) port map ( clka => clk, wea => wea, addra => std_logic_vector(wr_cnt), dina => mt_kk_s(31 downto 31), clkb => clk, addrb => std_logic_vector(kk_cnt), doutb => mt_kk31 ); dpram_inst1 : entity work.dpram generic map ( DATA_WIDTH => 31, ADDR_WIDTH => 10, INIT_FILE => "mt32_624x31.ini" ) port map ( clka => clk, wea => wea, addra => std_logic_vector(wr_cnt), dina => mt_kk_s(30 downto 0), clkb => clk, addrb => std_logic_vector(kp_cnt), doutb => mt_kp ); dpram_inst2 : entity work.dpram generic map ( DATA_WIDTH => 32, ADDR_WIDTH => 10, INIT_FILE => "mt32_624x32.ini" ) port map ( clka => clk, wea => wea, addra => std_logic_vector(wr_cnt), dina => mt_kk_s, clkb => clk, addrb => std_logic_vector(km_cnt), doutb => mt_km ); wea_proc : process (clk) begin if rising_edge(clk) then wea <= ena; end if; end process; wr_cnt_proc : process (clk) begin if rising_edge(clk) then if wr_cnt = to_unsigned(N, 10) then wr_cnt <= (others => '0'); elsif ena = '1' then wr_cnt <= wr_cnt + "1"; end if; end if; end process; kk_cnt_proc : process (clk) begin if rising_edge(clk) then if kk_cnt = to_unsigned(N, 10) then kk_cnt <= (others => '0'); elsif ena = '1' then kk_cnt <= kk_cnt + "1"; end if; end if; end process; kp_cnt_proc : process (clk) begin if rising_edge(clk) then if kp_cnt = to_unsigned(N, 10) then kp_cnt <= (others => '0'); elsif ena = '1' then kp_cnt <= kp_cnt + "1"; end if; end if; end process; km_cnt_proc : process (clk) begin if rising_edge(clk) then if km_cnt = to_unsigned(N, 10) then km_cnt <= (others => '0'); elsif ena = '1' then km_cnt <= km_cnt + "1"; end if; end if; end process; end MT32;