1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
6 from nmigen
.cli
import main
, verilog
8 from nmutil
.pipemodbase
import FPModBase
9 from ieee754
.fpcommon
.fpbase
import FPNumBaseRecord
10 from ieee754
.fpcommon
.fpbase
import MultiShiftRMerge
11 from ieee754
.fpcommon
.denorm
import FPSCData
12 from ieee754
.fpcommon
.getop
import FPPipeContext
17 def __init__(self
, pspec
):
19 self
.a
= FPNumBaseRecord(width
)
20 self
.b
= FPNumBaseRecord(width
)
21 self
.z
= FPNumBaseRecord(width
, False)
22 self
.out_do_z
= Signal(reset_less
=True)
23 self
.oz
= Signal(width
, reset_less
=True)
24 self
.ctx
= FPPipeContext(pspec
)
25 self
.muxid
= self
.ctx
.muxid
28 return [self
.z
.eq(i
.z
), self
.out_do_z
.eq(i
.out_do_z
), self
.oz
.eq(i
.oz
),
29 self
.a
.eq(i
.a
), self
.b
.eq(i
.b
), self
.ctx
.eq(i
.ctx
)]
32 class FPAddAlignMultiMod
:
34 def __init__(self
, width
):
35 self
.in_a
= FPNumBaseRecord(width
)
36 self
.in_b
= FPNumBaseRecord(width
)
37 self
.out_a
= FPNumBaseRecord(width
)
38 self
.out_b
= FPNumBaseRecord(width
)
39 self
.exp_eq
= Signal(reset_less
=True)
41 def elaborate(self
, platform
):
42 # This one however (single-cycle) will do the shift
47 #m.submodules.align_in_a = self.in_a
48 #m.submodules.align_in_b = self.in_b
49 #m.submodules.align_out_a = self.out_a
50 #m.submodules.align_out_b = self.out_b
52 # NOTE: this does *not* do single-cycle multi-shifting,
53 # it *STAYS* in the align state until exponents match
55 # exponent of a greater than b: shift b down
56 m
.d
.comb
+= self
.exp_eq
.eq(0)
57 m
.d
.comb
+= self
.out_a
.eq(self
.in_a
)
58 m
.d
.comb
+= self
.out_b
.eq(self
.in_b
)
59 agtb
= Signal(reset_less
=True)
60 altb
= Signal(reset_less
=True)
61 m
.d
.comb
+= agtb
.eq(self
.in_a
.e
> self
.in_b
.e
)
62 m
.d
.comb
+= altb
.eq(self
.in_a
.e
< self
.in_b
.e
)
64 m
.d
.comb
+= self
.out_b
.shift_down(self
.in_b
)
65 # exponent of b greater than a: shift a down
67 m
.d
.comb
+= self
.out_a
.shift_down(self
.in_a
)
68 # exponents equal: move to next stage.
70 m
.d
.comb
+= self
.exp_eq
.eq(1)
74 class FPAddAlignSingleMod(FPModBase
):
76 def __init__(self
, pspec
):
77 super().__init
__(pspec
, "align")
80 return FPSCData(self
.pspec
, True)
83 return FPNumIn2Ops(self
.pspec
)
85 def elaborate(self
, platform
):
86 """ Aligns A against B or B against A, depending on which has the
87 greater exponent. This is done in a *single* cycle using
88 variable-width bit-shift
90 the shifter used here is quite expensive in terms of gates.
91 Mux A or B in (and out) into temporaries, as only one of them
92 needs to be aligned against the other
96 # temporary (muxed) input and output to be shifted
97 width
= self
.pspec
.width
98 t_inp
= FPNumBaseRecord(width
)
99 t_out
= FPNumBaseRecord(width
)
100 espec
= (len(self
.i
.a
.e
), True)
101 msr
= MultiShiftRMerge(self
.i
.a
.m_width
, espec
)
102 m
.submodules
.multishift_r
= msr
104 ediff
= Signal(espec
, reset_less
=True)
105 ediffr
= Signal(espec
, reset_less
=True)
106 tdiff
= Signal(espec
, reset_less
=True)
107 elz
= Signal(reset_less
=True)
108 egz
= Signal(reset_less
=True)
110 # connect multi-shifter to t_inp/out mantissa (and tdiff)
111 m
.d
.comb
+= msr
.inp
.eq(t_inp
.m
)
112 m
.d
.comb
+= msr
.diff
.eq(tdiff
)
113 m
.d
.comb
+= t_out
.m
.eq(msr
.m
)
114 m
.d
.comb
+= t_out
.e
.eq(t_inp
.e
+ tdiff
)
115 m
.d
.comb
+= t_out
.s
.eq(t_inp
.s
)
117 m
.d
.comb
+= ediff
.eq(self
.i
.a
.e
- self
.i
.b
.e
)
118 m
.d
.comb
+= ediffr
.eq(self
.i
.b
.e
- self
.i
.a
.e
)
119 m
.d
.comb
+= elz
.eq(self
.i
.a
.e
< self
.i
.b
.e
)
120 m
.d
.comb
+= egz
.eq(self
.i
.a
.e
> self
.i
.b
.e
)
122 # default: A-exp == B-exp, A and B untouched (fall through)
123 m
.d
.comb
+= self
.o
.a
.eq(self
.i
.a
)
124 m
.d
.comb
+= self
.o
.b
.eq(self
.i
.b
)
125 # only one shifter (muxed)
126 #m.d.comb += t_out.shift_down_multi(tdiff, t_inp)
127 # exponent of a greater than b: shift b down
128 with m
.If(~self
.i
.out_do_z
):
130 m
.d
.comb
+= [t_inp
.eq(self
.i
.b
),
133 self
.o
.b
.s
.eq(self
.i
.b
.s
), # whoops forgot sign
135 # exponent of b greater than a: shift a down
137 m
.d
.comb
+= [t_inp
.eq(self
.i
.a
),
140 self
.o
.a
.s
.eq(self
.i
.a
.s
), # whoops forgot sign
143 m
.d
.comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
144 m
.d
.comb
+= self
.o
.z
.eq(self
.i
.z
)
145 m
.d
.comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
146 m
.d
.comb
+= self
.o
.oz
.eq(self
.i
.oz
)