#Lチカはバンコクの喧騒と共に
Lチカ(LEDチカチカ)という造語は I さんが考えたらしい。とある雑誌かウェブメディアだか何だかの取材の時に「Lチカ」という言葉が舞い降りてきた。以後、様々なメディアで使われるようになる。Lチカだけでは飯のタネにならない。かといってLチカができなければ始まらない。FPGA の世界の「Hello World」的な存在だ。
Polyphony でも Lチカが出来ることは必須だ。やってみよう。
from polyphony import testbench, module, is_worker_running
from polyphony.io import Port
from polyphony.typing import bit
from configs import Config
@module
class Blink:
def __init__(self, interval):
self.led = Port(bit, 'out')
self.interval = interval
self.append_worker(self.main)
def main(self):
ff_led:bit = 1
while is_worker_running():
self.led(ff_led)
ff_led = ~ff_led
self._wait()
def _wait(self):
for i in range(self.interval // 2):
pass
blink = Blink(Config.INTERVAL)
Polyphony は Python のコードをコンパイルする。オブジェクト指向をサポートしていて class が扱える。加えて、実際の Verilog-HDL のインタフェースを容易に想像できるようにPort というクラスを用意している。ソース上の __init__ にある次の記述に注目してほしい。
self.led = Port(bit, 'out')
最初の引数の bit が型名で、次の 'out' が属性だ。1bit の out の信号線をイメージできると思う。
Lチカなので”光っている時は1を出力"、"暗いときは0を出力"(ここではそうしよう。負論理とかは考えない)と状態を持つ必要がある。1を出力している時間も重要になるだろう。余りに早すぎると、我々には光っているようには見えない。
状態を持ちスレッドのように常駐して外部とのやり取りをする実体をworker と定義した。ソフトウェア的にすでに意味のあるプロセスやスレッドといった名称は避けることにした。worker は関数で表現され、__init__ 内で append_worker でworker として登録される。
この Lチカのモジュールは main という関数(メソッド)が worker だ。この中でff_led という変数を 0 と 1 と交互にして、その値を Port の led に書き込んでいる。ff_led の名前から連想されるように、生成されるVerilog-HDL では FF(フリップフロップ) が生成される。
main からは _wait 関数(メソッド)がよばれ、for 文で空まわりすることで時間を稼いでいる。クロックの指定はないので interval の値をシステムに合わせて調整する必要がある。
コンパイル結果の一部を見てみよう。
module Blink_blink
(
input wire clk,
input wire rst,
output reg led
);
//ざっくりと中略
endmodule
使用者が気にしなくてはならないのは Verilog-HDL としての module のインタフェースだ。module 内のコードを気にしてはいけない。高位合成とはそういうものだ。
あとはこれを自分の FPGA のデザインに埋め込む必要がある。Vivado での組み込み例を示そう。クロックの供給とリセットの接続のためにZynq を使っているので大げさな感じになっているが、本質的にはBlink_blink の RTL モジュールだけでよい。