-- -- 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 ;