0

I have a systemverilog module that references a generated header file that contains various typedefs and functions. This is synthesizable code. The module was working fine previously because the header file was included using the pre-processor.

Now my architecture has changed such that I need to instance multiple cases of this module and specify different header files for each instance. I don't believe the pre-processor approach will work anymore because of the global nature of pre-processor defined variables. I can't include one header file for one instance of a module and `include another header file for another instance. Correct?

So I am trying to use packages. What I want to do is something like the following:

package pack1;
  parameter from_pack = 1;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
  } test_t;
  function automatic void hello();
    $display("in pack1");
  endfunction
endpackage

package pack2;
  parameter from_pack = 2;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
    logic [18:0] test3;
  } test_t;
  function automatic void hello();
    $display("in pack2");
  endfunction
endpackage

module top();
  parameter PACKAGE_INST = 1;

  generate
    case (PACKAGE_INST)
      1: begin
//        import pack1::hello;
        import pack1::*;
      end
      default: begin
//        import pack2::hello;
        import pack2::*;        
      end
    endcase

      // Error! Compiler doesn't know anything about the test_t type
      test_t test_struct;
//    pack1::test_t test_struct;

    initial begin
      $display("P1 = %d", P1);

      // Error at elaboration! Simulator cannot find the 'hello()' function
      hello();
//    pack1::hello();
    end
  endgenerate
endmodule

Note the two problems with this code, both relating to my inability to specify which namespace to use with a parameter. I suspect my problem here is that a parameter change does not necessarily require a recompile, and the changes I am trying to affect definitely require a recompile. Which is fine for my application; I don't need to be able to make these changes without recompiling my code.

The closest discussion that I could find about this issue on SO, at least is here:

Handling parameterization in SystemVerilog packages

But the best answer there is using pre-processor wizardry that I don't think will work in my case. I would really appreciate any kind of insight into this problem. Thanks.

Community
  • 1
  • 1
sean
  • 61
  • 7

1 Answers1

3

The problem with what you are trying to do is the import statement is local to the begin/end scope it appears in. You would need to declare the test_struct variable in each branch, and unfortunately the only way to deal with the function is to write a wrapper.

package pack1;
  parameter from_pack = 1;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
  } test_t;
  function automatic void hello();
    $display("in pack1");
  endfunction
endpackage

package pack2;
  parameter from_pack = 2;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
    logic [18:0] test3;
  } test_t;
  function automatic void hello();
    $display("in pack2");
  endfunction
endpackage

module top();
  parameter PACKAGE_INST = 1;

   case (PACKAGE_INST)
     1: begin : genscope
    pack1::test_t test_struct;
    function void hello;
       pack1::hello();
    endfunction
     end
     default: begin :genscope
    pack2::test_t test_struct;
    function void hello;
       pack2::hello();
    endfunction
     end
   endcase

   initial begin
      $display("PACKAGE_INST = %d", PACKAGE_INST);
      $display("%p",genscope.test_struct); 
      genscope.hello();
   end

endmodule

Another completely different approach is to use an interface instead of a package. By connecting your module to different interface instances, you can select the types and function that connect to the module.

interface intf1;
  parameter from_intf = 1;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
  } test_t;
  function automatic void hello();
    $display("in intf1");
  endfunction
endinterface

interface intf2;
  parameter from_intf = 2;
  typedef struct packed
  {
    logic [7:0]  test1;
    logic        test2;
    logic [18:0] test3;
  } test_t;
  function automatic void hello();
    $display("in intf2");
  endfunction
endinterface

module DUT(interface itf);

   typedef itf.test_t test_t; // LRM requires this so typename does not
                              // appear as a hierarchical reference
   test_t test_struct;

   initial begin
      $display("%m from_intf = %d", itf.from_intf);
      $display("%p",test_struct); 
      itf.hello();
   end

endmodule

module top2;


   intf1 i1();
   intf2 i2();

   DUT d1(i1);
   DUT d2(i2);

endmodule
dave_59
  • 39,096
  • 3
  • 24
  • 63
  • The OP wants the code to be synthesizable and last I checked, most synthesis tool do not support interfaces. Is this changing? (As interfaces are generally pretty awesome with modports and such) – Unn Oct 24 '15 at 12:29
  • Interfaces are supported for synthesis, at least to some degree. I will try this out. It might be just what I needed. I had forgotten that I can pass different types of interfaces into a module that way using the 'interface' keyword. Thanks! – sean Oct 24 '15 at 15:04
  • Hmmm, now that I look at it again, I guess it was mostly that modports werent supported and they are what make interfaces really strong at least for me. – Unn Oct 24 '15 at 15:17
  • Interfaces are certainly synthesizable and supported by one of the largest synthesis vendors. The first example I wrote should also be synthesizable as most synthesis tools allow hierarchical references into generate blocks as long as you name the block. – dave_59 Oct 24 '15 at 17:11
  • Unfortunately, the interface solution is not synthesizable in Altera Quartus 15.1. Here is the error message: Error (10742): Verilog HDL error at ...: constant expression cannot contain a hierarchical identifier – sean Nov 05 '15 at 15:46
  • What constant expression is it reffering to?Have you tried the generate with a named block solution? – dave_59 Nov 05 '15 at 16:13