Intel® Quartus® Prime Software
Intel® Quartus® Prime Design Software, Design Entry, Synthesis, Simulation, Verification, Timing Analysis, System Design (Platform Designer, formerly Qsys)
17049 Discussions

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

Altera_Forum
Honored Contributor II
6,415 Views

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?
0 Kudos
10 Replies
Altera_Forum
Honored Contributor II
4,477 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

 

--- 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?
0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

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

0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

 

--- 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!
0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

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.

0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

 

--- 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 ?
0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

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

0 Kudos
Altera_Forum
Honored Contributor II
4,477 Views

 

--- 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!
0 Kudos
Reply