FC2カウンター FPGAの部屋 AXI4 Slave IPの作製

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

FPGAの部屋

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

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする8.2(テストベンチのVerilogコード)

前の記事は、”キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする8.1(BFMシミュレーション7)”だが、全体の関連は、”AXI4 Slave IPの作製”を参照のこと。

今回はテストベンチのVerilogコードを下に貼っておく。(2013/12/14:修正、DELAYをAXI4 Master BFMへ移動しました)

// CDC_axi_slave_tb.v

`default_nettype none

`timescale 100ps / 1ps

module CDC_axi_slave_tb;

    parameter DELAY    = 10;
    parameter NUMBER_OF_TEST = 100;    // テストする数

    parameter    ASIZE_BT_4    = 3'd2;    // 32 bit width
    parameter    ASIZE_BT_2 = 3'd1;    // 16 bit width
    parameter    ASIZE_BT_1 = 3'd0;    // 8 bit width

    parameter    ABURST_FIXED    = 2'd0;
    parameter    ABURST_INCR    = 2'd1;
    parameter    ABURST_WRAP    = 2'd2;

    parameter    BRESP_OKAY        = 2'b00;
    parameter    BRESP_EXOKAY    = 2'b01;
    parameter    BRESP_SLVERR    = 2'b10;
    parameter    BRESP_DECERR    = 2'b11;

    // Inputs
    wire ACLK;
    wire ARESETN;
    wire [0:0] S_AXI_AWID;
    wire [31:0] S_AXI_AWADDR;
    wire [7:0] S_AXI_AWLEN;
    wire [2:0] S_AXI_AWSIZE;
    wire [1:0] S_AXI_AWBURST;
    wire [1:0] S_AXI_AWLOCK;
    wire [3:0] S_AXI_AWCACHE;
    wire [2:0] S_AXI_AWPROT;
    wire [3:0] S_AXI_AWREGION;
    wire [3:0] S_AXI_AWQOS;
    wire [0:0] S_AXI_AWUSER;
    wire S_AXI_AWVALID;
    wire [0:0] S_AXI_WID;
    wire [31:0] S_AXI_WDATA;
    wire [3:0] S_AXI_WSTRB;
    wire S_AXI_WLAST;
    wire [0:0] S_AXI_WUSER;
    wire S_AXI_WVALID;
    wire S_AXI_BREADY;
    wire [0:0] S_AXI_ARID;
    wire [31:0] S_AXI_ARADDR;
    wire [7:0] S_AXI_ARLEN;
    wire [2:0] S_AXI_ARSIZE;
    wire [1:0] S_AXI_ARBURST;
    wire [1:0] S_AXI_ARLOCK;
    wire [3:0] S_AXI_ARCACHE;
    wire [2:0] S_AXI_ARPROT;
    wire [3:0] S_AXI_ARREGION;
    wire [3:0] S_AXI_ARQOS;
    wire [0:0] S_AXI_ARUSER;
    wire S_AXI_ARVALID;
    wire S_AXI_RREADY;
    wire pixclk;

    // Outputs
    wire S_AXI_AWREADY;
    wire S_AXI_WREADY;
    wire [0:0] S_AXI_BID;
    wire [1:0] S_AXI_BRESP;
    wire [0:0] S_AXI_BUSER;
    wire S_AXI_BVALID;
    wire S_AXI_ARREADY;
    wire [0:0] S_AXI_RID;
    wire [31:0] S_AXI_RDATA;
    wire [1:0] S_AXI_RRESP;
    wire S_AXI_RLAST;
    wire [0:0] S_AXI_RUSER;
    wire S_AXI_RVALID;
    wire TMDS_tx_clk_p;
    wire TMDS_tx_clk_n;
    wire TMDS_tx_2_G_p;
    wire TMDS_tx_2_G_n;
    wire TMDS_tx_1_R_p;
    wire TMDS_tx_1_R_n;
    wire TMDS_tx_0_B_p;
    wire TMDS_tx_0_B_n;

    // Instantiate the Unit Under Test (UUT)
    CDC_axi_slave uut (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .S_AXI_AWID(S_AXI_AWID),
        .S_AXI_AWADDR(S_AXI_AWADDR),
        .S_AXI_AWLEN(S_AXI_AWLEN),
        .S_AXI_AWSIZE(S_AXI_AWSIZE),
        .S_AXI_AWBURST(S_AXI_AWBURST),
        .S_AXI_AWLOCK(S_AXI_AWLOCK),
        .S_AXI_AWCACHE(S_AXI_AWCACHE),
        .S_AXI_AWPROT(S_AXI_AWPROT),
        .S_AXI_AWREGION(S_AXI_AWREGION),
        .S_AXI_AWQOS(S_AXI_AWQOS),
        .S_AXI_AWUSER(S_AXI_AWUSER),
        .S_AXI_AWVALID(S_AXI_AWVALID),
        .S_AXI_AWREADY(S_AXI_AWREADY),
        .S_AXI_WID(S_AXI_WID),
        .S_AXI_WDATA(S_AXI_WDATA),
        .S_AXI_WSTRB(S_AXI_WSTRB),
        .S_AXI_WLAST(S_AXI_WLAST),
        .S_AXI_WUSER(S_AXI_WUSER),
        .S_AXI_WVALID(S_AXI_WVALID),
        .S_AXI_WREADY(S_AXI_WREADY),
        .S_AXI_BID(S_AXI_BID),
        .S_AXI_BRESP(S_AXI_BRESP),
        .S_AXI_BUSER(S_AXI_BUSER),
        .S_AXI_BVALID(S_AXI_BVALID),
        .S_AXI_BREADY(S_AXI_BREADY),
        .S_AXI_ARID(S_AXI_ARID),
        .S_AXI_ARADDR(S_AXI_ARADDR),
        .S_AXI_ARLEN(S_AXI_ARLEN),
        .S_AXI_ARSIZE(S_AXI_ARSIZE),
        .S_AXI_ARBURST(S_AXI_ARBURST),
        .S_AXI_ARLOCK(S_AXI_ARLOCK),
        .S_AXI_ARCACHE(S_AXI_ARCACHE),
        .S_AXI_ARPROT(S_AXI_ARPROT),
        .S_AXI_ARREGION(S_AXI_ARREGION),
        .S_AXI_ARQOS(S_AXI_ARQOS),
        .S_AXI_ARUSER(S_AXI_ARUSER),
        .S_AXI_ARVALID(S_AXI_ARVALID),
        .S_AXI_ARREADY(S_AXI_ARREADY),
        .S_AXI_RID(S_AXI_RID),
        .S_AXI_RDATA(S_AXI_RDATA),
        .S_AXI_RRESP(S_AXI_RRESP),
        .S_AXI_RLAST(S_AXI_RLAST),
        .S_AXI_RUSER(S_AXI_RUSER),
        .S_AXI_RVALID(S_AXI_RVALID),
        .S_AXI_RREADY(S_AXI_RREADY),
        .pixclk(pixclk),
        .TMDS_tx_clk_p(TMDS_tx_clk_p),
        .TMDS_tx_clk_n(TMDS_tx_clk_n),
        .TMDS_tx_2_G_p(TMDS_tx_2_G_p),
        .TMDS_tx_2_G_n(TMDS_tx_2_G_n),
        .TMDS_tx_1_R_p(TMDS_tx_1_R_p),
        .TMDS_tx_1_R_n(TMDS_tx_1_R_n),
        .TMDS_tx_0_B_p(TMDS_tx_0_B_p),
        .TMDS_tx_0_B_n(TMDS_tx_0_B_n)
    );

    // clk_gen のインスタンス
    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 #(
        .CLK_PERIOD(250),    // 25nsec, 40MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) PIXCLKi (
        .clk_out(pixclk)
    );

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

    // AXI4_BFM のインスタンス
    AXI4_Master_BFM #(.DELAY(DELAY)) MBFMi(
        .ACLK(ACLK),
        .S_AXI_AWID(S_AXI_AWID),
        .S_AXI_AWADDR(S_AXI_AWADDR),
        .S_AXI_AWLEN(S_AXI_AWLEN),
        .S_AXI_AWSIZE(S_AXI_AWSIZE),
        .S_AXI_AWBURST(S_AXI_AWBURST),
        .S_AXI_AWLOCK(S_AXI_AWLOCK),
        .S_AXI_AWCACHE(S_AXI_AWCACHE),
        .S_AXI_AWPROT(S_AXI_AWPROT),
        .S_AXI_AWREGION(S_AXI_AWREGION),
        .S_AXI_AWQOS(S_AXI_AWQOS),
        .S_AXI_AWUSER(S_AXI_AWUSER),
        .S_AXI_AWVALID(S_AXI_AWVALID),
        .S_AXI_AWREADY(S_AXI_AWREADY),
        .S_AXI_WID(S_AXI_WID),
        .S_AXI_WDATA(S_AXI_WDATA),
        .S_AXI_WSTRB(S_AXI_WSTRB),
        .S_AXI_WLAST(S_AXI_WLAST),
        .S_AXI_WUSER(S_AXI_WUSER),
        .S_AXI_WVALID(S_AXI_WVALID),
        .S_AXI_WREADY(S_AXI_WREADY),
        .S_AXI_BID(S_AXI_BID),
        .S_AXI_BRESP(S_AXI_BRESP),
        .S_AXI_BUSER(S_AXI_BUSER),
        .S_AXI_BVALID(S_AXI_BVALID),
        .S_AXI_BREADY(S_AXI_BREADY),
        .S_AXI_ARID(S_AXI_ARID),
        .S_AXI_ARADDR(S_AXI_ARADDR),
        .S_AXI_ARLEN(S_AXI_ARLEN),
        .S_AXI_ARSIZE(S_AXI_ARSIZE),
        .S_AXI_ARBURST(S_AXI_ARBURST),
        .S_AXI_ARLOCK(S_AXI_ARLOCK),
        .S_AXI_ARCACHE(S_AXI_ARCACHE),
        .S_AXI_ARPROT(S_AXI_ARPROT),
        .S_AXI_ARREGION(S_AXI_ARREGION),
        .S_AXI_ARQOS(S_AXI_ARQOS),
        .S_AXI_ARUSER(S_AXI_ARUSER),
        .S_AXI_ARVALID(S_AXI_ARVALID),
        .S_AXI_ARREADY(S_AXI_ARREADY),
        .S_AXI_RID(S_AXI_RID),
        .S_AXI_RDATA(S_AXI_RDATA),
        .S_AXI_RRESP(S_AXI_RRESP),
        .S_AXI_RLAST(S_AXI_RLAST),
        .S_AXI_RUSER(S_AXI_RUSER),
        .S_AXI_RVALID(S_AXI_RVALID),
        .S_AXI_RREADY(S_AXI_RREADY)
    );

    // OVL Checker
    OVL_Checker OVLi (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .S_AXI_AWID(S_AXI_AWID),
        .S_AXI_AWADDR(S_AXI_AWADDR),
        .S_AXI_AWLEN(S_AXI_AWLEN),
        .S_AXI_AWSIZE(S_AXI_AWSIZE),
        .S_AXI_AWBURST(S_AXI_AWBURST),
        .S_AXI_AWLOCK(S_AXI_AWLOCK),
        .S_AXI_AWCACHE(S_AXI_AWCACHE),
        .S_AXI_AWPROT(S_AXI_AWPROT),
        .S_AXI_AWREGION(S_AXI_AWREGION),
        .S_AXI_AWQOS(S_AXI_AWQOS),
        .S_AXI_AWUSER(S_AXI_AWUSER),
        .S_AXI_AWVALID(S_AXI_AWVALID),
        .S_AXI_AWREADY(S_AXI_AWREADY),
        .S_AXI_WID(S_AXI_WID),
        .S_AXI_WDATA(S_AXI_WDATA),
        .S_AXI_WSTRB(S_AXI_WSTRB),
        .S_AXI_WLAST(S_AXI_WLAST),
        .S_AXI_WUSER(S_AXI_WUSER),
        .S_AXI_WVALID(S_AXI_WVALID),
        .S_AXI_WREADY(S_AXI_WREADY),
        .S_AXI_BID(S_AXI_BID),
        .S_AXI_BRESP(S_AXI_BRESP),
        .S_AXI_BUSER(S_AXI_BUSER),
        .S_AXI_BVALID(S_AXI_BVALID),
        .S_AXI_BREADY(S_AXI_BREADY),
        .S_AXI_ARID(S_AXI_ARID),
        .S_AXI_ARADDR(S_AXI_ARADDR),
        .S_AXI_ARLEN(S_AXI_ARLEN),
        .S_AXI_ARSIZE(S_AXI_ARSIZE),
        .S_AXI_ARBURST(S_AXI_ARBURST),
        .S_AXI_ARLOCK(S_AXI_ARLOCK),
        .S_AXI_ARCACHE(S_AXI_ARCACHE),
        .S_AXI_ARPROT(S_AXI_ARPROT),
        .S_AXI_ARREGION(S_AXI_ARREGION),
        .S_AXI_ARQOS(S_AXI_ARQOS),
        .S_AXI_ARUSER(S_AXI_ARUSER),
        .S_AXI_ARVALID(S_AXI_ARVALID),
        .S_AXI_ARREADY(S_AXI_ARREADY),
        .S_AXI_RID(S_AXI_RID),
        .S_AXI_RDATA(S_AXI_RDATA),
        .S_AXI_RRESP(S_AXI_RRESP),
        .S_AXI_RLAST(S_AXI_RLAST),
        .S_AXI_RUSER(S_AXI_RUSER),
        .S_AXI_RVALID(S_AXI_RVALID),
        .S_AXI_RREADY(S_AXI_RREADY)
    );


    // test

    // Write Channel

    // wr_data生成、+1する
    reg        [15:0]    wcount;
    wire    [31:0]    wdata;

    always @(posedge ACLK) begin
        if (~ARESETN)
            wcount <= 0;
        else begin
            if (S_AXI_WVALID & S_AXI_WREADY)
                wcount <= wcount + 16'd1;
        end
    end
    assign wdata = {{16{1'b0}}, wcount};


    reg    WriteTaskBusy = 1'b0;
    integer wt_cnt;
    initial begin
        // Wait 100 ns for global reset to finish
        #1000;
        #5000;    // 500nsec Wait, PLL Locked

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

        for (wt_cnt=0; wt_cnt<NUMBER_OF_TEST; wt_cnt=wt_cnt+1) begin
            WriteTaskBusy = 1'b1;
            MBFMi.AXI_Master_1Seq_Write(0, 32'h100, 8'd7, ASIZE_BT_4, ABURST_INCR, wdata, 0, 2);
            MBFMi.AXI_Master_1Seq_Write(0, 32'h200, 8'd3, ASIZE_BT_4, ABURST_INCR, wdata, 1, 3);
            MBFMi.AXI_Master_1Seq_Write(0, 32'h300, 8'd1, ASIZE_BT_4, ABURST_INCR, wdata, 1, 4);
            MBFMi.AXI_Master_1Seq_Write(0, 32'h400, 8'd0, ASIZE_BT_4, ABURST_INCR, wdata, 1, 5);

            WriteTaskBusy = 1'b0;
            while (ReadTestBusy) begin // Read 終了待ち
                @(posedge ACLK);    // 次のクロックへ
                #DELAY;
            end
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
        end
    end

    // Read Channel
    reg    ReadTestBusy = 1'b0;
    integer rd_cnt;
    initial begin
        // Wait 100 ns for global reset to finish
        #1000;
        #5000;    // 500nsec Wait, PLL Locked

        for (rd_cnt=0; rd_cnt<NUMBER_OF_TEST; rd_cnt=rd_cnt+1) begin

            ReadTestBusy = 1'b1;
            #1000;
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;

            MBFMi.AXI_Master_1Seq_Read(0, 32'h100, 8'd7, ASIZE_BT_4, ABURST_INCR, 2);
            MBFMi.AXI_Master_1Seq_Read(0, 32'h200, 8'd3, ASIZE_BT_4, ABURST_INCR, 3);
            MBFMi.AXI_Master_1Seq_Read(0, 32'h300, 8'd1, ASIZE_BT_4, ABURST_INCR, 4);
            MBFMi.AXI_Master_1Seq_Read(0, 32'h400, 8'd0, ASIZE_BT_4, ABURST_INCR, 5);

            ReadTestBusy = 1'b0;
            while (WriteTaskBusy) begin // Write の終了待ち
                @(posedge ACLK);    // 次のクロックへ
                #DELAY;
            end
            @(posedge ACLK);    // 次のクロックへ
            #DELAY;
        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
);
    begin
        initial begin
            reset_out = RESET_STATE;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
        end
    end
endmodule

`default_nettype wire

  1. 2012年10月25日 05:33 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする8.1(BFMシミュレーション7)

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする8(BFMシミュレーション6)”の続き。

書き込みトランザクションの時に、MasterがAWREADYを待って、WVALIDをアサートしていけないというルールがあったのを忘れていたので、AXI Slave IP用のBFMが間違っていたことがわかったので修正する。ちなみにWriteだけ変更している。Readは変更していない。

”キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする”シリーズの”BFMシミュレーション”~”BFMシミュレーション6”まで間違っているが、全部修正するのが大変なので、”キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする8(BFMシミュレーション6)”のみ状態でのみ書きなおす。

テストベンチ (CDC_axi_slave_tb.v) を変更した。任意の回数ループするトランザクションは、8バースト、4バースト、2バースト、単発転送とする。それぞれデータ転送の最大のWait数を変えることにした。Readの値をovl_increment でチェックするため、Write トランザクションとRead トランザクションは、最後のトランザクションで同期する。Write トランザクションよりRead トランザクションの方が、遅延して開始する。

Writeの一部分を下に示す。
AXI_Slave_BFM_1_121025.png

Readの一部を下に示す。
AXI_Slave_BFM_2_121025.png

Writeの1トランザクションの拡大を下に示す。
AXI_Slave_BFM_3_121025.png

Readの1トランザクションの拡大を下に示す。
AXI_Slave_BFM_4_121025.png

テストベンチAXI Master BFMOVLチェッカはそれぞれ1つずつブログ記事を作って紹介する。
  1. 2012年10月25日 05:28 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

AXIスレーブIPのパラメータ

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする9(インプリメント1)”でXPSからAdd IPでキャラクタ・ディスプレイ・コントローラをAXI4スレーブIPとしてシステムに入れたが、その際にパラメータはデフォルトとした。ダイアログにどのようなパラメータがあるかを見ていきたい。

なお、AXI4バスの信号とパラメータについては、LogiCORE IP AXIインターコネクト(v1.05.a) DS768 2012年1月18日 を参照した。(以下マニュアルと呼ぶ)なお、マスタ、スレーブで共通の信号はスレーブでは S_ が、マスタでは M_ がパラメータ名から抜けているようだ。

ダイアログで設定できるパラメータを列挙して、説明する。

・XPS Core Config ダイアログ(Systemタブ)
CDC_axi_slave_25_120317.png

* Address

- Slave AXI Number of Address Ranges (C_S_AXI_NUM_ADDR_RANGES)
 マニュアルには記述が無いが、アドレス範囲を4つまで選べて、その内の幾つを有効にするかを数で選択する。デフォルトはAutoで1。

- Slave AXI RNG00 Base Base Address (C_S_AXI_RNG00_BASEADDR)
 これもマニュアルには記述が無いが、最初のアドレス範囲のスタートアドレス。XPSのAddressタブでアドレスを入力すると反映されている。

- Slave AXI RNG00 High Base Address (C_S_AXI_RNG00_HIGHADDR)
最初のアドレス範囲のエンドアドレス。XPSのAddressタブでアドレスを入力すると反映されている。

- Slave AXI RNG01 Base Base Address ~ Slave AXI RNG03 High Base Address は省略

* S_AXI

- Slave AXI Protcol (C_S_AXI_PROTOCOL)
 AXI4, AXI4Lite, AXI3 を選択できる。ここでのデフォルト値はAXI4

- Slave AXI ID Width (C_S_AXI_ID_WIDTH)
 IDのビット幅。1~16ビットに設定可。ここでのデフォルト値は1。

- Slave AXI Address Width (C_S_AXI_ADDR_WIDTH)
 アドレスビット幅。ここでのデフォルト値は32。ここは設定できない。

- Slave AXI Supports Read (C_S_AXI_SUPPORTS_READ)
 スレーブIPがReadを行うか?を示す。デフォルトではAuto になっているが、チェックされている。Wirte のみのスレーブIPの場合はチェックを外す。

- Slave AXI Supports Write (C_S_AXI_SUPPORTS_WRITE)
 スレーブIPがWriteを行うか?を示す。デフォルトではAuto になっているが、チェックされている。Read のみのスレーブIPの場合はチェックを外す。

- Slave AXI Supports User Signals (C_S_AXI_SUPPORTS_USER_SIGNALS)
 USER信号 (5チャネルすべて) をAXI インターコネクトコアに伝搬するかどうかを示すそうだ。このチェックを外していてもUSER信号はデフォルト値の1になるようだ。
 チェックをすると下のUSER信号のグレーアウトがとれて、設定ができるようになる。

- Slave AXI AWUSER Width (C_S_AXI_AWUSER_WIDTH)
 AWUSER信号の幅。1 ~ 256。デフォルトは1。

- Slave AXI ARUSER Width (C_S_AXI_ARUSER_WIDTH)
 ARUSER信号の幅。1 ~ 256。デフォルトは1。

- Slave AXI WUSER Width (C_S_AXI_WUSER_WIDTH)
 WUSER信号の幅。1 ~ 256。デフォルトは1。

- Slave AXI RUSER Width (C_S_AXI_RUSER_WIDTH)
 RUSER信号の幅。1 ~ 256。デフォルトは1。

- Slave AXI BUSER Width (C_S_AXI_BUSER_WIDTH)
 BUSER信号の幅。1 ~ 256。デフォルトは1。

・XPS Core Config ダイアログ(Interconnect Settings for BUSIF)
CDC_axi_slave_26_120317.png

* S_AXI

- Is ACLK Asynchronous to Interconnect_ACLK (C_INTERCONNECT_S_AXI_IS_ACLK_ASYNC)
 0の時はインターコネクトとクロック同期、1の時はインターコネクトとクロック非同期。デフォルト値は0でチェックなし

- ACLK Frequency Ratio (C_INTERCONNECT_S_AXI_ACLK_RATIO)
 ACLKの動作周波数がセットされる。上の図での表示は1だが、現在の値は100000000Hz、つまり100MHz。たぶんXPSでクロックをACLKに接続するとその値が反映されるようだ。よって、Add IP時には設定せずに後でクロックをXPS上で接続したほうが良い。

- Require TrustZone Secure on all accesses (C_INTERCONNECT_S_AXI_SECURE)
 マニュアルによると”各MIスロットがセキュアなスレーブ デバイス(TrustZone のセキュアアクセスを許可)に接続されているかどうかを示します。”だそうです。0がセキュアでないスレーブデバイスで、1がセキュアなスレーブデバイス。デフォルトは0でチェックなし。

- Use register slice on AW channel (C_INTERCONNECT_S_AXI_AW_REGISTER)
 AWチャネルにレジスタを挿入する。レジスタを挿入するとレイテンシが増える代わりに高速動作するようになると思われる。BYPASS, AUTOMATIC, FULLY REGISTERED, LIGHT WEIGHTから選択。デフォルトはBYPASS。

- Use register slice on AR channel (C_INTERCONNECT_S_AXI_AR_REGISTER)
 ARチャネルにレジスタを挿入する。レジスタを挿入するとレイテンシが増える代わりに高速動作するようになると思われる。BYPASS, AUTOMATIC, FULLY REGISTERED, LIGHT WEIGHTから選択。デフォルトはBYPASS。

- Use register slice on W channel (C_INTERCONNECT_S_AXI_W_REGISTER)
 Wチャネルにレジスタを挿入する。レジスタを挿入するとレイテンシが増える代わりに高速動作するようになると思われる。BYPASS, AUTOMATIC, FULLY REGISTERED, LIGHT WEIGHTから選択。デフォルトはBYPASS。

- Use register slice on R channel (C_INTERCONNECT_S_AXI_R_REGISTER)
 Rチャネルにレジスタを挿入する。レジスタを挿入するとレイテンシが増える代わりに高速動作するようになると思われる。BYPASS, AUTOMATIC, FULLY REGISTERED, LIGHT WEIGHTから選択。デフォルトはBYPASS。

- Use register slice on B channel (C_INTERCONNECT_S_AXI_B_REGISTER)
 Bチャネルにレジスタを挿入する。レジスタを挿入するとレイテンシが増える代わりに高速動作するようになると思われる。BYPASS, AUTOMATIC, FULLY REGISTERED, LIGHT WEIGHTから選択。デフォルトはBYPASS。

- Write Data FIFO Depth (C_INTERCONNECT_S_AXI_WRITE_FIFO_DEPTH)
 Write Data FIFOの深度。0(None), 32(SRL), 512(BRAM)から選択。デフォルトは0(None)。

- Write Data FIFO Burst Delay (C_INTERCONNECT_S_AXI_WRITE_FIFO_DELAY)
 マニュアルによると”パケットFIFO 書き込み動作。 バースト全体がSI側の各 SIスロットの書き込みデータFIFOに格納されるまでアービタへの AWVALID 発行を遅延させます (対応するスロットのC_S_AXI_WRITE_FIFO_DEPTH = 0x200 とする必要がある)。”そうだ。チェックを入れる場合は、前のWrite Data FIFO Depthを512(BRAM)にする必要がある。デフォルト値はチェックなし。

- Read Data FIFO Depth (C_INTERCONNECT_S_AXI_READ_FIFO_DEPTH)
 Read Data FIFOの深度。0(None), 32(SRL), 512(BRAM)から選択。デフォルトは0(None)。

- Read Data FIFO Burst Delay (C_INTERCONNECT_S_AXI_READ_FIFO_DELAY)
 マニュアルによると”パケットFIFO 読み出し動作。SI側の各SIスロットの読み出しデータFIFOに全バースト長を格納する のに十分な空きが生じるまで、アービタへのARVALID 発行を遅延させます (対応するスロットのC_S_AXI_READ_FIFO_DEPTH = 0x200とする必要がある)。”そうだ。チェックを入れる場合は、前のRead Data FIFO Depthを512(BRAM)にする必要がある。デフォルト値はチェックなし。

- Write Transaction Acceptance Limit (C_INTERCONNECT_S_AXI_WRITE_ACCEPTANCE)
 インターコネクトから発行されるアクティブなWrite Transaction の数。デフォルトはAuto で1。

- Read Transaction Acceptance Limit (C_INTERCONNECT_S_AXI_READ_ACCEPTANCE)
 インターコネクトから発行されるアクティブなRead Transaction の数。デフォルトはAuto で1。
  1. 2012年04月06日 05:54 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする14(AXI4スレーブIPのソース公開)

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする13(Writeはうまく行った)”で、Write側はうまく行ったと思われるキャラクタ・ディスプレイ・コントローラAXI4バス・スレーブIPのソースをブログに貼っておこうと思う。長いです。

cdc_axi_slave.vhd を下に貼っておく。なお、entity部分の宣言は はXilinx社の ar37425.zip から引用した。

-----------------------------------------------------------------------------
--
-- AXI Slave
--
-----------------------------------------------------------------------------
-- 2012/02/25 : S_AXI_AWBURST=1 (INCR) にのみ対応、AWSIZE, ARSIZE = 000 (1byte), 001 (2bytes), 010 (4bytes) のみ対応。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

--library unisim;
--use unisim.vcomponents.all;

entity cdc_axi_slave is
  generic (
    C_S_AXI_ID_WIDTH     : integer := 1;
    C_S_AXI_ADDR_WIDTH   : integer := 32;
    C_S_AXI_DATA_WIDTH   : integer := 32;
    C_S_AXI_AWUSER_WIDTH : integer := 1;
    C_S_AXI_ARUSER_WIDTH : integer := 1;
    C_S_AXI_WUSER_WIDTH  : integer := 1;
    C_S_AXI_RUSER_WIDTH  : integer := 1;
    C_S_AXI_BUSER_WIDTH  : integer := 1
    );
  port(
    -- System Signals
    ACLK    : in std_logic;
    ARESETN : in std_logic;

    -- Slave Interface Write Address Ports
    S_AXI_AWID     : in  std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
    S_AXI_AWADDR   : in  std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
    S_AXI_AWLEN    : in  std_logic_vector(8-1 downto 0);
    S_AXI_AWSIZE   : in  std_logic_vector(3-1 downto 0);
    S_AXI_AWBURST  : in  std_logic_vector(2-1 downto 0);
    S_AXI_AWLOCK   : in  std_logic_vector(2-1 downto 0);
    S_AXI_AWCACHE  : in  std_logic_vector(4-1 downto 0);
    S_AXI_AWPROT   : in  std_logic_vector(3-1 downto 0);
    S_AXI_AWREGION : in  std_logic_vector(4-1 downto 0);
    S_AXI_AWQOS    : in  std_logic_vector(4-1 downto 0);
    S_AXI_AWUSER   : in  std_logic_vector(C_S_AXI_AWUSER_WIDTH-1 downto 0);
    S_AXI_AWVALID  : in  std_logic;
    S_AXI_AWREADY  : out std_logic;

    -- Slave Interface Write Data Ports
    S_AXI_WID    : in  std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
    S_AXI_WDATA  : in  std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
    S_AXI_WSTRB  : in  std_logic_vector(C_S_AXI_DATA_WIDTH/8-1 downto 0);
    S_AXI_WLAST  : in  std_logic;
    S_AXI_WUSER  : in  std_logic_vector(C_S_AXI_WUSER_WIDTH-1 downto 0);
    S_AXI_WVALID : in  std_logic;
    S_AXI_WREADY : out std_logic;

    -- Slave Interface Write Response Ports
    S_AXI_BID    : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
    S_AXI_BRESP  : out std_logic_vector(2-1 downto 0);
    S_AXI_BUSER  : out std_logic_vector(C_S_AXI_BUSER_WIDTH-1 downto 0);
    S_AXI_BVALID : out std_logic;
    S_AXI_BREADY : in  std_logic;

    -- Slave Interface Read Address Ports
    S_AXI_ARID     : in  std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
    S_AXI_ARADDR   : in  std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
    S_AXI_ARLEN    : in  std_logic_vector(8-1 downto 0);
    S_AXI_ARSIZE   : in  std_logic_vector(3-1 downto 0);
    S_AXI_ARBURST  : in  std_logic_vector(2-1 downto 0);
    S_AXI_ARLOCK   : in  std_logic_vector(2-1 downto 0);
    S_AXI_ARCACHE  : in  std_logic_vector(4-1 downto 0);
    S_AXI_ARPROT   : in  std_logic_vector(3-1 downto 0);
    S_AXI_ARREGION : in  std_logic_vector(4-1 downto 0);
    S_AXI_ARQOS    : in  std_logic_vector(4-1 downto 0);
    S_AXI_ARUSER   : in  std_logic_vector(C_S_AXI_ARUSER_WIDTH-1 downto 0);
    S_AXI_ARVALID  : in  std_logic;
    S_AXI_ARREADY  : out std_logic;

    -- Slave Interface Read Data Ports
    S_AXI_RID    : out std_logic_vector(C_S_AXI_ID_WIDTH-1 downto 0);
    S_AXI_RDATA  : out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
    S_AXI_RRESP  : out std_logic_vector(2-1 downto 0);
    S_AXI_RLAST  : out std_logic;
    S_AXI_RUSER  : out std_logic_vector(C_S_AXI_RUSER_WIDTH-1 downto 0);
    S_AXI_RVALID : out std_logic;
    S_AXI_RREADY : in  std_logic;
    
    -- TMDS Signals
    pixclk        : in    std_logic;
    TMDS_tx_clk_p :    out    std_logic;                    -- Clock
    TMDS_tx_clk_n :    out    std_logic;
    TMDS_tx_2_G_p :    out    std_logic;                    -- Green
    TMDS_tx_2_G_n :    out    std_logic;
    TMDS_tx_1_R_p :    out    std_logic;                    -- Red
    TMDS_tx_1_R_n :    out    std_logic;
    TMDS_tx_0_B_p :    out    std_logic;                    -- Blue
    TMDS_tx_0_B_n :    out    std_logic
    );

end cdc_axi_slave;

architecture implementation of cdc_axi_slave is
component dvi_disp 
    generic (
        PLL_CLKFBOUT_MULT : integer := 20;    -- VGA解像度 PLL VCO Freq 400MHz ~ 1000MHz
        PLL_CLKIN_PERIOD : real := 40.0;    -- VGA ピクセルクロック周期
        PLL_CLKOUT0_DIVIDE : integer := 2;    -- ピクセルクロックX10
        PLL_CLKOUT1_DIVIDE : integer := 20;    -- ピクセルクロック
        PLL_CLKOUT2_DIVIDE : integer := 10    -- ピクセルクロックX2
    );
    port (
        pixclk    :    in    std_logic;            -- pixel clock
        reset_in :    in     std_logic;            -- active high
        red_in :    in    std_logic_vector(7 downto 0);    -- RED入力
        green_in :    in    std_logic_vector(7 downto 0);    -- GREEN入力
        blue_in :    in    std_logic_vector(7 downto 0);    -- BLUE入力
        hsync :        in    std_logic;
        vsync :        in    std_logic;
        display_enable :    in std_logic;                -- 表示が有効
        TMDS_tx_clk_p :    out    std_logic;                    -- Clock
        TMDS_tx_clk_n :    out    std_logic;
        TMDS_tx_2_G_p :    out    std_logic;                    -- Green
        TMDS_tx_2_G_n :    out    std_logic;
        TMDS_tx_1_R_p :    out    std_logic;                    -- Red
        TMDS_tx_1_R_n :    out    std_logic;
        TMDS_tx_0_B_p :    out    std_logic;                    -- Blue
        TMDS_tx_0_B_n :    out    std_logic
    );
end component;

component CharDispCtrler
    port(
        axi4clk : in std_logic;
        pixclk : in std_logic;
        reset : in std_logic;
        
        processor_addr : in std_logic_vector(12 downto 0);
        processor_din : in std_logic_vector(15 downto 0);
        processor_dout : out std_logic_vector(15 downto 0);
        processor_we : in std_logic;
        
        VGA_RED : out std_logic_vector(2 downto 0);
        VGA_GREEN : out std_logic_vector(2 downto 0);
        VGA_BLUE : out std_logic_vector(2 downto 0);
        VGA_HSYNC : out std_logic;
        VGA_VSYNC : out std_logic;
        display_enable : out std_logic
    );
end component;
COMPONENT afifo_sm
  PORT (
    clk : IN STD_LOGIC;
    rst : IN STD_LOGIC;
    din : IN STD_LOGIC_VECTOR(15 DOWNTO 0);
    wr_en : IN STD_LOGIC;
    rd_en : IN STD_LOGIC;
    dout : OUT STD_LOGIC_VECTOR(15 DOWNTO 0);
    full : OUT STD_LOGIC;
    almost_full : OUT STD_LOGIC;
    overflow : OUT STD_LOGIC;
    empty : OUT STD_LOGIC;
    almost_empty : OUT STD_LOGIC;
    underflow : OUT STD_LOGIC
  );
END COMPONENT;

constant    AxBURST_FIXED    : std_logic_vector := "00";
constant    AxBURST_INCR    : std_logic_vector := "01";
constant    AxBURST_WRAP    : std_logic_vector := "10";

constant    RESP_OKAY        : std_logic_vector := "00";
constant    RESP_EXOKAY        : std_logic_vector := "01";
constant    RESP_SLVERR        : std_logic_vector := "10";
constant    RESP_DECERR        : std_logic_vector := "11";

-- for write transaction
type write_transaction_state is (idle_wr, awr_wait, awr_accept, wr_burst);
type write_response_state is (idle_wres, bvalid_assert);
type write_wready_state is (idle_wrdy, wready_assert);
signal wrt_cs : write_transaction_state;
signal wrres : write_response_state;
signal wrwr : write_wready_state;

-- for read transaction
type read_transaction_state is (idle_rd, arr_wait, arr_accept, rd_burst);
type read_last_state is (idle_rlast, rlast_assert);
signal rdt_cs : read_transaction_state;
signal rdlast : read_last_state;

signal reset_1d, reset_2d, reset : std_logic := '1';

signal awready         : std_logic;
signal wr_addr         : std_logic_vector(12 downto 0);
signal wr_bid         : std_logic_vector(0 downto 0);
signal wr_bresp     : std_logic_vector(1 downto 0);
signal wr_bvalid     : std_logic;

signal arready         : std_logic;
signal rd_addr         : std_logic_vector(12 downto 0);
signal rd_axi_count    : std_logic_vector(7 downto 0);
signal rd_cdc_count    : std_logic_vector(8 downto 0);
signal rdfifo_din    : std_logic_vector(15 downto 0);
signal rdfifo_wr_en    : std_logic;
signal rdfifo_rd_en    : std_logic;
signal rdfifo_full, rdfifo_empty    : std_logic;
signal rdfifo_almost_full, rdfifo_almost_empty : std_logic;
signal rdfifo_overflow, rdfifo_underflow : std_logic;
signal rvalid        : std_logic;
signal rlast        : std_logic;
signal cdc_addr        : std_logic_vector(12 downto 0);
signal vga_red, vga_green, vga_blue : std_logic_vector(2 downto 0);
signal vga_red8, vga_green8, vga_blue8 : std_logic_vector(7 downto 0);
signal vga_hsync, vga_vsync : std_logic;
signal display_enable : std_logic;
signal cdc_we : std_logic;
signal rdfifo_wr_en_node : std_logic;

begin
    -- ARESETN をACLK で同期化
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            reset_1d <= not ARESETN;
            reset_2d <= reset_1d;
        end if;
    end process;
    reset <= reset_2d;
    
    -- AXI4バス Write Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wrt_cs <= idle_wr;
                awready <= '0';
            else
                case (wrt_cs) is
                    when idle_wr =>
                        if S_AXI_AWVALID='1' then -- S_AXI_AWVALID が1にアサートされた
                            if rdt_cs=idle_rd then -- Read Transaction が終了している(Writeの方が優先順位が高い)
                                wrt_cs <= awr_accept;
                                awready <= '1';
                            else -- Read Transaction が終了していないのでWait
                                wrt_cs <= awr_wait;
                            end if;
                        end if;
                    when awr_wait => -- Read Transaction の終了待ち
                        if rdt_cs=idle_rd or rdt_cs=arr_wait then -- Read Transaction が終了
                            wrt_cs <= awr_accept;
                            awready <= '1';
                        end if;
                    when awr_accept => -- S_AXI_AWREADY をアサート
                        wrt_cs <= wr_burst;
                        awready <= '0';
                    when wr_burst => -- Writeデータの転送
                        if S_AXI_WLAST='1' and S_AXI_WVALID='1' then -- Write Transaction 終了
                            wrt_cs <= idle_wr;
                        end if;
                end case;
            end if;
        end if;
    end process;
    S_AXI_AWREADY <= awready;
    S_AXI_WREADY <= '1' when wrt_cs=wr_burst else '0';
    cdc_we <= '1' when wrt_cs=wr_burst and S_AXI_WVALID='1' else '0';
    
    -- wr_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_addr <= (others => '0');
            else
                if wrt_cs=awr_accept then
                    wr_addr <= S_AXI_AWADDR(14 downto 2); -- 32ビット幅データのため
                elsif wrt_cs=wr_burst and S_AXI_WVALID='1' then -- アドレスを1つ進める
                    wr_addr <= wr_addr + 1;
                end if;
            end if;
        end if;
    end process;
    
    -- wr_bid の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bid <= "0";
            else
                if wrt_cs=awr_accept then
                    wr_bid <= S_AXI_AWID;
                end if;
            end if;
        end if;
    end process;
    S_AXI_BID <= wr_bid;
    
    -- wr_bresp の処理
    -- S_AXI_AWBURSTがINCRの時はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bresp <= (others => '0');
            else
                if wrt_cs=awr_accept then
                    if S_AXI_AWBURST=AxBURST_INCR then -- バーストタイプがアドレス・インクリメントタイプ
                        wr_bresp <= RESP_OKAY; -- Write Transaction は成功
                    else
                        wr_bresp <= RESP_SLVERR; -- エラー
                    end if;
                end if;
            end if;
        end if;
    end process;
    S_AXI_BRESP <= wr_bresp;
    
    -- wr_bvalid の処理
    -- Write Transaction State Machineには含まない。axi_master のシミュレーションを見ると1クロックで終了しているので、長い間、Master側の都合でWaitしていることは考えない。
    -- 次のWrite転送まで遅延しているようであれば、Write Transaction State Machine に入れてブロックすることも考える必要がある。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bvalid <= '0';
            else
                if S_AXI_WLAST='1' and S_AXI_WVALID='1' then -- Write Transaction 終了
                    wr_bvalid <= '1';
                elsif wr_bvalid='1' and S_AXI_BREADY='1' then -- wr_bvalid が1でMaster側のReadyも1ならばWrite resonse channel の転送も終了
                    wr_bvalid <= '0';
                end if;
            end if;
        end if;
    end process;
    S_AXI_BVALID <= wr_bvalid;
    S_AXI_BUSER <= (others => '0');
    
    
    -- AXI4バス Read Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdt_cs <= idle_rd;
                arready <= '0';
            else
                case (rdt_cs) is
                    when idle_rd =>
                        if S_AXI_ARVALID='1' then -- Read Transaction 要求
                            if wrt_cs=idle_wr and S_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
                                rdt_cs <= arr_accept;
                                arready <= '1';
                            else -- Write Transaction が終了していないのでWait
                                rdt_cs <= arr_wait;
                            end if;
                        end if;
                    when arr_wait => -- Write Transaction の終了待ち
                        if wrt_cs=idle_wr and S_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
                            rdt_cs <= arr_accept;
                            arready <= '1';
                        end if;
                    when arr_accept => -- S_AXI_ARREADY をアサート
                        rdt_cs <= rd_burst;
                        arready <= '0';
                    when rd_burst => -- Readデータの転送
                        if rd_axi_count=0 and rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction 終了
                            rdt_cs <= idle_rd;
                        end if;
                end case;
            end if;
        end if;
    end process;
    S_AXI_ARREADY <= arready;
    
    -- rd_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_addr <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    rd_addr <= S_AXI_ARADDR(14 downto 2); -- 32ビット幅データのため
                elsif rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 then -- rdfifoに余裕があるときにはアドレスを1つ進める
                    rd_addr <= rd_addr + 1;
                end if;
            end if;
        end if;
    end process;
    
    -- Read用FIFOのインスタンス
    rdfifo : afifo_sm PORT MAP (
        clk => ACLK,
        rst => reset,
        din => rdfifo_din,
        wr_en => rdfifo_wr_en,
        rd_en => rdfifo_rd_en,
        dout => S_AXI_RDATA(15 downto 0),
        full => rdfifo_full,
        almost_full => rdfifo_almost_full,
        overflow => rdfifo_overflow,
        empty => rdfifo_empty,
        almost_empty => rdfifo_almost_empty,
        underflow => rdfifo_underflow
    );
    S_AXI_RDATA(31 downto 16) <= (others => '0');
    rvalid <= not rdfifo_empty;
    S_AXI_RVALID <= rvalid;
    
    rdfifo_wr_en_node <= '1' when rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 else '0';
    -- BlockRAMのReadは1クロック遅延するため、1クロック遅延させる。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdfifo_wr_en <= '0';
            else
                rdfifo_wr_en <= rdfifo_wr_en_node;
            end if;
        end if;
    end process;
        
    rdfifo_rd_en <= '1' when rdt_cs=rd_burst and rvalid='1' and S_AXI_RREADY='1' else '0';
    
    -- rd_cdc_count の処理(CDC側のデータカウント)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_cdc_count <= (others => '0');
            else
                if rdt_cs=arr_accept then -- ロード
                    rd_cdc_count <= ('0'& S_AXI_ARLEN) + 1;
                elsif rdt_cs=rd_burst and rdfifo_almost_full='0' and rd_cdc_count/=0 then -- FIFOに余裕がある
                    rd_cdc_count <= rd_cdc_count - 1;
                end if;
            end if;
        end if;
    end process;
                    
    -- rd_axi_count の処理(AXIバス側のデータカウント)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_axi_count <= (others => '0');
            else
                if rdt_cs=arr_accept then -- rd_axi_count のロード
                    rd_axi_count <= S_AXI_ARLEN;
                elsif rdt_cs=rd_burst and rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction が1つ終了
                    rd_axi_count <= rd_axi_count - 1;
                end if;
            end if;
        end if;
    end process;
    
    -- rdlast State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdlast <= idle_rlast;
                rlast <= '0';
            else
                case (rdlast) is
                    when idle_rlast =>
                        if rd_axi_count=1 and rvalid='1' and S_AXI_RREADY='1' then -- バーストする場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        elsif rdt_cs=arr_accept and S_AXI_ARLEN=0 then -- 転送数が1の場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        end if;
                    when rlast_assert => 
                        if rvalid='1' and S_AXI_RREADY='1' then -- Read Transaction 終了(rd_axi_count=0は決定)
                            rdlast <= idle_rlast;
                            rlast <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process;
    S_AXI_RLAST <= rlast;
    
    -- S_AXI_RID, S_AXI_RUSER の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                S_AXI_RID <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    S_AXI_RID <= S_AXI_ARID;
                end if;
            end if;
        end if;
    end process;
    S_AXI_RUSER <= (others => '0');
    
    -- S_AXI_RRESP は、S_AXI_ARBURST がINCR の場合はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                S_AXI_RRESP <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    if S_AXI_ARBURST=AxBURST_INCR then
                        S_AXI_RRESP <= RESP_OKAY;
                    else
                        S_AXI_RRESP <= RESP_SLVERR;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    
    -- CharDispCtrler
    cdc_addr <= wr_addr when rdt_cs=idle_rd or rdt_cs=arr_wait else rd_addr;
    
    CDC_inst : CharDispCtrler port map (
        axi4clk         => ACLK,
        pixclk            => pixclk,
        reset            => reset,
        processor_addr    => cdc_addr,
        processor_din    => S_AXI_WDATA(15 downto 0),
        processor_dout    => rdfifo_din,
        processor_we    => cdc_we,
        VGA_RED            => vga_red,
        VGA_GREEN        => vga_green,
        VGA_BLUE        => vga_blue,
        VGA_HSYNC        => vga_hsync,
        VGA_VSYNC        => vga_vsync,
        display_enable    => display_enable
    );
    
    -- dvi_disp
    -- VGA解像度 PLL VCO Freq=400MHz ~ 1000MHz なので、25MHz入力クロックだと最初に20倍する必要がある。
    -- XGA 解像度だと、PLL_CLKFBOUT_MULT=20だと、PLL VCO Freq=1300MHzとなり、1000MHzを超えるので、10倍に変更する。
    dvi_disp_inst : dvi_disp generic map (
        -- PLL_CLKFBOUT_MULT    => 20,    -- VGA
        -- PLL_CLKIN_PERIOD    => 40.0,
        -- PLL_CLKOUT0_DIVIDE    => 2,
        -- PLL_CLKOUT1_DIVIDE    => 20,
        -- PLL_CLKOUT2_DIVIDE    => 10
        
        PLL_CLKFBOUT_MULT    => 20,    -- SVGA
        PLL_CLKIN_PERIOD    => 25.0,
        PLL_CLKOUT0_DIVIDE    => 2,
        PLL_CLKOUT1_DIVIDE    => 20,
        PLL_CLKOUT2_DIVIDE    => 10
        
        -- PLL_CLKFBOUT_MULT    => 10,    -- XGA
        -- PLL_CLKIN_PERIOD    => 15.4,
        -- PLL_CLKOUT0_DIVIDE    => 1,
        -- PLL_CLKOUT1_DIVIDE    => 10,
        -- PLL_CLKOUT2_DIVIDE    => 5
        
        -- PLL_CLKFBOUT_MULT    => 10,    -- SXGA(-3スピードグレードのみ)
        -- PLL_CLKIN_PERIOD        => 9.3,
        -- PLL_CLKOUT0_DIVIDE    => 1,
        -- PLL_CLKOUT1_DIVIDE    => 10,
        -- PLL_CLKOUT2_DIVIDE    => 5
    ) port map (
        pixclk    => pixclk,
        reset_in    => reset,
        red_in        => vga_red8,
        green_in    => vga_green8,
        blue_in        => vga_blue8,
        hsync        => vga_hsync,
        vsync        => vga_vsync,
        display_enable    => display_enable,
        TMDS_tx_clk_p    => TMDS_tx_clk_p,
        TMDS_tx_clk_n    => TMDS_tx_clk_n,
        TMDS_tx_2_G_p    => TMDS_tx_2_G_p,
        TMDS_tx_2_G_n    => TMDS_tx_2_G_n,
        TMDS_tx_1_R_p    => TMDS_tx_1_R_p,
        TMDS_tx_1_R_n    => TMDS_tx_1_R_n,
        TMDS_tx_0_B_p    => TMDS_tx_0_B_p,
        TMDS_tx_0_B_n    => TMDS_tx_0_B_n
    );
    
    vga_red8    <= vga_red & "00000";
    vga_green8    <= vga_green & "00000";
    vga_blue8     <= vga_blue & "00000";

end implementation;


(2012/04/04:cdc_axi_slave.vhd のバグを修正)

下に、afifo_sm.xco の内容を示す。

##############################################################
#
# Xilinx Core Generator version 13.4
# Date: Sat Feb 25 06:45:30 2012
#
##############################################################
#
# This file contains the customisation parameters for a
# Xilinx CORE Generator IP GUI. It is strongly recommended
# that you do not manually alter this file as it may cause
# unexpected and unsupported behavior.
#
##############################################################
#
# Generated from component: xilinx.com:ip:fifo_generator:8.4
#
##############################################################
#
# BEGIN Project Options
SET addpads = false
SET asysymbol = true
SET busformat = BusFormatAngleBracketNotRipped
SET createndf = false
SET designentry = VHDL
SET device = xc6slx45
SET devicefamily = spartan6
SET flowvendor = Other
SET formalverification = false
SET foundationsym = false
SET implementationfiletype = Ngc
SET package = csg324
SET removerpms = false
SET simulationfiles = Behavioral
SET speedgrade = -2
SET verilogsim = false
SET vhdlsim = true
# END Project Options
# BEGIN Select
SELECT Fifo_Generator xilinx.com:ip:fifo_generator:8.4
# END Select
# BEGIN Parameters
CSET add_ngc_constraint_axi=false
CSET almost_empty_flag=true
CSET almost_full_flag=true
CSET aruser_width=1
CSET awuser_width=1
CSET axi_address_width=32
CSET axi_data_width=64
CSET axi_type=AXI4_Stream
CSET axis_type=FIFO
CSET buser_width=1
CSET clock_enable_type=Slave_Interface_Clock_Enable
CSET clock_type_axi=Common_Clock
CSET component_name=afifo_sm
CSET data_count=false
CSET data_count_width=5
CSET disable_timing_violations=false
CSET disable_timing_violations_axi=false
CSET dout_reset_value=0
CSET empty_threshold_assert_value=4
CSET empty_threshold_assert_value_axis=1022
CSET empty_threshold_assert_value_rach=1022
CSET empty_threshold_assert_value_rdch=1022
CSET empty_threshold_assert_value_wach=1022
CSET empty_threshold_assert_value_wdch=1022
CSET empty_threshold_assert_value_wrch=1022
CSET empty_threshold_negate_value=5
CSET enable_aruser=false
CSET enable_awuser=false
CSET enable_buser=false
CSET enable_common_overflow=false
CSET enable_common_underflow=false
CSET enable_data_counts_axis=false
CSET enable_data_counts_rach=false
CSET enable_data_counts_rdch=false
CSET enable_data_counts_wach=false
CSET enable_data_counts_wdch=false
CSET enable_data_counts_wrch=false
CSET enable_ecc=false
CSET enable_ecc_axis=false
CSET enable_ecc_rach=false
CSET enable_ecc_rdch=false
CSET enable_ecc_wach=false
CSET enable_ecc_wdch=false
CSET enable_ecc_wrch=false
CSET enable_handshake_flag_options_axis=false
CSET enable_handshake_flag_options_rach=false
CSET enable_handshake_flag_options_rdch=false
CSET enable_handshake_flag_options_wach=false
CSET enable_handshake_flag_options_wdch=false
CSET enable_handshake_flag_options_wrch=false
CSET enable_read_channel=false
CSET enable_read_pointer_increment_by2=false
CSET enable_reset_synchronization=true
CSET enable_ruser=false
CSET enable_tdata=false
CSET enable_tdest=false
CSET enable_tid=false
CSET enable_tkeep=false
CSET enable_tlast=false
CSET enable_tready=true
CSET enable_tstrobe=false
CSET enable_tuser=false
CSET enable_write_channel=false
CSET enable_wuser=false
CSET fifo_application_type_axis=Data_FIFO
CSET fifo_application_type_rach=Data_FIFO
CSET fifo_application_type_rdch=Data_FIFO
CSET fifo_application_type_wach=Data_FIFO
CSET fifo_application_type_wdch=Data_FIFO
CSET fifo_application_type_wrch=Data_FIFO
CSET fifo_implementation=Common_Clock_Distributed_RAM
CSET fifo_implementation_axis=Common_Clock_Block_RAM
CSET fifo_implementation_rach=Common_Clock_Block_RAM
CSET fifo_implementation_rdch=Common_Clock_Block_RAM
CSET fifo_implementation_wach=Common_Clock_Block_RAM
CSET fifo_implementation_wdch=Common_Clock_Block_RAM
CSET fifo_implementation_wrch=Common_Clock_Block_RAM
CSET full_flags_reset_value=1
CSET full_threshold_assert_value=15
CSET full_threshold_assert_value_axis=1023
CSET full_threshold_assert_value_rach=1023
CSET full_threshold_assert_value_rdch=1023
CSET full_threshold_assert_value_wach=1023
CSET full_threshold_assert_value_wdch=1023
CSET full_threshold_assert_value_wrch=1023
CSET full_threshold_negate_value=14
CSET id_width=4
CSET inject_dbit_error=false
CSET inject_dbit_error_axis=false
CSET inject_dbit_error_rach=false
CSET inject_dbit_error_rdch=false
CSET inject_dbit_error_wach=false
CSET inject_dbit_error_wdch=false
CSET inject_dbit_error_wrch=false
CSET inject_sbit_error=false
CSET inject_sbit_error_axis=false
CSET inject_sbit_error_rach=false
CSET inject_sbit_error_rdch=false
CSET inject_sbit_error_wach=false
CSET inject_sbit_error_wdch=false
CSET inject_sbit_error_wrch=false
CSET input_data_width=16
CSET input_depth=16
CSET input_depth_axis=1024
CSET input_depth_rach=16
CSET input_depth_rdch=1024
CSET input_depth_wach=16
CSET input_depth_wdch=1024
CSET input_depth_wrch=16
CSET interface_type=Native
CSET output_data_width=16
CSET output_depth=16
CSET overflow_flag=true
CSET overflow_flag_axi=false
CSET overflow_sense=Active_High
CSET overflow_sense_axi=Active_High
CSET performance_options=First_Word_Fall_Through
CSET programmable_empty_type=No_Programmable_Empty_Threshold
CSET programmable_empty_type_axis=Empty
CSET programmable_empty_type_rach=Empty
CSET programmable_empty_type_rdch=Empty
CSET programmable_empty_type_wach=Empty
CSET programmable_empty_type_wdch=Empty
CSET programmable_empty_type_wrch=Empty
CSET programmable_full_type=No_Programmable_Full_Threshold
CSET programmable_full_type_axis=Full
CSET programmable_full_type_rach=Full
CSET programmable_full_type_rdch=Full
CSET programmable_full_type_wach=Full
CSET programmable_full_type_wdch=Full
CSET programmable_full_type_wrch=Full
CSET rach_type=FIFO
CSET rdch_type=FIFO
CSET read_clock_frequency=1
CSET read_data_count=false
CSET read_data_count_width=5
CSET register_slice_mode_axis=Fully_Registered
CSET register_slice_mode_rach=Fully_Registered
CSET register_slice_mode_rdch=Fully_Registered
CSET register_slice_mode_wach=Fully_Registered
CSET register_slice_mode_wdch=Fully_Registered
CSET register_slice_mode_wrch=Fully_Registered
CSET reset_pin=true
CSET reset_type=Asynchronous_Reset
CSET ruser_width=1
CSET synchronization_stages=2
CSET synchronization_stages_axi=2
CSET tdata_width=64
CSET tdest_width=4
CSET tid_width=8
CSET tkeep_width=4
CSET tstrb_width=4
CSET tuser_width=4
CSET underflow_flag=true
CSET underflow_flag_axi=false
CSET underflow_sense=Active_High
CSET underflow_sense_axi=Active_High
CSET use_clock_enable=false
CSET use_dout_reset=true
CSET use_embedded_registers=false
CSET use_extra_logic=true
CSET valid_flag=false
CSET valid_sense=Active_High
CSET wach_type=FIFO
CSET wdch_type=FIFO
CSET wrch_type=FIFO
CSET write_acknowledge_flag=false
CSET write_acknowledge_sense=Active_High
CSET write_clock_frequency=1
CSET write_data_count=false
CSET write_data_count_width=5
CSET wuser_width=1
# END Parameters
# BEGIN Extra information
MISC pkg_timestamp=2011-10-22T06:08:52Z
# END Extra information
GENERATE
# CRC: 76cfed70


CharDispCtrlerは、”キャラクタ・ディスプレイ・コントローラのまとめ”からダウンロードすることが出来る。(Verilogです)

dvi_disp.vhd は、”DVI、HDMIの勉強4(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編1)”にVHDLソースコードを貼ってある。dvi_disp.vhd の下位階層のファイルについては、自分で作成したVHDLコードではないので、ブログに貼ることができない。VmodCAMのサンプルのVmodCAM_Ref_VGA Demo_13.zip をダウンロードして、ライブラリをいじってほしい。具体的には、インスタンス時のdigilentライブラリへのリンクは消して、VHDLファイルにcomponent宣言を追加した。
  1. 2012年03月29日 05:12 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする13(Writeはうまく行った)

windyさんから、貴重なアドバイスを頂いてキャラクタ・ディスプレイ・コントローラ AXI4バス・スレーブIPにMicroBlazeからアクセスすることができた。windyさん、ありがとうございました。助かりました。windyさんのアドバイスは”キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする11(インプリメント3)”のコメント欄を参照ください。

そうか、M_AXI_DCとM_AXI_IC は、キャッシュ直結のインターコネクトだったのか?そう言われてみれば、構成とすれば、そうなるか。MicroBlaze Processor Reference Guide Embedded Development Kit EDK 13.4 UG081 (v13.4) のFigure 2-1: MicroBlaze Core Block Diagram を見るとよく分かる。図を下に引用する。
CDC_axi_slave_53_120324.png

・M_AXI_DCとM_AXI_IC はD-CacheとI-Cache に接続されている。cdc_axi_slave をM_AXI_DC のみに接続した。
CDC_axi_slave_52_120324.png

・microblaze_0 をダブルクリックして、設定ダイアログを表示させて、CacheタブのData Cache Featureで、High Address を0xc7ffffff から0xcfffffff に変更した。
CDC_axi_slave_54_120324.png

・cdc_axi_slave_0 のベースアドレスを0xc8000000 に変更した。つまり、D-Cache の範囲に入れた。(2012/04/02:下図でcdc_axi_slave_0 のメモリ・サイズを16Kbytes にしているが、計算の結果これでは足りない。800/8 * 600/8 *4 ≒ 30Kbytes 必要だ)
CDC_axi_slave_55_120324.png

・これでインプリメントした。SDKのProgram FPGAが使えないので、ChipScope からFPGAをコンフィグレーションした。

・Project Navigator からExport Hardware Design To SDK with Bitstream でSDKを立ち上げて、Cプロジェクトを作成した。

・SDKで.elf ファイルの右クリックメニューからDebug As を選択して、デバックモードへ。

・XMDでキャラクタ・ディスプレイ・コントローラ AXI4バス・スレーブIPに mwr コマンドでデータを書き込んだ。
CDC_axi_slave_56_120324.png

・ディスプレイにも表示された。
CDC_axi_slave_57_120324.png

・mwr 0xc800000c 0x0000fc45 のAXI4バスのタイミングチャートを下に貼っておく。
CDC_axi_slave_58_120324.png

抜けいてる信号もあるが、今ある信号を見るかぎりは大丈夫そうだ。

Writeは大丈夫そうだが、Readがおかしいみたいだ。

・mrd 0xc8000000 を実行すると、ERROR: Cannot Read from targetになって、Readすることができない。
CDC_axi_slave_59_120324.png

ChipScope でS_AXI_ARVALID でトリガをかけてもトリガがかからない。キャラクタ・ディスプレイ・コントローラ AXI4バス・スレーブIPにアクセスが来ないみたいだ。

これで、AXI4スレーブIPはとりあえず終了として、次は、このキャラクタ・ディスプレイ・コントローラ AXI4バス・スレーブIPをテストするAXI4バス・マスタIPを作ろうと思う。
  1. 2012年03月24日 09:22 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:2

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする12(現状)

キャラクタ・ディスプレイ・コントローラのAXI4バス・スレーブIPの作成はあまりうまく行ってないが、現状を書いておこうと思う。

まずは、AXI4バス・スレーブIPの名前がCDC_axi_slave で、CDCの大文字が入っているので、シミュレーションできなかと思って、一旦、CDC_axi_slave をデリートして、cdc_axi_slave に書き換えて、もう一度XPSにAdd IP してみた。そうして、シミュレーションしてみたが、やはり、cdc_axi_slave がないと言われてしまった。
CDC_axi_slave_46_120322.png

SDKのXilinx ToolsメニューからProgram FPGA を選択したら、エラーになってしまう。
CDC_axi_slave_48_120322.png

仕方がないので、iMPACT でコンフィグレーションしてから、SDKでchardisp_w_r.elf を右クリックメニューからDebug As -> Launch on Hardware を選択して、デバックモードへ移行する。
XMDを起動して、mwr 0x0001000 0x0000ffc1 でキャラクタ・ディスプレイ・コントローラのAXI4バス・スレーブIPにキャラクタ・データの書き込みを行うが、mrd 0x0001000 で読みだしてもオール0のままで書き込めていない。
CDC_axi_slave_47_120322.png

同じAXI4バス上にあるMCBには読み書きできる。

(現在は、microblaze_0 のAXI4バスのアドレス0x0001000 にキャラクタ・ディスプレイ・コントローラのAXI4バス・スレーブIPを接続している)
CDC_axi_slave_49_120322.png

ChipScope でS_AXI_AWVALID が1の時にトリガーをかけておいてもmwr 0x0001000 0x0000ffc1 でトリガーがかからない。
CDC_axi_slave_50_120322.png

どうやってデバックするか?を考えている。

(2010/03/24:追加)
cdc_axi_slave_v2_1_0.pao ファイルに、”lib cdc_axi_slave_v1_00_a afifo_sm.vhd vhdl”の行を追加してもシミュレーションはできません。
system_top_tb_beh.prj にはcdc_axi_slave.vhd の行もあったし、良く分かりません。つまりコンパイルできているはず。なんでエラボレートできないのだろうか?名前間違っている?

  1. 2012年03月22日 06:01 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:5

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする11(インプリメント3)

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする10(インプリメント2)”でインプリメントすることができたので、今度はソフトウェアを作成して、キャラクタ・ディスプレイ・コントローラをテストする。

その前にMAPのレポートを下に貼っておく。

Release 13.4 Map O.87xd (nt)
Xilinx Mapping Report File for Design 'system_top'

Design Information
------------------
Command Line   : map -intstyle ise -p xc6slx45-csg324-2 -w -logic_opt off -ol
high -t 1 -xt 0 -register_duplication off -r 4 -global_opt off -mt off -ir off
-pr off -lc off -power off -o system_top_map.ncd system_top.ngd system_top.pcf 
Target Device  : xc6slx45
Target Package : csg324
Target Speed   : -2
Mapper Version : spartan6 -- $Revision: 1.55 $
Mapped Date    : MON 19 MAR 6:1:45 2012

Design Summary
--------------
Number of errors:      0
Number of warnings:   30
Slice Logic Utilization:
  Number of Slice Registers:                 4,171 out of  54,576    7%
    Number used as Flip Flops:               4,156
    Number used as Latches:                      0
    Number used as Latch-thrus:                  0
    Number used as AND/OR logics:               15
  Number of Slice LUTs:                      5,209 out of  27,288   19%
    Number used as logic:                    4,777 out of  27,288   17%
      Number using O6 output only:           3,550
      Number using O5 output only:             113
      Number using O5 and O6:                1,114
      Number used as ROM:                        0
    Number used as Memory:                     292 out of   6,408    4%
      Number used as Dual Port RAM:            108
        Number using O6 output only:             4
        Number using O5 output only:             1
        Number using O5 and O6:                103
      Number used as Single Port RAM:            4
        Number using O6 output only:             4
        Number using O5 output only:             0
        Number using O5 and O6:                  0
      Number used as Shift Register:           180
        Number using O6 output only:            83
        Number using O5 output only:             1
        Number using O5 and O6:                 96
    Number used exclusively as route-thrus:    140
      Number with same-slice register load:    123
      Number with same-slice carry load:        12
      Number with other load:                    5

Slice Logic Distribution:
  Number of occupied Slices:                 2,143 out of   6,822   31%
  Nummber of MUXCYs used:                      880 out of  13,644    6%
  Number of LUT Flip Flop pairs used:        6,114
    Number with an unused Flip Flop:         2,333 out of   6,114   38%
    Number with an unused LUT:                 905 out of   6,114   14%
    Number of fully used LUT-FF pairs:       2,876 out of   6,114   47%
    Number of unique control sets:             343
    Number of slice register sites lost
      to control set restrictions:           1,353 out of  54,576    2%

  A LUT Flip Flop pair for this architecture represents one LUT paired with
  one Flip Flop within a slice.  A control set is a unique combination of
  clock, reset, set, and enable signals for a registered element.
  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

IO Utilization:
  Number of bonded IOBs:                        97 out of     218   44%
    Number of LOCed IOBs:                       97 out of      97  100%
    IOB Flip Flops:                             11
    IOB Master Pads:                             4
    IOB Slave Pads:                              4

Specific Feature Utilization:
  Number of RAMB16BWERs:                        29 out of     116   25%
  Number of RAMB8BWERs:                          0 out of     232    0%
  Number of BUFIO2/BUFIO2_2CLKs:                 1 out of      32    3%
    Number used as BUFIO2s:                      1
    Number used as BUFIO2_2CLKs:                 0
  Number of BUFIO2FB/BUFIO2FB_2CLKs:             0 out of      32    0%
  Number of BUFG/BUFGMUXs:                       5 out of      16   31%
    Number used as BUFGs:                        5
    Number used as BUFGMUX:                      0
  Number of DCM/DCM_CLKGENs:                     0 out of       8    0%
  Number of ILOGIC2/ISERDES2s:                   6 out of     376    1%
    Number used as ILOGIC2s:                     6
    Number used as ISERDES2s:                    0
  Number of IODELAY2/IODRP2/IODRP2_MCBs:        24 out of     376    6%
    Number used as IODELAY2s:                    0
    Number used as IODRP2s:                      2
    Number used as IODRP2_MCBs:                 22
  Number of OLOGIC2/OSERDES2s:                  58 out of     376   15%
    Number used as OLOGIC2s:                     5
    Number used as OSERDES2s:                   53
  Number of BSCANs:                              1 out of       4   25%
  Number of BUFHs:                               0 out of     256    0%
  Number of BUFPLLs:                             1 out of       8   12%
  Number of BUFPLL_MCBs:                         1 out of       4   25%
  Number of DSP48A1s:                            3 out of      58    5%
  Number of ICAPs:                               0 out of       1    0%
  Number of MCBs:                                1 out of       2   50%
  Number of PCILOGICSEs:                         0 out of       2    0%
  Number of PLL_ADVs:                            2 out of       4   50%
  Number of PMVs:                                0 out of       1    0%
  Number of STARTUPs:                            0 out of       1    0%
  Number of SUSPEND_SYNCs:                       0 out of       1    0%

Average Fanout of Non-Clock Nets:                3.94

Peak Memory Usage:  407 MB
Total REAL time to MAP completion:  7 mins 6 secs 
Total CPU time to MAP completion:   7 mins 20 secs 


それでは、ソフトウェアを作るためにSDKを起動しよう。

・Project Navigator でsystem.xmp をクリックして、Export Hardware Desin To SDK with Bitstream をダブルクリックする。
CDC_axi_slave_40_120320.png

・SDKが立ち上がる。ワークスペースを聞いてくるので、Atlys_XPS_CDC_SVGA_134\SDK を指定した。

・SDKが立ち上がった。
CDC_axi_slave_41_120320.png

・FileメニューからNew -> Xilinx C Project を選択する。

・New Project ダイアログが立ち上がる。chardispctrl_test プロジェクトを作成する。Select Project Templete でEmpty Application を選択した。
CDC_axi_slave_42_120320.png

・Board Support Package project を作成する。
CDC_axi_slave_43_120320.png

・chardispctrl_test プロジェクトとempty_application_bsp_0 プロジェクトが生成された。

・・FileメニューからNew -> Source File を選択する。New Source File が出るので、Source file にchardispctrl_test.c を指定した。
CDC_axi_slave_45_120320.png

キャラクタ・ディスプレイ・コントローラの仕様は、”キャラクタ・ディスプレイ・コントローラの仕様の変更”に書いた。”赤 (R) の色情報は 15~13ビット目の3ビット、緑 (R) の色情報は 12~10ビット目の3ビット、青 (B) の色情報は 9~7ビット目の3ビットとする。6~0ビット目はキャラクタコードとする。”

・これを元に、ソフトウェアを作ろうとして、適当なソフトウェアを用意したが、SDKのXilinx ToolsメニューからProgram FPGA を選択したら、エラーになった。エラーを下に示す。

Program FPGA failed
Data2MEM failed.


・SDKからFPGAをコンフィグレーションできないので、iMPACTからコンフィグレーションした。

・SDKで.elf ファイルの右クリックメニューからDebug As を選択して、デバックモードへ。

・XMDで0x10000000 にデータをWriteしたが、Readはできなかった。

・microblaze_0 のAXI4バスに接続するとWrite/Readできないが、AXI4 Liteバスに接続すると、XMDのコマンドでWrite/Read することができて、画面をみてもキャラクタが正常に表示されている。

なぜAXI4バスに接続すると、Write/Readできないのかわからない?そのためシミュレーションを行うことにした。

(2010/03/21:追加)
シミュレーションは、キャラクタ・ディスプレイ・コントローラのAXI4バス・スレーブIPのCDC_axi_slaveのCDCが大文字のためシミュレーションがエラーになってしまった。ここは小文字にするべき。

ChipScope を入れて確かめてみることにする。
  1. 2012年03月20日 18:37 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:4
»