FC2カウンター FPGAの部屋 XORShiftを試してみた1(XORShift.vhd)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

XORShiftを試してみた1(XORShift.vhd)

なひたふさんの月刊 特電技術 第2号に載っている擬似乱数発生回路XORShift を試してみた。
このブログの掲載については、ツィッターで @nahitafu さんに許可をいただきました。ありがとうございました。

さて、なひたふさんのVHDLコードは、conv_std_logic_vector を使用していて、numeric_stdパッケージでは使用できないので、多少書き換えさせていただいた。下にVHDLコードを示す。

-- XORShift.vhd
-- 擬似乱数発生回路
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

entity XORShift is
    port(
        clk :         in std_logic;
        reset :        in std_logic;
        enable :    in std_logic;
        result :    out std_logic_vector(31 downto 0)
    );
end XORShift;

architecture RTL of XORShift is
signal x:    unsigned(31 downto 0);
signal y:    unsigned(31 downto 0);
signal z:    unsigned(31 downto 0);
signal w:    unsigned(31 downto 0);
begin
    process(clk)
        variable t:    unsigned(31 downto 0);
    begin
        if clk'event and clk='1' then
            if reset='1' then
                x <= TO_UNSIGNED(123456789, 32);
                y <= TO_UNSIGNED(362436069, 32);
                z <= TO_UNSIGNED(521288629, 32);
                w <= TO_UNSIGNED(88675123, 32);
            elsif enable='1' then
                t := x xor (x(20 downto 0) & TO_UNSIGNED(0, 11));
                x <= y;
                y <= z;
                z <= w;
                w <= (w xor (TO_UNSIGNED(0, 19) & w(31 downto 19))) xor (t xor (TO_UNSIGNED(0, 8) & t(31 downto 8)));
            end if;
        end if;
    end process;
    result <= STD_LOGIC_VECTOR(w);
end RTL;


XORShift.vhd のテストベンチとして、XORShift_test_tb.v を作成した。そのVerilog コードを下に示す。

// XORShift_test_tb.v
// XORShift.vhd のテスト
// 2000個のXORShiftの出力をRAMDOM_NUM_LIMIT個、ファイルに書き出す
// 

`default_nettype none

`timescale 100ps / 1ps

module XORShift_test_tb;
    parameter    RAMDOM_NUM_LIMIT = 2000;
    integer     F_HANDLE;
    integer        count = 0;
    wire clk;
    wire reset;
    wire    [31:0]    result;
    
    // clk のインスタンス
    clk_gen #(
        .CLK_PERIOD(100),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(clk)
    );
    
    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b1),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(reset)
    );
    
    // XORShift のインスタンス
    XORShift XORShift_i (
        .clk(clk),
        .reset(reset),
        .enable(1'b1),
        .result(result)
    );
    
    initial F_HANDLE = $fopen("XORShift_dump.log");
    
    always @(posedge clk) begin
        if (reset == 1'b0) begin
            if (count < RAMDOM_NUM_LIMIT) begin
                #1;
                $fdisplay(F_HANDLE, "%x", result);
                count = count + 1;
            end else begin
                $fclose(F_HANDLE);
                $stop;
            end
        end
    end
            
endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out
);
    begin
        initial begin
            reset_out = RESET_STATE;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
        end
    end
endmodule

`default_nettype wire


上記のテストベンチを$STOPするまで走らせると、XORShift_dump.logに2000個ランダムな値が保存される。
下にシミュレーションの波形を示す。
XORShift_1_120424.png

XORShift_dump.log の値の一部を下に示す。

dca345ea
1b5116e6
951049aa
d88d00b0
1ec7825e
8db24146
9af81443
2ac00f2c
0837ad58
17906569
4d9031d4
6703ee25
d2ebd2f0
46c45ee9
8a16d974
f21c7cd5
7eec4c34
1abb6616
265ac14c


次は、M系列も同様にやってみて、その数列のランダム性を検証してみたい。
通常は自己相関をとると思うのだが、今回は自己相関とビットのランダム性を検証してみたい。具体的には、XORを取って、1の数を数えてみようと思っている。
  1. 2013年04月24日 05:42 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/2448-bcdd3dba
この記事にトラックバックする(FC2ブログユーザー)