4.2.2 カウンタ

RTLシミュレーション

4.2.1のled.vの記述には、テストベンチがありません。Veritakシミュレーションを行うには、テストベンチが必要です。まず、テストベンチを作成しましょう。とりあえず、クロックとリセットがFPGAに供給されれば動くはずです。以下はled_test.vソースです。最初の50nsは、リセットさせます。その後、リセットを解除します。

`timescale 1ns/1ps
`define CYCLE  (10) //(6.522/2)
module led_test;


    reg  clk0=0;
    reg clk1;
    reg clk2;
    reg clk3;
    wire [36:0]  user ;
    wire [15:0]  sd_d ;
    wire [12:0]  sd_a ;
    wire sd_bs1;
    wire sd_bs0;
    wire sd_ldqm;
    wire sd_udqm;
    wire sd_wen;
    wire sd_ras;
    wire sd_cas;
    wire sd_clk;
    wire sd_cke;
    wire sd_cs;
    wire [7:0]  usb_d ;
    wire usb_wr;
    wire usb_rd;
    reg usb_txe=0;
    reg usb_rxf=0;
    reg usb_pwren=0;
    reg usb_rsto=0;


  main  led( .clk0(clk0), .clk1(clk1), .clk2(clk2), .clk3(clk3), .user(user), .sd_d(sd_d),
        .sd_a(sd_a), .sd_bs1(sd_bs1), .sd_bs0(sd_bs0), .sd_ldqm(sd_ldqm), .sd_udqm(sd_udqm),
        .sd_wen(sd_wen), .sd_ras(sd_ras), .sd_cas(sd_cas), .sd_clk(sd_clk), .sd_cke(sd_cke),
        .sd_cs(sd_cs), .usb_d(usb_d), .usb_wr(usb_wr), .usb_rd(usb_rd),
        .usb_txe(usb_txe), .usb_rxf(usb_rxf), .usb_pwren(usb_pwren), .usb_rsto(usb_rsto) );
    

   always #(`CYCLE) clk0=~clk0;

   initial begin
                #50;
                @(negedge clk0);
                usb_rsto=1;
                #100000;
                $finish;

   end





endmodule
    

   always #(`CYCLE) clk0=~clk0;

   initial begin
                #50;
                @(negedge);
                usb_rsto=1;
                #100000;
                $finish;

   end





endmodule
 

プロジェクトを作成します。プロジェクトの名前は、RTLとVeritakということがわかるようにした方がよろしいでしょう。



ファイルを指定します。
上で作成したファイルを指定します。指定した後、Save ProjectでSaveしておきます。

シミュレーション波形

リセットが解除になった後、インクリメント動作しています。期待通りです。


Xilinx Library を使う(veritak version 1.44以降)

WebPackでのunisim 、Foudationでのcorelib を使う場合は、下の「遅延シミュレーション」でのsimprims をそれぞれunisim ,xilinxcorelibに置き換えてたものと同様です。下の「遅延シミュレーション」の項をご参照ください。

<初期化付ファイルの場合>
xilinxcorelib で、RAM(ROM)の初期化付RAMを生成した場合は、そのモジュールでのファイルのフォルダの中で「ADD INCLUDE_DIR」しておきます。これは、生成したファイルが、内部で、*.mif ファイルを$readmemb しているためです。これがないと、プロジェクトのルートフォルダしか探索しないため、mifファイルが読み込まれません。下の例(筆者がDWM設計コンテスト2005に応募したプロジェクトです。オープンコアに設計途中の試行錯誤が載っています。)では、rom4k.vはcoregenで生成したファイルです。このファイルを含むフォルダdwmをINCLUDEしておきます。


遅延シミュレーション

Xilinx のWebpackで遅延シミュレーション用のVerilogファイルを生成させます。Generate Post-Place &Route Simulation ModeをRunすると *_timesim.vというファイルが生成されます。



遅延シミュレーションでは、それが出来ているフォルダ位置にプロジェクトファイルを構成する必要があります。

遅延シミュレーションで指定するファイルは、

です。glbl.v は、初期化のファイルらしいです。確かにこれがないとResetされなくてFFは、XXになってしまいます。simprims に入っている沢山のファイルは、ゲートシミュレーション用のプリミティブな記述が入っています。なお、プロジェクトと同じドライブ上にないときは、COPYしてプロジェクトと同じドライブ下としてください。以上を指定してSave Projectします。



遅延シミュレーション波形(Veritak1.12B以降)

波形を見てみると、ちゃんとインクリメント動作をしていることがわかります。ところで、期待値と違うことにお気づきでしょうか? カウンタの初期リセットは、usb_rstoでしたはずなのにカウンタのインクリメント動作は、glbl.vのGSRがHになって初めて行われているようです。glbl.vの記述を見てみると100ns後にHにしていることがわかります。プリミティブライブラリの中身を筆者は全然見てませんが、恐らくこの信号に起因して内部リセットがかかっているのだと思われます。従って、led_test.vを変更し、150nsにリセット解除に変更することにします。




記述を変更しました。ところで、下の上部波形を見ると1−>2、3−>4でハザードらしいものが見えます。REGの出力なのでハザードはないはずです。実際、ビット展開してみるとビット毎でみればハザードは発生していないことがわかります。また、IO遅延は、カーソル間(クロックを与えてから出力が落ち着くまで)でみると10.912nsあることがわかります。それでも内部の合成結果は、26ビットカウンタで153MHzになっていますからIOは遅くとも内部はそれなりに速いです。


下部の波形は、シミュレーション時間100usの全波形をビット展開したものですが、まだ、16ビット目(カウンタ12ビット目)にかかったところです。人間の目でLEDを確認するために、USER[3:0]には、counter[25:22]を割り付けたのですが、まだまだ程遠いことがわかります。実際的に遅延シミュレーションで確認するには、我慢の限界を超えていると思いますし、その必要もないでしょう。 (RTLシミュレーションならば可能性はありますが。)