1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
, Mux
, Array
, Const
6 from nmigen
.lib
.coding
import PriorityEncoder
7 from nmigen
.cli
import main
, verilog
10 from fpbase
import FPNumIn
, FPNumOut
, FPOp
, Overflow
, FPBase
, FPNumBase
11 from fpbase
import MultiShiftRMerge
, Trigger
12 from singlepipe
import (ControlBase
, StageChain
, UnbufferedPipeline
,
14 from multipipe
import CombMuxOutPipe
15 from multipipe
import PriorityCombMuxInPipe
17 from fpbase
import FPState
18 from fpcommon
.getop
import (FPGetOpMod
, FPGetOp
, FPNumBase2Ops
, FPADDBaseData
, FPGet2OpMod
, FPGet2Op
)
19 from fpcommon
.denorm
import (FPSCData
, FPAddDeNormMod
, FPAddDeNorm
)
22 class FPNormaliseModSingle
:
24 def __init__(self
, width
):
26 self
.in_z
= self
.ispec()
27 self
.out_z
= self
.ospec()
30 return FPNumBase(self
.width
, False)
33 return FPNumBase(self
.width
, False)
35 def setup(self
, m
, i
):
36 """ links module to inputs and outputs
38 m
.submodules
.normalise
= self
39 m
.d
.comb
+= self
.i
.eq(i
)
41 def elaborate(self
, platform
):
44 mwid
= self
.out_z
.m_width
+2
45 pe
= PriorityEncoder(mwid
)
46 m
.submodules
.norm_pe
= pe
48 m
.submodules
.norm1_out_z
= self
.out_z
49 m
.submodules
.norm1_in_z
= self
.in_z
51 in_z
= FPNumBase(self
.width
, False)
53 m
.submodules
.norm1_insel_z
= in_z
54 m
.submodules
.norm1_insel_overflow
= in_of
56 espec
= (len(in_z
.e
), True)
57 ediff_n126
= Signal(espec
, reset_less
=True)
58 msr
= MultiShiftRMerge(mwid
, espec
)
59 m
.submodules
.multishift_r
= msr
61 m
.d
.comb
+= in_z
.eq(self
.in_z
)
62 m
.d
.comb
+= in_of
.eq(self
.in_of
)
63 # initialise out from in (overridden below)
64 m
.d
.comb
+= self
.out_z
.eq(in_z
)
65 m
.d
.comb
+= self
.out_of
.eq(in_of
)
66 # normalisation decrease condition
67 decrease
= Signal(reset_less
=True)
68 m
.d
.comb
+= decrease
.eq(in_z
.m_msbzero
)
71 # *sigh* not entirely obvious: count leading zeros (clz)
72 # with a PriorityEncoder: to find from the MSB
73 # we reverse the order of the bits.
74 temp_m
= Signal(mwid
, reset_less
=True)
75 temp_s
= Signal(mwid
+1, reset_less
=True)
76 clz
= Signal((len(in_z
.e
), True), reset_less
=True)
78 # cat round and guard bits back into the mantissa
79 temp_m
.eq(Cat(in_of
.round_bit
, in_of
.guard
, in_z
.m
)),
80 pe
.i
.eq(temp_m
[::-1]), # inverted
81 clz
.eq(pe
.o
), # count zeros from MSB down
82 temp_s
.eq(temp_m
<< clz
), # shift mantissa UP
83 self
.out_z
.e
.eq(in_z
.e
- clz
), # DECREASE exponent
84 self
.out_z
.m
.eq(temp_s
[2:]), # exclude bits 0&1