FPGAの部屋 hls::LineBufferとhls::Windowでラプラシアンフィルタを実装する6
FC2ブログ

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

FPGAの部屋

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

hls::LineBufferとhls::Windowでラプラシアンフィルタを実装する6

hls::LineBufferとhls::Windowでラプラシアンフィルタを実装する5”の続き。

前回は、単純にmemcpy() を内側の for ループの外に於いた実装を試した。今回は memcpy() の代わりに for 文で1行分 Read, Write を行う実装を試してみた。

下に今回の lap_filter_axim() のみのC++ソースコードを示す。

int lap_filter_axim(volatile int *cam_fb, volatile int *lap_fb)
{
#pragma HLS INTERFACE s_axilite port=return

#pragma HLS INTERFACE m_axi depth=3072 port=cam_fb offset=slave bundle=cam_fb
#pragma HLS INTERFACE m_axi depth=3072 port=lap_fb offset=slave bundle=lap_fb

    hls::LineBuffer<2, HORIZONTAL_PIXEL_WIDTH, int> linebuf;
    hls::Window<33int> mbuf;
    int x, y;
    int val;
    int gray_pix;
    int i, j;
    const int lap_weight[3][3] = {{-1, -1, -1},{-18, -1},{-1, -1, -1}};
#pragma HLS ARRAY_PARTITION variable=lap_weight complete dim=0
    int read_line[HORIZONTAL_PIXEL_WIDTH];
    int write_line[HORIZONTAL_PIXEL_WIDTH];

    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        for(i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
            read_line[i] = cam_fb[y*(HORIZONTAL_PIXEL_WIDTH)+i];
        }
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            mbuf.shift_left();  // mbuf の列を1ビット左シフト
            //mbuf.insert_left(colbuf); // mbuf の列に colbuf[] を代入
            mbuf.insert(linebuf(1,x), 22);
            mbuf.insert(linebuf(0,x), 12);
            gray_pix = conv_rgb2y(read_line[x]);
            mbuf.insert(gray_pix, 02);

            // LineBuffer の更新
            linebuf.shift_down(x);
            linebuf.insert_bottom(gray_pix, x);

            // ラプラシアンフィルタの演算
            for (j=0, val=0; j<3; j++){
                for (i=0; i<3; i++){
                    val += lap_weight[j][i] * mbuf(2-j,i);
                }
            }
            if (val<0// 飽和演算
                val = 0;
            else if (val>255)
                val = 255;

            // ラプラシアンフィルタ・データの書き込み
            if (x>1 && y>1)
                write_line[x] = (val<<16)+(val<<8)+val ;
            else
                // x<2 || y<2 の場合はピクセルデータがまだ揃っていないので0にする
                write_line[x] = 0;
            // printf("x = %d  y = %d", x, y);
        }
        for (i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
            lap_fb[y*(HORIZONTAL_PIXEL_WIDTH)+i] = write_line[i];
        }
     }
     return(0);
}


これをC++コードの合成を行った。結果を下に示す。
LineBuffer_Window_65_160322.png

LineBuffer_Window_66_160322.png
Latency は 255745 クロックだった。リソースもほとんど前回と変化は無い。

Analysis 表示にしてみた。
LineBuffer_Window_67_160322.png
C21 ステートまでだった。

リソース表示にしてみた。
LineBuffer_Window_68_160322.png

C/RTL コシミュレーションを行った。
LineBuffer_Window_69_160322.png

C/RTL コシミュレーション波形を示す。
LineBuffer_Window_70_160322.png
2.56 ms かかっていた。

LineBuffer_Window_71_160322.png
Read 間隔は 58.41 us だったが、どうも RREADY や WVALID, WREADY の波形がおかしい?

もっと拡大してみた。
LineBuffer_Window_72_160322.png
それらの信号はアサート、ディアサートを繰り返している。なんでそうなるのだろうか?

次に、行の処理を行う内側の for ループと 1行Read するための for ループ、1 行Write するための for ループにPIPELINE II=1 ディレクティブを挿入した。
LineBuffer_Window_73_160322.png 

これで をC++コードの合成を行った。結果を下に示す。
LineBuffer_Window_74_160322.png 
Latency は 10513 クロックになった。

LineBuffer_Window_75_160322.png 
これは、前回の行の処理を行う内側の for ループにPIPELINE II=1 ディレクティブを挿入した場合と同じ回路だった。

Analysis 表示にしてみた。
LineBuffer_Window_76_160322.png
やはり、C22 ステートまでだった。

リソース表示にしてみた。
LineBuffer_Window_77_160322.png

C/RTL コシミュレーションを行った。
LineBuffer_Window_78_160322.png
Latencyは 11203 クロックだった。高位合成時よりも、それほど増えていない。

C/RTL コシミュレーション波形を示す。
LineBuffer_Window_79_160322.png
終了までに 113 us 程度になった。

LineBuffer_Window_80_160322.png
Read 間隔は、 2.33 us だった。これで、行の 64 ピクセルの処理を行っているので、800 x 600 ピクセルの時はどのくらいの時間で処理できるか?計算してみよう。2.33 us / 64 ピクセル x 800 x 600 = 17.4 ms となった。

最後に、今まで挿入したPIPELINE ディレクティブを削除して、一番外側のループにPIPELINE ディレクティブを入れてみた。
LineBuffer_Window_81_160322.png

をC++コードの合成を行った。結果を下に示す。
LineBuffer_Window_82_160322.png
Latency は 6114 クロックになった。

LineBuffer_Window_83_160322.png
使用リソースは、LUT がオーバーフローしている。。。

Analysis 表示を示す。
LineBuffer_Window_84_160322.png
C144 までだった。たくさんステートがある。

リソース表示にした。
LineBuffer_Window_85_160322.png

C/RTL コシミュレーションを行った。
LineBuffer_Window_86_160322.png
Latency は 14263 クロックだった。高位合成の見積からはだいぶ増えていた。

C/RTL コシミュレーション波形を示す。
LineBuffer_Window_87_160322.png

拡大してみると、なんとシングル転送だった。この実装はリソースのLUTがFPGAに内蔵される個数を超えているので、ダメなのだが、動作の点からもあまり良くないようだ。
LineBuffer_Window_88_160322.png
  1. 2016年03月22日 05:24 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/3425-db2fc97b
この記事にトラックバックする(FC2ブログユーザー)