ZYNQ——BRAM全双工PS_PL_数据交互
前言:由于本历程在网上确实没有发现,而且确实在PL端的读写数据废了很长的时间,个人认为具有一定的价值,因此本历程暂不免费开源。目前所有的代码都只放出部分参考不能复制直接用,希望购买资源的朋友们不要倒卖,尊重成果。
由于博主等级不高,无法使用CSDN方面的付费资源,目前考虑为私聊博主购买,价格:9.9人民币。
本资源实现了:采用ZYNQ7010;vivado 2018.3;vivado sdk;正点原子XCOM串口助手,PS与PL均读写操作。
1、PS写0-9地址 0-9数据,触发start给PL。
2、PL接收到触发后,做两次的打拍,再遍历一遍,然后PL将0-9地址的数据读取,分别+2,写在10-19地址上。
3、PS再读取10-19地址上的数据并显示。
博主认为,这才是真正完成了PS与PL之间的数据交互,而非仅仅使用了BRAM资源,而且有给定len长度与地址长判断,可以实现仅修改
len为20,实现PS0-19地址写入,PL读取后写在20-39。
先看效果图:
接下来让我们看如何操作。
ZYNQ如何实现PS与PL的数据交互
相信大家都看过采用AXI接口通过BRAM,实现PS、PL之间的数据交互,但是网上的教程不尽人意,要么只是将PL的BRAM资源拿出来使用,实际上还是PS自己进行回环,基本上没有什么意义,如下图1。
图1 BRAM内的数据回环
目前大部分厂商所构建的BRAM数据回环是下面这张图:但是基本上也都是假通信
图2 常见BRAM数据通信回环
本博客实现的不同点
我也是使用正点原子历程,但是这类代码基本上都是同样的结果:PS写入BRAM,PL的BRAM读取并非把数据读出来,而是搞个ILA可以实时看,这只有学习意义,也是假通信,而博主也是费尽心思,终于搞定了:
1、PS写0-9地址 0-9数据,触发start给PL。
2、PL接收到触发后,做两次的打拍,再遍历一遍,然后PL将0-9地址的数据实时读取,分别+2,写在10-19地址上。
3、PS再读取10-19地址上的数据并显示。
博主认为,这才是真正完成了PS与PL之间的数据交互,而非仅仅使用了BRAM资源。接下来让我们看如何操作。
实现方案
PL_BRAM端的数据读取与写入
module bram_rd开发
//延时两拍,采 start_rd 信号的上升沿 因为BRAM_B读取数据需要延迟两拍,即在PS写好数据,需要等一下才能读到RAM数据
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginstart_rd_d0 <= 1'b0; start_rd_d1 <= 1'b0;endelse beginstart_rd_d0 <= start; start_rd_d1 <= start_rd_d0; endend READ_RAM : begin read_data_temp<=din; //获取该地址的数据并存储 state <= READ_END ; end WRITE_RAM : beginif ((addr - start_addr_tmp2) >= (len_tmp)) //write completedbeginstate <= END ; en <= 1'b0 ;we <= 4'd0 ;endelsebegindout<=read_data_temp+32'd2; //将获取的数据+2写在下一个地址 state <= WRITE_END ;endend END : beginaddr <= 32'd0 ;dout <= 32'd0; intr <= 1'b1 ;state <= IDLE ;
可以看到第一部分的代码,即实现了PS数据写好后,其通过输出一个周期的高电平,FPGA实时捕获到后延迟两拍再进行接下来的数据操作。
最后END状态机,当FPGA实现完读写功能后,输出intr为高电平,其只保持一个周期,后面会再转为低电平。
AXI接口开发
// Add user logic herebram_rd u_bram_rd(.clk (S_AXI_ACLK),.rst_n (S_AXI_ARESETN),.start (slv_reg0[0]),.init_data (slv_reg1),.len (slv_reg2),.start_addr (slv_reg3), //RAM端口 .din (din),.en (en ),.addr (addr ),.we (we ),.dout (dout),.bramclk(bramclk),.bramrst_n(bramrst_n),//bram port //control signal.intr(intr) //start to read and write bram
RAM端为下部分,其中intr为单独一个端,其在BD文件中接入中断线,与PS的数据交互有start:触发信号。init_data起始数据(没有用到),len数据长度,start_addr:起始地址。
引脚打包教程正点原子开发已经很完善了就不再啰嗦,BRAM端打包连接到BRAM_PORTB,intr不打包,连接PS中断
VIVADO的BD文件开发
相信大家应该都有用过正点之类厂商的代码,也看过相应的流程,同样的本博客的也是采用图2的方式,通过构建BRAM,一端接在axi_bram_ctrl_0也就是由PS可控制,一端接在PL构建的IP核:pl_bram_rd_0,接下来首先看BD文件都需要什么。
1、PL->PS的中断:我们知道AXI接口可以实现PL与PS的基本数据交互,但是不能实现中断,对于PL端来说,因为是并行数据处理,我们可以仅仅通过判断AXI的一个位是否为高电平做触发, 但是对于PS这样的ARM,不可能让他自己在那里循环等待,(当然可以实现,但是比较呆)。因此,我们需要有一个PL到PS的中断,使得PL数据写好后,触发中断给PS,PS响应中断后读取数据即可,如下图。
这样我们就实现了一个PL->PS的中断接口。
2、串口数据交互,由于博主用的板子只有PS端的串口有芯片,但是不能接收电脑数据,因此用了FPGA的PL端做串口,但是是采用的EMIO,也就是说操作还是在PS端,
如图采用的PL串口,是需要进行RUN Synthesis后进行绑定管脚,然后用一个CH340的串口模块,通过连接GND、RX、TX后实现与电脑的通信,如果大家是正点的板子,就不用考虑这个问题了。
然后再生成bit流,并export,launch sdk即可。
VIVADO SDK开发PS端
#define BRAM_CTRL_BASE XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR
#define BRAM_CTRL_HIGH XPAR_AXI_BRAM_CTRL_0_S_AXI_HIGHADDR
#define PL_RAM_BASE XPAR_PL_BRAM_RD_0_S00_AXI_BASEADDR
#define PL_RAM_CTRL PL_BRAM_RD_S00_AXI_SLV_REG0_OFFSET
#define PL_RAM_INIT_DATA PL_BRAM_RD_S00_AXI_SLV_REG1_OFFSET
#define PL_RAM_LEN PL_BRAM_RD_S00_AXI_SLV_REG2_OFFSET
#define PL_RAM_ST_ADDR PL_BRAM_RD_S00_AXI_SLV_REG3_OFFSET
#define START_MASK 0x00000001 //b01
#define INTRCLR_MASK 0x00000002 //b10
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define INTR_ID XPAR_FABRIC_PL_BRAM_RD_0_INTR_INTR
#define TEST_START_VAL 0x0
#define BRAM_BYTENUM 4
XScuGic INTCInst;
char ch_data[1024]; //写入BRAM的字符数组
int Len=10 ;
int Start_Addr=0 ;
int Intr_flag ;
可以看到,定义数据传输的长度为10,BRAM_BYTENUM 大小为4,也就是说,一次占用4个字节即32bit,在BRAM端表现就是一个深度。
Start_Addr起始地址为0。
for(i = BRAM_BYTENUM*Start_Addr ; i < BRAM_BYTENUM*(Start_Addr + Len) ; i += BRAM_BYTENUM){XBram_WriteReg(XPAR_BRAM_0_BASEADDR, i , Write_Data) ;Write_Data += 1 ; //写0-9}printf("完成PS写入BRAM\t\n等待捕获PL写BRAM结束中断\t\n");//Set ram read and write lengthPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_LEN , BRAM_BYTENUM*Len) ; //设定长度//Set ram start addressPL_BRAM_RD_mWriteReg(PL_RAM_BASE, PL_RAM_ST_ADDR , BRAM_BYTENUM*Start_Addr) ; //设定起始地址
for(i = BRAM_BYTENUM*Start_Addr ; i < BRAM_BYTENUM*(Start_Addr + Len+15) ; i += BRAM_BYTENUM) //len+10即可,只是多打几位,验证PL写的正确性{Read_Data = XBram_ReadReg(XPAR_BRAM_0_BASEADDR , i) ;printf("Address is %d\t Read data is %d\t\n", i/BRAM_BYTENUM ,Read_Data) ;}
最终效果:
可以看到,当PS写入数据触发PL的start高电平,PL实时捕获到start后,开始读取BRAM的len长度数据分别+2,写在原数据的后面。
而且有给定len长度与地址长判断,可以实现仅修改
len为20,实现PS0-19地址写入,PL读取后写在20-39。
总结
本博客介绍了,PS写数据到BRAM,触发PL读取,PL读取并+2分别写入到后面地址上,触发PS中断读取。希望大家可以支持一下。
ZYNQ——BRAM全双工PS_PL_数据交互相关推荐
- 米联客 ZYNQ/SOC 精品教程 S02-CH19 利用BRAM进行PS与PL间数据交互
软件版本:VIVADO2017.4 操作系统:WIN10 64bit 硬件平台:适用米联客 ZYNQ系列开发板 米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!! ...
- zynq sdk 开发之通过 BRAM 进行 PL 与 PS 的数据交互
如何在 zynq 中进行 PL 端与 PS 端的数据交互? 在zynq的使用中,高效的进行 BRAM 与 zynq 硬核的数据交换至关重要,当我们需要进行小批量的数据交换时,可以考虑采用 BRAM 作 ...
- ZYNQ PS PL 数据交互 Bram
文章目录 前言 一.ZYNQ数据交互方式 二.Create Block Design 1.创建硬件工程 2.封装的ip代码 3.使用vitis写ps端程序 输出效果 前言 关于zynq PS PL 数 ...
- ZYNQ-基于BRAM的PS和PL数据交互
学习内容 本文介绍关于AXI BRAM控制器的相关内容,针对数据量较少.地址不连续.长度不规则的情况,通过 BRAM 来进行数据的交互. 开发环境 vivado 18.3&SDK,PYNQ-Z ...
- Power PC 与 zynq数据交互(基于LocalBus)
Power PC 与 zynq数据交互(基于LocalBus) 1. Power PC 地址空间映射: 实现 Power PC LocalBus控制外部设备,首先要把Power PC的effectiv ...
- vivado sdk中xil_out函数对指定的BRAM地址写数据为什么会导致程序挂起?
是有关zynq芯片的网口程序调试的,我在例程lwip_echo_server程序中加入了往指定的bram地址写数据的语句,想要实现PS到PL数据的交互,但是程序执行到xil_out这块直接就运行不下去 ...
- PL读写DDR3 实现PS和PL间的数据交互 代码分析
本文是PL读写DDR3 实现PS和PL间的数据交互 的继续,深入分析其代码. 首先分析基本要求,或者需求分析,然后读写流程描述,实测采集的读写过程的波形图,最后分段代码分析,这个代码是上文中利用viv ...
- PL读写DDR3 实现PS和PL间的数据交互
本文构建一个AXI4-Lite Master IP来实现PL读写DDR3.最后用sdk 程序验证pl 读写过程中写入的数据. 本文参考 https://www.eefocus.com/antaur/b ...
- FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)
1.大家好,今天给大家带来的内容是,基于AXI4协议的采用AXI-HP通道完成PL侧数据发送至PS侧(PS侧数据发送至PL侧并没有实现,但是保留了PL读取PS测数据的接口) 2.如果大家用到SoC这种 ...
最新文章
- python零基础入门教程视频下载-Python零基础入门学习视频教程全42集,资源教程下载...
- CSS选择器详细介绍
- C++四种类型强制转换——const_cast、static_cast、dynamic_cast、reinterpret_cast
- 电脑上有一个程序一直在按向上_HUAWEI Matebook 九个超牛电脑快捷键
- mysql 返回多行数据_mysql – 如何连接多个表,包括查找表和返回行中的数据
- Python flask 开发工具和框架安装
- Google 封杀我写的 Web 浏览器!
- [转] Web前端开发工程师常用技术网站整理
- 冈萨雷斯 数字图像处理 插图 打包下载 原tif版 + png版
- C# 调用控制台应用程序及传参
- jsessionId的使用
- java网吧计费系统源码_网吧计费管理系统 - WEB源码|JSP源码/Java|源代码 - 源码中国...
- WSO2 Micro Integrator环境安装及部署
- Kibana:使用 drilldown 从一个仪表板切换到另外一个仪表板
- AngularJs 生命周期$onChanges钩子函数总结
- 通过快递鸟如何接入圆通速递电子面单
- 16 部必看 AI 电影以及AI 电影脱颖而出的原因
- 健壮且可读的安卓架构设计
- Invalid prop: type check failed for prop “total“. Expected Number with value x, got String with valu
- CSS div DIV 居中 XX XXX xx
热门文章
- 两栏布局之右定宽左自适应,上定高下自适应,下定高上自适应
- 用Java将doc文档转成pdf格式
- 【经验】8位MCU EFM8LB1 I2C_Slave多地址接收原理详解,光模块普遍使用该功能
- 大神教你在 Linux 中查看你的时区
- Unity 优化之灯光
- 批处理命令之精确获取操作系统版本信息
- Java报错javax.net.ssl.SSLException MESSAGE: closing inbound before receiving peer‘s close_notify解决方法
- js常用的几种for循环
- 华为3g网卡 linux,华为 3G上网卡 E1750 在DM6446上移植的有关问题
- 多服务器虚拟化 map_软件保护系统WinLicense全新支持RDTSC虚拟化