AXI DMA Stream_FIFO读写研究 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

目的

  • 研究stream_fifo的读写行为
  • 研究发现,dma内部其实是有一定容量的fifo的,深度是4
  • 写200个,读300,其实只能读出200个来。

框图

image image

axi stream位宽128 bram位宽32

测试代码

`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 sys_clk;
  bit sys_rst_n;

 system_wrapper system_wrapper_i
       (
        .sys_clk(sys_clk),
        .sys_rst_n(sys_rst_n)
        );        
        
//AXI4-Lite signals
xil_axi_resp_t 	resp;
bit[31:0]  addr, data, base_addr = 32'h40000000;        

//创建时钟和复位信号
// Generate the clock : 50 MHz
initial sys_clk=0;    
always #10ns sys_clk = ~sys_clk;
initial begin
    //Assert the reset
    sys_rst_n = 0;
    #500ns
    // 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);

    #40us;    
    init_bram;

    #20us;
    test_axi4_stream_wr(10);
    
    //#20us;
    //write_sr(32'h40000004,1<<12);
    //test_axi4_stream_wr(20);
    
//    #20us;
//    write_sr(32'h40000004,1<<12);    
//    test_axi4_stream_wr(16*32);  
//    read_sr(32'h40000004);  
         
    #20us;
    //write_sr(32'h40000004,1<<12);    
    test_axi4_stream_rd(20);  
    read_sr(32'h40000004);            
           
end   

task read_sr;
    input [31:0] reg_addr;
    repeat(20) begin
        master_agent.AXI4LITE_READ_BURST(reg_addr,0,data,resp);  
        $display("read sr=%x", data);
    end  
endtask

task write_sr;
    input [31:0] reg_addr;
    input [31:0] reg_val;
     master_agent.AXI4LITE_WRITE_BURST(reg_addr,0,reg_val,resp);  
endtask

task init_bram;
    byte start_val;
    base_addr = 32'hc0000000;
    start_val=1;
    for(int i=0; i<128*4; i+=4) begin
        data[7:0]=start_val+i;
        data[15:8]=start_val+i+1;
        data[23:16]=start_val+i+2;
        data[31:24]=start_val+i+3;
        //$display("%x",data);       
        master_agent.AXI4LITE_WRITE_BURST(base_addr + i,0,data,resp);
    end 
        
    for(int i=0; i<128*4; i++) begin
        master_agent.AXI4LITE_READ_BURST(base_addr + i,0,data,resp);    
        $display("%x",data);
    end      
endtask


task test_axi4_stream_wr;
    input [31:0] length;
    base_addr = 32'h40000000;
    
    addr = 32'h00;  data = 32'h0001_0003;  //状态清除
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
    
    addr = 32'h30;  data = 32'h0001_0003;  //状态清除
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
    
    addr = 32'h18;  data = 32'hC000_0000; //配置源地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);

    addr = 32'h28;  data = length;   //配置传输长度,以byte为单位
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);        
endtask  


task test_axi4_stream_rd;
    input [31:0] length;
    base_addr = 32'h40000000;
    
    addr = 32'h00;  data = 32'h0001_0003;  //状态清除
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
    
    addr = 32'h30;  data = 32'h0001_0003;  //状态清除
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);
    
    addr = 32'h48;  data = 32'hC000_1000; //配置源地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);

    addr = 32'h58;  data = length;   //配置传输长度,以byte为单位
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);        
endtask   

//  initial begin
//    $monitor("Signal tx changed to %b at time %t", tx, $time);
//  end 
    
endmodule

波形(short wr/rd,写10个,读20个)

image image

axi_stream_fifo接口波形。 可见接收后立即就发送了,原因是dma内部有fifo,可以允许接收stream_fifo的数据。

image image image

bram的接口波形。 可以看到先read,后write的过程。由于stream位宽128,因此对于bram的读写一次都是4个word。由于写入的数据实际位宽是10,因此注意到wea[3:0]信号, 这个其实就是byte_mask,第1次0xf,第2次0xf,第3次0x3,因此一共4+4+2=10个数据有效。符合预期。 虽然读20个,其实是没有意义的。其实只是读了4次,因为fifo的有效数据最大只有10 bytes。

波形(long wr/rd,写200个,读300个)

image image image

axi_stream_fifo接口波形。 可见接收后立即就发送了,原因是dma内部有fifo,可以允许接收stream_fifo的数据,但最多只能接收4个stream数据。这说明dma的内部fifo深度是4。

image image image

bram的接口波形。 可以看到先read,后write的过程。由于stream位宽128,因此对于bram的读写一次都是4个word。 虽然读300bytes,其实是没有意义的。其实只是读了50次,因为fifo的有效数据最大只有200bytes。