PYNQ というボードで Jupyter

Digilent から販売されている PYNQ というボードが Jupyter を標準で使用できます。FPGA との連携という面白いコンセプトの製品なので紹介します。
そして、その後、polyphony という Python から verilog を生成する高位合成ツールを使ってみます。

PYNQ ってなに?

PYNQ の詳細はここ を見てほしいと思います。Zynq という ARM + FPGA の SoC を搭載したボードです。この手のボードをかき集めている僕は速攻購入しました。

Pynq の P はパイソンの P。ボタンまでピンクにしてある念の入れよう。
IMG_0427.JPG

HDMI OUT/HDMI IN がついていて何やら面白うだと思いませんか?じゃ、使ってみますか。

電源オン + ネットワークですぐ使える

通常、この手のボードはマニュアルを見ていろんなものつなげて、やれ IoT だとか夜中に叫びながら動かさなきゃいけないわけですが、このボードは昼間からサクッと使えます。電源をオンしてネットワークをつなげば、Windows なら http://pynq:9090 とブラウザで打つことで簡単につながります。
うらではどうやら Samba とか NetBIOS とかが動いて Windows のために名前解決しているみたいです。

2016-12-13.png

サンプルの顔認識を使う(USBカメラから)

USB カメラを接続することで簡単に OpenCV の顔認識が使えます。FPGA はどこいった?って感じですが、とにかく手元に装備や準備がたりなくても使えてしまうのが特徴です。USB カメラさえない場合はファイルからの読み込みもできるようです。
HDMI 出力のビデオカメラがあれば、そこからも入力できます。HDMI の入力に FPGA をつかってるんですね。

結果が微妙ですけど、もうキャプチャするのに疲れたので、これで許して。とにかくできるんです。
2016-12-13 (3).png

Polyphony をインストールして実行

Polyphony という高位合成ツールをインストールします。pip3 install でたぶんできるはず。高位合成の何たるかはここでは端折って実際に使ってみます。かませるソースはつぎの Python コード。

list11.py
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 で実行。
2016-12-13 (4).png

でほら polyphony_out.v が出来ました。

2016-12-13 (5).png

これが出来た verilog コードだ!!

と全部載せたいのですが、911 行にも及ぶので割愛しております。

polyphony_out.v
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 と連携して合成できると思います。まだそこまで達成してないからね。

書きかけの感じにも見えますが、これでおしまいです。