AXI接口虽然经常使用,很多同学可能并不清楚Vivado里面也集成了AXI的Verification IP,可以当做AXI的master、pass through和slave,本次内容我们看下AXI VIP当作master时如何使用。
新建Vivado工程,并新建block design,命名为:axi_demo
新建axi vip,参数设置如下,第一个参数设置为Master,其他都保持默认,当然如果可以根据自己的实际需求作改动,比如id位宽,数据位宽等等。
再添加AXI BRAM Controller和Block Memory Generator:
地址分配如下:0xc000_0000
生成ip的各种文件:
新建仿真的tb_top文件,需要注意,文件类型是system verilog。
仿真代码放到文章末尾,代码中中导入的axi_demo_axi_vip_0_0_pkg,就是下面axi vip的component_name再加上后缀_pkg
,后面的mst_agent也是component_name加上后缀 _mst_t
import axi_demo_axi_vip_0_0_pkg::*;
axi_demo_axi_vip_0_0_mst_t mst_agent;
运行仿真:
将axi vip的M-AXI添加到波形窗口中:
可以看到,我们一开始向地址0xc0001000写入0x12345678,又发起一次读操作,可以将该数据读出。
有同学可能习惯用vcs来仿真,下篇文章我们再用vcs+verdi来仿真vivado的axi vip。
关注公众号:傅里叶的猫
可以获取更多FPGA相关的博客和内容。
`timescale 1ns / 1psimport axi_vip_pkg::*;
import axi_demo_axi_vip_0_0_pkg::*;module tb_top();bit clk;
bit aresetn;//used in API and parital randomization for transaction generation and data read back from driver
axi_transaction wr_transaction; // Write transaction
axi_transaction rd_transaction; // Read transactionxil_axi_uint mtestWID; // Write ID
xil_axi_ulong mtestWADDR; // Write ADDR
xil_axi_len_t mtestWBurstLength; // Write Burst Length
xil_axi_size_t mtestWDataSize; // Write SIZE
xil_axi_burst_t mtestWBurstType; // Write Burst Type
xil_axi_uint mtestRID; // Read ID
xil_axi_ulong mtestRADDR; // Read ADDR
xil_axi_len_t mtestRBurstLength; // Read Burst Length
xil_axi_size_t mtestRDataSize; // Read SIZE
xil_axi_burst_t mtestRBurstType; // Read Burst Type
xil_axi_lock_t mtestLOCK; // LOCK value for WRITE/READ_BURST transaction
xil_axi_cache_t mtestCacheType = 3; // Cache Type value for WRITE/READ_BURST transaction
xil_axi_prot_t mtestProtectionType = 3'b000; // Protection Type value for WRITE/READ_BURST transaction
xil_axi_region_t mtestRegion = 4'b000; // Region value for WRITE/READ_BURST transaction
xil_axi_qos_t mtestQOS = 4'b000; // QOS value for WRITE/READ_BURST transaction
xil_axi_data_beat dbeat; // Data beat value for WRITE/READ_BURST transaction
xil_axi_user_beat usrbeat; // User beat value for WRITE/READ_BURST transaction
xil_axi_data_beat [255:0] mtestWUSER; // Wuser value for WRITE/READ_BURST transaction
xil_axi_data_beat mtestAWUSER = 'h0; // Awuser value for WRITE/READ_BURST transaction
xil_axi_data_beat mtestARUSER = 0; // Aruser value for WRITE/READ_BURST transaction
xil_axi_data_beat [255:0] mtestRUSER; // Ruser value for WRITE/READ_BURST transaction
xil_axi_uint mtestBUSER = 0; // Buser value for WRITE/READ_BURST transaction
xil_axi_resp_t mtestBresp; // Bresp value for WRITE/READ_BURST transaction
xil_axi_resp_t[255:0] mtestRresp; // Rresp value for WRITE/READ_BURST transactionbit [63:0] mtestWData; // Write Data
bit[8*4096-1:0] Wdatablock; // Write data block
xil_axi_data_beat Wdatabeat[]; // Write data beatsbit [63:0] mtestRData; // Read Data
bit[8*4096-1:0] Rdatablock; // Read data block
xil_axi_data_beat Rdatabeat[]; // Read data beatsinitial beginaresetn = 1'b0;clk = 1'b0;#100ns;aresetn = 1'b1;endalways #10 clk <= ~clk;axi_demo u_dut(.aclk_0 (clk ),.aresetn_0 (aresetn )
);axi_demo_axi_vip_0_0_mst_t mst_agent;initial beginmst_agent = new("master vip agent",u_dut.axi_vip_0.inst.IF);mst_agent.start_master(); // mst_agent start to runmtestWID = $urandom_range(0,(1<<(0)-1)); mtestWADDR = 'hc000_1000;//$urandom_range(0,(1<<(32)-1));mtestWBurstLength = 0;mtestWDataSize = xil_axi_size_t'(xil_clog2((32)/8));mtestWBurstType = XIL_AXI_BURST_TYPE_INCR;mtestWData = 'h12345678;//$urandom();$display("mtestWDataSize = %d", mtestWDataSize);//single write transaction filled in user inputs through API single_write_transaction_api("single write with api",.id(mtestWID),.addr(mtestWADDR),.len(mtestWBurstLength), .size(mtestWDataSize),.burst(mtestWBurstType),.wuser(mtestWUSER),.awuser(mtestAWUSER), .data(mtestWData));mtestRID = $urandom_range(0,(1<<(0)-1));mtestRADDR = mtestWADDR;mtestRBurstLength = 0;mtestRDataSize = xil_axi_size_t'(xil_clog2((32)/8)); mtestRBurstType = XIL_AXI_BURST_TYPE_INCR;$display("mtestRDataSize = %d", mtestRDataSize);//single read transaction filled in user inputs through API single_read_transaction_api("single read with api",.id(mtestRID),.addr(mtestRADDR),.len(mtestRBurstLength), .size(mtestRDataSize),.burst(mtestRBurstType));
endtask automatic single_write_transaction_api ( input string name ="single_write",input xil_axi_uint id =0, input xil_axi_ulong addr =0,input xil_axi_len_t len =0, input xil_axi_size_t size =xil_axi_size_t'(xil_clog2((32)/8)),input xil_axi_burst_t burst =XIL_AXI_BURST_TYPE_INCR,input xil_axi_lock_t lock = XIL_AXI_ALOCK_NOLOCK,input xil_axi_cache_t cache =3,input xil_axi_prot_t prot =0,input xil_axi_region_t region =0,input xil_axi_qos_t qos =0,input xil_axi_data_beat [255:0] wuser =0, input xil_axi_data_beat awuser =0,input bit [63:0] data =0);axi_transaction wr_trans;$display("single_write_transaction_api size = %d", size);wr_trans = mst_agent.wr_driver.create_transaction(name);wr_trans.set_write_cmd(addr,burst,id,len,size);wr_trans.set_prot(prot);wr_trans.set_lock(lock);wr_trans.set_cache(cache);wr_trans.set_region(region);wr_trans.set_qos(qos);wr_trans.set_data_block(data);mst_agent.wr_driver.send(wr_trans); endtask : single_write_transaction_api task automatic single_read_transaction_api ( input string name ="single_read",input xil_axi_uint id =0, input xil_axi_ulong addr =0,input xil_axi_len_t len =0, input xil_axi_size_t size =xil_axi_size_t'(xil_clog2((32)/8)),input xil_axi_burst_t burst =XIL_AXI_BURST_TYPE_INCR,input xil_axi_lock_t lock =XIL_AXI_ALOCK_NOLOCK ,input xil_axi_cache_t cache =3,input xil_axi_prot_t prot =0,input xil_axi_region_t region =0,input xil_axi_qos_t qos =0,input xil_axi_data_beat aruser =0);axi_transaction rd_trans;$display("single_read_transaction_api size = %d", size);rd_trans = mst_agent.rd_driver.create_transaction(name);rd_trans.set_read_cmd(addr,burst,id,len,size);rd_trans.set_prot(prot);rd_trans.set_lock(lock);rd_trans.set_cache(cache);rd_trans.set_region(region);rd_trans.set_qos(qos);mst_agent.rd_driver.send(rd_trans); endtask : single_read_transaction_apiendmodule