前言
接上篇仿真的遗留问题,板上调试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;
总结
改动之后的仿真图就不放了,下篇直接放板上验证的结果就好。