Debug This! How To Simplify Coverage Analysis And Closure

Improving debug for SoCs and FPGAs.


For years the process of ASIC and FPGA design and verification debug consisted primarily of comprehending the structure and source code of the design with waveforms showing activity over time, based on testbench stimulus. Today, functional verification is exponentially complex with the emergence of new layers of design requirements (beyond basic functionality) that did not exist years ago — for example, clocking requirements, security requirements, safety requirements, and requirements associated with hardware-software interactions.

Given these complex interactions, effective debug often demands experts that are familiar with all the components and a debug environment that is aware of these heterogeneous requirements.

What follows is a new approach to debugging, which in this case is based on Questa Visualizer Debug. The new tool is a high-performance, scalable, context-aware debugger that spans the logic verification flow, including simulation, emulation, prototyping, testbench, low-power, and assertion analysis, which provides new functionality support to improve analysis, debug and coverage closure.

Starting with coverage gives you another way to diagnose problems. Visualizer provides improved coverage data representation, taking advantage of its existing rich visualization capabilities. It is built with improved capacity and performance to handle the largest coverage models. The visualization tools display UCDB results for both code coverage and functional coverage, based on a single environment that can go from coverage to the full power of debug.

This is the first step in the overall requirements for coverage closure productivity. There are two invocation modes for analyzing coverage results using the unified coverage database (UCDB) from Questa simulation:

  • Coverage View Mode allows access to all coverage analysis windows
  • Coverage Debugging Mode gives access to all coverage analysis windows and, additionally, to all debugging capabilities within Visualizer

Coverage windows provide a variety of ways to help you start exploring the coverage statistics of your design. To get started, you can use the coverage summary window to see an overview of coverage types across your design as shown in figure 1.

Figure 1. Coverage summary window.

Two types of color-coded charts provide a graphical overview of the entire coverage space. The left side shows a pie chart that represents total coverage percentages for covered (green) and missed (red) bins. The right side of the window shows bar graphs for the hit bin count, total bin count, and total coverage percentage for each cover type. Both code and functional coverage types in the given design are listed.

To analyze coverage per design hierarchy, you can start with the design coverage window shown in figure 2. It displays a textual listing of the hierarchical structure of your design along with columns of statistics for code coverage types (statement, branch, toggle, FSM, condition, and expression) as well as functional coverage types (cover groups, assertions, and directives) provided for the hierarchical instances shown in the left column (design hierarchy).

Figure 2. Design window.

You can also discover the coverage distribution across your design units with the help of Visualizer’s design units coverage window as shown in figure 3. It shows all the design units in a listed format with local coverage calculated and displayed for each design unit.

Figure 3. Design units window.

Let’s Get Debugging
Now we will take a walk through a full debugging path for an uncovered item and see how we can fix the code at the same place. Starting from the testplan tracker window in figure 4, you may need to add more criteria to determine which section to start with.

Figure 4. Testplan tracker window, zero coverage sections.

Adding a priority column, as shown in figure 5, makes it more obvious now that the operand limit sub-section has “zero” coverage percentage with very high priority “1”. Let’s track the assertion type coverage linked to that section.

Figure 5. Adding priority column in the testplan tracker window.

Double clicking on the assertion type “greater_ than_99_a” opens the assertion coverage window for more analysis as well as highlighting the assertion in the source window (figure 6).

Figure 6. Assertion coverage window.

The assertion coverage window provides more details about the design assertions (status, assertion types, pass/fail count, etc.). It shows all embedded and external assertions that were successfully compiled and simulated during the current session. The “greater_than_99_a” assertion is marked as 0% covered because the assertions failed. For more debugging, you need to examine this property and try to add it to the wave. All of that can be done in the same tool by invoking debugging mode.

Now by double clicking, you can navigate to the property definition in the source code window as shown in figure 7.

Figure 7. Double clicking source highlighting.

The condition says that at the negative edge of clock, if the state is “write_to_stack”, the “new_ result” signal should be less than 100. You can examine the values by either enabling value annotation or adding the property to the waveform window as seen in figure 8.

Figure 8. Waveform debugging.

Now you can see that at the negative edge of clock with the state equal to “write_to_stack”, the “new_result” signal is undefined.

You can fix this in the code by defining an initial value for the “new_result” signal as shown in figure 9.

Figure 9. Source code window.

Rerunning the simulation, going back to the assertion window, and searching for “greater*” in the “filter assertions” box results in getting full coverage for the assertion, as seen in figure 10.

Figure 10. Assertion coverage window with fixed assertion item.

By checking the testplan tracker window, we can see the “operand limit” now has full coverage, too (figure 11).

Figure 11. Testplan tracker window after fixing the assertion.

Wrapping up
The Visualizer Debug Environment helps you fix and debug all the uncovered items in your design at one place. It provides visualization tools that display coverage results for both code and functional coverage. The graphical user interface shows coverage statistics in instance and design unit views, helps you to see a quick overview of your design coverage in terms of coverage types, test plan sections and design units, and has detailed information on every coverage item via the coverage analysis window to facilitate the deep analysis for that item.

For more on how to simplify closure on tomorrow’s designs today, read the white paper.

Leave a Reply

(Note: This name will be displayed publicly)