Interactive Testbench using Tcl

An interactive testbench is a simulator setup where input to the device under test (DUT) is provided by an operator while the testbench is running. Most often, this would mean you entering commands in the simulator console to provide the DUT with stimulus.

While you should always create a self-checking testbench, an interactive testbench can be a nice supplement. It’s easier to perform ad-hoc testing with an interactive testbench at hand, than it is to change the code of the self-checking testbench.

Often times, you will discover problems in the lab that you will want to try out in the testbench. With an interactive testbench, it can be as easy as typing in the input sequence that has been observed to replicate the undesirable behavior in the simulator.

Tcl interacting with VHDL

Most VHDL simulators use Tcl as their console language. The simulators have a bunch of vendor-specific commands, but the good news is that they can be treated as any other Tcl command. You can use Tcl for creating complex, mostly portable scripts for managing and supporting your VHDL testbenches.

Changing VHDL signals from Tcl

To interact with VHDL, we need to find the command for changing a signal value. In ModelSim, this is the “force” command. As specified in the command reference document, the synopsis for the command is:

force {<object_name> <value> [[@]<time_info>][, <value> [@]<time_info>]...
[-deposit | -drive | -freeze] [-cancel [@]<time_info>] [-repeat [@]<time_info>]

The switch that you want to use is the “-deposit” flag. This changes the value of the VHDL signal instantaneously, but allows another VHDL or Tcl driver to change it to something else at a later time.

By ignoring the options that we are not using, the simplified synopsis looks like this:

force -deposit <signal_name> <value>

The VHDL trigger

Now that we know how to control VHDL signals from Tcl, we need to create some sort of receiver process in our VHDL testbench. The code below shows a minimal example of such a testbench.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity interactive is
end interactive; 

architecture sim of interactive is

  -- Controlled by Tcl
  signal trigger : std_logic := '0';


  process is

    wait until trigger = '1';
    report "Triggered!";

  end process;

end architecture;

The process will wake up when the trigger signal changes from something to '1'. It will print “Triggered!” to the console when this happens, allowing us to test the concept of controlling VHDL processes from Tcl.

I did just that is the ModelSim console. The issued commands, as well as the output, can be viewed in the transcript below.

VSIM 1> run 10 ns;
VSIM 2> force -deposit /trigger '1'
VSIM 3> run 0 ns;
# ** Note: Triggered!
#    Time: 10 ns  Iteration: 0  Instance: /interactive
VSIM 4> force -deposit /trigger '0'
VSIM 5> run 10 ns;

I ran the testbench for 10 nanoseconds after starting the simulation.

Then, I forced the trigger signal to '1'. On the next line, I wait for 0 nanoseconds. The purpose of this is to create a delta cycle. I want the process to be triggered, but I don’t want any simulation time to pass.

Finally, I force the trigger signal back to '0' before continuing the testbench.

We can see that the VHDL process woke up after the “run 0 ns” line, and printed out “Triggered!” to the console.

Reading VHDL signal values in tcl

To read signal values in  ModelSim,  you can use the “examine” command. We can for example read the value of the trigger signal by using this command in the ModelSim console:

VSIM 6> examine /trigger
# 0

You would want to assign the value to a Tcl variable when using “examine” in a script. Let’s try this in the ModelSim console:

VSIM 7> set triggerVal [examine /trigger]
# 0

Then we can for example print out the variable by using the “puts” Tcl command:

VSIM 8> puts "triggerVal: $triggerVal"
# triggerVal: 0

Stopping the simulator after each test

The easiest way to run the test long enough for the DUT to react, is to simply run the simulator for a fixed time value. For example, if the DUT should react after two clock cycles, and the clock period is 10 nanoseconds, we would use the command “run 20 ns” in our Tcl script.

If the DUT doesn’t have a fixed reaction time, a VHDL assertion can be used for stopping the simulation and handing over control to a Tcl callback function. In ModelSim, this would mean setting a breakpoint from your Tcl script by using the “when” command:

when [[-fast] [-id <id#>] [-label <label>] {<when_condition_expression>} {<command>}]

You would also have to define an “onBreak” callback function in Tcl that will be run when the breakpoint is hit. The “onBreak” function is specified in the ModelSim command reference.

The drawbacks of Tcl-driven testing

There are drawbacks of using testbenches that rely heavily on Tcl scripts. The most apparent ones are the speed and portability issues.

Tcl-driven testbenches work by starting and stopping the simulator multiple times to interact with the VHDL code. Starting and stopping the simulation to run a Tcl function in between, is more time consuming than running a VHDL testbench continuously. While Tcl is an interpreted language, VHDL is compiled in the simulator and runs much faster than Tcl.

While Tcl is portable to other simulators, the simulator specific commands which you will have to use, are not. Even if you find the equivalent commands in the other simulator, they may work differently. Simulator vendors make up their own set of rules for the commands they support. Therefore, a Tcl-driven testbench should be considered to be less portable than a pure VHDL testbench.

New Tcl course

* Update 2022

Check out VHDLwhiz's new Tcl course with 18 video lessons!

Course: Tcl scripting for FPGA engineers

Tcl scripting course for FPGA engineers

Similar Posts


    1. Hi Srihari,

      I’ve moved your comment here from the blog post about self-checking testbenches where you originally posted it. I think it belongs here since you talk about this article in your comment.

      Check out my answer to you on Stack Overflow. I created an example of how you can use the ModelSim “when” command to trigger a TCL callback when a VHDL signal’s value is changed:

      You should also join my VHDL for FPGA Engineers group on Facebook where you can post questions like yours.

Leave a Reply

Your email address will not be published. Required fields are marked *