当前位置:   article > 正文

ZYNQ第六章-PS与PL数据交互第一篇_zynq ps与pl之间传输

zynq ps与pl之间传输


一、PL和PS端交互方式

  1. PS端作为AXI master,FPGA作为AXI slave
  2. 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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65

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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

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端去读在这里插入图片描述
实验结果一切正常!!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/830452
推荐阅读
  

闽ICP备14008679号