2
votes

i tried to compile my design that uses fphdl libraries http://www.eda.org/fphdl/ for floating point operations. While in modelsim simulation is fine when synthesizing in Quartus hdl compiler complains about the statement:

result := to_integer (fract (frac'high downto frac'high-base))

with reason: 'expression is not constant' from looking around similar posts i understand that this compiler does not like that frac'high-base is not constrained. I tried to constrained all relate signals as follows:

variable frac    : UNSIGNED (23 downto 0);  
variable base    : INTEGER range 0 to 23;

but still the error keeps on... is there any workaround for that in hdl level or in Quartus itself?

2

2 Answers

2
votes

Note that the error message says:

expression is not constant

and not:

... constrained

So the reason for the error message is that the to_integer function can't be synthesized when the range from fract is variable at run-time, and not fixed at elaboration time.

A work-around for Quartus can be:

variable part : UNSIGNED(23 downto 0);
...
part := (others => '0');
part(base downto 0) := frac(frac'high downto frac'high - base);
result := to_integer(part);

The extracted part from frac is then zero-extneded, and the vector length given to to_integer is then fixed, thus allowing Quartus synthesis.

1
votes

The code fragment in the question doesn't appear to have anything to do with the fphdl packages directly. It doesn't depend on any types declared in any of them.

The expression gives an integer result from frac with frac'HIGH - base 'bits' of accuracy.

An equivalent of the original expression could be:

    variable dist:  integer range 0 to 23;

    dist := frac'HIGH - base;
    result := to_integer (SHIFT_RIGHT(frac, dist));

SHIFT_RIGHT comes from the IEEE library package numeric_std, used because frac is an unsigned.

The canny observer might note this is the equivalent of an integer divide by power of two which tends to be supported by synthesis generally, providing more or less identical hardware.

And about here you might get the idea your statement is a multiplexer with shifted inputs that are zero filled, the whole thing subject to optimization.

Historically IEEE Std 1076.6-2004 (withdrawn) 8.6.5 Slice names provided -

For a discrete range that appears as part of a slice name, the bounds of the discrete range shall be specified directly or indirectly as static values belonging to an integer type.

Morten tell us Quartus Prime can deal with

    part := (others => '0');
    part(base downto 0) := frac(frac'high downto frac'high - base);
    result := to_integer(part);

where base isn't static (although you'd think it should be constrained).

For those synthesis tools that can't deal with non static discrete range the same thing can be done in a for loop depending on the loop parameter which is a constant in an unrolled loop:

    part := (others => '0');
    for i in part'range loop
        if i = b then
            part(i downto 0) := frac(frac'high downto frac'high - i);
        end if;
    end loop;
    result := to_integer(part);

The IEEE Std 1076=2008 10.10 Loop statement tells us:

For a loop statement with a for iteration scheme, the loop parameter specification is the declaration of the loop parameter with the given identifier. The loop parameter is an object whose type is the base type of the discrete range. Within the sequence of statements, the loop parameter is a constant.

The for loop gives the same result and should produce the same hardware.