4f8d248de966a6ead436461b3d70477d521ae7aa
1 # IEEE Floating Point Adder (Single Precision)
2 # Copyright (C) Jonathan P Dawson 2013
5 from nmigen
import Module
, Signal
, Cat
6 from nmigen
.cli
import main
, verilog
10 """ Floating-point Number Class, variable-width TODO (currently 32-bit)
12 Contains signals for an incoming copy of the value, decoded into
13 sign / exponent / mantissa.
14 Also contains encoding functions, creation and recognition of
15 zero, NaN and inf (all signed)
17 Four extra bits are included in the mantissa: the top bit
18 (m[-1]) is effectively a carry-overflow. The other three are
19 guard (m[2]), round (m[1]), and sticky (m[0])
21 def __init__(self
, width
, m_width
=None):
24 m_width
= width
- 5 # mantissa extra bits (top,guard,round)
25 self
.v
= Signal(width
) # Latched copy of value
26 self
.m
= Signal(m_width
) # Mantissa
27 self
.e
= Signal((10, True)) # Exponent: 10 bits, signed
28 self
.s
= Signal() # Sign bit
31 """ decodes a latched value into sign / exponent / mantissa
33 bias is subtracted here, from the exponent. exponent
34 is extended to 10 bits so that subtract 127 is done on
38 return [self
.m
.eq(Cat(0, 0, 0, v
[0:23])), # mantissa
39 self
.e
.eq(Cat(0,0,0, v
[23:31]) - 127), # exponent (minus bias)
40 self
.s
.eq(v
[31]), # sign
43 def create(self
, s
, e
, m
):
44 """ creates a value from sign / exponent / mantissa
46 bias is added here, to the exponent
49 self
.v
[31].eq(s
), # sign
50 self
.v
[23:31].eq(e
+ 127), # exp (add on bias)
51 self
.v
[0:23].eq(m
) # mantissa
55 """ shifts a mantissa down by one. exponent is increased to compensate
57 accuracy is lost as a result in the mantissa however there are 3
58 guard bits (the latter of which is the "sticky" bit)
60 return self
.create(self
.s
,
62 Cat(self
.m
[0] | self
.m
[1], self
.m
[1:-5], 0))
65 return self
.create(s
, 0x80, 1<<22)
68 return self
.create(s
, 0x80, 0)
71 return self
.create(s
, -127, 0)
74 return (self
.e
== 128) & (self
.m
!= 0)
77 return (self
.e
== 128) & (self
.m
== 0)
80 return (self
.e
== -127) & (self
.m
== 0)
82 def is_overflowed(self
):
85 def is_denormalised(self
):
86 return (self
.e
== -126) & (self
.m
[23] == 0)
90 def __init__(self
, width
):
93 self
.in_a
= Signal(width
)
94 self
.in_a_stb
= Signal()
95 self
.in_a_ack
= Signal()
97 self
.in_b
= Signal(width
)
98 self
.in_b_stb
= Signal()
99 self
.in_b_ack
= Signal()
101 self
.out_z
= Signal(width
)
102 self
.out_z_stb
= Signal()
103 self
.out_z_ack
= Signal()
105 def get_fragment(self
, platform
=None):
109 a
= FPNum(self
.width
)
110 b
= FPNum(self
.width
)
111 z
= FPNum(self
.width
, 24)
113 tot
= Signal(28) # sticky/round/guard bits, 23 result, 1 overflow
115 guard
= Signal() # tot[2]
116 round_bit
= Signal() # tot[1]
117 sticky
= Signal() # tot[0]
124 with m
.State("get_a"):
125 with m
.If((self
.in_a_ack
) & (self
.in_a_stb
)):
132 m
.d
.sync
+= self
.in_a_ack
.eq(1)
137 with m
.State("get_b"):
138 with m
.If((self
.in_b_ack
) & (self
.in_b_stb
)):
145 m
.d
.sync
+= self
.in_b_ack
.eq(1)
148 # unpacks operands into sign, mantissa and exponent
150 with m
.State("unpack"):
151 m
.next
= "special_cases"
152 m
.d
.sync
+= a
.decode()
153 m
.d
.sync
+= b
.decode()
156 # special cases: NaNs, infs, zeros, denormalised
158 with m
.State("special_cases"):
160 # if a is NaN or b is NaN return NaN
161 with m
.If(a
.is_nan() | b
.is_nan()):
165 # if a is inf return inf (or NaN)
166 with m
.Elif(a
.is_inf()):
168 m
.d
.sync
+= z
.inf(a
.s
)
169 # if a is inf and signs don't match return NaN
170 with m
.If((b
.e
== 128) & (a
.s
!= b
.s
)):
171 m
.d
.sync
+= z
.nan(b
.s
)
173 # if b is inf return inf
174 with m
.Elif(b
.is_inf()):
176 m
.d
.sync
+= z
.inf(b
.s
)
178 # if a is zero and b zero return signed-a/b
179 with m
.Elif(a
.is_zero() & b
.is_zero()):
181 m
.d
.sync
+= z
.create(a
.s
& b
.s
, b
.e
[0:8], b
.m
[3:26])
183 # if a is zero return b
184 with m
.Elif(a
.is_zero()):
186 m
.d
.sync
+= z
.create(b
.s
, b
.e
[0:8], b
.m
[3:26])
188 # if b is zero return a
189 with m
.Elif(b
.is_zero()):
191 m
.d
.sync
+= z
.create(a
.s
, a
.e
[0:8], a
.m
[3:26])
193 # Denormalised Number checks
196 # denormalise a check
197 with m
.If(a
.e
== -127):
198 m
.d
.sync
+= a
.e
.eq(-126) # limit a exponent
200 m
.d
.sync
+= a
.m
[26].eq(1) # set top mantissa bit
201 # denormalise b check
202 with m
.If(b
.e
== -127):
203 m
.d
.sync
+= b
.e
.eq(-126) # limit b exponent
205 m
.d
.sync
+= b
.m
[26].eq(1) # set top mantissa bit
208 # align. NOTE: this does *not* do single-cycle multi-shifting,
209 # it *STAYS* in the align state until the exponents match
211 with m
.State("align"):
212 # exponent of a greater than b: increment b exp, shift b mant
213 with m
.If(a
.e
> b
.e
):
214 m
.d
.sync
+= b
.shift_down()
215 # exponent of b greater than a: increment a exp, shift a mant
216 with m
.Elif(a
.e
< b
.e
):
217 m
.d
.sync
+= a
.shift_down()
218 # exponents equal: move to next stage.
223 # First stage of add. covers same-sign (add) and subtract
224 # special-casing when mantissas are greater or equal, to
225 # give greatest accuracy.
227 with m
.State("add_0"):
229 m
.d
.sync
+= z
.e
.eq(a
.e
)
230 # same-sign (both negative or both positive) add mantissas
231 with m
.If(a
.s
== b
.s
):
236 # a mantissa greater than b, use a
237 with m
.Elif(a
.m
>= b
.m
):
242 # b mantissa greater than a, use b
250 # Second stage of add: preparation for normalisation.
251 # detects when tot sum is too big (tot[27] is kinda a carry bit)
253 with m
.State("add_1"):
254 m
.next
= "normalise_1"
255 # tot[27] gets set when the sum overflows. shift result down
260 round_bit
.eq(tot
[2]),
261 sticky
.eq(tot
[1] | tot
[0]),
269 round_bit
.eq(tot
[1]),
274 # First stage of normalisation.
275 # NOTE: just like "align", this one keeps going round every clock
276 # until the result's exponent is within acceptable "range"
277 # NOTE: the weirdness of reassigning guard and round is due to
278 # the extra mantissa bits coming from tot[0..2]
280 with m
.State("normalise_1"):
281 with m
.If((z
.m
[23] == 0) & (z
.e
> -126)):
283 z
.e
.eq(z
.e
- 1), # DECREASE exponent
284 z
.m
.eq(z
.m
<< 1), # shift mantissa UP
285 z
.m
[0].eq(guard
), # steal guard bit (was tot[2])
286 guard
.eq(round_bit
), # steal round_bit (was tot[1])
289 m
.next
= "normalize_2"
292 # Second stage of normalisation.
293 # NOTE: just like "align", this one keeps going round every clock
294 # until the result's exponent is within acceptable "range"
295 # NOTE: the weirdness of reassigning guard and round is due to
296 # the extra mantissa bits coming from tot[0..2]
298 with m
.State("normalise_2"):
299 with m
.If(z
.e
< -126):
301 z
.e
.eq(z
.e
+ 1), # INCREASE exponent
302 z
.m
.eq(z
.m
>> 1), # shift mantissa DOWN
305 sticky
.eq(sticky | round_bit
)
313 with m
.State("round"):
314 m
.next
= "corrections"
315 with m
.If(guard
& (round_bit | sticky | z
.m
[0])):
316 m
.d
.sync
+= z
.m
.eq(z
.m
+ 1) # mantissa rounds up
317 with m
.If(z
.m
== 0xffffff): # all 1s
318 m
.d
.sync
+= z
.e
.eq(z
.e
+ 1) # exponent rounds up
323 with m
.State("corrections"):
325 # denormalised, correct exponent to zero
326 with m
.If(z
.is_denormalised()):
327 m
.d
.sync
+= z
.m
.eq(-127)
328 # FIX SIGN BUG: -a + a = +0.
329 with m
.If((z
.e
== -126) & (z
.m
[0:23] == 0)):
330 m
.d
.sync
+= z
.s
.eq(0)
335 with m
.State("pack"):
337 # if overflow occurs, return inf
338 with m
.If(z
.is_overflowed()):
341 m
.d
.sync
+= z
.create(z
.s
, z
.e
, z
.m
)
346 with m
.State("put_z"):
348 self
.out_z_stb
.eq(1),
351 with m
.If(self
.out_z_stb
& self
.out_z_ack
):
352 m
.d
.sync
+= self
.out_z_stb
.eq(0)
358 if __name__
== "__main__":
359 alu
= FPADD(width
=32)
361 alu
.in_a
, alu
.in_a_stb
, alu
.in_a_ack
,
362 alu
.in_b
, alu
.in_b_stb
, alu
.in_b_ack
,
363 alu
.out_z
, alu
.out_z_stb
, alu
.out_z_ack
,
367 # works... but don't use, just do "python fname.py convert -t v"
368 #print (verilog.convert(alu, ports=[
369 # alu.in_a, alu.in_a_stb, alu.in_a_ack,
370 # alu.in_b, alu.in_b_stb, alu.in_b_ack,
371 # alu.out_z, alu.out_z_stb, alu.out_z_ack,