FPGA实践教程(七)运用IPcore调用DDR

目的:直接运用IPcore调用DDR

一、IPcore与TestBench

1.1 IPcore程序的编写
// HLS IP Core
#include
#include
#include

unsigned int memDDR3Tester(unsigned int start, unsigned int size,
unsigned int mode, unsigned int data,
volatile unsigned int *memPtr, unsigned int *expectedVal,
unsigned int *failedAddr, unsigned int *numErrors)
{
#pragma HLS INTERFACE s_axilite port=numErrors bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=failedAddr bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=expectedVal bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=start bundle=CRTL_BUS
#pragma HLS INTERFACE m_axi depth=512 port=memPtr offset=slave
#pragma HLS INTERFACE s_axilite port=data bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=mode bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=size bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=return bundle=CRTL_BUS
unsigned int result = 0;
unsigned int idxMemAddr = 0;
unsigned int errorCounter = 0;
*numErrors = 0;
*expectedVal = 0;
*failedAddr = 0;

switch (mode){
case 0:{
// Write
for (idxMemAddr = 0; idxMemAddr < size; idxMemAddr++)
{
unsigned char isOdd = (idxMemAddr % 2);
unsigned int value = (isOdd)?0x55AA:0xAA55;
memPtr[idxMemAddr] = value;
}
// Read
for (idxMemAddr = 0; idxMemAddr < size; idxMemAddr++)
{
unsigned char isOdd = (idxMemAddr % 2);
unsigned int value = (isOdd)?0x55AA:0xAA55;
if (memPtr[idxMemAddr] != value)
{
result = 1;
*expectedVal = value;
*failedAddr = idxMemAddr;
// Bail out on the first error
*numErrors = 1;
break;
}
}
break;
}
/*
* Send an incremental value but don't stop if some error occured and return the number of errors
* */
case 1:{
// Write
for (idxMemAddr = 0; idxMemAddr < size; idxMemAddr++)
{
unsigned int value = idxMemAddr;
memPtr[idxMemAddr] = value;
}
// Read
for (idxMemAddr = 0; idxMemAddr < size; idxMemAddr++)
{
unsigned int value = idxMemAddr;
if (memPtr[idxMemAddr] != value)
{
result = 1;
errorCounter++;
}
}
*numErrors = errorCounter;
break;
}
}
return result;
}

程序除了主题的接口部分就是后续的执行部分,执行根据memPtr的指针来进行对读写,以实现对DDR的读写。

注意相应的接口:
unsigned int memDDR3Tester(unsigned int start, unsigned int size,
unsigned int mode, unsigned int data,
volatile unsigned int *memPtr, unsigned int *expectedVal,
unsigned int *failedAddr, unsigned int *numErrors)
{
#pragma HLS INTERFACE s_axilite port=numErrors bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=failedAddr bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=expectedVal bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=start bundle=CRTL_BUS
#pragma HLS INTERFACE m_axi depth=512 port=memPtr offset=slave
#pragma HLS INTERFACE s_axilite port=data bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=mode bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=size bundle=CRTL_BUS
#pragma HLS INTERFACE s_axilite port=return bundle=CRTL_BUS

参数运用接口的s_axilite协议,运用CTRL_BUS来传递。

指针作为master的axi总线,端口设为memPtr。运用memptr传入指针,然后IPcore对指针所指的内容进行读写。offset设为slave

1.2 TestBench的编写
// HLS test Bench
#include
unsigned int memDDR3Tester(unsigned start, unsigned int size,
unsigned int mode, unsigned int data,
//Use arrays to simulate DDR3 in HLS testBench
volatile unsigned int memPtr[512000000], unsigned int *expectedVal,
unsigned int *failedAddr, unsigned int *numErrors);
int main()
{
unsigned int memPtr[10];
unsigned int expectedVal;
unsigned int failedAddr;
unsigned int numErrors;
unsigned int result;
unsigned int size=10;
unsigned int mode=0;
//Test the IPcore
printf(" Test Size:%d, Test mode %d\n",size,mode);
result = memDDR3Tester(0,size,mode,0,memPtr,&expectedVal,&failedAddr,&numErrors);
printf("Result mode 0: %d Expected: %d failedAddr:%d numErrors:%d\n",result,expectedVal,failedAddr,numErrors);
printf("Results:\n");
//Output the values in array(DDR3)
for (int idx = 0; idx < size; idx++)
{
printf("address:%x DDR3[%d]=%x\n",&memPtr[idx],idx,memPtr[idx]);
}
return 0;
}

testBench较为简单,直接将相应的值传入IPcore。

其中DDR在TestBench之中运用一个大的数组volatile unsigned int memPtr[512000000]来实现,其指针当作DDR指针。然后直接运行HLS就能读出相应的值。

二、系统搭建与驱动生成
2.1 参考的系统搭建
运用MicroBlaze搭建的系统


2.2 我们搭建的系统
我们用7z035搭建的系统:(不要出现多余的连接的external,不然生成比特流总是不成功)

这里mig的参数按照下面的参数进行: FPGA实践教程(五)PS用MIG调用DDR https://blog.csdn.net/weixin_36474809/article/details/80997945#%E4%BA%94...

第一次:


第二次:


第一次通过一个interconnect连接,PS与IPcore均与interconnect相连,所以两者有共同的地址,第二次通过两个interconnect相连,IPcore只与mig相连,所以PS只能有testerIPcore的指针,IPcore只有DDR3的指针。

相应驱动已经生成,在相关的文件夹之中。

三、SDK程序的编写
 E:\FPGAdocuments\7z035\DDR3TestProject

上面文档缺失。下面重新开始(运行时要及时保存步骤,免得后期不好整理):

与之对应的IPcore程序为下面,相应DDR为m_axi接口,并且offset=slave
#include
#include
#include

int migTester(int size, volatile int *migPtr ,int totalNumDDR){
#pragma HLS INTERFACE s_axilite port=totalNumDDR
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=512 port=migPtr offset=slave
#pragma HLS INTERFACE s_axilite port=size
int testIdx=0;
int result=1; //1 means FAILURE,0 means SUCCESS!
int value;
totalNumDDR=0;
int totalNumIdx=0;
// Write Mig DDR
for (testIdx = 0; testIdx < size; testIdx++){
migPtr[testIdx] = testIdx;
totalNumIdx+=testIdx;
}
// Read Mig DDR
for (testIdx = 0; testIdx < size; testIdx++){
totalNumDDR+=migPtr[testIdx];
}
//compare results
if(totalNumIdx==totalNumDDR)
result=0;
else
result=1;
return result;
}

下面为testBench
#include
int migTester(int size, volatile int *migPtr ,int totalNumDDR);
int main()
{
int size=100;
int migPtr[100];
int totalNumDDR;
int idx;
int result;
//Test IPcore C code
printf(" Test Size:%d, migAddr %x\n",size,migPtr);
result = migTester(size,migPtr,totalNumDDR);
//result
if (result==0)
printf("IP core C code test SUCCESS!");
else
printf("IP core C code test FAILED!");
//Test Address using PC PS
printf("Results:\n");
for (idx = 0; idx < size; idx++)
{
printf("address:%x DDR3[%d]=%d\n",&migPtr[idx],idx,migPtr[idx]);
}
return 0;
}

生成相应的驱动,等等,SDK端的程序为下面,注意migPtr的值为vivado之中搭建系统之后mig的地址偏移量。
#include
#include
#include
#include

XMigtester XMigtesterCore;

int main()
{
printf("\n Program start SUCCESS!\n");

int statue,result,testIdx;
int size=5000;
int migPtr=0x80000000;

printf(" Testsize is %d......\n",size);

//Init IPcore
statue=XMigtester_Initialize(&XMigtesterCore, XPAR_MIGTESTER_0_DEVICE_ID);
if (statue==XST_DEVICE_NOT_FOUND){
printf(" IPcore find FAILURE!\n");
return 1;
}
printf(" IP core init SUCCESS!\n");

//Running IPcore
printf(" Running IP core......\n");
//set value
XMigtester_Set_size(&XMigtesterCore, size);
XMigtester_Set_migPtr(&XMigtesterCore, migPtr);
//start
XMigtester_Start(&XMigtesterCore);
//done
while (!XMigtester_IsDone(&XMigtesterCore));
result=XMigtester_Get_return(&XMigtesterCore);
int totalNumDDR=XMigtester_Get_totalNumDDR(&XMigtesterCore);
printf(" Get from IP core totalNumDDR=%d.......\n",totalNumDDR);

//PS run total
int totalNumPS=0;
for (testIdx = 0; testIdx < size; testIdx++){
totalNumPS+=testIdx;
}
printf(" Get from PS totalNumPS=%d.......\n",totalNumPS);

//IPcore result
if(result==0)
printf(" Result=0,IPcore test DDR3 SUCCESS!\n");
else
printf("FAILURE!\n");

return 0;
}

SDK程序的编写按照此套路进行。

---------------------
作者:邢翔瑞
来源:CSDN
原文: https://blog.csdn.net/weixin_36474809/article/details/84942607

最新文章

最新文章