Revert "Different approach to timing"
[yosys.git] / techlibs / xilinx / abc_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 // ============================================================================
22
23 module RAM32X1D (
24 output DPO, SPO,
25 (* techmap_autopurge *) input D,
26 (* techmap_autopurge *) input WCLK,
27 (* techmap_autopurge *) input WE,
28 (* techmap_autopurge *) input A0, A1, A2, A3, A4,
29 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
30 );
31 parameter INIT = 32'h0;
32 parameter IS_WCLK_INVERTED = 1'b0;
33 wire \$DPO , \$SPO ;
34 RAM32X1D #(
35 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
36 ) _TECHMAP_REPLACE_ (
37 .DPO(\$DPO ), .SPO(\$SPO ),
38 .D(D), .WCLK(WCLK), .WE(WE),
39 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
40 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
41 );
42 \$__ABC_LUT6 dpo (.A(\$DPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(DPO));
43 \$__ABC_LUT6 spo (.A(\$SPO ), .S({1'b0, A0, A1, A2, A3, A4}), .Y(SPO));
44 endmodule
45
46 module RAM64X1D (
47 output DPO, SPO,
48 (* techmap_autopurge *) input D,
49 (* techmap_autopurge *) input WCLK,
50 (* techmap_autopurge *) input WE,
51 (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5,
52 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
53 );
54 parameter INIT = 64'h0;
55 parameter IS_WCLK_INVERTED = 1'b0;
56 wire \$DPO , \$SPO ;
57 RAM64X1D #(
58 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
59 ) _TECHMAP_REPLACE_ (
60 .DPO(\$DPO ), .SPO(\$SPO ),
61 .D(D), .WCLK(WCLK), .WE(WE),
62 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
63 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
64 );
65 \$__ABC_LUT6 dpo (.A(\$DPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(DPO));
66 \$__ABC_LUT6 spo (.A(\$SPO ), .S({A0, A1, A2, A3, A4, A5}), .Y(SPO));
67 endmodule
68
69 module RAM128X1D (
70 output DPO, SPO,
71 (* techmap_autopurge *) input D,
72 (* techmap_autopurge *) input WCLK,
73 (* techmap_autopurge *) input WE,
74 (* techmap_autopurge *) input [6:0] A, DPRA
75 );
76 parameter INIT = 128'h0;
77 parameter IS_WCLK_INVERTED = 1'b0;
78 wire \$DPO , \$SPO ;
79 RAM128X1D #(
80 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
81 ) _TECHMAP_REPLACE_ (
82 .DPO(\$DPO ), .SPO(\$SPO ),
83 .D(D), .WCLK(WCLK), .WE(WE),
84 .A(A),
85 .DPRA(DPRA)
86 );
87 \$__ABC_LUT7 dpo (.A(\$DPO ), .S(A), .Y(DPO));
88 \$__ABC_LUT7 spo (.A(\$SPO ), .S(A), .Y(SPO));
89 endmodule
90
91 module SRL16E (
92 output Q,
93 (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
94 );
95 parameter [15:0] INIT = 16'h0000;
96 parameter [0:0] IS_CLK_INVERTED = 1'b0;
97 wire \$Q ;
98 SRL16E #(
99 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
100 ) _TECHMAP_REPLACE_ (
101 .Q(\$Q ),
102 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
103 );
104 \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A0, A1, A2, A3, 1'b1}), .Y(Q));
105 endmodule
106
107 module SRLC32E (
108 output Q,
109 output Q31,
110 (* techmap_autopurge *) input [4:0] A,
111 (* techmap_autopurge *) input CE, CLK, D
112 );
113 parameter [31:0] INIT = 32'h00000000;
114 parameter [0:0] IS_CLK_INVERTED = 1'b0;
115 wire \$Q ;
116 SRLC32E #(
117 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
118 ) _TECHMAP_REPLACE_ (
119 .Q(\$Q ), .Q31(Q31),
120 .A(A), .CE(CE), .CLK(CLK), .D(D)
121 );
122 \$__ABC_LUT6 q (.A(\$Q ), .S({1'b1, A}), .Y(Q));
123 endmodule
124
125 module DSP48E1 (
126 output [29:0] ACOUT,
127 output [17:0] BCOUT,
128 output reg CARRYCASCOUT,
129 output reg [3:0] CARRYOUT,
130 output reg MULTSIGNOUT,
131 output OVERFLOW,
132 output reg signed [47:0] P,
133 output PATTERNBDETECT,
134 output PATTERNDETECT,
135 output [47:0] PCOUT,
136 output UNDERFLOW,
137 (* techmap_autopurge *) input signed [29:0] A,
138 (* techmap_autopurge *) input [29:0] ACIN,
139 (* techmap_autopurge *) input [3:0] ALUMODE,
140 (* techmap_autopurge *) input signed [17:0] B,
141 (* techmap_autopurge *) input [17:0] BCIN,
142 (* techmap_autopurge *) input [47:0] C,
143 (* techmap_autopurge *) input CARRYCASCIN,
144 (* techmap_autopurge *) input CARRYIN,
145 (* techmap_autopurge *) input [2:0] CARRYINSEL,
146 (* techmap_autopurge *) input CEA1,
147 (* techmap_autopurge *) input CEA2,
148 (* techmap_autopurge *) input CEAD,
149 (* techmap_autopurge *) input CEALUMODE,
150 (* techmap_autopurge *) input CEB1,
151 (* techmap_autopurge *) input CEB2,
152 (* techmap_autopurge *) input CEC,
153 (* techmap_autopurge *) input CECARRYIN,
154 (* techmap_autopurge *) input CECTRL,
155 (* techmap_autopurge *) input CED,
156 (* techmap_autopurge *) input CEINMODE,
157 (* techmap_autopurge *) input CEM,
158 (* techmap_autopurge *) input CEP,
159 (* techmap_autopurge *) input CLK,
160 (* techmap_autopurge *) input [24:0] D,
161 (* techmap_autopurge *) input [4:0] INMODE,
162 (* techmap_autopurge *) input MULTSIGNIN,
163 (* techmap_autopurge *) input [6:0] OPMODE,
164 (* techmap_autopurge *) input [47:0] PCIN,
165 (* techmap_autopurge *) input RSTA,
166 (* techmap_autopurge *) input RSTALLCARRYIN,
167 (* techmap_autopurge *) input RSTALUMODE,
168 (* techmap_autopurge *) input RSTB,
169 (* techmap_autopurge *) input RSTC,
170 (* techmap_autopurge *) input RSTCTRL,
171 (* techmap_autopurge *) input RSTD,
172 (* techmap_autopurge *) input RSTINMODE,
173 (* techmap_autopurge *) input RSTM,
174 (* techmap_autopurge *) input RSTP
175 );
176 parameter integer ACASCREG = 1;
177 parameter integer ADREG = 1;
178 parameter integer ALUMODEREG = 1;
179 parameter integer AREG = 1;
180 parameter AUTORESET_PATDET = "NO_RESET";
181 parameter A_INPUT = "DIRECT";
182 parameter integer BCASCREG = 1;
183 parameter integer BREG = 1;
184 parameter B_INPUT = "DIRECT";
185 parameter integer CARRYINREG = 1;
186 parameter integer CARRYINSELREG = 1;
187 parameter integer CREG = 1;
188 parameter integer DREG = 1;
189 parameter integer INMODEREG = 1;
190 parameter integer MREG = 1;
191 parameter integer OPMODEREG = 1;
192 parameter integer PREG = 1;
193 parameter SEL_MASK = "MASK";
194 parameter SEL_PATTERN = "PATTERN";
195 parameter USE_DPORT = "FALSE";
196 parameter USE_MULT = "MULTIPLY";
197 parameter USE_PATTERN_DETECT = "NO_PATDET";
198 parameter USE_SIMD = "ONE48";
199 parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
200 parameter [47:0] PATTERN = 48'h000000000000;
201 parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
202 parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
203 parameter [0:0] IS_CLK_INVERTED = 1'b0;
204 parameter [4:0] IS_INMODE_INVERTED = 5'b0;
205 parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
206
207 parameter _TECHMAP_CELLTYPE_ = "";
208 localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");
209
210 `define DSP48E1_INST(__CELL__) """
211 __CELL__ #(
212 .ACASCREG(ACASCREG),
213 .ADREG(ADREG),
214 .ALUMODEREG(ALUMODEREG),
215 .AREG(AREG),
216 .AUTORESET_PATDET(AUTORESET_PATDET),
217 .A_INPUT(A_INPUT),
218 .BCASCREG(BCASCREG),
219 .BREG(BREG),
220 .B_INPUT(B_INPUT),
221 .CARRYINREG(CARRYINREG),
222 .CARRYINSELREG(CARRYINSELREG),
223 .CREG(CREG),
224 .DREG(DREG),
225 .INMODEREG(INMODEREG),
226 .MREG(MREG),
227 .OPMODEREG(OPMODEREG),
228 .PREG(PREG),
229 .SEL_MASK(SEL_MASK),
230 .SEL_PATTERN(SEL_PATTERN),
231 .USE_DPORT(USE_DPORT),
232 .USE_MULT(USE_MULT),
233 .USE_PATTERN_DETECT(USE_PATTERN_DETECT),
234 .USE_SIMD(USE_SIMD),
235 .MASK(MASK),
236 .PATTERN(PATTERN),
237 .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
238 .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
239 .IS_CLK_INVERTED(IS_CLK_INVERTED),
240 .IS_INMODE_INVERTED(IS_INMODE_INVERTED),
241 .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
242 ) _TECHMAP_REPLACE_ (
243 .ACOUT(ACOUT),
244 .BCOUT(BCOUT),
245 .CARRYCASCOUT(CARRYCASCOUT),
246 .CARRYOUT(CARRYOUT),
247 .MULTSIGNOUT(MULTSIGNOUT),
248 .OVERFLOW(OVERFLOW),
249 .P(oP),
250 .PATTERNBDETECT(PATTERNBDETECT),
251 .PATTERNDETECT(PATTERNDETECT),
252 .PCOUT(oPCOUT),
253 .UNDERFLOW(UNDERFLOW),
254 .A(iA),
255 .ACIN(ACIN),
256 .ALUMODE(ALUMODE),
257 .B(iB),
258 .BCIN(BCIN),
259 .C(iC),
260 .CARRYCASCIN(CARRYCASCIN),
261 .CARRYIN(CARRYIN),
262 .CARRYINSEL(CARRYINSEL),
263 .CEA1(CEA1),
264 .CEA2(CEA2),
265 .CEAD(CEAD),
266 .CEALUMODE(CEALUMODE),
267 .CEB1(CEB1),
268 .CEB2(CEB2),
269 .CEC(CEC),
270 .CECARRYIN(CECARRYIN),
271 .CECTRL(CECTRL),
272 .CED(CED),
273 .CEINMODE(CEINMODE),
274 .CEM(CEM),
275 .CEP(CEP),
276 .CLK(CLK),
277 .D(iD),
278 .INMODE(INMODE),
279 .MULTSIGNIN(MULTSIGNIN),
280 .OPMODE(OPMODE),
281 .PCIN(PCIN),
282 .RSTA(RSTA),
283 .RSTALLCARRYIN(RSTALLCARRYIN),
284 .RSTALUMODE(RSTALUMODE),
285 .RSTB(RSTB),
286 .RSTC(RSTC),
287 .RSTCTRL(RSTCTRL),
288 .RSTD(RSTD),
289 .RSTINMODE(RSTINMODE),
290 .RSTM(RSTM),
291 .RSTP(RSTP)
292 );
293 """
294
295 generate
296 if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin
297 wire [29:0] iA;
298 wire [17:0] iB;
299 wire [47:0] iC;
300 wire [24:0] iD;
301
302 wire pA, pB, pC, pD, pAD, pM, pP;
303 wire [47:0] oP, oPCOUT;
304
305 // Disconnect the A-input if MREG is enabled, since
306 // combinatorial path is broken
307 if (AREG == 0 && MREG == 0 && PREG == 0)
308 assign iA = A, pA = 1'bx;
309 else
310 \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA));
311 if (BREG == 0 && MREG == 0 && PREG == 0)
312 assign iB = B, pB = 1'bx;
313 else
314 \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB));
315 if (CREG == 0 && PREG == 0)
316 assign iC = C, pC = 1'bx;
317 else
318 \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC));
319 if (DREG == 0)
320 assign iD = D;
321 else if (techmap_guard)
322 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
323 assign pD = 1'bx;
324 if (ADREG == 1 && techmap_guard)
325 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
326 assign pAD = 1'bx;
327 if (PREG == 0) begin
328 assign pP = 1'bx;
329 if (MREG == 1)
330 \$__ABC_DSP48E1_REG rM (.Q(pM));
331 else
332 assign pM = 1'bx;
333 end
334 else begin
335 \$__ABC_DSP48E1_REG rP (.Q(pP));
336 assign pM = 1'bx;
337 end
338
339 \$__ABC_DSP48E1_MULT_P_MUX muxP (
340 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P)
341 );
342 \$__ABC_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
343 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT)
344 );
345
346 `DSP48E1_INST(\$__ABC_DSP48E1_MULT )
347 end
348 else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
349 wire [29:0] iA;
350 wire [17:0] iB;
351 wire [47:0] iC;
352 wire [24:0] iD;
353
354 wire pA, pB, pC, pD, pAD, pM, pP;
355 wire [47:0] oP, oPCOUT;
356
357 // Disconnect the A-input if MREG is enabled, since
358 // combinatorial path is broken
359 if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
360 assign iA = A, pA = 1'bx;
361 else
362 \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA));
363 if (BREG == 0 && MREG == 0 && PREG == 0)
364 assign iB = B, pB = 1'bx;
365 else
366 \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB));
367 if (CREG == 0 && PREG == 0)
368 assign iC = C, pC = 1'bx;
369 else
370 \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC));
371 if (DREG == 0 && ADREG == 0)
372 assign iD = D, pD = 1'bx;
373 else
374 \$__ABC_DSP48E1_REG rD (.I(D), .O(iD), .Q(pD));
375 if (PREG == 0) begin
376 if (MREG == 1)
377 \$__ABC_DSP48E1_REG rM (.Q(pM));
378 else begin
379 assign pM = 1'bx;
380 if (ADREG == 1)
381 \$__ABC_DSP48E1_REG rAD (.Q(pAD));
382 else
383 assign pAD = 1'bx;
384 end
385 end
386 else
387 \$__ABC_DSP48E1_REG rP (.Q(pP));
388
389 \$__ABC_DSP48E1_MULT_DPORT_P_MUX muxP (
390 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P)
391 );
392 \$__ABC_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
393 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT)
394 );
395
396 `DSP48E1_INST(\$__ABC_DSP48E1_MULT_DPORT )
397 end
398 else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
399 wire [29:0] iA;
400 wire [17:0] iB;
401 wire [47:0] iC;
402 wire [24:0] iD;
403
404 wire pA, pB, pC, pD, pAD, pM, pP;
405 wire [47:0] oP, oPCOUT;
406
407 // Disconnect the A-input if MREG is enabled, since
408 // combinatorial path is broken
409 if (AREG == 0 && PREG == 0)
410 assign iA = A, pA = 1'bx;
411 else
412 \$__ABC_DSP48E1_REG rA (.I(A), .O(iA), .Q(pA));
413 if (BREG == 0 && PREG == 0)
414 assign iB = B, pB = 1'bx;
415 else
416 \$__ABC_DSP48E1_REG rB (.I(B), .O(iB), .Q(pB));
417 if (CREG == 0 && PREG == 0)
418 assign iC = C, pC = 1'bx;
419 else
420 \$__ABC_DSP48E1_REG rC (.I(C), .O(iC), .Q(pC));
421 if (MREG == 1 && techmap_guard)
422 $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
423 assign pM = 1'bx;
424 if (DREG == 1 && techmap_guard)
425 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
426 assign pD = 1'bx;
427 if (ADREG == 1 && techmap_guard)
428 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
429 assign pAD = 1'bx;
430 if (PREG == 1)
431 \$__ABC_DSP48E1_REG rP (.Q(pP));
432 else
433 assign pP = 1'bx;
434
435 \$__ABC_DSP48E1_P_MUX muxP (
436 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oP), .Pq(pP), .O(P)
437 );
438 \$__ABC_DSP48E1_PCOUT_MUX muxPCOUT (
439 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .Mq(pM), .P(oPCOUT), .Pq(pP), .O(PCOUT)
440 );
441
442 `DSP48E1_INST(\$__ABC_DSP48E1 )
443 end
444 else
445 $error("Invalid DSP48E1 configuration");
446 endgenerate
447 `undef DSP48E1_INST
448 endmodule