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 get_fragment(self
, platform
):
34 a
= Signal(self
.width
)
35 b
= Signal(self
.width
)
36 z
= Signal(self
.width
)
39 a_m
= Signal(27) # ??? seems to be 1 bit extra??
40 b_m
= Signal(27) # ??? seems to be 1 bit extra??
43 # Exponent: 10 bits, signed (the exponent bias is subtracted)
44 a_e
= Signal((10, True))
45 b_e
= Signal((10, True))
46 z_e
= Signal((10, True))
64 with m
.State("get_a"):
65 with m
.If((self
.in_a_ack
) & (self
.in_a_stb
)):
72 m
.d
.sync
+= self
.in_a_ack
.eq(1)
77 with m
.State("get_b"):
78 with m
.If((self
.in_b_ack
) & (self
.in_b_stb
)):
85 m
.d
.sync
+= self
.in_b_ack
.eq(1)
88 # unpacks operands into sign, mantissa and exponent
90 with m
.State("unpack"):
91 m
.next
= "special_cases"
94 a_m
.eq(Cat(0, 0, 0, a
[0:23])),
95 b_m
.eq(Cat(0, 0, 0, b
[0:23])),
96 # exponent (take off exponent bias, here)
97 a_e
.eq(Cat(a
[23:31]) - 127),
98 b_e
.eq(Cat(b
[23:31]) - 127),
105 # special cases: NaNs, infs, zeros, denormalised
107 with m
.State("special_cases"):
109 # if a is NaN or b is NaN return NaN
110 with m
.If(((a_e
== 128) & (a_m
!= 0)) | \
111 ((b_e
== 128) & (b_m
!= 0))):
114 z
[31].eq(1), # sign: 1
115 z
[23:31].eq(255), # exp: 0b11111...
116 z
[22].eq(1), # mantissa top bit: 1
117 z
[0:22].eq(0) # mantissa rest: 0b0000...
120 # if a is inf return inf (or NaN)
121 with m
.Elif(a_e
== 128):
124 z
[31].eq(a_s
), # sign: a_s
125 z
[23:31].eq(255), # exp: 0b11111...
126 z
[0:23].eq(0) # mantissa rest: 0b0000...
128 # if a is inf and signs don't match return NaN
129 with m
.If((b_e
== 128) & (a_s
!= b_s
)):
131 z
[31].eq(b_s
), # sign: b_s
132 z
[23:31].eq(255), # exp: 0b11111...
133 z
[22].eq(1), # mantissa top bit: 1
134 z
[0:22].eq(0) # mantissa rest: 0b0000...
136 # if b is inf return inf
137 with m
.Elif(b_e
== 128):
140 z
[31].eq(b_s
), # sign: b_s
141 z
[23:31].eq(255), # exp: 0b11111...
142 z
[0:23].eq(0) # mantissa rest: 0b0000...
145 # if a is zero and b zero return signed-a/b
146 with m
.Elif(((a_e
== -127) & (a_m
== 0)) & \
147 ((b_e
== -127) & (b_m
== 0))):
150 z
[31].eq(a_s
& b_s
), # sign: a/b_s
151 z
[23:31].eq(b_e
[0:8] + 127), # exp: b_e (plus bias)
152 z
[0:23].eq(b_m
[3:26]) # mantissa: b_m top bits
155 # if a is zero return b
156 with m
.Elif((a_e
== -127) & (a_m
== 0)):
159 z
[31].eq(b_s
), # sign: a/b_s
160 z
[23:31].eq(b_e
[0:8] + 127), # exp: b_e (plus bias)
161 z
[0:23].eq(b_m
[3:26]) # mantissa: b_m top bits
164 # if b is zero return a
165 with m
.Elif((b_e
== -127) & (b_m
== 0)):
168 z
[31].eq(a_s
), # sign: a/b_s
169 z
[23:31].eq(a_e
[0:8] + 127), # exp: a_e (plus bias)
170 z
[0:23].eq(a_m
[3:26]) # mantissa: a_m top bits
173 # Denormalised Number checks
176 # denormalise a check
177 with m
.If(a_e
== -127):
178 m
.d
.sync
+= a_e
.eq(-126) # limit a exponent
180 m
.d
.sync
+= a_m
[26].eq(1) # set highest mantissa bit
181 # denormalise b check
182 with m
.If(b_e
== -127):
183 m
.d
.sync
+= b_e
.eq(-126) # limit b exponent
185 m
.d
.sync
+= b_m
[26].eq(1) # set highest mantissa bit
188 # align. NOTE: this does *not* do single-cycle multi-shifting,
189 # it *STAYS* in the align state until the exponents match
191 with m
.State("align"):
192 # exponent of a greater than b: increment b exp, shift b mant
193 with m
.If(a_e
> b_e
):
197 b_m
[0].eq(b_m
[0] | b_m
[1]) # moo??
199 # exponent of b greater than a: increment a exp, shift a mant
200 with m
.Elif(a_e
< b_e
):
204 a_m
[0].eq(a_m
[0] | a_m
[1]) # moo??
206 # exponents equal: move to next stage.
213 with m
.State("add_0"):
215 m
.d
.sync
+= z_e
.eq(a_e
)
216 # same-sign (both negative or both positive) add mantissas
217 with m
.If(a_s
== b_s
):
222 # a mantissa greater than b, use a
223 with m
.Else(a_m
>= b_m
):
228 # b mantissa greater than a, use b
237 always @(posedge clk)
245 if (s_in_a_ack && in_a_stb) begin
255 if (s_in_b_ack && in_b_stb) begin
264 a_m <= {a[22 : 0], 3'd0};
265 b_m <= {b[22 : 0], 3'd0};
266 a_e <= a[30 : 23] - 127;
267 b_e <= b[30 : 23] - 127;
270 state <= special_cases;
275 //if a is NaN or b is NaN return NaN
276 if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
282 //if a is inf return inf
283 end else if (a_e == 128) begin
287 //if a is inf and signs don't match return nan
288 if ((b_e == 128) && (a_s != b_s)) begin
295 //if b is inf return inf
296 end else if (b_e == 128) begin
301 //if a is zero return b
302 end else if ((($signed(a_e) == -127) && (a_m == 0)) && (($signed(b_e) == -127) && (b_m == 0))) begin
304 z[30:23] <= b_e[7:0] + 127;
305 z[22:0] <= b_m[26:3];
307 //if a is zero return b
308 end else if (($signed(a_e) == -127) && (a_m == 0)) begin
310 z[30:23] <= b_e[7:0] + 127;
311 z[22:0] <= b_m[26:3];
313 //if b is zero return a
314 end else if (($signed(b_e) == -127) && (b_m == 0)) begin
316 z[30:23] <= a_e[7:0] + 127;
317 z[22:0] <= a_m[26:3];
320 //Denormalised Number
321 if ($signed(a_e) == -127) begin
326 //Denormalised Number
327 if ($signed(b_e) == -127) begin
338 if ($signed(a_e) > $signed(b_e)) begin
341 b_m[0] <= b_m[0] | b_m[1];
342 end else if ($signed(a_e) < $signed(b_e)) begin
345 a_m[0] <= a_m[0] | a_m[1];
354 if (a_s == b_s) begin
358 if (a_m >= b_m) begin
375 sticky <= tot[1] | tot[0];
383 state <= normalise_1;
388 if (z_m[23] == 0 && $signed(z_e) > -126) begin
395 state <= normalise_2;
401 if ($signed(z_e) < -126) begin
406 sticky <= sticky | round_bit;
414 if (guard && (round_bit | sticky | z_m[0])) begin
416 if (z_m == 24'hffffff) begin
425 z[22 : 0] <= z_m[22:0];
426 z[30 : 23] <= z_e[7:0] + 127;
428 if ($signed(z_e) == -126 && z_m[23] == 0) begin
431 if ($signed(z_e) == -126 && z_m[23:0] == 24'h0) begin
432 z[31] <= 1'b0; // FIX SIGN BUG: -a + a = +0.
434 //if overflow occurs, return inf
435 if ($signed(z_e) > 127) begin
447 if (s_out_z_stb && out_z_ack) begin
463 assign in_a_ack = s_in_a_ack;
464 assign in_b_ack = s_in_b_ack;
465 assign out_z_stb = s_out_z_stb;
466 assign out_z = s_out_z;
471 if __name__
== "__main__":
472 alu
= FPADD(width
=32)
474 alu
.in_a
, alu
.in_a_stb
, alu
.in_a_ack
,
475 alu
.in_b
, alu
.in_b_stb
, alu
.in_b_ack
,
476 alu
.out_z
, alu
.out_z_stb
, alu
.out_z_ack
,