[X]关闭

[米联客-XILINX-H3_CZ08_7100] FPGA_SDK高级篇连载-10PL 使用PS 的 DDR 方案

文档创建者:FPGA课程
浏览次数:185
最后更新:2024-10-08
文档课程分类-AMD-ZYNQ
AMD-ZYNQ: ZYNQ-SOC » 1_SDK应用方案(仅旗舰型号) » 2-SDK高级应用方案
本帖最后由 FPGA课程 于 2024-10-8 09:07 编辑

​软件版本: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概述
对于ZYNQ SOC或者Ultrascale+ MPSOC都有PS DDR,通常来说PS DDR可以用于运行PS部分的程序,也可以用于PL 和PS之间的数据交互。
FDMA是米联客的基于AXI4总线协议定制的一个DMA控制器,该控制器既可以用于PL DDR的访问,也可以用于PS DDR的访问。FDMA IP CORE 已经广泛应用于ZYNQ SOC/Artix7/Kintex7 FPGA,同样适用于ultrascale/ultrascale+系列FPGA/SOC。
uiFDMA2.0/3.0新增特性:
1:支持多个FDMA IP同时挂带AXI-interconnect总线,同时工作
2:支持自动计算计算AXI-Burst长度(自动计算的最大长度为256),使用起来非常简单,只需要给出需要burst的长度。
本文实验目的:
1:分析FDMA源码,掌握基于FDMA的APP接口实现AXI4-FULL总线接口的访问。
2:掌握自定义总线接口封装方法
3:自定义AXI-FULL-Slave IP用于验证FDMA的工作情况。
2系统框图
本系统基于米联客 uiFDMA IP搭建图形化部分FPGA设计,并且编写了访问uiFMA IP的用户逻辑,产生测试数据用以读写测试PS DDR。
为了让PS的DDR可以运行,必须新建一个vitis-sdk工程,这个工程主要是为了初始化PS DDR,我们可以简单新建一个自带的hello工程。
51b1563d947d49cf99c9ba5bd51f929d.jpg
3搭建SOC系统工程
详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“3-1-01米联客2024版ZynqSocSDK入门篇”中第一个工程 “01Vitis Soc开发入门”这个实验。
本文开始不再详细描述图形化工程的搭建过程,对于VIVIADO软件工具使用可以参考前面的相关章节。
3.1Zynq IP PS部分设置
本文中的PS设置内容是新增加的配置部分,关于DDR、MIO、CPU时钟等设置请参考“3-1-01米联客2024版ZynqSocSDK入门篇”中第一个工程 “01Vitis Soc开发入门”这个实验。
1:PS复位设置
758ea5ccf5d04a12b0aedf92e72db382.jpg
2:设置PS HP Slave接口
977be49273174a57b644b03325292a19.jpg
3:设置PL的时钟
勾选FCLK_CLK0,设置为200M AXI-Stream到AXI4总线的数据时钟
勾选FCLK_CLK1,设置100M 用户数据时钟
本系统需要2个时钟完成数据方案传输, FCLK_CLK0大于FCLK_CLK1是为了满足AXI-4部分的数据吞吐能力要大于用户写数据速度。
462019f3c8064f56b5caec04d866873b.jpg
4:ZYNQ IP设置完成后
89f3708e5ea34897b7dd3ffe93f0ffcb.jpg
3.2PL IP设置
1:FDMA IP设置
M_AXI_Addr_Width 设置AXI4总线的地址位宽,对于32bit系统设置32,对于64bit系统一般设置64
M_AXI_Data_Width 设置AXI4总线的数据位宽,可以是32bit、64 bit、128 bit
M_AXI_ID 设置 AXI4的ID
M_AXI_ID_WIDTH 设置ID的位宽
0d1ea0aac3344a85abc031ddeeb46658.jpg
2:AXI-Interconnect IP设置
AXI- Interconnect用于AXI-4总线IP之间的互联,具有仲裁功能。设置AXI- Interconnect总线的参数可以提高AXI4总线接口的使用效率。
e6cf11a06c054098b3ca689a236939a9.jpg
设置FIFO,可以增加带宽利用率
833057dd5ef64c668793ab48034b13d2.jpg
3.3PL图形编程
本文demo中,我们添加了4路AXI-FDMA用以验证FDMA支持多个通路同时使用,并且可以在后续的波形数据中看到FDMA数据接口总线的工作情况。
433ad2ce8a544c98a33c9be074ef2231.jpg
3.4 FPGA FDMA读写代码分析
本文主要介绍FDMA的接口使用,关于更多AXI4总线相关知识可以阅读“3-2-02_axi_bus.pdf” 这个章节,这个章节专讲AXI4总线,其中也详细讲解了FDMA的代码分析。
1:添加代码
38876af45bc04cbf83e25f79eb6d1798.jpg
上图中在顶层的.v文件中调用了之前的FPGA图形代码,该源码在配套fpga工程的uisrc/rtl路径中,本文中我们修改了默认的system_wrapper.v文件名为system_wrapper_top.v这样的好处是对默认文件和手动修改过的文件加以区分,以免幸苦修改的代码一不小心,被软件自动更新替换掉。
2:读写状态机
以下是fdma_test.v中读写fdma ip接口的状态机,由于读写代码对称,对fdma的读写操作可以分为2步完成,分别是:1:发送读/写请求 2:读/写有效数据。
c5f2953e1b624253b93b1c1ea2280319.jpg
3:FDMA的写时序波形图
2828008926b94899a4c480b4b5dc95aa.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总线协议的使用。
4:FDMA的读时序波形图
f591826a14de477b81db84af96886635.jpg
fdma_rready设置为1,当fdma_rbusy=0的时候代表FDMA的总线非忙,可以进行一次新的FDMA传输,这个时候可以设置fdma_rreq=1,同时设置fdma burst的起始地址和fdma_rsize本次需要传输的数据大小(以bytes为单位)。当fdma_rvalid=1的时候需要给出有效的数据,写入AXI总线。当最后一个数写完后,fdma_rvalid和fdma_rbusy变为0。
同样对于AXI4总线的读操作,AXI4总线最大的burst lenth是256,而经过封装后,用户接口的fdma_size可以任意大小的,fdma ip内部代码控制每次AXI4总线的Burst长度,这样极大简化了AXI4总线协议的使用。
5:源码注解
以下程序中是fdma读写操作的具体实现,先写入一定数据到DDR中,然后再读出,对比是否有错误,几个关键参数:
TEST_MEM_SIZE:定义了测试内从空间的大小,以byte为单位,是整数倍的FDMA_BURST_LEN *(fdma_wdata/8)。
FDMA_BURST_LEN:定义每次FDMA传输的长度,这个长度是整数倍的fdma_wdata或者fdma_rdata。
ADDR_MEM_OFFSET:代码了内从访问的起始地址。
  1. /*******************************MILIANKE*******************************
  2. *Company : MiLianKe Electronic Technology Co., Ltd.
  3. *WebSite:https://www.milianke.com
  4. *TechWeb:https://www.uisrc.com
  5. *tmall-shop:https://milianke.tmall.com
  6. *jd-shop:https://milianke.jd.com
  7. *taobao-shop1: https://milianke.taobao.com
  8. *Create Date: 2021/10/15
  9. *Module Name:fdma_test
  10. *File Name:fdma_test.v
  11. *Description:
  12. *The reference demo provided by Milianke is only used for learning.
  13. *We cannot ensure that the demo itself is free of bugs, so users
  14. *should be responsible for the technical problems and consequences
  15. *caused by the use of their own products.
  16. *Copyright: Copyright (c) MiLianKe
  17. *All rights reserved.
  18. *Revision: 1.0
  19. *Signal description
  20. *1) _i input
  21. *2) _o output
  22. *3) _n activ low
  23. *4) _dg debug signal
  24. *5) _r delay or register
  25. *6) _s state mechine
  26. *********************************************************************/
  27. `timescale 1ns / 1ns
  28. module fdma_test#
  29. (
  30. parameter TEST_MEM_SIZE   = 32'd536800000,
  31. parameter FDMA_BURST_LEN  = 16'd1000,
  32. parameter ADDR_MEM_OFFSET = 1024*1024*50
  33. )
  34. (
  35. input               ui_clk,
  36. input               fdma_rstn,
  37. output     [31: 0]  fdma_waddr,
  38. output reg          fdma_wareq,
  39. output     [15: 0]  fdma_wsize,                                    
  40. input               fdma_wbusy,     
  41. output reg [31:0]   fdma_wdata,
  42. input               fdma_wvalid,
  43. output              fdma_wready,
  44. output     [31: 0]  fdma_raddr,
  45. output reg          fdma_rareq,
  46. output     [15: 0]  fdma_rsize,                                    
  47. input               fdma_rbusy,         
  48. input      [31:0]   fdma_rdata,
  49. input               fdma_rvalid,
  50. output              fdma_rready
  51.     );
  52.   
  53. parameter WRITE1 = 0;
  54. parameter WRITE2 = 1;
  55. parameter READ1  = 2;
  56. parameter READ2  = 3;
  57. reg [31: 0] fdma_waddr_r;
  58. reg [16 :0] fdma_rcnt = 0;
  59. reg [1  :0] T_S = 0;
  60. assign fdma_waddr = fdma_waddr_r + ADDR_MEM_OFFSET;//设置偏移地址
  61. assign fdma_raddr = fdma_waddr; //读写地址相同
  62. assign fdma_wsize = FDMA_BURST_LEN; //设置FDMA控制器一次写burst的数据长度
  63. assign fdma_rsize = FDMA_BURST_LEN; //设置FDMA控制器一次读burst的数据长度
  64. reg [10:0] rst_cnt = 0;
  65. //延迟复位
  66. always @(posedge ui_clk)
  67.     if(fdma_rstn == 1'b0)begin
  68.         rst_cnt <=0;
  69.     end
  70.     else begin
  71.         if(rst_cnt[10] == 1'b0)
  72.             rst_cnt <= rst_cnt + 1'b1;
  73.         else
  74.             rst_cnt <= rst_cnt;
  75.     end
  76. assign fdma_wready = 1'b1; //设置常量1
  77. assign fdma_rready = 1'b1; //设置常量1
  78. //FDMA 读写控制器,每次先写后读,读出后对比数据正确性
  79. always @(posedge ui_clk)begin
  80.     if(rst_cnt[10] == 1'b0)begin
  81.         T_S <=0;   
  82.         fdma_wareq  <= 1'b0;
  83.         fdma_rareq  <= 1'b0;
  84.         fdma_wdata<=0;
  85.         fdma_waddr_r <=0;      
  86.     end
  87.     else begin
  88.         case(T_S)      
  89.         WRITE1:begin
  90.             if(fdma_waddr_r>TEST_MEM_SIZE) fdma_waddr_r<=0; //超出测试内存范围,重新测试
  91.                 if(!fdma_wbusy)begin//当fdma进入空闲,fdma_wbusy=0,请求写
  92.                     fdma_wareq  <= 1'b1; //设置写请求
  93.                     fdma_wdata  <= 0; //设置初值
  94.                 end
  95.                 if(fdma_wareq&&fdma_wbusy)begin//当fdma响应请求后,fdma_wbusy=1,进入下一个状态
  96.                     fdma_wareq  <= 1'b0; //清除写请求
  97.                     T_S         <= WRITE2;
  98.                 end
  99.         end
  100.         WRITE2:begin
  101.             if(!fdma_wbusy) begin//当fdma完成请求后,fdma_wbusy=0,进入下一个状态
  102.                  T_S <= READ1;
  103.                  fdma_wdata  <= 32'd0;
  104.             end
  105.             else if(fdma_wvalid) begin//当fdma_wvalid有效期间必须写入有效数据
  106.                 fdma_wdata <= fdma_wdata + 1'b1;
  107.             end
  108.         end
  109.         
  110.         READ1:begin
  111.             if(!fdma_rbusy)begin//当fdma进入空闲,fdma_rbusy=0,请求读
  112.                 fdma_rareq  <= 1'b1; //设置读请求
  113.                 fdma_rcnt   <= 0; //设置初值
  114.             end
  115.             if(fdma_rareq&&fdma_rbusy)begin//当fdma响应请求后,fdma_rbusy=1,进入下一个状态
  116.                  fdma_rareq  <= 1'b0; //清除读请求
  117.                  T_S         <= READ2;
  118.             end
  119.         end
  120.         READ2:begin
  121.             if(!fdma_rbusy) begin//当fdma完成请求后,fdma_rbusy=0,进入下一个状态
  122.                  T_S <= WRITE1;
  123.                  fdma_rcnt  <= 32'd0;
  124.                  fdma_waddr_r  <= fdma_waddr_r + FDMA_BURST_LEN*4; //当本次读写周期完成增加地址,地址以BYTE计算
  125.             end
  126.             else if(fdma_rvalid) begin//当fdma_rvalid有效期间读出的数据有效
  127.                 fdma_rcnt <= fdma_rcnt + 1'b1;
  128.             end
  129.         end   
  130.         default:
  131.             T_S <= WRITE1;     
  132.         endcase
  133.     end
  134.   end

  135. //对比是否有错误数据
  136. wire test_error = ((fdma_rready&&fdma_rvalid) && (fdma_rcnt[15:0] != fdma_rdata[15:0]));
  137. //ila在线调试核的调用用于观察fdma运行的情况
  138. ila_0 ila_dbg (
  139.     .clk(ui_clk),
  140.     .probe0({fdma_waddr[15:0],fdma_wdata[15:0],fdma_wareq,fdma_wvalid,fdma_wready,fdma_wbusy}),
  141.     .probe1({fdma_rdata[15:0],fdma_rcnt[15:0],fdma_rvalid,fdma_rready,fdma_rbusy,T_S,test_error,fdma_rstn})
  142. );
  143.    
  144. endmodule
复制代码

3.5地址分配
a3a0e4c710c24d5985435284118b9389.jpg
3.6编译并导出平台文件
1:单击Block文件à右键àGenerate the Output ProductsàGlobalàGenerate。
2:单击Block文件à右键à Create a HDL wrapper(生成HDL顶层文件)àLet vivado manager wrapper and auto-update(自动更新)。
3:生成Bit文件。
4:导出到硬件: FileàExport HardwareàInclude bitstream
5:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。
6ecf2bb2de75429e87fa94598ad898a6.jpg
4搭建Vitis-sdk工程
创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。
4.1创建SDK Platform工程
58330d10ec3c4e6898657618e47ca3c2.jpg
4.2创建hello APP工程
这个程序只是为了让PS DDR可以工作。
3bd0c7507cd240d786fb919d95314bd5.jpg
5方案演示
5.1硬件准备
本实验需要用到 JTAG 下载器、USB 转串口外设,另外需要把核心板上的 2P 模式开关设置到 JTAG 模式,即 ON ON (注意新版本的 MLK-H3-CZ08-7100FC(米联客 7X 系列),支持 JTAG 模式,对于老版本的核心板,JTAG 调试 的时候一定要拔掉 TF 卡,并且设置模式开关为 OFF OFF)
以下图片中,TF 卡没有使用到
efcdf5c1c2034df298c99e95bae1c927.jpg
5.2实验结果
b5a34df39b394733beb55fae02920ef4.jpg
启动调试
378566c8b9044f69a634faa168537979.jpg
进入调试后
22ac536e08a946d8880a5a3105b8e7bc.jpg
直接观察内存中的数据
5c64298aca914eae903ac038840c2bd5.jpg
在vivado中打开ila 在线逻辑分析仪观察
5ba12447f2c441c88f12e01dac2dec02.jpg
可以看到ila核都加载进来了
5b58abbb7ccd4f28b95813751426b56a.jpg
hw_ila_1运行结果
281c12d92bc147e782ffb80921ea10c5.jpg
hw_ila_2运行结果
9b5fbeaf2d0b4c4d8161b35397454593.jpg
hw_ila_3运行结果
2d2fb7a95b9e4a6386cfe4cd9c7174c9.jpg
hw_ila_4运行结果
ad7c27a1d6fd42dbb80fdb08170ba9dc.jpg
可以看到所有通道运行正确。


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

本版积分规则