Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
10 years ago

modelsim compiling error:external function 'xxxxx' may not be used in a constant expr

Consider the following code:

package pkg;
function bit bitgen(int bit1idx);
    automatic bit res = '0;
    if (bit1idx >= 0 && bit1idx < 16)
        res = 1'b1;
    return res;
endfunction
function bit bit2test(bit bits2test);
    if ((bits2test&bitgen(2)) != 0)
        return 1'b1;
    return 1'b0;
endfunction
endpackage
module mod2test# (
    parameter para2test = 16'h000F
);
   import pkg::*;
    localparam bit2set_flag = bit2test(para2test);
    initial begin
        if (bit2set_flag == 0)
            $error("bit2 of para2test is not set!);
    end
endmodule

When compiling these code in modelsim, it reports some error message, one of them is:

External function 'bit2test' may not be used in a constant expression.

My purpose is: by defining a function to test the instantiate parameter of module , to obtain some state of instantiating of module and to make some special processing for it, the defined function should be used in many different module, for the testing work in them is same.

But if the function defined in package can not be used in constant expression, how can I realize my purpose in design?

10 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    This worked for me going back a number of releases. You have a few typos. Make sure what you posed is exactly what you are compiling.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    This worked for me going back a number of releases. You have a few typos. Make sure what you posed is exactly what you are compiling.

    --- Quote End ---

    Hi, Mr.dave_59.

    thanks for replying. I'm sorry that I had not made enough tests. After testing the code I found it worked in module, but not in an interface:

    
    package pkg;
    function bit bitgen(int bit1idx);
        automatic bit res = '0;
        if (bit1idx >= 0 && bit1idx < 16)
            res = 1'b1;
        return res;
    endfunction
    function bit bit2test(bit bits2test);
        if ((bits2test&bitgen(2)) != 0)
            return 1'b1;
        return 1'b0;
    endfunction
    endpackage
    interface iftest# (
        parameter para2test = 15
    );
        import pkg::*;
        localparam bit2set_flag = bit2test(para2test);   // modelsim reports compiling error here!
        initial begin
            if (bit2set_flag == 0)
                $error("bit2 of para2test is not set!");
        end
    end
    module mod2test# (
        parameter para2test = 15
    );
       import pkg::*;
        localparam bit2set_flag = bit2test(para2test);   // the code here passed modelsim's compiling
        initial begin
            if (bit2set_flag == 0)
                $error("bit2 of para2test is not set!");
        end
    endmodule
    

    can I get it work in interface?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    You still have typos. This works for me after replacing end with endinterface.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    You still have typos. This works for me after replacing end with endinterface.

    --- Quote End ---

    Thank you for your patiently replying, At last I found the reason why it didn't work in my design is:

    one of the functions in the package had declared a local variable without "static" or "automatic" prefix word. But the error message is suppressable for modelsim and is not reported with red color. So this key error message is covered by the following less important red color messages and ignored by me.

    Now After add a "automatic" prefix for that local variable, the problem has been solved. Thank you for your patient replying again!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Yes, without the static or automatic keyword, it is difficult to know if the local variable gets initialized once at time 0, or each time the function gets called. I think its best to declare your package as automatic, then all the functions are automatic, and all the local variables inside the functions are automatic. Then, only declare local variables as 'static' when they need to be.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Yes, without the static or automatic keyword, it is difficult to know if the local variable gets initialized once at time 0, or each time the function gets called. I think its best to declare your package as automatic, then all the functions are automatic, and all the local variables inside the functions are automatic. Then, only declare local variables as 'static' when they need to be.

    --- Quote End ---

    Did you mean I should declare the package like the following code?

    
    automatic package pkg;
    // ... dummy codes...
    endpackage
    

    I'm not familly enough for the SystemVerilog syntax, and not sure if it is right. Would you like tell me more details ?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Let's say you have this

    package pkg;
    int gacc;
    function int fout(input int in);
      int acc;
      if (in !=0) begin
          acc += in;
          fout = acc+ gacc;
          gacc = acc;
      end
    endfunction
    endpackage
    // in some code you have
    $display(fout(1)); // prints 1
    $display(fout(0)); // prints 1 - returns last value assigned to fout
    $display(fout(1)); // prints 3

    Those results are because gacc, add, in, and fout are all static variables initialized once at time 0.

    You can make a function automatic, which makes all arguments, return values, and local variables implicitly automatic (initialized upon each entry to the function)

    package pkg;
    int gacc;
    function automatic int fout(input int in);
      int acc; // implicitly automatic
      if (in !=0) begin
          acc += in;
          fout = acc+ gacc;
          gacc = acc;
      end
    endfunction
    endpackage
    // in some code you have
    $display(fout(1)); // prints 1
    $display(fout(0)); // prints 0 // no value assigned to fout
    $display(fout(1)); // prints 2

    When you declare a package or module as automatic, then all named blocks, tasks, and functions declared in that package become implicitly automatic

    package automatic pkg;
    int gacc; // always static - not inside any block
    function int fout(input int in); // implicitly automatic
      int acc; // implicitly automatic
      if (in !=0) begin
          acc += in;
          fout = acc+ gacc;
          gacc = acc;
      end
    endfunction
    endpackage
    // in some code you have
    $display(fout(1)); // prints 1
    $display(fout(0)); // prints 0
    $display(fout(1)); // prints 2
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Wow, it seems that the automatic package is just the feature what I want!. will it damage or impact the type definition in package?

    well... I mean if I define a type in an automatic package, will the type be deferent to non-automatic package?

    
    package automatic pkg1;
        typedef enum {
            t1 = 0,
            t2 = 1
        } type_t;
    endpackage
    package pkg2;
        typedef enum {
            t1 = 0,
            t2 = 1
        } type_t;
    endpackage
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    It has no impact on typedefs. It only affects the lifetimes of variables declared inside named blocks, functions or tasks.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    It has no impact on typedefs. It only affects the lifetimes of variables declared inside named blocks, functions or tasks.

    --- Quote End ---

    OK! Thank you! I've learned so much form your patient replying! Thank you very much!