FC2カウンター FPGAの部屋 ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする3(シミュレーション)

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

FPGAの部屋

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

ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする3(シミュレーション)

ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする2(bitmap_afifo)”の続き。

前回は、bitmap_afifo を生成した。今回は、”Vivado HLS でAXI4-Stream Master Model IP を作る”で作った AXI4-Stream Master Model IP を使って、AXI4-Stream版ビットマップ・ディスプレイ・コントローラをシミュレーションしてみた。なお、AXI4-Stream版ビットマップ・ディスプレイ・コントローラは、Verilog HDL で実装できている。

下図にシミュレーション画面を示す。なおここには、波形ウインドウは表示されていない。
AXI4-Stream_bitmap_disp_cont_13_160816.png

出力される画像データをアサーションでテストしている。アサーション・エラーが出ていないので、問題ないようだ。最初は、アサーション・エラーが出ていたので、HDL を修正した。

40 us シミュレーションした時の波形ウインドウを示す。
AXI4-Stream_bitmap_disp_cont_14_160816.png

画像データの出力開始部分を示す。
AXI4-Stream_bitmap_disp_cont_15_160816.png

17 ms シミュレーションを行った。
AXI4-Stream_bitmap_disp_cont_16_160818.png 

テストベンチの bitmap_disp_cont_axis_tb.v を貼っておく。

`default_nettype none

`timescale 100ps / 1ps

// bitmap_disp_cont_axis_tb.v
// 2012/07/03
// 2014/09/19 : for ZYBO
// 2016/08/14 : for AXI4-Stream

module bitmap_disp_cntrler_axi_master_tb;
    parameter integer C_S_AXI_LITE_ADDR_WIDTH = 9; // Address width of the AXI Lite Interface
    parameter integer C_S_AXI_LITE_DATA_WIDTH = 32; // Data width of the AXI Lite Interface
    parameter integer C_M_AXIS_DATA_WIDTH= 32; // AXI4-Stream Interface

    parameter DELAY = 1;

    wire ACLK;
    wire ARESETN;

    wire [C_M_AXIS_DATA_WIDTH-1:0]        s_axis_tdata;
    wire [(C_M_AXIS_DATA_WIDTH/8)-1:0]    s_axis_tstrb;
    wire                                s_axis_tvalid;
    wire                                   s_axis_tready;
    wire                                   s_axis_tlast;
    wire                                s_axis_tuser;
    reg        ap_start;
    wire    ap_done;
    wire    ap_idle;
    wire    ap_ready;

    wire pixclk;
    wire [4:0]    vga_red;
    wire [5:0]    vga_green;
    wire [4:0]    vga_blue;
    wire    vga_hsync;
    wire    vga_vsync;

    wire [23:0] vid_pData;
    wire    vid_pVDE;
    wire    vid_pHSync;
    wire    vid_pVSync;

    reg    [7:0]    red;
    reg    [7:0]    blue;
    reg    [7:0]    green;
    wire [32:0]    rbg_data;

    // AXI Lite Write Address Channel
    reg                                        s_axi_lite_awvalid = 1'b0;
    wire                                    s_axi_lite_awready;
    reg        [C_S_AXI_LITE_ADDR_WIDTH-1: 0]    s_axi_lite_awaddr = 0;
    //reg        [3-1:0]                            s_axi_lite_awport = 1'b0;

    // AXI Lite Write Data Channel
    reg                                        s_axi_lite_wvalid =1'b0;
    wire                                    s_axi_lite_wready;
    reg        [C_S_AXI_LITE_DATA_WIDTH-1: 0]    s_axi_lite_wdata = 0;

    // AXI Lite Write Response Channel
    wire    [1:0]                            s_axi_lite_bresp;
    wire                                    s_axi_lite_bvalid;
    reg                                        s_axi_lite_bready = 1'b0;

    // AXI Lite Read Address Channel
    reg                                        s_axi_lite_arvalid = 1'b0;
    wire                                    s_axi_lite_arready;
    reg        [C_S_AXI_LITE_ADDR_WIDTH-1: 0]    s_axi_lite_araddr = 1'b0;
    //reg        [3-1:0]                            s_axi_lite_arport = 0;

    // AXI Lite Read Data Channel
    wire                                    s_axi_lite_rvalid;
    reg                                        s_axi_lite_rready = 1'b0;
    wire    [C_S_AXI_LITE_DATA_WIDTH-1: 0]    s_axi_lite_rdata;
    wire    [1:0]                            s_axi_lite_rresp;

    integer i;

    // Instantiate the Unit Under Test (uut_bdc_axis)
    bitmap_disp_cont_axis #(
        .C_S_AXI_LITE_ADDR_WIDTH(C_S_AXI_LITE_ADDR_WIDTH),
        .C_S_AXI_LITE_DATA_WIDTH(C_S_AXI_LITE_DATA_WIDTH),
        .C_M_AXIS_DATA_WIDTH(C_M_AXIS_DATA_WIDTH),
        .RESOLUTION("SVGA")
    ) uut_bdc_axis (
        .s_axi_lite_aclk(ACLK),
        .AXIS_ACLK(ACLK),
        .ARESETN(ARESETN),

        .s_axi_lite_awvalid(s_axi_lite_awvalid),
        .s_axi_lite_awready(s_axi_lite_awready),
        .s_axi_lite_awaddr(s_axi_lite_awaddr),
        .s_axi_lite_wvalid(s_axi_lite_wvalid),
        .s_axi_lite_wready(s_axi_lite_wready),
        .s_axi_lite_wdata(s_axi_lite_wdata),
        .s_axi_lite_bresp(s_axi_lite_bresp),
        .s_axi_lite_bvalid(s_axi_lite_bvalid),
        .s_axi_lite_bready(s_axi_lite_bready),
        .s_axi_lite_arvalid(s_axi_lite_arvalid),
        .s_axi_lite_arready(s_axi_lite_arready),
        .s_axi_lite_araddr(s_axi_lite_araddr),
        .s_axi_lite_rvalid(s_axi_lite_rvalid),
        .s_axi_lite_rready(s_axi_lite_rready),
        .s_axi_lite_rdata(s_axi_lite_rdata),
        .s_axi_lite_rresp(s_axi_lite_rresp),

        .s_axis_tdata(s_axis_tdata),
        .s_axis_tstrb(s_axis_tstrb),
        .s_axis_tvalid(s_axis_tvalid),
        .s_axis_tready(s_axis_tready),
        .s_axis_tlast(s_axis_tlast),
        .s_axis_tuser(s_axis_tuser),

        .pixclk(pixclk),
        .vga_red(vga_red),
        .vga_green(vga_green),
        .vga_blue(vga_blue),
        .vga_hsync(vga_hsync),
        .vga_vsync(vga_vsync),
        .vid_pData(vid_pData),
        .vid_pVDE(vid_pVDE),
        .vid_pHSync(vid_pHSync),
        .vid_pVSync(vid_pVSync)
    );
    //defparam uut_master.bitmap_disp_eng_inst.INIT_COUNT_VAL = 20; // 初期化時のWaitタイマー

    // clk_gen のインスタンス(ACLK)
    clk_gen #(
        .CLK_PERIOD(100),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(ACLK)
    );

    // clk_gen のインスタンス(pixclk)
    clk_gen #(
        //.CLK_PERIOD(154),    // 15.4 nsec, 64.9 MHz
        .CLK_PERIOD(250),    // 25 nsec, 40 MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) pixclk_i (
        .clk_out(pixclk)
    );

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b0),
        .RESET_TIME(1000)    // 100nsec
    ) RESET_ARESETN (
        .reset_out(ARESETN),
        .init_done()
    );

    // Instantiate the AXI4-Stream Master Model (uut_axi4sm)
    axi4_stream_master uut_axi4sm (
        .ap_clk(ACLK),
        .ap_rst_n(ARESETN),

        .ap_start(ap_start),
        .ap_done(ap_done),
        .ap_idle(ap_idle),
        .ap_ready(ap_ready),
        .outs_TDATA(s_axis_tdata),
        .outs_TVALID(s_axis_tvalid),
        .outs_TREADY(s_axis_tready),
        .outs_TKEEP(),
        .outs_TSTRB(s_axis_tstrb),
        .outs_TUSER(s_axis_tuser),
        .outs_TLAST(s_axis_tlast),
        .outs_TID(),
        .outs_TDEST()
    );

    initial begin
        // Initialize Inputs
        ap_start = 1'b0;
        s_axi_lite_awaddr = 0;
        //s_axi_lite_awport = 0;
        s_axi_lite_wvalid = 0;
        s_axi_lite_wdata = 0;
        s_axi_lite_wvalid = 0;
        s_axi_lite_bready = 0;
        s_axi_lite_araddr = 0;
        //s_axi_lite_arport = 0;
        s_axi_lite_arvalid = 0;
        s_axi_lite_rready = 0;

        // Wait Reset rising edge
        @(posedge ARESETN);

        #10000;    // 1us wait

        for (i=0; i<10; i=i+1) begin
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
        end

        // Add stimulus here
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC1(32'h0000_0100, 32'h55AA_55AA);
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_RADC1(32'h0000_0100);
        #DELAY;

        ap_start = 1'b1;

        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_WADC2(32'h0000_0100, 32'h17800000);
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        AXI_MASTER_RADC2(32'h0000_0600);
    end

    // Write Transcation 1
    task AXI_MASTER_WADC1;
        input    [C_S_AXI_LITE_ADDR_WIDTH-1:0]    awaddr;
        input    [C_S_AXI_LITE_DATA_WIDTH-1:0]    wdata;
        begin
            s_axi_lite_awaddr    = awaddr;
            s_axi_lite_awvalid    = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_awvalid = 1'b0;
            s_axi_lite_wdata = wdata;
            s_axi_lite_wvalid = 1'b1;
            @(posedge ACLK);    // 次のクロックへ, s_axi_lite_wready は常に 1

            #DELAY;
            s_axi_lite_wvalid = 1'b0;
            s_axi_lite_bready = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_bready = 1'b0;
        end
    endtask

    // Write Transcation 2
    task AXI_MASTER_WADC2;
        input    [C_S_AXI_LITE_ADDR_WIDTH-1:0]    awaddr;
        input    [C_S_AXI_LITE_DATA_WIDTH-1:0]    wdata;
        begin
            s_axi_lite_awaddr    = awaddr;
            s_axi_lite_awvalid    = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_awvalid = 1'b0;
            s_axi_lite_wdata = wdata;
            s_axi_lite_wvalid = 1'b1;
            @(posedge ACLK);    // 次のクロックへ, s_axi_lite_wready は常に 1

            #DELAY;
            s_axi_lite_wvalid = 1'b0;
            @(posedge ACLK);    // 次のクロックへ

            #DELAY;
            s_axi_lite_bready = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_bready = 1'b0;
        end
    endtask

    // Read Transcation 1
    task AXI_MASTER_RADC1;
        input    [31:0]    araddr;
        begin
            s_axi_lite_araddr    = araddr;
            s_axi_lite_arvalid     = 1'b1;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_araddr    = 0;
            s_axi_lite_arvalid     = 1'b0;
            s_axi_lite_rready = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_rready = 1'b0;
        end
    endtask

    // Read Transcation 2
    task AXI_MASTER_RADC2;
        input    [31:0]    araddr;
        begin
            s_axi_lite_araddr    = araddr;
            s_axi_lite_arvalid     = 1'b1;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_araddr    = 0;
            s_axi_lite_arvalid     = 1'b0;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_rready = 1'b1;

            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            s_axi_lite_rready = 1'b0;
        end
    endtask

    // assertion
    always @(posedge pixclk or negedge ARESETN) begin
        if (~ARESETN) begin
            red <= 8'd0;
        end else if (vid_pVDE) begin
            red <= red + 8'd1;
        end
    end
    always @(posedge pixclk or negedge ARESETN) begin
        if (~ARESETN) begin
            green <= 8'd0;
        end else if (vid_pVDE) begin
            green <= green + 8'd2;
        end
    end
    always @(posedge pixclk or negedge ARESETN) begin
        if (~ARESETN) begin
            blue <= 8'd0;
        end else if (vid_pVDE) begin
            blue <= blue + 8'd3;
        end
    end
    assign rbg_data = {8'd0, red, blue, green};

    always @(posedge pixclk or negedge ARESETN) begin
        if (~ARESETN) begin
            ;
        end else if (vid_pVDE==1'b1 && {8'd0, vid_pData} != rbg_data) begin
            $display("%t Data Error : rbg_data = %h, vid_pData = %h", $realtime, rbg_data, vid_pData);
        end
    end
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,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end

endmodule

`default_nettype wire

  1. 2016年08月17日 04:13 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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