クリスマスなのでFPGAでクリスマスツリーを実装する　

## はじめに

何が楽しくて聖夜の夜にFPGAをいじってるのかわかりませんが、何故かクリスマスツリーを作ってみました。

![Xmas-Tree-0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/0c79b130-9e30-636d-2ae1-febe6ad6c193.gif)

やってることはとても簡単で、FPGAでLチカさせて、100均のツリーに飾りました。

また、今回はあえてハードウェア記述言語に触らず、Pythonによる高位合成(Polyphony)のみでやってみました。

## 環境
#### FPGAボード
- DE2-115

#### 言語・ライブラリ等
- Python3.6
- Polyphony(0.3.6)

#### その他
- ちょっと広めの机
- （電気を消しても怒られない環境）

## 実装
### Lチカ
LEDをチカチカさせること。通称Lチカ。

このLチカをPolyphonyの公式チュートリアルに沿って実装します。
参考: [ Python で FPGA これが Lチカだ](https://qiita.com/ryos36/items/fa814c1c7bb0936163e1)

というか、Polyphonyの開発者が「これが"Lチカ"だ」とおっしゃっていたので、これが"Lチカ"です。
恐れ多いですが、このコードを少しいじって、個人的に好きな書き方(や変数名)にしていきます。

```blink.py
from polyphony import testbench, module, is_worker_running
from polyphony.io import Port
from polyphony.typing import bit


# onとoffの数字に名前付け
ON = 1


def wait_1_clock():
    """
    for文中で 1 clock 何もしない
    """
    pass


@module
class Blink:
    """
    FPGAボードに乗っているLEDを光らせる
    """
    def __init__(self, interval):
        self.led = Port(bit, 'out')
        self.interval = interval
        self.append_worker(self.main)

    def main(self):
        # 初期化
        led_bit:bit = ON

        # waitの間隔でチカチカ光らせるループ
        while is_worker_running():
            self.led(led_bit)
            led_bit = ~led_bit  # OFF->ON, ON->OFF
            self._wait()

    def _wait(self):
        for _ in range(self.interval // 2):
            wait_1_clock()


blink = Blink(10)
```

`self.append_worker(self.main)`でIDEと自分の脳が🤔みたいな警告してきますが、無視して大丈夫です。

1bitの値の反転に`b=1-b`のような書き方をすることに違和感があったので、`b=~b`に書き換えました。
`for i in range(x):`の書き方も`i`を使ってないので`_`にしました。
for文の中もpassのみで見た目が悪かったので、無理やり`pass`に`wait_1_clock()`と名付けました。

コンパイルすると、Lチカするハードウェア記述言語のファイルが生成されます。

```bash
$ polyphony blink.py
```

#### Polyphonyの動作確認

そんなこんなで作ったLチカですが、本当にPythonでFPGAが動くのか？と不安があるのでテストをしてみました。

![wave (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/ba70116e-c66d-6d17-4e5c-619a81a43f60.png)

これを見た感じでは、LEDがチカチカするのできているようですが、１回チカチカさせるのに少しの遅延があり、`1 interval + 4 clock`ありそうです。
これにより、Pythonのプログラム中で`interval = interval - 4`ををすることで、正確な時間でチカチカさせる事ができます。

### 複数Lチカ

イメージではこんなものを作りたい。

![Xmas-Tree.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/cbe29ce4-9900-0ac0-f404-0c095db793a4.gif)


１秒毎にチカチカするLEDを0.5秒ずらして並べればできそうなので、先程のコードに継ぎ足していきます。

```blinks.py
from polyphony import testbench, module, is_worker_running
from polyphony.io import Port
from polyphony.typing import bit


# onとoffの数字に名前付け
OFF = 0
ON = 1


def wait_1_clock():
    """
    for文中で 1 clock 何もしない
    """
    pass


@module
class Blinks:
    """
    FPGAボードに乗っているLEDを光らせる
    """
    def __init__(self, interval):
        # 全18個分のLED
        self.led00 = Port(bit, 'out')
        self.led01 = Port(bit, 'out')
        self.led02 = Port(bit, 'out')
        self.led03 = Port(bit, 'out')
        self.led04 = Port(bit, 'out')
        self.led05 = Port(bit, 'out')
        self.led06 = Port(bit, 'out')
        self.led07 = Port(bit, 'out')
        self.led08 = Port(bit, 'out')
        self.led09 = Port(bit, 'out')
        self.led10 = Port(bit, 'out')
        self.led11 = Port(bit, 'out')
        self.led12 = Port(bit, 'out')
        self.led13 = Port(bit, 'out')
        self.led14 = Port(bit, 'out')
        self.led15 = Port(bit, 'out')
        self.led16 = Port(bit, 'out')
        self.led17 = Port(bit, 'out')
        self.led20 = Port(bit, 'out')
        self.led21 = Port(bit, 'out')
        self.led22 = Port(bit, 'out')
        self.led23 = Port(bit, 'out')
        self.led24 = Port(bit, 'out')
        self.led25 = Port(bit, 'out')
        self.led26 = Port(bit, 'out')
        self.led27 = Port(bit, 'out')
        self.interval = interval
        self.append_worker(self.main)

    def main(self):
        # 初期化
        led_bit_ptn0:bit = OFF
        led_bit_ptn1:bit = ON

        # waitの間隔でチカチカ光らせるループ
        while is_worker_running():
            self.led00(led_bit_ptn0)
            self.led01(led_bit_ptn1)
            self.led02(led_bit_ptn0)
            self.led03(led_bit_ptn1)
            self.led04(led_bit_ptn0)
            self.led05(led_bit_ptn1)
            self.led06(led_bit_ptn0)
            self.led07(led_bit_ptn1)
            self.led08(led_bit_ptn0)
            self.led09(led_bit_ptn1)
            self.led10(led_bit_ptn0)
            self.led11(led_bit_ptn1)
            self.led12(led_bit_ptn0)
            self.led13(led_bit_ptn1)
            self.led14(led_bit_ptn0)
            self.led15(led_bit_ptn1)
            self.led16(led_bit_ptn0)
            self.led17(led_bit_ptn1)
            self.led20(led_bit_ptn0)
            self.led21(led_bit_ptn1)
            self.led22(led_bit_ptn0)
            self.led23(led_bit_ptn1)
            self.led24(led_bit_ptn0)
            self.led25(led_bit_ptn1)
            self.led26(led_bit_ptn0)
            self.led27(led_bit_ptn1)
            led_bit_ptn0 = ~led_bit_ptn0  # OFF->ON, ON->OFF
            led_bit_ptn1 = ~led_bit_ptn1  # OFF->ON, ON->OFF
            self._wait()

    def _wait(self):
        for _ in range(self.interval):
            wait_1_clock()


# 1 interval = 1 clock = 50 MHz = 20 ns
# 1 s = 50,000,000*20 ns = 50,000,000 interval
# 4 clockの遅延を考慮
blink = Blink(49999996)
```

単純にLED(Portのインスタンス)を増やして、メインループもそれに対応させ、１秒のインターバルになるようにしました。

この後はPolyphonyでコンパイルして生成されたverilogコードをFPGA用のソフトウェアでコンパイルして、ピンを配置して、FPGAに書き込みして、などなどの作業がありますが、FPGAの知識が無いと少し難しいので省略します。


### 物理
最後にツリーの実装です。こちらもとてもかんたんで、ツリーにFPGAボードを乗せるだけです！

ただ、FPGAボードは重たいので、そのまま木の枝に乗せると落ちてしまいます。
なので、今回は「本」で主に支えて「プラスチックコップ」でバランスを保ち、木の枝を間から出す作戦を取りました。

イメージ図
![tree-base (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/564b7762-62c8-8fb6-e843-2d53824869f4.png)



あとは、それっぽい角度から写真を撮れれば完成です。

## 完成物

#### 明るいところver
![77465_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/0ec66d04-5bdf-6952-dfe9-473006466c42.jpeg)

#### 暗いところver
![77466_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/291273a7-f420-dadf-34ae-736eb4e88790.jpeg)

#### マウスとかVGAケーブルとか飾ってみたver
![77467_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280373/a7cfb8b5-ddc2-fa60-d08f-47dd595d7fc0.jpeg)

後ろのディスプレイにクリスマスっぽい画像を写すのがポイントです。

## ソースコード
[こちら](https://github.com/meihei3/x-mas-l-chika)