目录
1.概述
1.1简介
上一篇博客结束了如何通过Vivado调用Modelsim进行仿真,该过程无需繁琐的脚本编写过程,自动调用第三方软件执行仿真,非常方便。但在实际调试过程中会不断进行改错仿真的环节,此时直接在Modelsim中通过TCL脚本行仿真就更加一劳永逸。
本文结合实际的工程样例讲解如何通过编写TCL脚本实现对含bd/ip文件的被测工程快速构建仿真平台。
1.2准备
- 开发工具: vivado2022.2 ,Modelsim 10.5
- 示例工程:gitcode仓库链接
2.示例工程
2.1 文件结构
工程目录文件结构如下,每个文件夹作用已作标注。
2.1 被测样例
被测样例以AXI4总线为核心,挂载两个DDR4控制接口,一个axi4-bram模块,框图如下所示。
整个被测样例包含verilog文件(顶层)、BD文件(axi4-interconect模块)、IP核(DDR4、BRAM、clock等)。是一个典型的包含bd/ip的被测样例。
2.2 测试框架
本案例主要通过功能仿真测试被测样例的功能及语法正确性。因此仅对被测样例进行了简单的激励输入测试。整个测试框架如下图所示。
3.TCL脚本
3.1 资源库映射
由于被测样例包含bd/ip等文件,在功能仿真时需要用到xilinx提供的仿真库。在编写仿真脚本时要提前将编译好的资源库映射到工程中。
最简单的资源库的映射方法就是将库路径下的modelsim.ini文件拷贝到当前仿真工程路径下:
file copy -force [path_to_your_sim_lib]/modelsim.ini ./modelsim.ini
3.2 文件编译
- HDL文件编译
通常使用vlog或vcom命令编译用户的HDL文件,并将其映射到工作库(示例中的work)。
针对verilog/system verilog文件,可以使用“-incr”参数提高编译效率,有关vlog常用参数如下:
# vlog [options] files
# -work 声明工作库路径
# - incr 使能增量编译,提高编译速度
# -mfcu 当在命令行中进行编译操作时,命令行里包含的所有文件会组成一个编译单元。
# -sv 编译SystemVerilog
# +incdir+ 声明头文件路径
# -help 查看帮助
# 更多关于vlog命令的参数,可通过 “vlog -help”查看
- bd/ip文件编译
- 调用仿真网表文件
对于ip核文件,Vivado在生成IP文件时,同时生成了ip的仿真网表,对于fifo、bram、时钟管理等常见的简单IP,可以直接调用其仿真网表文件进行功能仿真。IP核对应文件夹下的*_simnetlist.v/*_simnetlist.vhd即为网表文件。示例工程中的clk_top、axi_bram两个IP就是直接调用的网表文件。 - 利用生成的仿真脚本
在生成IP文件时,vivado会为每个IP生成正对多种三方仿真软件的仿真脚本。这些脚本会被保存在工程路径下*.ip_user_files/sim_scripts文件夹。例如ddr4的仿真脚本如下所示。
- 调用仿真网表文件
vlib modelsim_lib/work
vlib modelsim_lib/msim
vlib modelsim_lib/msim/xil_defaultlib
vmap xil_defaultlib modelsim_lib/msim/xil_defaultlib
vcom -work xil_defaultlib -93 \
"../../../../../ip/ddr4_0/bd_0/ip/ip_0/sim/bd_9054_microblaze_I_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_1/sim/bd_9054_rst_0_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_2/sim/bd_9054_ilmb_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_3/sim/bd_9054_dlmb_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_4/sim/bd_9054_dlmb_cntlr_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_5/sim/bd_9054_ilmb_cntlr_0.vhd" \
vlog -work xil_defaultlib -incr -mfcu "+incdir+../../../../../ip/ddr4_0/ip_1/rtl/map" "+incdir+../../../../../ip/ddr4_0/rtl/ip_top" "+incdir+../../../../../ip/ddr4_0/rtl/cal" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_6/sim/bd_9054_lmb_bram_I_0.v" \
vcom -work xil_defaultlib -93 \
"../../../../../ip/ddr4_0/bd_0/ip/ip_7/sim/bd_9054_second_dlmb_cntlr_0.vhd" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_8/sim/bd_9054_second_ilmb_cntlr_0.vhd" \
vlog -work xil_defaultlib -incr -mfcu "+incdir+../../../../../ip/ddr4_0/ip_1/rtl/map" "+incdir+../../../../../ip/ddr4_0/rtl/ip_top" "+incdir+../../../../../ip/ddr4_0/rtl/cal" \
"../../../../../ip/ddr4_0/bd_0/ip/ip_9/sim/bd_9054_second_lmb_bram_I_0.v" \
vcom -work xil_defaultlib -93 \
"../../../../../ip/ddr4_0/bd_0/ip/ip_10/sim/bd_9054_iomodule_0_0.vhd" \
vlog -work xil_defaultlib -incr -mfcu "+incdir+../../../../../ip/ddr4_0/ip_1/rtl/map" "+incdir+../../../../../ip/ddr4_0/rtl/ip_top" "+incdir+../../../../../ip/ddr4_0/rtl/cal" \
"../../../../../ip/ddr4_0/bd_0/sim/bd_9054.v" \
"../../../../../ip/ddr4_0/ip_0/sim/ddr4_0_microblaze_mcs.v" \
vlog -work xil_defaultlib -incr -mfcu -sv "+incdir+../../../../../ip/ddr4_0/ip_1/rtl/map" "+incdir+../../../../../ip/ddr4_0/rtl/ip_top" "+incdir+../../../../../ip/ddr4_0/rtl/cal" \
"../../../../../ip/ddr4_0/ip_1/rtl/phy/ddr4_0_phy_ddr4.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/phy/ddr4_phy_v2_2_xiphy_behav.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/phy/ddr4_phy_v2_2_xiphy.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/iob/ddr4_phy_v2_2_iob_byte.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/iob/ddr4_phy_v2_2_iob.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/clocking/ddr4_phy_v2_2_pll.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_tristate_wrapper.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_riuor_wrapper.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_control_wrapper.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_byte_wrapper.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_bitslice_wrapper.sv" \
"../../../../../ip/ddr4_0/ip_1/rtl/ip_top/ddr4_0_phy.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_wtr.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ref.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_rd_wr.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_periodic.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_group.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_merge_enc.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_gen.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_fi_xor.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_dec_fix.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_buf.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ctl.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_cmd_mux_c.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_cmd_mux_ap.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_p.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_mux_p.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_c.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_a.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_act_timer.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_act_rank.sv" \
"../../../../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc.sv" \
"../../../../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_wr_data.sv" \
"../../../../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_rd_data.sv" \
"../../../../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_cmd.sv" \
"../../../../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_ar_channel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_aw_channel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_b_channel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_arbiter.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_fsm.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_translator.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_fifo.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_incr_cmd.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_r_channel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_w_channel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_wr_cmd_fsm.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_wrap_cmd.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_a_upsizer.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_register_slice.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_upsizer.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axic_register_slice.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_and.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_latch_and.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_latch_or.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_or.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_command_fifo.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator_sel.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator_sel_static.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_r_upsizer.sv" \
"../../../../../ip/ddr4_0/rtl/axi/ddr4_v2_2_w_upsizer.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_addr_decode.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_read.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_reg_bank.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_reg.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_top.sv" \
"../../../../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_write.sv" \
"../../../../../ip/ddr4_0/rtl/clocking/ddr4_v2_2_infrastructure.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_xsdb_bram.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_write.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_wr_byte.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_wr_bit.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_sync.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_read.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_rd_en.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_pi.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_mc_odt.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_debug_microblaze.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_cplx_data.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_cplx.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_config_rom.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_addr_decode.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_top.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_xsdb_arbiter.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_chipscope_xsdb_slave.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_v2_2_dp_AB9.sv" \
"../../../../../ip/ddr4_0/rtl/ip_top/ddr4_0_ddr4.sv" \
"../../../../../ip/ddr4_0/rtl/ip_top/ddr4_0_ddr4_mem_intfc.sv" \
"../../../../../ip/ddr4_0/rtl/cal/ddr4_0_ddr4_cal_riu.sv" \
"../../../../../ip/ddr4_0/rtl/ip_top/ddr4_0.sv" \
"../../../../../ip/ddr4_0/tb/ddr4_0_microblaze_mcs_0.sv" \
vlog -work xil_defaultlib \
"glbl.v"
通过上面的脚本可以看出,该脚本的仿真工程路径就在sim_examp_axi_ddr4.ip_user_files\sim_scripts\ddr4_0\modelsim,产生的文件也会被保存这个路径下,每个IP核的仿真脚本运行后生成的库都被保存在不同的路径下。
我们在编写仿真脚本时可以将路径指向这些文件夹,直接运行这些脚本,然后将生成的库映射到我们的工程中,实际操作起来会比较麻烦。
这里我选择最直接的办法,根据它提供的仿真脚本提取需要编译的文件,然后整个到我们的脚本中。整合后的编译脚本如下(DDR4部分):
vcom -work work -93 \
../../ip/ddr4_0/bd_0/ip/ip_0/sim/bd_9054_microblaze_I_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_1/sim/bd_9054_rst_0_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_2/sim/bd_9054_ilmb_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_3/sim/bd_9054_dlmb_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_4/sim/bd_9054_dlmb_cntlr_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_5/sim/bd_9054_ilmb_cntlr_0.vhd
vlog -work work -incr -mfcu +incdir+../../ip/ddr4_0/ip_1/rtl/map \
+incdir+../../ip/ddr4_0/rtl/ip_top \
+incdir+../../ip/ddr4_0/rtl/cal \
../../ip/ddr4_0/bd_0/ip/ip_6/sim/bd_9054_lmb_bram_I_0.v
vcom -work work -93 \
../../ip/ddr4_0/bd_0/ip/ip_7/sim/bd_9054_second_dlmb_cntlr_0.vhd \
../../ip/ddr4_0/bd_0/ip/ip_8/sim/bd_9054_second_ilmb_cntlr_0.vhd
vlog -work work -incr -mfcu +incdir+../../ip/ddr4_0/ip_1/rtl/map \
+incdir+../../ip/ddr4_0/rtl/ip_top \
+incdir+../../ip/ddr4_0/rtl/cal \
../../ip/ddr4_0/bd_0/ip/ip_9/sim/bd_9054_second_lmb_bram_I_0.v
vcom -work work -93 \
../../ip/ddr4_0/bd_0/ip/ip_10/sim/bd_9054_iomodule_0_0.vhd
vlog -work work -incr -mfcu +incdir+../../ip/ddr4_0/ip_1/rtl/map \
+incdir+../../ip/ddr4_0/rtl/ip_top \
+incdir+../../ip/ddr4_0/rtl/cal \
../../ip/ddr4_0/bd_0/sim/bd_9054.v \
../../ip/ddr4_0/ip_0/sim/ddr4_0_microblaze_mcs.v
vlog -work work -incr -mfcu -sv +incdir+../../ip/ddr4_0/ip_1/rtl/map \
+incdir+../../ip/ddr4_0/rtl/ip_top \
+incdir+../../ip/ddr4_0/rtl/cal \
../../ip/ddr4_0/ip_1/rtl/phy/ddr4_0_phy_ddr4.sv \
../../ip/ddr4_0/ip_1/rtl/phy/ddr4_phy_v2_2_xiphy_behav.sv \
../../ip/ddr4_0/ip_1/rtl/phy/ddr4_phy_v2_2_xiphy.sv \
../../ip/ddr4_0/ip_1/rtl/iob/ddr4_phy_v2_2_iob_byte.sv \
../../ip/ddr4_0/ip_1/rtl/iob/ddr4_phy_v2_2_iob.sv \
../../ip/ddr4_0/ip_1/rtl/clocking/ddr4_phy_v2_2_pll.sv \
../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_tristate_wrapper.sv \
../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_riuor_wrapper.sv \
../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_control_wrapper.sv \
../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_byte_wrapper.sv \
../../ip/ddr4_0/ip_1/rtl/xiphy_files/ddr4_phy_v2_2_xiphy_bitslice_wrapper.sv \
../../ip/ddr4_0/ip_1/rtl/ip_top/ddr4_0_phy.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_wtr.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ref.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_rd_wr.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_periodic.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_group.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_merge_enc.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_gen.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_fi_xor.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_dec_fix.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc_buf.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ecc.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_ctl.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_cmd_mux_c.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_cmd_mux_ap.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_p.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_mux_p.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_c.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_arb_a.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_act_timer.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc_act_rank.sv \
../../ip/ddr4_0/rtl/controller/ddr4_v2_2_mc.sv \
../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_wr_data.sv \
../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_rd_data.sv \
../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui_cmd.sv \
../../ip/ddr4_0/rtl/ui/ddr4_v2_2_ui.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_ar_channel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_aw_channel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_b_channel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_arbiter.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_fsm.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_cmd_translator.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_fifo.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_incr_cmd.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_r_channel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_w_channel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_wr_cmd_fsm.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_wrap_cmd.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_a_upsizer.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_register_slice.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axi_upsizer.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_axic_register_slice.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_and.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_latch_and.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_latch_or.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_carry_or.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_command_fifo.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator_sel.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_comparator_sel_static.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_r_upsizer.sv \
../../ip/ddr4_0/rtl/axi/ddr4_v2_2_w_upsizer.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_addr_decode.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_read.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_reg_bank.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_reg.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_top.sv \
../../ip/ddr4_0/rtl/axi_ctrl/ddr4_v2_2_axi_ctrl_write.sv \
../../ip/ddr4_0/rtl/clocking/ddr4_v2_2_infrastructure.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_xsdb_bram.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_write.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_wr_byte.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_wr_bit.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_sync.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_read.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_rd_en.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_pi.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_mc_odt.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_debug_microblaze.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_cplx_data.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_cplx.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_config_rom.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_addr_decode.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_top.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal_xsdb_arbiter.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_cal.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_chipscope_xsdb_slave.sv \
../../ip/ddr4_0/rtl/cal/ddr4_v2_2_dp_AB9.sv \
../../ip/ddr4_0/rtl/ip_top/ddr4_0_ddr4.sv \
../../ip/ddr4_0/rtl/ip_top/ddr4_0_ddr4_mem_intfc.sv \
../../ip/ddr4_0/rtl/cal/ddr4_0_ddr4_cal_riu.sv \
../../ip/ddr4_0/rtl/ip_top/ddr4_0.sv \
../../ip/ddr4_0/tb/ddr4_0_microblaze_mcs_0.sv
对bd源文件的编译方法与ddr4一致,此处就不再累述。
3.3 导入仿真
导入仿真时,尽量不要使用“-novopt”参数,尤其是被测样例含有GTX或DDR这种比较复杂的IP文件时,使用参数“-novopt”会导致仿真过程异常缓慢 。推荐使用参数 -voptargs=“+acc” 。
导入仿真需要注意的另一个问题就是资源库的导入。下面是几个比较常用的仿真库,被测样例包含IP或原语时,通常都会将这些资源库导入仿真。
# secureip - 安全IP库(用于加密或安全相关IP)
# unisims_ver -Xilinx原语仿真库(Verilog仿真)
# unimacro_ver -Xilinx宏仿真库(Verilog仿真)
# unifast_ver -Xilinx快速实现库(用于优化综合结果)
# simprims_ver -简化原语仿真库(VHDL仿真)
其他的仿真库根据实际需要进行导入,通常可以根据每个IP生成的仿真脚本simulate.do判断。例如,示例工程中ip和bd生成的compile.do文件如下:
# clk_top
vsim -voptargs="+acc " -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip -L xpm -lib xil_defaultlib xil_defaultlib.clk_top xil_defaultlib.glbl
# axi_bram
vsim -voptargs="+acc " -L blk_mem_gen_v8_4_5 -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip -L xpm -lib xil_defaultlib xil_defaultlib.axi_bram xil_defaultlib.glbl
# bd_top
vsim -voptargs="+acc " -L generic_baseblocks_v2_1_0 -L axi_infrastructure_v1_1_0 -L axi_register_slice_v2_1_27 -L fifo_generator_v13_2_7 -L axi_data_fifo_v2_1_26 -L axi_crossbar_v2_1_28 -L xil_defaultlib -L axi_protocol_converter_v2_1_27 -L axi_clock_converter_v2_1_26 -L blk_mem_gen_v8_4_5 -L axi_dwidth_converter_v2_1_27 -L unisims_ver -L unimacro_ver -L secureip -L xpm -lib xil_defaultlib xil_defaultlib.bd_top xil_defaultlib.glbl
# ddr4
vsim -voptargs="+acc " -L microblaze_v11_0_10 -L xil_defaultlib -L lib_cdc_v1_0_2 -L proc_sys_reset_v5_0_13 -L lmb_v10_v3_0_12 -L lmb_bram_if_cntlr_v4_0_21 -L blk_mem_gen_v8_4_5 -L iomodule_v3_1_8 -L unisims_ver -L unimacro_ver -L secureip -L xpm -lib xil_defaultlib xil_defaultlib.ddr4_0 xil_defaultlib.glbl
# xil_defaultlib 库即工作库
整理后得到最终的仿真导入命令:
vsim \
-voptargs="+acc" \
-L generic_baseblocks_v2_1_0 \
-L axi_infrastructure_v1_1_0 \
-L axi_register_slice_v2_1_27 \
-L axi_data_fifo_v2_1_26 \
-L axi_crossbar_v2_1_28 \
-L axi_protocol_converter_v2_1_27\
-L axi_clock_converter_v2_1_26 \
-L axi_dwidth_converter_v2_1_27 \
-L microblaze_v11_0_10 \
-L lib_cdc_v1_0_2 \
-L proc_sys_reset_v5_0_13 \
-L lmb_v10_v3_0_12 \
-L lmb_bram_if_cntlr_v4_0_21 \
-L blk_mem_gen_v8_4_5 \
-L iomodule_v3_1_8 \
-L secureip \
-L unisims_ver \
-L unimacro_ver \
-L unifast_ver \
-L simprims_ver \
-L xpm \
-L xilinx_vip \
-L fifo_generator_v13_2_7 \
glbl ddr4_tb
在导入仿真时如果缺少某个资源库,Modelsim会提示,根据提示查找添加即可。
3.4 注意事项
- 使用-voptargs="+acc"参数进行优化,加快仿真速度。
- 导入仿真库时注意资源库的链接,缺库时会报错,根据提示添加即可。
- 需要注意的是,具体的错误在LOG文件中其实没有被标红,需要用户仔细查找(在Modelsim的Transcript窗口可以通过Ctrl+F进行关键字搜索),如下图所示。
4.仿真
4.1 运行仿真
用modelsim进行仿真时可以不用新建工程,直接通过命令行执行仿真。打开Modelsim软件在下方的Transcript窗口输入:
cd g:/00_exp/example/sim_examp_axi_ddr4/sim/do
进入仿真工程路径,然后执行仿真:
do sim_axi4_ddr4_test.do
4.2 波形观察
由于没有过度优化,仿真的层级关系和代码一致,能观测到所有的信号,用户可以在GUI界面手动添加需要观测的波形。
在设置好进制、显示方式(数字/模拟)后,可以在wave窗口用ctrl+s将波形以do文件的形式保存。下一次执行仿真后,用do
命令直接导入波形进行查看。
#执行波形导入命令
do wave.do
单击wave窗口,选择wave->Format->Toggle leaf Names可隐藏信号名前面的路径。
5 总结
使用Modelsim进行功能仿真的步骤主要有:
- 器件库预编译
- 被测文件编译(HDL/BD/IP等)
- 导入仿真(资源库链接)
- 波形观测
如果用户不是特别熟悉,可以多看vivado中的样例工程仿真,学习官方的仿真脚本编写。自己尝试仿真几个工程,相信很快就能上手!