Sunday, March 22, 2020

使用Vivado Xilinx AXI verification IP進行AXI ip開發驗證

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);
blackdoor memory write範例:
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




Friday, March 6, 2020

Verilog Diagram generator

Verilog Diagram generator

最近剛好看到chisel/FIRRTL專案下有一個子專案叫做diagrammer,可以把FIRRTL進行dependency分析後,產生graphiz的dot檔案,包括其中的submodule都可以一併產生,想說看一下verilog開源的專案有沒有類似的工具。後來找到yosys這個synthesis tool可以達到類似的功能。yosys主要針對verilog-2005,systemverilog之類的沒有支援有點可惜。
用法先去clone該專案,進行安裝。
$ git clone https://github.com/YosysHQ/yosys
安裝相依工具:
$ sudo apt-get install build-essential clang bison flex \
 libreadline-dev gawk tcl-dev libffi-dev git \
 graphviz xdot pkg-config python3 libboost-system-dev \
 libboost-python-dev libboost-filesystem-dev zlib1g-dev
進去yosys資料夾後,選擇compiler:
$ make config-clang
$ make config-gcc
然後make && make install
$ make
$ sudo make install
這些步驟都跟readme寫的一樣。
這工具的command和vcs蠻相似的,執行yosys會進到command shell,透過read_verilog載入verilog module,或是read -sv載入verilog module同時elaborate。之後指定top module。她會產生檔案的AST。
yosys> read -sv folder/*.v
yosys> hierarchy -top top_module
接下來可以用show指令顯示diagram。
yosys> show
如果多個module,需要指定顯示程式。(gv是一個程式,可以透過apt-get安裝,ps是postscript的縮寫)
yosys> show -format ps -viewer gv
多個檔案會顯示多組diagram。不過看起來不會寫入合併成一個diagram。他也會在家目錄產生.yosys_show.dotdot檔。可以透過dot程式轉成png或是svg。
其他像xilinx的tool可以產生RTL schematic也可以產生類似功能。而一些商用工具也有這些功能如Synopsys Synplify Pro看起來很完整。
ref

精選文章

使用Ardunio Atmega2560 連接 nRF24L01+

使用Ardunio Atmega2560 連接 nRF24L01+ 關於library 目前主流有 https://github.com/maniacbug/RF24 與 https://github.com/TMRh20/RF24 這兩個。 其中TMRh20大大做...