はじめに
前回PYNQのOverlayまでつくることができました。いろいろなハードウェア回路を作って、ソフトからアクセスするには、これらの回路にAXIインターフェースをつけて、カスタムIPとして登録しなければなりません。
ちょっと敷居がたかそうですが、@kamotsuruさんの PYNQ-Z1でカスタムIP作成してLEDチカをなぞって、試してみました。なお、VHDL派ですので、ちょっとだけ変えましたが。
第1回 Setup PYNQ-Z1
第2回 はじめてのJupyter
第3回 pythonとPYNQ PL資源へのアクセス
第4回 PYNQ OVERLAY
第5回 PYNQのOverlayを作ってみた
第6回 カスタムIPを作ってPYNQ overlayに組み込む
第7回 PYNQのHDMI出力overlayを作る
番外編 python ジャンプスタート
プロジェクトとブロックデザインの作成
これは、第5回 PYNQのOverlayを作ってみたのZynqのピンの接続までは同じです。
開発言語をverilogからVHDLに変更
わたしは、VHDLの方がなれているので、デフォルトの開発言語をverilogからVHDLに変えます。
- flow navigatorのSettingをクリックして、Setting ダイヤログを表示
- Project SettingのGeneralを選択しGeneralペインを表示
- Target LanguageをVHDLに変更してOK
カスタムIP作成
ここからは、@kamotsuruさんのPYNQ-Z1でカスタムIP作成してLEDチカの3以降と、小林優さんの書籍FPGAプログラミング大全 Xilinx編など参考にしました。
- メニューバーのTools->Create and Package IP...を選択するとwizardが出てくる
- Create a new AXI4 peripheralを選択
- (中略)
- Edit IPを選択してFinish
カスタムIPのプロジェクトができる
カスタムIPプロジェクトで回路を作成
AXIインターフェスを記述する回路(IP名_v1_0_S00_AXI.vhd)とそのラッパー回路(IP名_v1_0.vhd)を書き換える。
このIPは基盤上の次のLEDとボタンと接続する。
- 出力はled[3:0],rgbled4[2:0],rgbled5[2:0]
- 入力はbtn[3:0]
32ビットレジスタへの割りつけは
- レジスタ0(アドレス0)下位4ビット出力にLED
- レジスタ1(アドレス4)下位3ビット出力にLED4
- レジスタ2(アドレス8)下位3ビット出力にLED5
- レジスタ0(アドレス0)19から16ビット入力にbtn
とします。
entity IP名_v1_0_S00_AXI is
PORT(
-- users to add ports here
btn: in std_logic_vector(3 downto 0);
led: out std_logic_vector(3 downto 0);
rgbled4: out std_logic_vector(2 downto 0);
rgbled5: out std_logic_vector(2 downto 0);
-- User ports end
...
)
end IP名_v1_0_S00_AXI;
architecture arch_imp of xxxx
...
begin
...
-- 読み出し
case loc_addr is
when b"00" =>
reg_data_out <=X"000" & btn & X"0000";
...
-- 書き込み
-- Add user logic here
led <= slv_reg0( 3 downto 0);
rgbled4<=slv_reg1( 2 downto 0);
rgbled5<=slv_reg2( 2 downto 0);
-- Use logic ends
end arch_imp
ラッパーのvhdファイルにもポートを追加して配線する(略)
カスタムIPのパッケージを整える
- Package IPペインから、Customization Parametersを選択
- 右上ののMerge changes from~をクリック
- Cutomization GUIを選択して端子の追加を確認
- Review and Packageを選択し、Re Package IP
カスタムIPをブロックデザインに追加し
(略)
端子を配線しValidate Design
(略)
Create HDL Wrapper
Sources->Design Sources->[ブロックデザイン]を右クリックして Create HDL Wrapper
(略)
制約ファイルを作成
PYNQの制約ファイルをcopyしてきて、btn,led,rgbledを有効化する
なお、RGB LEDの記述を簡単にするためRGBをstd_logic_vector形式に変更する。具体的にはled4_r
をrgbled4[2]
のように、R,G,Bの信号3本をまとめて、配列にしrgbled4[2],rgbled4[1],rgbled4[0]のようにリネームする。
ビットストリームを作成
(略)
tcl,hwh,ビットストリームをコピー
tcl,hwhはプロジェクト名.src/source_1/bd/デザイン名/hw_handoff/
の中にあります。
Jupyterからアクセス
基本は@kamotsuruさんの記事を参考に
from pynq import Overlay
from pynq import PL
OL = Overlay("/home/xilinx/pynq/overlays/適当なフォルダ/design_1.bit")
ip_dictでIPの名前情報を確認する
PL.ip_dict
Memory Mapped IOでアクセスする。
from pynq import MMIO
mmio=MMIO(int(PL.ip_dict["myIP_0"]['phys_addr']),12,True)
mmio.write(0,15) # LED0から3を点灯
mmio.write(4,6) # LED4を黄色点灯
mmio.write(8,4) # LED5を赤色点灯
mmio.read(0)>>16 # btn0からbtn3を読み出す
カスタムIPの再編集
カスタムIPの中身を再編集する場合は、IP Packagerから行います。これには、次の手順を踏む必要があります。
- IPカタログをクリック
- user repositoryからカスタムIPを選択
- 右クリックしてEdit in IP Packager
まとめ
- Tools->Create and Package IP...からCreate a new AXI4 peripheralでAXI4のカスタムIPプロジェクトを作成する
- portを追加する
- AXIの出力レジスタ、読み出しポートを周辺回路と結線する
- カスタムIPをブロックデザインに追加する
- overlayファイルを作成する
- Jupyterからip_dictでIPの名前情報を確認する
- IPの名前と物理アドレスを用いてMMIOオブジェクトを作成
- MMIOを経由して入出力をおこなう