EDN Access

[Download PDF version]

NOTE: Figures (below) link to Adobe Acrobat (PDF) files. To get the entire article in one PDF, click the button on the left.

GET ACROBAT READER


October 22, 1998


C modeling accelerates HDL-system design

C modeling's software models and benchmarks make it a powerful tool for enhancing HDL design and verification. You can use C models to evaluate early architectures and to verify intermediate and final system-simulation results.

Tom Balph And Pat O'Malley, Motorola Semiconductor

Verification is a major issue in any large Verilog-based chip design. How do you know that the results of your simulations are correct? And, if the results are incorrect, how do you know where the problem is? You'll find the design process even more complicated if the chip's pins give little visibility when you input data, the chip processes this data, and then you see only the results. An excellent approach is to compare the design's results with a good known reference model.

A C program is often an excellent choice for the reference model. Designers still do most initial system modeling and algorithm development in C, despite new tools and languages targeting these tasks. A C model is likely to be the first version of any new standard, and you frequently have good known C programs already available for use as a reference core.

It usually takes less time to develop a working C program than it does to develop good HDL code. The C language has more powerful math capability. Furthermore, the C programmer worries about only the data results rather than HDL-design concerns of timing and actual hardware implementation. Regardless of the starting point, you can modify C-model programs to verify intermediate results as well as functional simulation results.

C programs for design definition and verification fall into three major categories: algorithmic, bit accurate, and cycle accurate. An algorithmic, or traditional, program is most valuable for early function development and higher level design issues. Because you can write C models quickly, they can provide an effective means for early decision making that affects how you develop HDL code. Examples of tasks that you can evaluate in C before committing them to HDL are hardware partitioning, intermediate-storage requirements, arithmetic precision, and algorithm development. You can also easily iterate design tasks to speed system development. However, possible mismatches between C arithmetic and hardware arithmetic generally make the algorithmic C model a poor choice for an HDL-verification reference.

The bit-accurate C model is the preferred reference for HDL verification. You have to hand-code all of the arithmetic functions in the C model so that the C and HDL arithmetic results are exactly the same. The primary issues a C model must address to achieve bit accuracy are the order of operations, the number of bits, rounding, and saturation. Bit-accurate C models require more development time than traditional C models and often use the algorithmic model as the starting point. However, the initial traditional model still provides a valuable check against which you can compare the bit-accurate model.

Cycle-accurate C models have output values that agree exactly with the HDL model for every clock cycle. Cycle-accurate models have little advantage over bit-accurate models in verifying results. Turning a bit-accurate model into a cycle-accurate model can be trivial or a great deal of work, depending on your design. As you plan the C-model architecture and think about how routines have to run, the impact of cycle accuracy on your model will be obvious.

Usable algorithmic models

If you base your design on standards such as JPEG or MPEG, C models already exist and are readily available. They aren't exactly what you need, but they provide valuable starting points that significantly cut C development time. The Internet is a good place to start looking. Granted, there is much questionable code on the Net, but there is also some good code from reputable sources. Sometimes you can get C code from the organization that wrote the specification. For example, Dolby Laboratories (www.dolby.com) provides a C model as part of a Dolby-digital development agreement. Developers write many of these C models to promote implementation of a standard, so they are available free or for a nominal charge. Good designers write trustworthy code well enough to make modification practical. If the C code you obtain is written or documented so poorly that modification seems impractical, reconsider whether you can trust it as a reference.

Regardless of where you obtain the starting C code, you will end up modifying it. C programs written as software implementations of a particular function or algorithm seldom make good verification reference models without significant changes. The modifications depend heavily on the way someone has written the HDL and reflect the HDL structure, so the C programmer should be a member of the design team. Realize that once you start modifying the C code, you must be prepared to take ownership of the code. You can expect little or no support from the original authors for code you modify.

Another issue to consider before starting on the C model is how many ways you will use the model. Consider a design with an embedded processor. Will you use the C model to change the design functionality by adding new code for the embedded processor? In this case, you may want to emulate the embedded processor within the C model so you can try the new processor code on the C model. In other cases, you may want to have the C model and the embedded-processor code work in different ways, as long as they both produce the same results.

Regardless of where you start, use the first models developed to evaluate the algorithms, arithmetic requirements, and design structure. You can do this task totally in a C environment before you write any HDL code, with the results affecting the specification for the design to be implemented in an HDL. You should verify the modified C model against the original C model you obtained. You can often achieve verification by substituting one bit-accurate routine at a time into the original code to keep the differences between the two C models small and easy to inspect.

Modifying the model

Early design evaluation is important, but the primary benefit of a C model is to use it as a reference that you can compare with the HDL design during simulations. As an HDL testbench exercises your HDL design, it compares the results it sees with reference results generated by a bit-accurate C model and automatically flags any differences. Constructing a relatively simple, self-checking testbench by using the C model as a reference is straightforward. Such a testbench makes verification more efficient and much easier to automate for regression testing. Someone still has to analyze simulations that fail, but you can automate the decision on whether a simulation passes or fails.

The people who write the HDL code should not generate the bit-accurate C model. A separate effort on the C model provides a second opinion on the interpretation of the design specification. You should tightly couple the C-model and HDL teams, with frequent dialogue between them. C-code development normally occurs much faster than HDL development does. You can check out the C model before system-level HDL simulations; C- and HDL-model mismatches indicate HDL problems.

The bit-accurate model is normally derived from the algorithmic model and may require twice as much code as a traditional C-code implementation. Arithmetic functions and code partitioning are two primary considerations when writing the bit-accurate model. Arithmetic functions in the C model must be hand-coded so that both the C- and HDL- arithmetic results are exactly the same (for example, the same bit widths, rounding, and saturation). Listing 1 shows an example of rounding for the bit-accurate model versus that for traditional code. It is also a good idea to partition C-code functionality to match HDL-architecture partitioning.

Consider a JPEG function as a partitioning example. Simple JPEG encoding consists of a 2-D forward discrete-cosine transform (DCT), quantization, and Huffman encoding. The forward DCT is math-intensive. HDL arithmetic and standard C arithmetic may differ slightly, depending on whether the C program uses fixed- or floating-point math. One of the JPEG conformance tests is that the hardware forward-DCT results should be no worse than 51 LSB compared with a C double-precision, floating-point implementation. However, the Huffman step that occurs later in the JPEG-encoding process produces radically different output values given minor differences in input values. It is impractical to construct an HDL testbench that can verify the Huffman output results of an HDL model against a C model unless the Huffman input values are the same for both implementations.

Again considering the JPEG example, it is desirable to check the intermediate results of simulation at these functional boundaries: DCT, quantization, and Huffman encoding. If you partition the bit-accurate C-model code to reflect this structure, the testbench can isolate problems specific to the functional block causing the error. You can greatly speed debugging by identifying the flawed block instead of just checking final results.

Figure 1 shows a basic HDL-verification flow diagram for the JPEG example. The same set of input data stimulates the C and HDL models. The verification compares the simulation results of the C model with those of the HDL model and flags differences between the models. With this approach, the HDL testbench is self-checking and relatively simple. (Self-checking means that the testbench either reports that the simulation executed without error or reports what errors did occur.) The primary task in the testbench is to compare HDL- design results with the files that the C model generates and to report any differences.

It is easier to run the C model independent of the HDL simulation and to store results in files for use by the HDL testbench than it is to have the C model execute as part of the testbench. In addition to data results, the C model can also generate control data for the HDL design and store that data in a file. If you construct the bit-accurate C model to match the HDL architecture, you can then generate intermediate-results files and isolate simulation errors at the module level.

As previously mentioned, it is easiest to run the C model as a separate first step, store the results files, and then use the results files in an actual HDL simulation. The results files can provide a stimulus, such as control data, if required, and the actual results you use for checking. You can import the stimulus and results-file data directly into the HDL-simulation environment for checking.

The authors' scripts suit most Verilog simulators, such as Cadence's (www.cadence.com) Verilog-XL and synopsys' (www.synopsys.com) VCS. Verilog provides at least two ways to import file data. The simplest way is to build an input-source module based on a memory model. Once the module is instantiated into the testbench, the program calls a $readmemb or $readmemh task to read and load data from the specified results file into the memory model. Consider Listing 2, which illustrates the definition of a module decdata used to import data. The code defines a 32-bit memory block, mem, to hold the imported data. A counter increments the mem address every time the signal image_din_valid is active-high.

The testbench must then provide a way to access data from the memory block in a manner and time appropriate to properly use the data. A simple approach to checking results is to access the memory in a linear manner and present the new data each time the testbench HDL model generates a new result. In Listing 2, the testbench initializes the memory from the results file, test.data, using a $readmemh function. A 32-bit output image_din equals the memory-data contents at the current address, and you can use this data as stimulus to the testbench or to compare simulation results. The testbench can then do the checking and report any errors. When the testbench finds an error, it may be appropriate to stop the simulation, or you may continue to gather more results.

A second approach to importing results files is using Verilog Programming Language Interface (PLI) routines. PLIs are written in C and allow you to add custom system tasks to the Verilog code. For verification, you use PLIs primarily to add file I/O functions to the testbench. There are two reasons to consider using PLIs. First, the $readmemh approach can use an excessive amount of memory if your reference files are large and abundant. Second, you may want your reference files to contain data in a format that is incompatible with $readmemh or $readmemb. There is a learning curve to using PLIs, but the file I/O functions needed for verification are usually simple. Listing 3 provides an example of a PLI I/O routine.

You can use a C model as a testbench reference at a simple level or as a complex and powerful tool. In the most elementary situation, the C model can provide reference results that you can compare with simulation results even outside the testbench using simple software tools, such as a Unix "diff" command. The next level of complexity uses the C-model results to do real-time checking as the testbench simulations run. You enhance the debugging process by finding problems as they occur within the module boundaries. Perhaps the most rigorous use of a C model is to build a cycle-accurate model that provides a clock-cycle-by-clock-cycle reference. The scale and complexity of your design problem determine the value of investing your resources into C-model development.


Authors' biographies

Tom Balph has been with Motorola (www.mot.com) for 28 years. He is currently a technical staff member in the company's semiconductor sector, where he defines and implements system functions on silicon. Balph received a BSEE at the University of Cincinnati (OH) and an MSEE at Arizona State University (Tempe, AZ).

Pat O'Malley has been with Motorola for 15 years. He works in the consumer broadcast division as a member of the technical staff.


| EDN Access | Feedback | Table of Contents |


Copyright © 1998 EDN Magazine, EDN Access. EDN is a registered trademark of Reed Properties Inc, used under license. EDN is published by Cahners Business Information, a unit of Reed Elsevier Inc.