SSブログ

Vivado HLS を使ってみた(その4) [FPGA]

浮動小数点のままではさすがにでかいし、精度過剰なので固定小数点化します。
#define	fw	12

YCbCr rgb2ycbcr(RGB s)
{
    YCbCr    d;

    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> cY [3] = { 0.2126f,  0.7152f,  0.0722f };
    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> cCb[3] = {-0.1146f, -0.3854f,  0.5000f };
    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> cCr[3] = { 0.5000f, -0.4542f, -0.0458f };
    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> op5    = 0.5f * dat;
    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> llim   = 0.0f;
    const ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> ulim   = (float)(dat-1);

    ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> R,G,B;
    ap_fixed<2+dw+fw, fw, AP_RND_CONV, AP_SAT> Y,Cb,Cr;

    R = s.R;
    G = s.G;
    B = s.B;

    Y  = cY [0] * R + cY [1] * G + cY [2] * B;
    Cb = cCb[0] * R + cCb[1] * G + cCb[2] * B + op5;
    Cr = cCr[0] * R + cCr[1] * G + cCr[2] * B + op5;

    if (Y  < llim) Y  = llim;    if (ulim < Y ) Y  = ulim;
    if (Cb < llim) Cb = llim;    if (ulim < Cb) Cb = ulim;
    if (Cr < llim) Cr = llim;    if (ulim < Cr) Cr = ulim;

    d.Y  = Y;
    d.Cb = Cb;
    d.Cr = Cr;

    return d;
}

「ap_fixed<>」が固定小数点を扱う型です。bit数とか丸めモードとかサチュレーションモードとか設定できるようになってます。今は適当。floatの代わりに置き換えています。
まずはシミュレーション。fw(小数点以下の精度)が8bitぐらいだと明らかにおかしな画になりますが、12bitぐらいだと見た目は大丈夫そうです。出力されたBMPファイルをバイナリ比較すると1bitぐらい違います。

C Synthesisをかけてみます。
レポートファイル。
===============================================================
== Vivado HLS Report for 'rgb2ycbcr'
================================================================
* Date:

* Version:        2013.1
* Project:        rgb2ycbcr
* Solution:       solution1
* Product family: zynq zynq_fpv6 
* Target device:  xc7z020clg484-1


================================================================
== Performance Estimates
================================================================
+ Timing (ns): 
    * Summary: 
    +---------+--------+----------+------------+
    |  Clock  | Target | Estimated| Uncertainty|
    +---------+--------+----------+------------+
    |default  |  100.00|     24.80|       12.50|
    +---------+--------+----------+------------+

+ Latency (clock cycles): 
    * Summary: 
    +-----+-----+-----+-----+---------+
    |  Latency  |  Interval | Pipeline|
    | min | max | min | max |   Type  |
    +-----+-----+-----+-----+---------+
    |    0|    0|    1|    1|   none  |
    +-----+-----+-----+-----+---------+

    + Detail: 
        * Instance: 
        N/A

        * Loop: 
        N/A



================================================================
== Utilization Estimates
================================================================
* Summary: 
+-----------------+---------+-------+--------+-------+
|       Name      | BRAM_18K| DSP48E|   FF   |  LUT  |
+-----------------+---------+-------+--------+-------+
|Expression       |        -|      7|       0|    372|
|FIFO             |        -|      -|       -|      -|
|Instance         |        -|      -|       -|      -|
|Memory           |        -|      -|       -|      -|
|Multiplexer      |        -|      -|       -|      -|
|Register         |        -|      -|       -|      -|
|ShiftMemory      |        -|      -|       -|      -|
+-----------------+---------+-------+--------+-------+
|Total            |        0|      7|       0|    372|
+-----------------+---------+-------+--------+-------+
|Available        |      280|    220|  106400|  53200|
+-----------------+---------+-------+--------+-------+
|Utilization (%)  |        0|      3|       0|   ~0  |
+-----------------+---------+-------+--------+-------+

+ Detail: 
    * Instance: 
    N/A

    * Memory: 
    N/A

    * FIFO: 
    N/A

    * Shift register: 
    N/A

    * Expression: 
    +--------------------------+----------+-------+---+----+------------+------------+
    |       Variable Name      | Operation| DSP48E| FF| LUT| Bitwidth P0| Bitwidth P1|
    +--------------------------+----------+-------+---+----+------------+------------+
    |r_V_13_fu_246_p2          |     *    |      1|  0|   0|          18|           8|
    |r_V_17_fu_342_p2          |     *    |      1|  0|   0|          18|           7|
    |r_V_8_fu_140_p2           |     *    |      1|  0|   0|          18|          10|
    |r_V_9_fu_154_p2           |     *    |      1|  0|   0|          18|           8|
    |r_V_fu_130_p2             |     *    |      1|  0|   0|          18|           7|
    |rhs_V_2_cast_fu_256_p2    |     *    |      1|  0|   0|          18|          10|
    |rhs_V_4_cast_fu_360_p2    |     *    |      1|  0|   0|          18|          10|
    |p_Val2_11_fu_336_p2       |     +    |      0|  0|  18|          18|          18|
    |p_Val2_17_fu_440_p2       |     +    |      0|  0|  18|          18|          18|
    |p_Val2_5_fu_232_p2        |     +    |      0|  0|  18|          18|          18|
    |r_V_10_fu_164_p2          |     +    |      0|  0|  28|          28|          28|
    |r_V_11_fu_174_p2          |     +    |      0|  0|  28|          28|          28|
    |r_V_15_fu_272_p2          |     +    |      0|  0|  28|          28|          28|
    |Cb_V_fu_466_p3            |  Select  |      0|  0|  18|           1|          12|
    |Cr_V_fu_480_p3            |  Select  |      0|  0|  18|           1|          12|
    |Y_V_fu_452_p3             |  Select  |      0|  0|  18|           1|          12|
    |qb_assign_1_fu_222_p2     |    and   |      0|  0|   2|           1|           1|
    |qb_assign_3_fu_326_p2     |    and   |      0|  0|   2|           1|           1|
    |qb_assign_5_fu_430_p2     |    and   |      0|  0|   2|           1|           1|
    |r_1_fu_306_p2             |   icmp   |      0|  0|  10|           9|           1|
    |r_2_fu_410_p2             |   icmp   |      0|  0|  10|           9|           1|
    |r_fu_202_p2               |   icmp   |      0|  0|   2|           1|           1|
    |tmp_2_fu_460_p2           |   icmp   |      0|  0|  22|          18|          12|
    |tmp_4_fu_474_p2           |   icmp   |      0|  0|  22|          18|          12|
    |tmp_9_fu_446_p2           |   icmp   |      0|  0|  22|          18|          12|
    |brmerge_i62_i1_fu_320_p2  |    or    |      0|  0|   2|           1|           1|
    |brmerge_i62_i2_fu_424_p2  |    or    |      0|  0|   2|           1|           1|
    |brmerge_i62_i_fu_216_p2   |    or    |      0|  0|   2|           1|           1|
    |r_V_16_fu_278_p2          |    xor   |      0|  0|  40|          28|          29|
    |r_V_21_fu_382_p2          |    xor   |      0|  0|  40|          28|          29|
    +--------------------------+----------+-------+---+----+------------+------------+
    |Total                     |          |      7|  0| 372|         402|         337|
    +--------------------------+----------+-------+---+----+------------+------------+

    * Multiplexer: 
    N/A

    * Register: 
    N/A



================================================================
== Interface
================================================================
* Summary: 
+------------------------+-----+-----+------------+-----------------+--------------+
|        RTL Ports       | Dir | Bits|  Protocol  |  Source Object  |    C Type    |
+------------------------+-----+-----+------------+-----------------+--------------+
|ap_start                |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_done                 | out |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_idle                 | out |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_ready                | out |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|agg_result_Y_V          | out |    8|   ap_vld   |  agg_result_Y_V |    pointer   |
|agg_result_Y_V_ap_vld   | out |    1|   ap_vld   |  agg_result_Y_V |    pointer   |
|agg_result_Cb_V         | out |    8|   ap_vld   | agg_result_Cb_V |    pointer   |
|agg_result_Cb_V_ap_vld  | out |    1|   ap_vld   | agg_result_Cb_V |    pointer   |
|agg_result_Cr_V         | out |    8|   ap_vld   | agg_result_Cr_V |    pointer   |
|agg_result_Cr_V_ap_vld  | out |    1|   ap_vld   | agg_result_Cr_V |    pointer   |
|s_R_V                   |  in |    8|   ap_none  |      s_R_V      |    scalar    |
|s_G_V                   |  in |    8|   ap_none  |      s_G_V      |    scalar    |
|s_B_V                   |  in |    8|   ap_none  |      s_B_V      |    scalar    |
+------------------------+-----+-----+------------+-----------------+--------------+

データフローとリソース。
Image 015.pngImage 016.png
なんとまあ、組み合わせ回路になってしまいました。そりゃそうか。できたHDLを見てみると、ap_startがap_done,ready、各_ap_vldに直結されてます。

実際このままPlanAheadに放り込んでZynqでインプリしたところ、
   Number of DSP48E1s                        9 out of 220     4%
   Number of External IOBs                  55 out of 200    27%
      Number of LOCed IOBs                   0 out of 55      0%

   Number of Slices                         18 out of 13300   1%
   Number of Slice Registers                 0 out of 106400  0%
      Number used as Flip Flops              0
      Number used as Latches                 0
      Number used as LatchThrus              0

   Number of Slice LUTS                     60 out of 53200   1%
   Number of Slice LUT-Flip Flop pairs      60 out of 53200   1%
DSPリソースがHLSの計算より多い。多分0.5倍が最適化されずに乗算器が実装されたんでしょう。速度は約21[ns]と若干速いですがほぼ予想値通りです。

nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

Facebook コメント

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。