PL Design Primer
[
Front page
] [
New
|
Page list
|
Search
|
Recent changes
|
Help
|
Log in
]
Start:
[[zFIFO - an AXI DMA driver for Zynq and ZynqMP]]
* zFIFO むけの PL design を作る [#y2374b09]
ここでは、自分で作った FPGA デザインを PL にのせて、zFIFO...
- PLにAXI DMA (scatter & gather mode) を実装
- ユーザの設計したロジックはこの AXI DMA に AXI Streamで...
することになります。
** Vivadoのブロックデザインを用意する [#m2ffa4b5]
zFIFO のソースコードと一緒に、Ultra96 (無印およびv2)、ZYB...
Ultra96v2 を使う場合は Avnet の BDF repository (https://g...
スクリプトは examples/fifo/ 以下の、各ボードに対応したフ...
手順は簡単で、
+ Vivado で空のプロジェクトを作成 (デバイスの設定とかは適...
+ Vivado の Tools -> Run Tcl Script で、上記の Tcl script...
とするだけです。こうすると、以下のようにAXI DMA を AXI St...
#ref(PL Design Primer/ps_design.png,50%);
** Vivado HLSでのコード例 [#d691802d]
Vivado HLSでコードを書くときのポイントは、
+ 入出力ともAXI Streamなので、hls::streamクラスを使うのが...
-- TLAST信号をつけるには正式にはap_intクラスを使う方法が...
+ 出力 (FPGA -> Linux) については、Linux 側で長さが事前に...
の2点です。
1次元の整数配列の総和をもとめるVivado HLS用コードの例を以...
#geshi(c++,number){{
#include "hls_stream.h"
struct int_s{
int data;
bool last;
};
void vec_accum (hls::stream<int_s>& a,
hls::stream<int_s>& b){
#pragma HLS INTERFACE axis port=a
#pragma HLS INTERFACE axis port=b
int_s aa, bb;
int sum=0, i=0;
do {
aa = a.read();
int x = aa.data;
sum += x;
i ++;
} while(aa.last == 0);
bb.data=i; bb.last=0; b.write(bb);
bb.data=sum; bb.last=1; b.write(bb);
}
}}
これを普通にVivado HLSで合成すると、ブロックレベルのハン...
#ref(PL Design Primer/bd3.png,40%);
Vivadoで生成したビットストリームは、/boot/pl.bin に置くな...
** Linux (PS) 側のコード [#gbd857c3]
上記のHLSコードを動かすための、PS側のzfifoなコード (vec-a...
#geshi(c++,number){{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "zfifo.h"
int main(){
int fd = open("/dev/zfifo0", O_RDWR | O_SYNC);
if (fd<0) {
printf("Can't open /dev/zfifo0!\n");
return -1;
}
unsigned size = 10;
int send[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int recv[2] = { 0 };
zf_send(fd, (char*)send, sizeof(int)*size);
zf_recv(fd, (char*)recv, sizeof(int)*2);
printf("Length: %d, Sum: %d\n", recv[0], recv[1]);
close(fd);
return 0;
}
}}
配列に書いておいたデータを zf_send() で送信、zf_recv() で...
ダウンロード時点で用意されている DMA loopback の例題と同...
$ sudo sh load_driver
でドライバをロードしたあと、
$ gcc libzfifo.c vec-accum-ps.c -o vec-accum
$ ./vec-accum
Length: 10, Sum: 55
のようにして実行し、動作確認ができます。
** 制限事項など [#z5e83ab1]
zfifo によるデータ転送には以下のような制約があります。
- AXI DMA で PL から受信するデータ長と zf_recv() の第2引...
-- zf_send()、zf_recv() ともに、タイムアウトはありません
-- 現在のところDMAの終了検出は割り込みでなくドライバでの...
- 送受信するデータのメモリアドレスのアライメントは AXI DM...
-- Allow unaligned transfer の設定をしたコアなら、4バイト...
-- ふつうに配列として宣言したりmalloc() した領域は4バイト...
End:
[[zFIFO - an AXI DMA driver for Zynq and ZynqMP]]
* zFIFO むけの PL design を作る [#y2374b09]
ここでは、自分で作った FPGA デザインを PL にのせて、zFIFO...
- PLにAXI DMA (scatter & gather mode) を実装
- ユーザの設計したロジックはこの AXI DMA に AXI Streamで...
することになります。
** Vivadoのブロックデザインを用意する [#m2ffa4b5]
zFIFO のソースコードと一緒に、Ultra96 (無印およびv2)、ZYB...
Ultra96v2 を使う場合は Avnet の BDF repository (https://g...
スクリプトは examples/fifo/ 以下の、各ボードに対応したフ...
手順は簡単で、
+ Vivado で空のプロジェクトを作成 (デバイスの設定とかは適...
+ Vivado の Tools -> Run Tcl Script で、上記の Tcl script...
とするだけです。こうすると、以下のようにAXI DMA を AXI St...
#ref(PL Design Primer/ps_design.png,50%);
** Vivado HLSでのコード例 [#d691802d]
Vivado HLSでコードを書くときのポイントは、
+ 入出力ともAXI Streamなので、hls::streamクラスを使うのが...
-- TLAST信号をつけるには正式にはap_intクラスを使う方法が...
+ 出力 (FPGA -> Linux) については、Linux 側で長さが事前に...
の2点です。
1次元の整数配列の総和をもとめるVivado HLS用コードの例を以...
#geshi(c++,number){{
#include "hls_stream.h"
struct int_s{
int data;
bool last;
};
void vec_accum (hls::stream<int_s>& a,
hls::stream<int_s>& b){
#pragma HLS INTERFACE axis port=a
#pragma HLS INTERFACE axis port=b
int_s aa, bb;
int sum=0, i=0;
do {
aa = a.read();
int x = aa.data;
sum += x;
i ++;
} while(aa.last == 0);
bb.data=i; bb.last=0; b.write(bb);
bb.data=sum; bb.last=1; b.write(bb);
}
}}
これを普通にVivado HLSで合成すると、ブロックレベルのハン...
#ref(PL Design Primer/bd3.png,40%);
Vivadoで生成したビットストリームは、/boot/pl.bin に置くな...
** Linux (PS) 側のコード [#gbd857c3]
上記のHLSコードを動かすための、PS側のzfifoなコード (vec-a...
#geshi(c++,number){{
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include "zfifo.h"
int main(){
int fd = open("/dev/zfifo0", O_RDWR | O_SYNC);
if (fd<0) {
printf("Can't open /dev/zfifo0!\n");
return -1;
}
unsigned size = 10;
int send[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int recv[2] = { 0 };
zf_send(fd, (char*)send, sizeof(int)*size);
zf_recv(fd, (char*)recv, sizeof(int)*2);
printf("Length: %d, Sum: %d\n", recv[0], recv[1]);
close(fd);
return 0;
}
}}
配列に書いておいたデータを zf_send() で送信、zf_recv() で...
ダウンロード時点で用意されている DMA loopback の例題と同...
$ sudo sh load_driver
でドライバをロードしたあと、
$ gcc libzfifo.c vec-accum-ps.c -o vec-accum
$ ./vec-accum
Length: 10, Sum: 55
のようにして実行し、動作確認ができます。
** 制限事項など [#z5e83ab1]
zfifo によるデータ転送には以下のような制約があります。
- AXI DMA で PL から受信するデータ長と zf_recv() の第2引...
-- zf_send()、zf_recv() ともに、タイムアウトはありません
-- 現在のところDMAの終了検出は割り込みでなくドライバでの...
- 送受信するデータのメモリアドレスのアライメントは AXI DM...
-- Allow unaligned transfer の設定をしたコアなら、4バイト...
-- ふつうに配列として宣言したりmalloc() した領域は4バイト...
Page: