Friday, 17 April 2015

Bind Assertion in SystemVerilog

When RTL is already written and it becomes responsibility of a verification engineer to add assertion. And RTL designer does not want verification engineer to modify his RTL for the sake of adding assertion then, bind feature of SystemVerilog comes for rescue.
One can write all the assertion he or she wants to write in a separate file and using bind, he or she can bind the ports of his assertion file with the port/signals of the RTL in his test-bench code. What a cool feature.

The bind directive can be specified in any of the following:
  • A module
  • An interface
  • A compilation-unit scope

There are three forms of bind syntax.
  1. Binding is done to ALL instances of a module.
  2. Binding is done to single instance of a module.
  3. Binding is done to list of (multiple) instance of a module.

//=================================================
// Actual DUT RTL
//=================================================

module dut (
            input  wire clk,
            input  wire req,
            input  wire reset,
            output reg  gnt
           );
  always @ (posedge clk)
  begin
    gnt <= req;
  end
endmodule : dut
//=================================================

//=================================================
// Assertion Module
//=================================================

module assertion_module(
                        input wire clk_ip,
                        input wire req_ip,
                        input wire reset_ip,
                        input wire gnt_ip
                       );
  //=================================================
  // Sequence Layer
  //=================================================

  sequence req_gnt_seq;
    (~req_ip & gnt_ip) ##1 (~req_ip & ~gnt_ip);
  endsequence
  //=================================================
  // Property Specification Layer
  //=================================================

  property req_gnt_prop;
    @ (posedge clk_ip)
      disable iff (reset_ip)
        req_ip |=> req_gnt_seq;
  endproperty
  //=================================================
  // Assertion Directive Layer
  //=================================================

  req_gnt_assert : assert property (req_gnt_prop)
                   else
                   begin
                     $display("@%0dns Assertion Failed", $time);
                   end
endmodule : assertion_module
//=================================================


//=================================================
// Bind Module
//=================================================

module binding_module();
//=================================================
// Bind by Module name : This will bind ALL instance of DUT
//=================================================

// Syntax:
//   bind   RTL_Module_Name   Assertion_module_Name   Instance_Name


  bind dut assertion_module U_assert_ip (
                                         .clk_ip   (clk),
                                         .req_ip   (req),
                                         .reset_ip (reset),
                                         .gnt_ip   (gnt)
                                        );


//=================================================
// Bind by instance name : This will bind only one particular instance of DUT
//=================================================

// Syntax:
//   bind   RTL_Module_Name   :Instance_Path   Assertion_module_Name   Instance_Name


//  bind dut :$root.bind_assertion_tb.DUT_INST_1 assertion_module U_assert_ip (
//                                                                             .clk_ip   (clk),
//                                                                             .req_ip   (req),
//                                                                             .reset_ip (reset),
//                                                                             .gnt_ip   (gnt)
//                                                                            );


//=================================================
// Bind by instance name list : This will bind multiple instances of DUT
//=================================================

// Syntax:
//   bind   RTL_Module_Name   :Instance1_Path, Instance2_Path   Assertion_module_Name   Instance_Name

//  bind dut :$root.bind_assertion_tb.DUT_INST_1, $root.bind_assertion_tb.DUT_INST_2 assertion_module U_assert_ip (
//                                             .clk_ip   (clk),
//                                             .req_ip   (req),
//                                             .reset_ip (reset),
//                                             .gnt_ip   (gnt)
//                                           );


//=================================================
endmodule : binding_module


//=================================================
// TEST Module
//=================================================

module bind_assertion_tb();

  reg clk = 0;
  reg reset, req = 0;
  wire gnt;
 
  always #3 clk ++;
 
  initial begin
    reset <= 1;
    #20 reset <= 0;

    // Make the assertion pass

    #100 @ (posedge clk) req  <= 1;
    @ (posedge clk) req <= 0;

    // Make the assertion fail
    #100 @ (posedge clk) req  <= 1;
    repeat (5) @ (posedge clk);
    req <= 0;

    #10 $finish;
  end
 
  dut DUT_INST_1 (clk,req,reset,gnt);
  dut DUT_INST_2 (clk,req,reset,gnt);
  dut DUT_INST_3 (clk,req,reset,gnt);
 
endmodule : bind_assertion_tb



//=================================================
//Output:  Bind by Module name : This will bind ALL instance of DUT
//=================================================

//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_3.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_3.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_3.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'
//@261ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'
//@261ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_3.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'



//=================================================
//Output: Bind by instance name : This will bind only one particular instance of DUT
//=================================================

//"bind_top.sv", 43: bind_assertion_tb.DUT_INST.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'
//@261ns Assertion Failed



//=================================================
//Output: Bind by instance name list : This will bind multiple instances of DUT
//=================================================

//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 237s failed at 243s
//        Offending '((~req_ip) & gnt_ip)'
//@243ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 243s failed at 249s
//        Offending '((~req_ip) & gnt_ip)'
//@249ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 249s failed at 255s
//        Offending '((~req_ip) & gnt_ip)'
//@255ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_1.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'
//@261ns Assertion Failed
//"bind_top.sv", 43: bind_assertion_tb.DUT_INST_2.U_assert_ip.req_gnt_assert: started at 255s failed at 261s
//        Offending '((~req_ip) & gnt_ip)'
//@261ns Assertion Failed



 

Thursday, 16 April 2015

Pass unpack array between two modules

module module1();
  bit dyn_ary[11];
  initial begin
    foreach (dyn_ary[i]) begin
      dyn_ary[i] = $urandom_range(10, 12323);
    end
 
    #40;
    foreach (dyn_ary[i]) begin
      $display ($time,,"module1 : dyn_ary[%0d]=%0h", i, dyn_ary[i]);
    end
  end
endmodule : module1


module module2 (input bit dyn_array[11]);
  initial begin
    #100;
    foreach (dyn_array[i]) begin
      $display($time,,"module2 : dyn_array[%0d]=%0h", i, dyn_array[i]);
    end
  end
endmodule : module2
 

module top_module();
  module1 M1 ();
  module2 M2 (.dyn_array(M1.dyn_ary));
endmodule : top_module


Output:
 40 module1 : dyn_ary[0]=0
 40 module1 : dyn_ary[1]=0
 40 module1 : dyn_ary[2]=1
 40 module1 : dyn_ary[3]=0
 40 module1 : dyn_ary[4]=1
 40 module1 : dyn_ary[5]=1
 40 module1 : dyn_ary[6]=0
 40 module1 : dyn_ary[7]=1
 40 module1 : dyn_ary[8]=0
 40 module1 : dyn_ary[9]=1
 40 module1 : dyn_ary[10]=1
100 module2 : dyn_array[0]=0
100 module2 : dyn_array[1]=0
100 module2 : dyn_array[2]=1
100 module2 : dyn_array[3]=0
100 module2 : dyn_array[4]=1
100 module2 : dyn_array[5]=1
100 module2 : dyn_array[6]=0
100 module2 : dyn_array[7]=1
100 module2 : dyn_array[8]=0
100 module2 : dyn_array[9]=1
100 module2 : dyn_array[10]=1

Strength comparision in Systemverilog

`define compSigValues(sig_a, sig_b)\
  begin\
  string sig_a_strength, sig_b_strength;\
  sig_a_strength = $sformatf("%v", sig_a);\
  sig_b_strength = $sformatf("%v", sig_b);\
  if ( sig_a_strength == sig_b_strength) begin\
    $display("Signal values %s and %s match", sig_a_strength, sig_b_strength);\
  end\
  else begin\
    $display("Signal values %s and %s don't match", sig_a_strength, sig_b_strength);\
  end\
 end

module top ();
  wire a, b;
  wire c, d;

  assign (strong1, strong0) a = 1;
  assign (pull1, pull0)     b = 1;
  assign (weak1, weak0)     c = 1;
  assign (weak1, weak0)     d = 1;

  initial begin
    #5;
    $display("comparision of a, b");
    `compSigValues(a, b)

    $display("comparision of c, d");
    `compSigValues(c, d)
  end
endmodule

 
Output:
comparision of a, b
Signal values St1 and Pu1 don't match
comparision of c, d
Signal values We1 and We1 match

Constraint Override in Systemverilog

Same variable is constrained in base as well as child (extended) class but constraint name is same in both base  (constraint_cn) and child (constraint_cn) class.

class base;
  rand int unsigned data;
  constraint constraint_cn
  {
    data inside {[1:100]};
  }
endclass : base

class child extends base;
  constraint constraint_cn
  {
    data inside {[101:200]};
  }
endclass : child

module top();
  child C;
  initial begin
    C = new();
    if (!C.randomize()) begin
      $display("Randomization failed");
    end
    else begin
      $display("data = %0d", C.data);
    end
  end
endmodule : top

Output:
data = 114

Tool will try to solve only child (extended) class's constraint because Child class Override base class's Constraint as both constraint is having same name.

Take another example.


Same variable is constrained in base as well as child (extended) class but constraint name is different in base (constraint_cn) and child (constraint_cn_c) class.

class base;
  rand int unsigned data;
  constraint constraint_cn
  {
    data inside {[1:100]};
  }
endclass : base

class child extends base;
  constraint constraint_cn_c
  {
    data inside {[101:200]};
  }
endclass : child

module top();
  child C;
  initial begin
    C = new();
    if (!C.randomize()) begin
      $display("Randomization failed");
    end
    else begin
      $display("data = %0d", C.data);
    end
  end
endmodule : top

Tool will give compilation error like,
Solver failed when solving following set of constraints
 
rand bit[31:0] data; // rand_mode = ON
constraint constraint_cn    // (from this) (constraint_mode = ON) (top.sv:5)
{
   (data inside {[1:100]});
}
constraint constraint_cn_c    // (from this) (constraint_mode = ON) (top.sv:14)
{
   (data inside {[101:200]});
}

Tool will consider two different constraint so try to resolve both constraints because Same variable is constrained using two different constraint (Names are different so Child class can't override Base class's constraint) has their name is different and both constraints are contradict to each other.

Difference between typedef enum and only enum

module top();

  // create a data-type called on_off_e which is derived from enum type
  typedef enum bit {OFF, ON} on_off_e;
  // create a variable of enum
  enum bit {CLOSE, OPEN} switch_e;

  // create a variable of data-type on_off_e
  on_off_e on_off;

  // If you try to define variable of switch_e then tool will give compilation error because switch_e it self is a variable
  //switch_e switch_val;

  initial
  begin
    $display("on_off=%s, on_off=%b", on_off.name, on_off);
    $display("switch_e=%s, switch_e=%b", switch_e.name, switch_e);
  end

endmodule : top


Output:
on_off=OFF, on_off=0
switch_e=CLOSE, switch_e=0