Ug937 Vivado Design Suite Simulation Tutorial
Ug937 Vivado Design Suite Simulation Tutorial
Ug937 Vivado Design Suite Simulation Tutorial
Tutorial
Logic Simulation
IMPORTANT: This tutorial requires the use of the Kintex®-7 family of devices or UltraScale
devices. If you do not have this device family installed, you must update your Vivado® tools
installation. Refer to the Vivado Design Suite User Guide: Release Notes, Installation, and
Licensing (UG973) for more information on Adding Design Tools or Devices to your
installation.
Introduction
This Xilinx® Vivado® Design Suite tutorial provides designers with an in-depth introduction to the
Vivado simulator.
VIDEO: You can also learn more about the Vivado simulator by viewing the quick take
video at Vivado Logic Simulation.
TRAINING: Xilinx provides training courses that can help you learn more about the concepts
presented in this document. Use these links to explore related courses:
Designing FPGAs Using the Vivado Design Suite 1 Training Course
Designing FPGAs Using the Vivado Design Suite 2 Training Course
Designing FPGAs Using the Vivado Design Suite 2 Training Course
The Vivado simulator is a Hardware Description Language (HDL) simulator that lets you perform
behavioral, functional, and timing simulations for VHDL, Verilog, and mixed-language designs. The
Vivado simulator environment includes the following key elements:
1. xvhdl and xvlog: Parsers for VHDL and Verilog files, respectively, that store the parsed files into
an HDL library on disk.
2. xelab: HDL elaborator and linker command. For a given top-level unit, xelab loads up all sub-
design units, translates the design units into executable code, and links the generated executable
code with the simulation kernel to create an executable simulation snapshot.
3. xsim: Vivado simulation command that loads a simulation snapshot to effect a batch mode
simulation, or a GUI or Tcl-based interactive simulation environment.
4. Vivado Integrated Design Environment (IDE): An interactive design-editing environment that
provides the simulator user-interface.
IMPORTANT: Tutorial files are configured to run the Vivado simulator in a Windows
environment. To run elements of this tutorial under the Linux operating system, some
file modifications may be necessary.
You can run the Vivado simulator in both Project Mode (using a Vivado design project to manage
design sources and the design flow) and in Non-Project mode (managing the design more directly). For
more information about Project Mode and Non-Project Mode, refer to the Vivado Design Suite User
Guide: Design Flows Overview (UG892).
Figure 1 shows a block diagram of the tutorial design.
RECOMMENDED: You modify the tutorial design data while working through this tutorial.
Use a new copy of the design files each time you start this tutorial.
Directories/Files Description
/completed Contains the completed files, and a Vivado 2019.x project of the
tutorial design for reference.
(x denotes the latest version of Vivado 2019 IDE)
/sources Contains the HDL files necessary for the functional simulation.
readme.txt readme.txt is a readme file about the contents and version history
of this tutorial design.
Linux Support:
Red Hat Enterprise Workstation 6.4 and 6.5 (32-bit and 64-bit)
SUSE Linux Enterprise 11 (32-bit and 64-bit)
Cent OS 6.4 and 6.5 (64-bit)
Refer to the Vivado Design Suite User Guide: Release Notes, Installation, and Licensing (UG973) for a
complete list and description of the system and software requirements.
Introduction
In this lab, you create a new Vivado Design Suite project, add HDL design sources, add IP from the
Xilinx IP catalog, and generate IP outputs needed for simulation. Then you run a behavioral simulation
on an elaborated RTL design.
6. In the Add Source dialog box, click Add Directories and add the extracted tutorial design data:
<Extract_Dir>/sources
<Extract_Dir>/sim
Note: You can press the Ctrl key to click and select multiple files or directories.
7. Set the Target Language to Verilog to indicate the netlist language for synthesis.
8. Set the Simulator Language to Mixed as seen in Figure 5.
The Simulator Language indicates which languages the logic simulator supports or requires. Vivado
Design Site ensures the availability of simulation models of any IP cores in the design by using the
available synthesis files to generate the required language-specific structural simulation model when
9. Click Next.
10. Click Next to bypass the Add Constraints dialog box.
In the Default Part dialog box (Figure 6), select Boards, and then select either Kintex-7 KC705
Evaluation Platform for 7-Series or Kintex-UltraScale KCU105 Evaluation Platform for UltraScale
devices and click Next.
Note: Add sources from subdirectories option is preselected.
Notice that the Sine wave generator (sinegen.vhd) references cells that are not found in the current
design sources. In the Sources window, the missing design sources are marked by the missing source
icon .
Note: The missing source icon is used to view only the missing sources. This is useful in viewing the
missing sources in larger designs.
Now, add the sine_high, sine_mid, and sine_low modules to the project from the Xilinx IP
Catalog.
The IP Catalog opens in the graphical windows area. For more information on the specifics of
the Vivado IDE, refer to the Vivado Design Suite User Guide: Using the Vivado IDE (UG893).
2. In the search field of the IP Catalog, type DDS.
The Vivado IDE highlights the DDS Compilers in the IP catalog.
3. Under any category, double-click the DDS Compiler.
The Customize IP wizard opens (Figure 9).
4. In the IP Symbol on the left, ensure that Show disabled ports is unchecked.
5. Specify the following on the Configuration tab:
o Component Name: type sine_high
o Configuration Options: select SIN COS LUT only
When the sine_high IP core is added to the design, the output products required to support the IP in
the design must be generated. The Generate Output Products dialog box displays, as shown in Figure
11.
The output products allow the IP to be synthesized, simulated, and implemented as part of the design.
For more information on working with IP cores and the Xilinx IP Catalog, refer to the Vivado Design
Suite User Guide: Design with IP (UG896). You can also work through the Vivado Design Suite Tutorial:
Designing with IP (UG939).
Click Generate to generate the default output products for sine_high.
When the sine_mid IP core is added to the design, the Generate Output Products dialog box
displays to generate the output products required to support the IP in the design.
6. Click Generate to generate the default output products for sine_mid. A dialog box opens saying
that the Out of context module run was launched for generating output products. Click OK.
When the sine_low IP core is added to the design, the Generate Output Products dialog box
displays to generate the output products required to support the IP in the design.
6. Click Generate to generate the default output products for sine_low. A dialog box opens saying
that the Out of context module run was launched for generating output products. Click OK.
3. In the Simulation tab, observe that the Simulation Run Time is 1000ns.
Introduction
The Vivado simulator GUI contains the Waveform window, and Object and Scope Windows. It provides
a set of debugging capabilities to quickly examine, debug, and fix design problems. See the Vivado
Design Suite User Guide: Logic Simulation (UG900) for more information about the GUI components.
In this lab, you:
Enable debug capabilities
Examine a design bug
Use debug features to find the root cause of the bug
Make changes to the code
Re-compile and re-launch the simulation
An HDL scope, or scope, is defined by a declarative region in the HDL code, such as a module,
function, task, process, or named blocks in Verilog. VHDL scopes include entity/architecture
definitions, blocks, functions, procedures, and processes.
3. In the Scopes window, click to select the dut object.
Observe the sine signal output in the waveform. The Wave window can be undocked from Main
window layout to view it as standalone.
2. Click the Float button in the title bar of the Waveform Configuration window.
3. Display the whole time spectrum in the Waveform window by clicking the Zoom Fit button
Notice that the low frequency sine output is incorrect. You can view the waveform in detail by
zooming into the Waveform window. When you zoom into the waveform, you can use the
horizontal and vertical scroll bars to pan down the full waveform.
As seen in Figure 19, when the value of sineSel is 0, which indicates a low frequency sine selection, the
analog sine[19:0] output is not a proper sine wave, indicating a problem in the design or the
testbench.
Note: Press and hold the Ctrl key, or Shift key, to select multiple signals.
2. With the signals selected right-click to open the popup menu and select New Group. Rename it as
TB Signals.
Vivado simulator creates a collapsed group in the waveform configuration window. To expand
the group, click to the left of the group name
3. Create another signal group called DUT Signals to group signals sine[19:0] and
sine_sel[1:0].
You can add or remove signals from a group as needed. Cut and paste signals from the list of
signals in the Waveform window, or drag and drop a signal from one group into another.
You can also drag and drop a signal from the Objects window into the Waveform window, or
into a group.
You can ungroup all signals, thereby eliminating the group. Select a group, right-click to open
the popup menu and select Ungroup.
To better visualize which signals belong to which design units, add dividers to separate the
signals by design unit.
Adding Dividers
Dividers let you create visual breaks between signals or groups of signals to more easily identify related
objects.
1. In the Waveform window, right-click to open the popup menu and select New Divider. The Name
dialog box opens to let you name the divider you are adding to the Waveform window.
2. Add two dividers named:
o Testbench
o SineGen
3. Move the SineGen divider above the DUT Signals group.
Simulation objects associated with the currently selected scope display in the Objects window.
By default, all types of simulation objects display in the Objects window. However, you can limit
the types of objects displayed by selecting the object filters at the top of the Objects window.
Figure 20 shows the Objects window with the Input and Output port objects enabled, and the
other object types are disabled. Move the cursor to hover over a button to see the tooltip for
the object type.
2. Hold Ctrl, and click to select the sine[19:0] signals listed in the Outputs group, under the
SineGen divider.
3. Right-click in the Waveform window to open the popup menu, and select the Name > Long
command.
The displayed name changes to include the hierarchical path of the signal. You can now see that
the sine[19:0] signals under the DUT Signals group refers to different objects in the design
hierarchy than the sine[19:0] signals listed under the Outputs group.
See Figure 22.
TIP: You can also load a previously saved waveform configuration file using the File >
Simulation Waveform > Open Configuration command.
An untitled Waveform window opens with a default name. You can add signals, define groups,
add dividers, set properties and colors that are unique to this Waveform window.
2. Select signal groups in the first Waveform window by pressing and holding the Ctrl key, and
selecting the following groups: Inputs, Outputs, and Internal Signals.
3. Right-click to open the popup menu, and select Copy, or use the shortcut Ctrl+C on the selected
groups to copy them from the current Waveform window.
4. Select the new Waveform window to make it active.
5. Right-click in the Waveform window and select Paste, or use the shortcut Ctrl+V to paste the signal
groups into the prior Waveform window.
6. Select File > Simulation Waveform > Save Configuration or click the Save Wave Configuration
button, and save the waveform configuration to a file called tutorial_2.wcfg.
4. From the waveform toolbar menu, click the Next Transition button .
The current marker moves to the first value change of the selected sineSel[1:0] signal, at
3.5225 microseconds.
TIP: By default, the Waveform window displays the time unit in microseconds. However,
you can use whichever measurement you prefer while running or changing current
simulation time, and the Waveform window adjusts accordingly.
7. In the Waveform window, click the Go to Time 0 button, then click the Zoom in button
repeatedly to zoom into the beginning of the simulation run.
8. Continue to zoom in the Waveform window as needed, until you can see the reset signal asserted
low, and you can see the waveform of the clock signals, sys_clk_p and sys_clk_n, as seen in
Figure 26.
The Waveform window zooms in or out around the area centered on the cursor.
9. Place the main Waveform window cursor on the area by clicking at a specific time or point in the
waveform.
You can also click on the main cursor, and drag it to the desired time.
10. Because 0 is the initial or default FSM output, move the cursor to the first posedge of sys_clk_p
after reset is asserted low, at time 102.5 ns, as seen in Figure 27.
You can use the Waveform window to measure time between two points on the timeline.
11. Place a marker at the time of interest, 102.5 ns, by clicking the Add Marker button .
12. Click to select the marker.
The Floating Ruler option that is available in the General tab of waveform Settings displays a
ruler at the bottom of the Waveform window useful for measuring time between two points. Use
the floating ruler to measure the sineSel control signal period, and the corresponding
output_sine[19:0] values during this time frame.
When you select the marker, a floating ruler opens at the bottom of the Waveform window, with
time 0 on the ruler positioned at the selected marker. As you move the cursor along the
timeline, the ruler measures the time difference between the cursor and the marker.
TIP: Enable the Floating Ruler checkbox from the General tab of Waveform Settings, if the
ruler does not appear when you select the marker.
You can move the cursor along the timeline in a number of ways. You can scroll the horizontal
scroll bar at the bottom of the Waveform window. You can zoom out, or zoom fit to view more
of the time line, reposition the cursor as needed, and then zoom in for greater detail.
13. Select sineSel from the list of signals in the Waveform window and use the Next Transition
command to move to the specific transition of interest.
As shown in Figure 27, the ruler measures a time period of 3.420 ns as the period that FSM
selected the low frequency output.
Note: You can also use File > Text Editor > Open File from the main menu, or Open File from the
popup menu in the Sources window. You can also select an appropriate design object in the Scopes
window or Objects window, right-click and select Go to Source Code.
Using Breakpoints
A breakpoint is a user-determined stopping point in the source code used for debugging the design.
When simulating a design with set breakpoints, simulation of the design stops at each breakpoint to
verify the design behavior. After the simulation stops, an indicator shows in the text editor next to the
line in the source file where the breakpoint was set, so you can compare the Wave window results with
a particular event in the HDL source.
You use breakpoints to debug the error with the low frequency signal output that you previously
observed. The erroneous sine[19:0] output is driven from the sineGen VHDL block. Start your
debugging with this block.
1. Select the U_SINEGEN scope in the Scopes window to list the objects of that scope in the Objects
window.
2. In the Objects window, right-click sine[19:0] and use Go to Source Code to open the
sinegen.vhd source file in the Text Editor.
TIP: If you do not see the sine[19:0] signal in the Objects window, make sure that
the filters at the top of the Objects window are set properly to include Output objects.
Looking through the HDL code, the clk, reset, and sel inputs are correct as expected. Set
your first breakpoint after the reset asserts low at line 137.
Note: To delete all breakpoints in the file, right-click on one of the breakpoints and select Delete All
Breakpoints.
Debugging in the Vivado simulator, with breakpoints and line stepping, works best when you
can view the Tcl Console, the Waveform window, and the HDL source file at the same time, as
shown in Figure 30.
5. Resize the windows, and use the window Float command or the New Vertical Group command to
arrange the various windows so that you can see them all.
TIP: When you have arranged windows to perform a specific task, such as simulation
debug in this case, you can save the view layout to reuse it when needed. Use the
Layout > Save Layout As command from the main menu to save view layouts. See the
Vivado Design Suite User Guide: Using the Vivado IDE (UG893) for more information on
arranging windows and using view layouts.
The Find in Files results display at the bottom of the Vivado IDE, with all occurrences of sine_l
found in the sinegen.vhd file.
7. Expand the Find in Files results to view the results in the sinegen.vhd file.
The second result, on line 111, identifies a problem with the design. At line 111 in the
sinegen.vhd file, the m_axis_data_tdata_sine_low signal is assigned to sine_l. Since
line 111 is commented out, the sine_l signal is not connected to the low frequency DDS
compiler output, or any other input.
8. Uncomment line 111 in the sinegen.vhd file, and click the Save File button .
9. In the Tcl Console, remove the force on sine_l: remove_forces -all
Introduction
You can use the Vivado simulator Non-Project Mode flow to simulate your design without setting up a
project in Vivado Integrated Design Environment (IDE).
In this flow, you:
Prepare the simulation project manually by creating a Vivado simulator project script.
Create a simulation snapshot file using the Vivado simulator xelab utility.
Start the Vivado simulator GUI by running the xsim command with the resulting snapshot.
IMPORTANT: While you can specify one or more Verilog source files on a single
command line, you can only specify one VHDL source on a single command line.
In this step, you build a Vivado simulator project script by editing an existing project script to add
missing source files. The command lines for the project script should be constructed using the syntax
described above.
1. Browse to the <Extract_Dir>/scripts folder.
2. Open the simulate_xsim.prj project script with a text editor.
3. Add the following commands to the project script:
vhdl xil_defaultlib "../sources/sinegen.vhd"
vhdl xil_defaultlib "../sources/debounce.vhd"
vhdl xil_defaultlib "../sources/fsm.vhd"
vhdl xil_defaultlib "../sources/sinegen_demo.vhd"
verilog xil_defaultlib "../sim/testbench.v"
TIP: For your reference, a completed version of the tutorial files can be found in the
ug937-design-files/completed folder.
Running xelab
In this step, you use the xelab command with the project file completed in Step 1 to elaborate,
compile, and link all the design sources to create the simulation snapshot. To run the xelab command,
must open and configure a command window.
1. On Windows, open a Command Prompt window. On Linux, simply skip to the next step.
2. Change directory to the Xilinx installation area, and run settings64.bat as needed to setup the
Xilinx tool paths for your computer:
cd install_path\Vivado\2019.x\settings64.bat
Note: The settings64.bat file configures the path on your computer to run the Vivado Design
Suite.
TIP: You can also use the xelab command after the xvlog and xvhdl commands
have parsed the HDL design sources to read the specified simulation libraries. The
xelab command would be the same as described here, except that it would not require
the -prj option since there would be no simulation project file.
Introduction
Vivado simulator now supports synthesizable as well as test bench/verification feature of System
Verilog IEEE 1800-2012. In this chapter, you will go through a System Verilog example to learn about
different debugging capabilities added in the Vivado simulator. You will use an IP example design
provided with Vivado.
3. You will create an AXI-VIP example design that includes the following features:
a. Random Constraint
Logic Simulation www.xilinx.com Send Feedback
55
UG937 (v2019.1) June 4, 2019
b. Dynamic Types and Class
c. Virtual Interface
d. Assertion
e. Clocking Block
4. Invoke the following commands in Tcl console:
a. create_ip -name axi_vip -vendor xilinx.com -library ip -version 1.1 -
module_name axi_vip_0
b. open_example_project -force [get_ips axi_vip_0]
Now you have created an example design for AXI-VIP with the name axi_vip_0_ex.
Launching Simulation
You have an example project ready. Next, you will run the behavioral simulation. By default, the
simulation runs in a pre-compiled mode where the source code for static IP is not added in the project.
Run the simulation in a non-precompiled mode for a better understanding of the feature. Invoke the
following commands in Tcl console:
set_property sim.use_ip_compiled_libs 0 [current_project]
launch_simulation
Object Window
In System Verilog, all the net/variables are static type. They exist throughout the simulation. In System
Verilog, dynamic type is a new type along with static type. Class, Queue, and Associative Array are some
examples of dynamic type.
Unlike static type variables (int a; wire [7:0] b;), dynamic type variables do not have a fixed size
throughout the simulation. Variables keep changing during run-time. Through Object window, you can
view the value of a dynamic type variable during the simulation.
1. Click Restart button .
2. From the Scope window, select scope generic_tb present under the top module.
3. Maximize the Objects window. As the simulation is yet to start, observe the Queue and Class
dynamic type in the Data Type column. The Value for Queue appears empty while for class it
appears null.
5. On the text editor window, click the Circle on line number 64 to add a break point.
6. Click Run All button, the simulation will stop at line number 64. On the Object window
master_monitor_transaction_queue value appears empty.
Logic Simulation www.xilinx.com Send Feedback
59
UG937 (v2019.1) June 4, 2019
Figure 40: Objects Window
7. On the Vivado simulator toolbar menu, click the Step button . It executes the current
statement that is on line number 64 where the simulation is currently waiting. At this statement,
you are pushing an element after the execution. Your queue will be populated with a single
element.
8. In the Object window, the master_monitor_transaction_queue value is populated. This way
you can view the value of any dynamic type on the Object window.
3. In Tcl console, invoke the report_objects command to display all objects present in the selected
scope. Also, the Queue and Class appear as object type.
5. Click Run All button . The simulation stops at the line where you have added the break point.
6. Invoke get_value master_moniter_transaction_queue command and notice that it is still
empty.
7. On the Vivado simulator toolbar menu, click the Step button . It executes the current
statement that is on line number 64 where the simulation is currently waiting. At this statement,
you are pushing an element after the execution. Your queue will be populated with a single
element.
8. Invoke the get_value master_moniter_transaction_queue command and notice 1 entry in
the Queue. Like the Objects window, you can read the value of any dynamic type variable in Tcl
Console.
Functional Coverage
Functional coverage is a user defined metric that measures the extent to which the design specification,
as enumerated by features in the test plan, was exercised. It can be used to measure whether
interesting scenarios, corner cases, specification invariants, or other applicable design conditions—
captured as features of the test plan—have been observed, validated, and tested.
The Vivado simulator supports functional coverage. If your design contains any functional coverage
statement, the tool will generate a database (coverage database). To view coverage database, Vivado
simulator provides a utility named as xcrg (Xilinx Coverage Report Generator). Refer to the Vivado
Design Suite User Guide: Logic Simulation (UG900) for more information on functional coverage and
xcrg.
In the present example design, you will add a functional coverage code to view the utility of xcrg.
In this example, you are declaring a covergroup named as my_cover_group and the sampling event as
posedge aclk. This covergroup contains three coverpoints. You will add the cover group declaration
code in the example design.
1. In Tcl console invoke the following command:
current_scope
/axi_vip_0_exdes_adv_mst_active__pt_passive__slv_comb/DUT/ex_design/axi_vip_m
st
4. In Tcl console, invoke close_sim command to close the simulation running previously.
5. In Tcl console, invoke reset_simulation command to clean the simulation directory.
6. In Tcl console, invoke launch_simulation command to run the simulation.
7. C lick Run All button .
The simulation will stop after reaching $finish statement. The Vivado simulator has generated the
coverage database at the following location with the name (default name) xsim.covdb:
./axi_vip_0_ex.sim/sim_adv_mst_active__pt_passive__slv_comb/behav/xsim/
This way you can view the coverage and change your test bench/seed value to improve the coverage.
Assertion
In System Verilog, you have the following two types of assertion:
Immediate assertion
Concurrent Assertion
Immediate Assertion
Evaluated like an expression in ‘if’ statement.
always@(posedge clk)
assert(data == 4’b1010);
Concurrent Assertion
This assertion is based on clock semantic and use sampled value of their expression. These assertions
can expand over multiple cycle.
always@ (posedge clk)
a1: assert property (a ##2 b);
Random Constraint
System Verilog has random constraint, which is used to generate a random value. Using this feature,
you can even set the constraint on a random variable.
For each simulation, the simulator is supposed to generate fixed set of values. In this example,
randomize call is happening 10 times so each time the simulator is expected to assign a different value
If you want different set of values, you should change the random seed value. In Vivado simulator, it is
done by passing -seed option to xsim. In Tcl Console, you need to invoke the following command:
set_property -name {xsim.simulate.xsim.more_options} -value {-seed 2000} -objects
[get_filesets sim_adv_mst_active__pt_passive__slv_comb]
With seed, you have to provide any integer value. So just by changing a ‘seed’ value, you can get a
different value. You don’t need to do compilation and elaboration again.
1. Add the following code in a file and name it as random.sv.
module top();
class c1;
rand bit [3:0] b1;
endclass
c1 obj1 = new();
initial
begin
for(int i = 0; i < 10; i++)
begin
#5 obj1.randomize();
$display("At time %t the value is %p", $time, obj1);
end
end
endmodule
3. Re-run step 2b and notice the value is similar to the previous one.
4. Simulate the code with different SV seed xsim top -R -sv_seed 5000 and observe that the value
is different. Thus, you can generate different value without going through compile and elaboration
step.