0

@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.

Community
  • 1
  • 1
user3209815
  • 357
  • 1
  • 11
  • 25

2 Answers2

1

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.
Kevin Thibedeau
  • 3,299
  • 15
  • 26
  • still the same error... When I take the `shift` variable out of the above mentioned loop, everything compiles fine. Of course, this is not a solution, because of the obvious functionality impact – user3209815 Apr 12 '14 at 10:23
  • You aren't clear on what you're doing but it seems like you're trying evaluate our code with the Quartus synthesizer. You should first get things working in a simulator (Modelsim) and then move to the synthesizer. Modelsim was happy to run the code snippet for me so the problem may be a bug in Quartus. – Kevin Thibedeau Apr 12 '14 at 16:26
  • Yes, I am working in Quartus. I was under the assumption that I would first need to synthesize the code and then simulate it. The idea was to avoid the situation in which I would get code that can be simulated but not synthesized. Another thing, although I don't intend to actually forge a chip, I still need the floor plan and the analysis output that Quartus provides. That being said, it is apparent that I would at some point come back to Quartus and encounter this problem, regardless of the order in which I utilize the tools. That is my thought process I'd be happy to hear your suggestions. – user3209815 Apr 12 '14 at 17:50
  • 1
    Synthesizers use a limited subset of the language and don't provide the most helpful debugging info. The usual design flow is simulate, then synthesize, and then optionally simulate a back-annotated, synthesized netlist for verification. Following this flow will minimize your problems with the synthesizer by feeding it known good code. Then any errors will be limited to unsupported language constructs or tool bugs. – Kevin Thibedeau Apr 12 '14 at 18:42
1

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..

  • Yep, that seems to do it. Thanks a lot for your time. I really appreciate the effort you put in it (including the previous answers) – user3209815 Apr 14 '14 at 22:00
  • The important thing is you're moving forward. I'd been sitting on this all weekend, your question was creeping down the list, should have posted sooner. As far as the effort it was more a puzzle to be solved, it was educational. The solution became apparent when trying to fix the loop. Makes you wonder how much more is buried in those packages. You'd think the integer to_float could have converted to signed and called the signed version of to_float instead of torturing the language to produce what it has. –  Apr 14 '14 at 22:33
  • I found the same issue when converting float to_integer, the solution was the same. Seems like the integer type is problematic somewhat, after reading up a bit, I found no differences compared to the signed type, so that is a relatively easy workaround, at least in my current case. I'm surprised, though, that there are such big issues in such "old" packages. – user3209815 Apr 15 '14 at 09:21
  • You can't rewrite interface specifications on functions in a package declaration but can rewrite the actual implementation, based on copyright in latest [IEEE-SA Supplemental Material](http://standards.ieee.org/downloads/1076/1076-2008/). Someone suspicious might think is there is room for competitive advantage here having versions based on calls to the signed versions and converting to and from integers, that happen to be readily synthesis eligible. Then again it's an easy work around. Does beg the question of whether the current float_pkg, etc. are ready. –  Apr 15 '14 at 11:01