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随意 image image

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: 这个名字如何得到?

image image

在tcl窗口中执行上面命令

补充说明2: 这个名字如何得到?

image image

4)仿真结果

image image

可见模块执行正确。读取的数据正确。

5)读写寄存器的细节波形

image image

6)总线传输细节

image

写一次数据的详细过程:写地址-->写数据-->回响应
整个过程3次握手,经过了14个周期。当然,这个可能跟axi_interconnnect路由有关系。

image

读一次数据的详细过程:写地址-->读数据
整个过程2次握手,经过了12个周期。当然,这个可能跟axi_interconnnect路由有关系。

7)补充:如果不用axi_interconnect,直接驱动

image

image

写寄存器,10个周期。快多了。

image

读一个寄存器,5个周期。快多了。