Vivadoで配布するプロジェクトでソースコードを秘密にしたいと思ったことはありませんか?
例えば、
- 商用のコアを作りたい人
- 商用じゃなくても、秘密にしたコアを持っている人
- 学生に実習用に渡すライブラリの中身を見せたくないTAさん
- 学生実験のソースが汚すぎてTAに見られたくない学生さん
- ・・
ソースを秘密にするには、いろいろな理由があると思います。
こういう場合、本来のVivadoの使い方は公開鍵を使って暗号化したものを配布するらしいのですが、NDAとかあって、すぐにできるものではありません。
そこで、誰もが簡単に、秘密IPを配布できる方法として、ネットリストを使った配布方法を紹介します。ネットリストというのは、HDLのソースを論理合成して、XILINXのプリミティブを当てはめたもので、要するにC言語に対するOBJファイルみたいなものです。
1.プロジェクトのディレクトリを作る
まずはプロジェクトのディレクトリを作ります。プロジェクトの本体とレポジトリを分けますが、そのほかにコアを生成するためのmycoreというディレクトリも作ります。全体の構造は下の図のようになります。
そして、Vivadoでプロジェクトの本体を作ります。Vivadoでのプロジェクトの作り方については詳しい説明は割愛します。
2.ISEでコアを作る
次に、XILINXのISE14.7を使って、コアのプロジェクトを作ります。コア名はledchikaとしました。Working Directoryがrepoのledchikaになっているところがポイントです。こうすると後で少し楽になります。
そしてプロジェクトを作ったら、VHDLのソースを書きます。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
library UNISIM;
use UNISIM.VComponents.all;
entity ledchika_core is
Port ( clk_ip : in STD_LOGIC;
pushsw_ip : in STD_LOGIC;
led_op : out STD_LOGIC_VECTOR (7 downto 0));
end ledchika_core;
architecture Behavioral of ledchika_core is
signal clk : std_logic;
signal pushsw : std_logic;
signal timer : std_logic_vector(21 downto 0);
signal counter : std_logic_vector(7 downto 0);
signal led : std_logic_vector(7 downto 0);
begin
clk <= clk_ip;
pushsw <= pushsw_ip;
process(clk) begin
if(clk'event and clk='1') then
timer <= timer + 1;
if(timer = 0) then
counter <= counter + 1;
if(pushsw = '0') then -- pushed!
if(counter(4) = '0') then
led <= x"ff";
else
led <= x"00";
end if;
else
led <= not counter;
end if;
end if;
end if;
end process;
led_op <= led;
end Behavioral;
このとき、entityの名前は〇〇_coreのようにしておくと良いでしょう。
そうしたら、Synthesisのところで右クリックし、オプションを出します。そして、Xilinx Specific Optionsのタブを開き、Add I/O Buffersのチェックを外します。
そして、Synthesisを実行します。
Working Directoryで指定したrepo/ledchikaの中にledchika_core.ngcというファイルができています。
これがネットリストです。
3.ラッパ用のVHDLファイルを作る
そうしたら、コア用のラッパを作ります。ラッパは何もせずに下位のモジュールを呼び出すだけのものを作ります。component文では、ISEで作ったコアのエンティティ名を指定します。
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity ledchika is
Port ( clk_ip : in STD_LOGIC;
pushsw_ip : in STD_LOGIC;
led_op : out STD_LOGIC_VECTOR (7 downto 0));
end ledchika;
architecture Behavioral of ledchika is
component ledchika_core is
Port ( clk_ip : in STD_LOGIC;
pushsw_ip : in STD_LOGIC;
led_op : out STD_LOGIC_VECTOR (7 downto 0));
end component;
begin
inst_ledchika : ledchika_core port map (
clk_ip => clk_ip,
pushsw_ip => pushsw_ip,
led_op => led_op
);
end Behavioral;
4.VivadoでIPのプロジェクトを作る
そして、Vivadoへ戻ってメインのプロジェクトからTools->Create and Package New IPを行います。
Package a specified directoryを行い、
先ほど作ったngcとラッパVHDのあるディレクトリを指定します。
出来上がったプロジェクトには、ラッパのledchika.vhdとNGCがデフォルトで登録されてますが、ツリーの中に入っていないので気持ちがわるいので、いったんngcを削除します。
そして、Add Sourceで改めてngcを登録します。
Copy sourcesのチェックは外しておきます。
これで、ラッパの下にngcが入っている構造が認識されました。
最後にPackagingして完成です。
5.メインのプロジェクトから呼び出す
そうしたら、作ったIPコアをブロックデザインで呼び出せるようにします。プロジェクトのsettingsのIPの中からRepositoryを選び、今つくったrepoフォルダを指定します。
サブディレクトリにあるIPコアが認識され、IPカタログから呼び出せるようになります。
こうして、足をつけて、
論理合成実行!
何事も問題なくBitstreamが作れました。
ちゃんと動きます。
6.IPコアのソースを書き換える
IPコアのソースを書き換えたときは、再びISEでSynthesisを行います。ngcが生成されるので、Vivadoはngcの更新を検知してIP Statusが起動します。
あとはいつも通りにRefresh IP Catalogを行って、Upgrade Selectedを行えばコアがアップデートされます。
IPコアをRefreshするためにサブVivadoを開く必要はない(メインのプロジェクトでボタンを押すだけな)ので、普通にIPコアを作るよりも楽かもしれません。
なお、ISEのプロジェクトとソースファイルはなくても、NGCとラッパVHDLがあれば論理合成はできるので、ソースを秘密にしたまま配布できるというわけです。
7.まとめと注意点
要点をまとめると、
- ISEに含まれるXSTを使ってVHDLからNGCを作る(そのとき、Add I/Oバッファは外しておく)
- component宣言と、つなぐだけのラッパVHDLを作る。componentの名前はXSTで作ったコアの名前に合わせておく。
- ラッパVHDLをIPコア化する。
- 全体の論理合成には、ラッパVHDLとNGCがあればよく、ソースのVHDLは不要。
ということです。
注意点/問題点としては、
- Kintexでやる場合は、UltrascaleがどうのというCritical Warningが出るのでNGCではなくEDIFでやったほうが良いかもしれない(Warningが少し減る)
- ISEを使うため、Coregenの新しいコアが使えない
- Genericでパラメータ化ができない
NGCではなくて、DCPを使えば上の問題は解決できると思うのですが、Vivadoの非プロジェクトモードでDCPを作る方法がわからないので、それは後日また試してみることにします。
NGCでのIPコアは配布はISEではよくやられていたのですが、最近ではあまり見なくなりました。この方法は古い方法なのですがVivadoでも使えることがわかりました。
ソースが秘密のIPを配布できると思うので、みなさんぜひ試してみてください。
最近のコメント