2 // extracted from: https://github.com/eddiehung/vtr-with-yosys/blob/vtr7-with-yosys/vtr_flow/misc/yosys_models.v#L220
3 // revised by Andre DeHon
4 // further revised by David Shah
6 `define DSP_A_MAXWIDTH 18
9 `define DSP_B_MAXWIDTH 25
12 `ifndef ADDER_MINWIDTH
13 `define ADDER_MINWIDTH AAA
17 `define DSP_NAME M18x25
20 `define MAX(a,b) (a > b ? a : b)
21 `define MIN(a,b) (a < b ? a : b)
23 (* techmap_celltype = "$mul" *)
24 module \$mul (A, B, Y);
25 parameter A_SIGNED = 0;
26 parameter B_SIGNED = 0;
27 parameter A_WIDTH = 1;
28 parameter B_WIDTH = 1;
29 parameter Y_WIDTH = 1;
31 input [A_WIDTH-1:0] A;
32 input [B_WIDTH-1:0] B;
33 output [Y_WIDTH-1:0] Y;
36 if (B_WIDTH < A_WIDTH)
63 module \$__mul_gen (A, B, Y);
64 parameter A_SIGNED = 0;
65 parameter B_SIGNED = 0;
66 parameter A_WIDTH = 1;
67 parameter B_WIDTH = 1;
68 parameter Y_WIDTH = 1;
70 input [A_WIDTH-1:0] A;
71 input [B_WIDTH-1:0] B;
72 output [Y_WIDTH-1:0] Y;
74 wire [1023:0] _TECHMAP_DO_ = "proc; clean";
78 if (A_WIDTH > `DSP_A_MAXWIDTH) begin
79 localparam n_floored = A_WIDTH/`DSP_A_MAXWIDTH;
80 localparam n = n_floored + (n_floored*`DSP_A_MAXWIDTH < A_WIDTH ? 1 : 0);
81 wire [`DSP_A_MAXWIDTH+B_WIDTH-1:0] partial [n-1:1];
82 wire [Y_WIDTH-1:0] partial_sum [n-2:0];
87 .A_WIDTH(`DSP_A_MAXWIDTH),
89 .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH)
91 .A(A[`DSP_A_MAXWIDTH-1:0]),
93 .Y(partial_sum[0][B_WIDTH+`DSP_A_MAXWIDTH-1:0])
95 assign partial_sum[0][Y_WIDTH-1:B_WIDTH+`DSP_A_MAXWIDTH]=0;
97 for (i = 1; i < n-1; i=i+1) begin:slice
101 .A_WIDTH(`DSP_A_MAXWIDTH),
103 .Y_WIDTH(B_WIDTH+`DSP_A_MAXWIDTH)
105 .A(A[(i+1)*`DSP_A_MAXWIDTH-1:i*`DSP_A_MAXWIDTH]),
107 .Y(partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0])
109 //assign partial_sum[i] = (partial[i] << i*`DSP_A_MAXWIDTH) + partial_sum[i-1];
110 assign partial_sum[i] = {
111 partial[i][B_WIDTH+`DSP_A_MAXWIDTH-1:0]
112 + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_A_MAXWIDTH)],
113 partial_sum[i-1][(i*`DSP_A_MAXWIDTH)-1:0]
120 .A_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH),
122 .Y_WIDTH(A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH),
124 .A(A[A_WIDTH-1:(n-1)*`DSP_A_MAXWIDTH]),
126 .Y(partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH-1:0])
128 //assign Y = (partial[n-1] << (n-1)*`DSP_A_MAXWIDTH) + partial_sum[n-2];
130 partial[n-1][A_WIDTH-(n-1)*`DSP_A_MAXWIDTH+B_WIDTH:0]
131 + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_A_MAXWIDTH)],
132 partial_sum[n-2][((n-1)*`DSP_A_MAXWIDTH)-1:0]
135 else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
136 localparam n_floored = B_WIDTH/`DSP_B_MAXWIDTH;
137 localparam n = n_floored + (n_floored*`DSP_B_MAXWIDTH < B_WIDTH ? 1 : 0);
138 wire [A_WIDTH+`DSP_B_MAXWIDTH-1:0] partial [n-1:1];
139 wire [Y_WIDTH-1:0] partial_sum [n-2:0];
145 .B_WIDTH(`DSP_B_MAXWIDTH),
146 .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH)
149 .B(B[`DSP_B_MAXWIDTH-1:0]),
150 .Y(partial_sum[0][A_WIDTH+`DSP_B_MAXWIDTH-1:0])
152 assign partial_sum[0][Y_WIDTH-1:A_WIDTH+`DSP_B_MAXWIDTH]=0;
154 for (i = 1; i < n-1; i=i+1) begin:slice
159 .B_WIDTH(`DSP_B_MAXWIDTH),
160 .Y_WIDTH(A_WIDTH+`DSP_B_MAXWIDTH)
163 .B(B[(i+1)*`DSP_B_MAXWIDTH-1:i*`DSP_B_MAXWIDTH]),
164 .Y(partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0])
166 //assign partial_sum[i] = (partial[i] << i*`DSP_B_MAXWIDTH) + partial_sum[i-1];
168 //assign partial_sum[i] = {
169 // partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH],
170 // partial[i][`DSP_B_MAXWIDTH-1:0] + partial_sum[i-1][A_WIDTH+(i*`DSP_B_MAXWIDTH)-1:A_WIDTH+((i-1)*`DSP_B_MAXWIDTH)],
171 // partial_sum[i-1][A_WIDTH+((i-1)*`DSP_B_MAXWIDTH):0]
172 assign partial_sum[i] = {
173 partial[i][A_WIDTH+`DSP_B_MAXWIDTH-1:0]
174 + partial_sum[i-1][Y_WIDTH-1:(i*`DSP_B_MAXWIDTH)],
175 partial_sum[i-1][(i*`DSP_B_MAXWIDTH)-1:0]
183 .B_WIDTH(B_WIDTH-(n-1)*`DSP_B_MAXWIDTH),
184 .Y_WIDTH(A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH)
187 .B(B[B_WIDTH-1:(n-1)*`DSP_B_MAXWIDTH]),
188 .Y(partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0])
190 // AMD: this came comment out -- looks closer to right answer
191 //assign Y = (partial[n-1] << (n-1)*`DSP_B_MAXWIDTH) + partial_sum[n-2];
192 // was (looks broken)
194 // partial[n-1][A_WIDTH+`DSP_B_MAXWIDTH-1:`DSP_B_MAXWIDTH],
195 // 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)],
196 // partial_sum[n-2][A_WIDTH+((n-2)*`DSP_B_MAXWIDTH):0]
198 partial[n-1][A_WIDTH+B_WIDTH-(n-1)*`DSP_B_MAXWIDTH-1:0]
199 + partial_sum[n-2][Y_WIDTH-1:((n-1)*`DSP_B_MAXWIDTH)],
200 partial_sum[n-2][((n-1)*`DSP_B_MAXWIDTH)-1:0]
204 wire [A_WIDTH+B_WIDTH-1:0] out;
205 wire [(`DSP_A_MAXWIDTH+`DSP_B_MAXWIDTH)-(A_WIDTH+B_WIDTH)-1:0] dummy;
207 assign Asign = (A_SIGNED ? A[A_WIDTH-1] : 1'b0);
208 assign Bsign = (B_SIGNED ? B[B_WIDTH-1] : 1'b0);
209 `DSP_NAME _TECHMAP_REPLACE_ (
210 .A({ {{`DSP_A_MAXWIDTH-A_WIDTH}{Asign}}, A }),
211 .B({ {{`DSP_B_MAXWIDTH-B_WIDTH}{Bsign}}, B }),
214 if (Y_WIDTH < A_WIDTH+B_WIDTH)
215 assign Y = out[Y_WIDTH-1:0];
217 wire Ysign = (A_SIGNED || B_SIGNED ? out[A_WIDTH+B_WIDTH-1] : 1'b0);
218 assign Y = { {{Y_WIDTH-(A_WIDTH+B_WIDTH)}{Ysign}}, out[A_WIDTH+B_WIDTH-1:0] };