Intel® Cyclone V SoC のキット（Atlas）と PC を LAN ケーブルで繋ぎ、Python で UDP パケット通信させてみた

##目次
●[1.はじめに](#1はじめに)
●[2.環境](#2環境)
●[3.構成](#3構成)
●[4.コード](#4コード)
●[5.動作確認](#5動作確認)
●[6.おわり](#6おわり)

##1.はじめに
簡単に Python でパケット通信ができると聞き、
Intel® Cyclone® V SoC FPGA が搭載された DE0-nano-SoC（Atlas）と PC を
下記画像のように接続し試してみたので記事にしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/cd6bd745-338a-0fe6-f151-189134f5a801.png)

##2.環境
■ターゲット側
・使用ボード:
　Terasic 社 DE0-nano-SoC（Atlas）
　※Intel® Cyclone V SoC が搭載されています。

・Linux 環境:
　Rootfile System -> Angstrom
　Linux version -> 5.4.14-ltsi

・Python: 
　Python3.5.6
　※Python2.x ではエラーになります

■PC 側 
・OS:
 Windows® 10(64bit) バージョン 1803

・Python:
　Python3.8.3
　※Python3.x の環境があればどんな形でも問題ないと思います。
　※私の PC には Python3 を Anaconda でインストールしていたので、
　　今回はこちらを使用します。
　　Anaconda については下記をご参照ください。
　　https://www.anaconda.com/products/individual

##3. 構成 & 動作手順
■構成
ターゲット側である Atlas と PC が LAN ケーブルと UART で接続されています。
LAN ケーブル: PC とターゲット（Atlas） 間で UDP パケット通信
UART: PC 側からターゲット側（Atlas）を制御及びモニタ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/985d25b4-e993-222f-f297-69d9987e28f9.png)



■動作手順
a. PC 側で pc_side.py を実行し受信待機状態
b. ターゲット側(atlas) で target_side.py を実行し PC 側に UDP パケットの送信
c. PC 側で UDP パケットを受信
d. ターゲット側(atlas) へ UDP パケットの送信
e. ターゲット側(atlas) で UDP パケットを受信
f. "c" と "d" で PC が送受信した UDP パケットを Wireshark で確認

##4.コード
ターゲット側と PC 側でそれぞれ target_side.py と pc_side.py というファイル名の python コードを記述します。

```python:pc_side.py
import socket

print("Waiting for message!")

a = "How are you?"
aa = a.encode("utf-8")
    
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as packet:
    packet.bind(('169.254.191.20', 49152))
    while True:
        message, address = packet.recvfrom(1024)
        print("Received message -->> {}, From IP address -->> {}".format(message, address[0]))
        break
        
if aa in message:
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as packet:
        packet.sendto(b'I am fine.', (address[0], 49153))
```

```python:target_side.py
import socket

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as packet:
    packet.sendto(b'How are you?', ('169.254.191.20', 49152))

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as packet:
    packet.bind(('169.254.191.10', 49153))
    while True:
        message, address = packet.recvfrom(1024)
        print("Received message -->> {}, IP address -->> {}".format(message, address[0]))
        break
```

##5.動作確認

###a. PC 側で pc_side.py を実行し受信待機状態
pc_side.py を実行し、ターゲット側からの UDP パケットを待ち状態
※Anaconda に内包されている Jupyter Notebook 上で Python3 を実行しているため、
下記のようなフォーマットになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/2d9d5339-c10b-aeeb-8ef5-733e3aa43d4d.png)


###b. ターゲット側(atlas) で target_side.py を実行し PC 側に UDP パケットの送信
ターゲット側（atlas）で target_side.py を実行
※ターゲット側は Teraterm を用いて UART 経由で制御しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/ad6156ce-0be8-1628-f170-14054eb13e10.png)

※パケット送信コードは下記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/04051d01-5b53-566a-3445-03f71cfe042a.png)



###c. PC 側で UDP パケットを受信
PC がターゲット側（atlas）からの UDP パケットを受信。
受信したメッセージは "How are you?"。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/fd533ff8-0f78-6750-3bae-d0dfe42e2a71.png)

###d. ターゲット側(atlas) へ UDP パケットの送信
"c" で受信したメッセージが "How are you?" だったので、
ターゲット側（atlas）へ "I am fine." と送信。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/7eb5609f-f1ce-240b-162a-4e829ff96262.png)


###e. ターゲット側(atlas) で UDP パケットを受信
PC 側から UDP パケットを受信。
受信メッセージは "I am fine."。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/c1188444-409c-418d-7e68-e32c1e968757.png)


※受信情報出力のコードは下記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/cfe4bedc-0074-661d-621b-5a0904b4df8f.png)

###f. "c" で PC が受信した UDP パケットと "d" でターゲット（atlas）へ送信した UDP パケットを Wireshark で確認
まず Wireshark でイーサネットのパケット通信を確認すると、Protocol が UDP の転送を 2 つ発見。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/c69e488f-6af7-f665-3d9f-f7ad77793b38.png)



PC 側のイーサネットの IP アドレスが 169.254.191.20、
ターゲット側（atlas）の IP アドレスが 169.254.191.10。

つまり、
1 の Source:169.254.191.10 から Distination:169.254.191.20 への転送
　-->>ターゲット（atlas）から PC への転送
2 の Source:169.254.223.20 から Distination:169.254.191.10 への転送
　-->>PC からターゲット（atlas）への転送
ということになります。

1 と 2 を展開したものが下記になります。

● 1（ターゲット（atlas）から PC への転送）
"How are you?" と受信していることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/ff70e315-1da8-34ac-d907-c5ea50db4203.png)


● 2（PC からターゲット（atlas）への転送）
"I am fine." と送信していることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890170/723a3cac-e0bc-fa0f-7e3c-81e5a71dcb9c.png)


###6.おわり
最後まで記事を読んで頂きありがとうございます。
とても簡単に UDP パケット通信を Python で行うことができました。
また、Wireshark でパケット通信を可視化することができ、とても楽しかったです。
この記事を読んで興味を持たれた方は是非一度試してみてはいかがでしょうか。