zynq + vivado hls入門

177
ZYNQ + Vivado HLS入門 慶應義塾大学 天野研究室 修士1年 杉本

Upload: narusugimoto

Post on 15-Jul-2015

3.593 views

Category:

Devices & Hardware


5 download

TRANSCRIPT

Page 1: Zynq + Vivado HLS入門

ZYNQ + Vivado HLS入門

慶應義塾大学 天野研究室

修士1年 杉本 成

Page 2: Zynq + Vivado HLS入門

内容

• 対象はこれからZYNQを使ってみたい方

• 実習形式で進めていく

• ZYNQのCPU⇔FPGA間のデータ転送方法、共有方法をレクチャー

• VIVADO HLS, VIVADO IP Integratorを利用して手軽に実装

• RTLは1行も書かない

Page 3: Zynq + Vivado HLS入門

目次

• 基礎説明 ZYNQ構成 AXIとは ZYNQ内のAXI経路 VIVADOの特徴

• 実習内容の説明 目標とするデザイン ツールの説明 ツールフロー

• 実習 VIVADO HLSでmemcpyコアを実装 VIVADO IP integraterでIPコアを接続 SDKでソフトウェアを実装、実行 VIVADO Logic AnalyzerでAXI通信を観察

Page 4: Zynq + Vivado HLS入門

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

Page 5: Zynq + Vivado HLS入門

ZYNQ アドレスマップ

システムレベルのアドレスマップ *UG585 P103より引用

• 各機能にアクセスする際に使用するアドレス一覧

Page 6: Zynq + Vivado HLS入門

AXIとは

• ARM® AMBA インターフェースのこと※AXI4はAMBA第4世代インターフェース

• MasterとSlaveが1対1で通信を行う• スイッチを介すことで、複数Masterと複数Slaveを

繋げることもできる.(しかし通信は1対1)• Slaveはレジスタもしくはメモリを持っていて、

Masterはアドレスを指定してデータの読み書きを行う

MS

0x00000000

0x0000ffff

Page 7: Zynq + Vivado HLS入門

AXI4 バースト転送

MS

0x00000000

0x0000ffff

D0

D1

D2

D3

D4

D5

D6

D7

• AXI4は指定したアドレスから連続してデータを(毎サイクル)読み出し/書き込みできる

• 指定したアドレスからインクリメント、指定したアドレスから連続して等の設定ができる

• バースト長は最大256である

AXI4 バースト読み出しの例

Page 8: Zynq + Vivado HLS入門

AXIの種類

• AXI: 普通のAXI• AXILite: AXIの軽量版、バースト転送ができない• AXIstream: アドレスの概念を消したストリーム用

Page 9: Zynq + Vivado HLS入門

ZYNQ IOPへのアクセス

S M APU ⇔ IOP間 Master => APU Slave => IOP

IOPのレジスタ設定、入出力データの送受信に使用

Page 10: Zynq + Vivado HLS入門

ZYNQ AXIGP(Slave)

S

M APU ⇔ AXIGP(Slave)間 Master => CPU Slave => AXIGP

データ幅は32bit

Page 11: Zynq + Vivado HLS入門

ZYNQ AXIGP(Master)

S

M

APU ⇔ AXIGP(Slave)間 Master => AXIGP Slave => DDR

データ幅は32bit

Page 12: Zynq + Vivado HLS入門

ZYNQ DMAエンジン

S

M

DMA ⇔ DDR間 Master => DMA Slave => DDR

DMA ⇔ AXIGP(Slave)間 Master => DMA Slave => AXIGPS

Page 13: Zynq + Vivado HLS入門

ZYNQ AXIHP

S

M

AXIHP ⇔ DDR間 Master => AXIHP Slave => DDR

データ幅は32/64bit

Page 14: Zynq + Vivado HLS入門

ZYNQ ACP

S

M

AXIACP ⇔ APU間 Master => AXIACP Slave => APU

データ幅は64bit

Page 15: Zynq + Vivado HLS入門

VIVADO IP Integrator

• ISE => XPS

Page 16: Zynq + Vivado HLS入門

VIVADO Logic Analyzer

• ISE => Chip Scope

Page 17: Zynq + Vivado HLS入門

ZYNQ

目標とするデザイン

PS

APU

DDR Controler

AXIHP_MEMCPY(created by VIVADO HLS)

inte

rrupt

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

Page 18: Zynq + Vivado HLS入門

ツールフロー

AXIHP_MEMCPY関数のC記述

AXIHP_MEMCPY関数のDirective設定

AXIHP_MEMCPYのIP化

PSの設定

PSとAXIHP_MEMCPYの接続

bitstreamの生成

ソフトウェアの実装、実行

VIVADO HLS

VIVADO

SDK

VIVADO + SDK

使用するツール手順

波形のキャプチャ

Page 19: Zynq + Vivado HLS入門

環境

• Vivado 2014.4を対象としている(2014.2以降なら同様のことが可能)

• Zed Board、ZYBOを想定

• zynq_vivadohlsディレクトリで作業する

Page 20: Zynq + Vivado HLS入門

VIVADO HLS

AXIHP_MEMCPY関数のC記述

AXIHP_MEMCPY関数のDirective設定

AXIHP_MEMCPYのIP化

Projectの生成

AXIHP_MEMCPYの合成

作業手順

Page 21: Zynq + Vivado HLS入門

VIVADO HLS "AXIHP MEMCPYコア"

AXIHP_MEMCPY(created by VIVADO HLS)

interruptclk

reset

AXILite AXIMS32bit 64bit

Page 22: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成1/7”

• vivado_hlsを起動する• [Create New Project]をクリック

1

Page 23: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成2/7”

• 任意のProject nameを入力 (自分は”axihp_memcpy”とした)• “Location”は任意(自分はzynq_vivadohlsディレクトリにした)• [Next]をクリック

1

2

3

Page 24: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成3/7”

• Top Functionを”axihp_memcpy”とする(対象とする関数の関数名)• [Next] をクリック

1

2

Page 25: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成4/7”

• [Next] を選択(今回シミュレーションは行わないので何も加えない)

1

Page 26: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成5/7”

• Part Selectionのタブを開く

1

Page 27: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成6/7”

ZedBoardの場合• [Boards]タブを選択• “ZedBoard”を選択する• [OK]をクリックする

1

2

3

Zyboの場合• [Parts]タブを選択• “xc7z010clg400-1を選択する• [OK]をクリックする

Page 28: Zynq + Vivado HLS入門

VIVADO HLS “Projectの生成7/7”

• [Finish]をクリックする

1

Page 29: Zynq + Vivado HLS入門

VIVADO HLS 起動完了

• Projectの生成が完了した

Page 30: Zynq + Vivado HLS入門

VIVADO HLS “Fileの作成1/3”

• [Source]を右クリックする• [New File]をクリックする

12

Page 31: Zynq + Vivado HLS入門

VIVADO HLS “Fileの作成2/3”• File名を”axihp_memcpy.c”とする• 保存先は”zynq_vivadohls/axihp_memcpy/.apc”とする• [OK]をクリック

12

3

Page 32: Zynq + Vivado HLS入門

VIVADO HLS “Fileの生成3/3”

• [Source]タブの中に”axihp_memcpy.c”が作成された• このファイルにaxihp_memcpyを記述していく

Page 33: Zynq + Vivado HLS入門

VIVADO HLS “axihp_memcpyの実装1/4”

void axihp_memcpy();

void axihp_memcpy(){

}

• void型のaxihp_memcpy関数を記述する

Page 34: Zynq + Vivado HLS入門

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”に置き換える

Page 35: Zynq + Vivado HLS入門

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; とすると通常転送の読み出しとなる

Page 36: Zynq + Vivado HLS入門

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]; とすると通常転送の書き込みとなる

Page 37: Zynq + Vivado HLS入門

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]で設定していく

Page 38: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定1/10”

• [Directive]タブをクリックする

1

Page 39: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定2/10”

• 引数”axihp_in”をaxiポートのmasterとなるように設定していく• [axihp_in]を右クリックする• [Insert Directive]をクリックする

21

Page 40: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定3/10”

• [Directive]のプルダウンメニューを”INTERFACE”にする• [mode]のプルダウンメニューを”m_axi”にする• [offset]のプルダウンメニューを”slave”にする• [OK]をクリック

1

2

3

4

この設定を”slave”にすると読み出しアドレスを、slaveポートから指定できるようになる

“axihp_in”はaxiのmasterポートと認識されるようになる

Page 41: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定4/10”

• 引数“axihp_in”の設定が完了した• 設定した内容は[axihp_in]の下に表示される

Page 42: Zynq + Vivado HLS入門

VIVADO HLS ”Directive設定5/10”

• 引数”axihp_out”も同様に設定していく• [axihp_out]を右クリックする• [Insert Directive]をクリックする

21

Page 43: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定6/10”

• [Directive]のプルダウンメニューを”INTERFACE”にする• [mode]のプルダウンメニューを”m_axi”にする• [offset]のプルダウンメニューを”slave”にする• [OK]をクリック

1

2

3

4

この設定を”slave”にすると読み出しアドレスを、slaveポートから指定できるようになる

“axihp_out”はaxiのmasterポートと認識されるようになる

Page 44: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定7/10”

• 引数”axihp_out”の設定が完了した• 次は関数axihp_memcpyの制御方法の設定を行っていく

Page 45: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定8/10”

• 関数axihp_memcpyの制御方法を設定していく• [axihp_memcpy]を右クリックする• [Insert Directive]をクリックする

21

Page 46: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定9/10”

• [Directive]のプルダウンメニューを”INTERFACE”にする• [mode]のプルダウンメニューを”s_axilite”にする• [OK]をクリック

1

2

3

この設定により“axihp_memcpy”はaxi slaveポートから制御される.また終了を知らせるinterrupt信号も生成される.

Page 47: Zynq + Vivado HLS入門

VIVADO HLS “Directive設定10/10”

• 以上でDirectiveの設定が完了した

Page 48: Zynq + Vivado HLS入門

VIVADO HLS “Synthesis1/3”

• Synthesisを行っていく• [C Synthesis]をクリックする

1

Page 49: Zynq + Vivado HLS入門

VIVADO HLS “Synthesis2/3”

• Synthesisが完了した

Page 50: Zynq + Vivado HLS入門

VIVADO HLS “Synthesis3/3”

• 生成されるポート一覧

Slave AXIポート(AXILite)

Master AXIポート(AXI)

Page 51: Zynq + Vivado HLS入門

VIVADO HLS “IP Packageing1/3”

• axihp_memcpyをIPパッケージ化していく• [Export RTL]をクリックする

1

Page 52: Zynq + Vivado HLS入門

VIVADO HLS “IP Packaging 2/3”

• “Verilog”または”VHDL”を選択• [OK]をクリックする

1

2

Page 53: Zynq + Vivado HLS入門

VIVADO HLS “IP Packaging 3/3”

• IPパッケージ化が完了した• 以上でVIVADO HLSによる操作は終了となる

Page 54: Zynq + Vivado HLS入門

VIVADO

PSの設定

PSとAXIHP_MEMCPYの接続

HardwareのExport

Block Designの生成

Projectの生成

bitstreamの生成

作業手順

Page 55: Zynq + Vivado HLS入門

VIVADO “Projectの生成 1/9”

• VIVADOを起動する• [Create New Project] をクリック

Page 56: Zynq + Vivado HLS入門

VIVADO “Projectの生成2/9”

• [Next]をクリック

Page 57: Zynq + Vivado HLS入門

VIVADO “Projectの生成3/9”

• Project nameを任意のものに変更(自分はzynq_vivadohlsとした)• “Create project subdirectory”のcheckを外す• [Next]をクリック

1

2

3

Page 58: Zynq + Vivado HLS入門

VIVADO “Projectの生成4/9”

• “RTL Project” を選択する• [Next]をクリック

2

1

Page 59: Zynq + Vivado HLS入門

VIVADO “Projectの生成5/9”

• “Verilog”または”VHDL”を選択• [Next]をクリック

2

1

Page 60: Zynq + Vivado HLS入門

VIVADO “Projectの生成6/9”

• [Next]をクリック

1

Page 61: Zynq + Vivado HLS入門

VIVADO “Projectの生成7/9”

• [Next]をクリック

1

Page 62: Zynq + Vivado HLS入門

VIVADO “Projectの生成8/9”Zed Boardの場合• [Boards] を選択• “ZedBoard”を選択• [Next]をクリック

Zyboの場合• [Parts] を選択• “xc7z010clg400-1”を選択• [Next]をクリック

1

2

3

Page 63: Zynq + Vivado HLS入門

VIVADO “Projectの生成9/9”

• 内容を確認して[Finish]をクリック• これでプロジェクトの生成が完了する

1

Page 64: Zynq + Vivado HLS入門

VIVADO起動完了

Page 65: Zynq + Vivado HLS入門

VIVADO “Block Designの生成1/3”

• ここからIP IntegratorでBlock Designを生成していく• [Create Block Design] をクリック

1

Page 66: Zynq + Vivado HLS入門

VIVADO “Block Designの生成2/3”

• 任意のDesign nameに変更して [OK]をクリック• これでBlock Designe の生成が完了する

1

2

Page 67: Zynq + Vivado HLS入門

VIVADO “Block Designの生成3/3”

• Block Designが生成が完了した• 右側の”Diagram”部分でIPの追加、接続を行いデザインを作成していく

Page 68: Zynq + Vivado HLS入門

VIVADO “PSの追加1/3”• まずZYNQ PSを追加する• [Add IP] をクリック (Ctrl – i がショートカット)

1

Page 69: Zynq + Vivado HLS入門

VIVADO “PSの追加2/3”

• Searchに“zynq”と入力して絞り込む• ”ZYNQ7 Processing System”を選択し[ENTER]

1

2

Page 70: Zynq + Vivado HLS入門

VIVADO “PSの追加3/3”

• Processing Systemが追加された• 次はProcessing Systemの設定を行っていく

Page 71: Zynq + Vivado HLS入門

VIVADO “PSの設定1/7”

• ZYNQを右クリックし、[Customize Block]を選択(ZYNQをダブルクリックでも可)

1

Page 72: Zynq + Vivado HLS入門

VIVADO “PSの設定2/7”• [MIO Configuration] タブを選択クリック• [I/O Peripherals]を開く• [UART1] にチェックを入れ, MIO 48, 49が選択されていることを確認

2

1

3

3

Page 73: Zynq + Vivado HLS入門

VIVADO “PSの設定3/7”• [DDR Configuration] タブをクリック• [DDR Controller Configuration]を開く• ZedBoardの場合、Memory Partを”MT41J128M16 HA-15E”に変更• ZYBOの場合、Memory Partを”MT41J128M16JT-125”に変更

1

23

※ツールのバージョンによっては”MT41K128M16JT-125”

Page 74: Zynq + Vivado HLS入門

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

Page 75: Zynq + Vivado HLS入門

VIVADO “PSの設定5/7”

• [PS-PL Configuration]タブをクリック• [HP Slave AXI Interface]タブを開く• “S AXI HP0 interface”にチェックを入れる

1

2

3

Page 76: Zynq + Vivado HLS入門

VIVADO “PSの設定6/7”• [Interrupts]タブをクリック• [Fabric Interrupts]にチェックを入れて、タブを開く• [PL-PS Interrupt Ports]を開く• IRQ_F2P[15:0]にチェックを入れる• [OK]をクリック

1

2

34

5

Page 77: Zynq + Vivado HLS入門

VIVADO “PSの設定7/7”

• 以上でPSの設定が完了した

Page 78: Zynq + Vivado HLS入門

VIVADO “PS入出力ポート作成1/3”

• [Run Block Automation] をクリック

1

Page 79: Zynq + Vivado HLS入門

VIVADO “PS入出力ポート生成2/3”

• [Apply Board Preset] のチェックを外す• [OK]をクリック

1

2

Page 80: Zynq + Vivado HLS入門

VIVADO “PS入出力ポート生成3/3”

• PSの外部IOインターフェース(DDR, FIXED_IO)が生成された

Page 81: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加1/7”

• VIVADO HLSで作成したIPコアを追加していく• [IP Settings]をクリックする

1

Page 82: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加2/7”

• [Add Repository]をクリックする

1

Page 83: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加3/7”

• axihp_memcpy(VIVADO HLSのProjectディレクトリ)を選択• [Select]をクリック

1

2

Page 84: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加4/7”

• “Axihp_memcpy”が追加されていることを確認• [OK]をクリック

1

2

Page 85: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加5/7”

• “Axihp_memcpy”のimportが完了したのでIPを追加する• [Add IP]をクリックする

1

Page 86: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加6/7”

• “axihp”と入力して絞り込む• [Axihp_memcpy]を選択し[Enter]を押す

1

2

Page 87: Zynq + Vivado HLS入門

VIVADO “HLS IPコアの追加7/7”

• “axihp_memcpy”IPコアの追加が完了した• 次は、PSと接続していく

Page 88: Zynq + Vivado HLS入門

VIVADO “HLS IPコアとPSの接続1/5”

• axihp_memcpy IPコアとPSを接続していく• axihp_memcpyの”interrupt”とPSの”IRQ_F2P”を接続する

1

ドラッグでポート間を接続

Page 89: Zynq + Vivado HLS入門

VIVADO “HLS IPコアとPSの接続2/5”

• AXIポートを接続していく• [Run Connection Automation]をクリックする

1

Page 90: Zynq + Vivado HLS入門

VIVADO “HLS IPコアとPSの接続3/5”

• [All Automation]にチェックを入れる• [s_axi_AXILiteS]を選択する• [Clock Connection]を”FCLK_CLK0”に選択する

12

3

Page 91: Zynq + Vivado HLS入門

VIVADO “HLS IPコアとPSの接続4/5”

• [S_AXI_HP0]を選択する• [Clock Connection]を”FCLK_CLK0”に選択する• [OK]をクリックする

1

2

3

Page 92: Zynq + Vivado HLS入門

VIVADO “HLS IPコアとPSの接続5/5”

• axihp_memcpy IPコアとPSの接続が完了した• 次はAXIHPポートを監視するILAコアを追加していく

Page 93: Zynq + Vivado HLS入門

VIVADO 自動配線の結果自動配線を行うとAXIポートが自動的に接続される

自動でリセットシステムが追加される

インターコネクトが自動で挿入される• 複数マスタ、複数スレーブ間のスイッチとなる• 実はPS側のAMBAがAMBA4ではなくAMBA3となっている.

PS側のAMBA3とIP側のAMBA4の緩衝材の働きもする

Page 94: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続1/6”

• AXIHPポートを監視するためのILAコアを追加していく• [Add IP]をクリックする

1

Page 95: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続2/6”

• “ila”と入力して絞り込む• [ILA]を選択して[Enter]を押す

1

Page 96: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続3/6”

• ILAコアが追加された• AXIHPポートと接続していく

Page 97: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続4/6”

• ILAの”clk”とPSの”FCLK_CLK0”を接続する

1

Page 98: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続5/6”

• ILAの”SLOT_0_AXI”とaxihp_memcpyの”m_axi_gmem64”を接続する

1

Page 99: Zynq + Vivado HLS入門

VIVADO “ILAコアの追加・接続6/6”

• ILAコアの追加と接続が完了した• 以上でBlock Designでの設計は終了となる

Page 100: Zynq + Vivado HLS入門

VIVADO “Block Designエラーチェック”

• [Validate Design]をクリックする• エラーが無いことを確認したら、デザインを保存する

1

2

Page 101: Zynq + Vivado HLS入門

VIVADO “Generate Block Design 1/3”

• Block Designに含まれるIPに必要な制約、デザインのネットリストを生成する

• [Generate Block Design]をクリックする

1

Page 102: Zynq + Vivado HLS入門

VIVADO “Generate Block Design 2/3”

• [Generate]をクリックする

1

Page 103: Zynq + Vivado HLS入門

VIVADO “Generate Block Design 3/3”

• 終了したら[OK]をクリックする• Designの生成が完了した

1

Page 104: Zynq + Vivado HLS入門

VIVADO “HDL wrapperの生成1/3”

• Block DesignのHDL wrapperを生成していく• [Sources]タブを選択する• [design_1]を右クリック• [Create HDL Wrapper]をクリックする

1

23

Page 105: Zynq + Vivado HLS入門

• [OK]を選択

VIVADO “HDL wrapperの生成2/3”

1

Page 106: Zynq + Vivado HLS入門

VIVADO “HDL wrapperの生成3/3”

• “design_1_wrapper”ファイルが追加されていることを確認する• HDL wrapperの生成が完了した

1

Page 107: Zynq + Vivado HLS入門

VIVADO “SDK Export1/2”• Hardwareの情報をSDKにExportする• [File]をクリック• [Export] => [Export Hardware]をクリック

1

2

Page 108: Zynq + Vivado HLS入門

• [OK] をクリック• Exportが完了したらBitstreamを生成する

VIVADO “SDK Export2/2”

1

Page 109: Zynq + Vivado HLS入門

VIVADO “Generate Bitstream1/2”

• bitファイルを生成する• [Generate Bitstream]をクリックする

1

Page 110: Zynq + Vivado HLS入門

VIVADO “Generate Bitstream2/2”

• 完了したら[Cancel]をクリックする• 以上でVIVADOでの実装は終了となる• 次はSDKでソフトウェアを実装していく

1

Page 111: Zynq + Vivado HLS入門

SDK

Board Suppot Packageの生成

Application Projectの生成

ソフトウェア(polling)の実装

作業手順

アプリケーション実行1

interrupt制御プログラムの追加

アプリケーション実行2

Page 112: Zynq + Vivado HLS入門

SDK “SDKの起動1/2”• SDKを起動する (linuxの場合 “xsdk” コマンドで起動)• VIVADOは”project_dir/project_name.sdk”にHardware情報を

Exportしている• Workspaceは”zynq_vivadohls/zynq_vivadohls.sdk”を選択する• [OK]をクリック

1

Page 113: Zynq + Vivado HLS入門

SDK “SDKの起動2/2”

• SDKの起動が完了した• design_1_wrapper_hw_platform_0内にExportされた

hardware情報やPSの設定スクリプトがある(バージョンが2014. 2の場合、hardware Platform Specificationを自分で作成する必要あり)

Page 114: Zynq + Vivado HLS入門

SDK “Board Support Packageの生成1/4”

• [New]をクリック• [Xilinx]タブを開く• [Board Support Package]を選択• [Next]をクリックする

1

23

4

Page 115: Zynq + Vivado HLS入門

• Project nameに任意の名前を入力(自分は”standalone_bsp_0”を使用)• [Finish]をクリック

SDK “Board Support Packageの生成2/4”

1

2

Page 116: Zynq + Vivado HLS入門

• [OK]をクリック

SDK “Board Support Packageの生成3/4”

1

Page 117: Zynq + Vivado HLS入門

SDK “Board Support Packageの生成4/4”

• Board Support Packageが生成された• standalone_bsp_0内にはxilinxが提供するlibraryや

hardwareのアドレスを定義したヘッダーファイル等がある

Page 118: Zynq + Vivado HLS入門

SDK “Application Projectの生成1/4”• [New]をクリック• [Xilinx]タブを開く• [Application Project]を選択• [Next]をクリック

1

2 3

4

Page 119: Zynq + Vivado HLS入門

• Project nameを”axihp_memcpy”にする• [Use existing] をチェックをする• [Next]をクリック

SDK “Application Projectの生成2/4”

1

2

3

Page 120: Zynq + Vivado HLS入門

• [Empty Application] を選択• [Finish]をクリック

SDK “Application Projectの生成3/4”

1

2

Page 121: Zynq + Vivado HLS入門

SDK “Application Projectの生成4/4”

• Application Projectが生成された

Page 122: Zynq + Vivado HLS入門

SDK “Fileの生成1/3”

• [axihp_memcpy]タブを開く• [src]を右クリックする• [New] => [File]をクリックする

1

2 3

Page 123: Zynq + Vivado HLS入門

SDK “Fileの生成2/3”

• File nameを”axihp_memcpy.c”とする• [Finish]をクリックする

2

1

Page 124: Zynq + Vivado HLS入門

SDK “Fileの生成3/3”

• “axihp_memcpy.c”ファイルが生成された• C言語でソフトウェアを実装していく

Page 125: Zynq + Vivado HLS入門

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] = %d\n\r", 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!\n\r"):

xil_printf("memcpy fail\n\r");return 0;

}

• axihp_memcpyコアにsrc_dataの値をdst_dataにコピーさせる• 以降、この雛型に赤文字で書かれたプログラムを追加していく

Page 126: Zynq + Vivado HLS入門

SDK “キャッシュの無効化”

#include "xil_cache.h"…int main(){

Xil_DCacheDisable(); //Disable Data Cache…return 0;

}

• xil_cache.h内で定義されているXil_DCacheDisable関数を使うとデータキャッシュをオフにすることができる

• DMAを正しく実行するにはflushおよびinvalidateを適切に行う必要がある.簡単のため、今回はキャッシュを無効化する

Page 127: Zynq + Vivado HLS入門

SDK “axihp_memcpyコアのレジスタ構成1/2”

• standalone_bsp_0/ps_cortexa9_0/include内の“axihp_memcpy_hw.h”を開く

• ファイル内にレジスタのmapが記述されている

Page 128: Zynq + Vivado HLS入門

SDK “axihp_memcpyコアのレジスタ構成2/2”

0x00 Control signals

0x04Global Interrupt

Enable

0x08IP Interrupt

Enable

0x0cIP Interrupt

Status

0x10Data signal of

axihp_in

0x14 reserved

0x18Data 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)

Page 129: Zynq + Vivado HLS入門

SDK “axihp_memcpyアドレスの確認”

• standalone_bsp_0/ps_cortexa9_0/include内の“xparameters.h”に記述されている

• アドレスは0x43c00000で、次のように定義されている“XPAR_AXIHP_MEMCPY_0_S_AXI_AXILITES_BASEADDR”

Page 130: Zynq + Vivado HLS入門

SDK “読み出し/書き込みアドレスの設定”

…unsigned int *baseaddr = 0x43c00000; //reg0 of hls coreint main(){

…//control hls corebaseaddr[4] = src_data; //set read addrbaseaddr[6] = dst_data; //set write addr…

}

• 0x43c00000番地がaxihp_memcpyのレジスタ0の番地となる

Page 131: Zynq + Vivado HLS入門

SDK “axihp_memcpyの開始制御”

…int main(){

…//control hls corebaseaddr[4] = src_data; //set read addrbaseaddr[6] = dst_data; //set write addrif ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is high

xil_printf("memcpy start\n\r");baseaddr[0] |= 0x1; //make ap_start high

}…

}

• ap_idleが1であればap_startを1にして開始する

Page 132: Zynq + Vivado HLS入門

SDK “axihp_memcpyの終了制御(polling版)”

…int main(){

…//control hls core…if ((baseaddr[0] & 0x4) == 0x4) {//if ap_idle is high

xil_printf("memcpy start\n\r");baseaddr[0] |= 0x1; //make ap_start high

}while ((base_addr[0] & 0x4) == 0); //wait for memcpy(polling)xil_printf("memcpy done!\n\r");…

}

• ap_idleが再び1になるまでwhile文で待機する

Page 133: Zynq + Vivado HLS入門

SDK “axihp_memcpyソフトウェア”

#include "xil_cache.h"#include "xil_printf.h"typedef unsigned long long u64;unsigned int *baseaddr = 0x43c00000;//reg0 of hls coreint main(){

Xil_DCacheDisable(); //Disable Data Cacheint 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 corebaseaddr[4] = src_data; //set read addrbaseaddr[6] = dst_data; //set write addr

if ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is highxil_printf("memcpy start\n\r");baseaddr[0] |= 0x1; //make ap_start high

}while ((baseaddr[0] & 0x4) == 0); //wait for memcpy(polling)xil_printf("memcpy done!\n\r");

for (i = 0; i < 256; i++) {xil_printf("src_data[%d] = %d, ", i, src_data[i]);xil_printf("dst_data[%d] = %d\n\r", 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!\n\r"):

xil_printf("memcpy fail\n\r");return 0;

}

プログラム全体は以下のようになる

Page 134: Zynq + Vivado HLS入門

SDK “ソフトウェアのコンパイル1/2”

• [Build ALL]をクリックする• デフォルトでは保存する度に自動でBuildされる

1

Page 135: Zynq + Vivado HLS入門

SDK “ソフトウェアのコンパイル2/2”

• 実行ファイル(.elf)が生成された

同一

Page 136: Zynq + Vivado HLS入門

SDK “FPGAのコンフィグレーション1/2”

• ソフトウェア実装が終わったので実行手順に移る• まずFPGAに回路をダウンロードしていく• [Program FPGA]をクリックする

1

Page 137: Zynq + Vivado HLS入門

SDK “FPGAのコンフィグレーション2/2”

• Bitstreamを”...zynq_vivadohls/zynq_vivadohls.run/impl_1/design_1_wrapper.bit”と選択する

• [Program]をクリックする

1

2

Page 138: Zynq + Vivado HLS入門

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の場合)

Page 139: Zynq + Vivado HLS入門

SDK “アプリケーションの実行1/3”

• [Debug]タブを開く• [axihp_memcpy.elf]を右クリック• [Run As] => [Run Configuration]をクリック

1

2

3

Page 140: Zynq + Vivado HLS入門

• [Xilinx C/C++ application (GDB)] を右クリック• [New]をクリックする

12

SDK “アプリケーションの実行2/3”

Page 141: Zynq + Vivado HLS入門

SDK “アプリケーションの実行3/3”

• [Run]をクリックすると実行される

1

Page 142: Zynq + Vivado HLS入門

SDK "実行結果"

無事に一致しましたか?(^^)

Page 143: Zynq + Vivado HLS入門

SDK "二回目以降の実行"

• [Run]の右側の下矢印をクリック• [axihp_memcpy_Debug]をクリックで実行できる

1

2

Page 144: Zynq + Vivado HLS入門

SDK "Debugモード"

• [Debug]の右側の下矢印をクリック• [axihp_memcpy_Debug]をクリックでDebugモードで実行

1

2

Page 145: Zynq + Vivado HLS入門

SDK "割り込みプログラム1/4"

#include "xparameters.h"#include "xscugic_hw.h"#include "xil_exception.h"…int main(){

…//control hls coreunsigned 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);…

}

Page 146: Zynq + Vivado HLS入門

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 memcpywhile (memcpy_done == 0); //wait for interrupt…

}

void axihp_memcpy_handler(){

baseaddr[2] ^= 0x1;xil_printf("interrupt!\n\r");memcpy_done = 1;baseaddr[3] = 0x1;baseaddr[2] |= 0x1;

}

Page 147: Zynq + Vivado HLS入門

SDK "割り込みプログラム3/4"...zynq_vivadohls.sdk/standalone_bsp_0/ps7_cortexa9_0/libsrc/scugic_v2_1/src/xscugic_hw.c上記ファイル内にXScuGic_DeviceInterruptHangler関数が記述されてる

注意! キャストされていないので引数にはポインタではなく値をいれる

Page 148: Zynq + Vivado HLS入門

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 corevolatile int memcpy_done = 0;void axihp_memcpy_handler();int main(){

Xil_DCacheDisable(); //Disable Data Cacheint 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 coreunsigned 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 addrbaseaddr[6] = dst_data; //set write addr

if ((baseaddr[0] & 0x4) == 0x4) { //if ap_idle is highxil_printf("memcpy start\n\r");baseaddr[0] |= 0x1; //make ap_start high

}//while ((baseaddr[0] & 0x4) == 0); //wait for memcpy(poling)while (memcpy_done == 0); //wait for interruptxil_printf("memcpy done!\n\r");

for (i = 0; i < 256; i++) {xil_printf("src_data[%d] = %d, ", i, src_data[i]);xil_printf("dst_data[%d] = %d\n\r", 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!\n\r"):

xil_printf("memcpy fail\n\r");return 0;

}

void axihp_memcpy_handler(){

baseaddr[2] ^= 0x1;xil_printf("interrupt!\n\r");memcpy_done = 1;baseaddr[3] = 0x1;baseaddr[2] |= 0x1;

}

プログラム全体は以下のようになる

Page 149: Zynq + Vivado HLS入門

VIVADO Logic Analyzer

Harware Managerの起動

現在の波形をキャプチャ

トリガをかけてキャプチャ

作業手順

Page 150: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動1/6"

• [Open Hardware Manager]タブを開く• [Open Target]をクリック• [Open New Target]をクリック

1

2

3

Page 151: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動2/6"

• [Next]をクリック

1

Page 152: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動3/6"

• [Next]をクリック

1

Page 153: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動4/6"

• [Next]をクリック

1

Page 154: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動5/6"

• [Finish]をクリック

1

Page 155: Zynq + Vivado HLS入門

VIVADO "Hardware Manager の起動6/6"

• Hardware Managerが起動した

Page 156: Zynq + Vivado HLS入門

VIVADO "FPGAのコンフィグレーション1/2"

• FPGAのコンフィグレーションがまだの場合、ここでコンフィグレーションを行う

• "xc7z020_1"を右クリック• [Program Device]をクリック

1

2

Page 157: Zynq + Vivado HLS入門

VIVADO "FPGAのコンフィグレーション2/2"

• [Program]をクリックするとコンフィグレーションが実行される

1

Page 158: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない1/6"• ZYNQの電源を入れた直後に、ILAを含むデザインを

コンフィグレーションするとワーニングがでる上にILAの操作画面が出てこない

• これはZYNQからCLKがまだ出力されていないことが原因• CLK出力後に[Refresh device]をクリックすると解決される

Page 159: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない2/6"

• 実はコンフィグレーションが完了した段階ではZYNQからクロックは出力されない

• では、どのタイミングでクロックが出力されるのか?

• ネットで検索すると、"ARM上でアプリケーションを実行する"とクロックが出力されるという情報が多く出てくるが

正しい条件は"ps7_init_config, ps7_post_configを実行する"である

Page 160: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない3/6"

• 普通ps7_init_config, ps7_post_configはアプリケーション実行前に実行される

Page 161: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない4/6"

• しかし実行できないときがある

Page 162: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない5/6"

• AXIポートが何も使用されていないとps7_post_configが実行されない

Page 163: Zynq + Vivado HLS入門

寄り道 "CLKが出力されない6/6"

XMD% connect arm hwXMD% rst –slcrXMD% cd "project_name".sdk/designe_1_wrapper_hw_platform_0XMD% source ps7_init.tclXMD% ps7_initXMD% ps7_post_configXMD% disconnect 64

• SDKのxmdコンソールでps7_post_configを実行する方法

Page 164: Zynq + Vivado HLS入門

VIVADO "現在の波形をキャプチャする1/2"

• [Run trigger immediate for this ILA core]をクリックする

1

Page 165: Zynq + Vivado HLS入門

VIVADO "現在の波形をキャプチャする2/2"

• 現在の波形がキャプチャされた• 次はトリガを設定し、狙ったタイミングでキャプチャする

Page 166: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ1/6"

• バースト受信の開始時にトリガをかける• ARVALIDがHighになったらトリガがかかるように設定していく• Debug Probes内にある"ARVALID"信号を右クリック• [Add Probes to Basic Trigger Setup]をクリック

2

1

Page 167: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ2/6"

• Basic Trigger Setup にARVALID信号が追加される• [Compare Value]タブを開く• [Value]を"1"に設定する

2

1

Page 168: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ3/6"

• キャプチャを開始する• [Run trigger for this ILA core]をクリックする

1

Page 169: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ4/6"

• トリガ待ちの状態になる

Page 170: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ5/6"

• SDKでアプリケーションを実行し、AXI転送を行う

1

2

Page 171: Zynq + Vivado HLS入門

VIVADO "トリガをかけてキャプチャ6/6"

• VIVADOに戻ってくるとARVALIDがHighになった直後からキャプチャされている

Page 172: Zynq + Vivado HLS入門

VIVADO "AXI転送時の波形"

Page 173: Zynq + Vivado HLS入門

Next Step "RTLでAXI State Machine書きたい!!1/5"

• AXIの雛型の作り方• VIVADOのProject Setteingsで"Vendor"を設定する

Page 174: Zynq + Vivado HLS入門

Next Step "RTLでAXI State Machine書きたい!!2/5"

• [Tools] => [Create and Package IP]をクリック

Page 175: Zynq + Vivado HLS入門

Next Step "RTLでAXI State Machine書きたい!!3/5"

• [Create a new AXI4 peripheral]を選択

Page 176: Zynq + Vivado HLS入門

Next Step "RTLでAXI State Machine書きたい!!4/5"

• 必要なAXIポートを備えたIPを作成

Page 177: Zynq + Vivado HLS入門

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)