aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/common
diff options
context:
space:
mode:
authorEddie Hung <eddie@fpgeh.com>2019-07-31 15:45:41 -0700
committerEddie Hung <eddie@fpgeh.com>2019-07-31 15:45:41 -0700
commit60c4887d15f89499d351fe9bd9ed36a5a4c1fe37 (patch)
treee12cd8484bbb9c56b78084a67b10194965837f7e /techlibs/common
parente4a638c29297e3e8b915cf84a2dddc339f511476 (diff)
downloadyosys-60c4887d15f89499d351fe9bd9ed36a5a4c1fe37.tar.gz
yosys-60c4887d15f89499d351fe9bd9ed36a5a4c1fe37.tar.bz2
yosys-60c4887d15f89499d351fe9bd9ed36a5a4c1fe37.zip
For signed multipliers, compute sign bit separately...
Diffstat (limited to 'techlibs/common')
-rw-r--r--techlibs/common/mul2dsp.v65
1 files changed, 42 insertions, 23 deletions
diff --git a/techlibs/common/mul2dsp.v b/techlibs/common/mul2dsp.v
index 678de3796..b745547a8 100644
--- a/techlibs/common/mul2dsp.v
+++ b/techlibs/common/mul2dsp.v
@@ -54,8 +54,22 @@ module \$mul (A, B, Y);
generate
if (A_SIGNED != B_SIGNED || A_WIDTH <= 1 || B_WIDTH <= 1)
wire _TECHMAP_FAIL_ = 1;
- // NB: A_SIGNED == B_SIGNED == 0 from here
- else if (A_WIDTH >= B_WIDTH)
+ // NB: A_SIGNED == B_SIGNED from here
+ else if (A_WIDTH < B_WIDTH)
+ \$mul #(
+ .A_SIGNED(B_SIGNED),
+ .B_SIGNED(A_SIGNED),
+ .A_WIDTH(B_WIDTH),
+ .B_WIDTH(A_WIDTH),
+ .Y_WIDTH(Y_WIDTH)
+ ) _TECHMAP_REPLACE_ (
+ .A(B),
+ .B(A),
+ .Y(Y)
+ );
+ else if (A_SIGNED && (A_WIDTH > `DSP_A_MAXWIDTH || B_WIDTH > `DSP_B_MAXWIDTH)) begin
+ wire _;
+ assign Y[Y_WIDTH-1] = A[A_WIDTH-1] ^ B[B_WIDTH-1];
\$__mul #(
.A_SIGNED(A_SIGNED),
.B_SIGNED(B_SIGNED),
@@ -65,18 +79,19 @@ module \$mul (A, B, Y);
) _TECHMAP_REPLACE_ (
.A(A),
.B(B),
- .Y(Y)
+ .Y({_,Y[Y_WIDTH-2:0]})
);
+ end
else
\$__mul #(
- .A_SIGNED(B_SIGNED),
- .B_SIGNED(A_SIGNED),
- .A_WIDTH(B_WIDTH),
- .B_WIDTH(A_WIDTH),
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(B_WIDTH),
.Y_WIDTH(Y_WIDTH)
) _TECHMAP_REPLACE_ (
- .A(B),
- .B(A),
+ .A(A),
+ .B(B),
.Y(Y)
);
endgenerate
@@ -209,23 +224,27 @@ module \$__mul (A, B, Y);
.B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}),
.Y(partial[i])
);
- // TODO: Currently a 'cascade' approach to summing the partial
- // products is taken here, but a more efficient 'binary
- // reduction' approach also exists...
+ // TODO: Currently a 'cascade' approach to summing the partial
+ // products is taken here, but a more efficient 'binary
+ // reduction' approach also exists...
assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[i-1];
end
- \$__mul #(
- .A_SIGNED(A_SIGNED),
- .B_SIGNED(B_SIGNED),
- .A_WIDTH(A_WIDTH),
- .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom)),
- .Y_WIDTH(last_Y_WIDTH)
- ) mul_last (
- .A(A),
- .B(B[B_WIDTH-1 : (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)]),
- .Y(last_partial)
- );
+ localparam last_B_WIDTH = B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH-sign_headroom);
+ if (A_SIGNED && B_SIGNED && last_B_WIDTH == 1)
+ assign last_partial = 0;
+ else
+ \$__mul #(
+ .A_SIGNED(A_SIGNED),
+ .B_SIGNED(B_SIGNED),
+ .A_WIDTH(A_WIDTH),
+ .B_WIDTH(last_B_WIDTH),
+ .Y_WIDTH(last_Y_WIDTH)
+ ) mul_last (
+ .A(A),
+ .B(B[B_WIDTH-1 -: last_B_WIDTH]),
+ .Y(last_partial)
+ );
assign partial_sum[n-1] = (last_partial << (n-1)*(`DSP_B_MAXWIDTH-sign_headroom)) + partial_sum[n-2];
assign Y = partial_sum[n-1];
end