Zynq的BRAM操作及PS端操作Bug思考

作者: 高视,FPGA2嵌入式

1. BRAM介绍

BRAM 就是Block Memory,是Zynq的PL端的存储RAM单元,可以配置为双口RAM,用于实现Zynq中PS端到PL端的数据交互和共享,类似为Linux中的内存共享,也就是将数据写入共同可访问的数据空间,PS和PL端各自访问来达到信息交流的目的。

在这里我们有这样一种比较好的思维推荐:可以在一个BRAM中将一部分地址空间用于PS只写PL只读,剩下的地址空间用于PL只写PS只读。这样PS和PL之间的访问就不会出现读写冲突错误,当然,你也可以用2个BRAM来实现。

2. BRAM的PL端使用

BRAM的访问可以通过AXI总线访问或者把它当做RAM用读写逻辑操作。

其中,通过AXI总线操作就需要一个AXI接口的BRAM控制器,可以调用IP核或者自己写一个这样的AXI主机,另外控制逻辑还需要编写一个AXI总线的主机来通过AXI总线来操作BRAM,如下图:

上图AXI主机通过AXI总线控制AXI_BRAM_CTRL访问BRAM

上图AXI主机通过AXI总线控制AXI_BRAM_CTRL访问BRAM

另一种方式,就是把它当做我们常用的RAM,编写读写RAM的逻辑来操作BRAM,不通过AXI总线访问,如下图:

上图向BRAM中乒乓写入数据流

上图向BRAM中乒乓写入数据流

另外,我们是否可以不用BRAM来存储数据,用PL端的reg来储存数据,这样的话,PS端来直接操作这些寄存器,相当于只用BRAM的读写端口,特别是PS通过一些简单的指令来控制PL端的操作,还是很有用的。对应的代码操作如下图:

上图PS通过BRAM接口来访问一些控制寄存器

上图PS通过BRAM接口来访问一些控制寄存器

3. BRAM的PL-PS接口

BRAM的PS-PL接口相对比较简单,因为这些接口都是基于AXI总线的,都是调用IP核来实现,如下图:

4. BRAM的PS端使用

BRAM的PS端就是ARM对BRAM的读写,BRAM的读写就2个函数,即一个读,一个写,可以在底层库文件xbram_hw.h中找到,函数格式如下图:

因此,读写BRAM的操作如下:

data = XBram_In32(XPAR_BRAM_1_BASEADDR+0);

XBram_Out32(XPAR_BRAM_0_BASEADDR+0, 250);

5. BRAM的PS操作Bug

现象:每次Debug运行到BRAM读写函数时,发现调试的ARM直接跑飞,屡试不爽;

原因:因为BRAM数据位宽设的是32位,而此时读写字节地址不是4的倍数,最终导致CPU访问无效地址后直接跑飞。如下面的操作就会导致ARM跑飞:

XBram_Out32(XPAR_BRAM_0_BASEADDR+1, 250)。

举一反三:CPU跑飞大部分是地址访问出错,程序指令阻塞等原因,可以作为以后调试的一个经验。

6. 总结

BRAM的操作虽然很简单,但可以给我们提供了Zynq中PS与PL互相通信更多的思路,同时,PS访问BRAM导致ARM跑飞这个Bug,也同样给了我们导致CPU跑飞的启发:因为CPU也是不断的访问存储器执行指令,当读取或者译码指令出错了也会导致CPU跑飞。

另外,当PS端通过简单的几个控制reg控制PL的状态时,可以不用PL端BRAM的共享数据,用PL端的Reg来共享数据,能达到同样的效果,但却可以节省PL端的BRAM资源。

文章转载自:FPGA2嵌入式