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 PipeModBase
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
13 from ieee754
.fpcommon
.pscdata
import FPSCData
16 class FPAddAlignMultiMod
:
17 """Module to do mantissa alignment shift in multiple cycles
19 def __init__(self
, width
):
20 self
.in_a
= FPNumBaseRecord(width
)
21 self
.in_b
= FPNumBaseRecord(width
)
22 self
.out_a
= FPNumBaseRecord(width
)
23 self
.out_b
= FPNumBaseRecord(width
)
24 self
.exp_eq
= Signal(reset_less
=True)
26 def elaborate(self
, platform
):
30 # exponent of a greater than b: shift b down
31 comb
+= self
.exp_eq
.eq(0)
32 comb
+= self
.out_a
.eq(self
.in_a
)
33 comb
+= self
.out_b
.eq(self
.in_b
)
34 agtb
= Signal(reset_less
=True)
35 altb
= Signal(reset_less
=True)
36 comb
+= agtb
.eq(self
.in_a
.e
> self
.in_b
.e
)
37 comb
+= altb
.eq(self
.in_a
.e
< self
.in_b
.e
)
39 comb
+= self
.out_b
.shift_down(self
.in_b
)
40 # exponent of b greater than a: shift a down
42 comb
+= self
.out_a
.shift_down(self
.in_a
)
43 # exponents equal: move to next stage.
45 comb
+= self
.exp_eq
.eq(1)
49 class FPAddAlignSingleMod(PipeModBase
):
51 def __init__(self
, pspec
):
52 super().__init
__(pspec
, "align")
55 return FPSCData(self
.pspec
, True)
58 return FPSCData(self
.pspec
, True)
60 def elaborate(self
, platform
):
61 """ Aligns A against B or B against A, depending on which has the
62 greater exponent. This is done in a *single* cycle using
63 variable-width bit-shift
65 the shifter used here is quite expensive in terms of gates.
66 Mux A or B in (and out) into temporaries, as only one of them
67 needs to be aligned against the other
72 # temporary (muxed) input and output to be shifted
73 width
= self
.pspec
.width
74 espec
= (len(self
.i
.a
.e
), True)
76 t_inp
= FPNumBaseRecord(width
)
77 t_out
= FPNumBaseRecord(width
)
78 msr
= MultiShiftRMerge(self
.i
.a
.m_width
, espec
)
79 m
.submodules
.multishift_r
= msr
82 ediff
= Signal(espec
, reset_less
=True)
83 ediffr
= Signal(espec
, reset_less
=True)
84 tdiff
= Signal(espec
, reset_less
=True)
85 elz
= Signal(reset_less
=True)
86 egz
= Signal(reset_less
=True)
88 with m
.If(~self
.i
.out_do_z
):
89 # connect multi-shifter to t_inp/out mantissa (and tdiff)
90 # (only one: input/output is muxed)
91 comb
+= msr
.inp
.eq(t_inp
.m
)
92 comb
+= msr
.diff
.eq(tdiff
)
93 comb
+= t_out
.m
.eq(msr
.m
)
94 comb
+= t_out
.e
.eq(t_inp
.e
+ tdiff
)
95 comb
+= t_out
.s
.eq(t_inp
.s
)
97 comb
+= ediff
.eq(self
.i
.a
.e
- self
.i
.b
.e
) # a - b
98 comb
+= ediffr
.eq(-ediff
) # b - a
99 comb
+= elz
.eq(self
.i
.a
.e
< self
.i
.b
.e
) # ae < be
100 comb
+= egz
.eq(self
.i
.a
.e
> self
.i
.b
.e
) # ae > be
102 # default: A-exp == B-exp, A and B untouched (fall through)
103 comb
+= self
.o
.a
.eq(self
.i
.a
)
104 comb
+= self
.o
.b
.eq(self
.i
.b
)
106 # exponent of a greater than b: shift b down
108 comb
+= [t_inp
.eq(self
.i
.b
),
111 self
.o
.b
.s
.eq(self
.i
.b
.s
), # whoops forgot sign
113 # exponent of b greater than a: shift a down
115 comb
+= [t_inp
.eq(self
.i
.a
),
118 self
.o
.a
.s
.eq(self
.i
.a
.s
), # whoops forgot sign
121 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
122 comb
+= self
.o
.z
.eq(self
.i
.z
)
123 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
124 comb
+= self
.o
.oz
.eq(self
.i
.oz
)