SSブログ

Vivado HLS を使ってみた。第一回まとめ [FPGA]

今回のRGB→YCbCr変換、最適化はもっとかけられます。変換に3x3のマトリクス演算を行っていますが、ホントは必要ありません。Yの係数を全部足すと1.0になるという条件と、(B-Y)、(R-Y)の形に式を変えると、乗算器は4つで済みます。実際XilinxのIPなどはそうやって作られてます。IPの資料を見ると詳しく載ってます。C側の計算を変える事になりますが、HDLでがんばるより楽でしょう。
実際に使えるようなIPを作ることを目的にしていないので、一番シンプルな計算式を持ってきています。


ということで、簡単なプログラムを対象に、C to HDLをやってみました。

…やべぇ…前からかかってた「HDLなんかもう一行も書きたくないよ~」病に拍車をかける結果となりました…
実はAlteraのC2Hを使った時も同じ事を思ったんですが(笑)
最近(Qsysになってから)C2Hのアップデートが聞こえてきませんね?どうしたのかな?
今回の例は簡単なのでHDLで書いてもたかがしれてますが、ちょっと複雑な処理が入ったらもうHDLなんかやりたくないです。

本当はもっと色々なディレクティブが必要になります、I/Oにも設定が必要です、使えるCの構文にも制限があります、純粋にソフトウェア的な書き方だけでは最適化は難しいかも、思った通りの回路にはなかなかならない場合もある、などなど考慮する点はたくさんあります。

でもCで記述して、誤差とか精度とか詰めて、ソースの最適化かけたときもCのシミュレーションで確認、シミュレーションでOKだったらディレクティブとかいじって最適化、HDLを全く見ずにハードウェア完成。コンパイルも実行時間もHDLより遙かに速いので効率も良いです。これは癖になります。

HLSの新しいバージョンではAXI関連が有効になってます。今回のもAXI Streamにするとほかとの接続が良くなります。XPSへのエクスポートもあるので、Cで作ったモジュールを自動でZynqのAXIチャンネルに接続することもできます。ここでもHDLを排除できます。
AlteraもQsys、SOPC Builderで同様なことが可能です。というかこの辺昔からAlteraの方が強いです。AXIではなくAvalonという独自の接続形態でしたが、非常に便利です。やっとXilinxも追いついてきたという感じがします。
AXI対応はXilinxの方が先行ですかね。AXIは一種の流行なので、特にこだわる理由は無いと思いますが。

なにも書かずにものができあがる、AlteraもXilinxも、多分ほかのベンダーも、みんな目指してるところでしょう。
今はその中間解として、システム自動作成ツール(Qsys、XPS、+IP群)+C系合成ツール(C2H、HLS)+CPU(ARM、Nios、MB)+モデル設計ツール(DSP Builder、SystGen)というところに落ち着いてる感じでしょうか。バラバラなのが難点ですが適材適所で行くしか無いのが現状でしょう。もちろんHDLで書いた方が効率よい部分もあるので、しばらくはごちゃ混ぜ状態が続きそうです。

それにしてもやばい。結構できが良いので本気でHDL書きたくない気分になってます…ライセンス約50万でしたっけ…?う~む…
まぁそんなこと言いながらHDLは書くんですけどね(笑)
※DigiKeyとかで見てみたら、HLS単体だとFloatingでも25万ぐらいでした…うぅう~むぅ…

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

リアルタイムでFullHD 1080p60ぐらいは処理して欲しいですよね。
ソースは(その5)のintバージョン。

1080pで148.5MHzなので、ソリューションの周波数を150MHzにしてみます。
Image 019.png
MHzを付けると周波数と認識されるようです。
これで合成すると…(レポートファイル)
================================================================
== 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  |   6.67|      5.47|        0.83|
    +---------+-------+----------+------------+

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

    + Detail: 
        * Instance: 
        N/A

        * Loop: 
        N/A



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

+ Detail: 
    * Instance: 
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |            Instance            |            Module           | BRAM_18K| DSP48E| FF | LUT|
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |rgb2ycbcr_mul_8ns_10ns_18_3_U1  |rgb2ycbcr_mul_8ns_10ns_18_3  |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_10s_19_3_U5   |rgb2ycbcr_mul_8ns_10s_19_3   |        0|      1|   0|   0|
    |rgb2ycbcr_mul_8ns_12ns_20_3_U7  |rgb2ycbcr_mul_8ns_12ns_20_3  |        0|      1|   0|   0|
    |rgb2ycbcr_mul_8ns_12s_20_3_U3   |rgb2ycbcr_mul_8ns_12s_20_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_12s_20_3_U4   |rgb2ycbcr_mul_8ns_12s_20_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_9ns_17_3_U2   |rgb2ycbcr_mul_8ns_9ns_17_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_9s_18_3_U6    |rgb2ycbcr_mul_8ns_9s_18_3    |        0|      1|   0|   0|
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |Total                           |                             |        0|      7|  72|  20|
    +--------------------------------+-----------------------------+---------+-------+----+----+

    * Memory: 
    N/A

    * FIFO: 
    N/A

    * Shift register: 
    N/A

    * Expression: 
    +--------------------+----------+-------+---+----+------------+------------+
    |    Variable Name   | Operation| DSP48E| FF| LUT| Bitwidth P0| Bitwidth P1|
    +--------------------+----------+-------+---+----+------------+------------+
    |tmp1_fu_171_p2      |     +    |      0|  0|  19|          19|          19|
    |tmp_10_fu_272_p2    |     +    |      0|  0|  21|          21|          21|
    |tmp_5_fu_236_p2     |     +    |      0|  0|  21|          21|          21|
    |p_neg1_fu_320_p2    |     -    |      0|  0|  21|           1|          21|
    |p_neg5_fu_295_p2    |     -    |      0|  0|  21|           1|          21|
    |p_neg_t1_fu_339_p2  |     -    |      0|  0|  10|           1|          10|
    |p_neg_t7_fu_314_p2  |     -    |      0|  0|  10|           1|          10|
    |Cb_fu_373_p3        |  Select  |      0|  0|  10|           1|           1|
    |Cr_fu_396_p3        |  Select  |      0|  0|  10|           1|           1|
    |agg_result_Cb_V     |  Select  |      0|  0|   8|           1|           2|
    |agg_result_Cr_V     |  Select  |      0|  0|   8|           1|           2|
    |tmp_13_fu_367_p3    |  Select  |      0|  0|  10|           1|          10|
    |tmp_s_fu_358_p3     |  Select  |      0|  0|  10|           1|          10|
    |icmp1_fu_413_p2     |   icmp   |      0|  0|   2|           2|           1|
    |icmp_fu_390_p2      |   icmp   |      0|  0|   2|           2|           1|
    |tmp_14_fu_345_p2    |   icmp   |      0|  0|  26|          21|          13|
    |tmp_15_fu_350_p2    |   icmp   |      0|  0|  26|          21|          13|
    +--------------------+----------+-------+---+----+------------+------------+
    |Total               |          |      0|  0| 235|         117|         177|
    +--------------------+----------+-------+---+----+------------+------------+

    * Multiplexer: 
    N/A

    * Register: 
    +---------------------+----+-----+-----------+
    |         Name        | FF | Bits| Const Bits|
    +---------------------+----+-----+-----------+
    |G_cast_reg_462       |   8|   20|         12|
    |ap_CS_fsm            |   3|    3|          0|
    |p_neg_t1_reg_556     |  10|   10|          0|
    |p_neg_t7_reg_551     |  10|   10|          0|
    |tmp1_reg_504         |  19|   19|          0|
    |tmp3_cast_reg_509    |  21|   21|          0|
    |tmp5_cast_reg_514    |  21|   21|          0|
    |tmp_10_reg_535       |  21|   21|          0|
    |tmp_11_cast_reg_499  |  20|   20|          0|
    |tmp_11_reg_530       |   9|    9|          0|
    |tmp_12_reg_541       |   1|    1|          0|
    |tmp_14_reg_561       |   1|    1|          0|
    |tmp_15_reg_566       |   1|    1|          0|
    |tmp_17_reg_546       |   9|    9|          0|
    |tmp_2_reg_489        |  17|   17|          0|
    |tmp_4_reg_525        |   1|    1|          0|
    |tmp_5_reg_519        |  21|   21|          0|
    |tmp_7_cast_reg_494   |  20|   20|          0|
    |tmp_reg_484          |  18|   18|          0|
    +---------------------+----+-----+-----------+
    |Total                | 231|  243|         12|
    +---------------------+----+-----+-----------+



================================================================
== Interface
================================================================
* Summary: 
+------------------------+-----+-----+------------+-----------------+--------------+
|        RTL Ports       | Dir | Bits|  Protocol  |  Source Object  |    C Type    |
+------------------------+-----+-----+------------+-----------------+--------------+
|ap_clk                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_rst                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|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    |
+------------------------+-----+-----+------------+-----------------+--------------+
7クロックに1演算という回路になりました。今回はap_start,ap_doneなどが制御信号として働きます。ap_startで演算開始、ap_doneで計算結果が得られる、という制御になります。

1クロックに1つ答えが得られない困るので、ディレクティブ(指示子)を与えます。おぉ、やっと機種依存するところが出てきた(笑)
「Directive」タブを開き、関数(rgb2ycbcr)を右クリックします。
Image 020.png
ディレクティブの選択画面が出るので「PIPELINE」を選択します。「Source File」を選ぶと「#pragma HLS PIPELINE」がcppソースに埋め込まれます。「Directive File」を選ぶとディレクティブの別のファイルに保存されます。どちらでも効能は同じ。好みの方にします。
Image 021.pngImage 022.png
「Directive File」を選んだ場合。ディレクティブのタブに新しく「HLS_PIPELINE」が追加されます。
Image 023.png

これで合成開始。
================================================================
== 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  |   6.67|      5.47|        0.83|
    +---------+-------+----------+------------+

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

    + Detail: 
        * Instance: 
        N/A

        * Loop: 
        N/A



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

+ Detail: 
    * Instance: 
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |            Instance            |            Module           | BRAM_18K| DSP48E| FF | LUT|
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |rgb2ycbcr_mul_8ns_10ns_18_3_U1  |rgb2ycbcr_mul_8ns_10ns_18_3  |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_10s_19_3_U5   |rgb2ycbcr_mul_8ns_10s_19_3   |        0|      1|   0|   0|
    |rgb2ycbcr_mul_8ns_12ns_20_3_U7  |rgb2ycbcr_mul_8ns_12ns_20_3  |        0|      1|   0|   0|
    |rgb2ycbcr_mul_8ns_12s_20_3_U3   |rgb2ycbcr_mul_8ns_12s_20_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_12s_20_3_U4   |rgb2ycbcr_mul_8ns_12s_20_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_9ns_17_3_U2   |rgb2ycbcr_mul_8ns_9ns_17_3   |        0|      1|  18|   5|
    |rgb2ycbcr_mul_8ns_9s_18_3_U6    |rgb2ycbcr_mul_8ns_9s_18_3    |        0|      1|   0|   0|
    +--------------------------------+-----------------------------+---------+-------+----+----+
    |Total                           |                             |        0|      7|  72|  20|
    +--------------------------------+-----------------------------+---------+-------+----+----+

    * Memory: 
    N/A

    * FIFO: 
    N/A

    * Shift register: 
    +--------------------+---+----+-----+-----------+
    |        Name        | FF| LUT| Bits| Const Bits|
    +--------------------+---+----+-----+-----------+
    |G_cast_reg_467      |  0|   8|   20|         12|
    |s_B_V_read_reg_450  |  0|   8|    8|          0|
    |s_R_V_read_reg_456  |  0|   8|    8|          0|
    +--------------------+---+----+-----+-----------+
    |Total               |  0|  24|   36|         12|
    +--------------------+---+----+-----+-----------+

    * Expression: 
    +--------------------+----------+-------+---+----+------------+------------+
    |    Variable Name   | Operation| DSP48E| FF| LUT| Bitwidth P0| Bitwidth P1|
    +--------------------+----------+-------+---+----+------------+------------+
    |tmp1_fu_177_p2      |     +    |      0|  0|  19|          19|          19|
    |tmp_10_fu_277_p2    |     +    |      0|  0|  21|          21|          21|
    |tmp_5_fu_241_p2     |     +    |      0|  0|  21|          21|          21|
    |p_neg1_fu_325_p2    |     -    |      0|  0|  21|           1|          21|
    |p_neg5_fu_300_p2    |     -    |      0|  0|  21|           1|          21|
    |p_neg_t1_fu_344_p2  |     -    |      0|  0|  10|           1|          10|
    |p_neg_t7_fu_319_p2  |     -    |      0|  0|  10|           1|          10|
    |Cb_fu_378_p3        |  Select  |      0|  0|  10|           1|           1|
    |Cr_fu_401_p3        |  Select  |      0|  0|  10|           1|           1|
    |agg_result_Cb_V     |  Select  |      0|  0|   8|           1|           2|
    |agg_result_Cr_V     |  Select  |      0|  0|   8|           1|           2|
    |tmp_13_fu_372_p3    |  Select  |      0|  0|  10|           1|          10|
    |tmp_s_fu_363_p3     |  Select  |      0|  0|  10|           1|          10|
    |icmp1_fu_418_p2     |   icmp   |      0|  0|   2|           2|           1|
    |icmp_fu_395_p2      |   icmp   |      0|  0|   2|           2|           1|
    |tmp_14_fu_350_p2    |   icmp   |      0|  0|  26|          21|          13|
    |tmp_15_fu_355_p2    |   icmp   |      0|  0|  26|          21|          13|
    +--------------------+----------+-------+---+----+------------+------------+
    |Total               |          |      0|  0| 235|         117|         177|
    +--------------------+----------+-------+---+----+------------+------------+

    * Multiplexer: 
    N/A

    * Register: 
    +-------------------------------------+----+-----+-----------+
    |                 Name                | FF | Bits| Const Bits|
    +-------------------------------------+----+-----+-----------+
    |G_cast_reg_467                       |   8|   20|         12|
    |Y_reg_524                            |   8|    8|          0|
    |ap_CS_fsm                            |   1|    1|          0|
    |ap_reg_ppiten_pp0_it1                |   1|    1|          0|
    |ap_reg_ppiten_pp0_it2                |   1|    1|          0|
    |ap_reg_ppiten_pp0_it3                |   1|    1|          0|
    |ap_reg_ppiten_pp0_it4                |   1|    1|          0|
    |ap_reg_ppiten_pp0_it5                |   1|    1|          0|
    |ap_reg_ppiten_pp0_it6                |   1|    1|          0|
    |ap_reg_ppstg_Y_reg_524_pp0_it5       |   8|    8|          0|
    |ap_reg_ppstg_tmp_11_reg_540_pp0_it5  |   9|    9|          0|
    |ap_reg_ppstg_tmp_12_reg_551_pp0_it5  |   1|    1|          0|
    |ap_reg_ppstg_tmp_17_reg_556_pp0_it5  |   9|    9|          0|
    |ap_reg_ppstg_tmp_4_reg_535_pp0_it5   |   1|    1|          0|
    |p_neg_t1_reg_566                     |  10|   10|          0|
    |p_neg_t7_reg_561                     |  10|   10|          0|
    |s_B_V_read_reg_450                   |   8|    8|          0|
    |s_R_V_read_reg_456                   |   8|    8|          0|
    |tmp1_reg_509                         |  19|   19|          0|
    |tmp3_cast_reg_514                    |  21|   21|          0|
    |tmp5_cast_reg_519                    |  21|   21|          0|
    |tmp_10_reg_545                       |  21|   21|          0|
    |tmp_11_cast_reg_504                  |  20|   20|          0|
    |tmp_11_reg_540                       |   9|    9|          0|
    |tmp_12_reg_551                       |   1|    1|          0|
    |tmp_14_reg_571                       |   1|    1|          0|
    |tmp_15_reg_576                       |   1|    1|          0|
    |tmp_17_reg_556                       |   9|    9|          0|
    |tmp_2_reg_494                        |  17|   17|          0|
    |tmp_4_reg_535                        |   1|    1|          0|
    |tmp_5_reg_529                        |  21|   21|          0|
    |tmp_7_cast_reg_499                   |  20|   20|          0|
    |tmp_reg_489                          |  18|   18|          0|
    +-------------------------------------+----+-----+-----------+
    |Total                                | 287|  299|         12|
    +-------------------------------------+----+-----+-----------+



================================================================
== Interface
================================================================
* Summary: 
+------------------------+-----+-----+------------+-----------------+--------------+
|        RTL Ports       | Dir | Bits|  Protocol  |  Source Object  |    C Type    |
+------------------------+-----+-----+------------+-----------------+--------------+
|ap_clk                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_rst                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|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 024.pngImage 025.png
パイプライン化され、1クロックで1個結果が出てくるようになりました。予想周波数は5.47[ns](約182MHz)。

この辺でいい加減一度ぐらいHDLシミュレーションしておかないと…いままでCのシミュレーションが楽で楽で…改めて思う…HDLのテストベンチってめんどくさい…

中身はほぼ同じで、BMPファイルを流し込んで結果を保存します。ただ、色々書くのが面倒なので、BGRをCbYCrに置き換えたBMPファイルだけ作成します。
ちなみにI/Oピンの情報はレポートファイルの一番下に書かれています。細かい制御方法はXilinxの資料にゆずりますが、今回はI/Oになにも指定していないので、関数の返値(YCbCr)に「ap_ctrl_hs」が、引数(RGB)に「ap_none」が設定されています。Y,Cb,Crそれぞれに「_ap_vld」という信号が付いてますが、この場合「ap_done」と同じ信号になるので見ません。
・「ap_rst」を解除する。
・「ap_start」を'1'にすると動作開始。
・クロック立ち上がり&「ap_ready」が'1'にだったら次のRGBデータをBMPファイルから与える。
・クロック立ち上がり&「ap_done」が'1'だったらYCbCrデータをBMPファイルに書き込む。
という制御だけになります。
`timescale 1ns / 1ps
`default_nettype none

//******************************************
//
module bmp_file;

    integer    bfSize;            //    File Size
    integer    bfOffBits;        //    Image Offset
    integer    biWidth;        //    Width
    integer    biHeight;        //    Height
    integer    biBitCount;        //    bit/pixel
    integer    imgsize;        //    Size

    localparam    headersize    = 14+40;
    reg     [7:0]    tch;
    reg     [7:0]    header    [0:headersize-1];
    integer    ifp, ofp, tx;

    task    init;
        input    [8*20:0]    ifname;
        input    [8*20:0]    ofname;
        integer    i;
    begin
        ifp    = $fopen(ifname, "rb");
        ofp    = $fopen(ofname, "wb");
        $display("open %s", ifname);
        $display("%s created", ofname);

        tx    = $fread(header, ifp);    //, 0, headersize);
        $display("header = %d", tx);

        bfSize        = {header[ 5],header[ 4],header[ 3],header[ 2]};
        bfOffBits    = {header[13],header[12],header[11],header[10]};
        biWidth        = {header[21],header[20],header[19],header[18]};
        biHeight    = {header[25],header[24],header[23],header[22]};
        biBitCount    = {header[29],header[28]};
        imgsize        = bfSize - bfOffBits;
        $display(" = %d,%x :(%d,%d,%d)",bfSize,bfOffBits,biWidth,biHeight,biBitCount);

        for (i = 0; i < headersize; i = i+1) $fwrite(ofp,"%c",header[i]);    //    copy header info

    end
    endtask

    task    done;
    begin
        $fclose(ifp);
        $fclose(ofp);
    end
    endtask

    task    sread;
        output    [7:0]    B;
        output    [7:0]    G;
        output    [7:0]    R;
    begin
        $fread(B, ifp);
        $fread(G, ifp);
        $fread(R, ifp);
    end
    endtask

    task    swrite;
        input    [7:0]    B;
        input    [7:0]    G;
        input    [7:0]    R;
    begin
        $fwrite(ofp,"%c", B);
        $fwrite(ofp,"%c", G);
        $fwrite(ofp,"%c", R);
    end
    endtask

endmodule
//
//******************************************


//******************************************
//
module tb;

    localparam    ifname = "../H-IIA-F13.bmp";
    localparam    ofname = "../out_hdl.bmp";

    integer    bfSize;        //    File Size
    integer    bfOffBits;    //    Image Offset
    integer    biWidth;    //    Width
    integer    biHeight;    //    Height
    integer    biBitCount;    //    bit/pixel

    wire            ap_start;
    wire            ap_done;
    wire            ap_idle;
    wire            ap_ready;
    wire    [7:0]    agg_result_Y_V;
    wire            agg_result_Y_V_ap_vld;
    wire    [7:0]    agg_result_Cb_V;
    wire            agg_result_Cb_V_ap_vld;
    wire    [7:0]    agg_result_Cr_V;
    wire            agg_result_Cr_V_ap_vld;
    wire    [7:0]    s_R_V;
    wire    [7:0]    s_G_V;
    wire    [7:0]    s_B_V;

    reg             clock;
    reg             reset;
    reg             start;
    reg     [7:0]    R,G,B;
    wire    [7:0]    Y,Cb,Cr;

    rgb2ycbcr
    tgt
    (
        .ap_clk                    (clock                    ),    //    ap_clk,
        .ap_rst                    (reset                    ),    //    ap_rst,
        .ap_start                (ap_start                ),    //    ap_start,
        .ap_done                (ap_done                ),    //    ap_done,
        .ap_idle                (ap_idle                ),    //    ap_idle,
        .ap_ready                (ap_ready                ),    //    ap_ready,
        .agg_result_Y_V            (agg_result_Y_V            ),    //    agg_result_Y_V,
        .agg_result_Y_V_ap_vld    (agg_result_Y_V_ap_vld    ),    //    agg_result_Y_V_ap_vld,
        .agg_result_Cb_V        (agg_result_Cb_V        ),    //    agg_result_Cb_V,
        .agg_result_Cb_V_ap_vld    (agg_result_Cb_V_ap_vld    ),    //    agg_result_Cb_V_ap_vld,
        .agg_result_Cr_V        (agg_result_Cr_V        ),    //    agg_result_Cr_V,
        .agg_result_Cr_V_ap_vld    (agg_result_Cr_V_ap_vld    ),    //    agg_result_Cr_V_ap_vld,
        .s_R_V                    (s_R_V                    ),    //    s_R_V,
        .s_G_V                    (s_G_V                    ),    //    s_G_V,
        .s_B_V                    (s_B_V                    )    //    s_B_V,
    );

    bmp_file    bmp();

    assign    ap_start    = start;
    assign    s_R_V        = R;
    assign    s_G_V        = G;
    assign    s_B_V        = B;
    assign    Y            = agg_result_Y_V;
    assign    Cb            = agg_result_Cb_V;
    assign    Cr            = agg_result_Cr_V;

    integer s,d;
    initial
    begin
        reset    <= 1'b1;
        start    <= 1'b0;
        # 100;
        @(posedge clock);
        reset    <= 1'b0;
        @(posedge clock);
        start    <= 1'b1;

        bmp.init(ifname,ofname);

        for (s = 0; s < bmp.imgsize; s = s+3) begin
            wait (ap_ready);
            bmp.sread(B,G,R);
            @(posedge clock);
        end

        start    <= 1'b0;
        # 500;
    end

    initial
    begin
        wait (start);

        for (d = 0; d < bmp.imgsize; d = d+3) begin
            wait (ap_done);
            @(posedge clock);
            bmp.swrite(Cb,Y,Cr);
        end

        bmp.done;
        #300;
        $stop;
    end

    //    Clock
    localparam    period    = (1000.0/148.5);
    initial    clock                <= 1'b0;
    always    #(period/2)    clock    <= ~clock;

endmodule
//
//******************************************
`default_nettype wire
…行間から「HDLめんどくさい」が漏れてる…

シミュレーションの最初と最後だけ出してみます。
Image 026.png
Image 027.png
カラーコードにしたので、シミュレーションの最後の値が動いていませんが、これで正常です。下の方のsとdがそれぞれのピクセルカウンタです。

HDLシミュレーションで生成されたBMPファイルと、Cの整数シミュレーションで生成されたBMPファイルのバイナリ比較は完全一致でした。Cの浮動小数点モデルで生成したBMPファイルとの比較では所々1bitの差が出ます。

PlanAheadでインプリしてみます。
   Number of BUFGs                           1 out of 32      3%
   Number of DSP48E1s                        7 out of 220     3%
   Number of External IOBs                  57 out of 200    28%
      Number of LOCed IOBs                   0 out of 57      0%

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

   Number of Slice LUTS                    245 out of 53200   1%
   Number of Slice LUT-Flip Flop pairs     307 out of 53200   1%
HLSの予測値にかなり近い値になりました。レポートされた周波数は150MHz制約に対してSlack 1.63[ns]、約198MHzという結果になってます。

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

試しに精度の計算をコンパイラ任せにしてみます。ap_fixedではなくintで書き直します。
#define fw    12
#define frc    4096    /*    pow(2, fw)    */
#define dat    256        /*    pow(2, dw)    */

YCbCr rgb2ycbcr(RGB s)
{

    YCbCr    d;

    const int    cY [3] = { 0.2126f*frc,  0.7152f*frc,  0.0722f*frc };
    const int    cCb[3] = {-0.1146f*frc, -0.3854f*frc,  0.5000f*frc };
    const int    cCr[3] = { 0.5000f*frc, -0.4542f*frc, -0.0458f*frc };
    const int    op5    = 0.5f * dat * frc;
    const int    llim   = 0;
    const int    ulim   = dat-1;

    int    R,G,B;
    int    Y,Cb,Cr;

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

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

    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;
}
より簡単に。
レポートファイル。
================================================================
== 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|     23.29|       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|    235|
|FIFO             |        -|      -|       -|      -|
|Instance         |        -|      -|       -|      -|
|Memory           |        -|      -|       -|      -|
|Multiplexer      |        -|      -|       -|      -|
|Register         |        -|      -|       -|      -|
|ShiftMemory      |        -|      -|       -|      -|
+-----------------+---------+-------+--------+-------+
|Total            |        0|      7|       0|    235|
+-----------------+---------+-------+--------+-------+
|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|
    +-----------------------+----------+-------+---+----+------------+------------+
    |tmp_11_cast_fu_281_p2  |     *    |      1|  0|   0|           8|          12|
    |tmp_1_fu_136_p2        |     *    |      1|  0|   0|           8|          12|
    |tmp_2_fu_142_p2        |     *    |      1|  0|   0|           8|           9|
    |tmp_6_fu_179_p2        |     *    |      1|  0|   0|           8|          10|
    |tmp_7_cast_fu_189_p2   |     *    |      1|  0|   0|           8|          12|
    |tmp_7_fu_287_p2        |     *    |      1|  0|   0|           8|           9|
    |tmp_fu_126_p2          |     *    |      1|  0|   0|           8|          10|
    |tmp1_fu_152_p2         |     +    |      0|  0|  19|          19|          19|
    |tmp_10_fu_321_p2       |     +    |      0|  0|  21|          21|          21|
    |tmp_5_fu_219_p2        |     +    |      0|  0|  21|          21|          21|
    |p_neg1_fu_335_p2       |     -    |      0|  0|  21|           1|          21|
    |p_neg5_fu_233_p2       |     -    |      0|  0|  21|           1|          21|
    |p_neg_t1_fu_355_p2     |     -    |      0|  0|  10|           1|          10|
    |p_neg_t7_fu_253_p2     |     -    |      0|  0|  10|           1|          10|
    |Cb_fu_389_p3           |  Select  |      0|  0|  10|           1|           1|
    |Cr_fu_419_p3           |  Select  |      0|  0|  10|           1|           1|
    |agg_result_Cb_V        |  Select  |      0|  0|   8|           1|           2|
    |agg_result_Cr_V        |  Select  |      0|  0|   8|           1|           2|
    |tmp_13_fu_375_p3       |  Select  |      0|  0|  10|           1|          10|
    |tmp_s_fu_273_p3        |  Select  |      0|  0|  10|           1|          10|
    |icmp1_fu_437_p2        |   icmp   |      0|  0|   2|           2|           1|
    |icmp_fu_407_p2         |   icmp   |      0|  0|   2|           2|           1|
    |tmp_14_fu_383_p2       |   icmp   |      0|  0|  26|          21|          13|
    |tmp_15_fu_413_p2       |   icmp   |      0|  0|  26|          21|          13|
    +-----------------------+----------+-------+---+----+------------+------------+
    |Total                  |          |      7|  0| 235|         173|         251|
    +-----------------------+----------+-------+---+----+------------+------------+

    * 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 017.pngImage 018.png
中間値のbit幅が自動計算されてます。ap_fixedの時は18bitだった変数が自動で必要な幅になってます。また、リソースも減ってます。丸めやサチュレーション関連の回路でしょうか。

PlanAheadでインプリしたところ。
   Number of DSP48E1s                        5 out of 220     2%
   Number of External IOBs                  55 out of 200    27%
      Number of LOCed IOBs                   0 out of 55      0%

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

   Number of Slice LUTS                    171 out of 53200   1%
   Number of Slice LUT-Flip Flop pairs     171 out of 53200   1%
こちらだと乗算器が減ってます。詳しくは見てませんが、シフトなどでまかなえる部分は最適化されたんだと思います。速度は約23[ns]。だいたい同じです。


精度をユーザがちゃんと制御したい、自動計算だと中間精度のbit数がふくれあがってしまう、などの場合はfixedなどで精度を制御する必要がありますが、普通はintでコンパイラ任せの方がなんか良さそうです。第一楽ですし。

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]と若干速いですがほぼ予想値通りです。

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

ようやく対象となる関数本体を作ります。「Source」にある「rgb2ycbcr.cpp」を編集します。

まずはテストベンチの関数をそのまんまコピーして、関数名を「rgb2ycbcr」にします。浮動小数点使ってますが、気にしません。
#include "rgb2ycbcr.h"

#define dat    256        /*    pow(2, dw)    */

YCbCr rgb2ycbcr(RGB s)
{
    YCbCr    d;

    const float cY [3] = { 0.2126f,  0.7152f,  0.0722f };
    const float cCb[3] = {-0.1146f, -0.3854f,  0.5000f };
    const float cCr[3] = { 0.5000f, -0.4542f, -0.0458f };
    const float op5    = 0.5f * dat;
    const float llim   = 0.0f;
    const float ulim   = (float)(dat-1);

    float R,G,B;
    float Y,Cb,Cr;

    R = (float)s.R;
    G = (float)s.G;
    B = (float)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 (Cb < llim) Cr = llim;    if (ulim < Cb) Cr = ulim;

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

    return d;
}

main関数のコメントを切り替えて、この関数を使うように変更します。シミュレーション結果はもちろん変わりません。

試しにこのまま合成してみます。の前にソリューションの周波数を落とします。これは周波数が高いまま(デフォルト100MHz)だとレポート画面が横長になりすぎるから、というだけの理由です。
Image 012.png
緑色の再生ボタン(C Synthesis)を押します。ものの10数秒で完了です。レポートファイルがこちら。
================================================================
== 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|     37.63|       12.50|
    +---------+--------+----------+------------+

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

    + Detail: 
        * Instance: 
        N/A

        * Loop: 
        N/A



================================================================
== Utilization Estimates
================================================================
* Summary: 
+-----------------+---------+-------+--------+-------+
|       Name      | BRAM_18K| DSP48E|   FF   |  LUT  |
+-----------------+---------+-------+--------+-------+
|Expression       |        -|      -|       0|    114|
|FIFO             |        -|      -|       -|      -|
|Instance         |        -|     24|    2007|   5419|
|Memory           |        -|      -|       -|      -|
|Multiplexer      |        -|      -|       -|    388|
|Register         |        -|      -|      77|      -|
|ShiftMemory      |        -|      -|       -|      -|
+-----------------+---------+-------+--------+-------+
|Total            |        0|     24|    2084|   5921|
+-----------------+---------+-------+--------+-------+
|Available        |      280|    220|  106400|  53200|
+-----------------+---------+-------+--------+-------+
|Utilization (%)  |        0|     10|       1|     11|
+-----------------+---------+-------+--------+-------+

+ Detail: 
    * Instance: 
    +-------------------------------------------+----------------------------------------+---------+-------+-----+-----+
    |                  Instance                 |                 Module                 | BRAM_18K| DSP48E|  FF | LUT |
    +-------------------------------------------+----------------------------------------+---------+-------+-----+-----+
    |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp_U1  |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp  |        0|      2|  177|  385|
    |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp_U2  |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp  |        0|      2|  177|  385|
    |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp_U3  |rgb2ycbcr_fadd_32ns_32ns_32_3_full_dsp  |        0|      2|  177|  385|
    |rgb2ycbcr_fcmp_32ns_32ns_1_3_U14           |rgb2ycbcr_fcmp_32ns_32ns_1_3            |        0|      0|   66|  239|
    |rgb2ycbcr_fcmp_32ns_32ns_1_3_U15           |rgb2ycbcr_fcmp_32ns_32ns_1_3            |        0|      0|   66|  239|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U4   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U5   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U6   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U7   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U8   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp_U9   |rgb2ycbcr_fmul_32ns_32ns_32_3_max_dsp   |        0|      3|  128|  320|
    |rgb2ycbcr_fptoui_32ns_64_3_U10             |rgb2ycbcr_fptoui_32ns_64_3              |        0|      0|  160|  414|
    |rgb2ycbcr_fptoui_32ns_64_3_U11             |rgb2ycbcr_fptoui_32ns_64_3              |        0|      0|  160|  414|
    |rgb2ycbcr_uitofp_64ns_32_3_U12             |rgb2ycbcr_uitofp_64ns_32_3              |        0|      0|  128|  519|
    |rgb2ycbcr_uitofp_64ns_32_3_U13             |rgb2ycbcr_uitofp_64ns_32_3              |        0|      0|  128|  519|
    +-------------------------------------------+----------------------------------------+---------+-------+-----+-----+
    |Total                                      |                                        |        0|     24| 2007| 5419|
    +-------------------------------------------+----------------------------------------+---------+-------+-----+-----+

    * Memory: 
    N/A

    * FIFO: 
    N/A

    * Shift register: 
    N/A

    * Expression: 
    +------------------+----------+-------+---+----+------------+------------+
    |   Variable Name  | Operation| DSP48E| FF| LUT| Bitwidth P0| Bitwidth P1|
    +------------------+----------+-------+---+----+------------+------------+
    |Cb_1_fu_246_p3    |  Select  |      0|  0|  32|           1|           1|
    |Cb_2_fu_272_p3    |  Select  |      0|  0|  32|           1|          31|
    |Y_1_fu_236_p3     |  Select  |      0|  0|  32|           1|           1|
    |agg_result_Cr_V   |  Select  |      0|  0|   8|           1|           8|
    |agg_result_Y_V    |  Select  |      0|  0|   8|           1|           2|
    |tmp_22_fu_291_p2  |    or    |      0|  0|   2|           1|           1|
    +------------------+----------+-------+---+----+------------+------------+
    |Total             |          |      0|  0| 114|           6|          44|
    +------------------+----------+-------+---+----+------------+------------+

    * Multiplexer: 
    +-------------------+----+-----------+-----+-----------+
    |        Name       | LUT| Input Size| Bits| Total Bits|
    +-------------------+----+-----------+-----+-----------+
    |grp_fu_105_p0      |  32|          2|   32|         64|
    |grp_fu_105_p1      |  13|          2|   13|         26|
    |grp_fu_111_p1      |  10|          2|   10|         20|
    |grp_fu_141_p0      |  32|          2|   32|         64|
    |grp_fu_148_p0      |   8|          2|    8|         16|
    |grp_fu_161_opcode  |   2|          2|    2|          4|
    |grp_fu_161_p0      |  32|          4|   32|        128|
    |grp_fu_161_p1      |  10|          2|   10|         20|
    |grp_fu_168_opcode  |   2|          2|    2|          4|
    |grp_fu_168_p0      |  32|          2|   32|         64|
    |grp_fu_168_p1      |  10|          2|   10|         20|
    |grp_fu_80_p0       |  32|          3|   32|         96|
    |grp_fu_80_p1       |  32|          3|   32|         96|
    |grp_fu_84_p0       |  32|          3|   32|         96|
    |grp_fu_84_p1       |  32|          3|   32|         96|
    |grp_fu_88_p0       |  32|          2|   32|         64|
    |grp_fu_88_p1       |  32|          2|   32|         64|
    |grp_fu_99_p1       |  13|          2|   13|         26|
    +-------------------+----+-----------+-----+-----------+
    |Total              | 388|         42|  388|        968|
    +-------------------+----+-----------+-----+-----------+

    * Register: 
    +----------------+----+-----+-----------+
    |      Name      | FF | Bits| Const Bits|
    +----------------+----+-----+-----------+
    |Cb_1_reg_348    |  32|   32|          0|
    |ap_CS_fsm       |   5|    5|          0|
    |reg_201         |  32|   32|          0|
    |tmp_25_reg_354  |   8|    8|          0|
    +----------------+----+-----+-----------+
    |Total           |  77|   77|          0|
    +----------------+----+-----+-----------+



================================================================
== Interface
================================================================
* Summary: 
+------------------------+-----+-----+------------+-----------------+--------------+
|        RTL Ports       | Dir | Bits|  Protocol  |  Source Object  |    C Type    |
+------------------------+-----+-----+------------+-----------------+--------------+
|ap_clk                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|ap_rst                  |  in |    1| ap_ctrl_hs |    rgb2ycbcr    | return value |
|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    |
+------------------------+-----+-----+------------+-----------------+--------------+

「Analysis」でデータの流れが見られます。
Image 013.png
リソースの使われ方。
Image 014.png
なにも指示を与えていないので、パイプライン化もされていません。レイテンシ16クロック、17クロックに1演算、となっています。浮動小数点のコアを使っているので結構大きいです、が、これで良いのだったらこのまま完成でもOK?実際にインプリを試してはいませんが、HDLは普通にできてるのでこのままでも大丈夫そうです。

とは言えさすがにナンなので、整数化してみます。

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

まずテストプログラムを作ってしまいます。ごく普通にC/C++で書いていきます。
(tab=4をスペースに置換してるので崩れてます)
I/Oポートのデータ幅を決めておきたいので、そこだけ特別な記述が入ります。

前の記事の通り、題材はRGB→YCbCr変換。実はVivado HLSには画像のためのパッケージも入っていて、RGBとかYCbCrなどの型がすでに宣言されていますが、今回は使わずに全部自分で書いてみます。

ヘッダ。「Source」を右クリックして「rgb2ycbcr.h」というファイル名で追加。
#define dw 8

#include <ap_int.h>

struct RGB
{
    ap_uint<dw>	R,G,B;
};

struct YCbCr
{
    ap_uint<dw>	Y,Cb,Cr;
};

YCbCr rgb2ycbcr(RGB s);
「ap_uint<n>」が「nビットの符号無し整数」という型で、これがI/Oのデータ幅になります。SystemCの「sc_uint<>」とだいたい同じでしょう。「rgb2ycbcr」がハードウェアになる関数です。
※これは後から気づいたことですが、dwはマクロじゃ無くてテンプレートで与えるべきでしょうね。
テストベンチ。「TestBench」を右クリックして「test01.cpp」というファイル名で追加。

#include <fstream>
#include <iostream>
#include <iomanip>
#include <cstdlib>
using namespace std;

#include "rgb2ycbcr.h"

#define dat    256        /*    pow(2, dw)    */

////////////////////////////
//
//    Y  = ( 0.2126R + 0.7152G + 0.0722B)
//    Cb = (-0.1146R - 0.3854G + 0.5000B) + 0.5
//    Cr = ( 0.5000R - 0.4542G - 0.0458B) + 0.5
//
YCbCr ref_rgb2ycbcr(RGB s)
{
    YCbCr    d;

    const float cY [3] = { 0.2126f,  0.7152f,  0.0722f };
    const float cCb[3] = {-0.1146f, -0.3854f,  0.5000f };
    const float cCr[3] = { 0.5000f, -0.4542f, -0.0458f };
    const float op5    = 0.5f * dat;
    const float llim   = 0.0f;
    const float ulim   = (float)(dat-1);

    float R,G,B;
    float Y,Cb,Cr;

    R = (float)s.R;
    G = (float)s.G;
    B = (float)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 (Cb < llim) Cr = llim;    if (ulim < Cb) Cr = ulim;

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

    return d;
}


////////////////////////////
//
//    R = Y                  + 1.5748(Cr-0.5)
//    G = Y - 0.1873(Cb-0.5) - 0.4681(Cr-0.5)
//    B = Y + 1.8556(Cb-0.5)
//
//    R = Y            + 1.5748Cr - 0.7874
//    G = Y - 0.1873Cb - 0.4681Cr + 0.3277
//    B = Y + 1.8556Cb            - 0.9278
//
RGB ref_ycbcr2rgb(YCbCr s)
{
    RGB d;

    const float cR[3] = { 0.0000f,  1.5748f, -0.7874f * dat };
    const float cG[3] = {-0.1873f, -0.4681f,  0.3277f * dat };
    const float cB[3] = { 1.8556f,  0.0000f, -0.9278f * dat };
    const float llim   = 0.0f;
    const float ulim   = (float)(dat-1);

    float R,G,B;
    float Y,Cb,Cr;

    Y  = (float)s.Y;
    Cb = (float)s.Cb;
    Cr = (float)s.Cr;

    R = Y              + cR[1] * Cr + cR[2];
    G = Y + cG[0] * Cb + cG[1] * Cr + cG[2];
    B = Y + cB[0] * Cb              + cB[2];

    if (R < llim) R = llim;    if (ulim < R) R = ulim;
    if (G < llim) G = llim;    if (ulim < G) G = ulim;
    if (B < llim) B = llim;    if (ulim < B) B = ulim;

    d.R = R;
    d.G = G;
    d.B = B;

    return d;
}

#define dpath "../../../../"
const char ifname[]= dpath "H-IIA-F13.bmp";
const char ofname[]= dpath "out.bmp";
const char ofnameRGB[]= dpath "outRGB.bmp";
const char ofnameY[]= dpath "outY.bmp";
const char ofnameCb[]= dpath "outCb.bmp";
const char ofnameCr[]= dpath "outCr.bmp";

#pragma pack(1)
struct BITMAPFILEHEADER {
    char            bfType[2];            //    "BM"
    unsigned int    bfSize;                //    File Size (Byte)
    unsigned short    bfReserved1;        //
    unsigned short    bfReserved2;        //
    unsigned int    bfOffBits;            //    Image Offset
};
#pragma pack(0)

#pragma pack(1)
struct BGR {
    unsigned char B,G,R;
};
#pragma pack(0)

int main()
{
    ifstream ifile;
    ofstream ofile;
    ofstream ofileRGB;
    ofstream ofileY;
    ofstream ofileCb;
    ofstream ofileCr;
    BITMAPFILEHEADER bf;
    int    imgsize;

    RGB        src;
    YCbCr    des;

    ifile.open(ifname, ios::binary);
    ofile.open(ofname, ios::binary);
    ofileRGB.open(ofnameRGB, ios::binary);
    ofileY.open(ofnameY, ios::binary);
    ofileCb.open(ofnameCb, ios::binary);
    ofileCr.open(ofnameCr, ios::binary);

    //    bf
    ifile.read((char*)&bf, sizeof(bf));

    cout << "bfType : " << bf.bfType[0] << bf.bfType[1] << endl;
    cout << "bfSize : " << bf.bfSize << endl;
    cout << "bfOffBits : " << bf.bfOffBits << endl;

    //    copy header
    ofile.write((char*)&bf, sizeof(bf));
    ofileRGB.write((char*)&bf, sizeof(bf));
    ofileY.write((char*)&bf, sizeof(bf));
    ofileCb.write((char*)&bf, sizeof(bf));
    ofileCr.write((char*)&bf, sizeof(bf));

    for (int i = sizeof(bf); i < bf.bfOffBits; i++)
    {
        char tch;
        ifile.read(&tch, sizeof(tch));
        ofile.write(&tch, sizeof(tch));
        ofileRGB.write(&tch, sizeof(tch));
        ofileY.write(&tch, sizeof(tch));
        ofileCb.write(&tch, sizeof(tch));
        ofileCr.write(&tch, sizeof(tch));
    }

    //    copy
    imgsize = bf.bfSize - bf.bfOffBits;

    for (int i = 0; i < imgsize; i+=3)
    {
        BGR ipx, opx;
        ifile.read((char*)&ipx, sizeof(ipx));
        src.R = ipx.R;
        src.G = ipx.G;
        src.B = ipx.B;
        des = ref_rgb2ycbcr(src);
//        des = rgb2ycbcr(src);
        opx.R = des.Y;
        opx.B = des.Y;
        opx.G = des.Y;
        ofileY.write((char*)&opx, sizeof(opx));
        opx.R = des.Cb;
        opx.B = des.Cb;
        opx.G = des.Cb;
        ofileCb.write((char*)&opx, sizeof(opx));
        opx.R = des.Cr;
        opx.B = des.Cr;
        opx.G = des.Cr;
        ofileCr.write((char*)&opx, sizeof(opx));
        opx.R = des.Cr;
        opx.B = des.Cb;
        opx.G = des.Y;
        ofile.write((char*)&opx, sizeof(opx));

        src = ref_ycbcr2rgb(des);
        opx.R = src.R;
        opx.G = src.G;
        opx.B = src.B;
        ofileRGB.write((char*)&opx, sizeof(opx));
    }

    ifile.close();
    ofile.close();
    ofileRGB.close();
    ofileY.close();
    ofileCb.close();
    ofileCr.close();
    cout << "done\n";
}

BMPファイルを読み込んで、変換して、BMPに保存します。実行パスが「.\rgb2ycbcr\solution1\csim\build\csim.exe」という深いところにできるので画像へのパスが長めに…(笑)
RGB→YCbCr変換はWikiに書いてある方法そのままです。ついでに画像を元に戻すYCbCr→RGBの逆変換関数も用意します。けど、なにも工夫してません。ちゃんと精度のこと考えてないので、正確でもありません。エラーチェックもろくしていない全くもっていい加減なプログラム。まぁだいたい見た目が似てればよいや、的な作りです。
後でmainでコメントアウトしているrgb2ycbcrとref_rgb2ycbcrを入れ替えてテストします。

とりあえずこのまま実行してみます。「Run C Simulation」をポチ。
Image 010.png
デフォルトのまま実行開始。
Image 011.png

こんな画像が出てきます。(※So-netブログはBMPダメ)。
左から、元画像、Y、Cb、Cr、BGR=CbYCrに置き換え、逆変換した画像
out.PNG

実行環境ができたので、ハードウェアになる対象の関数を記述していきます。

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

またご無沙汰です。

最近、ZedBoardとこれ
http://avnet.co.jp/design/kits/xilinx/AES-FMC-IMAGEON-V2000C-G.aspx
入手しました。OnSemiのこのセンサーはFullHD 100fpsというセンサーですが、256x256 1700fpsで使ってみたいです。ちょっとした中速度撮影カメラですね。BayerパターンのRAW出力なので後処理は必要です。
また、Allowから低価格CycloneV SOCのSoCKitが発表されました。
http://www.arrownac.com/solutions/sockit/
DDR3がARMコアとFPGAハードマクロに1GBずつ2系統ってことでしょうか。DS5の扱いがどうなるかによりますが使ってみたいです。HSMCに上記のイメージセンサーつなぎたいな~

まぁ、この辺はおいおい。

さて、これまた最近、Xilinx VivadoのHLSに触れる機会がありました。その昔AutoESLと呼ばれてたC/C++→HDLツールです。もっと効率よい方法があるかもしれませんが、試行錯誤しながら使ってみます。参考資料はこれ。
http://www.xilinx.com/support/documentation/sw_manuals/xilinx2012_2/ug902-vivado-high-level-synthesis.pdf (PDF)
あと、サンプル記述の例が埋め込まれているので、それも参考になります。

起動画面。
Image 001.png
「Create New Project」で新しくプロジェクト作成します。
Image 002.png
題材としてRGB→YCbCr変換。IPはどこにでもあるので自分で作る必要は無いんですが、結果がわかっているので試すにはよろしかろうと。
ソースファイルの追加。「Top Function」で指定した関数から下がハードウェアに変換されます。
Image 003.png
ここでちょっと違和感。ファイルを追加しないと次にいけないんですが、まだプロジェクトフォルダが作成されていないので、ファイルの場所が?今回の場合
c:\work\hls_test\rgb2ycbcr
フォルダにファイルを入れるような気がするんですが、この時点で「rgb2ycbcr」は無いため、「hls_test」に作ることになります。後でファイルの場所を変えれば良いだけですが…想定されてる使い方が違うのかな?
テストベンチ。あとで。
Image 004.png
「ソリューション」と呼ばれる、回路生成の設定画面。
Image 005.png
コンパイラオプションセットみたいな感じです。速度とかデバイスを指定します。これは後で変更可能ですし、複数のソリューションを用意することもできます。
今回はZedBoardを想定してZynq7020を設定。速度はデフォルト。
Image 006.png
設定後。あ、デバイス間違えてるw
Image 007.png
設定完了後の画面。ここにテストベンチとか追加して行きます。
Image 008.png
使い方はほぼEclipseのままです。
上のメニューとかボタン。
Image 009.png
緑の再生ボタンがHDL生成。その左がC/C++シミュレーション。この二つをよく使います。
Debug、Synthesis、Analysisはパースペクティブの切り替え。Debugは普通のCデバッガです。Analysisがハードウェアのデータの流れを解析するツールになります。

ここからソースを記述していきます。順番として
・テストベンチ作成。リファレンスとなるデータの読み書きを行うプログラムを書きます。
・ハードウェアになる対象の関数を作成。
・対象の関数を最適化。しなくても良いかも。
・ディレクティブ(指示子?)追加。I/Oの種類とかパイプラインとか。
てな感じで行きます。

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