Domanda

@FRob's answer to my recent question (to_float() and dividing errors) led me to analyze the float_pkg_c.vhdl, particularly the to_float method.

When trying the following operation:

variable denum : integer; 
variable num : integer; 
variable dividend : float (4 downto -27);  

begin
dividend := to_float(num, 4, 27) / to_float(denum, 4, 27); 
...  

I keep getting this error: "Error (10454): VHDL syntax error at float_pkg_c.vhdl(3840): right bound of range must be a constant"

Now, at the mentioned line:

for I in fract'high downto maximum (fract'high - shift + 1, 0) loop

The variable fract is calculated based on the parameter fraction_width, which is 27 in my case, therefore a constant. However, the shift variable is calculated based on the arg parameter (basically, a log2 of the absolute value of arg), which is the num variable in my case, therefore not a constant.

So, the error is clear, but my question is: How can I cast a integer variable to float?

This is the definition of to_float:

function to_float (
    arg                     : INTEGER;
    constant exponent_width : NATURAL    := float_exponent_width;  -- length of FP output exponent
    constant fraction_width : NATURAL    := float_fraction_width;  -- length of FP output fraction
    constant round_style    : round_type := float_round_style)  -- rounding option

What is even more confusing to me is that arg in the above definition is not required ti be a constant.

È stato utile?

Soluzione

After spending a few hours reading up on synthesizing loops and trying to translate the to_float with integer arg I had a thought:

library ieee;
library ieee_proposed;
use ieee_proposed.float_pkg.all;
use ieee.numeric_std.all;

entity SM is
end entity;

architecture foo of SM is

-- From float_pkg_c.vhdl line 391/3927 (package float_pkg):

    -- -- to_float (signed)
    -- function to_float (
    --   arg                     : SIGNED;
    --   constant exponent_width : NATURAL    := float_exponent_width;  -- length of FP output exponent
    --   constant fraction_width : NATURAL    := float_fraction_width;  -- length of FP output fraction
    --   constant round_style    : round_type := float_round_style)  -- rounding option
    --   return UNRESOLVED_float is

begin
UNLABELLED:
    process
    variable denum : integer; 
    variable num : integer; 
    variable dividend : float (4 downto -27); 
    begin
        denum := 42;
        num := 21;
        dividend := to_float(TO_SIGNED(num,32), 4, 27) / to_float(TO_SIGNED(denum,32), 4, 27);
        assert dividend /= 0.5
        report "dividend = " & to_string(dividend)
        severity NOTE;
        wait;
    end process;

end architecture;

I don't think you really want to synthesize the integer version of to_float. Unfolding the loop gives you a bunch of ripple adds for decrementing shiftr and adjusting arg_int. Trying to get rid of those operations leads you to a bit array style representation of an integer.

Note there is no loop in the to_float who's arg type is signed. It's likely the TO_SIGNED calls are simply seen as defining the number of bits representing the size of integers instead of implying additional hardware. You end up with something converting bit fields and normalizing, clamping to infinity, etc..

Altri suggerimenti

You cast to float using the to_float function overload you are already using.

Your variables num and denum are uninitialized and default to integer'left which is -2**31. The to_float function tries to convert negative numbers to positive to stay within the natural range of arg_int but integer'high is limited to 2**31-1 and can't represent -integer'low. Set them to an initial value other than the default and see what happens.

From float_pkg_c.vhdl:

if arg < 0 then
  result (exponent_width) := '1';
  arg_int := -arg; -- Make it positive.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top