Xilinx AXI Verification IP (VIP) の Study
作成者:mou-mou
AXI Bus Functional Model (BFM)がXilinx社より提供されていましたが有償だったので使用していませんでしたが、最近調べてみるとAXI Verification IP (VIP)というものがVivado環境で無償提供されていましたので、少し雰囲気をつかむ為に動かしてみました。機能としては充実しているようで、使いこなすのには少し大変かもしれませんが、基本的なところの動きを見るまでなら非常に簡単に出来ました。ここでは、実際に動かしてみた手順などを紹介いたします。
VIVADOを起動しして、新規プロジェクトを作ります。
プロジェクト名は「AXI_VIP」としました。
AXI_VIPのブロックデザインを生成します。
BRAM ControllerのIPを置きます。
インターフェースを2から1に変更します。
自動配線を実行すると、BRAMが配置されます。
AXI Verification IPを置きます。
今回は、テスト用のAXI Master をおいて、AXI-BRAMのRead/Writeをおこなうので、MODEをMASTERにします。
aclk, aresetn, AXIを接続します。また、aclk, aresetn, rsta_busyのポートを生成します。
Address EditorでBRAMのAXIアドレスを割り付けます。
Address Mapを確認します。
Block Designのラッパーを生成します。
simの下にテストベンチファイルを作ります。
テストベンチ名は、AXI_VIP_TBとします。AXI VIPを使用する為にFile typeはSystem Verilogとします。
テストベンチファイルAXI_VIP_TB.svにコードを記述します。
import axi_vip_pkg::*;
import AXI_VIP_axi_vip_0_0_pkg::*;
module TB_AXI_VIP();
localparam CLK_PERIOD = 100;
localparam RST_PERIOD = 20;
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2022/05/12 17:39:17
// Design Name:
// Module Name: AXI_VIP_TB
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
import axi_vip_pkg::*;
import AXI_VIP_axi_vip_0_0_pkg::*;
module TB_AXI_VIP();
localparam CLK_PERIOD = 100;
localparam RST_PERIOD = 20;
logic aresetn = '0;
logic aclk = '0;
logic rsta_busy;
AXI_VIP_wrapper dut(.*);
initial begin
#(RST_PERIOD);
aresetn = '1;
end
always #(CLK_PERIOD/2) aclk = ~aclk;
task clk_dly(int n);
repeat(n) @(posedge aclk);
endtask
// VIP decreation
AXI_VIP_axi_vip_0_0_mst_t agent;
task init_agent();
agent = new("master vip agent", dut.AXI_VIP_i.axi_vip_0.inst.IF);
agent.start_master();
endtask
task wr_tran();
axi_transaction wr_transaction;
wr_transaction = agent.wr_driver.create_transaction("write transaction");
wr_transaction.set_write_cmd(32'h00000000, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd1);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h00000004, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd2);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h00000008, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd3);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h0000000C, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd4);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h00000010, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd5);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h00000014, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block(32'd6);
agent.wr_driver.send(wr_transaction);
wr_transaction.set_write_cmd(32'h00000018, XIL_AXI_BURST_TYPE_INCR, 0, 4, xil_axi_size_t'(xil_clog2((32)/8)));
wr_transaction.set_data_block({32'd10,32'd9,32'd8,32'd7});
agent.wr_driver.send(wr_transaction);
endtask
task rd_tran();
axi_transaction rd_transaction;
rd_transaction = agent.rd_driver.create_transaction("read transaction");
RD_TRANSACTION_FAIL_1a:assert(rd_transaction.randomize());
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000000, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000004, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000008, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h0000000C, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000010, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000014, XIL_AXI_BURST_TYPE_INCR, 0, 0, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
rd_transaction.set_read_cmd(32'h00000018, XIL_AXI_BURST_TYPE_INCR, 0, 4, xil_axi_size_t'(xil_clog2((32)/8)));
agent.rd_driver.send(rd_transaction);
endtask
enum { init_agent_st, wr_tran_st, rd_tran_st } state;
initial begin
state = init_agent_st; init_agent(); clk_dly(200);
state = wr_tran_st; wr_tran(); clk_dly(200);
state = rd_tran_st; rd_tran(); clk_dly(200);
$finish;
end
endmodule
Synthesisを実行します。
Simulationを実行します。
シミュレーション結果です。