OpenCores
URL https://opencores.org/ocsvn/rng_lib/rng_lib/trunk

Subversion Repositories rng_lib

[/] [rng_lib/] [trunk/] [bench/] [vhdl/] [rng_lib.vhd] - Blame information for rev 4

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 gedra
----------------------------------------------------------------------
2
----                                                              ----
3
---- Rand number generator library.                               ----
4
----                                                              ----
5
---- This file is part of the Random Number Generator project     ----
6
---- http://www.opencores.org/cores/rng_lib/                      ----
7
----                                                              ----
8
---- Description                                                  ----
9
---- This library has function for generation random numbers with ----
10
---- the following distributions:                                 ----
11
---- - Uniform (continous)                                        ----
12
---- - Exponential (continous)                                    ----
13
---- - Gaussian (continous)                                       ----
14
----                                                              ----
15
---- Random numbers are produced with a combination of 3          ----
16
---- Tausworthe generators which gives very good statistical      ----
17
---- properties.                                                  ----
18
----                                                              ----
19
---- NOTE! These functions will NOT synthesize. They are for test ----
20
----       bench use only!                                        ----
21
----                                                              ----
22
---- To Do:                                                       ----
23
---- -                                                            ----
24
----                                                              ----
25
---- Author(s):                                                   ----
26
---- - Geir Drange, gedra@opencores.org                           ----
27
----                                                              ----
28
----------------------------------------------------------------------
29
----                                                              ----
30
---- Copyright (C) 2004 Authors and OPENCORES.ORG                 ----
31
----                                                              ----
32
---- This source file may be used and distributed without         ----
33
---- restriction provided that this copyright statement is not    ----
34
---- removed from the file and that any derivative work contains  ----
35
---- the original copyright notice and the associated disclaimer. ----
36
----                                                              ----
37
---- This source file is free software; you can redistribute it   ----
38
---- and/or modify it under the terms of the GNU General          ----
39
---- Public License as published by the Free Software Foundation; ----
40
---- either version 2.0 of the License, or (at your option) any   ----
41
---- later version.                                               ----
42
----                                                              ----
43
---- This source is distributed in the hope that it will be       ----
44
---- useful, but WITHOUT ANY WARRANTY; without even the implied   ----
45
---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ----
46
---- PURPOSE. See the GNU General Public License for more details.----
47
----                                                              ----
48
---- You should have received a copy of the GNU General           ----
49
---- Public License along with this source; if not, download it   ----
50
---- from http://www.gnu.org/licenses/gpl.txt                     ----
51
----                                                              ----
52
----------------------------------------------------------------------
53
--
54
-- CVS Revision History
55
--
56
-- $Log: not supported by cvs2svn $
57
--
58
--
59
 
60
library ieee;
61
use ieee.std_logic_1164.all;
62
use ieee.numeric_std.all;
63
use std.textio.all;
64
use work.math_lib.all;
65
 
66
package rng_lib is
67
 
68
  type distribution is (UNIFORM, GAUSSIAN, EXPONENTIAL);
69
  type rand_var is record  -- random variable record
70
                     rnd: real;         -- random number
71
                     rnd_v: unsigned(31 downto 0); -- random number vector
72
                     dist: distribution;      -- distribution type
73
                     y, z: real;        -- distribution parameters
74
                     s1, s2, s3: unsigned(31 downto 0);  -- seeds
75
                     mask1, mask2, mask3: unsigned(31 downto 0);
76
                     shft1, shft2, shft3: natural;
77
                   end record;
78
 
79
  function rand (rnd: rand_var) return rand_var;
80
  function init_uniform(constant a, b, c: natural;
81
                        constant lo, hi: real) return rand_var;
82
  function init_gaussian(constant a, b, c: natural;
83
                         constant mean, stdev: real) return rand_var;
84
  function init_exponential(constant a, b, c: natural;
85
                        constant mean: real) return rand_var;
86
 
87
  constant q1: natural:=13;
88
  constant q2: natural:=2;
89
  constant q3: natural:=3;
90
  constant p1: natural:=12;
91
  constant p2: natural:=4;
92
  constant p3: natural:=17;
93
 
94
end rng_lib;
95
 
96
package body rng_lib is
97
 
98
-- Function to convert 32bit unsigned vector to real
99
-- Integers only go to 2**31 (VHDL'87), so do it clever
100
  function unsigned_2_real (constant a: unsigned(31 downto 0)) return real is
101
    variable r: real;
102
  begin
103
    r := 2.0*real(to_integer(a(31 downto 1)));
104
    if a(0) = '1' then
105
      r := r + 1.0;
106
    end if;
107
    return(r);
108
  end unsigned_2_real;
109
 
110
-- Generate random number using a combination of 3 tausworthe generators 
111
-- Source: Pierre L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
112
-- Generators". Mathematics of Computation, vol.65, no.213(1996), pp203--213.
113
  function rng (rnd: rand_var) return rand_var is
114
    variable new_rnd : rand_var;
115
    variable b : unsigned(31 downto 0);
116
  begin
117
    new_rnd :=rnd;
118
    b := ((new_rnd.s1 sll q1) xor new_rnd.s1) srl new_rnd.shft1;
119
    new_rnd.s1 := ((new_rnd.s1 and new_rnd.mask1) sll p1) xor b;
120
    b := ((new_rnd.s2 sll q2) xor new_rnd.s2) srl new_rnd.shft2;
121
    new_rnd.s2 := ((new_rnd.s2 and new_rnd.mask2) sll p2) xor b;
122
    b := ((new_rnd.s3 sll q3) xor new_rnd.s3) srl new_rnd.shft3;
123
    new_rnd.s3 := ((new_rnd.s3 and new_rnd.mask3) sll p3) xor b;
124
    new_rnd.rnd_v := new_rnd.s1 xor new_rnd.s2 xor new_rnd.s3;
125
    -- normalize to range [0,1)
126
    new_rnd.rnd := unsigned_2_real(new_rnd.rnd_v) / 65536.0;
127
    new_rnd.rnd := new_rnd.rnd / 65536.0;
128
    return (new_rnd);
129
  end rng;
130
 
131
-- rand function generates a random variable with different distributions
132
  function rand (rnd: rand_var) return rand_var is
133
    variable rnd_out : rand_var;
134
    variable x,y,z : real;
135
    variable t: real := 0.0;
136
  begin
137
    case rnd.dist is
138
      -- Uniform distribution
139
      when UNIFORM =>
140
        rnd_out := rng(rnd);
141
        rnd_out.rnd := rnd.y + (rnd_out.rnd * (rnd.z - rnd.y));
142
      -- Gaussian distribution
143
      when GAUSSIAN =>                  -- Box-Mueller method
144
        z := 2.0;
145
        rnd_out := rnd;
146
        while z > 1.0 or z = 0.0 loop
147
          -- choose x,y in uniform square (-1,-1) to (+1,+1)
148
          rnd_out := rng(rnd_out);
149
          x := -1.0 + 2.0 * rnd_out.rnd;
150
          rnd_out := rng(rnd_out);
151
          y := -1.0 + 2.0 * rnd_out.rnd;
152
          z := (x * x) + (y * y);
153
        end loop;
154
        -- Box-Mueller transform
155
        rnd_out.rnd := rnd_out.y + rnd_out.z * y * sqrt(-2.0 * log(z)/z);
156
      -- Exponential distribution
157
      when EXPONENTIAL =>
158
        rnd_out := rng(rnd);
159
        rnd_out.rnd := -rnd_out.y * log(1.0 - rnd_out.rnd);
160
      when others =>
161
        report "rand() function encountered an error!"
162
          severity failure;
163
    end case;
164
    return (rnd_out);
165
  end rand;
166
 
167
-- Initialize seeds, used by all init_ functions
168
  function gen_seed (constant a, b, c: natural) return rand_var is
169
    variable seeded : rand_var;
170
    variable x : unsigned(31 downto 0):= "11111111111111111111111111111111";
171
    constant k1: natural:=31;
172
    constant k2: natural:=29;
173
    constant k3: natural:=28;
174
  begin
175
    seeded.shft1 := k1-p1;
176
    seeded.shft2 := k2-p2;
177
    seeded.shft3 := k3-p3;
178
    seeded.mask1 := x sll (32-k1);
179
    seeded.mask2 := x sll (32-k2);
180
    seeded.mask3 := x sll (32-k3);
181
    seeded.s1 := to_unsigned(390451501, 32);
182
    seeded.s2 := to_unsigned(613566701, 32);
183
    seeded.s3 := to_unsigned(858993401, 32);
184
    if to_unsigned(a, 32) > (to_unsigned(1,32) sll (32-k1)) then
185
      seeded.s1 := to_unsigned(a, 32);
186
    end if;
187
    if to_unsigned(b, 32) > (to_unsigned(1,32) sll (32-k2)) then
188
      seeded.s2 := to_unsigned(b, 32);
189
    end if;
190
    if to_unsigned(c, 32) > (to_unsigned(1,32) sll (32-k3)) then
191
      seeded.s3 := to_unsigned(c, 32);
192
    end if;
193
    return(seeded);
194
  end gen_seed;
195
 
196
-- Uniform distribution random variable initialization
197
-- a,b,c are seeds
198
-- lo,hi is the range for the uniform distribution
199
  function init_uniform(constant a, b, c: natural;
200
                        constant lo, hi: real) return rand_var is
201
    variable rnd, rout : rand_var;
202
  begin
203
    if lo >= hi then
204
      report "Uniform parameter error: 'hi' must be > 'lo'!"
205
      severity failure;
206
    end if;
207
    rnd := gen_seed(a, b, c);
208
    rnd.dist := UNIFORM;
209
    rnd.y := lo;
210
    rnd.z := hi;
211
    rout := rand(rnd);
212
    return(rout);
213
  end init_uniform;
214
 
215
-- Gaussian distribution random variable initialization
216
-- a,b,c are seeds
217
-- mean,stdev is mean and standard deviation
218
  function init_gaussian(constant a, b, c: natural;
219
                        constant mean, stdev: real) return rand_var is
220
    variable rnd, rout : rand_var;
221
  begin
222
    if stdev = 0.0 then
223
      report "Gaussian parameter error: 'stdev' must be non-zero!"
224
      severity failure;
225
    end if;
226
    rnd := gen_seed(a, b, c);
227
    rnd.dist := GAUSSIAN;
228
    rnd.y := mean;
229
    rnd.z := stdev;
230
    rout := rand(rnd);
231
    return(rout);
232
  end init_gaussian;
233
 
234
-- Exponential distribution random variable initialization
235
-- a,b,c are seeds
236
-- mean: mean value
237
  function init_exponential(constant a, b, c: natural;
238
                            constant mean: real) return rand_var is
239
    variable rnd, rout : rand_var;
240
  begin
241
    if mean <= 0.0 then
242
      report "Exponential parameter error: 'mean' must be > 0!"
243
      severity failure;
244
    end if;
245
    rnd := gen_seed(a, b, c);
246
    rnd.dist := EXPONENTIAL;
247
    rnd.y := mean;
248
    rout := rand(rnd);
249
    return(rout);
250
  end init_exponential;
251
 
252
end rng_lib;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.