AXI VIP的用法 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
AXI VIP(Verification IP)的用法
1)参考文献
https://zhuanlan.zhihu.com/p/390789557
2)block设计
- 用vip驱动2个外设,pwm_ip和uart_ip,这2个外设都是我自己设计和封装好的
- my_uart配置成回环模式,自发自收
- VIP配置为Master模式即可,AXI4或者AXI4-Lite随意
3)testbench
`timescale 1ns / 1ps
//此处import报错为vivado bug,不影响仿真
//Import two required packages: axi_vip_pkg and <component_name>_pkg.
//how to get component_name? use tcl command: get_ips *vip*
import axi_vip_pkg::*;
import system_axi_vip_0_0_pkg::*;
module my_sim_top;
bit done_pulse;
bit led;
bit [3:0]start_pulse;
bit sys_clk;
bit sys_rst_n;
bit tx;
system_wrapper system_wrapper_i
(.done_pulse(done_pulse),
.led(led),
.start_pulse(start_pulse),
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.tx(tx));
//AXI4-Lite signals
xil_axi_resp_t resp;
bit[31:0] addr, data, base_addr = 32'h44A00000, switch_state;
//创建时钟和复位信号
// Generate the clock : 50 MHz
initial sys_clk=0;
always #10ns sys_clk = ~sys_clk;
initial begin
//Assert the reset
sys_rst_n = 0;
#340ns
// Release the reset
sys_rst_n = 1;
end
//创建axi_vip的agent
//<component_name>_mst_t
system_axi_vip_0_0_mst_t master_agent;
initial begin
// Step 4 - Create a new agent
master_agent = new("master vip agent",system_wrapper_i.system_i.axi_vip_0.inst.IF);
// Step 5 - Start the agent
master_agent.start_master();
//Wait for the reset to be released
wait (sys_rst_n == 1'b1);
// my_pwm_ip
#100us //写寄存器0, pwm_en
addr = 32'h00; data = 32'h01;
master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
#200ns //写寄存器1,set_freq
addr = 32'h04; data = 32'hee;
master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
#200ns //写寄存器2,set_width
addr = 32'h08; data = 32'h88;
master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
#200ns //写寄存器3,gen pwm_start_pulse
addr = 32'h00c; data = 32'h01;
master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
#20000
//switch to my_uart_ip
base_addr = 32'h44A10000;
addr = 32'h00; data = "h"; //写寄存器0, 发送'h'
master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
#200000 //读寄存器1,得到接收的数据
addr = 32'h04; data = 32'h0;
master_agent.AXI4LITE_READ_BURST(base_addr + addr,0,data,resp);
$display("read char=%c", data);
#200 //读寄存器2判断接收数据标志位
addr = 32'h08; data = 32'h0;
master_agent.AXI4LITE_READ_BURST(base_addr + addr,0,data,resp);
$display("read status=%x", data);
end
initial begin
$monitor("Signal tx changed to %b at time %t", tx, $time);
end
endmodule
补充说明1: 这个名字如何得到?
在tcl窗口中执行上面命令
补充说明2: 这个名字如何得到?
4)仿真结果
可见模块执行正确。读取的数据正确。
5)读写寄存器的细节波形
6)总线传输细节
写一次数据的详细过程:写地址-->写数据-->回响应
整个过程3次握手,经过了14个周期。当然,这个可能跟axi_interconnnect路由有关系。
读一次数据的详细过程:写地址-->读数据
整个过程2次握手,经过了12个周期。当然,这个可能跟axi_interconnnect路由有关系。
7)补充:如果不用axi_interconnect,直接驱动
写寄存器,10个周期。快多了。
读一个寄存器,5个周期。快多了。