ZYBO (Zynq) 初心者ガイド (5) PLだけでLチカ

- [1回目: 開発環境の準備](https://qiita.com/take-iwiw/items/966f252f6ca954aff08b)
- [2回目: Hello Worldプロジェクト](https://qiita.com/take-iwiw/items/24a8a94741fdbb80f62a)
- [3回目: PSのGPIOでLチカ](https://qiita.com/take-iwiw/items/39d2ed00fa88a1204fce)
- [4回目: PLのAXI GPIOでPSからLチカ](https://qiita.com/take-iwiw/items/a3b935a4e4dbd41593e1)
- __[5回目: PLだけでLチカ](https://qiita.com/take-iwiw/items/efcdfca1866b9941fd2a) <--- 今回の内容__
- [6回目: 自作IPでLチカ](https://qiita.com/take-iwiw/items/b0f2ce7b4653bc6f32b9)
- [7回目: ブートイメージを作る](https://qiita.com/take-iwiw/items/ece0cdf83e6e1908fad8)
- [8回目: Linux起動する](https://qiita.com/take-iwiw/items/6e6915f7318689818368)
- [9回目: Linuxカーネルを少しカスタマイズする](https://qiita.com/take-iwiw/items/6f2644d16cbfdb021d07)
- [10回目: LinuxのRootFSをカスタマイズする / PythonでHello World](https://qiita.com/take-iwiw/items/94a90047978664159681)
- [11回目: LinuxユーザアプリケーションでLチカ](https://qiita.com/take-iwiw/items/5e4ab9a106acfda2c866)
- [12回目: LinuxカーネルモジュールでLチカ](https://qiita.com/take-iwiw/items/e7efc48d92d7b979efdc)
- [13回目: LAN(Ethernet 0)を使う](https://qiita.com/take-iwiw/items/ac489acaca1ab54d7ce8)
- [14回目: Linuxユーザアプリをデバッグする / RootFSに取り込む](https://qiita.com/take-iwiw/items/8134ca7098622219b177)
- [15回目: Linux起動時にアプリケーションを自動実行させる](https://qiita.com/take-iwiw/items/50065df6cdd1ba8bcbd6)
- [16回目: Linuxから自作IPをUIOで制御する](https://qiita.com/take-iwiw/items/da91ce4dc2a8a8df3c0a)
- [17回目: Linuxで自作IPのデバイスドライバを作る](https://qiita.com/take-iwiw/items/05eb1204cb51ce0a5c03)
- [18回目: IoT化してスマホからLチカ](https://qiita.com/take-iwiw/items/e9311292c5078d785699)

この記事の内容を4分で見る ( https://www.youtube.com/watch?v=H5Qb428D7Sg )

# 環境
- 開発用PC: Windows 10 64-bit 
	- Vivado 2017.4 WebPACKライセンス
	- Xilinx SDK 2017.4
- ターゲットボード: ZYBO (Z7-20) 

Windows環境は[1回目](https://qiita.com/take-iwiw/items/966f252f6ca954aff08b)を参照。

# PLだけでLチカ
今回は、PLだけでLEDチカチカを実装します。PSは一切使いません。つまり、Zynqを通常のFPGAのように使います。 
まずは、verilogコードからシンプルにLチカさせてみます。その後に、作ったverilogコードをIPとして使用して、IP Integratorから使ってみようと思います。(IP化については次回ちゃんとやろうと思います。)

## Vivadoプロジェクトの準備
今回は、新しくプロジェクトを作ろうと思います。[2回目](https://qiita.com/take-iwiw/items/24a8a94741fdbb80f62a)の内容を参考に、ZYBOボードを指定してVivadoプロジェクトを作成してください。

## Verilogコードを書く
Verilogコードを追加します。左側のFlow Navigator -> PROJECT MANAGER -> Add Sourcesをクリックして、「Add or create design sources」を選びます。次の画面で、「Create File」を選び、ファイル名を"blink"とします。その後、モジュール名やIOポート定義を追加できますが、コードで書くので何もせずにOKします。

![01.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/ef5845f7-c698-198f-0623-b1fe1f514ed8.jpeg)
![02.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/118336e0-e040-e469-f54c-1813afe4fd76.jpeg)

Sourcesタブから、今作成したblink.vをダブルクリックして、以下のように実装します。このモジュールは入力として`CLK`を持ちます。このクロックは125MHzを想定します(理由は後述)。そして、4bitの`OUT`に出力します。`OUT`は全ビット同じ値で、1秒ごとにOn/Offします。

_記事を書いた後に気付いたのですが、`OUT`という名前は予約語なのでよろしくないです。別の名前を使うようにしてください。_

```verilog:blink.v
module blink(
    input CLK,
    output [3:0] OUT
);

parameter CNT_1SEC = 27'd124999999;  // 125MHz clk for 1sec
reg [26:0] cnt = 27'd0;
reg onoff = 1'd0;

always @(posedge CLK) begin
    if (cnt == CNT_1SEC) begin
        cnt <= 27'd0;
        onoff <= ~onoff;
    end
    else begin
        cnt <= cnt + 27'd1;
    end
end

assign OUT = {onoff, onoff, onoff, onoff};

endmodule
```

このblink.vがTop moduleとして自動的に設定されます。

![02_5.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/c2c99b8b-1cfb-1b3a-0bd2-8e22b7e8f9f9.jpeg)

## ピンアサインをする
### ピンアサインの決め方
先ほど実装したモジュールは、CLK入力と、4本の出力を持ちます。ZYBOボード上で適切なピンを探します。[ZYBO-Z7のリファレンスマニュアル](https://reference.digilentinc.com/_media/reference/programmable-logic/zybo-z7/zybo-z7_rm.pdf)を確認します。すると、クロックとしては、125MHzがK17に入っていることが分かります。また、LEDはM14、M15、G14、D18に接続していることが分かります。(LEDに関してはボード上のシルクでも確認できますし、前回使ったのと同じです。)　ちなみに、前回までは`FCLK_CLK0`というクロックがありました。これは、PSが内部のPLLを使って作り出しているものです。今回はPLのみなので、これは使えません。

![03.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/60d84c5c-39a9-3d39-7eb1-6f72a511de1b.jpeg)
![04.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/987cfa98-2d8e-e26c-d907-209beabf7865.jpeg)

### 制約ファイルを作る
ピンアサインするというのは、配置配線ツールにとっては、「アサインされたピンに接続しなくてはいけない」という制約になります。ピンアサイン(制約)を定義する制約ファイル(xdcファイル)を作ります。Flow Navigator -> RTL ANALYSIS -> Open Elaborated Designをクリックします。その後、Schematicを開くと、下記のようにRTLレベルでのブロック図を確認できます。現在、blink.vがTop moduleとして使われているので、blink.vで定義したIOポートであるCLK, OUTがそのまま外部とのIOとなります。これらのIOポートに実際にピンを割り当てます。Schematicを開くと自動的に画面下部にI/O Portsという画面が表示されているはずなので、ここを以下のように設定します。（IOレベルはLVCMOS33じゃないとエラーになりました)

![05.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/1ae4da20-1883-8034-9619-3fedf2ed123d.jpeg)

設定したら、Ctrl-sでこの制約を保存します。ファイル名は適当にblink.xdcとしておきます。

## 実行する
Flow Navigator -> PROGRAM AND DEBUG -> Genate Bitstreamをクリックして、論理合成、配置配線、ビットストリームの作成までまとめて実行します。 
完了後、Open Hardware Managerします。HARDWARE MANAGERでOpen Target (Auto Connect)し、Zynqに接続します。その後、Program deviceで、今作成したビットストリームファイルを書き込みます。　すると、1秒間隔で4つのLEDが同時にチカチカ点滅するはずです。

![06.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/663e72b6-4387-a47c-68bc-db08b04335e9.jpeg)

# blink.vをIP(モジュール)として使う (簡易版)
そこそこの規模になると、複数のIPを組み合わせてシステムを作るというのが一般的だと思います。先ほど作ったblink.vをモジュールとして取り込むということをやってみようと思います。Vivado上でIP INTEGRATORを使うことで、簡単に行うことが出来ます。(IP INTEGRATOR自体は前回までも、PSを搭載するために使っていました。)

_補足
ここで紹介する方法は、いわゆる「IP化」ではありません。IPとしてパッケージにする方法については次回説明します。
ここで紹介する方法は「モジュール化」と表現するのが正しいと思うのですが、「RTLモジュールをモジュール化」という分かりづらい表現になってしまうので、あえて「IP化(簡易版)」と記載しています。_

## ベースとなるブロックデザインを用意する
Flow Navigator -> IP INTEGRATOR -> Create Block Designをクリックして、新しいブロックデザインを作ります。名前は適当にdesign_1としておきます。Diagramビューを見ると、最初は何もない空っぽです。そこに、Sourcesからblinkをドラッグ&ドロップします。

![07.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/bc189256-2466-b19e-3243-55465c6c1d33.jpeg)
![08.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/6c2abb58-ab8c-f506-a112-7ff81c4b44e3.jpeg)

## ブロックデザインのIOポートを用意する
最終的には、今作成したブロックデザインを外部のピンに接続したいのですが、現状、このブロックデザイン(design_1)はIOを持っていません。CLKとOUTはdesign_1内部のblinkIPのIOになります。このブロックデザイン(design_1)としてのIOを用意して、それにCLKとOUTを接続します。それぞれ、CLK_BLKとOUT_BLKとします。(名前は同じでもいいですが、接続関係を理解するために別の名前にしました)。

ポートを追加するためには、Diagramビュー上で右クリックして、Create Portを選びます。OUTは4bitなので、Create vectorにチェックをします。また、向きもOutputにします。その後、Diagramビュー上でマウスをドラッグ&ドラッグして接続します。
(または、blinkモジュールの端子上で右クリックして、「Make External」を選択でもOKです)

![09.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/77309ded-4ffc-260d-26d4-98be85fd320b.jpeg)

## ブロックデザインのコードとWrapperを作る
前回までのPSと同様の手順です。Sourcesタブ上のdesign_1で右クリックして、Generate Output ProductsとCreate HDL Wrapperします。

![10.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/daecebc1-ebaf-290e-321e-fdc41aae05d4.jpeg)

すると、階層構造が以下のように変わります。また、Top moduleが自動的にdesign_1_wrapperになります。

![11.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/3b7e455a-5fad-9449-59c3-84343ada5093.jpeg)

## ピンアサインをする
先ほどと同様に、Open Elaborated Designを選びます。デザインを作り直しますか? みたいなことを聞かれるので、OKをして、以下のように設定して、Ctrl-sで保存します。

![12.jpg](https://qiita-image-store.s3.amazonaws.com/0/214268/526601fd-cd15-dfbe-b33b-26f52b527c2a.jpeg)

### ノート
今回のように、後からboard.xdcを編集すると、xdcファイルには制約(ピン配置)がどんどん追加されていきます。先ほど設定したピン配置設定も残ったままです。今回は害はありませんが、気になる場合は直接xdcファイルを編集して削除してください。(他に方法はあるかもしれませんが。)

また、ZYBO用の制約ファイルがDigilentから配布されています(https://github.com/Digilent/ZYBO/tree/master/Resources/XDC )。これをベースに自分が使うピンだけ編集して使うというのもありだと思います。~~しかし、配布されている制約ファイルは初代ZYBO用です。僕が今使っているZ7-20とは異なるので、自分で作ることにしました。~~
(追記: https://github.com/Digilent/digilent-xdc/blob/master/Arty-Z7-20-Master.xdc にあった)

## 実行する
先ほどと同様に、ビットストリームを作成して書き込むことで、LEDがチカチカするはずです。ちなみに、書き込むビットストリームのファイル名は、先ほどはblink.bitでしたが今回はdesign_1_wrapper.bitに代わっているはずです。

# 参考資料
https://reference.digilentinc.com/_media/reference/programmable-logic/zybo-z7/zybo-z7_rm.pdf