前回までの記事では Digilent が提供している ZYBO Base Design をそのまま使って FreeBSD を起動する、というのをやったのですが、この Base Design には HDMI のコントローラやら何やらが載っており、それなりに PL 部のリソースを使っています。自分で hack する以上は、PL 部はほとんどからっぽ、という状態からスタートしたいのが人情です。
というわけで、自分でやってみました。結果からいうと簡単で自明な理由なのですが、実はけっこうはまりましたので、記録としてここに残しておこうと思います。
作業を始める前に、Digilent のウェブサイトから ZYBO_zynq_def.xml (ZYBO Board Definition File for configuring the Zynq Processing System core in Xilinx Platform Studio and Vivado IP Integrator) をダウンロードしておくと便利です。これを使うと、クロックや MIO の設定などを ZYBO 用に一括で設定可能です (ZedBoard 用もあります)。
- Vivado のプロジェクトを作る (XC7Z010-CLG400-1)
- Create Block Design で新しいブロックデザインを開く
- Add IP で Zynq7 Processing System を加える
- 現れた Zynq PS のブロックをダブルクリックして設定画面を開く
これで、”Import XPS Settings” からさきほどの ZYBO_zynq_def.xml を読み込むと、画面が以下のようになります。
I2C や UART1, SD0, USB0, ENET0 などにチェックが入ったら PS の設定は OK です。Clock Configuration や DDR Configuration なども正しく設定されているはずです。このあと、PS 周辺部の設定をしていきます。
ポイントは、
- DDR と FIXED_IO は Make External する (これは自動でもできる)
- IIC_0 (I2Cのこと) も Make External する
- SDIO0_WP は Low に落とす
- Master AXI GP port のクロックは FCLK_CLK0 をつないでおく
というあたりです。
DDR (DDR SDRAM) と、FIXED_IO (固定機能ピン) は右クリックして “Make External” すれば下の図のようにブロックの出力ポートとなり、これはピンが決まっているので、なにもしなくても配置配線後にちゃんと外にでてくれます。
IIC_0 (I2C) も同様に Make External してブロックの外に出しますが、これは Zynq PS の設定の Peripheral I/O Pins の画面で見ると “EMIO” でなっており、PL 部の programmable fabric につながるので、最終的にどこのピンにつながるかを自分で指定する必要があります。
I2C、何に使うのかわからなくて放置していたのですが、実は ZYBO では MAC アドレスが I2C ROM に記録されており、FSBL を書き換えるところのコード (fsbl_hooks.c) ではこの ROM を参照しにいっています。このとき I2C が配線されていないとそこで止まってしまい、OS の起動までたどり着けないので注意しましょう。
また、ZYBO には Micro SD カードスロットが載っていますが、Micro SD なので Write Protect の検出がありません。これも EMIO に出ているピンですので、Add IP で “Constant” を呼び出して、値を 0 にして SDIO0_WP につないでしまいましょう。
Master AXI ポートがひとつありますが、いまのところ使わないので、このクロックは FCLK_CLK0 につないでおけばよいでしょう。何もつながないとエラーになります。
ということで、できあがりの block design は下のようになります。
あとは、
- Generate Block Design する (Flow navigator で)
- Create HDL Wrapper する (デザイン階層でブロックデザインを右クリック)
- I2C のピンを制約に追加して bitstream 生成
すれば OK です。
デフォルトで HDL Wrapper に現れる I2C なポートの名前は iic_0_scl_io と iic_0_sda_io だと思いますので、以下を XDC ファイルに追加すれば OK です。これを書かずにやると、I2C のピンがどこか知らないところへ行ってしまうので気を付けましょう。
[code:plain]
set_property PACKAGE_PIN N18 [get_ports iic_0_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_0_scl_io]
set_property PACKAGE_PIN N17 [get_ports iic_0_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_0_sda_io]
[/code]