1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
,
6 from nmigen
.lib
.coding
import PriorityEncoder
7 from nmigen
.cli
import main
, verilog
10 from fpbase
import Overflow
, FPNumBase
11 from fpbase
import MultiShiftRMerge
13 from fpbase
import FPState
16 class FPNormaliseModSingle
:
18 def __init__(self
, width
):
20 self
.in_z
= self
.ispec()
21 self
.out_z
= self
.ospec()
24 return FPNumBase(self
.width
, False)
27 return FPNumBase(self
.width
, False)
29 def setup(self
, m
, i
):
30 """ links module to inputs and outputs
32 m
.submodules
.normalise
= self
33 m
.d
.comb
+= self
.i
.eq(i
)
35 def elaborate(self
, platform
):
38 mwid
= self
.out_z
.m_width
+2
39 pe
= PriorityEncoder(mwid
)
40 m
.submodules
.norm_pe
= pe
42 m
.submodules
.norm1_out_z
= self
.out_z
43 m
.submodules
.norm1_in_z
= self
.in_z
45 in_z
= FPNumBase(self
.width
, False)
47 m
.submodules
.norm1_insel_z
= in_z
48 m
.submodules
.norm1_insel_overflow
= in_of
50 espec
= (len(in_z
.e
), True)
51 ediff_n126
= Signal(espec
, reset_less
=True)
52 msr
= MultiShiftRMerge(mwid
, espec
)
53 m
.submodules
.multishift_r
= msr
55 m
.d
.comb
+= in_z
.eq(self
.in_z
)
56 m
.d
.comb
+= in_of
.eq(self
.in_of
)
57 # initialise out from in (overridden below)
58 m
.d
.comb
+= self
.out_z
.eq(in_z
)
59 m
.d
.comb
+= self
.out_of
.eq(in_of
)
60 # normalisation decrease condition
61 decrease
= Signal(reset_less
=True)
62 m
.d
.comb
+= decrease
.eq(in_z
.m_msbzero
)
65 # *sigh* not entirely obvious: count leading zeros (clz)
66 # with a PriorityEncoder: to find from the MSB
67 # we reverse the order of the bits.
68 temp_m
= Signal(mwid
, reset_less
=True)
69 temp_s
= Signal(mwid
+1, reset_less
=True)
70 clz
= Signal((len(in_z
.e
), True), reset_less
=True)
72 # cat round and guard bits back into the mantissa
73 temp_m
.eq(Cat(in_of
.round_bit
, in_of
.guard
, in_z
.m
)),
74 pe
.i
.eq(temp_m
[::-1]), # inverted
75 clz
.eq(pe
.o
), # count zeros from MSB down
76 temp_s
.eq(temp_m
<< clz
), # shift mantissa UP
77 self
.out_z
.e
.eq(in_z
.e
- clz
), # DECREASE exponent
78 self
.out_z
.m
.eq(temp_s
[2:]), # exclude bits 0&1