6aa205616367c9b9f1ea1703d86f00dd7176d97f
[ieee754fpu.git] / src / ieee754 / fpmul / mul1.py
1 """IEEE754 Floating Point Multiplier Pipeline
2
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4
5 """
6
7 from nmigen import Module, Signal, Elaboratable
8 from nmigen.cli import main, verilog
9
10 from ieee754.fpcommon.postcalc import FPAddStage1Data
11 from ieee754.fpmul.mul0 import FPMulStage0Data
12
13
14 class FPMulStage1Mod(Elaboratable):
15 """ Second stage of mul: preparation for normalisation.
16 """
17
18 def __init__(self, pspec):
19 self.pspec = pspec
20 self.i = self.ispec()
21 self.o = self.ospec()
22
23 def ispec(self):
24 return FPMulStage0Data(self.pspec)
25
26 def ospec(self):
27 return FPAddStage1Data(self.pspec)
28
29 def process(self, i):
30 return self.o
31
32 def setup(self, m, i):
33 """ links module to inputs and outputs
34 """
35 m.submodules.mul1 = self
36 m.d.comb += self.i.eq(i)
37
38 def elaborate(self, platform):
39 m = Module()
40 m.d.comb += self.o.z.eq(self.i.z)
41 with m.If(~self.i.out_do_z):
42 # results are in the range 0.25 to 0.999999999999
43 # sometimes the MSB will be zero, (0.5 * 0.5 = 0.25 which
44 # in binary is 0b010000) so to compensate for that we have
45 # to shift the mantissa up (and reduce the exponent by 1)
46 p = Signal(len(self.i.product), reset_less=True)
47 with m.If(self.i.product[-1]):
48 m.d.comb += p.eq(self.i.product)
49 with m.Else():
50 # get 1 bit of extra accuracy if the mantissa top bit is zero
51 m.d.comb += p.eq(self.i.product<<1)
52 m.d.comb += self.o.z.e.eq(self.i.z.e-1)
53
54 # top bits are mantissa, then guard and round, and the rest of
55 # the product is sticky
56 mw = self.o.z.m_width
57 m.d.comb += [
58 self.o.z.m.eq(p[mw+2:]), # mantissa
59 self.o.of.m0.eq(p[mw+2]), # copy of LSB
60 self.o.of.guard.eq(p[mw+1]), # guard
61 self.o.of.round_bit.eq(p[mw]), # round
62 self.o.of.sticky.eq(p[0:mw].bool()) # sticky
63 ]
64
65 m.d.comb += self.o.out_do_z.eq(self.i.out_do_z)
66 m.d.comb += self.o.oz.eq(self.i.oz)
67 m.d.comb += self.o.ctx.eq(self.i.ctx)
68
69 return m