Xilinx AXI Verification IP tutorial
前情提要
一般來說開發Xilinx FPGA上的AXI master/slave ip都是透過C/C++ 轉成HLS或是直接撰寫Verilog。透過C/C++ 轉成的HLS可以自己寫簡單的C/C++ 程式作為testbench,驗證結果可以直接看C/C++ testbench的結果而定,Verilog細節、AXI操作等問題Vivado HLS會幫你完全處理(如果這些部份出現問題,你也沒輒了)。但是透過Verilog直接寫成的IP,通常需要CPU還有記憶體界面(eg. mig)之類的進行全系統測試,而獲取波形等資訊需要透過合成ILA在板子上實際測試。這流程十分繁瑣,合成ILA會浪費大量syntesis和implementation時間,而且可以debug的的訊號數量受限於晶片上的block ram以及LUT數量。然而很多人忽略了Xilinx其實提供了AXI verification IP,可以簡單快速撰寫testbench直接進行behavior simulation,這對於縮短演算法邏輯開發的時間有益。本文主要以 CPU <-> AXI slave <=> AXI master <-> memory此模式為主。
完整文件請看AXI Verification IP v1.0。
AXI Verification IP 簡介
Xilinx AXI Verification IP主要提供的功能為:- 產生AXI master command與資料(可自訂)
- 產生AXI slave進行資料讀取與回覆(也可以模擬mig記憶體界面)
- 檢查AXI protocol
而Xilinx AXI Verification IP (VIP)主要有三種模式:
- 作為AXI master
- 用來測試AXI slave ip
- 作為AXI slave
- 用來測試AXI master ip
- 作為AXI pass-through
- (檢查兩個AXI IP之間的通訊)
AXI VIP提供SystemVerilog界面,透過SystemVerilog的OOP包裝一些AXI protocol操作與memory model。讓開發者可以專注在測試策略上。
flow
tools -> create and Package New IP -> choose Create AXI Peripheral其他創造ip都按照基本流程。
這邊可以選取Verify Peripheral IP using AXI4 VIP,會建構完整的測試template。
完成後會產生如下block diagram
並且產生以下範例testbench,註解為程式區段用途。
`timescale 1ns / 1ps `include "my_dma_v1_0_tb_include.svh" // 以下為必要package import axi_vip_pkg::*; import my_dma_v1_0_bfm_1_slave_0_0_pkg::*; import my_dma_v1_0_bfm_1_master_0_0_pkg::*; module my_dma_v1_0_tb(); // AXI slave VIP 參數宣告(以下省略部份程式碼) xil_axi_uint error_cnt = 0; xil_axi_uint comparison_cnt = 0; axi_transaction wr_transaction; ....... xil_axi_uint mst_agent_verbosity = 0; xil_axi_uint slv_agent_verbosity = 0; // AXI Slave VIP with memory model (如果你的ip為AXI master full會自動產生對應VIP) my_dma_v1_0_bfm_1_slave_0_0_slv_mem_t slv_agent_0; integer result_slave; bit [31:0] S00_AXI_test_data[3:0]; localparam LC_AXI_BURST_LENGTH = 8; localparam LC_AXI_DATA_WIDTH = 32; // AXI master VIP 參數參數宣告 integer i; integer j; xil_axi_uint trans_cnt_before_switch = 48; xil_axi_uint passthrough_cmd_switch_cnt = 0; ...... axi_ready_gen arready_gen2; xil_axi_payload_byte data_mem[xil_axi_ulong]; //AXI master VIP my_dma_v1_0_bfm_1_master_0_0_mst_t mst_agent_0; // Design under test `BD_WRAPPER DUT( .ARESETN(reset), .ACLK(clock) ); initial begin //基本AXI VIP agent初始設定 slv_agent_0 = new("slave vip agent",DUT.`BD_INST_NAME.slave_0.inst.IF); slv_agent_0.set_agent_tag("Slave VIP"); slv_agent_0.set_verbosity(slv_agent_verbosity); slv_agent_0.start_slave(); mst_agent_0 = new("master vip agent",DUT.`BD_INST_NAME.master_0.inst.IF);//ms mst_agent_0.set_agent_tag("Master VIP"); mst_agent_0.set_verbosity(mst_agent_verbosity); mst_agent_0.start_master(); $timeformat (-12, 1, " ps", 1); end initial begin reset <= 1'b0; #100ns; reset <= 1'b1; repeat (5) @(negedge clock); end always #5 clock <= ~clock; initial begin S_AXI_TEST ( ); init_0 = 0; #200ns; init_0 =1'b1; #20ns; init_0 = 1'b0; #1ns; $finish; end initial begin #1; forever begin slv_agent_0.monitor.item_collected_port.get(slv_monitor_transaction); slave_moniter_transaction_queue.push_back(slv_monitor_transaction); slave_moniter_transaction_queue_size++; end end //測試task範例 task automatic S_AXI_TEST; begin #1; $display("Sequential write transfers example similar to AXI BFM WRITE_BURST method starts"); mtestID = 0; mtestADDR = 64'h00000000; mtestBurstLength = 0; mtestDataSize = xil_axi_size_t'(xil_clog2(32/8)); mtestBurstType = XIL_AXI_BURST_TYPE_INCR; mtestLOCK = XIL_AXI_ALOCK_NOLOCK; mtestCacheType = 0; mtestProtectionType = 0; mtestRegion = 0; mtestQOS = 0; result_slave = 1; mtestWDataL[31:0] = 32'h00000001; for(int i = 0; i < 4;i++) begin S00_AXI_test_data[i] <= mtestWDataL[31:0]; //AXI master write transaction mst_agent_0.AXI4LITE_WRITE_BURST( mtestADDR, mtestProtectionType, mtestWDataL, mtestBresp ); mtestWDataL[31:0] = mtestWDataL[31:0] + 1; mtestADDR = mtestADDR + 64'h4; end $display("Sequential write transfers example similar to AXI BFM WRITE_BURST method completes"); $display("Sequential read transfers example similar to AXI BFM READ_BURST method starts"); mtestID = 0; mtestADDR = 64'h00000000; mtestBurstLength = 0; mtestDataSize = xil_axi_size_t'(xil_clog2(32/8)); mtestBurstType = XIL_AXI_BURST_TYPE_INCR; mtestLOCK = XIL_AXI_ALOCK_NOLOCK; mtestCacheType = 0; mtestProtectionType = 0; mtestRegion = 0; mtestQOS = 0; for(int i = 0; i < 4;i++) begin //AXI master產生read transaction mst_agent_0.AXI4LITE_READ_BURST( mtestADDR, mtestProtectionType, mtestRDataL, mtestRresp ); end endtask endmodule
- 對於slave agent有兩種model,分別是:
- <component_name>_slv_t
- 必須自行在user environment(testbecnch)中補上write response與read response(response包含回傳訊息的內容等)
- <component_name>_slv_mem_t
- write response與read response會由agent自行處理
- 帶有memory model
- 對於AXI full master的ip,Vivado會預設使用此agent
Testbench、AXI VIP與DUT的關係
以此架構產生的目標測試環境如上所示。其中由於AXI VIP slave是使用memory mode,所以Slave write/read driver不需要user自己在testbench中補上處理程序。
在使用memory model版本的AXI VIP,可以透過blackdoor_memory_write與blackdoor_memory_read存取模擬出的data memory,而AXI master則可透過一般AXI transaction進行讀寫。memory model大小取決於AXI data width的定址空間大小。
blackdoor memory read範例:
xil_axi_ulong mem_rd_addr = 32'h00000000; bit [32-1:0] mem_rd_data; mem_rd_data = slv_agent_0.mem_model.backdoor_memory_read(mem_rd_addr);blackdoor memory write範例:
bit [32-1:0] wr_data = 0; xil_axi_ulong wr_addr = 0; bit [(32/8)-1:0] wr_strb = 4'hf; //byte select slv_agent_0.mem_model.backdoor_memory_write(wr_addr,wr_data,wr_strb);
memory model使用上可以透過以下code將memory給入預設值方便debug:
slv_agent_0.mem_model.set_memory_fill_policy(XIL_AXI_MEMORY_FILL_FIXED); slv_agent_0.mem_model.set_default_memory_value(32'hdeadbeef);
AXI master VIP進行AXI4 lite read/write的讀寫方式可透過:
xil_axi_ulong mtestADDR; xil_axi_prot_t mtestProtectionType = 3'b000; bit [63:0] mtestWDataL; bit [63:0] mtestRDataL; xil_axi_resp_t mtestBresp; xil_axi_resp_t[255:0] mtestRresp; mst_agent_0.AXI4LITE_WRITE_BURST( mtestADDR, mtestProtectionType, mtestWDataL, mtestBresp); mst_agent_0.AXI4LITE_READ_BURST( mtestADDR, mtestProtectionType, mtestRDataL, mtestRresp);
示範testbench code
在gist連結中:https://gist.github.com/Daichou/6b2e0a62bfc4eeb338e7f82fe40f0cc8其他資源
Xilinx AXI VIP很多資訊只能透過從範例code看註解學習,開啟範例的方法為,先建立一個AXI VIP block design,在block diagram中點擊AXI VIP按右鍵然後會跳出選單,選取open IP example design。在該專案根目錄底下的imports就會含有所有範例testbench。Reference
- AXI Verification IP v1.0
- Validating a master AXI4 interface using the Verification IP as a slave
- Validating a master AXI4 interface using the Verification IP as a slave (part 2)