FC2カウンター FPGAの部屋 2022年12月30日
fc2ブログ

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

FPGAの部屋

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

AXI4-Stream 32 ビット入出力のガボール・フィルタを変更する2

AXI4-Stream 32 ビット入出力のガボール・フィルタを変更する1”の続き。

Vitis HLS 2022.2 を使用して、AXI4-Stream 32 ビット入出力のガボール・フィルタ Gabor_Filter_lh_2 を Gabor_Filter_lh_3 として作成することにしたということで、前回は、ソースコードを貼って、Vitis HLS 2022.2 の Gabor_Filter_lh_3 プロジェクトを作成した。今回は、C シミュレーションを行って、C コードの合成を行ったところ、Estimated が 10.213 ns と 10 ns をオーバーしてしまったので、 Gabor_Filter_lh_3.cpp を書き換えた。

C シミュレーションを行った。結果を示す。
Zybot2_63_221229.png

Gabor_Filter_lh_3/solution1/csim/build ディレクトリを示す。
???0.bmp が左白線用パラメータのガボール・フィルタ画像で、???0.bmp が右白線パラメータのガボール・フィルタ画像を示す。
Zybot2_64_221229.png

C コードの合成を行ったが、Estimated が 10.213 ns と 10 ns をオーバーしてしまった。
Zybot2_65_221229.png

Estimated は、Uncertainty を大きくしても変わらなかった。
そこで、クリティカル・パスを調査した。
その結果、最後の”('icmp_ln54', Gabor_Filter_lh_3/Gabor_Filter_lh_3.cpp:54) [315] (2.47 ns)”は回避することができそうだ。
Zybot2_66_221230.png

この if 文は画像の最初の user = 1 の時のピクセルはすでに do while() 文で読み込まれているので、最初だけピクセルを読まないようにする文だ。
この文は、最初から user = 1 だったら無くすことができる。その場合は、do while() 文も削除する。
もし最初に user = 1 じゃない場合は、最初に user = 1 になってから受け取るような IP を置いておけば良いはずだ。
その様に改良した Gabor_Filter_lh_3.cpp を示す。

// Gabor_Fiter_lh_3.cpp
// 2016/07/23 by marsee
// 2016/07/25 : 右白線検出用のGabor Filterを追加して、右左の白線を指定するRorL 引数を追加
// 2016/07/27 : 右白線検出用配列と左白線検出用配列を統合
// 2016/08/29 : 1回目左白線検出、2回目右白線検出のモードを追加
// 2022/12/14 : Vitis HLS用に書き直した
// 2022/12/27 : 引数にrow_size, col_size, functionを追加
//              functionの値で元画像をスルーとガボール・フィルタ処理を選択できるようにした
// 2022/12/30 : user=1を待つdo while()文とmain()中のif文を削除した
//

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

#include "Gabor_Filter_lh_3.h"

int conv_rgb2y(int rgb);

int Gabor_Filter_lh_3(hls::stream<ap_axis<32,1,1,1> >& ins,
        hls::stream<ap_axis<32,1,1,1> >& outs, ap_uint<2> & RorL,
        int32_t row_size, int32_t col_size, int32_t function){
#pragma HLS INTERFACE mode=s_axilite port=function
#pragma HLS INTERFACE mode=s_axilite port=col_size
#pragma HLS INTERFACE mode=s_axilite port=row_size
#pragma HLS INTERFACE mode=ap_none port=RorL
#pragma HLS INTERFACE mode=axis register_mode=both port=ins register
#pragma HLS INTERFACE mode=axis register_mode=both port=outs register
#pragma HLS INTERFACE mode=s_axilite port=return

    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> gabor;

    ap_int<32> line_buf[ARRAY_SIZE-1][1920]; // Up to HD resolution
#pragma HLS array_partition variable=line_buf block factor=9 dim=1

    ap_int<32> pix_mat[ARRAY_SIZE][ARRAY_SIZE];
    int gray_pix, val, i, j, x, y, k;

    LOOP_LR: for (k=0; k<2; k++){
        LOOP_Y: for (y=0; y<row_size; y++){
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=48
            LOOP_X: for (x=0; x<col_size; x++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=64
#pragma HLS PIPELINE II=1
                ins >> pix;    // AXI4-Stream からの入力

                LOOP_PIX_MAT_K: for(int k=0; k<ARRAY_SIZE; k++){
                    LOOP_PIX_MAT_M: for(int m=0; m<ARRAY_SIZE-1; m++){
                        pix_mat[k][m] = pix_mat[k][m+1];
                    }
                }
                for (i=0; i<ARRAY_SIZE-1; i++){
                    pix_mat[i][ARRAY_SIZE-1] = line_buf[i][x];
                }
                ap_int<32> y_val = conv_rgb2y(pix.data);
                pix_mat[ARRAY_SIZE-1][ARRAY_SIZE-1] = y_val;

                for (i=0; i<ARRAY_SIZE-2; i++){    // 行の入れ替え
                    line_buf[i][x] = line_buf[i+1][x];
                }
                line_buf[ARRAY_SIZE-2][x] = y_val;

                // 使用する配列を決定する
                int ano;
                switch (RorL){
                case LEFT_WEIGHT :
                    ano = LEFT_WEIGHT;
                    break;
                case RIGHT_WEIGHT :
                    ano = RIGHT_WEIGHT;
                    break;
                case L_R_WEIGHT :
                    if (k == 0)
                        ano = LEFT_WEIGHT;
                    else
                        ano = RIGHT_WEIGHT;
                    break;
                default :
                    ano = L_R_WEIGHT;
                    break;
                }

                // Gabor filter の演算
                for (j=0, val=0; j<ARRAY_SIZE; j++){
                    for (i=0; i<ARRAY_SIZE; i++){
                        val += gabor_weight[ano][j][i] * pix_mat[j][i];
                    }
                }
                val = val/256; // 256倍してあるので、1/256して戻す
                if (val<0)
                    //val = -val; // 絶対値
                    val = 0; // マイナスの値を0に丸める
                else if (val>255)
                    val = 255;

                // Gabor filter・データの書き込み
                if(function == Gabor_Filter)
                    gabor.data = (val<<16)+(val<<8)+val;
                else
                    gabor.data = pix.data;

                // 最初のARRAY_SIZE-1行とその他の行の最初のARRAY_SIZE-1列は無効データなので0とする
                if (x<(ARRAY_SIZE-1) || y<(ARRAY_SIZE-1)){
                    if(function == Gabor_Filter)
                        gabor.data = 0;
                }

                if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
                    gabor.user = 1;
                else
                    gabor.user = 0;

                if (x == (col_size-1))    // 行の最後で TLAST をアサートする
                    gabor.last = 1;
                else
                    gabor.last = 0;

                outs << gabor;    // AXI4-Stream へ出力
             }
         }
    }
     return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8; // 256で割る

    return(y);
}

  1. 2022年12月30日 15:50 |
  2. Vitis HLS
  3. | トラックバック:0
  4. | コメント:0