1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
, Elaboratable
6 from nmigen
.cli
import main
, verilog
8 from fpbase
import FPNumBase
9 from fpbase
import FPState
10 from fpcommon
.denorm
import FPSCData
13 class FPAddStage0Data
:
15 def __init__(self
, width
, id_wid
):
16 self
.z
= FPNumBase(width
, False)
17 self
.out_do_z
= Signal(reset_less
=True)
18 self
.oz
= Signal(width
, reset_less
=True)
19 self
.tot
= Signal(self
.z
.m_width
+ 4, reset_less
=True)
20 self
.mid
= Signal(id_wid
, reset_less
=True)
23 return [self
.z
.eq(i
.z
), self
.out_do_z
.eq(i
.out_do_z
), self
.oz
.eq(i
.oz
),
24 self
.tot
.eq(i
.tot
), self
.mid
.eq(i
.mid
)]
27 class FPAddStage0Mod(Elaboratable
):
29 def __init__(self
, width
, id_wid
):
36 return FPSCData(self
.width
, self
.id_wid
)
39 return FPAddStage0Data(self
.width
, self
.id_wid
)
44 def setup(self
, m
, i
):
45 """ links module to inputs and outputs
47 m
.submodules
.add0
= self
48 m
.d
.comb
+= self
.i
.eq(i
)
50 def elaborate(self
, platform
):
52 m
.submodules
.add0_in_a
= self
.i
.a
53 m
.submodules
.add0_in_b
= self
.i
.b
54 m
.submodules
.add0_out_z
= self
.o
.z
56 # store intermediate tests (and zero-extended mantissas)
57 seq
= Signal(reset_less
=True)
58 mge
= Signal(reset_less
=True)
59 am0
= Signal(len(self
.i
.a
.m
)+1, reset_less
=True)
60 bm0
= Signal(len(self
.i
.b
.m
)+1, reset_less
=True)
61 m
.d
.comb
+= [seq
.eq(self
.i
.a
.s
== self
.i
.b
.s
),
62 mge
.eq(self
.i
.a
.m
>= self
.i
.b
.m
),
63 am0
.eq(Cat(self
.i
.a
.m
, 0)),
64 bm0
.eq(Cat(self
.i
.b
.m
, 0))
66 # same-sign (both negative or both positive) add mantissas
67 with m
.If(~self
.i
.out_do_z
):
68 m
.d
.comb
+= self
.o
.z
.e
.eq(self
.i
.a
.e
)
71 self
.o
.tot
.eq(am0
+ bm0
),
72 self
.o
.z
.s
.eq(self
.i
.a
.s
)
74 # a mantissa greater than b, use a
77 self
.o
.tot
.eq(am0
- bm0
),
78 self
.o
.z
.s
.eq(self
.i
.a
.s
)
80 # b mantissa greater than a, use b
83 self
.o
.tot
.eq(bm0
- am0
),
84 self
.o
.z
.s
.eq(self
.i
.b
.s
)
87 m
.d
.comb
+= self
.o
.oz
.eq(self
.i
.oz
)
88 m
.d
.comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
89 m
.d
.comb
+= self
.o
.mid
.eq(self
.i
.mid
)
93 class FPAddStage0(FPState
):
94 """ First stage of add. covers same-sign (add) and subtract
95 special-casing when mantissas are greater or equal, to
96 give greatest accuracy.
99 def __init__(self
, width
, id_wid
):
100 FPState
.__init
__(self
, "add_0")
101 self
.mod
= FPAddStage0Mod(width
)
102 self
.o
= self
.mod
.ospec()
104 def setup(self
, m
, i
):
105 """ links module to inputs and outputs
109 # NOTE: these could be done as combinatorial (merge add0+add1)
110 m
.d
.sync
+= self
.o
.eq(self
.mod
.o
)