An brief introduction to fixed-point has been added here Introduction to fixed-point.
The above introduction uses slightly different terminology than the documents below. And the comments by others are useful as well. The following information is currently being updated and improved. Look for updates soon (I hope) [3-May-2011].
The following page outlines the design and examples for a Python / MyHDL fixed-point object. The fixed-point object is based on the intbv object that is part of MyHDL. Because the fixed-point object (fxintbv) inherits the intbv it is convertible. Meaning that designs using the fxintbv can be converted to Verilog or VHDL. See the pdf for examples.
See the following PDF for an introduction to the Python / MyHDL fixed-point object. The PDF also contains the design overview and examples.
The following tarball is a standard python package, it can be install using $ python setup.py install . MyHDL needs to be installed for this package. Download MyHDL from sourceforge or checkout the latest development from the mercurial repo.
The current version of the Fixed-Point Python package only the fxintbv is convertible (generates Verilog/VHDL code). The following enhancements are under development so the fxint object is also convertible. This is useful because the fxintbv only provides the Fixed-Point representation and helper functions. The fxint does point alignment and auto promotion. Having the fxint convertible is a much more powerful tool. To move toward fxint convertibility a “Q” property will be added to the fxintbv and a @always_fx decorator will be added to provide introspection for the MyHDL generator.
The “Q” property replaces all the helper functions to manage alignment and bit growth. The “Q” property can be used outside the MyHDL generators (elaboration phase) to assist auto-promotion (result type) and alignment.
def fx_mix_ex(a,b,c,d,e): # Elaboration phase point calculations e.Q = (b.Q-a.Q)*c.Q + d.Q @always_comb def rtl(): # RTL fixed-point computation e.next = (b-a)*c + d return rtl a = Signal(fxintbv(0, Q=(0,15) )) b = Signal(fxintbv(0, Q=(0,15) )) c = Signal(fxintbv(0, Q=(0,15) )) d = Signal(fxintbv(0, Q=(0,15) )) e = Signal(fxintbv(0)) toVerilog(fx_mix_ex, a, b, c, d, e) # Verilog creation toVHDL(fx_mix_ex, a, b, c, d, e) # VHDL creation
The above example is only valid if the inputs are the same type (aligned). If the inputs are not the same type the align(…) function can be used. Some care needs to be taken the “Q” operator will modify the Signal sizes during the elaboration phase. This is useful for creating modular components. The following example is an illustration how to align the inputs.
def fx_mix_ex(a,b,c,d,e): def getOutputType(a,b,c,d): Q = (b.Q-a.Q)*c.Q + d.Q return fxintbv(0, Q=Q) @always_comb def rtl(): # RTL fixed-point computation e.next = (b-a)*c + d return rtl a = Signal(fxintbv(0, Q=(1,3) )) b = Signal(fxintbv(0, Q=(7,8) )) c = Signal(fxintbv(0, Q=(0,15) )) d = Signal(fxintbv(0, Q=(16,15) )) e = Signal(fxintbv(0)) toVerilog(fx_mix_ex, a, b, c, d, e) # Verilog creation toVHDL(fx_mix_ex, a, b, c, d, e) # VHDL creation print a print b print c print d print e
The print out from the above code shows the Signal(fxintbv) modifications to the correct size. Again, this approach modifies the signals and in some cases this is not desired. For a general template for creating fxintbv calculating see the template and explanation below.
The “Q” property is used the same as the helper functions to adjust the integer and fractional bit widths. The “Q” property has been implemented in the 0.4 release.
The proposal is that the @always_fx decorator can be used with the MyHDL decorators to adjust the fixed-point expression in following generator. It will have to identify the fxint types and create intermediate results and signals.
def FixedPointMath(a,b,c,d,e): @always_fx(a,b,c,d) # <-- Replaces @always(a,b,c,d) def rtl_fixed_point(): e.next = (a+b)*c - d return rtl_fixed_point a = Signal(fxint(0, Q=(4,8) )) b = Signal(fxint(0, Q=(0,15) )) c = Signal(fxint(0, Q=(0,7) )) d = Signal(fxint(0, Q=(2,15) )) e = Signal(fxint(0)) toVerilog(FixedPointMath,a, b, c, d, e)
In the above example the decorator will have to align the 4 inputs (a,b,c,d) and determine the correct Q format for the result, e. The @always_fx decorator is only a proposal and has not been implemented. More information can be retrieved from the MyHDL newsgroup.