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,註解為程式區段用途。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | `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範例:
1 2 3 | 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); |
1 2 3 4 | 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:
1 2 | 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的讀寫方式可透過:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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)