How do you stop the VHDL simulator when the simulation is complete? There are several ways to do that. In this article, we will examine the most common ways to end a successful testbench run.

The VHDL code presented here is universal, and it should work in any capable VHDL simulator. For the methods involving Tcl, I will list the commands for the ModelSim and Vivado simulators.

You can download an example project with the four different testbenches from this article if you have ModelSim installed. Enter your email address in the form below to receive the Zip file!

Need the ModelSim project files?

Let me send you a Zip with everything you need to get started in 30 seconds

How does it work?

Tested on Windows and Linux Loading Gif.. How it works

    Unsubscribe at any time

    Using finish procedure

    The VHDL finish procedure is my favorite way of stopping a VHDL testbench that completes without errors. You have to import “finish” from the STD.ENV package, and you have to compile the testbench in VHDL-2008 or newer to use it.

    The code below ends the simulation when we reach the last line of the testbench sequencer process.

    use std.env.finish;
    
    ...
    
    SEQUENCER_PROC : process
    begin
    
      -- Replace this line with your testbench logic
      wait until stop_condition;
    
      report "Calling 'finish'";
      finish;
    
    end process;
    

    Finish Vsim: Are you sure you want to finish?
    Note that finish quits the simulation by default. If you are running ModelSim in the GUI version, a popup will appear saying “Are you sure you want to finish?”. If you click Yes, ModelSim is going to quit.

    That’s probably not what you want. Fortunately, we can prevent this behavior by adding the “-onfinish stop” option to the vsim command, as shown below. By doing so, the finish procedure will behave in the same way as the stop procedure that we will discuss in the next section of this article.

    vsim -onfinish stop work.using_finish_tb
    

    An advantage of using finish is that you can use the default behavior when simulating in batch mode. If you are using scripts to start the simulation, you want to return control to the calling script after the simulation finishes.

    The example below shows a testbench using the finish procedure started in ModelSim batch mode in Linux. After the testbench completes, the simulator quits, and at the last line, we are back in the Linux shell.

    jonas@ubuntu:~/stop_tb$ vsim -c -do 'vsim work.using_finish_tb; run -all'
    Reading pref.tcl
    
    # 10.5b
    
    # vsim work.using_finish_tb
    # vsim work.using_finish_tb 
    # Start time: 22:58:31 on Jun 21,2020
    # Loading std.standard
    # Loading std.env(body)
    # Loading work.using_finish_tb(sim)
    #  run -all
    # ** Note: Calling 'finish'
    #    Time: 1 ms  Iteration: 0  Instance: /using_finish_tb
    # End time: 22:58:31 on Jun 21,2020, Elapsed time: 0:00:00
    # Errors: 0, Warnings: 8
    jonas@ubuntu:~/stop_tb$ 
    

    The VHDL finish procedure is defined in the standard ENV package. As we can see from the code below, it comes in two overloaded flavors. There’s the version without any parameters, which is the one I always use, and there’s another that takes a status integer as a constant input.

    procedure FINISH (STATUS: INTEGER);
    procedure FINISH;
    

    You would think that the status integer becomes the exit code when called from a Linux shell, but that’s not the case, at least not with ModelSim. The problem with using this status code is that what it does depends on the simulator. The wording in the VHDL-2008 standard is “the value of the STATUS parameter may be used in an implementation defined manner by the host simulator“.

    However, you can control the Linux exit code value in ModelSim by using the Tcl command exit -code <value>, but that’s another story.

    Using the stop procedure

    The VHDL stop procedure causes the simulation to pause. That may be useful if you want to examine signal values manually or even continue the simulation later. The simulator treats it like a breakpoint.

    The example below shows how to import and use the stop procedure.

    use std.env.stop;
    
    ...
    
    SEQUENCER_PROC : process
    begin
    
      -- Replace this line with your testbench logic
      wait until stop_condition;
    
      report "Calling 'stop'";
      stop;
    
    end process;
    

    A problem with using stop in script-based setups is that it doesn’t quit the simulation. Instead of returning control to the caller, ModelSim opens a Tcl command shell, causing the calling script to hang indefinitely.

    The listing below shows the output from running the testbench that uses the stop procedure in batch mode. After the simulation stops, we are still in ModelSim. To get out of the Tcl shell, we would have to type “exit”.

    jonas@ubuntu:~/stop_tb$ vsim -c -do 'vsim work.using_stop_tb; run -all'
    Reading pref.tcl
    
    # 10.5b
    
    # vsim work.using_stop_tb
    # vsim work.using_stop_tb 
    # Start time: 22:58:56 on Jun 21,2020
    # Loading std.standard
    # Loading std.env(body)
    # Loading work.using_stop_tb(sim)
    #  run -all
    # ** Note: Calling 'stop'
    #    Time: 1 ms  Iteration: 0  Instance: /using_stop_tb
    # Break in Process SEQUENCER_PROC at ~/stop_tb/src/using_stop_tb.vhd line 23
    # Stopped at ~/stop_tb/src/using_stop_tb.vhd line 23
    VSIM 3> 
    

    Just like the finish procedure, stop requires VHDL-2008 or newer. As shown below, an overloaded version of the procedure exists. It takes an integer status value, but the behavior varies among simulators.

    procedure STOP (STATUS: INTEGER);
    procedure STOP;
    

    Using the assert keyword

    A failsafe and universal way to stop a VHDL testbench is to create an assertion failure. That was the first way someone taught me to end the simulation when I was learning VHDL at the university.

    No additional imports are needed, and it works in all VHDL versions. Just make sure to use severity level failure, as shown in the example below.

    SEQUENCER_PROC : process
    begin
    
      -- Replace this line with your testbench logic
      wait until stop_condition;
    
      assert false report "Test: OK" severity failure;
    
    end process;
    

    And why do I hate this way of stopping a successful simulation?

    First of all, it’s looks strange and confusing to see the printout from the above example:

    # ** Failure: Test: OK
    

    It says that it’s a “failure”, but the test is “OK” at the same time. That’s because the assert statement is supposed to indicate an error condition and not the successful completion of the simulation.

    The other annoying problem I can think of is that it becomes difficult to find out programmatically if the simulation was successful.

    Most VHDL professionals start the simulations from a script at some point, for example, as part of a larger regression testing scheme. If the testbench also stops at an assertion failure when there is nothing wrong, we can’t use that as a marker to determine the health of the VHDL module.

    Using Tcl

    The last method of stopping the simulation that I’m going to cover is to use Tcl in combination with VHDL. Instead of stopping the testbench from the VHDL file, we set a regular VHDL signal when its time to stop. And beforehand, we configure the simulator to listen for a change on this trigger signal.

    Read also:
    Why you need to learn Tcl

    Look at the example below, which sets a signal named stop_condition when all test cases have completed.

      signal stop_condition : boolean;
    
    begin
    
      -- Replace this line with your DUT instantiation
      stop_condition <= not stop_condition after 1 ms;
    
      SEQUENCER_PROC : process
      begin
    
        -- Put your testbench logic here
    
        -- Pause this process forever after all tests are done
        wait;
    
      end process;
    

    You can put any testbench process that has done its job to sleep with a single wait statement before the end process tag. That will prevent it from restarting. The Tcl code for actually stopping the simulation differs between simulators.

    In ModelSim

    What we want is to stop the testbench when the stop_condition VHDL signal becomes true. We can do that by setting up a callback in Tcl before we run the VHDL testbench.

    According to the ModelSim Command Reference Manual, we can achieve that by using the Tcl when command. In the Tcl code below, we register such a callback, and then we start the simulator using run -all.

    when {stop_condition} {
      stop
      echo "Test: OK"
    }
    
    run -all
    

    Note that the code within the braces won’t run until the callback happens. When the VHDL code changes the stop_condition signal to true, the simulator will pause and execute the two lines. In the example, we stop the simulation and print “Test: OK” to the console. You could also have a Tcl exit command in there, which would quit the simulator, just like the VHDL finish procedure.

    # vsim 
    # Start time: 22:31:11 on Jun 22,2020
    # Loading std.standard
    # Loading work.using_tcl_tb(sim)
    # Test: OK
    # Simulation stop requested.
    

    The listing above shows the output printed to the ModelSim console when the Tcl / VHDL testbench completes. If you want to try it on your computer, use the form below to download the ModelSim project with all the examples from this article!

    Need the ModelSim project files?

    Let me send you a Zip with everything you need to get started in 30 seconds

    How does it work?

    Tested on Windows and Linux Loading Gif.. How it works

      Unsubscribe at any time

      In Vivado

      According to the Vivado Design Suite Tcl Command Reference Guide, we can register a Tcl callback using the add_condition command. The code below shows the Xilinx equivalent for the previously discussed ModelSim version.

      set sim_fileset sim_1
      launch_simulation -simset [get_filesets $sim_fileset]
      
      add_condition -notrace stop_condition {
          stop
          puts "Test: OK"
      }
      
      run all
      

      The -notrace switch prevents the code lines in the callback function from being echoed to the terminal as they execute. I prefer not having the extra clutter in the console.

      The listing below shows an excerpt from the simulation running in the Vivado simulator console.

      launch_simulation: ...
      add_condition -notrace stop_condition {
          stop
          puts "Test: OK"
      }
      condition8
      run all
      Test: OK
      

      Final thoughts

      As you have seen, there are many ways to terminate a VHDL simulation. However, the only one that I ever use is the VHDL-2008 finish procedure.

      All simulators support VHDL-2008 by now, and you don’t need to compile the RTL code in 2008, only the testbench. The finish procedure is the most portable method, and it allows you to stop the simulator when running in GUI mode, or quit when running in batch mode. Exactly the behavior I want most of the time.

      But there are advantages to the Tcl methods that are out of the scope of this article. When you have paused the simulator in the Tcl callback, you can do a lot more than just stopping the simulator and exiting. You can examine VHDL signals and even manipulate them using Tcl, while you are in the callback. That’s verification using Tcl.

      Leave a Reply

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

      This site uses Akismet to reduce spam. Learn how your comment data is processed.