Immediate assertions are executed based on simulation event semantics and are required to be specified in a procedural block. It is treated the same way as the expression in a if statement during simulation.

The immediate assertion will pass if the expression holds true at the time when the statement is executed, and will fail if the expression evaluates to be false (X, Z or 0). These assertions are intended for use in simulation and is not suitable for formal verification. It can be used in both RTL code and testbench to flag errors in simulations.

Syntax

 
// Simple assert statement  
assert(<expression>);
 
// Assert statement with statements to be executed for pass/fail conditions
assert(<expression>) begin
  // If condition is true, execute these statements
end else begin
  // If condition is false, execute these statements
end
 
// Optionally give name for the assertion
[assert_name] : assert(<expression>);
 

Immediate Assertion in Design

Here is an example where the design has an immediate assertion to check that a push request to the FIFO does not come at a time when the FIFO is already full. If the expression within the assert statement evaluates to true, the first begin end block will be executed and if the expression evaluates to false, the else part will be evaluated. This is much like the if construct, with the difference that it is not required for the user to place display statement to flag the error.

 
module my_des (my_if _if);
 
  always @ (posedge _if.clk) begin
    if (_if.push) begin
      // Immediate assertion and ensures that
      // fifo is not full when push is 1
      a_push: assert (!_if.full) begin
          $display("[PASS] push when fifo not full");
      end else begin
          $display("[FAIL] push when fifo full !");
      end
    end
 
    if (_if.pop) begin
      // Immediate assertion to ensure that fifo is not 
      // empty when pop is 1
      a_pop: assert (!_if.empty) begin
          $display ("[PASS] pop when fifo not empty");
      end else begin
          $display ("[FAIL] pop when fifo empty !");
      end
    end
  end
endmodule
 

Without such immediate assertions, one would need to duplicate the logic leading to that particular point using concurrent assertions that can take extra effort and resources.

 
interface my_if(input bit clk);
  logic pop;
  logic push;
  logic empty;
  logic full;
endinterface
 
module tb;
  bit clk;
  always #10 clk <= ~clk;
 
  my_if _if (clk);  
  my_des u0 (.*);
 
  initial begin
    for (int i = 0; i < 5; i++) begin
      _if.push  <= $random;
      _if.pop   <= $random;
      _if.empty <= $random;
      _if.full  <= $random;
      $strobe("[%0t] push=%0b full=%0b pop=%0b empty=%0b",
              $time, _if.push, _if.full, _if.pop, _if.empty);
      @(posedge clk);
    end
    #10 $finish;
  end             
endmodule
 

See that the time and line of assertion failure is displayed as *E.

Simulation Log
ncsim> run
[0] push=0 full=1 pop=1 empty=1
ncsim: *E,ASRTST (./design.sv,13): (time 10 NS) Assertion tb.u0.a_pop has failed 
[FAIL] pop when fifo empty !
[10] push=1 full=0 pop=1 empty=1
[PASS] push when fifo not full
ncsim: *E,ASRTST (./design.sv,13): (time 30 NS) Assertion tb.u0.a_pop has failed 
[FAIL] pop when fifo empty !
[30] push=1 full=1 pop=1 empty=0
ncsim: *E,ASRTST (./design.sv,5): (time 50 NS) Assertion tb.u0.a_push has failed 
[FAIL] push when fifo full !
[PASS] pop when fifo not empty
[50] push=1 full=0 pop=0 empty=1
[PASS] push when fifo not full
[70] push=1 full=1 pop=0 empty=1
ncsim: *E,ASRTST (./design.sv,5): (time 90 NS) Assertion tb.u0.a_push has failed 
[FAIL] push when fifo full !
Simulation complete via $finish(1) at time 100 NS + 0
./testbench.sv:25     #10 $finish;
ncsim> exit

Click to try this example in a simulator!   

Immediate Assertion in Testbench

Assume a class called Packet is created and randomized. However this example has a constraint error and randomization will fail. But, the failure will be displayed as a warning message and if the user is not careful enough the test may display incorrect behavior and may even appear to pass.

 
class Packet;
  rand bit [7:0] addr;
 
  constraint c_addr { addr > 5; addr < 3; }
endclass
 
module tb;
  initial begin
    Packet m_pkt = new();
 
    m_pkt.randomize();
  end
endmodule
 
Simulation Log
ncsim> run
    m_pkt.randomize();
                  |
ncsim: *W,SVRNDF (./testbench.sv,11|18): The randomize method call failed. The unique id of the failed randomize call is 0.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_addr { addr > 5; addr < 3; } (./testbench.sv,4)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints: rand variables: addr [./testbench.sv, 2] ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit

Instead an immediate assertion can be placed on the randomization method call to ensure that the return value is always 1, indicating the randomization is successful. If the assertion fails, it prompts the user to first look at the failure thereby reducing debug efforts.

 
class Packet;
  rand bit [7:0] addr;
 
  constraint c_addr { addr > 5; addr < 3; }
endclass
 
module tb;
  initial begin
    Packet m_pkt = new();
 
    assert(m_pkt.randomize());
  end
endmodule
 

Simulator assigns a generated name for the assertion if the user has not specified one.

Simulation Log
ncsim> run
    assert(m_pkt.randomize());
                         |
ncsim: *W,SVRNDF (./testbench.sv,11|25): The randomize method call failed. The unique id of the failed randomize call is 0.
Observed simulation time : 0 FS + 0
ncsim: *W,RNDOCS: These constraints contribute to the set of conflicting constraints:

  constraint c_addr { addr > 5; addr < 3; } (./testbench.sv,4)
ncsim: *W,RNDOCS: These variables contribute to the set of conflicting constraints:

rand variables:
       addr [./testbench.sv, 2]

ncsim: *E,ASRTST (./testbench.sv,11): (time 0 FS) Assertion tb.unmblk1.__assert_1 has failed 
ncsim: *W,RNQUIE: Simulation is complete.
ncsim> exit

In a similar way, assert can be used with any expression that evaluates to true or false within a procedural block.

You consent to our cookies if you continue to use our website. To know more about cookies, see our privacy policy. I accept cookies from this site.

Agree