Library of reusable VHDL components
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

224 lines
8.2 KiB

--
-- File Name: RandomBasePkg.vhd
-- Design Unit Name: RandomBasePkg
-- Revision: STANDARD VERSION, revision 2.0, VHDL-2008
--
-- Maintainer: Jim Lewis email: jim@synthworks.com
-- Contributor(s):
-- Jim Lewis jim@synthworks.com
--
--
-- Description:
-- Defines Base randomization, seed definition, seed generation,
-- and seed IO functionality for RandomPkg.vhd
-- Defines:
-- Procedure Uniform - baseline randomization
-- Type RandomSeedType - the seed as a single object
-- function GenRandSeed from integer_vector, integer, or string
-- IO function to_string, & procedures write, read
--
-- In revision 2.0 these types and functions are included by package reference.
-- Long term these will be passed as generics to RandomGenericPkg
--
--
-- Developed for:
-- SynthWorks Design Inc.
-- VHDL Training Classes
-- 11898 SW 128th Ave. Tigard, Or 97223
-- http://www.SynthWorks.com
--
-- Revision History:
-- Date Version Description
-- 01/2008: 0.1 Initial revision
-- Numerous revisions for VHDL Testbenches and Verification
-- 02/2009: 1.0 First Public Released Version
-- 02/25/2009 1.1 Replaced reference to std_2008 with a reference
-- to ieee_proposed.standard_additions.all ;
-- 03/01/2011 2.0 STANDARD VERSION
-- Fixed abstraction by moving RandomParmType to RandomPkg.vhd
--
--
-- Copyright (c) 2008, 2009, 2010, 2011 by SynthWorks Design Inc. All rights reserved.
--
-- Verbatim copies of this source file may be used and
-- distributed without restriction.
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the ARTISTIC License
-- as published by The Perl 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 Artistic License for details.
--
-- You should have received a copy of the license with this source.
-- If not download it from,
-- http://www.perlfoundation.org/artistic_license_2_0
--
library ieee ;
use ieee.math_real.all ;
use std.textio.all ;
-- comment out following 2 lines with VHDL-2008. Leave in for VHDL-2002
library ieee_proposed ; -- remove with VHDL-2008
use ieee_proposed.standard_additions.all ; -- remove with VHDL-2008
package RandomBasePkg is
-- RandomSeedType and Uniform can be replaced by any procedure that
-- produces a uniform distribution with 0 <= Value < 1 or 0 < Value < 1
-- and maintains the same call interface
type RandomSeedType is array (1 to 2) of integer ;
procedure Uniform (Result : out real ; Seed : inout RandomSeedType) ;
-- Translate from integer_vector, integer, or string to RandomSeedType
-- Required by RandomPkg.InitSeed
-- GenRandSeed makes sure all values are in a valid range
function GenRandSeed(IV : integer_vector) return RandomSeedType ;
function GenRandSeed(I : integer) return RandomSeedType ;
function GenRandSeed(S : string) return RandomSeedType ;
-- IO for RandomSeedType. If use subtype, then create aliases here
-- in a similar fashion VHDL-2008 std_logic_textio.
-- Not required by RandomPkg
function to_string(A : RandomSeedType) return string ;
procedure write(variable L: inout line ; A : RandomSeedType ) ;
procedure read (variable L: inout line ; A : out RandomSeedType ; good : out boolean ) ;
procedure read (variable L: inout line ; A : out RandomSeedType ) ;
end RandomBasePkg ;
-----------------------------------------------------------------
-----------------------------------------------------------------
package body RandomBasePkg is
-----------------------------------------------------------------
-- Uniform
-- Generate a random number with a Uniform distribution
-- Required by RandomPkg. All randomization is derived from here.
-- Value produced must be either:
-- 0 <= Value < 1 or 0 < Value < 1
--
-- Current version uses ieee.math_real.Uniform
-- This abstraction allows higher precision version
-- of a uniform distribution to be used provided
--
procedure Uniform (
Result : out real ;
Seed : inout RandomSeedType
) is
begin
ieee.math_real.Uniform (Seed(Seed'left), Seed(Seed'right), Result) ;
end procedure Uniform ;
-----------------------------------------------------------------
-- GenRandSeed
-- Convert integer_vector to RandomSeedType
-- Uniform requires two seed values of the form:
-- 1 <= SEED1 <= 2147483562; 1 <= SEED2 <= 2147483398
--
-- if 2 seed values are passed to GenRandSeed and they are
-- in the above range, then they must remain unmodified.
--
function GenRandSeed(IV : integer_vector) return RandomSeedType is
alias iIV : integer_vector(1 to IV'length) is IV ;
variable Seed1 : integer ;
variable Seed2 : integer ;
constant SEED1_MAX : integer := 2147483562 ;
constant SEED2_MAX : integer := 2147483398 ;
begin
if iIV'Length <= 0 then -- no seed
report "%%FATAL: GenRandSeed received NULL integer_vector" severity failure ;
return (3, 17) ; -- if continue seed = (3, 17)
elsif iIV'Length = 1 then -- one seed value
-- inefficient handling, but condition is unlikely
return GenRandSeed(iIV(1)) ; -- generate a seed
else -- only use the left two values
-- 1 <= SEED1 <= 2147483562
-- mod returns 0 to MAX-1, the -1 adjusts legal values, +1 adjusts them back
Seed1 := ((iIV(1)-1) mod SEED1_MAX) + 1 ;
-- 1 <= SEED2 <= 2147483398
Seed2 := ((iIV(2)-1) mod SEED2_MAX) + 1 ;
return (Seed1, Seed2) ;
end if ;
end function GenRandSeed ;
-----------------------------------------------------------------
-- GenRandSeed
-- transform a single integer into the internal seed
--
function GenRandSeed(I : integer) return RandomSeedType is
variable result : integer_vector(1 to 2) ;
begin
result(1) := I ;
result(2) := I/3 + 1 ;
return GenRandSeed(result) ; -- make value ranges legal
end function GenRandSeed ;
-----------------------------------------------------------------
-- GenRandSeed
-- transform a string value into the internal seed
-- usage: RV.GenRandSeed(RV'instance_path));
--
function GenRandSeed(S : string) return RandomSeedType is
constant LEN : integer := S'length ;
constant HALF_LEN : integer := LEN/2 ;
alias revS : string(LEN downto 1) is S ;
variable result : integer_vector(1 to 2) ;
variable temp : integer := 0 ;
begin
for i in 1 to HALF_LEN loop
temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ;
end loop ;
result(1) := temp ;
for i in HALF_LEN + 1 to LEN loop
temp := (temp + character'pos(revS(i))) mod (integer'right - 2**8) ;
end loop ;
result(2) := temp ;
return GenRandSeed(result) ; -- make value ranges legal
end function GenRandSeed ;
-----------------------------------------------------------------
function to_string(A : RandomSeedType) return string is
begin
return to_string(A(A'left)) & " " & to_string(A(A'right)) ;
end function to_string ;
-----------------------------------------------------------------
procedure write(variable L: inout line ; A : RandomSeedType ) is
begin
write(L, to_string(A)) ;
end procedure ;
-----------------------------------------------------------------
procedure read(variable L: inout line ; A : out RandomSeedType ; good : out boolean ) is
variable iGood : boolean ;
begin
for i in A'range loop
read(L, A(i), iGood) ;
exit when not iGood ;
end loop ;
good := iGood ;
end procedure read ;
-----------------------------------------------------------------
procedure read(variable L: inout line ; A : out RandomSeedType ) is
variable good : boolean ;
begin
read(L, A, good) ;
assert good report "read[line, RandomSeedType] failed" severity error ;
end procedure read ;
end RandomBasePkg ;