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
, FPID
18 from fpcommon
.denorm
import (FPSCData
, FPAddDeNormMod
, FPAddDeNorm
)
19 from fpcommon
.postcalc
import FPAddStage1Data
20 from fpcommon
.postnormalise
import (FPNorm1Data
, FPNorm1ModSingle
,
21 FPNorm1ModMulti
, FPNorm1Single
, FPNorm1Multi
)
22 from fpcommon
.roundz
import (FPRoundData
, FPRoundMod
, FPRound
)
23 from fpcommon
.corrections
import (FPCorrectionsMod
, FPCorrections
)
24 from fpcommon
.pack
import (FPPackData
, FPPackMod
, FPPack
)
25 from fpcommon
.normtopack
import FPNormToPack
26 from fpcommon
.putz
import (FPPutZ
, FPPutZIdx
)
28 from fpadd
.specialcases
import (FPAddSpecialCasesMod
, FPAddSpecialCases
,
29 FPAddSpecialCasesDeNorm
)
30 from fpadd
.align
import (FPAddAlignMulti
, FPAddAlignMultiMod
, FPNumIn2Ops
,
31 FPAddAlignSingleMod
, FPAddAlignSingle
)
32 from fpadd
.add0
import (FPAddStage0Data
, FPAddStage0Mod
, FPAddStage0
)
35 class FPAddStage1Mod(FPState
):
36 """ Second stage of add: preparation for normalisation.
37 detects when tot sum is too big (tot[27] is kinda a carry bit)
40 def __init__(self
, width
, id_wid
):
47 return FPAddStage0Data(self
.width
, self
.id_wid
)
50 return FPAddStage1Data(self
.width
, self
.id_wid
)
55 def setup(self
, m
, i
):
56 """ links module to inputs and outputs
58 m
.submodules
.add1
= self
59 m
.submodules
.add1_out_overflow
= self
.o
.of
61 m
.d
.comb
+= self
.i
.eq(i
)
63 def elaborate(self
, platform
):
65 m
.d
.comb
+= self
.o
.z
.eq(self
.i
.z
)
66 # tot[-1] (MSB) gets set when the sum overflows. shift result down
67 with m
.If(~self
.i
.out_do_z
):
68 with m
.If(self
.i
.tot
[-1]):
70 self
.o
.z
.m
.eq(self
.i
.tot
[4:]),
71 self
.o
.of
.m0
.eq(self
.i
.tot
[4]),
72 self
.o
.of
.guard
.eq(self
.i
.tot
[3]),
73 self
.o
.of
.round_bit
.eq(self
.i
.tot
[2]),
74 self
.o
.of
.sticky
.eq(self
.i
.tot
[1] | self
.i
.tot
[0]),
75 self
.o
.z
.e
.eq(self
.i
.z
.e
+ 1)
77 # tot[-1] (MSB) zero case
80 self
.o
.z
.m
.eq(self
.i
.tot
[3:]),
81 self
.o
.of
.m0
.eq(self
.i
.tot
[3]),
82 self
.o
.of
.guard
.eq(self
.i
.tot
[2]),
83 self
.o
.of
.round_bit
.eq(self
.i
.tot
[1]),
84 self
.o
.of
.sticky
.eq(self
.i
.tot
[0])
87 m
.d
.comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
88 m
.d
.comb
+= self
.o
.oz
.eq(self
.i
.oz
)
89 m
.d
.comb
+= self
.o
.mid
.eq(self
.i
.mid
)
94 class FPAddStage1(FPState
):
96 def __init__(self
, width
, id_wid
):
97 FPState
.__init
__(self
, "add_1")
98 self
.mod
= FPAddStage1Mod(width
)
99 self
.out_z
= FPNumBase(width
, False)
100 self
.out_of
= Overflow()
101 self
.norm_stb
= Signal()
103 def setup(self
, m
, i
):
104 """ links module to inputs and outputs
108 m
.d
.sync
+= self
.norm_stb
.eq(0) # sets to zero when not in add1 state
110 m
.d
.sync
+= self
.out_of
.eq(self
.mod
.out_of
)
111 m
.d
.sync
+= self
.out_z
.eq(self
.mod
.out_z
)
112 m
.d
.sync
+= self
.norm_stb
.eq(1)
115 m
.next
= "normalise_1"