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