第8章
- AXIプロトコルはさらっとおさらい
- 応答チャネルがBなのはResponseとかAnswerとかが使用済みだったから説
- アウトスタンディング転送=オーバーラップ転送。私はアウトスタンディング転送派
AXI VIP
- Xilinx提供のAXI検証用IPであり、無償で使用できる
- AXI3,AXI4,AXI4-Lite,AXI4-Streamをサポート
- すべてのデータ幅、アドレス幅、転送タイプ、応答をサポート
- トランザクションレベルのプロトコルチェック
- マスター、スレーブ、パススルーのモードをサポート
- スレーブ時は内部にメモリを含む/含まないを選択可能
- パススルーはマスター・スレーブ間に挿入してプロトコルチェックを行うモード
テストベンチの確認
テストベンチの記述を上から見ていく。
import部分
VIPに関連するパッケージをインポート
import axi_vip_pkg::*;
import design_1_axi_vip_0_0_pkg::*;
design_1_axi_vip_0_0_pkg
axisim\axisim.srcs\sources_1\bd\design_1\ip\design_1_axi_vip_0_0\sim\design_1_axi_vip_0_0_pkg.sv
BlockDesign上でコンフィグレーションした値でパラメータがコンフィグされ、

それらのパラメータを与えたエージェントを簡単に呼び出すために、typedefでエイリアスしている。
typedef axi_slv_agent #(design_1_axi_vip_0_0_VIP_PROTOCOL,
// 中略
design_1_axi_vip_0_0_VIP_HAS_ARESETN) design_1_axi_vip_0_0_slv_t;
typedef axi_slv_mem_agent #(design_1_axi_vip_0_0_VIP_PROTOCOL,
// 中略
design_1_axi_vip_0_0_VIP_HAS_ARESETN) design_1_axi_vip_0_0_slv_mem_t;
axi_vip_pkg
C:\Xilinx\Vivado\2020.1\data\xilinx_vip\hdl\axi_vip_pkg.sv
ソースコードはVivadoのインストールディレクトリ以下に存在。AXI-VIPの自体の定義であり、enum、parameter、taskなどが記述されている。axi_slv_mem_agentもこのファイルに定義されている。
/*
Class: axi_slv_mem_agent
AXI Slave Agent with Memory
*/
class axi_slv_mem_agent`AXI_PARAM_DECL extends axi_slv_agent`AXI_PARAM_ORDER;
メモリなしのaxi_slv_agentの派生クラスになっている。
エージェントの宣言、起動、制御
/* VIP Slave用のエージェントを宣言し起動 */
design_1_axi_vip_0_0_slv_mem_t agent;
initial begin
agent = new("AXI Slave Agent", dut.design_1_i.axi_vip_0.inst.IF);
agent.start_slave();
fork
user_gen_wready();
user_gen_arready();
join
end
- design_1_axi_vip_0_0_pkg.svのエイリアスにより、テストベンチでの宣言が簡略化されている
- newで実体化するのはSystemVerilog標準だが、newの引数はVIPごとに異なり、axi_slave_mem_agentの場合は下記。第一引数はラベル、第二引数はバーチャルインタフェース
axi_vip_pkg.sv
//Constructor to create an AXI Slave Agent with memory model /* Function: new Constructor to create an AXI Slave Agent with memory model */ function new(string name="unnamed_axi_slv_mem_agent", virtual interface axi_vip_if `AXI_PARAM_ORDER vif); super.new(name,vif); this.mem_model = new($sformatf("%s_mem_model",name)); endfunction :new - エージェントの起動
super.start_slave()はメモリなしのスレーブモデルクラスのメソッドaxi_vip_pkg.sv
virtual task start_slave(); super.start_slave(); fork this.put_wr_response(); this.put_rd_response(); join_none endtask : start_slaveaxi_vip_pkg.svvirtual task start_slave(); fork this.start_monitor(); this.wr_driver.run_phase(); this.rd_driver.run_phase(); join_none fork this.wr_driver.wait_enabled(); this.rd_driver.wait_enabled(); join if(vif_proxy.m_vif.intf_is_slave !=1) begin `xil_fatal(this.get_tag(),$sformatf("Attempting to assign non-SLAVE virtual interface toto slave agent (%s)", this.get_name())) end endtask : start_slave - 別途定義したwready生成タスクとarready生成タスクを並列実行
信号制御タスク
/* WREADYの挙動をプログラミング */
task user_gen_wready();
axi_ready_gen wready_gen;
wready_gen = agent.wr_driver.create_ready("wready");
wready_gen.set_ready_policy(XIL_AXI_READY_GEN_RANDOM);
wready_gen.set_low_time(5);
wready_gen.set_high_time(1);
agent.wr_driver.send_wready(wready_gen);
endtask
- axi_ready_genはバーチャルファンクション
axi_vip_pkg.sv
/* Function: create_ready Returns a ready class that has been "newed". */ virtual function axi_ready_gen create_ready (string name = "unnamed_ready"); axi_ready_gen ready=new(name); return(ready); endfunction
と、ここまで書いてギブアップ。なんとなくやっていることはわかるが、どうやってwready_genをwready信号と対応させているのかとか、agent、sequence_item???
UVMの全体像を少し確認してから、改めて戻ってくることにしたい。
