---
# System prepended metadata

title: PYNQ使用介紹

---

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>
![image](https://hackmd.io/_uploads/rydidfnl0.png)

- Pynq PS and PL
![image](https://hackmd.io/_uploads/ByuQeM2eR.png)
    
![image](https://hackmd.io/_uploads/HJLyF1EW0.png)
![image](https://hackmd.io/_uploads/HJR70kNZA.png)

## Pynq-z2開機

[開機設定教學](https://youtu.be/RiFbRf6gaK4)

### 大致流程總結和注意事項
![image](https://hackmd.io/_uploads/B1_JHBkNA.png)


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**

![image](https://hackmd.io/_uploads/BJFybcENR.png) ![image](https://hackmd.io/_uploads/SJk-bcV40.png)

    
先下載vivado HLS和Vivado IDE作為客製化單個IP和監控整個硬體設計流程的工具就好(直接下載Vivado suite就同時包含這兩個)注意不要下載Update version或lab solution，然後舊版的會是HLS edition，新版的會是ML edition，並且Unified installer預設只會支持三年的時間，所以如果要下載舊版的要下載SFD(Single File Download)，有遇到一些需要帳號的地方可以正常輸入，然後會跳出一些警告訊息直接點確定就好了。


下方的圖是Vivado suite 的設計流程
![image](https://hackmd.io/_uploads/SJGhlcNVC.png)

### 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文件
![image](https://hackmd.io/_uploads/BJn3goYV0.png)

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設定完成
![image](https://hackmd.io/_uploads/B1mJujt4C.png)

7. 於上方工具欄找到Run符號![image](https://hackmd.io/_uploads/Bk66OsFVR.png)，並點擊。

8. 出現這個樣子就是成功了
![image](https://hackmd.io/_uploads/HkpPKsYN0.png)

9. 這邊可以找到等一下使用Overlay的時候需要讀寫的記憶體位址，也可以等block design完之後匯入Vitis找到這些地址。
![image](https://hackmd.io/_uploads/H1JA9iKVA.png)

10. 可以在上方工具列找到黃色的export RTL![image](https://hackmd.io/_uploads/rksqjitVR.png)，匯出IP盒
![image](https://hackmd.io/_uploads/S1CU2stN0.png)
選擇IP Catalog(給Vivado使用)，而System Generator for DSP這個選項可以給Simulink使用。按OK，等下方出現這個就算是成功匯出。
![image](https://hackmd.io/_uploads/S1v5TotV0.png)

### Block design
1. 開啟Vivado IDE，Create Project，然後輸入完project name 和location之後下一步，勾選不要匯入源文件，按下一步。
![image](https://hackmd.io/_uploads/B1-9l2t4C.png)
2. 到Default parts 的地方，如果剛剛有設定pynq-z2 board file 可以點擊boards -> 選擇pynq-z2，然後下一步到完成創建，否則一樣選擇xc7z020clg400-1型號。
![image](https://hackmd.io/_uploads/SkWLW2t40.png)
3. 點擊左邊Create Block Design ![image](https://hackmd.io/_uploads/SkwFzhFNC.png)

4. 右邊Diagram的位置點擊![image](https://hackmd.io/_uploads/HyWE7nFVA.png)，找到一個ZYNQ7 prosessing system的IP盒，並點兩下加入。
![image](https://hackmd.io/_uploads/rksQX2tER.png)

5. 點擊Run Block Automation並點擊OK，自動將ZYNQ IP盒需要的東西添加進Diagram。![image](https://hackmd.io/_uploads/Hy9B42F4A.png)
應該只會出現兩個灰色的輸出端。
![image](https://hackmd.io/_uploads/ByTMS2F4A.png)
6. 點擊左邊Project Manager 的 settings ![image](https://hackmd.io/_uploads/rkaTB2KVC.png)
並點擊IP底下的Repository，並加入剛剛利用HLS設計的project位置，應該是xxx\add
    ![image](https://hackmd.io/_uploads/ryw1U3K4A.png)
選擇 add IP
    ![image](https://hackmd.io/_uploads/S169w3KNC.png)
    
7.一樣點擊 ![image](https://hackmd.io/_uploads/S1xd_nFER.png)並加入IP ![image](https://hackmd.io/_uploads/rJWcO3tNR.png)
8. 點Run Connection Automation 點OK就可以了
9. 可以看到IP盒已經連接完成
    ![image](https://hackmd.io/_uploads/Sk_oYnKEC.png)
10. 旁邊的source區點擊 Create HDL wrapper 點擊OK
    ![image](https://hackmd.io/_uploads/BkNfqhtE0.png)
    會生成一個verilog(.v)檔然後把剛剛的橘色block design(.bd)包在下面，這個verilog檔是用來定義，.bd檔的連接狀況
    ![image](https://hackmd.io/_uploads/Bk4QohF4C.png)

11. 最後點擊左邊的Generate Bitstream，一路點OK，這裡可能會跑有點久。
    ![image](https://hackmd.io/_uploads/rJMUs3YE0.png)
    
12. 完成了之後可以Open Implemented Design，也可以不開 ![image](https://hackmd.io/_uploads/S1KfAhK40.png)
    
13. 在左邊sources點兩下打開design_1.bd(這邊很重要不然export有些選項會不同)
![image](https://hackmd.io/_uploads/B1cLR6YVR.png)
14. 到File -> Export -> Export Block Design
![image](https://hackmd.io/_uploads/HyZ110KVA.png)

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) 是一個官方的社群論壇


