最近、ようやくVivadoを使い始めました。
私はFPGAの回路をVHDLで書くことが多いのですが、Vivadoのユーザガイドやチュートリアルを見ても、カスタムIPというのは主にXILINXの既存のFIFOやメモリをカスタマイズしたものを指す言葉であって、RTLで一から書くやり方はあまり書かれていないようです。
そこで、手近にあった特電Artix-7ボードを使って、IPインテグレータを使ってRTLのIPを作る方法を練習してみました。
VivadoでRTLのIPの作り方
まず、Vivadoでプロジェクトを作ったら、sources_1ディレクトリの下にnewというフォルダを作って、その下にIP化するフォルダ(ここではledchika)を作ります。その中にVHDLファイルを作ります。

そして、Tools→Create and Package IPを実行します。

Package a specified directoryを選びます。ディレクトリ単位でIP化されるので、AXIバスでも何でもない普通のIPコアの場合は、VHDLのソースディレクトリを分けておかなければなりません。

どのディレクトリをIP化するか聞かれるので、newの下にあるledchikaディレクトリを指定します。

IPを作るための「一時的なプロジェクト」を作るので、その名前を入れます。ここは、デフォルトのedit_ip_projectのままでよいようです。

子プロジェクトでledchika.vhdを編集します。


Package IPをクリックします。

自動的に一時プロジェクトが削除されて、元の親プロジェクトに戻ります。
そうしたらIPカタログの検索ボックスでled・・と打つと、さきほどのledchikaが出てきますので、これをBlockDesignに追加します。

これに適当な入出力ポートを付け回路を完成させます。プロジェクトのHierarchyのところで右クリックし、main.bdのところを右クリックして、Create HDL wrapperを行います。

こうすると、bdのラッパができるので、論理合成、インプリメント、BitStream生成を行います。

Bitファイルが出来上がるので、特電Artix-7ボードに書き込みます。

LEDがチカチカして一安心。

RTLのソースを更新するには
一度作ったIPのソースを変更するには、BlockDesignの上で右クリックし、Edit in IP Packagerを行います。

子プロジェクトが開くので、RTLソースを編集します。

「Package IP」のページを開き、Re-Package IPを押します。(2回目以降だとRe-Packageと出るのが芸が細かいと思います)

親プロジェクトに戻ると、一番上のところに黄色いバーが出て、Report IP Statusと書かれているので、これを押します。

すると、レポートのところにIP Statusというのが開くので、ScanしてUpdate Selectedを行います。つまり、この時点でVivadoはIPが更新されたことを認識しているようです。

Update Selectedを押すと、このようなダイアログが開きます。GlobalかOut of context per IPを選びます。

- Global・・・BD全体を1つのまとまりとして論理合成する。Synthのたびに全IPを再合成するので遅い。
- Out of context per IP・・・個々のIPごとにSynthを行ってデザイン・チェック・ポイントを作成する。こちらの方が論理合成時間が速い。
- Out of context per Block Design・・・サードパーティ製の論理合成ツールを使う場合に選択する??※未確認
このオプションはどれを選んでも良いです。
すると、IP Statusのところに、現在のリビジョンと更新後のリビジョンが表示されます。

もう一度Rerunを押すと、黄色い状態が直り、IPが最新版に更新されたことがわかります。
しかし、この状態で論理合成してBitStreamを生成しても、IPは更新されないのです!!
ハマったー
その原因
今回作ったledchika.vhdというファイルは、Vivadoによって自動的にコピーがいくつか生成されます。書き換えたオリジナルが10:10という時間のものですが、コピーは9:55で最初にIPを生成した時間を指しています。困ったことに、論理合成にはこのコピーのほうが使われてしまうようです。

このコピーは、子プロジェクトで、Re-Packageをしても、親プロジェクトのIP StatusでUpdate Selectedをしても更新されません。そのため、IPのRTLソースを修正しても更新されないようなのです。
対策を考えてみた
① main.bdでReset Output Productsを行う
これが一番、正当なやり方のようですね。これを行うと生成されたコピーも消え、更新されたRTLソースで動作するようになります。

② VHDLのコピーを手動で削除する
この方法でもいけるようです。

③ 子プロジェクトでVersionを意図的に変える
新規のIPを作ったときにはVersion 1.0になっていますが、これを1.0.1とかに変えると、Vivadoは更新されたことを認識するようです。IP StatusのVersionで表示されている(Rev. ●)で、番号が自動でインクリメントしていくやつは更新とは認識されないようです。

逆に、以下の手段では更新したことを認識してくれません。
- 子プロジェクトでSynthやimplを実行する
- IP StatusのUpdate
- IP Chacheの有効無効を切り替える
- Refresh IP Catalogの実行
- Generate Output Productsの実行
いろいろなオプションを変えても、特に効果はないようです。
世界中の悩んでいる人たち
結果的にはReset Output Productsを実行すればよいのですが、世界中には同じようなことで悩んでいる人がいたようです。Reset Output Productsという答えを見つけたので、「"Reset Output Products" vivado」でgoogle検索するといろいろなフォーラムの議論が出てきます。
結論
IPのRTLを修正したら、トップのBDで右クリックして、Reset Output Productsを行わなければならない。

※CoreGenやLogiCoreで作ったIPも全部生成し直しになるけど、仕方ない。
最近のコメント