はじめに
Xilinx 社のFPGA開発環境の Vivado、いちいち GUI でマウスボタンをポチポチするのは面倒です。
Vivado は Tcl スクリプトでバッチ処理が出来るので、決まり切った仕事なら Tcl スクリプトを書いて処理させたほうが楽です。
また、ユーザーが作った RTL を IP 化しておくと、Vivado の Block Design で利用したり、パラメーターを GUI から変更可能に出来たりして便利です。
この記事では、Vivado でユーザーが作った RTL を IP 化 する Tclスクリプトを解説します。
環境
- Xilinx Vivado 2023.1
- Xilinx Vivado 2025.1
Tclスクリプトの説明
1 あらかじめ使用する定数を定義しておく
この記事では、IP を作るための各種定数を設定しておく Tcl スクリプトを setting.tcl として用意しておきます。
例えばIP の名前(ip_name)、バージョン(ip_version/ip_core_revision)、ベンダー名(ip_vendor_name)、ライブラリ名(ip_library_name)、簡単な説明(ip_description)、IPを作るディレクトリ(ip_root_directory)を次のように定義しておきます。
また、IP を作る際は Vivado プロジェクトが必要になるので、そのプロジェクトの名前(project_name)と、プロジェクトを作るディレクトリ(project_directory) もあわせて定義しておきます。
この記事では『VHDL で書くマージソーター(ArgSort IP)』@Qiita で紹介した ArgSort IP を作る際に使用した Tcl スクリプトを例に示します。
#
# setting.tcl Tcl script for create project and generate IP
#
set ip_name "ArgSort_AXI"
set ip_version "1.7"
set ip_core_revision 1
set ip_vendor_name "ikwzm"
set ip_description "ArgSort_AXI"
set ip_library_name "Merge_Sorter"
set ip_root_directory [file join [file dirname [info script]] ".." "argsort_axi_$ip_version"]
set project_name "argsort_axi"
set project_directory [file join [file dirname [info script]] "work"]
set device_parts "xc7z010clg400-1"
IP を作る Tcl スクリプト(create_ip.tcl)の先頭には、上述の setting.tcl を読み込むようにしておきます。
#
# create_ip.tcl Tcl script for create project and generate IP
#
source [file join [file dirname [info script]] "setting.tcl"]
2 新しい空のプロジェクトを作る
まずまっさらのプロジェクトを作ります。なお、Vivado の新しいプロジェクトを作る Tcl スクリプトは以下の記事で別途紹介しています。詳しいことはそちらを参照してください。
この記事では、Tcl スクリプトのみをあげておきます。
#
# Create project
#
cd [file dirname [info script]]
create_project -force $project_name $project_directory
#
# Set project properties
#
set_property "part" $device_parts [get_projects $project_name]
set_property "default_lib" "xil_defaultlib" [get_projects $project_name]
set_property "simulator_language" "Mixed" [get_projects $project_name]
set_property "target_language" "VHDL" [get_projects $project_name]
#
# Create fileset "sources_1"
#
if {[string equal [get_filesets -quiet sources_1] ""]} {
create_fileset -srcset sources_1
}
#
# Create fileset "constrs_1"
#
if {[string equal [get_filesets -quiet constrs_1] ""]} {
create_fileset -constrset constrs_1
}
#
# Create fileset "sim_1"
#
if {[string equal [get_filesets -quiet sim_1] ""]} {
create_fileset -simset sim_1
}
#
# Create run "synth_1" and set property
#
if {[string equal [get_runs -quiet synth_1] ""]} {
create_run -name synth_1 -part $device_parts -flow "Vivado Synthesis 2014" -strategy "Vivado Synthesis Defaults" -constrset constrs_1
} else {
# set_property flow "Vivado Synthesis 2014" [get_runs synth_1]
set_property strategy "Vivado Synthesis Defaults" [get_runs synth_1]
set_property strategy "Flow_PerfOptimized_High" [get_runs synth_1]
}
current_run -synthesis [get_runs synth_1]
#
# Create run "impl_1" and set property
#
if {[string equal [get_runs -quiet impl_1] ""]} {
create_run -name impl_1 -part $device_parts -flow "Vivado Implementation 2014" -strategy "Vivado Implementation Defaults" -constrset constrs_1 -parent_run synth_1
} else {
# set_property flow "Vivado Implementation 2014" [get_runs impl_1]
set_property strategy "Vivado Implementation Defaults" [get_runs impl_1]
set_property strategy "Performance_Explore" [get_runs impl_1]
}
current_run -implementation [get_runs impl_1]
3 sources_1 にVHDLファイルを追加する。
この例ではVHDLファイルを追加する方法を説明していますが、同様の方法でVerilogファイルを追加することも出来るはずです。
VHDLファイルをsources_1 に追加する場合は次のようにします。
VHDLファイルは多数あることが多いので、まずはファイルセットに追加するためのプロシージャ(add_vhdl_file)を定義しておきます。
ファイルセットに追加する際、ファイルそのものをプロジェクトにコピーする場合は次のように import_files を使用します。
#
# Add files
#
proc add_vhdl_file {fileset_name library_name file_name} {
set file [file normalize $file_name ]
set fileset [get_filesets $fileset_name]
set file_obj [import_files -norecurse -fileset $fileset $file]
set_property "file_type" "VHDL" $file_obj
set_property "library" $library_name $file_obj
}
上記プロシージャを使って、追加したいVHDLファイルを指定します。
次のように追加したいVHDLファイルを別のスクリプトファイルと用意しておき(この例では add_sources.tcl)、そのファイルを読み込むことも可能です。
source add_sources.tcl
このような add_sources.tcl を作る際には、次の記事の「Create add_sources.tcl」も参考にしてください。
4 IP パッケージプロジェクトを作る
Vivado のプロジェクトから、さらに ipx::package_project を使って IP パッケージ専用のプロジェクトをつくります。
#
# Create IP-Package project
#
ipx::package_project -root_dir $ip_root_directory -vendor $ip_vendor_name -library $ip_library_name -taxonomy /UserIP -generated_files -import_files -force
5 バスインターフェースを指定する
IP が使うバスインターフェースを指定します。指定するバスインターフェースは IP によって異なります。この例(ArgSort IP)では、すでに Vivado で定義済みの AXI4 Memory Mapped と AXI4-Stream を指定しています。
#
# Infer Bus Interfaces
#
ipx::infer_bus_interfaces xilinx.com:interface:aximm_rtl:1.0 [ipx::current_core]
ipx::infer_bus_interfaces xilinx.com:interface:axis_rtl:1.0 [ipx::current_core]
なお、IP のポート名が Vivado で定義済みのバスインターフェースの命名規則にしたがっている場合は、自動認識するため、特にポートとのマッピングは必要ありません。例えば、ArgSort IP の entity は次のようになっています。
argsort_axi.vhd(長いので折りたたみ)
library ieee;
use ieee.std_logic_1164.all;
entity ArgSort_AXI is
generic (
MRG_WAYS : --! @brief MERGE WAY SIZE :
integer := 4;
MRG_WORDS : --! @brief MERGE WORD SIZE :
integer := 1;
WORD_BITS : --! @brief SORT WORD BIT SIZE :
integer := 32;
INDEX_BITS : --! @brief INDEX BIT SIZE :
integer := 32;
COMP_SIGN : --! @brief COMPARE SIGN :
boolean := FALSE;
SORT_ORDER : --! @brief SORT ORDER :
integer := 0;
SORT_SIZE_BITS : --! @brief SORT SIZE BITS :
integer range 1 to 32 := 28;
MRG_FIFO_SIZE : --! @brief MERGE FIFO SIZE :
integer := 16;
STM_FEEDBACK : --! @brief STREAM FEED BACK NUMBER :
integer := 0;
STM_IN_QUEUE_SIZE : --! @brief STREAM IN QUEUE SIZE :
integer := 0;
CSR_AXI_ADDR_WIDTH : --! @brief CSR I/F AXI ADDRRESS WIDTH :
integer := 12;
CSR_AXI_DATA_WIDTH : --! @brief CSR I/F AXI DATA WIDTH :
integer := 32;
STM_AXI_ADDR_WIDTH : --! @brief STREAM IN/OUT AXI ADDRESS WIDTH :
integer := 32;
STM_AXI_DATA_WIDTH : --! @brief STREAM IN/OUT AXI DATA WIDTH :
integer := 64;
STM_AXI_ID_WIDTH : --! @brief STREAM IN/OUT AXI ID WIDTH :
integer := 1;
STM_AXI_USER_WIDTH : --! @brief STREAM IN/OUT AXI ADDRESS USER WIDTH :
integer := 2;
STM_AXI_ID_BASE : --! @brief STREAM IN/OUT AXI ID BASE :
integer := 0;
STM_RD_AXI_XFER_SIZE: --! @brief STREAM IN AXI MAX XFER SIZE :
integer := 11;
STM_RD_AXI_BUF_SIZE : --! @brief STREAM IN AXI BUFFER SIZE :
integer := 0;
STM_RD_AXI_QUEUE : --! @brief STREAM IN AXI QUEUE SIZE :
integer := 4;
STM_RD_AXI_DATA_REGS: --! @brief STREAM IN AXI DATA REGISTER :
integer := 2;
STM_RD_AXI_ACK_REGS : --! @brief STREAM IN AXI ACKNOWLEDGE REGISTER :
integer range 0 to 1 := 1;
STM_WR_AXI_XFER_SIZE: --! @brief STREAM OUT AXI MAX XFER SIZE :
integer := 11;
STM_WR_AXI_BUF_SIZE : --! @brief STREAM OUT AXI BUFFER SIZE :
integer := 0;
STM_WR_AXI_QUEUE : --! @brief STREAM OUT AXI QUEUE SIZE :
integer := 4;
STM_WR_AXI_REQ_REGS : --! @brief STREAM OUT AXI REQUEST REGISTER :
integer range 0 to 1 := 1;
STM_WR_AXI_ACK_REGS : --! @brief STREAM OUT AXI ACKNOWLEDGE REGISTER :
integer range 0 to 1 := 1;
STM_WR_AXI_RESP_REGS: --! @brief STREAM OUT AXI RESPONSE REGISTER :
integer range 0 to 1 := 1;
MRG_AXI_ADDR_WIDTH : --! @brief MERGE IN/OUT AXI ADDRESS WIDTH :
integer := 32;
MRG_AXI_DATA_WIDTH : --! @brief MERGE IN/OUT AXI DATA WIDTH :
integer := 64;
MRG_AXI_ID_WIDTH : --! @brief MERGE IN/OUT AXI ID WIDTH :
integer := 1;
MRG_AXI_USER_WIDTH : --! @brief MERGE IN/OUT AXI ADDRESS USER WIDTH :
integer := 2;
MRG_AXI_ID_BASE : --! @brief MERGE IN/OUT AXI ID BASE :
integer := 0;
MRG_RD_AXI_XFER_SIZE: --! @brief MERGE IN AXI MAX XFER SIZE :
integer := 11;
MRG_RD_AXI_BUF_SIZE : --! @brief MERGE IN AXI BUFFER SIZE :
integer := 0;
MRG_RD_AXI_QUEUE : --! @brief MERGE IN AXI QUEUE SIZE :
integer := 4;
MRG_RD_AXI_DATA_REGS: --! @brief MERGE IN AXI DATA REGISTER :
integer := 2;
MRG_RD_AXI_ACK_REGS : --! @brief MERGE IN AXI ACKNOWLEDGE REGISTER :
integer range 0 to 1 := 1;
MRG_RD_ARB_NODE_NUM : --! @brief MERGE IN ARBITER NODE SIZE :
integer := 4;
MRG_RD_ARB_PIPELINE : --! @brief MERGE IN ARBITER PIPELINE :
integer := 0;
MRG_RD_PRE_STATE : --! @brief MERGE IN PRE STATE :
integer := 0;
MRG_WR_AXI_XFER_SIZE: --! @brief MERGE OUT AXI MAX XFER SIZE :
integer := 11;
MRG_WR_AXI_BUF_SIZE : --! @brief MERGE OUT AXI BUFFER SIZE :
integer := 0;
MRG_WR_AXI_QUEUE : --! @brief MERGE OUT AXI QUEUE SIZE :
integer := 4;
MRG_WR_AXI_REQ_REGS : --! @brief MERGE OUT AXI REQUEST REGISTER :
integer range 0 to 1 := 1;
MRG_WR_AXI_ACK_REGS : --! @brief MERGE OUT AXI ACKNOWLEDGE REGISTER :
integer range 0 to 1 := 1;
MRG_WR_AXI_RESP_REGS: --! @brief MERGE OUT AXI RESPONSE REGISTER :
integer range 0 to 1 := 1;
DEBUG_ENABLE : --! @brief DEBUG ENABLE :
integer range 0 to 1 := 0
);
port(
-------------------------------------------------------------------------------
-- Clock / Reset Signals.
-------------------------------------------------------------------------------
ACLK : in std_logic;
ARESETn : in std_logic;
-------------------------------------------------------------------------------
-- Control Status Register I/F AXI4 Read Address Channel Signals.
-------------------------------------------------------------------------------
CSR_AXI_ARADDR : in std_logic_vector(CSR_AXI_ADDR_WIDTH -1 downto 0);
CSR_AXI_ARVALID : in std_logic;
CSR_AXI_ARREADY : out std_logic;
------------------------------------------------------------------------------
-- Control Status Register I/F AXI4 Read Data Channel Signals.
------------------------------------------------------------------------------
CSR_AXI_RDATA : out std_logic_vector(CSR_AXI_DATA_WIDTH -1 downto 0);
CSR_AXI_RRESP : out std_logic_vector(1 downto 0);
CSR_AXI_RVALID : out std_logic;
CSR_AXI_RREADY : in std_logic;
------------------------------------------------------------------------------
-- Control Status Register I/F AXI4 Write Address Channel Signals.
------------------------------------------------------------------------------
CSR_AXI_AWADDR : in std_logic_vector(CSR_AXI_ADDR_WIDTH -1 downto 0);
CSR_AXI_AWVALID : in std_logic;
CSR_AXI_AWREADY : out std_logic;
------------------------------------------------------------------------------
-- Control Status Register I/F AXI4 Write Data Channel Signals.
------------------------------------------------------------------------------
CSR_AXI_WDATA : in std_logic_vector(CSR_AXI_DATA_WIDTH -1 downto 0);
CSR_AXI_WSTRB : in std_logic_vector(CSR_AXI_DATA_WIDTH/8 -1 downto 0);
CSR_AXI_WVALID : in std_logic;
CSR_AXI_WREADY : out std_logic;
------------------------------------------------------------------------------
-- Control Status Register I/F AXI4 Write Response Channel Signals.
------------------------------------------------------------------------------
CSR_AXI_BRESP : out std_logic_vector(1 downto 0);
CSR_AXI_BVALID : out std_logic;
CSR_AXI_BREADY : in std_logic;
-------------------------------------------------------------------------------
-- STREAM IN/OUT AXI4 Read Address Channel Signals.
-------------------------------------------------------------------------------
STM_AXI_ARID : out std_logic_vector(STM_AXI_ID_WIDTH -1 downto 0);
STM_AXI_ARADDR : out std_logic_vector(STM_AXI_ADDR_WIDTH -1 downto 0);
STM_AXI_ARLEN : out std_logic_vector(7 downto 0);
STM_AXI_ARSIZE : out std_logic_vector(2 downto 0);
STM_AXI_ARBURST : out std_logic_vector(1 downto 0);
STM_AXI_ARLOCK : out std_logic_vector(0 downto 0);
STM_AXI_ARCACHE : out std_logic_vector(3 downto 0);
STM_AXI_ARPROT : out std_logic_vector(2 downto 0);
STM_AXI_ARQOS : out std_logic_vector(3 downto 0);
STM_AXI_ARREGION : out std_logic_vector(3 downto 0);
STM_AXI_ARUSER : out std_logic_vector(STM_AXI_USER_WIDTH -1 downto 0);
STM_AXI_ARVALID : out std_logic;
STM_AXI_ARREADY : in std_logic;
-------------------------------------------------------------------------------
-- STREAM IN/OUT AXI4 Read Data Channel Signals.
-------------------------------------------------------------------------------
STM_AXI_RID : in std_logic_vector(STM_AXI_ID_WIDTH -1 downto 0);
STM_AXI_RDATA : in std_logic_vector(STM_AXI_DATA_WIDTH -1 downto 0);
STM_AXI_RRESP : in std_logic_vector(1 downto 0);
STM_AXI_RLAST : in std_logic;
STM_AXI_RVALID : in std_logic;
STM_AXI_RREADY : out std_logic;
-------------------------------------------------------------------------------
-- STREAM IN/OUT AXI4 Write Address Channel Signals.
-------------------------------------------------------------------------------
STM_AXI_AWID : out std_logic_vector(STM_AXI_ID_WIDTH -1 downto 0);
STM_AXI_AWADDR : out std_logic_vector(STM_AXI_ADDR_WIDTH -1 downto 0);
STM_AXI_AWLEN : out std_logic_vector(7 downto 0);
STM_AXI_AWSIZE : out std_logic_vector(2 downto 0);
STM_AXI_AWBURST : out std_logic_vector(1 downto 0);
STM_AXI_AWLOCK : out std_logic_vector(0 downto 0);
STM_AXI_AWCACHE : out std_logic_vector(3 downto 0);
STM_AXI_AWPROT : out std_logic_vector(2 downto 0);
STM_AXI_AWQOS : out std_logic_vector(3 downto 0);
STM_AXI_AWREGION : out std_logic_vector(3 downto 0);
STM_AXI_AWUSER : out std_logic_vector(STM_AXI_USER_WIDTH -1 downto 0);
STM_AXI_AWVALID : out std_logic;
STM_AXI_AWREADY : in std_logic;
-------------------------------------------------------------------------------
-- STREAM IN/OUT AXI4 Write Data Channel Signals.
-------------------------------------------------------------------------------
STM_AXI_WID : out std_logic_vector(STM_AXI_ID_WIDTH -1 downto 0);
STM_AXI_WDATA : out std_logic_vector(STM_AXI_DATA_WIDTH -1 downto 0);
STM_AXI_WSTRB : out std_logic_vector(STM_AXI_DATA_WIDTH/8-1 downto 0);
STM_AXI_WLAST : out std_logic;
STM_AXI_WVALID : out std_logic;
STM_AXI_WREADY : in std_logic;
-------------------------------------------------------------------------------
-- STREAM IN/OUT AXI4 Write Response Channel Signals.
-------------------------------------------------------------------------------
STM_AXI_BID : in std_logic_vector(STM_AXI_ID_WIDTH -1 downto 0);
STM_AXI_BRESP : in std_logic_vector(1 downto 0);
STM_AXI_BVALID : in std_logic;
STM_AXI_BREADY : out std_logic;
-------------------------------------------------------------------------------
-- MERGE IN/OUT AXI4 Read Address Channel Signals.
-------------------------------------------------------------------------------
MRG_AXI_ARID : out std_logic_vector(MRG_AXI_ID_WIDTH -1 downto 0);
MRG_AXI_ARADDR : out std_logic_vector(MRG_AXI_ADDR_WIDTH -1 downto 0);
MRG_AXI_ARLEN : out std_logic_vector(7 downto 0);
MRG_AXI_ARSIZE : out std_logic_vector(2 downto 0);
MRG_AXI_ARBURST : out std_logic_vector(1 downto 0);
MRG_AXI_ARLOCK : out std_logic_vector(0 downto 0);
MRG_AXI_ARCACHE : out std_logic_vector(3 downto 0);
MRG_AXI_ARPROT : out std_logic_vector(2 downto 0);
MRG_AXI_ARQOS : out std_logic_vector(3 downto 0);
MRG_AXI_ARREGION : out std_logic_vector(3 downto 0);
MRG_AXI_ARUSER : out std_logic_vector(MRG_AXI_USER_WIDTH -1 downto 0);
MRG_AXI_ARVALID : out std_logic;
MRG_AXI_ARREADY : in std_logic;
-------------------------------------------------------------------------------
-- MERGE IN/OUT AXI4 Read Data Channel Signals.
-------------------------------------------------------------------------------
MRG_AXI_RID : in std_logic_vector(MRG_AXI_ID_WIDTH -1 downto 0);
MRG_AXI_RDATA : in std_logic_vector(MRG_AXI_DATA_WIDTH -1 downto 0);
MRG_AXI_RRESP : in std_logic_vector(1 downto 0);
MRG_AXI_RLAST : in std_logic;
MRG_AXI_RVALID : in std_logic;
MRG_AXI_RREADY : out std_logic;
-------------------------------------------------------------------------------
-- MERGE IN/OUT AXI4 Write Address Channel Signals.
-------------------------------------------------------------------------------
MRG_AXI_AWID : out std_logic_vector(MRG_AXI_ID_WIDTH -1 downto 0);
MRG_AXI_AWADDR : out std_logic_vector(MRG_AXI_ADDR_WIDTH -1 downto 0);
MRG_AXI_AWLEN : out std_logic_vector(7 downto 0);
MRG_AXI_AWSIZE : out std_logic_vector(2 downto 0);
MRG_AXI_AWBURST : out std_logic_vector(1 downto 0);
MRG_AXI_AWLOCK : out std_logic_vector(0 downto 0);
MRG_AXI_AWCACHE : out std_logic_vector(3 downto 0);
MRG_AXI_AWPROT : out std_logic_vector(2 downto 0);
MRG_AXI_AWQOS : out std_logic_vector(3 downto 0);
MRG_AXI_AWREGION : out std_logic_vector(3 downto 0);
MRG_AXI_AWUSER : out std_logic_vector(MRG_AXI_USER_WIDTH -1 downto 0);
MRG_AXI_AWVALID : out std_logic;
MRG_AXI_AWREADY : in std_logic;
-------------------------------------------------------------------------------
-- MERGE IN/OUT AXI4 Write Data Channel Signals.
-------------------------------------------------------------------------------
MRG_AXI_WID : out std_logic_vector(MRG_AXI_ID_WIDTH -1 downto 0);
MRG_AXI_WDATA : out std_logic_vector(MRG_AXI_DATA_WIDTH -1 downto 0);
MRG_AXI_WSTRB : out std_logic_vector(MRG_AXI_DATA_WIDTH/8-1 downto 0);
MRG_AXI_WLAST : out std_logic;
MRG_AXI_WVALID : out std_logic;
MRG_AXI_WREADY : in std_logic;
-------------------------------------------------------------------------------
-- MERGE IN/OUT AXI4 Write Response Channel Signals.
-------------------------------------------------------------------------------
MRG_AXI_BID : in std_logic_vector(MRG_AXI_ID_WIDTH -1 downto 0);
MRG_AXI_BRESP : in std_logic_vector(1 downto 0);
MRG_AXI_BVALID : in std_logic;
MRG_AXI_BREADY : out std_logic;
-------------------------------------------------------------------------------
-- Interrupt Request
-------------------------------------------------------------------------------
INTERRUPT : out std_logic
);
end ArgSort_AXI;
上記のような entity の場合、Vivado は CSR_AXI_ で始まるポート群、STM_AXI_ で始まるポート群、MRG_AXI_ で始まるポート群を各々 CSR_AXI という AXI4-Lite Slave I/F、STM_AXI という AXI4 Memory Mapped Master I/F、MRG_AXI という AXI4 Memory Mapped Master I/F として解釈します。
自動認識されない場合は、Tcl スクリプトで手動でポートとマッピングする必要があります。あるいは、Vivado で自動認識できるようにポート名を変更するか、ポート名を変更したラッパーをかぶせたほうが簡単かもしれません。
6 サポートするデバイスを定義する
この例(ArgSort IP)では、ほとんどのデバイスをサポートしています。
#
# Set Supported Families
#
set_property supported_families {zynq Production virtex7 Production qvirtex7 Production kintex7 Production kintex7l Production qkintex7 Production qkintex7l Production artix7 Production artix7l Production aartix7 Production qartix7 Production zynq Production qzynq Production azynq Production zynquplus Production} [ipx::current_core]
7 IP の各種属性(property)を設定する
IP の名前(ip_name)、バージョン(ip_version/ip_core_revision)、簡単な説明(ip_description)を IP に設定します。
#
# Set Core Version
#
set_property version $ip_version [ipx::current_core]
set_property core_revision $ip_core_revision [ipx::current_core]
set_property name $ip_name [ipx::current_core]
set_property display_name $ip_name [ipx::current_core]
set_property description $ip_description [ipx::current_core]
8 IP の各種ファイル生成する
最後に各種ファイルを生成して ip_root_directory で指定したディレクトリに保存します。
#
# Generate files
#
ipx::create_xgui_files [ipx::current_core]
ipx::update_checksums [ipx::current_core]
ipx::save_core [ipx::current_core]
#
# Close and Done.
#
close_project
GUI の設定
この記事で紹介した Tcl スクリプトは IP として必要最低限のものしか作りません。そのままでも IP として使えないことはないのですが、Vivado の Block Design からパラメーターを設定する場合は、次のように少し GUI が貧弱です(というかパラメーターが多すぎてよくわからない)。
そこで次の記事で IP の GUI を変更する方法を紹介する予定です(近日公開)。
- 『Vivado で IP の GUI を整える Tclスクリプト』@Qiita
