Merge remote-tracking branch 'origin/eddie/submod_po' into xaig_dff
[yosys.git] / techlibs / xilinx / abc9_map.v
1 /*
2 * yosys -- Yosys Open SYnthesis Suite
3 *
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * 2019 Eddie Hung <eddie@fpgeh.com>
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 // The following techmapping rules are intended to be run (with -max_iter 1)
22 // before invoking the `abc9` pass in order to transform the design into
23 // a format that it understands.
24 //
25 // For example, (complex) flip-flops are expected to be described as an
26 // combinatorial box (containing all control logic such as clock enable
27 // or synchronous resets) followed by a basic D-Q flop.
28 // Yosys will automatically analyse the simulation model (described in
29 // cells_sim.v) and detach any $_DFF_P_ or $_DFF_N_ cells present in
30 // order to extract the combinatorial control logic left behind.
31 // Specifically, a simulation model similar to the one below:
32 //
33 // ++===================================++
34 // || Sim model ||
35 // || /\/\/\/\ ||
36 // D -->>-----< > +------+ ||
37 // R -->>-----< Comb. > |$_DFF_| ||
38 // CE -->>-----< logic >-----| [NP]_|---+---->>-- Q
39 // || +--< > +------+ | ||
40 // || | \/\/\/\/ | ||
41 // || | | ||
42 // || +----------------------------+ ||
43 // || ||
44 // ++===================================++
45 //
46 // is transformed into:
47 //
48 // ++==================++
49 // || Comb box ||
50 // || ||
51 // || /\/\/\/\ ||
52 // D -->>-----< > || +------+
53 // R -->>-----< Comb. > || |$__ABC|
54 // CE -->>-----< logic >--->>-- $nextQ --| _FF_ |--+-->> Q
55 // $abc9_currQ +-->>-----< > || +------+ |
56 // | || \/\/\/\/ || |
57 // | || || |
58 // | ++==================++ |
59 // | |
60 // +----------------------------------------------+
61 //
62 // The purpose of the following FD* rules are to wrap the flop with:
63 // (a) a special $__ABC9_FF_ in front of the FD*'s output, indicating to abc9
64 // the connectivity of its basic D-Q flop
65 // (b) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock
66 // domain (used when partitioning the module so that `abc9' only
67 // performs sequential synthesis (with reachability analysis) correctly on
68 // one domain at a time)
69 // (c) a special _TECHMAP_REPLACE_.$abc9_control that captures the control
70 // domain (which, combined with this cell type, encodes to `abc9' which
71 // flops may be merged together)
72 // (d) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback
73 // into the (combinatorial) FD* cell to facilitate clock-enable behaviour
74 module FDRE (output reg Q, input C, CE, D, R);
75 parameter [0:0] INIT = 1'b0;
76 parameter [0:0] IS_C_INVERTED = 1'b0;
77 parameter [0:0] IS_D_INVERTED = 1'b0;
78 parameter [0:0] IS_R_INVERTED = 1'b0;
79 wire $nextQ;
80 FDRE #(
81 .INIT(INIT),
82 .IS_C_INVERTED(IS_C_INVERTED),
83 .IS_D_INVERTED(IS_D_INVERTED),
84 .IS_R_INVERTED(IS_R_INVERTED)
85 ) _TECHMAP_REPLACE_ (
86 .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
87 );
88 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
89
90 // Special signals
91 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
92 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, R, IS_R_INVERTED};
93 wire _TECHMAP_REPLACE_.$abc9_currQ = Q;
94 endmodule
95 module FDRE_1 (output reg Q, input C, CE, D, R);
96 parameter [0:0] INIT = 1'b0;
97 wire $nextQ;
98 FDRE_1 #(
99 .INIT(INIT),
100 ) _TECHMAP_REPLACE_ (
101 .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
102 );
103 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
104
105 // Special signals
106 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
107 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, R, 1'b0 /* IS_R_INVERTED */};
108 wire _TECHMAP_REPLACE_.$abc9_currQ = Q;
109 endmodule
110
111 module FDCE (output reg Q, input C, CE, D, CLR);
112 parameter [0:0] INIT = 1'b0;
113 parameter [0:0] IS_C_INVERTED = 1'b0;
114 parameter [0:0] IS_D_INVERTED = 1'b0;
115 parameter [0:0] IS_CLR_INVERTED = 1'b0;
116 wire $nextQ, $abc9_currQ;
117 FDCE #(
118 .INIT(INIT),
119 .IS_C_INVERTED(IS_C_INVERTED),
120 .IS_D_INVERTED(IS_D_INVERTED),
121 .IS_CLR_INVERTED(IS_CLR_INVERTED)
122 ) _TECHMAP_REPLACE_ (
123 .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
124 // ^^^ Note that async
125 // control is not directly
126 // supported by abc9 but its
127 // behaviour is captured by
128 // $__ABC9_ASYNC below
129 );
130 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
131 // Since this is an async flop, async behaviour is also dealt with
132 // using the $_ABC9_ASYNC box by abc9_map.v
133 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(Q));
134
135 // Special signals
136 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
137 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, CLR, IS_CLR_INVERTED};
138 wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
139 endmodule
140 module FDCE_1 (output reg Q, input C, CE, D, CLR);
141 parameter [0:0] INIT = 1'b0;
142 wire $nextQ, $abc9_currQ;
143 FDCE_1 #(
144 .INIT(INIT)
145 ) _TECHMAP_REPLACE_ (
146 .D(D), .Q($nextQ), .C(C), .CE(CE), .CLR(CLR)
147 // ^^^ Note that async
148 // control is not directly
149 // supported by abc9 but its
150 // behaviour is captured by
151 // $__ABC9_ASYNC below
152 );
153 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
154 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(Q));
155
156 // Special signals
157 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
158 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, CLR, 1'b0 /* IS_CLR_INVERTED */};
159 wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
160 endmodule
161
162 module FDPE (output reg Q, input C, CE, D, PRE);
163 parameter [0:0] INIT = 1'b0;
164 parameter [0:0] IS_C_INVERTED = 1'b0;
165 parameter [0:0] IS_D_INVERTED = 1'b0;
166 parameter [0:0] IS_PRE_INVERTED = 1'b0;
167 wire $nextQ, $abc9_currQ;
168 FDPE #(
169 .INIT(INIT),
170 .IS_C_INVERTED(IS_C_INVERTED),
171 .IS_D_INVERTED(IS_D_INVERTED),
172 .IS_PRE_INVERTED(IS_PRE_INVERTED),
173 ) _TECHMAP_REPLACE_ (
174 .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
175 // ^^^ Note that async
176 // control is not directly
177 // supported by abc9 but its
178 // behaviour is captured by
179 // $__ABC9_ASYNC below
180 );
181 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
182 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(Q));
183
184 // Special signals
185 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
186 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, PRE, IS_PRE_INVERTED};
187 wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
188 endmodule
189 module FDPE_1 (output reg Q, input C, CE, D, PRE);
190 parameter [0:0] INIT = 1'b0;
191 wire $nextQ, $abc9_currQ;
192 FDPE_1 #(
193 .INIT(INIT)
194 ) _TECHMAP_REPLACE_ (
195 .D(D), .Q($nextQ), .C(C), .CE(CE), .PRE(PRE)
196 // ^^^ Note that async
197 // control is not directly
198 // supported by abc9 but its
199 // behaviour is captured by
200 // $__ABC9_ASYNC below
201 );
202 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
203 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(Q));
204
205 // Special signals
206 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
207 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, PRE, 1'b0 /* IS_PRE_INVERTED */};
208 wire _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
209 endmodule
210
211 module FDSE (output reg Q, input C, CE, D, S);
212 parameter [0:0] INIT = 1'b1;
213 parameter [0:0] IS_C_INVERTED = 1'b0;
214 parameter [0:0] IS_D_INVERTED = 1'b0;
215 parameter [0:0] IS_S_INVERTED = 1'b0;
216 wire $nextQ;
217 FDSE #(
218 .INIT(INIT),
219 .IS_C_INVERTED(IS_C_INVERTED),
220 .IS_D_INVERTED(IS_D_INVERTED),
221 .IS_S_INVERTED(IS_S_INVERTED)
222 ) _TECHMAP_REPLACE_ (
223 .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
224 );
225 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
226
227 // Special signals
228 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
229 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, IS_D_INVERTED, S, IS_S_INVERTED};
230 wire _TECHMAP_REPLACE_.$abc9_currQ = Q;
231 endmodule
232 module FDSE_1 (output reg Q, input C, CE, D, S);
233 parameter [0:0] INIT = 1'b1;
234 wire $nextQ;
235 FDSE_1 #(
236 .INIT(INIT),
237 ) _TECHMAP_REPLACE_ (
238 .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
239 );
240 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
241
242 // Special signals
243 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
244 wire [3:0] _TECHMAP_REPLACE_.$abc9_control = {CE, 1'b0 /* IS_D_INVERTED */, S, 1'b0 /* IS_S_INVERTED */};
245 wire _TECHMAP_REPLACE_.$abc9_currQ = Q;
246 endmodule
247
248 module RAM32X1D (
249 output DPO, SPO,
250 (* techmap_autopurge *) input D,
251 (* techmap_autopurge *) input WCLK,
252 (* techmap_autopurge *) input WE,
253 (* techmap_autopurge *) input A0, A1, A2, A3, A4,
254 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
255 );
256 parameter INIT = 32'h0;
257 parameter IS_WCLK_INVERTED = 1'b0;
258 wire \$DPO , \$SPO ;
259 RAM32X1D #(
260 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
261 ) _TECHMAP_REPLACE_ (
262 .DPO(\$DPO ), .SPO(\$SPO ),
263 .D(D), .WCLK(WCLK), .WE(WE),
264 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
265 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
266 );
267 \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
268 \$__ABC9_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
269 endmodule
270
271 module RAM64X1D (
272 output DPO, SPO,
273 (* techmap_autopurge *) input D,
274 (* techmap_autopurge *) input WCLK,
275 (* techmap_autopurge *) input WE,
276 (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5,
277 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
278 );
279 parameter INIT = 64'h0;
280 parameter IS_WCLK_INVERTED = 1'b0;
281 wire \$DPO , \$SPO ;
282 RAM64X1D #(
283 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
284 ) _TECHMAP_REPLACE_ (
285 .DPO(\$DPO ), .SPO(\$SPO ),
286 .D(D), .WCLK(WCLK), .WE(WE),
287 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
288 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
289 );
290 \$__ABC9_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
291 \$__ABC9_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
292 endmodule
293
294 module RAM128X1D (
295 output DPO, SPO,
296 (* techmap_autopurge *) input D,
297 (* techmap_autopurge *) input WCLK,
298 (* techmap_autopurge *) input WE,
299 (* techmap_autopurge *) input [6:0] A, DPRA
300 );
301 parameter INIT = 128'h0;
302 parameter IS_WCLK_INVERTED = 1'b0;
303 wire \$DPO , \$SPO ;
304 RAM128X1D #(
305 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
306 ) _TECHMAP_REPLACE_ (
307 .DPO(\$DPO ), .SPO(\$SPO ),
308 .D(D), .WCLK(WCLK), .WE(WE),
309 .A(A),
310 .DPRA(DPRA)
311 );
312 \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
313 \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
314 endmodule
315
316 module SRL16E (
317 output Q,
318 (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
319 );
320 parameter [15:0] INIT = 16'h0000;
321 parameter [0:0] IS_CLK_INVERTED = 1'b0;
322 wire \$Q ;
323 SRL16E #(
324 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
325 ) _TECHMAP_REPLACE_ (
326 .Q(\$Q ),
327 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
328 );
329 \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
330 endmodule
331
332 module SRLC32E (
333 output Q,
334 output Q31,
335 (* techmap_autopurge *) input [4:0] A,
336 (* techmap_autopurge *) input CE, CLK, D
337 );
338 parameter [31:0] INIT = 32'h00000000;
339 parameter [0:0] IS_CLK_INVERTED = 1'b0;
340 wire \$Q ;
341 SRLC32E #(
342 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
343 ) _TECHMAP_REPLACE_ (
344 .Q(\$Q ), .Q31(Q31),
345 .A(A), .CE(CE), .CLK(CLK), .D(D)
346 );
347 \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
348 endmodule
349
350 module DSP48E1 (
351 (* techmap_autopurge *) output [29:0] ACOUT,
352 (* techmap_autopurge *) output [17:0] BCOUT,
353 (* techmap_autopurge *) output reg CARRYCASCOUT,
354 (* techmap_autopurge *) output reg [3:0] CARRYOUT,
355 (* techmap_autopurge *) output reg MULTSIGNOUT,
356 (* techmap_autopurge *) output OVERFLOW,
357 (* techmap_autopurge *) output reg signed [47:0] P,
358 (* techmap_autopurge *) output PATTERNBDETECT,
359 (* techmap_autopurge *) output PATTERNDETECT,
360 (* techmap_autopurge *) output [47:0] PCOUT,
361 (* techmap_autopurge *) output UNDERFLOW,
362 (* techmap_autopurge *) input signed [29:0] A,
363 (* techmap_autopurge *) input [29:0] ACIN,
364 (* techmap_autopurge *) input [3:0] ALUMODE,
365 (* techmap_autopurge *) input signed [17:0] B,
366 (* techmap_autopurge *) input [17:0] BCIN,
367 (* techmap_autopurge *) input [47:0] C,
368 (* techmap_autopurge *) input CARRYCASCIN,
369 (* techmap_autopurge *) input CARRYIN,
370 (* techmap_autopurge *) input [2:0] CARRYINSEL,
371 (* techmap_autopurge *) input CEA1,
372 (* techmap_autopurge *) input CEA2,
373 (* techmap_autopurge *) input CEAD,
374 (* techmap_autopurge *) input CEALUMODE,
375 (* techmap_autopurge *) input CEB1,
376 (* techmap_autopurge *) input CEB2,
377 (* techmap_autopurge *) input CEC,
378 (* techmap_autopurge *) input CECARRYIN,
379 (* techmap_autopurge *) input CECTRL,
380 (* techmap_autopurge *) input CED,
381 (* techmap_autopurge *) input CEINMODE,
382 (* techmap_autopurge *) input CEM,
383 (* techmap_autopurge *) input CEP,
384 (* techmap_autopurge *) input CLK,
385 (* techmap_autopurge *) input [24:0] D,
386 (* techmap_autopurge *) input [4:0] INMODE,
387 (* techmap_autopurge *) input MULTSIGNIN,
388 (* techmap_autopurge *) input [6:0] OPMODE,
389 (* techmap_autopurge *) input [47:0] PCIN,
390 (* techmap_autopurge *) input RSTA,
391 (* techmap_autopurge *) input RSTALLCARRYIN,
392 (* techmap_autopurge *) input RSTALUMODE,
393 (* techmap_autopurge *) input RSTB,
394 (* techmap_autopurge *) input RSTC,
395 (* techmap_autopurge *) input RSTCTRL,
396 (* techmap_autopurge *) input RSTD,
397 (* techmap_autopurge *) input RSTINMODE,
398 (* techmap_autopurge *) input RSTM,
399 (* techmap_autopurge *) input RSTP
400 );
401 parameter integer ACASCREG = 1;
402 parameter integer ADREG = 1;
403 parameter integer ALUMODEREG = 1;
404 parameter integer AREG = 1;
405 parameter AUTORESET_PATDET = "NO_RESET";
406 parameter A_INPUT = "DIRECT";
407 parameter integer BCASCREG = 1;
408 parameter integer BREG = 1;
409 parameter B_INPUT = "DIRECT";
410 parameter integer CARRYINREG = 1;
411 parameter integer CARRYINSELREG = 1;
412 parameter integer CREG = 1;
413 parameter integer DREG = 1;
414 parameter integer INMODEREG = 1;
415 parameter integer MREG = 1;
416 parameter integer OPMODEREG = 1;
417 parameter integer PREG = 1;
418 parameter SEL_MASK = "MASK";
419 parameter SEL_PATTERN = "PATTERN";
420 parameter USE_DPORT = "FALSE";
421 parameter USE_MULT = "MULTIPLY";
422 parameter USE_PATTERN_DETECT = "NO_PATDET";
423 parameter USE_SIMD = "ONE48";
424 parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
425 parameter [47:0] PATTERN = 48'h000000000000;
426 parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
427 parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
428 parameter [0:0] IS_CLK_INVERTED = 1'b0;
429 parameter [4:0] IS_INMODE_INVERTED = 5'b0;
430 parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
431
432 parameter _TECHMAP_CELLTYPE_ = "";
433 localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");
434
435 `define DSP48E1_INST(__CELL__) """
436 __CELL__ #(
437 .ACASCREG(ACASCREG),
438 .ADREG(ADREG),
439 .ALUMODEREG(ALUMODEREG),
440 .AREG(AREG),
441 .AUTORESET_PATDET(AUTORESET_PATDET),
442 .A_INPUT(A_INPUT),
443 .BCASCREG(BCASCREG),
444 .BREG(BREG),
445 .B_INPUT(B_INPUT),
446 .CARRYINREG(CARRYINREG),
447 .CARRYINSELREG(CARRYINSELREG),
448 .CREG(CREG),
449 .DREG(DREG),
450 .INMODEREG(INMODEREG),
451 .MREG(MREG),
452 .OPMODEREG(OPMODEREG),
453 .PREG(PREG),
454 .SEL_MASK(SEL_MASK),
455 .SEL_PATTERN(SEL_PATTERN),
456 .USE_DPORT(USE_DPORT),
457 .USE_MULT(USE_MULT),
458 .USE_PATTERN_DETECT(USE_PATTERN_DETECT),
459 .USE_SIMD(USE_SIMD),
460 .MASK(MASK),
461 .PATTERN(PATTERN),
462 .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
463 .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
464 .IS_CLK_INVERTED(IS_CLK_INVERTED),
465 .IS_INMODE_INVERTED(IS_INMODE_INVERTED),
466 .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
467 ) _TECHMAP_REPLACE_ (
468 .ACOUT(ACOUT),
469 .BCOUT(BCOUT),
470 .CARRYCASCOUT(CARRYCASCOUT),
471 .CARRYOUT(CARRYOUT),
472 .MULTSIGNOUT(MULTSIGNOUT),
473 .OVERFLOW(OVERFLOW),
474 .P(oP),
475 .PATTERNBDETECT(PATTERNBDETECT),
476 .PATTERNDETECT(PATTERNDETECT),
477 .PCOUT(oPCOUT),
478 .UNDERFLOW(UNDERFLOW),
479 .A(iA),
480 .ACIN(ACIN),
481 .ALUMODE(ALUMODE),
482 .B(iB),
483 .BCIN(BCIN),
484 .C(iC),
485 .CARRYCASCIN(CARRYCASCIN),
486 .CARRYIN(CARRYIN),
487 .CARRYINSEL(CARRYINSEL),
488 .CEA1(CEA1),
489 .CEA2(CEA2),
490 .CEAD(CEAD),
491 .CEALUMODE(CEALUMODE),
492 .CEB1(CEB1),
493 .CEB2(CEB2),
494 .CEC(CEC),
495 .CECARRYIN(CECARRYIN),
496 .CECTRL(CECTRL),
497 .CED(CED),
498 .CEINMODE(CEINMODE),
499 .CEM(CEM),
500 .CEP(CEP),
501 .CLK(CLK),
502 .D(iD),
503 .INMODE(INMODE),
504 .MULTSIGNIN(MULTSIGNIN),
505 .OPMODE(OPMODE),
506 .PCIN(PCIN),
507 .RSTA(RSTA),
508 .RSTALLCARRYIN(RSTALLCARRYIN),
509 .RSTALUMODE(RSTALUMODE),
510 .RSTB(RSTB),
511 .RSTC(RSTC),
512 .RSTCTRL(RSTCTRL),
513 .RSTD(RSTD),
514 .RSTINMODE(RSTINMODE),
515 .RSTM(RSTM),
516 .RSTP(RSTP)
517 );
518 """
519
520 wire [29:0] iA;
521 wire [17:0] iB;
522 wire [47:0] iC;
523 wire [24:0] iD;
524
525 wire pA, pB, pC, pD, pAD, pM, pP;
526 wire [47:0] oP, mP;
527 wire [47:0] oPCOUT, mPCOUT;
528
529 generate
530 if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin
531 // Disconnect the A-input if MREG is enabled, since
532 // combinatorial path is broken
533 if (AREG == 0 && MREG == 0 && PREG == 0)
534 assign iA = A, pA = 1'bx;
535 else
536 \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
537 if (BREG == 0 && MREG == 0 && PREG == 0)
538 assign iB = B, pB = 1'bx;
539 else
540 \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
541 if (CREG == 0 && PREG == 0)
542 assign iC = C, pC = 1'bx;
543 else
544 \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
545 if (DREG == 0)
546 assign iD = D;
547 else if (techmap_guard)
548 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
549 assign pD = 1'bx;
550 if (ADREG == 1 && techmap_guard)
551 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
552 assign pAD = 1'bx;
553 if (PREG == 0) begin
554 if (MREG == 1)
555 \$__ABC9_REG rM (.Q(pM));
556 else
557 assign pM = 1'bx;
558 assign pP = 1'bx;
559 end else begin
560 assign pM = 1'bx;
561 \$__ABC9_REG rP (.Q(pP));
562 end
563
564 if (MREG == 0 && PREG == 0)
565 assign mP = oP, mPCOUT = oPCOUT;
566 else
567 assign mP = 1'bx, mPCOUT = 1'bx;
568 \$__ABC9_DSP48E1_MULT_P_MUX muxP (
569 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
570 );
571 \$__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
572 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
573 );
574
575 `DSP48E1_INST(\$__ABC9_DSP48E1_MULT )
576 end
577 else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
578 // Disconnect the A-input if MREG is enabled, since
579 // combinatorial path is broken
580 if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
581 assign iA = A, pA = 1'bx;
582 else
583 \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
584 if (BREG == 0 && MREG == 0 && PREG == 0)
585 assign iB = B, pB = 1'bx;
586 else
587 \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
588 if (CREG == 0 && PREG == 0)
589 assign iC = C, pC = 1'bx;
590 else
591 \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
592 if (DREG == 0 && ADREG == 0)
593 assign iD = D, pD = 1'bx;
594 else
595 \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
596 if (PREG == 0) begin
597 if (MREG == 1) begin
598 assign pAD = 1'bx;
599 \$__ABC9_REG rM (.Q(pM));
600 end else begin
601 if (ADREG == 1)
602 \$__ABC9_REG rAD (.Q(pAD));
603 else
604 assign pAD = 1'bx;
605 assign pM = 1'bx;
606 end
607 assign pP = 1'bx;
608 end else begin
609 assign pAD = 1'bx, pM = 1'bx;
610 \$__ABC9_REG rP (.Q(pP));
611 end
612
613 if (MREG == 0 && PREG == 0)
614 assign mP = oP, mPCOUT = oPCOUT;
615 else
616 assign mP = 1'bx, mPCOUT = 1'bx;
617 \$__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP (
618 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
619 );
620 \$__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
621 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
622 );
623
624 `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT )
625 end
626 else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
627 // Disconnect the A-input if MREG is enabled, since
628 // combinatorial path is broken
629 if (AREG == 0 && PREG == 0)
630 assign iA = A, pA = 1'bx;
631 else
632 \$__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
633 if (BREG == 0 && PREG == 0)
634 assign iB = B, pB = 1'bx;
635 else
636 \$__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
637 if (CREG == 0 && PREG == 0)
638 assign iC = C, pC = 1'bx;
639 else
640 \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
641 if (DREG == 1 && techmap_guard)
642 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
643 assign pD = 1'bx;
644 if (ADREG == 1 && techmap_guard)
645 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
646 assign pAD = 1'bx;
647 if (MREG == 1 && techmap_guard)
648 $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
649 assign pM = 1'bx;
650 if (PREG == 1)
651 \$__ABC9_REG rP (.Q(pP));
652 else
653 assign pP = 1'bx;
654
655 if (MREG == 0 && PREG == 0)
656 assign mP = oP, mPCOUT = oPCOUT;
657 else
658 assign mP = 1'bx, mPCOUT = 1'bx;
659 \$__ABC9_DSP48E1_P_MUX muxP (
660 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
661 );
662 \$__ABC9_DSP48E1_PCOUT_MUX muxPCOUT (
663 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
664 );
665
666 `DSP48E1_INST(\$__ABC9_DSP48E1 )
667 end
668 else
669 $error("Invalid DSP48E1 configuration");
670 endgenerate
671 `undef DSP48E1_INST
672 endmodule