2018.07.16

VivadoでIEEE-1735によるソースコード暗号化

製品を作る際に、ユーザがカスタマイズできるようにしたいけれども、FPGAのソースコードを公開したくないという場合があります。

そんな場合、どうすればよいでしょうか。ISEのころは、EDIFのネットリストで配ったり難読化を施したコードを配ったりすることもあったと思います。

VivadoではIEEE-1735という暗号化の方法がサポートされています。IEEE-1735を使うとVivadoの公開鍵であなたのソースコードを暗号化し、Vivadoでしかそれを解読できないので、秘密を守ることができるようになります。

やり方を説明します。

https://japan.xilinx.com/support/answers/68071.htmlのページを参考に、ライセンスが欲しい旨を英語でメールします。しばらくすると、ライセンスが追加された旨のメールが送られてくるので、XILINXのライセンスサイトに行きます。

すると、1735のライセンスが使えるようになっているので、Createします。

Enc_1

② ライセンスを生成するとメールでlicファイルが送られてくるので、これをVivadoに取り込みます。

Enc_2

これでVivadoで暗号化ができるようになります。

③ Vivadoのプロジェクトを作り、暗号化したいソースを作ります。

ここではD:/enctest/project_1/というフォルダにプロジェクトを作ります。

以下は暗号化させたいソースファイルの例です。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity led is
    Port ( clk_ip : in std_logic;
           din    : in STD_LOGIC_VECTOR(3 downto 0);
           dout   : out STD_LOGIC_VECTOR(3 downto 0));
end led;
architecture Behavioral of led is
begin
    process(clk_ip) begin
        if(clk_ip'event and clk_ip = '1') then 
            case din is
                when x"0" =>
                    dout <= "1000";
                when x"1" =>
                    dout <= "0100";
                when x"2" =>
                    dout <= "0010";
                when x"3" =>
                    dout <= "0001";
                when others =>
                    dout <= "0000";
            end case;
        end if;
    end process;
end Behavioral;

④ Keyファイルを作ります。

`protect version = 2
`protect encrypt_agent = "XILINX"
`protect encrypt_agent_info = "Xilinx Encryption Tool 2017"
`protect begin_commonblock
`protect control error_handling = "delegated"
`protect control runtime_visibility = "delegated"
`protect control child_visibility = "delegated"
`protect control decryption=(activity==simulation) ? "false" : "true"
`protect end_commonblock
`protect begin_toolblock
`protect rights_digest_method="sha256"
`protect key_keyowner = "Xilinx", key_keyname= "xilinxt_2017_05", key_method = "rsa", key_public_key
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxngMPQrDv/s/Rz/ED4Ri
j3tGzeObw/Topab4sl+WDRl/up6SWpAfcgdqb2jvLontfkiQS2xnGoq/Ye0JJEp2
h0NYydCB5GtcEBEe+2n5YJxgiHJ5fGaPguuM6pMX2GcBfKpp3dg8hA/KVTGwvX6a
L4ThrFgEyCSRe2zVd4DpayOre1LZlFVO8X207BNIJD29reTGSFzj5fbVsHSyRpPl
kmOpFQiXMjqOtYFAwI9LyVEJpfx2B6GxwA+5zrGC/ZptmaTTj1a3Z815q1GUZu1A
dpBK2uY9B4wXer6M8yKeqGX0uxDAOW1zh7tvzBysCJoWkZD39OJJWaoaddvhq6HU
MwIDAQAB
`protect control xilinx_configuration_visible = "false"
`protect control xilinx_enable_modification = "false"
`protect control xilinx_enable_probing = "false"
`protect control xilinx_enable_netlist_export = "false"
`protect control xilinx_enable_bitstream = "true"
`protect control decryption=(xilinx_activity==simulation) ? "false" : "true"
`protect end_toolblock = ""

中央にある公開鍵の部分(緑色の部分)は、Vivadoをインストールしたフォルダの Vivado\2018.1\data\pubkey にあります。

protect controlの部分は、暗号化したコアがユーザにどのようなアクセスを許可するかを指定します。

  • xilinx_configuration_visible・・・VivadoビューワーでLUT値を表示できるかどうかを設定します。
  • xilinx_enable_modification・・・Vivadoツールで、保護領域内の情報を変更できるかどうかを設定します。
  • xilinx_enable_probing・・・Vivadoデバッグプローブを保護領域内に挿入できるかどうかを設定します。
  • xilinx_enable_netlist_export・・・保護領域のネットリストをエクスポートできるかどうかを指定します。
  • xilinx_enable_bitstream・・・Vivadoでビットストリームを生成できるようにします。

例えば、ビットストリームの生成を不可にすると、Generate Bitstreamで以下のようなエラーが出ます。

Enc_3

⑤ VivadoのTclコンソールで以下のコマンドを打つ

cd D:/enctest/project_1/src/
encrypt -key keyfile.txt -ext .vhdp -lang vhd led.vhd

こうすると、led.vhdからled.vhdpが生成されます。.vhdpの内容は以下のようになります。

`protect begin_protected
`protect version = 2
`protect encrypt_agent = "XILINX"
`protect encrypt_agent_info = "Xilinx Encryption Tool 2015"
`protect begin_commonblock
`protect control error_handling = "delegated"
`protect control runtime_visibility = "delegated"
`protect control child_visibility = "delegated"
`protect control decryption=(activity==simulation) ? "false" : "true"
`protect end_commonblock
`protect begin_toolblock
`protect rights_digest_method="sha256"
`protect key_keyowner = "Xilinx", key_keyname= "xilinxt_2017_05", key_method = "rsa", key_block
pdjNjyoCm2WBMs0KG3Q+ePaDB6ARbd7Y7H3A26a55OOdnew+1OzTUK2k96Ntxukr+wj/aCI2W080
iHpbvKfzLLHduvQ2c1dY3pwuILRpF/YrHydz3MK+Z2IVWvREP/HYxv29SL9MCchFczqEoILOZLfP
PqBHW8jMADoKFmexdPzUm3dx10P1hOGMQ5/4Twzq9dj1Ff3x0QHNcDwsuPj1ed1DXdXP9LAUlWAa
MSTo8PBOP9BHKipCYhrDYSWJqXrAqFtdwzMyixefO7cSleSt4QYoZ6wXS3cgV7hfxtgjsD+C2eu8
RnTUg7kB/iZJT93cNeLAopn9eFLt6Mo9mu1lMw==

`protect control xilinx_configuration_visible = "false"
`protect control xilinx_enable_modification = "false"
`protect control xilinx_enable_probing = "false"
`protect control xilinx_enable_netlist_export = "false"
`protect control xilinx_enable_bitstream = "true"
`protect control decryption=(xilinx_activity==simulation) ? "false" : "true"
`protect end_toolblock="Gvz94Xjb16LqWZIuHZl19gXgAJUP/A9Ayg7PWzSp71Q="
`protect data_method = "AES128-CBC"
`protect encoding = (enctype = "BASE64", line_length = 76, bytes = 464)
`protect data_block
vZGEdHA8Zx5d5yGCb7CGj0ZiCC7CbVudUtULGxqOfj8l+1wRnXKQ4uevKFe6wrMj+P8OXGSBZrl4
VPAnc7iJAC5jXR7TwXtDbO9YzXA8d6sPl2PEb9W/gdLZSEoPqcLfi7oG0pxYaSXzSur2BN9LDYX8
jTYhPDwhPQqOEUwDpmxHxYTqIo+lJEKGOkJDE/Gh2VQ1pZnP1huOVn6MD60nZRZ0CnNL2+zFtf8z
BggLumqLrIY+4yWGI/qLgeDL9zo/COv/AWBmJsb9oCRmBrEcPKOS86jX8nmVejTTuQJwxDId2h2p
w+tj7NFlIF3ay1x26G8UVrQvxxtUsqsfgj+IZ1hIiBr7b6Ae11p2zSKRzW9dQTW5nc1E6C7DzqlJ
6eTAnJ29y9AhU/zH4Q1WBVHlutg0wAANMIwEEjLH+9ZicjzZQBpIwG3A65e1ylAnLw8mCP6aeXTt
cSM2Mwfx+GSWOaJCaymED+E1w6qGw6efC2vdeTzIuedN2ejxDGG45uNzW8zhZGrb/oFToDwh2NaB
CAy3AXRgadtedUPE/mt9Jq0MXqDqh1aHv5e3x8Ebqbiq6tQsI8jUi7BhWis9fSG7kVP2jDTB257q
NX/VL7bljOo=
`protect end_protected

この最後にあるprotect data_block~protect end_protectedの間の暗号化された部分が、元のled.vhdに相当します。

このled.vhdは、人間が読んでもわかりませんが、Vivadoには元のled.vhdを復元できるので、論理合成できるというわけです。

⑥ ラッパを作る

上で暗号化した、led.vhd→led.vhdpは暗号化されていて使いにくいので、led_wrap.vhdというラッパを作ります。

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity led_wrap is
    Port ( clk_ip : in std_logic;
           din : in STD_LOGIC_VECTOR(3 downto 0);
           dout : out STD_LOGIC_VECTOR(3 downto 0));
end led_wrap;

architecture Behavioral of led_wrap is
    component led
        Port ( clk_ip : in std_logic;
           din : in STD_LOGIC_VECTOR(3 downto 0);
           dout : out STD_LOGIC_VECTOR(3 downto 0));
    end component;
begin

    u0 : led
    port map( clk_ip => clk_ip, din => din, dout => dout );

end Behavioral;

これで論理合成すれば、led.vhdが暗号化されたIPとなって、無事に回路が合成されます。

Enc_4

sun

いかがでしたでしょうか?

意外と簡単だったと思います。

ポイントは、

  • 暗号化ライセンスを取得してVivadoに機能追加する
  • keyファイルを作り、ユーザに与えたい権限を設定し、tclコマンドでVHDLファイルを暗号化する
  • vhdpファイルは、人間には読めないが、ツールにはVHDLと同じように使用可能

このような手順で、貴方のつくった回路の秘密が守られるので、ぜひ試してみてください。

| | コメント (0)

2018.07.12

JTAGチャレンジ基板(仮称)を作ります

JTAGチャレンジ基板(仮称)というものを作ります。

これはどういうものかというと、RXマイコン、Spartan-7、MAX10が乗った基板なのですが、基板にいろいろとミスが仕込んであって、動かないのです。

そのミスというのは、回路設計者や基板設計者がやりがちな、よくある設計ミスです。

クロックが来ていないとか、リセットがかからないとか、FPGAが起動しないとか・・そういうミスなのですが、本当の基板でやったら即作り直しになって、再設計費数十万円と1か月を無駄にするような、胃が痛くなるようなミスをたくさん仕込んであります。

Jtagchallenge

で、そんな動かない基板をどうするかというと、MITOUJTAGを使えばそういうミスが一瞬で発見できるということを体験してもらおうというわけです。

MITOUJTAGというのは、世界で一番最初にJTAGバウンダリスキャンを組み込み回路のデバッグに活用できるようにしたツールです。

http://www.tokudenkairo.co.jp/jtag/

今までは工場の出荷検査くらいにしか使われてこなかったJTAGバウンダリスキャンを、開発者ひとりひとりが自分の回路のために使えるようにしたツールなのです。

sun

たとえば、DDR3メモリのアドレス線が入れ替わっていたら、どうやってデバッグしますか?MIGを使って何度も作り直す?

たとえば、FPGAにクロックが入っていなかったら、どうやってデバッグしますか?Vivadoの内蔵JTAGアナライザはクロックがなかったら動きませんよね。

もし、6層基板の内層が切れていたら、どうやって発見しますか?片方のFPGAからテスト信号を出して、もう一個のFPGAでロジアナを動かす?そんなめんどくさいこと・・・

でも、内層が切れているかも・・・ということにどうやって気づきますか?

sun

JTAGの本来の機能は「バウンダリスキャン」といって、FPGAやCPUが動作しないレベルの致命的なバグがある基板でも使えるのです。

MITOUJTAGは、バウンダリスキャンを強力なデバッグ手段にすることができ、基板の間違いをもっと早期に、もっとストレスを感じない方法で見つけてもらいたいと思い、この基板を設計しています。

早ければ9月中にこの基板を使って最初のセミナーを開催できればと思っています。

| | コメント (0)

2018.07.08

ZynqberryでJupyter notebookが動いた!

何度目かの挑戦でようやくZynqberryでJupyterが動くようになりました。

参考にしたページは、この2つです。

ただし、ZYNQのUbuntu 14.04では上記のページのままのコマンドを実行してもうまくいきません。

  • pip installコマンドで、メモリ不足が出る
  • いくつかのモジュールが足りず、apt-getで足りないものを入れなければならない
  • Ubuntuに入っているPythonのバージョンが低くてpip install ipython[notebook]が通らない
  • sixというモジュールが自動的にはRemoveされない

という問題があるためです。

ARMのシステムにJupyterを入れるのに数時間は軽くかかります。一晩中放っておいたり、外出したりして、うまくいっていたらラッキーという感じです。

とにかく、Jupyterはインストールするのにものすごく時間がかかります。正しい手順を知っていても半日~1日はかかります。

そこで、Zynqberry用にJupyterをインストールしたSDカードイメージを作りました。Zynqberryスタータキットをご利用のお客様は、下記のURLのページからダウンロードできるようになります。

https://www.trenz.jp/download.html

ubuntu14-richというSDカードイメージを書き込めば、Ubuntu14.04上でJupyter (Python 3.5.1および2.7.12)が動くようになります。

sun

なおpyenvは/root/.pyenv/にインストールしてあるので、rootユーザしか起動できません。

使い方は、rootでログインした後、

export PYENV_ROOT=$HOME/.pyenv
export PATH=$PYENV_ROOT/bin:$PATH
eval "$(pyenv init -)"
pyenv global 3.5.1
eval "$(pyenv virtualenv-init -)"
pyenv virtualenv 3.5.1 dev1_3.5.1
pyenv local dev1_3.5.1
python -V
jupyter notebook --allow-root&

で起動できます。

Jupyter起動時のコンソールは

Jupyter4

こんな感じでした。

Webブラウザの画面には

Jupyter5

このような棒グラフが表示されています。

ネットで見つけてきたグラフ描画のスクリプトをいくつか実行してみます。

Jupyter1_2

Jupyter2_2

ちゃんと綺麗なグラフが描画されますね。

それから、Jupyterにはコンソールが付いているようで、これを使うとSSHでTeraTermに接続するということをユーザに強要しなくても、コマンドラインが使えるようになるのかなと思います。それと同時に大きなセキュリティホールにもなりますが。

Jupyter3

このコンソールは気を付けなければなりません。

| | コメント (0)

2018.06.29

ZYNQのLinux上でSDSoCを動かす方法

ZYNQのLinux上でSDSoCアプリを実行する方法をわかりやすく解説したチュートリアルにまとめました。

http://www.trenz.jp/tutorial/zbsdsoc-linux.html

Zbsdsoc1

Zynqberryが「FPGAで任意の関数をアクセラレートして高速に実行できるRaspberry Pi互換機」に近づきました。

下の図は、xの逆数を求めるFPGAのハードウェアをSDSoCで実装し、Linuxのアプリから動かしたものです。

Zbsdsoc2

機械学習や人工知能などFPGAならではのアプリを、ぜひともZynqberryで試してみてください。

| | コメント (0)

2018.06.28

ZYNQのLinux上でSDSoCアプリを動かすための条件

ZYNQのLinux上でSDSoCアプリを動かせる条件がわかってきました。

まとめると、

  • デバイスツリーにxlnkドライバを登録しておく
  • デバイスツリー・オーバーレイは採用はしなくてもよい。SDSoCで作るハードが変わっても、デバイスツリーに変化はないので、オーバーレイはしなくてもよい。
  • アプリを作り替えるたびの再起動やデバイスツリーの再構築はしなくてもよい。
  • U-Bootは普通のU-Bootでよい。
  • デバイスドライバとして、xlnk-eng.koとxlnk-dma.koとxlnk-apf.koが必要。ただし、これをビルドするのはかなり面倒。
  • Linuxのカーネルは4.9でよいが、/dev/xdevcfgが必要。
  • Linuxのカーネルを4.14に上げる必要はない
デバイスツリーは、/ {の中に
        xlnk {
             compatible = "xlnx,xlnk-1.0";
        };

を書いておきます。そして、

insmod /usr/bin/xlnk-eng.ko
insmod /usr/bin/xlnk-dma.ko
insmod /usr/bin/xlnk-apf.ko

でドライバをインストールします。この3つのドライバはこの順序でインストールします。

SDSoCのプロジェクトをビルドすると、sd_cardというフォルダに_sds/_p0_.binとelfが出来上がります。

この_sds/_p0_.binをsambaのファイル共有でZYNQシステム上にコピーして、

cat _sds/_p0_.bin > /dev/xdevcfg

でFPGAのPLに書き込んで、elfを実行すれば、SDSoCアプリが起動します。
Zbsdsoc3 Zbsdsoc4

パーシャル・リコンフィギュレーションは使用しませんが、XC7Z010では上のcatコマンドは一瞬で終了するので、パーシャルでなくても時間的には気になりません。

ただ、PLの全レジスタがクリアされてしまうので、HDMI出力機能とかに弊害は出てきます。

SDSoCのアプリが起動するとxlnk_engドライバが動いてハードウェア関数が実装されているのを探しますが、SDSoCのハードウェアが全く入っていないFPGAだとハングするようです。

また、ハードウェア関数が変わるとbitファイルも変わりますが、異なるデザイン用に作ったbitファイルを書き込んでしまっても、運がよければプログラムは実行できると思います。正しい結果にはならないでしょうが。

| | コメント (0)

2018.06.18

ZynqberryでSDSoCのアプリが動いた!

ついに、できました!!

ZynqberryでSDSoCのアプリが動くようになりました。

Zb

Zynqberryというのは、Raspberry Pi形状のFPGAボードでZYNQが乗っています。

ここにあるスタータキットを使うと、Ubuntuが動いて、apt-getで便利なコマンドがいろいろインストールできるようになってRasPiみたいになります。

http://www.trenz.jp/product/TE0726-STARTER-KIT/

私は、FPGAでアクセラレートできるRasPiを作りたいので、Zynqberryのアプリ(HW/SW)をSDSoCで開発する方法を確立しようとしています。

sun

プロジェクトやらファイルをいじっていたら、SD_CARDフォルダに起動用のboot.binが作られるようになりました。

Sdsoc_files

いずれはオリジナル・プラットフォームでSDSoCを使う手順を確立して手順書を作りたいと思いますが、まずはできあがったBoot.binを使って実際に動かしてみます。

動かしている回路は、XILINXのサンプルプログラムに入っている並列加算器のデモらしく、1024個の加算をするという、いかにもなものでした。高位合成をしたらこのような回路が出来上がっていました。

Zb_sdsoc_circuit

まずはハードウェアで実行したときのCPUのクロック数(?)を表示しています。

Zb_hw_acc_2

次はソフトウェアで実行したときのCPUのクロック数(?)です。

Zb_sw

確かに違いが出ていますね。

Estimate PerformanceをONにすると、プログラム全体と、ハードウェア化した関数の詳細なプロファイルを取ってくれるそうです。

Estim

が、結果を見てもよくわかりません。

Sdsoc_speedup

あまり高速になっていないような気もします。

データはBRAMに入れているようなので、1024個の加算を同時にやっているわけではないのでしょう。

SDSoCはデータ転送に相当なクロックサイクルを使うし、CPUがそもそも666MHzで動いているので、PLを100MHzかそこらで動かしても加速はたかが知れたものです。

SDSoCを試すなら、並列加算なんていうぬるいものではなく、もっとパワーが必要な演算回路を入れてやらねば真価を発揮しないということだと思います。

重い演算、どんとこい!

| | コメント (0)

2018.06.13

Zynqberryセミナーを開催しました

秋葉原にて、第4回目となるZynqberryセミナーを開催しました。

今回の参加者は6名でした。遠方から来ていただいた方もいらっしゃいました。

Zbs1

4回目にもなるとだいぶん慣れてきているはずなのですが、一昨日くらいに舌を噛んでしまった影響で、口内炎が痛くて活舌が悪くなっていたのが心残りです。

いままでで一番、丁寧に深く細かく説明できたセミナーではなかったかと思います。デバイスツリーのあたりで時間がなくなってしまったので、後半のデバイスツリーや、UIOの説明は駆け足で説明しました。セミナー資料のWebページはそのまま残してあるので、ご参加された方はどうぞダウンロードしてゆっくりお試しください。

sun

前回(5月)のセミナーでは、U-BootやLinuxカーネルのバージョンを指定していなかったので、GithubにあるU-bootが更新されていて会場でビルドに失敗するという大混乱を引き起こしましたが、今回はU-Bootは最新版でビルドできるようセミナー資料を更新したので、そういうことはなかったはずなのですが、実際には・・

Zbs2

Linuxに関してはバージョンを指定したため、そういうことはなかったと思いたいです。

| | コメント (0)

2018.06.12

ZynqberryのSDSoC対応(2)

SDSoCのチュートリアルや使用例のほとんどは、DDRメモリの中のデータとハードウェアアクセラレータの間でやりとりをしています。人工知能とか機械学習とか、画像処理とか、そういうメモリに籠ったアプリではそれがいいのでしょう。

そういう例では、メモリ上のデータをやりとりするだけなので、I/Oポートの設定はさほど気にならないのでしょう。SDSoCでI/Oピンを設定する方法が書かれたものは皆無です。XILINXのフォーラムにちょっとだけ質問が書かれていましたが、具体的な回答は書かれていません。

みんな、ZYBOとか使ってやっていて、自分でボード作る人はいないんでしょうか???

sun

私がやりたいことは、カメラや高速ADCですから、SDSoC8でピン配置を設定する方法を本気で探さなければなりません。

そこで、ZynqberryにHDMI出力やPWMなど、リッチな環境を入れて、さらにピン配置も指定した状態のSDSoC用のプラットフォームを作ってみました。

Zb_rich_sdsoc

まず、Trenz社提供のサンプル回路をベースにSDSoCプラットフォームを作りました。

しかし、このサンプル回路が曲者で、Vivado2017.3以降では論理合成が通らないのです。

苦労してデバッグして、ようやくその原因もわかって、対策もしましたが、Vivado2018.1では最終的にタイミングエラーが出てしまいます。

VivadoのプロジェクトをSDSoCに持っていって、いざ合成しようとしてみると、AXI RegsなどXILINXの標準IPのdriverがないと言われたり、ハードウェアのカスタムIPがないといわれるなどしましたが、SDSoCのプロジェクトの一時ディレクトリに無理やりコピーして何とか合成させました。

ただ、Vivadoでも出ていたタイミングエラーが原因となって、最終的にSDSoCもエラーで終わってしまいました。

なかなかうまくいきません。

| | コメント (0)

«ZynqberryのSDSoC対応