FC2カウンター FPGAの部屋 Custom Video Timing Controller の作製2(シミュレーション)
FC2ブログ

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

FPGAの部屋

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

Custom Video Timing Controller の作製2(シミュレーション)

Custom Video Timing Controller の作製1(仕様の検討)”で仕様の検討をしたが、Verilog HDLで書いて完成したので、シミュレーションを行った。

Project Navigator でプロジェクトを作製して、シミュレーションを行った。Project Navigator の画面を下に示す。
custom_vtc_4_130606.png

下に17msec までシミュレーションした波形を示す。
custom_vtc_1_130606.png

vtc_vsync と vtc_vblank が出ているのがわかると思う。

今度は最初の部分を拡大してみた。
custom_vtc_2_130606.png

vtc_act_vid がピクセルデータが出ている部分で 1 になるのがわかる。vtc_hsync と vtc_hblank が出ているのが見える。

次に、vtc_vblank が 1 になる辺りを拡大してみた。
custom_vtc_3_130606.png

V_FRONT_PORCH = 1 なので、vtc_vsync が随分と前よりになっている。

Verilog HDLで書いたソースコードを貼っておく。(2013/07/07:修正)
custom_vtc.v を下に示す。

// Custom Video Timing Controller IP
// custom_vtc.v
// AXI4バス用

`default_nettype none

// synthesis translate_off
// `include "std_ovl_defines.h"
// synthesis translate_on

module custom_vtc # (
    parameter    integer    H_ACTIVE_VIDEO =    800,
    parameter    integer    H_FRONT_PORCH =         40,
    parameter    integer    H_SYNC_PULSE =        128,
    parameter    integer    H_BACK_PORCH =        88,
    parameter    integer    V_ACTIVE_VIDEO =    600,
    parameter    integer    V_FRONT_PORCH =        1,
    parameter    integer    V_SYNC_PULSE =        4,
    parameter    integer    V_BACK_PORCH =        23
)(
    input    wire    vclk,                // ディスプレイ表示用クロック
    input    wire    aresetn,            // 非同期リセット負論理
    input    wire    vtc_ce,                // VTC clock enable.
    output    wire    vtg_act_vid,        // VTG active video signal. 
    output    wire    vtg_vsync,
    output    wire    vtg_hsync,
    output    wire    vtg_vblank,
    output    wire    vtg_hblank
);
    localparam    integer    H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;
    localparam    integer    V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

    reg    reset_1b, reset;
    reg [15:0] h_count;
    reg [15:0] v_count;
    reg hsyncx_node, vsyncx_node;
    reg display_enable;
    reg hblank;
    reg    vblank;

    // aresetn をvclk で同期化
    always @(posedge vclk) begin
        reset_1b <= ~aresetn;
        reset <= reset_1b;
    end
    
    // h_countの実装(水平カウンタ)
    always @(posedge vclk) begin
        if (reset)
            h_count <= 0;
        else if (vtc_ce) begin
            if (h_count>=(H_SUM-1)) // h_count がH_SUM-1よりも大きければ0に戻す(mod H_SUM)
                h_count <= 0;
            else
                h_count <= h_count + 1;
        end
    end
    
    // v_countの実装(垂直カウンタ)
    always @(posedge vclk) begin
        if (reset)
            v_count <= 0;
        else if (vtc_ce) begin
            if (h_count>=(H_SUM-1)) begin // 水平カウンタがクリアされるとき
                if (v_count>=(V_SUM-1)) // v_count がV_SUM-1よりも大きければ0に戻す(mode V_SUM)
                    v_count <= 0;
                else
                    v_count <= v_count + 1;
            end
        end
    end
    
    // vtg_hsync 出力(水平同期信号)
    always @(posedge vclk) begin
        if (reset)
            hsyncx_node <= 1'b1;
        else if (vtc_ce) begin
            if (h_count>(H_ACTIVE_VIDEO + H_FRONT_PORCH-1) && h_count<=(H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE-1)) // 水平同期期間
                hsyncx_node <= 1'b0;
            else
                hsyncx_node <= 1'b1;
        end
    end
    assign vtg_hsync = ~hsyncx_node;
    
    // vtg_vsync 出力(水平同期信号)
    always @(posedge vclk) begin
        if (reset)
            vsyncx_node <= 1'b1;
        else  if (vtc_ce) begin
            if (v_count>(V_ACTIVE_VIDEO + V_FRONT_PORCH-1) && v_count<=(V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE-1)) // 垂直同期期間
                vsyncx_node <= 1'b0;
            else
                vsyncx_node <= 1'b1;
        end
    end
    assign vtg_vsync = ~vsyncx_node;
    
    // vtg_act_vid 出力
    always @(posedge vclk) begin
        if (reset)
            display_enable <= 1'b0;
        else if (vtc_ce) begin
            if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
                display_enable <= 1'b1;
            else
                display_enable <= 1'b0;
        end
    end
    assign vtg_act_vid = display_enable;
    
    // vtg_hblank 出力
    always @(posedge vclk) begin
        if (reset)
            hblank <= 1'b0;
        else if (vtc_ce) begin
            if (h_count >= H_ACTIVE_VIDEO)
                hblank <= 1'b1;
            else
                hblank <= 1'b0;
        end
    end
    assign vtg_hblank = hblank;
    
    // vtg_vblank 出力
    always @(posedge vclk) begin
        if (reset)
            vblank <= 1'b0;
        else if (vtc_ce) begin
            if (v_count >= V_ACTIVE_VIDEO)
                vblank <= 1'b1;
            else
                vblank <= 1'b0;
        end
    end
    assign vtg_vblank = vblank;
            
endmodule

`default_nettype wire


次に、テストベンチの custom_vtc_tb.v を下に示す。(2013/07/07:修正)

`default_nettype none
`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   05:22:59 06/05/2013
// Design Name:   custom_vtc
// Module Name:   D:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/test/VDMA_test/custom_vtc_tb.v
// Project Name:  VDMA_test
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: custom_vtc
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module custom_vtc_tb;

    // Inputs
    wire vclk;
    wire aresetn;
    reg vtc_ce;

    // Outputs
    wire vtg_act_vid;
    wire vtg_vsync;
    wire vtg_hsync;
    wire vtg_vblank;
    wire vtg_hblank;

    // Instantiate the Unit Under Test (UUT)
    custom_vtc uut (
        .vclk(vclk), 
        .aresetn(aresetn), 
        .vtc_ce(vtc_ce), 
        .vtg_act_vid(vtg_act_vid), 
        .vtg_vsync(vtg_vsync), 
        .vtg_hsync(vtg_hsync), 
        .vtg_vblank(vtg_vblank), 
        .vtg_hblank(vtg_hblank)
    );

    initial begin
        // Initialize Inputs
        vtc_ce = 1'b0;

        // Wait 200 ns for global reset to finish
        #2000;
        
        // Add stimulus here
        vtc_ce = 1'b1;
    end

    // vclk generate
    clk_gen #(
        .CLK_PERIOD(250),    // 25.0nsec, 40MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) pclk_from_pll_i (
        .clk_out(vclk)
    );
    
    // aresetn generate
    reset_gen #(
        .RESET_STATE(1'b0),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(aresetn)
    );

endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out
);
    begin
        initial begin
            reset_out = RESET_STATE;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
        end
    end
endmodule

`default_nettype wire

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

コメント

コメントの投稿


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

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