Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zynq + Vivado HLS入門

20,819 views

Published on

Trax workshop(http://lut.eee.u-ryukyu.ac.jp/traxjp/workshop.html)で使用した資料です。
間違いがある場合、ご指摘お願い致します。

修正 2015.4.2
p22, 情報追加
p28, シュミレーション => シミュレーション
p116, 情報追加
p128, dst_dataの => dst_dataに
p141, su => sudo, 不要なsudoの削除, screenコマンドの使い方を追加
p150, 説明追加

Published in: Devices & Hardware
  • 少し修正しました。詳細はdescriptionに
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Zynq + Vivado HLS入門

  1. 1. ZYNQ + Vivado HLS入門 慶應義塾大学 天野研究室 修士1年 杉本 成
  2. 2. 内容 • 対象はこれからZYNQを使ってみたい方 • 実習形式で進めていく • ZYNQのCPU⇔FPGA間のデータ転送方法、 共有方法をレクチャー • VIVADO HLS, VIVADO IP Integratorを 利用して手軽に実装 • RTLは1行も書かない
  3. 3. 目次 • 基礎説明  ZYNQ構成  AXIとは  ZYNQ内のAXI経路  VIVADOの特徴 • 実習内容の説明  目標とするデザイン  ツールの説明  ツールフロー • 実習  VIVADO HLSでmemcpyコアを実装  VIVADO IP integraterでIPコアを接続  SDKでソフトウェアを実装、実行  VIVADO Logic AnalyzerでAXI通信を観察
  4. 4. ZYNQ構成 DDR ZYNQブロック図 *xilinx ホームページより引用 • PS (Processing System)および PL (Programmable Logic)から 構成される • PSの構成は以下の通り  Application Processing Unit(APU) CPU, DMAコントローラ, GIC等  Memory Interface DDRコントローラ等  IO Peripheral(IOP) GPIO, UARTコントローラ等 • PS内、PS⇔PL間のインターフェースは 全てARM AXIで統一されている PS PL
  5. 5. ZYNQ アドレスマップ システムレベルのアドレスマップ *UG585 P103より引用 • 各機能にアクセスする際に使用するアドレス一覧
  6. 6. AXIとは • ARM® AMBA インターフェースのこと※AXI4はAMBA第4世代インターフェース • MasterとSlaveが1対1で通信を行う • スイッチを介すことで、複数Masterと複数Slaveを 繋げることもできる.(しかし通信は1対1) • Slaveはレジスタもしくはメモリを持っていて、 Masterはアドレスを指定してデータの読み書きを行う M S 0x00000000 0x0000ffff
  7. 7. AXI4 バースト転送 M S 0x00000000 0x0000ffff D 0 D 1 D 2 D 3 D 4 D 5 D 6 D 7 … • AXI4は指定したアドレスから連続してデータを(毎サイクル) 読み出し/書き込みできる • 指定したアドレスからインクリメント、指定したアドレス から連続して等の設定ができる • バースト長は最大256である AXI4 バースト読み出しの例
  8. 8. AXIの種類 • AXI: 普通のAXI • AXILite: AXIの軽量版、バースト転送ができない • AXIstream: アドレスの概念を消したストリーム用
  9. 9. ZYNQ IOPへのアクセス S M APU ⇔ IOP間  Master => APU  Slave => IOP IOPのレジスタ設定、入出力 データの送受信に使用
  10. 10. ZYNQ AXIGP(Slave) S M APU ⇔ AXIGP(Slave)間  Master => CPU  Slave => AXIGP データ幅は32bit
  11. 11. ZYNQ AXIGP(Master) S M APU ⇔ AXIGP(Slave)間  Master => AXIGP  Slave => DDR データ幅は32bit
  12. 12. ZYNQ DMAエンジン S M DMA ⇔ DDR間  Master => DMA  Slave => DDR DMA ⇔ AXIGP(Slave)間  Master => DMA  Slave => AXIGPS
  13. 13. ZYNQ AXIHP S M AXIHP ⇔ DDR間  Master => AXIHP  Slave => DDR データ幅は32/64bit
  14. 14. ZYNQ ACP S M AXIACP ⇔ APU間  Master => AXIACP  Slave => APU データ幅は64bit
  15. 15. VIVADO IP Integrator • ISE => XPS
  16. 16. VIVADO Logic Analyzer • ISE => Chip Scope
  17. 17. ZYNQ 目標とするデザイン PS APU DDR Controler AXIHP_MEMCPY (created by VIVADO HLS) interrupt M S S M DDR AXIGP AXIHP • AXIHPを使用してMEMCPY を行う”AXIHP MEMCPY”を VIVADO HLSで実装 • 読み出し/書き込みアドレス およびMEMCPYの制御は、 APUからAXIGP経由で行う • 読み出し/書き込みは共に 256バースト転送 • ILAコアでAXIのやりとりを 監視する • MEMCPYの終了はinterrupt でAPUに割り込みをかける ILA VIVADO HLSを利用したMEMCPY
  18. 18. ツールフロー AXIHP_MEMCPY関数のC記述 AXIHP_MEMCPY関数のDirective設定 AXIHP_MEMCPYのIP化 PSの設定 PSとAXIHP_MEMCPYの接続 bitstreamの生成 ソフトウェアの実装、実行 VIVADO HLS VIVADO SDK VIVADO + SDK 使用するツール手順 波形のキャプチャ
  19. 19. 環境 • Vivado 2014.4を対象としている (2014.2以降なら同様のことが可能) • Zed Board、ZYBOを想定 • zynq_vivadohlsディレクトリで作業する
  20. 20. VIVADO HLS AXIHP_MEMCPY関数のC記述 AXIHP_MEMCPY関数のDirective設定 AXIHP_MEMCPYのIP化 Projectの生成 AXIHP_MEMCPYの合成 作業手順
  21. 21. VIVADO HLS "AXIHP MEMCPYコア" AXIHP_MEMCPY (created by VIVADO HLS) interrupt clk reset AXILite AXIMS 32bit 64bit
  22. 22. VIVADO HLS “Projectの生成1/7” • vivado_hlsを起動する • [Create New Project]をクリック 1
  23. 23. VIVADO HLS “Projectの生成2/7” • 任意のProject nameを入力 (自分は”axihp_memcpy”とした) • “Location”は任意(自分はzynq_vivadohlsディレクトリにした) • [Next]をクリック 1 2 3
  24. 24. VIVADO HLS “Projectの生成3/7” • Top Functionを”axihp_memcpy”とする(対象とする関数の関数名) • [Next] をクリック 1 2
  25. 25. VIVADO HLS “Projectの生成4/7” • [Next] を選択(今回シミュレーションは行わないので何も加えない) 1
  26. 26. VIVADO HLS “Projectの生成5/7” • Part Selectionのタブを開く 1
  27. 27. VIVADO HLS “Projectの生成6/7” ZedBoardの場合 • [Boards]タブを選択 • “ZedBoard”を選択する • [OK]をクリックする 1 2 3 Zyboの場合 • [Parts]タブを選択 • “xc7z010clg400-1を選択する • [OK]をクリックする
  28. 28. VIVADO HLS “Projectの生成7/7” • [Finish]をクリックする 1
  29. 29. VIVADO HLS 起動完了 • Projectの生成が完了した
  30. 30. VIVADO HLS “Fileの作成1/3” • [Source]を右クリックする • [New File]をクリックする 1 2
  31. 31. VIVADO HLS “Fileの作成2/3” • File名を”axihp_memcpy.c”とする • 保存先は”zynq_vivadohls/axihp_memcpy/.apc”とする • [OK]をクリック 1 2 3
  32. 32. VIVADO HLS “Fileの生成3/3” • [Source]タブの中に”axihp_memcpy.c”が作成された • このファイルにaxihp_memcpyを記述していく
  33. 33. VIVADO HLS “axihp_memcpyの実装1/4” void axihp_memcpy(); void axihp_memcpy() { } • void型のaxihp_memcpy関数を記述する
  34. 34. VIVADO HLS “axihp_memcpyの実装2/4” typedef unsigned long long u64; void axihp_memcpy(u64 *axihp_in, u64 *axihp_out); void axihp_memcpy(u64 *axihp_in, u64 *axihp_out) { } • axihp(64bit)用の入力, 出力ポートを関数の引数に記述 • “unsigned long long”は長いので”u64”に置き換える
  35. 35. VIVADO HLS “axihp_memcpyの実装3/4” typedef unsigned long long u64; void axihp_memcpy(u64 *axihp_in, u64 *axihp_out); void axihp_memcpy(u64 *axihp_in, u64 *axihp_out) { u64 buf[256]; memcpy(buf, axihp_in, 256 * sizeof(u64)); } • 入力データを受け取るための配列”buf”を用意する • burst転送はmemcpyを使用して表現する バースト長256のバースト転送(受信)となる ※buf[0] = *axihp_in; とすると通常転送の読み出しとなる
  36. 36. VIVADO HLS “axihp_memcpyの実装4/4” typedef unsigned long long u64; void axihp_memcpy(u64 *axihp_in, u64 *axihp_out); void axihp_memcpy(u64 *axihp_in, u64 *axihp_out) { u64 buf[256]; memcpy(buf, axihp_in, 256 * sizeof(u64)); memcpy(axihp_out, buf, 256 * sizeof(u64)); } • memcpyでバースト転送の書き込みを記述する バースト長256のバースト転送(送信)となる ※*axihp_out = buf[0]; とすると通常転送の書き込みとなる
  37. 37. VIVADO HLS “axihp_memcpy関数” typedef unsigned long long u64; void axihp_memcpy(u64 *axihp_in, u64 *axihp_out); void axihp_memcpy(u64 *axihp_in, u64 *axihp_out) { u64 buf[256]; memcpy(buf, axihp_in, 256 * sizeof(u64)); memcpy(axihp_out, buf, 256 * sizeof(u64)); } • 以上でaxihp_memcpy関数は完成となる • AXIHPの読み出し/書き込みアドレスおよび axihp_memcpyの制御方法は[Directive]で設定していく
  38. 38. VIVADO HLS “Directive設定1/10” • [Directive]タブをクリックする 1
  39. 39. VIVADO HLS “Directive設定2/10” • 引数”axihp_in”をaxiポートのmasterとなるように設定していく • [axihp_in]を右クリックする • [Insert Directive]をクリックする 21
  40. 40. VIVADO HLS “Directive設定3/10” • [Directive]のプルダウンメニューを”INTERFACE”にする • [mode]のプルダウンメニューを”m_axi”にする • [offset]のプルダウンメニューを”slave”にする • [OK]をクリック 1 2 3 4 この設定を”slave”にすると読み 出しアドレスを、slaveポート から指定できるようになる “axihp_in”はaxiのmaster ポートと認識されるようになる
  41. 41. VIVADO HLS “Directive設定4/10” • 引数“axihp_in”の設定が完了した • 設定した内容は[axihp_in]の下に表示される
  42. 42. VIVADO HLS ”Directive設定5/10” • 引数”axihp_out”も同様に設定していく • [axihp_out]を右クリックする • [Insert Directive]をクリックする 21
  43. 43. VIVADO HLS “Directive設定6/10” • [Directive]のプルダウンメニューを”INTERFACE”にする • [mode]のプルダウンメニューを”m_axi”にする • [offset]のプルダウンメニューを”slave”にする • [OK]をクリック 1 2 3 4 この設定を”slave”にすると読み 出しアドレスを、slaveポート から指定できるようになる “axihp_out”はaxiのmaster ポートと認識されるようになる
  44. 44. VIVADO HLS “Directive設定7/10” • 引数”axihp_out”の設定が完了した • 次は関数axihp_memcpyの制御方法の設定を行っていく
  45. 45. VIVADO HLS “Directive設定8/10” • 関数axihp_memcpyの制御方法を設定していく • [axihp_memcpy]を右クリックする • [Insert Directive]をクリックする 21
  46. 46. VIVADO HLS “Directive設定9/10” • [Directive]のプルダウンメニューを”INTERFACE”にする • [mode]のプルダウンメニューを”s_axilite”にする • [OK]をクリック 1 2 3 この設定により “axihp_memcpy”はaxi slave ポートから制御される. また終了を知らせるinterrupt 信号も生成される.
  47. 47. VIVADO HLS “Directive設定10/10” • 以上でDirectiveの設定が完了した
  48. 48. VIVADO HLS “Synthesis1/3” • Synthesisを行っていく • [C Synthesis]をクリックする 1
  49. 49. VIVADO HLS “Synthesis2/3” • Synthesisが完了した
  50. 50. VIVADO HLS “Synthesis3/3” • 生成されるポート一覧 Slave AXIポート (AXILite) Master AXIポート (AXI)
  51. 51. VIVADO HLS “IP Packageing1/3” • axihp_memcpyをIPパッケージ化していく • [Export RTL]をクリックする 1
  52. 52. VIVADO HLS “IP Packaging 2/3” • “Verilog”または”VHDL”を選択 • [OK]をクリックする 1 2
  53. 53. VIVADO HLS “IP Packaging 3/3” • IPパッケージ化が完了した • 以上でVIVADO HLSによる操作は終了となる
  54. 54. VIVADO PSの設定 PSとAXIHP_MEMCPYの接続 HardwareのExport Block Designの生成 Projectの生成 bitstreamの生成 作業手順
  55. 55. VIVADO “Projectの生成 1/9” • VIVADOを起動する • [Create New Project] をクリック
  56. 56. VIVADO “Projectの生成2/9” • [Next]をクリック
  57. 57. VIVADO “Projectの生成3/9” • Project nameを任意のものに変更(自分はzynq_vivadohlsとした) • “Create project subdirectory”のcheckを外す • [Next]をクリック 1 2 3
  58. 58. VIVADO “Projectの生成4/9” • “RTL Project” を選択する • [Next]をクリック 2 1
  59. 59. VIVADO “Projectの生成5/9” • “Verilog”または”VHDL”を選択 • [Next]をクリック 2 1
  60. 60. VIVADO “Projectの生成6/9” • [Next]をクリック 1
  61. 61. VIVADO “Projectの生成7/9” • [Next]をクリック 1
  62. 62. VIVADO “Projectの生成8/9” Zed Boardの場合 • [Boards] を選択 • “ZedBoard”を選択 • [Next]をクリック Zyboの場合 • [Parts] を選択 • “xc7z010clg400-1”を選択 • [Next]をクリック 1 2 3
  63. 63. VIVADO “Projectの生成9/9” • 内容を確認して[Finish]をクリック • これでプロジェクトの生成が完了する 1
  64. 64. VIVADO起動完了
  65. 65. VIVADO “Block Designの生成1/3” • ここからIP IntegratorでBlock Designを生成していく • [Create Block Design] をクリック 1
  66. 66. VIVADO “Block Designの生成2/3” • 任意のDesign nameに変更して [OK]をクリック • これでBlock Designe の生成が完了する 1 2
  67. 67. VIVADO “Block Designの生成3/3” • Block Designが生成が完了した • 右側の”Diagram”部分でIPの追加、接続を行いデザインを作成していく
  68. 68. VIVADO “PSの追加1/3” • まずZYNQ PSを追加する • [Add IP] をクリック (Ctrl – i がショートカット) 1
  69. 69. VIVADO “PSの追加2/3” • Searchに“zynq”と入力して絞り込む • ”ZYNQ7 Processing System”を選択し[ENTER] 1 2
  70. 70. VIVADO “PSの追加3/3” • Processing Systemが追加された • 次はProcessing Systemの設定を行っていく
  71. 71. VIVADO “PSの設定1/7” • ZYNQを右クリックし、[Customize Block]を選択 (ZYNQをダブルクリックでも可) 1
  72. 72. VIVADO “PSの設定2/7” • [MIO Configuration] タブを選択クリック • [I/O Peripherals]を開く • [UART1] にチェックを入れ, MIO 48, 49が選択されていることを確認 2 1 3 3
  73. 73. VIVADO “PSの設定3/7” • [DDR Configuration] タブをクリック • [DDR Controller Configuration]を開く • ZedBoardの場合、Memory Partを”MT41J128M16 HA-15E”に変更 • ZYBOの場合、Memory Partを”MT41J128M16JT-125”に変更 1 2 3 ※ツールのバージョンによっては”MT41K128M16JT-125”
  74. 74. VIVADO “PSの設定4/7” • [Clock Configuration]タブを選択 • ZedBoardの場合、Input Frequencyを”33.333333”にする • Zyboの場合、Input Frequencyを”50”にする • [PL Fablic Clocks]タブを開く • FCLK_CLK0の周波数を”100”に設定する 1 2 3 4
  75. 75. VIVADO “PSの設定5/7” • [PS-PL Configuration]タブをクリック • [HP Slave AXI Interface]タブを開く • “S AXI HP0 interface”にチェックを入れる 1 2 3
  76. 76. VIVADO “PSの設定6/7” • [Interrupts]タブをクリック • [Fabric Interrupts]にチェックを入れて、タブを開く • [PL-PS Interrupt Ports]を開く • IRQ_F2P[15:0]にチェックを入れる • [OK]をクリック 1 2 3 4 5
  77. 77. VIVADO “PSの設定7/7” • 以上でPSの設定が完了した
  78. 78. VIVADO “PS入出力ポート作成1/3” • [Run Block Automation] をクリック 1
  79. 79. VIVADO “PS入出力ポート生成2/3” • [Apply Board Preset] のチェックを外す • [OK]をクリック 1 2
  80. 80. VIVADO “PS入出力ポート生成3/3” • PSの外部IOインターフェース(DDR, FIXED_IO)が生成された
  81. 81. VIVADO “HLS IPコアの追加1/7” • VIVADO HLSで作成したIPコアを追加していく • [IP Settings]をクリックする 1
  82. 82. VIVADO “HLS IPコアの追加2/7” • [Add Repository]をクリックする 1
  83. 83. VIVADO “HLS IPコアの追加3/7” • axihp_memcpy(VIVADO HLSのProjectディレクトリ)を選択 • [Select]をクリック 1 2
  84. 84. VIVADO “HLS IPコアの追加4/7” • “Axihp_memcpy”が追加されていることを確認 • [OK]をクリック 1 2
  85. 85. VIVADO “HLS IPコアの追加5/7” • “Axihp_memcpy”のimportが完了したのでIPを追加する • [Add IP]をクリックする 1
  86. 86. VIVADO “HLS IPコアの追加6/7” • “axihp”と入力して絞り込む • [Axihp_memcpy]を選択し[Enter]を押す 1 2
  87. 87. VIVADO “HLS IPコアの追加7/7” • “axihp_memcpy”IPコアの追加が完了した • 次は、PSと接続していく
  88. 88. VIVADO “HLS IPコアとPSの接続1/5” • axihp_memcpy IPコアとPSを接続していく • axihp_memcpyの”interrupt”とPSの”IRQ_F2P”を接続する 1 ドラッグでポート間を接続
  89. 89. VIVADO “HLS IPコアとPSの接続2/5” • AXIポートを接続していく • [Run Connection Automation]をクリックする 1
  90. 90. VIVADO “HLS IPコアとPSの接続3/5” • [All Automation]にチェックを入れる • [s_axi_AXILiteS]を選択する • [Clock Connection]を”FCLK_CLK0”に選択する 1 2 3
  91. 91. VIVADO “HLS IPコアとPSの接続4/5” • [S_AXI_HP0]を選択する • [Clock Connection]を”FCLK_CLK0”に選択する • [OK]をクリックする 1 2 3
  92. 92. VIVADO “HLS IPコアとPSの接続5/5” • axihp_memcpy IPコアとPSの接続が完了した • 次はAXIHPポートを監視するILAコアを追加していく
  93. 93. VIVADO 自動配線の結果 自動配線を行うとAXIポートが自動的に接続される 自動でリセットシステムが追加される インターコネクトが自動で挿入される • 複数マスタ、複数スレーブ間のスイッチとなる • 実はPS側のAMBAがAMBA4ではなくAMBA3となっている. PS側のAMBA3とIP側のAMBA4の緩衝材の働きもする
  94. 94. VIVADO “ILAコアの追加・接続1/6” • AXIHPポートを監視するためのILAコアを追加していく • [Add IP]をクリックする 1
  95. 95. VIVADO “ILAコアの追加・接続2/6” • “ila”と入力して絞り込む • [ILA]を選択して[Enter]を押す 1 2
  96. 96. VIVADO “ILAコアの追加・接続3/6” • ILAコアが追加された • AXIHPポートと接続していく
  97. 97. VIVADO “ILAコアの追加・接続4/6” • ILAの”clk”とPSの”FCLK_CLK0”を接続する 1
  98. 98. VIVADO “ILAコアの追加・接続5/6” • ILAの”SLOT_0_AXI”とaxihp_memcpyの ”m_axi_gmem64”を接続する 1
  99. 99. VIVADO “ILAコアの追加・接続6/6” • ILAコアの追加と接続が完了した • 以上でBlock Designでの設計は終了となる
  100. 100. VIVADO “Block Designエラーチェック” • [Validate Design]をクリックする • エラーが無いことを確認したら、デザインを保存する 1 2
  101. 101. VIVADO “Generate Block Design 1/3” • Block Designに含まれるIPに必要な制約、 デザインのネットリストを生成する • [Generate Block Design]をクリックする 1
  102. 102. VIVADO “Generate Block Design 2/3” • [Generate]をクリックする 1
  103. 103. VIVADO “Generate Block Design 3/3” • 終了したら[OK]をクリックする • Designの生成が完了した 1
  104. 104. VIVADO “HDL wrapperの生成1/3” • Block DesignのHDL wrapperを生成していく • [Sources]タブを選択する • [design_1]を右クリック • [Create HDL Wrapper]をクリックする 1 2 3
  105. 105. • [OK]を選択 VIVADO “HDL wrapperの生成2/3” 1
  106. 106. VIVADO “HDL wrapperの生成3/3” • “design_1_wrapper”ファイルが追加されていることを確認する • HDL wrapperの生成が完了した 1
  107. 107. VIVADO “SDK Export1/2” • Hardwareの情報をSDKにExportする • [File]をクリック • [Export] => [Export Hardware]をクリック 1 2
  108. 108. • [OK] をクリック • Exportが完了したらBitstreamを生成する VIVADO “SDK Export2/2” 1
  109. 109. VIVADO “Generate Bitstream1/2” • bitファイルを生成する • [Generate Bitstream]をクリックする 1
  110. 110. VIVADO “Generate Bitstream2/2” • 完了したら[Cancel]をクリックする • 以上でVIVADOでの実装は終了となる • 次はSDKでソフトウェアを実装していく 1
  111. 111. SDK Board Suppot Packageの生成 Application Projectの生成 ソフトウェア(polling)の実装 作業手順 アプリケーション実行1 interrupt制御プログラムの追加 アプリケーション実行2
  112. 112. SDK “SDKの起動1/2” • SDKを起動する (linuxの場合 “xsdk” コマンドで起動) • VIVADOは”project_dir/project_name.sdk”にHardware情報を Exportしている • Workspaceは”zynq_vivadohls/zynq_vivadohls.sdk”を選択する • [OK]をクリック 1 2
  113. 113. SDK “SDKの起動2/2” • SDKの起動が完了した • design_1_wrapper_hw_platform_0内にExportされた hardware情報やPSの設定スクリプトがある (バージョンが2014. 2の場合、hardware Platform Specificationを自分で作成する必要あり)
  114. 114. SDK “Board Support Packageの生成1/4” • [New]をクリック • [Xilinx]タブを開く • [Board Support Package]を選択 • [Next]をクリックする 1 2 3 4
  115. 115. • Project nameに任意の名前を入力(自分は”standalone_bsp_0”を使用) • [Finish]をクリック SDK “Board Support Packageの生成2/4” 1 2
  116. 116. • [OK]をクリック SDK “Board Support Packageの生成3/4” 1
  117. 117. SDK “Board Support Packageの生成4/4” • Board Support Packageが生成された • standalone_bsp_0内にはxilinxが提供するlibraryや hardwareのアドレスを定義したヘッダーファイル等がある
  118. 118. SDK “Application Projectの生成1/4” • [New]をクリック • [Xilinx]タブを開く • [Application Project]を選択 • [Next]をクリック 1 2 3 4
  119. 119. • Project nameを”axihp_memcpy”にする • [Use existing] をチェックをする • [Next]をクリック SDK “Application Projectの生成2/4” 1 2 3
  120. 120. • [Empty Application] を選択 • [Finish]をクリック SDK “Application Projectの生成3/4” 1 2
  121. 121. SDK “Application Projectの生成4/4” • Application Projectが生成された
  122. 122. SDK “Fileの生成1/3” • [axihp_memcpy]タブを開く • [src]を右クリックする • [New] => [File]をクリックする 1 2 3
  123. 123. SDK “Fileの生成2/3” • File nameを”axihp_memcpy.c”とする • [Finish]をクリックする 2 1
  124. 124. SDK “Fileの生成3/3” • “axihp_memcpy.c”ファイルが生成された • C言語でソフトウェアを実装していく
  125. 125. SDK “HLS コア 制御アプリケーション雛型” #include "xil_printf.h" typedef unsigned long long u64; int main() { int i, mismatch = 0; volatile u64 src_data[256], dst_data[256]; for (i = 0; i < 256; i++) src_data[i] = i; //create source data //control hls core for (i = 0; i < 256; i++) { xil_printf("src_data[%d] = %d, ", i, src_data[i]); xil_printf("dst_data[%d] = %dnr", i, dst_data[i]); if (src_data[i] != dst_data[i]) mismatch = 1; //compare src_data and dst_data } (mismatch == 0) ? xil_printf("memcpy success!nr"): xil_printf("memcpy failnr"); return 0; } • axihp_memcpyコアにsrc_dataの値をdst_dataにコピーさせる • 以降、この雛型に赤文字で書かれたプログラムを追加していく
  126. 126. SDK “キャッシュの無効化” #include "xil_cache.h" … int main() { Xil_DCacheDisable(); //Disable Data Cache … return 0; } • xil_cache.h内で定義されているXil_DCacheDisable関数を使うと データキャッシュをオフにすることができる • DMAを正しく実行するにはflushおよびinvalidateを適切に行う必要 がある.簡単のため、今回はキャッシュを無効化する
  127. 127. SDK “axihp_memcpyコアのレジスタ構成1/2” • standalone_bsp_0/ps_cortexa9_0/include内の “axihp_memcpy_hw.h”を開く • ファイル内にレジスタのmapが記述されている
  128. 128. SDK “axihp_memcpyコアのレジスタ構成2/2” 0x00 Control signals 0x04 Global Interrupt Enable 0x08 IP Interrupt Enable 0x0c IP Interrupt Status 0x10 Data signal of axihp_in 0x14 reserved 0x18 Data signal of axihp_out 0x1c reserved 読み出しアドレス 書き込みアドレス • bit0: ap_start • bit1: ap_done • bit2: ap_idle • bit3: ap_ready • bit7: auto_restart • others: reserved axihp_memcpyレジスタ(32bit)
  129. 129. SDK “axihp_memcpyアドレスの確認” • standalone_bsp_0/ps_cortexa9_0/include内の “xparameters.h”に記述されている • アドレスは0x43c00000で、次のように定義されている “XPAR_AXIHP_MEMCPY_0_S_AXI_AXILITES_BASEADDR”
  130. 130. SDK “読み出し/書き込みアドレスの設定” … unsigned int *baseaddr = 0x43c00000; //reg0 of hls core int main() { … //control hls core baseaddr[4] = src_data; //set read addr baseaddr[6] = dst_data; //set write addr … } • 0x43c00000番地がaxihp_memcpyのレジスタ0の番地となる
  131. 131. SDK “axihp_memcpyの開始制御” … int main() { … //control hls core baseaddr[4] = src_data; //set read addr baseaddr[6] = dst_data; //set write addr if ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is high xil_printf("memcpy startnr"); baseaddr[0] |= 0x1; //make ap_start high } … } • ap_idleが1であればap_startを1にして開始する
  132. 132. SDK “axihp_memcpyの終了制御(polling版)” … int main() { … //control hls core … if ((baseaddr[0] & 0x4) == 0x4) {//if ap_idle is high xil_printf("memcpy startnr"); baseaddr[0] |= 0x1; //make ap_start high } while ((base_addr[0] & 0x4) == 0); //wait for memcpy(polling) xil_printf("memcpy done!nr"); … } • ap_idleが再び1になるまでwhile文で待機する
  133. 133. SDK “axihp_memcpyソフトウェア” #include "xil_cache.h" #include "xil_printf.h" typedef unsigned long long u64; unsigned int *baseaddr = 0x43c00000;//reg0 of hls core int main() { Xil_DCacheDisable(); //Disable Data Cache int i, mismatch = 0; volatile u64 src_data[256], dst_data[256]; for (i = 0; i < 256; i++) src_data[i] = i; //create source data //control hls core baseaddr[4] = src_data; //set read addr baseaddr[6] = dst_data; //set write addr if ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is high xil_printf("memcpy startnr"); baseaddr[0] |= 0x1; //make ap_start high } while ((baseaddr[0] & 0x4) == 0); //wait for memcpy(polling) xil_printf("memcpy done!nr"); for (i = 0; i < 256; i++) { xil_printf("src_data[%d] = %d, ", i, src_data[i]); xil_printf("dst_data[%d] = %dnr", i, dst_data[i]); if (src_data[i] != dst_data[i]) mismatch = 1; //compare src_data and dst_data } (mismatch == 0) ? xil_printf("memcpy success!nr"): xil_printf("memcpy failnr"); return 0; } プログラム全体は以下のようになる
  134. 134. SDK “ソフトウェアのコンパイル1/2” • [Build ALL]をクリックする • デフォルトでは保存する度に自動でBuildされる 1
  135. 135. SDK “ソフトウェアのコンパイル2/2” • 実行ファイル(.elf)が生成された 同一
  136. 136. SDK “FPGAのコンフィグレーション1/2” • ソフトウェア実装が終わったので実行手順に移る • まずFPGAに回路をダウンロードしていく • [Program FPGA]をクリックする 1
  137. 137. SDK “FPGAのコンフィグレーション2/2” • Bitstreamを ”...zynq_vivadohls/zynq_vivadohls.run/impl_1/design_1_wrapper.bit” と選択する • [Program]をクリックする 1 2
  138. 138. SDK “アプリケーション実行の前に” • アプリケーションの実行結果はuartで出力される • SDK上で結果を確認することもできるが、不具合が多い(linuxの場合) したがってscreen, cuコマンドやminicomでシリアルポートに接続する >ls /dev/ttyACM* ttyACMx >sudo chmod 666 /dev/ttyACMx >cu -s 115200 -l /dev/ttyACMx cuコマンドの例(ZedBoardの場合) >ls /dev/ttyACM* ttyACMx >sudo chmod 666 /dev/ttyACMx >screen /dev/ttyACMx 115200 screenコマンドの例(ZedBoardの場合)
  139. 139. SDK “アプリケーションの実行1/3” • [Debug]タブを開く • [axihp_memcpy.elf]を右クリック • [Run As] => [Run Configuration]をクリック 1 2 3
  140. 140. • [Xilinx C/C++ application (GDB)] を右クリック • [New]をクリックする 1 2 SDK “アプリケーションの実行2/3”
  141. 141. SDK “アプリケーションの実行3/3” • [Run]をクリックすると実行される 1
  142. 142. SDK "実行結果" 無事に一致しましたか?(^^)
  143. 143. SDK "二回目以降の実行" • [Run]の右側の下矢印をクリック • [axihp_memcpy_Debug]をクリックで実行できる 1 2
  144. 144. SDK "Debugモード" • [Debug]の右側の下矢印をクリック • [axihp_memcpy_Debug]をクリックでDebugモードで実行 1 2
  145. 145. SDK "割り込みプログラム1/4" #include "xparameters.h" #include "xscugic_hw.h" #include "xil_exception.h" … int main() { … //control hls core unsigned int device_id = 0; XScuGic_DeviceInitialize(device_id); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, XScuGic_DeviceInterruptHandler, device_id); Xil_ExceptionEnable(); XScuGic_RegisterHandler(XPAR_PS7_SCUGIC_0_BASEADDR, 61, axihp_memcpy_handler, NULL); baseaddr[2] |= 0x1; baseaddr[1] = 0x1; XScuGic_EnableIntr(XPAR_PS7_SCUGIC_0_DIST_BASEADDR, 61); … }
  146. 146. SDK "割り込みプログラム2/4" #include "xparameters.h" #include "xscugic_hw.h" #include "xil_exception.h" … volatile int memcpy_done = 0; void axihp_memcpy_handler(); int main() { … //while ((baseaddr[0] & 0x4) == 0); //wait for memcpy while (memcpy_done == 0); //wait for interrupt … } void axihp_memcpy_handler() { baseaddr[2] ^= 0x1; xil_printf("interrupt!nr"); memcpy_done = 1; baseaddr[3] = 0x1; baseaddr[2] |= 0x1; }
  147. 147. SDK "割り込みプログラム3/4" ...zynq_vivadohls.sdk/standalone_bsp_0/ps7_cortexa9_0/libsrc/ scugic_v2_1/src/xscugic_hw.c 上記ファイル内にXScuGic_DeviceInterruptHangler関数が記述されてる 注意! キャストされていないので引数にはポインタではなく値をいれる
  148. 148. SDK "割り込みプログラム4/4" #include "xparameters.h" #include "xscugic_hw.h" #include "xil_exception.h" #include "xil_cache.h" #include "xil_printf.h" typedef unsigned long long u64; unsigned int *baseaddr = 0x43c00000;//reg0 of hls core volatile int memcpy_done = 0; void axihp_memcpy_handler(); int main() { Xil_DCacheDisable(); //Disable Data Cache int i, mismatch = 0; volatile u64 src_data[256], dst_data[256]; for (i = 0; i < 256; i++) src_data[i] = i; //create source data //control hls core unsigned int device_id = 0; XScuGic_DeviceInitialize(device_id); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, XScuGic_DeviceInterruptHandler, device_id); Xil_ExceptionEnable(); XScuGic_RegisterHandler(XPAR_PS7_SCUGIC_0_BASEADDR, 61, axihp_memcpy_handler, NULL); baseaddr[2] |= 0x1; baseaddr[1] = 0x1; XScuGic_EnableIntr(XPAR_PS7_SCUGIC_0_DIST_BASEADDR, 61); baseaddr[4] = src_data; //set read addr baseaddr[6] = dst_data; //set write addr if ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is high xil_printf("memcpy startnr"); baseaddr[0] |= 0x1; //make ap_start high } //while ((baseaddr[0] & 0x4) == 0); //wait for memcpy(poling) while (memcpy_done == 0); //wait for interrupt xil_printf("memcpy done!nr"); for (i = 0; i < 256; i++) { xil_printf("src_data[%d] = %d, ", i, src_data[i]); xil_printf("dst_data[%d] = %dnr", i, dst_data[i]); if (src_data[i] != dst_data[i]) mismatch = 1; //compare src_data and dst_data } (mismatch == 0) ? xil_printf("memcpy success!nr"): xil_printf("memcpy failnr"); return 0; } void axihp_memcpy_handler() { baseaddr[2] ^= 0x1; xil_printf("interrupt!nr"); memcpy_done = 1; baseaddr[3] = 0x1; baseaddr[2] |= 0x1; } プログラム全体は以下のようになる
  149. 149. VIVADO Logic Analyzer Harware Managerの起動 現在の波形をキャプチャ トリガをかけてキャプチャ 作業手順
  150. 150. VIVADO "Hardware Manager の起動1/6" • [Open Hardware Manager]タブを開く • [Open Target]をクリック • [Open New Target]をクリック 1 2 3
  151. 151. VIVADO "Hardware Manager の起動2/6" • [Next]をクリック 1
  152. 152. VIVADO "Hardware Manager の起動3/6" • [Next]をクリック 1
  153. 153. VIVADO "Hardware Manager の起動4/6" • [Next]をクリック 1
  154. 154. VIVADO "Hardware Manager の起動5/6" • [Finish]をクリック 1
  155. 155. VIVADO "Hardware Manager の起動6/6" • Hardware Managerが起動した
  156. 156. VIVADO "FPGAのコンフィグレーション1/2" • FPGAのコンフィグレーションがまだの場合、 ここでコンフィグレーションを行う • "xc7z020_1"を右クリック • [Program Device]をクリック 1 2
  157. 157. VIVADO "FPGAのコンフィグレーション2/2" • [Program]をクリックするとコンフィグレーションが実行される 1
  158. 158. 寄り道 "CLKが出力されない1/6" • ZYNQの電源を入れた直後に、ILAを含むデザインを コンフィグレーションするとワーニングがでる上にILAの 操作画面が出てこない • これはZYNQからCLKがまだ出力されていないことが原因 • CLK出力後に[Refresh device]をクリックすると解決される
  159. 159. 寄り道 "CLKが出力されない2/6" • 実はコンフィグレーションが完了した段階ではZYNQから クロックは出力されない • では、どのタイミングでクロックが出力されるのか? • ネットで検索すると、"ARM上でアプリケーションを実行する" とクロックが出力されるという情報が多く出てくるが 正しい条件は "ps7_init_config, ps7_post_configを実行する"である
  160. 160. 寄り道 "CLKが出力されない3/6" • 普通ps7_init_config, ps7_post_configはアプリケーション 実行前に実行される
  161. 161. 寄り道 "CLKが出力されない4/6" • しかし実行できないときがある
  162. 162. 寄り道 "CLKが出力されない5/6" • AXIポートが何も使用されていないとps7_post_configが実行されない
  163. 163. 寄り道 "CLKが出力されない6/6" XMD% connect arm hw XMD% rst –slcr XMD% cd "project_name".sdk/designe_1_wrapper_hw_platform_0 XMD% source ps7_init.tcl XMD% ps7_init XMD% ps7_post_config XMD% disconnect 64 • SDKのxmdコンソールでps7_post_configを実行する方法
  164. 164. VIVADO "現在の波形をキャプチャする1/2" • [Run trigger immediate for this ILA core]をクリックする 1
  165. 165. VIVADO "現在の波形をキャプチャする2/2" • 現在の波形がキャプチャされた • 次はトリガを設定し、狙ったタイミングでキャプチャする
  166. 166. VIVADO "トリガをかけてキャプチャ1/6" • バースト受信の開始時にトリガをかける • ARVALIDがHighになったらトリガがかかるように設定していく • Debug Probes内にある"ARVALID"信号を右クリック • [Add Probes to Basic Trigger Setup]をクリック 2 1
  167. 167. VIVADO "トリガをかけてキャプチャ2/6" • Basic Trigger Setup にARVALID信号が追加される • [Compare Value]タブを開く • [Value]を"1"に設定する 2 1
  168. 168. VIVADO "トリガをかけてキャプチャ3/6" • キャプチャを開始する • [Run trigger for this ILA core]をクリックする 1
  169. 169. VIVADO "トリガをかけてキャプチャ4/6" • トリガ待ちの状態になる
  170. 170. VIVADO "トリガをかけてキャプチャ5/6" • SDKでアプリケーションを実行し、AXI転送を行う 1 2
  171. 171. VIVADO "トリガをかけてキャプチャ6/6" • VIVADOに戻ってくるとARVALIDがHighになった 直後からキャプチャされている
  172. 172. VIVADO "AXI転送時の波形"
  173. 173. Next Step "RTLでAXI State Machine書きたい!!1/5" • AXIの雛型の作り方 • VIVADOのProject Setteingsで"Vendor"を設定する
  174. 174. Next Step "RTLでAXI State Machine書きたい!!2/5" • [Tools] => [Create and Package IP]をクリック
  175. 175. Next Step "RTLでAXI State Machine書きたい!!3/5" • [Create a new AXI4 peripheral]を選択
  176. 176. Next Step "RTLでAXI State Machine書きたい!!4/5" • 必要なAXIポートを備えたIPを作成
  177. 177. Next Step "RTLでAXI State Machine書きたい!!5/5" "…/zynq_vivadohls/../ip_repo/"ip名"/hdl/"に生成したIPの ソースファイルが格納されている AXIステートマシンが記述されているので、このファイルを改造 していくのが良いと思われる DigilentのZYBOのチュートリアル前半部分が似たような内容になっている (http://digilentinc.com/Data/Products/ZYBO/ZYBO-Embedded_Linux_Hands-on_Tutorial.pdf)

×