0

I want to have universal function to initialize same module with different parameters. One of them is packed array with size depends on another parameter.

I've tried something like this:

package my_pkg;

    class helper #(
        parameter p_WIDTH = 16,
        parameter p_COUNT = 2
    );

    typedef logic [p_COUNT - 1 : 0] [p_WIDTH - 1 : 0] ret_t;

    static function ret_t GetRand(int value);
        automatic ret_t result;

        for (int i = 0; i < p_COUNT; ++i) begin
            result[i] = value * i;
        end
    endfunction

    endclass : helper

endpackage : my_pkg

module myModule #(
    parameter                                     p_WIDTH = 16,
    parameter                                     p_COUNT = 2,
    parameter [p_COUNT - 1 : 0] [p_WIDTH - 1 : 0] p_INIT  = '{default: 0}
);

    // other module i can't edit
    otherModule #(
        ......
        .p_INIT(p_INIT),
        ......
    ) (
      .....
    )

endmodule : myModule

module test_class
    import my_pkg::*;
#();

    localparam p_WIDTH = 16;
    localparam p_COUNT = 2;
    localparam p_STEP  = 6;

    typedef helper#(.p_WIDTH(p_WIDTH), .p_COUNT(p_COUNT)) helper_t;

    myModule #(
        .p_WIDTH(p_WIDTH                  ),
        .p_COUNT(p_COUNT                  ),
        .p_INIT (helper_t::GetRand(p_STEP))
    ) i_myModule (
        .....
    );

endmodule : test_class 

Vivado synthesis tool builds it without any errors, but Questa Sim doesn't allow to simulate this code. I'm getting following errors:

\*\* Error: External function '\<class-spec#1\>::GetRand' may not be used in a constant expression.

May be some one could advice some workaround for this trouble?

Same code with class without any parameters simulates with no problems. But function stops be universal...

toolic
  • 57,801
  • 17
  • 75
  • 117
Don Rumata
  • 11
  • 2

1 Answers1

0

Unfortunately, in system verilog you can only use locally (or globally) defined functions in constant expressions like that. Because it depends on module parameters, it should be defined locally within the module as in the following example:

module myModule #(
          parameter                                     p_WIDTH = 16,
          parameter                                     p_COUNT = 2,
          parameter [p_COUNT - 1 : 0] [p_WIDTH - 1 : 0] p_INIT  = '{default: 0}
          )();


endmodule : myModule


module test_class#();

   localparam p_WIDTH = 16;
   localparam p_COUNT = 2;
   localparam p_STEP  = 6;

   typedef logic [p_COUNT - 1 : 0] [p_WIDTH - 1 : 0] ret_t;
   function automatic ret_t GetRand(int value);
      automatic ret_t result;

      for (int i = 0; i < p_COUNT; ++i) begin
         result[i] = value * i;
      end
   endfunction

   myModule #(
              .p_WIDTH(p_WIDTH                  ),
              .p_COUNT(p_COUNT                  ),
              .p_INIT (GetRand(p_STEP))
          ) i_myModule ();

endmodule : test_class

There are a couple of ways to make this function reusable.

  1. define it as a macro:

`define GetRand(p_COUNT, p_WIDTH) \
  typedef logic [p_COUNT - 1 : 0] [p_WIDTH - 1 : 0] ret_t;\
  function automatic ret_t GetRand(int value);\
      automatic ret_t result;\
    for (int i = 0; i < p_COUNT; ++i) begin\
      result[i] = value * i;\
      end\
   endfunction

module test_class#();
  ...
  `GetRand(p_COUNT, p_WIDTH) // define it within the module by instantiating the macro
   myModule #(
              ...
              .p_INIT (GetRand(p_STEP))
          ) i_myModule ();

  1. you can define the function in a separate file and use `include to bring it into a module. However, I do not recommend using of this method.
Serge
  • 11,616
  • 3
  • 18
  • 28
  • Thank you! May be i am wrong, but i was sure that following System Verilog stantard it's not allowed to initialize constants with hierarchical calling. So in above example it would be non-static method helper.GetRand() About macros. I came up with the same idea and used it for old software. New versions of the Output of the given example are synthesized without problems. But simulation errors ruins my approach – Don Rumata May 26 '23 at 08:29
  • simulation errors is a different story and is not related to the way how the function is used in your example. – Serge May 26 '23 at 15:56
  • what do you mean, could you explain? @Serge – Don Rumata May 29 '23 at 09:37
  • I mean, that you had a question about syntax, not about simulation results. For simulation errors you need a new question with a reproducer and bad/expected results. – Serge May 30 '23 at 00:08