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

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

FPGAの部屋

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

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製7(MCBインプリメント4)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製6(MCBインプリメント3)”の続き。

前回は、MCBをmicorblaze_0 のAXI4 Liteバスに接続してインプリメントしたが、WriteはできてもReadは出来ていなかった。他に原因があるかもしれないが、本来はMCBはビットマップ・ディスプレイ・コントローラから使用する。microblaze_0 がアクセスするのはおまけなので、MCBを別のAXI4 Interconnect に移動することにした。その場合は、AXI to AXI Connector を間に介してAXI4 Interconnect 同士を接続する。

・まずは下図左のaxi4lite_0 とaxi_s6_ddrx_0 の交点をクリックして、axi_s6_ddrx_0 をNo Connection にした。
BitMapDispCont_38_120730.png

・IP Catalog からAXI to AXI Connector を選択し、右クリックメニューからAdd IP を選択した。
BitMapDispCont_39_120730.png

・ダイアログが開いた。OKボタンをクリックした。
BitMapDispCont_40_120730.png

・XPS Core Config ダイアログが開く。Systemタブの設定項目を下に示す。
BitMapDispCont_41_120730.png

・Interconnect Settings for BUFIF の設定項目を下に示す。(デフォルト値のままとした)
BitMapDispCont_42_120730.png
BitMapDispCont_43_120730.png

・axi2axi_connector_0 が入った。
BitMapDispCont_44_120730.png

次に、AXI4 Interconnect を入れる。

・IP Catalog からAXI Interconnect を選択し、右クリックメニューからAdd IPを選択した。
BitMapDispCont_45_120730.png

・ダイアログが開いた。OKボタンをクリックした。
BitMapDispCont_46_120730.png

・・XPS Core Config ダイアログが開く。Interconnect Strategyタブの設定項目を下に示す。
BitMapDispCont_47_120730.png

・その他の設定項目を下に示す。(すべてデフォルト値のままとした)
BitMapDispCont_48_120730.png
BitMapDispCont_49_120730.png
BitMapDispCont_50_120730.png
BitMapDispCont_51_120730.png

・axi_interconnect_0 が入った。
BitMapDispCont_52_120730.png

・axi2axi_connector_0 のS_AXI にaix4lite_0 をM_AXI にaxi_interconnect_0 を接続した。axi_interconnect_0 にaxi_s6_ddrx_0 を接続した。
BitMapDispCont_53_120730.png

・axi_interconnect_0 をダブルクリックしてダイアログを開き、Master/Slave Specific Settingsタブを開く。axi_s6_ddrx_0:S0_AXIの設定を下の図のように設定した。
BitMapDispCont_54_120730.png

・Portsタブをクリックして、INTERCONNECT_ACLK とINTERCONNECT_ARESETN を下図のように接続した。
BitMapDispCont_55_120730.png

・Addressesタブをクリックした。axi2axi_connector_0 のSizeを512Mバイトとした。これは256Mバイトを使用するaxi_s6_ddrx_0 を収めるためだ。アドレス領域の確保は2のn乗である必要があるので、0x20000000 ~ 0x3fffffff までとした。axi_s6_ddrx_0 はその下なので、0x20000000 ~ 0x2fffffff に変更した。
BitMapDispCont_56_120730.png

・UCFファイルにrzqとzio のIOSTANDARD を追加した。
BitMapDispCont_57_120730.png

・ProjectメニューからDesign Rule Check をやってみたところエラーは無かった。
BitMapDispCont_58_120730.png

次に、SDKにハードウェアをエクスポートしてSDKを立ちあげた。デバックモードでXMDを使用して、MCBのアドレスにWrite/Readしてみたが、Readをするとおかしくなって、以後、正常に出来ていたアクセスもだめになるようだ。
BitMapDispCont_59_120731.png

なお、SDKの使用方法は前回と全く同じなので、”AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製6(MCBインプリメント3)”を参照。

注意として、AtlysボードでSDKを使用する場合は、内臓のコンフィグ回路はとっても不安定だ。Xilinx純正ダウンロードケーブルを使用するか、XUP USB-JTAG Programming Cableの方が安定して動作する。
  1. 2012年07月30日 05:39 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

夏休み自由研究お助け企画

今年も8月の最初の土日に夏休み自由研究お助け企画をやります。
中学生対象で、自由研究の補助をするという企画です。本当は中学生がやりたいことを考えて、それに対してアドバイスするというスタンスが良いのですが、それだとあまり人が集まらなそうなので、(でも独自企画を持ってきた中学生はいますよ)こちらからテーマを提示して中学生に応募してもらうという形式です。
私の担当テーマは、音の自由研究とライントレース・ロボットです。
音の自由研究は、パソコンを使用して音声波形をソフトウェアでキャプチャして見てもらいます。これは主に母音ですね。(連続波形)子音も見られますよ。後は楽器の波形とかです。これは土曜日にやります。
ライントレース・ロボットは秋月に売っているのを使用します。これは今年作ったテーマです。去年までは、太陽電池の発電量を調べるというのやっていたんですが、やはりイベントの時が曇だと評判が悪かったので。。。でも、どちらのテーマも家でもできるように機材は差し上げているんですが、やはり家じゃなくてイベントの時に電力でないとがっかりされるようです。夏休み期間中調べて積分するところでいいところなんですが残念です。
ライントレース・ロボットは、数値は測るところがあまりないのですが、やはり意図通りに動くと面白いですね。中学生受けは良いと思います。
  1. 2012年07月28日 20:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

おおかみこどもの雨と雪(映画)を見てきました

おおかみこどもの雨と雪(映画)を見てきました。映画館は人で一杯でした。珍しい。珍しく午後に見に行ったから?でも、映画がとっても良かったためだと思います。本当にとっても良かったです。。。泣けます。本当はあまり面白くないのかな?と思って見に行ったんですが、良い意味で期待が外れました。
  1. 2012年07月28日 20:07 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製6(MCBインプリメント3)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製5(MCBインプリメント2)”の続き。

まだ、DDR2 SDRAMコントローラ(MCB) しか実装していないが、これでインプリメントして動作を確認して見ることにした。それに制約ファイルでMCBの入出力ピンをしていないけれども、どのMCBを使うか決まったところで入出力ピンは決まっているはずなので、それを確かめるためでもある。
前回でXPSの設定は終了しているので、XPSを終了してPlanAhead プロジェクトに戻った。最初にMCBを追加して、大幅に入出力ピンが増えているので、トップファイルのsystem_stub.v を作りなおした。
更に、PlanAhead14.2が出たので、14.1から乗り換えることにした。プロジェクトをアップグレードするようなので、14.1に戻れなくなると困るので、トップのフォルダごとコピーして、Atlys_EDK_test_PA_142とした。これでインプリメントを行った。

・最初にsystem.xpsをダブルクリックしてXPS14.2に変換した。変換後、Design Rule Check はすんなり通った。一安心。最近、バージョンが上がって変換にしくじることは少なくなった気がする。

・TopファイルにMCBの入出力ピンを追加するためにsystem.xpsで右クリックして、Create Top HDLを実行して、system_stub.v を再生成した。
BitMapDispCont_28_120727.png

・Program and Debug のGenerate Bitstream をクリックして実行し、論理合成、インプリメントを行い、ビットストリームを生成した。
BitMapDispCont_29_120728.png

・FileメニューからExport -> Export Hardware for SDK を選択して、SDKにハードウェア構成をExportした。Launch SDK にチェックを入れてOKボタンをクリックした。
BitMapDispCont_30_120728.png

・SDKが立ち上がった。以前書いたchar_rom_axi_lite_test.c が表示されていた。
BitMapDispCont_31_120728.png

・Xilinx Tools メニューからProgram FPGA を選択する。ダイアログが開くので、Program ボタンをクリックして、AtlysボードのSpartan-6をコンフィギュレーションする。
BitMapDispCont_32_120729.png

・これだとやはりエラーになったので、iMPACTからコンフィギュレーションした。Spartan6\Atlys\test\Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.sdk\SDK\SDK_Export\system_hw_platform のsystem.bit を使用した。
BitMapDispCont_33_120729.png

一旦、char_rom_axi_lite_test.elf を選んでDebugモードにしてみたが、Cソースが表示されなかった。よって、リンカスクリプトを再生成する。

・Xilinx Tools メニューからGenerate linker script を選択した。

・Output Scriptに、H:\HDL\FndtnISEWork\Spartan6\Atlys\test\Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.sdk\SDK\SDK_Export\char_rom_axi_lite_test\src\lscript.ld を指定した。Generateボタンをクリックした。
BitMapDispCont_34_120729.png

・もう一度Debugモードにした。
BitMapDispCont_35_120729.png

・今度はソースコード・デバック出来るようになった。
BitMapDispCont_36_120729.png

・ここでXilinx Tools メニューからXMDを選択して、MCBのアドレス0x10000000 にWrite、ReadしてみたところWriteはできるが、Readはできかなった?
BitMapDispCont_37_120729.png

なぜだろう?Writeは出来たのに、Readはできない?やはり、AXI4 LiteバスにAXI4バスを接続したのが悪かったのか?マニュアルでは出来るように書いてあったと思ったんだが?
もう一度テストしてみたい。キャラクタ・ジェネレータROMにもアクセスしてみよう。

やはり、キャラクタ・ジェネレータROMのデータは読めるが、DDR2 SDRAMのデータは読めなかった。
  1. 2012年07月28日 06:48 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

Vivado 2012.2

昨日、ISE14.2が出ていたのでインストールした。Vivado 2012.2 も一緒にインストールされた。今回はVivado を立ち上げたら普通に立ち上がった。
Vivado_1_120727.png

Open Example Project からBFT core を選んでプロジェクトを開いた。プロジェクトを他の所にセーブする仮定があったが、プロジェクトが開いたところを下に示す。
Vivado_2_120727.png

PlanAheadとあまり変わらない感じがするが、制約ファイルのbft_full.xdc を開けてみると、Altera社のTimeQuest で見慣れたSDC記述だった。やっぱりVivado なんだね。
Vivado_3_120727.png

RTL Analysis でSchematic をクリックして回路図を表示してみた。この辺はPlanAhead14.1とあまり変わらない気がする。(”PlanAhead14.1のExampleのBFT Core を試してみた1(RTL Analysis)”参照)
Vivado_4_120727.png

Synthesis をやってみたところライセンスが無いと言われてしまった。ライセンスの問題を解決してビットストリームの生成まで出来た。でも、シミュレーションは私のWindows XPでは初期化次にエラーになってしまった。(ダイアログが出た)Windwos7 64ビット版ではシミュレーションが出来た。シミュレータはVivado にビルトインされていた。
Vivado のビットストリームの生成が完了した画面を下に示す。
Vivado_5_120727.png

  1. 2012年07月27日 05:22 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:4

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製5(MCBインプリメント2)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製4(MCBインプリメント1)”の続き。

前回の続き。(使用バージョンは14.1)

・Ports タブをクリックすると、MCBのピンが全くExternal に出ていない。
BitMapDispCont_19_120726.png

・axi_s6_ddrx_0 -> (IO_IF) memory_0 の下向き^をクリックして、Make Ports External を選択して外部ポートに接続した。
BitMapDispCont_20_120726.png

・上の図を見るとわかるが、axi_s6_ddrx_0 のsysclk_2x やsysclk_2x_180 がつながっていない。

clock_generator_0 がAXIバスクロックの100MHzのCLKOUT0 のみなので、クロック出力を生成する。(1から設定すると面倒だ。BSBウィザードでボードパッケージを使えるメリットを十分に感じた。。。)(下の図ではConnected Port などのメニューのところを右クリックして右クリックメニューからNetをチェックして、Netを表示している)
BitMapDispCont_21_120726.png

・clock_generator_0 をダブルクリックして、ダイアログを出す。

・CLKOUT1のRequired Frequency (Hz) に600000000 (600MHz), Required Phase に 0, Required Group に PLL0, Bufferd にFALSE を設定した。
・CLKOUT2のRequired Frequency (Hz) に600000000 (600MHz), Required Phase に 180, Required Group に PLL0, Bufferd にFALSE を設定した。
・CLKOUT0のRequired Group に PLL0を設定した。
BitMapDispCont_22_120726.png

・axi_s6_ddrx_0 のsysclk_2x のConnected Port 空きスペースを右クリックして右クリックメニューから、New Connection を選択する。
・axi_s6_ddrx_0 のsysclk_2x_180 のConnected Port 空きスペースを右クリックして右クリックメニューから、New Connection を選択する。
・axi_s6_ddrx_0_sysclk_2x とaxi_s6_ddrx_0_sysclk_2x_180 のネットが出来た。
・clk_generator_0 のCLKOUT1 とCLKOUT2 Netを選択して接続した。
BitMapDispCont_23_120726.png

・axi_s6_ddrx_0 のpll_lock をclock_generator_0::LOCKED に、sys_rst をproc_sys_reset::Bus_Struct_Resetに、ui_clk をclk_generator_0::CLKOUT0 (100MHz)に接続した。
BitMapDispCont_24_120726.png

・更に、axi_s6_ddrx_0の(BUS_IF) S0_AXI を展開して s0_axi_aclk を clk_generator_0::CLKOUT0 (100MHz)に接続した。
BitMapDispCont_25_120726.png

これで大体のMCBのIPのポートは接続できたかな?次にMCBのアドレスをマップする。

・Addressタブをクリックして、axi_s6_ddrx_0 のBase Address を0x10000000 に設定した。すると、High Address が自動的に0x1FFFFFFF に変更された。
BitMapDispCont_26_120726.png

これで、MCBの設定は大体終了かな?結構大変だった。
後は、DDR2の外部ポートのUCFは書かなくて良いのだろうか?おいおい見て行こう。

おまけとして、最後に、ProjectメニューからDesign Rule Check をやってみたところエラーは無かった。
BitMapDispCont_27_120726.png
  1. 2012年07月26日 05:59 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製4(MCBインプリメント1)

Zynqをやっていて、だいぶ間が開いてしまったが、”AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製3(単体シミュレーション)”の続き。

キャラクタROMをAXI4 Lite Slave として実装する4(UARTをXPSプロジェクトに追加する)”のPlanAheadプロジェクトを使用する。まずはXPSプロジェクトにDDR2 SDRAMコントローラのMCBを追加する。(使用バージョンは14.1)

・XPSで、AXI S6 Memory Controller(DDR/DDR2/DDR3) 1.05a の右クリックメニューからAdd IP を選択する。
BitMapDispCont_6_120726.png

・ダイアログが表示される。Yesボタンをクリックする。
BitMapDispCont_7_120726.png

・MCBの設定ダイアログが立ち上がる。DDR2 SDRAMに変更した。
BitMapDispCont_8_120726.png

・Memory Part を設定する。EDE1116AXX-8E を選択した。
BitMapDispCont_9_120726.png

・Output Drive Strength やODT などを設定する。Defaultのままとする。
BitMapDispCont_10_120726.png

・ビットマップ・ディスプレイ・コントローラのデータ幅は64ビットなので、Two 64-bit bi-directional ports を選択して、Port0のみにチェックを入れる。
BitMapDispCont_11_120726.png

・次のダイアログでは、AR, AW, B, R, W Register をAUTOMATIC に設定した。
BitMapDispCont_12_120726.png
BitMapDispCont_13_120726.png
BitMapDispCont_14_120726.png

・Arbitration はデフォルトのままとした。
BitMapDispCont_15_120726.png

・Select RZQ pin location を L6 に、Select ZIO pin location を C2 に変更してFinish ボタンをクリックした。
BitMapDispCont_16_120726.png

・AXIバスをmicroblaze_0 に接続するために、OKボタンをクリックした。
BitMapDispCont_17_120726.png

・XPSに axi_s6_ddrx_0 が追加された。S0_AXIを axi4lite_0 に接続した。
BitMapDispCont_18_120726.png

  1. 2012年07月25日 05:48 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ZC702ボードを返却します

先月の末に借用したZC702ボード(Zynqのボードです)をそろそろ返却します。長い間ありがとうございました。おかげ様で、チュートリルの続きもできました。Linuxを立ち上げることができて、リモートデバックを使って、mmap() で物理アドレス空間を仮想アドレス空間にマップしてGPIOを制御することができました。HDMIを使えなかったのは残念ですが、ZebBoardを頼んであるので、ボードが届いたら、そっちで存分に試してみようと思っています。

それでは、今度は懸案の”AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製3(単体シミュレーション)”の続きをやりたいと思います。シミュレーション上では動いているようなので、ソフトウェアを作ってテストします。”キャラクタROMをAXI4 Lite Slave として実装する8(SDK2)”で作ったキャラクタROMのラスタデータをソフトウェア的に読み込んで、ビットマップ・ディスプレイ・コントローラに書き込むことでディスプレイに文字を書いてみたいと思います。
  1. 2012年07月23日 05:51 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

お祭り終了

一昨日と今日で地元のお祭がありました。うちの地区のお祭りは大人と子供のお神輿が出ます。地区の大人のお神輿は1基ですが、子供のお神輿は小学校低学年用、小学校高学年用、中学生用と3基あります。それに付いて行って危なく無いよう警備する役どころです。他の地区の中学生用神輿が集まってきて、何基も一緒になると興奮してきて神輿同士をぶつけようとするので抑えるが大変です。ほんとうに疲れました。例年、夏休みの初めの土日に行われるのですが、今年は暑くなくて涼しくて助かりました。土日とも最高気温22度くらいだったので、異常気象ですね?今日からは暑くなるようなので、片付けを頑張ります。今日は午後から打ち合わせと会議があるので、午前休を取ります。
mikoshi_120723.jpg
  1. 2012年07月23日 05:33 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

AutoESLのセミナを受けてきました

7月17日(火)、7月18日(木)にXilinx本社のセミナルームで、”AutoESLを使用したハイレベルの合成”という題のセミナを受けてきました。

2日間ともお昼の後は眠かったんですが、特に1日目は前の夜がとても蒸し暑く寝苦しかったので、とっても眠く夢心地で聞いていたので、誤解や聞き間違いがあるかもしれませんので、眉につばをつけて御覧ください。

以前、展示会のデモでCatapult C Synthesis のデモを見せてもらったことがあります。その時は、何の回路か忘れましたが、レイテンシとスループットを設定して簡単にいろいろな構成の回路を生成していました。これはとっても素敵なことだと思いました。FPGAを使っていて何が困るかというと、レイテンシを最短に、スループットを最小にしたいという妄想?にとらわれている時に、ぎりぎりのところを狙うとします。このくらいパイプラインしたら、この動作周波数で行けるかな?というギリギリのところを狙った時に、HDLを書いて論理合成、インプリメントするまでは、その回路で行けるかどうかわからないことです。インプリメントして結果を見た時にだめだったとなった時に、色々、ツールのエフォートレベルを変えてみたり、ダメだったら配置制約を加えてクリティカルパスを潰していきます。でも、そういう時は往々にして、他のところがクリティカルパスに新たになってもぐらたたきゲームの用になったりします。そうすると回路を書き換えてパイプライン段数を変更したりしました。データパス系だけだと比較的簡単にパイプラインできることが多いですが、制御系が絡んでいたりするとだと作り直しになったりします。
そこでHigh Level Synthesis(HLS) を使って、お手軽にレイテンシとスループットを設定して変更しながら、色々な回路を生成してもらって、ピッタリの動作周波数で動くものを選べれば簡単なのにと思いました。これは時間と労力が劇的に少なくなるとっても素敵なことです。でもツールの価格が高いという欠点がありました。
AutoESLはVivado のSystem Editon に組み込まれるそうなので、お手軽に使えそうです。期待してセミナに行きました。結論から言うとAutoESLはそういうツールではないようです。C言語からVHDL、Verilog、SystemCを合成してくれますが、お手軽にレイテンシとスループットを設定して回路を生成してくれるツールではないとの説明でした。C言語で書いたアルゴリズムをHDLに変換できるのですが、どのように変換するかはディレクティブで指定するようです。PIPELINEやDATAFLOWなどのディレクティブをCソースコードに付加することによって、最適化するイメージみたいです。XilinxのFPGAに最適化されているようで、RESOURCEというディレクティブでは、BRAMやLUTRAMも選べるようです。セミナをやってみた感じでは、C to HDLの品質をディレクティブを入れていくことによってチューニングして品質を上げていって、品質を上げたことによるリソースの増加を見て落とし所を決めるというイメージでした。これはこれで使いこなせるようになった時は、カリカリにチューニングできそうです。(注:カリカリにチューニング出来るというのは、適切な部分にディレクティブを入れていくと、どんどん早くなってチューニングが進む様子のことを書きました。HDLで適切に書けば、その方が性能が上がるのは言うまでもないことだと思います)
一番良いと思ったのは、データ型でビット幅を自由に選べて、C++でしたら飽和演算のタイプも指定できることです。固定小数点型もあります。これで演算途中のビット精度を自由に決めることができるので、演算がたくさんある場合のFPGAのリソース量をコントロールしやすいと思います。
AutoESLは、プロセッサで実行しているCコードを手軽にハードウェアにオフロードするという用途にピッタリなのではないか?と思いました。PLB、FSL、AXIスレーブ、マスタ、ストリームバスも選択すれば簡単に接続できるようです。
非常に制限も少なく使いやすいのですが、例えば、3X3の画像用のラプラシアンフィルタなどでは、HDLでやっている方法では作りづらいのではないか?と思いました。
例えば、”画像のエッジ検出6(3X3での方式の検討)”でラプラシアンフィルタをVHDLで書いたのですが、この場合には、画像の2ラインをBRAMにバッファして現在のピクセルとクロック遅れのピクセルを集めてきてラプラシアンフィルタを構成していました。これをCで書くことはなかなか難しいのではないか?ということです。Cで書くとすると、どうしても画像データを入れておく部分は配列にする必要があります。(malloc()禁止です)配列にするとメモリにマップされるので、DDRなどのSDRAMに領域が大きいためマップされることになると思います。ラプラシアンフィルタの演算要素を取ってくるために配列をReadすると、DDR SDRAMに3x3要素のデータを取りに行く事になると思われます。この方法ではDDR SDRAMのメモリ負荷が増え、場合によっては帯域が足りなくなることが考えられます。この程度の画像の演算ではローカルにピクセルデータを持っている方が、メモリ帯域の面からもベターだと思われます。つまり、ラプラシアンフィルタのアルゴリズムをAutoESLで書いて、それにデータを入れる部分はHDLで書いた方が我々の用途には合っていると思われます。
適材適所でツールを使用するといった方法が良いのでは?と思います。スループットを求め、小さなメモリ帯域でプロセッサをほとんど使用しない場合は、前に書いたような構成にしたいと思います。またプロセッサでほとんど処理をしていて、もっと早い処理を望む場合はAutoESLが使うことが最も適していると思われます。使用したいバスを自動生成しながらZynqのPL部にオフロードします。更にハードウェアにオフロードした部分をディレクティブを指定してチューニングすることが出来ます。
今の私の用途では、主要なブロックはEDKでIPを使用して構成して、独自の部分はAXI4バスプロトコルを独自に構成してインターフェースします。それにつながる独自アルゴリズムの部分をCで書いてAutoESLでHDLにコンパイルしてもらいます。この様に作るのが一番だと今のところは思っています。(注:AutoESLでは、あくまでソフトウェアで書けるように書くのが良いと思っています。色々なバッファを入れるためにテクニックを使ってCで書くのは本末転倒になる可能性があるのではないでしょうか? 普通にCで書けないのであれば、HDLを使うか、IPを使えば良いのでは?と思います。アルゴリズムをソフトウェアの浮動小数点(ハードでも出来ると思いますが)とハードウェアに最適化するための固定小数点、飽和演算をifdef で切り替えてお手軽にシミュレーション出来るのは魅力的です)
最後に、AutoESLの吐いたVHDL, Verilogはわかり易かったです。HDLに落としてからでも、もしかしたらそれでデバックできるのではないでしょうか?

最後にも付け足しておきますが、講師の方には本当に申し訳なかったですが、夢心地で聞いていたので間違っているかもしれません。もし間違っているというご指摘がありましたら、コメント欄でお知らせください。
  1. 2012年07月21日 22:24 |
  2. HLS
  3. | トラックバック:0
  4. | コメント:1

Zynq-7000(ZC702)のLinuxでMIOに接続されているLEDを制御2

Zynq-7000(ZC702)のLinuxでMIOに接続されているLEDを制御”の続き。

前回はDS23(LED) をLinuxで制御したが、今回はAXI GPIOに接続されたSW5を押した時にDS23(LED) を点灯させて、その後消灯させてみようと思う。これが出来れば、”Zynq-7000(ZC702)でビットファイル入りのLinuxのブートイメージが入ったSDカードを作る”で作ったビットファイル入りのLinuxブートイメージで間違いなくビットファイルをコンフィギュレーションしていることがわかった。

(注)今回のブログでは、”Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の19ページからの”Embedded System Design Using the Zynq Processing System and Programmable Logic”チュートリアル(通称、チュートリアル2)で作成したビットファイルでコンフィギュレーションされた回路をZynqのLinux上から動作させている。
このチュートリアルについては、”Zynq-7000(ZC702)のチュートリアル2をやってみた1(XPSプロジェクトの生成)”の記事とそれに続く記事を参照のこと。


さて、それでは、やってみよう。手順は前回と同じだが、もう一度書いておく。

・SDカードをZC702に挿入し、電源ON。

・Linuxが立ち上がる。IPアドレスを10.10.70.120 にセットする。(ifconfig eth0 10.10.70.120 netmask 255.255.255.0)

・パソコンで、SDKを立ちあげて、チュートリアル2のワークスペースを指定する。

・SDKのRemote Absolute File Path for C/C++ Application でLinuxのリモートデバックをするファイルを作成する。(”Zynq-7000(ZC702)のLinuxチュートリアル4(リモートデバック2)”参照)

今回のCソースを下に貼る。

#define MIO_GPIO_BASE    0xE000A000
#define AXI_GPIO_BASE    0x41200000

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

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

// I/O access

volatile unsigned *setup_io(off_t addr);

int main()
{
    volatile unsigned *mask_data_0_lsw, *mask_data_0_msw;
    volatile unsigned *data_0, *data_0_ro;
    volatile unsigned *dirm_0, *oen_0; 
    volatile unsigned *mio_gpio;
    volatile unsigned *axi_gpio, *axi_gpio_tri;
    int axi_gpio_val, axi_gpio_val_old;

    mio_gpio = setup_io((off_t)MIO_GPIO_BASE);
    axi_gpio = setup_io((off_t)AXI_GPIO_BASE);

    mask_data_0_lsw =     mio_gpio;
    mask_data_0_msw =     mio_gpio + 1;        // 0x4番地
    data_0 =             mio_gpio + 0x10;    // 0x40番地
    data_0_ro =         mio_gpio + 0x18;    // 0x60番地
    dirm_0 =             mio_gpio + 0x81;    // 0x204番地
    oen_0 =             mio_gpio + 0x82;    // 0x208番地
    axi_gpio_tri =        axi_gpio + 1;        // 0x4番地
    
    *(dirm_0) = *(dirm_0)|0x400;    // gpio[10]を出力に設定
    *(oen_0) = *(oen_0)|0x400;        // gpio[10]をイネーブル
    *(axi_gpio_tri) = 0x1;            // axi_gpio入力設定

    printf("AXI_GPIO_TRI = %x\n", *(axi_gpio_tri));

    printf("MASK_DATA_0_LSW = %x\n", *(mask_data_0_lsw));
    printf("MASK_DATA_0_MSW = %x\n", *(mask_data_0_msw));
    printf("DATA_0 = %x\n", *(data_0));
    printf("DATA_0_RO = %x\n", *(data_0_ro));
    printf("DIRM_0 = %x\n", *(dirm_0));
    printf("OEN_0 = %x\n", *(oen_0));

    *(data_0) = *(data_0)&(~(0x400));    // DS23 (LED) 消灯
    printf("DATA_0 = %x\n", *(data_0));

    axi_gpio_val_old = *(axi_gpio);
    while(1){
        axi_gpio_val = *(axi_gpio);
        if (axi_gpio_val)
            *(data_0) = *(data_0)|(0x400);    // DS23点灯
        else
            *(data_0) = *(data_0)&(~(0x400));    // DS23消灯

        if (!axi_gpio_val && axi_gpio_val_old)
            break;    // axi_gpio が1から0になった立下りでループを抜ける
        axi_gpio_val_old = axi_gpio_val;
    }

    printf("AXI_GPIO = %x\n", *(axi_gpio));

    printf("Hello World\n");

    return 0;
}


AXI_GPIO_BASEの値は、xparameter.h からいただいてきた。xparameter.h がどこにあるかというと、SDKのProject Explorer のBSP(hello_world_bsp_0) -> ps7_cortexa9_0 -> include にある。プログラムはDS23を消灯して、SW5の値をDS23に設定する。SW5が押された時にDS23を点灯して、離された時にDS23を消灯してからreturn する。
なぜ、hello world があるかというとhello_worldプロジェクトを書き換えているからだ。hello world はそのままで残している。
setup_io() は前回から、物理アドレスを引数に入れて関数をコールし、返り値に論理アドレスを返すように書き換えた。基本的なコードは、”RPi Low-level peripherals”のsetup_io() のままだ。
どこを書き換えたか説明する。最初に関数の宣言を書き換えた。コメントアウトしてあるのが元の関数宣言だ。

volatile unsigned *setup_io(off_t mapped_addr)
// void setup_io()


グローバルだった変数をローカル変数に変更して、setup_io() に追加した。

    int  mem_fd;
    char *gpio_mem, *gpio_map;


mmap() の部分を書き変えた。最後の引数のGPIO_BASEを、関数が呼ばれた時の引数のmapped_addr に書き換えている。

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


最後にreturn() を書き加えた。コメントアウトしてあるのが、書き換えた行だ。

   // gpio = (volatile unsigned *)gpio_map;
   return((volatile unsigned *)gpio_map);


・これでCソースは完成したので、セーブすれば、オートでビルドされる。

・下図がDebugモードに移行したSDKだ。この状態ではConsole にgdb のデバッグメッセージが出ている。これを抑制するために、ピンクの四角で囲ったVerbose console mode をクリックして解除する。
ZC702_Linux_54_120720.png

Verbose console mode をクリックして解除すると、gdb のメッセージが抑制されて、printfで書かれたメッセージがよく見えるようになる。

・RunメニューからResumeをクリックするとソフトウェアが動作して、SW5を押すとDS23が点灯し、SW5を話すとDS23が消灯してソフトウェアからリターンした。

実行時のSDKのConsole に表示されたメッセージを下に貼っておく。

zynq> gdbserver :1234 /Apps/linux_hello_world_0.elf null
Process /Apps/linux_hello_world_0.elf created; pid = 655
Listening on port 1234
Remote debugging from host 10.10.70.121
AXI_GPIO_TRI = 1
MASK_DATA_0_LSW = 2ab2
MASK_DATA_0_MSW = 681
DATA_0 = 6812ab2
DATA_0_RO = 6802a32
DIRM_0 = 480
OEN_0 = 480
DATA_0 = 6c12ab2
AXI_GPIO = 0
Hello World

Child exited with status 0
GDBserver exiting
zynq>
zynq> exit


これで、PL部分に構築されたAXI GPIOを、PS部分のARMプロセッサで動作するLinuxで使うことが出来た。つまり、ビットファイル入りのLinuxブートイメージで、間違いなくビットファイルをコンフィギュレーション出来ているということになる。

おまけとして、ZynqのLinuxにソフトウェアをロードしてリモートデバックを実行しているので、実体はZynqのLinux上のApps -> linux_hello_world_0.elf となる。当然、Zynq上でlinux_hello_world_0.elf を実行すると同じ結果になる。
ZC702_Linux_55_120720.png

(注)mmap() はroot権限でしか使えません。
  1. 2012年07月20日 05:11 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のLinuxでMIOに接続されているLEDを制御

ZC702のLinuxを立ち上げた状態で、”Zynq-7000(ZC702)のLinuxチュートリアル3(リモートデバック)”でやってきたSDKのリモートデバックを使用して、DS23(LED)を制御してみた。

Zynq-7000(ZC702)でビットファイル入りのLinuxのブートイメージが入ったSDカードを作る”で作ったチュートリアル2が入ったSDカードでLinuxをブートしたが、そのSDカードを使ってブートしたLinuxを使用する。

LEDのDS23はMIO 10に接続されている。チュートリアル2でのMIO Configuration はMIO 10にgpio[10] が接続されている。”Zynq-7000(ZC702)のチュートリアル2のXPSでのZynqの設定”参照。

ZynqのMIOの設定については、”Zynq-7000 Extensible Processing Platform Technical Reference Manual UG585 (v1.0) May 8, 2012"を参照した。そのマニュアルの282ページ、”14.3 GPIO Control of Device Pins”の”Figure 14‐2: GPIO Channel”によると、GPIOの出力はDATA, MASK_DATA_LSW, MASK_DATA_MSW, DIRM, OEN が関係する。下に”Figure 14‐2: GPIO Channel”を引用させていただく。
ZC702_Linux_53_120718.png

(なお、ツイッターで@jet_lagさんに大変お世話になりました。ありがとうございました。)

このGPIOの設定レジスタの情報は、同じマニュアルの1191ページ、”B.19 General Purpose I/O (gpio) ”に書いてある。
MASK_DATA_0_LSW は32ビットのレジスタでMIO[15:0]を設定する。下の16ビットが MASK_0_LSW で1がセットされているとマスクされる。上の16ビットは DATA_0_LSW で、DATA_0[15:0] の値を設定する。ReadするとWriteした値が見える。Readは DATA_0_RO をReadすると、ピンの値が見える。
MASK_DATA_0_MSW は同じく32ビットのレジスタでMIO[31:16]を設定する。
DATA_0はMIO[31:0] の出力の値を設定する。
DIRM_0は、そのピットの入出力設定で、0が入力、1が出力だ。
OEN_0は、そのビットのイネーブル設定で、0がディスエーブル、1がイネーブルだ。

これらを踏まえて、SDKのリモートデバックを使用して、DS23(LED)を制御してみる。

・SDカードをZC702に挿入し、電源ON。

・Linuxが立ち上がる。IPアドレスを10.10.70.120 にセットする。(ifconfig eth0 10.10.70.120 netmask 255.255.255.0)

・パソコンで、SDKを立ちあげて、チュートリアル2のワークスペースを指定する。

・SDKのRemote Absolute File Path for C/C++ Application でLinuxのリモートデバックをするファイルを作成する。(”Zynq-7000(ZC702)のLinuxチュートリアル4(リモートデバック2)”参照)

GPIOを制御する方法は、mmap() を使用することにした。Raspberry PiのLinux用だが、調度良いサンプルが”RPi Low-level peripherals”にあったので、これを参照してプログラムを書いた。
プログラムを下に貼っておく。なお、void setup_io() は、”RPi Low-level peripherals”のものをそのまま使用しているので、そちらを参照して欲しい。

#define GPIO_BASE                0xE000A000

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>

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

int  mem_fd;
char *gpio_mem, *gpio_map;

// I/O access
volatile unsigned *gpio;

void setup_io();

int main()
{
    setup_io();
    volatile unsigned *mask_data_0_lsw, *mask_data_0_msw;
    volatile unsigned *data_0, *data_0_ro;
    volatile unsigned *dirm_0, *oen_0; 
    
    mask_data_0_lsw =     gpio;
    mask_data_0_msw =     gpio + 1;        // 0x4番地
    data_0 =             gpio + 0x10;    // 0x40番地
    data_0_ro =         gpio + 0x18;    // 0x60番地
    dirm_0 =             gpio + 0x81;    // 0x204番地
    oen_0 =             gpio + 0x82;    // 0x208番地

    *(dirm_0) = *(dirm_0)|0x400;    // gpio[0]を出力に設定
    *(oen_0) = *(oen_0)|0x400;        // gpio[0]をイネーブル

    printf("MASK_DATA_0_LSW = %x\n", *(mask_data_0_lsw));
    printf("MASK_DATA_0_MSW = %x\n", *(mask_data_0_msw));
    printf("DATA_0 = %x\n", *(data_0));
    printf("DATA_0_RO = %x\n", *(data_0_ro));
    printf("DIRM_0 = %x\n", *(dirm_0));
    printf("OEN_0 = %x\n", *(oen_0));

    *(data_0) = *(data_0)&(~(0x400));    // gpio[10]を0にする。DS23(LED)を消灯
    printf("DATA_0 = %x\n", *(data_0));

    printf("Hello World\n");

    return 0;
}


DS23 (LED) はLinuxブート時に、最初から点灯しているので、このプログラムで消灯することが出来た。
なお、上のプリント文の出力結果を下に示す。(Hello Worldのプリントは除く)

MASK_DATA_0_LSW = 2eb2
MASK_DATA_0_MSW = 6c1
DATA_0 = 6c12eb2
DATA_0_RO = 6c12e32
DIRM_0 = 480
OEN_0 = 480
DATA_0 = 6c02ab2


次はPL部に実装したAXI GPIO やAXI Timer を使ってみることにする。
  1. 2012年07月18日 05:53 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)でビットファイル入りのLinuxのブートイメージが入ったSDカードを作る

Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の45ページ、”5.2.6 Take a Test Drive! Booting Linux From the SD Card”をやってみたが、Linuxのブートイメージだけでなく、チュートリアル2のビットファイルをSDカードのブートイメージに追加してみた。

・まずは、 J20, J21, J22, J25, J26, J27, J28の設定ピンを下の写真のように設定した。
ZC702_Linux_14_120711.jpg

・チュートリアル2のワークスペースを指定して、SDKを立ち上げた。

・ Xilinx Tools メニューからCreate Boot Image を選択した。

・ダイアログで、ug873_design_files.zip に入っていたzynq_fsbl_0.elfを追加した。

・次に、チュートリアル2のビットファイルを追加した。

ug873_design_files.zip に入っていたu-boot.elf を追加した。
ZC702_Linux_47_120716.png

・Create Image ボタンをクリックして、ブートイメージを作製した。

・指定されたフォルダにBOOT.bin、BOOT.mcs、bootimage.bif の3つのファイルが生成された。
ZC702_Linux_52_120717.png

このBOOT.binのファイルサイズは、4.09Mバイトで、数百Kバイトのug873_design_files.zipのBOOT.BIN と違っていて、ビットファイルが入っているようだ。

・上で生成したBOOT.binとダウンロードしたug873_design_files.zip内のzImage、devicetree.dtb、ramdisk8M.image.gz をSDカードにコピーして、ZC702のSDカードソケットに挿入した。

・電源をONして、慌ててTeraTermを立ちあげ、115200bpsに設定すると、Linuxのプロンプトが表示された。
ZC702_Linux_48_120716.png

たぶんビットファイルをZynqにコンフィグして、Linuxが立ち上がるブート用のSDカードが出来たと思う。(まだ、ビットファイルが本当にZynqにコンフィグされているか?は未確認です。)

(2012/07/19:追記)
ブートイメージのビットファイルはZynqにコンフィグされていました。axi gpio を使うことができました。

  1. 2012年07月17日 05:05 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のLinuxチュートリアル4(リモートデバック2)

Zynq-7000(ZC702)のLinuxチュートリアル3(リモートデバック)”の続き。

前回、Zynqで起動しているLinuxにSSHを使用して、パソコンのSDK からリモートデバックを行った。これは、フォルダと実行ファイルのスケルトンを作っておいて、SDKから実行ファイルをZynqのLinuxに送って実行させでバックしているのだと思う。よって、ZC702ボードの電源を切ってしまうと、Linuxに作成したフォルダ (Apps) と実行ファイルのスケルトンが消えてしまう。次にZC702ボードの電源を入れた際には、Linuxに作成したフォルダ (Apps) と実行ファイルのスケルトンを作ってデバックする必要がある。その辺のことを書いてみようと思う。

・linux_hello_world を右クリックして、右クリックメニューからDebug as -> Debug Configurations を選択した。

Connection に設定はすでに10.10.70.120が入っているので、設定は問題ない。 Remote Absolute File Path for C/C++ Application を再設定する。

・emote Absolute File Path for C/C++ Application
ZC702_Linux_49_120716.png

・Remote Absolute File Path for C/C++ Application のBrows... ボタンをクリックした。

・ウイザードでroot を展開する。
ZC702_Linux_28_120712.png

・エラーダイアログが出るが無視する。・Select Remote C/C++ Application File ダイアログで、ツリー状のマークを展開した。
ZC702_Linux_33_120712.png

・Rootの下にフォルダを作る。右クリックメニューからNew -> Folder をクリックした。
ZC702_Linux_34_120712.png

・New folder name: にApps と入力した。Apps フォルダを作成する。
ZC702_Linux_35_120712.png

・Apps フォルダの右クリックメニューからNew -> File を選択した。
ZC702_Linux_36_120712.png

・New file name: にlinux_hello_world_0.elf と入力して、ファイルを作成した。
ZC702_Linux_50_120716.png

この時にZynq Linuxの/Apps/linux_hello_world_0.elf が作成されたが、ファイルの大きさは0だった。(シリアル・インターフェースのTeraTerm で、zynq > のプロンプトからコマンドを入れて確認。下にファイルの大きさを示す。

zynq> cd Apps
zynq> ls -l
total 0
-rw-r--r-- 1 root 0 0 Jan 1 00:29 linux_hello_world_0.elf


・Debug Configuration に戻って、Apply ボタンをクリックした。
ZC702_Linux_49_120716.png

これで、ダイアログをクリアしていくと、デバック用のパースペクティブが開いて、前回同様デバックできるようになる。
ZC702_Linux_51_120716.png

・デバック・パースペクティブになった時に、ZynqのLinuxの/Apps/linux_hello_world_0.elf を見るとelfバイナリが転送されて? 58Kバイト程度になっていた。

zynq> ls -l
total 59
-rwxr-xr-x 1 root 0 58513 Jan 1 00:35 linux_hello_world_0.elf

  1. 2012年07月16日 21:06 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアル2のXPSでのZynqの設定

Zynq-7000(ZC702)のチュートリアル2をやってみた5(実機でテスト)”でSW5やSW7をプッシュすることでDS23(LED) を消灯、点灯させたが、その時のXPS上でのZynqの設定を見てみることにした。

・まずはDS23のLEDからどこにつながっているか調べてみた。ZC702の回路図を見るとDS23はG7に接続されている。UCFを見ると、PS_MIO10_500だそうだ。これはXPSのZynqタブのI/O Peripherals をクリックすると出てくるZynq PS MIO Configurations によるとgpio[10]だそうだ。これは、

下にZynqタブの図を示す。ピンクの矢印のI/O Peripherals をクリックする。
Zynq_test_1_120715.png

Zynq PS MIO Configurations のMIO 10、gpio[10] がDS23(LED) に接続されている。
Zynq_test_2_120715.png

SDKのxparameter.h では、XPAR_PS7_GPIO_0_BASEADDRの10番目なのかもしれない?

/* Definitions for peripheral PS7_GPIO_0 */
#define XPAR_PS7_GPIO_0_DEVICE_ID 0
#define XPAR_PS7_GPIO_0_BASEADDR 0xE000A000
#define XPAR_PS7_GPIO_0_HIGHADDR 0xE000AFFF


・ZynqのMIO (multiplexed I/O) に接続されているDS23(LED) と違って、SW7はEMIO (extended multiplexed I/O) に接続されている。EMIOはPL部分のピンを使用してZynq内のARMプロセッサにGPIOとして使用させる方式のことだ。設定は”Zynq-7000(ZC702)のチュートリアル2をやってみた3(PSの設定、インプリメント)”で行なっている。XPSのZynqタブで、緑色の32b GP AXI Master Portsボタンをクリックして出てきたprocessing_system7のダイアログで行なっている。ZynqのF19ピンにアサインされている。SW7もXPAR_PS7_GPIO_0_BASEADDR の中に入っているかもしれない?
ZC702_61_120624.png

# Connect to Push Button "SW7"
NET processing_system7_0_GPIO_pin IOSTANDARD=LVCMOS25 | LOC=F19;


・SW5はPL部分のAXIバスにAXI GPIOモジュールを接続してそこからSW5に結んでいる。チュートリアルの20ページ、Figure 3-1: Block Diagramを下に引用する。
ZC702_54_120623.png

# Connect to Push Button "SW5"
NET axi_gpio_0_GPIO_IO_pin IOSTANDARD=LVCMOS25 | LOC=G19;


SDKのxparameter.h での記述を下に示す。

/* Definitions for peripheral AXI_GPIO_0 */
#define XPAR_AXI_GPIO_0_BASEADDR 0x41200000
#define XPAR_AXI_GPIO_0_HIGHADDR 0x4120FFFF
#define XPAR_AXI_GPIO_0_DEVICE_ID 0
#define XPAR_AXI_GPIO_0_INTERRUPT_PRESENT 0
#define XPAR_AXI_GPIO_0_IS_DUAL 0


・XPSのZynqタブのClock Generation をクリックする。
Zynq_test_3_120715.png
ARM PLLクロックが666MHz、DDR PLLが533MHzというのがわかる。PLのクロックは50MHzだ。
Zynq_test_4_120715.png

・XPSのZynqタブのMemoryInterface をクリックした。
Zynq_test_5_120715.png

DDR3 SDRAMコントローラに設定してあった。データ幅は32ビット、動作周波数533MHz、DDR3-1066 だ。なかなか凄い、さすがハードマクロ。
Zynq_test_6_120715.png

・XPSのZynqタブのIRQをクリックした。
Zynq_test_7_120715.png

axi_timer_0 がIRQに接続されているのが見えた。
Zynq_test_8_120715.png

大体、チュートリアル2で使用したZC702のスイッチ、LEDがどのように接続されているかがわかった。
  1. 2012年07月15日 07:13 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のLinuxチュートリアル3(リモートデバック)

Zynq-7000(ZC702)のLinuxチュートリアル2(Master Boot Method、SDカード)”の続き。

Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の39ページ、”5.2.4 Take a Test Drive! Debugging the Linux Application Using SDK Remote Debugging”をやってみた。

以前の状態でチュートリアルを実行した。ZynqのIPアドレスは10.10.70.120、サブネットマスクは255.255.255.0、LANケーブルで接続されているパソコンのIPアドレスは10.10.70.121、サブネットマスクは255.255.255.0 にセットしてある。

・チュートリアル1のワークスペースを使用してSDKを立ち上げた。

・SDKのFileメニューから New -> Xilinx C Project を選択した。

・New Projectウイザードで、Linux ラジオボタンをクリックして、Linux Hello World を選択した。processorには、ps7_cortexa9_0が選択されている。Finishボタンをクリックした。
ZC702_Linux_20_120712.png

・LinuxのHello Worldアプリケーションがコンパイルされて、ELFバイナリファイルが生成された。
ZC702_Linux_21_120712.png

・linux_hello_world を右クリックして、右クリックメニューからDebug as -> Debug Configurations を選択した。

・ Debug Configurationウイザードで、Remote ARM Linux Application を右クリックして右クリックメニューからNew を選択した。
ZC702_Linux_22_120712.png

・Debug Configurationウイザードで、Connection のNew ボタンをクリックした。
ZC702_Linux_23_120712.png

・New Connection ウイザードが開く。SSH Only をクリックした。
ZC702_Linux_24_120712.png

・Next -> ボタンをクリックした。
ZC702_Linux_25_120712.png

・Host Name にZC702ボードのIPを入力した。(10.10.70.120)
・Description には、linux_hello_world_test と入力した。
・Finishボタンをクリックした。
ZC702_Linux_26_120712.png

・ Remote Absolute File Path for C/C++ Application のBrows... ボタンをクリックした。
ZC702_Linux_27_120712.png

・ウイザードでroot を展開する。
ZC702_Linux_28_120712.png

・Enter Passwordウイザードで、ID (root) とパスワード (root) を入力する。
・Save User ID と Save Password のチェックボックスにチェックを入れる。
ZC702_Linux_29_120712.png

・OKボタンをクリックした。Warning ダイアログが出た。Yesボタンをクリックした。
ZC702_Linux_30_120712.png

・ssh\known_hostsを生成しても良いか?と聞いてきた。Yesボタンをクリックした。
ZC702_Linux_31_120712.png

・ssh フォルダ生成が成功した。OKボタンをクリックした。
ZC702_Linux_32_120712.png

・Select Remote C/C++ Application File ダイアログで、ツリー状のマークを展開した。
ZC702_Linux_33_120712.png

・Rootの下にフォルダを作る。右クリックメニューからNew -> Folder をクリックした。
ZC702_Linux_34_120712.png

・New folder name: にApps と入力した。Apps フォルダを作成する。
ZC702_Linux_35_120712.png

・Apps フォルダの右クリックメニューからNew -> File を選択した。
ZC702_Linux_36_120712.png

・New file name: にlinux_hello_world.elf と入力して、ファイルを作成した。
ZC702_Linux_37_120712.png

・Apps フォルダの下にlinux_hello_world.elf が作成された。OKボタンをクリックした。
ZC702_Linux_38_120712.png

・TeraTerm で確認するとルートの下にApps ディレクトリの下にlinux_hello_world.elf が作成されているのが見えた。
ZC702_Linux_39_120712.png

・Debug Configuration に戻って、Apply ボタンをクリックした。
ZC702_Linux_40_120712.png

・Debug ボタンをクリックして、Debug を開始した。
ZC702_Linux_41_120712.png

・パースペクティブをデバックにスイッチするダイアログが出るので、Yes ボタンをクリックした。
ZC702_Linux_42_120712.png

・Eclipse がデバックモードになってHello Worldのprintf で停止している。
ZC702_Linux_43_120712.png

・return の所にブレークポイントを設定して、Resume ボタンをクリックした。
ZC702_Linux_44_120712.png

・ブレークポイントのところまで実行された。
ZC702_Linux_45_120712.png

これで、Debugging the Linux Application Using SDK Remote Debugging は終了。リモートデバック出来た。

(2012/07/16:追加)
リモートデバックでそのまま実行するとHello Worldが表示された。リモートデバックで便利そうだ。
ZC702_Linux_46_120716.png

Zynq-7000(ZC702)のLinuxチュートリアル4(リモートデバック2)”に続く。

  1. 2012年07月13日 04:04 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のLinuxチュートリアル2(Master Boot Method、SDカード)

前回の”Zynq-7000(ZC702)のLinuxチュートリアル1(Slave Boot Method)”では、JTAGからブートイメージをロードするSlave Boot Methodでうまくブートできなかった。設定が違っているかもしれないが、とりあえずはLinuxをブートできた。Master Boot Method、SDカードからのブートをやってみることにした。

Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の45ページ、”5.2.6 Take a Test Drive! Booting Linux From the SD Card”をやってみることにした。

・まずは、 J20, J21, J22, J25, J26, J27, J28の設定ピンを下の写真のように設定する。
ZC702_Linux_14_120711.jpg

・ZC702ボードの電源をON。

・急いで、TeraTermを立ちあげて、115200bpsにセットする。

・U-Bootを経由して、自動的にLinuxがブートする。
ZC702_Linux_13_120711.png

・ブートした時の全メッセージを下に貼っておく。

FSBL, Video hacked version 1.0

video stuff starting to run
Reset and Initialize the FMC devices ...
Config is 6A
3A Config is 6A
3B Config is 6A
3C Config is 6A
3D Config is 6A
De-skew is 6A


U-Boot 2010.09-01918-g068cc03 (Jan 20 2012 - 14:02:15)
Xilinx Pele Emulation Platform

DRAM: 256 MiB
## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
Flash: 0 Bytes
MMC: SDHCI: 0
Using default environment

In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
Copying Linux from SD to RAM...
Device: SDHCI
Manufacturer ID: 3
OEM: 5344
Name: SU08G
Tran Speed: 25000000
Rd Block Len: 512
SD version 1.10
High Capacity: Yes
Capacity: 7948206080
Bus Width: 1-bit
reading zImage

2020464 bytes read
reading devicetree.dtb

2347 bytes read
reading ramdisk8M.image.gz

2500546 bytes read
Trying to set up GEM link...
Resetting PHY...

PHY reset complete.
Waiting for PHY to complete auto-negotiation...
Link is now at 100Mbps!
ping failed; host 10.10.70.101 is not alive
## Starting application at 0x00008000 ...
Uncompressing Linux... done, booting the kernel.
Linux version 3.0.0 (djoja@ubuntu) (gcc version 4.5.1 (Sourcery G++ Lite 2010.09-62) ) #54 SMP PREEMPT Thu Jan 19 17:24:27 PST 2012
CPU: ARMv7 Processor [413fc090] revision 0 (ARMv7), cr=18c5387d
CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Xilinx Zynq Platform, model: Xilinx Zynq ZC770 - V&C dt1 - minimum)
Memory policy: ECC disabled, Data cache writealloc
PERCPU: Embedded 7 pages/cpu @c180a000 s4928 r8192 d15552 u32768
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 256000
Kernel command line: console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8M ip=192.168.1.10
PID hash table entries: 2048 (order: 1, 8192 bytes)
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 240MB 768MB = 1008MB total
Memory: 1011248k/1011248k available, 37328k reserved, 655360K highmem
Virtual kernel memory layout:
vector : 0xffff0000 - 0xffff1000 ( 4 kB)
fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB)
DMA : 0xffc00000 - 0xffe00000 ( 2 MB)
vmalloc : 0xd8800000 - 0xe0000000 ( 120 MB)
lowmem : 0xc0000000 - 0xd8000000 ( 384 MB)
pkmap : 0xbfe00000 - 0xc0000000 ( 2 MB)
modules : 0xbf000000 - 0xbfe00000 ( 14 MB)
.init : 0xc0008000 - 0xc002b000 ( 140 kB)
.text : 0xc002b000 - 0xc03b3bc0 (3619 kB)
.data : 0xc03b4000 - 0xc03dbe00 ( 160 kB)
.bss : 0xc03dbe24 - 0xc03f1e4c ( 89 kB)
Preemptible hierarchical RCU implementation.
Verbose stalled-CPUs detection is disabled.
NR_IRQS:246
xlnx,ps7-ttc-1.00.a #0 at 0xd8800000, irq=43
Console: colour dummy device 80x30
Calibrating delay loop... 1594.16 BogoMIPS (lpj=7970816)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
Calibrating local timer... 399.20MHz.
hw perfevents: enabled with ARMv7 Cortex-A9 PMU driver, 7 counters available
CPU1: Booted secondary processor
Brought up 2 CPUs
SMP: Total of 2 processors activated (3188.32 BogoMIPS).
devtmpfs: initialized
NET: Registered protocol family 16
L310 cache controller enabled
l2x0: 8 ways, CACHE_ID 0x410000c8, AUX_CTRL 0x72060000, Cache size: 524288 B
registering platform device 'pl330' id 0
registering platform device 'arm-pmu' id 0
hw-breakpoint: found 6 breakpoint and 1 watchpoint registers.
hw-breakpoint: 1 breakpoint(s) reserved for watchpoint single-step.
hw-breakpoint: maximum watchpoint size is 4 bytes.
bio: create slab at 0
xgpiops e000a000.gpio: gpio at 0xe000a000 mapped to 0xd8808000
SCSI subsystem initialized
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Switching to clocksource xttcpss_timer1
NET: Registered protocol family 2
IP route cache hash table entries: 16384 (order: 4, 65536 bytes)
TCP established hash table entries: 65536 (order: 7, 524288 bytes)
TCP bind hash table entries: 65536 (order: 7, 786432 bytes)
TCP: Hash tables configured (established 65536 bind 65536)
TCP reno registered
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
Trying to unpack rootfs image as initramfs...
rootfs image is not initramfs (no cpio magic); looks like an initrd
Freeing initrd memory: 8192K
PMU: registered new PMU device of type 0
xscugtimer xscugtimer.0: ioremap f8f00200 to d880a200 with size 400
pl330 dev 0 probe success
highmem bounce pool size: 64 pages
JFFS2 version 2.2. (NAND) (SUMMARY) c 2001-2006 Red Hat, Inc.
msgmni has been set to 711
io scheduler noop registered
io scheduler deadline registered
io scheduler cfq registered (default)
e0001000.uart: ttyPS0 at MMIO 0xe0001000 (irq = 82) is a xuartps
console [ttyPS0] enabled
brd: module loaded
loop: module loaded
m25p80 spi0.1: unrecognized JEDEC id ffffff
xspips e0007000.spi: at 0xE0007000 mapped to 0xD8860000, irq=81
m25p80 spi1.0: n25q128 (16384 Kbytes)
Creating 7 MTD partitions on "serial_flash":
0x000000000000-0x000000080000 : "qspi-fsbl"
0x000000080000-0x000000100000 : "qspi-u-boot"
0x000000100000-0x000000600000 : "qspi-linux"
0x000000600000-0x000000620000 : "qspi-device-tree"
0x000000620000-0x000000700000 : "qspi-user"
0x000000700000-0x000000800000 : "qspi-scratch"
0x000000800000-0x000001000000 : "qspi-rootfs"
xqspips e000d000.spi: at 0xE000D000 mapped to 0xD8862000, irq=51
GEM: BASEADDRESS hw: e000b000 virt: d8864000
XEMACPS mii bus: probed
GEM: phydev d7966c00, phydev->phy_id 0x1410e40, phydev->addr 0x7
GEM: MAC addr 00:00:00:00:00:00
xemacps e000b000.eth: invalid address, use assigned
MAC updated 82:36:7f:74:92:ae
eth0, pdev->id -1, baseaddr 0xe000b000, irq 54
eth0, phy_addr 0x7, phy_id 0x01410e40
eth0, attach [Generic PHY] phy driver
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
xusbps-ehci xusbps-ehci.0: Xilinx PS USB EHCI Host Controller
xusbps-ehci xusbps-ehci.0: new USB bus registered, assigned bus number 1
xusbps-ehci xusbps-ehci.0: irq 53, io mem 0x00000000
xusbps-ehci xusbps-ehci.0: USB 2.0 started, EHCI 1.00
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
Xilinx PS USB Device Controller driver (Apr 01, 2011)
mousedev: PS/2 mouse device common for all mice
at24 0-0050: 256 byte 24c02 EEPROM, writable, 1 bytes/write
xi2cps e0004000.i2c: 400 kHz mmio e0004000 irq 57
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
mmc0: Invalid maximum block size, assuming 512 bytes
mmc0: SDHCI controller on e0100000.sdhci [e0100000.sdhci] using DMA
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
TCP cubic registered
NET: Registered protocol family 17
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 4
Registering SWP/SWPB emulation handler
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
GEM: lp->tx_bd ffdfb000 lp->tx_bd_dma 170ee000 lp->tx_skb d7b064a0
GEM: lp->rx_bd ffdfc000 lp->rx_bd_dma 170ed000 lp->rx_skb d7b063a0
GEM: MAC 0x747f3682, 0x0000ae92, 82:36:7f:74:92:ae
mmc0: new SDHC card at address e624
mmcblk0: mmc0:e624 SU08G 7.40 GiB
mmcblk0: p1
GEM: mc addr 0x1:0x0:0x5e:0x0:0x0:0x1
IP-Config: Guessing netmask 255.255.255.0
IP-Config: Complete:
device=eth0, addr=192.168.1.10, mask=255.255.255.0, gw=255.255.255.255,
host=192.168.1.10, domain=, nis-domain=(none),
bootserver=255.255.255.255, rootserver=255.255.255.255, rootpath=
RAMDISK: gzip image found at block 0
VFS: Mounted root (ext2 filesystem) on device 1:0.
devtmpfs: mounted
Starting rcS...
++ Mounting filesystem
++ Setting up mdev
++ Starting telnet daemon
++ Starting http daemon
++ Starting ftp daemon
++ Starting dropbear (ssh) daemon
rcS Complete
zynq>


次に、”5.2.3 Take a Test Drive! Linux Booting Using JTAG Mode”の38ページ、”8. At the Zynq> prompt, do the following:”からの内容をやってみた。

・TeraTerm で、ifconfig eth0 10.10.70.120 netmask 255.255.255.0 を入力した。
ZC702_Linux_17_120712.png

・ZC702ボードからのLANケーブルが接続されているパソコンのIPアドレスを静的に10.10.70.121, サブネットマスクを255.255.255.0 に設定した。
ZC702_Linux_15_120712.png

・パソコンのコマンド プロンプトを立ちあげて、ping 10.10.70.120 を実行したところ、ZC702ボードからの応答が帰ってきた。
ZC702_Linux_16_120712.png

・TeraTermで、ps コマンドを実行したら、httpd も走っていた。
ZC702_Linux_18_120712.png

・パソコンのChromeで、10.10.70.120 を見てみると、立派なページが出てきた。
ZC702_Linux_19_120712.png

Zynq-7000(ZC702)のLinuxチュートリアル3(リモートデバック)”に続く。

  1. 2012年07月12日 04:22 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のLinuxチュートリアル1(Slave Boot Method)

、”Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の37ページ、”5.2.3 Take a Test Drive! Linux Booting Using JTAG Mode”をやってみる。

・J27,J28をSDコネクタ側で無い方に、それ以外のジャンパーピンをSDコネクタ側にした。

・ホストPCとイーサネットケーブルを接続した。

・ダウンロードケーブルを接続。今まで通りにDigilent社のコンフィグ回路にマイクロUSBケーブルを接続。

・USBシリアルコネクタJ17にミニUSBケーブルを挿して、ホストPCのUSBへ接続。

・J310はショートしてあったので、J30を基板の端に近い方に挿し換えた。(以前は逆側だった)

・ZC702ボードの電源をONした。

・Tera Termを立ちあげて、115200bpsでZC702ボードのUSB-シリアルに接続した。

・SDKを立ちあげて、Zynq-7000(ZC702)のチュートリアル2のワークスペースを指定して立ち上げる。
ZC702_Linux_1_120710.png

・ビットファイルをダウンロードする。SDKのXilinx Tools メニューからProgram FPGAを選択した。Programボタンをクリックした。
ZC702_Linux_2_120710.png

・SDKのXilinx Tools メニューからXMD console を選択した。

・XMDプロンプトにconnect arm hw を入力し、ZynqのPSのCPUに接続する。
ZC702_Linux_3_120710.png

・ARMにコネクトされた。
ZC702_Linux_4_120710.png

・XMDプロンプトに、source K:/HDL/FndtnISEWork/Zynq-7000/ZC702/ZC702_example2/ZC702_example2.sdk/SDK/SDK_Export/system_hw_platform/ps7_init.tcl を入力した。

・XMDプロンプトに、ps7_init を入力した。PSセクションを初期化。Clock PLL、MIO、DDRコントローラを初期化。
ZC702_Linux_5_120710.png

・XMDプロンプトに、dow K:/HDL/FndtnISEWork/Zynq-7000/ZC702/ug873_design_files/u-boot.elf を入力した。
ZC702_Linux_6_120710.png

・XMDプロンプトに、con を入力した。
ZC702_Linux_7_120710.png

・Teraterm を表示して、Enterキー(なんでも良いらしいが)を10秒以内に押す。
ZC702_Linux_8_120710.png

・U-Bootのautoboot を停止して、プロンプトが出た。

・XMDで、stop を入力した。

・XMDで、dow -data K:/HDL/FndtnISEWork/Zynq-7000/ZC702/ug873_design_files/zImage 0x8000 を入力した。
ZC702_Linux_9_120710.png

・XMDで、dow -data K:/HDL/FndtnISEWork/Zynq-7000/ZC702/ug873_design_files/ramdisk8M.image.gz 0x800000 を入力した。
ZC702_Linux_10_120710.png

・XMDで、dow -data K:/HDL/FndtnISEWork/Zynq-7000/ZC702/ug873_design_files/devicetree.dtb 0x1000000 を入力した。
ZC702_Linux_11_120710.png

・XMDで、con を入力して、U-Bootを起動する。

・TeraTermのU-Bootのプロンプトから、go 0x8000 を入力した。

・Uncompressing Linux... done, booting the kernel.のまま止まってしまう。
ZC702_Linux_12_120711.png

もう一度、Zynq-7000(ZC702)のチュートリアル1のワークスペースを指定してやってみようと思う。
やってみたが同様にUncompressing Linux... done, booting the kernel.のまま止まってしまう。
ZC702ボードはRev BだったがチュートリアルはRev C用なのが問題なのか?
付属のSDカードに入っているLinuxの関連ファイルをコピーしてやってみようと思う。

(追加)
付属のSDカードからブートしたらZynqのLinuxがブートしました。
ZC702_Linux_13_120711.png

Zynq-7000(ZC702)のLinuxチュートリアル2(Master Boot Method、SDカード)”に続く。

  1. 2012年07月10日 05:54 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:2

Zynq-7000(ZC702)のLinuxチュートリアルの勉強

今回は、”Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の34ページ、”Linux Booting and Application Debugging Using SDK”を見ていくことにする。
これは覚書です。上記のマニュアルを参照させていただきました。ありがとうございます。

・ Zynq™-7000 EPPのボードでLinux OSをブートする方法がこの章に書いてあるそうだ。
・最初にJTAGインタフェースを使ってメモリにLinuxのイメージををダウンロードする方法をやる。
・次に非揮発メモリにLinuxのイメージを入れておいて、ボードのスイッチを切り替えることで、ブートさせてみる。
・非揮発メモリの種類はオンボードのQSPI Flash とSDカード。

・この章では、ターゲットボード上で動作するLinuxアプリケーションをデバッグするためのSDKのリモートデバッグ機能の使用方法について説明するそうだ。
・SDKツールのソフトウェアは、Windowsホストマシン上で実行される。
・アプリケーションのデバッグについては、SDKは既にLinux OSを実行しているターゲットボードへのイーサネット接続を確立する。

使用ファイル
必要なファイルは、デザインファイル ug873_design_files.zip からダウンロードする事ができる。

・BOOT.bin  :bootgenで作られたU-BootイメージとFSBL(first stage boot loader)を含むブートイメージ
・Boot.bif  :BOOT.BINの作成時にbootgenを制御するためのファイル
・Devicetree.dtb  :Linuxで使用されるDevice tree binary large object (blob)。U-Bootによってメモリにロードされる。
・ramdisk8M.image.gz  :Linuxで使用されるRamdiskイメージ。U-Bootによってメモリにロードされる。
・README.txt  :(これは言うまでもない)
・U-boot.elf  :U-BootファイルはBOOT.BINイメージを作るのに使用される。
・zImage  :Linuxカーネル・イメージ。U-bootでメモリにロードされる。
・zynq_fsbl_0.elf  :FSBLイメージはBOOT.BINイメージを作るのに使用される。

ブート方法
Linuxをブートする方法は2つあるようだ。
マスタ・ブート・メソッドとスレーブ・ブート・メソッド

マスタ・ブート・メソッド
・マスタ・ブート・メソッドは QSPI、NAND、NOR flash、SDカードなどの非揮発メモリにLinuxのブート・イメージを入れておいて、そこからブートする方法。
・ブート・プロセスはPS中のARMプロセッサを初期化して非揮発メモリのコードを実行する。
・非揮発メモリのコードはFSBLを実行する。

FSBLの実行手順
 ・もしあれば、FPGAのビットファイルをコンフィグ。
 ・MIOインタフェースをコンフィグ。
 ・DDRコントローラを初期化。
 ・PLLクロックを初期化。
 ・非揮発メモリからDDRにロードしてU-Bootを実行。

・U-BootはLinuxカーネル・イメージ、ファイル・システム、デバイス・ツリーの非揮発メモリからDDRへのロードと実行を行う。

スレーブ・ブート・メソッド
・スレーブ・ブート・メソッドはJTAGだけを使って、ホストPCからDDRへブート・イメージをロードして、Linuxをブートする。

JTAGからのLinuxブート方法は下の図の通り。(チュートリアル36ページの Figure 5-1: Linux Boot Process on the Target Platform を引用させていただきました)
ZC702_131_120709.png
  1. 2012年07月09日 05:48 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアル2をやってみた7(ChipScopeによるデバック)

Zynq-7000(ZC702)のチュートリアル2をやってみた6(SDKデバック)”の続き。

Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の31ページ、”4.2 Take a Test Drive! Debugging Hardware Using ChipScope Software”をやってみる。

・ZC702ボードの電源をONした。

・TeaTerm を立ちあげて115200bps に設定した。

・ Xilinx Toolsメニューから Program FPGA を選択した。

・ Program FPGA ダイアログが出た。Program ボタンをクリックした。ビットファイルがダウンロードされ、PLファブリックがプログラムされる。
ZC702_96_120707.png

・hello_world_0の右クリックメニューからRun as -> Run Configurations... を選択した。
ZC702_97_120707.png

・hello_world_0 Debug を選択した。
ZC702_98_120707.png

・Runボタンをクリックした。

・Reset Status ダイアログが出た。OKボタンをクリックした。
ZC702_99_120707.png

・SDK Logに、ps7 initialization done.が表示された。
ZC702_100_120707.png

・Tera Termにメニューが表示されていた。
ZC702_101_120707.png

・PlanAheadのChipScope Analyzer をクリックしてChipScope Analyzer を立ち上がる。
ZC702_113_120708.png

・ChipScope Analyzer が立ち上がった。Open/Search JTAG Cable アイコンをクリックした。
ZC702_114_120708.png

・Zynqが見つかった。
ZC702_115_120708.png

・ダイアログのOKボタンをクリックした。ChipScope Pro Analyazer の状態を下に示す。
ZC702_116_120708.png

・chipscope_axi_monitor_0.cdc をインポートする。Dev 1 Mydevice1(XC7020)を選択して、FileメニューからImport を選択する。
ZC702_117_120708.png

・Signal Import ダイアログが開く。Select New File ボタンをクリックした。
ZC702_118_120708.png

・ZC702_example2\ZC702_example2.srcs\sources_1\edk\system\implementation\chipscope_axi_monitor_0_wrapperフォルダの下の chipscope_axi_monitor_0.cdc を選択した。
ZC702_119_120708.png

・Signal Import ダイアログに chipscope_axi_monitor_0.cdc が設定された。OKボタンをクリックした。
ZC702_120_120708.png

・ChipScope Analyzer の画面に信号名が表示された。
ZC702_121_120708.png

・Trigger Setupウインドウを開いて、M1:MON_AXI_ARADDRCONTROLの下のaxi_gpio_0_S_AXI/MON_AXI_AVALIDを1にした。
ZC702_122_120708.png

・Trigger Condition Equation がMOになっているので、そこをクリックした。
ZC702_123_120708.png

・Trigger Condition ダイアログで、Enableを見るとM0にチェックが入っている。これをクリックで消して、M1の所にチェックを入れた。
ZC702_124_120708.png

・Position の設定を10にした。
ZC702_125_120708.png

・Runボタンをクリックした。
ZC702_127_120708.png

・そのまま待っていてもトリガが掛からなかった。Tera Termから1を入力したところ、トリガが掛かった。
ZC702_128_120708.png

・Waveウインドウを下に示す。
ZC702_129_120708.png

・最初にトリガが掛かった辺りを拡大してみた。
ZC702_130_120708.png

  1. 2012年07月08日 07:45 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアル2をやってみた6(SDKデバック)

Zynq-7000(ZC702)のチュートリアル2をやってみた5(実機でテスト)”の続き。

今度は、”Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の29ページ、Chapter 4 Debugging with SDK and ChipScope をやってみる。

・ZC702ボードの電源をONした。

・ Xilinx Toolsメニューから Program FPGA を選択した。

・ Program FPGA ダイアログが出た。Program ボタンをクリックした。ビットファイルがダウンロードされ、PLファブリックがプログラムされる。
ZC702_96_120707.png

・SDKの Hello_world_0 プロジェクトの右クリックメニューから Debug As -> Debug Configurations... を選択した。
ZC702_106_120708.png

・Debug Configurations ダイアログが開く。 Debug ボタンをクリックした。
ZC702_107_120708.png

・Reset Status ダイアログが出た。OKボタンをクリックした。
ZC702_99_120707.png

・Confirm Perspective Switch ダイアログが開く。Yesボタンをクリックした。
ZC702_108_120708.png

・Debug Perspective が開いた。helloworld.c を見ると、"u32 Readstatus=0,OldReadStatus=0;" で実行が一時停止している。
ZC702_109_120708.png

Debug ウインドウを見ると、アセンブリレベルのプログラムの実行が0x00100608番地で停止しているのがわかる。

・Window メニューからShow view > Disassembly を選択した。
ZC702_110_120708.png

・Disassembly ウインドウが表示された。
ZC702_111_120708.png

・init_platform(); の前の編みかけの部分をダブルクリックするとブレークポイントを設定できる。Resume アイコンをクリックするとブレークポイントまでのコードを実行する。
ZC702_112_120708.png

後は普通のSDKを使ったデバックなので割愛する。

・RunメニューからTerminate を選択して、デバックモードを終了し、パースペクティブをCに戻すために、WindowsメニューからOpen Perspective -> C/C++ を選択しておこう。

Zynq-7000(ZC702)のチュートリアル2をやってみた7(ChipScopeによるデバック)”に続く。
  1. 2012年07月08日 05:17 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアル2をやってみた5(実機でテスト)

Zynq-7000(ZC702)のチュートリアル2をやってみた4(実機でテストの準備)”の続き。

Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の28ページ、”3.1.2 Take a Test Drive! Working with SDK”をやってみた。

・ZC702ボードの電源をONした。

・TeaTerm を立ちあげて115200bps に設定した。

・ Xilinx Toolsメニューから Program FPGA を選択した。

・ Program FPGA ダイアログが出た。Program ボタンをクリックした。ビットファイルがダウンロードされ、PLファブリックがプログラムされる。
ZC702_96_120707.png

・hello_world_0の右クリックメニューからRun as -> Run Configurations... を選択した。
ZC702_97_120707.png

・Xilinx C/C++ ELF の右クリックメニューからNew を選択した。
ZC702_82_120705.png

・hello_world_0 Debug が出来た。
ZC702_98_120707.png

・Runボタンをクリックした。

・Reset Status ダイアログが出た。OKボタンをクリックした。
ZC702_99_120707.png

・SDK Logに、ps7 initialization done.が表示された。
ZC702_100_120707.png

・Tera Termにメニューが表示されていた。
ZC702_101_120707.png

・Tera Termで'1'キーを押してから、ZC702ボードのSW5キーを押すとLEDのDS23が一旦消灯してから、また点灯した。(SW7とSW5の表示が間違っています。SW5は1、SW7は2です)
ZC702_102_120707.png

・Tera Termで'0'キーを押してメニューに戻した。

・Tera Termで'2'キーを押してから、ZC702ボードのSW7キーを押すとLEDのDS23が一旦消灯してから、また点灯した。
ZC702_103_120707.png

・Tera Termで'3'キーを押したらBYEで終了した。
ZC702_104_120707.png

ZC702ボードのSW5, SW7, DS23 の位置を下の写真に示す。
ZC702_105_120707.jpg

Zynq-7000(ZC702)のチュートリアル2をやってみた6(SDKデバック)”に続く。

  1. 2012年07月07日 14:21 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

映画『グスコーブドリの伝記』を見てきました

映画『グスコーブドリの伝記』(音注意)を奥さんと見てきました。私は元々ますむらひろしが好きで、30年以上前に谷山浩子のコンサートにゲストで来ていたますむら氏に情報理論の教科書にサインしてもらいました。なぜ情報理論の教科書かというと、その時それしか持ってなかったからです。(”アタゴオルは猫の森を見てきました”参照)
ヒデヨシの様なあかひげも出てきたし、相変わらず意味はよくわからなかったけど、楽しかったです。奥さんはあまり面白くないようでした。でも、なんで、この映画が文部科学省特選なんでしょうか?良くわかりません?
  1. 2012年07月07日 13:28 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアル2をやってみた4(実機でテストの準備)

Zynq-7000(ZC702)のチュートリアル2をやってみた3(PSの設定、インプリメント)”の続き。

今回は、”Zynq-7000 EPP Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design UG873 (v14.1) May 31, 2012”の2番めのチュートリアルを実機でテストしてみた。

・File メニューからExport -> Export Hardware... を選択した。
ZC702_90_120707.png

・Export Hardware ダイアログが開く。Launch SDKにチェックを入れて、OKボタンをクリックした。
ZC702_91_120707.png

・Hardware 構成をExport してSDKが立ち上がった。
ZC702_92_120707.png

・FileメニューからNew -> Xilinx C Projectを選択した。

・New Projectダイアログが開いた。Hello Worldが選択されている。
ZC702_24_120622.png

・次のダイアログが開いた。Finishボタンをクリックした。
ZC702_25_120622.png

・Hello Worldプロジェクトがビルドされた。トータルでは0x12C10 (76.8KBytes) メモリを使用している。さすがに大きい。
ZC702_93_120707.png

次にhelloworld.c を書き換える。どのように修正するかはチュートリアルの47ページ、”Application Software”に書いてある。

main()関数 はソフトを実行するエントリポイントです。main() 関数は初期化とシステムの周辺デバイスの設定をします。EMIOインターフェースを使用して、そのようなAXI GPIOおよびPS GPIOなど、さまざまなユースケースを実行するために選択する手順を持っています。シリアル端末上の命令にで、異なるユースケースを選択することができます。

ソフトウェア実行の手順

1.AXI GPIOモジュールを初期化。

2.ボード上のSW5プッシュボタンに接続されている入力ピンとして、AXI GPIOピンの方向コントロールを設定する。ピン配置は、システムの作成時にユーザー制約ファイル(UCF)でLOC制約を使用して固定されている。

3.デバイスIDが0のAXI TIMERモジュールを初期化。

4.AXI timer ISRにコールバック関数を対応付ける。
この関数は、タイマ割り込みが発生するたびに呼び出される。コールバック関数はDS23 LEDをスイッチし、割り込みフラグをセットする。
main()関数は実行を停止する割り込みフラグを使用して、タイマー割り込みを待ち、再起動実行。

5.リセット間にタイマー設定値をタイマーにロード。

6.割り込みモードやAuto Reload mode などのタイマーオプションを設定。

7.PSセクションのGPIOを初期化

8.PSセクションGPIOのチャネル0、ピン番号10を設定する。これはMIOピンにマッピングされ、ボード上のLED"DS23"に接続された出力ピンだ。

9.PSセクションGPIOのチャネル2、ピン番号0を設定する。これはEMIOインターフェースを介してPLサイドに接続されたSW7プッシュポタンスイッチだ。

10.Snoop control unit Global Interrupt controllerを初期化。ID '91'割り込みの割り込みルーチンを登録。例外ハンドラを登録して、割り込み許可。

11. シリアル端末経由で選択されたAXI GPIO または PS GPIO ユースケースを元にシーケンスを実行。

ソフトウェアは、シリアル端末からの選択でプロシージャを実行する。
シリアル端末を経由しての使用例を選択した後は、端末上の指示に従ってボード上のプッシュボタンを押す必要がある。そうすると、'DS23'LEDが消灯、タイマーがスタートし、タイマー割り込みが来るまでウエイトする関数が呼ばれる。タイマー割り込みが起こったら'DS23'LEDを点灯して実行を再スタートする。

(英語に自信がないので、間違っていたらお知らせください)


書き換えたhelloworld.c はデザインファイル ug873_design_files.zip に入っていた。

・デザインファイル ug873_design_files.zip に入っていたhelloworld.c をSDKのhello_world_0 -> src のhelloworld.c と置き換えた。
ZC702_94_120707.png

・順番を間違ったが、Project メニューからClean... を選択した。

・Clean ダイアログが開く。OKボタンをクリックした。
ZC702_95_120707.png

・再コンパイルされた。

Zynq-7000(ZC702)のチュートリアル2をやってみた5(実機でテスト)”に続く。

  1. 2012年07月07日 05:55 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

Zynq-7000(ZC702)のチュートリアルをやってみた3(実機でテスト)

Zynq-7000(ZC702)のチュートリアルをやってみた2(XPS、SDK)”の続き。

ツイッターでお世話になっているykazu1998さんからZC702ボードをお借りすることが出来たので、チュートリアルの続きをやってみたいと思う。まずはチュートリアル1から実機でテストする。

・ZC702に電源ケーブルを接続した。

・Xilinx Platform cable USB II がなかったので、Digilent社のUSB-JTAG Programming Cable を接続した。

・J17 (USB-Serial) からミニUSBケーブルでパソコンのUSBポートに接続した。

・J27,J28をSDコネクタ側で無い方に、それ以外のジャンパーピンをSDコネクタ側にした。
ZC702_80_120705.jpg

・電源をONした。

USB-Serial のICはデバイスマネージャを見ると、Silicon Labs CP210x USB to UART Bridge だった。ドライバが入っていてCOM6 が割り当てられていた。

・Tera Term を立ちあげて、COM6に接続して、115200bps, 8bit, No Parity, Stop 1bit, フローコントロール無しに設定した。

・hello_world_0 の右クリックメニューからRun As -> Run Configurations... を選択した。
ZC702_81_120705.png

・Xilinx C/C++ ELF の右クリックメニューからNew を選択した。
ZC702_82_120705.png

・hello_world_0 Debug (4) が出来た。
ZC702_83_120705.png

・Device Initialization タブをクリックして、path to the initialization TCL file にps7_init.tcl がPath情報付きで入っていた。
ZC702_84_120705.png

STDIO Connection タブで、Connect STDIO to Console にチェックを入れて、Port をCOM6、BAUD Rate を115200に設定した。(チェックを入れないのが正解だった。詳しくは再追記を参照)
ZC702_85_120705.png

TeraTerm を上げているとCOM6がすでに使われていると言われてエラーになるので、Tera Termを落としてやってみた。

やはりエラーだった。
ZC702_86_120705.png

今度はZC702の電源をONしたまま、SDKのCプロジェクトを作るところからやってみることにする。

(2012/07/06:追記)
やはりうまく行きません。何が悪いのかな?皆さんの環境でSDKのXilinx Tools -> Program FPGAはフェイルしないでしょうか?
ZC702のリファレンス・デザインをやってみようと思います。でも、これXilinxのライセンスをaccept しているので、ブログに書けないんですよね。

原因の一端がわかりました。JTAG切り替えスイッチがJTAG Header J58 に設定してありました。これじゃZynqがiMPACTから見えません。ZC702には、Digilent社のUSB-JTAG Programming Module が載っているので、これにJTAGを切り替えたら、iMPACTからZynqが見えました。これでやり直します。

(2012/07/06:再追記)
・TDIO Connection タブで、Connect STDIO to Console にチェックを入れずにそのままとした。
ZC702_87_120706.png

・ソフトウェアの実行が終了した。
ZC702_88_120706.png

・TeraTerm にHello Worldが表示された。嬉しい。。。
ZC702_89_120706.png

Hello Worldを表示しただけだが、苦労したので、とっても嬉しかった。

  1. 2012年07月05日 06:10 |
  2. Zynq
  3. | トラックバック:0
  4. | コメント:0

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製3(単体シミュレーション)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製2(コード製作)”の続き。

前回は本体のbitmap_disp_cntrler_axi_master.v から下のVerilog ファイルを作製した。今回はテストベンチとBFMを用意してbitmap_disp_cntrler_axi_master.v 単体でシミュレーションを行う。
シミュレーション用のテストベンチとBFMは、”AXI4スレーブ・バス・ファンクション・モデル(BFM)の作製3”のものを流用する。
テストベンチ、bitmap_disp_cntrler_axi_master_tb.v 以下の階層構造を下に示す。
BitMapDispCont_4_120704.png

bitmap_disp_cntrler_axi_master_tb.v の下に、bitmap_disp_cntrler_axi_master.v (uut_master) があって、それにスティミュラスを与えるaxi_master_BFM.vhd(一番下)が入っている。
この階層構造でISimでシミュレーションを行った。なお、ISEのバージョンはISE14.1 を使用した。
シミュレーション結果を下に示す。AXI4バスのRead部分とTMDS信号(HDMIコネクタから出力する信号)の出力を表示している。Write部分は使用していないので割愛した。
BitMapDispCont_5_120704.png

上のシミュレーション波形で、M_AXI_ARLENを注目すると、最初の値は7Fであるが、途中から3Fとなっている。それは下の図の非同期FIFOを満タンにしてから、AXI4バス経由で読んできたRGBの値を出力し始めて、非同期FIFOに溜まっているRGBデータが半分になったら、またAXI4バス経由で非同期FIFOの容量の半分を読みだしてくるからだ。それに応じてM_AXI_RDATAにもデータが来ていて、M_AXI_RVALIDとM_AXI_RREADYが両方共1の時にデータ転送が成立する。今回は非同期FIFOが絶対にFULLやEMPTYにならないように制御しているので、Readデータ転送中は、M_AXI_RREADYが常に1になっているはずだ。

下に、テストベンチ bitmap_disp_cntrler_axi_master_tb.v を貼っておく。defparam でparameter を変更している。これは、bitmap_disp_engine.v でAXI4バスのリセットとディスプレイ表示側のリセットのタイムラグを吸収するために 1msec 表示用の信号出力をWaitするようにした。シミュレーションでは長い時間になるので、そのカウント値を小さくするためである。

`default_nettype none

`timescale 100ps / 1ps

// bitmap_disp_cntrler_axi_master_tb.v
// 2012/07/03

module bitmap_disp_cntrler_axi_master_tb;

    // Inputs
    wire ACLK;
    wire ARESETN;
    wire M_AXI_AWREADY;
    wire M_AXI_WREADY;
    wire [0:0] M_AXI_BID;
    wire [1:0] M_AXI_BRESP;
    wire [0:0] M_AXI_BUSER;
    wire M_AXI_BVALID;
    wire M_AXI_ARREADY;
    wire [0:0] M_AXI_RID;
    wire [63:0] M_AXI_RDATA;
    wire [1:0] M_AXI_RRESP;
    wire M_AXI_RLAST;
    wire [0:0] M_AXI_RUSER;
    wire M_AXI_RVALID;

    // Outputs
    wire [0:0] M_AXI_AWID;
    wire [31:0] M_AXI_AWADDR;
    wire [7:0] M_AXI_AWLEN;
    wire [2:0] M_AXI_AWSIZE;
    wire [1:0] M_AXI_AWBURST;
    wire M_AXI_AWLOCK;
    wire [3:0] M_AXI_AWCACHE;
    wire [2:0] M_AXI_AWPROT;
    wire [3:0] M_AXI_AWQOS;
    wire [0:0] M_AXI_AWUSER;
    wire M_AXI_AWVALID;
    wire [63:0] M_AXI_WDATA;
    wire [7:0] M_AXI_WSTRB;
    wire M_AXI_WLAST;
    wire [0:0] M_AXI_WUSER;
    wire M_AXI_WVALID;
    wire M_AXI_BREADY;
    wire [0:0] M_AXI_ARID;
    wire [31:0] M_AXI_ARADDR;
    wire [7:0] M_AXI_ARLEN;
    wire [2:0] M_AXI_ARSIZE;
    wire [1:0] M_AXI_ARBURST;
    wire [1:0] M_AXI_ARLOCK;
    wire [3:0] M_AXI_ARCACHE;
    wire [2:0] M_AXI_ARPROT;
    wire [3:0] M_AXI_ARQOS;
    wire [0:0] M_AXI_ARUSER;
    wire M_AXI_ARVALID;
    wire M_AXI_RREADY;

    wire pixclk;
    wire    TMDS_tx_clk_p;
    wire    TMDS_tx_clk_n;
    wire    TMDS_tx_2_G_p;
    wire    TMDS_tx_2_G_n;
    wire    TMDS_tx_1_R_p;
    wire    TMDS_tx_1_R_n;
    wire    TMDS_tx_0_B_p;
    wire    TMDS_tx_0_B_n;
    

    // Instantiate the Unit Under Test (UUT_MASTER)
    bitmap_disp_cntrler_axi_master uut_master (
        .ACLK(ACLK), 
        .ARESETN(ARESETN), 
        .M_AXI_AWID(M_AXI_AWID), 
        .M_AXI_AWADDR(M_AXI_AWADDR), 
        .M_AXI_AWLEN(M_AXI_AWLEN), 
        .M_AXI_AWSIZE(M_AXI_AWSIZE), 
        .M_AXI_AWBURST(M_AXI_AWBURST), 
        .M_AXI_AWLOCK(M_AXI_AWLOCK), 
        .M_AXI_AWCACHE(M_AXI_AWCACHE), 
        .M_AXI_AWPROT(M_AXI_AWPROT), 
        .M_AXI_AWQOS(M_AXI_AWQOS), 
        .M_AXI_AWUSER(M_AXI_AWUSER), 
        .M_AXI_AWVALID(M_AXI_AWVALID), 
        .M_AXI_AWREADY(M_AXI_AWREADY), 
        .M_AXI_WDATA(M_AXI_WDATA), 
        .M_AXI_WSTRB(M_AXI_WSTRB), 
        .M_AXI_WLAST(M_AXI_WLAST), 
        .M_AXI_WUSER(M_AXI_WUSER), 
        .M_AXI_WVALID(M_AXI_WVALID), 
        .M_AXI_WREADY(M_AXI_WREADY), 
        .M_AXI_BID(M_AXI_BID), 
        .M_AXI_BRESP(M_AXI_BRESP), 
        .M_AXI_BUSER(M_AXI_BUSER), 
        .M_AXI_BVALID(M_AXI_BVALID), 
        .M_AXI_BREADY(M_AXI_BREADY), 
        .M_AXI_ARID(M_AXI_ARID), 
        .M_AXI_ARADDR(M_AXI_ARADDR), 
        .M_AXI_ARLEN(M_AXI_ARLEN), 
        .M_AXI_ARSIZE(M_AXI_ARSIZE), 
        .M_AXI_ARBURST(M_AXI_ARBURST), 
        .M_AXI_ARLOCK(M_AXI_ARLOCK), 
        .M_AXI_ARCACHE(M_AXI_ARCACHE), 
        .M_AXI_ARPROT(M_AXI_ARPROT), 
        .M_AXI_ARQOS(M_AXI_ARQOS), 
        .M_AXI_ARUSER(M_AXI_ARUSER), 
        .M_AXI_ARVALID(M_AXI_ARVALID), 
        .M_AXI_ARREADY(M_AXI_ARREADY), 
        .M_AXI_RID(M_AXI_RID), 
        .M_AXI_RDATA(M_AXI_RDATA), 
        .M_AXI_RRESP(M_AXI_RRESP), 
        .M_AXI_RLAST(M_AXI_RLAST), 
        .M_AXI_RUSER(M_AXI_RUSER), 
        .M_AXI_RVALID(M_AXI_RVALID), 
        .M_AXI_RREADY(M_AXI_RREADY), 
        .pixclk(pixclk), 
        .TMDS_tx_clk_p(TMDS_tx_clk_p), 
        .TMDS_tx_clk_n(TMDS_tx_clk_n), 
        .TMDS_tx_2_G_p(TMDS_tx_2_G_p), 
        .TMDS_tx_2_G_n(TMDS_tx_2_G_n), 
        .TMDS_tx_1_R_p(TMDS_tx_1_R_p), 
        .TMDS_tx_1_R_n(TMDS_tx_1_R_n), 
        .TMDS_tx_0_B_p(TMDS_tx_0_B_p), 
        .TMDS_tx_0_B_n(TMDS_tx_0_B_n)
    );
    defparam uut_master.bitmap_disp_eng_inst.INIT_COUNT_VAL = 20; // 初期化時のWaitタイマー

    // clk_gen のインスタンス(ACLK)
    clk_gen #(
        .CLK_PERIOD(100),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(ACLK)
    );
    
    // clk_gen のインスタンス(pixclk)
    clk_gen #(
        .CLK_PERIOD(250),    // 25nsec, 40MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) pixclk_i (
        .clk_out(pixclk)
    );
    
    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b0),
        .RESET_TIME(1000)    // 100nsec
    ) RESETi (
        .reset_out(ARESETN)
    );

    // Instantiate the Unit Under Test (UUT_slave)
    axi_master_bfm #(
        .C_M_AXI_DATA_WIDTH(64),
        .READ_ONLY_TRANSACTION(1)    // Read Transaciton のみ使用する = 1(データは+1したデータをReadデータとして使用する
    ) uut_slave (
        .ACLK(ACLK), 
        .ARESETN(ARESETN), 
        .M_AXI_AWID(M_AXI_AWID), 
        .M_AXI_AWADDR(M_AXI_AWADDR), 
        .M_AXI_AWLEN(M_AXI_AWLEN), 
        .M_AXI_AWSIZE(M_AXI_AWSIZE), 
        .M_AXI_AWBURST(M_AXI_AWBURST), 
        .M_AXI_AWLOCK(M_AXI_AWLOCK), 
        .M_AXI_AWCACHE(M_AXI_AWCACHE), 
        .M_AXI_AWPROT(M_AXI_AWPROT), 
        .M_AXI_AWQOS(M_AXI_AWQOS), 
        .M_AXI_AWUSER(M_AXI_AWUSER), 
        .M_AXI_AWVALID(M_AXI_AWVALID), 
        .M_AXI_AWREADY(M_AXI_AWREADY), 
        .M_AXI_WDATA(M_AXI_WDATA), 
        .M_AXI_WSTRB(M_AXI_WSTRB), 
        .M_AXI_WLAST(M_AXI_WLAST), 
        .M_AXI_WUSER(M_AXI_WUSER), 
        .M_AXI_WVALID(M_AXI_WVALID), 
        .M_AXI_WREADY(M_AXI_WREADY), 
        .M_AXI_BID(M_AXI_BID), 
        .M_AXI_BRESP(M_AXI_BRESP), 
        .M_AXI_BUSER(M_AXI_BUSER), 
        .M_AXI_BVALID(M_AXI_BVALID), 
        .M_AXI_BREADY(M_AXI_BREADY), 
        .M_AXI_ARID(M_AXI_ARID), 
        .M_AXI_ARADDR(M_AXI_ARADDR), 
        .M_AXI_ARLEN(M_AXI_ARLEN), 
        .M_AXI_ARSIZE(M_AXI_ARSIZE), 
        .M_AXI_ARBURST(M_AXI_ARBURST), 
        .M_AXI_ARLOCK(M_AXI_ARLOCK), 
        .M_AXI_ARCACHE(M_AXI_ARCACHE), 
        .M_AXI_ARPROT(M_AXI_ARPROT), 
        .M_AXI_ARQOS(M_AXI_ARQOS), 
        .M_AXI_ARUSER(M_AXI_ARUSER), 
        .M_AXI_ARVALID(M_AXI_ARVALID), 
        .M_AXI_ARREADY(M_AXI_ARREADY), 
        .M_AXI_RID(M_AXI_RID), 
        .M_AXI_RDATA(M_AXI_RDATA), 
        .M_AXI_RRESP(M_AXI_RRESP), 
        .M_AXI_RLAST(M_AXI_RLAST), 
        .M_AXI_RUSER(M_AXI_RUSER), 
        .M_AXI_RVALID(M_AXI_RVALID), 
        .M_AXI_RREADY(M_AXI_RREADY)
    );
      
endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out
);
    begin
        initial begin
            reset_out = RESET_STATE;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
        end
    end
endmodule

`default_nettype wire


BFMも以前はRAMを実装して、RAMにWriteしたデータをReadで読み出す方式だったが、今回はWriteが無いので、Readだけでも +1 のデータを出力する機能をBFMに追加した。
axi_master_BFM.vhd を下に貼っておく。

-----------------------------------------------------------------------------
--
-- AXI Master用 Bus Function Mode (BFM)
--
-----------------------------------------------------------------------------
-- 2012/02/25 : M_AXI_AWBURST=1 (INCR) にのみ対応、AWSIZE, ARSIZE = 000 (1byte), 001 (2bytes), 010 (4bytes) のみ対応。
-- 2012/07/04 : READ_ONLY_TRANSACTION を追加。Read機能のみでも+1したデータを出力することが出来るように変更した。


library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;

package m_seq_bfm_pack is
    function M_SEQ16_BFM_F(mseq16in : std_logic_vector
        )return std_logic_vector;
end package m_seq_bfm_pack;
package body m_seq_bfm_pack is
    function M_SEQ16_BFM_F(mseq16in : std_logic_vector
        )return std_logic_vector is
            variable mseq16 : std_logic_vector(15 downto 0);
            variable xor_result : std_logic;
    begin
        xor_result := mseq16in(15) xor mseq16in(12) xor mseq16in(10) xor mseq16in(8) xor mseq16in(7) xor mseq16in(6) xor mseq16in(3) xor mseq16in(2);
        mseq16 := mseq16in(14 downto 0) & xor_result;
        return mseq16;
    end M_SEQ16_BFM_F;
end m_seq_bfm_pack;


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use IEEE.math_real.all;

library work;
use work.m_seq_bfm_pack.all;

--library unisim;
--use unisim.vcomponents.all;

entity axi_master_bfm is
  generic (
    C_M_AXI_ID_WIDTH     : integer := 1;
    C_M_AXI_ADDR_WIDTH   : integer := 32;
    C_M_AXI_DATA_WIDTH   : integer := 32;
    C_M_AXI_AWUSER_WIDTH : integer := 1;
    C_M_AXI_ARUSER_WIDTH : integer := 1;
    C_M_AXI_WUSER_WIDTH  : integer := 1;
    C_M_AXI_RUSER_WIDTH  : integer := 1;
    C_M_AXI_BUSER_WIDTH  : integer := 1;
    
    C_M_AXI_TARGET        : integer := 0;
    C_OFFSET_WIDTH        : integer := 10; -- 割り当てるRAMのアドレスのビット幅
    C_M_AXI_BURST_LEN    : integer := 256;
    
    WRITE_RANDOM_WAIT    : integer := 1; -- Write Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
    READ_RANDOM_WAIT    : integer := 0; -- Read Transaction のデータ転送の時にランダムなWaitを発生させる=1, Waitしない=0
    READ_ONLY_TRANSACTION :    integer := 0 -- Read, Write Transaciton 双方を使用する = 0(RAMにWriteしたものをReadする)、Read Transaciton のみ使用する = 1(データは+1したデータをReadデータとして使用する
    );
  port(
    -- System Signals
    ACLK    : in std_logic;
    ARESETN : in std_logic;

    -- Master Interface Write Address Ports
    M_AXI_AWID     : in  std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_AWADDR   : in  std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
    M_AXI_AWLEN    : in  std_logic_vector(8-1 downto 0);
    M_AXI_AWSIZE   : in  std_logic_vector(3-1 downto 0);
    M_AXI_AWBURST  : in  std_logic_vector(2-1 downto 0);
    -- M_AXI_AWLOCK   : in  std_logic_vector(2-1 downto 0);
    M_AXI_AWLOCK   : in  std_logic;
    M_AXI_AWCACHE  : in  std_logic_vector(4-1 downto 0);
    M_AXI_AWPROT   : in  std_logic_vector(3-1 downto 0);
    M_AXI_AWQOS    : in  std_logic_vector(4-1 downto 0);
    M_AXI_AWUSER   : in  std_logic_vector(C_M_AXI_AWUSER_WIDTH-1 downto 0);
    M_AXI_AWVALID  : in  std_logic;
    M_AXI_AWREADY  : out std_logic;

    -- Master Interface Write Data Ports
    M_AXI_WDATA  : in  std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
    M_AXI_WSTRB  : in  std_logic_vector(C_M_AXI_DATA_WIDTH/8-1 downto 0);
    M_AXI_WLAST  : in  std_logic;
    M_AXI_WUSER  : in  std_logic_vector(C_M_AXI_WUSER_WIDTH-1 downto 0);
    M_AXI_WVALID : in  std_logic;
    M_AXI_WREADY : out std_logic;

    -- Master Interface Write Response Ports
    M_AXI_BID    : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_BRESP  : out std_logic_vector(2-1 downto 0);
    M_AXI_BUSER  : out std_logic_vector(C_M_AXI_BUSER_WIDTH-1 downto 0);
    M_AXI_BVALID : out std_logic;
    M_AXI_BREADY : in  std_logic;

    -- Master Interface Read Address Ports
    M_AXI_ARID     : in  std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_ARADDR   : in  std_logic_vector(C_M_AXI_ADDR_WIDTH-1 downto 0);
    M_AXI_ARLEN    : in  std_logic_vector(8-1 downto 0);
    M_AXI_ARSIZE   : in  std_logic_vector(3-1 downto 0);
    M_AXI_ARBURST  : in  std_logic_vector(2-1 downto 0);
    M_AXI_ARLOCK   : in  std_logic_vector(2-1 downto 0);
    M_AXI_ARCACHE  : in  std_logic_vector(4-1 downto 0);
    M_AXI_ARPROT   : in  std_logic_vector(3-1 downto 0);
    M_AXI_ARQOS    : in  std_logic_vector(4-1 downto 0);
    M_AXI_ARUSER   : in  std_logic_vector(C_M_AXI_ARUSER_WIDTH-1 downto 0);
    M_AXI_ARVALID  : in  std_logic;
    M_AXI_ARREADY  : out std_logic;

    -- Master Interface Read Data Ports
    M_AXI_RID    : out std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
    M_AXI_RDATA  : out std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
    M_AXI_RRESP  : out std_logic_vector(2-1 downto 0);
    M_AXI_RLAST  : out std_logic;
    M_AXI_RUSER  : out std_logic_vector(C_M_AXI_RUSER_WIDTH-1 downto 0);
    M_AXI_RVALID : out std_logic;
    M_AXI_RREADY : in  std_logic
    );

end axi_master_bfm;

architecture implementation of axi_master_bfm is

constant    AxBURST_FIXED    : std_logic_vector := "00";
constant    AxBURST_INCR    : std_logic_vector := "01";
constant    AxBURST_WRAP    : std_logic_vector := "10";

constant    RESP_OKAY        : std_logic_vector := "00";
constant    RESP_EXOKAY        : std_logic_vector := "01";
constant    RESP_SLVERR        : std_logic_vector := "10";
constant    RESP_DECERR        : std_logic_vector := "11";

constant    DATA_BUS_BYTES     : natural := C_M_AXI_DATA_WIDTH/8; -- データバスのビット幅
constant    ADD_INC_OFFSET    : natural := natural(log(real(DATA_BUS_BYTES), 2.0));

-- RAMの生成
constant    SLAVE_ADDR_NUMBER    : integer := 2**(C_OFFSET_WIDTH - ADD_INC_OFFSET);
type ram_array_def is array (SLAVE_ADDR_NUMBER-1 downto 0) of std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);
signal ram_array : ram_array_def := (others => (others => '0'));

-- for write transaction
type write_transaction_state is (idle_wr, awr_wait, awr_accept, wr_burst);
type write_response_state is (idle_wres, bvalid_assert);
type write_wready_state is (idle_wrdy, wready_assert);
signal wrt_cs : write_transaction_state;
signal wrres : write_response_state;
signal wrwr : write_wready_state;
signal addr_inc_step_wr : integer := 1;
signal awready         : std_logic;
signal wr_addr         : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal wr_bid         : std_logic_vector(C_M_AXI_ID_WIDTH-1 downto 0);
signal wr_bresp     : std_logic_vector(1 downto 0);
signal wr_bvalid     : std_logic;
signal m_seq16_wr    : std_logic_vector(15 downto 0);
signal wready        : std_logic;
type wready_state is (idle_wready, assert_wready, deassert_wready);
signal cs_wready : wready_state;
signal cdc_we : std_logic;

-- for read transaction
type read_transaction_state is (idle_rd, arr_wait, arr_accept, rd_burst);
type read_last_state is (idle_rlast, rlast_assert);
signal rdt_cs : read_transaction_state;
signal rdlast : read_last_state;
signal addr_inc_step_rd : integer := 1;
signal arready         : std_logic;
signal rd_addr         : std_logic_vector(C_OFFSET_WIDTH-1 downto 0);
signal rd_axi_count    : std_logic_vector(7 downto 0);
signal rvalid        : std_logic;
signal rlast        : std_logic;
signal m_seq16_rd    : std_logic_vector(15 downto 0);
type rvalid_state is (idle_rvalid, assert_rvalid, deassert_rvalid);
signal cs_rvalid : rvalid_state;
signal read_data_count : std_logic_vector(C_M_AXI_DATA_WIDTH-1 downto 0);

signal reset_1d, reset_2d, reset : std_logic := '1';

begin
    -- ARESETN をACLK で同期化
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            reset_1d <= not ARESETN;
            reset_2d <= reset_1d;
        end if;
    end process;
    reset <= reset_2d;
    
    -- AXI4バス Write Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wrt_cs <= idle_wr;
                awready <= '0';
            else
                case (wrt_cs) is
                    when idle_wr =>
                        if M_AXI_AWVALID='1' then -- M_AXI_AWVALID が1にアサートされた
                            if rdt_cs=idle_rd then -- Read Transaction が終了している(Writeの方が優先順位が高い)
                                wrt_cs <= awr_accept;
                                awready <= '1';
                            else -- Read Transaction が終了していないのでWait
                                wrt_cs <= awr_wait;
                            end if;
                        end if;
                    when awr_wait => -- Read Transaction の終了待ち
                        if rdt_cs=idle_rd or rdt_cs=arr_wait then -- Read Transaction が終了
                            wrt_cs <= awr_accept;
                            awready <= '1';
                        end if;
                    when awr_accept => -- M_AXI_AWREADY をアサート
                        wrt_cs <= wr_burst;
                        awready <= '0';
                    when wr_burst => -- Writeデータの転送
                        if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
                            wrt_cs <= idle_wr;
                        end if;
                end case;
            end if;
        end if;
    end process;
    M_AXI_AWREADY <= awready;
    
    -- m_seq_wr、16ビットのM系列を計算する
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                m_seq16_wr <= (0 => '1', others => '0');
            else
                if WRITE_RANDOM_WAIT=1 then -- Write Transaction 時にランダムなWaitを挿入する
                    if wrt_cs=wr_burst and M_AXI_WVALID='1' then
                        m_seq16_wr <= M_SEQ16_BFM_F(m_seq16_wr);
                    end if;
                else -- Wait無し
                    m_seq16_wr <= (others => '0');
                end if;
            end if;
        end if;
    end process;
                
    -- wready の処理、M系列を計算して128以上だったらWaitする。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                cs_wready <= idle_wready;
                wready <= '0';
            else
                case (cs_wready) is
                    when idle_wready =>
                        if wrt_cs=awr_accept then -- 次はwr_burst
                            if m_seq16_wr(7)='0' then -- wready='1'
                                cs_wready <= assert_wready;
                                wready <= '1';
                            else -- m_seq16_wr(7)='1' then -- wready='0'
                                cs_wready <= deassert_wready;
                                wready <= '0';
                            end if;
                        end if;
                    when assert_wready => -- 一度wreadyがアサートされたら、1つのトランザクションが終了するまでwready='1'
                        if wrt_cs=wr_burst and M_AXI_WLAST='1' and M_AXI_WVALID='1' then -- 終了
                            cs_wready <= idle_wready;
                            wready <= '0';
                        elsif wrt_cs=wr_burst and M_AXI_WVALID='1' then -- 1つのトランザクション終了。
                            if m_seq16_wr(7)='1' then
                                cs_wready <= deassert_wready;
                                wready <= '0';
                            end if;
                        end if;
                    when deassert_wready =>
                        if m_seq16_wr(7)='0' then -- wready='1'
                            cs_wready <= assert_wready;
                            wready <= '1';
                        end if;
                end case;
            end if;
        end if;
    end process;
    
    M_AXI_WREADY <= wready;
    cdc_we <= '1' when wrt_cs=wr_burst and wready='1' and M_AXI_WVALID='1' else '0';
    
    -- addr_inc_step_wr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                addr_inc_step_wr <= 1;
            else
                if wrt_cs=awr_accept then
                    case (M_AXI_AWSIZE) is
                        when "000" => -- 8ビット転送
                            addr_inc_step_wr <= 1;
                        when "001" => -- 16ビット転送
                            addr_inc_step_wr <= 2;
                        when "010" => -- 32ビット転送
                            addr_inc_step_wr <= 4;
                        when "011" => -- 64ビット転送
                            addr_inc_step_wr <= 8;
                        when "100" => -- 128ビット転送
                            addr_inc_step_wr <= 16;
                        when "101" => -- 256ビット転送
                            addr_inc_step_wr <= 32;
                        when "110" => -- 512ビット転送
                            addr_inc_step_wr <= 64;
                        when others => --"111" => -- 1024ビット転送
                            addr_inc_step_wr <= 128;
                    end case;
                end if;
            end if;
        end if;
    end process;
    
    -- wr_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_addr <= (others => '0');
            else
                if wrt_cs=awr_accept then
                    wr_addr <= M_AXI_AWADDR(C_OFFSET_WIDTH-1 downto 0);
                elsif wrt_cs=wr_burst and M_AXI_WVALID='1' and wready='1' then -- アドレスを進める
                    wr_addr <= wr_addr + addr_inc_step_wr;
                end if;
            end if;
        end if;
    end process;
    
    -- wr_bid の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bid <= "0";
            else
                if wrt_cs=awr_accept then
                    wr_bid <= M_AXI_AWID;
                end if;
            end if;
        end if;
    end process;
    M_AXI_BID <= wr_bid;
    
    -- wr_bresp の処理
    -- M_AXI_AWBURSTがINCRの時はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bresp <= (others => '0');
            else
                if wrt_cs=awr_accept then
                    if M_AXI_AWBURST=AxBURST_INCR then -- バーストタイプがアドレス・インクリメントタイプ
                        wr_bresp <= RESP_OKAY; -- Write Transaction は成功
                    else
                        wr_bresp <= RESP_SLVERR; -- エラー
                    end if;
                end if;
            end if;
        end if;
    end process;
    M_AXI_BRESP <= wr_bresp;
    
    -- wr_bvalid の処理
    -- Write Transaction State Machineには含まない。axi_master のシミュレーションを見ると1クロックで終了しているので、長い間、Master側の都合でWaitしていることは考えない。
    -- 次のWrite転送まで遅延しているようであれば、Write Transaction State Machine に入れてブロックすることも考える必要がある。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                wr_bvalid <= '0';
            else
                if M_AXI_WLAST='1' and M_AXI_WVALID='1' and wready='1' then -- Write Transaction 終了
                    wr_bvalid <= '1';
                elsif wr_bvalid='1' and M_AXI_BREADY='1' then -- wr_bvalid が1でMaster側のReadyも1ならばWrite resonse channel の転送も終了
                    wr_bvalid <= '0';
                end if;
            end if;
        end if;
    end process;
    M_AXI_BVALID <= wr_bvalid;
    M_AXI_BUSER <= (others => '0');
    
    
    -- AXI4バス Read Transaction State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdt_cs <= idle_rd;
                arready <= '0';
            else
                case (rdt_cs) is
                    when idle_rd =>
                        if M_AXI_ARVALID='1' then -- Read Transaction 要求
                            if wrt_cs=idle_wr and M_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
                                rdt_cs <= arr_accept;
                                arready <= '1';
                            else -- Write Transaction が終了していないのでWait
                                rdt_cs <= arr_wait;
                            end if;
                        end if;
                    when arr_wait => -- Write Transaction の終了待ち
                        if wrt_cs=idle_wr and M_AXI_AWVALID='0' then -- Write Transaction State Machine がidle でWrite要求もない
                            rdt_cs <= arr_accept;
                            arready <= '1';
                        end if;
                    when arr_accept => -- M_AXI_ARREADY をアサート
                        rdt_cs <= rd_burst;
                        arready <= '0';
                    when rd_burst => -- Readデータの転送
                        if rd_axi_count=0 and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了
                            rdt_cs <= idle_rd;
                        end if;
                end case;
            end if;
        end if;
    end process;
    M_AXI_ARREADY <= arready;

    -- m_seq_rd、16ビットのM系列を計算する
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                m_seq16_rd <= (others => '1'); -- Writeとシードを変更する
            else
                if READ_RANDOM_WAIT=1 then -- Read Transaciton のデータ転送でランダムなWaitを挿入する場合
                    if rdt_cs=rd_burst and M_AXI_RREADY='1' then
                        m_seq16_rd <= M_SEQ16_BFM_F(m_seq16_rd);
                    end if;
                else -- Wati無し
                    m_seq16_rd <= (others => '0');
                end if;
            end if;
        end if;
    end process;
                
    -- rvalid の処理、M系列を計算して128以上だったらWaitする。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                cs_rvalid <= idle_rvalid;
                rvalid <= '0';
            else
                case (cs_rvalid) is
                    when idle_rvalid =>
                        if rdt_cs=arr_accept then -- 次はrd_burst
                            if m_seq16_rd(7)='0' then -- rvalid='1'
                                cs_rvalid <= assert_rvalid;
                                rvalid <= '1';
                            else -- m_seq16_rd(7)='1' then -- rvalid='0'
                                cs_rvalid <= deassert_rvalid;
                                rvalid <= '0';
                            end if;
                        end if;
                    when assert_rvalid => -- 一度rvalidがアサートされたら、1つのトランザクションが終了するまでrvalid='1'
                        if rdt_cs=rd_burst and rlast='1' and M_AXI_RREADY='1' then -- 終了
                            cs_rvalid <= idle_rvalid;
                            rvalid <= '0';
                        elsif rdt_cs=rd_burst and M_AXI_RREADY='1' then -- 1つのトランザクション終了。
                            if m_seq16_rd(7)='1' then
                                cs_rvalid <= deassert_rvalid;
                                rvalid <= '0';
                            end if;
                        end if;
                    when deassert_rvalid =>
                        if m_seq16_rd(7)='0' then -- rvalid='1'
                            cs_rvalid <= assert_rvalid;
                            rvalid <= '1';
                        end if;
                end case;
            end if;
        end if;
    end process;
    
    M_AXI_RVALID <= rvalid;
    
    -- addr_inc_step_rd の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                addr_inc_step_rd <= 1;
            else
                if rdt_cs=arr_accept then
                    case (M_AXI_ARSIZE) is
                        when "000" => -- 8ビット転送
                            addr_inc_step_rd <= 1;
                        when "001" => -- 16ビット転送
                            addr_inc_step_rd <= 2;
                        when "010" => -- 32ビット転送
                            addr_inc_step_rd <= 4;
                        when "011" => -- 64ビット転送
                            addr_inc_step_rd <= 8;
                        when "100" => -- 128ビット転送
                            addr_inc_step_rd <= 16;
                        when "101" => -- 256ビット転送
                            addr_inc_step_rd <= 32;
                        when "110" => -- 512ビット転送
                            addr_inc_step_rd <= 64;
                        when others => -- "111" => -- 1024ビット転送
                            addr_inc_step_rd <= 128;
                    end case;
                end if;
            end if;
        end if;
    end process;
    
    -- rd_addr の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_addr <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    rd_addr <= M_AXI_ARADDR(C_OFFSET_WIDTH-1 downto 0);
                elsif rdt_cs=rd_burst and M_AXI_RREADY='1' and rvalid='1' then
                    rd_addr <= rd_addr + addr_inc_step_rd;
                end if;
            end if;
        end if;
    end process;
    
    -- rd_axi_count の処理(AXIバス側のデータカウント)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rd_axi_count <= (others => '0');
            else
                if rdt_cs=arr_accept then -- rd_axi_count のロード
                    rd_axi_count <= M_AXI_ARLEN;
                elsif rdt_cs=rd_burst and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction が1つ終了
                    rd_axi_count <= rd_axi_count - 1;
                end if;
            end if;
        end if;
    end process;
    
    -- rdlast State Machine
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                rdlast <= idle_rlast;
                rlast <= '0';
            else
                case (rdlast) is
                    when idle_rlast =>
                        if rd_axi_count=1 and rvalid='1' and M_AXI_RREADY='1' then -- バーストする場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        elsif rdt_cs=arr_accept and M_AXI_ARLEN=0 then -- 転送数が1の場合
                            rdlast <= rlast_assert;
                            rlast <= '1';
                        end if;
                    when rlast_assert => 
                        if rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction 終了(rd_axi_count=0は決定)
                            rdlast <= idle_rlast;
                            rlast <= '0';
                        end if;
                end case;
            end if;
        end if;
    end process;
    M_AXI_RLAST <= rlast;
    
    -- M_AXI_RID, M_AXI_RUSER の処理
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                M_AXI_RID <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    M_AXI_RID <= M_AXI_ARID;
                end if;
            end if;
        end if;
    end process;
    M_AXI_RUSER <= (others => '0');
    
    -- M_AXI_RRESP は、M_AXI_ARBURST がINCR の場合はOKAYを返す。それ以外はSLVERRを返す。
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                M_AXI_RRESP <= (others => '0');
            else
                if rdt_cs=arr_accept then
                    if M_AXI_ARBURST=AxBURST_INCR then
                        M_AXI_RRESP <= RESP_OKAY;
                    else
                        M_AXI_RRESP <= RESP_SLVERR;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    -- RAM
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if cdc_we='1' then
                for i in 0 to C_M_AXI_DATA_WIDTH/8-1 loop
                    if M_AXI_WSTRB(i)='1' then -- Byte Enable
                        ram_array(CONV_INTEGER(wr_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET)))(i*8+7 downto i*8) <= M_AXI_WDATA(i*8+7 downto i*8);
                    end if;
                end loop;
            end if;
        end if;
    end process;

    -- Read Transaciton のみの場合のReadデータ(Transction 毎に+1)
    process (ACLK) begin
        if ACLK'event and ACLK='1' then 
            if reset='1' then
                read_data_count <= (others => '0');
            else
                if rdt_cs=rd_burst and rvalid='1' and M_AXI_RREADY='1' then -- Read Transaction が1つ終了
                    read_data_count <= read_data_count + 1;
                end if;
            end if;
        end if;
    end process;
    
    M_AXI_RDATA <= ram_array(CONV_INTEGER(rd_addr(C_OFFSET_WIDTH-1 downto ADD_INC_OFFSET))) when READ_ONLY_TRANSACTION=0 else read_data_count;
    
end implementation;

  1. 2012年07月04日 05:12 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製2(コード製作)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製1(仕様)”の続き。

下に示す図のとおりにVerilog ファイルを作製した。
BitMapDispCont_1_120626.png

bitmap_disp_cntrler_axi_master.v --- axi_master_interface.v
                     |- bitmap_disp_engine.v --- bitmap_afifo.xco(非同期FIFO IP)
上に示すVerilog ファイルを作製した。dvi_disp.vhd は以前に作ってあったものを使用した。

シミュレーションをするためにISE Projcect Navigator のプロジェクトを作って、Check Syntaxを行ったところ成功した。
BitMapDispCont_3_120703.png

これからテストベンチを記述する。BFMも作成したい。
  1. 2012年07月03日 05:38 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

さくらんぼ狩りに行って、蔵王温泉スキー場の大露天風呂を堪能しました

一昨日と昨日の土日に、奥さんと一緒に仙台の娘のところに行って、念願だったさくらんぼ狩りと蔵王温泉スキー場の大露天風呂に行って来ました。
例によって、車で行って来ました。午前5時過ぎに家を出発して、矢板インターから東北道に乗りました。午前10時ころ娘の所に到着。娘を乗せて山形に出発です。さくらんぼ狩り出来るところは色々あったのですが、蔵王温泉スキー場に近い山形市黒沢の喜三郎さくらんぼ狩園へ行きました。
6月30日の山形は暑かったです。到着して料金を払ってさくらんぼ狩りへ。さくらんぼ園は上に鳥よけのビニールがかかっていて、更に暑かったです。まるで蒸し風呂のようです。さくらんぼ狩りをする時間は40分とのことでしたが、特に計測していないそうです。だけど、この暑さなので、あまりいられないでしょうとの事でした。係の人はとってもフレンドリー。さくらんぼが食べごろの木を教えてくれました。その木のさくらんぼは甘酸っぱくとっても美味しかったです。こんな風にさくらんぼがなっています。
sakuranbogari_1_120702.jpg

手で取れる所にいっぱい実を付けています。
sakuranbogari_2_120702.jpg

これは佐藤錦ですが、その他の種類もたくさんありました。佐藤錦は甘酸っぱく、バランスが良い味で、さすが、さくらんぼの品種の代表格だと思います。南陽という種類は実が大きく、食べごたえがありました。ただ酸味は佐藤錦よりも少ないような気がしますが、美味しかったです。これが一番美味しかったかもです。品種はよくわかりませんが(黒砂糖錦かも)アメリカン・チェリーの様なさくらんぼがありました。これは甘かったのですが、酸味がなくて淡白な味でした。
sakuranbogari_3_120702.jpg

いや~生まれて初めて、お腹がすいた状態から腹がいっぱいになるまでさくらんぼを食べました。もう食えないということで、蒸し暑いさくらんぼ園を後にして昼食へ。なお、佐藤錦のベストシーズンは6月の最終週くらいとのことです。1週間遅いくらいだったようです。
さくらんぼで腹一杯なので、蕎麦でもということで蕎麦屋へ行って山菜そばを食べました。食べられないと思っても結構腹に入るものですね。

次は、蔵王温泉スキー場でサンシャイン・ゲレンデをつなぐ連絡橋のところから見える露天風呂に行きました。
sakuranbogari_4_120702.jpg

いつもスキーに行って、露天風呂に入りたいと思っていても冬期は閉鎖なので、冬以外に行かないと入れません。階段を降りていくと良い風情です。
sakuranbogari_5_120702.jpg

露天風呂は2つの浴槽にわかれていて、岩を使って作ってありました。上の浴槽はとっても湯の温度が熱いので、調度良い温度の下の浴槽につかってきました。脇に川が流れていて、とっても良い景色です。30年弱以来の願いがかないました。蔵王温泉スキー場に夏来たことがなかったので、露天風呂に入れなかったんです。とっても良かったですよ。皆さんも蔵王に冬以外に行った際にはどうでしょうか?

娘にも久しぶりに会えたし、満足して帰って来ました。ETC休日割引で高速料金は半額でした。矢板インターから仙台宮城インターまでの高速代金は2,450円でした。
  1. 2012年07月02日 05:39 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0