9.基于BRAM的PS-PL数据交互实验
时间:2023-02-04 21:59:48  来源:哔哩哔哩  
1
听新闻

一、基本概念&本节任务

0.写在前面


(资料图片仅供参考)

本来是想先做ov5640的LCD显示实验的,OV5640和LCD都能点亮了,但是我想当然地把OV5640的数据直接接到了LCD上,显示出来频闪很厉害,不可用,还是先继续学习AXI吧。开学之前争取把AXI总线学完,能操作内存或者直接内存访问的话,按帧存储数据再读出显示可能会好很多。

1.本节任务

本章的实验任务是 PS 将串口接收到的数据写入 BRAM,然后从 BRAM 中读出数据,并通过串口打印出来;与此同时,PL 从BRAM中同样读出数据,并通过ILA来观察读出的数据与串口打印的数据是否一致。

2.BRAM

BRAM(Block RAM)是PL部分的存储器阵列,PS和PL通过对BRAM进行读写操作,来实现数据的交互。在PL中,通过输出时钟、地址、读写控制等信号来对BRAM 进行读写操作;在PS中,处理器并不需要直接驱动BRAM的端口,而是通过AXI  BRAM控制器来对BRAM进行读写操作。

对于少量、不连贯数据,使用BRAM是很好的选择,而对于大量连续的数据,ZYNQ7020只有4.9Mb的BRAM,使用DMA(直接内存访问)是更好的选择,这个过后会学到。

AXI BRAM IP核简介,可以配置为AXI4或AXI4 Lite接口。

二、程序设计

1.Vivado

①新建工程

添加BRAM控制器、BRAM、PS IP核

可以选择关掉ECC、安全电路

基本框架搭建完成

②创建读BRAM IP核

新建一个带AXI4接口的IP核

此时在IP Catalog中就有了刚才打包的IP核

由于选择了生成一个带AXI接口的IP核,VIVADO帮我们做好了AXI接口

新建设计文件,添加一个读BRAM模块(这里直接copy正点原子的代码了):

根据接口要求,在两个上层模块加入地址、时钟、使能、复位等信号。

在AXI例化的模块中加入RAM的端口

在第二层的模块中例化bram读取模块,同时用寄存器0,1,2分别传输读开始、起始地址、读数据长度等信号。

③封装IP核

修改好IP核后进行刷新

对于我们新增的ram端口,我们可以把它封装成一个总线。如果不封装,在Block design中就需要一个一个连线。

对总线接口命名,官方给出了一些接口的类型,我们选择BRAM,并对其进行映射。

并在Parameters中加入主机类型,否则后续会报警告

④加入读BRAM IP核

完成后重新封装整个IP,并在原工程中加入这个IP核,此时可以看见BRAM的端口封装好了(寄我才发现名字错了)

与之前对应的参数

在Address Editor中可以设置BRAM的大小,下面可以改为4K(字节),由于宽度为32位,所以深度为1024位,

⑤添加ILA

综合好后点击综合选项的Set Up Debug,在Netlist中添加BRAM生成器的端口,我们在PL中读端口B,所以加入端口B的地址、数据输出、使能信号的端口,并选择Domain时钟。

深度为1024位

2.Vitis工程

在xparameters.h中,有BRAM控制器、BRAM、自定义IP核pl_bram_rd的各个参数。

xbram_hw.h中定义了两个函数如下所示,XBram_WriteReg用于向Bram写数据,第一个参数为Bram器件基地址,第二个参数为要写入数据的地址(我们选了4K大小,所以这里只能写0~1023),第三个参数为要写入Bram的数据(最大32位)。

XBram_ReadReg用于向Bram读数据,第一个参数为Bram器件基地址,第二个参数为要读取数据的地址,返回读出的数据。

①写入Bram和PL读Bram

这里的START_ADDR为0,BRAM_DATA_BYTE为4(即4字节),即i=0,每次从BRAM的0地址开始写入数据。当i小于4*总数据长度时,i=i+4。

即这里向BRAM写入数据,每次的地址偏移量为4字节。

②读Bram数据并发送至上位机

③完整代码

④发送数据,观察ILA

设置ILA触发条件,在向开发板串口发送“WritetoBram”,开发板返回数据:

三、总结

春节过完不写Vitis感觉都快忘了,由于不涉及PS的外设,所以这里不用在查找配置信息、初始化器件之类的了。过几天继续深挖AXI总线,学习AXI写入DDR和DMA。