はじめに
VivadoでZynqを使っているとBlockDiagramでIPコアを接続して回路を配置していくと思いますが、このIPコアをどうやって作るの?と質問を受けたため作り方を解説していきます。
また、複数の信号線を束ねる(インターフェースといいます)方法も説明します。
以前のAXIインターフェースを持つIPの作成方法の記事も参考になると思います。
ブロック図の例(こちらの記事より)
青い箱がIPコア、黒線が信号線、青線がインターフェース
環境
Vivado 2020.1 WebPACK Edition
IPコアって?
IP(Intellectual Property-知的財産)コアは回路を機能単位でまとめたモジュールです。
VivadoではVerilogなどのHDL言語で記述したものを直接FPGAで動かす他にIPコアを複数接続してFPGAに乗せる方法があります(ブロックデザイン機能)。
IPコアはVivadoで用意されていて無償で使えるもののほか、有償で販売されているものあり、もちろん自作することも可能です。
取り扱う回路
ここでは以下の4本の信号線(まとめてCommandインターフェースとします)でデータをやり取りする回路を想定します。
方向 | 名前 | ビット幅 | 説明 |
---|---|---|---|
M>S | ADDR | 4 | アドレス |
M>S | DATA | 8 | データ |
M>S | VALID | 1 | データ・アドレス有効 |
M<S | READY | 1 | 要求受付可否 |
方向のMはマスター、Sはスレーブです。
また、ここでは送信を行うMaster回路とSlave回路を作成します。
(内部の処理はここでは考えないこととします。)
作成する回路と信号線の接続イメージです(なお、クロックとリセットは別で供給します。)
インターフェースの作成
インターフェースの定義ファイルの作成
まずはインターフェースの定義を作成します。
IPやインターフェースの作成を行うにはVivadoで適当なプロジェクトを開くか、IP管理用プロジェクトを作成するかします。
IP管理用プロジェクトを作成する場合は Vivadoを起動後「Tasks」の「Manage IP」を選択し、「New IP Location」を選択します。
ダイアログが表示されるので「Next」を押し、
保存先やボードなどを設定して「Finish」を押します。
Vivadoのプロジェクトを開いた後は「Tools」から「Create Interface Definition...」を選択します。
インターフェースを作成するダイアログが表示されるのでインターフェース名や保存先などを入力します。
この例ではD:/IP/IFフォルダーの下にインターフェースの定義ファイル(XML)が作成されます。
インターフェースの編集
インターフェースの定義ファイルを作成すると編集画面が表示されます。
まずは「Description」(説明)と「Display Name」(表示名-多分GUI上で使われる?)を入力します。
続けてインターフェースにポート(信号線)を追加するため「+」ボタンを押します。
名前 | 説明 |
---|---|
Display Name | 表示名(IPブロックのポート名) |
Description | ポートの説明 |
Default Value | デフォルト値(未接続時にinポートに設定される値) |
Width | ビット幅 -1で自動 |
Presence | 必須(required) or オプション(option) |
Direction | 方向 図の場合SlaveからMasterとなる |
Type | 種別(該当するものがあればチェック) |
なお、制御線のデフォルト値は未接続時に回路がおかしくならないような値を選ぶ必要があります。
例えばVALIDを0にする、BUSYを1にするなど
入力後OKを押すとインターフェースの編集画面にポートが追加されます。
確認して問題がなければ「Save」を押してください。
インターフェースを修正するには?
プロジェクトにIPのパスを設定した後(IP管理用プロジェクトの場合はIPのパスが予め設定されています。また、あるプロジェクトでIPやインターフェースを作成した場合もパスが設定されています。)、「IP Catalog」の「Interfaces」タブを開き、編集したいインターフェースを選択後、編集ボタン「」を選択します。
インターフェース編集画面が表示されます。
IPコアの作成
IPの定義ファイル(と雛形コード)の作成
Vivadoのプロジェクトを開いた後「Tools」から「Create and Package New IP...」を選択します。
ダイアログが表示されるので「Next」を押し、
今回は雛形を作るので「Create a new AXI4 peripheral」を選択し「Next」を押します。
IPの名前や保存場所などを入力して「Next」を押します。
今回は自作インターフェースのみの回路を作るためデフォルトのままにして「Next」を押します。
自作インターフェースとAXIを持つIPを作る場合はここでAXIの設定もします。
※AXIなしでは作成できません。
最後に次に何をするのか聞かれるので「Edit IP」を選択して「Finish」を押します。(IPの定義ファイル(XML)と雛形のVerilogファイル、IP編集用プロジェクトが生成されて開きます。)
※ここで編集しなくても後から編集することもできます。
回路の作成・ファイルの追加削除
まずはIPの中身である回路を記述します。
AXIの雛形でIPを作成すると上位回想のモジュールとAXI本体のモジュールの2つが生成されます。
この内下位モジュールは不要なのでファイルごと削除し、上位モジュールの中の記述を書き換えます。
なお、IP編集用プロジェクトの方でファイルを追加、削除してもIP本体に反映されないため手動で反映させる必要があります。
「Package IP」内の「File Groups」を開き、「Merge changes from File Groups Wizard」を選択します。
※IP編集用プロジェクトはあくまで一時的なものなので、Package IPでIPの定義ファイルに反映させる必要があります。
上位モジュールは今回は適当に実装します。
`timescale 1 ns / 1 ps
module Master_v1_0 #(
parameter CONST_ADDR = 4'd0,
parameter CONST_DATA = 8'd0
) (
input clk,
input rst,
output [3:0] addr,
output [7:0] data,
output valid,
input ready
);
assign addr = CONST_ADDR;
assign data = CONST_DATA;
assign valid = 1;
endmodule
ファイルを追加する場合は「Sources」の「Design Sources」を右クリックして「Add Sources...」を選択します。
一般的にHDL記述の保存場所はIPの保存先のhdlフォルダーの中に配置します。
ファイル追加後は削除時同様に「Merge changes from File Groups Wizard」を選択して同期してください。
なお、ファイルを追加したり作成する場合はIPの定義ファイル(xml)があるフォルダー以下に配置することが推奨されます。
手動でHDL記述を追加する場合
Vivadoのバグなどでうまく同期ができない場合は手動で追加します。
「Package IP」の「File Groups」の「Verilog(VHDL) Synthesis」と「Verilog(VHDL) Simulation」をそれぞれ右クリックして「Add File」を選択して追加します。
この手順で追加した場合はIP編集用プロジェクトに反映されないため一旦プロジェクトを閉じて後述する方法で編集用プロジェクトを再生成する必要があります。
IPコアの設定
ファイルを追加したらIPの設定をしていきます。
IPコアの情報(Identification)
バージョン番号や作成者、IPコアの名前や説明などを入力します。
「Categories」はIPコアのカテゴリーを選択します。ここで選択したものが「IP Catalog」に反映されます。
AXIの雛形で作成するとデフォルトはAXI Peripheralが指定されているためIPカタログ上は図のようになります。
パラメーター(Customization Parameters)
IPコアにGUIで変更可能なパラメーター(Customization Parameters)と隠しパラメーター(Hidden Parameters)を含めることができます。
デフォルトではAXIの雛形のパラメーターが入っています。
Verilogの上位モジュールからこれらのパラメーターを削除した場合はエラーになるかもしれないので一旦削除します。
サンプルのVerilogのように上位モジュールにパラメーターを含む場合は、適当なところを右クリックして「Import IP Parameters...」を選択し
最上位のVerilog/VHDLファイルとモジュール名を選択してOKを押すとインポートできます。
インポート後、デフォルト値や型が期待通りか確認します。
図の例では型とデフォルト値がおかしいので項目をダブルクリックして編集します。
今回はCONST_ADDRは0~15のlong型、CONST_DATAは0,32,64のlong型にしてみました。
ポート(Ports and Interfaces)
IPコアの入出力を指定します。
こちらもAXIの雛形が指定されているためすべてのインターフェースを削除し、再インポートします。
上位モジュール編集時にMerge changes from~が表示され、こちらを押すと自動的に同期される場合がありますが、うまく行かない場合はインターフェースを削除してから再インポートし直すと良いと思います。
まず表示されているすべてのインターフェースを削除し、ポートだけの状態にします。
インターフェースを削除するには削除したいインターフェースを右クリックし「Remvoe Interface」を選択します。
「Clock and Reset Signals」などのフォルダー内にもインターフェースがあるため全て削除します。
次に適当なところを右クリックして「Import IP Ports...」を選択します。
上位モジュールのVerilog/VHDLファイルとモジュール名を選択してOKを押します。
図のようにサンプルのVerilogの入出力と同じものが表示されると思います。
続けてて、クロック、リセット、インターフェースの割当を行います。
クロックやリセットのポートを右クリックし、「Auto Infer Signle Bit Interface」を選択し、「Clock」や「Reset」を選択します。
インターフェースはインターフェースを構成するポートを複数選択し、「Auto Infer Interface...」を選択します。
インターフェースを選択するダイアログが表示されるので、先ほど作成したインターフェースを選択します。
インターフェースの編集ダイアログが表示されます。
Generalタブにはインターフェースの名前やMaster/Slave設定、説明などが変更できます。
Port MappingはIPのポートとインターフェースのポートの対応付けを行います。
Master/SlaveとPort Mappingはポート名が同じであれば自動的に推定されてマッピングされます。
マッピングがおかしい場合はMapped Ports Summaryから削除したいものを選択し「」を押して削除した後に
「Interface's Logical Ports」と「IP's Physical Ports」からそれぞれポートを選択後「Map Ports」を選択して対応付けます。
対応付を確認後OKを押してインターフェースを登録します。
最後にインターフェースとクロックを対応付けるため、作成したインターフェースを右クリックして「Associate Clocks...」を選択します。
最初に登録したClockが表示されると思うので、それにチェックを入れてOKを押して閉じます。
メモリ空間(Addressing and Memory)
AXIがアクセスするメモリの範囲などを設定します。AXIの雛形を使用してIPを作成後、AXIのインターフェースを削除した場合は不要なので削除します。
MemoryMap名を右クリックして「Remove Memory Map」を選択することで削除できます。
GUIの設定(Customization GUI)
BlockDiagramでIPコアを追加するときに表示されるダイアログをカスタマイズできます。先程パラメーターを追加したものが編集できることが確認できると思います。
特に問題なければそのままにしておきます。
IPのパッケージ(Review and Package)
最後にIPコアのエラーや保存場所などを確認し、問題なければ「Re-Package IP」を選択してIPコアの設定を保存します。
Slaveの作成
SlaveもMaster同様に作成します。以下に最上位モジュールのVerilogコードを示します。
`timescale 1 ns / 1 ps
module Slave_v1_0 (
input clk,
input rst,
input [3:0] addr,
input [7:0] data,
input valid,
output ready
);
assign ready = 1;
endmodule
IPコアを再編集するには?
IP Catalogから作成したIPを探し、右クリックして「Edit in IP Packeger」を選択することで編集用一時プロジェクトを生成して編集できます。
IPコアを利用する
最後に作成したIPを利用して見ます。
とりあえずVivadoでRTLプロジェクトを作成します。
Verilogファイルはついかしないので途中のProject Typeは Do not specify sources at this timeにチェックを入れるとダイアログの量が減ります。
プロジェクト設定
作成したIPのパスをプロジェクトに設定します。
「Flow Navigator」の「Settings」を選択して設定画面を開きます。
「ProjectSettings」の中から「IP」を開き、「Repository」を選択します。
IP RepositoriesにIP(やインターフェース)のパスを設定しますので、追加ボタン「」を選択して、IPの保存場所を指定します(再帰的に探してくれるので保存先のルートフォルダーを指定すれば良いです)。
IPやインターフェースが見つかれば一覧が表示されます。
Master/SlaveとCommandが含まれていることを確認し、設定画面も閉じてください。
これでIPとインターフェースがIP Catalogに登録されます。
ブロックデザイン
最後にブロックデザインを作成します。
「Flow Navigator」の「Create Block Design」を選択し、
名前などを適当に入力して作成します。
続けて空のブロックデザインに作成したIPを追加します。
適当なところを右クリックして「Add IP...」を選択すると
IP検索ボックスが表示されるのでMasterを探し、ダブルクリックして追加します。
ここで追加されたMasterをダブルクリックするとパラメーター編集画面が表示されます。
IP作成時に指定した Const AddrパラメーターとConst Dataパラメーターが変更できることが確認できます。
ここでMasterのCommandの横の「」にカーソルを載せクリックしながらSlaveの「」までカーソルを持っていき離すとインターフェースの接続ができます。
これで自作インターフェース付きIPがブロックデザインで利用できることが確認できました。
TIPS
IPにアイコンを入れたい
JPEG, GIF, PNGのアイコンに対応しています。
(サイズに関してはドキュメントに記載が無いのです(見つけられてないだけかも)が、自動的にリサイズされますので、試行錯誤して丁度いいサイズを見つける必要があります。)
例えば以下のようなicon.png(32px*32px)を用意したとして、IPにアイコンを組み込んでみます。
まず、IPの編集用プロジェクトを開き、「Package IP」から「File Groups」を開き、適当なところを右クリックして「Add File Group...」を選択します。
ダイアログが表示されるので「Advanced」の中から「Utility XIT/TTCL」を選び「OK」を押します。
File GroupsにUtility XIT/TTCLが追加されました。
続けてアイコンファイルを登録します。
「File Groups」の「Advanced」の中の「Utility XIT/TTCL」を右クリックし「Add Files...」を選択します。
ファイルを追加するダイアログが表示されるので「Add Files」を押してアイコンファイルを選択し、OKを押して閉じます。
次にRe-Package IPを押して保存して閉じます。
このままではIconが表示されないためIP定義ファイル(component.xml)を手動で編集します。
追加したアイコンファイルに関する部分を探し、userFileType imageの下にLOGOを追加します。
<spirit:fileSet>
<spirit:name>xilinx_utilityxitfiles_view_fileset</spirit:name>
<spirit:file>
<spirit:name>icon.png</spirit:name>
<spirit:userFileType>image</spirit:userFileType>
<spirit:userFileType>LOGO</spirit:userFileType> <!-- NEW -->
</spirit:file>
</spirit:fileSet>
</spirit:fileSets>
xmlを保存して閉じます。
この後ブロックデザインに戻り、アイコンを追加したIPを追加すると以下のようにアイコンが表示されます。
資料
UG994 Vivado Design Suite ユーザー ガイド: IP インテグレーターを使用した IP サブシステムの設計