PYNQ使用介紹
===
- [PYNQ概述]()
- [Zynq 與 Pynq]()
Pynq-z2開機
---
- [大致流程總結和注意事項]()
自定義Overlay
---
- [Vivado HLS 介紹]()
- [Vivado IDE 介紹]()
- [Vitis 介紹]()
- [使用Vivado HLS設計IP]()
- [使用Vivado 做 Block Design]()
- [使用PYNQ讀取Overlay]()
---
## PYNQ概述
PYNQ是一個嵌入式開發平台,在Xilinx的產品中被歸類為ZYNQ系列的擴展,並以Pynq-Z2作為平台的實體開發板。
[PYNQ-z1 和 PYNQ-z2 內建設備規格比較](https://blog.umer-farooq.com/pynq-z1-vs-pynq-z2-which-is-better-213e3dc15527)
板子分為兩個部分:
- 硬體實現(PL端)
-- 使用Zynq7000系列晶片作為處理器
- 軟體實現(PS端)
-- 使用Ipython kernel 作為開發用伺服器
### **Zynq 與 Pynq**
- Zynq PS and PL
<font size=4>**硬體(FPGA) ⮕ 操作系統(PetaLinux、driver & API) ⮕ Application** <font>

- Pynq PS and PL



## Pynq-z2開機
[開機設定教學](https://youtu.be/RiFbRf6gaK4)
### 大致流程總結和注意事項

1. 下載此處的[image](https://bit.ly/pynqz2_v3_0_1),並使用燒錄工具([點擊下載](https://win32diskimager.b-cdn.net/win32diskimager-1.0.0-install.exe)),燒錄至隨板附的SD card,並插入上圖SD Card(On the Back Side)的位置,如果使用自己買的SD card可能要注意容量大小問題。
2. 連接上圖JTAG/UART(Micro USB)接口,和Ethernet(RJ45)至電腦,也可以將Ethernet(RJ45)改成網路路由器,由Wifi連接至電腦。
3. 電腦設定網路IP位置,控制台 -> 網路和共用中心 -> 變更介面卡設定 -> 乙太網路XXX -> ......這裡具體看官方教學。
4. 上圖 Jumper for Boot Mode Selection 位置設定為 SD card
5. 打開上圖Power Switch,這部份需要一點時間,待板子上LED燈閃爍完後變為長亮,即開機完成。
6. 打開瀏覽器網址欄輸入192.168.2.99進入jupyter notebook,預設密碼為xilinx,也可以在windows檔案管理員於上方搜索欄輸入\\pynq\xilinx,預設使用者帳號密碼一樣是xilinx。
7. 開機完成後Jupyter notebook中有一些Getting start 之類的教學文件也可以作為參考。
---
## 自定義Overlay
前面提到的Overlay作為pynq平台裡操作硬體設計的軟體實現,最後使用者會用python操作overlay達到控制硬體設計的目的。
**先講結論,在最後要燒錄到Pynq開發板的文件中要包含至少兩個檔案,分別是.bit ,和.tcl、.hwh任選一個,官方更推薦.hwh,並且有之後會取代.tcl,因為內含的IP訊息會比tcl更多,可以丟進專案目錄底下,然後透過內建python底下的pynq套件下的Overlay來讀取.bit檔並燒錄到PL裡面,就可以開始使用定義好的Overlay**
 
先下載vivado HLS和Vivado IDE作為客製化單個IP和監控整個硬體設計流程的工具就好(直接下載Vivado suite就同時包含這兩個)注意不要下載Update version或lab solution,然後舊版的會是HLS edition,新版的會是ML edition,並且Unified installer預設只會支持三年的時間,所以如果要下載舊版的要下載SFD(Single File Download),有遇到一些需要帳號的地方可以正常輸入,然後會跳出一些警告訊息直接點確定就好了。
下方的圖是Vivado suite 的設計流程

### Vivado HLS介紹
Vivado HLS主要是讓設計人員可以快速的使用C/C++/System C作為描述電路邏輯的語言來實做IP,也就是通過Xilinx定義的接口規範(透過#pragma調用),再透過C語言來描述IP的邏輯,最後輸出成想要的IP盒,IP盒最後會匯入到Vivado IDE做block design。
[可以在這邊找到Vivado HLS 定義的所有Pragma,用於之後客製化自己的IP](https://docs.amd.com/r/en-US/ug1399-vitis-hls/HLS-Pragmas)
### Vivado IDE介紹
Vivado IDE作為管控整個硬體開發流程的工具,可以在於設計完IP盒後,用於block design調整IP和PYNQ間的溝通方式和測試硬體設計是否有錯誤,最後確認無誤後輸出bitstream,也就是.bit檔。另外Vivado等同於Xilinx開發的tcl,也就是說Vivado IDE的GUI的選項分別對映著tcl的不同指令,所以可以單純的寫一個tcl file匯入,或利用command line逐行建構一個Vivado project。
下面是官方的一個教學,用tcl建構vivado project,可以當作練習tcl的指令
[Using Tcl Commands in the Vivado Design Suite Project Flow](https://www.xilinx.com/video/hardware/using-tcl-commands-in-the-vivado-design-suite-project-flow.html)
### Vitis介紹
Vitis則是用於設計軟體的部分,包括利用Vivado IDE做完Block Design之後使用C語言的方式測試硬體實作功能,或是需要第三方套件和額外的軟體功能、為petalinux新增一些功能等等,如果速度方面沒有要求的話,也可以使用Vitis HLS實現IP功能,相對Vivado HLS來說,Vitis HLS較為方便debug和快速開發。
### 設計IP
1. 打開Vivado HLS,create new project,輸入Project名稱、位置,注意名稱和路徑最好都是英文,不然之後匯出的時候會報錯,可以有底線沒關係。
2. 一直按下一步直到solution configration的地方需要設定板子型號,點擊part selection右邊的...進入Device selection dialog,可以在parts的地方搜尋xc7z020clg400-1並選擇晶片型號,或是到boards選擇pynq-z2,但必須先[下載pynq-z2的board file](https://dpoauwgwqsy2x.cloudfront.net/Download/pynq-z2.zip),解壓縮後將pynq-z2資料夾放到Vivado安裝路徑C:\xilinx\Vivado\2019.2\data\boards\board_files,重啟Vivado HLS才會有這個選項,然後按finish。
3. 在左邊的Source 點擊右鍵new file,建立一個add.cpp文件

4. 在add.cpp 文件裡面輸入下方程式碼,注意這邊變數c作為output一定要加一個&,不然雖然在Vivado HLS裡面不會報錯,但是之後讀取會有問題。
```c++=
void add(int a, int b, int &c){
#pragma HLS INTERFACE ap_ctrl_none port=return
#pragma HLS INTERFACE s_axilite port=a
#pragma HLS INTERFACE s_axilite port=b
#pragma HLS INTERFACE s_axilite port=c
c = a + b;
}
```
5. 左邊選擇Project Settings -> synthesis -> browse top function -> 選擇add.cpp -> 點擊OK設定完成

7. 於上方工具欄找到Run符號,並點擊。
8. 出現這個樣子就是成功了

9. 這邊可以找到等一下使用Overlay的時候需要讀寫的記憶體位址,也可以等block design完之後匯入Vitis找到這些地址。

10. 可以在上方工具列找到黃色的export RTL,匯出IP盒

選擇IP Catalog(給Vivado使用),而System Generator for DSP這個選項可以給Simulink使用。按OK,等下方出現這個就算是成功匯出。

### Block design
1. 開啟Vivado IDE,Create Project,然後輸入完project name 和location之後下一步,勾選不要匯入源文件,按下一步。

2. 到Default parts 的地方,如果剛剛有設定pynq-z2 board file 可以點擊boards -> 選擇pynq-z2,然後下一步到完成創建,否則一樣選擇xc7z020clg400-1型號。

3. 點擊左邊Create Block Design 
4. 右邊Diagram的位置點擊,找到一個ZYNQ7 prosessing system的IP盒,並點兩下加入。

5. 點擊Run Block Automation並點擊OK,自動將ZYNQ IP盒需要的東西添加進Diagram。
應該只會出現兩個灰色的輸出端。

6. 點擊左邊Project Manager 的 settings 
並點擊IP底下的Repository,並加入剛剛利用HLS設計的project位置,應該是xxx\add

選擇 add IP

7.一樣點擊 並加入IP 
8. 點Run Connection Automation 點OK就可以了
9. 可以看到IP盒已經連接完成

10. 旁邊的source區點擊 Create HDL wrapper 點擊OK

會生成一個verilog(.v)檔然後把剛剛的橘色block design(.bd)包在下面,這個verilog檔是用來定義,.bd檔的連接狀況

11. 最後點擊左邊的Generate Bitstream,一路點OK,這裡可能會跑有點久。

12. 完成了之後可以Open Implemented Design,也可以不開 
13. 在左邊sources點兩下打開design_1.bd(這邊很重要不然export有些選項會不同)

14. 到File -> Export -> Export Block Design

15. 打開Project 的所在位置資料夾,並將.tcl和.bit兩個檔案除了文件後輟名以外,要改成一樣。
- design_1.tcl
剛剛已經export出來了
這個文件主要是用於描述硬體的型號、接口,規格等等的文件。
- design_1_wrapper.bit
在xxx\project_1\project_1.runs\impl_1裡面
這個文件是block design出來的硬體實作。
- design_1.hwh
在xxx\project_1\project_1.srcs\sources_1\bd\design_1\hw_handoff裡面
這個文件與tcl相似但內容更豐富,也是描述硬體的規格之類的文件,未來有可能會取代.tcl,但目前舊版的系統是可以支持只有.bit和.tcl,所以還是建議三個文件都要有,某些版本的PYNQ系統和Vitis如果沒有.hwh file會報錯。
16. 最後把15.取得的三個文件放到Jupyter Notebook中想要的位置,接下來只剩使用python將.bit file 讀取成 Overlay 並用來測試和實現想要的軟體功能。
### 使用PYNQ讀取Overlay
打開瀏覽器輸入192.168.2.1開啟jupyter notebook
1.讀取IP寫一些簡單的操作
```python=
from pynq import Overlay
overlay = Overlay('./design_1.bit')
adder = overlay.add_0
adder.write(0x10, 10)
adder.write(0x18, 10)
adder.read(0x20)
```
```
20
```
看一下Overlay的詳細資料
```python=+
help(overlay)
```
```
Help on Overlay in module pynq.overlay:
<pynq.overlay.Overlay object>
Default documentation for overlay ./design_1.bit. The following
attributes are available on this overlay:
IP Blocks
----------
add_0 : pynq.overlay.DefaultIP
processing_system7_0 : pynq.overlay.DefaultIP
Hierarchies
-----------
None
Interrupts
----------
None
GPIO Outputs
------------
None
Memories
------------
PSDDR : Memory
```
地址可以透過前面講的方式在Vivado HLS和Vitis中找到,和用下面程式碼的方式找到。
```python=+
print(hex(adder.register_map.a.address))
print(hex(adder.register_map.b.address))
print(hex(adder.register_map.c.address))
```
```
0x10
0x18
0x20
```
也可以不用地址的方式直接和IP交互
```python=+
adder.register_map.a = 3
adder.register_map.b = 3
adder.register_map.c
```
```
Register(c=6)
```
2.也可以預先寫好Overlay的driver,這樣就可以只透過調用add函數進行加法。
```python=+
from pynq import DefaultIP
class AddDriver(DefaultIP):
def __init__(self, description):
super().__init__(description=description)
bindto=['xilinx.com:hls:add:1.0']
def add(self, a, b):
self.write(0x10, a)
self.write(0x18, b)
return self.read(0x20)
overlay = Overlay('./design_1.bit')
overlay.add_0.add(3, 4)
```
```
7
```
bindto變數中的內容可以在這裡找到
```python=+
overlay.ip_dict['add_0']['type']
```
```
'xilinx.com:hls:add:1.0'
```
[參考資料](https://pynq.readthedocs.io/en/v3.0.0/overlay_design_methodology/overlay_tutorial.html)
---
#### 補充
可以參考[Xilinx University Program](https://www.amd.com/en/corporate/university-program/workshops.html#tabs-78d8c6d64f-item-360e7ff952-tab)
這裡有官方的HLS教學,可以在裡面找到如何使用Vivado HLS設計較複雜一點的IP。
也可以參考[Adaptive SoC & FPGA Support](https://support.xilinx.com/s/?language=en_US) 是一個官方的社群論壇