SYNAPTICADcolon TECHNICAL PAPERS
 

Test Bench Generation from Timing Diagrams

by Donna Mitchell

Appendix D to VHDL Made Easy by David Pellerin 1996

Introduction

Surveys of VHDL users have indicated that generation of VHDL test benches typically consumes 35% of the entire front-end ASIC design cycle. It is clear that automation of test bench generation would significantly reduce the costs of VHDL-based design. This section describes a method for automating the generation of VHDL test benches using a combination of graphical and equation-based methods.

Background: What is a Test Bench?

After a VHDL model is written, it must be tested to verify correct operation. To do this, the designer provides the simulator with a set of input signal transitions (stimulus vectors) to exercise the circuit. These stimulus vectors are usually grouped together in an entity called a test bench. Grouping the stimulus vectors together in an isolated entity provides a means to reuse the stimulus vectors as the VHDL code for the circuit changes (e.g. as the simulation models are changed behavioral models to structural models).

In VHDL there are two ways to write stimulus vectors: using wait statements or using transport statements. Transport-based test benches are smaller and easier to read than wait-based test benches, but wait-based test benches are easier to understand when single-stepping through a simulation to debug it. Figure 1 shows examples of both wait-based and transport-based test benches.

Transport VHDL Test Bench 
library ieee, std;
use std.textio.all;
use ieee.std_logic_1164.all;

entity testbench is
  port(
      CLK0      : out std_logic;
      SIG0      : out std_logic;
      SIG1      : out integer;
      SIG2      : out std_logic
      );
end testbench;

architecture test of testbench is
begin

  process
  begin
    CLK0 <="1" ;
    wait for 0 ps;
    while true loop
      CLK0 <="0" ;
      wait for 25000 ps;
      CLK0 <="1" ;
      wait for 25000 ps;
    end loop;
  end process;

  process
  begin

    SIG0 <=
      transport '1' after 0 ps,
      transport '0' after 50000 ps,
      transport '1' after 90000 ps,
      transport '0' after 175000 ps;
    SIG1 <=
      transport 4 after 0 ps,
      transport 16 after 55000 ps,
      transport 9 after 120000 ps,
      transport 12 after 180000 ps,
      transport 3 after 235000 ps;
    SIG2 <=
      transport '0' after 0 ps,
      transport '1' after 20000 ps,
      transport '0' after 40000 ps,
      transport '1' after 60000 ps,
      transport '0' after 80000 ps,
      transport '1' after 100000 ps,
      transport '0' after 120000 ps,
      transport '1' after 140000 ps,
      transport '0' after 160000 ps,
      transport '1' after 170000 ps,
      transport '0' after 180000 ps,
      transport '1' after 190000 ps,
      transport '0' after 200000 ps,
      transport '1' after 210000 ps,
      transport '0' after 220000 ps,
      transport '1' after 230000 ps,
      transport '0' after 240000 ps,
      transport '1' after 250000 ps;
  end process;

end test;
Wait VHDL Test Bench
library ieee, std;
use std.textio.all;
use ieee.std_logic_1164.all;

entity testbench is
  port(
      CLK0      : out std_logic;
      SIG0      : out std_logic;
      SIG1      : out integer;
      SIG2      : out std_logic
      );
end testbench;

architecture test of testbench is
begin

  process
  begin
    CLK0 <="1" ;
    wait for 0 ps;
    while true loop
      CLK0 <="0" ;
      wait for 25000 ps;
      CLK0 <="1" ;
      wait for 25000 ps;
    end loop;
  end process;

  process
  begin
  SIG0 <="1" ;
  SIG1 <="4;
  SIG2 <="0" ;
  wait for 20000 ps;

  SIG2 <="1" ;
  wait for 20000 ps;

  SIG2 <="0" ;
  wait for 10000 ps;

  SIG0 <="0" ;
  wait for 5000 ps;

  SIG1 <="16;"
  wait for 5000 ps;

  SIG2 <="1" ;
  wait for 20000 ps;

  SIG2 <="0" ;
  wait for 10000 ps;

  SIG0 <="1" ;
  wait for 10000 ps;

  -- More code removed because
  --  of space limitations

wait for 848 ps;

  wait;
  end process;

end test;wait;

Figure 1: VHDL test benches

Writing a VHDL test bench is one of the most tedious and error prone parts of the simulation process. In VHDL you are required to specify the time for each signal transition. It is easy to make mistakes when writing an HDL test bench, because it is difficult to visualize the temporal relationships between transitions on different waveforms. For instance, take a look at the transfer statements in fig. 1 and see if you can figure out if the first rising edge of SIG0 comes before the rising edge of the third cycle of clock clk. This is where a graphical timing diagram editor like The WaveFormer excels. Figure 2 shows a timing diagram that generated the code in Figure 1. Looking at the timing diagram, it is easy to see that the SIG0 transition does occur before the rising edge of the clock.

Pvme_f2.png (3885 bytes)

Figure 2: Timing diagram that generated the code of Figure 1

Automating Test Bench Generation using The WaveFormer

The WaveFormer is a timing diagram editor with the ability to generate and translate stimulus vectors to a variety of different simulation and documentation formats (including HDL test bench formats). Although specialized tools for translating stimulus vectors have existed for several years, these tools have traditionally been high-priced niche products that don’t offer the sophisticated timing analysis and documentation features of timing diagram editors. Timing diagram editors such as The WaveFormer allow users to interactively perform timing analysis on their waveforms and document timing relationships using delays, setups, holds, and textual information. These features along with the ability to generate test benches and import results from simulations and test equipment makes The WaveFormer the ideal environment for waveform manipulation and analysis.

write_cycle_timing_diagram.png (17256 bytes)

Figure 3: Picture of The WaveFormer

Tutorial: Generating VHDL Test Benches with The WaveFormer

In this tutorial we will demonstrate how to use The WaveFormer to generate VHDL test benches. You can perform the tutorial using The WaveFormer evaluation version located on the CD ROM at the back of this book. If you are running Windows 3.1 then you will also have to install the Win32s libraries which are also located on the CD ROM (Windows 95 & NT users do not need the Win32s libraries). A SunOS UNIX evaluation version can also be downloaded from SynaptiCAD’s web site at http://www.syncad.com/. Figure 2 is the completed tutorial timing diagram.

Automatically generate a clock signal using The WaveFormer

The WaveFormer supports automatic generation of periodic signals (e.g. a 66MHz clock with a 40% duty cycle). To create a periodic waveform, the user enters information about the clock such as frequency and duty cycle and The WaveFormer generates an appropriate waveform. We begin the tutorial by creating a clock named "clk0" with a period of 50ns (20mhz).

Add clock CLK0.
Click on the Add Clock button (top left hand corner of the screen). This will cause the Edit Clock Parameters dialog box to appear. Enter the name CLK0 in the Label edit box. Enter 50 in the Period box. Make sure the MHz/ns radio button is selected. Note: the frequency will change to match the new period value when you move the selection to another edit box. Left mouse click on the OK button to close the dialog and create the clock.

Although we only used a value to set the period of this clock, clock attributes can also be based on formulas. Clock formulas can be defined in terms of timing parameters and the attributes of other clocks. For more information on clock parameters, read the on-line help Table of Contents/Design Function Index/Clocks entry.

Your clock should look like the clock in figure 2. If you made a mistake designing the clock, double left click on a clock segment to reopen the "Edit Clock Parameters" dialog box. Double left clicking on a clock edge opens up the "Edge Properties" dialog box which displays the edge time.

Draw signals in The WaveFormer

Next we will draw signals SIG0 and SIG1.

Add SIG0 and SIG1
Left mouse click on the Add Signal button two times to add two signals.
Sketch the waveform for SIG0 using high and low segments.
Left click on the LOW button, then left click on the HIGH button. This sets up the drawing and next drawing state (notice that the HIGH button is red and the LOW button has a red T at the top). Next, put the mouse inside the drawing window at the same level as SIG0 and left click at approximately 50ns, 90ns, 175ns, and 270ns. Your waveform should look like SIG0 of figure 2.
Sketch the waveform for SIG1 using just valid segments.
Left click on the VAL button to turn it red, and left click again on the VAL button to move the red T to the button. This causes the VAL button to stay selected when you draw waveform segments. Next put the mouse inside the drawing window at the same level as SIG1, left click at approximately 55ns, 120ns, 180ns, 235ns, and 270ns. Your waveform should look like SIG1 of figure 2 without the state values (we will add the state values later in the tutorial).

If you made a mistake drawing the waveforms, use the following editing techniques to correct the waveform: 1) drag and drop signal edges, 2) select a segment then click a new state button to change the state of the segment, 3) select an edge, a segment, or a signal name and hit the delete key to delete the selected object, 4) double click on an edge or signal name to edit it, 5) double click on a segment to insert a new segment.

Generate Signals using Waveform Equations

If a waveform has a periodic or known pattern, then it is easier to specify the signal as an equation rather than drawing each repetitive piece of the signal. The WaveFormer has an equation interface for just those types of signals. For example, SIG2 is a periodic waveform with a change in frequency from 25Mhz to 50Mhz which is generated from the following temporal equation:

          SIG2 (20ns=0 20ns=1)*4 (10ns=0 10ns=1)*5
Generate SIG2 using the above equation.
Choose the Export\Draw Waveform Equation menu option, which will open a dialog of the same name. Type the equation into the edit box in the dialog, and choose the OK button. This creates a signal in The WaveFormer called SIG2 with an initial frequency of 25MHz (period = 20+20 = 40ns) for 4 cycles and switches to 50Mhz for 5 more cycles. This type of waveform is tedious to draw by hand, but can be concisely expressed as a temporal equation.

If a signal named SIG2 already existed when this equation was entered, this waveform would be added on to the end of the signal. This ability to concatenate waveforms to an existing signal in combination with the scripting language of The WaveFormer (discussed further in the import/export section) makes it possible to create extremely complex waveforms.

Advanced data types: Extended State Information and Object Properties

The WaveFormer supports both simple std_logic signals and complex user-defined data types for VHDL test benches. By default all signals are assumed to have a type of std_logic and a direction of out (CLK0, SIG0, and SIG2 will use the defaults for this tutorial). To model complex data types and user defined states, The WaveFormer has object properties and extended state features which allow the user to attach arbitrary data to objects in the timing diagram. This means that The WaveFormer can support all VHDL data types including arrays and user-defined enumerated types.

To demonstrate the object properties and extended state features, we will add information to SIG1 so that it is exported as a VHDL signal with a type of integer, and each state in SIG1 will have an integer value.

Change the type of SIG1 to integer.
First choose the Export\Edit Object Properties menu option which opens a dialog box of the same name. From the Object Type drop-down listbox at the top of the dialog, select Signal Properties. Select the Sig1 from the “Object Name” listbox. Type VHDLtype into the Property edit box. Type integer into the Value edit box. Click the ADD button to add it to the signal. Click the OK button to close the dialog. You could also change the direction by adding a VHDLdir property and value but we don’t do this in this tutorial.
Add the integer state values to SIG1.
First select a segment of SIG1 by left clicking on it, a selected segment has a dotted box drawn around it. Next left click on the HEX button, this will open the Edit Bus dialog. Type an integer into the ExState edit box, and choose the next or previous buttons (alt-n or alt-p keys) to edit the segments on either side. In figure 2, SIG 1 has 4, 16, 9, 12, and 3 signal state values. Click OK when you are done.

Note: The type and state values of SIG1 could be anything that the user desired. For example the VHDLtype could be MYCOLOR and extended state information could be RED, BLUE, BRIGHT BLUE, GREEN, and PURPLE.

Export to VHDL

Next export the timing diagram to a VHDL test bench.

To export the timing diagram to VHDL:

  • Choose the Export\Export Signals As menu option. This will open the Export Dialog.
  • Choose the type of script using the "Save File as Type" list box in the lower left corner of the Export Dialog Box. We used VHDL transport(*.vhd)s and VHDL wait(*.vhd)s to generate the test benches in figure 2.
  • Pick a file name and click the OK button. The WaveFormer will produce a file with the timing data in that format.
  • View the generated file using a text editor (e.g. Notepad).

The generated file should look approximately like the file displayed in Figure 1 (because of drawing differences the times for signal transitions may differ slightly).

Customizable VHDL output using Waveperl Scripting Language

The WaveFormer uses a scripting language based on Perl (Practical Extraction and Report Language) to import and export waveform stimulus. The use of a scripting language means users can modify the output of existing translation scripts and even create their own scripts to support waveform formats used by custom test equipment and internally developed software.

The WaveFormer currently creates input stimulus for:
VHDL, Verilog, SPICE (analog & digital formats supported), Viewlogic's Viewsim simulator, and Mentor’s QuickSim simulator
Waveform import is supported for:
Accolade's VHDL simulator, WellSpring's Verilog simulator, Viewlogic's Viewsim simulator, and Boulder Creek Engineering's Pod-A-Lyzer (a PC-based logic analyzer).

We are adding new scripts all the time so send us an email at Sales Office and tell us what import/export formats that you would like us to add. Also all the scripts that ship with The WaveFormer are editable by the user. This is particularly useful because most waveform timing information is written in only a couple of different formats. So most likely if you have a proprietary format then there is probably a Waveperl script that does most of what you need done. Waveperl scripts are normal text files that can be edited with any text editor.

Beyond Simple Stimulus Generation:

In this tutorial we have a demonstrated how to create a simple timing diagram using drawn and equation-generated signals and clocks, and how to generate a VHDL test bench from this diagram. We have not demonstrated the timing analysis features of The WaveFormer such as min/max delay path calculations, setup and hold checking, timing parameter equations, reconvergent fanout calculation, and library generation. These features are covered in the on-line tutorials and examples that ship with the evaluation version.