surabhig
surabhig

Reputation: 33

How can I make the same module use different packages depending on its instantiation

I have a System Verilog module that is instantiated multiple times in the design. Each instantiation needs to use a different package. What is the best way to implement this?

  package A;
   parameter logic [15:0] array [0:15] = '{
   16'd1,
   16'd2,
   .
   .
   16'd16 
   }
  endpackage

  package B;
   parameter logic [15:0] array [0:7] = '{
   16'd1,
   16'd2,
   .
   .
   16'd8 
   }
  endpackage

   module test(

   );

    import packageA::*;

This is how I would use it in one instantiation of the module. But in the second instantiation I would like to use packageB.

should i use:

  1. ifdefs?
  2. passing a package name if it is possible? or
  3. just pass it as a parameter to the module? even if it is a 2 dimensional array?

What is the best approach for it?

Upvotes: 0

Views: 1191

Answers (1)

Serge
Serge

Reputation: 12344

System Verilog syntax does not provide any way for passing packages as arguments to anything. It is possible to use macros which would alter module definition. Though it is possible, it is a bad practice and is not usually recommended. I'll give an example at the end.

The only way is to handle it is to parameterize the module and pass a corresponding array at the instantiation time, e.g.

package A;
parameter bit[3:0] data[4] = '{0,1,2,3};
endpackage

package B;
parameter bit[3:0] data[6] = '{5,4,3,2,1,0};
endpackage

module C#(int WDT = 1, bit [3:0] array [WDT] = '{0}) ();
  initial begin
    for (int i = 0; i < WDT; i++) 
      $display("%m: array[%0d] = %0d", i, array[i]);
  end
endmodule

module D();
  C #($size(A::data), A::data) c1();
  C #($size(B::data), B::data) c2();  
endmodule

there are other versions with types, i.e.

package A;
typedef  bit[3:0] Array[4];
parameter Array array = {0,1,2,3};
endpackage

package B;
typedef  bit[3:0] Array[6] ;
parameter Array array = {5,4,3,2,1,0};
endpackage

typedef bit[3:0] DefaultArray[1];
module C#(type  X = DefaultArray, X array = {0}) ();
  initial begin
    for (int i = 0; i < $size(array); i++) 
      $display("%m array[%0d] = %0d", i, array[i]);
  end
endmodule

module D();
  D #(A::Array, A::array)d1();
  D #(B::Array, B::array)d2();
endmodule

for macros you can either define the whole module in a macro. I think it is ugly

`define PMOD(NAME,PKG) module NAME (); ... import PKG""* ...
 ...
`PMOD(C1, A)
`PMOD(C2, B)

 ...
 C1 c1();
 C2 c2();

One can also use ifdefs withinclude. I would not recommend any of the macro-based or in particular, include-based approaches. They create readability, maintainability, code analysis, and debugging issues.

Upvotes: 1

Related Questions