X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fieee754%2Fpart_mul_add%2Fadder.py;h=e1849b4d25fc5ec4fc4473cc02b32f49dd5912b2;hb=77f150cff440bed025e2487b6f0fcda9f529290b;hp=ebcbe75e12594078082e1ae48580b9fa5977115f;hpb=2ba745c5fb2ef27f65a5720a1323386c237e44b9;p=ieee754fpu.git diff --git a/src/ieee754/part_mul_add/adder.py b/src/ieee754/part_mul_add/adder.py index ebcbe75e..e1849b4d 100644 --- a/src/ieee754/part_mul_add/adder.py +++ b/src/ieee754/part_mul_add/adder.py @@ -113,6 +113,7 @@ class PartitionedAdder(Elaboratable): to the next bit. Then the final output *removes* the extra bits from the result. + In the case of no carry: partition: .... P... P... P... P... (32 bits) a : .... .... .... .... .... (32 bits) b : .... .... .... .... .... (32 bits) @@ -121,17 +122,39 @@ class PartitionedAdder(Elaboratable): exp-o : ....xN...xN...xN...xN... (32+4 bits - x to be discarded) o : .... N... N... N... N... (32 bits - x ignored, N is carry-over) + However, with carry the behavior is a little different: partition: p p p p (4 bits) - carry-in : c c c c (4 bits) - C = c & P: C C C c (4 bits) - I = P=>c : I I I I (4 bits) + carry-in : c c c c c (5 bits) + C = c & P: C C C C c (5 bits) + I = P=>c : I I I I c (5 bits) a : AAAA AAAA AAAA AAAA AAAA (32 bits) b : BBBB BBBB BBBB BBBB BBBB (32 bits) - exp-a : 0AAAApAAAACAAAACAAAACAAAAc (32+4 bits, P=1 if no partition) - exp-b : 0BBBB0BBBBIBBBBIBBBBIBBBBI (32 bits plus 4 zeros) - exp-o : o....oN...oN...oN...oN...x (32+4 bits - x to be discarded) + exp-a : 0AAAACAAAACAAAACAAAACAAAAc (32+4+2 bits, P=1 if no partition) + exp-b : 0BBBBIBBBBIBBBBIBBBBIBBBBc (32+2 bits plus 4 zeros) + exp-o : o....oN...oN...oN...oN...x (32+4+2 bits - x to be discarded) o : .... N... N... N... N... (32 bits - x ignored, N is carry-over) - carry-out: o o o o (4 bits) + carry-out: o o o o o (5 bits) + + A couple of differences should be noted: + - The expanded a/b/o have 2 extra bits added to them. These bits + allow the carry-in for the least significant partition to be + injected, and the carry out for the most significant partition + to be extracted. + - The partition bits P and 0 in the first example have been + replaced with bits C and I. Bits C and I are set to 1 when + there is a partition and a carry-in at that position. This has + the effect of creating a carry at that position in the expanded + adder, while preventing carries from the previous partition + from propogating through to the next. These bits are also used + to extract the carry-out information for each partition, as + when there is a carry out in a partition, the next most + significant partition bit will be set to 1 + + Additionally, the carry-out bits must be rearranged before being + output to move the most significant carry bit for each partition + into the least significant bit for that partition, as well as to + ignore the other carry bits in that partition. This is + accomplished by the MoveMSBDown module :attribute width: the bit width of the input and output. Read-only. :attribute a: the first input to the adder @@ -238,8 +261,13 @@ class PartitionedAdder(Elaboratable): # special hardware on FPGAs comb += expanded_o.eq(expanded_a + expanded_b) + # ok now we have the carry-out, however because it's the MSB it's + # in the wrong position in the output as far as putting it into + # a chain of adds (or other operations). therefore we need to + # "ripple" carry-out down to the same position that carry-in is + # in [the LSB of each partition]. comb += ripple.results_in.eq(carry_tmp) comb += ripple.gates.eq(self.part_pts.as_sig()) - comb += self.carry_out.eq(ripple.output) + m.d.sync += self.carry_out.eq(ripple.output) return m