# SPDX-License-Identifier: MIT ################################################################### # Questa/ModelSim simulation helper # # Expected variables from the project Makefile: # SYN_FILES - RTL sources # TB_FILES - testbench sources # INC_FILES - include files, optional # SIM_TOP - simulation top module # SIM_DEFS - defines, optional # SIM_RUNTIME - run time, for example "10000 us" or "-all" # # Useful overrides: # make sim-questa XILINX_VIVADO=/opt/Xilinx/Vivado/2024.2 # make sim-questa-gui ################################################################### .PHONY: sim-questa sim-questa-gui questa-clean questa-xpm-clean VLIB ?= vlib VMAP ?= vmap VLOG ?= vlog VSIM ?= vsim QUESTA_WORK_LIB ?= work QUESTA_XPM_LIB ?= xpm QUESTA_DIR ?= questa_build QUESTA_TRANSCRIPT ?= transcript XILINX_VIVADO=/tools/Xilinx/2025.1/Vivado SIM_RUNTIME ?= 10000 us QUESTA_RUN ?= run $(SIM_RUNTIME) # XPM is needed by this design because accum.sv uses xpm_memory_sdpram and # out_axis_fifo.sv uses xpm_fifo_async. Point XILINX_VIVADO to your Vivado # install if it is not already exported by settings64.sh. QUESTA_USE_XPM ?= 1 QUESTA_XPM_SRC = \ $(XILINX_VIVADO)/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv \ $(XILINX_VIVADO)/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv \ $(XILINX_VIVADO)/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv QUESTA_GLBL_SRC = $(XILINX_VIVADO)/data/verilog/src/glbl.v QUESTA_DEFS = $(foreach d,$(SIM_DEFS),+define+$(d)) QUESTA_INC_DIRS = $(sort $(dir $(SYN_FILES) $(TB_FILES) $(INC_FILES))) QUESTA_INCS = $(foreach d,$(QUESTA_INC_DIRS),+incdir+$(d)) QUESTA_LIBS = $(if $(filter 1,$(QUESTA_USE_XPM)),-L $(QUESTA_XPM_LIB),) QUESTA_SOURCES = $(SYN_FILES) $(TB_FILES) $(if $(wildcard $(QUESTA_GLBL_SRC)),$(QUESTA_GLBL_SRC),) QUESTA_GLBL_TOP = $(if $(wildcard $(QUESTA_GLBL_SRC)),$(QUESTA_WORK_LIB).glbl,) $(QUESTA_DIR): mkdir -p $@ $(QUESTA_DIR)/sources.f: Makefile | $(QUESTA_DIR) @rm -f $@ @for inc in $(QUESTA_INCS); do echo $$inc >> $@; done @for src in $(QUESTA_SOURCES); do echo $$src >> $@; done $(QUESTA_DIR)/xpm.stamp: | $(QUESTA_DIR) @if [ "$(QUESTA_USE_XPM)" = "1" ]; then \ if [ -z "$(XILINX_VIVADO)" ]; then \ echo "ERROR: XILINX_VIVADO is not set. Source Vivado settings64.sh or pass XILINX_VIVADO=/path/to/Vivado/."; \ exit 1; \ fi; \ for src in $(QUESTA_XPM_SRC); do \ if [ ! -f $$src ]; then \ echo "ERROR: XPM source not found: $$src"; \ exit 1; \ fi; \ done; \ $(VLIB) $(QUESTA_XPM_LIB); \ $(VMAP) $(QUESTA_XPM_LIB) $(QUESTA_XPM_LIB); \ $(VLOG) -sv -work $(QUESTA_XPM_LIB) $(QUESTA_XPM_SRC); \ fi @touch $@ $(QUESTA_DIR)/compile.stamp: $(QUESTA_DIR)/sources.f $(SYN_FILES) $(TB_FILES) $(INC_FILES) $(QUESTA_DIR)/xpm.stamp $(VLIB) $(QUESTA_WORK_LIB) $(VMAP) $(QUESTA_WORK_LIB) $(QUESTA_WORK_LIB) $(VLOG) -sv -work $(QUESTA_WORK_LIB) $(QUESTA_DEFS) -timescale 1ns/1ps $(QUESTA_INCS) -f $(QUESTA_DIR)/sources.f @touch $@ sim-questa: $(QUESTA_DIR)/compile.stamp $(VSIM) -c $(QUESTA_LIBS) $(QUESTA_WORK_LIB).$(SIM_TOP) $(QUESTA_GLBL_TOP) -do "$(QUESTA_RUN); quit -f" sim-questa-gui: $(QUESTA_DIR)/compile.stamp $(VSIM) $(QUESTA_LIBS) -voptargs="+acc" $(QUESTA_WORK_LIB).$(SIM_TOP) $(QUESTA_GLBL_TOP) questa-clean: -rm -rf $(QUESTA_DIR) $(QUESTA_WORK_LIB) $(QUESTA_TRANSCRIPT) vsim.wlf *.wlf questa-xpm-clean: questa-clean -rm -rf $(QUESTA_XPM_LIB)