1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Xilinx FPGA の Vivado の Tcl を読み解くために必要な情報:HLS IP をブロックデザインで使うまでの流れ

Last updated at Posted at 2025-08-19

はじめに

Vivado HLSを使うと、C/C++で記述したアルゴリズムを高位合成 (HLS)し、FPGAで利用可能なカスタムIPコアとして生成できます。Zynqデバイス(ARMプロセッサ + FPGA)では、この自作IPをVivadoのIPカタログに登録し、ブロックデザイン (IP Integrator) 上で組み込むことで、プロセッサと連携したシステムを構築できます。この記事では、自分向けの備忘録のメモを少し広げて、なるべくVivado HLSでのIPコア作成からVivadoプロジェクトへの取り込み、ブロックデザインへインスタンス化する一連の手順が伝わるようにと、京都大学の鈴木先生のTclスクリプトをベースに解説します。特に、Tclスクリプト(例:dds_hls.tcl)内のcreate_bd_celllatest_ipといったコマンドの意味を中心に、初心者にも分かりやすく説明します。

この記事の流れ:

  1. Vivado HLSでC++からIPを生成 – C++デザイン(例: dds_hls.cpp)を高位合成し、Vivado用のIPにパッケージ化
  2. VivadoへIPを登録 – 生成したIPをVivadoのIPカタログに追加
  3. ブロックデザインにIPをインスタンス化 – Tclスクリプトを用いてIPをブロックデザイン上に配置し、設定や接続を行う
  4. 主要なVivado Tclコマンドの解説create_bd_cellget_ipdefsset_propertyなどIP統合に使われるコマンドの使い方
  5. トラブルシューティング – 「No Catalog IPs found」といったエラーへの対処やVLNV不一致の問題解決

はじめての人でも雰囲気がわかるように、順を追った解説とコード例、ディレクトリ構成の例などを示します。要点は箇条書きやコードブロックで整理し、リファレンスも適宜引用します。まずは、高位合成IPをブロックデザインで利用する手順を見ていきましょう。

(この記事は、下記の記事のような超伝導遷移端検出器などの超伝導デバイスの読み出しにRFSoCを使うことを想定しています。)

基本的な流れの確認

Vivado Tcl フロー全体像(典型的な手順)

ステップ 目的 主なコマンド例
1️⃣ プロジェクト作成 プロジェクト環境の初期化 create_project
2️⃣ ソース追加 HDL/BDソースの追加 add_files, import_files
3️⃣ ボード or デバイス指定 ターゲット FPGA を設定 set_part, set_property board_part ...
4️⃣ ブロックデザイン作成 IP構成と接続を GUI / Tcl で定義 create_bd_design, create_bd_cell, connect_bd_net
5️⃣ デザイン保存と検証 BDの整合性確認 validate_bd_design, save_bd_design
6️⃣ ラッパー生成 RTLに変換 make_wrapper -files [get_files system.bd] -top, add_files
7️⃣ トップモジュール設定 合成対象のトップを指定 set_property top <top_module_name> [current_fileset]
8️⃣ 合成実行 HDL → ネットリスト変換 launch_runs synth_1, wait_on_run synth_1
9️⃣ インプリメンテーション実行 配置配線(P&R) launch_runs impl_1, wait_on_run impl_1
🔟 ビットストリーム生成 最終FPGA用ファイル launch_runs impl_1 -to_step write_bitstream
✅ 完了後ファイル出力 Bitファイルなどを取得 file copy, report_*
create_project → add_files / BD構築 → validate/save_bd_design
→ make_wrapper → set top → synth → impl → write_bitstream

この順序が基本となります。これを意識すれば、Vivado Tcl による自動化・再現性の高い設計フローの理解を進めましょう。

Vivado HLSでC++デザインをIPコアに高位合成する

まずはC++で書かれたアルゴリズムをVivado HLSでIPコア化する手順です。例として、Direct Digital Synthesizer (DDS) を実装したdds_hls.cppを用いると仮定します。Vivado HLSのGUIを使う場合、Projectを作成してソースを追加し、Run C Synthesisを実行した後、Export RTLを選択してIP化します。Export RTLを行うことで、高位合成結果がVivadoで利用可能なIPとしてパッケージ化されます。

例えばVivado HLS GUI上では以下の順序になります:

  1. Cシミュレーションやデバッグ (必要に応じて)
  2. Run C Synthesis (C/C++をRTLに合成)
  3. Export RTL (合成したRTLをIPパッケージとして出力)

GUIを使わずバッチ処理で行う場合、Vivado HLSはTclスクリプトで同様の操作が可能です。Vivado HLSのコマンドライン (vitis_hls) からtclスクリプトを指定して実行できます(例:vitis_hls -f dds_hls.tcl)。dds_hls.tcl内では、プロジェクト作成から合成・IPエクスポートまでのコマンドが順番に呼ばれているはずです。以下はVivado HLS用Tclスクリプトの一例です(実際の内容に合わせて読み替えてください):

# Vivado HLS Tcl スクリプト例
open_project dds_hls           ;# プロジェクト名を指定してオープン/新規作成
set_top dds_top                ;# 合成するトップ関数名を指定 (例: dds_top)
add_files dds_hls.cpp          ;# 高位合成するC++ファイルを追加
open_solution -reset solution1 -flow_target vivado
set_part {xc7z020clg400-1}     ;# Zynqなどターゲットデバイスを設定
create_clock -period 10 -name default
csynth_design                  ;# C合成を実行
# cosim_design                 ;# (必要なら)C/RTL協調シミュレーション
export_design -format ip_catalog -rtl verilog -output "./solution1/impl/ip" 
exit

上記は簡略化した例ですが、ポイントは最後のexport_design -format ip_catalogです。-format ip_catalogオプションにより、Vivado IPカタログに追加可能な形式でRTLがパッケージ化されます。export_designにはオプションでVendorLibraryNameVersionといったVLNV情報を指定することもできます。指定しない場合、デフォルトではVivado HLSプロジェクト名や関数名等から自動設定されます。例えば上記スクリプトでは-output"./solution1/impl/ip"ディレクトリを指定しており、その中にIPが出力されます。デフォルトVendorはxilinx.com、Libraryはhls、Versionは1.0になるケースが多いです(Vivado HLS GUIでExportする際に変更可能)。

高位合成が成功すると、プロジェクトのディレクトリにIPパッケージが生成されます。標準的には、<project_name>/solution1/impl/ip以下にIPコア用のフォルダが作られ、その中にcomponent.xml(IP定義ファイル)やHDLファイル、xciファイル等が含まれます。例えばdds_hlsプロジェクトの場合、以下のような構成になります(フォルダ名やファイル名はプロジェクト設定によって異なります):

dds_hls/solution1/impl/ip/
└── dds_hls_1.0/
    ├── component.xml            # IPコアのメタデータ (VLNV やポート定義など)
    ├── synth/                   # 合成されたHDL等
    ├── sim/                     # シミュレーションモデル等 (あれば)
    └── example_design/          # サンプルデザイン (オプション)

このようにVivado HLSでC++からIPが生成できました。次は、このIPをVivadoのプロジェクトで使用するための手順に移ります。

VivadoプロジェクトにHLS IPを統合する(IPカタログへの登録)

VivadoでカスタムIPを使うには、まずそのIPをVivadoのIPカタログに認識させる必要があります。Vivado GUIの場合、プロジェクトを開きFlow NavigatorIP Integrator -> Create Block Designでブロックデザインを作成した後、空白部分で右クリックしてIP Settingsを開き、Repositoryに先ほどのIPフォルダを追加します。具体的には、Repositoriesリストで「+」ボタンを押し、先ほどVivado HLSが出力したsolution1/impl/ipディレクトリをパスとして追加します。するとVivadoがそのフォルダをスキャンし、中のcomponent.xmlを読み取ってIPカタログに登録します。GUI上では、solution1/impl/ipを追加して「Select」すると検出されたIPの一覧(今回の場合自作IPひとつだけ)が表示されるのでOKします。これでIPカタログに自作IPが加わり、ブロックデザイン上でAdd IPから選択できるようになります。

Tclスクリプトで同様の操作を行う場合は、プロジェクトに対してip_repo_pathsプロパティを設定し、その後にupdate_ip_catalogコマンドでカタログを更新します。例えば以下のように記述します:

# プロジェクトにローカルIPリポジトリを追加するTcl例
set_property ip_repo_paths "./dds_hls/solution1/impl/ip" [current_fileset]
update_ip_catalog

上記ではcurrent_filesetに対してIPリポジトリのパスを設定しています(current_projectでも類似の効果がありますが、Vivadoの仕様上current_fileset推奨)。update_ip_catalogを呼ぶことで即座にカタログが更新され、追加したディレクトリ以下のcomponent.xmlを探してIP定義を読み込みます。実際、VivadoのTclスクリプトテンプレートでは以下のようにチェックして追加するコードが含まれています:

if {[info exists ip_repo_path_list] && [llength $ip_repo_path_list] > 0} {
    set_property ip_repo_paths $ip_repo_path_list [current_fileset]
    update_ip_catalog
}

この部分は、リポジトリパスのリストip_repo_path_listに要素があれば、それらをプロジェクトに登録している例です。

以上でVivadoのIPカタログに自作IPが登録されました。登録が成功していれば、Tools -> IP Catalogから自作IP(例えばdds_hlsなど)を検索して一覧に出てくるはずです。次はいよいよ、このIPをブロックデザインに組み込んでみましょう。

ブロックデザインにIPを追加してシステムに組み込む

VivadoでZynq向けシステムを設計する際は、IP Integratorのブロックデザイン上で各種IPを配置し相互接続します。ここでは自作したHLS IPコアをブロックデザインにインスタンス化し、必要に応じて他のブロック(Zynq MPSoCやAXIインターコネクトなど)と接続する流れを説明します。Tclスクリプトで自動化する場合のコマンドに着目しつつ、ポイントを解説します。

ブロックデザインの作成 (GUI と Tcl)

GUIでは、Flow NavigatorのIP IntegratorからCreate Block Designを選び、新しいブロックデザイン(例: design_1)を作成します。Tclではcreate_bd_designコマンドを使用して同様にブロックデザインを新規作成できます。例えば:

create_bd_design "design_1"

とすることで、design_1という名前のBD (Block Design) が作られます。Note: 既にGUI上でBlock Designを作成済みの場合、Tclスクリプト内で改めてcreate_bd_designする必要はありません。

カスタムIPのインスタンス化 – create_bd_cell コマンド

自作IPをブロックデザインに追加するには、GUIなら「Add IP」から該当IPを選択しますが、Tclではcreate_bd_cellコマンドを使います。このコマンドはVivado IPカタログからIPをブロックデザイン上にインスタンス化する役割を持ちます。基本的な構文は以下のとおりです:

create_bd_cell -type ip -vlnv <Vendor:Library:Name:Version> <インスタンス名>
  • -type ip オプションでIPコアを追加する指定をします(省略時も既定でIP扱いですが-vlnv指定が必要)
  • -vlnv に続けて、追加したいIPのVLNV(Vendor:Library:Name:Version)を指定します
  • 最後にブロックデザイン上でのインスタンス名を指定します(任意の名前。GUIでAdd IPした際につくデフォルト名に相当)

例えば、AXI FIFO IPコアを追加する場合は次のようになります:

create_bd_cell -vlnv xilinx.com:ip:axi_fifo_mm_s:4.0 axi_fifo_1

上記では、xilinx.com:ip:axi_fifo_mm_s:4.0というVLNVのIP (AXI FIFO Memory Mapped Stream, Version 4.0) をaxi_fifo_1という名前でBDに追加しています。-type ipはデフォルトなので省略されています。このように、カタログ上の既存IPはVLNVを完全指定することで直接インスタンス追加可能です。

では、自作のHLS IPの場合はどうでしょうか。HLSでエクスポートしたIPにもVLNVが割り当てられています。デフォルトではVendorxilinx.comLibraryhlsNameはトップ関数名やHLSプロジェクト名、Version1.0になっていることが多いです。仮に我々のDDS IPのVLNVがxilinx.com:hls:dds_hls:1.0だった場合、次のように追加できます:

create_bd_cell -type ip -vlnv xilinx.com:hls:dds_hls:1.0 dds_hls_0

ここではインスタンス名をdds_hls_0としました。このコマンドが実行されると、VivadoはIPカタログから該当VLNVのIPコアを探し出し(事前にIPカタログに追加済みであることが前提です)、ブロックデザイン上に配置します。配置されたIPは[get_bd_cells dds_hls_0]のように参照可能で、他のIP同様、GUI上にもブロックが現れます。

latest_ipを使ったIPバージョン指定の動的化

🔍 latest_ip Tcl 関数の意味と用途

proc latest_ip {i_ip} {
    return [get_ipdefs -all -filter "VLNV =~ *:${i_ip}:* && \
    design_tool_contexts =~ *IPI* && UPGRADE_VERSIONS == \"\""]
}

これは Vivado の IP Catalog から、指定した IP 名に一致する 最新バージョンの IP を探して返す ユーザー定義関数です。

🧠 各構文の意味を解説
構文 意味
proc latest_ip {i_ip} { ... } Tcl関数latest_ipの定義。引数は1つ i_ip(IPの名前)
get_ipdefs Vivadoで登録されたIP定義(VLNV)を取得するコマンド
-all 非表示のものも含め、すべての IP を対象に検索
-filter "..." 条件式でフィルタ。ここが肝です。
VLNV =~ *:${i_ip}:* IPの名前に i_ip が含まれるものを探す(VendorとVersionはワイルドカード)
design_tool_contexts =~ *IPI* Vivado のブロックデザイン用に作られた IP(IPI)に限定
UPGRADE_VERSIONS == "" アップグレード可能な旧バージョンを除く(最新バージョンのみ)
🧩 使用例
set dds_hls [create_bd_cell -type ip -vlnv [latest_ip dds_hls] dds_hls]

上記のように使うと、

  • latest_ip dds_hls が IP カタログの中から dds_hls という名前に一致する 最新の IP の VLNV(Vendor:Library:Name:Version) を返す。
  • それを create_bd_cell に渡すことで、ブロックデザイン上に IP を配置する。
🔁 置き換え可能な手動操作

この latest_ip がなくても、代わりに明示的に VLNV を書けば動作します:

create_bd_cell -type ip -vlnv user.org:user:dds_hls:1.0 dds_hls

ただし、バージョンが将来変わるとこの方法では古いIPを指定してしまう可能性があるため、latest_ip は非常に便利な補助関数なのです。

✅ まとめ
関数 用途
latest_ip dds_hls IP Catalog の中から dds_hls という名前を含む 最新の IP VLNV を取得する
create_bd_cell -vlnv ... 指定した IP をブロックデザインにインスタンスとして追加する

latest_ip は、複数のプロジェクト・複数人開発環境で IPのバージョンが自動で追従されるため、特にチーム開発やスクリプト自動化で役立ちます。

latest_ipは単独のVivadoコマンドは存在しません。これは**ユーザー定義のTclプロシージャで、VivadoのTcl出力スクリプトが生成する便宜上の関数名です。

に定義されています。

get_ipdefsコマンドは、IP定義を検索し、最新バージョンをフィルタで取得することです。get_ipdefsは現在プロジェクトで利用可能なIP定義を取得するコマンドで、-filterオプションでプロパティに基づく絞り込みが可能です。例えば、名前に"axi"を含むIPを探す場合:

get_ipdefs -filter {NAME=~*axi*}

NAME=~*axi*はDISPLAY_NAME(表示名)に"axi"が含まれるIPをゆるくマッチします。他にもIS_AXI==1とすればAXIインターフェイスを持つIPに限定できます。

そして複数バージョンのIPが存在する場合、UPGRADE_VERSIONSプロパティが空文字列かどうかで最新かどうかを判別できます。UPGRADE_VERSIONSが空("")のIP定義は、それより新しいバージョンが存在しない=最新バージョンであることを意味します。従って、「最新バージョンのIP定義」を取得するには以下のようなフィルタが使えます:

get_ipdefs -all *dds_hls* -filter {UPGRADE_VERSIONS == ""}

上記では名前やVLNVにdds_hlsを含むIPを-all(ユーザーIPも含め全カタログ対象)で探し、その中からアップグレード先がない(最新である)ものを取得しています。-allオプションを付けているのは、Vivado標準IPカタログだけでなくプロジェクト追加IP(IP Integratorカタログ)も対象に含めるためです。get_ipdefsはデフォルトではVivadoインストール済みの標準IPのみ検索しますが、-allを指定するとユーザー追加IPも検索対象に含められます。

要するに、**create_bd_cell -vlnv [latest_ip ...] ...**という記述は、「指定IPの最新バージョンを自動選択してセル生成する」ための工夫だと理解できます。スクリプトを読む際は、まずlatest_ipがどのように定義されているか(proc latest_ip { ... } { ... }のような記述が前後にないか)確認すると良いでしょう。

IPパラメータの設定 – set_property コマンド

IPをブロックデザインに追加した直後は、IPはデフォルト設定のままです。必要に応じてパラメータを設定することで、IPの挙動や接続を調整します。Vivadoではset_property -dictを用いてIPインスタンスのパラメータをまとめて設定できます。例えば、Block Memory Generator IPを「True Dual Port RAM」に設定する場合や、AXI BRAM Controllerを生成する場合のTclスクリプト例は以下の通りです:

set bmgName bmg_0
set bmg [create_bd_cell -type ip -vlnv xilinx.com:ip:blk_mem_gen:8.4 $bmgName]
set_property -dict [list \
    CONFIG.Memory_Type {True_Dual_Port_RAM} \
    CONFIG.Assume_Synchronous_Clk {true} \
] $bmg

set axiCtrlName axi_bram_ctrl_0
set axiCtrl [create_bd_cell -type ip -vlnv xilinx.com:ip:axi_bram_ctrl:4.1 $axiCtrlName]

上記では、まずBlock Memory Generator (blk_mem_gen) IPをbmg_0として追加し、続いてset_property -dictでそのIPオブジェクト$bmgに対して複数のCONFIGプロパティを設定しています。CONFIG.Memory_TypeCONFIG.Assume_Synchronous_ClkなどはUG付きマニュアルに記載のIPパラメータ名です。set_property -dict [list ...] <オブジェクト>の形式で、一度に複数のプロパティをディクショナリ形式で適用できます。例えばHLSから生成されたIPで、カスタムのパラメータ(例えばデータ幅や係数など)があれば、同様にCONFIG.<パラメータ名>で設定可能です。

HLS由来のIPの場合、AXIハンドシェイク等の制御方式によっては 制御インターフェイス (S_AXI) を持つものもあります。たとえばトップ関数に#pragma HLS INTERFACE s_axiliteがある場合、生成IPにはAXI Liteのコントロールレジスタが実装され、C_S_AXI_CONTROL_BASEADDRなどのパラメータが設定されています。そのようなパラメータもset_propertyで変更可能ですが、通常デフォルトの0x4000_0000などが使われ、そのままで問題なければ手を加える必要はありません。いずれにせよ、特定のIPが持つ設定項目を知りたいときは、Vivado GUIでそのIPをダブルクリックして設定画面を見るか、report_property -all [get_bd_cells <インスタンス名>]コマンドで可能なプロパティ一覧を出力すると良いでしょう。

IPの接続 – connect_bd_netconnect_bd_intf_net

IPを追加しただけでは回路は完成しません。ZynqのようなプロセッサIP や他のIPとポートを接続する必要があります。Vivadoでは、スカラーの端子(1ビット信号やクロック、リセット線など)connect_bd_netコマンドで、**バスインターフェイス(AXIやストリームなど)**はconnect_bd_intf_netコマンドで接続します。

例えば、前述のAXI BRAM Controller (axi_bram_ctrl_0)のBRAMポートと、Block Memory (bmg_0)のBRAMポートを接続するには:

connect_bd_intf_net [get_bd_intf_pins $axiCtrlName/BRAM_PORTA] [get_bd_intf_pins $bmgName/BRAM_PORTA]
connect_bd_intf_net [get_bd_intf_pins $axiCtrlName/BRAM_PORTB] [get_bd_intf_pins $bmgName/BRAM_PORTB]

このように、get_bd_intf_pins <セル名/ポート名>でインターフェイスピンを取得し、二つをconnect_bd_intf_netで結びます。クロックやリセットのような普通のポート(スカラー信号)の場合はget_bd_pinsでピンを取得しconnect_bd_netでつなぎます。

Zynqを含むシステムの場合、自作IPのAXIインターフェイス(例えばAXI4-StreamやAXI4-Lite)をZynq PSの対応するマスター/スレーブポートに接続する必要があります。Tclスクリプト上では、PS部分もcreate_bd_cell -type ip -vlnv xilinx.com:ip:processing_system7:5.5 ps_0のように追加し(バージョンは適宜)、connect_bd_intf_net ps_0/M_AXI_HPM0_FPD <-> dds_hls_0/S_AXIのように接続します。具体的な接続方法はIPの種類や目的によって異なりますが、クロックおよびリセットは必ず自作IPに供給する必要があります。AXI系IPなら、AXIインターフェイス同士をつなぎ、アドレスマップも設定します(後述)。

アドレスマップの設定(必要な場合)

AXI Liteのコントロールポートなどアドレス空間を持つIPをZynq PSに接続した場合、アドレスエディタでPSのマスター空間上にスレーブ側のアドレス範囲を割り当てる必要があります。Vivado GUIではBlock Design編集画面上のAddress Editorタブで操作できますが、Tclではassign_bd_addressコマンドで自動割り当てができます。例えば:

assign_bd_address [get_bd_addr_segs ps_0/Data/SEG_dds_hls_0_Reg] 

のように、PSのアドレス空間に自作IP(例ではdds_hls_0)のレジスタマップ領域を割り当てることができます(実際のパスや名前は環境により異なります)。割り当て後、set_property range 0x10000 [get_bd_addr_segs ps_0/Data/SEG_dds_hls_0_Reg]といった具合に範囲やオフセットを変更することも可能です。アドレスマップ設定は少し難しい部分なので、GUIで一度割り当ててからExport Block DesignでTclを確認するとよいでしょう。

ブロックデザインの検証と保存

IPを追加し、パラメータ設定や接続が完了したら、デザインの検証保存を行います。Vivadoではvalidate_bd_designコマンドで接続や設定に不備がないかチェックでき、save_bd_designでブロックデザインを保存できます。検証では、未接続ポートや不適合な接続があるとエラー/警告が表示されます。特にクロックやリセットの接続忘れに注意してください。

最後にgenerate_targetcreate_hw_designなどでHDLラッパーの生成、合成・Implementationを行えば、ビットストリーム生成までたどり着けます(これらは本記事の範囲外なので割愛します)。

Vivado Tcl主要コマンドのまとめと解説

上記手順で登場したVivado Tclコマンドについて、要点を整理します。スクリプトを読み解く際の参考にしてください。

  • create_project: Vivadoプロジェクトを作成するコマンドです。引数にプロジェクト名、ディレクトリ、ターゲットデバイス/ボードなどを指定します。-part-boardオプションでターゲットFPGAを設定できます。例: create_project myproj ./myproj -part xc7z020clg400-1。プロジェクト作成後、current_projectでプロジェクトオブジェクトを参照できます。

  • set_property ip_repo_paths: カスタムIPの検索パスをプロジェクトに設定します。複数のディレクトリをリスト形式で指定可能です。指定後はupdate_ip_catalogを忘れずに実行します。例: set_property ip_repo_paths [list "./ip_repo" "/home/user/myIPs"] [current_fileset]。なお、一度Vivadoを起動している間はこの設定がキャッシュされるため、スクリプトをやり直す際はプロジェクトを再作成/削除するか、update_ip_catalogでリフレッシュしてください。

  • update_ip_catalog: 上記のように追加したIPリポジトリをスキャンし、IPカタログを更新します。実行後、get_ipdefsで追加IPが取得可能になります。

  • create_bd_design: 新規ブロックデザインを作成します。名前を引数に指定して呼び出します。既にデザインが存在する場合は上書きされるため注意してください。

  • create_bd_cell: IPやモジュールをブロックデザインに追加するコマンドです。-typeipを指定し、-vlnvにIPのVLNV文字列を与えて使用します。戻り値として作成したcellオブジェクト(インスタンス)の参照が得られます。例えばset my_ip [create_bd_cell -type ip -vlnv vendor:lib:name:ver inst_0]のように使い、後続のset_property$my_ipを指定することでそのIPに対する設定が可能です。

  • get_ipdefs: IPカタログ内のIP定義を取得します。-filter-nameで検索可能。引数なしで呼ぶと大量のIPリストが返ってくるため、通常は何らかのフィルタを使います。カスタムIPを取得するには、-allオプションを付けてユーザーIPまで含めることを忘れないでください。例えばget_ipdefs -all xilinx.com:hls:dds_hls:*とすると、カタログ中のxilinx.com:hls:dds_hlsという名前のあらゆるバージョンのIP定義が取得できます。そのリストから特定要素(最新など)を選んで使う、という手法が考えられます。

  • set_property -dict: オブジェクト(IPインスタンス等)のプロパティを一括設定します。-dict [list KEY1 VALUE1 KEY2 VALUE2 ...]の形式で渡し、最後に対象オブジェクトを指定します。IPのパラメータ設定によく使われ、キー名にはCONFIG.<パラメータ名>またはPARAMETER.<パラメータ名>(IPごとに異なる)を指定します。複数設定する場合も一回のset_propertyでまとめて記述できるため便利です。また、ボード周辺の設定(例: M_AXI GPポートのクロック接続先など)にもCONFIGプロパティがありますので、IPを追加したら必要に応じてCONFIG項目を確認しましょう。

  • connect_bd_net / connect_bd_intf_net: ブロックデザイン上のネット(配線)を接続するコマンドです。前者はクロック・リセット・割り込み線などの1ビット~複数ビットのスカラーポート接続に、後者はAXIやストリーム等のバスインターフェイス接続に使います。使用する際はget_bd_pinsまたはget_bd_intf_pinsで、それぞれ接続したいピン(ポート端子)を取得してから渡します。例えば、connect_bd_net [get_bd_pins ip1/clk] [get_bd_pins ip2/clk]とすればip1ip2のクロックピンを同じネットに接続します。同一ネットに複数ピンをぶら下げる場合は、連続してconnect_bd_netで同じネット名に繋ぐか、一度に複数ピンをリストで渡すこともできます。インターフェイス版も同様です。VivadoのExport Block Design機能で生成されたTclを見ると、これらの接続コマンドが多数並んでいるはずです。

  • assign_bd_address: アドレス空間の自動割り当てを行います。SoC設計ではPS側のマスターアドレス空間に各IPのスレーブ領域をマップする必要がありますが、手動でset_property offset等を設定する代わりに、このコマンドで自動的に未使用領域に割り当てられます。使用方法は少し分かりにくいですが、引数に[get_bd_addr_segs <マスター名/アドレス空間名/SEG_IPNAME_BaseName>]という形でアドレスセグメントオブジェクトを指定します(SEG_~はVivadoが内部管理する名前)。割り当て後にget_bd_addr_segsで得られるオブジェクトに対しrangeoffsetプロパティをset_propertyで設定することで、サイズ変更や開始アドレスの調整が可能です。このあたりは必要に応じVivadoのUG (IPIユーザーガイド UG895等)を参照してください。

  • validate_bd_design: ブロックデザインの整合性チェックを行います。未接続ポートがある、パラメータ不整合がある、クロックやリセットが未配置などの場合にエラー/警告を出します。スクリプトの最後に実行し、戻り値やメッセージを確認することで自動化時の問題検出ができます。

  • save_bd_design: ブロックデザインを保存します。Vivado GUIで言うところのFile -> Save Block Designに相当します。Non-Projectモードでは意味がないですが、プロジェクトモードであれば.bdファイルが更新されます。

  • make_wrapper -top: Block DesignからHDLラッパーを生成するコマンドです。bitstream生成にはブロックデザインをHDLモジュールにラップしたファイルが必要になるため、make_wrapper -files [get_files <design_name>.bd] -topを実行しておきます。

  • launch_runs / wait_on_runs: 合成や実装をコマンドラインで回す場合、launch_runs synth_1launch_runs impl_1でRunを実行し、wait_on_runsで完了待ちできます。

(※上記以外にもVivado Tclコマンドは多数ありますが、本記事の範囲に沿って主要なもののみ抜粋しました)

トラブルシューティングと注意点

No Catalog IPs found エラーが出る

初めてカスタムIPをスクリプトで扱う際によく遭遇するのが、"No Catalog IPs found" というエラーです。これは「指定したIPがIPカタログに見つからない」という旨のエラーで、典型的には次のようなメッセージが現れます:

WARNING: [Coretcl 2-175] No Catalog IPs found  
ERROR: [BD::TCL 103-2012] The following IPs are not found in the IP Catalog:  
  xilinx.com:hls:dds_hls:1.0  
Resolution: Please add the repository containing the IP(s) to the project.

上記の例では、xilinx.com:hls:dds_hls:1.0というIPが見つからないと言われています。原因は、先述した「IPリポジトリの追加」がなされていないか、追加したパスが正しくない可能性が高いです。Vivadoは標準IP以外は自動ではカタログに出てこないため、HLSで生成したIPフォルダをプロジェクトのIPリポジトリに含めてからスクリプトを流す必要があります。解決策としては、エラーメッセージにある通り該当IPを含むリポジトリパスをプロジェクトに追加し、update_ip_catalogすることです。具体的には前述のset_property ip_repo_paths ...; update_ip_catalogをエラーが出る前(例えばプロジェクト作成直後、BD作成前)に挿入すればOKです。以下に例を示します:

# 指定のIPリポジトリを追加してカタログ更新(エラー解消のために挿入)
set_property ip_repo_paths "$script_folder/solution1/impl/ip" [current_fileset]
update_ip_catalog

$script_folderはスクリプト自身のディレクトリパスを指す変数(実際にはfile normalize [info script]等で取得)で、上記ではその配下のパスを指定しています。このようにTclスクリプトに直接リポジトリ登録処理を入れておくと、後から単独でスクリプトを実行してもエラー無く復元できるので便利です。実際、VivadoのBlock DesignをエクスポートしたTclをそのまま使うとユーザーIPのパス情報が含まれず、再実行時にエラーになることがあるため、こうした処置が推奨されています。参考までにXilinxのフォーラム記事やKnowledge Base (AR# 70400)でも、同様の対処法が案内されています。

VLNVの不一致・バージョン違い

カスタムIPが見つからないもう一つの要因はVLNVの不一致です。HLSでIPをエクスポートする際、デフォルト値からVendorやLibrary、Nameを変更した場合や、プロジェクト名に依存したNameが付いている場合、スクリプト内のVLNV文字列と実際のIPのVLNVが食い違うことがあります。例えば、HLSエクスポート時にVendorをuser.org、Libraryをuserに変更していたのに、Tclスクリプトではxilinx.com:hls:...のままになっているといったケースです。この場合、当然ながら一致しないためIPが見つかりません。対処法は、正しいVLNVを調べてスクリプトを修正することです。正しいVLNVは、HLS生成フォルダ内のcomponent.xmlをテキストエディタで開くと確認できます。 <spirit:vendor><spirit:library>タグに記載されている内容がそれです。またはVivadoでIPカタログ追加後にGUI上で該当IPを右クリック→Detailsを見てもVLNVが表示されます。これらを参照し、Tcl内のcreate_bd_cell -vlnv引数を修正してください。

また、バージョン違いにも注意です。Vivadoのバージョンを上げた際にザイリンクス提供IPのバージョンが繰り上がることがあります。今回の自作IPはユーザーIPなので自分で変えない限りバージョンは1.0のままですが、スクリプト作成時からHLS IPを再エクスポートしてバージョンを更新した場合(例えば1.1にした等)は、スクリプト側も同じバージョンに合わせるか、前述のlatest_ip的な手法で自動化する必要があります。VivadoのエクスポートされたBD Tclでは、IPバージョンが異なる環境で実行したときに警告を出しつつ継続する仕組みがあります。自前のスクリプトでも、バージョン番号をワイルドカードにしたVLNV指定(例: xilinx.com:hls:dds_hls:*)が可能ですので、環境によって変わり得る部分は柔軟に対応させると良いでしょう。

その他の注意点

  • IPの互換性: HLS IPは基本的に生成に使用したFPGAファミリで使えるようになっています。例えばZynq-7000用に合成したIPはUltraScale+でも使える場合がありますが、Vivadoが「Compatible」かどうかを判断します。もしIPをカタログに追加しても表示されない場合、現在のプロジェクトのデバイスに非対応の可能性があります(HLS IPでは稀ですが)。その際はHLS合成時に適切なset_partを指定して再合成してください。

  • Block Design Tclの再利用: VivadoのBlock DesignはGUI操作からFile -> Export -> Export Block DesignでTclスクリプトに書き出せます。これを用いて一度環境構築したブロックデザインをTcl化し、編集・再実行することで自動プロジェクト生成が可能です。エクスポートされたスクリプトにはIPパラメータや接続も一通り含まれます。本記事で解説したコマンドを理解しておけば、そのエクスポートTclも読み解きやすくなるでしょう。

  • 日本語名やスペース: プロジェクト名やフォルダパスに日本語や空白が入ると、Tclでエスケープが必要になったり予期せぬ不具合のもとになります。可能な限り半角英数字のみで構成することをお勧めします。特にLinux環境ではパスの大文字小文字も区別されるため、HLSスクリプト内とVivado側でパスがずれないよう注意してください。

  • GUIとの併用: Tclスクリプトで自動生成した後にGUIで開いて微修正、といった使い方もできます。ただし、GUIで変更を加えたらwrite_bd_tclwrite_project_tclでTclを書き出しておき、それを元に次回はスクリプトを更新するようにしましょう。でないとスクリプトと手動編集内容が乖離してしまいます。

おわりに

今回は、Vivado HLSで作成したカスタムIPをVivadoのブロックデザインで使用するまでの一連の流れを、初心者向けに解説しました。HLSツールでC++からIPを生成し、VivadoプロジェクトにIPリポジトリを追加してIPカタログに登録、そしてTclスクリプトを用いてブロックデザイン上にIPをインスタンス化する方法を順を追って説明しています。特にスクリプト中のcreate_bd_cellコマンドはIPコアを配置する要となるコマンドであり、その引数であるVLNVや、スクリプト上でバージョンを管理するための工夫(latest_ip相当の処理)について詳しく述べました。また、get_ipdefsによるIP検索、set_property -dictによるIPパラメータ設定、connect_bd_net等による接続方法にも触れています。

最後に、初心者の方がつまづきやすいエラーである「No Catalog IPs found」の対処や、VLNV不一致への注意点についても解説しました。Tclスクリプトは慣れるまで難しく感じるかもしれませんが、一行ずつ意味を追っていけばGUI操作の自動記録にすぎないことがわかるはずです。VivadoのTclコマンドは膨大ですが、公式のTclコマンドリファレンスUG835やユーザーガイドUG894/UG895等に詳細が記載されています。必要に応じてリファレンスを参照しつつ、少しずつスクリプトを書いて試してみてください。

この記事が、Vivado HLS初心者の方が**「生成したIPをどうVivadoで使うか」**を理解する一助になれば幸いです。ブロックデザインTclスクリプトを読み解けるようになれば、大規模なデザインの自動生成やバージョン管理にも役立ちます。ぜひチャレンジしてみてください。お疲れ様でした!

補足事項

古いvivadoを使う場合

コマンド名 対応するツール 状況
vivado_hls Vivado HLS Vivado 2019.1 以前の古いツールチェーン
vitis_hls Vitis HLS Vivado 2019.2 以降の新しい統合環境

なぜ変わったのか?

  • Xilinx は 2019.2 以降、開発ツールを Vivado / SDx / HLS → Vitis に統合
  • これにより、HLS ツールも vivado_hls から vitis_hls に移行。
  • Vitis HLS では、Vivado HLS 互換の .tcl スクリプトや .cpp ファイルが基本的にそのまま動作しますが、プロジェクトの構造や一部オプションが微妙に異なることがあります。

自分の環境で確認するには?

以下のいずれかをターミナルで実行してみてください:

which vivado_hls
which vitis_hls

出力があれば、それがインストールされている方の HLS コマンドです。

例:dds_hls.tcl を使うとき

open_project -reset proj_dds_hls
add_files dds_hls.cpp
set_top dds_hls
open_solution -reset solution1 -flow_target vivado

このような .tcl スクリプトは、Vivado HLS (vivado_hls) に最適化されていますが、vitis_hls でも -flow_target vivado を指定すれば通常問題なく動作します

  • Vivado 2019.1以前 → vivado_hls
  • Vivado 2019.2以降 → vitis_hls(推奨)

どちらで .tcl スクリプトを実行するかは、Vivado/Vitisのバージョンに依存します。

参考文献など

  • Vivado High-Level Synthesis ユーザーガイド (UG902)
  • Vivado IP Integrator ユーザーガイド (UG895)
  • Vivado Tcl コマンドリファレンス (UG835)

理学系のRFSoC関係

  • 「超伝導検出器のマイクロ波読み出し技術開発」 京都大学 鈴木惇也 先生の発表資料

  • 「ダークフォトン探索に向けた広帯域分光計の開発と評価」竹内 広樹 さんの修士論文

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?