FC2カウンター FPGAの部屋 2018年02月07日
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

これから作る畳み込みニューラルネットワークについての目標2

これから作る畳み込みニューラルネットワークについての目標”の続き。

AXI4-Stream 対応のラプラシアンフィルタの様に畳み込みニューラルネットワークを作る予定だ。
畳み込み層はそのままフィルタなので、ラプラシアンフィルタなどの構造を元に作ることができると思う。
それに各層、畳み込み層やReLU、マックス・プーリング層、全結合層などをAXI4-Stream インターフェースで接続されるIPとしてVivado のIP インテグレータで接続すればよいのではないだろうか?もし、1 個のFPGA でロジックが足りなければ、AXI4-Stream インターフェースを外に出して他のFPGA に接続すれば良いのでは?と思う。

つまりこんなイメージだ。
AXI4-Stream_CNN_1_180207.png

ストリーム・データをIP を接続して処理させるのはFPGAの得意とするところだし、一番利点が生きる構成だ。これを使わない手は無いと思う。当然複雑なCNN はFPGAのリソースが足りなくてできないのだが、今度はストリームされる画像データ分だけの演算器があれば良いし、(1 クロックで処理できるとしてだが。。。)何とかなるだろう?

2つ目の全結合層では、1つ目の全結合層の演算がすべて終わるまで 1 個のデータも入ってこない。そこがボトルネックだが仕方がない。そので1フレームずれるのは仕方がないか。。。
  1. 2018年02月07日 21:07 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Vivado HLSで関数内のBRAMを関数外から制御する1

この前、Vivado HLS 勉強会で一緒だった学生さんからVivado HLSの関数内で宣言したBRAM を外から読み書きしたいのだけど、どう書いたら良いか?という質問があったので、サンプルコードを書いてみた。

bram_test1.cpp を示す。

// bram_test1.cpp
// 2018/02/06 by marsee
//

int bram_test(int &index, int &wr, int &data){
#pragma HLS INTERFACE s_axilite port=data
#pragma HLS INTERFACE s_axilite port=wr
#pragma HLS INTERFACE s_axilite port=index
#pragma HLS INTERFACE s_axilite port=return
    int array[1024];

    if(wr == 0){ // Read
        data = array[index];
    }else// Write
        array[index] = data;
    }

    return(0);
}


テストベンチの bram_test1_tb.cpp を示す。Read してWrite してRead というだけの単純なテストベンチだ。

// bram_test1_tb.cpp
// 2018/02/06 by marsee
//

#include <stdio.h>

int bram_test(int &index, int &wr, int &data);

int main(){
    int index, wr, data;

    wr = 0; index = 0;
    bram_test(index, wr, data);
    printf("data = %x\n", data);

    wr = 1; index = 0; data = 0x1;
    bram_test(index, wr, data);

    wr = 0; index = 0;
    bram_test(index, wr, data);
    printf("data = %x\n", data);

    wr = 0; index = 1;
    bram_test(index, wr, data);
    printf("data = %x\n", data);

    wr = 1; index = 1; data = 0x2;
    bram_test(index, wr, data);

    wr = 0; index = 1;
    bram_test(index, wr, data);
    printf("data = %x\n", data);

    return(0);
}


Vivado HLS 2017.4 で bram_test1 というプロジェクトを作成した。ターゲットはZYBO Z7-20 だ。
bram_test_1_180207.png

C シミュレーションを行った。配列のイニシャライズはされていないが、書き込んだ後は同じ値が読めている。
bram_test_2_180207.png

C コードの合成を行った。結果を示す。
bram_test_3_180207.png

BRAM_18K の使用量は 0 個だった。BRAM が実装されていない。
やはり、これは、C 言語では、関数内の宣言したローカル変数の配列はスタック領域にマップされて、関数から戻るときはクリアされる仕様が問題なんじゃないかな?ということで、static を配列の宣言に追加することにした。こうすれば、関数を抜けても配列は保持される。
bram_test_4_180207.png

// bram_test1.cpp
// 2018/02/06 by marsee
//

int bram_test(int &index, int &wr, int &data){
#pragma HLS INTERFACE s_axilite port=data
#pragma HLS INTERFACE s_axilite port=wr
#pragma HLS INTERFACE s_axilite port=index
#pragma HLS INTERFACE s_axilite port=return
    static int array[1024];

    if(wr == 0){ // Read
        data = array[index];
    }else// Write
        array[index] = data;
    }

    return(0);
}


これで、C シミュレーションを行った。結果を示す。
bram_test_5_180207.png

今度は配列がイニシャライズされていた。Read、Write も問題ない。

C コードの合成を行った。結果を示す。
bram_test_6_180207.png

BRAM_18K が 2 個実装されている。良さそうだ。

C/RTL 協調シミュレーションを行うと、終わらなかった。
なので、テストベンチをRead、Write 1 個のみにして、C/RTL 協調シミュレーションを行った。
bram_test_7_180207.png

でもやはり、終わらない。
bram_test_8_180207.png

途中で止めて波形を見てみよう。C/RTL 協調シミュレーションの波形を拡大してみてみよう。まずは、WVALID などのWrite の信号が表示されていない。これは、途中でC/RTL 協調シミュレーションを止めてしまったからなのか?
bram_test_14_180207.png

それじゃ、AXI4 Lite Slave インターフェースの予定だが、デフォルトでやってみよう。AXI4 Lite のインターフェースの指示子を取ってしまった。
bram_test_9_180207.png

これで、C コードの合成を行った。結果を示す。
bram_test_10_180207.png

FF、LUT は使用量が少なくなったが、BRAM_18K は 2 個使用されていて問題ないようだ。

C/RTL 協調シミュレーションを行った。結果を示す。
bram_test_11_180207.png

正常終了している。やはり、AXI4 Lite インターフェースの時だけおかしいのかな?

C/RTL 協調シミュレーションの波形を示す。
bram_test_12_180207.png

正常にアクセスできているようだ。

このまま、Export RTL を行った。結果を示す。
なお、Vivado synthesis, place and route にチェックを入れてある。
bram_test_13_180207.png

BRAM も 2 個使われていて、問題なさそうだ。
  1. 2018年02月07日 05:06 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0