Now that we have created a design unit which has a clearly defined behavior, we need to verify that we have correctly specified that behavior in the VHDL code. We will do this using FPGA Advantage's simulation tool, ModelSim.
ModelSim is a very powerful and versatile HDL simulation tool which
has been tightly integrated with FPGA Advantage. As a result, there are
several methods by which we could go about verifying our design ranging from
loading the bare design unit into the simulator and watching the outputs as we
force the input signals into different states to creating a VHDL Test Bench
which will automate this process for us. For our introduction to ModelSim,
we will be using the first approach to get a feel for some of what the
simulator can do.
The ModelSim simulator cannot directly load and simulate your
FPGA Advantage design unit source files. In order to prepare a design
for simulation, two steps must be taken: generation and compilation.
Once the VHDL for the Logical sub-block has been generated, it needs to be
compiled into a ModelSim simulation file. This can be done in one step by
highlighting the Logical block in the Design Manager and using the ModelSim design
flow button: from the following available
butons: .
If there is a problem, check the design unit block diagram for errors and/or call theinstructor.
Once the design has been compiled, the simulator should start automatically. This
will bring up the options window seen in the figure below. Leave all of the default
options as they are and click OK.
After a few seconds, the ModelSim main window pictured in the figure below
will appear.
You will also notice that the bottom of the FPGA Advantage design window
with the Logical sub-block diagram has a new simulation toolbar pictured below:
In addition to the ModelSim main window, where all text commands to the
simulator are entered, there are several other graphical interface windows available.
In this section of the tutorial we will be using the Objects and Waves windows.
When we first attempt to "power up" the Logical unit it ModelSim,
it must first be placed into a starting state. In a real circuit this state will
be completely random; ModelSim will treats everything as unknown. To prevent
ModelSim from throwing warnings about every unknown output, go to the Simulate
menu in ModelSim, select Runtime Options, click the Assertions tab
and place a check next to warning in the No Messesage Display For: VHDL list.
To display the Signals window, go to the View
menu in the main ModelSim window and select Debug Windows | Objects
from the list (note: this window may already be displayed by default).
You will find that most current digital simulators consist of graphical shells
which issue text commands to the actual simulator. This is a remnant of the fact
that until recently most serious digital simulation was done on high-end UNIX workstations
where a text interface is the norm.
Looking at the Objects window, you can see that all of the ports and internal signals
for the Logical sub-block are present. Since the simulator has not yet run forward in
time, they are all currently in an undefined state.
Next open the Waves window from the View | Debug Windows menu. The window in figure
below will appear. Click the "undock" button
to undock the waves window from the main Modelsim window.
This is the waveform viewer for ModelSim. By default, it appears without
any signals in the viewing area, they must be added by hand.
Now that we have the Signals and Waves windows open, we will start
adding signals to the waveform viewer. There are several different ways to do
this. We will do it by dragging them from the Objects window and dropping
them into the left hand frame of the Waves window.
Begin by selecting the ALUOp signal in the Signals window by left-clicking
over it. Once you have selected it, left-click again and this time hold the mouse
button down. While the mouse button remains depressed, drag the pointer over to the
Waves window and release. Once the ALUOp signal has been added to the Waves
window, you will need to resize the dividers in the waves window to allow for enough
room to display the name of the signal and the current value. The Waves window
should now look like figure below:
Now drag the A and B signals respectively into the Waves window
so that it looks like the figure below:
We can also drag multiple signals at once. Left-click on the LogicalR signal
in the Signals window to select it, but this time hold the SHIFT button down
to select the bottom four signals. Now, let go of the SHIFT button and hold down the CTRL
button. Left-click and select the final signal that has not been added. Now left-click
and hold again and drag this group of signals onto the Waves window, which should
now resemble the figure below: (CTRL can be used to select multiple signals individualy, while
SHIFT select all signals from the first signal selected to the last signal selected)
Finally, within the Waves window we can rearrange the display order to our
liking. It is often convenient to place the output or outputs of the design unit
at the bottom of the waveform display. Currently, however, the LogicalR
signal is sitting in the middle of the display. Select this signal in the left-hand
frame of the Waves window by left-clicking. Now left-click and hold and drag
it down to the bottom of the list. Your waveform display should now look something
the figure below:
Now that we have our display set up to our liking, lets look at how we can make this
simulation do something. The most direct way to do this is to stimulate the input
signals by forcing them to particular values. Remember, forcing a signal to a value
does not actually take effect until you advance the simulator time.
The command in ModelSim to stimulate a signal is called force. For
our first timestep, we wish to set the ALUOp to "00", so we type
force ALUOp "00" at the VSIM prompt and hit return. The main window
will now look like the figure below. Constant strings of bits can simply be represented
by a sequence of ones and zeros.
For the inputs, A and B, we also wish to assign values. However,
for signals with so many bits, it is tedious to type out the constant assignment
values bit by bit. Instead, it is possible to represent constant values in other
bases like hexadecimal or decimal which will be converted to actual bit strings
by the simulator. There are two equivalent syntaxes to do this. One is to type
a decimal number representing the base, followed by the # sign, followed by the
value in the appropriate base. The other is to use the VHDL standard method of
the baseidentifier (hexadecimal is X) followed by the value in double-quotes.
We will be assigning A to a value of all zeros and B to a value
of all ones. In hexadecimal assignment, this would be done by typing:
force A 16#00000000 force B X"FFFFFFFF"
into the main window as seen in the figure below:
Finally, we need to step the simulator forward in time. Since we do not have
any timing delay information in our design, leading to all transitions occurring
instantaneously, the amount of time we step by means little, so for starters we
will move forward 10ns. We run the simulator for a specified amount of time by
typing run xxx where xxx is a time in nanoseconds. So type run 10
at the prompt as seen in the figure below:
Now that we have moved forward with stimulus on the inputs, there should be well
defined values at the outputs and the waveform window should hold history of the
specified signals for zero to ten nanoseconds. Your Signals and Waves
windows should look like figures respectively.
Unfortunately, in the default configuration, the data in the Waves
window is impossible to read. This can be fixed in several ways. First
resize the window, if you haven't already done so, so that it takes up
most of the width of the screen.
Next, highlight all seven of the 32 bit signals and right click on any of
highlighted signals. Click Radix and then Hexadecimal.
Now position the pointer over the divider between the two viewing frames.
Left-click over it and drag to the right until all of the signal values in
the left frame are visible. The left frame contains the name of the signals
and the value of each signal at the point in the waveform window that the
cursor is located.
Finally, click the right-most magnifying glass on the toolbar (the one with
the dark-blue center) to maximally zoom in on the displayed waveform.
Your Waves window should now look like the figure below:
Now to show a transition on the output, lets change up the values of the
inputs. Set ALUOp to "10", A to X"00000000", and B to
"FEDCBA98" and then run the simulator for 20ns.
The waveform display should now show the update values for ALUOp and B
transitioning at 10ns as well as new values for NORR = X"01234567", ORR= "FEDCBA98",
XORR= X"FEDCBA98", and LogicalR = X"FEDCBA98" also transitioning at 10ns. Check
to make sure that your waveform window looks like the figure below.
If does not, then you have an error in your design.
In addition to viewing the simulator output in the various ModelSim
windows, data is annotated to the original FPGA Advantage design.
Go to your opened Logical block diagram. If you have no signals selected,
at the bottom of the window on the simulation toolbar, there will be a grayed
out button labeled Add Probe,.
By selecting a signal or bus in the design, this button will change color and
allow you to activate the tool:. Activate
this tool, move the mouse pointer over the ALUOp bus, and left-click.
This will add a probe to the net, meaning that the current simulator value
of that signal will be displayed in a red box near the net. Since "10" was
ALUOp's value, a "10" should appear by your probe. The design area
should now look like the figure below:
Now add probes to all of the signals on the diagram so that it looks like the figure below:
Now we have seen several ways to look at the values in the simulator. However, it
is still a tedious process to individually type all of the stimulus commands for
a complete design test. To this end, we can use something called a Macro File.
A macro file is simply a text file which can be created by a program such as
notepad containing a sequence of ModelSim commands. In ModelSim these
are usually saved with the extension .do because they are also known as
do files and are executed via the do command.
To test the Logical sub-block a little bit more fully, I have created a small
sequence of simulator commands and commented it. Enter this sequence of commands in a
a text editor such as gedit or kwrite and save it as LogicalTest.do in your mentor_work
directory. To execute the ".do" file, you must include the full path location.
(You may leave out the comments or cut and paste)
-- Restart the simulator restart -f -- First set A and B to zero and the ALUOp to NOR (11). -- Check that NORR and LogicalR are both "FFFFFFFFFFFFFFFF" and -- that ANDR, ORR, and XORR are all "0000000000000000". This -- will verify one test case for each individual logic -- operation and will verify that the "11" select of the -- multiplexor is working. force ALUOp "11" force A X"00000000" force B X"00000000" run 10 -- Now leave A as zero, set B to "FFFF0000" and set the -- ALUOp to "00". Check that ANDR and LogicalR are -- both "00000000". Since ANDR is the only intermediate -- result that should be zero, if LogicalR is also -- zero, then the multiplexor should be working for "00" -- on the select. ORR and XORR should be "FFFF0000" and -- NORR should be "0000FFFF". force ALUOp "00" force A X"00000000" force B X"FFFF0000" run 10 -- Now we will set A to "FFFFFFFF" and B to "F0F0F0F0". -- This will give a unique answer for ORR of "FFFFFFFF" -- so we will set ALUOp to "01". Check that ORR and -- LogicalR are "FFFFFFFF". ANDR should be "F0F0F0F0", -- NORR should be "00000000" and XORR should be "0F0F0F0F". force ALUOp "01" force A X"FFFFFFFF" force B X"F0F0F0F0" run 10 -- Since there is a unique value for the only ALUOp which -- we haven't tested on the multiplexor with the -- current values of A and B, we can leave them alone -- and set the ALUOp to XOR or "10". This time all that -- we need to check is that LogicalR is now equal to -- the value of XORR, or "0F0F0F0F". force ALUOp "10" run 10 |
Once you have entered and saved this text we are ready to run the macro file.
First, however, we will want to reset the simulator so that we are starting
from time zero. This is done by entering restart at the main ModelSim
window prompt. Now run the command file by entering do LogicalTest.do at the
prompt in the main ModelSim window.
Confirm that your design is functioning properly by checking the actual values
in the Waves window with the expected results. The final output should
look something like the figure below:
Now that you have verified the functionality of your first design unit, we can go
on to create the next one which is the Shifter.