move add to ieee754 directory
[ieee754fpu.git] / src / ieee754 / add / fpcommon / prenormalise.py
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
3 # 2013-12-12
4
5 from nmigen import Module, Signal, Cat,
6 from nmigen.lib.coding import PriorityEncoder
7 from nmigen.cli import main, verilog
8 from math import log
9
10 from fpbase import Overflow, FPNumBase
11 from fpbase import MultiShiftRMerge
12
13 from fpbase import FPState
14
15
16 class FPNormaliseModSingle:
17
18 def __init__(self, width):
19 self.width = width
20 self.in_z = self.ispec()
21 self.out_z = self.ospec()
22
23 def ispec(self):
24 return FPNumBase(self.width, False)
25
26 def ospec(self):
27 return FPNumBase(self.width, False)
28
29 def setup(self, m, i):
30 """ links module to inputs and outputs
31 """
32 m.submodules.normalise = self
33 m.d.comb += self.i.eq(i)
34
35 def elaborate(self, platform):
36 m = Module()
37
38 mwid = self.out_z.m_width+2
39 pe = PriorityEncoder(mwid)
40 m.submodules.norm_pe = pe
41
42 m.submodules.norm1_out_z = self.out_z
43 m.submodules.norm1_in_z = self.in_z
44
45 in_z = FPNumBase(self.width, False)
46 in_of = Overflow()
47 m.submodules.norm1_insel_z = in_z
48 m.submodules.norm1_insel_overflow = in_of
49
50 espec = (len(in_z.e), True)
51 ediff_n126 = Signal(espec, reset_less=True)
52 msr = MultiShiftRMerge(mwid, espec)
53 m.submodules.multishift_r = msr
54
55 m.d.comb += in_z.eq(self.in_z)
56 m.d.comb += in_of.eq(self.in_of)
57 # initialise out from in (overridden below)
58 m.d.comb += self.out_z.eq(in_z)
59 m.d.comb += self.out_of.eq(in_of)
60 # normalisation decrease condition
61 decrease = Signal(reset_less=True)
62 m.d.comb += decrease.eq(in_z.m_msbzero)
63 # decrease exponent
64 with m.If(decrease):
65 # *sigh* not entirely obvious: count leading zeros (clz)
66 # with a PriorityEncoder: to find from the MSB
67 # we reverse the order of the bits.
68 temp_m = Signal(mwid, reset_less=True)
69 temp_s = Signal(mwid+1, reset_less=True)
70 clz = Signal((len(in_z.e), True), reset_less=True)
71 m.d.comb += [
72 # cat round and guard bits back into the mantissa
73 temp_m.eq(Cat(in_of.round_bit, in_of.guard, in_z.m)),
74 pe.i.eq(temp_m[::-1]), # inverted
75 clz.eq(pe.o), # count zeros from MSB down
76 temp_s.eq(temp_m << clz), # shift mantissa UP
77 self.out_z.e.eq(in_z.e - clz), # DECREASE exponent
78 self.out_z.m.eq(temp_s[2:]), # exclude bits 0&1
79 ]
80
81 return m
82
83