前回高位合成用のC++コードを作成しました。今回はそのコードを使って高位合成を行い、その流れで回路まで作成します。
1.高位合成
今回はVitis HLSを用いてPYNQ-Z2向けに合成を行います。その際の設定は以下の通り。
- ターゲット周波数:200MHz
- Uncertainty:12.5%
- ターゲットデバイス:pynq-z2(xc7z020clg400-1)
- 言語:C++0x
今回は2つのソースファイル(FMA.cpp, FMA.hpp)、1つのテストベンチ(FMA_TB.cpp)を登録します。このうちFMA.cppとFMA_TB.cppのCFLAGSに-std=c++0xオプションを付与します。
合成結果はこんな感じになりました。
|
高位合成の結果 |
Iteration Latencyは16となりましたが、Intervalが1になっていることからいい感じにパイプライン化できたようです。使用率は
- DSP : 4%(10/220)
- LUT:3%(1992/53200)
- FF:1%(1718/106400)
- BRAM:0%(0/140)
となっています。余裕ありありですね。合成されたデータフローはこんな感じでした。
|
データフローの一部。2か所ほど"長い棒"がみえるが、 それぞれfmulとfaddの計算ステップとなっていた。
|
一応仕様通りに2並列で計算できているようです。また大半のステップがfmulとfaddで占められていることもわかりました。
この後CoSimを走らせて結果を確認後、IPを出力します(そのまま出力してもいいのだが、Configuration...のボタンからVendor、Library、Description、Display Nameあたりをいじってからいったん出力->Solution Settings内のConfiguration Settingsのconfig_exportにあるipnameをいじってから出力すると、VivadoでIPを読み込んだ際にオリジナルの名前が付き、ベンダー名で検索がかけられる)。
2.回路合成
高位合成で作成したIPを使って回路を作成します。ZYNQのIPを最初に置いて、Run Connection Automationを走らせるとDDRとFIXED_IOと外部端子がつながるはずです。
その後、AXI_HPポートの0から3を有効化します。データ幅はすべて64bitにしましょう。
|
AXI_HPポートの設定。データ幅はすべて64bitとした。 |
AXI_HPポートの設定後、IPへ供給するクロックの設定をします。今回は単一のクロックソースかつ周波数が200MHz程度なので、ZYNQのIPから供給します。Clock Configuration->PL Fabric Clocksの順にたどり、FCLK_CLK0を200MHzに設定します。
|
クロック設定。今回はHLSに合わせて200MHz。 |
ZYNQ IPの設定が終わったら、AXI Direct Memory AccessとAXI Interconnectを4つずつ出します。
AXI Interconnectの方はMasterとSlaveの数をそれぞれ1に設定します。
DMAの方は入力側(W, X, B)と出力側(Y)で少し異なります。入力側のDMA IPについて、Enable Scatter Gather Engineを無効化し、Width of Buffer Legth Registerを26bits、Address Widthを64Bitsにしておきます。データ入力のIPなので、Read Channelのみ有効にしておきます。Memory Map Data WidthとStream Data Widthは64にしておきます。
|
読み込み側のDMA IPの設定 |
出力側のDMA IPについては、入力側で行ったEnable Scatter Gather Enginenの無効化、Width of Buffer Legth Register->26bits、Address Width->64Bitsの操作を同じく行います。その後、Read Channelを無効化し、Write Channelの有効かを行います。Memory Map Data WidthとStream Data WidthはAUTOのままでOKです。
|
書き込み側のDMA IPの設定 |
最後に各IPを接続します。DMAのIPをCPU側から制御するため、個々のIPに割り当てられている名前が必要になります。サンプルコードをそのまま使いたい場合、
- S_AXI_HP0 -> axi_dma_0(+interconnect) -> w_axi_0
- S_AXI_HP1 -> axi_dma_1(+interconnect) -> x_axi_1
- S_AXI_HP2 -> axi_dma_2(+interconnect) -> b_axi_2
- y_axi_3 -> axi_dma_3(+interconnect) -> S_AXI_HP3
と接続しましょう。
|
IPの配線図。 Wが0、Xが1、Bが2、Yが3と覚えると分かりやすい。
|
この接続を終えると、Run Connection Automationの表示が出るので、すべてにチェックを入れて実行すれば最終的な回路の完成です。この後、アドレスエディタでDMAと自作IPに対してアドレスを割り当てておきましょう。
Generate Output Productsを実行し、Create HDL WrapperをLet Vivado manage...の方に入れておきます。Generate Bitsteramをクリックすれば回路の合成が始まります(2回に1回ぐらいで失敗するが、Output Productsをリセットしたのち、Generateしなおして再びBitstreamの生成を行えばいけるはず)。
Bitstreamの生成が終わったら、.bitのファイルと.hwhのファイルを書きだします。画面左上のFile->Export->Export Hardwareを選択し、Platform typeをFixed、Outputを Include bitstreamに設定します。その後、XSAのファイル名を聞かれるので、適当な名前にします(サンプルコードの通りにしたい場合は、design_1_wrapperをdesign_1に変更)。出力先はどこでもよいです。
.bitと.hwhはこのXSAファイルに入っているので、7zip等を使い取り出します。最終的にこの.bitと.hwhのファイルを.ipynbから読みだしてプログラムを実行することになります。
3.次回
©2022 shts All Right Reserved.