FC2カウンター FPGAの部屋 2013年04月25日
fc2ブログ

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

FPGAの部屋

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

XORShiftを試してみた2(M系列、m_seq_32.vh)

XORShiftを試してみた1(XORShift.vhd)”では、XORShift という擬似乱数回路を試してみた。
今回は、M系列を使用した32ビット長の擬似乱数を作ってみる。今まで書いたM系列のブログ記事を下に示す。
擬似乱数、M系列を使う1
擬似乱数、M系列を使う2

今回は、32ビット長のM系列回路を作成する。参考にさせて頂いたのは、”M系列の生成多項式”だ。ありがとうございます。
ここの 32: (32,22,2,1) を使用した。その Verilog ファイル、m_seq_32.v を下に示す。

// M sequence test(m_seq_32.v)

`default_nettype none

module m_seq_32(
    input    wire         clk,
    input    wire        reset,
    output    reg [31:0]    mseq32
    
);

    function [31:0] mseqf32 (input [31:0] din);
        reg xor_result;
        begin
            xor_result = din[31] ^ din[21] ^ din[1] ^ din[0];
            mseqf32 = {din[30:0], xor_result};
        end
    endfunction
     
    always @(posedge clk) begin
        if (reset) 
            mseq32 <= 32'h789ABCDE;
        else
            mseq32 <= mseqf32(mseq32);
    end
     
endmodule

`default_nettype wire


これをテストするテストベンチを下に示す。前回のテストベンチとほとんど変わらない。

// m_seq_32_test_tb.v
// m_seq_32.v のテスト
// 2000個のM系列の出力をRAMDOM_NUM_LIMIT個、ファイルに書き出す
// 

`default_nettype none

`timescale 100ps / 1ps

module m_seq_32_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)
    );
    
    // m_seq_32 のインスタンス
    m_seq_32 m_seq_32_i (
        .clk(clk),
        .reset(reset),
        .mseq32(result)
    );
    
    initial F_HANDLE = $fopen("mseq32_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


シミュレーション波形の一部を下に示す。
XORShift_2_120425.png

出力された擬似乱数 mseq32_dump.log の一部を下に示す。

f13579bd
e26af37b
c4d5e6f6
89abcdec
13579bd8
26af37b0
4d5e6f61
9abcdec3
3579bd86
6af37b0c
d5e6f619
abcdec33
579bd867
af37b0ce
5e6f619d
bcdec33a
79bd8674
f37b0ce9
e6f619d3
cdec33a6


M系列でのシード、つまりリセット時の値は重要で、例えば、いつも使っていた 1 にすると、出力された擬似乱数 mseq32_dump.log の最初は下のようになった。

00000003
00000006
0000000d
0000001b
00000036
0000006d
000000db
000001b6
0000036d
000006db
00000db6
00001b6d
000036db
00006db6
0000db6d
0001b6db
00036db6
0006db6d
000db6db
001b6db6
0036db6d
006db6da
00db6db4
01b6db68
036db6d1
06db6da2
0db6db45
1b6db68a


1ビットずつ最下位に挿入していくので仕方が無いところだ。
次に、リセットの時の値を 0x55555555 にしてみた。下に結果を示す。

aaaaaaab
55555556
aaaaaaad
5555555b
aaaaaab6
5555556d
aaaaaadb
555555b6
aaaaab6d
555556db
aaaaadb6
55555b6d
aaaab6db
55556db6
aaaadb6d
5555b6db
aaab6db6
5556db6d
aaadb6db
555b6db6
aab6db6d
556db6db
aadb6db7


という訳で、16進表記で値が異なる数を入れておいたほうが良さそうだ。
  1. 2013年04月25日 05:04 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0