HLSは私の救世主
(使わなきゃ損です…)
FPGAの部屋の中の人
小野 雅晃
1
自己紹介(1/2)
• 筑波大学シニアスタッフ技術職員、63歳の爺さん
• 1980年に大学卒業
• 大学卒業後に某F社の子会社に入社
• 3年後筑波大学に技術職員として転職
• 教授から声がかかり研究のお手伝い(1995?)
• FPGAを使い始める
• 初めはAltrea(現在はIntel)を使用
• Xilinxに乗り換える
• 来年度は週4日勤務予定
2
FPGAの部屋のブログ
• 2005年にスタート
• 現在5,500記事位
• 664万アクセス
• カテゴリ数は167個
• Vitis HLS (77)
• Vitis_Vision (44)
• NNgen (14)などなど
• https://marsee101.blog.fc2.com/
• FPGA友達がいないので、寂しくて書き始めた
• 途中からは脳の外部記憶として書いた
3
Vitis HLS, Vivado HLSとは?
• Xilinx社の高位合成ツール
• C、C++からVHDL、Verilog HDLに合成しIPを生成す
るツール
• 機能を検証するための2種類のシミュレーション
• Cシミュレーション
• C/RTL協調シミュレーション
4
Vitis HLSの実行手順
5
Vitis HLS(Vivado HLS)の私が考
える特徴および利点1
• C、C++からVHDL、Verilog HDLに合成しIPを生成する
• FPGAの種類を指定して、クロック周期を設定する
• 指定したクロック周期で動作するRTLを出力
• クロック周期を短く設定すると自動的にパイプライン段数が
増える
• AXI-Master, AXI-Lite Slaveはプラグマ1行のみで自動生成
• AXI-Streamはストリーム用テンプレートを使用する
• ソフトウェアから使用するためのドライバも自動生成
• ベアメタル用、Linux用
• 無料!!!(ただしデバイス限定)
• Vivado 2015.4から無償、すべてのバージョンで提供
• https://marsee101.blog.fc2.com/blog-entry-3319.html
• ライセンスが必要ない(ダウンロード時の登録は必要)
6
Vitis HLS(Vivado HLS)の私が考
える特徴および利点2
• 制御部(ステートマシン)を書く必要が無いということは、
ステートマシンに起因するバグが無くなる
• つまりHDL書くよりもバグが少なくなる
• 機能はCベースのシミュレーションで検証可能
• デバック時間が短い
• Eclipseのデバッカーでデバックできる
• HDLを合成したらRTLシミュレーションでHDLを検証
(C/RTL協調シミュレーション)
• CテストベンチからRTLシミュレータにデータを入力
• RTLシミュレーション
• RTLシミュレーションの結果をCテストベンチに返して検証
• タイミング波形を確認できる
7
HLSの欠点
• タイミングの決まっている信号がある回路
• インターフェースIP
• カメラ・インターフェースIP
• ビットマップ・ディスプレイ・コントローラIP
• <例> A信号の3クロック後にB信号を1にする必要がある
• クロックに同期していない信号がある
• シンクロナイザーIP(xpm_cdc)を前段に使用
• 複数クロックがある回路
8
私のVivado HLS, Vitis HLS使用経
緯
• 2013年8月からVivado HLS 2013.2を使い始めた
• https://marsee101.blog.fc2.com/blog-entry-2563.html
• Vivado HLS 2013.4で作成したラプラシアンフィルタ
画像はソフトウェア画像と比べて画像が違ってい
た
• https://marsee101.blog.fc2.com/blog-entry-2737.html
• Vivado HLS 2014.1でソフトウェアとラプラシアンフィ
ルタ画像が同一になった
• バグが解消されたようだ
• Vivado HLSが使えるようになった
• https://marsee101.blog.fc2.com/blog-entry-2800.html
9
Vivado HLSからVitis HLSへ
• Vivado HLSを使用してきたが2020.1からVitis HLSへバト
ンタッチ
• 大体Vivado HLSと同じだが、変更されている部分も
• AXI4マスター・インターフェース作成したときのアドレスだが、
64ビット・アドレスがデフォルトになった
• ハードウェア化する関数内でのストリームの扱い
• Vitis HLSの方がデフォルトの状態でチューニングされている
(レイテンシが短い)
• 初心者は特にVitis HLSをお勧めする
• その他、いろいろ変更有り
• Vitis HLS 移行ガイド UG1391 (v2020.2) 2020 年 11 月
24 日参照
• https://www.xilinx.com/support/documentation/sw_manuals
_j/xilinx2020_2/ug1391-vitis-hls-migration-guide.pdf
10
Vivado HLS 対 Vitis HLS性能比
較、sobel_filter_aximの実装
• DDR SDRAMから画像データを直接Read
2022/3/7 「FPGAの部屋」, marsee101 11
Vivado HLS対Vitis HLS(ソーベ
ル・フィルタ)
12
int sobel_filter_axim(volatile int32_t *cam_fb, volatile int32_t *sobel_fb){
#pragma HLS INTERFACE m_axi depth=3072 port=sobel_fb offset=slave
#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave
#pragma HLS INTERFACE s_axilite port=return
int32_t sobel_val, sobel_h_val, sobel_v_val;
int32_t pix[3][3];
LOOP_Y: for(int y=0; y<(DISPLAY_HIGHT-2); y++){
LOOP_X: for(int x=0; x<(DISPLAY_WIDTH-2); x++){
LOOP1: for(int i=0; i<3; i++){
LOOP2: for(int j=0; j<3; j++){
pix[i][j] = conv_rgb2y(cam_fb[(y+i)*DISPLAY_WIDTH+(x+j)]);
}
}
sobel_h_val = sobel_fil(HORIZONTAL, pix[0][0], pix[0][1], pix[0][2],
pix[1][0], pix[1][1], pix[1][2],
pix[2][0], pix[2][1], pix[2][2]);
sobel_v_val = sobel_fil(VERTICAL, pix[0][0], pix[0][1], pix[0][2],
pix[1][0], pix[1][1], pix[1][2],
pix[2][0], pix[2][1], pix[2][2]);
sobel_val = square_root8(sobel_h_val*sobel_h_val + sobel_v_val*sobel_v_val);
sobel_fb[y*(DISPLAY_WIDTH-2)+x] = (sobel_val<<16)+(sobel_val<<8)+sobel_val; // 通常出力
}
}
Vivado HLS 2019.2
Cコードの合成結果1
• TimingのSummaryでClockのTarget周期が10nsのところ、
8.750 nsなので問題無い
• Syn->Verilogに、6個のVerilog HDLファイルが生成された 13
Vivado HLS 2019.2
Cコードの合成結果2
• Latencyは251299
クロック、Interval
も251299クロック
だった
• BRAM_18Kは2個、
DSP48Eは9個、FF
は1264個、LUTは
2041個使用して
いる
14
Vitis HLS 2021.2
Cコードの合成1
15
• Estimatedは7.300 ns
• Verilog HDLファイルは11個
16
Vitis HLS 2021.2
Cコードの合成2
• Latencyは25706クロック
• Vivado HLSでは251299
クロック
• 性能は約9.8倍
• リソース使用率
• BRAM_18Kが4個
• Vivado HLSでは2個
• DSPが19個
• Vivado HLSでは9個
• FFが2280個
• Vivado HLSでは
1264個
• LUTが3300個
• Vivado HLSでは
2041個
HLSを使うに当たってのモチベー
ション
• 以前はHDL、主にVHDLで回路を書いていた
• 歳を取る毎に集中できる時間が減ってきた
• HDLだと制御部(ステートマシン)と機能を書くので、
時間がかかる
• 歳をとっても回路を実装したい
• そこで、HLSに目をつけた
• 制御部を書く必要がないので、機能だけ書けば良い
• 時短になる
• HDLで1週間かかるところが1時間という場合も
• 若い人が使っても時短になる
17
Vitis HLS, Vivado HLSに対する
私の熱い思い(本音)
• 趣味or大学のお仕事でFPGAを使っているとシステムを
丸ごと(ハードもソフトも)自分1人で実装する
• 科研費の実装は速くする必要がある
• 実装は1年未満に… 6ヶ月位?
• 歳とともにHDLを書けない、書くスピードが遅くなった
• コードを書き始められない…引退が近い???
• そんなときにHLSでCコードを書いてIP実装
• 大幅なスピードアップ
• Xilinxさん、Vivado HLS、Vitis HLSを無料にしてくれて本当
にありがとうございます!
• Vitis HLS、Vivado HLSは私の救世主(使わなきゃ損です)
18
カメラを使用した画像認識により
白線間走行及び隊列走行するロ
ボットカー
• 2016年度の科研費奨励研究
• (課題番号16H00383)
• ガボール・フィルタで白線を検出して白線間を走る
ロボットカー
• 先頭車両のマーカーを検出して隊列走行
19
ロボットカーの構成
• Zybotのプラットフォームを利用した
• Digilent社のZYBOボードを使用した全長30cm程度のロボット
カー
• プラットフォームは使用しているが、ハード、ソフトとも独自開
発
• ZYBO(旧)ボード
• Xilinx社のARMプロセッサ(Cortex-A9デュアル)+FPGAチップ
• Zynq-7010
• 2つのCortex-A9(650MHz動作)でUbuntu14.04が動作
• ソフトウェア実装後にハードウェアにオフロードが簡単
に行える
20
ロボットカー(Zybot)
21
カメラを使用した画像認識により
白線間走行及び隊列走行するロ
ボットカーの使用IP
• 自作IP(9個)
• Vivado HLSで作成したIP(C言語で書いたIP)
• モーター用PWM IP
• モーター・モニターIP(モーターのパルス数をカウント)
• 超音波センサ・インターフェースIP
• ガボール・フィルタIP
• ガボール・フィルタ用DMAC IP
• ラプラシアンフィルタIP
• RGB-HSV変換IP
• ビットマップ・ディスプレイ・コントローラIP
• カメラ・インターフェースIP
• https://marsee101.web.fc2.com/white_line_detect.html
22
白線をガボール・フィルタで検出1
• ガボール・フィルタを使用
• 正弦波とガウス関数の積
• 1次元
• 2次元
• ガウス関数の分散(Sigma)
• 正弦波の周期(Lambda)
• 正弦波の進行方向(角度)(theta)
• 正弦波の位相(Psi)
23
X =
Sigma=4,
Lambda=80,
Theta=68, Psi=94
Sigma=4,
Lambda=80,
Theta=135, Psi=94
白線をガボール・フィルタで検出2
• 左白線用、右白線用ガボール・フィルタのパラメータを決定
• Sigma, Lambda, Theta, Psi
• 日本大学の方のガボール・フィルタの実装を使用した(今Webサイトが無い)
• カーネルサイズを21ピクセルから9ピクセルへ変更
• パラメータを使って演算すればn x nの重みを画像に掛け算するのみ
24
• 9 x 9ピクセルの左白線用、右白線用ガボール・フィルタの重みを
取得した
• 左白線用、右白線用の2つのパラメータのガボール・フィルタを
Vivado HLS でC言語からHDLへ変換してIP化
左白線用、右白線用ガボール・
フィルタ処理画像
25
X X
ガボール・フィルタIPのソースコード
26
int Gabor_filter_lh(hls::stream<ap_axis<32,1,1,1> >& ins,
hls::stream<ap_axis<32,1,1,1> >& outs){
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
ap_axis<32,1,1,1> gabor;
hls::LineBuffer<ARRAY_SIZE-
1, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf;
int gray_pix, val, i, j, x, y;
do { // user が 1になった時にフレームがスタートする
ins >> pix;
} while(pix.user == 0);
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
mbuf.shift_left(); // mbuf の列を1ビット左シフト
for(i=ARRAY_SIZE-2; i>=0; --i){
mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1);
}
gray_pix = conv_rgb2y(pix.data);
mbuf.insert(gray_pix, 0, ARRAY_SIZE-1);
// LineBuffer の更新
linebuf.shift_down(x);
linebuf.insert_bottom(gray_pix, x);
// Gabor filter の演算
for (j=0, val=0; j<ARRAY_SIZE-1; j++){
for (i=0; i<ARRAY_SIZE-1; i++){
val += gabor_weight[j][i] * mbuf(ARRAY_SIZE-1-j,i);
}
}
val = val/256; // 256倍してあるので、1/256して戻す
if (val<0)
//val = -val; // 絶対値
val = 0; // マイナスの値を0に丸める
else if (val>255)
val = 255;
// Gabor filter・データの書き込み
gabor.data = (val<<16)+(val<<8)+val;
// 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-
1列は無効データなので0とする
if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1))
gabor.data = 0;
if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
gabor.user = 1;
else
gabor.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1)) // 行の最後
で TLAST をアサートする
gabor.last = 1;
else
gabor.last = 0;
outs << gabor; // AXI4-Stream へ出力
}
}
return(0);
}
https://marsee101.blog.fc2.com/b
log-entry-3524.html
カメラからのデータの流れ
27
白線間走行のデモ
28
カメラを使用した画像認識により
白線間走行及び隊列走行するロ
ボットカーの使用IP
• 自作IP(9個)
• Vivado HLSで作成したIP(C言語で書いたIP)
• モーター用PWM IP
• モーター・モニターIP(モーターのパルス数をカウント)
• 超音波センサ・インターフェースIP
• ガボール・フィルタIP
• ガボール・フィルタ用DMAC IP
• ラプラシアンフィルタIP
• RGB-HSV変換IP
• ビットマップ・ディスプレイ・コントローラIP
• カメラ・インターフェースIP
• https://marsee101.web.fc2.com/zybot.html
29
隊列走行ロボットカーの追従用
マーカー
• HSV でのH (色相)は、0~360 までの円で表される
ので、0 と 180 の距離が一番離れている。
• S = V = 255 とすると H = 0 は R=255, G = 0, B = 0 つ
まり赤であり、H =180 は R = 0, G = 255, B = 255 の
水色
30
水色の中に赤 RGB画像 HSV変換-S=V=255固定後
RGB変換
RGB2HSV IPのソースコード(一部)
31
int rgb2hsv(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis
<32,1,1,1> >& outs){
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE axis port=ins
ap_axis<32,1,1,1> pix;
int r, g, b;
int h, s, v;
int max, min;
int hsv;
do{
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
}while(pix.user == 0);
loop_y: for(int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
loop_x: for(int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS UNROLL factor=2
#pragma HLS PIPELINE II=1
if(!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
b = pix.data & 0xff;
g = (pix.data>>8) & 0xff;
r = (pix.data>>16) & 0xff;
// h と max, min を求める
if(r==g && g==b && r==b){
max = r; // 8倍
min = r;
}else if(r>=g && r>=b){ // r が最大
max = r;
if(g>=b)
min = b;
else
min = g;
}else if(g>=r && g>=b){ // g が最大
max = g;
if(r>=b)
min = b;
else
min = r;
}else{ // b が最大
max = b;
if(r>=g)
min = g;
else
min = r;
}
if(max-min == 0)
h = 0;
else if(max == r)
h = 60 * (((g-b)<<MAG)/(max-min)); // MAGビットシフトして精
度を確保
else if(max == g)
h = 60 * (((b-r)<<MAG)/(max-min)) + (120<<MAG); // MAG
ビットシフトして精度を確保
else // if(max == b)
h = 60 * (((r-g)<<MAG)/(max-min)) + (240<<MAG); // MAG
ビットシフトして精度を確保
if(h < 0)
h += 360<<MAG;
h += 1<<(MAG-1); // +0.5、四捨五入
https://marsee101.blog.fc2.com/b
log-entry-3604.html
Zybotのカメラで撮影した画像と
判定出力1
32
Small size, Center
Zybotのカメラで撮影した画像と
判定出力2
33
Normal size, Right side
隊列走行ロボットカーのデモ
34
その他の高位合成ツール
• インテル® HLS コンパイラーはインテル® Quartus®
Prime 開発ソフトウェアのインストールに含まれる
• 2017年に試してみたことがある
• https://marsee101.web.fc2.com/intel_hls.html
• Microchip社のSmartHLS
• 2021年12月に試してみた
• https://marsee101.web.fc2.com/smarthls.html
35
まとめ
• HLSは老齢エンジニアの救世主、使わなきゃ損
• 若いエンジニアにも時短のメリット
• バグが少ない
• 実装時間が短い
• 作れないIPもあるがHDLで書いちゃえばOK
• カメラ・インターフェースIP
• ビットマップ・ディスプレイ・コントローラIP
• シンクロナイザーIP…
• 使い方分からない?
• トレーニングで解消
36

ACRiウェビナー:小野様ご講演資料

  • 1.
  • 2.
    自己紹介(1/2) • 筑波大学シニアスタッフ技術職員、63歳の爺さん • 1980年に大学卒業 •大学卒業後に某F社の子会社に入社 • 3年後筑波大学に技術職員として転職 • 教授から声がかかり研究のお手伝い(1995?) • FPGAを使い始める • 初めはAltrea(現在はIntel)を使用 • Xilinxに乗り換える • 来年度は週4日勤務予定 2
  • 3.
    FPGAの部屋のブログ • 2005年にスタート • 現在5,500記事位 •664万アクセス • カテゴリ数は167個 • Vitis HLS (77) • Vitis_Vision (44) • NNgen (14)などなど • https://marsee101.blog.fc2.com/ • FPGA友達がいないので、寂しくて書き始めた • 途中からは脳の外部記憶として書いた 3
  • 4.
    Vitis HLS, VivadoHLSとは? • Xilinx社の高位合成ツール • C、C++からVHDL、Verilog HDLに合成しIPを生成す るツール • 機能を検証するための2種類のシミュレーション • Cシミュレーション • C/RTL協調シミュレーション 4
  • 5.
  • 6.
    Vitis HLS(Vivado HLS)の私が考 える特徴および利点1 •C、C++からVHDL、Verilog HDLに合成しIPを生成する • FPGAの種類を指定して、クロック周期を設定する • 指定したクロック周期で動作するRTLを出力 • クロック周期を短く設定すると自動的にパイプライン段数が 増える • AXI-Master, AXI-Lite Slaveはプラグマ1行のみで自動生成 • AXI-Streamはストリーム用テンプレートを使用する • ソフトウェアから使用するためのドライバも自動生成 • ベアメタル用、Linux用 • 無料!!!(ただしデバイス限定) • Vivado 2015.4から無償、すべてのバージョンで提供 • https://marsee101.blog.fc2.com/blog-entry-3319.html • ライセンスが必要ない(ダウンロード時の登録は必要) 6
  • 7.
    Vitis HLS(Vivado HLS)の私が考 える特徴および利点2 •制御部(ステートマシン)を書く必要が無いということは、 ステートマシンに起因するバグが無くなる • つまりHDL書くよりもバグが少なくなる • 機能はCベースのシミュレーションで検証可能 • デバック時間が短い • Eclipseのデバッカーでデバックできる • HDLを合成したらRTLシミュレーションでHDLを検証 (C/RTL協調シミュレーション) • CテストベンチからRTLシミュレータにデータを入力 • RTLシミュレーション • RTLシミュレーションの結果をCテストベンチに返して検証 • タイミング波形を確認できる 7
  • 8.
    HLSの欠点 • タイミングの決まっている信号がある回路 • インターフェースIP •カメラ・インターフェースIP • ビットマップ・ディスプレイ・コントローラIP • <例> A信号の3クロック後にB信号を1にする必要がある • クロックに同期していない信号がある • シンクロナイザーIP(xpm_cdc)を前段に使用 • 複数クロックがある回路 8
  • 9.
    私のVivado HLS, VitisHLS使用経 緯 • 2013年8月からVivado HLS 2013.2を使い始めた • https://marsee101.blog.fc2.com/blog-entry-2563.html • Vivado HLS 2013.4で作成したラプラシアンフィルタ 画像はソフトウェア画像と比べて画像が違ってい た • https://marsee101.blog.fc2.com/blog-entry-2737.html • Vivado HLS 2014.1でソフトウェアとラプラシアンフィ ルタ画像が同一になった • バグが解消されたようだ • Vivado HLSが使えるようになった • https://marsee101.blog.fc2.com/blog-entry-2800.html 9
  • 10.
    Vivado HLSからVitis HLSへ •Vivado HLSを使用してきたが2020.1からVitis HLSへバト ンタッチ • 大体Vivado HLSと同じだが、変更されている部分も • AXI4マスター・インターフェース作成したときのアドレスだが、 64ビット・アドレスがデフォルトになった • ハードウェア化する関数内でのストリームの扱い • Vitis HLSの方がデフォルトの状態でチューニングされている (レイテンシが短い) • 初心者は特にVitis HLSをお勧めする • その他、いろいろ変更有り • Vitis HLS 移行ガイド UG1391 (v2020.2) 2020 年 11 月 24 日参照 • https://www.xilinx.com/support/documentation/sw_manuals _j/xilinx2020_2/ug1391-vitis-hls-migration-guide.pdf 10
  • 11.
    Vivado HLS 対Vitis HLS性能比 較、sobel_filter_aximの実装 • DDR SDRAMから画像データを直接Read 2022/3/7 「FPGAの部屋」, marsee101 11
  • 12.
    Vivado HLS対Vitis HLS(ソーベ ル・フィルタ) 12 intsobel_filter_axim(volatile int32_t *cam_fb, volatile int32_t *sobel_fb){ #pragma HLS INTERFACE m_axi depth=3072 port=sobel_fb offset=slave #pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave #pragma HLS INTERFACE s_axilite port=return int32_t sobel_val, sobel_h_val, sobel_v_val; int32_t pix[3][3]; LOOP_Y: for(int y=0; y<(DISPLAY_HIGHT-2); y++){ LOOP_X: for(int x=0; x<(DISPLAY_WIDTH-2); x++){ LOOP1: for(int i=0; i<3; i++){ LOOP2: for(int j=0; j<3; j++){ pix[i][j] = conv_rgb2y(cam_fb[(y+i)*DISPLAY_WIDTH+(x+j)]); } } sobel_h_val = sobel_fil(HORIZONTAL, pix[0][0], pix[0][1], pix[0][2], pix[1][0], pix[1][1], pix[1][2], pix[2][0], pix[2][1], pix[2][2]); sobel_v_val = sobel_fil(VERTICAL, pix[0][0], pix[0][1], pix[0][2], pix[1][0], pix[1][1], pix[1][2], pix[2][0], pix[2][1], pix[2][2]); sobel_val = square_root8(sobel_h_val*sobel_h_val + sobel_v_val*sobel_v_val); sobel_fb[y*(DISPLAY_WIDTH-2)+x] = (sobel_val<<16)+(sobel_val<<8)+sobel_val; // 通常出力 } }
  • 13.
    Vivado HLS 2019.2 Cコードの合成結果1 •TimingのSummaryでClockのTarget周期が10nsのところ、 8.750 nsなので問題無い • Syn->Verilogに、6個のVerilog HDLファイルが生成された 13
  • 14.
    Vivado HLS 2019.2 Cコードの合成結果2 •Latencyは251299 クロック、Interval も251299クロック だった • BRAM_18Kは2個、 DSP48Eは9個、FF は1264個、LUTは 2041個使用して いる 14
  • 15.
    Vitis HLS 2021.2 Cコードの合成1 15 •Estimatedは7.300 ns • Verilog HDLファイルは11個
  • 16.
    16 Vitis HLS 2021.2 Cコードの合成2 •Latencyは25706クロック • Vivado HLSでは251299 クロック • 性能は約9.8倍 • リソース使用率 • BRAM_18Kが4個 • Vivado HLSでは2個 • DSPが19個 • Vivado HLSでは9個 • FFが2280個 • Vivado HLSでは 1264個 • LUTが3300個 • Vivado HLSでは 2041個
  • 17.
    HLSを使うに当たってのモチベー ション • 以前はHDL、主にVHDLで回路を書いていた • 歳を取る毎に集中できる時間が減ってきた •HDLだと制御部(ステートマシン)と機能を書くので、 時間がかかる • 歳をとっても回路を実装したい • そこで、HLSに目をつけた • 制御部を書く必要がないので、機能だけ書けば良い • 時短になる • HDLで1週間かかるところが1時間という場合も • 若い人が使っても時短になる 17
  • 18.
    Vitis HLS, VivadoHLSに対する 私の熱い思い(本音) • 趣味or大学のお仕事でFPGAを使っているとシステムを 丸ごと(ハードもソフトも)自分1人で実装する • 科研費の実装は速くする必要がある • 実装は1年未満に… 6ヶ月位? • 歳とともにHDLを書けない、書くスピードが遅くなった • コードを書き始められない…引退が近い??? • そんなときにHLSでCコードを書いてIP実装 • 大幅なスピードアップ • Xilinxさん、Vivado HLS、Vitis HLSを無料にしてくれて本当 にありがとうございます! • Vitis HLS、Vivado HLSは私の救世主(使わなきゃ損です) 18
  • 19.
    カメラを使用した画像認識により 白線間走行及び隊列走行するロ ボットカー • 2016年度の科研費奨励研究 • (課題番号16H00383) •ガボール・フィルタで白線を検出して白線間を走る ロボットカー • 先頭車両のマーカーを検出して隊列走行 19
  • 20.
    ロボットカーの構成 • Zybotのプラットフォームを利用した • Digilent社のZYBOボードを使用した全長30cm程度のロボット カー •プラットフォームは使用しているが、ハード、ソフトとも独自開 発 • ZYBO(旧)ボード • Xilinx社のARMプロセッサ(Cortex-A9デュアル)+FPGAチップ • Zynq-7010 • 2つのCortex-A9(650MHz動作)でUbuntu14.04が動作 • ソフトウェア実装後にハードウェアにオフロードが簡単 に行える 20
  • 21.
  • 22.
    カメラを使用した画像認識により 白線間走行及び隊列走行するロ ボットカーの使用IP • 自作IP(9個) • VivadoHLSで作成したIP(C言語で書いたIP) • モーター用PWM IP • モーター・モニターIP(モーターのパルス数をカウント) • 超音波センサ・インターフェースIP • ガボール・フィルタIP • ガボール・フィルタ用DMAC IP • ラプラシアンフィルタIP • RGB-HSV変換IP • ビットマップ・ディスプレイ・コントローラIP • カメラ・インターフェースIP • https://marsee101.web.fc2.com/white_line_detect.html 22
  • 23.
    白線をガボール・フィルタで検出1 • ガボール・フィルタを使用 • 正弦波とガウス関数の積 •1次元 • 2次元 • ガウス関数の分散(Sigma) • 正弦波の周期(Lambda) • 正弦波の進行方向(角度)(theta) • 正弦波の位相(Psi) 23 X = Sigma=4, Lambda=80, Theta=68, Psi=94 Sigma=4, Lambda=80, Theta=135, Psi=94
  • 24.
    白線をガボール・フィルタで検出2 • 左白線用、右白線用ガボール・フィルタのパラメータを決定 • Sigma,Lambda, Theta, Psi • 日本大学の方のガボール・フィルタの実装を使用した(今Webサイトが無い) • カーネルサイズを21ピクセルから9ピクセルへ変更 • パラメータを使って演算すればn x nの重みを画像に掛け算するのみ 24 • 9 x 9ピクセルの左白線用、右白線用ガボール・フィルタの重みを 取得した • 左白線用、右白線用の2つのパラメータのガボール・フィルタを Vivado HLS でC言語からHDLへ変換してIP化
  • 25.
  • 26.
    ガボール・フィルタIPのソースコード 26 int Gabor_filter_lh(hls::stream<ap_axis<32,1,1,1> >&ins, hls::stream<ap_axis<32,1,1,1> >& outs){ #pragma HLS INTERFACE axis port=ins #pragma HLS INTERFACE axis port=outs #pragma HLS INTERFACE s_axilite port=return ap_axis<32,1,1,1> pix; ap_axis<32,1,1,1> gabor; hls::LineBuffer<ARRAY_SIZE- 1, HORIZONTAL_PIXEL_WIDTH, int> linebuf; hls::Window<ARRAY_SIZE, ARRAY_SIZE, int> mbuf; int gray_pix, val, i, j, x, y; do { // user が 1になった時にフレームがスタートする ins >> pix; } while(pix.user == 0); for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){ for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){ #pragma HLS PIPELINE II=1 if (!(x==0 && y==0)) // 最初の入力はすでに入力されている ins >> pix; // AXI4-Stream からの入力 mbuf.shift_left(); // mbuf の列を1ビット左シフト for(i=ARRAY_SIZE-2; i>=0; --i){ mbuf.insert(linebuf(i,x), i+1, ARRAY_SIZE-1); } gray_pix = conv_rgb2y(pix.data); mbuf.insert(gray_pix, 0, ARRAY_SIZE-1); // LineBuffer の更新 linebuf.shift_down(x); linebuf.insert_bottom(gray_pix, x); // Gabor filter の演算 for (j=0, val=0; j<ARRAY_SIZE-1; j++){ for (i=0; i<ARRAY_SIZE-1; i++){ val += gabor_weight[j][i] * mbuf(ARRAY_SIZE-1-j,i); } } val = val/256; // 256倍してあるので、1/256して戻す if (val<0) //val = -val; // 絶対値 val = 0; // マイナスの値を0に丸める else if (val>255) val = 255; // Gabor filter・データの書き込み gabor.data = (val<<16)+(val<<8)+val; // 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE- 1列は無効データなので0とする if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1)) gabor.data = 0; if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする gabor.user = 1; else gabor.user = 0; if (x == (HORIZONTAL_PIXEL_WIDTH-1)) // 行の最後 で TLAST をアサートする gabor.last = 1; else gabor.last = 0; outs << gabor; // AXI4-Stream へ出力 } } return(0); } https://marsee101.blog.fc2.com/b log-entry-3524.html
  • 27.
  • 28.
  • 29.
    カメラを使用した画像認識により 白線間走行及び隊列走行するロ ボットカーの使用IP • 自作IP(9個) • VivadoHLSで作成したIP(C言語で書いたIP) • モーター用PWM IP • モーター・モニターIP(モーターのパルス数をカウント) • 超音波センサ・インターフェースIP • ガボール・フィルタIP • ガボール・フィルタ用DMAC IP • ラプラシアンフィルタIP • RGB-HSV変換IP • ビットマップ・ディスプレイ・コントローラIP • カメラ・インターフェースIP • https://marsee101.web.fc2.com/zybot.html 29
  • 30.
    隊列走行ロボットカーの追従用 マーカー • HSV でのH(色相)は、0~360 までの円で表される ので、0 と 180 の距離が一番離れている。 • S = V = 255 とすると H = 0 は R=255, G = 0, B = 0 つ まり赤であり、H =180 は R = 0, G = 255, B = 255 の 水色 30 水色の中に赤 RGB画像 HSV変換-S=V=255固定後 RGB変換
  • 31.
    RGB2HSV IPのソースコード(一部) 31 int rgb2hsv(hls::stream<ap_axis<32,1,1,1>>& ins, hls::stream<ap_axis <32,1,1,1> >& outs){ #pragma HLS INTERFACE axis port=outs #pragma HLS INTERFACE axis port=ins ap_axis<32,1,1,1> pix; int r, g, b; int h, s, v; int max, min; int hsv; do{ #pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1 ins >> pix; }while(pix.user == 0); loop_y: for(int y=0; y<VERTICAL_PIXEL_WIDTH; y++){ loop_x: for(int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){ #pragma HLS UNROLL factor=2 #pragma HLS PIPELINE II=1 if(!(x==0 && y==0)) // 最初の入力はすでに入力されている ins >> pix; // AXI4-Stream からの入力 b = pix.data & 0xff; g = (pix.data>>8) & 0xff; r = (pix.data>>16) & 0xff; // h と max, min を求める if(r==g && g==b && r==b){ max = r; // 8倍 min = r; }else if(r>=g && r>=b){ // r が最大 max = r; if(g>=b) min = b; else min = g; }else if(g>=r && g>=b){ // g が最大 max = g; if(r>=b) min = b; else min = r; }else{ // b が最大 max = b; if(r>=g) min = g; else min = r; } if(max-min == 0) h = 0; else if(max == r) h = 60 * (((g-b)<<MAG)/(max-min)); // MAGビットシフトして精 度を確保 else if(max == g) h = 60 * (((b-r)<<MAG)/(max-min)) + (120<<MAG); // MAG ビットシフトして精度を確保 else // if(max == b) h = 60 * (((r-g)<<MAG)/(max-min)) + (240<<MAG); // MAG ビットシフトして精度を確保 if(h < 0) h += 360<<MAG; h += 1<<(MAG-1); // +0.5、四捨五入 https://marsee101.blog.fc2.com/b log-entry-3604.html
  • 32.
  • 33.
  • 34.
  • 35.
    その他の高位合成ツール • インテル® HLSコンパイラーはインテル® Quartus® Prime 開発ソフトウェアのインストールに含まれる • 2017年に試してみたことがある • https://marsee101.web.fc2.com/intel_hls.html • Microchip社のSmartHLS • 2021年12月に試してみた • https://marsee101.web.fc2.com/smarthls.html 35
  • 36.
    まとめ • HLSは老齢エンジニアの救世主、使わなきゃ損 • 若いエンジニアにも時短のメリット •バグが少ない • 実装時間が短い • 作れないIPもあるがHDLで書いちゃえばOK • カメラ・インターフェースIP • ビットマップ・ディスプレイ・コントローラIP • シンクロナイザーIP… • 使い方分からない? • トレーニングで解消 36