big (single-purpose) update: move width arg into pspec
[ieee754fpu.git] / src / ieee754 / fpadd / add1.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, Elaboratable
6 from nmigen.cli import main, verilog
7 from math import log
8
9 from ieee754.fpcommon.fpbase import FPState
10 from ieee754.fpcommon.postcalc import FPAddStage1Data
11 from .add0 import FPAddStage0Data
12
13
14 class FPAddStage1Mod(FPState, Elaboratable):
15 """ Second stage of add: preparation for normalisation.
16 detects when tot sum is too big (tot[27] is kinda a carry bit)
17 """
18
19 def __init__(self, pspec):
20 self.pspec = pspec
21 self.i = self.ispec()
22 self.o = self.ospec()
23
24 def ispec(self):
25 return FPAddStage0Data(self.pspec)
26
27 def ospec(self):
28 return FPAddStage1Data(self.pspec)
29
30 def process(self, i):
31 return self.o
32
33 def setup(self, m, i):
34 """ links module to inputs and outputs
35 """
36 m.submodules.add1 = self
37 #m.submodules.add1_out_overflow = self.o.of
38
39 m.d.comb += self.i.eq(i)
40
41 def elaborate(self, platform):
42 m = Module()
43 m.d.comb += self.o.z.eq(self.i.z)
44 # tot[-1] (MSB) gets set when the sum overflows. shift result down
45 with m.If(~self.i.out_do_z):
46 with m.If(self.i.tot[-1]):
47 m.d.comb += [
48 self.o.z.m.eq(self.i.tot[4:]),
49 self.o.of.m0.eq(self.i.tot[4]),
50 self.o.of.guard.eq(self.i.tot[3]),
51 self.o.of.round_bit.eq(self.i.tot[2]),
52 self.o.of.sticky.eq(self.i.tot[1] | self.i.tot[0]),
53 self.o.z.e.eq(self.i.z.e + 1)
54 ]
55 # tot[-1] (MSB) zero case
56 with m.Else():
57 m.d.comb += [
58 self.o.z.m.eq(self.i.tot[3:]),
59 self.o.of.m0.eq(self.i.tot[3]),
60 self.o.of.guard.eq(self.i.tot[2]),
61 self.o.of.round_bit.eq(self.i.tot[1]),
62 self.o.of.sticky.eq(self.i.tot[0])
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
70
71
72 class FPAddStage1(FPState):
73
74 def __init__(self, pspec):
75 FPState.__init__(self, "add_1")
76 self.mod = FPAddStage1Mod(width)
77 self.out_z = FPNumBase(width, False)
78 self.out_of = Overflow()
79 self.norm_stb = Signal()
80
81 def setup(self, m, i):
82 """ links module to inputs and outputs
83 """
84 self.mod.setup(m, i)
85
86 m.d.sync += self.norm_stb.eq(0) # sets to zero when not in add1 state
87
88 m.d.sync += self.out_of.eq(self.mod.out_of)
89 m.d.sync += self.out_z.eq(self.mod.out_z)
90 m.d.sync += self.norm_stb.eq(1)
91
92 def action(self, m):
93 m.next = "normalise_1"
94