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
10 """ Floating-point Number Class, variable-width TODO (currently 32-bit)
11 Contains signals for an incoming copy of the value, decoded into
12 sign / exponent / mantissa.
13 Also contains encoding functions, creation and recognition of
14 zero, NaN and inf (all signed)
16 def __init__(self
, width
, m_width
=None):
19 m_width
= width
- 5 # mantissa extra bits (top,guard,round)
20 self
.v
= Signal(width
) # Latched copy of value
21 self
.m
= Signal(m_width
) # Mantissa
22 self
.e
= Signal((10, True)) # Exponent: 10 bits, signed
23 self
.s
= Signal() # Sign bit
27 return [self
.m
.eq(Cat(0, 0, 0, v
[0:23])), # mantissa
28 self
.e
.eq(Cat(v
[23:31]) - 127), # exponent (take off bias)
29 self
.s
.eq(Cat(v
[31])), # sign
32 def create(self
, s
, e
, m
):
34 self
.v
[31].eq(s
), # sign
35 self
.v
[23:31].eq(e
+ 127), # exp
36 self
.v
[0:23].eq(m
) # mantissa
40 return self
.create(self
.s
,
42 Cat(self
.m
[0] | self
.m
[1], self
.m
[1:-5], 0))
45 return self
.create(s
, 0x80, 1<<22)
48 return self
.create(s
, 0x80, 0)
51 return (self
.e
== 128) & (self
.m
!= 0)
54 return (self
.e
== 128) & (self
.m
== 0)
57 return (self
.e
== -127) & (self
.m
== 0)
61 def __init__(self
, width
):
64 self
.in_a
= Signal(width
)
65 self
.in_a_stb
= Signal()
66 self
.in_a_ack
= Signal()
68 self
.in_b
= Signal(width
)
69 self
.in_b_stb
= Signal()
70 self
.in_b_ack
= Signal()
72 self
.out_z
= Signal(width
)
73 self
.out_z_stb
= Signal()
74 self
.out_z_ack
= Signal()
76 def get_fragment(self
, platform
):
82 z
= FPNum(self
.width
, 24)
95 with m
.State("get_a"):
96 with m
.If((self
.in_a_ack
) & (self
.in_a_stb
)):
103 m
.d
.sync
+= self
.in_a_ack
.eq(1)
108 with m
.State("get_b"):
109 with m
.If((self
.in_b_ack
) & (self
.in_b_stb
)):
116 m
.d
.sync
+= self
.in_b_ack
.eq(1)
119 # unpacks operands into sign, mantissa and exponent
121 with m
.State("unpack"):
122 m
.next
= "special_cases"
123 m
.d
.sync
+= a
.decode()
124 m
.d
.sync
+= b
.decode()
127 # special cases: NaNs, infs, zeros, denormalised
129 with m
.State("special_cases"):
131 # if a is NaN or b is NaN return NaN
132 with m
.If(a
.is_nan() | b
.is_nan()):
136 # if a is inf return inf (or NaN)
137 with m
.Elif(a
.is_inf()):
139 m
.d
.sync
+= z
.inf(a
.s
)
140 # if a is inf and signs don't match return NaN
141 with m
.If((b
.e
== 128) & (a
.s
!= b
.s
)):
142 m
.d
.sync
+= z
.nan(b
.s
)
144 # if b is inf return inf
145 with m
.Elif(b
.is_inf()):
147 m
.d
.sync
+= z
.inf(b
.s
)
149 # if a is zero and b zero return signed-a/b
150 with m
.Elif(a
.is_zero() & b
.is_zero()):
152 m
.d
.sync
+= z
.create(a
.s
& b
.s
, b
.e
[0:8], b
.m
[3:26])
154 # if a is zero return b
155 with m
.Elif(a
.is_zero()):
157 m
.d
.sync
+= z
.create(b
.s
, b
.e
[0:8], b
.m
[3:26])
159 # if b is zero return a
160 with m
.Elif(b
.is_zero()):
162 m
.d
.sync
+= z
.create(a
.s
, a
.e
[0:8], a
.m
[3:26])
164 # Denormalised Number checks
167 # denormalise a check
168 with m
.If(a
.e
== -127):
169 m
.d
.sync
+= a
.e
.eq(-126) # limit a exponent
171 m
.d
.sync
+= a
.m
[26].eq(1) # set highest mantissa bit
172 # denormalise b check
173 with m
.If(b
.e
== -127):
174 m
.d
.sync
+= b
.e
.eq(-126) # limit b exponent
176 m
.d
.sync
+= b
.m
[26].eq(1) # set highest mantissa bit
179 # align. NOTE: this does *not* do single-cycle multi-shifting,
180 # it *STAYS* in the align state until the exponents match
182 with m
.State("align"):
183 # exponent of a greater than b: increment b exp, shift b mant
184 with m
.If(a
.e
> b
.e
):
185 m
.d
.sync
+= b
.shift_down()
186 # exponent of b greater than a: increment a exp, shift a mant
187 with m
.Elif(a
.e
< b
.e
):
188 m
.d
.sync
+= a
.shift_down()
189 # exponents equal: move to next stage.
194 # First stage of add. covers same-sign (add) and subtract
195 # special-casing when mantissas are greater or equal, to
196 # give greatest accuracy.
198 with m
.State("add_0"):
200 m
.d
.sync
+= z
.e
.eq(a
.e
)
201 # same-sign (both negative or both positive) add mantissas
202 with m
.If(a
.s
== b
.s
):
207 # a mantissa greater than b, use a
208 with m
.Elif(a
.m
>= b
.m
):
213 # b mantissa greater than a, use b
221 # Second stage of add: preparation for normalisation.
222 # detects when tot sum is too big (tot[27] is kinda a carry bit)
224 with m
.State("add_1"):
225 m
.next
= "normalise_1"
226 # tot[27] gets set when the sum overflows. shift result down
231 round_bit
.eq(tot
[2]),
232 sticky
.eq(tot
[1] | tot
[0]),
240 round_bit
.eq(tot
[1]),
245 # First stage of normalisation.
246 # NOTE: just like "align", this one keeps going round every clock
247 # until the result's exponent is within acceptable "range"
248 # NOTE: the weirdness of reassigning guard and round is due to
249 # the extra mantissa bits coming from tot[0..2]
251 with m
.State("normalise_1"):
252 with m
.If((z
.m
[23] == 0) & (z
.e
> -126)):
254 z
.e
.eq(z
.e
- 1), # DECREASE exponent
255 z
.m
.eq(z
.m
<< 1), # shift mantissa UP
256 z
.m
[0].eq(guard
), # steal guard bit (was tot[2])
257 guard
.eq(round_bit
), # steal round_bit (was tot[1])
260 m
.next
= "normalize_2"
263 # Second stage of normalisation.
264 # NOTE: just like "align", this one keeps going round every clock
265 # until the result's exponent is within acceptable "range"
266 # NOTE: the weirdness of reassigning guard and round is due to
267 # the extra mantissa bits coming from tot[0..2]
269 with m
.State("normalise_2"):
270 with m
.If(z
.e
< -126):
272 z
.e
.eq(z
.e
+ 1), # INCREASE exponent
273 z
.m
.eq(z
.m
>> 1), # shift mantissa DOWN
276 sticky
.eq(sticky | round_bit
)
284 with m
.State("round"):
286 with m
.If(guard
& (round_bit | sticky | z
.m
[0])):
287 m
.d
.sync
+= z
.m
.eq(z
.m
+ 1) # mantissa rounds up
288 with m
.If(z
.m
== 0xffffff): # all 1s
289 m
.d
.sync
+= z
.e
.eq(z
.e
+ 1) # exponent rounds up
294 """ TODO: see if z.create can be used *later*. convert
295 verilog first (and commit), *second* phase, convert nmigen
296 code to use FPNum.create() (as a separate commit)
300 z[22 : 0] <= z_m[22:0];
301 z[30 : 23] <= z_e[7:0] + 127;
303 if ($signed(z_e) == -126 && z_m[23] == 0) begin
306 if ($signed(z_e) == -126 && z_m[23:0] == 24'h0) begin
307 z[31] <= 1'b0; // FIX SIGN BUG: -a + a = +0.
309 //if overflow occurs, return inf
310 if ($signed(z_e) > 127) begin
327 if (s_out_z_stb && out_z_ack) begin
337 always @(posedge clk)
345 if (s_in_a_ack && in_a_stb) begin
355 if (s_in_b_ack && in_b_stb) begin
364 a_m <= {a[22 : 0], 3'd0};
365 b_m <= {b[22 : 0], 3'd0};
366 a_e <= a[30 : 23] - 127;
367 b_e <= b[30 : 23] - 127;
370 state <= special_cases;
375 //if a is NaN or b is NaN return NaN
376 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
382 //if a is inf return inf
383 end else if (a_e == 128) begin
387 //if a is inf and signs don't match return nan
388 if ((b_e == 128) && (a_s != b_s)) begin
395 //if b is inf return inf
396 end else if (b_e == 128) begin
401 //if a is zero return b
402 end else if ((($signed(a_e) == -127) && (a_m == 0)) && (($signed(b_e) == -127) && (b_m == 0))) begin
404 z[30:23] <= b_e[7:0] + 127;
405 z[22:0] <= b_m[26:3];
407 //if a is zero return b
408 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
410 z[30:23] <= b_e[7:0] + 127;
411 z[22:0] <= b_m[26:3];
413 //if b is zero return a
414 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
416 z[30:23] <= a_e[7:0] + 127;
417 z[22:0] <= a_m[26:3];
420 //Denormalised Number
421 if ($signed(a_e) == -127) begin
426 //Denormalised Number
427 if ($signed(b_e) == -127) begin
438 if ($signed(a_e) > $signed(b_e)) begin
441 b_m[0] <= b_m[0] | b_m[1];
442 end else if ($signed(a_e) < $signed(b_e)) begin
445 a_m[0] <= a_m[0] | a_m[1];
454 if (a_s == b_s) begin
458 if (a_m >= b_m) begin
475 sticky <= tot[1] | tot[0];
483 state <= normalise_1;
488 if (z_m[23] == 0 && $signed(z_e) > -126) begin
495 state <= normalise_2;
501 if ($signed(z_e) < -126) begin
506 sticky <= sticky | round_bit;
514 if (guard && (round_bit | sticky | z_m[0])) begin
516 if (z_m == 24'hffffff) begin
525 z[22 : 0] <= z_m[22:0];
526 z[30 : 23] <= z_e[7:0] + 127;
528 if ($signed(z_e) == -126 && z_m[23] == 0) begin
531 if ($signed(z_e) == -126 && z_m[23:0] == 24'h0) begin
532 z[31] <= 1'b0; // FIX SIGN BUG: -a + a = +0.
534 //if overflow occurs, return inf
535 if ($signed(z_e) > 127) begin
547 if (s_out_z_stb && out_z_ack) begin
563 assign in_a_ack = s_in_a_ack;
564 assign in_b_ack = s_in_b_ack;
565 assign out_z_stb = s_out_z_stb;
566 assign out_z = s_out_z;
571 if __name__
== "__main__":
572 alu
= FPADD(width
=32)
574 alu
.in_a
, alu
.in_a_stb
, alu
.in_a_ack
,
575 alu
.in_b
, alu
.in_b_stb
, alu
.in_b_ack
,
576 alu
.out_z
, alu
.out_z_stb
, alu
.out_z_ack
,