ZYBO / Pmod / UART > PmodからUART接続してみた (UARTLITE使用)

```txt:動作確認
DIGILENT ZYBO
Vivado 2015.4 on Windows 8.1 pro(64bit)
3.3VのUARTシリアル変換IC
  - 今回は右記のもの使用 http://www.akafugu.jp/ja/posts/products/ftdi-adapter/ 
```

PmodコネクタからUART接続したい。

UARTLITEというものがあるらしい。

作業の主な流れは以下と大半がかぶる
http://qiita.com/7of9/items/2e714e66d4a6c78c4a02

## 関連資料

Pmodコネクタ http://www.marutsu.co.jp/contents/shop/marutsu/datasheet/595400.pdf

## Vivado

### プロジェクト作成

- Project Name: 160709_pmodUART
  - RTL Project (Do not specify sources at this time はチェックしておく)
- ZYBO指定

### Create Block Design

- Design name: design_1
- add IP: ZYNQ7 Processing System
- Run Block Automation
- add IP: AXI Uartlite
- Run Connection Automation
  - S_AXI
  - UART

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/ab49ae54-63e5-3343-bf41-2b13a8b8a9a4.png)

### UARTLITEの設定

初期設定では9600bps, Data Bits 8, No Parityになっている。今回はこのままで使う。

### HDL Wrapper作成

- Sourcesウィンドウにおいて、design_1上にて右クリックして「Create HDL Wrapper...」を選択する
  - Let Vivado manager wrapper and auto-update

### 制約ファイルの作成

XDCファイルを作っておく。
ZYBO用にDIGILENTからテンプレートファイルがあるが、ここでは新規作成する。

- Sourcesウィンドウにおいて、Constraints > constrs_1上にて右クリック、「Add Source」選択
- Add or create constraints選択して、Next
- Create Fileをクリック
- File name: pmodUART.xdc とした
- FinishをクリックしてAdd Sourcesウィンドウを閉じる

### Run Implementation実行

- Generate Bistreamまで実行してもエラーとなるので、Run Implementationを実行する
- Implementation Completedが表示されたらOpen Implementation Designを選択してOKをクリック
- 画面下のI/O Portsタブを選択して以下のように展開表示する
  - Scaler ports以下にある

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/43b75ac8-c54c-0e0f-dfc5-bfe4d1e80560.png)

### TX, RXの設定

ZYBOのPmodからTX, RXの信号線を接続するには以下の３つの設定が必要。

- I/O StdをdefaultからLVCMOS33などの固定値にする
- SiteにPmodのコネクタのピンを指定する
- Fixedのチェックをつける

http://www.marutsu.co.jp/contents/shop/marutsu/datasheet/595400.pdf
の以下の図を参考にPmod JEコネクタを使う。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/87f789f1-e0b6-5271-ffeb-8673e2982e0b.png)

上記のV12とW16をそれぞれRX, TXとして以下となった。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/1edaa95d-5111-5271-1add-3ac23737dcdb.png)


- Ctrl+Sで保存する
- Out of Date Designというウィンドウが出るのでOKをクリック
- Save Constraintsというウィンドウが出るのでSelect an existing fileを選択してOK (新規作成したpmodUART.xdcに上書きすることになる)

### XDCファイルの確認

上記によりpmodUART.xdcファイルが変更された。

- Open Block Designをクリック
- SourcesのConstraints > constrs_1 > pmodUART.xdcを開くと以下のように変更されている

```pmodUART.xdc
set_property IOSTANDARD LVCMOS33 [get_ports uart_rtl_rxd]
set_property IOSTANDARD LVCMOS33 [get_ports uart_rtl_txd]
set_property PACKAGE_PIN W16 [get_ports uart_rtl_rxd]
set_property PACKAGE_PIN V12 [get_ports uart_rtl_txd]
```

### Generate Bitstream

- Generate Bitstreamを実行する

### Export

- File > Export > Export Hardware...
  - Include bitstreamチェックしてOKクリック
- File > Launch SDK
  - OKクリック

## XSDK

プロジェクト作成

- File > New > Application Project
  - Project name: pmodUART
  - Nextクリック
  - Hellow Worldを選択してFinish
- Project ExplorerのpmodUART> src > helloworld.cを以下のソースに書換える。

```helloworld.c
#include "xparameters.h"
#include "xstatus.h"
#include "xuartlite.h"

#define UARTLITE_DEVICE_ID  ( XPAR_AXI_UARTLITE_0_DEVICE_ID )

int SendAndReceive(u16 DeviceId);

XUartLite UartLite;
u8 RecvBuffer[100];

int main(void)
{
    int Status;

    Status = SendAndReceive(UARTLITE_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    return XST_SUCCESS;

}

int SendAndReceive(u16 DeviceId)
{
    int Status;
    unsigned int ReceivedCount = 0;

    Status = XUartLite_Initialize(&UartLite, DeviceId);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    Status = XUartLite_SelfTest(&UartLite);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    // send
    u8 testmsg[] = "Hello from ZYBO\r\n";
    XUartLite_Send(&UartLite, testmsg, sizeof(testmsg));
    usleep(200000); // 200msec

    // recv
    while (1) {
        ReceivedCount += XUartLite_Recv(&UartLite,
                       RecvBuffer + ReceivedCount,
                       1);
        if (RecvBuffer[ReceivedCount - 1] == '\r') {
            break;
        }
    }

    print("You have received:");
    print(RecvBuffer);
    print("\r\n");

    return XST_SUCCESS;
}
```

上記の動作としては以下となる。

- ZYBOから"Hello from ZYBO\r\n"を送信
- ZYBOが改行つき文字列を受信待ち
- 受信した文字列をZYBOのPROG UART接続に出力

### 接続設定

今回はUART接続の相手側が必要。

相手側としては3.3Vでシリアル接続できる端末があればいい。
今回は以下のFTDIアダプタを使用した。
http://www.akafugu.jp/ja/posts/products/ftdi-adapter/ 

上記のドライバを設定して、TeraTermの通信ポートで接続するようにする。
その際、TeraTermでは以下の設定をしておく

- [設定]-[端末]のページにて「受信」を[CR+LF]にする
- [設定]-[端末]のページにて「送信」を[CR+LF]にする

CRだけの設定では受信した時に改行がされなかった。

上記のFTDIアダプタとZYBO間の接続は以下

- ZYBO Pmod JE: GND <--> FTDI:GND
- ZYBO Pmod JE: ピン1(TX) <--> FTDI:RX
- ZYBO Pmod JE: ピン2(RX) <--> FTDI:TX

...

- ZYBO側のTeraTermは115200bpsに設定する
- FTDI側のTeraTermは9600bpsに設定する


### 実行

- TeraTermなどを立ち上げて115200bpsにしておく
- ZYBOの電源投入
- メニュー Xilinx Tools > Program FPGA > Programをクリック
- Project ExplorerのpmodUART > Binaries > pmodUART.elf上で右クリックして、Run As > 1. Launch on Hardware (System Debugger)で実行する

FTDI側のTeraTermに「Hello from ZYBO」が表示され、ZYBOが受信待ち状態になる。

- FTDI側のTeraTerm側で任意の文字列を入力してEnterを入力 (例: hi, zybo + [Enter])

ZYBO接続側のTeraTermに上記入力文字列が以下のように表示される。


![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/623df6b1-dbaf-3a16-0340-ab12dd855e95.png)


## 補足

### UARTLITEサンプル

https://github.com/Xilinx/embeddedsw/tree/master/XilinxProcessorIPLib/drivers/uartlite/examples
にサンプルプログラムがある。

### XUartLite_Send()の後の待ち

```
    XUartLite_Send(&UartLite, testmsg, sizeof(testmsg));
    usleep(200000); // 200msec
```
のようにXUartLite_Send()の後に「待ち」を入れている。「待ち」がなく複数行を送信した時に受信側で改行まで受信されない症状が見られた。
送信処理を待ちなしで繰り返した場合に送信シフトレジスタ?のオーバーフローが起きているような感じだった。

待ち時間については、baud rateなど考慮して適宜調整することになる。