0

I was thinking about the range a result signal should have to acommodate an unsigned fixed point division. Suppose we have:

SIGNAL a : UFIXED (3 DOWNTO -3);

SIGNAL b : UFIXED (4 DOWNTO -2);

am I wrong assuming:

SIGNAL y <= a/b should have

y'RANGE = (a'LEFT - b'RIGHT DOWNTO a'RIGHT - b'LEFT +1)

to acommodate any resulting y from this division?

cr4150n
  • 9
  • 5
  • 2
    According to the [source the for fixed_generic_pkg body](http://standards.ieee.org/downloads/1076/1076-2008/) the return value will have a range calculated by `-- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1)`,`"/" [UNRESOLVED_ufixed, UNRESOLVED_ufixed return UNRESOLVED_ufixed]` calls an internal function `divide` where the comment is found. That'd be 3 - -2 downto -3 - 4 - 1 or `y(5 downto -8)`. `divide` converts the l and r arguments to unsigned and uses numeric_std "/"[unsigned, unsigned return unsigned] converting the return value to the result range. –  Nov 10 '17 at 17:47
  • Oh, I realized I typoed my question, it is supposed to be -1 on the right side (DOWNTO a'RIGHT - b'LEFT -1), of course. The question arised after spotting an inconsistency in the V.Pedroni's book on Circuit Design and Simulation with VHDL 2nd ed. Page 57. "a/b unsigned: Range is a'LEFT - b'RIGHT DOWNTO a'RIGHT + b'LEFT - 1." – cr4150n Nov 11 '17 at 18:17

1 Answers1

2

There's a divide function declared in IEEE package that demonstrates the correct arithmetic for finding the bounds of the divide operator:

-- ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d downto b-c-1)

And because the rules for bounds can be complex there are functions (ufixed_high, ufixed_low) where you pass the operation:

library ieee;
use ieee.std_logic_1164.all;
use ieee.fixed_pkg.all;

entity ufixed_div_range is
end entity;

architecture fum of ufixed_div_range is
    signal a : ufixed (3 downto -3); 
    signal b : ufixed (4 downto -2);
begin

    a <= to_ufixed(1.75, a'LEFT, a'RIGHT);
    b <= to_ufixed(2.5,  b'LEFT, b'RIGHT);

    process          
        variable result: ufixed 
         (ufixed_high(a, '/', b) downto ufixed_low(a, '/', b));
    begin
        wait for 1 ns;
        result := a/b;
        report LF & HT & "to_real(result) = " & real'image(to_real(result))
              & LF & HT & "result'LEFT = " & integer'image(result'left)
              & LF & HT &"result'RIGHT = " & integer'image(result'right);
        wait;
    end process;
end architecture;

And when run this gives:

ufixed_div_range.vhdl:35:9:@1ns:(report note):
        to_real(result) = 6.9921875e-1
        result'LEFT = 5
        result'RIGHT = -8

Noting that the real value is dependent on both the result accuracy (number of fraction bits) and rounding modes. (And reals are approximate anyway).

This was demonstrated using VHDL-2008.