分享一个AMBA AXI VIP,用法和Synopsys的VIP非常类似。本文会详细介绍如何使用该VIP的全过程;文末送全部资料。
svk--
|-- base
|
|-- vip
|
|-- example
| |-- axi
|-- src
|-- axi
运行AXI VIP example的方法,如下所示:
cd svk/vip/example/axi/
make run
总体结构框图,如下图所示
4.集成AXI VIP的步骤
如果想集成该AXI VIP到TestBench中,一共需要如下五步:
4.1连接VIP和DUT;
4.2实例化和配置VIP;
4.3构造一个Sequence;
4.4构造一个Test;
4.5添加VIP的文件和路径到编译和仿真。
4.1连接VIP和DUT
module harness;
// 1. Include packages.
import uvm_pkg::*;
import svk_pkg::*;
import svk_axi_pkg::*;
import axi_env_pkg::*;
...
// 2. instantiate and connect clock/reset.
svk_axi_ifs u_if();
assign u_if.master[0].aclk = clk;
assign u_if.master[0].aresetn = rstn;
assign u_if.slave[0].aclk = clk;
assign u_if.slave[0].aresetn = rstn;
// 3. connect AXI interface to the DUT, recommand use force
initial begin
force u_if.slave[0].awvalid = MST_DUT.awvalid;
force MST_DUT.awready = u_if.slave[0].awready;
force SLV_DUT.awvalid = u_if.master[0].awvalid;
force u_if.master[0].awready = SLV_DUT.awready;
...
end
// 4. send virtual interface to environment, "axi_sys_env" is an instance of the AXI system environment(svk_axi_sys_env)
initial begin
uvm_config_db#(virtual svk_axi_ifs)::set(null, "uvm_test_top.env.axi_sys_env", "vif", u_if);
end
endmodule
4.2实例化和配置VIP
4.2.1 参考下面的cfg代码: class cust_axi_sys_env_cfg extends svk_axi_sys_env_cfg;
`uvm_object_utils(cust_axi_sys_env_cfg)
function new(string name="cust_axi_sys_env_cfg");
super.new(name);
master_num = 1;
slave_num = 1;
create_sub_cfg(master_num, slave_num);
for(int i=0; i<master_num; ++i)begin
master_cfg[i].version = svk_axi_dec::AXI4;
master_cfg[i].work_mode = svk_dec::MASTER;
master_cfg[i].wr_osd = 10;
master_cfg[i].rd_osd = 10;
master_cfg[i].ready_timeout_time = 1000;
master_cfg[i].data_width = 256;
master_cfg[i].addr_width = 32;
master_cfg[i].id_width = 8;
end
for(int i=0; i<slave_num; ++i)begin
slave_cfg[i].version = svk_axi_dec::AXI4;
slave_cfg[i].work_mode = svk_dec::SLAVE;
slave_cfg[i].wr_osd = 10;
slave_cfg[i].rd_osd = 10;
slave_cfg[i].ready_timeout_time = 1000;
slave_cfg[i].data_width = 256;
slave_cfg[i].addr_width = 32;
slave_cfg[i].id_width = 8;
end
endfunction
endclass
4.2.2 env参考下面的代码
class axi_env extends uvm_env;
`uvm_component_utils(axi_env)
svk_axi_sys_env axi_sys_env;
svk_axi_sys_env_cfg axi_sys_env_cfg;
function new(string name="axi_env", uvm_component parent);
super.new(name, parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// instanciate svk_axi_sys_env
axi_sys_env = svk_axi_sys_env::type_id::create("axi_sys_env", this);
// set configuration to svk_axi_sys_env
axi_sys_env_cfg = cust_axi_sys_env_cfg::type_id::create("axi_sys_env_cfg");
uvm_config_db#(svk_axi_sys_env_cfg)::set(this, "axi_sys_env", "cfg", axi_sys_env_cfg);
endfunction
endclass
5.构造Sequence,参考下面的代码:
svk_axi_default_master_sequence如下所示:
task svk_axi_default_master_sequence::body();
svk_axi_transaction tr;
svk_axi_agent_cfg axi_cfg;
svk_agent_cfg get_cfg;
// get agent configuration
get_cfg = p_sequencer.get_cfg();
if(!$cast(axi_cfg, get_cfg))
`uvm_error(get_type_name(), "config type is not svk_axi_agent_cfg")
repeat(10)begin
// construct transaction and set configuration
tr = svk_axi_transaction::type_id::create("tr");
tr.cfg = axi_cfg;
// randomize transactoin and send to driver
tr.randomize() with {
addr >= 'h8000_0000;
addr < 'h8000_00ff;
dir == svk_axi_dec::READ;
burst == svk_axi_dec::BURST_INCR;
length < 20;
need_resp == 1;
};
`uvm_send(tr)
if(tr.need_resp)
get_response(rsp, tr.get_transaction_id());
end
...
endtask
svk_axi_default_slave_sequence如下所示:
task body();
svk_axi_transaction tr;
forever begin
// get transacton from slave dirver
p_sequencer.response_request_port.peek(req);
$cast(tr, req);
// randomize and set delay
tr.randomize();
tr.awready_delay = 2;
tr.arready_delay = 0;
foreach(tr.wready_delay[i])
tr.wready_delay[i] = i;
tr.bvalid_delay = 1;
foreach(tr.rvalid_delay[i])
tr.rvalid_delay[i] = i;
// write transaction data to memory or read data from memory to transaction
if(tr.dir == svk_axi_dec::WRITE)begin
p_sequencer.write_data_to_mem(tr);
end
else if(tr.dir == svk_axi_dec::READ)begin
p_sequencer.read_data_from_mem(tr);
end
`uvm_send(tr)
end
endtask
6.构造TEST,请参考下面的代码:
function void build_phase(uvm_phase phase);
super.build_phase(phase);
// Instanciate environment
env = axi_env::type_id::create("env", this);
// start sequence by default sequence mechanism
uvm_config_db#(uvm_object_wrapper)::set(null, "*axi_sys_env.master[0].sqr.main_phase", "default_sequence", svk_axi_default_master_sequence::type_id::get());
uvm_config_db#(uvm_object_wrapper)::set(null, "*axi_sys_env.slave[0].sqr.main_phase", "default_sequence", svk_axi_default_slave_sequence::type_id::get());
endfunction
7.添加文件和路径到编译和仿真,请参考下面的代码:
// specify the directory paths for compiler to load VIP files
+incdir+../../../../svk
// Add Packges and Source file for compiler
../../../../svk/svk_pkg.sv
../../../../svk/svk_axi_pkg.sv
axi_env_pkg.sv
top.sv
8.更多的配置
8.1AGENT的配置,如下面代码所示:
svk_axi_dec::version_enum version = svk_axi_dec::AXI3 ;
int unsigned wr_osd = 1 ;
int unsigned rd_osd = 10 ;
bit wr_interleave_en = 1'b0 ;
int unsigned wr_interleave_depth = 1 ;
bit rd_interleave_en = 1'b0 ;
bit wr_out_of_order_en = 1'b0 ;
bit rd_out_of_order_en = 1'b0 ;
bit data_before_addr = 1'b0 ;
svk_axi_dec::awvalid_delay_event_enum awvalid_delay_event = svk_axi_dec::AWV_PREV_AW_HANDSHAKE_EVENT;
svk_axi_dec::arvalid_delay_event_enum arvalid_delay_event = svk_axi_dec::ARV_PREV_AR_HANDSHAKE_EVENT;
svk_axi_dec::first_wvalid_delay_event_enum first_wvalid_delay_event = svk_axi_dec::FWV_PREV_W_HANDSHAKE_EVENT ;
svk_axi_dec::next_wvalid_delay_event_enum next_wvalid_delay_event = svk_axi_dec::NWV_PREV_W_HANDSHAKE_EVENT ;
svk_axi_dec::first_rvalid_delay_event_enum first_rvalid_delay_event = svk_axi_dec::FRV_AR_HANDSHAKE_EVENT ;
svk_axi_dec::next_rvalid_delay_event_enum next_rvalid_delay_event = svk_axi_dec::NRV_PREV_R_HANDSHAKE_EVENT ;
svk_axi_dec::bvalid_delay_event_enum bvalid_delay_event = svk_axi_dec::BV_LAST_W_HANDSHAKE_EVENT ;
svk_axi_dec::awready_delay_event_enum awready_delay_event = svk_axi_dec::AWR_AWVALID_EVENT ;
svk_axi_dec::arready_delay_event_enum arready_delay_event = svk_axi_dec::ARR_ARVALID_EVENT ;
svk_axi_dec::wready_delay_event_enum wready_delay_event = svk_axi_dec::WR_WVALID_EVENT ;
svk_axi_dec::bready_delay_event_enum bready_delay_event = svk_axi_dec::BR_BVALID_EVENT ;
svk_axi_dec::rready_delay_event_enum rready_delay_event = svk_axi_dec::RR_RVALID_EVENT ;
bit default_bready = 1'b1 ;
bit default_rready = 1'b1 ;
bit default_awready = 1'b1 ;
bit default_arready = 1'b1 ;
bit default_wready = 1'b1 ;
svk_dec::default_value_enum mem_default_value = svk_dec::DEFAULT_ZERO ;
svk_dec::idle_value_enum idle_value = svk_dec::IDLE_ZERO ;
int unsigned ready_timeout_time = 1000 ;
int unsigned data_width = `SVK_AXI_DATA_WIDTH ;
int unsigned addr_width = `SVK_AXI_ADDR_WIDTH ;
int unsigned id_width = `SVK_AXI_ID_WIDTH ;
int unsigned data_user_width = `SVK_AXI_USER_WIDTH ; // w/r
int unsigned resp_user_width = `SVK_AXI_USER_WIDTH ; // b
int unsigned addr_user_width = `SVK_AXI_USER_WIDTH ; // aw/ar
8.2 Transaction的配置,参考下面的代码:
uvm_object extension ;
rand bit need_resp ;
rand int awready_delay ;
rand int awvalid_delay ;
rand int arready_delay ;
rand int arvalid_delay ;
rand int wready_delay[] ;
rand int wvalid_delay[] ;
rand int rready_delay[] ;
rand int rvalid_delay[] ;
rand int bvalid_delay ;
rand int bready_delay ;
svk_axi_agent_cfg cfg;
9.重要的宏定义
`define SVK_AXI_ADDR_WIDTH 64
`define SVK_AXI_DATA_WIDTH 1024
`define SVK_AXI_WSTRB_WIDTH `SVK_AXI_DATA_WIDTH/8
`define SVK_AXI_LEN_WIDTH 8
`define SVK_AXI_SIZE_WIDTH 3
`define SVK_AXI_BURST_WIDTH 2
`define SVK_AXI_LOCK_WIDTH 2
`define SVK_AXI_CACHE_WIDTH 4
`define SVK_AXI_PROT_WIDTH 3
`define SVK_AXI_ID_WIDTH 64
`define SVK_AXI_QOS_WIDTH 4
`define SVK_AXI_REGION_WIDTH 4
`define SVK_AXI_RESP_WIDTH 2
`define SVK_AXI_USER_WIDTH 64
`define SVK_AXI_MAX_OSD 1024
`define SVK_AXI_MAX_NUM_MASTER 16
`define SVK_AXI_MAX_NUM_SLAVE 16
10.接口信号,如下代码所示:
logic aclk;
logic aresetn;
logic awvalid;
logic awready;
logic [`SVK_AXI_ID_WIDTH -1: 0] awid;
logic [`SVK_AXI_ADDR_WIDTH -1: 0] awaddr;
logic [`SVK_AXI_LEN_WIDTH -1: 0] awlen;
logic [`SVK_AXI_SIZE_WIDTH -1: 0] awsize;
logic [`SVK_AXI_BURST_WIDTH -1: 0] awburst;
logic [`SVK_AXI_LOCK_WIDTH -1: 0] awlock;
logic [`SVK_AXI_CACHE_WIDTH -1: 0] awcache;
logic [`SVK_AXI_PROT_WIDTH -1: 0] awprot;
logic [`SVK_AXI_REGION_WIDTH -1: 0] awregion;
logic [`SVK_AXI_USER_WIDTH -1: 0] awuser;
logic [`SVK_AXI_QOS_WIDTH -1: 0] awqos;
logic arvalid;
logic arready;
logic [`SVK_AXI_ID_WIDTH -1: 0] arid;
logic [`SVK_AXI_ADDR_WIDTH -1: 0] araddr;
logic [`SVK_AXI_LEN_WIDTH -1: 0] arlen;
logic [`SVK_AXI_SIZE_WIDTH -1: 0] arsize;
logic [`SVK_AXI_BURST_WIDTH -1: 0] arburst;
logic [`SVK_AXI_LOCK_WIDTH -1: 0] arlock;
logic [`SVK_AXI_CACHE_WIDTH -1: 0] arcache;
logic [`SVK_AXI_PROT_WIDTH -1: 0] arprot;
logic [`SVK_AXI_REGION_WIDTH -1: 0] arregion;
logic [`SVK_AXI_USER_WIDTH -1: 0] aruser;
logic [`SVK_AXI_QOS_WIDTH -1: 0] arqos;
logic rvalid;
logic rready;
logic rlast;
logic [`SVK_AXI_ID_WIDTH -1: 0] rid;
logic [`SVK_AXI_DATA_WIDTH -1: 0] rdata;
logic [`SVK_AXI_RESP_WIDTH -1: 0] rresp;
logic [`SVK_AXI_USER_WIDTH -1: 0] ruser;
logic wvalid;
logic wready;
logic wlast;
logic [`SVK_AXI_ID_WIDTH -1: 0] wid;
logic [`SVK_AXI_DATA_WIDTH -1: 0] wdata;
logic [`SVK_AXI_WSTRB_WIDTH -1: 0] wstrb;
logic [`SVK_AXI_USER_WIDTH -1: 0] wuser;
logic bvalid;
logic bready;
logic [`SVK_AXI_ID_WIDTH -1: 0] bid;
logic [`SVK_AXI_RESP_WIDTH -1: 0] bresp;
logic [`SVK_AXI_USER_WIDTH -1: 0] buser;
logic csysreq;
logic csysack;
logic cactive;
资料获取:
链接:https://pan.baidu.com/s/1BupW11F7a_iWzbgQXgQh7g?pwd=1234
提取码:1234
*免责声明:本文由作者原创。文章内容系作者个人观点,路科验证转载仅为了传达一种不同的观点,不代表路科验证对该观点赞同或支持,如果有任何异议,欢迎联系路科验证。