[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_PL-DDR篇连载-01AXI4-FULL-MASTER IP FDMA

文档创建者:FPGA课程
浏览次数:509
最后更新:2024-09-09
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-FPGA部分 » 2_FPGA实验篇(仅旗舰) » 2-FPGA PL DDR使用
​ 软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!



1概述
FDMA是米联客的基于AXI4总线协议定制的一个DMA控制器。本文对AXI4-FULL总线接口进行了封装,同时定义了简单的APP接口提供用户调用AXI4总线实现数据交互。这个IP 我们命名为FDMA(Fast Direct Memory Access)。
有了这个IP我们可以统一实现用FPGA代码直接读写PL的DDR或者ZYNQ/ZYNQMP SOC PS的DDR或者BRAM。FDMA IP CORE 已经广泛应用于ZYNQ SOC/Artix7/Kintex7/ultrascale/ultrascale+系列FPGA/SOC。
如果用过ZYNQ/ZYNQMPSOC的都知道,要直接操作PS的DDR 通常是DMA 或者VDMA,然而用过XILINX 的DMA IP 和VDMA IP,总有一种遗憾,那就是不够灵活,还需要对寄存器配置,真是麻烦。XILINX 的总线接口是AXI4总线,自定义AXI4 IP挂到总线上就能实现对内存地址空间的读写访问。因此,我们只要掌握AXI4协议就能完成不管是PS还是PL DDR的读写操作。
米联客封装的AXI4总线IP命名为uiFDMA,自2018年第一版本发布后,就引起了很多FPGA工程师的兴趣,并且得到了广大FPGA工程师的好评,但是FDMA1.0版本还是有一些局限和BUG,再实际的应用中被FPGA工程师发现,因此给了我们很多宝贵意见。
2020和2022版本中FDMA版本从1.0升级到3.0, Burst默认长度为256,并且自动计算剩余burst长度,相比FDMA1.0具有更好的可靠性,更高的效率,但是3.0发布后,当通常4个FDMA开始传输1080P@60帧的视频同时输出的时候,会导致某个通道总是处于饥饿状态,因为每次AXI burst 256长度太长了,所以我们下面升级到了fdma3.1版本。相比3.0版本默认256 burst长度,在多个FDMA同时使用的时候会导致AXI4总线上某一个通路大量占用总线带宽,3.1版本可以手动设置AXI4的最大burst长度,可以在多个FDMA同时使用的时候,通过设置合理的burst长度,来优化总线上某个通路同一时刻独占AXI4总线的时间。
uiFDMA3.1新增特性:
1:支持多个FDMA IP同时挂到AXI-interconnect总线,同时工作
2:支持自动计算AXI-Burst长度,使用起来非常简单,只需要给出FDMA burst需要burst的总长度。
3:支持AXI-Burst最大长度的人工设置
借此2024版本教程更新发布之际,我们也对FDMA3.1版本升级到FDMA3.2版本。解决3.1版本中,当总的burst长度是奇数的时候出现错误,修改端口命名规则,设置I代表了输入信号,O代表了输出信号。
从本文开始,我们从多个应用方案来演示FDMA的用途。
本文实验目的:
1:分析FDMA源码,掌握基于FDMA的APP接口实现AXI4-FULL总线接口的访问。
2:掌握自定义总线接口封装方法
2AXI总线协议介绍
关于AXI4总线的更多内容可以学习“米联客2024版AXI4总线专题篇”相关课程内容,以下我们继续给出AXI总线相关的描述。
1:AXI总线概述
在XIINX FPGA的软件工具vivado以及相关IP中有支持三种AXI总线,拥有三种AXI接口,当然用的都是AXI协议。其中三种AXI总线分别为:
AXI4:(For high-performance memory-mapped requirements.)主要面向高性能地址映射通信的需求,是面向地址映射的接口,允许最大256轮的数据突发传输;
AXI4-Lite:(For simple, low-throughput memory-mapped communication )是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。
AXI4-Stream:(For high-speed streaming data.)面向高速流数据传输;去掉了地址项,允许无限制的数据突发传输规模。
由于AXI4和AXI4-Lite信号大部分一样,以下只介绍AXI4信号.另外对于AXI4-Stream协议不再本文中介绍,后面有单独介绍的文章。
2:AXI-4总线信号功能2-1:时钟和复位
                        
信号
                        
                        
方向
                        
                        
描述
                        
                        
ACLK
                        
                        
时钟源  
                        
                        
全局时钟信号
                        
                        
ARESETn
                        
                        
复位源
                        
                        
全局复位信号,低有效
                        

2-2:写地址通道信号:
                        
信号
                        
                        
方向
                        
                        
描述
                        
                        
AWID
                        
                        
主机to从机
                        
                        
写地址ID,用来标志一组写信号
                        
                        
AWADDR
                        
                        
主机to从机
                        
                        
写地址,给出一次写突发传输的写地址
                        
                        
AWLEN
                        
                        
主机to从机
                        
                        
AWLEN[7:0]决定写传输的突发长度。AXI3只支持1~16次的突发传输(Burst_length=AxLEN[3:0]+1),AXI4扩展突发长度支持INCR突发类型为1~256次传输,对于其他的传输类型依然保持1~16次突发传输(Burst_Length=AxLEN[7:0]+1)。
                        
burst传输具有如下规则:
                        
wraping burst ,burst长度必须是2,4,8,16
                        
burst不能跨4KB边界
                        
不支持提前终止burst传输
                        
                        
AWSIZE
                        
                        
主机to从机
                        
                        
写突发大小,给出每次突发传输的字节数支持1、2、4、8、16、32、64、128
                        
                        
AWBURST
                        
                        
主机to从机
                        
                        
突发类型:
                        
2’b00 FIXED:突发传输过程中地址固定,用于FIFO访问
                        
2’b01 INCR :增量突发,传输过程中,地址递增。增加量取决AxSIZE的值。
                        
2’b10 WRAP:回环突发,和增量突发类似,但会在特定高地址的边界处回到低地址处。回环突发的长度只能是2,4,8,16次传输,传输首地址和每次传输的大小对齐。最低的地址整个传输的数据大小对齐。回环边界等于(AxSIZE*AxLEN)
                        
2’b11 Reserved
                        
                        
AWLOCK
                        
                        
主机to从机
                        
                        
总线锁信号,可提供操作的原子性
                        
                        
AWCACHE
                        
                        
主机to从机
                        
                        
内存类型,表明一次传输是怎样通过系统的
                        
                        
AWPROT
                        
                        
主机to从机
                        
                        
保护类型,表明一次传输的特权级及安全等级
                        
                        
AWQOS
                        
                        
主机to从机
                        
                        
质量服务QoS
                        
                        
AWREGION
                        
                        
主机to从机
                        
                        
区域标志,能实现单一物理接口对应的多个逻辑接口
                        
                        
AWUSER
                        
                        
主机to从机
                        
                        
用户自定义信号
                        
                        
AWVALID
                        
                        
主机to从机
                        
                        
有效信号,表明此通道的地址控制信号有效
                        
                        
AWREADY
                        
                        
从机to主机
                        
                        
表明“从”可以接收地址和对应的控制信号
                        
2-3:写数据通道信号:
                        
信号名    
                        
                        
方向
                        
                        
描述      
                        
                        
WID
                        
                        
主机to从机
                        
                        
一次写传输的ID tag
                        
                        
WDATA
                        
                        
主机to从机
                        
                        
写数据
                        
                        
WSTRB
                        
                        
主机to从机
                        
                        
WSTRB[n:0]对应于对应的写字节,WSTRB[n]对应WDATA[8n+7:8n]。WVALID为低时,WSTRB可以为任意值,WVALID为高时,WSTRB为高的字节线必须指示有效的数据。
                        
                        
WLAST
                        
                        
主机to从机
                        
                        
表明此次传输是最后一个突发传输
                        
                        
WUSER
                        
                        
主机to从机
                        
                        
用户自定义信号
                        
                        
WVALID
                        
                        
主机to从机
                        
                        
写有效,表明此次写有效
                        
                        
WREADY
                        
                        
从机to主机
                        
                        
表明从机可以接收写数据
                        
2-4:写响应信号:
                        
信号名    
                        
                        
方向
                        
                        
描述      
                        
                        
BID
                        
                        
从机to主机
                        
                        
写响应ID tag
                        
                        
BRESP
                        
                        
从机to主机
                        
                        
写响应,表明写传输的状态
                        
                        
BUSER
                        
                        
从机to主机
                        
                        
用户自定义
                        
                        
BVALID
                        
                        
从机to主机
                        
                        
写响应有效
                        
                        
BREADY
                        
                        
主机to从机
                        
                        
表明主机能够接收写响应
                        
2-5:读地址通道信号:
                        
信号
                        
                        
方向
                        
                        
描述
                        
                        
ARID
                        
                        
主机to从机
                        
                        
读地址ID,用来标志一组写信号
                        
                        
ARADDR
                        
                        
主机to从机
                        
                        
读地址,给出一次读突发传输的读地址
                        
                        
ARLEN
                        
                        
主机to从机
                        
                        
ARLEN[7:0]决定读传输的突发长度。AXI3只支持1~16次的突发传输(Burst_length=AxLEN[3:0]+1),AXI4扩展突发长度支持INCR突发类型为1~256次传输,对于其他的传输类型依然保持1~16次突发传输(Burst_Length=AxLEN[7:0]+1)。
                        
burst传输具有如下规则:
                        
wraping burst ,burst长度必须是2,4,8,16
                        
burst不能跨4KB边界
                        
不支持提前终止burst传输
                        
                        
ARSIZE
                        
                        
主机to从机
                        
                        
读突发大小,给出每次突发传输的字节数支持1、2、4、8、16、32、64、128
                        
                        
ARBURST
                        
                        
主机to从机
                        
                        
突发类型:
                        
2’b00 FIXED:突发传输过程中地址固定,用于FIFO访问
                        
2’b01 INCR :增量突发,传输过程中,地址递增。增加量取决AxSIZE的值。
                        
2’b10 WRAP:回环突发,和增量突发类似,但会在特定高地址的边界处回到低地址处。回环突发的长度只能是2,4,8,16次传输,传输首地址和每次传输的大小对齐。最低的地址整个传输的数据大小对齐。回环边界等于(AxSIZE*AxLEN)
                        
2’b11 Reserved
                        
                        
ARLOCK
                        
                        
主机to从机
                        
                        
总线锁信号,可提供操作的原子性
                        
                        
ARCACHE
                        
                        
主机to从机
                        
                        
内存类型,表明一次传输是怎样通过系统的
                        
                        
ARPROT
                        
                        
主机to从机
                        
                        
保护类型,表明一次传输的特权级及安全等级
                        
                        
ARQOS
                        
                        
主机to从机
                        
                        
质量服务QoS
                        
                        
ARREGION
                        
                        
主机to从机
                        
                        
区域标志,能实现单一物理接口对应的多个逻辑接口
                        
                        
ARUSER
                        
                        
主机to从机
                        
                        
用户自定义信号
                        
                        
ARVALID
                        
                        
主机to从机
                        
                        
有效信号,表明此通道的地址控制信号有效
                        
                        
ARREADY
                        
                        
从机to主机
                        
                        
表明“从”可以接收地址和对应的控制信号
                        
2-6:读数据通道信号:
                        
信号名    
                        
                        
方向
                        
                        
描述      
                        
                        
RID
                        
                        
从机to主机
                        
                        
一次读传输的ID tag
                        
                        
RDATA
                        
                        
从机to主机
                        
                        
读数据
                        
                        
RRESP
                        
                        
从机to主机
                        
                        
读响应,表明读传输的状态
                        
                        
RLAST
                        
                        
从机to主机
                        
                        
表明此次传输是最后一个突发传输
                        
                        
RUSER
                        
                        
从机to主机
                        
                        
用户自定义信号
                        
                        
RVALID
                        
                        
从机to主机
                        
                        
读有效,表明数据总线上数据有效
                        
                        
RREADY
                        
                        
主机to从机
                        
                        
表明主机准备好可以接收数据
                        
3:数据有效的情况
AXI4所采用的是一种READY,VALID握手通信机制,简单来说主从双方进行数据通信前,有一个握手的过程。传输源产生VLAID信号来指明何时数据或控制信息有效。而目地源产生READY信号来指明已经准备好接受数据或控制信息。传输发生在VALID和READY信号同时为高的时候。VALID和READY信号的出现有三种关系。

  • VALID先变高READY后变高。时序图如下:
cc546d40f9b94dce8b9b2871e10df422.jpg
在箭头处信息传输发生。

  • READY先变高VALID后变高。时序图如下:
f22a3bafa6a24e739f13191d85441632.jpg
同样在箭头处信息传输发生。

  • VALID和READY信号同时变高。时序图如下:
81891bf0ed8d4438bc02c2336ef3e9ad.jpg
在这种情况下,信息传输立马发生,如图箭头处指明信息传输发生。
4:突发式读写
4-1:突发式写时序图
0f90c76c9dcf448787545666b676a76f.jpg
290e027273ad44ee9c3ccbe22082caca.jpg
这一过程的开始时,主机发送地址和控制信息到写地址通道中,然后主机发送每一个写数据到写数据通道中。当主机发送最后一个数据时,WLAST信号就变为高。当设备接收完所有数据之后他将一个写响应发送回主机来表明写事务完成。
4-2:突发式读的时序图
7f86191180614e83a52fa53ffafa4f32.jpg
66a5544761e141a4a325887dd3150922.jpg
当地址出现在地址总线后,传输的数据将出现在读数据通道上。设备保持VALID为低直到读数据有效。为了表明一次突发式读写的完成,设备用RLAST信号来表示最后一个被传输的数据。
5:AXI4数据路由及缓存机制
c0a5764f8e0d45c493607fe951f01140.jpg
在上图中,我们描述了典型的AXI总线互联方式,经过AXI-interconnect 可以完成多个MASTER和多个SLAVE之间的互联。比如对于XILINX的SOC来说,内存有PS的DDR也有PL的DDR,还有基于AXI4总线的其他IP,比如PCIE的XDMA IP等,都可以通过AXI-interconnect实现高效的互联,这样各个外设之间的数据就能非常方便的基于AXI4总线实现共享访问。
这里我们有必要了解下AXI4总线中的缓存机制,主要是ARCACHE[3:0]和AWCAHE[3:0]的设置。由于关于这两个参数我们并没有查阅到非常详尽的应用说明,这里米联客的教程以我们查阅的资料和我们自己的理解介绍这两个参数。
5-1:Modifiable和Non-modifiable transaction
当设置AxCACHE[1] = 0,则是Non-modifiable transaction,Non-modifiable transaction不能被拆分成多个transaction传输,也不能合并transaction传输。
在Non-modifiable transaction中以下信号不能修改。
                        
AXADDR
                        
                        
传输起始地址
                        
                        
AXSIZE
                        
                        
传输长度
                        
                        
AXLEN
                        
                        
突然长度
                        
                        
AXBURST
                        
                        
突发类型
                        
                        
AXLOCK
                        
                        
锁类型
                        
                        
AXPORT
                        
                        
保护类型
                        
当设置AxCACHE[1] = 1,则是modifiable transaction, modifiable transaction能被拆分成多个transaction传输,也能合并transaction传输,因此AxADDR、AxSIZE、AxLEN、AxBURST可以被改变。
5-2:AXI4存储类型参数描述
                        
ARCACHE[3:0]
                        
                        
AWCACHE[3:0]
                        
                        
Memory type
                        
                        
0000
                        
                        
0000
                        
                        
Device Non-bufferable
                        
1- write response必须从final destination响应
                        
2- Read data 必须从final destination响应
                        
3- Transactions are non-modifiable(cacheable)
                        
4-读不能被prefetched,写不能被merged
                        
5-来自于同一ID并到同一个Slave的所有Non-modifiable 读写 transactions必须保持顺序
                        
                        
0001
                        
                        
0001
                        
                        
Device Bufferable
                        
1- write response可以从一个中间节点响应
                        
2-write response必须及时到达final destination,而不能永远存储在buffer中
                        
3- Read data必须从final destination响应
                        
4-Transactions are non-modifiable
                        
5-读不能被prefetched,写不能被merged
                        
6-同一ID并到同一个Slave的所有Non-modifiable 读写操作必须保持顺序
                        
                        
0010
                        
                        
0010
                        
                        
Normal Non-cacheable Non-bufferable
                        
1-write response必须从finaldestination 响应
                        
2-Read data 必须从final destination响应
                        
3-Transactions are modifiable
                        
4-写可以merge
                        
5-到有重叠目的地址的来自于同一ID的读写transactions必须保持顺序
                        
                        
0011
                        
                        
0011
                        
                        
Normal Non-cableable Bufferable
                        
1-write response可以从一个中间节点响应
                        
2-Write transaction必须对finaldestination及时可见
                        
3-Read data 要么从final destination 得到,要么从一个正在到它的final destination 的write transaction响应(“它”指write transaction)
                        
4-如果read data从一个write transaction得到,它必须是该write的最近版本,并且,这个data不能被缓存下来。
                        
5-到有重叠目的地址的来自于同一ID的读写transactions必须保持顺序
                        
                        
1010
                        
                        
0110
                        
                        
Write-through No-allocate
                        
1-write response可以从一个中间节点响应
                        
2-Write transaction必须对finaldestination及时可见
                        
3-Read data可以从中间的cache响应
                        
4-Transactions are modifiable
                        
5-Reads可以被prefetched
                        
6-Writes可以被merged
                        
7-Cache lookup is required
                        
8-到有重叠目的地址的来自于同一ID的读写transactions必须保持顺序
                        
8-建议不要对read and write transactions 进行 allocation操作
                        
                        
1110(0110)
                        
                        
0110
                        
                        
Write-through Read-allocate
                        
同Write-through No-allocate功能一样
                        
                        
1010
                        
                        
1110(1010)
                        
                        
Write-through Write-allocate
                        
同Write-through No-allocate功能一样
                        
                        
1110
                        
                        
1110
                        
                        
Write-through Read and Write-allocate
                        
同Write-through No-allocate功能一样
                        
                        
1011
                        
                        
0111
                        
                        
Write-back No-allocate
                        
1-write response可以从一个中间节点得到
                        
2-Write transaction可以对finaldestination不及时可见
                        
3-Read data可以从中间的cache得到
                        
4-Transactions are modifiable
                        
5-Reads可以被prefetched
                        
6-Writes可以被merged
                        
7-Cache lookup is required
                        
8-到有重叠目的地址的来自于同一ID的读写transactions必须保持顺序
                        
9-建议不要对read and write transactions 进行 allocation操作
                        
                        
1111(0111)
                        
                        
0111
                        
                        
Write-back Read-allocate
                        
同Write-back no allocate功能一样
                        
                        
1011
                        
                        
1111(1011)
                        
                        
Write-back Write-allocate
                        
同Write-back no allocate功能一样
                        
                        
1111
                        
                        
1111
                        
                        
Write-back Read and Write-allocate
                        
同Write-back no allocate功能一样
                        
3FDMA源码分析
由于AXI4总线协议直接操作起来相对复杂一些,容易出错,因此我们封装一个简单的用户接口,间接操作AXI4总线会带来很多方便性。先看下我们计划设计一个怎么样的用户接口。
1:FDMA的写时序
cec4979e6f2c4d59b44e97f548f890f0.jpg
fdma_wready设置为1,当fdma_wbusy=0的时候代表FDMA的总线非忙,可以进行一次新的FDMA传输,这个时候可以设置fdma_wreq=1,同时设置fdma burst的起始地址和fdma_wsize本次需要传输的数据大小(以bytes为单位)。当fdma_wvalid=1的时候需要给出有效的数据,写入AXI总线。当最后一个数写完后,fdma_wvalid和fdma_wbusy变为0。
AXI4总线最大的burst lenth是256,而经过封装后,用户接口的fdma_size可以任意大小的,fdma ip内部代码控制每次AXI4总线的Burst长度,这样极大简化了AXI4总线协议的使用。
2:FDMA的读时序
404093143e14490ba6579789bfbfbee1.jpg
同样对于AXI4总线的读操作,AXI4总线最大的burst lenth是256,而经过封装后,用户接口的fdma_size可以任意大小的,fdma ip内部代码控制每次AXI4总线的Burst长度,这样极大简化了AXI4总线协议的使用。
3:FDMA的AXI4-Master写操作
以下代码中我们给出axi4-master写操作的代码分析注释
  1. //AXI4 FULL Write
  2. assign  axi_wdata        = I_fdma_wdata;
  3. assign  O_fdma_wvalid      = w_next;
  4. reg     fdma_wstart_locked = 1'b0;
  5. wire    fdma_wend;
  6. wire    fdma_wstart;
  7. assign   O_fdma_wbusy = fdma_wstart_locked ;
  8. //在整个写过程中fdma_wstart_locked将保持有效,直到本次FDMA写结束
  9. always @(posedge M_AXI_ACLK)
  10.     if(M_AXI_ARESETN == 1'b0 || fdma_wend == 1'b1 )
  11.         fdma_wstart_locked <= 1'b0;
  12.     else if(fdma_wstart)
  13.         fdma_wstart_locked <= 1'b1;                                
  14. //产生fdma_wstart信号,整个信号保持1个  M_AXI_ACLK时钟周期
  15. assign fdma_wstart = (fdma_wstart_locked == 1'b0 && I_fdma_wareq == 1'b1);   
  16.         

  17. //AXI4 write burst lenth busrt addr ------------------------------
  18. //当fdma_wstart信号有效,代表一次新的FDMA传输,首先把地址本次fdma的burst地址寄存到axi_awaddr作为第一次axi burst的地址。如果fdma的数据长度大于256,那么当axi_wlast有效的时候,自动计算下次axi的burst地址
  19. always @(posedge M_AXI_ACLK)
  20.     if(fdma_wstart)   
  21.         axi_awaddr <= I_fdma_waddr;
  22.     else if(axi_wlast == 1'b1)
  23.         axi_awaddr <= axi_awaddr + axi_wburst_size ;                    
  24. //AXI4 write cycle -----------------------------------------------
  25. //axi_wstart_locked_r1, axi_wstart_locked_r2信号是用于时序同步
  26. reg axi_wstart_locked_r1 = 1'b0, axi_wstart_locked_r2 = 1'b0;
  27. always @(posedge M_AXI_ACLK)begin
  28.     axi_wstart_locked_r1 <= axi_wstart_locked;
  29.     axi_wstart_locked_r2 <= axi_wstart_locked_r1;
  30. end
  31. // axi_wstart_locked的作用代表一次axi写burst操作正在进行中。
  32. always @(posedge M_AXI_ACLK)
  33.     if((fdma_wstart_locked == 1'b1) &&  axi_wstart_locked == 1'b0)
  34.         axi_wstart_locked <= 1'b1;
  35.     else if(axi_wlast == 1'b1 || fdma_wstart == 1'b1)
  36.         axi_wstart_locked <= 1'b0;
  37.         
  38. //AXI4 addr valid and write addr-----------------------------------
  39. always @(posedge M_AXI_ACLK)
  40.      if((axi_wstart_locked_r1 == 1'b1) &&  axi_wstart_locked_r2 == 1'b0)
  41.          axi_awvalid <= 1'b1;
  42.      else if((axi_wstart_locked == 1'b1 && M_AXI_AWREADY == 1'b1)|| axi_wstart_locked == 1'b0)
  43.          axi_awvalid <= 1'b0;      
  44. //AXI4 write data---------------------------------------------------        
  45. always @(posedge M_AXI_ACLK)
  46.     if((axi_wstart_locked_r1 == 1'b1) &&  axi_wstart_locked_r2 == 1'b0)
  47.         axi_wvalid <= 1'b1;
  48.     else if(axi_wlast == 1'b1 || axi_wstart_locked == 1'b0)
  49.         axi_wvalid <= 1'b0;//   
  50. //AXI4 write data burst len counter----------------------------------
  51. always @(posedge M_AXI_ACLK)
  52.     if(axi_wstart_locked == 1'b0)
  53.         wburst_cnt <= 'd0;
  54.     else if(w_next)
  55.         wburst_cnt <= wburst_cnt + 1'b1;   
  56.             
  57. assign axi_wlast = (w_next == 1'b1) && (wburst_cnt == M_AXI_AWLEN);
  58. //fdma write data burst len counter----------------------------------
  59. reg wburst_len_req = 1'b0;
  60. reg [15:0] fdma_wleft_cnt =16'd0;

  61. // wburst_len_req信号是自动管理每次axi需要burst的长度
  62. always @(posedge M_AXI_ACLK)
  63.         wburst_len_req <= fdma_wstart|axi_wlast;

  64. // fdma_wleft_cnt用于记录一次FDMA剩余需要传输的数据数量  
  65. always @(posedge M_AXI_ACLK)
  66.     if( fdma_wstart )begin
  67.         wfdma_cnt <= 1'd0;
  68.         fdma_wleft_cnt <= I_fdma_wsize;
  69.     end
  70.     else if(w_next)begin
  71.         wfdma_cnt <= wfdma_cnt + 1'b1;  
  72.         fdma_wleft_cnt <= (I_fdma_wsize - 1'b1) - wfdma_cnt;
  73.     end
  74. //当最后一个数据的时候,产生fdma_wend信号代表本次fdma传输结束
  75. assign  fdma_wend = w_next && (fdma_wleft_cnt == 1 );
  76. //一次axi最大传输的长度是256因此当大于256,自动拆分多次传输
  77. always @(posedge M_AXI_ACLK)begin
  78.     if(M_AXI_ARESETN == 1'b0)begin
  79.         wburst_len <= 1;
  80.     end
  81.     else if(wburst_len_req)begin
  82.         if(fdma_wleft_cnt[15:MAX_BURST_LEN_SIZE] >0)  
  83.             wburst_len <= M_AXI_MAX_BURST_LEN;
  84.         else
  85.             wburst_len <= fdma_wleft_cnt[MAX_BURST_LEN_SIZE-1:0];
  86.     end
  87.     else wburst_len <= wburst_len;
  88. end
复制代码


以上代码我们进行了详细的注释性分析。以下给出FDMA写操作源码部分的时序图。下图中一次传输以传输262个长度的数据为例,如果需要MAX_BURST_LEN_SIZE 设置了最大值256,那么2次AXI4 BURST才能完成,第一次传输256个长度数据,第二次传输6个长度的数据。
da07852f2fe449fb989f4f5138d608bf.jpg
4:FDMA的AXI4-Master读操作
以下代码中我们给出axi4-master读操作的代码分析注释
  1. //fdma axi read----------------------------------------------
  2. reg     [M_AXI_ADDR_WIDTH-1 : 0]    axi_araddr =0   ; //AXI4 读地址
  3. reg                         axi_arvalid  =1'b0; //AXI4读地有效
  4. wire                        axi_rlast   ; //AXI4 读LAST信号
  5. reg                         axi_rready  = 1'b0;//AXI4读准备好
  6. wire                              r_next      = (M_AXI_RVALID && M_AXI_RREADY);// 当valid ready信号都有效,代表AXI4数据传输有效
  7. reg   [8 :0]                        rburst_len  = 1  ; //读传输的axi burst长度,代码会自动计算每次axi传输的burst 长度
  8. reg   [8 :0]                        rburst_cnt  = 0  ; //每次axi bust的计数器
  9. reg   [15:0]                       rfdma_cnt   = 0  ; //fdma的读数据计数器
  10. reg                               axi_rstart_locked =0; //axi 传输进行中,lock住,用于时序控制
  11. wire  [15:0] axi_rburst_size   =   rburst_len * AXI_BYTES; //axi 传输的地址长度计算  

  12. assign M_AXI_ARID       = M_AXI_ID; //读地址ID,用来标志一组写信号, M_AXI_ID是通过参数接口定义
  13. assign M_AXI_ARADDR     = axi_araddr;
  14. assign M_AXI_ARLEN      = rburst_len - 1; //AXI4 burst的长度
  15. assign M_AXI_ARSIZE     = clogb2((AXI_BYTES)-1);
  16. assign M_AXI_ARBURST    = 2'b01; //AXI4的busr类型INCR模式,地址递增
  17. assign M_AXI_ARLOCK     = 1'b0; //不使用cache,不使用buffer
  18. assign M_AXI_ARCACHE    = 4'b0010;
  19. assign M_AXI_ARPROT     = 3'h0;
  20. assign M_AXI_ARQOS      = 4'h0;
  21. assign M_AXI_ARVALID    = axi_arvalid;
  22. assign M_AXI_RREADY     = axi_rready&&I_fdma_rready; //读数据准备好,这里必须设置I_fdma_rready有效
  23. assign O_fdma_rdata       = M_AXI_RDATA;   
  24. assign O_fdma_rvalid      = r_next;   

  25. //AXI4 FULL Read-----------------------------------------   

  26. reg     fdma_rstart_locked = 1'b0;
  27. wire    fdma_rend;
  28. wire    fdma_rstart;
  29. assign   O_fdma_rbusy = fdma_rstart_locked ;
  30. //在整个读过程中fdma_rstart_locked将保持有效,直到本次FDMA写结束
  31. always @(posedge M_AXI_ACLK)
  32.     if(M_AXI_ARESETN == 1'b0 || fdma_rend == 1'b1)
  33.         fdma_rstart_locked <= 1'b0;
  34.     else if(fdma_rstart)
  35.         fdma_rstart_locked <= 1'b1;                                
  36. //产生fdma_rstart信号,整个信号保持1个  M_AXI_ACLK时钟周期
  37. assign fdma_rstart = (fdma_rstart_locked == 1'b0 && I_fdma_rareq == 1'b1);   
  38. //AXI4 read burst lenth busrt addr ------------------------------
  39. //当fdma_rstart信号有效,代表一次新的FDMA传输,首先把地址本次fdma的burst地址寄存到axi_araddr作为第一次axi burst的地址。如果fdma的数据长度大于256,那么当axi_rlast有效的时候,自动计算下次axi的burst地址
  40. always @(posedge M_AXI_ACLK)
  41.     if(fdma_rstart == 1'b1)   
  42.         axi_araddr <= I_fdma_raddr;
  43.     else if(axi_rlast == 1'b1)
  44.         axi_araddr <= axi_araddr + axi_rburst_size ;                                                
  45. //AXI4 r_cycle_flag-------------------------------------   
  46. //axi_rstart_locked_r1, axi_rstart_locked_r2信号是用于时序同步
  47. reg axi_rstart_locked_r1 = 1'b0, axi_rstart_locked_r2 = 1'b0;
  48. always @(posedge M_AXI_ACLK)begin
  49.     axi_rstart_locked_r1 <= axi_rstart_locked;
  50.     axi_rstart_locked_r2 <= axi_rstart_locked_r1;
  51. end
  52. // axi_rstart_locked的作用代表一次axi读burst操作正在进行中。
  53. always @(posedge M_AXI_ACLK)
  54.     if((fdma_rstart_locked == 1'b1) &&  axi_rstart_locked == 1'b0)
  55.         axi_rstart_locked <= 1'b1;
  56.     else if(axi_rlast == 1'b1 || fdma_rstart == 1'b1)
  57.         axi_rstart_locked <= 1'b0;
  58. //AXI4 addr valid and read addr-----------------------------------  
  59. always @(posedge M_AXI_ACLK)
  60.      if((axi_rstart_locked_r1 == 1'b1) &&  axi_rstart_locked_r2 == 1'b0)
  61.          axi_arvalid <= 1'b1;
  62.      else if((axi_rstart_locked == 1'b1 && M_AXI_ARREADY == 1'b1)|| axi_rstart_locked == 1'b0)
  63.          axi_arvalid <= 1'b0;      
  64. //AXI4 read data---------------------------------------------------     
  65. always @(posedge M_AXI_ACLK)
  66.     if((axi_rstart_locked_r1 == 1'b1) &&  axi_rstart_locked_r2 == 1'b0)
  67.         axi_rready <= 1'b1;
  68.     else if(axi_rlast == 1'b1 || axi_rstart_locked == 1'b0)
  69.         axi_rready <= 1'b0;//   
  70. //AXI4 read data burst len counter----------------------------------
  71. always @(posedge M_AXI_ACLK)
  72.     if(axi_rstart_locked == 1'b0)
  73.         rburst_cnt <= 'd0;
  74.     else if(r_next)
  75.         rburst_cnt <= rburst_cnt + 1'b1;            
  76. assign axi_rlast = (r_next == 1'b1) && (rburst_cnt == M_AXI_ARLEN);
  77. //fdma read data burst len counter----------------------------------
  78. reg rburst_len_req = 1'b0;
  79. reg [15:0] fdma_rleft_cnt =16'd0;
  80. // rburst_len_req信号是自动管理每次axi需要burst的长度  
  81. always @(posedge M_AXI_ACLK)
  82.         rburst_len_req <= fdma_rstart | axi_rlast;  
  83. // fdma_rleft_cnt用于记录一次FDMA剩余需要传输的数据数量         
  84. always @(posedge M_AXI_ACLK)
  85.     if(fdma_rstart )begin
  86.         rfdma_cnt <= 1'd0;
  87.         fdma_rleft_cnt <= I_fdma_rsize;
  88.     end
  89.     else if(r_next)begin
  90.         rfdma_cnt <= rfdma_cnt + 1'b1;  
  91.         fdma_rleft_cnt <= (I_fdma_rsize - 1'b1) - rfdma_cnt;
  92.     end
  93. //当最后一个数据的时候,产生fdma_rend信号代表本次fdma传输结束
  94. assign  fdma_rend = r_next && (fdma_rleft_cnt == 1 );
  95. //axi auto burst len caculate-----------------------------------------
  96. //一次axi最大传输的长度是256因此当大于256,自动拆分多次传输
  97. always @(posedge M_AXI_ACLK)begin
  98.      if(M_AXI_ARESETN == 1'b0)begin
  99.         rburst_len <= 1;
  100.      end
  101.      else if(rburst_len_req)begin
  102.         if(fdma_rleft_cnt[15:MAX_BURST_LEN_SIZE] >0)  
  103.             rburst_len <= M_AXI_MAX_BURST_LEN;
  104.         else
  105.             rburst_len <= fdma_rleft_cnt[MAX_BURST_LEN_SIZE-1:0];
  106.      end
  107.      else rburst_len <= rburst_len;
  108. end
复制代码

以上代码我们进行了详细的注释性分析。FDMA的读写代码高度对称,以上源码和以下波形图都和写操作类似,理解起会提高很多效率。
以下给出FDMA读操作源码部分的时序图。下图中一次传输以传输262个长度的数据为例,如果需要MAX_BURST_LEN_SIZE 设置了最大值256,那么2次AXI4 BURST才能完成,第一次传输256个长度数据,第二次传输6个长度的数据。
bfd34dcf499c4272a7bc1c5027c4af61.jpg
4FDMA IP的封装
我先讲解如何封装FDMA IP,之后再分析源码。封装IP少不了源码,这里是利用已经编写好的uiFDMA.v进行封装。
默认的源码路径在配套的工程uisrc/uifdma路径下
ddaf1b0cb06d4cc8a6b7f0b197cac144.jpg
创建一个新的空的fpga工程
578b3e0748414234a210e67ac7c68909.jpg
50fdc8219aa247afa8df7d919addf9a5.jpg
986eb36b8172463486fac1d03af2588b.jpg
f91daa981158474a8f5be79849d2a9eb.jpg
dc237b1caf2249dcb8608983da1ec1d7.jpg
创建IP
e19b08b09d5c4174a1dec7570fe5d6e6.jpg
8d2b113214cd46659cf369fdd570cb4d.jpg
选择Package your current project
4928a084f4b64420ba8e6e5335ff2314.jpg
69c96d4759ef4baea55ba8b2b4dd03ac.jpg
45a8894c308742c2b7c854a46758a8fb.jpg
9e93e3298e35400a8006c65c9433bedc.jpg
按住shift全选后,右击弹出菜单后选择Create Interface Definition
08b063f5995d4b5e9c871dcbabc90dca.jpg
接口定义为slave,命名为FDMA
60a6cf5b30ee406ea2029a175e2432ab.jpg
设置完成,uisrc/03_ip/uifdma路径下多出2个文件,这个两个文件就是定义了自定义的总线接口。
20355624e52f421db41b327c75bc8a34.jpg
d3dc85e4534a42fa9315b61d9c90d567.jpg
现在可以看到封装后的总线
e7f0a04b482a40d19420cc1f787ad4e4.jpg
建议把名字改简洁一些
ab27041f86664a8bb2bdcf88087c70a7.jpg
可以看到封装好的接口,更加美观
e893328ef2184bca81d17020d08fba06.jpg
172db2e333a84cd9a8cf8c150bd5cbb4.jpg


您需要登录后才可以回帖 登录 | 立即注册

本版积分规则