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 def __init__(self
, width
):
13 self
.in_a
= Signal(width
)
14 self
.in_a_stb
= Signal()
15 self
.in_a_ack
= Signal()
17 self
.in_b
= Signal(width
)
18 self
.in_b_stb
= Signal()
19 self
.in_b_ack
= Signal()
21 self
.out_z
= Signal(width
)
22 self
.out_z_stb
= Signal()
23 self
.out_z_ack
= Signal()
25 s_out_z_stb
= Signal()
26 s_out_z
= Signal(width
)
30 def create_z(self
, z
, s
, e
, m
):
34 z
[0:23].eq(m
) # mantissa
37 def get_fragment(self
, platform
):
41 a
= Signal(self
.width
)
42 b
= Signal(self
.width
)
43 z
= Signal(self
.width
)
46 a_m
= Signal(27) # ??? seems to be 1 bit extra??
47 b_m
= Signal(27) # ??? seems to be 1 bit extra??
50 # Exponent: 10 bits, signed (the exponent bias is subtracted)
51 a_e
= Signal((10, True))
52 b_e
= Signal((10, True))
53 z_e
= Signal((10, True))
71 with m
.State("get_a"):
72 with m
.If((self
.in_a_ack
) & (self
.in_a_stb
)):
79 m
.d
.sync
+= self
.in_a_ack
.eq(1)
84 with m
.State("get_b"):
85 with m
.If((self
.in_b_ack
) & (self
.in_b_stb
)):
92 m
.d
.sync
+= self
.in_b_ack
.eq(1)
95 # unpacks operands into sign, mantissa and exponent
97 with m
.State("unpack"):
98 m
.next
= "special_cases"
101 a_m
.eq(Cat(0, 0, 0, a
[0:23])),
102 b_m
.eq(Cat(0, 0, 0, b
[0:23])),
103 # exponent (take off exponent bias, here)
104 a_e
.eq(Cat(a
[23:31]) - 127),
105 b_e
.eq(Cat(b
[23:31]) - 127),
112 # special cases: NaNs, infs, zeros, denormalised
114 with m
.State("special_cases"):
116 # if a is NaN or b is NaN return NaN
117 with m
.If(((a_e
== 128) & (a_m
!= 0)) | \
118 ((b_e
== 128) & (b_m
!= 0))):
120 m
.d
.sync
+= self
.create_z(z
, 1, 255, 1<<22)
122 # if a is inf return inf (or NaN)
123 with m
.Elif(a_e
== 128):
125 m
.d
.sync
+= self
.create_z(z
, a_s
, 255, 0)
126 # if a is inf and signs don't match return NaN
127 with m
.If((b_e
== 128) & (a_s
!= b_s
)):
128 m
.d
.sync
+= self
.create_z(z
, b_s
, 255, 1<<22)
130 # if b is inf return inf
131 with m
.Elif(b_e
== 128):
133 m
.d
.sync
+= self
.create_z(z
, b_s
, 255, 0)
135 # if a is zero and b zero return signed-a/b
136 with m
.Elif(((a_e
== -127) & (a_m
== 0)) & \
137 ((b_e
== -127) & (b_m
== 0))):
139 m
.d
.sync
+= self
.create_z(z
, a_s
& b_s
,
143 # if a is zero return b
144 with m
.Elif((a_e
== -127) & (a_m
== 0)):
146 m
.d
.sync
+= self
.create_z(z
, b_s
,
150 # if b is zero return a
151 with m
.Elif((b_e
== -127) & (b_m
== 0)):
153 m
.d
.sync
+= self
.create_z(z
, a_s
,
157 # Denormalised Number checks
160 # denormalise a check
161 with m
.If(a_e
== -127):
162 m
.d
.sync
+= a_e
.eq(-126) # limit a exponent
164 m
.d
.sync
+= a_m
[26].eq(1) # set highest mantissa bit
165 # denormalise b check
166 with m
.If(b_e
== -127):
167 m
.d
.sync
+= b_e
.eq(-126) # limit b exponent
169 m
.d
.sync
+= b_m
[26].eq(1) # set highest mantissa bit
172 # align. NOTE: this does *not* do single-cycle multi-shifting,
173 # it *STAYS* in the align state until the exponents match
175 with m
.State("align"):
176 # exponent of a greater than b: increment b exp, shift b mant
177 with m
.If(a_e
> b_e
):
181 b_m
[0].eq(b_m
[0] | b_m
[1]) # moo??
183 # exponent of b greater than a: increment a exp, shift a mant
184 with m
.Elif(a_e
< b_e
):
188 a_m
[0].eq(a_m
[0] | a_m
[1]) # moo??
190 # exponents equal: move to next stage.
197 with m
.State("add_0"):
199 m
.d
.sync
+= z_e
.eq(a_e
)
200 # same-sign (both negative or both positive) add mantissas
201 with m
.If(a_s
== b_s
):
206 # a mantissa greater than b, use a
207 with m
.Elif(a_m
>= b_m
):
212 # b mantissa greater than a, use b
220 # Second stage of add: preparation for normalisation
222 with m
.State("add_1"):
223 m
.next
= "normalise_1"
224 # tot[27] gets set when the sum overflows. shift result down
229 round_bit
.eq(tot
[2]),
230 sticky
.eq(tot
[1] | tot
[0]),
238 round_bit
.eq(tot
[1]),
244 always @(posedge clk)
252 if (s_in_a_ack && in_a_stb) begin
262 if (s_in_b_ack && in_b_stb) begin
271 a_m <= {a[22 : 0], 3'd0};
272 b_m <= {b[22 : 0], 3'd0};
273 a_e <= a[30 : 23] - 127;
274 b_e <= b[30 : 23] - 127;
277 state <= special_cases;
282 //if a is NaN or b is NaN return NaN
283 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
289 //if a is inf return inf
290 end else if (a_e == 128) begin
294 //if a is inf and signs don't match return nan
295 if ((b_e == 128) && (a_s != b_s)) begin
302 //if b is inf return inf
303 end else if (b_e == 128) begin
308 //if a is zero return b
309 end else if ((($signed(a_e) == -127) && (a_m == 0)) && (($signed(b_e) == -127) && (b_m == 0))) begin
311 z[30:23] <= b_e[7:0] + 127;
312 z[22:0] <= b_m[26:3];
314 //if a is zero return b
315 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
317 z[30:23] <= b_e[7:0] + 127;
318 z[22:0] <= b_m[26:3];
320 //if b is zero return a
321 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
323 z[30:23] <= a_e[7:0] + 127;
324 z[22:0] <= a_m[26:3];
327 //Denormalised Number
328 if ($signed(a_e) == -127) begin
333 //Denormalised Number
334 if ($signed(b_e) == -127) begin
345 if ($signed(a_e) > $signed(b_e)) begin
348 b_m[0] <= b_m[0] | b_m[1];
349 end else if ($signed(a_e) < $signed(b_e)) begin
352 a_m[0] <= a_m[0] | a_m[1];
361 if (a_s == b_s) begin
365 if (a_m >= b_m) begin
382 sticky <= tot[1] | tot[0];
390 state <= normalise_1;
395 if (z_m[23] == 0 && $signed(z_e) > -126) begin
402 state <= normalise_2;
408 if ($signed(z_e) < -126) begin
413 sticky <= sticky | round_bit;
421 if (guard && (round_bit | sticky | z_m[0])) begin
423 if (z_m == 24'hffffff) begin
432 z[22 : 0] <= z_m[22:0];
433 z[30 : 23] <= z_e[7:0] + 127;
435 if ($signed(z_e) == -126 && z_m[23] == 0) begin
438 if ($signed(z_e) == -126 && z_m[23:0] == 24'h0) begin
439 z[31] <= 1'b0; // FIX SIGN BUG: -a + a = +0.
441 //if overflow occurs, return inf
442 if ($signed(z_e) > 127) begin
454 if (s_out_z_stb && out_z_ack) begin
470 assign in_a_ack = s_in_a_ack;
471 assign in_b_ack = s_in_b_ack;
472 assign out_z_stb = s_out_z_stb;
473 assign out_z = s_out_z;
478 if __name__
== "__main__":
479 alu
= FPADD(width
=32)
481 alu
.in_a
, alu
.in_a_stb
, alu
.in_a_ack
,
482 alu
.in_b
, alu
.in_b_stb
, alu
.in_b_ack
,
483 alu
.out_z
, alu
.out_z_stb
, alu
.out_z_ack
,