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 $error("Macro DSP_A_MAXWIDTH must be defined");
8 `ifndef DSP_A_SIGNEDONLY
9 `define DSP_A_SIGNEDONLY 0
11 `ifndef DSP_B_MAXWIDTH
12 $error("Macro DSP_B_MAXWIDTH must be defined");
14 `ifndef DSP_B_SIGNEDONLY
15 `define DSP_B_SIGNEDONLY 0
19 $error("Macro DSP_NAME must be defined");
22 `define MAX(a,b) (a > b ? a : b)
23 `define MIN(a,b) (a < b ? a : b)
25 module \$mul (A, B, Y);
26 parameter A_SIGNED = 0;
27 parameter B_SIGNED = 0;
28 parameter A_WIDTH = 1;
29 parameter B_WIDTH = 1;
30 parameter Y_WIDTH = 1;
32 input [A_WIDTH-1:0] A;
33 input [B_WIDTH-1:0] B;
34 output [Y_WIDTH-1:0] Y;
37 if (`DSP_SIGNEDONLY && !A_SIGNED) begin
42 .A_WIDTH(A_WIDTH + 1),
43 .B_WIDTH(B_WIDTH + 1),
51 // NB: A_SIGNED == B_SIGNED == 0 from here
52 else if (A_WIDTH >= B_WIDTH)
79 module \$__mul_gen (A, B, Y);
80 parameter A_SIGNED = 0;
81 parameter B_SIGNED = 0;
82 parameter A_WIDTH = 1;
83 parameter B_WIDTH = 1;
84 parameter Y_WIDTH = 1;
86 input [A_WIDTH-1:0] A;
87 input [B_WIDTH-1:0] B;
88 output [Y_WIDTH-1:0] Y;
90 wire [1023:0] _TECHMAP_DO_ = "proc; clean";
93 localparam sign_headroom = 1;
95 localparam sign_headroom = 0;
100 if (A_WIDTH > `DSP_A_MAXWIDTH) begin
101 localparam n = (A_WIDTH + `DSP_A_MAXWIDTH - sign_headroom - 1)/(`DSP_A_MAXWIDTH - sign_headroom);
102 localparam partial_Y_WIDTH = `MIN(Y_WIDTH, B_WIDTH+`DSP_A_MAXWIDTH);
103 wire [partial_Y_WIDTH-1:0] partial [n-1:1];
104 wire [Y_WIDTH-1:0] partial_sum [n-1:0];
109 .A_WIDTH(`DSP_A_MAXWIDTH),
111 .Y_WIDTH(partial_Y_WIDTH)
113 .A({{sign_headroom{1'b0}}, A[`DSP_A_MAXWIDTH-sign_headroom-1:0]}),
117 assign partial_sum[0] = partial[0];
119 for (i = 1; i < n-1; i=i+1) begin:slice
123 .A_WIDTH(`DSP_A_MAXWIDTH),
125 .Y_WIDTH(partial_Y_WIDTH)
127 .A({{sign_headroom{1'b0}}, A[i*(`DSP_A_MAXWIDTH-sign_headroom) +: `DSP_A_MAXWIDTH-sign_headroom]}),
131 assign partial_sum[i] = (partial[i] << i*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[i-1];
137 .A_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)),
139 .Y_WIDTH(A_WIDTH-(n-1)*(`DSP_A_MAXWIDTH-sign_headroom) + B_WIDTH),
141 .A(A[A_WIDTH-1:(n-1)*(`DSP_A_MAXWIDTH-sign_headroom)]),
145 assign Y = (partial[n-1] << (n-1)*(`DSP_A_MAXWIDTH-sign_headroom)) + partial_sum[n-2];
147 else if (B_WIDTH > `DSP_B_MAXWIDTH) begin
148 `ifdef DSP_B_SIGNEDONLY
149 localparam sign_headroom = 1;
151 localparam sign_headroom = 0;
153 localparam n = (B_WIDTH + `DSP_B_MAXWIDTH - sign_headroom - 1)/(`DSP_B_MAXWIDTH - sign_headroom);
154 localparam partial_Y_WIDTH = `MIN(Y_WIDTH, A_WIDTH+`DSP_B_MAXWIDTH);
155 wire [partial_Y_WIDTH-1:0] partial [n-1:1];
156 wire [Y_WIDTH-1:0] partial_sum [n-1:0];
162 .B_WIDTH(`DSP_B_MAXWIDTH),
163 .Y_WIDTH(partial_Y_WIDTH)
166 .B({{sign_headroom{1'b0}}, B[`DSP_B_MAXWIDTH-sign_headroom-1:0]}),
169 assign partial_sum[0] = partial[0];
171 for (i = 1; i < n-1; i=i+1) begin:slice
176 .B_WIDTH(`DSP_B_MAXWIDTH),
177 .Y_WIDTH(partial_Y_WIDTH)
180 .B({{sign_headroom{1'b0}}, B[i*(`DSP_B_MAXWIDTH-sign_headroom) +: `DSP_B_MAXWIDTH-sign_headroom]}),
183 assign partial_sum[i] = (partial[i] << i*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[i-1];
190 .B_WIDTH(B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)),
191 .Y_WIDTH(A_WIDTH + B_WIDTH-(n-1)*(`DSP_B_MAXWIDTH - sign_headroom))
194 .B(B[B_WIDTH-1:(n-1)*(`DSP_B_MAXWIDTH - sign_headroom)]),
197 assign Y = (partial[n-1] << (n-1)*(`DSP_B_MAXWIDTH - sign_headroom)) + partial_sum[n-2];
201 wire signed [`DSP_A_MAXWIDTH-1:0] Aext = $signed(A);
203 wire [`DSP_A_MAXWIDTH-1:0] Aext = A;
205 wire signed [`DSP_B_MAXWIDTH-1:0] Bext = $signed(B);
207 wire [`DSP_B_MAXWIDTH-1:0] Bext = B;
209 `DSP_NAME _TECHMAP_REPLACE_ (