Computer Laboratory

Course pages 2016–17

ECAD and Architecture Practical Classes

Exercise 0: SystemVerilog web tutor and tools introduction


You are expected to complete Step 1 in the first week and complete the other steps in the second week.

Step 1: SystemVerilog web tutor

Please login to our SystemVerilog web tutor to learn more about the SystemVerilog language. Completing all of the exercises will really help you complete the tickable exercises in a timely manner.

Step 2: Prepare to simulate your traffic light controller

In the last but one web tutor exercise, you designed a traffic light controller. In preparation for the tickable exercises, let's have a go at simulating your design using the ModelSim simulator you'll be using for the ticks. We're going to use this tool on an MCS Linux machine or within the course virtual machine.

First create a directory exercise0 for your simulation project and copy in your SystemVerilog code for your tlight module (including the header and footer). Put this into a file of the same name as the module with suffix .sv (for SystemVerilog), i.e.

Before we can simulate the design, we will need a test bench to provide input stimulus. In this instance there is just one input, the clock. We can provide a clock as follows and instantiate the tlight module to test it. Let's create a in which we will call the test bench tb_tlight and the instance of tlight to test dut (Design Under Test), viz:

`timescale 1ns / 1ps

module tb_tlight(
  output r,
  output a,
  output g);

  logic clk;      // clock signal we are going to generate

                  // instantiate design under test (dut)
  tlight dut(.clk(clk), .r(r), .a(a), .g(g));

  initial         // sequence of events to simulate
      clk = 0;   // at time=0 set clock to zero

  always #5       // every five simulation units...
    clk <= !clk;  // ...invert the clock

                  // produce debug output on the negative edge of the clock
  always @(negedge clk)
    $display("time=%05d: (r,a,g) = (%1d,%1d,%1d)",
      $time,      // simulator time
      r, a, g);   // outputs to display: red, amber, green

endmodule // tb_tlight

Step 3: Simulate your design

To start up ModelSim, we first need to setup paths and environment variables to use the ECAD tools, depending on your setup. Open a new terminal window. On the MCS you will need to source the appropriate setup.bash script as described in the setup instructions.

To start the ModelSim simulator, type:


This will open up a graphical window similar to the following:

The main ModelSim window consists of three areas. The "Transcript" area contains a command line terminal that you can use to give commands. All functions in ModelSim are accessible through the menus, but the command line can help in scripting up various sequences of operations that you wish to repeat. In addition, the Transcript area will show the output of any print statement that has been added to your component design.

On the left there is the library panel. This panel contains various libraries that contain one or more (compiled) components. To create a new library, click File->New->Library. ModelSim mandates that you create a library called "work" (Library Name and Library Physical Name), in which all custom compiled projects are stored. (If you already have a library 'work (unavailable)', right click it, go to New->Library and 'Create: a new library' with physical name 'work').

To compile your design in ModelSim, click on Compile->Compile.... From the file chooser dialogue, you can now navigate to the folder where you stored your sources. Double-click on the files that you wish to compile ( and When unsuccessful, the transcript area should give you some hints about why it failed to compile. For more info, you can also look in the compile summary, that can be opened by clicking Compile->Compile Summary. ModelSim is only able to figure out dependencies on other modules after they have been compiled, so either select all components by holding ctrl and click on all source files, or compile your components from the bottom up.

If everything went well, your components should now have appeared in the library "work" (you may need to click the + symbol by work to see the compiled modules). By double-clicking on the top-level component (tb_tlight), you will start a simulation. This will add the simulate buttons to the toolbar area above and insert another area in the ModelSim GUI called objects that contains all signals of the module selected in the "Sim" area, defaulting to the top level module.

There should be a "Wave" panel which contains no signals. Add the signals r, a, g and clk from the "Objects" panel by dragging them to the "Wave" panel.

Now to simulate the design. Look for the simulation time period (typically 100ns) and the "Run" button to the right of it which looks like:

You might wish to press the zoom-in button a couple of times to get a simulation like the following.

In the "Transcripts" window you should also see the output from the $display statement in the test bench which should produce the following which provides the same information as the waveform output:

# time=    0: (r,a,g) = (x,x,x)
# time=   10: (r,a,g) = (1,0,0)
# time=   20: (r,a,g) = (1,1,0)
# time=   30: (r,a,g) = (0,0,1)
# time=   40: (r,a,g) = (0,1,0)
# time=   50: (r,a,g) = (1,0,0)
# time=   60: (r,a,g) = (1,1,0)
# time=   70: (r,a,g) = (0,0,1)
# time=   80: (r,a,g) = (0,1,0)
# time=   90: (r,a,g) = (1,0,0)
# time=  100: (r,a,g) = (1,1,0)

Step 4: Script the simulation

During test driven hardware development, simulation runs are frequent and using the GUI to setup the simulation run each time is a bit tedious. The solution is scripting. ECAD tool vendors often use the TCL scripting language. Here is an example commented "do" script in TCL.

# set up the "work" library
vlib work
# compile our SystemVerilog files
# point the simulator at the compiled design
vsim work.tb_tlight
# add waveforms to the "Wave" pane
add wave -position insertpoint \
  /tb_tlight/r                 \
  /tb_tlight/a                 \
  /tb_tlight/g                 \
# run simulation for 200 nanoseconds
run 200 ns

If you copy the above script into a file you can execute it by typing the following into the "Transcript" pane of ModelSim:


You can also run ModelSim (vsim) from the command-line only with no GUI. This can be useful when you just want the output from $display statements and no waveform viewer. For example:

vsim -c -do

Adding "quit" to the end of the script will cause vsim to cleanly exit after the simulation run. The "add wave ..." statement is redundant if there is no waveform window, so can be removed.


There is a ModelSim quick reference guide on the downloads page.

Optional exercise

Try out your electronic dice in ModelSim. You will need to provide a "button" input. One approach is to extend the initial block with changes of state to a "button" register using specified delays and non-blocking assignment, viz:

    clk = 0;
    button = 0;
    // after 20 simulation units (2 clock cycles given the clk configuration)
    #20 button = 1;
    // after 100 simulation units
    #100 button = 0;

Hints and Tips

You may find that your simulation produces x's as output due to registers being uninitialised at the start of the simulation. For FPGA designs we're sometimes lazy and rely on the FPGA to come up with registers reset to zero. This can be mimicked in simulation by adding an initial statement, e.g. for tlight you might add:

initial state=0;

Initial statements are ignored when synthesising a design into a real circuit. A synthesisable (i.e. better) approach to initialising state is to use reset signals. For example, for tlight you might add another input called "rst" and for the always_ff block add:

always_ff @(posedge clk or posedge rst)
    state <= 4'b000;

In your test bench you'd need to add the rst signal as a register and initialise it for simulation viz:

  initial          // sequence of events to simulate
      clk = 0;     // at time=0 set clock to zero and reset to active (1)
      rst = 1;
      #20 rst = 0; // after 2 clock ticks set reset to inactive (0)

SystemVerilog is not a type-safe language, which means it will silently convert values of different types. One of the most annoying features for debugging is it will create undeclared signals (`implicit nets') for you if you don't define them. This can be problematic if you mistype a net name, because the correct version and the typo version will not be connected together, and the tools may synthesise these away. You can force an error to be generated with:

  `default_nettype none

in your source file. However this does not work for all compilation tools.