软件版本:VIVADO2017.4

操作系统:WIN10 64bit

硬件平台:适用米联客 ZYNQ系列开发板

米联客(MSXBO)论坛:www.osrc.cn答疑解惑专栏开通,欢迎大家给我提问!!

19.1 概述

本课介绍一种基于PL端BRAM的方式,进行PS和PS之间的数据交互。适用于在PS和PL之间传输少量,地址不连续,且长度不规则的数据,比如,配置参数,变量,控制信息等。

19.2 基本原理

在本例程中,在PL端设计了1个4KB(位宽32,深度1024)的BRAM。首先,PS通过M_AXI_GP口向BRAM中1024个地址依次存入1024个32位的数据。PS每向BRAM完成写入1个32位数据后通过AXI GPIO输出1个上升沿信号,PL捕获上升沿后立即将PS写入的32位数据读出,然后加2,再存入原地址中。存储完成后,PL通过AXI GPIO向PS输入1个翻转信号,每翻转1次,AXI GPIO便向PS触发1次中断。PS触发中断后,再从BRAM中读出该数据,判断是否被加了2,若不一致,则报错。

以上过程重复1024次,便将BRAM的所有地址都进行了遍历。之后,则不断重复这个过程。

19.3 FPGA BD工程

VIVADO 2017.4开始可以使用axi_smc IP这个IP和AXI_interconnect IP功能类似,但是没有AXI_interconnect IP强大,在一些高带宽的要求下,还是要用AXI_interconnect IP,VIVADO2017.4自动连线会优先使用axi_smc IP。

以下是VIVADO 2016.4版本以前的自动联系,只会采用AXI_interconnect IP。所以从VIVADO2017.4开始我们多了axi_smc IP进行AXI4总线接口的互联。

19.3.2 PS配置

PS的配置如下图所示。使能M_AXI_GP0口,将FCLK_CLK0设为100MHz,使能PL至PS的中断。

19.3.3 AXI BRAM Controller

AXI BRAM Controller是本例程中的关键,该IP核连接PS的M_AXI_GP0口和BRAM,完成AXI接口至BRAM接口的转换。设置如下图所示。

19.3.4 Block Memory Generator

添加BRAM,将BRAM设置为双口RAM,将PORTA与AXI BRAM Controller连接,PS通过PORTA读写BRAM,另外,将PORTB引出至外部模块,PL通过PORTB读写BRAM。如下图所示。

由于要与AXI BRAM Controller进行连接,BRAM接口的位宽固定为32位。BRAM的深度无法在该IP中进行设置,需要在所有模块连接完成后,在Address Editor里对AXI BRAM Controller的地址范围进行设置,本例程中设置为4KB。该地址范围即对应BRAM的深度,如下图所示。

例如,4KB=32bit×1024,因此BRAM的深度为1024。如下图所示。

去掉Enable Safety Circuit

19.3.5 AXI GPIO

添加AXI GPIO,位宽设为2,使能中断,将中断输出与PS的中断接口连接,设置如下图所示。其中GPIO0作为PS向PL输出的PS BRAM写入完成信号,对于PL而言,上升沿有效。GPIO1作为PL向PS输入的BRAM写入完成信号,该信号为翻转信号,每次翻转向PS产生1次中断。

19.4逻辑设计

PL部分逻辑设计主要包括以下几个过程:

检测AXI GPIO输出的GPIO0的上升沿;

若检测到GPIO0的上升沿,则从BRAM的某1个地址中读出1个PS写入32位数据,然后加2,存入原地址中;

1个32数据存储完毕后,将AXI GPIO的输入信号GPIO1进行翻转,告知PS一次数据读写完成。

不断循环上述过程,依次遍历BRAM中0~4092的地址范围。

module system_wrapper_BRAM(

inout [14:0]DDR_addr,

inout [2:0]DDR_ba,

inout DDR_cas_n,

inout DDR_ck_n,

inout DDR_ck_p,

inout DDR_cke,

inout DDR_cs_n,

inout [3:0]DDR_dm,

inout [31:0]DDR_dq,

inout [3:0]DDR_dqs_n,

inout [3:0]DDR_dqs_p,

inout DDR_odt,

inout DDR_ras_n,

inout DDR_reset_n,

inout DDR_we_n,

inout FIXED_IO_ddr_vrn,

inout FIXED_IO_ddr_vrp,

inout [53:0]FIXED_IO_mio,

inout FIXED_IO_ps_clk,

inout FIXED_IO_ps_porb,

inout FIXED_IO_ps_srstb

);

wire [31:0]BRAM_PORTB_addr;

wire BRAM_PORTB_clk;

wire [31:0]BRAM_PORTB_din;

wire [31:0]BRAM_PORTB_dout;

wire BRAM_PORTB_en;

wire BRAM_PORTB_rst;

wire [3:0]BRAM_PORTB_we;

wire [0:0]GPIO_tri_i_0;

wire [1:1]GPIO_tri_i_1;

wire [0:0]GPIO_tri_o_0;

wire [1:1]GPIO_tri_o_1;

wire [0:0]aresetn;

reg gpio_tri_o_0_reg;

reg ps_bram_wr_done;

reg pl_bram_wr_done;

reg bram_en;

reg [3:0]  bram_we;

reg [31:0] bram_addr;

reg [31:0] bram_rd_data;

reg [31:0] bram_wr_data;

reg [2:0] state;

localparam  BRAM_ADDRESS_HIGH = 32'd4096 - 32'd4;

always@(posedge FCLK_CLK0)

begin

if(!aresetn)

gpio_tri_o_0_reg <= 1'b0;

else

gpio_tri_o_0_reg <= GPIO_tri_o_0;

end

always@(posedge FCLK_CLK0)

begin

if(!aresetn)

ps_bram_wr_done <= 1'b0;

else if({gpio_tri_o_0_reg, GPIO_tri_o_0} == 2'b01) //gpio0 rising edge

ps_bram_wr_done <= 1'b1;

else

ps_bram_wr_done <= 1'b0;

end

always@(posedge FCLK_CLK0)

begin

if(!aresetn) begin

bram_we <= 4'd0;

bram_en <= 1'b0;

bram_addr <= 32'd0;

bram_rd_data <= 32'd0;

bram_wr_data <= 32'd0;

pl_bram_wr_done <= 1'b0;

state <= 3'd0;

end

else begin

case(state)

0: begin

if(ps_bram_wr_done) begin

bram_en <= 1'b1;

bram_we <= 4'd0;

state <= 1;

end

else begin

state <= 0;

bram_en <= 1'b0;

bram_we <= 4'd0;

bram_addr <= bram_addr;

end

end

1: begin

bram_en <= 1'b0;

state <= 2;

end

2: begin

bram_rd_data <= BRAM_PORTB_dout;

state <= 3;

end

3: begin

bram_en <= 1'b1;

bram_we <= 4'hf;

bram_wr_data <= bram_rd_data + 2;

pl_bram_wr_done <= ~pl_bram_wr_done;

state <= 4;

end

4: begin

state <= 0;

bram_en <= 1'b0;

if(bram_addr == BRAM_ADDRESS_HIGH)

bram_addr <= 32'd0;

else

bram_addr <= bram_addr + 32'd4;

end

default: state <= 0;

endcase

end

end

assign BRAM_PORTB_en = bram_en;

assign BRAM_PORTB_we = bram_we;

assign BRAM_PORTB_rst = ~aresetn;

assign BRAM_PORTB_clk = FCLK_CLK0;

assign BRAM_PORTB_addr = bram_addr;

assign BRAM_PORTB_din = bram_wr_data;

assign GPIO_tri_i_1 = pl_bram_wr_done;

system system_i

(.BRAM_PORTB_addr(BRAM_PORTB_addr),

.BRAM_PORTB_clk(BRAM_PORTB_clk),

.BRAM_PORTB_din(BRAM_PORTB_din),

.BRAM_PORTB_dout(BRAM_PORTB_dout),

.BRAM_PORTB_en(BRAM_PORTB_en),

.BRAM_PORTB_rst(BRAM_PORTB_rst),

.BRAM_PORTB_we(BRAM_PORTB_we),

.DDR_addr(DDR_addr),

.DDR_ba(DDR_ba),

.DDR_cas_n(DDR_cas_n),

.DDR_ck_n(DDR_ck_n),

.DDR_ck_p(DDR_ck_p),

.DDR_cke(DDR_cke),

.DDR_cs_n(DDR_cs_n),

.DDR_dm(DDR_dm),

.DDR_dq(DDR_dq),

.DDR_dqs_n(DDR_dqs_n),

.DDR_dqs_p(DDR_dqs_p),

.DDR_odt(DDR_odt),

.DDR_ras_n(DDR_ras_n),

.DDR_reset_n(DDR_reset_n),

.DDR_we_n(DDR_we_n),

.FCLK_CLK0(FCLK_CLK0),

.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),

.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),

.FIXED_IO_mio(FIXED_IO_mio),

.FIXED_IO_ps_clk(FIXED_IO_ps_clk),

.FIXED_IO_ps_porb(FIXED_IO_ps_porb),

.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),

.GPIO_tri_i({GPIO_tri_i_1,GPIO_tri_i_0}),

.GPIO_tri_o({GPIO_tri_o_1,GPIO_tri_o_0}),

.GPIO_tri_t(),

.aresetn(aresetn));

19.4.1 BRAM读时序

BRAM读时序如下图所示。

19.4.2 BRAM写时序

BRAM写时序如下图所示。

19.5 PS程序设计

将提供例程中SDK工程的源文件复制,并粘贴到新建SDK工程。

19.5.1 main函数

main函数的完成的功能如下:

配置AXI GPIO及其中断;

初始化中断控制器及系统中断;

依次向BRAM所对应的地址写入1024个32位整型数据,每写入1个数据等待PL的读写完成中断来临后继续写入下一个;

依次从BRAM所对应的地址读出1024个32位整型数据,并判断是否被加了2,若比对不一致则报错。

19.5.2 GPIO输入输出

在main函数调用Gpiopl_init()函数初始化AXI GPIO,设置2个GPIO的方向,其中GPIO[0]为输出,GPIO[1]为输入。并将GPIO[0]置为0。每个GPIO的宏定义在gpiopl_intr.h中,如下所示。

#define PS_BRAM_MASK            0x00000001

#define PL_INTR_MASK             0x00000002

通过Gpiopl_Setup_Intr_System()初始化并使能AXI GPIO的输入中断,GPIO[1]的输入发生1次改变将触发1次中断,GpioplIntrHandler()为GPIO的中断函数。

GpioplIntrHandler()函数将PL读写BRAM完成中断标志位pl_bram_flag置1,该信号将在PS写入BRAM时使用。

19.5.3 BRAM数据写入

每一个循环PS向BRAM写入1024个32bit整型数据,每次循环后将下一次写入的1024个数据都加1。因此,第1次写入BRAM的数据为0~1023,第2次写入的为1~1024,第3次为2~1025,以此类推。BRAM写入通过如下函数完成:

Xil_Out32(XPAR_BRAM_0_BASEADDR + 4*i, write_data);

由于在ZYNQ中最小可寻址单元为字节,因此1个32位数据需占用4个地址,每次写入的地址都需要加4。

每次写入完成后,拉高GPIO0,通过如下代码完成:

XGpio_DiscreteWrite(&Gpio, 1, PS_BRAM_MASK);

然后,PS等待PL完成BRAM中该地址32bit数据的读写,PL翻转GPIO1使AXI GPIO产生中断,代码如下所示:

while(!pl_bram_flag);

pl_bram_flag = 0;

PL完成BRAM读写后,PS拉低GPIO0,通过如下代码完成:

XGpio_DiscreteWrite(&Gpio, 1, ~PS_BRAM_MASK);

循环1024次,完成1024个数据的写入。

19.5.4 BRAM数据读出

当PS完成1024个数据的写入,此时PL也完成了1024个数据的读出、加2、写入工作。因此,PS需要依次将1024个数据读出进行比对,验证PL给每个数据加2的正确性,因此,第1次读出的1024个数据应该为2~1025,第2次为3~1026,第3次为4~1027,以此类推。若比对出现不一致,则通过串口进行报错。代码如下:

for(i = 0; 4*i < (XPAR_BRAM_0_HIGHADDR - XPAR_BRAM_0_BASEADDR); i++)

{

read_data = Xil_In32(XPAR_BRAM_0_BASEADDR + 4*i);

//xil_printf("data at address %d is %d\r\n", 4*i, read_data);

/*compare data read form bram if they are add by 2*/

if(read_data != (i + j + 2))

xil_printf("error: data at address %d should be %d, but is %d\r\n", 4*i, (i + j + 2), read_data);

}

其中,可通过xil_printf("data at address %d is %d\r\n", 4*i, read_data);查看每一次从BRAM读出的数据的具体值,若无需使用则可注释掉。

19.6 程序测试

程序测试串口打印信息如下图所示。

第1次读出的1024个数据。

第2次读出的1024个数据。

第3次读出的1024个数据。

后面不作一一列举。

本课读写的速度相对较慢,读者可以尝试修改程序,实现批量数据的读写。

转载于:https://my.oschina.net/msxbo/blog/3100642

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

  1. 米联客 ZYNQ/SOC精品教程 S01-CH05 FPGA程序的固化和下载

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

  2. 基于zynq的千兆网udp项目_米联客 ZYNQ/SOC 精品教程 S05-CH05 PS 千兆 UDP 加速

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

  3. 米联客 ZYNQ/SOC精品教程 S02-CH13 CAN总线通信实验

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

  4. fast角点检测 java_米联客 ZYNQ/SOC 精品教程 S04-CH11 快速角点检测之硬件实现

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

  5. 米联客 ZYNQ/SOC精品教程 S01-CH04 VIVADO创建工程之流水灯

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

  6. 米联客 ZYNQ/SOC 精品教程 S02-CH15 AXI_Lite 总线详解

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

  7. 米联客 ZYNQ/SOC 精品教程 S02-CH24 利用AXI VDMA 实现MT9V034摄像头采集

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

  8. 米联客 ZYNQ/SOC精品教程 S01-CH06 FPGA按钮去抖实验

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

  9. 米联客 ZYNQ/SOC 精品教程 S02-CH25 利用OSD实现双目摄像头字幕叠加

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

  10. 米联客 ZYNQ/SOC精品教程 S01-CH07 FPGA多路分频器实验

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

最新文章

  1. R语言使用igraph包进行网络(network)可视化实战
  2. volley框架使用
  3. Kibana停止kibana的方法命令:找到5601端口对应的进程ID 把此进程进行kill即可
  4. 后台导出大量数据超时报 nginx404错误
  5. CSS3实现的响应式字体:自适应视图窗口大小的新单位
  6. python元类使用场景_python 元类的使用
  7. 国内最火的 HTML、CSS、JavaScript 开源项目 Top 榜,你知多少?
  8. Eclipse官方下载及配置流程
  9. matlab 实现disparity,Matlab里的disparity map 计算
  10. 计算机专业对口升学考哪些科目,对口升学考试科目
  11. 医疗行业能否成功入场直播带货?
  12. 【调剂】东华理工大学2020年硕士研究生预调剂信息
  13. strace命令总结
  14. JPAQuery日期分组查询
  15. 当自由职业者这些年,这点事
  16. matlab画立体星星教程,抖音星空画的人怎么画 制作教程完整视频步骤分享
  17. c++11:std::chrono::time_point、time_t、std::localtime、std::gmtime、std::chrono::steady_clock
  18. 中国天气网天气预报API接口城市代码(XML格式,信息全)
  19. EPR测试与生物医学应用
  20. 转:.NET程序的序列号控制

热门文章

  1. 在大厂实习,表示很慌!
  2. 第39届龙家展盛大开幕,规模为历届之最,首日人气旺盛
  3. git分支合并冲突解决方法及步骤
  4. git命令进行分支合并
  5. autoware1.13版本,无法打开可视化界面
  6. python时间计算_python时间运算
  7. NumPy和Matplotlib绘图
  8. SpringMVC接收Get请求参数
  9. 4.28 poll API介绍及代码编写
  10. 第十二届蓝桥杯CB组国赛二等奖总结