mul2dsp: Lower partial products always have unsigned inputs
authorDavid Shah <dave@ds0.me>
Thu, 18 Jul 2019 10:33:37 +0000 (11:33 +0100)
committerDavid Shah <dave@ds0.me>
Thu, 18 Jul 2019 10:33:37 +0000 (11:33 +0100)
Signed-off-by: David Shah <dave@ds0.me>
techlibs/common/mul2dsp.v

index 7344bc5fefe1f2017c3e90cc91dfc0c608c46a4d..31469ddeb30c8d4a24c303de6a2d4249ee94d58a 100644 (file)
@@ -92,20 +92,25 @@ module \$__mul_gen (A, B, Y);
        genvar i;\r
        generate\r
                if (A_WIDTH > `DSP_A_MAXWIDTH) begin\r
-                       localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH;\r
-                       localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0);\r
+`ifdef DSP_A_SIGNEDONLY\r
+                       localparam sign_headroom = 1;\r
+`else  \r
+                       localparam sign_headroom = 0;\r
+`endif\r
+                       localparam n_floored = A_WIDTH/(`DSP_A_MAXWIDTH - sign_headroom);\r
+                       localparam n = n_floored + (n_floored*(`DSP_A_MAXWIDTH - sign_headroom) < A_WIDTH ? 1 : 0);\r
                        wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1];\r
                        wire [Y_WIDTH-1:0] partial_sum [n-2:0];\r
                        localparam int_yw = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH);\r
 \r
                        \$__mul_gen #(\r
-                               .A_SIGNED(A_SIGNED),\r
+                               .A_SIGNED(0),\r
                                .B_SIGNED(B_SIGNED),\r
                                .A_WIDTH(`DSP_A_MAXWIDTH),\r
                                .B_WIDTH(B_WIDTH),\r
                                .Y_WIDTH(int_yw)\r
                        ) mul_slice_first (\r
-                               .A(A[`DSP_A_MAXWIDTH-1:0]),\r
+                               .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1:0]}),\r
                                .B(B),\r
                                .Y(partial_sum[0][int_yw-1:0])\r
                        );\r
@@ -114,73 +119,78 @@ module \$__mul_gen (A, B, Y);
 \r
                        for (i = 1; i < n-1; i=i+1) begin:slice\r
                                \$__mul_gen #(\r
-                                       .A_SIGNED(A_SIGNED),\r
+                                       .A_SIGNED(0),\r
                                        .B_SIGNED(B_SIGNED),\r
                                        .A_WIDTH(`DSP_A_MAXWIDTH),\r
                                        .B_WIDTH(B_WIDTH),\r
                                        .Y_WIDTH(int_yw)\r
                                ) mul_slice (\r
-                                       .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]),\r
+                                       .A({{sign_headroom{1'b0}}, A[(i+1)*(`DSP_A_MAXWIDTH-sign_headroom)-1:i*(`DSP_A_MAXWIDTH-sign_headroom)]}),\r
                                        .B(B),\r
                                        .Y(partial[i][int_yw-1:0])\r
                                );\r
                                //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1];\r
                                assign partial_sum[i] = {\r
                                        partial[i][int_yw-1:0]\r
-                                       + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_A_MAXWIDTH)],\r
-                                       partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0]\r
+                                       + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_A_MAXWIDTH-sign_headroom))],\r
+                                       partial_sum[i-1][(i*(`DSP_A_MAXWIDTH-sign_headroom))-1:0]\r
                                };\r
                        end\r
 \r
                        \$__mul_gen #(\r
                                .A_SIGNED(A_SIGNED),\r
                                .B_SIGNED(B_SIGNED),\r
-                               .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH),\r
+                               .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)),\r
                                .B_WIDTH(B_WIDTH),\r
-                               .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)),\r
+                               .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)),\r
                        ) mul_slice_last (\r
-                               .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]),\r
+                               .A(A[A_WIDTH-1:(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]),\r
                                .B(B),\r
-                               .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH)-1:0])\r
+                               .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH)-1:0])\r
                        );\r
                        //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2];\r
                        assign Y = {\r
-                               partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH):0]\r
-                               + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_A_MAXWIDTH)],\r
-                               partial_sum[n-2][((n-1)*`DSP_A_MAXWIDTH)-1:0]\r
+                               partial[n-1][`MIN(Y_WIDTH, A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)+B_WIDTH):0]\r
+                               + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))],\r
+                               partial_sum[n-2][((n-1)*(`DSP_A_MAXWIDTH-sign_headroom))-1:0]\r
                        };\r
                end\r
                else if (B_WIDTH > `DSP_B_MAXWIDTH) begin\r
-                       localparam n_floored = B_WIDTH/`DSP_B_MAXWIDTH;\r
-                       localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0);\r
+`ifdef DSP_B_SIGNEDONLY\r
+                       localparam sign_headroom = 1;\r
+`else  \r
+                       localparam sign_headroom = 0;\r
+`endif\r
+                       localparam n_floored = B_WIDTH/(`DSP_B_MAXWIDTH - sign_headroom);\r
+                       localparam n = n_floored + (n_floored*(`DSP_B_MAXWIDTH - sign_headroom) < B_WIDTH ? 1 : 0);\r
                        wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1];\r
                        wire [Y_WIDTH-1:0] partial_sum [n-2:0];\r
                        localparam int_yw = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH);\r
 \r
                        \$__mul_gen #(\r
                                .A_SIGNED(A_SIGNED),\r
-                               .B_SIGNED(B_SIGNED),\r
+                               .B_SIGNED(0),\r
                                .A_WIDTH(A_WIDTH),\r
                                .B_WIDTH(`DSP_B_MAXWIDTH),\r
                                .Y_WIDTH(int_yw)\r
                        ) mul_first (\r
                                .A(A),\r
-                               .B(B[`DSP_B_MAXWIDTH-1:0]),\r
+                               .B({{sign_headroom{1'b0}}, B[(`DSP_B_MAXWIDTH - sign_headroom)-1:0]}),\r
                                .Y(partial_sum[0][int_yw-1:0])\r
                        );\r
                        if (Y_WIDTH > int_yw)\r
-                               assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0;\r
+                               assign partial_sum[0][Y_WIDTH-1:int_yw]=0;\r
 \r
                        for (i = 1; i < n-1; i=i+1) begin:slice\r
                                \$__mul_gen #(\r
                                        .A_SIGNED(A_SIGNED),\r
-                                       .B_SIGNED(B_SIGNED),\r
+                                       .B_SIGNED(0),\r
                                        .A_WIDTH(A_WIDTH),\r
                                        .B_WIDTH(`DSP_B_MAXWIDTH),\r
                                        .Y_WIDTH(int_yw)\r
                                ) mul (\r
                                        .A(A),\r
-                                       .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]),\r
+                                       .B({{sign_headroom{1'b0}}, B[(i+1)*(`DSP_B_MAXWIDTH - sign_headroom)-1:i*(`DSP_B_MAXWIDTH - sign_headroom)]}),\r
                                        .Y(partial[i][int_yw-1:0])\r
                                );\r
                                //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1];\r
@@ -191,8 +201,8 @@ module \$__mul_gen (A, B, Y);
                                //      partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0]\r
                                assign partial_sum[i] = {\r
                                        partial[i][int_yw-1:0]\r
-                                       + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_B_MAXWIDTH)],\r
-                                       partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0] \r
+                                       + partial_sum[i-1][Y_WIDTH-1:(i*(`DSP_B_MAXWIDTH - sign_headroom))],\r
+                                       partial_sum[i-1][(i*(`DSP_B_MAXWIDTH - sign_headroom))-1:0] \r
                                };\r
                        end\r
 \r
@@ -200,12 +210,12 @@ module \$__mul_gen (A, B, Y);
                                .A_SIGNED(A_SIGNED),\r
                                .B_SIGNED(B_SIGNED),\r
                                .A_WIDTH(A_WIDTH),\r
-                               .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH),\r
-                               .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH))\r
+                               .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)),\r
+                               .Y_WIDTH(`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)))\r
                        ) mul_last (\r
                                .A(A),\r
-                               .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]),\r
-                               .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0])\r
+                               .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]),\r
+                               .Y(partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0])\r
                        );\r
                        // AMD: this came comment out -- looks closer to right answer\r
                        //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2];\r
@@ -215,9 +225,9 @@ module \$__mul_gen (A, B, Y);
                        //      partial[n-1][`DSP_B_MAXWIDTH-1:0] + partial_sum[n-2][A_WIDTH+((n-1)*`DSP_B_MAXWIDTH)-1:A_WIDTH+((n-2)*`DSP_B_MAXWIDTH)],\r
                        //      partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0]\r
                        assign Y = {\r
-                               partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)-1:0]\r
-                               + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)],\r
-                               partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0]\r
+                               partial[n-1][`MIN(Y_WIDTH, A_WIDTH+B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0]\r
+                               + partial_sum[n-2][Y_WIDTH-1:((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))],\r
+                               partial_sum[n-2][((n-1)*(`DSP_B_MAXWIDTH - sign_headroom))-1:0]\r
                        };\r
                end\r
                else begin \r