一、pl和ps端交互方式
- ps端作为axi master,fpga作为axi slave
- ps端作为axi slave,fpga作为axi master
二、ps端为主机,fpga为从机
bd框图:
1、实验一
1.1、pl端工作
pl端在bram地址0-39当中写入40个字节数据,然后ps端去读该数据
注: 写代码的时候需要注意一点,在平时我们使用bram时候,如果位宽为32,那么地址加一时候的单位是以4字节为单位,但是在bd里面通过axi bram ctrl去控制bram的时候,地址加一对应的是一个byte数据,我们位宽为32,那么写一个数据,地址就应该加32/8,也就是4。
module ram_wr#(
parameter p_operation_num = 40 ,
parameter p_data_width = 32 ,
parameter p_write_baseaddr= 0 ,
parameter p_read_baseaddr = 40
)(
input i_clk ,
input i_rst ,
output [31:0] o_bram_addr ,
output [31:0] o_bram_data ,
output o_bram_en ,
output o_bram_wen ,
input [31:0] i_bram_data
);
localparam p_burst_len = p_operation_num/(p_data_width/8);
reg [31:0] ro_bram_addr ;
reg [31:0] ro_bram_data ;
reg ro_bram_en ;
reg ro_bram_wen ;
reg [15:0] r_cnt ;
assign o_bram_addr = ro_bram_addr ;
assign o_bram_data = ro_bram_data ;
assign o_bram_en = ro_bram_en ;
assign o_bram_wen = ro_bram_wen ;
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst)
r_cnt <= 'd0;
else if(r_cnt == 1000)
r_cnt <= 'd0;
else
r_cnt <= r_cnt + 1;
end
always@(posedge i_clk,posedge i_rst)
begin
if(i_rst) begin
ro_bram_addr <= 'd0;
ro_bram_data <= 'd0;
ro_bram_en <= 'd0;
ro_bram_wen <= 'd0;
end else if(r_cnt >= 100 && r_cnt < 100 + p_burst_len) begin
ro_bram_addr <= p_write_baseaddr + ((r_cnt - 100) << 2);
ro_bram_data <= r_cnt - 100;
ro_bram_en <= 'd1;
ro_bram_wen <= 'd1;
end else if(r_cnt >= 800 && r_cnt < 800 + p_burst_len) begin
ro_bram_addr <= p_read_baseaddr + ((r_cnt - 800) << 2);
ro_bram_data <= 'd0;
ro_bram_en <= 'd1;
ro_bram_wen <= 'd0;
end else begin
ro_bram_addr <= 'd0;
ro_bram_data <= 'd0;
ro_bram_en <= 'd0;
ro_bram_wen <= 'd0;
end
end
endmodule
1.2、ps端工作
ps端在bram地址0-39当中读出pl写入的40个字节数据
首先上电禁用cache,让arm直接从ddr当中读取数据;
while循环当中使用xil_in32()函数将barm地址0-39当中的40个字节读出,一次读出4byte,也就是32bit,并且写入数组bramreaddata[]当中xpar_axi_bram_ctrl_0_s_axi_baseaddr 为bram控制器基地址,同样要记得地址加1对应一个byte,所以地址一次加4。usleep(5000)表示延时5ms,usleep函数单位为us。
读完数据延时5ms后ps端在bram地址40-79当中写入40byte数据,一次写入32bit,所以地址一次加4.
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xil_cache.h"//禁用cache,让cpu直接访问ddr,否则是先将ddr数据读到cache里,cpu再去读数据
#include "sleep.h"//延时函数
#include "xil_io.h"//输入输出库,包含了写内存函数
#include "xparameters.h"
int main()
{
init_platform();
xil_dcachedisable();
xil_icachedisable();
print("cache is disabled\n\r");
int i = 0;
u32 bramreaddata[10];
while(1){
for(i=0; i<10; i++){
bramreaddata[i] = xil_in32(xpar_axi_bram_ctrl_0_s_axi_baseaddr + i*4);
}
usleep(5000);
for(i=0; i<10; i++){
xil_out32(xpar_axi_bram_ctrl_0_s_axi_baseaddr + 40 + i*4,i);
}
usleep(5000);
}
cleanup_platform();
return 0;
}
1.3、ps端上板效果
成功关闭cache,ps端成功将pl端写入的数据1-10读出。
1.4、pl端上板效果
pl端加入了俩个ila,一个用来捕获我们自己写的bram_wr模块是如何进行读写bram,一个用来捕获ps端如何通过axi接口进行读写bram。
ila1:
pl端写入数据过程:
pl端在bram地址0-39写入十个从0开始的递增数据,然后让ps端去读
pl端读出数据过程:
ps端在bram地址40-79写入十个从0开始的递增数据,然后让pl端去读
ila2:
ps端读出数据过程:
pl端在bram地址0-39写入十个从0开始的递增数据,然后让ps端去读
从波形图可以看出ps端gp_master_axi接口其实是一个axi_lite接口,一次读写都只能读写一个数据
ps端写入数据过程:
ps端在bram地址40-79写入十个从0开始的递增数据,然后让pl端去读
实验结果一切正常!!
发表评论