本文构建一个AXI4-Lite Master IP来实现PL读写DDR3。最后用sdk 程序验证pl 读写过程中写入的数据。

本文参考 https://www.eefocus.com/antaur/blog/17-08/423773_0818c.html 学习而来,但我添加了数据验证部分。

我的另篇博文是:zynq 7000 自定义IP 实验https://blog.csdn.net/leon_zeng0/article/details/78674832

对于理解本文也有很多帮助。那篇是 构建一个AXI4-Lite Slave IP,本文是AXI4-Lite Master IP。

对于代码的解说,请见:PL读写DDR3 实现PS和PL间的数据交互 代码分析

1:新建一个试验工程

这里只是简单介绍一下,详细的设置,可以查看我的上文:自定义IP 实验。

打开Vivado, 点击新建工程,工程取名 RWddr。

一路Next , 在硬件设置界面设置好你所用的硬件。

点击Create Block Design,取名system。

在原理图里右键添加ip , 添加ZYNQ Processing System. 添加完成后点击 Run Block Automation。

然后 点击图标, recustom ip, 设置处理器。首先设置好DDR,设置信息监控端口, UART1,

时钟设置比较重要,选择Clock Configuration,点开 IO Peripheral Clocks, PL Fabric Clocks, 检查FCLK_CLK0 是否已勾上,并且频率设置为100 MHZ。

PS-PL Configuration 这里是本文与上文自定义IP 实验的差异。上面红箭是上文中选择了的,使用 AXI4-Lite Slave IP 就要勾上一个。

下面的红箭则是因为我们要用到AXI4-Lite Master IP

2:建立自定义IP

菜单选择 Tools -> Create and Package IP... 。这里前面操作与上文基本一致。

这里说一下不同点:就是在下面这个界面里,Interface Mode不是选择 Slave, 而是Master

在上文中,我介绍的是直接Edit IP, 这里介绍另个方法, 先 Add IP, 然后再编辑ip,在Add IP 后,选择左边Flow Navigator的  IP Catalog, 在右边原理图这边, IP Catalog , 选择User Repository, 可以看到我们加的 IP, 图中名字为 AzIP_AXI_Master-v1.0,在这个ip 上右键,选择Edit in Packager

3: 自定义ip 的设计

我们先来看看主界面。在 Design Source 下面有2个.v 文件。上面的AzIP_AXI_Master_v1_0.v 是顶层文件, top level,但他只是实现接口界面,并调用实例函数。所以真正实现是在 下面的文件, AzIP_AXI_Master_v1_0_M00_AXI.v, 当然这个文件主要是实现AXI接口。重要的逻辑实现需要我们另外添加自己的函数。但在这个例子,我们把这部分最简单化,只是看看他的代码,主要是学习他的读写流程。

我们再查看这个ip 的逻辑连线。这个操作是左边FLOW->RTL ANALYSIS->Schematic 得到。看这个图可以帮助我们了解输入输出的信息。总共有157 个io

如果要看代码的中文讲解,可以查看 https://www.eefocus.com/antaur/blog/17-08/423751_6cc0d.html

这里不做过多介绍了。

除了读写的基本逻辑线外,程序里多了INIT_AXI_TXT, TXT_DONE, ERROR, 这3根应该算测试线吧。

本以为只有读写逻辑模块的,可能master 的特别性, 包含了一个测试例子。INIT_AXI_TXT发起,TXT_DONE结束, ERROR作为错误指示。

例子里的逻辑是写入DDR, 读取 DDR, 比较2个数据是否一致,不一致就ERROR指示,这样循环4个地址。

基地址由参数 parameter  C_M_TARGET_SLAVE_BASE_ADDR    = 32'h40000000 这个确定。偏置地址是0,4,8,12

如果要做出自己的ip ,估计要整理这个例子。也不是那么容易,这里就不动了。

4:添加ip,完成工程

ip add 选择添加刚才的工程, 添加完后点击 自动连线,然后 在上面3个端口 Make External, 用Validate Design(F6)检查原理图错误, 用原理图上方图标Regenerate Layout整理图形,最后的原理图如下:

Generate Output Products, Create HDL  Wrapper, 然后添加约束文件,内容如下:

这个文件的端口号要与你硬件对应, m00_axi_error_0,m00_axi_txn_done_0 是输出,比如led, m00_axi_init_axi_txn_0 则是输入,比如按钮。

set_property IOSTANDARD LVCMOS33 [get_ports {m00_axi_error_0}]
set_property IOSTANDARD LVCMOS33 [get_ports {m00_axi_txn_done_0}]set_property PACKAGE_PIN G15 [get_ports {m00_axi_error_0}]
set_property PACKAGE_PIN K16 [get_ports {m00_axi_txn_done_0}]set_property IOSTANDARD LVCMOS33 [get_ports m00_axi_init_axi_txn_0]
set_property PACKAGE_PIN T19 [get_ports m00_axi_init_axi_txn_0]

产生 比特流, Export Hardware, launch SDK,

5: SDK 工程

建立一个 hello world 工程,Program fpga, debug 或 Run as

可以看到 helloworld ,但这不是重要的。按按钮,激活axi_init_axi_txn, 然后观察报错,和完成指示灯。

我在读写完后done 亮, 错误不亮。这是最后结果的情况,开始没怎么注意。

在这里我们要注意一个对应关系,操作的ddr 地址是 C_M_TARGET_SLAVE_BASE_ADDR    = 32'h40000000开始的4个4字节。这里对吗?

如果写的范围不是有效的ddr 范围,估计会报错吧, 还有要避免写代码区和栈区。

6:查看数据

在上面这个简单helloworld 的程序,感觉没什么内容,我把以前的ddr 读写代码放这里,再来看看ddr 的ps 读写过程。

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"#define MAXLENTH   512000000
unsigned char lasercmd[MAXLENTH];
//int ip_data;void test_ram(void)
{int i,j;int* ip=(int*)lasercmd;printf("ip=%x\n",(int)ip);for(i=0;i<512000000/4;i++){ip[i]=i*2;}for(i=0;i<51;i++){printf("%d=%d\n",i,ip[i*1000000]);}
}int main()
{init_platform();print("Hello World\n\r");test_ram();cleanup_platform();return 0;
}

程序运行的结果是:

Hello World
ip=114320
0=0
1=2000000
2=4000000

这个程序与我们实验有什么相关呢?ip=114320 (hex)

我们开始设置的地址根本就不在ddr 区,回到vivado 再重新设置

C_M_TARGET_SLAVE_BASE_ADDR    = 32'h00400000

还有起始数据 CM00 AXI START DATA VALUE = 0xA1002200

设置的界面如下,具体数据,你也可以不一样,但要保证读取范围在DDR里:.

现在把测试代码修改一下,读取pl-ip 读写的区间,我在这里设置了断点的。显示完pl 读写区间,赋初值,断点,按一下按钮,显示pl 读写区间。

void test_ram(void)
{int i=0;int* ip=(int*)lasercmd;int* obj=(int*)0x400000;printf("ip=%x,obj=%x\n",(int)ip,(int)obj);printf("pl ddr=%x, %x %x %x\n",obj[0],obj[1],obj[2],obj[3]);for(i=0;i<512000000/4;i++){ip[i]=i*2;}printf("2pl ddr=%x, %x %x %x\n",obj[0],obj[1],obj[2],obj[3]);for(i=0;i<512000000/4;i++){if(ip[i]!=i*2)printf("i=%x, ip=%x\n",i,ip[i]);}for(i=0;i<51;i++){printf("%d=%x\n",i,ip[i*1000000]);}
}

程序运行的显示结果部分如下:

ip=114320,obj=400000
pl ddr=175e70, 175e72 175e74 175e76
2pl ddr=a1002200, a1002201 a1002202 a1002203
i=baf38, ip=a1002200
i=baf39, ip=a1002201
i=baf3a, ip=a1002202
i=baf3b, ip=a1002203
0=0
1=1e8480

主程序里,对这个程序循环了几次,方便测试。可以看到

2pl ddr=a1002200, a1002201 a1002202 a1002203

这个是pl 写入的数据的四个数据。

开始好像读取不到,所以我有段查找的代码,看这段空间里哪个数据与ps 写入的不一致,这里找到4个数据。

i=baf38, ip=a1002200
i=baf39, ip=a1002201
i=baf3a, ip=a1002202
i=baf3b, ip=a1002203

我们进行一下计算 (hex 运算):baf38*4=2ebce0

2ebce0+114320=400000

我觉得看灯,好像不能说明问题,既然是读写,至少看看写入的数据是不是预期的。

PL读写DDR3 实现PS和PL间的数据交互相关推荐

  1. PL读写DDR3 实现PS和PL间的数据交互 代码分析

    本文是PL读写DDR3 实现PS和PL间的数据交互 的继续,深入分析其代码. 首先分析基本要求,或者需求分析,然后读写流程描述,实测采集的读写过程的波形图,最后分段代码分析,这个代码是上文中利用viv ...

  2. C#实现Winform间的数据交互的三种方法

    使用.NET编写winform程序,比较常见的一种情况就是如何实现Form间的数据交互,下面就简单总结一下常见的几种数据交互方式:     (1)修改子窗体的构造函数:简单地说就是通过修改子窗体For ...

  3. 学习swing鼠标点击事件心得体会_西门子COMOS软件开发定制学习8-查询列表间的数据交互...

    ​本篇在西门子COMOS软件开发定制学习6-管理界面定制基础上定制,简单介绍两个查询列表之间的数据交互. 实现效果: 在左侧列表中选择某一设备,右侧列表自动根据所选设备,显示该设备相关的设计图纸(如P ...

  4. GAMS-01 GAMS与MATLAB间的数据交互方法

    在MATLAB中设置安装GAMS的路径.

  5. ZYNQ从放弃到入门(八)-PS和PL交互

    之前的几篇文章主要集中在 Zynq SoC 的处理系统 (PS) 方面,包括: 使用 MIO 和 EMIO Zynq SoC 的中断结构 Zynq 私有定时器和看门狗 Zynq SoC 的三重定时器计 ...

  6. ddr传输 pl ps_PS/PL之间的数据交互办法

    01概述 MPSoC是Xilinx基于16nm工艺推出的异构计算平台,由于灵活.稳定,在业界得到了广泛的使用.异构计算是一个比较新的领域,需要协调硬件设计.逻辑设计.软件设计,对工程师的要求很高.实际 ...

  7. axi ps读写pl_Xilinx SDK 初学之——PS对PL寄存器的读写控制

    对于FPGA编程时的v文件中的寄存器,在SDK编程时需要一些读写操作,以实现PS与PL部分的信息交换.下面用一具体例子记录所需要的步骤 .如若有误请指正. 首先需要将v文件代码封装为带有AXI总线的I ...

  8. 【ZYNQ Ultrascale+ MPSOC FPGA教程】第三十二章 PL读写PS端DDR数据

    本原创教程由芯驿电子科技(上海)有限公司(ALINX)创作,版权归本公司所有,如需转载,需授权并注明出处. 适用于板卡型号: AXU2CGA/AXU2CGB/AXU3EG/AXU4EV-E/AXU4E ...

  9. 米联客 ZYNQ/SOC 精品教程 S02-CH19 利用BRAM进行PS与PL间数据交互

    软件版本:VIVADO2017.4 操作系统:WIN10 64bit 硬件平台:适用米联客 ZYNQ系列开发板 米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!! ...

最新文章

  1. [机器学习] 模型稳定度指标PSI
  2. 正则表达式||grep的使用
  3. 题解: 区间合并(opj 2-4-7620)
  4. Apollo进阶课程 ⑦ | 高精地图的采集与生产
  5. 伪随机数与采样(sampling)
  6. css浮动层被遮盖,兼容主流浏览器的背景遮盖和居中浮动层的CSS样式
  7. java jcmd,jcmd命令用法
  8. 开机自动启动程序的操作(就是这么简单)
  9. 读 PHP - Pimple 源码笔记(下)
  10. 老徐FrankXuLei 受邀为中国东方航空上海研发中心讲授微软.NET企业开发课程
  11. python count函数时间复杂度_关于python:了解如何测量函数的时间复杂度
  12. 有符号数和无符号数的范围
  13. Android判断网络状态是否断开
  14. 火车头php post提取内容,【火车头采集教程】轻而易举学会火车头采集(附带采集案例)...
  15. 32*4段 超低功耗LCD液晶显示驱动IC-VKL128 LQFP44,适用水表/传感器/热能表/压力表/测厚仪等,工作电流约7.5微安
  16. 提交一个骗子喵喵源码站
  17. STM32正倒计时器程序设计
  18. printf 日常使用指南
  19. 创建不可删除的IE快捷方式图标
  20. [整理]统计数据的可视化——图表绘制(一)

热门文章

  1. 学习Word必学这一招——样式
  2. DataGrip如何将创建的console保存路径设置到指定目录?
  3. 实践中的重构19_脱裤子放屁
  4. 二维码如何转为链接,看了这篇文章才知道多好用!
  5. [:, None]的作用是什么?
  6. c语言数组读心术,超准,一棵树的读心术
  7. 【gis技术】web墨卡托投影和经纬度直投的差别
  8. R语言学习笔记8_回归分析和相关分析
  9. java对象转json格式化_Java对象转json JsonFormat注解
  10. PHP之两个日期之间相差天数