AXI VIP DMA CDMA BRAM AXI4_IP综合验证(DMA,CDMA,StreamIP大位宽) - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

配置

image image

DMA和CDMA的配置。设置发现,如果Stream Data Width=128,那么Memory Mapped Data Width必须大于等于128(只有这个选项)。 勾选Allow unaliged transfers

Bram填充数据的波形

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

image axi总线部分:写+读全局

image image axi总线部分:写局部,可以看到bram的awready/wready都是一直有效的。这个与一般的axi4 ip不一样。

image bram接口部分:写局部。对于非连续写,bram的en信号只有1个周期宽度。

image axi总线部分:读局部,地址=00/01/02/03,读出的数据都是一样的。每4个地址的值相同的。也就是说,即使以byte读,也是每次读出的是一个word。这应该是bram的特性, 因为我们的bram的数据位宽是32bits.

image bram接口部分:读局部。可以见,虽然00/01/02/03连续发起了4次读,但是实际上送给bram的地址没有变,都是0x00000000,因此读出的结果是一样的。对于非连续读,bram的en信号只有1个周期宽度。

DMA执行Bram<-->AXI stream ip的拷贝波形(data witdh=128)

task test_axi4_stream_ip;
    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 = 16*32;   //配置传输长度,以byte为单位
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);        
endtask   

分析:data_width=128bits,相当于16bytes。我们要传输的容量=128*4bytes=512bytes,因此要传输32次。另外,由于设置dma的max burst size=16,因此一次burst传输16个128bits,也就是16x16=256bytes。一共需要发生2次burst传输。

image image bram_ctrl部分: 连续发送了2次burst读,后面才开始执行真正的burst读。这就是所谓的outstanding读写模式。因为我们的传输byte=512,而对于axi4_full接口来说(bram的接口是axi4 full), 一次burst只能传输256bytes,因此要拆分为2次传输。 可以看到,每次burst的长度是0x3f=63,对应的bytes数是64x4=256bytes。可以看到地址每次变化0x100,是能够对应的。 rlast一共发生了2次,对应2次burst读。 在连续读模式下,bram的en持续为高。

image dma部分: dma的参数配置过程(axi4_lite接口)

image image image dma接口axi_mm2s部分: 可以看到,mm2s发起了2次读,每次读0xf(对应16个),每次读长度4(对应2^4=16bytes=128bits),因此是16x16=256bytes。 注意每次读16个,应该是我们dma的配置max burst size=16决定的。 可以看到,对于mm2s的memory接口,每读4个cycle,拼满128bits数据,产生一个mm2s_rvalid信号。符合预期。

image image dma接口axis_mm2s部分: 注意到,axis_mm2s的发送,仅仅比axi_mm2s的读取稍晚一点,几乎是同时发生的。这是因为没有fifo,数据没有地方存。 可以看到,mm2s_tvalid/tready会自适应的流控。tvalid与tready的配置,有的地方还会连续发生2次传输结果(例如最后)。自适应的流控是一种握手,这是一件非常好的事情。

仔细观察上面的波形,有发现一个问题,可以看到因为mm2s_tvalid/tready的自适应的流控,导致数据速率忽快忽慢。这不太好,外设不希望速录是忽快忽满的。这可以增加一个stream data fifo来解决这个问题。

18b935558cf198bac028c64da4609cab image

image image stream fifo的波形: 可以看到,fifo是先填充(fifo填满或者数据写完,就启动输出),后输出的。2个不是同时执行的。 可以看到,fifo一加,效果立竿见影!数据基本就是均匀发送了。

image image 如果将data = 16*128,波形如上。可以看到,fifo先填充,随后开始传输(当count=64时候,fifo填满,然后启动传输),后面是并行进行的。由于填充需要4个cycles才能填充一行fifo,但是读出是一个cycle读出一行。因此读出的速度比写入速度快4倍。很快fifo就被读空了。后面就会进入流控阶段了,这个时候stream的发送就是不均匀的了。因此要避免stream发送不均匀,fifo就不能满。

关于Stream Data fifo的一个选项(Enable Packet mode)的用途

image image Enable Packe mode=0,可以看到fifo的tx和fill几乎同时开启,仍然会导致流控。导致tx的数据流速率不稳定。

image image image Enable Packe mode=1,可以看到fifo是先fill,后tx。只要fifo不满,几乎不会有流控问题。因此tx的速率非常稳定。 不过也需要注意到m_axis_ready信号高电平宽度是9个cycles,也就是每发起一轮传输9个。至于9个是怎么来的,不清楚。

CDMA执行Bram<-->Bram的拷贝波形(data witdh=128)

task test_cdma_bram2bram;
    base_addr = 32'h41000000;

    addr = 32'h18;  data = 32'hC000_0000; //配置源地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);

    addr = 32'h20;  data = 32'hC000_1000; //配置目的地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);    

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

image cdma: 传输配置部分

image image image

cdma:rdata部分。可以看到,发起了2次传输,每次长度=0xf(对应16),为什么是这个值? 因为cdma的目前的配置max burst size=16。注意size=4,对应一次传输的长度是2^4=16bytes(也就是位宽是128),那么一次突发的长度是16x16=256bytes。 由于位宽是128,因此每4个cycle(也就是读bram 4次,凑够128bits数据)才产生产生一次rvalid信号。

image image cdma:wdata部分。跟上面相似。

image image bram:rdata部分。可以看到,发起了2次传输,每次长度=0x3f(对应64)为什么是这个值?因为cdma的一次burst,对应bram的一次burst长度是16*4=64,因为它们的位宽是1:4的关系。

image image bram:wdata部分。跟上面相似。

CDMA执行Bram<-->AXI full ip的拷贝波形(data witdh=128)

task test_cdma_bram2axi_full;
    base_addr = 32'h41000000;
  
    //write burst  
    addr = 32'h18;  data = 32'hC000_0000; //配置源地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);

    addr = 32'h20;  data = 32'h4200_0000; //配置目的地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);    

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

    //read burst
    #10us 
    addr = 32'h18;  data = 32'h4200_0000; //配置源地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);

    addr = 32'h20;  data = 32'hC000_1000; //配置目的地址
    master_agent.AXI4LITE_WRITE_BURST(base_addr + addr,0,data,resp);    

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

image cdma的配置

image image cdma: rdata部分,是从bram读取数据。这部分波形,与前面bram->bram的传输几乎一样。不再赘述。

image image cdma: wdata部分,是将数据写入axi_full_ip。这部分的波形,与前面bram->bram的传输几乎一样。其实也就是说,axi_full_ip的默认行为,跟一块bram非常相似。

image axi_lite_full:wdata部分,发生了2次burst写。每次写64个。