FC2カウンター FPGAの部屋 Synthesijerを試してみる2(VHDLファイルをシミュレーション)

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

FPGAの部屋

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

Synthesijerを試してみる2(VHDLファイルをシミュレーション)

Synthesijerを試してみる1(VHDLファイルを出力)”の続き。

今回はテストベンチ (Test_tb.v) を書いて、シミュレーションを行った。シミュレーション環境はVivado 2014.4のVivado Simulatorで行った。何故かと言うと、混在シミュレーションができるシミュレータが少ないからだ。ZYBOボードの xc7z010clg400-1 でプロジェクトを作製した。

シミュレータを行ったが、カウント数が多いので、シミュレーションが大変ということで、ループカウントを10 に変更した。変更したJava のコードを下に示す。

public class Test{
  public boolean flag;
  private int count;

  public void run(){
    while(true){
      count++;
      if(count > 10){
      //if(count > 5000000){
           count = 0;
           flag = !flag;
      }
    }
  }
}


これでシミュレーションを行った。Vivado Simulator の画面を下に示す。
Synthesijer_6_141218.png

上の図から flag_out の周期は 1.6 usec となった。flag_out の値が反転するのは半分の 800 nsec である。それをカウント値の11カウントで割ると、

800 /11 ≒ 72.7 nsec

となる。現在の動作クロックは 100MHz で 10 nsec なので、1カウント分の平均的なクロック数は

72.7 / 10 = 7.27 クロック

となった。どうやら run_method_S_0011 の時に、flag_out が変化するようだ。ステートを遷移して行って判定を行いながら結果を出力しているのか?ユーザーズ・マニュアルが欲しいと思った。

下にテストベンチのTest_tb.v を示す。

`default_nettype none

`timescale 1ns / 100ps

// Test_tb.v
// 2014/12/17
//

module Test_tb;
    parameter DELAY = 1;

    wire    clk;
    wire    reset;
    reg        flag_in;
    reg        flag_we;
    wire    flag_out;
    reg        run_req;
    wire    run_busy;

    Test uut_Test (
        .clk(clk),
        .reset(reset),
        .flag_in(flag_in),
        .flag_we(flag_we),
        .flag_out(flag_out),
        .run_req(run_req),
        .run_busy(run_busy)
    );

    initial begin
        // Initialize Inputs
        flag_in <= 1'b0;
        flag_we <= 1'b0;
        run_req <= 1'b1;
    end

    // clk_gen のインスタンス(clk)
    clk_gen #(
        .CLK_PERIOD(10),    // 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(100)    // 100nsec
    ) RESET_ARESETN (
        .reset_out(reset),
        .init_done()
    );
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,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end

endmodule

`default_nettype wire

  1. 2014年12月19日 04:39 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:5

コメント

面白いものを作られている方が多いですね。
ぱっと考えて、JAVAのバイトコードからVHDLコードを起こしているのかと思ったのですが....
そんな単純なものでもなかったです。

ループ時間は 7state × 10 + 10state = 80state(clock) ですね。

---------------- JAVAバイトコード -------------------------
public void run();
Code:
0: aload_0
1: dup
2: getfield #2; //Field count:I
5: iconst_1
6: iadd
7: putfield #2; //Field count:I
10: aload_0
11: getfield #2; //Field count:I
14: ldc #3; //int 5000000
16: if_icmple 0
19: aload_0
20: iconst_0
21: putfield #2; //Field count:I
24: aload_0
25: aload_0
26: getfield #4; //Field flag:Z
29: ifne 36
32: iconst_1
33: goto 37
36: iconst_0
37: putfield #4; //Field flag:Z
40: goto 0

---------------- なんちゃってステートマシン ---------------------
IDLE:goto #000
#000:goto #001
#001:if run_request then goto #002
#002:if break then goto #003 else goto #004
#003:goto #014
#004:[カウント値+1] : goto #005
#005:[カウンタロード] : goto #006
#006:[カウンタ判定] : goto #007
#007:if 判定結果(>10) then goto #008 else goto #009
#008:goto #013
#009:[カウンタクリア] : goto #011
#011:[フラグ反転] : goto #012
#012:goto #008
#013:goto #002 ' 無限ループ

[カウント値+1
if #004 then tmp<=count+1;
]

[カウンタロード/カウンタクリア
if #005 then count <= tmp;
elseif #009 then count <= 0;
]

[フラグ反転
if #011 then flga <= !flag;
]

[カウンタ判定
if #006 then 判定結果 <= (カウンタ>10)
]
  1. 2014/12/19(金) 10:10:33 |
  2. URL |
  3. おる #mQop/nM.
  4. [ 編集 ]

おるさん、こんにちは。

面白いのでやってみました。0から10までカウントするので、カウントは11のはずですね。
  1. 2014/12/19(金) 22:01:18 |
  2. URL |
  3. marsee #f1oWVgn2
  4. [ 編集 ]

JAVAの仮想マシンの代わりにシーケンサを回していて、演算とかの命令はシーケンサの番号で処理しているようです。
仮想CPUみたいな動きになるので、ループ判定=偽の場合は7クロック、真の場合は10クロック(3クロックはFLAG反転シーケンス)使って
7×10+10=80クロック=800ns×2=1.6μsです。
複雑なプログラムを変換すると巨大なシーケンサができそうですね。
  1. 2014/12/20(土) 20:24:48 |
  2. URL |
  3. おる #mQop/nM.
  4. [ 編集 ]

了解しました。最後の11が10クロックということですね。
違う表現方法でJAVAを書いてみました。
http://marsee101.blog19.fc2.com/blog-entry-3014.html
こちらは真の場合に8クロックかかっているようです。
  1. 2014/12/21(日) 05:19:59 |
  2. URL |
  3. marsee #f1oWVgn2
  4. [ 編集 ]

JAVAを動かそうと思ったら、普通の人ならJAVAの仮想マシンをインプリメントして
バイトコードを解釈して実行しそうなものですが、

バイトコードを0~数stateのrun_methodとして割り付け
バイトコードはstateマシンとして動かす
要素(スタック)へのアクセスは、run_methodの番号で処理

としているのかなと、このコードを見て想像しました。
これならCPUコアのようなものはいらないしメモリの割り当ても必要ないので、
ある程度の規模までのステップ数ならコアを入れるより小さく出来そうです。

「勝手に入るゴミ箱」みたいで面白い発想ですね。
  1. 2014/12/24(水) 09:58:54 |
  2. URL |
  3. おる #mQop/nM.
  4. [ 編集 ]

コメントの投稿


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

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3013-a8479694
この記事にトラックバックする(FC2ブログユーザー)