FC2カウンター FPGAの部屋 Interface2011年2月号のNSLサンプルを試す4(NSLをVerilogに変換してシミュレーション)
FC2ブログ

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

FPGAの部屋

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

Interface2011年2月号のNSLサンプルを試す4(NSLをVerilogに変換してシミュレーション)

”Interface2011年2月号のNSLサンプルを試す3(インスタンス作成)”でスケルトンコードを生成することができた。今度はスケルトンコードにメソッドを書かなくてはいけないのだけれども、CQ出版社から落としたプロジェクト一式に入っている完成版のNSLファイルtimer7seg.nslを使って、Verilog、VHDL、SystemCへの変換を行ってみようと思う。NSL Coreのバージョンは20110102、使用したISimのバージョンは12.4だ。

CQ出版社から落としたプロジェクト一式の中のAGX20\timer7seg\NSL_Sourceフォルダの下のtimer7seg.nslを使用する。timer7seg.nslを見るとtimer7segモジュール?のdeclare は下のようになっていて、UMLコードを書いた時よりもinput resetが増えているようだ。(下に引用する)

declare    timer7seg  {
    
    // -- timer_30MHz_to_1sec  --
    input        reset ;
    output        seg1_o[8] ;
    output        seg2_o[8] ;
    output        seg_figure[2] ;        // For support DYNAMIC drive.
}


このSTOPWATCHプロジェクトではキッチンタイマーを作るという目的があるようなので、このreset端子はキッチンタイマーのリセットではないかと思われる。そういえばトップモジュールに1つも入力がないというのはおかしい?よって、以前のUMLのクラス図にinput resetを追加することにした。
NSL_Sample_24_110114.png

これで、UMLtoNSLツールを起動してNSLのスケルトンを吐かせると、declare timer7segにinput reset; が入っていた。これで良いのだと思う。このresetはNSLコードを見ると1秒に1回評価されるようだ。
さて、次はダウンロードしたtimer7seg.nslを使って、NSL Coreツールで、VerilogやVHDL、SystemCに変換してみようと思う。
NSL Coreツールを起動して、NSLファイルを指定するために...ボタンをクリックして、ダウンロードしたプロジェクトの中のtimer7seg.nslを指定した。デフォルトのLanguageはVerilogなので、これでSynthesisボタンをクリックして、Verilogに変換した。
NSL_Sample_25_110114.png

変換されたVerilogはこんな感じだ。下図参照。
NSL_Sample_26_110114.png

//synthesis translate_off、//synthesis translate_on の組がよく出てきて、ネットが 'x' の時にWarningが出るようだ。アサーション・チェッカーなのかな?

次に、LanguageをVHDL に変更して、Synthesisボタンをクリックする。すると、VHDLファイルが出力された。下図参照。
NSL_Sample_27_110114.png

LanguageをSystemC に変更して、Synthesisボタンをクリックする。生成されたSystemCファイル。
NSL_Sample_28_110114.png

LanguageをSimultaion(Verilog) に変更して、Synthesisボタンをクリックする。生成されたVerilogファイル。
NSL_Sample_29_110114.png

テストベンチ(tb)の辺り、当然ながら、resetのスティミュラスは書く必要がありそうだ。

LanguageをSimultaion(SystemC)に変更して、Synthesisボタンをクリックする。生成されたSystemCファイル。
NSL_Sample_30_110114.png

Verilogでシミュレーションを試みた。Simultaion(Verilog) で、ISimでシミュレーションを行った。
シミュレーションを行う際に、resetのスティミュラスを追加した。修正後のソースを下に示す。

module tb;
    parameter tCYC=2;
    parameter tPD=(tCYC/10);

    reg p_reset;
    reg m_clock;
    reg reset;
    wire [7:0] seg1_o;
    wire [7:0] seg2_o;
    wire [1:0] seg_figure;

    timer7seg timer7seg_instance(
        .p_reset(p_reset),
        .m_clock(m_clock),
        .reset(reset),
        .seg1_o(seg1_o),
        .seg2_o(seg2_o),
        .seg_figure(seg_figure)
    );

    initial forever #(tCYC/2) m_clock = ~m_clock;

    initial begin
        $dumpfile("timer7seg.vcd");
        $dumpvars(0,timer7seg_instance);
    end

    initial begin
        #(tPD)
            p_reset = 1;
            m_clock = 0;
            reset = 0;
        #(tCYC)
            p_reset = 0;
            reset = 1;
        #200000 $stop;
    end

endmodule


これでISim用のバッチファイルを書いてシミュレーションした。ISim用のバッチファイルを下に示す。

vlogcomp -work work -incremental timer7seg.v
fuse work.tb -o tb.exe
tb.exe -gui


ISimのシミュレーション結果は、sig2_oが 'XX' になってしまっている。
NSL_Sample_31_110114.png

原因を追求して行ったのだが、どうやら、counter_0to5モジュールのcounter が 'X'になってしまっている。counter_0to9モジュールのcounter は正常な値になっている。
NSL_Sample_32_110114.png

counter_0to9モジュールのcounterの記述はp_resetが入っていて、0にクリアされている。下に記述の一部を引用する。

always @(posedge m_clock or posedge p_reset)
  begin
if (p_reset)
     counter <= 4'b0000;
else 
//synthesis translate_off
if ((reset&countup&(~_net_5))|((reset|(countup&(~_net_5)))&countup&_net_5))   counter <= 4'bx; 
  else 
//synthesis translate_on
if (reset)
      counter <= 4'b0000;
else if (countup&(~_net_5))
      counter <= (counter)+(4'b0001);
else if (countup&_net_5)
      counter <= 4'b0000;
end


counter_0to5モジュールのcounter の記述はp_resetの記述がない。これが取り敢えずcounter の値が 'X' になる原因のようだ。

always @(posedge m_clock)
  begin

//synthesis translate_off
if ((reset&countup&(~_net_6))|((reset|(countup&(~_net_6)))&countup&_net_6))   counter <= 3'bx; 
  else 
//synthesis translate_on
if (reset)
      counter <= 3'b000;
else if (countup&(~_net_6))
      counter <= (counter)+(3'b001);
else if (countup&_net_6)
      counter <= 3'b000;
end


counter_0to5モジュールのcounter の記述にp_clockの記述を追加したところsig2_oも0xC0になった。
NSL_Sample_33_110114.png

ちょっとキッチンタイマーのシミュレーションは時間がかかって現実的じゃないので、timer7seg.nslの最初の時間間隔定義を修正した。

//    #define ONE_SECOND        ( 32'd50000000 - 32'd1 )
//    #define CNT_DYNAMIC        19'b100_1001_0011_1110_0000
      #define ONE_SECOND        ( 32'd4 )
      #define CNT_DYNAMIC        19'b000_0000_0000_0000_1000


これでISimでシミュレーションをしたところ、カウント値が変わるのを確認できた。
NSL_Sample_34_110114.png

そういえば、SystemCでシミュレーションしているとおっしゃっていた。SystemCでシミュレーションする必要があるのかもしれない。Verilogでシミュレーションする場合は、まだバグがあるようだ。

原因はtimer7seg.nslにバグがあったためのようです。counter_0to5モジュールの宣言は下のようでしたが、

module    counter_0to5 {
    
    // -- counter_0to5  --
    reg                counter[3];
    hex_to_7segout    u_hex_to_7segout;


これには、reg counter[3];の初期化の記述がありません。そこで、下のように書き換えたところ、

module    counter_0to5 {
    
    // -- counter_0to5  --
    reg                counter[3] = 0;
    hex_to_7segout    u_hex_to_7segout;


p_resetの記述が入りました。これで問題なくなりました。NSL Coreのバグではありませんでした。

なお、SystemCは殆ど知らないので、SystemCも勉強したいと思っている。
  1. 2011年01月14日 05:58 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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