[vhdl-200x-ft] Bit size rules

From: Hinton, Ryan W @ CSW-SLC <@>
Date: Tue Jul 06 2004 - 11:45:48 PDT

I am very excited to use David Bishop's fixed point packages. I had
actually just started to write my own when I found it was in the standards
process. I have a few proposed changes that I hope will make them more
useful.

Note that several of these proposals differ from conventions in numeric_std.
I realize the huge advantage of consistency with an established convention.
On the other hand, I think this is an excellent opportunity to make some
well-reasoned adjustments to remedy oversights in numeric_std that
numeric_std has to maintain for backward compatibility.

PROPOSAL 1

The first change is to allow negative index ranges. I quite often model my
fixed point data as a real number with absolute value less than 1.0. For
the UFIXED type, this would give me an index range of (-1 downto -x). Many
other values I use have ranges that would exclude a binary point from the
index range. This is a critical feature for me as a user.

PROPOSAL 2

Change the interpretation of ascending ranges to maintain the bit values.
The killer feature of a fixed point type is that it gives an unambiguous
value to each bit. For a descending range, bit 0 has value 2**0, bit -1 has
value 2**-1, etc. The current interpretation of ascending ranges negates
the bounds and swaps the directions. Here is an example

-- descending --
descending range: ufixed(0 downto -3)
descending value: 1.110b = 1.75d

-- old ascending --
ascending range: ufixed(-3 to 0)
descending range: ufixed(3 downto 0)
ascending value: 011.1b = 1.75d
descending value: 0.111b = 0.875d

-- proposed ascending --
ascending range: ufixed(-3 to 0)
descending range: ufixed(0 downto -3)
ascending value: 011.1b = 1.75d
descending value: 1.110b = 1.75d

Note that the proposed ascending range interpretation requires reversing the
bits for the corresponding descending value, which differs from VHDL's
default matching rule (for implicit subtype conversions). This is
different, but I think it is the right solution. Again, the reason for this
change is to maintain bit values.

PROPOSAL 3

Add one or more extra arguments to RESIZE to specify rounding/saturation
method. This control is critical to signal processing hardware design, and
often varies even within a single block. I think David has something in
mind based on IEEE 854.

PROPOSAL 4

Define mixed signed/unsigned logic. Add "+", "*", "-", and "/" operators
for all combinations of UFIXED/SFIXED. This is another fairly common
operation in signal processing hardware that is well-defined. David noted
that bit literals need a type cast anyway, so we shouldn't have the same
problem as mixed arithmetic in numeric_std.

PROPOSAL 5

Change the bit widths of arithmetic results. Here are my proposed bit
sizing rules.

        -- addition (note mixed addition returns signed)
      ufixed(a downto b) + ufixed(c downto d) = ufixed(max(a,c)+1 downto
min(b,d))
      ufixed(a downto b) + sfixed(c downto d) = sfixed(max(a,c)+1 downto
min(b,d))
      sfixed(a downto b) + sfixed(c downto d) = sfixed(max(a,c)+1 downto
min(b,d))

        -- subtraction the same except "ufixed - ufixed = sfixed"
      ufixed(a downto b) - ufixed(c downto d) = sfixed(max(a,c)+1 downto
min(b,d))

        -- multiply returns almost sum of widths
        ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c+1 downto b+d)
        ufixed(a downto b) * sfixed(c downto d) = sfixed(a+c+1 downto b+d)
        sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c downto b+d)

        -- divide returns odd combination of widths
        ufixed(a downto b) / ufixed(c downto d) = ufixed(a-d+1 downto b-c-1)
        ufixed(a downto b) / sfixed(c downto d) = sfixed(a-d+1 downto b-c)
        sfixed(a downto b) / ufixed(c downto d) = sfixed(a-d downto b-c-1)
        sfixed(a downto b) / sfixed(c downto d) = sfixed(a-d downto b-c)

Note that these do not match the bit sizing conventions for numeric_std.
The result sizes above are conservative in that (except for division) they
do not lose any information in the worst case.

Take addition for example. These rules mandate bit growth in sums. In some
cases wrapping may be the desired behavior, so this behavior should be easy
to specify using the RESIZE functions proposed above. In other cases bit
growth may be overly conservative, for example the last sum in "((a+b)+c)+d"
where a, b, c, and d are all the same range. The language can't determine
this automatically. It could if we had unconstrained elements in records,
and could do it efficiently if we had multi-mode (mixed constant/signal)
records. However, these cases are the exception rather than the rule.

These types are intended for signal processing hardware. The numeric_std
result sizes require input resizing for every operation in order to not lose
range or precision. (I looked at some old code and confirmed this: I had at
least one input or output RESIZE on _every line_ of code.) I think these
proposed rules promote good signal processing hardware design instead of
hindering it. Again, I think this reason justifies being inconsistent with
numeric_std.

CONCLUSION

Proposals 1 and 2 are specific to the new fixed point types. Proposals 3
and 4 are enhancements that I have talked with David and others about adding
to numeric_std (though there may be some issues). I would love to see
Proposal 5 implemented in numeric_std also, but it would be impossible to
maintain backward compatibility. Still, I don't think we should mandate
that the new system has to be broken in the same ways the old system was
broken.

Discussion is welcome as always.

---
Ryan Hinton
L-3 Communications / Communication Systems - West
ryan.w.hinton@L-3com.com
Received on Tue Jul 6 11:46:04 2004

This archive was generated by hypermail 2.1.8 : Tue Jul 06 2004 - 11:46:31 PDT