文章目录概述1 AXI 总线协议介绍1.1 AXI 总线概述1.2 AXI-4 总线信号功能1.2.2 时钟和复位1.2.2 写地址通道信号1.2.3 写数据通道信号1.2.4 写响应信号1.2.5 读地址通道信号1.2.6 读数据通道信号1.3 数据有效的情况1.4 突发式读写1.4.1 突发式写时序图1.4.2 突发式读的时序图1.5 AXI4 数据路由及缓存机制1.5.1 Modifiable 和 Non-modifiable transaction1.5.2 AXI4 存储类型参数描述2 FDMA源码分析2.1 FDMA 的写时序2.2 FDMA 的读时序2.3 FDMA 的 AXI4-Master 写操作2.4 FDMA 的 AXI4-Master 读操作3 FDMA IP的封装4 总结概述FDMA 是米联客的基于 AXI4 总线协议定制的一个 DMA 控制器。 本文将对FDMA(Fast Direct MemoryAccess)这一IP进行详细介绍和使用说明。我们基于这个IP可以统一实现用FPGA代码直接读写PL的DDR或者ZYNQ/ZYNQ MP SOC PS的DDR或者BRAMFDMA IP CORE已经广泛应用于ZYNQSOC/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的读写操作。本文的目的1:分析 FDMA 源码掌握基于FDMA的APP接口实现AXI4-FULL总线接口的访问。2:掌握自定义总线接口封装方法。PS:目前米联客已经将FDMA版本更新至FDMA5.1,但整体思路还是一直没变。感兴趣的可以自己去官网下载了解。1 AXI 总线协议介绍1.1 AXI 总线概述在 XIINX FPGA 的软件工具vivado以及相关IP中有支持三种AXI总线拥有三种AXI接口当然用的都是AXI协议。其中三种AXI总线分别为AXI4For high-performance memory-mapped requirements.主要面向高性能地址映射通信的需求是面向地址映射的接口允许最大256轮的数据突发传输AXI4-LiteFor simple, low-throughput memory-mapped communication 是一个轻量级的地址映射单次传输接口占用很少的逻辑单元。AXI4-StreamFor high-speed streaming data.面向高速流数据传输去掉了地址项 允许无限制的数据突发传输规模。由于AXI4和AXI4-Lite信号大部分一样以下只介绍AXI4信号。另外对于AXI4-Stream协议不再本文中介绍后面有单独介绍的文章。1.2 AXI-4 总线信号功能1.2.2 时钟和复位信号方向描述ACLK时钟源全局时钟信号ARESETn复位源全局复位信号 低有效1.2.2 写地址通道信号1.2.3 写数据通道信号1.2.4 写响应信号1.2.5 读地址通道信号1.2.6 读数据通道信号1.3 数据有效的情况AXI4所采用的是一种READYVALID握手通信机制简单来说主从双方进行数据通信前有一个握手的过程。传输源产生VLAID信号来指明何时数据或控制信息有效。而目地源产生READY信号来指明已经准备好接受数据或控制信息。传输发生在VALID和READY信号同时为高的时候。VALID和READY信号的出现有三种关系。1VALID先变高READY后变高。时序图如下在箭头处信息传输发生。2READY先变高VALID后变高。时序图如下同样在箭头处信息传输发生。3VALID和READY信号同时变高。时序图如下在这种情况下信息传输立马发生如图箭头处指明信息传输发生。1.4 突发式读写1.4.1 突发式写时序图这一过程的开始时主机发送地址和控制信息到写地址通道中然后主机发送每一个写数据到写数据通道中。当主机发送最后一个数据时WLAST信号就变为高。当设备接收完所有数据之后他将一个写响应发送回主机来表明写事务完成。1.4.2 突发式读的时序图当地址出现在地址总线后传输的数据将出现在读数据通道上。设备保持VALID为低直到读数据有效。为了表明一次突发式读写的完成设备用RLAST信号来表示最后一个被传输的数据。1.5 AXI4 数据路由及缓存机制在上图中我们描述了典型的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]的设置。由于关于这两个参数我们并没有查阅到非常详尽的应用说明,这里米联客的教程以我们查阅的资料和我们自己的理解介绍这两个参数。1.5.1 Modifiable 和 Non-modifiable transaction当设置AxCACHE[1] 0则是Non-modifiable transactionNon-modifiable transaction不能被拆分成多个transaction传输也不能合并transaction传输。在Non-modifiable transaction中以下信号不能修改。当设置AxCACHE[1] 1则是modifiable transactionmodifiable transaction能被拆分成多个transaction传输也能合并transaction传输因此 AxADDR、AxSIZE、AxLEN、AxBURST可以被改变。1.5.2 AXI4 存储类型参数描述2 FDMA源码分析由于AXI4总线协议直接操作起来相对复杂一些容易出错因此我们封装一个简单的用户接口间接操作 AXI4总线会带来很多方便性。先看下我们计划设计一个怎么样的用户接口。2.1 FDMA 的写时序fdma_wready设置为1当fdma_wbusy0的时候代表FDMA的总线非忙可以进行一次新的FDMA传输这个时候可以设置fdma_wreq1同时设置fdma burst的起始地址和 fdma_wsize本次需要传输的数据大小(以 bytes为单位)。当fdma_wvalid1的时候需要给出有效的数据写入AXI总线。当最后一个数写完后fdma_wvalid和fdma_wbusy变为0。AXI4总线最大的burst lenth是256而经过封装后用户接口的fdma_size可以任意大小的fdma ip内部代码控制每次AXI4总线的Burst 长度这样极大简化了AXI4总线协议的使用。2.2 FDMA 的读时序fdma_rready设置为1当fdma_rbusy0的时候代表FDMA的总线非忙可以进行一次新的FDMA传输这个时候可以设置fdma_rreq1同时设置fdma burst的起始地址和fdma_rsize本次需要传输的数据大小(以bytes为单位)。当 fdma_rvalid1的时候需要给出有效的数据写入AXI总线。当最后一个数写完后fdma_rvalid和fdma_rbusy变为0。同样对于AXI4总线的读操作AXI4总线最大的 burst lenth是256而经过封装后用户接口的fdma_size可以任意大小的fdma ip内部代码控制每次AXI4总线的Burst长度这样极大简化了AXI4总线协议的使用。2.3 FDMA 的 AXI4-Master 写操作以下代码中我们给出axi4-master写操作的代码分析注释//AXI4 FULL Writeassign axi_wdataI_fdma_wdata;assign O_fdma_wvalidw_next;reg fdma_wstart_locked1b0;wire fdma_wend;wire fdma_wstart;assign O_fdma_wbusyfdma_wstart_locked;//在整个写过程中fdma_wstart_locked将保持有效直到本次FDMA写结束always (posedge M_AXI_ACLK)if(M_AXI_ARESETN1b0 || fdma_wend 1b1)fdma_wstart_locked1b0;elseif(fdma_wstart)fdma_wstart_locked1b1;//产生fdma_wstart信号整个信号保持1个 M_AXI_ACLK时钟周期assign fdma_wstart(fdma_wstart_locked1b0 I_fdma_wareq 1b1);//AXI4 write burst lenth busrt addr ------------------------------//当fdma_wstart信号有效代表一次新的FDMA传输首先把地址本次fdma的burst地址寄存到axi_awaddr作为第一次axi burst的地址。如果fdma的数据长度大于256那么当axi_wlast有效的时候自动计算下次axi的burst地址always (posedge M_AXI_ACLK)if(fdma_wstart)axi_awaddrI_fdma_waddr;elseif(axi_wlast1b1)axi_awaddraxi_awaddraxi_wburst_size;//AXI4 write cycle -----------------------------------------------//axi_wstart_locked_r1, axi_wstart_locked_r2信号是用于时序同步reg axi_wstart_locked_r11b0, axi_wstart_locked_r2 1b0;always (posedge M_AXI_ACLK)begin axi_wstart_locked_r1axi_wstart_locked;axi_wstart_locked_r2axi_wstart_locked_r1;end// axi_wstart_locked的作用代表一次axi写burst操作正在进行中。always (posedge M_AXI_ACLK)if((fdma_wstart_locked1b1) axi_wstart_locked 1b0)axi_wstart_locked1b1;elseif(axi_wlast1b1 || fdma_wstart 1b1)axi_wstart_locked1b0;//AXI4 addr valid and write addr-----------------------------------always (posedge M_AXI_ACLK)if((axi_wstart_locked_r11b1)axi_wstart_locked_r21b0)axi_awvalid1b1;elseif((axi_wstart_locked1b1 M_AXI_AWREADY 1b1)||axi_wstart_locked1b0)axi_awvalid1b0;//AXI4 write>(posedge M_AXI_ACLK)if((axi_wstart_locked_r11b1)axi_wstart_locked_r21b0)axi_wvalid1b1;elseif(axi_wlast1b1 || axi_wstart_locked 1b0)axi_wvalid1b0;////AXI4 write data burst len counter----------------------------------always (posedge M_AXI_ACLK)if(axi_wstart_locked1b0)wburst_cntd0;elseif(w_next)wburst_cntwburst_cnt1b1;assign axi_wlast(w_next1b1)(wburst_cntM_AXI_AWLEN);//fdma write data burst len counter----------------------------------reg wburst_len_req1b0;reg[15:0]fdma_wleft_cnt16d0;// wburst_len_req信号是自动管理每次axi需要burst的长度always (posedge M_AXI_ACLK)wburst_len_reqfdma_wstart|axi_wlast;// fdma_wleft_cnt用于记录一次FDMA剩余需要传输的数据数量always (posedge M_AXI_ACLK)if(fdma_wstart)begin wfdma_cnt1d0;fdma_wleft_cntI_fdma_wsize;endelseif(w_next)begin wfdma_cntwfdma_cnt1b1;fdma_wleft_cnt(I_fdma_wsize-1b1)-wfdma_cnt;end//当最后一个数据的时候产生fdma_wend信号代表本次fdma传输结束assign fdma_wendw_next(fdma_wleft_cnt1);//一次axi最大传输的长度是256因此当大于256自动拆分多次传输always (posedge M_AXI_ACLK)beginif(M_AXI_ARESETN1b0)begin wburst_len1;endelseif(wburst_len_req)beginif(fdma_wleft_cnt[15:MAX_BURST_LEN_SIZE]0)wburst_lenM_AXI_MAX_BURST_LEN;elsewburst_lenfdma_wleft_cnt[MAX_BURST_LEN_SIZE-1:0];endelsewburst_lenwburst_len;end以上代码我们进行了详细的注释性分析。 以下给出FDMA写操作源码部分的时序图。下图中一次传输以传输262个长度的数据为例如果需要MAX_BURST_LEN_SIZE设置了最大值 256 那么2次AXI4 BURST才能完成第一次传输256个长度数据第二次传输6个长度的数据。2.4 FDMA 的 AXI4-Master 读操作以下代码中我们给出axi4-master读操作的代码分析注释//fdma axi read----------------------------------------------reg[M_AXI_ADDR_WIDTH-1:0]axi_araddr0;//AXI4 读地址reg axi_arvalid1b0;//AXI4读地有效wire axi_rlast;//AXI4 读LAST信号reg axi_rready1b0;//AXI4读准备好wire r_next(M_AXI_RVALIDM_AXI_RREADY);// 当valid ready信号都有效代表AXI4数据传输有效reg[8:0]rburst_len1;//读传输的axi burst长度代码会自动计算每次axi传输的burst 长度reg[8:0]rburst_cnt0;//每次axi bust的计数器reg[15:0]rfdma_cnt0;//fdma的读数据计数器reg axi_rstart_locked0;//axi 传输进行中lock住用于时序控制wire[15:0]axi_rburst_sizerburst_len*AXI_BYTES;//axi 传输的地址长度计算assign M_AXI_ARIDM_AXI_ID;//读地址ID用来标志一组写信号, M_AXI_ID是通过参数接口定义assign M_AXI_ARADDRaxi_araddr;assign M_AXI_ARLENrburst_len-1;//AXI4 burst的长度assign M_AXI_ARSIZEclogb2((AXI_BYTES)-1);assign M_AXI_ARBURST2b01;//AXI4的busr类型INCR模式地址递增assign M_AXI_ARLOCK1b0;//不使用cache,不使用bufferassign M_AXI_ARCACHE4b0010;assign M_AXI_ARPROT3h0;assign M_AXI_ARQOS4h0;assign M_AXI_ARVALIDaxi_arvalid;assign M_AXI_RREADYaxi_rreadyI_fdma_rready;//读数据准备好这里必须设置I_fdma_rready有效assign O_fdma_rdataM_AXI_RDATA;assign O_fdma_rvalidr_next;//AXI4 FULL Read-----------------------------------------reg fdma_rstart_locked1b0;wire fdma_rend;wire fdma_rstart;assign O_fdma_rbusyfdma_rstart_locked;//在整个读过程中fdma_rstart_locked将保持有效直到本次FDMA写结束always (posedge M_AXI_ACLK)if(M_AXI_ARESETN1b0 || fdma_rend 1b1)fdma_rstart_locked1b0;elseif(fdma_rstart)fdma_rstart_locked1b1;//产生fdma_rstart信号整个信号保持1个 M_AXI_ACLK时钟周期assign fdma_rstart(fdma_rstart_locked1b0 I_fdma_rareq 1b1);//AXI4 read burst lenth busrt addr ------------------------------//当fdma_rstart信号有效代表一次新的FDMA传输首先把地址本次fdma的burst地址寄存到axi_araddr作为第一次axi burst的地址。如果fdma的数据长度大于256那么当axi_rlast有效的时候自动计算下次axi的burst地址always (posedge M_AXI_ACLK)if(fdma_rstart1b1)axi_araddrI_fdma_raddr;elseif(axi_rlast1b1)axi_araddraxi_araddraxi_rburst_size;//AXI4 r_cycle_flag-------------------------------------//axi_rstart_locked_r1, axi_rstart_locked_r2信号是用于时序同步reg axi_rstart_locked_r11b0, axi_rstart_locked_r2 1b0;always (posedge M_AXI_ACLK)begin axi_rstart_locked_r1axi_rstart_locked;axi_rstart_locked_r2axi_rstart_locked_r1;end// axi_rstart_locked的作用代表一次axi读burst操作正在进行中。always (posedge M_AXI_ACLK)if((fdma_rstart_locked1b1) axi_rstart_locked 1b0)axi_rstart_locked1b1;elseif(axi_rlast1b1 || fdma_rstart 1b1)axi_rstart_locked1b0;//AXI4 addr valid and read addr-----------------------------------always (posedge M_AXI_ACLK)if((axi_rstart_locked_r11b1)axi_rstart_locked_r21b0)axi_arvalid1b1;elseif((axi_rstart_locked1b1 M_AXI_ARREADY 1b1)||axi_rstart_locked1b0)axi_arvalid1b0;//AXI4 read>(posedge M_AXI_ACLK)if((axi_rstart_locked_r11b1)axi_rstart_locked_r21b0)axi_rready1b1;elseif(axi_rlast1b1 || axi_rstart_locked 1b0)axi_rready1b0;////AXI4 read data burst len counter----------------------------------always (posedge M_AXI_ACLK)if(axi_rstart_locked1b0)rburst_cntd0;elseif(r_next)rburst_cntrburst_cnt1b1;assign axi_rlast(r_next1b1)(rburst_cntM_AXI_ARLEN);//fdma read data burst len counter----------------------------------reg rburst_len_req1b0;reg[15:0]fdma_rleft_cnt16d0;// rburst_len_req信号是自动管理每次axi需要burst的长度always (posedge M_AXI_ACLK)rburst_len_reqfdma_rstart|axi_rlast;// fdma_rleft_cnt用于记录一次FDMA剩余需要传输的数据数量always (posedge M_AXI_ACLK)if(fdma_rstart)begin rfdma_cnt1d0;fdma_rleft_cntI_fdma_rsize;endelseif(r_next)begin rfdma_cntrfdma_cnt1b1;fdma_rleft_cnt(I_fdma_rsize-1b1)-rfdma_cnt;end//当最后一个数据的时候产生fdma_rend信号代表本次fdma传输结束assign fdma_rendr_next(fdma_rleft_cnt1);//axi auto burst len caculate-----------------------------------------//一次axi最大传输的长度是256因此当大于256自动拆分多次传输always (posedge M_AXI_ACLK)beginif(M_AXI_ARESETN1b0)begin rburst_len1;endelseif(rburst_len_req)beginif(fdma_rleft_cnt[15:MAX_BURST_LEN_SIZE]0)rburst_lenM_AXI_MAX_BURST_LEN;elserburst_lenfdma_rleft_cnt[MAX_BURST_LEN_SIZE-1:0];endelserburst_lenrburst_len;end以上代码我们进行了详细的注释性分析。FDMA的读写代码高度对称 以上源码和以下波形图都和写操作类似理解起会提高很多效率。以下给出FDMA读操作源码部分的时序图。下图中一次传输以传输262个长度的数据为例 如果需要MAX_BURST_LEN_SIZE设置了最大值256那么2次AXI4 BURST才能完成 第一次传输256个长度数据 第二次传输6个长度的数据。3 FDMA IP的封装这部分可参考博主之前的总结: FPGA应用技巧之Vivado自定义IP创建与使用4 总结以上就是AXI4-FULL-MASTER IP FDMA的基本介绍后续会继续输出关于FDMA IP的仿真验证、读写axi-bram、读写DDR等实际应用方案介绍。敬请期待。不要忘记关注我点赞收藏我会为你带来更多优质内容