SystemVerilog loops in functions are completely broken
- 11 months ago
Working version
After trying multiple different ways, I found a working version:
function automatic int smaller_pow_3(input int x);
smaller_pow_3 = 1;
while(smaller_pow_3 * 3 < x) smaller_pow_3 *= 3;
endfunctionThis has:
- while instead of for
- no local variables
- no return statement (return value assigned to function name)
Not working versions
Other technically correct, but not working versions (based on the working one):
1. local variable + (optional) return
function automatic int smaller_pow_3(input int x);
int p = 1;
while (p * 3 < x) p *= 3;
return p;
// or
// smaller_pow_3 = p;
endfunctionUsing a separate local variable makes Quartus think that the loop does not terminate. It does not matter whether a return statement or assignment to function name is used - just using a variable breaks synthesis.
2. Equivalent for loop
function automatic int smaller_pow_3(input int x);
for (smaller_pow_3 = 1; smaller_pow_3 * 3 < x; smaller_pow_3 *= 3)
;
endfunctionAccording to Verilog-2001 standard (IEEE 1364-2001, section 9.6) this should behave exactly like the working version with while loop, but in Quartus it warns that the function may return Don't Care (10241) and exits with an error, because the returned value is not a constant expression (10192).
Conclusions
I'm not sure why the not working versions don't, work, but if someone else has this problem (in SystemVerilog or Verilog) try the following.
In Quartus Prime Standard/Lite:
- don't use for loops - try an equivalent while
- don't use local variables in functions
- if you need a variable to return, use assignment to function name (even as temporary variable)