XorShift-Add法による擬似乱数生成VHDLパッケージ

#XORSHIFT-ADD (xsadd) Pseudo Random Number Generator VHDL Package and RTL.

ソースコード一式はgistにあります。
[XORSHIFT-ADD (xsadd) Pseudo Random Number Generator VHDL Package and RTL.](https://gist.github.com/ikwzm/24ea1ac481e3a2e80803)

#Overview

##Introduction

XORSHIFT-ADD(XSadd)法による擬似乱数生成パッケージと論理合成可能なサンプル回路です。

XORSHIFT-ADD(XSadd)法に関してはこちらを参照してください。
[XORSHIFT_ADD(XSadd): A variant of XORSHIFT](http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/XSADD/index-jp.html)

実は XORSHIFT-ADD は Tiny Mersenne Twister と同じ方が作りました。そのせいか、 [「Tiny Merrsene Twister(tinymt32)法による擬似乱数生成パッケージ」](http://qiita.com/ikwzm/items/73616e155642570e1930)で紹介したソースコードとほとんど同じようになっています（比較してみるとびっくりするほど似ている）。

[「XorShift-Add法による擬似乱数生成回路」](http://qiita.com/ikwzm/items/420084eef005ac3ec53b)に、このVHDLパッケージを使って実際にFPGAに実装した例があります。あわせて参考にしてください。

##Features

 * 単精度の浮動小数点はサポートしていません。32ビット整数か実数のみです。
 * xsadd.vhd は擬似乱数生成パッケージです。
   この擬似乱数生成パッケージは、テストベンチなどのモデルからも、論理回路からも使えるようになっています。
 * xsadd_gen.vhd は論理合成可能な擬似乱数生成回路の簡単なサンプルです。

##Licensing

二条項BSDライセンス (2-clause BSD license) で公開しています。

#Source Code

参考までにソースコードを貼っておきます。

##xsadd.vhd(擬似乱数生成パッケージ)

````VHDL:xsadd.vhd
-----------------------------------------------------------------------------------
--!     @file    xsadd.vhd
--!     @brief   Pseudo Random Number Generator Package(XORSHIFT-ADD).
--!     @version 1.0.0
--!     @date    2016/3/25
--!     @author  Ichiro Kawazome <ichiro_k@ca2.so-net.ne.jp>
-----------------------------------------------------------------------------------
--
--      Copyright (C) 2016 Ichiro Kawazome
--      All rights reserved.
--
--      Redistribution and use in source and binary forms, with or without
--      modification, are permitted provided that the following conditions
--      are met:
--
--        1. Redistributions of source code must retain the above copyright
--           notice, this list of conditions and the following disclaimer.
--
--        2. Redistributions in binary form must reproduce the above copyright
--           notice, this list of conditions and the following disclaimer in
--           the documentation and/or other materials provided with the
--           distribution.
--
--      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
--      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
--      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
--      A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
--      OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
--      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
--      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
--      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
--      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
--      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
--      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-----------------------------------------------------------------------------------
library ieee;
use     ieee.std_logic_1164.all;
use     ieee.numeric_std.all;
-----------------------------------------------------------------------------------
--! @brief   Pseudo Random Number Generator Package(XORSHIFT-ADD).
-----------------------------------------------------------------------------------
package XSADD is
    -------------------------------------------------------------------------------
    --! @brief Type of Random Number.
    -------------------------------------------------------------------------------
    subtype  RANDOM_NUMBER_TYPE   is unsigned(31 downto 0);
    -------------------------------------------------------------------------------
    --! @brief Vector of Random Number.
    -------------------------------------------------------------------------------
    type     RANDOM_NUMBER_VECTOR is array(integer range <>) of RANDOM_NUMBER_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Convert Integer to RANDOM_NUMBER_TYPE
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    arg       Integer.
    --! @return             Generated random number.
    -------------------------------------------------------------------------------
    function TO_RANDOM_NUMBER_TYPE(arg:integer) return RANDOM_NUMBER_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Type of Seed Number for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    subtype  SEED_TYPE            is unsigned(31 downto 0);
    -------------------------------------------------------------------------------
    --! @brief Vector of Seed Number for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    type     SEED_VECTOR          is array(integer range <>) of SEED_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Convert Integer to SEED_TYPE
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    arg       Integer.
    --! @return             Generated seed number.
    -------------------------------------------------------------------------------
    function TO_SEED_TYPE(arg:integer) return SEED_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Type of Record for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    type     PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE is record
        status  : RANDOM_NUMBER_VECTOR(0 to 3);
    end record;    
    -------------------------------------------------------------------------------
    --! @brief Generate instance for Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    seed      Seed Number for Pseudo Random Number Generator.
    --! @return             Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    function  NEW_PSEUDO_RANDOM_NUMBER_GENERATOR(
                 seed      :       SEED_TYPE
    )            return            PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Generate instance for Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    seed      Seed Number Vector for Pseudo Random Number Generator.
    --! @return             Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    function  NEW_PSEUDO_RANDOM_NUMBER_GENERATOR(
                 seed      :       SEED_VECTOR
    )            return            PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Initialize Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    mat1      Parameter for Pseudo Random Number Generator.
    --! @param    mat2      Parameter for Pseudo Random Number Generator.
    --! @param    tmat      Parameter for Pseudo Random Number Generator.
    --! @param    seed      Seed Number for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
                 seed      : in    SEED_TYPE
    );
    -------------------------------------------------------------------------------
    --! @brief Initialize Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    seed      Seed Number Vector for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
                 seed      : in    SEED_VECTOR
    );
    -------------------------------------------------------------------------------
    --! @brief This function changes internal state of tinymt32.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! * Users should not call this function directly.
    --! @param    generator Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    );
    -------------------------------------------------------------------------------
    --! @brief This function outputs 32-bit unsigned integer from internal state.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! * Users should not call this function directly.
    --! @param    generator Pseudo Random Number Generator.
    --! @return             Generated temper number.
    -------------------------------------------------------------------------------
    function  GENERATE_TEMPER(
                 generator : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    )            return      RANDOM_NUMBER_TYPE;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_NUMBER(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   RANDOM_NUMBER_TYPE
    );
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on (std_logic_vector).
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_STD_LOGIC_VECTOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   std_logic_vector
    );
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,0x7fffffff]-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_INT31(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   integer
    );
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,1]-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL1(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    );
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,1)-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL2(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    );
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on (0,1)-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL3(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    );
end     XSADD;
-----------------------------------------------------------------------------------
-- 
-----------------------------------------------------------------------------------
library ieee;
use     ieee.std_logic_1164.all;
use     ieee.numeric_std.all;
package body XSADD is
    -------------------------------------------------------------------------------
    -- Period parameters
    -------------------------------------------------------------------------------
    constant  SH1             : integer :=  15;
    constant  SH2             : integer :=  18;
    constant  SH3             : integer :=  11;
    constant  MIN_LOOP        : integer :=   8;
    constant  PRE_LOOP        : integer :=   8;
    -------------------------------------------------------------------------------
    --! @brief Convert Integer to SEED_TYPE
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    arg       Integer.
    --! @return             Generated seed number.
    -------------------------------------------------------------------------------
    function  TO_SEED_TYPE(arg:integer) return SEED_TYPE is
    begin
        return to_unsigned(arg,SEED_TYPE'length);
    end function;
    -------------------------------------------------------------------------------
    --! @brief Convert Integer to RANDOM_NUMBER_TYPE
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    arg       Integer.
    --! @return             Generated random number.
    -------------------------------------------------------------------------------
    function  TO_RANDOM_NUMBER_TYPE(arg:integer) return RANDOM_NUMBER_TYPE is
    begin
        return to_unsigned(arg,RANDOM_NUMBER_TYPE'length);
    end function;
    -------------------------------------------------------------------------------
    --! @brief Convert from Random Number to real.
    ---------------------------------------------------------------------------
    function  TO_REAL(arg:RANDOM_NUMBER_TYPE) return real is
        variable result: real := 0.0;
    begin
        for i in arg'range loop
            result := result + result;
            if (arg(i) = '1') then
                result := result + 1.0;
            end if;
        end loop;
        return result;
    end function;
    -------------------------------------------------------------------------------
    --! @brief RANDOM_NUMBER_TYPE multiplied by integer.
    -------------------------------------------------------------------------------
    function MUL_K(k:integer;arg:RANDOM_NUMBER_TYPE) return RANDOM_NUMBER_TYPE is
        variable tmp : unsigned(2*RANDOM_NUMBER_TYPE'length-1 downto 0);
    begin
        tmp := arg * TO_RANDOM_NUMBER_TYPE(k);
        return tmp(RANDOM_NUMBER_TYPE'range);
    end function;
    -------------------------------------------------------------------------------
    --! @brief Generate instance for Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    seed      Seed Number for Pseudo Random Number Generator.
    --! @return             Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    function  NEW_PSEUDO_RANDOM_NUMBER_GENERATOR(
        seed    : SEED_TYPE
    )   return    PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    is
        variable generator : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    begin
        INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator,seed);
        return generator;
    end function;
    -------------------------------------------------------------------------------
    --! @brief Generate instance for Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    seed      Seed Number Vector for Pseudo Random Number Generator.
    --! @return             Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    function  NEW_PSEUDO_RANDOM_NUMBER_GENERATOR(
        seed    : SEED_VECTOR
    )   return    PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    is
        variable generator : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    begin
        INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator,seed);
        return generator;
    end function;
    -------------------------------------------------------------------------------
    --! @brief This function certificate the period of 2^127-1.
    -------------------------------------------------------------------------------
    procedure period_certification(generator:inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE) is
    begin 
        if ((generator.status(0) = 0) and
            (generator.status(1) = 0) and
            (generator.status(2) = 0) and
            (generator.status(3) = 0)) then
             generator.status(0) := TO_RANDOM_NUMBER_TYPE(character'pos('X'));
	     generator.status(1) := TO_RANDOM_NUMBER_TYPE(character'pos('S'));
	     generator.status(2) := TO_RANDOM_NUMBER_TYPE(character'pos('A'));
	     generator.status(3) := TO_RANDOM_NUMBER_TYPE(character'pos('D'));
        end if;
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Initialize Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    seed      Seed Number for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
                 seed      : in    SEED_TYPE
    ) is
    begin 
        generator.status(0) := seed;
        generator.status(1) := TO_RANDOM_NUMBER_TYPE(0);
        generator.status(2) := TO_RANDOM_NUMBER_TYPE(0);
        generator.status(3) := TO_RANDOM_NUMBER_TYPE(0);
        for i in 1 to MIN_LOOP-1 loop
            generator.status(i mod 4) := generator.status(i mod 4) xor
                                         (MUL_K(1812433253,
                                               ((generator.status((i-1) mod 4)) xor
                                                (generator.status((i-1) mod 4) srl 30))) + i);
        end loop;
        period_certification(generator);
        for i in 0 to PRE_LOOP-1 loop
           NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        end loop;
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Initialize Pseudo Random Number Generator.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    seed      Seed Number Vector for Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure INIT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
                 seed      : in    SEED_VECTOR
    ) is
        constant lag       : integer := 1;
        constant mid       : integer := 1;
        constant size      : integer := 4;
        variable i,j       : integer;
        variable count     : integer;
        variable r         : RANDOM_NUMBER_TYPE;
        alias    init_key  : SEED_VECTOR(1 to seed'length) is seed;
        function ini_func1(x:RANDOM_NUMBER_TYPE) return RANDOM_NUMBER_TYPE is
        begin 
            return MUL_K(1664525   ,(x xor (x srl 27)));
        end function;
        function ini_func2(x:RANDOM_NUMBER_TYPE) return RANDOM_NUMBER_TYPE is
        begin 
            return MUL_K(1566083941,(x xor (x srl 27)));
        end function;
    begin
        generator.status(0) := TO_RANDOM_NUMBER_TYPE(0);
        generator.status(1) := TO_RANDOM_NUMBER_TYPE(0);
        generator.status(2) := TO_RANDOM_NUMBER_TYPE(0);
        generator.status(3) := TO_RANDOM_NUMBER_TYPE(0);
        if (init_key'length + 1 > MIN_LOOP) then
            count := init_key'length + 1;
        else
            count := MIN_LOOP;
        end if;
        i := 0;
        for j in 0 to count-1 loop
            r := ini_func1(generator.status(i) xor
                           generator.status((i+mid) mod size) xor
                           generator.status((i+size-1) mod size));
            generator.status((i+mid    ) mod size) := generator.status((i+mid    ) mod size) + r;
            if    (j = 0) then
                r := r + init_key'length;
            elsif (init_key'low <= j and j <= init_key'high) then
                r := r + init_key(j) + i;
            else
                r := r + i;
            end if;
            generator.status((i+mid+lag) mod size) := generator.status((i+mid+lag) mod size) + r;
            generator.status(i) := r;
            i := (i + 1) mod size;
        end loop;
        for j in 0 to size-1 loop
            r := ini_func2(generator.status(i) +
                           generator.status((i+mid   ) mod size) +
                           generator.status((i+size-1) mod size));
            generator.status((i+mid    ) mod size) := generator.status((i+mid    ) mod size) xor r;
            r := r - i;
            generator.status((i+mid+lag) mod size) := generator.status((i+mid+lag) mod size) xor r;
            generator.status(i) := r;
            i := (i + 1) mod size;
        end loop;
        period_certification(generator);
        for i in 0 to PRE_LOOP-1 loop
            NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        end loop;
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief This function changes internal state of tinymt32.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! * Users should not call this function directly.
    --! @param    generator Pseudo Random Number Generator.
    -------------------------------------------------------------------------------
    procedure NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(
        variable generator  : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    ) is
        variable t          :       RANDOM_NUMBER_TYPE;
    begin
        t := generator.status(0);
        t := t xor (t sll SH1);
        t := t xor (t srl SH2);
        t := t xor (generator.status(3) sll SH3);
        generator.status(0) := generator.status(1);
        generator.status(1) := generator.status(2);
        generator.status(2) := generator.status(3);
        generator.status(3) := t;
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief This function outputs 32-bit unsigned integer from internal state.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! * Users should not call this function directly.
    --! @param    generator Pseudo Random Number Generator.
    --! @return             Generated temper number.
    -------------------------------------------------------------------------------
    function GENERATE_TEMPER(
                 generator  :       PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE
    )            return             RANDOM_NUMBER_TYPE
    is
    begin
        return generator.status(3) + generator.status(2);
    end function;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_NUMBER(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   RANDOM_NUMBER_TYPE
    ) is
    begin 
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        number := GENERATE_TEMPER(generator);
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on (std_logic_vector).
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_STD_LOGIC_VECTOR(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   std_logic_vector
    ) is
        variable word      :       RANDOM_NUMBER_TYPE;
        variable number_t  :       std_logic_vector(number'length-1 downto 0);
    begin
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        word := GENERATE_TEMPER(generator);
        for i in number_t'range loop
            if (word(i) = '1') then
                number_t(i) := '1';
            else
                number_t(i) := '0';
            end if;
        end loop;  
        number := number_t;
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,0x7fffffff]-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_INT31(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   integer
    ) is
        variable word      :       RANDOM_NUMBER_TYPE;
    begin
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        word := GENERATE_TEMPER(generator);
        number := to_integer(word(31 downto 1));
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,1]-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL1(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    ) is
        variable word      :       RANDOM_NUMBER_TYPE;
    begin
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        word := GENERATE_TEMPER(generator);
        number := (1.0/4294967295.0)*TO_REAL(word);
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on [0,1)-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL2(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    ) is
        variable word      :       RANDOM_NUMBER_TYPE;
    begin
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        word := GENERATE_TEMPER(generator);
        number := (1.0/4294967296.0)*TO_REAL(word);
    end procedure;
    -------------------------------------------------------------------------------
    --! @brief Generates a random number on (0,1)-real-interval.
    --! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    --! @param    generator Pseudo Random Number Generator.
    --! @param    number    Generated random number.
    -------------------------------------------------------------------------------
    procedure GENERATE_RANDOM_REAL3(
        variable generator : inout PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        variable number    : out   real
    ) is
        variable word      :       RANDOM_NUMBER_TYPE;
    begin
        NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(generator);
        word := GENERATE_TEMPER(generator);
        number := (1.0/4294967296.0)*(0.5+TO_REAL(word));
    end procedure;
end     XSADD;
````

##xsadd_gen.vhd(擬似乱数生成回路のサンプル)

````VHDL:xsadd_gen.vhd
-----------------------------------------------------------------------------------
--!     @file    xsadd_gen.vhd
--!     @brief   Pseudo Random Number Generator (XORSHIFT-ADD).
--!     @version 1.0.0
--!     @date    2016/3/25
--!     @author  Ichiro Kawazome <ichiro_k@ca2.so-net.ne.jp>
-----------------------------------------------------------------------------------
--
--      Copyright (C) 2016 Ichiro Kawazome
--      All rights reserved.
--
--      Redistribution and use in source and binary forms, with or without
--      modification, are permitted provided that the following conditions
--      are met:
--
--        1. Redistributions of source code must retain the above copyright
--           notice, this list of conditions and the following disclaimer.
--
--        2. Redistributions in binary form must reproduce the above copyright
--           notice, this list of conditions and the following disclaimer in
--           the documentation and/or other materials provided with the
--           distribution.
--
--      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
--      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
--      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
--      A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
--      OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
--      SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
--      LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
--      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
--      THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
--      (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
--      OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--
-----------------------------------------------------------------------------------
library ieee;
use     ieee.std_logic_1164.all;
use     work.XSADD.RANDOM_NUMBER_TYPE;
use     work.XSADD.PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
entity  XSADD_GEN is
    port (
        CLK         : in  std_logic;
        RST         : in  std_logic;
        INIT        : in  std_logic;
        INIT_PARAM  : in  PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
        RND_RUN     : in  std_logic;
        RND_VAL     : out std_logic;
        RND_NUM     : out RANDOM_NUMBER_TYPE
    );
end     XSADD_GEN;
-----------------------------------------------------------------------------------
--
-----------------------------------------------------------------------------------
library ieee;
use     ieee.std_logic_1164.all;
use     ieee.numeric_std.all;
use     work.XSADD.all;
architecture RTL of XSADD_GEN is
    constant  DEFAULT_PARAM    : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE :=
                                 NEW_PSEUDO_RANDOM_NUMBER_GENERATOR(
                                     TO_SEED_TYPE(1234)
                                 );
    signal    curr_status      : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    signal    status_valid     : std_logic;
begin
    process(CLK, RST)
        variable next_status   : PSEUDO_RANDOM_NUMBER_GENERATOR_TYPE;
    begin
        if (RST = '1') then
                curr_status  <= DEFAULT_PARAM;
                status_valid <= '0';
                RND_VAL      <= '0';
                RND_NUM      <= (others => '0');
        elsif (CLK'event and CLK = '1') then
            if (INIT = '1') then
                curr_status  <= INIT_PARAM;
                status_valid <= '0';
                RND_VAL      <= '0';
                RND_NUM      <= (others => '0');
            else
                if (RND_RUN = '1') then
                    next_status := curr_status;
                    NEXT_PSEUDO_RANDOM_NUMBER_GENERATOR(next_status);
                    curr_status  <= next_status;
                    status_valid <= '1';
                else
                    status_valid <= '0';
                end if;
                if (status_valid = '1') then
                    RND_NUM <= GENERATE_TEMPER(curr_status);
                    RND_VAL <= '1';
                else
                    RND_VAL <= '0';
                end if;
            end if;
        end if;
    end process;
end RTL;
````