1500円ZYNQ基板でFPGAプログラミング大全Xilinx編(第2版)の実習 9-2 グラフィック表示回路 IP の組み込み / 9-3 動作確認

#はじめに
1500円 ZYNQ 基板(EBAZ4205)で、
FPGAプログラミング大全Xilinx編(第2版)の
課題9-2「グラフィック表示回路の検証と組み込み」と、
課題9-3「動作確認と実機デバッグ」
を実習したいと思います。

#プロジェクトの概要
DDR3 上にフレームバッファを作成し、PL で表示データを読み出して HDMI から画像として出力する、というのがこのプロジェクトの概要です。
PS(ARM)のメインメモリである DDR3 上にバッファが用意されていて、PS から指定アドレスに表示データを書き込むだけで、HDMI から画像として出力されます。

設計については、大全で解説されている通りです。

グラフィック表示回路の IP パッケージ作成までが前半の作業、
回路デザインを作成して、ARM プログラムで画を描いて表示するまでが後半の作業、
となっています。

EBAZ4205 からの HDMI 出力には、
[1500円ZYNQ基板でFPGAプログラミング大全Xilinx編(第2版)の実習 2-3 HDMIでパターン表示](https://qiita.com/kan573/items/44ced51037d221a4d171#hdmi-%E5%87%BA%E5%8A%9B%E3%81%AE%E6%8E%A5%E7%B6%9A%E5%9B%B3)
で作成した HDMI 出力ケーブルを使用します。
![16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/08204a59-2144-685e-0d6b-073d1e090018.jpeg)

#グラフィック表示回路の IP 作成とフレームバッファの生成

p.405～ に書かれている手順に沿って進めます。

##1. プロジェクトの準備
ダウンロードした大全のサポートファイルから、
\XilinxFPGA_SE\Zybo_Z7-10\dai9sho\display
を、フォルダごとデスクトップにコピーして、Vivado の作業フォルダとします。

フォルダの中にある、display.tcl は削除します。
display.xdc は、EBAZ4205 用の制約ファイルと置き換えます。

```display_ebaz4205.xdc
# EBAZ4205 constraints file
# chapter: 9
# project: display

#HDMI TX
set_property -dict { PACKAGE_PIN D20   IOSTANDARD TMDS_33  } [get_ports { HDMI_CLK_N }];
set_property -dict { PACKAGE_PIN D19   IOSTANDARD TMDS_33  } [get_ports { HDMI_CLK_P }];
set_property -dict { PACKAGE_PIN B20   IOSTANDARD TMDS_33  } [get_ports { HDMI_N[0] }];
set_property -dict { PACKAGE_PIN C20   IOSTANDARD TMDS_33  } [get_ports { HDMI_P[0] }];
set_property -dict { PACKAGE_PIN A20   IOSTANDARD TMDS_33  } [get_ports { HDMI_N[1] }];
set_property -dict { PACKAGE_PIN B19   IOSTANDARD TMDS_33  } [get_ports { HDMI_P[1] }];
set_property -dict { PACKAGE_PIN H17   IOSTANDARD TMDS_33  } [get_ports { HDMI_N[2] }];
set_property -dict { PACKAGE_PIN H16   IOSTANDARD TMDS_33  } [get_ports { HDMI_P[2] }];

#Single LED
set_property -dict { PACKAGE_PIN W13   IOSTANDARD LVCMOS33 } [get_ports { LED[0] }];
set_property -dict { PACKAGE_PIN W14   IOSTANDARD LVCMOS33 } [get_ports { LED[1] }];

# false path
set_clock_groups -asynchronous -group [get_clocks clk_fpga_0] \
    -group [get_clocks -include_generated_clocks clk_fpga_0 -filter {NAME !~ clk_fpga_0}]

```


\XilinxFPGA_SE\COMMON
も、フォルダごとデスクトップにコピーしておきます。
後で使う HDMI_VGA の IP です。

##2. プロジェクトと IP パッケージの作成
シミュレーションは省略して、そのままプロジェクトを作成します。

Vivado を起動したら、Create Project で親プロジェクトを作成します。
・プロジェクト名: display
・プロジェクトのフォルダ: \desktop\display (上でコピーしたフォルダ)
とします。

Default part は xc7z010clg400-1 を選択。

プロジェクトが開けたら、
Tools → Create and Package New IP...
を開きます。

・ディレクトリ: /Desktop/display/disp_ip
・プロジェクト名: disp_ip
・プロジェクトのロケーション: (デフォルトのまま)
として進めます。

disp_ip フォルダからソースが読み込まれると、disp_fifo だけ不足した状態で起動します。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/b13698cf-94c1-6ea7-fe2b-33a59c560141.png)

IP CATALOG から FIFO Generator を選び、p.405-p.410 の通りに設定して disp_fifo を作成します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/adccbbbd-a857-4b94-7c43-97dee9ce57e7.png)

File Groups で登録されたファイルを確認して、Synthesis (8) になっていれば完成です。
disp_fifo.xci が登録されない時は、p.315 の不具合対策を実施してみてください。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/ffec76fc-f03d-e525-d6d7-4d8c0ebe940a.png)

全て解決したら、Review and Package から Re-Package IP を押して IP パッケージの作成を完了します。

edit_ip_project が閉じられ、display プロジェクトに戻ります。
シミュレーションは省略して、システムの構築と動作確認に移ります。


#システムへの組み込み
p.412 【9-2-2】Zynq システムへの組み込み
に沿って進めます。
EBAZ4205 専用の部分が必要ですので、順に説明します。

##1. HDMI_VGA の IP カタログへの登録
p.414 ◎グラフィック表示回路と HDMI/VGA 変換回路を IP として登録
display プロジェクトが開いているところで、
PROJECT MANAGER → Settings から IP の Repository を開いて、
C:\Users\(ユーザー名)\Desktop\COMMON
を追加します。

先ほど作成した display_ip も登録されているので、2 つの IP が使えるようになります。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/f90b17a9-c1a5-2fe5-6406-f4b8714d81e5.png)

OK を押して、IP の登録を完了します。


##2. システムの構築
最初にシステムを作成します。
IP INTEGRATOR から Create Block Design を選択し、新規デザインを作成します。
Design name はデフォルトのままでよいです。

design_1 が開きますので、Diagram ウィンドウの + を押して ZYNQ7 Processing System を追加します。

##3. PS の設定
ZYNQ7 Processing System をダブルクリックして、PS の設定を行います。
設定内容は、
[1500円ZYNQ基板でFPGAプログラミング大全Xilinx編(第2版)の実習 5-2 Zynqシステムのハードウェア構築 - PS の詳細設定](https://qiita.com/kan573/items/3c1ca1c4cd7ff94da38c#ps-%E3%81%AE%E8%A9%B3%E7%B4%B0%E8%A8%AD%E5%AE%9A)
の通りでよいですが、２か所を変更します。

>1. PS-PL Configuration - HP Slave AXI Interface
> S AXI HP0 interface にチェックを入れて有効化
>
>2. Clock Configuration - PL Fabric Clocks
> FCLK_CLK0 : 50MHz → 100MHz に変更

![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/478c461e-be55-e245-cde7-731e67fe3f61.png)
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/d11d0b77-265a-d9d2-77c9-12f3737f326a.png)



##4. 各 IP の追加とダイアグラムの完成
p.414 ◎システムに組み込む (図9-18)
・display_v1_0 と hdmi_vga_v1_0 を配置
・Run Connection Autiomation で AXI バスを接続

p.415 ◎GPIO の追加と設定 (図9-19)
・GPIO を 2 つ追加 (axi_gpio_0, axi_gpio_1)
・2つのGPIOを p.415 の通りに設定
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/85d0c406-7737-04ca-1ead-2426a388f7c3.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/1018e9ee-2b57-1a67-3877-6cdaa27b68f5.png)

・Run Connection Autiomation で AXI バスを接続
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/f76a2016-f00f-548e-75ec-bc5309c465ee.png)

p.416 ◎グラフィック表示回路 IP の配線 (図9-20)
・axi_gpio_0 の gpio_io_o[29:0] と、display_v1_0 の DISPADDR[29:0] を接続
・axi_gpio_0 の gpio2_io_o[0:0] と、display_v1_0 の DISPON を接続
・axi_gpio_1 の gpio_io_i[0:0] と、display_v1_0 の VBLANK を接続
・axi_gpio_1 の gpio2_io_o[0:0] と、display_v1_0 の CLRVBLNK を接続
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/b3846fe6-f91f-3432-1004-53b41814ff0e.png)

・display_v1_0 と hdmi_vga_v1_0 の対応する入出力を接続
>   VGA_R[7:0], VGA_G[7:0], VGA_B[7:0]
>   PCK, VGA_HS, VGA_VS, VGA_DE

![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/be1f2d78-51c1-132a-7959-ec4668841ed1.png)


・hdmi_vga_v1_0 の nRST を PS の FCLK_RESET0_N と接続

p.418 ◎FIFO のフラグ出力を配線 (図9-21)
・Concat を配置する (IP の設定はデフォルトのままでよい)
・Concat の In0[0:0] と、display_v1_0 の FIFO_UNDER を接続
・Concat の In1[0:0] と、display_v1_0 の FIFO_OVER を接続
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/7d3fb19e-972c-72f4-53dd-c22564355f73.png)

・LED の点灯論理が逆なので、Add IP で Utility Vector Logic を追加
・Utility Vector Logic をダブルクリックして設定を開き、C_SIZE を 2、C_OPERATION を NOT にしてOK
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/b538907e-282a-5256-ca31-8abe1438675d.png)

・Utility Vector Logic の Op1[1:0] と Concat の dout[1:0] を接続
・Utility Vector Logic の Res[1:0] で右クリックして Make External を実施し、出力信号名を LED に変更
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/fe1da8ac-e258-25af-ce16-a0c58998b824.png)

・hdmi_vga_v1_0 の出力端子でも Make External し、出力信号名から _0 を削る
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/2475047b-cdef-d8ce-f73c-0539b89fdc5c.png)

・Diagram ウィンドウ上で右クリックし、Regenerate Layout でレイアウト配置を最適化
・Validate Design でチェック

これでダイアグラムが完成しました。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/6a4ab38f-82eb-6b3c-c71f-69e5cd756e9c.png)

##5. 上位階層の作成からエクスポートまで
・Create HDL Wrapper で上位階層を作成
・display_ebaz4205.xdc の読み込み
・Generate Bitstream でコンパイル

問題なくコンパイルが完了したら、Include bitstream の設定でエクスポートします。
File → Export → Export Hardware → Platform type = Fixed で Next → Include bitstream で Next →
 XSA file name: display
 Export to: \desktop\display.vitis
で Next → Finish

display.xsa が作成され、エクスポートが完了しました。

#動作確認
ワークスペースを、
C:\Users\(ユーザー名)\Desktop\display.vitis
として、Vitis を起動します。

・プラットフォームプロジェクトを display.xsa から作成します。out-of-date なので、先に Build Project しておきます。
・アプリケーションプロジェクトを作成します。Applicaion Project name は disp_test とし、Empty Application で作成します。
・アプリケーションプロジェクトの src フォルダに、disp_test.c を登録します。

##1. テストプログラムの変更
グラフィック表示回路では、DDR3 の領域の後部を、フレームバッファ(VRAM)に割り当て、そこに表示データを書き込むことで、画面表示を行います。

搭載された DDR3 メモリの大きさは、ボードにより違いがあります。

Cora Z7 : 0x0000_0000～0x1FFF_FFFF の 512M バイト
Zybo Z7 : 0x0000_0000～0x3FFF_FFFF の 1G バイト

大全の課題 9-3 で示されているテストプログラム disp_test.c では、DDR3 の領域を前部と後部に分けて利用しています。

前部 256M バイト: 0x0000_0000～0x0FFF_FFFF = プログラムで使用するエリア (Cora Z7/Zybo Z7 共通)

後部 256M バイト: 0x1000_0000～0x1FFF_FFFF = VRAM として使用するエリア (Cora Z7)
後部 768M バイト: 0x1000_0000～0x3FFF_FFFF = VRAM として使用するエリア (Zybo Z7)

![14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/3f50ef24-90fd-4ece-e52a-abeb36219e99.jpeg)

EBAZ4205 では、搭載されている DDR3 メモリが 256M バイトしかありません。
前部に 256MB を割り当ててしまうと、後部エリアが無くなってしまいます。

そこで、下記のように割り当てを変更します。
前部 128M バイト: 0x0000_0000～0x07FF_FFFF = プログラムで使用するエリア (EBAZ4205)
後部 128M バイト: 0x0800_0000～0x0FFF_FFFF = VRAM として使用するエリア (EBAZ4205)
![15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/5eb18eaf-9d4d-3673-323c-3dda3a5e29c7.jpeg)


このため、テストプログラム disp_test.c の2箇所を変更します。

>L19: #define VRAM ((volatile unsigned int *) 0x10000000)
> 0x10000000 ⇒ 0x08000000 へ変更
>
>L67:  XGpio_DiscreteWrite(&GpioAddrOn, DISPADDR, 0x10000000);
> 0x10000000 ⇒ 0x08000000 へ変更

L19 はプログラム上で VRAM として扱うアドレスの設定、
L67 は PL の表示回路が AXI 経由で PS-DDR から読み出すアドレスの設定、
となっています。

##2. プログラムの実行
・アプリケーションプロジェクトを Build Project します。
・Debug Configurations を作成して、デバッグを開始します。
・disp_test.c のブレークポイント指定4箇所にブレークポイントを設定してから、Resume ボタンを押します。
(disp_test.c の行番号表示の左横の網部分をダブルクリックすると、ブレークポイントが設定できます)

3番目のブレークポイントでの表示。
※外周白枠の右側が水色に見えるのは、HDMIモニタLV5382のバグのようです。
![12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/b2912810-33a5-503c-4a78-e5c723c06101.jpeg)

4番目のブレークポイントでの表示。
![13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/933d9c0a-e829-47cb-4a11-5cdd51f36087.jpeg)

無事、動作させることができました。

#課題【9-4-1】SD カードの画像ファイルを読み出して表示する
上で作成したプラットフォームプロジェクトを流用して、SD カードの画像ファイルを読み出して表示するのを実行してみます。

p.434 コラム I の通り、プラットフォームプロジェクトの BSP を変更します。
FAT ファイルシステムを設定したら、プラットフォームプロジェクトを再ビルドします。

次に新しいアプリケーションプロジェクトを作成し、sd_picture.c を入れてビルドします。
こちらも引数2か所を 0x10000000 ⇒ 0x08000000 に変更しておきます。

FAT フォーマットの microSD カードに、funamori.raw をコピーして、EBAZ4205 のソケットに挿しておきます。

デバッグでブレークポイントを設定して Resume すると、下記表示ができました。
![20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955220/0ad482e2-4ae4-d024-2994-ed444725b710.jpeg)

表示できなかったときは、Vitis Serial Terminal にエラーメッセージが出ますので、確認してみてください。


#まとめ
FPGAプログラミング大全Xilinx編(第2版)の課題9-2
「グラフィック表示回路の検証と組み込み」
と、課題9-3
「動作確認と実機デバッグ」
を EBAZ4205 で実習することができました。