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 # connect multi-shifter to t_inp/out mantissa (and tdiff)
89 # (only one: input/output is muxed)
90 comb
+= msr
.inp
.eq(t_inp
.m
)
91 comb
+= msr
.diff
.eq(tdiff
)
92 comb
+= t_out
.m
.eq(msr
.m
)
93 comb
+= t_out
.e
.eq(t_inp
.e
+ tdiff
)
94 comb
+= t_out
.s
.eq(t_inp
.s
)
96 comb
+= ediff
.eq(self
.i
.a
.e
- self
.i
.b
.e
) # a - b
97 comb
+= ediffr
.eq(-ediff
) # b - a
98 comb
+= elz
.eq(self
.i
.a
.e
< self
.i
.b
.e
) # ae < be
99 comb
+= egz
.eq(self
.i
.a
.e
> self
.i
.b
.e
) # ae > be
101 # default: A-exp == B-exp, A and B untouched (fall through)
102 comb
+= self
.o
.a
.eq(self
.i
.a
)
103 comb
+= self
.o
.b
.eq(self
.i
.b
)
105 # exponent of a greater than b: shift b down
107 comb
+= [t_inp
.eq(self
.i
.b
),
110 self
.o
.b
.s
.eq(self
.i
.b
.s
), # whoops forgot sign
112 # exponent of b greater than a: shift a down
114 comb
+= [t_inp
.eq(self
.i
.a
),
117 self
.o
.a
.s
.eq(self
.i
.a
.s
), # whoops forgot sign
120 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
121 comb
+= self
.o
.z
.eq(self
.i
.z
)
122 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
123 comb
+= self
.o
.oz
.eq(self
.i
.oz
)