LoginSignup
4
5

More than 3 years have passed since last update.

第7回PYNQのHDMI出力overlayを作る

Last updated at Posted at 2019-08-24

はじめに

base overlayでもHDMIスルーやキャプチャはできたのですが、ちょっと物足りない。せっかくなのでなにか画面を出力する回路を作りたい。小林優著「FPGAプログラミング大全 Xilinx編」を頼りにして、VGAのテスト信号をHDMIに出力するoverlayをつくってみました。

第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 ジャンプスタート

方針

道具立て

とりあえず、小林さんの書籍を基にして640x480のVGAのテスト信号を作成する回路をつくり、Digilentさんからvivado用ライブラリとして提供されている「RGB信号をHDMIに出力するrgb2DVI IPコア」を使うことにします。

構成

(phase 1)テスト信号の出力を目指す
とりあえず、ZynqのPSから制御はいらないのですが、あとあと信号を変えたり、フォーマットを変えたりしたくなるので、AXI GPIOで接続する周辺IPとします。
(phase 2)PYNQから自由に作画できるVRAMをつくる
小林さんの本のとおり。

テスト信号作成回路をつくる

プロジェクトをつくる

  1. Zynq (ZC7020)の新規プロジェクトをつくる。
  2. Settingから開発言語を VHDL にかえる

回路をつくる

小林さんの書籍の「2-3 PC用ディスプレイにパターンを表示」を参考ににして回路を作り、シミュレーションで動作を確認します。

  1. 信号フォーマットを確認する。
    VGA信号は、ピクセルクロックが25MHz、有効画素640x480ピクセル、その周りに水平・垂直同期期間があるので、信号のフレーム周期は800x525/25MHz=1/59.52です。
  2. クロックジェネレータ回路(pckgen)を作成
  3. 同期信号とピクセル座標を作成する回路(syncgen)を作成
  4. ピクセル座標に対応する信号を作成する回路(pattern)を作成
  5. テストベンチ回路を作成
  6. チェック

細かな内容は、書籍を参照していただくとして、VHDLで書く時のポイント、書籍とちょっと変えたところなど以下に示します。

pclgen (VGAクロック作成)

クロックジェネレータで150MHzから25MHzのピクセルクロックを作る。クロックイングウィザードを使わず、直接プリミティブにパラメータを入れてインスタンス化している。
将来、VGA以外のサイズに対応させるときに、周波数を変えねばならないため、分周比などのパラメータはGenericで指定する形が良いかと。

syncgen (同期信号作成)

verilogからVHDLに変更するために、以下の書き換えを行う。

  • 信号フォーマットのパラメータをpackageファイルにまとめる。
  • VHDLではverilogのように型変換を自動でしてくれないため、変換を多段階に分解し、各段階に応じた信号を定義する。

pattern

下記のとおり(課題のgraduationも同様)。

  • 書籍のクロックは125MHzだが、AXIクロック100MHzに対応するため、pclgenでパラメタライズした値をGenericポートに追加する
  • vga2DVIでは、pixcel clock、EN(有効画面)が必要なのでこれらの信号を出力ポートに追加
  • 注意点はCLKとPCK(ピクセルクロック)を間違えないようにすること。
  • ピクセル座標をもとにピクセルデータを計算するのだが、ラッチするため1クロック遅延が発生する

overlayをつくる

プロジェクトをつくる

  1. Zynq (ZC7020)の新規プロジェクトをつくる。
  2. Settingから開発言語をVHDLにかえる
  3. ブロックデザインを作る

カスタムIP作成

  1. メニューバーのTools->Create and Package IP...を選択するとwizardが出てくる
  2. Create a new AXI4 peripheralを選択
  3. (中略)
  4. Edit IPを選択してFinish -->カスタムIPのプロジェクトができる
  5. 既に作成した信号作成のファイルを追加する。
  6. RGB信号、同期信号、EN、ピクセルクロックのポートを追加して配線する

rgb2dvi IPの修正と接続

配布されているIPをそのまま結線するとMMCMの実装エラーがでました。VCOの周波数が低すぎるとのこと。marseeさんのFPGAの部屋 AXI VDMAのMM2Sを使用してビデオ出力6(インプリメントしたがエラー)を参考にして解決しました。

  • エラーはピクセルクロックからピクセルクロックとその5倍のクロックを作成する(ClockGen.vhd)のMMCMで起こっている。
  • ピクセルクロック(25MHz)が低すぎてVCOの下限周波数を下回る。
  • MMCMのフィードバック係数の値(分周比)を大きくする修正を加えることで、VCOの周波数を高くする。
  • VCOの周波数はrgb2dviの設定メニューで変更することができるのだが、配布されたパッケージでは分周比は5(=1x5)もしくは10(=2x5)にしか設定できない。そこで、以下のようにIPコアを修正し25(=5x5)を選択できるようにする。

(IPコアの修正)
1. rgb2dviを右クリックしてIP packagerで開く
2. Customization Parameters をクリックし
3. kClkRange の Value Validation List に 25MHz (5)を追加する。この項を選択すると、(5)を5倍した値(5 x 5 =25)が分周比となるので、25MHzx25=625MHzがVCOの周波数になる。
4. Re-packageし、IP packagerを終了する

(IPコア修正をプロジェクトに反映)
1. Reportメニューから[Report IP Status]を選び
2. 下段のペインのIP Status タグを選び
3. rgb2dviを選択し [Upgrade Selected]ボタンをクリック

(rgb2dviへの接続)
R,G,Bの信号をcatで結合し、24bitの信号pDataをつくる。ここで、MSBからR,B,Gの順序で結合すること。
pData<-R_DATA&B_DATA&G_DATA
参考 rgb2dviのドキュメント
参考2 tom01hさんの雑多な趣味の記録帳

(bitファイルを作成しPYNQ-Z1にコピー)
(略)

テスト

HDMI TXとディスプレーを接続しておき、Jupyter notebook にて新たに作成したbitファイルを読み込めば、信号が出力される。

VRAM化

VRAMのメモリアドレスをちゃんと確保してやらないといけません。
第3回 pythonとPYNQ PL資源へのアクセスを参考にしてCMAメモリを確保します。

バッファ取得関数の定義
import numpy as np
import pynq

def get_pynq_buffer(shape, dtype):
    return pynq.Xlnk().cma_array(shape, dtype)
uint16の480x640配列バッファを確保
buffer = get_pynq_buffer(shape=(480,640), dtype=np.uint16)
GPIO_0でbufferの物理アドレスを送る例
from pynq import MMIO
mmio=MMIO(int(PL.ip_dict["axi_gpio_0"]['phys_addr']),4,True)
mmio.write(0, buffer.physical_address)

あとは、buffer(y,x)にピクセルデータをかくだけ。

まとめ

質問あれば、更新します。

こちらも参考になりそうです。@iwatake2222 さんの記事ZYBO (Zynq) でHDMI出力をする

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5