by Paul B. Egan, Rockwell Automation
Using formal analysis to validate chip level connectivity is one of "The Top Five Formal Verification Applications" (Verification Horizons Oct 2012), and has been proven as the most efficient way to verify interconnects in complex Systems on Chips (SoCs) [3, 4, 5]. So, could formal analysis also be applied at the module level, even small modules? To test our theory, formal connectivity verification was first run on a relatively small block that contained eight instances each of seven different modules (56 instances total). We discovered that, not only does it work well on small blocks, formal analysis found two bugs that would have been very difficult to find in simulation.
Traditionally, connectivity verification at the block level has been completed using dynamic simulation, and typically involves writing directed tests to toggle the top level signals, then debugging why signal values did not transition as expected. For modules with a high number of wires and many modes of operation, the number of required tests quickly becomes unmanageable. We were searching for a better approach.
This article will explain how we applied formal analysis at the block level, extended this to full chip and describe how we significantly reduced verification time at both the block and chip level. Just like a block and tackle provides a mechanical advantage, the formal connectivity flow provides a verification advantage.
Formal connectivity verification was first used on a relatively small block (retriggerable timers) that contained eight instances of seven different modules (56 instances total). The sub-modules are connected to common busses at the top level of the block; several instances have a port that forms a part-select (slice) for a vector net. The RTL code for this module is very compact due to the use of a generate construct (pseudo code shown here):
generate for (gen_modules = 0; gen_modules
< NUM_OF_MODULES; gen_modules++)
begin : gen_blk_module_1
module_1 u_module_1 ()
generate for (gen_modules = 0; gen_modules
< NUM_OF_MODULES; gen_modules++)
begin : gen_blk_module_N
module_N u_module_N ()
The connectivity verification flow is a very simple three step process as shown in Figure 1.
Figure 1. Connectivity Formal Verification Flow
- Create a spreadsheet that defines point to point connections
- Run script to generate properties
- Run static Formal Verification
STEP 1: CREATE THE SPREADSHEET
The connectivity is defined in a Tab Separated Value (TSV) file (shown below) that can be created using any standard text editor, but using a spreadsheet tool like MS-Excel or OpenOffice Calc makes the data entry easier. For the retriggerable timers block, the connections are all point to point without any delay, so the "connect" keyword is used for the connectivity check:
STEP 2: RUN SCRIPT TO GENERATE PROPERTIES
Once the TSV file has been created, run the utility to generate the properties used for formal verification.
GenConn timers.tsv -m -tsv -sva -o checkers.sv
STEP 3: RUN STATIC FORMAL VERIFICATION
The next step in the process is to run Formal analysis using the generated checkers. Two additional files are required to run Formal, an initialization sequence file that describes the reset sequence for the design and a directives file that defines the clock(s). The design and checkers are compiled, and Formal is run:
vmap work work
vlog –f filelist –sv
vlog –sv checkers.sv
qformal –c –od conn_results –do "do directives.tcl; \
formal compile –d retriggerable_timers_wrapper
–cuname bindings; \
formal verify –init init.seq –effort high; exit"
The compilation and Formal analysis commands are best done using a script in the language of your choice (i.e. TCL, Make, Perl, Python, etc). After confirming all syntax and hierarchical paths were correct on a single connection, we added the remaining paths to the TSV file. This block has 112 connections, but only 14 unique connections per instance so populating the TSV file was easily done using copy/paste/edit.
Once we were comfortable with the connectivity verification flow on a small block, the next step was to use this process on a larger, more complex block - the I/O multiplexer (pin_multiplex) block in our design. Our design has 8 groups of General Purpose Input Output (GPIO) pins, each with 16 pins that can be connected to 16 different peripherals (SPI, Ethernet, UART, I2C, etc) inside the chip, or configured as a plain old input or output. The pin_multiplex block is a large programmable multiplexor that connects the peripherals in the SoC core to/from the I/O pads through the GPIO block. The GPIO block contains additional multiplexing logic that we verified with chip level connectivity testing.
The pin_multiplex block has approximately 6144 paths to check – 2048 outputs, 2048 output enables, 2048 inputs. Creating the TSV file for this block took a bit more time, and uses a conditional connect check:
After we completed testing at the block level, we ran at the chip level. The pin_multiplex TSV file was used as a starting point for the top level TSV file; path names were edited using global search/replace, and the condition was updated to include the GPIO block:
enable_g1_g2_ff==1'b1) & (neo_top_
Formal analysis on the retriggerable timers block found two bugs that would have been very difficult to find in simulation: incorrect vector bit-select, and an incorrect indexed part select on a vectored net connection (see code on the opposite page).
For this particular block, tool setup was insignificant, less than an hour to create an input spreadsheet; runtime was less than 2 minutes. Closer inspection of the RTL shows there are several potential errors that were easily detected using Formal:
- Vector order on secondary_trigger_count_rd_data
- Vector bit select
- Indexed part-select base expression (vector[base_expr+: width_expr])
- Indexed part-select width expression
- Indexed part-select operator (-:, +:)
Note: For detailed syntax rules see IEEE 1364-2005 section 5.2.1 Vector bit-select and part-select addressing Analysis of the pin_multiplex block found several "showstopper" bugs:
- Incorrect output enable on a SPI port
- Incorrect output enables on the ECC pins for a memory port
- Missing pin assignments for a memory port
- Pin connections where none should exist
Since our chip is designed to boot from an external device, the first two bugs would have made the chip almost unusable. Setup, analysis and debugging failures took about 32 hours, and runtime was about 2 or 3 minutes. We estimate using formal analysis to verify connectivity was more than 10X faster than using simulation. Another critical advantage is that formal is exhaustive; not only were all "legal" pin assignments validated, we confirmed there were no "illegal" pin assignments either. For example, a SPI clock can be connected to only 4 of the 128 available pins. Verifying the legal pin connections in simulation can be done during chip level functional testing of the peripherals, but it is much more difficult to verify if the SPI clock is connected to any of the 124 pins it shouldn't be.
Connectivity checking at the chip level was nearly as easy as our smallest block since we had already verified the pin_ multiplex block. Setup and analysis was less than 16 hours; runtime was less than 5 minutes, and no bugs were found.
output logic [23:0] secondary_trigger_count_rd_data,
generate for (gen_modules = 0; gen_modules < NUM_OF_TIMERS; gen_modules++)
begin : seed_enable_blks
// Bug #1
// gen_control_reg should be gen_modules
// Bug #2 [gen_modules +: 3] should be [gen_modules*3 +: 3]
.secondary_trigger_count_rd_data(secondary_trigger_count_rd_data[gen_modules +: 3])
endgenerate // block : seed_enable_blks
Formal analysis for SoC interconnect verification is a proven methodology and this technique should also be applied at the module level, even small blocks. This is especially true for any modules that have a large number of wide busses connected, and modules that use Generate constructs and/ or Vectors with part-selects (base_expr +/-: width_expr). The setup is semi-automated, does not require a testbench, has fast runtime, and is well supported by the Electronic Design Automation (EDA) tool vendors.
Where the connectivity flow really shined was for the dreaded late stage design change. In our case a change request was made to add an output signal to two multiplexed output pins; the initial estimate of schedule impact was 1 week to implement and verify; the actual verification took less than 15 minutes – edit 4 lines in the TSV file and rerun Formal.
- "IEEE Standard for Verilog Hardware Description Language", IEEE STD 1364-2005, 2005
- "IEEE Standard for System Verilog-Unified Hardware Design, Specification, and Verification Language", 1800-2009, 2009
- Mark Handover, Abdelouahab Ayari, "Using Formal Verification to check SoC connectivity correctness", Mentor Graphics
- Olivia Wu, "Push Button Verification of Complex Pad Ring Logic Direct from an Executable Specification" Proceedings of the 48th Design Automation Conference, 2011
- Subir K. Roy, "Top Level SoC Interconnectivity Verification using Formal Techniques", International Workshop on Microprocessor Test and Verification, Austin, Texas,USA, 2007
Back to Top