2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5 * 2019 Eddie Hung <eddie@fpgeh.com>
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.
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.
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.
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:
33 // ++===================================++
36 // D -->>-----< > +------+ ||
37 // R -->>-----< Comb. > |$_DFF_| ||
38 // CE -->>-----< logic >-----| [NP]_|---+---->>-- Q
39 // || +--< > +------+ | ||
42 // || +----------------------------+ ||
44 // ++===================================++
46 // is transformed into:
48 // ++==================++
52 // D -->>-----< > || +------+
53 // R -->>-----< Comb. > || |$__ABC|
54 // CE -->>-----< logic >--->>-- $nextQ --| _FF_ |--+-->> Q
55 // $abc9_currQ +-->>-----< > || +------+ |
58 // | ++==================++ |
60 // +----------------------------------------------+
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;
80 .IS_C_INVERTED(IS_C_INVERTED),
81 .IS_D_INVERTED(IS_D_INVERTED),
82 .IS_R_INVERTED(IS_R_INVERTED)
84 .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
86 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
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;
93 module FDRE_1 (output reg Q, input C, CE, D, R);
94 parameter [0:0] INIT = 1'b0;
99 .D(D), .Q($nextQ), .C(C), .CE(CE), .R(R)
101 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
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;
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;
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
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));
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;
138 module FDCE_1 (output reg Q, input C, CE, D, CLR);
139 parameter [0:0] INIT = 1'b0;
140 wire $nextQ, $abc9_currQ;
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
151 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
152 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(CLR), .Y(Q));
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;
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;
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
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));
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;
187 module FDPE_1 (output reg Q, input C, CE, D, PRE);
188 parameter [0:0] INIT = 1'b0;
189 wire $nextQ, $abc9_currQ;
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
200 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q($abc9_currQ));
201 \$__ABC9_ASYNC abc_async (.A($abc9_currQ), .S(PRE), .Y(Q));
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;
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;
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)
223 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
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;
230 module FDSE_1 (output reg Q, input C, CE, D, S);
231 parameter [0:0] INIT = 1'b1;
235 ) _TECHMAP_REPLACE_ (
236 .D(D), .Q($nextQ), .C(C), .CE(CE), .S(S)
238 \$__ABC9_FF_ abc_dff (.D($nextQ), .Q(Q));
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;
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
254 parameter INIT = 32'h0;
255 parameter IS_WCLK_INVERTED = 1'b0;
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)
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));
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
277 parameter INIT = 64'h0;
278 parameter IS_WCLK_INVERTED = 1'b0;
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)
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));
294 (* techmap_autopurge *) input D,
295 (* techmap_autopurge *) input WCLK,
296 (* techmap_autopurge *) input WE,
297 (* techmap_autopurge *) input [6:0] A, DPRA
299 parameter INIT = 128'h0;
300 parameter IS_WCLK_INVERTED = 1'b0;
303 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
304 ) _TECHMAP_REPLACE_ (
305 .DPO(\$DPO ), .SPO(\$SPO ),
306 .D(D), .WCLK(WCLK), .WE(WE),
310 \$__ABC9_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
311 \$__ABC9_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
316 (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
318 parameter [15:0] INIT = 16'h0000;
319 parameter [0:0] IS_CLK_INVERTED = 1'b0;
322 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
323 ) _TECHMAP_REPLACE_ (
325 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
327 \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
333 (* techmap_autopurge *) input [4:0] A,
334 (* techmap_autopurge *) input CE, CLK, D
336 parameter [31:0] INIT = 32'h00000000;
337 parameter [0:0] IS_CLK_INVERTED = 1'b0;
340 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
341 ) _TECHMAP_REPLACE_ (
343 .A(A), .CE(CE), .CLK(CLK), .D(D)
345 \$__ABC9_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
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
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;
430 parameter _TECHMAP_CELLTYPE_ = "";
431 localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");
433 `define DSP48E1_INST(__CELL__) """
437 .ALUMODEREG(ALUMODEREG),
439 .AUTORESET_PATDET(AUTORESET_PATDET),
444 .CARRYINREG(CARRYINREG),
445 .CARRYINSELREG(CARRYINSELREG),
448 .INMODEREG(INMODEREG),
450 .OPMODEREG(OPMODEREG),
453 .SEL_PATTERN(SEL_PATTERN),
454 .USE_DPORT(USE_DPORT),
456 .USE_PATTERN_DETECT(USE_PATTERN_DETECT),
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_ (
468 .CARRYCASCOUT(CARRYCASCOUT),
470 .MULTSIGNOUT(MULTSIGNOUT),
473 .PATTERNBDETECT(PATTERNBDETECT),
474 .PATTERNDETECT(PATTERNDETECT),
476 .UNDERFLOW(UNDERFLOW),
483 .CARRYCASCIN(CARRYCASCIN),
485 .CARRYINSEL(CARRYINSEL),
489 .CEALUMODE(CEALUMODE),
493 .CECARRYIN(CECARRYIN),
502 .MULTSIGNIN(MULTSIGNIN),
506 .RSTALLCARRYIN(RSTALLCARRYIN),
507 .RSTALUMODE(RSTALUMODE),
512 .RSTINMODE(RSTINMODE),
523 wire pA, pB, pC, pD, pAD, pM, pP;
525 wire [47:0] oPCOUT, mPCOUT;
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;
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;
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;
542 \$__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
545 else if (techmap_guard)
546 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
548 if (ADREG == 1 && techmap_guard)
549 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
553 \$__ABC9_REG rM (.Q(pM));
559 \$__ABC9_REG rP (.Q(pP));
562 if (MREG == 0 && PREG == 0)
563 assign mP = oP, mPCOUT = oPCOUT;
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)
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)
573 `DSP48E1_INST(\$__ABC9_DSP48E1_MULT )
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;
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;
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;
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;
593 \$__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
597 \$__ABC9_REG rM (.Q(pM));
600 \$__ABC9_REG rAD (.Q(pAD));
607 assign pAD = 1'bx, pM = 1'bx;
608 \$__ABC9_REG rP (.Q(pP));
611 if (MREG == 0 && PREG == 0)
612 assign mP = oP, mPCOUT = oPCOUT;
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)
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)
622 `DSP48E1_INST(\$__ABC9_DSP48E1_MULT_DPORT )
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;
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;
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;
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\"");
642 if (ADREG == 1 && techmap_guard)
643 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
645 if (MREG == 1 && techmap_guard)
646 $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
649 \$__ABC9_REG rP (.Q(pP));
653 if (MREG == 0 && PREG == 0)
654 assign mP = oP, mPCOUT = oPCOUT;
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)
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)
664 `DSP48E1_INST(\$__ABC9_DSP48E1 )
667 $error("Invalid DSP48E1 configuration");