Forum Discussion

k_dz's avatar
k_dz
Icon for New Contributor rankNew Contributor
11 months ago
Solved

SystemVerilog loops in functions are completely broken

While writing a ternary adder tree (code below and in attached project archive), I wrote a constant function (IEEE 1800-2023 section 13.4.3) that uses a loop to calculate parameter values for lower l...
  • k_dz's avatar
    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;
    endfunction

    This 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;
    endfunction

    Using 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)
    ;
    endfunction

    According 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)