はじめに
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でパターン表示
で作成した HDMI 出力ケーブルを使用します。
グラフィック表示回路の IP 作成とフレームバッファの生成
p.405~ に書かれている手順に沿って進めます。
1. プロジェクトの準備
ダウンロードした大全のサポートファイルから、
\XilinxFPGA_SE\Zybo_Z7-10\dai9sho\display
を、フォルダごとデスクトップにコピーして、Vivado の作業フォルダとします。
フォルダの中にある、display.tcl は削除します。
display.xdc は、EBAZ4205 用の制約ファイルと置き換えます。
# 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 だけ不足した状態で起動します。
IP CATALOG から FIFO Generator を選び、p.405-p.410 の通りに設定して disp_fifo を作成します。
File Groups で登録されたファイルを確認して、Synthesis (8) になっていれば完成です。
disp_fifo.xci が登録されない時は、p.315 の不具合対策を実施してみてください。
全て解決したら、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 が使えるようになります。
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 の詳細設定
の通りでよいですが、2か所を変更します。
PS-PL Configuration - HP Slave AXI Interface
S AXI HP0 interface にチェックを入れて有効化Clock Configuration - PL Fabric Clocks
FCLK_CLK0 : 50MHz → 100MHz に変更
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 の通りに設定
・Run Connection Autiomation で AXI バスを接続
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 を接続
・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
・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 を接続
・LED の点灯論理が逆なので、Add IP で Utility Vector Logic を追加
・Utility Vector Logic をダブルクリックして設定を開き、C_SIZE を 2、C_OPERATION を NOT にしてOK
・Utility Vector Logic の Op1[1:0] と Concat の dout[1:0] を接続
・Utility Vector Logic の Res[1:0] で右クリックして Make External を実施し、出力信号名を LED に変更
・hdmi_vga_v1_0 の出力端子でも Make External し、出力信号名から _0 を削る
・Diagram ウィンドウ上で右クリックし、Regenerate Layout でレイアウト配置を最適化
・Validate Design でチェック
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)
EBAZ4205 では、搭載されている DDR3 メモリが 256M バイトしかありません。
前部に 256MB を割り当ててしまうと、後部エリアが無くなってしまいます。
そこで、下記のように割り当てを変更します。
前部 128M バイト: 0x0000_0000~0x07FF_FFFF = プログラムで使用するエリア (EBAZ4205)
後部 128M バイト: 0x0800_0000~0x0FFF_FFFF = VRAM として使用するエリア (EBAZ4205)
このため、テストプログラム 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のバグのようです。
無事、動作させることができました。
課題【9-4-1】SD カードの画像ファイルを読み出して表示する
上で作成したプラットフォームプロジェクトを流用して、SD カードの画像ファイルを読み出して表示するのを実行してみます。
p.434 コラム I の通り、プラットフォームプロジェクトの BSP を変更します。
FAT ファイルシステムを設定したら、プラットフォームプロジェクトを再ビルドします。
次に新しいアプリケーションプロジェクトを作成し、sd_picture.c を入れてビルドします。
こちらも引数2か所を 0x10000000 ⇒ 0x08000000 に変更しておきます。
FAT フォーマットの microSD カードに、funamori.raw をコピーして、EBAZ4205 のソケットに挿しておきます。
デバッグでブレークポイントを設定して Resume すると、下記表示ができました。
表示できなかったときは、Vitis Serial Terminal にエラーメッセージが出ますので、確認してみてください。
まとめ
FPGAプログラミング大全Xilinx編(第2版)の課題9-2
「グラフィック表示回路の検証と組み込み」
と、課題9-3
「動作確認と実機デバッグ」
を EBAZ4205 で実習することができました。