PYNQ というボードで Jupyter
Digilent から販売されている PYNQ というボードが Jupyter を標準で使用できます。FPGA との連携という面白いコンセプトの製品なので紹介します。
そして、その後、polyphony という Python から verilog を生成する高位合成ツールを使ってみます。
PYNQ ってなに?
PYNQ の詳細はここ を見てほしいと思います。Zynq という ARM + FPGA の SoC を搭載したボードです。この手のボードをかき集めている僕は速攻購入しました。
Pynq の P はパイソンの P。ボタンまでピンクにしてある念の入れよう。
HDMI OUT/HDMI IN がついていて何やら面白うだと思いませんか?じゃ、使ってみますか。
電源オン + ネットワークですぐ使える
通常、この手のボードはマニュアルを見ていろんなものつなげて、やれ IoT だとか夜中に叫びながら動かさなきゃいけないわけですが、このボードは昼間からサクッと使えます。電源をオンしてネットワークをつなげば、Windows なら http://pynq:9090 とブラウザで打つことで簡単につながります。
うらではどうやら Samba とか NetBIOS とかが動いて Windows のために名前解決しているみたいです。
サンプルの顔認識を使う(USBカメラから)
USB カメラを接続することで簡単に OpenCV の顔認識が使えます。FPGA はどこいった?って感じですが、とにかく手元に装備や準備がたりなくても使えてしまうのが特徴です。USB カメラさえない場合はファイルからの読み込みもできるようです。
HDMI 出力のビデオカメラがあれば、そこからも入力できます。HDMI の入力に FPGA をつかってるんですね。
結果が微妙ですけど、もうキャプチャするのに疲れたので、これで許して。とにかくできるんです。
Polyphony をインストールして実行
Polyphony という高位合成ツールをインストールします。pip3 install でたぶんできるはず。高位合成の何たるかはここでは端折って実際に使ってみます。かませるソースはつぎの Python コード。
from polyphony import testbench
def sum(l1:list):
def sub_sum(l2:list):
def sub_sub_sum(l2:list):
s = 0
for l in l2:
s += l
return s
return sub_sub_sum(l2)
return sub_sum(l1)
def list11(x):
data1 = [x, 1, 2]
data2 = [x, 1, 2, 3, 4, 5]
s1 = sum(data1)
s2 = sum(data2)
return s1 + s2 + x
@testbench
def test():
assert 18 == list11(0)
assert 21 == list11(1)
assert 24 == list11(2)
test()
なんかちょっとずるいですが、Jupyter から subprocess で実行。
でほら polyphony_out.v が出来ました。
これが出来た verilog コードだ!!
と全部載せたいのですが、911 行にも及ぶので割愛しております。
module sum_sub_sum_sub_sub_sum
(
input wire signed [31:0] l21_q,
input wire signed [12:0] l21_len,
input wire CLK,
input wire RST,
input wire sub_sub_sum_READY,
input wire sub_sub_sum_ACCEPT,
output reg signed [31:0] sub_sub_sum_OUT0,
output reg l21_req,
output reg signed [31:0] l21_d,
output reg signed [12:0] l21_addr,
output reg l21_we,
output reg sub_sub_sum_VALID );
ザックっと中略
begin
if (in_addr[ADDR_WIDTH-1] == 1'b1) begin
address = RAM_LENGTH + in_addr;
end else begin
address = in_addr;
end
end
endfunction // address
wire [ADDR_WIDTH-1:0] a;
assign a = address(ADDR);
assign Q = mem[read_addr];
assign LEN = RAM_LENGTH;
always @ (posedge CLK) begin
if (WE)
mem[ADDR] <= D;
read_addr <= a;
end
endmodule
その後どうする?
おそらく iverilog をインストールすればシミュレーションできるでしょう。Samba もあるので、うまくやると Vivado と連携して合成できると思います。まだそこまで達成してないからね。
書きかけの感じにも見えますが、これでおしまいです。