AXI VIP(AXI Verification IP) Master のお試し

FPGA
スポンサーリンク

はじめに

今回はVivadoのVIP、AXI VIP(AXI Verification IP)を使って、AXI4-LiteMasterとして動作させます。MicroBlazeの代わりとして、AXI GPIO IPのレジスタアクセスをすることを目標とします。

Vivadoバージョン: 2023.2

準備

以下では、Block Designを使って回路を作ります。また、IPのコンフィグを示します。

Block Design

簡単にするために、下記のようなブロック図を考えます。このBlock Designを「Create HDL Wrapper」して、DUTにします。

AXI VIPのコンフィグ

AXI VIPのProduct Guideはこちらです。以下の画像のようなコンフィグで動かします。

IP の概要 • AXI Verification IP v1.1 LogiCORE IP 製品ガイド (PG267) • Reader • AMD Technical Information Portal

AXI GPIOのコンフィグ

GPIOのProduct Guideはこちらです。以下の画像のようなコンフィグで動かします。出力だけです。

AXI GPIO v2.0 Product Guide (PG144) • Viewer • AMD Technical Information Portal

レジスタ空間はこちらです。Address 0x0000にアクセスすれば、Output Dataを変えられるようです。

Address Editor

メモリマップは以下のようにしています。GPIOしかありませんが。

AXI VIPを動かす

AXI VIP Masterを使って、AXI GPIOのレジスタを叩き、出力を変化しているところを見ます。

テストベンチ

以下のようなテストベンチを記載しています。

  • tb_top_gpio: テストベンチ TOPです
  • test: Testシーケンスを記述しています
  • DUT: Block Designから生成したWrapperファイルです

SystemVerilogのコードは以下です。テストベンチの書き方等はSystemVerilog TestBench Example – ADDER – Verification Guideを参考にしました。(全然わかりやすくかけてないですが。)

tb_top_gpio.sv

`timescale 1ns / 1ps

// Interface
`include "interface.sv"

// Testcase
`include "directed_test.sv"

module tb_top_gpio ();

    bit aclk;

    // creatinng instance of interface, inorder to connect DUT and testcase
    intf i_intf (aclk);

    // Testcase instance, interface handle is passed to test as an argument
    test t1 (i_intf);

    // instantiate bd
    AXI_VIP_TEST_wrapper DUT (
        .aclk_0(i_intf.aclk),
        .aresetn_0(i_intf.aresetn),
        .GPIO_0_tri_o(i_intf.GPIO_0_tri_o)
    );

    // Clock
    localparam CLK_CYCLE = 5;  // ns, 100MHz
    always #(CLK_CYCLE) aclk <= ~aclk;

endmodule

interface.sv

interface intf (
    input logic aclk

);
    //declaring the signals
    logic aresetn;
    logic [31:0] GPIO_0_tri_o;

endinterface

test.sv

import axi_vip_pkg::*;
import AXI_VIP_TEST_axi_vip_0_0_pkg::*;

`ifndef GPIO_BASE_ADDR
`define GPIO_BASE_ADDR 32'h4000_0000
`endif

program test (
    intf i_intf
);

    bit [31:0] axi_addr;
    logic [31:0] axi_rd_data = '0;
    bit [31:0] axi_wr_data;
    logic resp;

    AXI_VIP_TEST_axi_vip_0_0_mst_t axi_mst_agent;

    task wait_clk(int n);
        repeat (n) @(posedge i_intf.aclk);
    endtask

    initial begin
        i_intf.aresetn = 1'b0;
        wait_clk(100);
        i_intf.aresetn = 1'b1;
        wait_clk(100);

        // *******************************************************************
        // * AXI VIP
        // *******************************************************************
        // Init AXI agent
        axi_mst_agent = new("my vip agent", DUT.AXI_VIP_TEST_i.axi_vip_0.inst.IF);
        axi_mst_agent.start_master();

        /////////////////////////////////////////////////////////////////////
        // Read Transactions
        /////////////////////////////////////////////////////////////////////
        axi_addr = `GPIO_BASE_ADDR + 0;
        axi_mst_agent.AXI4LITE_READ_BURST(axi_addr, 0, axi_rd_data, resp);
        $display($time, "ns, [READ] ADDR=%h, DATA=%h", axi_addr, axi_rd_data);
        wait_clk(4);

        /////////////////////////////////////////////////////////////////////
        // Write Transactions
        /////////////////////////////////////////////////////////////////////
        axi_addr = `GPIO_BASE_ADDR + 0;
        axi_wr_data = 32'h1;
        axi_mst_agent.AXI4LITE_WRITE_BURST(axi_addr, 0, axi_wr_data, resp);
        $display($time, "ns, [WRITE] ADDR=%h, DATA=%h", axi_addr, axi_wr_data);
        wait_clk(4);

        /////////////////////////////////////////////////////////////////////
        // Read Transactions
        /////////////////////////////////////////////////////////////////////
        axi_addr = `GPIO_BASE_ADDR + 0;
        axi_mst_agent.AXI4LITE_READ_BURST(axi_addr, 0, axi_rd_data, resp);
        $display($time, "ns, [READ] ADDR=%h, DATA=%h", axi_addr, axi_rd_data);

        wait_clk(100);
        $finish();
    end
endprogram

AXI VIP周りの説明を書いておくと、

まずはPackageのimportが必要です。

import axi_vip_pkg::*;
import AXI_VIP_TEST_axi_vip_0_0_pkg::*;

そしたら、MasterのAXI VIPを宣言(?)をします。

    AXI_VIP_TEST_axi_vip_0_0_mst_t axi_mst_agent;

以下で初期設定を行って、

        axi_mst_agent = new("my vip agent", DUT.AXI_VIP_TEST_i.axi_vip_0.inst.IF);
        axi_mst_agent.start_master();

そしたら、行いたいタイミングで、AXI4 LiteのRead/Writeトランザクションを行います。AXI4LITE_READ_BURSTAXI4LITE_WRITE_BURSTで行うようです。たまたま以下で見かけました。結構最近の記事のようです。(日本語に直されたのが最近かも)[日本語ブログ] AXI の基礎 3 – AXI VIP を使用したマスター AXI4-Lite のシミュレーション (xilinx.com)

        /////////////////////////////////////////////////////////////////////
        // Read Transactions
        /////////////////////////////////////////////////////////////////////
        axi_mst_agent.AXI4LITE_READ_BURST(axi_addr, 0, axi_rd_data, resp);


        /////////////////////////////////////////////////////////////////////
        // Write Transactions
        /////////////////////////////////////////////////////////////////////
        axi_mst_agent.AXI4LITE_WRITE_BURST(axi_addr, 0, axi_wr_data, resp);

シミュレーション波形

波形も確認しておきましょう。

矢印の位置で、AXI4 Lite経由でレジスタのRead/Writeおよび、GPIO出力の更新ができていることが確認できました。

おわりに

AXI VIPを使ってみました。初めて使ったのと、テストベンチの書き方が慣れないので、今後も勉強進めていきたいと思います。

参考資料

公式資料

AXI Verification IP (VIP) (xilinx.com)

AR# 70620: 検証 IP (VIP) の API 資料 (xilinx.com)

AXI の基礎 2 – AXI Verification IP (AXI VIP) を使用した AXI インターフェイスのシミュレーション (xilinx.com)

[日本語ブログ] AXI の基礎 3 – AXI VIP を使用したマスター AXI4-Lite のシミュレーション (xilinx.com)

その他記事

XilinxのAXI Verification IPを試す。 #FPGA – Qiita

FPGAの部屋 Vivado 2017.1 の新機能2(AXI Verification IPの概要) (fc2.com)

Xilinx AXI Verification IP (VIP) の Study | 株式会社ライト・ライト (rightxlight.co.jp)

AXI Verification IPを使って任意のアドレスにデータを書き込む #FPGA – Qiita

AXI VIPを使ってレジスタにライトする – ぱたへね (hatenablog.com)

SystemVerilog TestBench Example – ADDER – Verification Guide

コメント

タイトルとURLをコピーしました