SYNAPTICADcolon TECHNICAL PAPERS

Finally, A Verification GUI!

Graphical Code Generation Solves Verification Problems

Verification design complexity will force many of you to reconsider your current methods of creating test benches. But the available choices are difficult to evaluate. Will you stick with a modeling language like VHDL, Verilog, or SystemC? Or will you switch to one of the new verification languages such as OpenVera or the "e" language? Whatever choice you make, you are still faced with the problem of developing complex test benches, and maintaining that code over the course of several projects and possibly several verification engineers. Graphical code generation offers a language independent solution to test bench development that enables engineers to quickly describe test benches in a manner that is clear and precise.

Graphical test bench generation is the process of automatically creating test bench source code from an interface description and the bus transactions supported by the user's model. Instead of entering the test bench code by hand, the developer sends his HDL model under test to a test bench generator, which automatically extracts the port interface signals of the design into a timing diagram editing environment. This timing diagram editor is then used to create timing diagrams that describe the bus transactions for the test bench. By automating the most tedious aspects of test bench development, engineers can focus on the design and operation of the test bench rather than the painstaking aspects of code development.

Advanced Modeling

SynaptiCAD has developed TestBencher, a simple and intuitive graphical test bench generator that can be used to model very advanced bus transactions and interface descriptions. Pipelining, split-phase transactions, data structures and memories, and sequence recognition can all be modeled. TestBencher uses the timing diagrams to generate bus transactor source code in the user's preferred verification language. By using timing diagrams, the engineer can work at a higher level of abstraction, free from the coding details that arise solely from the choice of a particular verification language.

In the following sections we will examine some of the common problems that occur during functional verification and discuss how these problems are alleviated by graphical generation of the test bench code.

Race Conditions

Test benches are frequently plagued by concurrency and synchronization issues that cause race conditions and non-deterministic execution. While these issues are simple enough in theory to overcome, in reality they are extremely difficult to manage when coding by hand. One reason is that race conditions are caused by subtle design choices that cannot be automatically found in the same way that syntactical errors are. These conditions only manifest at run time. And often they are not even detectable at run time because the race conditions may "go the right way" on a particular simulator, only to fail when run on another simulator which made a different decision on the order in which to execute the theoretically parallel operations.

This poses a particular problem for IP vendors who need to distribute test benches to customers using simulators from different EDA vendors. Even when running on the same simulator, these sorts of race conditions can cause problems, because it is quite possible that a future release of the same simulator may change the order in which it executes processes to enhance simulation performance, leading to a severe maintenance headache.

Using a graphical code generator, circumstances that can cause race conditions are handled automatically. For example, race conditions are common in clocked functional test benches where signals are frequently driven and sampled at the same clock edge, but on different zero-time delta cycles. Figure 1 shows a simplified example of one way these races can occur. When hand coding, the engineer must be sure to write the code in such a way that the sampling occurs as the first thing that happens during each clock cycle. This is not an easy task in hardware description languages where signals frequently change state several times during a single clock cycle. However, the concurrent events that cause these race conditions are visually obvious in a timing diagram, leading to the easy avoidance of these types of race conditions.

Figure 1: Simple Race Condition

Constrained Random Data

During the implementation of a hand-coded test bench it is very easy to mismatch port sizes or make other similar small errors. Automatic code generation from graphical descriptions makes it easier for an engineer to define the information in one location and use it throughout the test bench. This is especially true for creating and maintaining complex data structures that are used to supply or store state information for different transactions. A small change to a data structure often causes code changes in many different locations in the test bench. With a graphical interface, once a data structure has been defined for a project, changes to that data structure are automatically propagated throughout the test bench.

The newer verification languages also support advanced data structure features such as constrained randomization of test stimulus during a simulation. With a graphical interface it is very easy to experiment with different randomization options because data structure changes are made in only one location. The example in Figure 2 shows the definition for a data structure that will provide constrained randomized data to a transaction. The fields specified for a data structure can be elements, arrays, or queues. Each field can have different properties defined, depending on the test bench language and the data type being used.

Figure 2: Complex Data Structure using Constrained Random Data

TestBencher also provides the capability of easily creating complex data structures which allow data to be read from or written to a file using a spreadsheet format or can store data internally in memory. By using the memory features, data can be stored in one transaction and then used by another.

Pipelined Transactions

Another challenge in verification of designs is the implementation of pipelined bus transactions. A common need is to model some form of pipelined bus master that gets its transaction data from a queue (FIFO) of data packets. A signal state driven by the queue will cause transaction execution to pause when the queue is empty until more data is placed in the queue. Otherwise, the bus transactor will take the next value from the queue and the transaction will continue execution immediately.

Figure 3 shows how a single timing diagram can be used to model both the read and write transactions of an AMBA (Advanced High-Performance Bus) master device. The AMBA bus is the main system bus for the ARM microprocessor family which supports pipelined burst reads and writes. In this example, the HADDR, HWDATA, HWRITE signals are set up to get their data from a queue called ahb which is filled by a standalone process at the top level of the test bench. Another queue is used by a sampling process callled CheckForRead_THEN to store data during a read operation. The first clock cycle in the diagram drives the HADDR and HWRITE signals. If it is a write operation, the data corresponding to that address is driven during the next clock cycle. If it is a read operation, the sampled data will be placed into a queue that can be monitored at the top-level test bench level or output to a file. There is a loop set up using markers to continue driving addresses and reading/writing data in this pipelined manner until the address queue is empty, with the address of the next read or write being transmitted at the same time as the data of the current read/write.

Figure 3: AMBA pipelined bus master driven by queue data structure

Figure 4: PCI Slave transaction implemented with Sequence Recognition

Test Bench Maintenance

Test bench code is often difficult to understand even when written using modular programming techniques because of the large amount of parallel activity occurring in the test bench, much of which is distributed throughout the test bench. Timing diagrams allow a much clearer and concise description of the interaction of parallel processes and signal activity. A graphical representation also facilitates the collaboration of many engineers on a single test bench by removing the need to interpret source code. Any engineer familiar with the design specifications is able to look at a given timing diagram and have an immediate understanding of what the transactor does, dramatically simplifying test bench maintenance.

Summary

Graphical automatic test bench generation provides a good solution to many of the problems faced during functional design verification. In this solution, timing diagrams are used to describe bus transactions in the test bench. Engineers are familiar with timing diagrams, so they are easily understood and the graphical representation enables the engineer to quickly visualize the test bench at a higher level of abstraction. The transactions depicted in the timing diagrams form modular components of a test bench that can quickly be modified and re-used in other designs, paving the way for faster verification of future designs.

Author

Donna Mitchell is Vice President of Strategic Marketing at SynaptiCAD Inc. She received her BS and MS degrees in electrical engineering from Virginia Tech. Mitchell is one of the two founders of SynaptiCAD Inc. She can be reached via email at Donna.

Back to Technical Papers page