FC2カウンター FPGAの部屋 2013年12月15日
fc2ブログ

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

FPGAの部屋

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

AXI4 Lite Master BFM の Verilog HDL コード

AXI4 Lite Master BFM の Verilog HDL コードを貼っておく。AXI4 Lite Master BFM は、AXI4 Master BFM のラッパーとして作られている。
Verilog HDL の task で書いてあって、下に示す。7つの task がある。

AXI_LiteM_1Seq_Write(Write Address, Write Data, Write Response をシーケンシャルにオーバーラップせずに行う)
AXI_LiteM_WAC(Write Address Channel の Transaction を実行する)
AXI_LiteM_WDC(Write Data Channel の Transaction を実行する)
AXI_LiteM_WRC(Write Response Channel の Transaction を実行する)
AXI_LiteM_1Seq_Read(Read Address, Read Data をシーケンシャルに行う)
AXI_LiteM_RAC(Read Address Channel の Transaction を実行する)
AXI_LiteM_RDC(Read Data Channel の Transaction を実行する)


下に、Verilog HDL コードを示す。

// AXI4 bus Lite Master Bus Fucntion Mode
// 2013/12/14
// AXI4_Master_BFM のラッパー
//
//

`default_nettype none

`timescale 100ps / 1ps

module AXI4_Lite_Master_BFM #(
    parameter DELAY = 10 )
(
    input   wire    ACLK,

    output wire [31:0] S_AXI_AWADDR,
    output wire [2:0] S_AXI_AWPROT,
    output wire S_AXI_AWVALID,
    output wire [31:0] S_AXI_WDATA,
    output wire [3:0] S_AXI_WSTRB,
    output wire S_AXI_WVALID,
    output wire S_AXI_BREADY,
    output wire [31:0] S_AXI_ARADDR,
    output wire [2:0] S_AXI_ARPROT,
    output wire S_AXI_ARVALID,
    output wire S_AXI_RREADY,

    input wire S_AXI_AWREADY,
    input wire S_AXI_WREADY,
    input wire [1:0] S_AXI_BRESP,
    input wire S_AXI_BVALID,
    input wire S_AXI_ARREADY,
    input wire [31:0] S_AXI_RDATA,
    input wire [1:0] S_AXI_RRESP,
    input wire S_AXI_RVALID
);

    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;

    // RESP の値の定義
    parameter   RESP_OKAY =     2'b00;
    parameter   RESP_EXOKAY =   2'b01;
    parameter   RESP_SLVERR =   2'b10;
    parameter   RESP_DECERR =   2'b11;

    reg  [7:0]  awlen_hold = 0;
    reg  [0:0]  wid_hold = 0;
    reg  axi_w_transaction_active = 0;
    reg  axi_r_transaction_active = 0;
    reg  [7:0]  arlen_hold = 0;

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

    // Write Channel
    // wait_clk_bready : 0 - bready の Wait は無し、0以外 - bready の Wait は wait_clk_bready の値の Wait が入る
    // wmax_wait : 0 - wvalid の Wait は無し、0以外 - wmax_wait を最大値とするランダムな値の Wait が wvalid に入る
    task AXI_LiteM_1Seq_Write; // Write Address, Write Data, Write Response をシーケンシャルにオーバーラップせずに行う。
        input   [31:0]  awaddr;
        input   [31:0]  wdata;
        input   [7:0]   wait_clk_bready;
        input   [7:0]   wmax_wait;
        begin
            MBFMi.AXI_Master_1Seq_Write(1'b0, awaddr, 8'd0, ASIZE_BT_4, ABURST_INCR, wdata, wait_clk_bready, wmax_wait);
        end
    endtask

    // Write Address Channel
    task AXI_LiteM_WAC;
        input   [31:0]  awaddr;
        begin
            MBFMi.AXI_MASTER_WAC(1'b0, awaddr, 8'd0, ASIZE_BT_4, ABURST_INCR);
        end
    endtask

    // Write Data Channel
    // wmax_wait : 0 - wvalid の Wait は無し、0以外 - wmax_wait を最大値とするランダムな値の Wait が wvalid に入る
    task AXI_LiteM_WDC;    // WDATA は+1する
    // とりあえず、WSTRBはオール1にする
        input   [31:0]  wdata;
        input   [7:0]   wmax_wait;  // Write時の最大wait数
        begin
            MBFMi.AXI_MASTER_WDC(wdata, wmax_wait);
        end
    endtask

    // Write Response Channel
    // wait_clk_bready : 0 - bready の Wait は無し、0以外 - bready の Wait は wait_clk_bready の値の Wait が入る
    task AXI_LiteM_WRC;    // wait_clk_bready
        input   [7:0]   wait_clk_bready;
        begin
            MBFMi.AXI_MASTER_WRC(wait_clk_bready);
        end
    endtask

    // Read Channel
    task AXI_LiteM_1Seq_Read; // Read Address, Read Data をシーケンシャルに行う。
        input   [31:0]  araddr;
        input   [7:0]   rmax_wait;  // Read時の最大wait数
        begin
            MBFMi.AXI_Master_1Seq_Read(1'b0, araddr, 8'd0, ASIZE_BT_4, ABURST_INCR);
        end
    endtask

    // Read Address Channel
    task AXI_LiteM_RAC;
        input   [31:0]  araddr;
        begin
            MBFMi.AXI_MASTER_RAC(1'b0, araddr, 8'd0, ASIZE_BT_4, ABURST_INCR);
        end
    endtask

    // Read Data Channel
    task AXI_LiteM_RDC; // S_AXI_RLAST がアサートされるまでS_AXI_RREADY をアサートする
        input   [7:0]   rmax_wait;  // Read時の最大wait数
        begin
            MBFMi.AXI_MASTER_RDC(rmax_wait);
        end
    endtask
endmodule

`default_nettype wire

  1. 2013年12月15日 04:07 |
  2. AX4 Lite Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

ZedBoard AXI4 Lite Slave 演習2(シミュレーション)

ZedBoard AXI4 Lite Slave 演習1”の続き。

今回は、ZedBoard AXI4 Lite Slave 演習の回路 led8_axi_lite_slave.v を作り、テストベンチ (led8_axi_lite_slave_tb.v) を作った。更に、AXI4 Master BFMのラッパーとして、AXI4 Lite Master BFM を作製した。
Project Navigator のプロジェクトを作製して、シミュレーションを行った。
下に、Project Navigator のプロジェクトを示す。(ISE14.7)
AXI4_practice_11_131214.png

AXI4 Lite Slave Write Transaction を示す。Writeの手順を下に示す。

・オフセット4 (LED Counter Load Register) に 32'hAA を Writeする。
・オフセットC (LED Interval Register) に 32'h8 を Writeする。
・オフセット0 (Command Register) に 1 を Writeする。


下に、AXI4 Lite Slave Write のシミュレーション波形を示す。
AXI4_practice_12_131214.png

次に、AXI4 Lite Slave Read Transaction を示す。Readの手順はオフセット0、オフセット4、オフセット8、オフセットCと順番に Readした。シミュレーション波形を下に示す。
AXI4_practice_13_131214.png

最後に、led8_axi_lite_slave.v のシミュレーション波形を下に示す。
AXI4_practice_14_131214.png

テストベンチ、led8_axi_lite_slave_tb.v を下に貼っておく。

`default_nettype none

`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:   05:08:14 12/14/2013
// Design Name:   led8_axi_lite
// Module Name:   D:/HDL/FndtnISEWork/Zynq-7000/ZedBoard/AXI4_bus/parctices/PS_PL_Tutorial/system/pcores/led8_axi_lite_v1_00_a/led8_axi_lite_verilog/led8_axi_lite_tb.v
// Project Name:  led8_axi_lite_verilog
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: led8_axi_lite
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////

module led8_axi_lite_slave_tb;

    parameter DELAY    = 10;

    // Inputs
    wire ACLK;
    wire ARESETN;
    wire [31:0] S_AXI_AWADDR;
    wire [2:0] S_AXI_AWPROT;
    wire S_AXI_AWVALID;
    wire [31:0] S_AXI_WDATA;
    wire [3:0] S_AXI_WSTRB;
    wire S_AXI_WVALID;
    wire S_AXI_BREADY;
    wire [31:0] S_AXI_ARADDR;
    wire [2:0] S_AXI_ARPROT;
    wire S_AXI_ARVALID;
    wire S_AXI_RREADY;

    // Outputs
    wire S_AXI_AWREADY;
    wire S_AXI_WREADY;
    wire [1:0] S_AXI_BRESP;
    wire S_AXI_BVALID;
    wire S_AXI_ARREADY;
    wire [31:0] S_AXI_RDATA;
    wire [1:0] S_AXI_RRESP;
    wire S_AXI_RVALID;
    wire [7:0] LED8bit;

    // Instantiate the Unit Under Test (UUT)
    led8_axi_lite_slave uut (
        .ACLK(ACLK),
        .ARESETN(ARESETN),
        .S_AXI_AWADDR(S_AXI_AWADDR),
        .S_AXI_AWPROT(S_AXI_AWPROT),
        .S_AXI_AWVALID(S_AXI_AWVALID),
        .S_AXI_AWREADY(S_AXI_AWREADY),
        .S_AXI_WDATA(S_AXI_WDATA),
        .S_AXI_WSTRB(S_AXI_WSTRB),
        .S_AXI_WVALID(S_AXI_WVALID),
        .S_AXI_WREADY(S_AXI_WREADY),
        .S_AXI_BRESP(S_AXI_BRESP),
        .S_AXI_BVALID(S_AXI_BVALID),
        .S_AXI_BREADY(S_AXI_BREADY),
        .S_AXI_ARADDR(S_AXI_ARADDR),
        .S_AXI_ARPROT(S_AXI_ARPROT),
        .S_AXI_ARVALID(S_AXI_ARVALID),
        .S_AXI_ARREADY(S_AXI_ARREADY),
        .S_AXI_RDATA(S_AXI_RDATA),
        .S_AXI_RRESP(S_AXI_RRESP),
        .S_AXI_RVALID(S_AXI_RVALID),
        .S_AXI_RREADY(S_AXI_RREADY),
        .LED8bit(LED8bit)
    );

    // AXI4_Lite_Master_BFM
    AXI4_Lite_Master_BFM #(.DELAY(DELAY)) LMBFMi(
        .ACLK(ACLK),
        .S_AXI_AWADDR(S_AXI_AWADDR),
        .S_AXI_AWPROT(S_AXI_AWPROT),
        .S_AXI_AWVALID(S_AXI_AWVALID),
        .S_AXI_AWREADY(S_AXI_AWREADY),
        .S_AXI_WDATA(S_AXI_WDATA),
        .S_AXI_WSTRB(S_AXI_WSTRB),
        .S_AXI_WVALID(S_AXI_WVALID),
        .S_AXI_WREADY(S_AXI_WREADY),
        .S_AXI_BRESP(S_AXI_BRESP),
        .S_AXI_BVALID(S_AXI_BVALID),
        .S_AXI_BREADY(S_AXI_BREADY),
        .S_AXI_ARADDR(S_AXI_ARADDR),
        .S_AXI_ARPROT(S_AXI_ARPROT),
        .S_AXI_ARVALID(S_AXI_ARVALID),
        .S_AXI_ARREADY(S_AXI_ARREADY),
        .S_AXI_RDATA(S_AXI_RDATA),
        .S_AXI_RRESP(S_AXI_RRESP),
        .S_AXI_RVALID(S_AXI_RVALID),
        .S_AXI_RREADY(S_AXI_RREADY)
    );

    // test
    initial begin
        // Initialize Inputs

        // Wait 100 ns for global reset to finish
        #1000;

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

        LMBFMi.AXI_LiteM_1Seq_Write(32'h4, 32'hAA, 0, 0);    // LED8bit = AA, wait_clk_bready=0, wmax_wait=0
        LMBFMi.AXI_LiteM_1Seq_Write(32'hC, 32'h8, 1, 2);    // 8クロックでLEDが+1される, wait_clk_bready=1, wmax_wait=2
        LMBFMi.AXI_LiteM_1Seq_Write(32'h0, 32'h1, 2, 3);    // LED incriment Enable, wait_clk_bready=2, wmax_wait=3

        #1000;    // Wait 100 ns
        @(posedge ACLK);    // 次のクロックへ
        #DELAY;
        LMBFMi.AXI_LiteM_1Seq_Read(32'h0, 0);    // Command Register, rmax_wait=0
        LMBFMi.AXI_LiteM_1Seq_Read(32'h4, 1);    // LED Counter Load Register, rmax_wait=1
        LMBFMi.AXI_LiteM_1Seq_Read(32'h8, 2);    // LED Monitor Register, rmax_wait=2
        LMBFMi.AXI_LiteM_1Seq_Read(32'hC, 3);    // LED Interval Register, rmax_wait=3
    end

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

    // reset_gen
    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年12月15日 03:51 |
  2. AXI4バスの演習資料
  3. | トラックバック:0
  4. | コメント:0