Zynqを使ったカスタムデザインのIPが作りたくて、IPの生成方法をいろいろ調査しているのだが、どうもGUIを操作するものばかりでつまらない。
GUIの操作方法なんて一瞬で忘れてしまうので、tclとmakefileで一気に作れるような環境を用意しておきたい。
いろいろ調査していて、結局ZedBoardのIP生成ディレクトリのスクリプトにたどり着いた。
こちらのリポジトリは"project"と"library"のディレクトリに分かれており、libraryはVivadoのIPを生成するようなスクリプトが用意されている。
例えば、axi_clkgenというIPを作るためには、リポジトリ内でaxi_clkgenのリポジトリに移動してmake
を叩くだけである。
$ cd library/axi_clkgen $ make rm -rf *.cache *.data *.xpr *.log component.xml *.jou xgui *.ip_user_files *.srcs *.hw *.sim .Xil vivado -mode batch -source axi_clkgen_ip.tcl >> axi_clkgen_ip.log 2>&1
axi_clkgen_ip.tcl
を見てみると、以下のような構造になっている。各種サポート関数群 (adi_xxx
)は、 adi_ip.tcl
に格納されているので、これは必要ならば参照する。
source ../scripts/adi_env.tcl source $ad_hdl_dir/library/scripts/adi_ip.tcl adi_ip_create axi_clkgen adi_ip_files axi_clkgen [list \ "$ad_hdl_dir/library/common/ad_rst.v" \ "$ad_hdl_dir/library/xilinx/common/ad_mmcm_drp.v" \ "$ad_hdl_dir/library/common/up_axi.v" \ "$ad_hdl_dir/library/common/up_clkgen.v" \ "axi_clkgen_constr.xdc" \ "axi_clkgen.v" ] adi_ip_properties axi_clkgen ipx::remove_bus_interface {clk} [ipx::current_core] ipx::associate_bus_interfaces -busif s_axi -clock s_axi_aclk [ipx::current_core] set_property driver_value 0 [ipx::get_ports *clk2* -of_objects [ipx::current_core]] adi_ip_constraints axi_clkgen [list \ "axi_clkgen_constr.xdc" ] ipx::save_core [ipx::current_core]
どうやら必要なのは、
adi_ip_create
でIPを生成する。adi_ip_files
でコンパイル対象のファイル群を指定する。adi_ip_properties
でコンパイル対象プロジェクトのプロパティを設定する。- 各種バスや製薬の設定。
adi_ip_constraints
で制約条件の設定。- `ipx::save_core でIPの保存。
上記の構成を真似て、オリジナルのIPを作ってみる。ベースはまずはGUI生成したものからとってる来るが、インタフェースを合わせて合成できるようにする。
注意する点としては adi_ip_properties
で設定するインタフェースの信号名と合わせておいた方がよい。
- adi_ip.tcl
proc adi_ip_properties {ip_name} { adi_ip_properties_lite $ip_name ipx::infer_bus_interface {\ s_axi_awvalid \ s_axi_awaddr \ s_axi_awprot \ s_axi_awready \ s_axi_wvalid \ ...
- blockram_test_v1_0.v
// Ports of Axi Slave Bus Interface S00_AXI input wire s_axi_aclk, input wire s_axi_aresetn, input wire [C_S00_AXI_ID_WIDTH-1 : 0] s_axi_awid, input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s_axi_awaddr, input wire [7 : 0] s_axi_awlen, input wire [2 : 0] s_axi_awsize, input wire [1 : 0] s_axi_awburst, input wire s_axi_awlock, input wire [3 : 0] s_axi_awcache, input wire [2 : 0] s_axi_awprot, input wire [3 : 0] s_axi_awqos, input wire [3 : 0] s_axi_awregion, input wire [C_S00_AXI_AWUSER_WIDTH-1 : 0] s_axi_awuser,
最初、Verilog記述の方がs00_axi_...
という記述で全くコンパイルが通らなかったので不思議に思っていたのだが、s_axi_...
という記述に変更したら上手く行くようになった。
次に、これをVivadoに取り込んで、IPとして利用できるようにする。