フィボナッチを求める回路をSynthesijerとMessagePack-RPCでFPGAに実装してみた(ZYNQ編)

#はじめに
[フィボナッチを求める回路をSynthesijerとMessagePack-RPCでFPGAに実装してみた(シミュレーション編)](http://qiita.com/ikwzm/items/6b3e8120cc4ebbdd5a27)の続きです。
今回は Javaで記述してSynthesijerを使って高位合成したRTLを Zynq上に実装して Linuxから MessagePack-RPC で制御する例を示します。
ここでは次のような環境を使っています。

 - FPGA  : Xilinx Zynq Z-7010 AP SoC
 - Board : Digilent ZYBO
 - OS    : Linux 3.18 + Debian 8.2(jessie)

プロジェクトの全ソースコードは[こちら](https://github.com/ikwzm/msgpack-vhdl-examples/tree/master/examples/fibonacci)にあります。

#ブロック図

![akgeo1.jpg](https://qiita-image-store.s3.amazonaws.com/0/24981/27a5a198-6166-ce04-e07a-e92fa95bb9dd.jpeg)

#ソースコード

フィボナッチを求めるjavaのソースコードです。kazunori279さんの[フィボナッチをFPGAで書いてみた](http://qiita.com/kazunori279/items/70030eaa08fe632b6b49)を参考にしました。

````Java:Fib.java
public class Fib {
    public long fib(int n) {
        long cur  = 0;
        long next = 1;
        for (int i = 0; i < n; ++i) {
            long tmp = cur;
            cur = next;
            next += tmp;
        }
        return cur;
    }
}
````

#テスト用スクリプト

````ruby:fibonacci_server.rb
require 'msgpack'
require 'serialport'

class FibonacciServer

  def initialize
    @port     = SerialPort.new("/dev/zptty0", 38400)
    @port.read_timeout = 1000
    @port.flow_control = SerialPort::HARD
    @unpacker = MessagePack::Unpacker.new(@port)
    @msgid    = 0
  end

  def call(method, args)
    @msgid = (@msgid+1) % 256
    req = [0, @msgid, method, args].to_msgpack
    @port.write(req)
    @unpacker.each do |obj|
      type, resid, error, result = obj
      if (error == nil) then
        return result
      else
        puts error
        return nil
      end
      break
    end 
  end

  def fib(arg)
    return call('fib', [arg])
  end
end
````

````ruby:test.rb
require_relative 'fibonacci_server'

fib = FibonacciServer.new

(0..90).to_a.each do |n|
  f = fib.fib(n)
  puts "#{n} => #{f}"
end
````

#実行結果

````
shell% ruby test.rb
0 => 0
1 => 1
2 => 1
3 => 2
4 => 3
5 => 5
6 => 8
7 => 13
8 => 21
9 => 34
10 => 55
11 => 89
12 => 144
13 => 233
14 => 377
15 => 610
16 => 987
17 => 1597
18 => 2584
19 => 4181
20 => 6765
21 => 10946
22 => 17711
23 => 28657
24 => 46368
25 => 75025
26 => 121393
27 => 196418
28 => 317811
29 => 514229
30 => 832040
31 => 1346269
32 => 2178309
33 => 3524578
34 => 5702887
35 => 9227465
36 => 14930352
37 => 24157817
38 => 39088169
39 => 63245986
40 => 102334155
41 => 165580141
42 => 267914296
43 => 433494437
44 => 701408733
45 => 1134903170
46 => 1836311903
47 => 2971215073
48 => 4807526976
49 => 7778742049
50 => 12586269025
51 => 20365011074
52 => 32951280099
53 => 53316291173
54 => 86267571272
55 => 139583862445
56 => 225851433717
57 => 365435296162
58 => 591286729879
59 => 956722026041
60 => 1548008755920
61 => 2504730781961
62 => 4052739537881
63 => 6557470319842
64 => 10610209857723
65 => 17167680177565
66 => 27777890035288
67 => 44945570212853
68 => 72723460248141
69 => 117669030460994
70 => 190392490709135
71 => 308061521170129
72 => 498454011879264
73 => 806515533049393
74 => 1304969544928657
75 => 2111485077978050
76 => 3416454622906707
77 => 5527939700884757
78 => 8944394323791464
79 => 14472334024676221
80 => 23416728348467685
81 => 37889062373143906
82 => 61305790721611591
83 => 99194853094755497
84 => 160500643816367088
85 => 259695496911122585
86 => 420196140727489673
87 => 679891637638612258
88 => 1100087778366101931
89 => 1779979416004714189
90 => 2880067194370816120
````

#デザインフロー

##用意するもの

ZYNQ用に回路をインプリメンテーションするためには次の開発ツールを使います。

 - Xilinx Vivado 2015.3
 - Xilinx SDK 2015.3


テストスクリプトを実行するためには次の ruby パッケージが必要です。

 - msgpack-ruby
 - serialport


##リポジトリと各submodule をダウンロード

````
shell% git clone git://github.com/ikwzm/msgpack-vhdl-examples.git
shell% cd msgpack-vhdl-examples
shell% git submodule init
shell% git submodule update
````

##Fib.javaを高位合成

````
shell% export SYNTHESIJER=~/work/synthesijer/synthesijer/bin 
shell% cd examples/fibonacci/src/main/synthesijer
shell% make
````

なお、SYNTHESIJER　にはsynthesijerをインストールしているパスをしてください。

##IP-Packageを作る

具体的な手順は[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(IP-Package編)](http://qiita.com/ikwzm/items/924fc3fd59bdf7da55a2)と同様です。詳細はそちらを参照してください。
ここでは簡単に次のスクリプトを実行することでIPを作ります。

````
shell% cd examples/fibonacci/fpga/xilinx/zybo_test_synthesijer/ip
shell% vivado -mode batch -source create_ip.tcl
````

##論理合成～BOOT.binを作るまで

具体的な手順は[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(ZYNQ論理合成編)](http://qiita.com/ikwzm/items/0254f1d49602095b5cde)と同様です。詳細はそちらを参照してください。
ここでは以下の手順でBOOT.binを作ります。

###まずは論理合成

````
shell% cd examples/fibonacci/fpga/xilinx/zybo_test_synthesijer/project
shell% vivado -mode batch -source create_project.tcl
shell% vivado -mode batch -source implementation.tcl
````

###SDKのためにハードウェア情報をエクスポートする.

````
Vivado> File > Export > Export Hardware > Export to: > OK
````

これで project/project.sdk/design_1_wrapper.hdf が出来ます.

###SDKを起動する.

````
Vivado> File > Launch SDK > Exported location: Workspace: > OK
````

###FSBL(First Stage Boot Loader)を生成する.

````
SDK> File > New > Aplication Project
````

###u-bootを生成する.

このプロジェクトでは u-boot の作成は行いません. とりあえず適当に作った u-boot.elf を ./boot に入れておきました.

###BOOT.binを生成する.

````
shell% cd examples/fibonacci/fpga/xilinx/zybo_test_synthesijer/boot/
shell% bootgen -image u-boot.bif -w on -o BOOT.bin
````

##ZPTTYドライバをインストール

具体的な手順は[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(TTYドライバ編)](http://qiita.com/ikwzm/items/533b905f7d1eb2e6c4d5)と同様です。

#参照

[MessagePack for VHDL (https://github.com/ikwzm/msgpack-vhdl)](https://github.com/ikwzm/msgpack-vhdl)
[MessagePack for VHDL Examples (https://github.com/ikwzm/msgpack-vhdl-examples)](https://github.com/ikwzm/msgpack-vhdl-examples)
[MessagePack-RPCを使ってFPGAを制御](http://qiita.com/ikwzm/items/2644c6e50a7049c75d49)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(アーキテクチャ編)](http://qiita.com/ikwzm/items/6cb623b057a687ff4a8e)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(IP-Package編)](http://qiita.com/ikwzm/items/924fc3fd59bdf7da55a2)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(ZYNQ論理合成編)](http://qiita.com/ikwzm/items/0254f1d49602095b5cde)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(TTYドライバ編)](http://qiita.com/ikwzm/items/533b905f7d1eb2e6c4d5)
[Synthesijerで作ったモジュールをMessagePack-RPCで制御する(MessagePack-Ruby編)](http://qiita.com/ikwzm/items/f742e2c9b5d9642d8857)
[フィボナッチを求める回路をSynthesijerとMessagePack-RPCでFPGAに実装してみた(シミュレーション編)](http://qiita.com/ikwzm/items/6b3e8120cc4ebbdd5a27)