Verilog verification tool

2009.07

 

Recent changes...


2010-01-07

new Resources section:

  • VHDL dual-language howto
  • HDL coding styles for synthesis: VHDL and Verilog code examples, together with Maia testbenches
Welcome!

Maia is a low-level verification language. Its purpose is to verify Verilog and VHDL modules, by using simple 'vectors' to drive the module inputs, and to check the resulting outputs. Maia code is simple and intuitive, and lets you trivially check HDL modules, without writing any Verilog or VHDL code. You don’t need to be a verification engineer to use Maia. You don't need to know how to write a testbench. If you know how your module should respond to a given set of inputs, then you can verify it.

You can download a Maia compiler (mtv) from the Downloads section. mtv translates your code into an HDL program, which is a complete self-checking testbench for your design. mtv currently produces Verilog output; in order to test your DUT, you will still need a Verilog simulator (or, if you're verifying VHDL code, a dual-language simulator). You don't need to change your design flow: you simply add the new auto-generated testbench to your design and simulate it, in exactly the same way that you'd simulate any other file.

mtv is currently free, and base versions are likely to remain free. The compiler is available for both Linux and Windows.

The Tutorials section contains a number of simple tutorial examples, which should get you up and running with Maia within a couple of hours. If you want to keep up to date with new releases, make sure to sign up on the Announcements mailing list.

 


What does a Maia program look like?

At its simplest level, a program is no more than a declaration of the DUT, together with a list of test vectors; see tut8.tv, for example, from the Tutorials section. However, this style is suitable only for the simplest testbenches. More complex programs have the look-and-feel of C code (and, in fact, Maia will compile many simple C programs without modification). However, Maia is not simply a C-lookalike: it automates the processes of driving and testing timed device inputs and outputs, clock generation, stability checking, pipeline handling, and so on. This housekeeping is all handled implicitly by the compiler, rather than being explicitly coded by the user. Maia also provides the features which are required for HDL coding and verification, and which are missing from traditional C-like languages: 4-value logic, arbitrarily-sized variables, and bitfield handling, for example.

For an example of a more complex program, see the triple-DES code in the Tutorials section. des_kats.tv is the Maia testbench; the equivalent Verilog testbench, for comparison, is des_kats.v.

 


What is a 'low-level verification language'?

Early versions of VHDL and Verilog were first released in 1985. In the succeeding 25 years there has, arguably, been only one significant development in commercial functional verification: the release of 'e' in 1996 (and, to a lesser extent, System Science's Vera, at about the same time). These languages introduced or popularised a number of key verification methodologies, including the use of temporal assertions, constrained randomised stimulus generation, and coverage analysis. For any significant ASIC development, there's little question that the use of the methodologies pioneered by these languages is fundamental to producing a Right-First-Time device.

Given this, surely it's clear that low-level verification - in other words, the verification of individual modules or limited groups of modules - should also be carried out using these languages, or their derivatives, such as SystemVerilog? Well... no. There are two very simple reasons:

  • These languages are primarily useful for system-level verification. System-level verification is difficult only because the limited complexity of individual modules multiplies exponentially as modules are combined. This rapidly leads to low coverage, and the requirement for randomisation techniques and coverage analysis. These techniques are simply not appropriate when verifying sub-components, before the complexity explosion has occurred.
  • Module verification is normally carried out by the same engineer who designed the module. Engineers are not generally also programmers, and so are unlikely to have the skills, or the inclination, to use complex object-oriented programming languages. It's simply a pointless distraction which introduces an unwanted level of complexity between the problem and the solution.

This is where Maia fits in. Maia is targeted at module-level verification. It was specifically designed to be trivially easy to learn and use; by, and for, hardware engineers. It is simple to use because it is a declarative language. This means that you don't need to derive and write down a recipe for solving your problem; you instead write down the expected solution. Finding a route to that solution is the computer's problem, not yours.

 

A what language?

Declarative. Take a look at this Maia program:

DUT {                            // the declaration of the Device Under Test
   module MAC1                   // declare the module interface...
      @(.stages(3))              // ...just paste in the Verilog module
       (input  RST, CLK,         //    declaration (replacing '#' with '@')
        input  [3:0] A, B,
        output [9:0] Q);
   
   [RST, CLK, A, B] -> [Q];      // declare the format of any vectors used below
   create_clock CLK;             // declare clock inputs, with default timing
}

main() {
   var4  i, j;
   var10 sum = 0;
   [1, .C, -, -] ->3 [sum];      // check that Q resets to 0 after 3 cycles

   for all i                     // loop over all input combinations
      for all j {
         /* derive the expected sum using an 8-bit multiply. Apply i and j to
          * the A and B inputs of the DUT, clock it, and confirm that the Q
          * output has the expected value 3 cycles later */
         sum += (i *$8 j);
         [0, .C, i, j] ->3 [sum];
      }
}

This is a complete, working, program; it tests a pipelined multiply-accumulate HDL module. The HDL code (in Verilog) multiplies two 4-bit inputs to give an 8-bit result, and adds the result to a 10-bit accumulator, over a period of 3 cycles. There's nothing in this Maia code that describes how the test should be carried out: the Maia code simply specifies the expected result. The compiler is smart enough to work out for itself how to carry out the test.

Compare this to the traditional 'imperative' solution, coded in Verilog or VHDL: you have to provide clock and reset generators; you have to generate and drive device inputs; you have to collect device outputs and compare them against expected values; you have to carry out stability checking; you have to carry out manual pipeline loading and flushing; you have to write multi-process code to synchronise everything, advance time, report errors, and so on. But why bother? What value does any of this actually add to the design process? And surely you have something better to do than repeat this pointless exercise on every project?

This is what distinguishes declarative languages from imperative languages, such as C, 'e', and SystemVerilog. You provide the expected solution: you don't waste your time explaining in minute detail how the computer might carry out the individual steps to arrive at an answer.

This is 2010, after all; not 1985.