FC2カウンター FPGAの部屋 Vivado HLS によるアンシャープマスクキング・フィルタの作製9(C++ の任意精度固定小数点型3)

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

FPGAの部屋

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

Vivado HLS によるアンシャープマスクキング・フィルタの作製9(C++ の任意精度固定小数点型3)

Vivado HLS によるアンシャープマスクキング・フィルタの作製8(C++ の任意精度固定小数点型2)”の続き。

前回、int 型で予め左シフトして小数を整数にして演算するよりも、固定小数点型にしたほうが、LUT 使用量は減ったが、FF 使用量は増えた。

今回は、固定小数点型で更にリソース使用量の削減、レイテンシの削減を図る。使用しているのは Vivado HLS 2014.4 。
(2015/10/13:C++ソースコードが間違っていたので、修正した)

まずは、”Vivado Design Suite ユーザー ガイド 高位合成 UG902 (v2015.1) 2015 年 4 月 1 日”の550ページ ” C++ の任意精度固定小数点型”を読むと、固定小数点型のデフォルトの量子化モードは AP_TRN、デフォルトのオーバーフロー・モードは AP_WRAP に指定されている。
量子化モードの AP_TRN は切り捨てで、オーバーフロー・モードの AP_WRAP は折り返しと、後での演算が必要無いモードになっている気がする。
今の固定小数点のモードは、量子化モードは AP_RND で、正の無限大への丸め、オーバーフロー・モードは AP_SAT で飽和にしている。これを本当に飽和演算の必要な z 以外はデフォルトにすることにした。
更に、z を飽和演算は必要なので、オーバーフロー・モードは AP_SAT の飽和だが、量子化モードを AP_TRN にしてみる。

これで、C から HDL への合成を行った。結果を下に示す。
unsharp_mask_51_151010.png

unsharp_mask_52_151010.png
FF 使用量は 1997 個だった。LUT 使用量は 1993 個だった。”Vivado HLS によるアンシャープマスクキング・フィルタの作製8(C++ の任意精度固定小数点型2)”の時の、FF 使用量が 2304 個、LUT 使用量が 2835 個の時よりも少なくなっている。

Analysis 結果を示す。
unsharp_mask_53_151010.png

unsharp_mask_54_151010.png
36 ステートだった。

順番が逆になったが、Cシミュレーションを行った。
unsharp_mask_55_151010.png
誤差が大きくなってしまった。

次に z の量子化モードを AP_RND に戻す。
これで、Cシミュレーションを行った。
unsharp_mask_56_151010.png
問題ないようだ。

C から HDL への合成を行った。
unsharp_mask_57_151010.png

unsharp_mask_58_151010.png
FF 使用量は 1966 個、LUT 使用量は 2131 個で、 z の量子化モードが AP_TRN の場合ののリソース使用量よりも増えている。

Analysis 結果を示す。
unsharp_mask_59_151010.png

unsharp_mask_60_151010.png
36 ステートだった。 z の量子化モードが AP_TRN の場合と同じだ。

ほとんどの固定小数点型の数はオーバーフローしないようにビット長を決定しているので、量子化モードやオーバーフロー・モードは関係ないので、演算が軽いデフォルトで使用する。最後に飽和演算が必要な場合にだけ、必要な量子化モードとオーバーフロー・モードを設定したほうが良いと思う。

最後に、unsharp_masking() を示す。

// アンシャープマスキング・フィルタ
// x0y0 x1y0 x2y0 -k   -j  -k
// x0y1 x1y1 x2y1 -k  9+8k -k x 1/9
// x0y2 x1y2 x2y2 -k   -k  -k
//
// k : 鮮鋭化の強さ(固定小数点) , k != 0
// num_adec_k : Kの小数点の位置
//

int unsharp_masking(int pix_mat[3][3], k_fixed_td k_fixed)
{
    ap_ufixed<88> xy[3][3];
    int result=0;
    ap_ufixed<88, AP_RND, AP_SAT> z;
    x1y1_fixed_td x1y1;
    y_fixed_td y;
    
    x1y1 = (x1y1_fixed_td)9/(x1y1_fixed_td)k_fixed + (x1y1_fixed_td)8// ビット長は 9+8 が2^5=32 より小さく、k_fixedで割るので、NUM_ADC_Kが増える可能性がある

    for (int i=0; i<=16; i += 8){
        for (int j=0; j<3; j++){
            for (int k=0; k<3; k++){
                xy[j][k] = (pix_mat[j][k] >> i) & 0xff; // RGBのいずれかを抽出
            }
        }

        y = -xy[0][0]    -xy[0][1]        -xy[0][2]
            -xy[1][0]    +x1y1*xy[1][1]    -xy[1][2]
            -xy[2][0]    -xy[2][1]        -xy[2][2];

        y = (k_fixed * y)/(y_fixed_td)9;

        y = y+(y_fixed_td)0.5// 四捨五入
        if (y < 0)
            z = 0;
        else if (y > 255)
            z = 255;
        else
            z = y;

        result += z.to_int()<<i; // i=0 : blue, i=8 : green, i=16 : red
    }
    return(result);
}


次に、unsharp_mask_axis.h を下に示す。

// unsharp_mask_axis.h
// 2015/09/26 by marsee

#ifndef __UNSHARP_MASK_AXIS_H_
#define __UNSHARP_MASK_AXIS_H_

//#define HORIZONTAL_PIXEL_WIDTH    1280
//#define VERTICAL_PIXEL_WIDTH    720

#define HORIZONTAL_PIXEL_WIDTH    64
#define VERTICAL_PIXEL_WIDTH    48

#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

#define PRECISION    6    // 小数点以下の桁数、精度(0 以上の数を指定する)
#define K_BITLEN    4    // k のビット長
#define NUM_ADC_K    2    // k の小数点の位置

typedef ap_ufixed<K_BITLEN, K_BITLEN-NUM_ADC_K> k_fixed_td;
typedef ap_fixed<6+PRECISION+NUM_ADC_K, (6+PRECISION+NUM_ADC_K)-PRECISION> x1y1_fixed_td;
typedef ap_fixed<6+PRECISION+NUM_ADC_K+8+3, (6+PRECISION+NUM_ADC_K+8+3)-PRECISION> y_fixed_td;

#endif

  1. 2015年10月10日 05:32 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3271-c052e41d
この記事にトラックバックする(FC2ブログユーザー)