FC2カウンター FPGAの部屋 2014年02月
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

VivadoでZYBO用LEDテストプロジェクト2(プロジェクト作製、ビットストリーム生成まで)

”VivadoでZYBO用LEDテストプロジェクト1(単体テスト)”の続き。

やっと、Vivado 2013.4でZYBO用LEDテストプロジェクトが動いたので、ブログに書くことにする。IP Integrator にAdd IPしたZYNQのPS部のZYBO用のコンフィギュレーションをするのを忘れてビットストリームの生成まで全部走らせたら二度とシリアルが動かなくなってしまった。Vivado 2013.4で不可解な現象が起きたら、さっさとプロジェクトを作り直すことを強くお勧めする。

さて、前回、Vivado 2013.4で単体テストを行ったので、今回やることを箇条書きにする。

1.Vivado 2013.4のプロジェクトを作製する。
2.IP Integrator で、Block Design (Vivado_ZYBO_led_test) を作製する。
3.Gnerate Block Desgin を行う。
4.Synthesis を行う。
5.Open Synthesized Design を起動して、配置制約、IO_STANDARD制約を生成する。
6.Implementaion, Benerate Bitstream を行う。
7.Export Hardware for SDK... を実行して、ハードウェアをSDKにエクスポートして、SDKを同時に立ち上げる。
8.SDKでApplication Project (led_axi_lite_slave) を作製する。
9・SDKで、Program FPGAでZynqのFPGA部にビットストリームをダウンロードする。
10.SDKで、led_axi_lite_slaveのRun Configuration を作製し、Runを実行する。


さて、Vivado 2013.4のプロジェクトの作製から行う。

・Vivado 2013.4の xc7x010clg400-1 用のプロジェクトを作製した。
Vivado_ZYBO_LED_test_7_140226.png

・左の Flow Navigator -> Project Manager -> IP Catalog をクリックする。

・右に IP Catalog のウインドウが出る。そこで右クリックして、右クリックメニューから IP Setting... を選択する。

・Project Setting のダイアログが出る。Add Repository... ボタンをクリックしてZYBO\IP_test\led4_axi_lite_slave を選択する。

・led4_axi_lite_slave_v1_0 がリポジトリに追加された。
Vivado_ZYBO_LED_test_8_140226.png

・IP Catalog のBase IP に追加されているのがわかる。
Vivado_ZYBO_LED_test_9_140226.png

・左の Flow Navigator -> Project Manager -> Create Block Design をクリックする。

・Create Block Design ダイアログが出る。Vivado_ZYBO_LED_test と入力して、OKボタンをクリックする。
Vivado_ZYBO_LED_test_10_140226.png

・Diagramウインドウが開く。

・Add IPをクリックして、IPコアをインポートする。

・ZYNQ 7 Processing System をダブルクリックする。

・ZYNQがインポートされた。

・Run Block Automation をクリックした。

・Run Block Automation ダイアログが開いた。OKボタンをクリックした。

・ポートが増えて、DDRとFIXED_IOの外部ポートが追加された。

・ZYNQ 7 Processing System を右クリックし、右クリックメニューから Customize Block... を選択する。

ここで、ZYBOのMIOなどの設定を行う。

・ZYBOのWebサイトからダウンロードしたZYBOの設定ファイル (ZYBO_zynq_def.xml)を読み込む。重要、忘れたらプロジェクトを作り直し。

・Import XPS Settingsをクリックして、ZYBO_zynq_def.xmlを指定する。
Vivado_ZYBO_LED_test_25_140227.png

・ZYBOのMIOの情報などが表示された。
Vivado_ZYBO_LED_test_26_140227.png

・Page Navigatgor から、Clock Configuration をクリックし、PL Fabric Clocks を展開し、FCLK_CLK0を100MHzに設定する。
Vivado_ZYBO_LED_test_27_140228.png

・これでZYNQ 7 Processing System の設定は終了だ。

・led4_axi_lite_slave_v1_0 をAdd IPする。この辺りの配線は自動的に行われる。

・LED4bit をExternal Portとして出力した。

・完成したBlock Design を下に示す。
Vivado_ZYBO_LED_test_11_140226.png

ここまでの配線は、ほとんど自動配線だ。

・Vivado 2013.4の右のFlow Navigator のIP Integrator -> Generate Block Design をクリックする。
Vivado_ZYBO_LED_test_12_140226.png

・Generate Output Productsダイアログがでた。Generate ボタンをクリックした。

・Block Desgin の Vivado_ZYBO_LED_test_i を右クリックし、右クリックメニューから Create HDL Wrapper... を選択した。

・Create HDL Wrapperダイアログが開いた。デフォルトのまま、OKボタンをクリックした。

・Vivado_ZYBO_LED_test_wrapper.v が生成された。
Vivado_ZYBO_LED_test_13_140226.png

・Vivado 2013.4の右のFlow Navigator の Synthesis -> Run Synthesis をクリックして、論理合成を行う。

・Synthesis が終了したら、 ダイアログから、Open Synthesized Design を選択して、OKボタンをクリックする。

・Synthesized Design が開く。LED4bit のピン配置と信号レベルの設定を行った。
Vivado_ZYBO_LED_test_14_140226.png

・Vivado 2013.4の右のFlow Navigator の Program and Debug -> Generate Bitstream をクリックして、インプリメント、ビットストリームの生成を行う。

・ビットストリームの生成まで終了した。
Vivado_ZYBO_LED_test_15_140226.png

なお、これらのプロジェクトなどの図はうまく行かなかった時のプロジェクトです。今は、C:\Users\Masaaki\Documents\Vivado\Zynq\ZYBO\Vivado_ZYBO_LED_test2 を使用してします。

VivadoでZYBO用LEDテストプロジェクト3(SDK、実機テスト)”に続く。
  1. 2014年02月28日 05:24 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

VivadoでZYBO用LEDテストプロジェクト1(単体テスト)

ISEでZYBO用LEDテストプロジェクトを作製した。今度はVivado 2013.4でZYBO用LEDテストプロジェクトを作ってみようと思う。
最初にled4_axi_lite_slave の単体テストから行う。

・Vivado 2013.4の led4_axi_lite_salve プロジェクトを作製して、HDLファイルをAdd Source した。
Vivado_ZYBO_LED_test_1_140226.png

・Flow Navigator のSimulation -> Run Simulation をクリックして、Behavioral Simulation を実行した。
Vivado_ZYBO_LED_test_2_140226.png

シミュレーションは正常にできていた。

このプロジェクトを IP Packager で IP にしよう。

・Toolsメニューから Create and Package IP... を選択した。

・Create And Package New IPダイアログが立ち上がった。今度は、IP Packaging と AXI4 Peripheral Creation が出来るらしい。
IP_Integrator_2013_4_6_140103.png

・次の画面でPackage your projectのラジオボタンを選択した。
IP_Integrator_2013_4_7_140103.png

・Summaryが表示されたので、Finishボタンをクリックした。

・Pacage IPの画面を下に示す。
Vivado_ZYBO_LED_test_3_140226.png

Vivado_ZYBO_LED_test_4_140226.png

・Review and Package 画面で、Package IPボタンをクリックして、IP化した。
Vivado_ZYBO_LED_test_5_140226.png

・IP化された。
Vivado_ZYBO_LED_test_6_140226.png

VivadoでZYBO用LEDテストプロジェクト2(プロジェクト作製、ビットストリーム生成まで)”に続く。
  1. 2014年02月26日 05:05 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBO用LEDテストプロジェクト4(実機でテスト)

ZYBO用LEDテストプロジェクト3(インプリメント)”の続き。

今回は実機テストだが、Githubの https://github.com/marsee101/ZYBO_LED_test にISE14.7のプロジェクトを上げておいたので、それを使用して説明する。

・https://github.com/marsee101/ZYBO_LED_testページの Download ZIPボタンで、ZIPファイルをダウンロードする。

・ZYBO_LED_test-master.zipファイルがダウンロードできるので、それを解凍する。

・ZYBO_LED_test-masterフォルダができるので、その下の ZYBO_LED_test.xise がProject Navigator のプロジェクトだ。

・Project Navigator を立ちあげ、ZYBO_LED_test.xise を開く。下の図はビットストリームの生成後のプロジェクトだ。
ZYBO_LED_test_13_140225.png

・system_i をダブルクリックして、XPSプロジェクトを立ちあげる。

・XPSプロジェクトで、Projectメニューから Clean All Generate Files を行う。

・Project Navigator でProjectメニューから Clean Project Filse... を行う。

・Processes ウインドウで、Generate Programming File をダブルクリックして、ビットストリームの生成までを行う。

・\ZYBO_LED_test-master\system\SDK\SDK_Exportフォルダの中身をすべて消す。
ZYBO_LED_test_14_140225.png

・Project Navigator で、system_i をクリックして、Processes ウインドウの Export Hardware Design To SDK with Bitstream をダブルクリックする。

・SDKが立ち上がり、workspace を確認してOKボタンをクリックする。

・SDKが立ち上がり、system_hw_platform が生成され、system.xml に led4_axi_lite_slave_0 が表示されている。
ZYBO_LED_test_15_140225.png

・File メニューから New -> Application Projectを選択する。

・Project name に led4_axi_lite_slave と入力して、Next >ボタンをクリックする。
ZYBO_LED_test_16_140225.png

・Empty Application を選択し、Finishボタンをクリックする。
ZYBO_LED_test_17_140225.png

・led4_axi_lite_slave と led4_axi_lite_slave_bsp が生成された。

・led4_axi_lite_slave を展開して、src を展開し、\ZYBO_LED_test\system\SDK フォルダにある led_axi_lite_slave.c を src フォルダにドラッグアンドドロップする。
ZYBO_LED_test_18_140225.png

・led_axi_lite_slave.cをセーブすると、自動でコンパイルが始まる。

・コンパイルが終了した。エラーはない。(2014/02/25の20時以前にダウンロードした場合は、エラーの部分を消して下さい)
ZYBO_LED_test_20_140225.png

・ZYBOの電源をONする。その時の電流値は0.25Aだった。電源はUSBケーブルから取っている。
ZYBO_LED_test_30_140225.jpg

・SDKの Xilinx Tools メニューの Program FPGA を選択する。

・ビットストリームの場所を確認して、Program ボタンをクリックする。
ZYBO_LED_test_21_140225.png

・ZYBOボードの緑色のDONE LEDが点灯する。電流は少し減って、0.23A。
ZYBO_LED_test_32_140225.jpg

・Tera Tremなどのターミナルソフトを立ちあげる。

・シリアルポートに設定する。
ZYBO_LED_test_22_140225.png

・設定メニューから端末を選択し、ローカルエコーにチェックを入れる。
ZYBO_LED_test_23_140225.png

・設定メニューからシリアルポートを選択し、ボー・レート:115200、データ8ビット、パリティ none、ストップ1ビット、フロー制御 none に設定する。
ZYBO_LED_test_24_140225.png

・Run メニューから Run Configuration...を選択する。

・Xilinx C/C++ application (GDB) を右クリックし、右クリックメニューから New を選択する。
ZYBO_LED_test_25_140225.png

・led4_axi_lite_slave_Debug が出来る。Runボタンをクリックする。
ZYBO_LED_test_26_140225.png

・Tera Termにメニューが表示される。
ZYBO_LED_test_27_140225.png

・ZYBOの電流値は0.30Aになった。
ZYBO_LED_test_33_140225.jpg

・4 のキーを押して、LED Interval Resister を設定する。値は、50000000を設定すると、0.5秒毎にLEDの値がインクリメントされるので、これを設定する。
ZYBO_LED_test_28_140225.png

・2 のキーを押すとLEDがカウントを始める。
ZYBO_LED_test_29_140225.png

カウントをしている様子をYouTube に上げておいたので、見て欲しい。
  1. 2014年02月25日 20:51 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBO用LEDテストプロジェクト3(インプリメント)

ZYBO用LEDテストプロジェクト2(単体シミュレーション)”の続き。

前回、単体シミュレーションが終了した。今回は、XPSプロジェクトを完成させて、Project Navigator でインプリメントを行った。

・led4_axi_lite_slave_v1_00_a IPコアを、ZYBO_LED_test\system\pcores フォルダの下にコピーした。

・led4_axi_lite_slave_v1_00_a IPコアをXPSプロジェクトでAdd IPして、Portsタブで設定を行った。

下に完成したXPSプロジェクトを示す。

・Bus Interfacesタブ
ZYBO_LED_test_6_140223.png

・Portsタブ(外部ポート)
ZYBO_LED_test_7_140223.png

・Portsタブ(LED4bit)
ZYBO_LED_test_8_140223.png

・Addressタブ
ZYBO_LED_test_9_140223.png

・左下のProjectタブをクリックして、data\system.ucf にUCFを書いた。これは、Digilent社のZYBO のWebページの”ZYBO Master UCF File for ISE designs.”を元にした。

・Project Navigator に戻って、論理合成、インプリメント、ビットストリームの生成を行った。
ZYBO_LED_test_11_140223.png

・成功した。

・SDKにハードウェアをエクスポートしてSDKを立ちあげた。

・ソフトウェアを作った。
ZYBO_LED_test_12_140224.png

次回は、このZYBO用LEDテストプロジェクトの使い方を使う立場に立って詳述する。

ZYBO用LEDテストプロジェクト4(実機でテスト)”に続く。
  1. 2014年02月24日 05:28 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBO用LEDテストプロジェクト2(単体シミュレーション)

ZYBO用LEDテストプロジェクト1(プロジェクト作製)”の続き。

自作の AXI4 Lite Master BFM を使用してシミュレーションを行った。

・まずは、単体シミュレーションの Project Navigator のプロジェクトを作った。
ZYBO_LED_test_4_140223.png

・テストベンチは、 を led4_axi_lite_slave_tb.v にちょちょいと修正しただけだ。

・AXI Lite Master BFMを使って、シミュレーションを行う。

・ISimでのシミュレーション結果を下に示す。
ZYBO_LED_test_5_140223.png

led4bit がLEDの表示部分だ。+1されているのがわかると思う。

これで単体シミュレーションは終了だ。
  1. 2014年02月23日 05:35 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBO用LEDテストプロジェクト1(プロジェクト作製)

ZYBO はDigilent社の新しい Zynq-7010 のボードだ。Digilent社のZYBOのWebサイトには、リファレンス・デザインもまだ載っていないが、LEDをテストするテストプロジェクトを作ってみようと思う。プロジェクトとしては、ZedBoard用に作ってあって、Zynq勉強会の1番目の AXI Lite Slave カスタムIPを作る課題用のプロジェクトとして使用している。それをZYBO用に変更してみようと思う。ZedBoardはLEDを8ビット分持っていたが、ZYBOは4ビット分のLEDしか無いので、そこを変更する。

それでは始めるが、チュートリアルとしては書かない予定なので、手順を飛ばすところがあるのでご了承下さい。

・最初にZYBO用のProject Navigator プロジェクトを作製した。デバイスは、xc7z010-1clg400

・次に、New Source で Embedded Processor を選択して、system という名前を付けた。

・Project Navigatorの画面を下に示す。
ZYBO_LED_test_1_140223.png

ZYBOのサイトから”ZYBO Board Definition File for configuring the Zynq Processing System core in Xilinx Platform Studio and Vivado IP Integrator.”をダウンロードする。

・ダウンロードしたZYBO_def.zipファイルを展開すると、中に ZYBO_zynq_def.xml が入っている。これを何処かにおいておく。

・XPSプロジェクトを立ち上がる。

・Zynqタブで、importをクリックし、User Template のところで、先ほどダウンロードした ZYBO_zynq_def.xml を指定する。
ZYBO_LED_test_3_140223.png

・Zynqタブが ZYBO の設定になった。MIO部の使用状況が見える。
ZYBO_LED_test_2_140223.png

ZYBO用LEDテストプロジェクト2(単体シミュレーション)”に続く。
  1. 2014年02月23日 04:45 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:2

Zynq勉強会2日目

Zynq勉強会の2日目が終了しました。

午前中に、XPSプロジェクトでカスタムIPを作る方法とAXI4 バス説明をしてました。
午後には、AXI4バスを使用したカスタムIPの作成方法を説明してから、演習1と演習2をやりました。

演習1は、LEDに表示するバイナリカウンタのAXI4 Lite Slave カスタムIPを作り課題でした。これはかなりの人が出来たと思います。
演習2は、キャラクタ・ジェネレーターROMのAXI4 Lite Slave カスタムIPと、ビットマップ・ディスプレイ・コントローラAXI4 Master カスタムIPを組み込みます。ARMプロセッサから、キャラクタ・ジェネレーターROMのキャラクタデータに従って、ビットマップ・ディスプレイにキャラクタを表示する演習です。最初は、キャッシュが効いているので、DDR3 SDRAMにフラッシュされないピクセルデータがあって、ボロボロですが、キャッシュをフラッシュするとちゃんと写るね。という演習です。HDMIで出力した時は相性があって、表示できませんでした。VGAポートは問題無いです。800x600のSVGAのためということもあると思います。

やはり、1年半くらいを2日間に凝縮したので、特にXPSプロジェクトの作り方あたりは、細かいところまでやったので、眠くなったと思います。説明していて、これは眠くなるだろうな?と思ったので、実例を上げて説明したのですが、やはり眠くなりますよね。。。でも、ほんの少しでも雰囲気に触れてくれれば良いと思っています。(眠くなるのは、こっちの説明が悪いです。これを自分で聞いていたら眠くなると思います。。。)

勉強会の様子です。
Zynq_seminar_1_140221.jpg
  1. 2014年02月21日 20:44 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq勉強会1日目

今日は、Zynq勉強会を開催しました。15人程度の参加がありました。

午前中は、1_Zynq-7000の概要.pdf、2_Zynq用ツール概要です。
午後は、Zynqチュートリアルを皆で一緒にライブコーディングしました。が。。。ノートパソコンにISEをインストールして持ってきてもらったのですが、ISE14.4, ISE14.5は途中でエラーが出たりしました。ISE14.7とISE14.6 でチェックしたんですが。。。
後、ライセンスの問題など盛りだくさん。いろいろと問題が多かったですが、皆さん助けあって解決したりして頂いて、大体出来たと思います。良かったです。

XPSを初めて使った人もいたと思いますが、大体感じを掴んでくれたんではないでしょうか?
明日は、本番のカスタムIPの作り方を勉強します。
  1. 2014年02月21日 05:38 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

ZYBOが届いた

昨日、ZYBOが届いた。ZYBO は Zynq の Z-7010が搭載されたボードだ。

ZYBO のスペックを下に引用する。

ZYNQ XC7Z2010-1CLG400C
512MB x32 DDR3 w/ 1050Mbps bandwidth
Dual-role (Source/Sink) HDMI port
16-bits per pixel VGA output port
Trimode (1Gbit/100Mbit/10Mbit) Ethernet PHY
MicroSD slot (supports Linux file system)
OTG USB 2.0 PHY (supports host and device)
External EEPROM (programmed with 48-bit globally unique EUI-48/64™ compatible identifier)
Audio codec with headphone out, microphone and line in jacks
128Mb Serial Flash w/ QSPI interface
On-board JTAG programming and UART to USB converter
GPIO: 6 pushbuttons, 4 slide switches, 5 LEDs
Six Pmod connectors (1 processor-dedicated, 1 dual analog/digital)


価格は、$189、アカデミックで$125

パッケージはとても小さく、ボードのみ入っていた。他には何も入っていない。
ZYBO_1_140219.jpg

箱を開けたところ。
ZYBO_2_140219.jpg

ZYBO_3_140219.jpg

ダウンロード用のUSB A - MicroBケーブルで電源も供給できるので、つないで電源ONしてみた。
ZYBO_4_140219.jpg

HDMI出力は、1600 x 900 の WXGA++(Wide-XGA++)だった。
ZYBO_5_140219.jpg

VGA出力は、1280 x 960 の QVGA (Quad-VGA)だった。
ZYBO_6_140219.jpg

やはり、HDMIで見たほうが画像が滑らかに写っている。
  1. 2014年02月19日 04:36 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:6

AXI VDMAを使ったカメラ画像回路の作製1(プロジェクトの作製)

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製17(ハードウェアのデバック5)”まで、Vivado 2013.4でAXI VDMA を使ったカメラ画像回路を作ってきたが、Vivado 2013.4だと、動作が重いので、ISEで試作してみようと思った。Vivado 2013.4は私の家の古いパソコンではとっても重い。

まずは、Project Navigator の ZedBoard用のプロジェクトを作製した。
Cam_VDMA_ISE_1_140217.png

次に、XPSプロジェクトを下に示す。
Cam_VDMA_ISE_2_140217.png

Cam_VDMA_ISE_3_140217.png

Cam_VDMA_ISE_4_140217.png

AXI_GP0、AXI_HP0 のクロックは 100MHz だ。

下に、system_top.ucf を示す。

NET "vga_blue[0]" LOC = Y21;
NET "vga_blue[1]" LOC = Y20;
NET "vga_blue[2]" LOC = AB20;
NET "vga_blue[3]" LOC = AB19;
NET "vga_blue[0]" IOSTANDARD = LVCMOS33;
NET "vga_blue[1]" IOSTANDARD = LVCMOS33;
NET "vga_blue[2]" IOSTANDARD = LVCMOS33;
NET "vga_blue[3]" IOSTANDARD = LVCMOS33;
INST "vga_blue_0_OBUF" IOB =FORCE;
INST "vga_blue_1_OBUF" IOB =FORCE;
INST "vga_blue_2_OBUF" IOB =FORCE;
INST "vga_blue_3_OBUF" IOB =FORCE;
NET "vga_green[0]" LOC = AB22;
NET "vga_green[1]" LOC = AA22;
NET "vga_green[2]" LOC = AB21;
NET "vga_green[3]" LOC = AA21;
NET "vga_green[0]" IOSTANDARD = LVCMOS33;
NET "vga_green[1]" IOSTANDARD = LVCMOS33;
NET "vga_green[2]" IOSTANDARD = LVCMOS33;
NET "vga_green[3]" IOSTANDARD = LVCMOS33;
INST "vga_green_0_OBUF" IOB =FORCE;
INST "vga_green_1_OBUF" IOB =FORCE;
INST "vga_green_2_OBUF" IOB =FORCE;
INST "vga_green_3_OBUF" IOB =FORCE;
NET "vga_red[0]" LOC = V20;
NET "vga_red[1]" LOC = U20;
NET "vga_red[2]" LOC = V19;
NET "vga_red[3]" LOC = V18;
NET "vga_red[0]" IOSTANDARD = LVCMOS33;
NET "vga_red[1]" IOSTANDARD = LVCMOS33;
NET "vga_red[2]" IOSTANDARD = LVCMOS33;
NET "vga_red[3]" IOSTANDARD = LVCMOS33;
INST "vga_red_0_OBUF" IOB =FORCE;
INST "vga_red_1_OBUF" IOB =FORCE;
INST "vga_red_2_OBUF" IOB =FORCE;
INST "vga_red_3_OBUF" IOB =FORCE;
NET "vga_hsync" LOC = AA19;
NET "vga_vsync" LOC = Y19;
NET "vga_hsync" IOSTANDARD = LVCMOS33;
NET "vga_vsync" IOSTANDARD = LVCMOS33;
INST "vga_hsync_OBUF" IOB =FORCE;
INST "vga_vsync_OBUF" IOB =FORCE;

INST "hdmi_clk_OBUF" IOB =FORCE;
NET "hdmi_clk" LOC = W18;
NET "hdmi_clk" IOSTANDARD = LVCMOS33;
INST "hdmi_vsync_OBUF" IOB =FORCE;
NET "hdmi_vsync" LOC = W17;
NET "hdmi_vsync" IOSTANDARD = LVCMOS33;
INST "hdmi_hsync_OBUF" IOB =FORCE;
NET "hdmi_hsync" LOC = V17;
NET "hdmi_hsync" IOSTANDARD = LVCMOS33;
INST "hdmi_data_e_OBUF" IOB =FORCE;
NET "hdmi_data_e" LOC = U16;
NET "hdmi_data_e" IOSTANDARD = LVCMOS33;
INST "hdmi_data_0_OBUF" IOB =FORCE;
NET "hdmi_data[0]" LOC = Y13;
NET "hdmi_data[0]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_1_OBUF" IOB =FORCE;
NET "hdmi_data[1]" LOC = AA13;
NET "hdmi_data[1]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_2_OBUF" IOB =FORCE;
NET "hdmi_data[2]" LOC = AA14;
NET "hdmi_data[2]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_3_OBUF" IOB =FORCE;
NET "hdmi_data[3]" LOC = Y14;
NET "hdmi_data[3]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_4_OBUF" IOB =FORCE;
NET "hdmi_data[4]" LOC = AB15;
NET "hdmi_data[4]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_5_OBUF" IOB =FORCE;
NET "hdmi_data[5]" LOC = AB16;
NET "hdmi_data[5]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_6_OBUF" IOB =FORCE;
NET "hdmi_data[6]" LOC = AA16;
NET "hdmi_data[6]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_7_OBUF" IOB =FORCE;
NET "hdmi_data[7]" LOC = AB17;
NET "hdmi_data[7]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_8_OBUF" IOB =FORCE;
NET "hdmi_data[8]" LOC = AA17;
NET "hdmi_data[8]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_9_OBUF" IOB =FORCE;
NET "hdmi_data[9]" LOC = Y15;
NET "hdmi_data[9]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_10_OBUF" IOB =FORCE;
NET "hdmi_data[10]" LOC = W13;
NET "hdmi_data[10]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_11_OBUF" IOB =FORCE;
NET "hdmi_data[11]" LOC = W15;
NET "hdmi_data[11]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_12_OBUF" IOB =FORCE;
NET "hdmi_data[12]" LOC = V15;
NET "hdmi_data[12]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_13_OBUF" IOB =FORCE;
NET "hdmi_data[13]" LOC = U17;
NET "hdmi_data[13]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_14_OBUF" IOB =FORCE;
NET "hdmi_data[14]" LOC = V14;
NET "hdmi_data[14]" IOSTANDARD = LVCMOS33;
INST "hdmi_data_15_OBUF" IOB =FORCE;
NET "hdmi_data[15]" LOC = V13;
NET "hdmi_data[15]" IOSTANDARD = LVCMOS33;
NET "hdmi_iic_Scl" LOC = AA18;
NET "hdmi_iic_Scl" IOSTANDARD = LVCMOS33;
NET "hdmi_iic_Sda" LOC = Y16;
NET "hdmi_iic_Sda" IOSTANDARD = LVCMOS33;
NET "hdmi_data[15]" SLEW = FAST;
NET "hdmi_data[14]" SLEW = FAST;
NET "hdmi_data[13]" SLEW = FAST;
NET "hdmi_data[12]" SLEW = FAST;
NET "hdmi_data[11]" SLEW = FAST;
NET "hdmi_data[10]" SLEW = FAST;
NET "hdmi_data[9]" SLEW = FAST;
NET "hdmi_data[8]" SLEW = FAST;
NET "hdmi_data[7]" SLEW = FAST;
NET "hdmi_data[6]" SLEW = FAST;
NET "hdmi_data[5]" SLEW = FAST;
NET "hdmi_data[4]" SLEW = FAST;
NET "hdmi_data[3]" SLEW = FAST;
NET "hdmi_data[2]" SLEW = FAST;
NET "hdmi_data[1]" SLEW = FAST;
NET "hdmi_data[0]" SLEW = FAST;
NET "vga_blue[3]" SLEW = FAST;
NET "vga_blue[2]" SLEW = FAST;
NET "vga_blue[1]" SLEW = FAST;
NET "vga_blue[0]" SLEW = FAST;
NET "vga_green[3]" SLEW = FAST;
NET "vga_green[2]" SLEW = FAST;
NET "vga_green[1]" SLEW = FAST;
NET "vga_green[0]" SLEW = FAST;
NET "vga_red[3]" SLEW = FAST;
NET "vga_red[2]" SLEW = FAST;
NET "vga_red[1]" SLEW = FAST;
NET "vga_red[0]" SLEW = FAST;
NET "hdmi_clk" SLEW = FAST;
NET "hdmi_data_e" SLEW = FAST;
NET "hdmi_hsync" SLEW = FAST;
NET "hdmi_iic_Scl" SLEW = SLOW;
NET "hdmi_vsync" SLEW = FAST;
NET "vga_hsync" SLEW = FAST;
NET "vga_vsync" SLEW = FAST;
NET "mt9d111_d[7]" LOC = W12;
NET "mt9d111_d[6]" LOC = V12;
NET "mt9d111_d[5]" LOC = W11;
NET "mt9d111_d[4]" LOC = W10;
NET "mt9d111_d[3]" LOC = V10;
NET "mt9d111_d[2]" LOC = V9;
NET "mt9d111_d[1]" LOC = W8;
NET "mt9d111_d[0]" LOC = V8;
NET "mt9d111_d[7]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[6]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[5]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[4]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[3]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[2]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[1]" IOSTANDARD = LVCMOS33;
NET "mt9d111_d[0]" IOSTANDARD = LVCMOS33;
NET "mt9d111_href" LOC = AB10;
NET "mt9d111_pclk" LOC = AA9;
NET "mt9d111_Scl" LOC = Y11;
NET "mt9d111_Sda" LOC = AB11;
NET "mt9d111_standby" LOC = Y10;
NET "mt9d111_vsync" LOC = AA11;
NET "mt9d111_xck" LOC = AA8;
NET "mt9d111_href" IOSTANDARD = LVCMOS33;
NET "mt9d111_pclk" IOSTANDARD = LVCMOS33;
NET "mt9d111_Scl" IOSTANDARD = LVCMOS33;
NET "mt9d111_Sda" IOSTANDARD = LVCMOS33;
NET "mt9d111_standby" IOSTANDARD = LVCMOS33;
NET "mt9d111_vsync" IOSTANDARD = LVCMOS33;
NET "mt9d111_xck" IOSTANDARD = LVTTL;
NET "mt9d111_d[0]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[1]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[2]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[3]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[4]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[5]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[6]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_d[7]" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_href" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_vsync" OFFSET = IN 10.8 ns VALID 21.7 ns BEFORE "mt9d111_pclk" RISING;
NET "mt9d111_Scl" PULLUP;
NET "mt9d111_Sda" PULLUP;


現在、論理合成中だ。

”AXI VDMAを使ったカメラ画像回路の作製2(Xilinxアンサーを検索)”に続く。
  1. 2014年02月17日 04:42 |
  2. ZedBoard
  3. | トラックバック:0
  4. | コメント:0

大統領の執事の涙(映画)を見てきました

大統領の執事の涙(音注意)を見てきました。う~ん。はっきり言うと、あまり面白くなかったです。お父さんと息子が仲直りするシーンでは感動しましたが、それ以外は平凡な映画じゃないでしょうか?これが、実際に時代を体験したアメリカ合衆国の国民の人だったら感動具合が違うんでしょうか?
  1. 2014年02月16日 20:39 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製17(ハードウェアのデバック5)

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製16(ハードウェアのデバック4)”の続き

間がずいぶん離れてしまったが、Vivado 2013.4に戻って、AXI VDMAを使ったカメラ画像表示システムのデバックを継続しようと思う。
Vivado Logic Analyzer のやり方を勉強しながらデバックしていこうと思う。
Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製15(ハードウェアのデバック3)”で、Hardware Manager に各ILAが見えたところから再開する。

hw_ila_4 は S2MMの mt9d111_inf_axi_stream の AXI4 Stream バスなので、まずは s2mm_fsync をトリガに加える。

・Debug Probes ウインドウから s2mm_fsync を Basic Trigger Setup ウインドウにドラッグ&ドロップする。

・Run trigger for this ILA core のアイコンをクリックする。
Cam_VDMA_203_140214.png

・波形をキャプチャして波形ウインドウが生成された。
Cam_VDMA_204_140214.png

・次に、m_axis_TLAST も Basic Trigger Setup ウインドウに加えたいのだが、ドラック&ドロップしても加えられなかったので、m_axis_TLAST を右クリックし、右クリックメニューから Add Probes to Basic Trigger Setup を選択した。
Cam_VDMA_205_140214.png

・m_axis_TLAST も Basic Trigger Setup ウインドウに追加された。

・次にトリガレベルを変更する。Compare Value の項の下向き三角をクリックして、Value に 1 を入力して、OKボタンをクリックした。
Cam_VDMA_207_140214.png

・m_axis_TLAST の Compare Value の項が、”== [B] 1”になった。
Cam_VDMA_208_140214.png

・Trigger position を 1000 にして、Run trigger for this ILA core のアイコンをクリックした。
Cam_VDMA_209_140214.png

・波形をキャプチャして波形ウインドウが更新された。
Cam_VDMA_210_140214.png

・AXI VDMA の AXI4 Master アクセスを見てみよう。hw_ila_2 をキャプチャする。
Cam_VDMA_211_140214.png

・波形をキャプチャして波形ウインドウが生成された。
Cam_VDMA_212_140214.png

AXI4 Master Read は信号が出ているが、AXI4 Master Write は信号が出ていない。

・AXI VDMA の 1つの AXI4 Master Read アクセスを引き伸ばしてみた。結構良い感じだが、やはりReadレイテンシがあるね。
Cam_VDMA_213_140214.png

・最後に画像出力用のAXI4 Stream を見てみよう。
Cam_VDMA_214_140214.png

・波形を下に表示する。
Cam_VDMA_215_140215.png

vtg_sync を AXI VDMAの mm2s_sync 端子に入れてあるが、mm2s_tuser と一緒に mm2s_tvalid がアサートされている。

なお、前回はランダムパターンをディスプレイが表示していたが、AXI VDMA の S2MM_DMACR を設定するのを忘れていた。

Xil_Out32((XPAR_AXI_VDMA_0_BASEADDR+0x30), 0x3); // S2MM_DMACR


を追加したところ、1回だけだが画像が出力できた。
Cam_VDMA_216_140215.jpg

但し、この1回だけしか画像を更新出来ていない。それになぜ白黒なのだろうか?
  1. 2014年02月15日 08:33 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado 2013.4でHardware Manager を強制終了させた時にやること

Vivado 2013.4で、どうしようも無くなってHardware Manager を強制終了させた時は、次の2つのプロセスも強制終了させる必要があります。

・vcse_server.exe
・hw_server.exe


こうしないとVivado 2013.4を立ち上げなおしても、Open TargetでTarget をOpen できません。

なお、ZynqでHardware Manager を使っている時は、SDKも動かしていると思いますが、xmd.exe は、SDKが使っているので、強制終了させないようにしましょう。
  1. 2014年02月15日 05:07 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする9(Directive2)

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする8(Directive)”の続き。

前回は、UNROLL Directive を入れてたが効果は得られなかった。あれからPIPELINE Directive を試してみたが、大きいループにPIPELINE Directive 属性を付加すると時間がかかりすぎる。小さいループにPIPELINE Directive をかけても他がPIPELINE化されていないので、効果なしという結果になるような気がする。

PIPELINE Directive を追加したプロジェクトを下に示す。
Vivado_HLS_2013_4_40_140213.png

IP化して、シミュレーションを行った結果を下に示す。
Vivado_HLS_2013_4_41_140213.png

変化なしだ。

自分でHDLで作ったラプラシアンフィルタAXI4 Master IPは、ピクセルデータRead の DMAと、ラプラシアンフィルタ結果Write の DMA の間が殆ど無い。すべてパイプライン処理をしているからだ。
下に、HDLで自作したラプラシアンフィルタAXI4 Master IPのシミュレーション結果を示す。上が AXI4 Write で下が AXI4 Readになっているので、トランザクションの様子がよくわかる。
axi4m_lap_filter_10_131124.png

ReadとWriteの差がほとんど0だ。このように、Vivado HLS 2013.4 の出力したIPの処理を行いたいがどのようにチューニングしてよいかわからない?
マニュアルを熟読すべきなのだろうが、時間もないので、後の課題とすることにして、中断していたVivado 2013.4 IP Integrater の回路のデバックに戻ろうと思う。
  1. 2014年02月13日 04:24 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする8(Directive)

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする7(ソース公開)”の続き。

Vivado HLS 2013.4 でラプラシアンフィルタのCソースコードをVerilog HDLで書かれたIPとして高位合成をして、できたIPを実機でテストしてみたところ、結果はちょっとおかしいが、無事に動作した。今回は、実行時間が約 100msec 程度と遅いので、もう少し早くしてみようと思う。そのためには、Directiveを追加する必要がある。

さてDirectiveを追加していこう。とりあえず、forループを展開するDirective の UNROLL を RGBピクセルを白黒ビクセルに変換する conv_rgb2y() に入れていこう。

・Vivado HLS 2013.4 で右のウインドウのDirective をクリックする。

・最初の conv_rgb2y() の for Statement をクリックする。
Vivado_HLS_2013_4_30_140211.png

・当該 for Statement を右クリックし、右クリックメニューから Insert Diective... を選択する。
Vivado_HLS_2013_4_31_140211.png

・Vivado HLS Directive Editor ダイアログが表示された。Directive で UNROLL を選択し、factor を 4 に設定した。OKボタンをクリックした。
Vivado_HLS_2013_4_32_140211.png

・Insert Statement Label ダイアログが表示された。Label Name に conv_rgb2y_loop1 と入力した。
Vivado_HLS_2013_4_33_140211.png

・Vivado HLS に UNROLL Dierctive が追加された。ループ本体のコピーを4つ生成したことになると思う。
Vivado_HLS_2013_4_34_140211.png

・もう1つの、conv_rgb2y() のループにも、UNROLL Directive を追加した。
Vivado_HLS_2013_4_35_140211.png

・ファイルをセーブして、C Synthesis を行った。

・Analysis モードで結果を観察した。

まずはリソースについて比較する

・BRAMは10で変化なし
・DSPは以前の16から34に増えた
・FFは、1961から2243に増えた
・LUTは、2146から2298に増えた
・Latencyは、1450201~69427730201 から 1450201~2910730201になった。
・Intervalは、1450201~69427730201 から 1450201~2910730201になった。


UNROLL Directive -factor=4 を追加した時の高位合成結果を下に示す。
Vivado_HLS_2013_4_36_140211.png

Directive を追加していない状態での高位合成結果を下に示す。
Vivado_HLS_2013_4_29_140210.png

・この高位合成結果を EDK の pcore とした。

さて、これをシミュレーション環境に持って行ってシミュレーションしてみよう。

シミュレーション結果を下に示す。
Vivado_HLS_2013_4_37_140211.png

memcopy() の間隔は 111.67usec だった。

以前のシミュレーションを下に示す。
Vivado_HLS_2013_4_22_140208.png

memcopy() の間隔は 145.67usec だった。

111.64 / 145.67 ≒ 0.77 なので、総実行時間を予想すると100msec / 0.77 = 77msec くらいか?でも、ラプラシアンフィルタの実行時間の割合を考えるともう少し長くかかると思う。

次に、UNROLL Directive -factor=8 にしてみた。高位合成結果を下に示す。
Vivado_HLS_2013_4_38_140211.png

シミュレーションを行った時のmemcopy() のインターバルは 118.64usec で UNROLL Directive -factor=4 の時よりも増えてしまった。結構難しい。
Vivado_HLS_2013_4_39_140211.png

UNROLL Directive -factor=4 を追加して作ったラプラシアンフィルタIPをXPSプロジェクトにIPと交換して、ISEで論理合成、インプリメント、ビットストリームの生成を行い、SDKからテストした所、104msec となり 3msecほど実行時間が増えてしまった。のmemcopy() のインターバルは少なくなっていたのだが、他の所で時間が掛かるようになってしまったのかもしれない。
というわけで、今のところ Directive の効果は見えていない。

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする9(Directive2)”に続く。
  1. 2014年02月11日 07:01 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする7(ソース公開)

”Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする6(実機でテスト)”の続き。

前回までのソースを公開します。使用は自己責任でお願いします。なお、バグを見つけたらコメント欄で教えて下さい。よろしくお願いします。

まずは、Vivado HLS 2013.4 のCソースから公開します。(laplacian_filter.c)

// laplacian_filter.c
// lap_filter_axim()

#include <stdio.h>
#include <string.h>

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);

int lap_filter_axim(int cam_addr, int lap_addr, volatile int *cam_fb, volatile int *lap_fb)
{
    #pragma HLS RESOURCE variable=cam_addr core=AXI4LiteS metadata="-bus_bundle LiteS"
    #pragma HLS RESOURCE variable=lap_addr core=AXI4LiteS metadata="-bus_bundle LiteS"
    #pragma HLS RESOURCE variable=return core=AXI4LiteS metadata="-bus_bundle LiteS"
    
    #pragma HLS INTERFACE ap_bus port=cam_fb depth=480000
    #pragma HLS INTERFACE ap_bus port=lap_fb depth=480000
    #pragma HLS RESOURCE variable=cam_fb core=AXI4M
    #pragma HLS RESOURCE variable=lap_fb core=AXI4M

    unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
    unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
    int x, y;
    int lap_fil_val;
    int a, b;
    int fl, sl, tl;
    unsigned int offset_cam_addr, offset_lap_addr;
    int *cam_fb_addr, *lap_fb_addr;

    offset_cam_addr = cam_addr/sizeof(int);
    offset_lap_addr = lap_addr/sizeof(int);
    
    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        fl = (y-1)%3;    // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
        sl = y%3;        // 2番めのライン
        tl = (y+1)%3;    // 3番目のライン
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
                lap_fil_val = 0;
            }else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
                lap_fil_val = 0;
            }else{
                 if (x == 1){ // ラインの最初でラインの画素を読み出す
                    if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
                        for (a=0; a<3; a++){ // 3ライン分
                            cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
                            memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                            for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
                                line_buf[a][b] = conv_rgb2y(line_buf[a][b]);    // カラーから白黒へ
                            }
                        }
                    } else { // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
                        cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
                         memcpy(line_buf[(y+1)%3], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
                        for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
                            line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]);    // カラーから白黒へ
                        }
                    }
                }
                lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
            }
            lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
        }
        lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
        memcpy(lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
    }
    return(7);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8; // 256で割る

    return(y);
}

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
    int y;

    y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
    if (y<0)
        y = 0;
    else if (y>255)
        y = 255;
    return(y);
}


Cのテストベンチです。(lap_filter_tb.c)

// Testbench of laplacian_filter.c
// M系列データをハードウェアとソフトウェアで、ラプラシアン・フィルタを掛けて、それを比較する
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

int laplacian_fil_soft(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y_soft(int rgb);
int lap_filter_axim(int cam_addr, int lap_addr, volatile int *cam_fb, volatile int *lap_fb);    // hardware
void laplacian_filter_soft(volatile int *cam_fb, volatile int *lap_fb); // software

int mseq_po[ALL_PIXEL_VALUE];
int hw_lap_po[ALL_PIXEL_VALUE];
int sf_lap_po[ALL_PIXEL_VALUE];

int main()
{
//    int *mseq_po, *hw_lap_po, *sf_lap_po;
    int *s, *h;
    int x, y;
    int lfsr = 1;
    int cam_addr, lap_addr;
    
    // ピクセルデータ領域にM系列データを入力
    for (y=0, s=mseq_po; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            lfsr = (lfsr >> 1) ^ (-(lfsr & 1) & 0xd0000001); /* taps 32 31 29 1 */
            // ”線形帰還シフトレジスタ ”参照 : http://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E5%B8%B0%E9%82%84%E3%82%B7%E3%83%95%E3%83%88%E3%83%AC%E3%82%B8%E3%82%B9%E3%82%BF
            *s = lfsr;
            s++;
        }
    }
    
    cam_addr = (int)mseq_po;
    lap_addr = (int)hw_lap_po;
    lap_filter_axim(cam_addr, lap_addr, (volatile int *)0, (volatile int *)0);    // ハードウェアのラプラシアン・フィルタ
    laplacian_filter_soft(mseq_po, sf_lap_po);    // ソフトウェアのラプラシアン・フィルタ
    
    // ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
    for (y=0, h=hw_lap_po, s=sf_lap_po; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (*h != *s){
                printf("ERROR HW and SW results mismatch HW = %d, SW = %d\n", *h, *s);
                return(1);
            } else {
                h++;
                s++;
            }
        }
    }
    printf("Success HW and SW results match\n");
}

void laplacian_filter_soft(volatile int *cam_fb, volatile int *lap_fb)
{
    int x, y;
    int lap_fil_val;
    int xy[3][3];
    int a, b;
    
    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
                lap_fil_val = 0;
            }else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
                lap_fil_val = 0;
            }else{
                for (a=0; a<3; a++){
                    for (b=0; b<3; b++){
                        xy[a][b] = conv_rgb2y_soft(cam_fb[((y+b-1)*HORIZONTAL_PIXEL_WIDTH)+x+a-1]);
                    }
                }
                lap_fil_val = laplacian_fil_soft(xy[0][0], xy[1][0], xy[2][0],  xy[0][1], xy[1][1], xy[2][1],  xy[0][2], xy[1][2], xy[2][2]);
            }
            lap_fb[y*HORIZONTAL_PIXEL_WIDTH+x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
        }
    }
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y_soft(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8; // 256で割る

    return(y);
}

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil_soft(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
    int y;

    y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
    if (y<0)
        y = 0;
    else if (y>255)
        y = 255;
    return(y);
}


次は、SDKの Vivado HLSで作ったラプラシアンフィルタAXI Master IP制御用のCソフトウェアです。4つファイルがあって、lap_fil_hls_axim.c、lap_fil_axim_uty.c、lap_fil_axim_uty.h、xlap_filter_axim_hw.hです。

最初に、lap_fil_hls_axim.cから公開します。

// lap_filter_axim.c
// AXI4 Master のVivado HLS出力ハードウェア・バージョン
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/10/15

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/kernel.h>
#include "lap_fil_axim_uty.h"

#define LAP_FILTER_AXIM_HW_ADDRESS    0x49000000    // ラプラシアン・フィルタのAXI4 Masterハードウェアのアドレス

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

#define BUFSIZE    1024

#define MEASURE_COUNT    5000

int conv_rgb2y(int rgb);
int chkhex(char *str);
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr);

int main()
{
    FILE *fd;
    unsigned int bitmap_dc_reg_addr;
    unsigned int read_num;
    volatile unsigned *bm_disp_cnt_reg;
    unsigned int fb_addr, next_frame_addr;
    int return_val;
    struct timeval start_time, end_time;
    unsigned int rmmap_cnt=0, wmmap_cnt=0;
    unsigned int lap_fil_hw, *lap_fil_hw_addr;
    char buf[BUFSIZE], *token;
    unsigned int val;
    unsigned int bitmap_buf;

    gettimeofday(&start_time, NULL);    // プログラム起動時の時刻を記録

    // fb_start_addr.txt の内容をパイプに入れる
    memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
    // fb_start_addr.txt を開く
    fd = popen("cat /Apps/fb_start_addr.txt", "r");
    if (fd != NULL){
        read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
        if (read_num > 0){
            sscanf(buf, "%x\n", &fb_addr);
        }
    }
    pclose(fd);

    // ラプラシアンフィルタの結果を入れておくフレーム・バッファ
    next_frame_addr = ((fb_addr + (ALL_PIXEL_VALUE*4)) & (~(int)(PAGE_SIZE-1))) + PAGE_SIZE;

    // Vivado HLS で作製したラプラシアン・フィルタIPのアドレスを取得
    lap_fil_hw_addr = setup_io((off_t)LAP_FILTER_AXIM_HW_ADDRESS, &lap_fil_hw);

    lap_fil_initialize(lap_fil_hw_addr);    // ラプラシアン・フィルタIPの初期化とap_start
    // ラプラシアン・フィルタAXI4 Master IPスタート
    return_val = laplacian_fil_hw(lap_fil_hw_addr, fb_addr, next_frame_addr);
    printf("return Value = %d\n", return_val);
    
    munmap((unsigned int *)lap_fil_hw_addr, BLOCK_SIZE);
    free((unsigned int *)lap_fil_hw);

    // bitmap-disp-cntrler-axi-master のアドレスを取得
    memset(buf, '\0', sizeof(buf)); // buf すべてに\0 を入れる
    // ls /sys/devices/axi.0 の内容をパイプに入れる
    fd = popen("ls /sys/devices/axi.0", "r");
    if (fd != NULL){
        read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
        if (read_num > 0){
            token = buf;
            if ((token=strtok(token, ".\n")) != NULL){
                do {
                    if (chkhex(token)){ // 16進数
                        sscanf(token, "%x", &val);
                    } else {
                        if (strcmp(token, "bitmap-disp-cntrler-axi-master") == 0)
                            bitmap_dc_reg_addr = val;
                    }
                }while((token=strtok(NULL, ".\n")) != NULL);
            }
        }
    }
    pclose(fd);

    // ラプラシアンフィルタの掛かった画像のスタートアドレスを bitmap-disp-cntrler-axi-master にセット
    bm_disp_cnt_reg = setup_io((off_t)bitmap_dc_reg_addr, &bitmap_buf);
    *bm_disp_cnt_reg = next_frame_addr;

    munmap((unsigned int *)bm_disp_cnt_reg, BLOCK_SIZE);
    free((unsigned int *)bitmap_buf);

    gettimeofday(&end_time, NULL);
    printf("rmmap_cnt = %d\n", rmmap_cnt);
    printf("wmmap_cnt = %d\n", wmmap_cnt);
    if (end_time.tv_usec < start_time.tv_usec) {
        printf("total time = %d.%d sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec);
    }
    else {
        printf("total time = %d.%d sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
    }
    return(0);
}


// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8; // 256で割る

    return(y);
}

//
// Set up a memory regions to access GPIO
//
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr)
// void setup_io()
{
    int  mem_fd;
    char *gpio_mem, *gpio_map;

   /* open /dev/mem */
   if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
      printf("can't open /dev/mem \n");
      printf("mapped_addr = %x\n", mapped_addr);
      exit (-1);
   }

   /* mmap GPIO */

   // Allocate MAP block
   if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
      printf("allocation error \n");
      exit (-1);
   }
    *buf_addr = gpio_mem;    // mallocしたアドレスをコピー

   // Make sure pointer is on 4K boundary
   if ((unsigned long)gpio_mem % PAGE_SIZE)
     gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);

   // Now map it
   gpio_map = (unsigned char *)mmap(
      (caddr_t)gpio_mem,
      BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      mapped_addr
   );

   if ((long)gpio_map < 0) {
      printf("mmap error %d\n", (int)gpio_map);
      printf("mapped_addr = %x\n", mapped_addr);
      exit (-1);
   }

   close(mem_fd); // /dev/mem のクローズ

   // Always use volatile pointer!
   // gpio = (volatile unsigned *)gpio_map;
   return((volatile unsigned *)gpio_map);

} // setup_io

// 文字列が16進数かを調べる
int chkhex(char *str){
    while (*str != '\0'){
        if (!isxdigit(*str))
            return 0;
        str++;
    }
    return 1;
}


次は、lap_fil_axim_uty.c です。

/*
 * lap_fil_axim_uty.c
 *
 *  Created on: 2013/10/15
 *      Author: Masaaki
 */

#include "xlap_filter_axim_hw.h"

#define AP_START_BIT_POS        1    // ap_start のビット位置 bit0
#define AP_DONE_BIT_POS            2    // ap_done のビット位置 bit1
#define AP_AUTO_RESTART_BIT_POS    0x80    // auto_restart のビット位置 bit7
#define VLD_BIT_POS                1

void lap_fil_initialize(unsigned int *lap_fil_hw_addr)
{
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_GIE) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_IER) = 1;    // ap_done=1
}

// ラプラシアン・フィルタ・スタート
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr, unsigned int cam_fb, unsigned int lap_fb)
{
    int ap_status, ap_done;
    int ap_return;

    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA) = cam_fb;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA) = lap_fb;

    // ap_start enable
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = AP_START_BIT_POS;

    // wait ap_done
    do{
        ap_status = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL);
        ap_done = ap_status & AP_DONE_BIT_POS;
    }while(!ap_done);
    
    // ap_return read
    ap_return = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_RETURN);
    //printf("ap_return = %d\n", ap_return);
    return(ap_return);
}


lap_fil_axim_uty.h です。

/*
* lap_fil_axim_uty.h
*
* Created on: 2013/10/15
* Author: Masaaki
*/

#ifndef LAP_FIL_AXIM_UTY_H_
#define LAP_FIL_AXIM_UTY_H_

void lap_fil_initialize(unsigned int *lap_fil_hw_addr);
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr, unsigned int *cam_fb, unsigned int *lap_fb);

#endif /* LAP_FIL_AXIM_UTY_H_ */


最後に、xlap_filter_axim_hw.h です。これは、Vivado HLSが生成したファイルです。

// ==============================================================
// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
// Version: 2013.4
// Copyright (C) 2013 Xilinx Inc. All rights reserved.
//
// ==============================================================

// LiteS
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x04 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x10 : reserved
// 0x14 : Data signal of cam_addr
// bit 31~0 - cam_addr[31:0] (Read/Write)
// 0x18 : reserved
// 0x1c : Data signal of lap_addr
// bit 31~0 - lap_addr[31:0] (Read/Write)
// 0x20 : Data signal of ap_return
// bit 31~0 - ap_return[31:0] (Read)
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)

#define XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL 0x00
#define XLAP_FILTER_AXIM_LITES_ADDR_GIE 0x04
#define XLAP_FILTER_AXIM_LITES_ADDR_IER 0x08
#define XLAP_FILTER_AXIM_LITES_ADDR_ISR 0x0c
#define XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA 0x14
#define XLAP_FILTER_AXIM_LITES_BITS_CAM_ADDR_DATA 32
#define XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA 0x1c
#define XLAP_FILTER_AXIM_LITES_BITS_LAP_ADDR_DATA 32
#define XLAP_FILTER_AXIM_LITES_ADDR_AP_RETURN 0x20
#define XLAP_FILTER_AXIM_LITES_BITS_AP_RETURN 32

  1. 2014年02月09日 06:11 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする6(実機でテスト)

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする5(単体シミュレーション)”の続き。

前回、単体シミュレーションが成功したので、ISEの ZedBoard Linux プロジェクトの XPSプロジェクトに追加した。と言うか、すでにVivado HLSで作ったラプラシアンフィルタIPが入っているので、入れ替えた。
ISEのプロジェクトを示す。
Vivado_HLS_2013_4_23_140208.png

下にXPSプロジェクトを示す。
Vivado_HLS_2013_4_24_140208.png

lap_filter_axim_top_0 が今回、Vivado HLS 2013.4 で作製したラプラシアンフィルタAXI4 Master IPだ。

ハードウェアをエクスポートしてSDKを立ちあげた。
Vivado_HLS_2013_4_25_140208.png

後は、おなじみの BOOT.bin を作ってSDカードにコピーして、ZedBoradを立ちあげて、SDKからSSHでラプラシアンフィルタ起動用のソフトウェアをFTPして起動させた。その結果を下に示す。
Vivado_HLS_2013_4_26_140208.jpg

うまくは行ったのだが、画像は全体的に強調されていて、余計な線が入っている。下に、ソフトウェアでのラプラシアンフィルタ結果を示す。
Vivado_HLS_2013_4_27_140208.jpg

う~ん。うまくDONEは出るようになったのだが、なんとも微妙な結果だ。なお、ラプラシアンフィルタ自体のプログラムはソフトウェアとVivado HLSで全く同じだ。

SDKのラプラシアンフィルタ制御用のソフトウェアの全体での実行時間は 100msec 程度だった。下にTera Termの画面を示す。
Vivado_HLS_2013_4_28_140208.png

ピンクの四角で囲んだのが、Vivado HLSでの実行時間だ。394msec がソフトウェアでのラプラシアンフィルタの実行時間、10msec が自作ハードウェア・ラプラシアンフィルタ AXI Master IPでの実行時間だが、これだけはハードウェア部分のみの実行時間となっている。

"Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする7(ソース公開)”に続く。
  1. 2014年02月09日 05:51 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする5(単体シミュレーション)

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする4”の続き。

前回、Vivado HLS 2013.4 でラプラシアンフィルタのAXI4 Master IPを生成できたので、今度は単体シミュレーションを行った。

ISE14.7 のプロジェクトを作製し、その下にXPSプロジェクトを作った。ISEのプロジェクトを下に示す。
Vivado_HLS_2013_4_19_140208.png

XPSプロジェクトを下に示す。
Vivado_HLS_2013_4_20_140208.png

lap_filter_axim_top_0 が Vivado HLS 2013.4 で作ったラプラシアンフィルタのAXI4 Master IPで、mem_sim_axi_slave_0 は、汎用のメモリモデル(”AXI4 Slave インターフェースのメモリ・シミュレーション用 IP の作製2(シミュレーション)”参照)、reg_set_axi_lite_master_0 は設定レジスタを設定する AXI Lite Master IP(”AXI VDMAのレジスタ設定用AXI Lite Master IPの作製2(シミュレーション)”参照)だ。

各 AXI Slave のアドレスを下に示す。
Vivado_HLS_2013_4_21_140208.png

これで、XPSプロジェクト内で閉じてシミュレーションを行えるはずだ。

lap_filter_axim_top_0 の AXI Lite Slave部分のレジスタのアドレスオフセットを引用する。

//------------------------Address Info-------------------
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved
// 0x04 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
// bit 0 - Channel 0 (ap_done)
// bit 1 - Channel 1 (ap_ready)
// others - reserved
// 0x10 : reserved
// 0x14 : Data signal of cam_addr
// bit 31~0 - cam_addr[31:0] (Read/Write)
// 0x18 : reserved
// 0x1c : Data signal of lap_addr
// bit 31~0 - lap_addr[31:0] (Read/Write)
// 0x20 : Data signal of ap_return
// bit 31~0 - ap_return[31:0] (Read)
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)


reg_set_axi_lite_master_0 のレジスタ設定用コマンドファイルを下に示す。

10000014
00000000
1000001c
00075300
10000000
00000001
ffffffff


これで用意は整ったので、シミュレーションを開始した。ISimの画面を下に示す。
Vivado_HLS_2013_4_22_140208.png

上のシミュレーション波形を見て、やっていることを解析した結果を下に示す。

1.最初のラインのオール0をラプラシアンフィルタの結果としてWriteする。

2.元画像 3ラインをReadする。

3.ラプラシアンフィルタの結果を1ライン分 Writeする。

4.次からは、1ラインずつReadして、ラプラシアンフィルタの結果をWriteする。


4.の間隔は 約 146usec であることがわかった。単純に 600ラインとすると、146usec x 600ライン = 87.6msec となる。必要なフレームレート60fps = 16.7msec よりも遅いという結果になった。

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする6(実機でテスト)”に続く。
  1. 2014年02月08日 07:24 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

XPSプロジェクトのカスタムIP内のgenerateで生成したメモリの初期値を設定する(Verilog HDL)

現在、Vivado HLS 2013.4で生成したラプラシアンフィルタのカスタムIPをシミュレーションしようとしている。”Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする4”参照

ISEでシミュレーション用のプロジェクトを作製し、XPSプロジェクトをISEプロジェクト内に作製した。
Vivado_HLS_2013_4_16_140207.png

XPSプロジェクトがこちら。lap_filter_axim_top_0 の M_AXI_CAM_FB, M_AXI_LAP_FB がメモリモデルの mem_sim_axi_slave_0 に接続されている。
Vivado_HLS_2013_4_17_140207.png

メモリモデルの mem_sim_slave については、”AXI4 Slave インターフェースのメモリ・シミュレーション用 IP の作製2(シミュレーション)”を参照のこと。C_MEMORY_SIZE = 960000 に設定している。800x600ピクセルのSVGA画面2画面分だ。

2画面分の領域を確保したうちの1画面だけを画像の情報として初期化したいという欲求があった。画像データをファイルから読み込んで、そのまま使用してもよいのだが、面倒なので、おなじみのM系列の擬似ランダム数で初期化することにした。

いろいろと試行錯誤してしまったが、出来たのでやり方を書いておく。階層としては、次の通りになる。

1.system_top_tbがシミュレーションのテストベンチで最上位ということになる。

2.その下に、system_topを uut してインスタンスしてある。

3.systemという名前のXPSプロジェクトが、system_i という名前でインスタンスしてある。

4.XPSプロジェクトに下に、 mem_sim_axi_slave_0をインスタンスしてある。

5.mem_sim_axi_slaveでは、memory_8bit を memory_8bit_i というインスタンス名で generate 文でインスタンスしてある。


mem_sim_axi_slave.v 上で、memory_8bit をインスタンスしてある部分を下に示す。

    // instance memory_8bit
    generate
        genvar i;
        
        for (i=(C_S_AXI_DATA_WIDTH/8-1); i>=0; i=i-1) begin : MEMORY_GEN
            memory_8bit #(
                .C_S_AXI_ADDR_WIDTH(C_S_AXI_ADDR_WIDTH),
                .C_MEMORY_SIZE(C_MEMORY_SIZE)
            ) memory_8bit_i (
                .clk(ACLK),
                .waddr(waddr),
                .write_data(S_AXI_WDATA[i*8+7:i*8]),
                .write_enable(wready & S_AXI_WVALID),
                .byte_enable(S_AXI_WSTRB[i]),
                .raddr(raddr),
                .read_data(S_AXI_RDATA[i*8+7:i*8])
            );
        end
    endgenerate


この mem にM系列の擬似ランダム数を入れたい。下にテストベンチでのM系列の生成するためのfunction を示す。

    // R, G, B 毎に違った生成多項式のM系列を用意した
    function [7:0] mseqf8_R (input [7:0] din);
        reg xor_result;
        begin
            xor_result = din[7] ^ din[3] ^ din[2] ^ din[1];
            mseqf8_R = {din[6:0], xor_result};
        end
    endfunction

    function [7:0] mseqf8_G (input [7:0] din);
        reg xor_result;
        begin
            xor_result = din[7] ^ din[4] ^ din[2] ^ din[0];
            mseqf8_G = {din[6:0], xor_result};
        end
    endfunction

    function [7:0] mseqf8_B (input [7:0] din);
        reg xor_result;
        begin
            xor_result = din[7] ^ din[5] ^ din[2] ^ din[1];
            mseqf8_B = {din[6:0], xor_result};
        end
    endfunction


下に、初期化を行った Verilog HDL のコードを示す。これは、テストベンチ system_top_tb.v から、XPSプロジェクト以下の メモリの前半分を初期化している。

    // M系列を使用した擬似ランダム数でメモリの半分を初期化した
    initial begin : memory_init_zero
        integer i;
        for (i=0; i<480000; i=i+1) begin
            uut.system_i.mem_sim_axi_slave_0.mem_sim_axi_slave_0.MEMORY_GEN[3].memory_8bit_i.mem[i] = 8'd0;
        end
    end

    initial begin : memory_init_red
        integer i;
        for (i=0; i<480000; i=i+1) begin
            uut.system_i.mem_sim_axi_slave_0.mem_sim_axi_slave_0.MEMORY_GEN[2].memory_8bit_i.mem[i] = mseq8r;
            mseq8r = mseqf8_R(mseq8r);
        end
    end

    initial begin : memory_init_green
        integer i;
        for (i=0; i<480000; i=i+1) begin
            uut.system_i.mem_sim_axi_slave_0.mem_sim_axi_slave_0.MEMORY_GEN[1].memory_8bit_i.mem[i] = mseq8g;
            mseq8g = mseqf8_G(mseq8g);
        end
    end

    initial begin : memory_init_blue
        integer i;
        for (i=0; i<480000; i=i+1) begin
            uut.system_i.mem_sim_axi_slave_0.mem_sim_axi_slave_0.MEMORY_GEN[0].memory_8bit_i.mem[i] = mseq8b;
            mseq8b = mseqf8_B(mseq8b);
        end
    end


ISim のメモリ表示を下に示す。
Vivado_HLS_2013_4_18_140207.png

メモリがM系列の擬似ランダム数で初期化されているのがわかった。


注意が必要なのは、XPSプロジェクトでは、mem_sim_axi_slave_0 の下の mem_sim_axi_slave_0 に実体があるということだ。それに、generate 文を使った時のインスタンス名に注意して欲しい。(XilinxのXSTを使用した時のインスタンスの仕方です。Altera の Quartus II では、インスタンス名が違うかもしれません?)
  1. 2014年02月07日 04:39 |
  2. 入門Verilog
  3. | トラックバック:0
  4. | コメント:0

ISEからのQuestaシミュレーションでMicron社のDDR3モデルを使用する

ISEからQuestaを使ったシミュレーションを行っている。その際に、Micron社のDDR3 Verilog HDL model(モデルのダウンロードが始まるので注意)を使わせて頂いている。その場合の注意点を覚書で残しておく。

ddr3.v を修正した。

・string で宣言してある行をコメントアウト

・int 宣言を integer 宣言に変更

・2048Mb_ddr3_parameters.vh の ceil()を削除


このくらいだったか?後は忘れた。。。

ISEのシミュレーション状態で、Questaのプロパティを下図の様に変更した。
Questa_2_140206.png

vlog のオプションは、vhファイルを2Gbit のDDR3 SDRAMに設定して、sg125グレードを使用し、16ビット・データ幅にセットするためのdefineである。

bank_fileが開けないと言われてfinishしてしまうのを回避するために、1つ上の階層に ddr3 フォルダを作成して、+model_data+../ddr3 を vsim のオプションとして使用する。これは、”MIG DDR3 using MAX_MEM module error: simulation cannot run because file can not open ”の2ページ目を参考にした。

なお、RESETが外れてから、MIGの init_calib_complete が 1 になるまで 110us 程度かかっている。(ビヘイビアー シミュレーションで、MIGへの供給クロックが400MHzの場合、DDR3-800、C_SIM_BYPASS_INIT_CAL = "FAST")
Questa_1_140204.png
  1. 2014年02月06日 10:41 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:1

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする4

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする3”の続き。

前回は、Visual Studio 2012 でVivado HLS 2013.4 に使うためのCソースをシミュレーションしてみた。うまく行ったので、今回は、Vivado HLS 2013.4 に持ってきてCシミュレーションやCからHDLへの合成、IP化などを行う。

まずは、Vivado HLSで C Simulation を行った。
Vivado_HLS_2013_4_13_140206.png

成功した。初めて C Simulation で成功したので嬉しい。但し時間が掛かった。やはり、Visual Studioで完璧に仕上げてから Vivado HLS に持って来るべきだと思う。

次にCからHSLへの合成を行った。下にログを示す。

================================================================
== Vivado HLS Report for 'lap_filter_axim'
================================================================
* Date: Wed Feb 05 06:31:08 2014

* Version: 2013.4 (build date: Mon Dec 09 17:07:59 PM 2013)
* Project: lap_filter_axim_2013_4
* Solution: solution1
* Product family: zynq zynq_fpv6
* Target device: xc7z020clg484-1


================================================================
== Performance Estimates
================================================================
+ Timing (ns):
* Summary:
+---------+-------+----------+------------+
| Clock | Target| Estimated| Uncertainty|
+---------+-------+----------+------------+
|default | 10.00| 8.75| 1.25|
+---------+-------+----------+------------+

+ Latency (clock cycles):
* Summary:
+---------+------------+---------+------------+---------+
| Latency | Interval | Pipeline|
| min | max | min | max | Type |
+---------+------------+---------+------------+---------+
| 1450201| 6942730201| 1450202| 6942730202| none |
+---------+------------+---------+------------+---------+

+ Detail:
* Instance:
N/A

* Loop:
+---------------------+---------+------------+-----------------+-----------+-----------+------+----------+
| | Latency | Iteration | Initiation Interval | Trip | |
| Loop Name | min | max | Latency | achieved | target | Count| Pipelined|
+---------------------+---------+------------+-----------------+-----------+-----------+------+----------+
|- Loop 1 | 1450200| 6942730200| 2417 ~ 11571217 | -| -| 600| no |
| + Loop 1.1 | 1600| 11570400| 2 ~ 14463 | -| -| 800| no |
| ++ Loop 1.1.1 | 14451| 14451| 4817| -| -| 3| no |
| +++ Loop 1.1.1.1 | 814| 814| 16| 1| 1| 800| yes |
| +++ Loop 1.1.1.2 | 4000| 4000| 5| -| -| 800| no |
| ++ Loop 1.1.2 | 814| 814| 16| 1| 1| 800| yes |
| ++ Loop 1.1.3 | 4800| 4800| 6| -| -| 800| no |
| + Loop 1.2 | 801| 801| 3| 1| 1| 800| yes |
+---------------------+---------+------------+-----------------+-----------+-----------+------+----------+



================================================================
== Utilization Estimates
================================================================
* Summary:
+-----------------+---------+-------+--------+-------+
| Name | BRAM_18K| DSP48E| FF | LUT |
+-----------------+---------+-------+--------+-------+
|Expression | -| 14| 0| 905|
|FIFO | -| -| -| -|
|Instance | -| 2| 960| 952|
|Memory | 10| -| 0| 0|
|Multiplexer | -| -| -| 281|
|Register | -| -| 1001| -|
|ShiftMemory | -| -| 0| 8|
+-----------------+---------+-------+--------+-------+
|Total | 10| 16| 1961| 2146|
+-----------------+---------+-------+--------+-------+
|Available | 280| 220| 106400| 53200|
+-----------------+---------+-------+--------+-------+
|Utilization (%) | 3| 7| 1| 4|
+-----------------+---------+-------+--------+-------+

+ Detail:
* Instance:
+-----------------------------------------+--------------------------------------+---------+-------+-----+-----+
| Instance | Module | BRAM_18K| DSP48E| FF | LUT |
+-----------------------------------------+--------------------------------------+---------+-------+-----+-----+
|lap_filter_axim_mul_8ns_7ns_15_3_U4 |lap_filter_axim_mul_8ns_7ns_15_3 | 0| 1| 0| 0|
|lap_filter_axim_mul_8ns_7ns_15_3_U6 |lap_filter_axim_mul_8ns_7ns_15_3 | 0| 1| 0| 0|
|lap_filter_axim_srem_11ns_11ns_11_14_U0 |lap_filter_axim_srem_11ns_11ns_11_14 | 0| 0| 110| 130|
|lap_filter_axim_urem_10ns_10ns_10_13_U1 |lap_filter_axim_urem_10ns_10ns_10_13 | 0| 0| 110| 130|
|lap_filter_axim_urem_10ns_10ns_10_13_U2 |lap_filter_axim_urem_10ns_10ns_10_13 | 0| 0| 110| 130|
|lap_filter_axim_urem_12ns_12ns_12_15_U3 |lap_filter_axim_urem_12ns_12ns_12_15 | 0| 0| 315| 281|
|lap_filter_axim_urem_12ns_12ns_12_15_U5 |lap_filter_axim_urem_12ns_12ns_12_15 | 0| 0| 315| 281|
+-----------------------------------------+--------------------------------------+---------+-------+-----+-----+
|Total | | 0| 2| 960| 952|
+-----------------------------------------+--------------------------------------+---------+-------+-----+-----+

* Memory:
+------------+--------------------------+---------+------+-----+------+-------------+
| Memory | Module | BRAM_18K| Words| Bits| Banks| W*Bits*Banks|
+------------+--------------------------+---------+------+-----+------+-------------+
|lap_buf_U |lap_filter_axim_lap_buf | 2| 800| 24| 1| 19200|
|line_buf_U |lap_filter_axim_line_buf | 8| 2400| 32| 1| 76800|
+------------+--------------------------+---------+------+-----+------+-------------+
|Total | | 10| 3200| 56| 2| 96000|
+------------+--------------------------+---------+------+-----+------+-------------+

* FIFO:
N/A

* Shift register:
+--------------------+---+----+-----+-----------+
| Name | FF| LUT| Bits| Const Bits|
+--------------------+---+----+-----+-----------+
|exitcond1_reg_1538 | 0| 1| 1| 0|
|exitcond7_reg_1434 | 0| 1| 1| 0|
|tmp_39_reg_1453 | 0| 3| 3| 0|
|tmp_43_reg_1556 | 0| 3| 3| 0|
+--------------------+---+----+-----+-----------+
|Total | 0| 8| 8| 0|
+--------------------+---+----+-----+-----------+

* Expression:
+--------------------------+----------+-------+---+----+------------+------------+
| Variable Name | Operation| DSP48E| FF| LUT| Bitwidth P0| Bitwidth P1|
+--------------------------+----------+-------+---+----+------------+------------+
|mul1_fu_717_p2 | * | 1| 0| 0| 12| 13|
|mul_fu_940_p2 | * | 1| 0| 0| 12| 13|
|p_addr10_fu_789_p2 | * | 1| 0| 0| 11| 10|
|p_addr16_fu_1113_p2 | * | 1| 0| 0| 10| 10|
|p_addr3_fu_774_p2 | * | 1| 0| 0| 10| 10|
|p_addr6_fu_965_p2 | * | 1| 0| 0| 3| 10|
|p_addr7_fu_1152_p2 | * | 1| 0| 0| 10| 10|
|p_addr_fu_736_p2 | * | 1| 0| 0| 3| 10|
|tmp_2_fu_598_p2 | * | 1| 0| 0| 10| 10|
|tmp_35_i1_fu_826_p2 | * | 1| 0| 0| 8| 8|
|tmp_35_i_fu_1038_p2 | * | 1| 0| 0| 8| 8|
|tmp_36_i1_fu_816_p2 | * | 1| 0| 0| 8| 5|
|tmp_36_i_fu_1028_p2 | * | 1| 0| 0| 8| 5|
|y_i44_op_cast_fu_1297_p2 | * | 1| 0| 1| 24| 17|
|a_1_fu_883_p2 | + | 0| 0| 2| 2| 1|
|b_2_fu_990_p2 | + | 0| 0| 10| 10| 1|
|b_fu_761_p2 | + | 0| 0| 10| 10| 1|
|grp_fu_553_p0 | + | 0| 0| 11| 11| 2|
|grp_fu_559_p0 | + | 0| 0| 10| 10| 1|
|grp_fu_708_p0 | + | 0| 0| 12| 12| 12|
|indvar_next1_fu_1320_p2 | + | 0| 0| 10| 10| 1|
|indvar_next2_fu_687_p2 | + | 0| 0| 10| 10| 1|
|indvar_next_fu_914_p2 | + | 0| 0| 10| 10| 1|
|next_mul1_fu_525_p2 | + | 0| 0| 19| 19| 10|
|next_mul2_fu_865_p2 | + | 0| 0| 12| 12| 10|
|next_mul_fu_871_p2 | + | 0| 0| 12| 12| 10|
|p_addr11_fu_1189_p2 | + | 0| 0| 12| 12| 12|
|p_addr12_fu_1086_p2 | + | 0| 0| 13| 13| 13|
|p_addr13_fu_1100_p2 | + | 0| 0| 13| 13| 13|
|p_addr14_fu_1130_p2 | + | 0| 0| 13| 13| 13|
|p_addr15_fu_1179_p2 | + | 0| 0| 12| 12| 12|
|p_addr17_fu_1140_p2 | + | 0| 0| 13| 13| 13|
|p_addr18_fu_1000_p2 | + | 0| 0| 12| 12| 12|
|p_addr1_fu_746_p2 | + | 0| 0| 13| 13| 13|
|p_addr2_fu_1208_p2 | + | 0| 0| 12| 12| 12|
|p_addr5_fu_1203_p2 | + | 0| 0| 12| 12| 12|
|p_addr8_fu_1199_p2 | + | 0| 0| 13| 13| 13|
|p_addr9_fu_975_p2 | + | 0| 0| 13| 13| 13|
|p_sum1_fu_583_p2 | + | 0| 0| 33| 33| 33|
|p_sum2_fu_893_p2 | + | 0| 0| 33| 33| 33|
|p_sum_fu_666_p2 | + | 0| 0| 33| 33| 33|
|sum3_i_fu_1242_p2 | + | 0| 0| 32| 32| 32|
|tmp3_fu_1166_p2 | + | 0| 0| 32| 32| 32|
|tmp4_fu_1226_p2 | + | 0| 0| 32| 32| 32|
|tmp5_fu_1221_p2 | + | 0| 0| 32| 32| 32|
|tmp_15_fu_930_p2 | + | 0| 0| 12| 12| 12|
|tmp_s_fu_1077_p2 | + | 0| 0| 11| 11| 2|
|x_1_fu_610_p2 | + | 0| 0| 10| 10| 1|
|tmp_38_i_fu_1252_p2 | - | 0| 0| 32| 32| 32|
|tmp_39_i_fu_1258_p2 | - | 0| 0| 32| 32| 32|
|tmp_i2_fu_1246_p2 | - | 0| 0| 32| 32| 32|
|y_3_fu_1263_p2 | - | 0| 0| 32| 32| 32|
|phitmp_fu_1302_p3 | Select | 0| 0| 24| 1| 2|
|ap_sig_bdd_131 | and | 0| 0| 1| 1| 1|
|ap_sig_bdd_174 | and | 0| 0| 1| 1| 1|
|ap_sig_bdd_520 | and | 0| 0| 1| 1| 1|
|exitcond1_fu_908_p2 | icmp | 0| 0| 11| 10| 9|
|exitcond2_fu_1314_p2 | icmp | 0| 0| 11| 10| 9|
|exitcond3_fu_984_p2 | icmp | 0| 0| 11| 10| 9|
|exitcond4_fu_877_p2 | icmp | 0| 0| 2| 2| 2|
|exitcond5_fu_604_p2 | icmp | 0| 0| 11| 10| 9|
|exitcond6_fu_531_p2 | icmp | 0| 0| 11| 10| 10|
|exitcond7_fu_681_p2 | icmp | 0| 0| 11| 10| 9|
|exitcond_fu_755_p2 | icmp | 0| 0| 11| 10| 9|
|icmp_fu_1287_p2 | icmp | 0| 0| 30| 24| 1|
|isIter0_fu_924_p2 | icmp | 0| 0| 11| 10| 1|
|isIter1_fu_697_p2 | icmp | 0| 0| 11| 10| 1|
|isIter_fu_1331_p2 | icmp | 0| 0| 11| 10| 1|
|tmp_16_fu_638_p2 | icmp | 0| 0| 11| 10| 9|
|tmp_17_fu_644_p2 | icmp | 0| 0| 11| 10| 1|
|tmp_5_fu_656_p2 | icmp | 0| 0| 11| 10| 1|
|tmp_6_fu_626_p2 | icmp | 0| 0| 11| 10| 1|
|tmp_9_fu_574_p2 | icmp | 0| 0| 11| 10| 1|
|tmp_fu_620_p2 | icmp | 0| 0| 11| 10| 10|
|tmp_26_fu_650_p2 | or | 0| 0| 1| 1| 1|
|tmp_8_fu_632_p2 | or | 0| 0| 1| 1| 1|
+--------------------------+----------+-------+---+----+------------+------------+
|Total | | 14| 0| 905| 996| 811|
+--------------------------+----------+-------+---+----+------------+------------+

* Multiplexer:
+-----------------------+----+-----------+-----+-----------+
| Name | LUT| Input Size| Bits| Total Bits|
+-----------------------+----+-----------+-----+-----------+
|a_reg_368 | 2| 2| 2| 4|
|b1_reg_414 | 10| 2| 10| 20|
|b_1_reg_357 | 10| 2| 10| 20|
|cam_fb_address | 32| 3| 32| 96|
|indvar1_reg_443 | 10| 2| 10| 20|
|indvar9_reg_346 | 10| 2| 10| 20|
|indvar_reg_403 | 10| 2| 10| 20|
|lap_buf_address0 | 10| 3| 10| 30|
|lap_fil_val_1_reg_425 | 24| 2| 24| 48|
|line_buf_address0 | 24| 11| 12| 132|
|line_buf_address1 | 12| 6| 12| 72|
|line_buf_d0 | 32| 4| 32| 128|
|phi_mul1_reg_322 | 19| 2| 19| 38|
|phi_mul2_reg_391 | 12| 2| 12| 24|
|phi_mul_reg_379 | 12| 2| 12| 24|
|reg_484 | 32| 2| 32| 64|
|x_reg_334 | 10| 2| 10| 20|
|y_reg_310 | 10| 2| 10| 20|
+-----------------------+----+-----------+-----+-----------+
|Total | 281| 53| 269| 800|
+-----------------------+----+-----------+-----+-----------+

* Register:
+-----------------------------------------+----+-----+-----------+
| Name | FF | Bits| Const Bits|
+-----------------------------------------+----+-----+-----------+
|a_1_reg_1527 | 2| 2| 0|
|a_reg_368 | 2| 2| 0|
|ap_CS_fsm | 6| 6| 0|
|ap_reg_ppiten_pp0_it0 | 1| 1| 0|
|ap_reg_ppiten_pp0_it1 | 1| 1| 0|
|ap_reg_ppiten_pp0_it10 | 1| 1| 0|
|ap_reg_ppiten_pp0_it11 | 1| 1| 0|
|ap_reg_ppiten_pp0_it12 | 1| 1| 0|
|ap_reg_ppiten_pp0_it13 | 1| 1| 0|
|ap_reg_ppiten_pp0_it14 | 1| 1| 0|
|ap_reg_ppiten_pp0_it15 | 1| 1| 0|
|ap_reg_ppiten_pp0_it2 | 1| 1| 0|
|ap_reg_ppiten_pp0_it3 | 1| 1| 0|
|ap_reg_ppiten_pp0_it4 | 1| 1| 0|
|ap_reg_ppiten_pp0_it5 | 1| 1| 0|
|ap_reg_ppiten_pp0_it6 | 1| 1| 0|
|ap_reg_ppiten_pp0_it7 | 1| 1| 0|
|ap_reg_ppiten_pp0_it8 | 1| 1| 0|
|ap_reg_ppiten_pp0_it9 | 1| 1| 0|
|ap_reg_ppiten_pp1_it0 | 1| 1| 0|
|ap_reg_ppiten_pp1_it1 | 1| 1| 0|
|ap_reg_ppiten_pp1_it10 | 1| 1| 0|
|ap_reg_ppiten_pp1_it11 | 1| 1| 0|
|ap_reg_ppiten_pp1_it12 | 1| 1| 0|
|ap_reg_ppiten_pp1_it13 | 1| 1| 0|
|ap_reg_ppiten_pp1_it14 | 1| 1| 0|
|ap_reg_ppiten_pp1_it15 | 1| 1| 0|
|ap_reg_ppiten_pp1_it2 | 1| 1| 0|
|ap_reg_ppiten_pp1_it3 | 1| 1| 0|
|ap_reg_ppiten_pp1_it4 | 1| 1| 0|
|ap_reg_ppiten_pp1_it5 | 1| 1| 0|
|ap_reg_ppiten_pp1_it6 | 1| 1| 0|
|ap_reg_ppiten_pp1_it7 | 1| 1| 0|
|ap_reg_ppiten_pp1_it8 | 1| 1| 0|
|ap_reg_ppiten_pp1_it9 | 1| 1| 0|
|ap_reg_ppiten_pp2_it0 | 1| 1| 0|
|ap_reg_ppiten_pp2_it1 | 1| 1| 0|
|ap_reg_ppiten_pp2_it2 | 1| 1| 0|
|ap_reg_ppstg_exitcond2_reg_1730_pp2_it1 | 1| 1| 0|
|ap_reg_ppstg_isIter_reg_1744_pp2_it1 | 1| 1| 0|
|b1_reg_414 | 10| 10| 0|
|b_1_reg_357 | 10| 10| 0|
|b_2_reg_1574 | 10| 10| 0|
|b_3_reg_1493 | 8| 8| 0|
|b_4_reg_1584 | 8| 8| 0|
|b_reg_1471 | 10| 10| 0|
|cam_fb_addr_1_reg_1532 | 32| 32| 0|
|cam_fb_addr_reg_1393 | 32| 32| 0|
|exitcond1_reg_1538 | 1| 1| 0|
|exitcond2_reg_1730 | 1| 1| 0|
|exitcond4_reg_1523 | 1| 1| 0|
|exitcond7_reg_1434 | 1| 1| 0|
|fl_reg_1379 | 11| 11| 0|
|icmp_reg_1715 | 1| 1| 0|
|indvar1_reg_443 | 10| 10| 0|
|indvar9_reg_346 | 10| 10| 0|
|indvar_reg_403 | 10| 10| 0|
|isIter0_reg_1547 | 1| 1| 0|
|isIter1_reg_1443 | 1| 1| 0|
|isIter_reg_1744 | 1| 1| 0|
|lap_buf_load_reg_1748 | 24| 24| 0|
|lap_fb_addr_reg_1429 | 32| 32| 0|
|lap_fil_val_1_reg_425 | 24| 24| 0|
|line_buf_addr_11_reg_1579 | 12| 12| 0|
|line_buf_addr_2_reg_1488 | 12| 12| 0|
|line_buf_load_4_reg_1657 | 32| 32| 0|
|next_mul1_reg_1352 | 19| 19| 0|
|next_mul2_reg_1513 | 12| 12| 0|
|next_mul_reg_1518 | 12| 12| 0|
|p_addr10_reg_1481 | 8| 13| 5|
|p_addr1_reg_1463 | 13| 13| 0|
|p_addr2_reg_1682 | 12| 12| 0|
|p_addr4_reg_1476 | 12| 12| 0|
|p_addr5_reg_1677 | 12| 12| 0|
|p_addr6_reg_1561 | 8| 13| 5|
|p_addr8_reg_1672 | 13| 13| 0|
|p_addr9_reg_1566 | 13| 13| 0|
|p_addr_reg_1458 | 8| 13| 5|
|phi_mul1_reg_322 | 19| 19| 0|
|phi_mul2_reg_391 | 12| 12| 0|
|phi_mul_reg_379 | 12| 12| 0|
|phitmp_reg_1725 | 24| 24| 0|
|reg_475 | 32| 32| 0|
|reg_480 | 8| 8| 0|
|reg_484 | 32| 32| 0|
|sl_reg_1384 | 10| 10| 0|
|tl_reg_1372 | 10| 10| 0|
|tmp3_reg_1652 | 32| 32| 0|
|tmp4_reg_1697 | 32| 32| 0|
|tmp_10_reg_1447 | 12| 12| 0|
|tmp_15_trn_cast_reg_1604 | 13| 13| 0|
|tmp_2_reg_1399 | 7| 12| 5|
|tmp_30_reg_1620 | 7| 12| 5|
|tmp_33_reg_1626 | 8| 13| 5|
|tmp_34_reg_1641 | 7| 12| 5|
|tmp_35_reg_1647 | 8| 13| 5|
|tmp_36_i1_reg_1503 | 14| 14| 0|
|tmp_36_i_reg_1594 | 14| 14| 0|
|tmp_38_i_reg_1707 | 32| 32| 0|
|tmp_39_reg_1453 | 3| 3| 0|
|tmp_41_reg_1720 | 24| 24| 0|
|tmp_43_reg_1556 | 3| 3| 0|
|tmp_4_cast_reg_1341 | 32| 33| 1|
|tmp_5_cast_reg_1347 | 32| 33| 1|
|tmp_5_reg_1425 | 1| 1| 0|
|tmp_9_reg_1389 | 1| 1| 0|
|x_1_reg_1407 | 10| 10| 0|
|x_cast_reg_1414 | 10| 11| 1|
|x_reg_334 | 10| 10| 0|
|y_1_reg_1361 | 10| 10| 0|
|y_2_reg_1508 | 8| 8| 0|
|y_4_reg_1599 | 8| 8| 0|
|y_reg_310 | 10| 10| 0|
+-----------------------------------------+----+-----+-----------+
|Total |1001| 1044| 43|
+-----------------------------------------+----+-----+-----------+



================================================================
== Interface
================================================================
* Summary:
+--------------------+-----+-----+------------+-----------------+--------------+
| RTL Ports | Dir | Bits| Protocol | Source Object | C Type |
+--------------------+-----+-----+------------+-----------------+--------------+
|ap_clk | in | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_rst | in | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_start | in | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_done | out | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_idle | out | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_ready | out | 1| ap_ctrl_hs | lap_filter_axim | return value |
|ap_return | out | 32| ap_ctrl_hs | lap_filter_axim | return value |
|cam_addr | in | 32| ap_none | cam_addr | scalar |
|lap_addr | in | 32| ap_none | lap_addr | scalar |
|cam_fb_req_din | out | 1| ap_bus | cam_fb | pointer |
|cam_fb_req_full_n | in | 1| ap_bus | cam_fb | pointer |
|cam_fb_req_write | out | 1| ap_bus | cam_fb | pointer |
|cam_fb_rsp_empty_n | in | 1| ap_bus | cam_fb | pointer |
|cam_fb_rsp_read | out | 1| ap_bus | cam_fb | pointer |
|cam_fb_address | out | 32| ap_bus | cam_fb | pointer |
|cam_fb_datain | in | 32| ap_bus | cam_fb | pointer |
|cam_fb_dataout | out | 32| ap_bus | cam_fb | pointer |
|cam_fb_size | out | 32| ap_bus | cam_fb | pointer |
|lap_fb_req_din | out | 1| ap_bus | lap_fb | pointer |
|lap_fb_req_full_n | in | 1| ap_bus | lap_fb | pointer |
|lap_fb_req_write | out | 1| ap_bus | lap_fb | pointer |
|lap_fb_rsp_empty_n | in | 1| ap_bus | lap_fb | pointer |
|lap_fb_rsp_read | out | 1| ap_bus | lap_fb | pointer |
|lap_fb_address | out | 32| ap_bus | lap_fb | pointer |
|lap_fb_datain | in | 32| ap_bus | lap_fb | pointer |
|lap_fb_dataout | out | 32| ap_bus | lap_fb | pointer |
|lap_fb_size | out | 32| ap_bus | lap_fb | pointer |
+--------------------+-----+-----+------------+-----------------+--------------+


C/RTL Cosimulation を行った。これはエラーになってしまった。
Vivado_HLS_2013_4_14_140206.png

最後に、Export RTL を行った。pcores の下に、lap_filter_axim_top_v1_00_a が出来た。
Vivado_HLS_2013_4_15_140206.png

これで、IPは生成できた。出来上がったIPをISim でシミュレーションを行ってみようと思う。

”Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする5(単体シミュレーション)”に続く。
  1. 2014年02月06日 05:03 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする3

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする2”の続き。

S様にVivado HLSについてお尋ねしたら、私のラプラシアン・フィルタを評価していただけるということなので、お願いしたら、デバックして頂いた。その知見を元に、私なりに今までのラプラシアン・フィルタのコードを見なおしてみたい。S様、本当にお手間を取らせてすみませんでした。そして、ありがとうございました。

というわけで、もう一度、ラプラシアン・フィルタのCコードからのHDL合成にチャレンジすることにした。

最初に、Vivado HLS 2013.4でCシミュレーションすると、何でおかしいのか?よく分からないので、Cシミュレーションは、Visual Studio 2012 でやることにした。これならば、デバックも慣れている。
Visual Studio 2012の画面を下に示す。
Vivado_HLS_2013_4_11_140205.png

S様のアドバイスを元に修正したのだが、いろいろと間違っていた。修正して、Visual Studio 2012でデバックし、動かすことができた。
Vivado_HLS_2013_4_12_140205.png

次に、Vivdo HLS 2013.4 に戻って、もう一度、Cシミュレーションからやってみよう。

Vivado HLS 2013.4でラプラシアン・フィルタ関数をaxi masterモジュールにする4”に続く。
  1. 2014年02月05日 05:23 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製16(ハードウェアのデバック4)

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製15(ハードウェアのデバック3)”の続き。

AXI IICの出力がなくなっていたので、これを修正することにした。最初にiic_3state_buf IP のコードをIOBUFプリミティブを使用するように変更した。下にVerilog HDLファイルを示す。

`default_nettype none

module iic_3state_buf(
    output  wire    sda_i,
    input   wire    sda_o,
    input   wire    sda_t,
    output  wire    scl_i,
    input   wire    scl_o,
    input   wire    scl_t,
    inout   wire    sda,
    inout   wire    scl
);
    IOBUF scl_iobuf (
        .I(scl_o),
        .IO(scl),
        .O(scl_i),
        .T(scl_t)
    );
    IOBUF sda_iobuf (
        .I(sda_o),
        .IO(sda),
        .O(sda_i),
        .T(sda_t)
    );
endmodule

`default_nettype wire


これで、論理合成、インプリメントしてみたが、怪しいクリティカル・ワーニングが出てしまった。その後、iic_3state_buf IPを使用するのを止めて、ikwzm さんに教えてもらった手順でAXI IICのIOBUF をインスタンスしたが、いろいろといじりすぎてか?論理合成でエラーが出るようになってしまった。
Cam_VDMA_197_140203.png

PSが無いと言われては、完全におかしい。。。仕方が無いので、新しく 1日がかりでVivado 2013.4のプロジェクトを作りなおした。そして、ikwzm さんに教えてもらった手順でAXI IICのIOBUF をインスタンスした。それして、論理合成、インプリメントを行ったところ、AXI IICのIOBUFが実装されていた。下の図に hdmi_iic_scl_iobuf の様子を示す。きちんとIOピンに配線が行っているのが見えるはずだ。
Cam_VDMA_198_140203.png

下に新しく作りなおしたVivado 2013.4のプロジェクトを示す。
Cam_VDMA_199_140203.png

IP Integrator のBlock Design (CamD_VDMA.bd) を示す。
Cam_VDMA_200_140203.png

ハードウェアをエクスポートして、SDKを起動した。
Cam_VDMA_201_140203.png

Program FPGAして、ソフトウェアを作り直して、Run Configuration を作製し、Runを行ったが、ディスプレイには、ランダムパターンが表示されただけで、失敗した。
Cam_VDMA_202_140203.jpg

1歩前進したので、もう一度 Vivado Logic Analyzer をかけてデバックを行う。

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製17(ハードウェアのデバック5)”に続く。
  1. 2014年02月03日 04:53 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製15(ハードウェアのデバック3)

”Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製14(ハードウェアのデバック2)”の続き。

今回は、Hardware Manager を立ちあげて、実際の波形を観測する。

・ZedBoardの電源をONにしておく。

・Flow Navigator からOpen Hardware Manager を立ち上げる。
Cam_VDMA_178_140129.png

・Hardware Manager が立ち上がった。Open a new hardware target をクリックした。
Cam_VDMA_179_140131.png

・Open Hardware Target ダイアログが表示された。Next >ボタンをクリックした。
Cam_VDMA_180_140131.png

・Vivado CSE Server Name を設定する。localhost:60001 のデフォルトのまま、Next >ボタンをクリックした。
Cam_VDMA_181_140131.png

・Select Hardware Target でARM とZynq-7020 が見えた。Next >ボタンをクリックした。
Cam_VDMA_182_140131.png

・Set Hardware Properties で、FREQUENCYを 1500000Hz に設定した。
Cam_VDMA_183_140131.png

・Summary が表示された。Finishボタンをクリックした。
Cam_VDMA_184_140131.png

・Hardware Manager はこんな感じになった。
Cam_VDMA_185_140131.png

・xc7x020_1 を右クリックし、右クリックメニューからProgram Device... を選択した。
Cam_VDMA_186_140131.png

・コンフィグレーションするビットストリームがすでに表示されていた。OKボタンをクリックした。
Cam_VDMA_187_140131.png

・そうするとエラーになった。ZynqでPSからクロックをもらっているので、当然クロックは来ていないはず。PSをブートする必要があるね。。。
Cam_VDMA_188_140131.png

ここで、ZedBoard.org の Reference Designs/Tutorials ページの”Zynq Concepts, Tools, and Techniques on ZedBoard, Vivado 2013.2 Version”をダンロードして、マニュアル、”ZedBoard: Zynq-7000 AP SoC Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design ZedBoard (Vivado 2013.2)”の 47, 48ページを見ると、エラーダイアログが出たら、SDKでHello World を実行しろと書いてあった。そうか、Hello World を実行すれば、PSからクロックが来るね。。。

・SDKでHello World プロジェクトを作製した。
Cam_VDMA_189_140131.png

・Run Configuration を作って、Runした。
Cam_VDMA_190_140131.png

・ps7_init is completed. になった。
Cam_VDMA_191_140131.png

・Vivado に戻って、Refresh device をクリックし、xc7z020_1 を選択した。
Cam_VDMA_192_140131.png

・Hardware Manager に各ILAが見えた。成功。。。
Cam_VDMA_193_140131.png

・図のアイコンをクリックした。トリガ条件はまだ入れていない。
Cam_VDMA_194_140201.png

・現在のAXIバスの様子が波形で示された。
Cam_VDMA_195_140201.png

SDKで、cam_disp_vdmaソフトウェアを走らせて、Hardware Manager で波形を見たが、AXIバスが動作していない。SDKでRUNしているのに、cam_disp_vdmaソフトウェアは終了していなかった。おかしい。。。
SDKでデバックしてみると、HDMI用AXI IICのステータスレジスタのReadでTX FIFOがEmpty になっていなかった。

いろいろと調べてみると驚愕の事実が判明した。AXI IICのSDA, SCL の出力をつないだはずの hdmi_iic_Scl, hdmi_iic_Sda ピンがGNDにつながっていた。下に、hdmi_iic_Sda ピンを示す。
Cam_VDMA_196_140201.png

緑色のロジックに行く線が LOGIC0 になっていた。

自分で作ったiic_3state_buf_0, iic_3state_buf_1 IPがおかしいのか?
Cam_VDMA_99_140113.png

iic_3state_bufを何とかしてみることにする。

Vivado 2013.4でAXI VDMAを使ったカメラ表示回路の作製16(ハードウェアのデバック4)”に続く。
  1. 2014年02月02日 04:29 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

つくば健康マラソンに出場しました

今日はつくば健康マラソンに出場しました。40歳以上の男子の部で5kmです。
5kmは昨年の11月10日に、坂東ハーフマラソンに出ました。その時に記録は、5kmで29分48秒でしたが、今日はそれよりも3分以上速くなりました。26分33秒で走れました。約5:18/km です。3分以上も速くなって、とっても嬉しいです。
Tsukuba_kenkou_marathon_1_140203.jpg

うちの奥さんも40歳以上の女子の部で、5位でした。おめでとうございます。パチパチ。。。
タイムは、23分52秒でした。ゴール直前で4位の人に抜かれたそうです。4位とは1秒差、3位とも10秒位の差だそうです。ともかくお立ち台ということでめでたいです。
下が5位の賞状です。
Tsukuba_kenkou_marathon_2_140203.jpg

盾ももらってきました。
Tsukuba_kenkou_marathon_3_140203.jpg

私のつくば健康マラソンの走行記録へのリンクです。
  1. 2014年02月01日 22:28 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado Logic AnalyzerでTCP番号60001番を使用するソフトウェア

Vivado Logic Analyzerを使っていて、Vivadoが反応しなくなるので、vivado.exeをタスクマネージャーから落とすのだが、TCP番号60001を使用していて、60001番を開放されない時がある。

TCP番号60001番をどんなプロセスが使っているか調べるには、コマンドプロンプトで”netstat -ano”を実行する。そうすると、TCP番号60001番を使用しているPID (Process ID) がわかる。下の図の場合は、7080のPIDのプロセスがTCP番号60001番を使用している。
vcse_server_1_140201.png

タスクマネージャーを開いて、表示メニューから列の選択... を選んでPIDにチェックを入れて、PIDを表示させる。
PID順にソートすると、vcse_server.exe がPID番号が7080でこれが、TCP番号60001を使っていることがわかる。
vcse_server_2_140201.png

このプロセスを終了させて、”netstat -ano”を実行したところ、TCP番号60001は未使用になった。
vcse_server_3_140201.png

Vivado でLogic Analyzer を起動していて、どうにもキャンセルできなくて、vivado.exeを落とした時には、hw_server.exe も強制終了させないとダメなようです。
vcse_server_4_140201.png
  1. 2014年02月01日 05:08 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0