AXI DMA IP核 SG模式 实战:基于BRAM的数据搬移仿真例程

本文是AXI Direct Memory Access IP核在SG模式下的实战例程,参考文档:

AXI Direct Memory Access IP核(1):AXI DMA深度解析_xilinx axi-dma-优快云博客

AXI Direct Memory Access IP核(3):AXI DMA --SG模式仿真例程(xilinx example)


1 引言

       在FPGA设计中,AXI DMA(Direct Memory Access)是实现高速数据搬运的关键IP核。其中SG(Scatter-Gather)模式提供了更灵活的数据传输方式,允许通过描述符链表管理多个不连续内存区域的数据传输。今天我将分享一个完整的AXI DMA SG模式仿真例程,实现从BRAM0到BRAM1的数据搬移。

2 系统架构设计

我们的系统包含以下关键组件:

  • BRAM0:源数据存储区,存放待传输的测试数据

  • BRAM1:目标数据存储区,接收传输完成的数据

  • BRAM2:DMA描述符存储区,存放SG模式的链表信息

  • AXI_DMA0:S2MM通道,将AXI Stream数据转为AXI4写入BRAM1

  • AXI_DMA1:MM2S通道,将BRAM0数据转为AXI Stream输出

  • AXI_VIP:用于初始化内存和配置的AXI验证IP

3 仿真环境搭建

3.1  工程搭建

3.2  地址分配

4 关键代码实现

4.1 测试数据生成与写入

4.2 SG描述符链表配置

此处需要特别注意 0x18的bit [26][27]

在MM2S中,bit[26]为数据包的结束,当该位置1的时候,这一包数据传输完成才会产生Tlast信号,进而拉起MM2S的中断,如果该位为0,即使数据传输完成,tlast也无法拉起,中断也无法产生。

同样在S2MM中,如果没有收到AXIS的Tlast信号,他只是会完成固定数据量的传输,但是不会收到S2MM的中断,这里需要特别注意。

/*Bram2 
0x0000_0000~0x0000_ffff--->DMA0_SG  
    0x0000_0000~0x0000_7fff--->DMA0_SG_MM2S;
    0X0000_8000~0x0000_ffff--->DMA0_SG_S2MM; 

0x0001_0000~0x0001_ffff---->DMA1_SG
    0x0001_0000~0x0001_7fff--->DMA1_SG_MM2S;
    0X0001_8000~0x0001_ffff--->DMA1_SG_S2MM;
*/
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0000 + 8'h00 ,0,32'h0001_0040,mtestBresp); //下一个描述符指针
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0000 + 8'h08 ,0,32'h7000_0000,mtestBresp); //Buffer Address
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0000 + 8'h18 ,0,32'h0c00_0080,mtestBresp); 
//[25:0] buffer length(byte):128个byte-->32个32bit  [26]-->1 数据包的结束   [27]--> 数据包的开始
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0040 + 8'h00 ,0,32'h0001_0080,mtestBresp); //下一个描述符指针
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0040 + 8'h08 ,0,32'h7000_0080,mtestBresp); //Buffer Address
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0040 + 8'h18 ,0,32'h0800_0080,mtestBresp); 

mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0080 + 8'h00 ,0,32'h0000_00C0,mtestBresp); //下一个描述符指针
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0080 + 8'h08 ,0,32'h7000_0100,mtestBresp); //Buffer Address
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0001_0080 + 8'h18 ,0,32'h0400_0080,mtestBresp); 

// DMA0_SG_S2MM
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0000_8000 + 8'h00 ,0,32'h0000_0040,mtestBresp); //下一个描述符指针
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0000_8000 + 8'h08 ,0,32'h6000_0000,mtestBresp); //Buffer Address
mst_agent.AXI4LITE_WRITE_BURST(32'h0000_0000 + 32'h0000_8000 + 8'h18 ,0,32'h0c00_0080,mtestBresp); 

4.3 DMA通道配置

//config axi_dma_0   0x4000_0000
/*0002_7001
[0]=1:启动DMA操作
[12]=1:使能完成中断
[13]=1:延迟中断使能
[14]=1:错误中断使能
[23:16]=0X2 中断阈值
*/
//config dma0
// mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h08 ,0,32'h0001_0000,mtestBresp);    //MM2S 当前描述符指针地址的低32bit
// mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h00 ,0,32'h0002_7001,mtestBresp);    //MM2S DMA控制寄存器
// mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h10 ,0,32'h0001_0000,mtestBresp);    //MM2S 尾描述符指针的低32bit
mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h38 ,0,32'h0000_8000,mtestBresp);    //S2MM 当前描述符指针的低32bit
mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h30 ,0,32'h0001_7001,mtestBresp);    //S2MM 控制寄存器
mst_agent.AXI4LITE_WRITE_BURST(32'h4000_0000 + 8'h40 ,0,32'h0000_8000,mtestBresp);    //S2MM 尾描述符指针的低32bit
//config axi_dma_1   0x5000_0000
/*0002_7001
[0]=1:启动DMA操作
[12]=1:使能完成中断
[13]=1:延迟中断使能
[14]=1:错误中断使能
[23:16]=0X2 中断阈值
*/
//config dma1
mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h08 ,0,32'h0001_0000,mtestBresp);    //MM2S 当前描述符指针地址的低32bit
mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h00 ,0,32'h0001_7001,mtestBresp);    //MM2S DMA控制寄存器
mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h10 ,0,32'h0001_0000,mtestBresp);    //MM2S 尾描述符指针的低32bit
// mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h38 ,0,32'h0000_00c0,mtestBresp);    //S2MM 当前描述符指针的低32bit
// mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h30 ,0,32'h0002_7001,mtestBresp);    //S2MM 控制寄存器
// mst_agent.AXI4LITE_WRITE_BURST(32'h5000_0000 + 8'h40 ,0,32'h0000_0100,mtestBresp);    //S2MM 尾描述符指针的低32bit

5 仿真波形分析

5.1 源数据写入

通过AXI_VIP我们将源数据写入了BRAM0,数据为递增数。

5.2 SG描述符链表配置

通过AXI_VIP我们将描述符链表写入了BRAM2,指定DMA1_MM2S的源地址为BRAM0的基地址,置顶DMA0_S2MM的目的地址为BRAM1的基地址,指定每次传输的数据量为0x80byte。

5.3 DMA配置

通过AXI_VIP配置AXI_DMA1的MM2S,配置其描述符的首指针和尾指针以确认从哪个地址取描述符,配置DMA的使能,中断信息等。

通过AXI_VIP配置AXI_DMA0的S2MM,配置其描述符的首指针和尾指针以确认从哪个地址取描述符,配置DMA的使能,中断信息等。

5.4 AXI_DMA MM2S处理流程

当AXI_LITE配置完成之后,SG接口从BRAM2中读取配置的链表信息。

根据读取的SG信息,MM2S从BRAM0中取数据,DMA将其转为AXIS发出,传输完成之后拉起MM2S中断,之后SG接口往0x1c地址写入完成状态信息,正常为0x8000_0000+buffer_len,之前没有Tlast信号的时候,中断无法拉起,这里的状态信息就是0x8800_0000+buffer_len。

5.5 AXI_DMA S2MM处理流程

当AXI_LITE配置完成之后,SG接口从BRAM2中读取配置的链表信息。

根据读取的SG信息,S2MM接收前端的AXIS数据,DMA将其转为AXI4存入BRAM1,传输完成之后拉起S2MM中断,之后SG接口往0x1c地址写入完成状态信息。

6 资源下载

AXIDMAIP核SG模式实战:基于BRAM的数据搬移仿真例程资源-优快云下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA_小田老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值