FC2カウンター FPGAの部屋 キャラクタ・ディスプレイ・コントローラをNSLで書こう5(シミュレーション1)
FC2ブログ

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

FPGAの部屋

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

キャラクタ・ディスプレイ・コントローラをNSLで書こう5(シミュレーション1)

PlanAhead12.4でCharDispCtler のNSLコードのデバック”の続き。

前回、PlanAheadのプロジェクトを作成して、ある程度のデバックができた。今回はISimでシミュレーションを行う。Top_wDCM_tb.vというテストベンチを用意した。このテストベンチは、”キャラクタ・ディスプレイ・コントローラのシミュレーション”のテストベンチを改造して使った。*キャラクタを使用して文字を描画するテストベンチだ。テストベンチを下に示す。

// Top Module is Top_wDCM

`timescale 1ns/1ps

module Top_wDCM_tb;
    `include "disp_timing_parameters.vh"

    reg m_clock = 1'b0;
    reg p_reset = 1'b1;
    wire [3:0] VGA_RED;
    wire [3:0] VGA_GREEN;
    wire [3:0] VGA_BLUE;
    wire VGA_HSYNC;
    wire VGA_VSYNC;
    integer i, j, k, m, n;

    parameter PERIOD = 20;
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for m_clock
    begin
        #OFFSET;
        forever
        begin
            m_clock = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) m_clock = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end

    Top_wDCM UUT (
        .m_clock(m_clock),
        .p_reset(p_reset),
        .VGA_RED(VGA_RED),
        .VGA_GREEN(VGA_GREEN),
        .VGA_BLUE(VGA_BLUE),
        .VGA_HSYNC(VGA_HSYNC),
        .VGA_VSYNC(VGA_VSYNC));

    initial begin // キャラクタを*で表示する
        
        #(PERIOD*10);
        p_reset = 1'b0;
        
        @(posedge VGA_VSYNC); // 垂直同期の立ち上がりまでWAIT
        
        for(i=0; i<= V_FRONT_PORCH-1-10; i=i+1) // V_FRONT_PORCHの10ライン前まで数える(表示範囲を広げるため)
            @(posedge VGA_HSYNC); // 水平同期の立ち上がりまでWAIT
            
        for(j=0; j<= H_FRONT_PORCH-1-10; j=j+1) // H_FRONT_PORCHの10ピクセルクロック前まで数える(表示範囲を広げるため)
            @(posedge m_clock);
            
        for(k=0; k<(8*5); k=k+1) begin // 8行(1キャラクタ)*5行
            for(m=0; m<(8*12); m=m+1) begin // 8ピクセル(1キャラクタ)*12列
                #1; // wait
                if(VGA_RED>0 || VGA_GREEN>0 || VGA_BLUE>0)
                    $write("*");
                else
                    $write(" ");
                @(posedge m_clock); // 次のクロックへ
            end
            $write("\n");
            
            @(posedge VGA_HSYNC) ; // 水平同期の立ち上がりまでWAIT
            for(n=0; n<= H_FRONT_PORCH-1-10; n=n+1) // H_FRONT_PORCHの10ピクセルクロック前まで数える(表示範囲を広げるため)
                @(posedge m_clock);
        end
        $stop; // 終了
    end

endmodule


次に、ISim用のプロジェクトファイルを作成した。下に示す。

verilog work ../char_gen_rom.v
verilog work ../dcm_inst.v
verilog work ../Papyrus_work/CharDispCntrler/CharDispCntrler.v
verilog work Top_wDCM_tb.v
verilog work K:\HDL\Xilinx\12.4\ISE_DS\ISE\verilog\src\glbl.v


最後に、ISimシミュレーション用のバッチファイルを下に示す。

del Top_wDCM_tb.exe
K:\HDL\Xilinx\12.4\ISE_DS\ISE\bin\nt\fuse work.Top_wDCM_tb work.glbl -incremental -L unisims_ver=K:\HDL\Xilinx\12.4\ISE_DS\ISE\verilog\hdp\nt\unisims_ver -o Top_wDCM_tb.exe -prj Top_wDCM_tb.prj
Top_wDCM_tb.exe -gui


バッチファイルを実行して、ISimが起動したので、信号を波形ウインドウに入れて、シミュレーションを試みた。下の波形は少しデバックをしたところなのだが、まだ'X'の信号が多い。
CDCont_NSL_10_110215.png

シミュレーションでデバックを進めていくことにする。

(追加)
NSLはmodule内でregを宣言するが、リセットの記述を書かないので、regのところで初期化しないと初期化されない。分かってみると当たり前のことだけど気がつかなかった。

regtemp_pointer[13];


と宣言すると、NSLからVerilogに変換したコードは、

always @(posedge m_clock)
  begin
if ((_u_disp_timing_v_sync)|(_net_12)) 
      temp_pointer <= ((_u_disp_timing_v_sync) ?13'b0000000000000:13'b0)|
    ((_net_12) ?display_addr:13'b0);

end


で、p_resetの記述が入っていない。

regtemp_pointer[13] = 0;


と宣言すると、NSLからVerilogに変換したコードは、

always @(posedge m_clock or posedge p_reset)
  begin
if (p_reset)
     temp_pointer <= 13'b0000000000000;
else if ((_u_disp_timing_v_sync)|(_net_12)) 
      temp_pointer <= ((_u_disp_timing_v_sync) ?13'b0000000000000:13'b0)|
    ((_net_12) ?display_addr:13'b0);

end


で、p_resetの記述が入っている。regの値は初期化する必要があるようだ。初期値が0で実機動作だったら動くと思うが、少なくともシミュレーションの時には初期化は必須だ。

<教訓> NSLでregを宣言したら初期化を忘れないこと。

  1. 2011年02月15日 05:06 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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