Constraint Random Verification (CRV) is a technique for generating randomized test cases with specific constraints to ensure that the generated input stimuli meet certain design requirements.

In CRV, a set of constraints that capture the requirements of the design, such as data ranges, timing requirements, and interface protocols are defined. The testbench then generates a set of input stimuli that satisfies these constraints. The generated test cases can then be used to verify the design's functionality and performance.

CRV is a popular verification technique because it can generate a large number of randomized test cases that cover a wide range of scenarios. By using CRV, a verification engineer can quickly identify potential design bugs that may not be found using other verification techniques.

One of the major advantages of CRV is its scalability. It can be used to verify designs of any size and complexity, and can generate millions of test cases with relative ease. Additionally, CRV allows for quick iteration and modification of test cases, which can accelerate the verification process.

However, CRV also has some limitations. The generated test cases may not cover all possible scenarios, and some bugs may still go undetected. Additionally, creating effective constraints can be challenging, especially for complex designs. Finally, debugging failed test cases can be difficult, as the root cause of the failure may not be immediately apparent.


Let's say we want to verify a 4-bit adder that adds two inputs, A and B, and produces a 4-bit output, C. We want to use CRV to generate a set of test cases that cover a wide range of scenarios and satisfy the following constraints:

  1. The input values A and B should be within the range of 0 to 15 (4-bit numbers).
  2. The output value C should be within the range of 0 to 31 (5-bit numbers).
  3. The adder should operate correctly for both signed and unsigned inputs.
  4. The adder should operate correctly for all possible combinations of A and B.

To generate the test cases, we would define the constraints using a CRV tool, such as SystemVerilog's randomize() function. Here's an example code snippet that shows how the constraints could be defined in SystemVerilog:

class Adder;

  // Define the inputs and output
  rand bit [3:0] A, B;
  rand bit [4:0] C;

  // Define the constraints
  constraint c_adder { 	A inside {[0:15]}; 
  						B inside {[0:15]}; 
  						C == A + B;

  function void display();
    $display("A=0x%0h B=0x%0h C=0x%0h", A, B, C);

module tb;
  initial begin
	Adder m_adder = new();

	// Generate A and B randomly with the constraint that A and B cannot be the same
	m_adder.randomize() with { A != B };  



In this example, we define a testbench class that contains the inputs and output of the adder, as well as the constraints that we want to satisfy. Then we create an object of this class and randomize it. The values assumed by the variables inside the object will be based on the constraints defined in it.

Using this testbench, we can quickly generate a large number of randomized test cases that cover a wide range of scenarios and verify the functionality of the adder design.


Some of the potential limitations are :

  • Complexity: As the design becomes more complex, it may be difficult to define the constraints that fully capture the design requirements. In some cases, the constraints may need to be refined over multiple iterations to ensure that they cover all possible scenarios.
  • Debugging: With randomized test cases, it can be more difficult to isolate and debug failing tests. Since the inputs and outputs are generated randomly, it may be challenging to determine the root cause of a failure.
  • Coverage: While CRV can generate a large number of test cases, it does not guarantee that all scenarios have been covered. In some cases, additional test cases may need to be added to ensure full coverage.
  • Performance: Since CRV generates randomized test cases, it may not be efficient for performance-critical designs. In such cases, directed tests may be more appropriate.
  • Scalability: For very large designs, generating randomized test cases may become computationally expensive or may require excessive amounts of memory. In such cases, alternative techniques such as formal verification may be more appropriate.