⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rng_lib.vhd

📁 此代码用于产生系统设计仿真阶段需要的仿真数据
💻 VHD
字号:
--------------------------------------------------------------------------                                                              -------- Rand number generator library.                               --------                                                              -------- This file is part of the Random Number Generator project     -------- http://www.opencores.org/cores/rng_lib/                      --------                                                              -------- Description                                                  -------- This library has function for generation random numbers with -------- the following distributions:                                 -------- - Uniform (continous)                                        -------- - Exponential (continous)                                    -------- - Gaussian (continous)                                       --------                                                              -------- Random numbers are produced with a combination of 3          -------- Tausworthe generators which gives very good statistical      -------- properties.                                                  --------                                                              -------- NOTE! These functions will NOT synthesize. They are for test --------       bench use only!                                        --------                                                              -------- To Do:                                                       -------- -                                                            --------                                                              -------- Author(s):                                                   -------- - Geir Drange, gedra@opencores.org                           --------                                                              ------------------------------------------------------------------------------                                                              -------- Copyright (C) 2004 Authors and OPENCORES.ORG                 --------                                                              -------- This source file may be used and distributed without         -------- restriction provided that this copyright statement is not    -------- removed from the file and that any derivative work contains  -------- the original copyright notice and the associated disclaimer. --------                                                              -------- This source file 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.0 of the License, or (at your option) any   -------- later version.                                               --------                                                              -------- This source is distributed in the hope that it will be       -------- useful, but WITHOUT ANY WARRANTY; without even the implied   -------- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      -------- PURPOSE. See the GNU General Public License for more details.--------                                                              -------- You should have received a copy of the GNU General           -------- Public License along with this source; if not, download it   -------- from http://www.gnu.org/licenses/gpl.txt                     --------                                                              ------------------------------------------------------------------------------ CVS Revision History---- $Log: rng_lib.vhd,v $-- Revision 1.2  2007/10/14 13:35:04  gedra-- Code beautification---- 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;use std.textio.all;use work.math_lib.all;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;   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-- 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;-- 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;-- 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;-- 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;-- 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;-- 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;-- 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;   end rng_lib;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -