ID: N-008
Proposed by: David Bishop 03/05/2003
Analyzed by:
Resolved:
Summary:
Add packages for fixed point arithmetic
Detail:
Please tell me (David) what you think. Note that this discussion will parallel one on the Verilog 200x side.
Resolution: A new type needs to be created. Changing the type of "signed" and "unsigned" would cause funcitonal changes in how these types work and cause existing code problems.
Resolution: These will be called "sfixed" (signed fixed point) and "ufixed" (unsigned fixed point). Their behavior will be similar to that of the signed and unsigned arithmetic in numeric_std.
Normally the fixed point representation will be "ufixed (7 downto -8)" however may people expressed the need for "ufixed (-8 to 7)" to be supported and to be treated as having the same direction as the downto example.
Resolution: Will be supported
Resolution: Can't be done because arrays in records must have fixed lenghts.
fixed + fixed := fixed (max(l'high,r'high) downto -(max(-l'low,-r'low))) 8:-3 + 9:-2 := 9:-3 numeric_std rule: + and - = size of largest input strung fixed - fixed := fixed (max(l'high,r'high) downto -(max(-l'low,-r'low))) 8:-3 + 9:-2 := 9:-3 fixed * fixed := fixed (l'high+r'high downto l'low+r'low) 8:-3 * 9:-2 := 17:-5 numeric_std rule: * = add the sizes together to create result fixed / fixed := fixed (l'high downto l'low+r'low) 8:-3 / 9:-2 := 8:-5 numeric_std rule: / = size of left operand.
Resolution: [To be determined by the Working Group]
The fixed point packages introduce two new types:
type ufixed is array (integer range <>) of std_logic; type sfixed is array (integer range <>) of std_logic;
Where "ufixed" is an unsigned fixed point number and "sfixed" is a signed fixed point number. These numbers can have a negative index. A decimal point is assumed between the "0" and "-1" element in the string.
Usage model: use work.fixed_pkg.all; .... signal a, b : sfixed (7 downto -5); signal mulout : sfixed (14 downto -10); begin .... a <= to_sfixed (-5.4, a'high, a'low); mulout <= a * b;
Detail: Our argument is this:
variable a8r : ufixed (-1 to 7) := "010011100";How is the string interpreted? Are the lower bits "10" or "00"? Analysis: Is the result interpreted as 57.0 or 78.0? Bit wise, if we reverse the range to be 7 downto -1 the result would be 57. However, if we follow the rules from "numeric_std" the answer would be 78. Pros and Cons:
In numeric_std (1076.3) we always interperate the left most bit to be the MSB. If we follow that convention in the fixed point packages then the answer is 78.0. Any other interpretation would be a break from this convention.
Looking at the number and the interpretation of it (expressed as "to" rather than "downto") an interpretation of 57.0 would seem natural.
This would also complicate the interpretation of FT09.
Recommendation: Stick with the numeric_std interpretation (answer is 78.0).
Resolution
variable a8r : ufixed (-1 to 7) := "010011100";
1.34375 = 01.0011100
Under this,
1) MSB is on the left
2) Whole number is on the left
3) Fraction is on the right
4) Decimal point is to the right of the 0 index.
Pro: Preserves the sense of numeric_std
Pro: Consistency in that decimal point is
to the right of the "0" index.
Currently we have
ufixed(a downto b) + ufixed(c downto d) = ufixed(max(a,c) downto min(b,d))
Which actually tosses the overflow bit.
Proposed is the following:
ufixed(a downto b) + ufixed(c downto d) = ufixed(max(a,c)+1 downto min(b,d))
Alternatives:
Recommendation:
Add the "|+" and "|-" operaters to extend the bit width, leave
the current "+" and "-" alone (c).
Resolution:
Expand the number
ufixed(a downto b) + ufixed(c downto d) = ufixed(max(a,c)+1 downto
min(b,d))
use the resize funciton to make the a <= a+b case work
For a multiply in numeric_std:
signed (a downto 0) * signed (c downto 0) = signed (a+c+1 downto 0)
unsigned (a downto 0) * unsigned (c downto 0) = unsigned (a+c+1 downto 0)
Currently in the fixed point packages
ufixed(a downto b) * ufixed(c downto d) = ufixed(a+c downto b+d)
sfixed(a downto b) * sfixed(c downto d) = sfixed(a+c downto b+d)
Proposed is:
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)
For division in numeric_std:
signed (a downto 0) / signed (c downto 0) := signed (a downto 0);
unsigned (a downto 0) / unsigned (c downto 0) := unsigned (a downto 0);
Currently in the fixed point package
ufixed (a downto b) / ufixed (c downto d) := ufixed (max(a,c) downto min(b,d))
sfixed (a downto b) / sfixed (c downto d) := sfixed (max(a,c) downto min(b,d))
Proposed:
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 from several post (and the problem I am currently having with
the packages) they appear to be problematic.
Alternatives:
Recommendation: Accept the proposal
Resolution: Accept the proposal
The proposal is to add the following functions:
b) sfixed := ufixed - ufixed;
c) sfixed := sfixed + ufixed; (- * /)
d) sfixed := ufixed + signed; (- * /) (once a signed number is involved
the result would be "sfixed")
Pros:
People need to do this anyway
Pro:
You already MUST cast any bit literals
Con:
more functions to maintain and test
Con:
Doesn't have the same restrictions as "numeric_std".
Work around:
sfixed := sfixed + to_sfixed (ufixed);
Recommendation:
Accept the proposal.
Resolution: Only overload for "real" force all others to convert.