ZYNQ_DMA控制BRAM读写的地址问题

ZYNQ_DMA控制BRAM读写的地址问题

前言

接上篇仿真的遗留问题,板上调试PS和PL对BRAM的读写。

PL

在这里插入图片描述
这个0xC000_0000~0xC000_1FFF是BRAM的绝对地址,8K byte,也就是2048个32bit,我这里要把它一分为二,即从DDR->0xC000_0000至0xC000_0FFF,DDR<-0xC000_1000至0xC000_1FFF,对于28*28的32bit源图像够用。
在这里插入图片描述

PS

测试,跟之前类似,DMA先把DDR的数据传输至BRAM,再从BRAM传输到DDR的另一个内存空间,这里要注意的一点,DMA通道的BRAM,PS是不能通过xil_in/out接口去读写的,要有AXI GP通道才可以,如果去读不会报错,但是会卡住。

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

#include "xparameters.h"
#include "xaxicdma.h"
#include "xil_cache.h"
#include "xil_io.h"

#define PL_BRAM_Addr 0xC0001000 // 需要单独定义
#define BUFF_LEN  3136  //28*28

XAxiCdma_Config *axi_cdma_cfg;
XAxiCdma axi_cdma;


static int SourceAddr  = 0x11000000;
static int DestAddr    = 0x12000000;



int main()
{
    init_platform();

    print("Hello World\n\r");

    /

    int Status;

    int *SrcPtr;
    int *DestPtr;

    SrcPtr = (int*)SourceAddr;
    DestPtr = (int*)DestAddr;

    //u32 *rx_buffer = (u32 *) PS_OCM_Addr;
    //u32 *tx_buffer = (u32 *) PL_BRAM_Addr;

    //
    static int Array_0[28][28];
    //static int Array_1[28][28];
    int i,j;
    for (i=0;i<28;i++){
    	for (j=0;j<28;j++){
    		Array_0[i][j] = (i*28+j);
    		//Array_1[i][j] = 0;
    	}
    }

    for (i=0;i<28;i++){
    	for (j=0;j<28;j++){
    		SrcPtr[i*28+j] = Array_0[i][j];
    		DestPtr[i+j] = 0;
    	}
    }


    int *tx_buffer = (int *) SrcPtr;
    int *rx_buffer = (int *) PL_BRAM_Addr;

    printf("%d %d\n\r",SrcPtr[55],2*28);

    for(i=28;i<28*3;i++){
  	  printf("%d  %d at %d\n\r",i,SrcPtr[i],&SrcPtr[i]);
    }


    // Set up the AXI CDMA
    printf("--Set up the AXI CDMA\n\r");
    axi_cdma_cfg = XAxiCdma_LookupConfig(XPAR_AXICDMA_0_DEVICE_ID);
    if (!axi_cdma_cfg) {
        printf("AXAxiCdma_LookupConfig failed\n\r");
    }

    Status = XAxiCdma_CfgInitialize(&axi_cdma, axi_cdma_cfg, axi_cdma_cfg->BaseAddress);
    if (Status == XST_SUCCESS ){
        printf("XAxiCdma_CfgInitialize succeed\n\r");
    }
    printf("--Disable Interrupt of AXI CDMA\n\r");
    XAxiCdma_IntrDisable(&axi_cdma, XAXICDMA_XR_IRQ_ALL_MASK);

    if (XAxiCdma_IsBusy(&axi_cdma)) {
    printf("AXI CDMA is busy...\n\r");
    while (XAxiCdma_IsBusy(&axi_cdma));
    }


    Xil_DCacheFlush();

    Status = XAxiCdma_SimpleTransfer(
                                     &axi_cdma,
                                     (u32) tx_buffer,
                                     (u32) rx_buffer,
                                     BUFF_LEN,
                                     NULL,
                                     NULL);

    Xil_DCacheFlush();

    printf("%d",Status);

    printf("transaction from ps2pl is done\n\r");

    u32 *tx_buffer1 = (u32 *) PL_BRAM_Addr;
    u32 *rx_buffer1 = (u32 *) DestAddr;

    // Set up the AXI CDMA
       printf("--Set up the AXI CDMA\n\r");
       axi_cdma_cfg = XAxiCdma_LookupConfig(XPAR_AXICDMA_0_DEVICE_ID);
       if (!axi_cdma_cfg) {
           printf("AXAxiCdma_LookupConfig failed\n\r");
       }

       Status = XAxiCdma_CfgInitialize(&axi_cdma, axi_cdma_cfg, axi_cdma_cfg->BaseAddress);
       if (Status == XST_SUCCESS ){
           printf("XAxiCdma_CfgInitialize succeed\n\r");
       }
       printf("--Disable Interrupt of AXI CDMA\n\r");
       XAxiCdma_IntrDisable(&axi_cdma, XAXICDMA_XR_IRQ_ALL_MASK);

       if (XAxiCdma_IsBusy(&axi_cdma)) {
       printf("AXI CDMA is busy...\n\r");
       while (XAxiCdma_IsBusy(&axi_cdma));
       }


       Xil_DCacheFlush();

       Status = XAxiCdma_SimpleTransfer(
                                        &axi_cdma,
                                        (u32) tx_buffer1,
                                        (u32) rx_buffer1,
                                        BUFF_LEN,
                                        NULL,
                                        NULL);

       Xil_DCacheFlush();

       printf("transaction from pl2ps is done\n\r");





      for(i=28*27;i<28*28;i++){
    	  printf("%x  %x at %x\n\r",i,rx_buffer1[i],&rx_buffer1[i]);
      }


    //cleanup_platform();
    return 0;
}


我直接验证最后一组数据,是可以的,接下来测试一下如果超过BRAM地址边界会发生什么
在这里插入图片描述
这边简单一点,直接修改BRAM的偏移地址
#define PL_BRAM_Addr 0xC0001F00 // 需要单独定义
在这里插入图片描述
这里可以看到依然可以读,但是数值是不正确的,打印的地址的递增也证明了对PL BRAM和寄存器资源的操作的最小单位是一个字节,32bit数据的操作是4个字节,因此,逻辑部分也很好修改,layer1模块的地址 <<2 就可以了,这个也说明仿真的结果可能是有问题的。

	wire [31:0] ram_addr;
       
       layer1 layer1_inst(
            .sys_clk             (FCLK_CLK       ),     //input    
            .sys_rst_n           (FCLK_RESET_N   ),     //input    
            .PL_interrupt        (PL_interrupt    ),      //output            
            .reg0                (reg0            ),   //input    
            .reg1                (reg1            ),   //input   
            .reg2                (reg2            ),   //input   
            .reg3                (reg3            ),   //input   
            .reg4                (reg4            ),   //input   
            .reg5                (reg5            ),   //input   
            .reg6                (reg6            ),   //input   
            .reg7                (reg7            ),   //input   
            .reg8                (reg8            ),   //input   
            .reg9                (reg9            ),   //input   
            .reg10               (reg10           ),   //input   
            .reg11               (reg11           ),   //input   
            .reg12               (reg12           ),   //input   
            .reg13               (reg13           ),   //input   
            .reg14               (reg14           ),   //input   
            .reg15               (reg15           ),   //input   
            .reg16               (reg16           ),   //input   
            .reg17               (reg17           ),   //input   
            .reg18               (reg18           ),   //input   
            .reg19               (reg19           ),   //input   
            .reg20               (reg20           ),   //input   
            .reg21               (reg21           ),   //input   
            .reg22               (reg22           ),   //input   
            .reg23               (reg23           ),   //input   
            .reg24               (reg24           ),     //input   
            .reg25               (reg25           ),     //input   
            .reg26               (reg26           ),     //input   
            .reg27               (reg27           ),     //input   
            .reg28               (reg28           ),   //output  
            .reg29               (reg29           ),   //output  
            .reg30               (reg30           ),   //output  
            .reg31               (reg31           ),   //output  
            .ram_addr            (ram_addr        ),     //output  //revised 190412
            .wr_out              (dinb            ),   //output  
            .rd_in               (doutb           ),   //input     
            .enb                 (enb             ),   //output  >design_1_wrapper
            .web                 (web             )     //output  
            
        );
       
      // 
      
      assign addrb = ram_addr << 2;

总结

改动之后的仿真图就不放了,下篇直接放板上验证的结果就好。

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值