PS和PL使用BRAM进行数据交互

一、简介

BRAM(Block RAM)是 PL 部分的存储器阵列,PS 和 PL 通过对 BRAM 进行读写操作,来实现数据的交互。在 PL 中,通过输出时钟、地址、读写控制等信号来对 BRAM 进行读写操作。而在 PS 中,处理器并不需要直接驱动 BRAM 的端口,而是通过 AXI BRAM 控制器来对 BRAM 进行读写操作。AXI BRAM 控制器是集成在 Vivado 设计软件中的软核,可以配置成 AXI4-lite 接口模式或者 AXI4 接口模式。

AXI4 接口模式的 BRAM 控制器支持的数据位宽为 32 位、64 位、128 位、512 位和 1024 位,而 AXI4-Lite接口仅支持 32 位数据位宽。PS 通过 AXI4-Lite 接口访问 BRAM,当使能 ECC 选项时,ECC 允许 AXI 主接口检测和纠正 BRAM 块中的单位和双位错误。AXI BRAM 控制器作为 AXI 总线的从接口,和 AXI 主接口实现互联,来对 BRAM 进行读写操作。针对不同的应用场合,该 IP 核支持单次传输和突发传输两种方式。

任务:

PS 将串口接收到的数据写入 BRAM,然后从 BRAM 中读出数据,并通过串口打印出来;与此同时,PL 从 BRAM 中同样读出数据,并通过 ILA 来观察读出的数据与串口打印的数据是否一致。下面是系统框图

PS 端的 M_AXI_GP0 作为主端口,与 PL 端的 AXI BRAM 控制器 IP 核和 PL 读 BRAM IP (pl_bram_rd)通过 AXI4 总线进行连接。其中,AXI 互联 IP(AXI Interconnect)用于连接 AXI 存储器映射(memory-mapped)的主器件和从器件;AXI BRAM 控制器作为 PS 端读写 BRAM 的 IP 核;PL 读BRAM IP 核是我们自定义的 IP 核,实现了 PL 端从 BRAM 中读出数据的功能,除此之外,PS 端通过 AXI总线来配置该 IP 核读取 BRAM 的起始地址和个数等。本实验中,我们将自定义的IP核替换成AXI BRAM IP核。

本次实验创建的BRAM是双端口RAM,两个端口均连接AXI BRAM控制器

二、硬件设计

接着我们调用一个双端口RAM

综合后的连线图

三、SDK验证

工程代码

#include <stdio.h>
#include "xil_io.h"
#include "xparameters.h"
#include "xbram.h"

#define BRAM_CTRL_0_BASE      XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR//用于写入数据,操作A端口的AXI总线基地址
#define BRAM_CTRL_1_BASE      XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR//用于读数据,操作B端口的AXI总线基地址
char test_string[]="test ps pl bram string\n";
int main()
{
    int num,str_len;
    int str_rev;
    xil_printf("application start \n");
    str_len=strlen(test_string);//计算写入长度
    //通过控制axi_bram_ctrl_0像双端口ram写入test_string
    for( num=0; num<str_len; num++ )
    {
        XBram_WriteReg(BRAM_CTRL_0_BASE , num*4, test_string[num]);
    }

    //通过控制axi_bram_ctrl_1读出写入的数据
   for( num=0; num<str_len; num++ )
   {
       str_rev = XBram_ReadReg( BRAM_CTRL_1_BASE, num*4);
       xil_printf( "ADDR:%x DAT:%c\n",XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR + num*4,str_rev);
   }

    xil_printf("test over!\n");

    return 0;
}

调试如下

地址高位是42开头的

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用DMA实现PSPL之间的数据传输之前,需要确保已经完成了以下步骤: 1. 在PL中实现所需的IP核并进行管脚约束。 2. 在PS使用设备树将IP核与DMA控制器进行连接。 3. 在PS中初始化DMA控制器。 完成上述步骤后,可以使用以下代码示例在PSPL之间使用DMA进行数据传输: ```c #include <stdio.h> #include <stdint.h> #include "xaxidma.h" // DMA控制器相关信息 #define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID #define DMA_MEM_BASE XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR #define DMA_MEM_HIGH XPAR_AXI_BRAM_CTRL_0_S_AXI_HIGHADDR #define DMA_TX_CHAN XPAR_AXIDMA_0_TX_CHAN_ID #define DMA_RX_CHAN XPAR_AXIDMA_0_RX_CHAN_ID #define DMA_BUFFER_SIZE 1024 // 数据缓冲区 uint32_t tx_buffer[DMA_BUFFER_SIZE]; uint32_t rx_buffer[DMA_BUFFER_SIZE]; // AXI DMA实例 XAxiDma dma_inst; int main() { int i; // 初始化 DMA 控制器 XAxiDma_Config *cfg_ptr = XAxiDma_LookupConfig(DMA_DEV_ID); if (XAxiDma_CfgInitialize(&dma_inst, cfg_ptr) != XST_SUCCESS) { printf("Error initializing DMA controller\n"); return -1; } // 检查 DMA 控制器的状态 if (!XAxiDma_HasSg(&dma_inst)) { printf("DMA controller configured as simple mode\n"); return -1; } // 将缓冲区中的数据设置为递增的数值 for (i = 0; i < DMA_BUFFER_SIZE; ++i) { tx_buffer[i] = i; } // 将数据入 DMA 控制器的内存区域 if (XAxiDma_SimpleTransfer(&dma_inst, (uint32_t)tx_buffer, DMA_BUFFER_SIZE * sizeof(uint32_t), XAXIDMA_DMA_TO_DEVICE) != XST_SUCCESS) { printf("Error writing data to DMA controller\n"); return -1; } // 等待 DMA 控制器数据并将其存储到缓冲区中 while (XAxiDma_Busy(&dma_inst, XAXIDMA_DEVICE_TO_DMA)) {} // 从 DMA 控制器的内存区域数据 if (XAxiDma_SimpleTransfer(&dma_inst, (uint32_t)rx_buffer, DMA_BUFFER_SIZE * sizeof(uint32_t), XAXIDMA_DEVICE_TO_DMA) != XST_SUCCESS) { printf("Error reading data from DMA controller\n"); return -1; } // 等待 DMA 控制器数据并将其取到缓冲区中 while (XAxiDma_Busy(&dma_inst, XAXIDMA_DMA_TO_DEVICE)) {} // 打印取到的数据 for (i = 0; i < DMA_BUFFER_SIZE; ++i) { printf("rx_buffer[%d] = %d\n", i, rx_buffer[i]); } return 0; } ``` 需要注意的是,上述代码中的DMA控制器的相关信息需要根据具体的硬件平台进行修改。此外,在使用DMA进行数据传输之前,还需要确保IP核和DMA控制器之间的连接已经正确地进行了配置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值