URL
https://opencores.org/ocsvn/rng_lib/rng_lib/trunk
Subversion Repositories rng_lib
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/trunk/bench/vhdl/math_lib.vhd
44,9 → 44,12
-- CVS Revision History |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2004/09/28 15:02:56 gedra |
-- Math functions library. |
-- |
-- |
|
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
53,177 → 56,177
|
package math_lib is |
|
function sqrt(x: real) return real; -- returns square root |
function ln(x: real ) return real; -- natural logarithm |
function log(x: real) return real; -- base 10 logarithm |
function exp(x: real ) return real; -- exponential function |
|
-- Some mathematical constants |
constant MATH_E: real := 2.71828_18284_59045_23536; |
|
function sqrt(x : real) return real; -- returns square root |
function ln(x : real) return real; -- natural logarithm |
function log(x : real) return real; -- base 10 logarithm |
function exp(x : real) return real; -- exponential function |
|
-- Some mathematical constants |
constant MATH_E : real := 2.71828_18284_59045_23536; |
|
end math_lib; |
|
package body math_lib is |
|
-- Square root calculation |
function sqrt (x : real ) return real is |
-- returns square root of X; X >= 0 |
-- |
-- Computes square root using the Newton-Raphson approximation: |
-- F(n+1) = 0.5*[F(n) + x/F(n)]; |
-- |
|
constant inival: real := 1.5; |
constant eps : real := 0.000001; |
constant relative_err : real := eps*X; |
|
variable oldval : real; |
variable newval : real; |
function sqrt (x : real) return real is |
-- returns square root of X; X >= 0 |
-- |
-- Computes square root using the Newton-Raphson approximation: |
-- F(n+1) = 0.5*[F(n) + x/F(n)]; |
-- |
|
constant inival : real := 1.5; |
constant eps : real := 0.000001; |
constant relative_err : real := eps*X; |
|
begin |
-- check validity of argument |
if x < 0.0 then |
report "x < 0 in sqrt(x)" |
severity failure; |
return (0.0); |
end if; |
|
-- get the square root for special cases |
if x = 0.0 then |
return 0.0; |
else |
if x = 1.0 then |
return 1.0; -- return exact value |
variable oldval : real; |
variable newval : real; |
|
begin |
-- check validity of argument |
if x < 0.0 then |
report "x < 0 in sqrt(x)" |
severity failure; |
return (0.0); |
end if; |
end if; |
|
-- get the square root for general cases |
oldval := inival; |
newval := (X/oldval + oldval)/2.0; |
|
while ( abs(newval -oldval) > relative_err ) loop |
oldval := newval; |
|
-- get the square root for special cases |
if x = 0.0 then |
return 0.0; |
else |
if x = 1.0 then |
return 1.0; -- return exact value |
end if; |
end if; |
|
-- get the square root for general cases |
oldval := inival; |
newval := (X/oldval + oldval)/2.0; |
end loop; |
|
return newval; |
end sqrt; |
|
while (abs(newval -oldval) > relative_err) loop |
oldval := newval; |
newval := (X/oldval + oldval)/2.0; |
end loop; |
|
return newval; |
end sqrt; |
|
-- Natural logarithm calculation |
function ln (x: real ) return real is |
-- returns natural logarithm of X; X > 0 |
-- |
-- This function computes the exponential using the following series: |
-- log(x) = 2[ (x-1)/(x+1) + (((x-1)/(x+1))**3)/3.0 + ...] ; x > 0 |
-- |
|
constant eps : real := 0.000001; -- precision criteria |
function ln (x : real) return real is |
-- returns natural logarithm of X; X > 0 |
-- |
-- This function computes the exponential using the following series: |
-- log(x) = 2[ (x-1)/(x+1) + (((x-1)/(x+1))**3)/3.0 + ...] ; x > 0 |
-- |
|
constant eps : real := 0.000001; -- precision criteria |
|
variable xlocal: real ; -- following variables are |
variable oldval: real ; -- used to evaluate the series |
variable xlocalsqr: real ; |
variable factor : real ; |
variable count: integer ; |
variable newval: real ; |
|
begin |
-- check validity of argument |
if x <= 0.0 then |
report "x <= 0 in ln(x)" |
severity failure; |
return(real'LOW); |
end if; |
variable xlocal : real; -- following variables are |
variable oldval : real; -- used to evaluate the series |
variable xlocalsqr : real; |
variable factor : real; |
variable count : integer; |
variable newval : real; |
|
begin |
-- check validity of argument |
if x <= 0.0 then |
report "x <= 0 in ln(x)" |
severity failure; |
return(real'low); |
end if; |
|
-- compute value for special cases |
if x = 1.0 then |
return 0.0; |
else |
if x = MATH_E then |
return 1.0; |
-- compute value for special cases |
if x = 1.0 then |
return 0.0; |
else |
if x = MATH_E then |
return 1.0; |
end if; |
end if; |
end if; |
|
-- compute value for general cases |
xlocal := (x - 1.0)/(x + 1.0); |
oldval := xlocal; |
xlocalsqr := xlocal*xlocal; |
factor := xlocal*xlocalsqr; |
count := 3; |
newval := oldval + (factor/real(count)); |
|
while ( abs(newval - oldval) > eps ) loop |
oldval := newval; |
count := count +2; |
factor := factor * xlocalsqr; |
newval := oldval + factor/real(count); |
end loop; |
|
newval := newval * 2.0; |
return newval; |
end ln; |
-- compute value for general cases |
xlocal := (x - 1.0)/(x + 1.0); |
oldval := xlocal; |
xlocalsqr := xlocal*xlocal; |
factor := xlocal*xlocalsqr; |
count := 3; |
newval := oldval + (factor/real(count)); |
|
while (abs(newval - oldval) > eps) loop |
oldval := newval; |
count := count +2; |
factor := factor * xlocalsqr; |
newval := oldval + factor/real(count); |
end loop; |
|
newval := newval * 2.0; |
return newval; |
end ln; |
|
-- Base 10 logarithm calculation |
function log (x: real) return real is |
-- returns logarithm base 10 of x; x > 0 |
begin |
-- check validity of argument |
if x <= 0.0 then |
assert false report "x <= 0.0 in log(x)" |
severity ERROR; |
return(real'LOW); |
end if; |
function log (x : real) return real is |
-- returns logarithm base 10 of x; x > 0 |
begin |
-- check validity of argument |
if x <= 0.0 then |
assert false report "x <= 0.0 in log(x)" |
severity error; |
return(real'low); |
end if; |
|
-- compute the value |
return (ln(x)/2.30258509299); |
end log; |
-- compute the value |
return (ln(x)/2.30258509299); |
end log; |
|
-- Calculate e**x |
function exp (x: real ) return real is |
-- returns e**X; where e = MATH_E |
-- |
-- This function computes the exponential using the following series: |
-- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; x > 0 |
-- |
constant eps : real := 0.000001; -- precision criteria |
|
variable reciprocal: boolean := x < 0.0;-- check sign of argument |
variable xlocal : real := abs(x); -- use positive value |
variable oldval: real ; -- following variables are |
variable num: real ; -- used for series evaluation |
variable count: integer ; |
variable denom: real ; |
variable newval: real ; |
|
begin |
-- compute value for special cases |
if x = 0.0 then |
return 1.0; |
else |
if x = 1.0 then |
return MATH_E; |
function exp (x : real) return real is |
-- returns e**X; where e = MATH_E |
-- |
-- This function computes the exponential using the following series: |
-- exp(x) = 1 + x + x**2/2! + x**3/3! + ... ; x > 0 |
-- |
constant eps : real := 0.000001; -- precision criteria |
|
variable reciprocal : boolean := x < 0.0; -- check sign of argument |
variable xlocal : real := abs(x); -- use positive value |
variable oldval : real; -- following variables are |
variable num : real; -- used for series evaluation |
variable count : integer; |
variable denom : real; |
variable newval : real; |
|
begin |
-- compute value for special cases |
if x = 0.0 then |
return 1.0; |
else |
if x = 1.0 then |
return MATH_E; |
end if; |
end if; |
end if; |
|
-- compute value for general cases |
oldval := 1.0; |
num := xlocal; |
count := 1; |
denom := 1.0; |
newval:= oldval + num/denom; |
|
while ( abs(newval - oldval) > eps ) loop |
oldval := newval; |
num := num*xlocal; |
count := count +1; |
denom := denom*(real(count)); |
-- compute value for general cases |
oldval := 1.0; |
num := xlocal; |
count := 1; |
denom := 1.0; |
newval := oldval + num/denom; |
end loop; |
|
if reciprocal then |
newval := 1.0/newval; |
end if; |
|
return newval; |
end exp; |
|
while (abs(newval - oldval) > eps) loop |
oldval := newval; |
num := num*xlocal; |
count := count +1; |
denom := denom*(real(count)); |
newval := oldval + num/denom; |
end loop; |
|
if reciprocal then |
newval := 1.0/newval; |
end if; |
|
return newval; |
end exp; |
|
end math_lib; |
/trunk/bench/vhdl/tb_rng.vhd
44,9 → 44,12
-- CVS Revision History |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2004/09/28 15:12:52 gedra |
-- Test bench for random numbers. |
-- |
-- |
|
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
53,103 → 56,103
use std.textio.all; |
use work.rng_lib.all; |
|
entity tb_rng is |
entity tb_rng is |
|
end tb_rng; |
|
architecture behav of tb_rng is |
|
constant BIN_COUNT : integer := 15; |
constant PLOT_HEIGHT : real := 40.0; |
constant RAND_COUNT : integer := 10000; |
|
type rand_array is array (0 to RAND_COUNT - 1) of real; -- array used for plot |
type bin_array is array (0 to BIN_COUNT - 1) of integer; |
constant BIN_COUNT : integer := 15; |
constant PLOT_HEIGHT : real := 40.0; |
constant RAND_COUNT : integer := 10000; |
|
type rand_array is array (0 to RAND_COUNT - 1) of real; -- array used for plot |
type bin_array is array (0 to BIN_COUNT - 1) of integer; |
|
-- Plot a distribution of the numbers that are between lo,hi values |
impure function plot_dist (numbs: rand_array; lo, hi: real) return integer is |
variable bins: bin_array; |
variable bin_size, height : real; |
variable idx, max: integer; |
variable bar : line; |
begin |
-- reset bins |
for i in 0 to BIN_COUNT - 1 loop |
bins(i) := 0; |
end loop; |
-- sort numbers into bins |
bin_size := (hi - lo) / real(BIN_COUNT); |
for i in 0 to RAND_COUNT - 1 loop |
if numbs(i) > lo and numbs(i) < hi then |
idx := integer(((numbs(i) - lo) / bin_size) - 0.5); |
if idx > BIN_COUNT - 1 then |
idx := BIN_COUNT - 1; |
elsif idx < 0 then |
idx := 0; |
end if; |
bins(idx) := bins(idx) + 1; |
end if; |
end loop; |
-- find largest bin |
max := 0; |
for i in 0 to BIN_COUNT - 1 loop |
if bins(i) > max then |
max := bins(i); |
end if; |
end loop; |
-- plot bins |
for i in 0 to BIN_COUNT - 1 loop |
height := PLOT_HEIGHT * real(bins(i)) / real(max); |
for j in 1 to integer(height) loop |
write(bar, string'("*")); |
impure function plot_dist (numbs : rand_array; lo, hi : real) return integer is |
variable bins : bin_array; |
variable bin_size, height : real; |
variable idx, max : integer; |
variable bar : line; |
begin |
-- reset bins |
for i in 0 to BIN_COUNT - 1 loop |
bins(i) := 0; |
end loop; |
writeline(OUTPUT, bar); |
end loop; |
return 0; |
end plot_dist; |
|
-- sort numbers into bins |
bin_size := (hi - lo) / real(BIN_COUNT); |
for i in 0 to RAND_COUNT - 1 loop |
if numbs(i) > lo and numbs(i) < hi then |
idx := integer(((numbs(i) - lo) / bin_size) - 0.5); |
if idx > BIN_COUNT - 1 then |
idx := BIN_COUNT - 1; |
elsif idx < 0 then |
idx := 0; |
end if; |
bins(idx) := bins(idx) + 1; |
end if; |
end loop; |
-- find largest bin |
max := 0; |
for i in 0 to BIN_COUNT - 1 loop |
if bins(i) > max then |
max := bins(i); |
end if; |
end loop; |
-- plot bins |
for i in 0 to BIN_COUNT - 1 loop |
height := PLOT_HEIGHT * real(bins(i)) / real(max); |
for j in 1 to integer(height) loop |
write(bar, string'("*")); |
end loop; |
writeline(OUTPUT, bar); |
end loop; |
return 0; |
end plot_dist; |
|
begin |
|
p1: process |
variable r_uni, r_gauss, r_exp : rand_var; |
variable r_poisson : rand_var; |
variable txt : line; |
variable a: integer; |
variable numbs : rand_array; |
begin |
-- Test the uniform distribution |
r_uni := init_uniform(0, 0, 0, 0.0, 10.0); -- range 0 to 10 |
t1: for i in 0 to RAND_COUNT - 1 loop |
r_uni := rand(r_uni); |
numbs(i) := r_uni.rnd; |
end loop t1; |
write(txt, string'("Uniform distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, 0.0, 10.0); |
-- Test the gaussian distribution |
r_gauss := init_gaussian(0, 0, 0, 0.0, 10.0); -- mean=0, stdev=10 |
t2: for i in 0 to RAND_COUNT - 1 loop |
r_gauss := rand(r_gauss); |
numbs(i) := r_gauss.rnd; |
end loop t2; |
write(txt, string'("Gaussian distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, -20.0, 20.0); |
-- Test the exponential distribution |
r_exp := init_exponential(0, 0, 0, 10.0); -- mean=10 |
t3: for i in 0 to RAND_COUNT - 1 loop |
r_exp := rand(r_exp); |
numbs(i) := r_exp.rnd; |
end loop t3; |
write(txt, string'("Exponential distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, 0.0, 20.0); |
|
wait for 1 ns; |
|
report "End of simulation! (ignore this failure)" |
severity failure; |
wait; |
end process p1; |
|
p1 : process |
variable r_uni, r_gauss, r_exp : rand_var; |
variable r_poisson : rand_var; |
variable txt : line; |
variable a : integer; |
variable numbs : rand_array; |
begin |
-- Test the uniform distribution |
r_uni := init_uniform(0, 0, 0, 0.0, 10.0); -- range 0 to 10 |
t1 : for i in 0 to RAND_COUNT - 1 loop |
r_uni := rand(r_uni); |
numbs(i) := r_uni.rnd; |
end loop t1; |
write(txt, string'("Uniform distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, 0.0, 10.0); |
-- Test the gaussian distribution |
r_gauss := init_gaussian(0, 0, 0, 0.0, 10.0); -- mean=0, stdev=10 |
t2 : for i in 0 to RAND_COUNT - 1 loop |
r_gauss := rand(r_gauss); |
numbs(i) := r_gauss.rnd; |
end loop t2; |
write(txt, string'("Gaussian distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, -20.0, 20.0); |
-- Test the exponential distribution |
r_exp := init_exponential(0, 0, 0, 10.0); -- mean=10 |
t3 : for i in 0 to RAND_COUNT - 1 loop |
r_exp := rand(r_exp); |
numbs(i) := r_exp.rnd; |
end loop t3; |
write(txt, string'("Exponential distribution:")); |
writeline(OUTPUT, txt); |
a := plot_dist (numbs, 0.0, 20.0); |
|
wait for 1 ns; |
|
report "End of simulation! (ignore this failure)" |
severity failure; |
wait; |
end process p1; |
|
end behav; |
/trunk/bench/vhdl/rng_lib.vhd
54,9 → 54,12
-- CVS Revision History |
-- |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2004/09/28 15:12:28 gedra |
-- Random number library functions. |
-- |
-- |
|
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.numeric_std.all; |
65,32 → 68,32
|
package rng_lib is |
|
type distribution is (UNIFORM, GAUSSIAN, EXPONENTIAL); |
type rand_var is record -- random variable record |
rnd: real; -- random number |
rnd_v: unsigned(31 downto 0); -- random number vector |
dist: distribution; -- distribution type |
y, z: real; -- distribution parameters |
s1, s2, s3: unsigned(31 downto 0); -- seeds |
mask1, mask2, mask3: unsigned(31 downto 0); |
shft1, shft2, shft3: natural; |
end record; |
|
function rand (rnd: rand_var) return rand_var; |
function init_uniform(constant a, b, c: natural; |
constant lo, hi: real) return rand_var; |
function init_gaussian(constant a, b, c: natural; |
constant mean, stdev: real) return rand_var; |
function init_exponential(constant a, b, c: natural; |
constant mean: real) return rand_var; |
type distribution is (UNIFORM, GAUSSIAN, EXPONENTIAL); |
type rand_var is record -- random variable record |
rnd : real; -- random number |
rnd_v : unsigned(31 downto 0); -- random number vector |
dist : distribution; -- distribution type |
y, z : real; -- distribution parameters |
s1, s2, s3 : unsigned(31 downto 0); -- seeds |
mask1, mask2, mask3 : unsigned(31 downto 0); |
shft1, shft2, shft3 : natural; |
end record; |
|
constant q1: natural:=13; |
constant q2: natural:=2; |
constant q3: natural:=3; |
constant p1: natural:=12; |
constant p2: natural:=4; |
constant p3: natural:=17; |
|
function rand (rnd : rand_var) return rand_var; |
function init_uniform(constant a, b, c : natural; |
constant lo, hi : real) return rand_var; |
function init_gaussian(constant a, b, c : natural; |
constant mean, stdev : real) return rand_var; |
function init_exponential(constant a, b, c : natural; |
constant mean : real) return rand_var; |
|
constant q1 : natural := 13; |
constant q2 : natural := 2; |
constant q3 : natural := 3; |
constant p1 : natural := 12; |
constant p2 : natural := 4; |
constant p3 : natural := 17; |
|
end rng_lib; |
|
package body rng_lib is |
97,156 → 100,156
|
-- Function to convert 32bit unsigned vector to real |
-- Integers only go to 2**31 (VHDL'87), so do it clever |
function unsigned_2_real (constant a: unsigned(31 downto 0)) return real is |
variable r: real; |
begin |
r := 2.0*real(to_integer(a(31 downto 1))); |
if a(0) = '1' then |
r := r + 1.0; |
end if; |
return(r); |
end unsigned_2_real; |
|
function unsigned_2_real (constant a : unsigned(31 downto 0)) return real is |
variable r : real; |
begin |
r := 2.0*real(to_integer(a(31 downto 1))); |
if a(0) = '1' then |
r := r + 1.0; |
end if; |
return(r); |
end unsigned_2_real; |
|
-- Generate random number using a combination of 3 tausworthe generators |
-- Source: Pierre L'Ecuyer, "Maximally Equidistributed Combined Tausworthe |
-- Generators". Mathematics of Computation, vol.65, no.213(1996), pp203--213. |
function rng (rnd: rand_var) return rand_var is |
variable new_rnd : rand_var; |
variable b : unsigned(31 downto 0); |
begin |
new_rnd :=rnd; |
b := ((new_rnd.s1 sll q1) xor new_rnd.s1) srl new_rnd.shft1; |
new_rnd.s1 := ((new_rnd.s1 and new_rnd.mask1) sll p1) xor b; |
b := ((new_rnd.s2 sll q2) xor new_rnd.s2) srl new_rnd.shft2; |
new_rnd.s2 := ((new_rnd.s2 and new_rnd.mask2) sll p2) xor b; |
b := ((new_rnd.s3 sll q3) xor new_rnd.s3) srl new_rnd.shft3; |
new_rnd.s3 := ((new_rnd.s3 and new_rnd.mask3) sll p3) xor b; |
new_rnd.rnd_v := new_rnd.s1 xor new_rnd.s2 xor new_rnd.s3; |
-- normalize to range [0,1) |
new_rnd.rnd := unsigned_2_real(new_rnd.rnd_v) / 65536.0; |
new_rnd.rnd := new_rnd.rnd / 65536.0; |
return (new_rnd); |
end rng; |
function rng (rnd : rand_var) return rand_var is |
variable new_rnd : rand_var; |
variable b : unsigned(31 downto 0); |
begin |
new_rnd := rnd; |
b := ((new_rnd.s1 sll q1) xor new_rnd.s1) srl new_rnd.shft1; |
new_rnd.s1 := ((new_rnd.s1 and new_rnd.mask1) sll p1) xor b; |
b := ((new_rnd.s2 sll q2) xor new_rnd.s2) srl new_rnd.shft2; |
new_rnd.s2 := ((new_rnd.s2 and new_rnd.mask2) sll p2) xor b; |
b := ((new_rnd.s3 sll q3) xor new_rnd.s3) srl new_rnd.shft3; |
new_rnd.s3 := ((new_rnd.s3 and new_rnd.mask3) sll p3) xor b; |
new_rnd.rnd_v := new_rnd.s1 xor new_rnd.s2 xor new_rnd.s3; |
-- normalize to range [0,1) |
new_rnd.rnd := unsigned_2_real(new_rnd.rnd_v) / 65536.0; |
new_rnd.rnd := new_rnd.rnd / 65536.0; |
return (new_rnd); |
end rng; |
|
-- rand function generates a random variable with different distributions |
function rand (rnd: rand_var) return rand_var is |
variable rnd_out : rand_var; |
variable x,y,z : real; |
variable t: real := 0.0; |
begin |
case rnd.dist is |
-- Uniform distribution |
when UNIFORM => |
rnd_out := rng(rnd); |
rnd_out.rnd := rnd.y + (rnd_out.rnd * (rnd.z - rnd.y)); |
-- Gaussian distribution |
when GAUSSIAN => -- Box-Mueller method |
z := 2.0; |
rnd_out := rnd; |
while z > 1.0 or z = 0.0 loop |
-- choose x,y in uniform square (-1,-1) to (+1,+1) |
rnd_out := rng(rnd_out); |
x := -1.0 + 2.0 * rnd_out.rnd; |
rnd_out := rng(rnd_out); |
y := -1.0 + 2.0 * rnd_out.rnd; |
z := (x * x) + (y * y); |
end loop; |
-- Box-Mueller transform |
rnd_out.rnd := rnd_out.y + rnd_out.z * y * sqrt(-2.0 * log(z)/z); |
-- Exponential distribution |
when EXPONENTIAL => |
rnd_out := rng(rnd); |
rnd_out.rnd := -rnd_out.y * log(1.0 - rnd_out.rnd); |
when others => |
report "rand() function encountered an error!" |
severity failure; |
end case; |
return (rnd_out); |
end rand; |
function rand (rnd : rand_var) return rand_var is |
variable rnd_out : rand_var; |
variable x, y, z : real; |
variable t : real := 0.0; |
begin |
case rnd.dist is |
-- Uniform distribution |
when UNIFORM => |
rnd_out := rng(rnd); |
rnd_out.rnd := rnd.y + (rnd_out.rnd * (rnd.z - rnd.y)); |
-- Gaussian distribution |
when GAUSSIAN => -- Box-Mueller method |
z := 2.0; |
rnd_out := rnd; |
while z > 1.0 or z = 0.0 loop |
-- choose x,y in uniform square (-1,-1) to (+1,+1) |
rnd_out := rng(rnd_out); |
x := -1.0 + 2.0 * rnd_out.rnd; |
rnd_out := rng(rnd_out); |
y := -1.0 + 2.0 * rnd_out.rnd; |
z := (x * x) + (y * y); |
end loop; |
-- Box-Mueller transform |
rnd_out.rnd := rnd_out.y + rnd_out.z * y * sqrt(-2.0 * log(z)/z); |
-- Exponential distribution |
when EXPONENTIAL => |
rnd_out := rng(rnd); |
rnd_out.rnd := -rnd_out.y * log(1.0 - rnd_out.rnd); |
when others => |
report "rand() function encountered an error!" |
severity failure; |
end case; |
return (rnd_out); |
end rand; |
|
-- Initialize seeds, used by all init_ functions |
function gen_seed (constant a, b, c: natural) return rand_var is |
variable seeded : rand_var; |
variable x : unsigned(31 downto 0):= "11111111111111111111111111111111"; |
constant k1: natural:=31; |
constant k2: natural:=29; |
constant k3: natural:=28; |
begin |
seeded.shft1 := k1-p1; |
seeded.shft2 := k2-p2; |
seeded.shft3 := k3-p3; |
seeded.mask1 := x sll (32-k1); |
seeded.mask2 := x sll (32-k2); |
seeded.mask3 := x sll (32-k3); |
seeded.s1 := to_unsigned(390451501, 32); |
seeded.s2 := to_unsigned(613566701, 32); |
seeded.s3 := to_unsigned(858993401, 32); |
if to_unsigned(a, 32) > (to_unsigned(1,32) sll (32-k1)) then |
seeded.s1 := to_unsigned(a, 32); |
end if; |
if to_unsigned(b, 32) > (to_unsigned(1,32) sll (32-k2)) then |
seeded.s2 := to_unsigned(b, 32); |
end if; |
if to_unsigned(c, 32) > (to_unsigned(1,32) sll (32-k3)) then |
seeded.s3 := to_unsigned(c, 32); |
end if; |
return(seeded); |
end gen_seed; |
|
function gen_seed (constant a, b, c : natural) return rand_var is |
variable seeded : rand_var; |
variable x : unsigned(31 downto 0) := "11111111111111111111111111111111"; |
constant k1 : natural := 31; |
constant k2 : natural := 29; |
constant k3 : natural := 28; |
begin |
seeded.shft1 := k1-p1; |
seeded.shft2 := k2-p2; |
seeded.shft3 := k3-p3; |
seeded.mask1 := x sll (32-k1); |
seeded.mask2 := x sll (32-k2); |
seeded.mask3 := x sll (32-k3); |
seeded.s1 := to_unsigned(390451501, 32); |
seeded.s2 := to_unsigned(613566701, 32); |
seeded.s3 := to_unsigned(858993401, 32); |
if to_unsigned(a, 32) > (to_unsigned(1, 32) sll (32-k1)) then |
seeded.s1 := to_unsigned(a, 32); |
end if; |
if to_unsigned(b, 32) > (to_unsigned(1, 32) sll (32-k2)) then |
seeded.s2 := to_unsigned(b, 32); |
end if; |
if to_unsigned(c, 32) > (to_unsigned(1, 32) sll (32-k3)) then |
seeded.s3 := to_unsigned(c, 32); |
end if; |
return(seeded); |
end gen_seed; |
|
-- Uniform distribution random variable initialization |
-- a,b,c are seeds |
-- lo,hi is the range for the uniform distribution |
function init_uniform(constant a, b, c: natural; |
constant lo, hi: real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if lo >= hi then |
report "Uniform parameter error: 'hi' must be > 'lo'!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := UNIFORM; |
rnd.y := lo; |
rnd.z := hi; |
rout := rand(rnd); |
return(rout); |
end init_uniform; |
function init_uniform(constant a, b, c : natural; |
constant lo, hi : real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if lo >= hi then |
report "Uniform parameter error: 'hi' must be > 'lo'!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := UNIFORM; |
rnd.y := lo; |
rnd.z := hi; |
rout := rand(rnd); |
return(rout); |
end init_uniform; |
|
-- Gaussian distribution random variable initialization |
-- a,b,c are seeds |
-- mean,stdev is mean and standard deviation |
function init_gaussian(constant a, b, c: natural; |
constant mean, stdev: real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if stdev = 0.0 then |
report "Gaussian parameter error: 'stdev' must be non-zero!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := GAUSSIAN; |
rnd.y := mean; |
rnd.z := stdev; |
rout := rand(rnd); |
return(rout); |
end init_gaussian; |
function init_gaussian(constant a, b, c : natural; |
constant mean, stdev : real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if stdev = 0.0 then |
report "Gaussian parameter error: 'stdev' must be non-zero!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := GAUSSIAN; |
rnd.y := mean; |
rnd.z := stdev; |
rout := rand(rnd); |
return(rout); |
end init_gaussian; |
|
-- Exponential distribution random variable initialization |
-- a,b,c are seeds |
-- mean: mean value |
function init_exponential(constant a, b, c: natural; |
constant mean: real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if mean <= 0.0 then |
report "Exponential parameter error: 'mean' must be > 0!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := EXPONENTIAL; |
rnd.y := mean; |
rout := rand(rnd); |
return(rout); |
end init_exponential; |
|
function init_exponential(constant a, b, c : natural; |
constant mean : real) return rand_var is |
variable rnd, rout : rand_var; |
begin |
if mean <= 0.0 then |
report "Exponential parameter error: 'mean' must be > 0!" |
severity failure; |
end if; |
rnd := gen_seed(a, b, c); |
rnd.dist := EXPONENTIAL; |
rnd.y := mean; |
rout := rand(rnd); |
return(rout); |
end init_exponential; |
|
end rng_lib; |