前言:由于本历程在网上确实没有发现,而且确实在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_数据交互相关推荐

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

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

  2. zynq sdk 开发之通过 BRAM 进行 PL 与 PS 的数据交互

    如何在 zynq 中进行 PL 端与 PS 端的数据交互? 在zynq的使用中,高效的进行 BRAM 与 zynq 硬核的数据交换至关重要,当我们需要进行小批量的数据交换时,可以考虑采用 BRAM 作 ...

  3. ZYNQ PS PL 数据交互 Bram

    文章目录 前言 一.ZYNQ数据交互方式 二.Create Block Design 1.创建硬件工程 2.封装的ip代码 3.使用vitis写ps端程序 输出效果 前言 关于zynq PS PL 数 ...

  4. ZYNQ-基于BRAM的PS和PL数据交互

    学习内容 本文介绍关于AXI BRAM控制器的相关内容,针对数据量较少.地址不连续.长度不规则的情况,通过 BRAM 来进行数据的交互. 开发环境 vivado 18.3&SDK,PYNQ-Z ...

  5. Power PC 与 zynq数据交互(基于LocalBus)

    Power PC 与 zynq数据交互(基于LocalBus) 1. Power PC 地址空间映射: 实现 Power PC LocalBus控制外部设备,首先要把Power PC的effectiv ...

  6. vivado sdk中xil_out函数对指定的BRAM地址写数据为什么会导致程序挂起?

    是有关zynq芯片的网口程序调试的,我在例程lwip_echo_server程序中加入了往指定的bram地址写数据的语句,想要实现PS到PL数据的交互,但是程序执行到xil_out这块直接就运行不下去 ...

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

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

  8. PL读写DDR3 实现PS和PL间的数据交互

    本文构建一个AXI4-Lite Master IP来实现PL读写DDR3.最后用sdk 程序验证pl 读写过程中写入的数据. 本文参考 https://www.eefocus.com/antaur/b ...

  9. FPGA----ZCU106基于axi-hp通道的pl与ps数据交互(全网唯一最详)

    1.大家好,今天给大家带来的内容是,基于AXI4协议的采用AXI-HP通道完成PL侧数据发送至PS侧(PS侧数据发送至PL侧并没有实现,但是保留了PL读取PS测数据的接口) 2.如果大家用到SoC这种 ...

最新文章

  1. python零基础入门教程视频下载-Python零基础入门学习视频教程全42集,资源教程下载...
  2. CSS选择器详细介绍
  3. C++四种类型强制转换——const_cast、static_cast、dynamic_cast、reinterpret_cast
  4. 电脑上有一个程序一直在按向上_HUAWEI Matebook 九个超牛电脑快捷键
  5. mysql 返回多行数据_mysql – 如何连接多个表,包括查找表和返回行中的数据
  6. Python flask 开发工具和框架安装
  7. Google 封杀我写的 Web 浏览器!
  8. [转] Web前端开发工程师常用技术网站整理
  9. 冈萨雷斯 数字图像处理 插图 打包下载 原tif版 + png版
  10. C# 调用控制台应用程序及传参
  11. jsessionId的使用
  12. java网吧计费系统源码_网吧计费管理系统 - WEB源码|JSP源码/Java|源代码 - 源码中国...
  13. WSO2 Micro Integrator环境安装及部署
  14. Kibana:使用 drilldown 从一个仪表板切换到另外一个仪表板
  15. AngularJs 生命周期$onChanges钩子函数总结
  16. 通过快递鸟如何接入圆通速递电子面单
  17. 16 部必看 AI 电影以及AI 电影脱颖而出的原因
  18. 健壮且可读的安卓架构设计
  19. Invalid prop: type check failed for prop “total“. Expected Number with value x, got String with valu
  20. CSS div DIV 居中 XX XXX xx

热门文章

  1. 两栏布局之右定宽左自适应,上定高下自适应,下定高上自适应
  2. 用Java将doc文档转成pdf格式
  3. 【经验】8位MCU EFM8LB1 I2C_Slave多地址接收原理详解,光模块普遍使用该功能
  4. 大神教你在 Linux 中查看你的时区
  5. Unity 优化之灯光
  6. 批处理命令之精确获取操作系统版本信息
  7. Java报错javax.net.ssl.SSLException MESSAGE: closing inbound before receiving peer‘s close_notify解决方法
  8. js常用的几种for循环
  9. 华为3g网卡 linux,华为 3G上网卡 E1750 在DM6446上移植的有关问题
  10. 多服务器虚拟化 map_软件保护系统WinLicense全新支持RDTSC虚拟化