PynqのPLでLチカ

# 概要
PynqをあくまでもFPGAとして利用する方向けに、Vivado上でプロジェクトを作成しPynqに乗っている4つのLEDを光らせる手順を説明します。
学校のFPGAの実験を終えたあとPYNQを買った後輩が多くいたので、PYNQでもFPGA開発を続けられるようにまとめました。

# 環境
Windows 10 Pro 1709
PYNQ-Z1
VivadHL 2017.4 Web Pack

# ボードファイルの追加
https://github.com/cathalmccabe/pynq-z1_board_files
こちらのリポジトリをクローンし pynq-z1フォルダーを

```
Vivadoのインストール先\data\boards\board_files
例：C:\FPGA\Xilinx\Vivado\2017.4\data\boards\board_files
```

以下にコピーします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/1b1607fa-89d0-d544-4474-6020b3fa4a8a.png)


このボードファイルはPSのプリセットや周辺回路のピン設定などを含んでいます。

# プロジェクトの作成
Vivadoを立ち上げ「File」から「New Project」を選択します。
とりあえずプロジェクトの保存先などを適当に埋めファイルを追加せずに「Default Part」画面まで進めます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/f01817de-40ab-9a80-d393-2d3220aabd10.png)

「Select」の「Boards」を選択するとPYNQ-Z1という項目が追加されていると思うのでこちらを選択しNextを押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/9aca0992-77f7-fbd8-d396-61f8bc01ac9c.png)

確認画面が出るので内容を確認し「Finish」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/016e15b7-b686-39c9-4c62-86e999d93d4c.png)

# Lチカ回路を作成
左側「Flow Navigator」から「PROJECT MANAGER」内の「ADD Source」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/c546f934-7814-2da8-99f4-6e5a17950f5e.png)
「Add or create design sources」にチェックが入っていることを確認し次へ
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/22fce438-a4ec-0120-b1fc-f85bef9f1303.png)
「Create File」を選択しVerilogファイルを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/32d3464b-9d2d-b34e-e693-5e7da3b358a0.png)
名前は適当に入力し「OK」を押します。

最後に「Finish」を押してダイアログを閉じます。

モジュールの定義を入力される画面が表示されるのでクロック、リセット（負論理）、LED用出力（4bit）を追加します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/3ec6b113-b473-a089-2d62-f8f62e24b4a7.png)

内容を確認して「OK」を押します。

>なぜか、後述する方法でVerilogモジュールを直接ブロックデザインにいれると正論理rstが負論理として扱われるのでrstnとし、負論理リセットとしています。

作成されたverilogファイルを開き適当に作成します。
今回はカウンターを用意しそれを元にLEDを光らせます。

```verilog
module led(
    input clk,
    input rstn,
    output [3:0] led
    );
    reg [25:0] count;
    always @(posedge clk) begin
      if (~rstn) count <= 26'd0;
      else count <= count + 26'd1;
    end
    assign led[0] = count[25];
    assign led[1] = count[24];
    assign led[2] = count[21];
    assign led[3] = count[15];
endmodule
```


# ブロックデザインの作成
左側「Flow Navigator」から「IP INTEGRATOR」内の「Create Block Design」を選択し、表示されるダイアログに名前などを入力して「OK」を押します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/a49ffce9-9aec-1019-c296-8b2d7102069f.png)

まずはPS(Processing System)を追加します。
右クリックして「AddIP」を選択し、「ZYNQ7 Processing System」を選択してPSを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/147b13a9-7342-926b-fadf-7b3f327ae2e4.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/8690df56-7336-d6b4-7116-905cb08c9eb8.png)

次に上部に表示されている「Run Block Automation」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/aaa45ba4-211d-a3eb-a666-cd6888d7d523.png)
表示されるダイアログはデフォルトのまま「OK」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/33587bcc-ed9a-3037-64d1-1a5f6a5af0dd.png)

続けて先ほど作成したLチカ回路を追加します。
Diaglam上で右クリックし「Add Module」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/a7c3c57e-ccb5-ee36-339f-c3462f97dda1.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/207c09e6-90c0-9af2-4315-b1519fe0c478.png)

先ほど作成した回路が認識されていると思うので選択し「OK」を押します。

ブロック図がこのようになると思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/e4a886fd-4a0d-db8c-a0f8-101b83d02136.png)

クロックやリセットを自動で接続するため、上部に表示されている「Run Connection Automation」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/7ec278b6-6e70-f726-b0f5-11705aa8212e.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/3a7d73ed-6bfe-3152-0f3d-0881c7bdbb65.png)

デフォルトのまま「OK」を選択します。

リセット回路が追加され、自動で配線されました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/c4310da0-6c9a-3927-554d-2444e655ec0c.png)

Lチカ回路の「led[3:0]」を外部に接続するため「led[3:0]」を右クリックし「Make External」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/2b00b514-9e83-5b38-2c4f-532d96c6b59b.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/a1c6eed5-f071-7f29-c67a-ec9d16f1b256.png)


>PSの「M_AXI_GP0_ACLK」が自動配線されていない場合（上図）は、「M_AXI_GP0_ACLK」と「FCLK_CLK0」を接続してください。
>![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/8a6c2b40-3b29-13cd-d6bb-52ff1836cada.png)

これでブロック図は完成です。
「Source」タブのブロックデザインを右クリックし「Create HDL Wrapper」を選択し、ラッパーを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/8a344087-2f37-6dff-63ba-a6d8d7746589.png)

# 論理合成
「Flow Navigator」から「SYNTHESIS」内の「Run Synthesis」を選択し、論理合成します。

# IOピンの設定
論理合成が終わったら「Flow Navigator」から「SYNTHESIS」内の「Open Synthesiszed Design」を選択し、右上のレイアウト選択を「I/O Planning」にします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/aa63e853-d0d7-1181-d606-3dbd8e369da1.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/333fef25-8cc9-f055-d4e8-b54e70966798.png)

LEDピンの設定をする必要があるので下部「I/O Ports」内の「led_0」を開きます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/995259e1-8678-99b3-bafa-b85fcc196ad7.png)

この表のPackagePinで足のピンを指定します。
PynqのLEDは回路図から以下のように対応しています。

|LED番号|ピン番号|
|:---:|:---:|
|0|R14|
|1|P14|
|2|N16|
|3|M14|

その為、「led_0[0]~[3]」のPackagePinは上のピン番号を選択します。
また、「I/O Std」（入出力規格）がデフォルトのままなので3.3Vである「LVCMOS33」を選択します。
最終的にIOの設定は図のようになると思います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/8e465c81-ab00-f095-1108-3fac6f68651b.png)

# 配置配線&ビットストリームの作成
「Flow Navigator」から「IMPLEMENTATION」内の「Run Implementation」を選択し、配置配線を行います。
デザイン制約ファイル（XDC）がない場合は作成する画面が表示されるので適当に名前を入れて「OK」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/140084/e92fb7c6-197e-d04a-b7e1-11531e59ac1b.png)

作成されたXDCファイルを開くと先ほど入力したIOの設定が反映されていると思います。

```xdc
set_property PACKAGE_PIN R14 [get_ports {led_0[0]}]
set_property PACKAGE_PIN P14 [get_ports {led_0[1]}]
set_property PACKAGE_PIN N16 [get_ports {led_0[2]}]
set_property PACKAGE_PIN M14 [get_ports {led_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {led_0[0]}]
```

配置配線が終わったら、「Flow Navigator」から「PROGRAM AND DEBUG」内の「Generate Bitstream」を選択し、ビットストリームを作成します。

# 動作確認
今回はPSからクロックを取り出しているため、PSを起動する必要があります。
「File」から「Export」を選択し「ExportHardware」でビットストリームをエクスポートし「Launch SDK」でSDKを立ち上げます。
適当なCプログラムを作成し、ビットストリームをFPGAに書き込みCプログラムを実行してください。

SDK周りは気が向いたらまとめます。
うまく動けばこんな感じで動作するはずです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Lチカ <a href="https://t.co/eIjBWtwiJY">pic.twitter.com/eIjBWtwiJY</a></p>&mdash; mmitti (青ペンギン) (@mi_mmitti) <a href="https://twitter.com/mi_mmitti/status/962708321982595072?ref_src=twsrc%5Etfw">2018年2月11日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 資料
pynqの回路図
https://reference.digilentinc.com/_media/reference/programmable-logic/pynq-z1/pynq-z1_sch.pdf