如何在 zynq 中进行 PL 端与 PS 端的数据交互?
在zynq的使用中,高效的进行 BRAM 与 zynq 硬核的数据交换至关重要,当我们需要进行小批量的数据交换时,可以考虑采用 BRAM 作为数据交换的媒介,在 PS 端,将数据通过 AXI 总线写入 PL端的 BRAM 里面去,并且再读出来。整体的设计图如下所示:

PL 端硬件的设计
在 vivado 2017.4 下,可以通过 block design 快速进行模块的添加与设计。设计出来的架构如图所示:

注意事项:
- BRAM 使用真实双端口 RAM ,一个端口连接 axi BRAM controller(用于 PS 端控制 BRAM),一个连接 PL BRAM controller(一个自定义的 PL 端 BRAM 控制器,可以由 PS 端给一些控制信号)。
- BRAM需要选择 BRAM controller 模式。
- zynq 端要打开中断
在经过上面的 block design 设计之后,可将硬件导出,然后打开 sdk ide 开始进行 PS 端程序的开发。
程序的整体流程如下:
- 在 PS 端输入起始地址和长度
- CPU通过 axi BRAM controller 写入BRAM数据
- 通知 PL BRAM controller 读取数据
- PL 内部读完后向相同的位置写入数据,初始数据有CPU告知
- 写完后使能 write_end 信号,出发GPIO 中断
- 中断读取 BRAM 数据,打印显示
关于自定义 IP 的设计:
自定义 IP 实现了对 PL 端 BRAM 的读写操作,并且在外部封装的有 AXI 总线的端口,核心的读写逻辑如下:
module ram_read_write
(
input clk,
input rst_n,
//bram port
input [31:0] din,
output reg [31:0] dout,
output reg en,
output reg [3:0] we,
output rst,
output reg [31:0] addr,
//control signal
input start, //start to read and write bram
input [31:0] init_data, //initial data defined by software
output reg start_clr, //clear start register
input [31:0] len, //data count
input [31:0] start_addr, //start bram address
//Interrupt
input intr_clr, //clear interrupt
output reg intr //interrupt
);
assign rst = 1'b0 ;
localparam IDLE = 3'd0 ;
localparam READ_RAM = 3'd1 ;
localparam READ_END = 3'd2 ;
localparam WRITE_RAM = 3'd3 ;
localparam WRITE_END = 3'd4 ;
reg [2:0] state ;
reg [31:0] len_tmp ;
reg [31:0] start_addr_tmp ;
//Main statement
always @(posedge clk or negedge rst_n)
begin
if (~rst_n)
begin
state <= IDLE ;
dout <= 32'd0 ;
en <= 1'b0 ;
we <= <

本文详细介绍了如何在Zynq FPGA平台上实现PL端与PS端通过BRAM进行数据交互。首先,通过Vivado设计硬件,配置双端口BRAM并连接到PS和PL的控制器。接着,自定义IP实现BRAM的读写操作,通过AXI总线在PS端写入数据,PL端读取并处理后再写回。在SDK中编写PS端软件,读取用户输入的起始地址和长度,通过中断机制触发数据交换。最后,展示了程序运行的效果。
最低0.47元/天 解锁文章
3161





