FC2カウンター FPGAの部屋 ビットマップVGAコントローラのデバック2(実機デバック)
fc2ブログ

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

FPGAの部屋

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

ビットマップVGAコントローラのデバック2(実機デバック)

キャラクタ描画テスト回路の実機デバックをしていたが、どうも全体をデバックしていると問題の切り分けが難しいので、単体でデバックしてみることにした。
ビットマップVGAコントローラを単体でデバックするには、新たに画像データを作る回路とDCMで50MHzクロックから65MHzと150MHzを生成する回路を付け加える必要がある。画像データはRGBが000から始まって、インクリメントして行くような回路を付け加えた。DCMは使っていたdcm_DDR2VGA_clk.vが使えるので、そのまま使用した。
その、Bitmap_VGA_Controller_top.vを下に示す。

// Bitmap_VGA_Controller_top.v
// Bitmap_VGA_Controllerをテストするトップファイル

module Bitmap_VGA_Controller_top(SYS_CLK, SYS_RST, red_out, green_out, blue_out, hsyncx, vsyncx);
`include "Address_Map_Define.vh"

    input wire SYS_CLK;
    input wire SYS_RST;
    output wire    [3:0] red_out;
    output wire    [3:0] green_out;
    output wire  [3:0] blue_out;
    output wire hsyncx;
    output wire vsyncx;

    wire clk_vga; // 65MHz クロック入力(VGA用)
    wire clk_ddr2; // 150MHz クロック入力(DDR2へのインターフェース用)
    wire reset_vga; // clk_vga用リセット
    wire reset_ddr2; // clk_ddr2リセット
    wire [31:0] vram_start_addr; // バイトアドレス
    wire vram_request; // VRAMへのRead要求。アービタへ
    wire vram_grant; // VRAMへのRead許可。アービタから
    wire [31:0] vram_address; // バイトアドレス
    wire read_write;
    wire vram_req_we; // VRAM へのRead要求のWrite Enable
    wire vram_addr_fifo_full; // VRAMのRead要求用FIFOのFULL
    wire [31:0] vram_data_in;
    reg vram_data_valid;
    wire afifo_overflow; // 非同期FIFO のオーバーフロー・エラー
    wire afifo_underflow; // 非同期FIFO 
    wire clk_ddr2_locked, clk_vga_locked;
    
    reg [15:0] vram_data_in1, vram_data_in2;
    reg vram_req_we_1d;
    
    dcm_DDR2_VGA_clk dcm_DDR2_VGA_clk_i(
        .sysclk(SYS_CLK),
        .reset(SYS_RST),
        .clk_ddr2(clk_ddr2),
        .dcm_ddr2_locked(clk_ddr2_locked),
        .clk_vga(clk_vga),
        .dcm_vga_locked(clk_vga_locked)
    );
    assign reset_vga = SYS_RST | ~clk_vga_locked;
    assign reset_ddr2 = SYS_RST | ~ clk_ddr2_locked;
    
    Bitmap_VGA_Controller Bitmap_VGA_Cntrler_i(
        .clk_vga(clk_vga),
        .clk_ddr2(clk_ddr2),
        .reset_vga(reset_vga),
        .reset_ddr2(reset_ddr2),
        .vram_start_addr(VRAM_START_ADDRESS),
        .vram_request(vram_request),
        .vram_grant(vram_grant),
        .vram_address(vram_address),
        .read_write(read_write),
        .vram_req_we(vram_req_we),
        .vram_addr_fifo_full(vram_addr_fifo_full), 
        .vram_data_in(vram_data_in), 
        .vram_data_valid(vram_data_valid), 
        .red_out(red_out), 
        .green_out(green_out), 
        .blue_out(blue_out), 
        .hsyncx(hsyncx), 
        .vsyncx(vsyncx), 
        .afifo_overflow(afifo_overflow), 
        .afifo_underflow(afifo_underflow)
    );        

    assign vram_addr_fifo_full = 1'b0;
    assign vram_grant = 1'b1;
    always @(posedge clk_ddr2) begin // vram_req_weを1クロック遅延する
        if (reset_ddr2) 
            vram_req_we_1d <= 1'b0;
        else
            vram_req_we_1d <= vram_req_we;
    end
    
    always @(posedge clk_ddr2) begin
        if (reset_ddr2) begin
            vram_data_in1 <= 16'h0000;
            vram_data_in2 <= 16'h0fff;
        end else begin
            if (vram_req_we || vram_req_we_1d) begin // 1リクエストで2つデータを出力する
                if (vram_address==VRAM_START_ADDRESS) begin
                    vram_data_in1 <= 16'h0000;
                    vram_data_in2 <= 16'h0000;
                end else begin
                    vram_data_in1 <= vram_data_in1 + 16'd1;
                    vram_data_in2 <= vram_data_in2 + 16'd1;
                end
            end
        end
    end
    assign vram_data_in = {vram_data_in1, vram_data_in2};
    
    always @(posedge clk_ddr2) begin
        if (reset_ddr2)
            vram_data_valid <= 1'b0;
        else begin
            if (vram_req_we || vram_req_we_1d) // 1リクエストで2つデータを出力する
                vram_data_valid <= 1'b1;
            else
                vram_data_valid <= 1'b0;
        end
    end
endmodule

`default_nettype wire


テストベンチを作成して、シミュレーションを行った。その結果、アービタに出力するアドレスがおかしいバグが1つ見つかったが、他は大丈夫そうだった。シミュレーション結果を下に示す。
Bitmap_VGAC_debug_5_100217.png

大丈夫そうだったので、ISE11.4でインプリメントした。
やはり、以前のTIG制約をUCFに追加しないとタイミングエラーが出てしまった。

PIN "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm.CLKFX" TNM = VGA_CLK_OUTPUT;
PIN "dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm.CLKFX" TNM = DDR2_CLK_OUTPUT;
TIMESPEC TS_VGA2DDR2_CLK_TIG = FROM "VGA_CLK_OUTPUT" TO "DDR2_CLK_OUTPUT" TIG;
TIMESPEC TS_DDR22VGA_CLK_TIG = FROM "DDR2_CLK_OUTPUT" TO "VGA_CLK_OUTPUT" TIG;


無事にインプリメントできた。
Bitmap_VGAC_debug_6_100217.png

実機にダウンロードして、ディスプレイに表示させた。
Bitmap_VGAC_2_100217.jpg

画像は安定している。問題ない気がする。1つバグは修正したので、もう一度、キャラクタ描画テスト回路に戻ってやってみよう。それでもおかしい場合はDDR2 SDRAMコントローラがうまくDDR2 SDRAMのデータを読めていないのかもしれない。
もう1つ心配なのが、Spartan3A Starter Kitの抵抗分割A/Dコンバータで、果たしてドットクロック65MHzのXGAがうまく出力出来て、1ドットが見えるのか?ということが心配になってきた。その場合はSGAかVGAに落とすしかないかな?

(2010/02/18:修正)
Bitmap_VGA_Controller_top.vとシミュレーション波形を変更しました。DDR2 SDRAMコントローラは1つReadコマンドを投げると、32ビットデータ2つが帰ってくるので、整合が取れなくなっていました。
  1. 2010年02月17日 05:28 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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