-
Notifications
You must be signed in to change notification settings - Fork 0
AXI VIP DMA(小位宽及非整数位宽验证)
minichao9901 edited this page Apr 20, 2024
·
2 revisions
- stream_ip的位宽是128,我们想验证如果发送的数据<128bits怎么样?这个时候观察TLAST信号的行为。
- 我们还想验证DMA的SR寄存器,它的行为,这将为软件判断标志位提供帮助。
task test_axi4_stream_ip_short;
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 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
#40us;
init_bram;
read_sr(32'h40000004);
#40us;
test_axi4_stream_ip_short(10);
#40us;
test_axi4_stream_ip_short(20);
#40us;
test_axi4_stream_ip_short(16*32);
read_sr(32'h40000004);
可以看到: 1是写bram阶段, 2是读sr阶段,以及发起第一次dma传输阶段, 3是发起第二次dma传输阶段, 4是发起第三次dma传输阶段, 5是读sr阶段,
可以看到,在启动dma传输前,读取的sr是默认值(最低位Halt=1);发起dma传输后,注意Idle位会从0-->1,因此这个位可以用来作为判断完成的标志。 注意到IOC_Irq位在完成一次dma后会变成1,该为是R/WC,必须手动写1清0,否则会一直是1,因此这个位不适合用作判断完成的标志位。
第一次dma传输(size=10bytes),tkeep[15:0]其实就是byte_mask。可以看到tkeep=0x3ff,也就是最低10个bytes是有效的。
可见,stream的位宽是128,当发送的数据量<128bits时,是通过tkeep来决定哪些数据是有效的,这个相当的巧妙。
第二次dma传输(size=20bytes),需要拆分成2次发送。第一次发送16bytes,tkeep=0xffff用满了;第二次发送4bytes,tkeep=0x000f,只有最低4bytes有效。符合预期。
第三次dma传输(size=16*32bytes),需要拆分成32次发送。由于是整数没有小数,因此32次传输tkeep=0xffff,符合预期。
- 可以看到dmacr初始是0x0001_0002, dmasr初始是0x0000_0001,
- 当往dmacr寄存器写入0x0001_0003之后,于是RS位=1,于是dma开始启动了。这个时候,如果放大可以看到dmasr从0x0000_0001变成0x0000_0000,也也就是Halted=0。当然,注意到其实此时产生了mm2s_halted_set/mm2s_halted_clr信号。
- 我们把第3次dma传输的图局部放大。很清晰了展示了整个过程。
- 可以看到,当最后写入length寄存器的时候,就会产生mm2s_length_wren脉冲,于是启动了dma传输。这个时候会同步产生mm2s_idle_clr,于是IDLE_bit=0。
- 当dma传输完成后,产生mm2s_idle_set和mm2s_ioc_irq_set,于是IDLE_bit=1,IOC_Irq_bit=1。由于IOC_Irq_bit第一次dma后就变成1,一直没有手动清除,因此一直维持为1。