FPGA実践教程(七)IPcoreを用いてDDRを呼び出す
目的:IPcoreを直接運用してDDRを呼び出す
参考資料:
1. Using the DDR memory independently of the Processor:
http://zedboard.org/content/using-ddr-memory-independently-processor
2.UG 873 Chaptet 6では、AXI CDMA coreがDDR 3を呼び出す可能性があるが、実際に見てもPS対DDRの呼び出しである.
3.axi-liteルーチン:D:xilinxSDx2016.4Vivado_HLS\examples\design\axi_lite
4.他の人とDDR 3を呼び出すプロセス:
https://forums.xilinx.com/t5/Vivado-High-Level-Synthesis-HLS/Axi-Master-DDR-MIG-tester/td-p/641990
5.FPGA実践教程(五)PS用MIG呼び出しDDRhttps://blog.csdn.net/weixin_36474809/article/details/80997945#%E4%BA%94%E3%80%81SDK
6.FPGA実践教程(六)AXI-Lite PSとPL通信を実現https://blog.csdn.net/weixin_36474809/article/details/81206660
目次
一、IPcoreとTestBench
1.1 IPcoreプログラムの作成
1.2 TestBenchの作成
二、システム構築と駆動生成
2.1参考のシステム構築
2.2デルが構築したシステム
三、SDKプログラムの作成
一、IPcoreとTestBench
1.1 IPcoreプログラムの作成
プログラムはトピックのインタフェース部分を除いて後続の実行部分であり,memPtrのポインタに従って読み書きを行い,DDRの読み書きを実現する.
対応するインタフェースに注意:
パラメータ運用インタフェースのs_axiliteプロトコル、CTRLの運用BUSが伝わる.
ポインタはマスターのaxiバスとして、ポートはmemPtrとします.memptrを使用してポインタを入力し、IPcoreでポインタが指す内容を読み書きします.offsetをslaveに設定
1.2 TestBenchの作成
testBenchは簡単で、対応する値をIPcoreに直接入力します.
ここでDDRはTestBenchにおいて大きな配列volatile unsigned int memPtr[5200000]を用いて実現され、そのポインタはDDRポインタとして扱われる.その後、HLSを直接運転すると、対応する値が読み出されます.
二、システム構築と駆動生成
2.1参考のシステム構築
MicroBlazeで構築されたシステムの運用
2.2デルが構築したシステム
7 z 035で構築したシステム:(余分な接続のexternalが現れないでください.そうしないと、ビットストリームの生成はいつも成功しません)
ここでmigのパラメータは以下のパラメータに従って行う:FPGA実践教程(五)PSはMIGでDDRを呼び出すhttps://blog.csdn.net/weixin_36474809/article/details/80997945#%E4%BA%94%E3%80%81SDK
1回目:
2回目:
1回目は1つのインターコネクトで接続され、PSとIPcoreはいずれもインターコネクトで接続されているため、両者に共通のアドレスがあり、2回目は2つのインターコネクトで接続され、IPcoreはmigにしか接続されていないため、PSにはtesterIPcoreのポインタしかなく、IPcoreにはDDR 3のポインタしかありません.
対応するドライバは、関連するフォルダに生成されました.
三、SDKプログラムの作成
E:\FPGAdocuments\7z035\DDR3TestProject
上のドキュメントが欠落しています.次に再開します(後で整理しないように、手順をタイムリーに保存してください):
これに対応するIPcoreプログラムは以下、対応するDDRはm_axiインタフェース、offset=slave
以下testBench
対応するドライバを生成するなど、SDK側のプログラムは以下のようになり、migPtrの値はvivadoでシステムを構築した後のmigのアドレスオフセット量であることに注意する.
SDKプログラムの作成はこのように行われる.
参考資料:
1. Using the DDR memory independently of the Processor:
http://zedboard.org/content/using-ddr-memory-independently-processor
2.UG 873 Chaptet 6では、AXI CDMA coreがDDR 3を呼び出す可能性があるが、実際に見てもPS対DDRの呼び出しである.
3.axi-liteルーチン:D:xilinxSDx2016.4Vivado_HLS\examples\design\axi_lite
4.他の人とDDR 3を呼び出すプロセス:
https://forums.xilinx.com/t5/Vivado-High-Level-Synthesis-HLS/Axi-Master-DDR-MIG-tester/td-p/641990
5.FPGA実践教程(五)PS用MIG呼び出しDDRhttps://blog.csdn.net/weixin_36474809/article/details/80997945#%E4%BA%94%E3%80%81SDK
6.FPGA実践教程(六)AXI-Lite PSとPL通信を実現https://blog.csdn.net/weixin_36474809/article/details/81206660
目次
一、IPcoreとTestBench
1.1 IPcoreプログラムの作成
1.2 TestBenchの作成
二、システム構築と駆動生成
2.1参考のシステム構築
2.2デルが構築したシステム
三、SDKプログラムの作成
一、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が伝わる.
ポインタはマスターの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
",size,mode);
result = memDDR3Tester(0,size,mode,0,memPtr,&expectedVal,&failedAddr,&numErrors);
printf("Result mode 0: %d Expected: %d failedAddr:%d numErrors:%d
",result,expectedVal,failedAddr,numErrors);
printf("Results:
");
//Output the values in array(DDR3)
for (int idx = 0; idx < size; idx++)
{
printf("address:%x DDR3[%d]=%x
",&memPtr[idx],idx,memPtr[idx]);
}
return 0;
}
testBenchは簡単で、対応する値をIPcoreに直接入力します.
ここでDDRはTestBenchにおいて大きな配列volatile unsigned int memPtr[5200000]を用いて実現され、そのポインタはDDRポインタとして扱われる.その後、HLSを直接運転すると、対応する値が読み出されます.
二、システム構築と駆動生成
2.1参考のシステム構築
MicroBlazeで構築されたシステムの運用
2.2デルが構築したシステム
7 z 035で構築したシステム:(余分な接続のexternalが現れないでください.そうしないと、ビットストリームの生成はいつも成功しません)
ここでmigのパラメータは以下のパラメータに従って行う:FPGA実践教程(五)PSはMIGでDDRを呼び出すhttps://blog.csdn.net/weixin_36474809/article/details/80997945#%E4%BA%94%E3%80%81SDK
1回目:
2回目:
1回目は1つのインターコネクトで接続され、PSとIPcoreはいずれもインターコネクトで接続されているため、両者に共通のアドレスがあり、2回目は2つのインターコネクトで接続され、IPcoreはmigにしか接続されていないため、PSにはtesterIPcoreのポインタしかなく、IPcoreにはDDR 3のポインタしかありません.
対応するドライバは、関連するフォルダに生成されました.
三、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
",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:
");
for (idx = 0; idx < size; idx++)
{
printf("address:%x DDR3[%d]=%d
",&migPtr[idx],idx,migPtr[idx]);
}
return 0;
}
対応するドライバを生成するなど、SDK側のプログラムは以下のようになり、migPtrの値はvivadoでシステムを構築した後のmigのアドレスオフセット量であることに注意する.
#include
#include
#include
#include
XMigtester XMigtesterCore;
int main()
{
printf("
Program start SUCCESS!
");
int statue,result,testIdx;
int size=5000;
int migPtr=0x80000000;
printf(" Testsize is %d......
",size);
//Init IPcore
statue=XMigtester_Initialize(&XMigtesterCore, XPAR_MIGTESTER_0_DEVICE_ID);
if (statue==XST_DEVICE_NOT_FOUND){
printf(" IPcore find FAILURE!
");
return 1;
}
printf(" IP core init SUCCESS!
");
//Running IPcore
printf(" Running IP core......
");
//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.......
",totalNumDDR);
//PS run total
int totalNumPS=0;
for (testIdx = 0; testIdx < size; testIdx++){
totalNumPS+=testIdx;
}
printf(" Get from PS totalNumPS=%d.......
",totalNumPS);
//IPcore result
if(result==0)
printf(" Result=0,IPcore test DDR3 SUCCESS!
");
else
printf("FAILURE!
");
return 0;
}
SDKプログラムの作成はこのように行われる.