Search code examples
vhdlfpgafixed-pointghdl

VHDL Fixed_pkg Getting bound check failure when adding 2 ufixed values


I am attempting to used the ufixed datatype and add 2 ufixed values together, I have calculated I should have enough bits to store the result and the output should be able to be stored in the signal, but when I attempt to perform it I get a bound check failure. Can someone tell me why I am getting this?

The important parts of the code are:

-- definition of parameters used in the failing calculation

input : in ufixed(0 downto -15); -- Q1.15

constant VectorLength : integer := 3;
type vector_ufixed is array(0 to VectorLength-1) of ufixed(1 downto -14);

constant InnerProductArray : vector_ufixed := (to_ufixed(1.2,1,-14), to_ufixed(1.0,1,-14), to_ufixed(0.2,1,-14));

signal InnerProductResult : ufixed(4 downto -29); -- Q5.29

signal counter : integer := 0;


write(l, real'image(to_real(InnerProductResult)));
write(l, string'(", "));
write(l, real'image(to_real(InnerProductResult + input*InnerProductArray(counter))));
writeline(output, l);
InnerProductResult <= InnerProductResult +                                                                            
                      input*InnerProductArray(counter);

When I simulate this with ghdl I get the following result:

0.0, 6.00006103515625e-1
ghdl:error: bound check failure at InnerProduct.vhd:55
  from: process work.innerproduct(innerproductarchitecture).P0 at InnerProduct.vhd:55
ghdl:error: simulation failed

line 55 in this case is the line InnerProductResult <= InnerProductResult + input*InnerProductArray(counter);

input takes the value 0.5, as can be observed from the resulting value of 6.00006103515625e-1 when input is multiplied by 1.2.

The value 6.00006103515625e^-1*2^29 is 322125824 as well which is an integer less than 2^34 so it should fit fine, I don't understand why this might be?


Solution

  • When performing a arithmetic operations such as this, addition and multiplication in this case, it is necessary to resize the result of the operation to fit into the location it is being stored. In this case we add a 34 bit number to 2 16 bit numbers and so we need to resize the result to be 34 bits wide in order to fit precisely into the storage location i.e. InnerProductResult.

    The syntax for resize in fixed_pkg appears to differ from that used in numeric_std for signed and unsigned numbers. The following syntax is nessesary to use for operations done with fixed_pkg, this was found in http://www.klabs.org/mapld05/presento/189_lewis_p.pdf:

    InnerProductResult <= resize(                                                                                         
        arg => InnerProductResult + input*InnerProductArray(counter),                                                       
        size_res => InnerProductResult                                                                                      
        );