This tutorial covers Mentor Graphic's ModelSim SEŠ, an
Integrated Development Environment (IDE) for HDL circuit design.
In CS 552 we will use ModelSim to develop and simulate circuit
designs written in Verilog. Before using ModelSim for your own
designs be sure to review the Verilog style rules that apply to
work done for the CS 552 project and homework, found in the
handouts section of the course web page.
This document will provide a only brief introduction to the
tools necessary to complete coursework in CS 552. Those looking
for more detailed coverage can consult the ModelSim SE tutorial
published by Mentor found here.
Additionally, the help menu in ModelSim has a large volume of
documentation covering the features of the IDE.
You will learn best from this tutorial by following along on
your own machine. ModelSim can be accessed through any of the CS
UNIX/Linux machines or through an SSH connection to a CS
workstation. Be aware, however, that due to the size of ModelSim
a remote connection through SSH may be too slow for your liking.
For historical reasons, the ModelSim IDE runs under the UNIX
program name vsim
. To begin a new project, navigate
to the directory where you want your project to be located and
type vsim
at the terminal command prompt. You may
close the welcome screen if it appears after opening the
program. You should now see the screen shown in Figure 1. On the
left is the Workspace window and on the right is the ModelSim
command prompt.
To open a new project, choose File -> New
-> Project. Enter tutorial as
the project name and cs552_tutorial
as the default library name. If a dialog box opens and asks you
which version of the modelsim.ini file you would like to use,
choose Use Default ini.
You can add files to an open project by selecting File -> Add to Project -> New File. In the
dialog box that appears, enter mux2_1
under "File Name". The "Add File as Type" selection box should
be set to Verilog and "Folder" should
be Top Level. After clicking OK, the
newly created file will appear in the workspace project tab.
Double click the file name to begin editing the file. Type
the code below in the ModelSim edit window then select File -> Save.
// a 2-1 multiplexer module
module mux2_1(i0, i1, sel, out);
input i0;
input i1;
input sel;
output out;
reg outreg;
always @* case (sel)
2'b0 : outreg = i0;
2'b1 : outreg = i1;
endcase
assign out = outreg;
endmodule
Sub modules will automatically work in ModelSim as long as all
the needed files are included in the current project. To
exemplify this, use the module you just created to construct a
4-1 multiplexer. Choose File -> Add to
Project -> New File and create a verilog file named mux4_1. Open the new file for editing and
copy and paste in the code shown below.
//a 4-1 multiplexer module
module mux4_1(i0, i1, i2, i3, Sel, out);
input i0;
input i1;
input i2;
input i3;
input [1:0] Sel;
output out;
wire s0, s1;
//use mux2_1 as a submodule
mux2_1 submod1(i0, i1, Sel[0], s0);
mux2_1 submod2(i2, i3, sel[0], s1);
mux2_1 submod3(s0, s1, Sel[1], out);
endmodule
To compile your newly created files, find the Compile All button found in the ModelSim
toolbar located to the right of the paste icon. You could
alternatively choose to compile each file individually by
highlighting the file in the workspace and clicking the Compile button. The result of the
compilation is shown in the right frame of the ModelSim main
window. If you copied the code for mux4_1 exactly, you will see a
compilation failure shown in red, as seen in Figure 2. To view
the error, double click the red line. The window that appears
explains that line 13 of the file mux4_1.v has an illegal
variable. Double click the error to jump directly to the
erroneous line in the ModelSim editor. A quick look at the code
reveals that the Sel variable was not capitalized. Fix the error,
save the file, and compile again.
To simulate a design you must first locate your working
library. Navigate to the Library tab
in the Workspace window. There you will find the library you just
created named "cs552_tutorial". Expand this row to find your
design files. Select the top-most design in your project, in this
case mux4_1, right click over the name, and choose Simulate.
This will create two new tabs in the Workspace window named sim
and Files. The sim tab will contain a hierarchy of modules used
in the current simulation, and the Files tab lists the source
files used. Open the sim tab, right click on the mux4_1 module,
and select Add to Wave. This will
open a new "wave" window with the mux4_1 signals already
included. You will notice that the internal wires s0 and s1 are
present as well. In larger designs it is useful to examine these
signals during debugging.
Choose a signal in the wave window and right click to view
the options. The Radix option allows you to change the display
format of the signal. This is useful for displaying buses in
hexadecimal format instead of binary. However, because the mux4_1
module has only single wire inputs we will leave all signals in
the default binary format.
Now you will add forces to the input signals so that you can
test the multiplexer's function. In the ModelSim main window,
choose View -> Signals. This will
open a new window that contains a list of all the signals in the
current simulation. Highlight the signal i0 and then select Edit -> Force. You should see the screen
shown in Figure 3. Set the value of the signal by entering either
a 1 or 0 in the Value field and then select the Freeze option in
the Kind area. Repeat this step for all the input signals i0-i3
and Sel. When forcing Sel, be sure to enter a two digit binary
number.
After forcing all the input signals, the design is ready for
simulation. Navigate back to the waveform window and find the
button labeled Run. Clicking this
will run the simulation for the default time of 100ns. Clicking
the Run button again will run the simulation from the previous
stopping point, NOT from time 0. You can test a different set of
inputs by switching to the signals window, applying new forces,
and running the simulation again.
Clicking in the waveform window will bring up a cursor, which
you will see as a vertical yellow line. You can drag the cursor
along the simulation timeline to examine signal values. By using
the Find next transition and Find previous transition buttons, you can
also advance the cursor automatically to the next value change for
a selected signal. ModelSim makes it easy to compare the value of
a signal at different times by using two cursors. Find the Add Cursor button in the wave window
toolbar. Clicking it will add another cursor to the design as
shown in Figure 4.
To end the current simulation, close both the wave and signal
windows and navigate back to the sim tab of the main window's
Workspace frame. Right click on the top level module that you are
simulating, in this case mux4_1, and select end simulation.
When simulating large designs, it is often too cumbersome to
manually force a signal using the graphic interface each time you
want it to change. ModelSim remedies this by providing a long
list of simulator commands. The complete list can be found in the
ModelSim help documentation, but for purposes of this tutorial we
will cover some of the most commonly used commands.
You will now recreate the simulation you performed in the
previous section using only command line functions. First, you
must initiate the simulation. This is done using the vsim
<library_name>.<design_unit>
command (not to be confused
with the vsim
command that starts ModelSim from the
UNIX command prompt). To start a simulation of the 4-1
multiplexer, type the following in the ModelSim command window.
vsim cs552_tutorial.mux4_1
.
If you do not specify a library name, ModelSim will look for
the design in the "work" library.
The next step is to add signals to the waveform. This is
accomplished with the add wave <signal>
command. The
signal argument can take the form of a UNIX wildcard string,
i.e. i*
, which would include the signals i0, i1,
etc... With the add wave
command you can also pass
optional arguments to format the display. Common options are
-color, -<radix>,
and
-<format>
. See the ModelSim help documentation
for their specific usage and more options. For your simulation,
add all the signals with the command:
add wave *
After signals have been added to the wave file, you must next
force them to run a meaningful simulation. In ModelSim the
force <signal> <value> <start time>
command performs this task. You can specify the type of force
using the options -freeze, -drive,
or
-deposit
. If no option is used, ModelSim defaults to
the freeze type. The force
command can also be used
to create clock signals using the -repeat
option.
Consult the ModelSim command reference, found in the help section,
for examples of clock forces. To continue with your simulation,
type the following:
force i0 0 0
force i1 1 0
force i2 1 0
force i3 0 0
force Sel 00 0
force Sel 01 50
force Sel 10 100
force Sel 11 150
The compliment command of force
is noforce
<signal> <stop time>
.
Now all that is left to do is to run and view the simulation.
You can run the simulation using the run <time>
command.
run 200
To see the results of the simulation, open the wave window by typing
view wave
ModelSim allows you to automate sequences of commands using DO
files. The files are simple in structure, containing only
comments starting with a # and a sequential list of commands. To
create a new DO file, navigate to the ModelSim main window and
choose File -> New -> Source -> Do.
This will open the editor window with a blank document. Type the
following in the editor and then save the file as
"tutorial.do".
# reset the simulation
restart -force -nowave
# add all input and output signals to the wave file
add wave -logic i0
add wave -logic i1
add wave -logic i2
add wave -logic i3
add wave -logic Sel
add wave -logic out
# force the input signals
force -freeze i0 0 0
force -freeze i1 1 0
force -freeze i2 1 0
force -freeze i3 0 0
force -freeze Sel 00 0
force -freeze Sel 01 50
force -freeze Sel 10 100
force -freeze Sel 11 150
# run the full simulation
run 200
# open the wave window
view wave
To execute the DO file, type the following in the ModelSim command prompt:
do tutorial.do
One of the most powerful features of ModelSim is it's tight
integration with the Tcl/Tk (commonly pronounced
"tickle"/"tee-kay") scripting language. Tcl and its graphical
extension Tk are interpreted languages similar to python or perl.
The Tcl syntax makes heavy use of curly braces and list data types
and does not closely resemble any of the common languages such as
C or Java. Nevertheless, it is simple enough that meaningful
scripts can be created in a short amount of time by learning a few
simple rules. While using Tk to graphically represent simulations
can be a useful tool, it is beyond the scope of this document. To
learn more about Tk scripting in ModelSim, consult the ModelSim SE
tutorial found in the program's help documentation.
The real advantage to Tcl scripting in ModelSim is the ability
to control the flow of a simulation as you would a sequential
program. You can create loops to iterate through a series of
forces or format the simulation output to fit your needs. For
example, in your 4-1 multiplexer simulation, you can easily
iterate through all possible input combinations with a single
loop:
set step 10
proc runSim {} {
set runtime 0
global step
restart -force -nowave
add wave *
for {set i 0} {$i < 64} {incr i} {
force -freeze i0 [expr $i & 0x01] $runtime
force -freeze i1 [expr ($i & 0x02) >> 1] $runtime
force -freeze i2 [expr ($i & 0x04) >> 2] $runtime
force -freeze i3 [expr ($i & 0x08) >> 3] $runtime
force -freeze Sel [expr ($i & 0x20) >> 5][expr ($i & 0x10) >> 4] $runtime
set runtime [expr $runtime + $step]
}
run $runtime
view wave
}
Notice that ModelSim commands can be mixed with Tcl syntax to
easily control a simulation. To use a Tcl script, add a new file
to your project by selecting File -> New ->
Source -> Other. Copy the script above to the file and then
save it as tutorial.tcl. In the ModelSim command window, type
source tutorial.tcl
. This command makes all
procedures in your Tcl script callable from the ModelSim command
window. Run the exhaustive simulation by typing
runSim
. When the script is finished the wave window
will appear as shown in Figure 5.
You can use Tcl scripts to automate design testing. Through
the use of the ModelSim examine
command, a Tcl
script can import a signal value as a script variable. This
enables you to create automatic checks for your test cases.
Consider the following function, which, when used in conjunction
with the runSim
procedure above, will verify the
results of the exhaustive 4-1 multiplexer simulation.
proc verifySim {} {
global step
set runtime 5
set errorFound 0
for {set i 0} {$i < 64} {incr i} {
set i0 [expr ($i & 0x01) ]
set i1 [expr ($i & 0x02) >> 1]
set i2 [expr ($i & 0x04) >> 2]
set i3 [expr ($i & 0x08) >> 3]
set Sel0 [expr ($i & 0x10) >> 4]
set Sel1 [expr ($i & 0x20) >> 5]
set correctOut [expr (!$Sel0 & !$Sel1 & $i0) | \
($Sel0 & !$Sel1 & $i1) | \
(!$Sel0 & $Sel1 & $i2) | \
($Sel0 & $Sel1 & $i3)]
set simOut [examine -time $runtime -binary /mux4_1/out]
if {$correctOut != $simOut} {
echo "discrepancy found"
echo "correctOut:$correctOut"
echo "simOut:$simOut"
echo "time:$runtime"
set errorFound 1
}
set runtime [expr $runtime + $step]
}
if {$errorFound == 0} {
echo "design verified successfully"
} else {
echo "errors were found in the design"
}
}
To use the verification function, copy the code above into the
end of the tutorial.tcl
script file. After saving,
retype source tutorial.tcl
in the ModelSim command
window. You can then verify your design by typing
runSim
followed by verifySim
.