Why do we need parameterization for classes ?

At times it would be much easier to write a generic class which can be instantiated in multiple ways to achieve different array sizes or data types. This avoids the need to re-write code for specific features like size or type and instead allow a single specification to be used for different objects. This is achieved by extending the SystemVerilog parameter mechanism to classes.

Parameters are like constants that are local to the specified class. Classes are allowed to have default value for each parameter that can be overridden during class instantiation.

Syntax


	// Declare parameterized class
	class <name_of_class> #(<parameters>);
	class Trans #(addr = 32);
	
	// Override class parameter
	<name_of_class>  #(<parameters>) <name_of_inst>;
	Trans #(.addr(16)) obj;

Examples

Parameterized Classes

Given below is a parameterized class which has size as the parameter that can be changed during instantiation.


// A class is parameterized by #() 
// Here, we define a parameter called "size" and gives it 
// a default value of 8. The "size" parameter is used to
// define the size of the "out" variable
class something #(int size = 8);
	bit [size-1:0] out;
endclass

module tb;
  
  // Override default value of 8 with the given values in #()
  something  #(16) sth1;                 // pass 16 as "size" to this class object
  something  #(.size (8)) sth2;          // pass 8 as "size" to this class object
  typedef something #(4) td_nibble;      // create an alias for a class with "size" = 4 as "nibble"
  td_nibble nibble;
  
  initial begin
    // 1. Instantiate class objects
    sth1 = new;
    sth2 = new;
  	nibble = new;  
    
    // 2. Print size of "out" variable. $bits() system task will return
    // the number of bits in a given variable
    $display ("sth1.out   = %0d bits", $bits(sth1.out));
    $display ("sth2.out   = %0d bits", $bits(sth2.out));
    $display ("nibble.out = %0d bits", $bits(nibble.out));
  end
endmodule
 Simulation Log
ncsim> run
sth1.out   = 16 bits
sth2.out   = 8 bits
nibble.out = 4 bits
ncsim: *W,RNQUIE: Simulation is complete.

Pass datatype as a parameter

Data-type is parameterized in this case and can be overridden during instantiation. In the previous case, we defined parameters to have a specific value.


// "T" is a parameter that is set to have a default value of "int"
// Hence "items" will be "int" by default 
class stack #(type T = int);
  T item;             
	
  function T add_a (T a); 	
    return item + a;
  endfunction
endclass

module tb;
	stack 			 	st; 	// st.item is by default of int type
	stack #(bit[3:0]) 	bs; 	// bs.item will become a 4-bit vector
	stack #(real) 		rs; 	// rs.item will become a real number
  
  	initial begin
      st = new;
      bs = new;
      rs = new;
      
      // Assign different values, and add 10 to these values
      // Then print the result - Note the different values printed
      // that are affected by change in data type
      st.item = -456;
      $display ("st.item = %0d", st.add_a (10));
      
      bs.item = 8'hA1;
      $display ("bs.item = %0d", bs.add_a (10));
      
      rs.item = 3.14;
      $display ("rs.item = %0.2f", rs.add_a (10));
    end
endmodule

Note that any type can be supplied as a parameter, including user-defined type such as class or struct.

 Simulation Log
ncsim> run
st.item = -446
bs.item = 11
rs.item = 13.14
ncsim: *W,RNQUIE: Simulation is complete.