[myhdl-list] fixed-point thoughts : part two
Brought to you by:
jandecaluwe
From: Christopher F. <chr...@gm...> - 2013-09-05 03:28:39
|
In part one I discussed fixed-point representation and introduced /fixbv/ construction. Representation is only part of the fixed-point functionality. In this conversation fixed-point operations and the proposed *resize* function will be discussed. First, lets review fixed-point mathematics, given two fixed-point variables, /x/ and /y/: x = fixbv(0, min=-8, max=8, res=1/16) # siii.ffff y = fixbv(0, min=-1, max=1, rest=1/128) # s.fffffff Addition and subtraction require the operands to be aligned, they don't necessarily need to be the same word-length (wl) but the "point" needs to be aligned, using the above as operands: siii.ffff000 + ssss.fffffff -------------- siiii.fffffff once the operands are aligned normal 2's complement addition/ subtraction can be performed. The maximum result would be 2*max(x.max,y.max) (or max(len(x),len(y))+1). If addition or subtraction is attempted and the values are not aligned an error will be thrown, example: >>> x = fixbv(0,min=-8,max=8,res=1/16.) >>> y = fixbv(0,min=-1,max=1,res=1/128.) >>> x + y AssertionError: Add: points not aligned fixbv(0.00, format=(8,3,4), ) and fixbv(0.00, format=(8,0,7), ) It is assumed the /fixbv/ operations will actually return an /int/ same as /intbv/ operations >>> x1 = fixbv(2.5,min=-8,max=8,res=1/16.) >>> x2 = fixbv(1.25,min=-8,max=8,res=1/16.) >>> x1 + x2 15 When assigned to another /fixbv/ the value will fit in the format of the accepting object. >>> x1 = fixbv(2.5,min=-8,max=8,res=1/16.) >>> x2 = fixbv(1.25,min=-8,max=8,res=1/16.) >>> z = fixbv(0,min=-16,max=16,res=1/16.) >>> z[:] = x1 + x2 fixbv(3.75, format=(9,4,4)) For multiplication the operands do not need to be aligned before the operation but the "point" bookkeeping needs to be accounted siii.ffff * s.fffffff ----------------- ssiii.fffffffffff (total 16 bits) An example using the example operands: >>> x = fixbv(1.5,min=-8,max=8,res=1/16.) >>> y = fixbv(0.25,min=-1,max=1,res=1/128.) >>> myhdl.bin(x*y, 16) '00000.01100000000' # 3/2*1/4 = 3/8 = 1/4+1/8 The basic mathematical operations have been reviewed, we will exclude division for now because we can achieve "division" by multiplying by the fractional parts. The next topic: rounding and overflow handling. During operations it is common not to maintain the maximum word-length through out a chain of operations. When reducing the word-length rounding and overflow come into play. Example, multiplying two numbers requires len(x)+len(y) bits or x.max*y.max range. It is typical for the result to be *resized* after an operation. In the previous multiply example, it may be desired to only preserve four fraction bits: ssiii.ffff ffff fff ~~~~~~~~ <- these bits remove The remaining bits will be rounded based on the removed bits, there are different rounding methods that can be used. This is a base feature of a fixed-point package. Also, when resizing overflow (underflow) is also an issue. If the value being resized does not fit, it needs to be saturated or wrapped. As eluded, the *resize* function is essential, the resize function will need to be a convertible function. Logic will need to be created to handle the rounding and overflow. The proposed *resized* function will look like: resize(val,format [,round_mode='convergent'] [,overflow_mode='saturate']) Example: z[:] = resize(x+y,z) The above will resize the result of /x+y/ to the format of the /z/ fixbv variable (note x and y need to be aligned or resized before the operation). This conversation reviewed fixed-point operations, how the proposed /fixbv/ handles unalignment, and bounds. Finally, the *resize* function was introduced. The next part will cover the implementation details of the *resize* function and implications. Regards, Chris Felton |