FC2カウンター FPGAの部屋 2010年08月01日
FC2ブログ

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

FPGAの部屋

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

Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路6(シミュレーション2)

Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路5(シミュレーション)”でシミュレーションをしてみたが、CMOSカメラモデルのデータの出力が遅いため、(でもそれが通常のタイミング)短いシミュレーション時間では、VGA_Display_Contorller がX以外のRGB値を出力できなかった。
今回は、テストベンチからdefpram を使用して、CMOSカメラの1フレームを極端に短くすることによって、なんとか短いシミュレーション時間でRGBの値を出力できることを目指す。

    defparam OV7670.H_ACTIVE_VIDEO = 20;
    defparam OV7670.H_BLANK_SPACE = 2;
    defparam OV7670.V_ACTIVE_VIDEO = 20;
    defparam OV7670.V_FRONT_PORCH = 1;
    defparam OV7670.V_SYNC_PULSE = 1;
    defparam OV7670.V_BACK_PORCH = 1;
    OV7670_Model OV7670 (
        .clk(cam_clk),
        .resetx(~reset),
        .vsync(cam_vsync),
        .href(cam_href),
        .pclk(cam_pclk),
        .ydata(cam_data)
    );


更に、VGA_Display_Controller のスタート番地もアドレスが0になる直前のアドレスを設定する。これは、Camere Controllerが最初に0番地から書くため、書く時間をCamere Controllerに与えるためだ。これも本当は、テストベンチに書きたかったのだが、なぜかdefpramがエラーになってしまったため、VGA_Display_Controllerに書いてある。(多分、階層を間違えていたのでしょう?)

// parameter VGA_CON_STAR_ADDR = 0;
parameter VGA_CON_STAR_ADDR = 19'd307000;


この修正を施して、シミュレーションを試みたところ、RGBにデータが出力されるのが確認できた。
CamDispCntrler_DDR2_12_100801.png

黒いカーソルのところでdata_inに有効がデータが入ってきているのが分かる。data_validが1の時が有効なデータである。その後で赤のカーソルの時にred_out, green_out, blue_outの値が変化しているのがわかる。RGBの出力値に遅延があるのは、FIFOの容量が1/2になった時に、データを取り込むので、黒いカーソルのところでデータを取り込んだときには、まだ、以前のデータがFIFOの1/2容量分残っていたからだ。

Arbiterにアサーションを挿入した。結果、アサーションの行数の方が、実体の回路の行数を上回ってしまった。しかし、人間の目で波形を見て、GO/NGを判定するのは困難なので、積極的に入れていこうと思う。今回はVerilogでアサーションを書いたが、OVLで書きなおしてみたい。今回、OVLを取り敢えず使っていないのは、いろいろなライブラリの準備が面倒という事情はあるが、必要なアサーションが頭の中に明確ではなく、慣れているVerilogでアサーションを書いたほうが、ずっと楽という事情があったからだ。今度はアサーションの内容が明確になったので、OVLに描き直すことができるとおもう。その前に、UCFを完璧にして実機で確かめてみようと思う。下に、Arbiterに書いたVerilogのアサーションを示す。

    // アサーション
    // synthesis translate_off
    always @ (posedge clk_ddr2) begin
        if (reset_ddr2) begin
            camc_addr_1d <= 0;
            vgadc_addr_1d <= 0;
            addr_assertion_valid <= 1'b0;
        end else begin
            if (ddr2_addr_we) begin
                camc_addr_1d <= camc_addr;
            end
            if (vgadc_addr_we) begin
                vgadc_addr_1d <= vgadc_addr;
            end
            if (ddr2_addr_we || vgadc_addr_we) begin
                addr_assertion_valid <= 1'b1;
            end
        end
    end
            
    always @ (posedge clk_ddr2) begin // VGA_Display_Controller 用アサーション
        if (reset_ddr2)
            ;
        else begin
            if (cs_abt==CAMC_Grant || cs_abt==VGADC_Wait) begin // Camera_Controllerが有効
                // Camera_Controllerが有効の時に、vgadc_addr_weが1になるかどうかを調べる。その時には、vgadc_addr_we は1にならないはず。
                if (vgadc_addr_we) begin
                    $display("%m: at time %t ERROR : Camera_Controller が有効の時にVGA_Display_Controller がライトした",$time);
                    $stop;
                end
                // Camera_Controllerが有効の時に、以前の書き込みよりもcamc_addrが4増加していることを調べる。初回にアサーションエラーになってしまうので、最初は無視するように変更した。
                if (camc_addr!=19'd0 && camc_addr_1d+4 != camc_addr && ddr2_addr_we && addr_assertion_valid) begin
                    $display("%m: at time %t ERROR : 以前のcamc_addr から+4されていない", $time);
                    $stop;
                end
            end else if(cs_abt==VGADC_Grant || cs_abt==CAMC_Wait) begin // VGA_Display_Controller 用アサーション
                // VGA_Display_Controller が有効の時に、camc_addr_ena, camc_data_ena が1にならないことを調べる
                if (ddr2_addr_we || ddr2_data_we) begin
                    $display("%m: at time %t ERROR : VGA_Display_Controller が有効の時に、camc_addr_ena, camc_data_ena が1になった", $time);
                    $stop;
                end
                // VGA_Display_Controller が有効の時に、以前の書き込みよりもvgadc_addrが4増加していることを調べる。初回にアサーションエラーになってしまうので、最初は無視するように変更した。
                if (vgadc_addr!=19'd0 && vgadc_addr_1d+4 != vgadc_addr && vgadc_addr_we && addr_assertion_valid) begin
                    $display("%m: at time %t ERROR : 以前のvgadc_addr から+4されていない", $time);
                    $stop;
                end
            end
        end
    end
    // Camera_Controller がFIFOがフルの時に書き込んでいるか?をチェックするアサーション
    always @(posedge clk_ddr2) begin
        if (reset_ddr2)
            ;
        else begin
            if (ddr2_addr_we && ddr2_addr_fifo_full) begin
                $display("%m: at time %t ERROR : アドレスFIFOがフルの時にCamera_Controller が書き込んだ", $time);
                $stop;
            end
            if (ddr2_data_we && ddr2_wrdata_fifo_full) begin
                $display("%m: at time %t ERROR :  データFIFOがフルの時にCamera_Controller が書き込んだ", $time);
                $stop;
            end
        end
    end
    // VGA_Display_Controller がFIFOがフルの時に書き込んでいるか?をチェックするアサーション
    always @(posedge clk_ddr2) begin
        if (reset_ddr2)
            ;
        else begin
            if (vgadc_addr_we && ddr2_addr_fifo_full) begin
                $display("%m: at time %t ERROR :  アドレスFIFOがフルの時にVGA_Display_Controller が書き込んだ", $time);
                $stop;
            end
        end
    end
    // synthesis translate_on


(2007/08/03:修正)
アサーションのVerilog記述が間違っていたので、修正しました。(アインさん、ありがとうございました)
  1. 2010年08月01日 05:18 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:4