2cabe57d776937756789a88da0725ab19ccc51bb
[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. > || +----------+
54 // CE -->>-----< logic >--->>-- $Q --|$__ABC_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) an optional $__ABC9_ASYNC_ cell in front of $__ABC_FF_'s output to
66 // capture asynchronous behaviour
67 // (c) a special _TECHMAP_REPLACE_.$abc9_clock wire to capture its clock
68 // domain and polarity (used when partitioning the module so that `abc9' only
69 // performs sequential synthesis (with reachability analysis) correctly on
70 // one domain at a time) and also used to infer the optional delay target
71 // from the (* abc9_clock_period = %d *) attribute attached to any wire
72 // within
73 // (d) a special _TECHMAP_REPLACE_.$abc9_init wire to encode the flop's initial
74 // state
75 // (e) a special _TECHMAP_REPLACE_.$abc9_currQ wire that will be used for feedback
76 // into the (combinatorial) FD* cell to facilitate clock-enable behaviour
77 //
78 // In order to perform sequential synthesis, `abc9' also requires that
79 // the initial value of all flops be zero.
80
81 module FDRE (output Q, input C, CE, D, R);
82 parameter [0:0] INIT = 1'b0;
83 parameter [0:0] IS_C_INVERTED = 1'b0;
84 parameter [0:0] IS_D_INVERTED = 1'b0;
85 parameter [0:0] IS_R_INVERTED = 1'b0;
86 `ifdef DFF_MODE
87 wire QQ, $Q;
88 generate if (INIT == 1'b1) begin
89 assign Q = ~QQ;
90 FDSE #(
91 .INIT(1'b0),
92 .IS_C_INVERTED(IS_C_INVERTED),
93 .IS_D_INVERTED(IS_D_INVERTED),
94 .IS_S_INVERTED(IS_R_INVERTED)
95 ) _TECHMAP_REPLACE_ (
96 .D(~D), .Q($Q), .C(C), .CE(CE), .S(R)
97 );
98 end
99 else begin
100 assign Q = QQ;
101 FDRE #(
102 .INIT(1'b0),
103 .IS_C_INVERTED(IS_C_INVERTED),
104 .IS_D_INVERTED(IS_D_INVERTED),
105 .IS_R_INVERTED(IS_R_INVERTED)
106 ) _TECHMAP_REPLACE_ (
107 .D(D), .Q($Q), .C(C), .CE(CE), .R(R)
108 );
109 end
110 endgenerate
111 $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
112
113 // Special signals
114 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
115 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
116 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
117 `else
118 (* abc9_keep *)
119 FDRE #(
120 .INIT(INIT),
121 .IS_C_INVERTED(IS_C_INVERTED),
122 .IS_D_INVERTED(IS_D_INVERTED),
123 .IS_R_INVERTED(IS_R_INVERTED)
124 ) _TECHMAP_REPLACE_ (
125 .D(D), .Q(Q), .C(C), .CE(CE), .R(R)
126 );
127 `endif
128 endmodule
129 module FDRE_1 (output Q, input C, CE, D, R);
130 parameter [0:0] INIT = 1'b0;
131 `ifdef DFF_MODE
132 wire QQ, $Q;
133 generate if (INIT == 1'b1) begin
134 assign Q = ~QQ;
135 FDSE_1 #(
136 .INIT(1'b0)
137 ) _TECHMAP_REPLACE_ (
138 .D(~D), .Q($Q), .C(C), .CE(CE), .S(R)
139 );
140 end
141 else begin
142 assign Q = QQ;
143 FDRE_1 #(
144 .INIT(1'b0)
145 ) _TECHMAP_REPLACE_ (
146 .D(D), .Q($Q), .C(C), .CE(CE), .R(R)
147 );
148 end
149 endgenerate
150 $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
151
152 // Special signals
153 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
154 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
155 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
156 `else
157 (* abc9_keep *)
158 FDRE_1 #(
159 .INIT(INIT)
160 ) _TECHMAP_REPLACE_ (
161 .D(D), .Q(Q), .C(C), .CE(CE), .R(R)
162 );
163 `endif
164 endmodule
165
166 module FDCE (output Q, input C, CE, D, CLR);
167 parameter [0:0] INIT = 1'b0;
168 parameter [0:0] IS_C_INVERTED = 1'b0;
169 parameter [0:0] IS_D_INVERTED = 1'b0;
170 parameter [0:0] IS_CLR_INVERTED = 1'b0;
171 `ifdef DFF_MODE
172 wire QQ, $Q, $abc9_currQ;
173 generate if (INIT == 1'b1) begin
174 assign Q = ~QQ;
175 FDPE #(
176 .INIT(1'b0),
177 .IS_C_INVERTED(IS_C_INVERTED),
178 .IS_D_INVERTED(IS_D_INVERTED),
179 .IS_PRE_INVERTED(IS_CLR_INVERTED)
180 ) _TECHMAP_REPLACE_ (
181 .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR)
182 // ^^^ Note that async
183 // control is not directly
184 // supported by abc9 but its
185 // behaviour is captured by
186 // $__ABC9_ASYNC1 below
187 );
188 // Since this is an async flop, async behaviour is dealt with here
189 $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
190 end
191 else begin
192 assign Q = QQ;
193 FDCE #(
194 .INIT(1'b0),
195 .IS_C_INVERTED(IS_C_INVERTED),
196 .IS_D_INVERTED(IS_D_INVERTED),
197 .IS_CLR_INVERTED(IS_CLR_INVERTED)
198 ) _TECHMAP_REPLACE_ (
199 .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR)
200 // ^^^ Note that async
201 // control is not directly
202 // supported by abc9 but its
203 // behaviour is captured by
204 // $__ABC9_ASYNC0 below
205 );
206 // Since this is an async flop, async behaviour is dealt with here
207 $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ));
208 end endgenerate
209 $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
210
211 // Special signals
212 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
213 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
214 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
215 `else
216 (* abc9_keep *)
217 FDCE #(
218 .INIT(INIT),
219 .IS_C_INVERTED(IS_C_INVERTED),
220 .IS_D_INVERTED(IS_D_INVERTED),
221 .IS_CLR_INVERTED(IS_CLR_INVERTED)
222 ) _TECHMAP_REPLACE_ (
223 .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR)
224 );
225 `endif
226 endmodule
227 module FDCE_1 (output Q, input C, CE, D, CLR);
228 parameter [0:0] INIT = 1'b0;
229 `ifdef DFF_MODE
230 wire QQ, $Q, $abc9_currQ;
231 generate if (INIT == 1'b1) begin
232 assign Q = ~QQ;
233 FDPE_1 #(
234 .INIT(1'b0)
235 ) _TECHMAP_REPLACE_ (
236 .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR)
237 // ^^^ Note that async
238 // control is not directly
239 // supported by abc9 but its
240 // behaviour is captured by
241 // $__ABC9_ASYNC1 below
242 );
243 $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));
244 end
245 else begin
246 assign Q = QQ;
247 FDCE_1 #(
248 .INIT(1'b0)
249 ) _TECHMAP_REPLACE_ (
250 .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR)
251 // ^^^ Note that async
252 // control is not directly
253 // supported by abc9 but its
254 // behaviour is captured by
255 // $__ABC9_ASYNC0 below
256 );
257 $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(CLR), .Y(QQ));
258 end endgenerate
259 $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
260
261 // Special signals
262 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
263 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
264 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
265 `else
266 (* abc9_keep *)
267 FDCE_1 #(
268 .INIT(INIT)
269 ) _TECHMAP_REPLACE_ (
270 .D(D), .Q(Q), .C(C), .CE(CE), .CLR(CLR)
271 );
272 `endif
273 endmodule
274
275 module FDPE (output Q, input C, CE, D, PRE);
276 parameter [0:0] INIT = 1'b1;
277 parameter [0:0] IS_C_INVERTED = 1'b0;
278 parameter [0:0] IS_D_INVERTED = 1'b0;
279 parameter [0:0] IS_PRE_INVERTED = 1'b0;
280 `ifdef DFF_MODE
281 wire QQ, $Q, $abc9_currQ;
282 generate if (INIT == 1'b1) begin
283 assign Q = ~QQ;
284 FDCE #(
285 .INIT(1'b0),
286 .IS_C_INVERTED(IS_C_INVERTED),
287 .IS_D_INVERTED(IS_D_INVERTED),
288 .IS_CLR_INVERTED(IS_PRE_INVERTED),
289 ) _TECHMAP_REPLACE_ (
290 .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE)
291 // ^^^ Note that async
292 // control is not directly
293 // supported by abc9 but its
294 // behaviour is captured by
295 // $__ABC9_ASYNC0 below
296 );
297 $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
298 end
299 else begin
300 assign Q = QQ;
301 FDPE #(
302 .INIT(1'b0),
303 .IS_C_INVERTED(IS_C_INVERTED),
304 .IS_D_INVERTED(IS_D_INVERTED),
305 .IS_PRE_INVERTED(IS_PRE_INVERTED),
306 ) _TECHMAP_REPLACE_ (
307 .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE)
308 // ^^^ Note that async
309 // control is not directly
310 // supported by abc9 but its
311 // behaviour is captured by
312 // $__ABC9_ASYNC1 below
313 );
314 $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ));
315 end endgenerate
316 $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
317
318 // Special signals
319 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
320 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
321 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
322 `else
323 (* abc9_keep *)
324 FDPE #(
325 .INIT(INIT),
326 .IS_C_INVERTED(IS_C_INVERTED),
327 .IS_D_INVERTED(IS_D_INVERTED),
328 .IS_PRE_INVERTED(IS_PRE_INVERTED),
329 ) _TECHMAP_REPLACE_ (
330 .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE)
331 );
332 `endif
333 endmodule
334 module FDPE_1 (output Q, input C, CE, D, PRE);
335 parameter [0:0] INIT = 1'b1;
336 `ifdef DFF_MODE
337 wire QQ, $Q, $abc9_currQ;
338 generate if (INIT == 1'b1) begin
339 assign Q = ~QQ;
340 FDCE_1 #(
341 .INIT(1'b0)
342 ) _TECHMAP_REPLACE_ (
343 .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE)
344 // ^^^ Note that async
345 // control is not directly
346 // supported by abc9 but its
347 // behaviour is captured by
348 // $__ABC9_ASYNC0 below
349 );
350 $__ABC9_ASYNC0 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));
351 end
352 else begin
353 assign Q = QQ;
354 FDPE_1 #(
355 .INIT(1'b0)
356 ) _TECHMAP_REPLACE_ (
357 .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE)
358 // ^^^ Note that async
359 // control is not directly
360 // supported by abc9 but its
361 // behaviour is captured by
362 // $__ABC9_ASYNC1 below
363 );
364 $__ABC9_ASYNC1 abc_async (.A($abc9_currQ), .S(PRE), .Y(QQ));
365 end endgenerate
366 $__ABC9_FF_ abc_dff (.D($Q), .Q($abc9_currQ));
367
368 // Special signals
369 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
370 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
371 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = $abc9_currQ;
372 `else
373 (* abc9_keep *)
374 FDPE_1 #(
375 .INIT(INIT)
376 ) _TECHMAP_REPLACE_ (
377 .D(D), .Q(Q), .C(C), .CE(CE), .PRE(PRE)
378 );
379 `endif
380 endmodule
381
382 module FDSE (output Q, input C, CE, D, S);
383 parameter [0:0] INIT = 1'b1;
384 parameter [0:0] IS_C_INVERTED = 1'b0;
385 parameter [0:0] IS_D_INVERTED = 1'b0;
386 parameter [0:0] IS_S_INVERTED = 1'b0;
387 `ifdef DFF_MODE
388 wire QQ, $Q;
389 generate if (INIT == 1'b1) begin
390 assign Q = ~QQ;
391 FDRE #(
392 .INIT(1'b0),
393 .IS_C_INVERTED(IS_C_INVERTED),
394 .IS_D_INVERTED(IS_D_INVERTED),
395 .IS_R_INVERTED(IS_S_INVERTED)
396 ) _TECHMAP_REPLACE_ (
397 .D(~D), .Q($Q), .C(C), .CE(CE), .R(S)
398 );
399 end
400 else begin
401 assign Q = QQ;
402 FDSE #(
403 .INIT(1'b0),
404 .IS_C_INVERTED(IS_C_INVERTED),
405 .IS_D_INVERTED(IS_D_INVERTED),
406 .IS_S_INVERTED(IS_S_INVERTED)
407 ) _TECHMAP_REPLACE_ (
408 .D(D), .Q($Q), .C(C), .CE(CE), .S(S)
409 );
410 end endgenerate
411 $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
412
413 // Special signals
414 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, IS_C_INVERTED};
415 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
416 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
417 `else
418 (* abc9_keep *)
419 FDSE #(
420 .INIT(INIT),
421 .IS_C_INVERTED(IS_C_INVERTED),
422 .IS_D_INVERTED(IS_D_INVERTED),
423 .IS_S_INVERTED(IS_S_INVERTED)
424 ) _TECHMAP_REPLACE_ (
425 .D(D), .Q(Q), .C(C), .CE(CE), .S(S)
426 );
427 `endif
428 endmodule
429 module FDSE_1 (output Q, input C, CE, D, S);
430 parameter [0:0] INIT = 1'b1;
431 `ifdef DFF_MODE
432 wire QQ, $Q;
433 generate if (INIT == 1'b1) begin
434 assign Q = ~QQ;
435 FDRE_1 #(
436 .INIT(1'b0)
437 ) _TECHMAP_REPLACE_ (
438 .D(~D), .Q($Q), .C(C), .CE(CE), .R(S)
439 );
440 end
441 else begin
442 assign Q = QQ;
443 FDSE_1 #(
444 .INIT(1'b0)
445 ) _TECHMAP_REPLACE_ (
446 .D(D), .Q($Q), .C(C), .CE(CE), .S(S)
447 );
448 end endgenerate
449 $__ABC9_FF_ abc_dff (.D($Q), .Q(QQ));
450
451 // Special signals
452 wire [1:0] _TECHMAP_REPLACE_.$abc9_clock = {C, 1'b1 /* IS_C_INVERTED */};
453 wire [0:0] _TECHMAP_REPLACE_.$abc9_init = 1'b0;
454 wire [0:0] _TECHMAP_REPLACE_.$abc9_currQ = QQ;
455 `else
456 (* abc9_keep *)
457 FDSE_1 #(
458 .INIT(INIT)
459 ) _TECHMAP_REPLACE_ (
460 .D(D), .Q(Q), .C(C), .CE(CE), .S(S)
461 );
462 `endif
463 endmodule
464
465 module RAM32X1D (
466 output DPO, SPO,
467 (* techmap_autopurge *) input D,
468 (* techmap_autopurge *) input WCLK,
469 (* techmap_autopurge *) input WE,
470 (* techmap_autopurge *) input A0, A1, A2, A3, A4,
471 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
472 );
473 parameter INIT = 32'h0;
474 parameter IS_WCLK_INVERTED = 1'b0;
475 wire $DPO, $SPO;
476 RAM32X1D #(
477 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
478 ) _TECHMAP_REPLACE_ (
479 .DPO($DPO), .SPO($SPO),
480 .D(D), .WCLK(WCLK), .WE(WE),
481 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4),
482 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4)
483 );
484 $__ABC9_LUT6 spo (.A($SPO), .S({1'b1, A4, A3, A2, A1, A0}), .Y(SPO));
485 $__ABC9_LUT6 dpo (.A($DPO), .S({1'b1, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO));
486 endmodule
487
488 module RAM64X1D (
489 output DPO, SPO,
490 (* techmap_autopurge *) input D,
491 (* techmap_autopurge *) input WCLK,
492 (* techmap_autopurge *) input WE,
493 (* techmap_autopurge *) input A0, A1, A2, A3, A4, A5,
494 (* techmap_autopurge *) input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
495 );
496 parameter INIT = 64'h0;
497 parameter IS_WCLK_INVERTED = 1'b0;
498 wire $DPO, $SPO;
499 RAM64X1D #(
500 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
501 ) _TECHMAP_REPLACE_ (
502 .DPO($DPO), .SPO($SPO),
503 .D(D), .WCLK(WCLK), .WE(WE),
504 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .A4(A4), .A5(A5),
505 .DPRA0(DPRA0), .DPRA1(DPRA1), .DPRA2(DPRA2), .DPRA3(DPRA3), .DPRA4(DPRA4), .DPRA5(DPRA5)
506 );
507 $__ABC9_LUT6 spo (.A($SPO), .S({A5, A4, A3, A2, A1, A0}), .Y(SPO));
508 $__ABC9_LUT6 dpo (.A($DPO), .S({DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0}), .Y(DPO));
509 endmodule
510
511 module RAM128X1D (
512 output DPO, SPO,
513 (* techmap_autopurge *) input D,
514 (* techmap_autopurge *) input WCLK,
515 (* techmap_autopurge *) input WE,
516 (* techmap_autopurge *) input [6:0] A, DPRA
517 );
518 parameter INIT = 128'h0;
519 parameter IS_WCLK_INVERTED = 1'b0;
520 wire $DPO, $SPO;
521 RAM128X1D #(
522 .INIT(INIT), .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
523 ) _TECHMAP_REPLACE_ (
524 .DPO($DPO), .SPO($SPO),
525 .D(D), .WCLK(WCLK), .WE(WE),
526 .A(A),
527 .DPRA(DPRA)
528 );
529 $__ABC9_LUT7 spo (.A($SPO), .S(A), .Y(SPO));
530 $__ABC9_LUT7 dpo (.A($DPO), .S(DPRA), .Y(DPO));
531 endmodule
532
533 module RAM32M (
534 output [1:0] DOA,
535 output [1:0] DOB,
536 output [1:0] DOC,
537 output [1:0] DOD,
538 (* techmap_autopurge *) input [4:0] ADDRA,
539 (* techmap_autopurge *) input [4:0] ADDRB,
540 (* techmap_autopurge *) input [4:0] ADDRC,
541 (* techmap_autopurge *) input [4:0] ADDRD,
542 (* techmap_autopurge *) input [1:0] DIA,
543 (* techmap_autopurge *) input [1:0] DIB,
544 (* techmap_autopurge *) input [1:0] DIC,
545 (* techmap_autopurge *) input [1:0] DID,
546 (* techmap_autopurge *) input WCLK,
547 (* techmap_autopurge *) input WE
548 );
549 parameter [63:0] INIT_A = 64'h0000000000000000;
550 parameter [63:0] INIT_B = 64'h0000000000000000;
551 parameter [63:0] INIT_C = 64'h0000000000000000;
552 parameter [63:0] INIT_D = 64'h0000000000000000;
553 parameter [0:0] IS_WCLK_INVERTED = 1'b0;
554 wire [1:0] $DOA, $DOB, $DOC, $DOD;
555 RAM32M #(
556 .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D),
557 .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
558 ) _TECHMAP_REPLACE_ (
559 .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD),
560 .WCLK(WCLK), .WE(WE),
561 .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD),
562 .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID)
563 );
564 $__ABC9_LUT6 doa0 (.A($DOA[0]), .S({1'b1, ADDRA}), .Y(DOA[0]));
565 $__ABC9_LUT6 doa1 (.A($DOA[1]), .S({1'b1, ADDRA}), .Y(DOA[1]));
566 $__ABC9_LUT6 dob0 (.A($DOB[0]), .S({1'b1, ADDRB}), .Y(DOB[0]));
567 $__ABC9_LUT6 dob1 (.A($DOB[1]), .S({1'b1, ADDRB}), .Y(DOB[1]));
568 $__ABC9_LUT6 doc0 (.A($DOC[0]), .S({1'b1, ADDRC}), .Y(DOC[0]));
569 $__ABC9_LUT6 doc1 (.A($DOC[1]), .S({1'b1, ADDRC}), .Y(DOC[1]));
570 $__ABC9_LUT6 dod0 (.A($DOD[0]), .S({1'b1, ADDRD}), .Y(DOD[0]));
571 $__ABC9_LUT6 dod1 (.A($DOD[1]), .S({1'b1, ADDRD}), .Y(DOD[1]));
572 endmodule
573
574 module RAM64M (
575 output DOA,
576 output DOB,
577 output DOC,
578 output DOD,
579 (* techmap_autopurge *) input [5:0] ADDRA,
580 (* techmap_autopurge *) input [5:0] ADDRB,
581 (* techmap_autopurge *) input [5:0] ADDRC,
582 (* techmap_autopurge *) input [5:0] ADDRD,
583 (* techmap_autopurge *) input DIA,
584 (* techmap_autopurge *) input DIB,
585 (* techmap_autopurge *) input DIC,
586 (* techmap_autopurge *) input DID,
587 (* techmap_autopurge *) input WCLK,
588 (* techmap_autopurge *) input WE
589 );
590 parameter [63:0] INIT_A = 64'h0000000000000000;
591 parameter [63:0] INIT_B = 64'h0000000000000000;
592 parameter [63:0] INIT_C = 64'h0000000000000000;
593 parameter [63:0] INIT_D = 64'h0000000000000000;
594 parameter [0:0] IS_WCLK_INVERTED = 1'b0;
595 wire $DOA, $DOB, $DOC, $DOD;
596 RAM64M #(
597 .INIT_A(INIT_A), .INIT_B(INIT_B), .INIT_C(INIT_C), .INIT_D(INIT_D),
598 .IS_WCLK_INVERTED(IS_WCLK_INVERTED)
599 ) _TECHMAP_REPLACE_ (
600 .DOA($DOA), .DOB($DOB), .DOC($DOC), .DOD($DOD),
601 .WCLK(WCLK), .WE(WE),
602 .ADDRA(ADDRA), .ADDRB(ADDRB), .ADDRC(ADDRC), .ADDRD(ADDRD),
603 .DIA(DIA), .DIB(DIB), .DIC(DIC), .DID(DID)
604 );
605 $__ABC9_LUT6 doa (.A($DOA), .S(ADDRA), .Y(DOA));
606 $__ABC9_LUT6 dob (.A($DOB), .S(ADDRB), .Y(DOB));
607 $__ABC9_LUT6 doc (.A($DOC), .S(ADDRC), .Y(DOC));
608 $__ABC9_LUT6 dod (.A($DOD), .S(ADDRD), .Y(DOD));
609 endmodule
610
611 module SRL16E (
612 output Q,
613 (* techmap_autopurge *) input A0, A1, A2, A3, CE, CLK, D
614 );
615 parameter [15:0] INIT = 16'h0000;
616 parameter [0:0] IS_CLK_INVERTED = 1'b0;
617 wire $Q;
618 SRL16E #(
619 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
620 ) _TECHMAP_REPLACE_ (
621 .Q($Q),
622 .A0(A0), .A1(A1), .A2(A2), .A3(A3), .CE(CE), .CLK(CLK), .D(D)
623 );
624 $__ABC9_LUT6 q (.A($Q), .S({1'b1, A3, A2, A1, A0, 1'b1}), .Y(Q));
625 endmodule
626
627 module SRLC32E (
628 output Q,
629 output Q31,
630 (* techmap_autopurge *) input [4:0] A,
631 (* techmap_autopurge *) input CE, CLK, D
632 );
633 parameter [31:0] INIT = 32'h00000000;
634 parameter [0:0] IS_CLK_INVERTED = 1'b0;
635 wire $Q;
636 SRLC32E #(
637 .INIT(INIT), .IS_CLK_INVERTED(IS_CLK_INVERTED)
638 ) _TECHMAP_REPLACE_ (
639 .Q($Q), .Q31(Q31),
640 .A(A), .CE(CE), .CLK(CLK), .D(D)
641 );
642 $__ABC9_LUT6 q (.A($Q), .S({1'b1, A}), .Y(Q));
643 endmodule
644
645 module DSP48E1 (
646 (* techmap_autopurge *) output [29:0] ACOUT,
647 (* techmap_autopurge *) output [17:0] BCOUT,
648 (* techmap_autopurge *) output reg CARRYCASCOUT,
649 (* techmap_autopurge *) output reg [3:0] CARRYOUT,
650 (* techmap_autopurge *) output reg MULTSIGNOUT,
651 (* techmap_autopurge *) output OVERFLOW,
652 (* techmap_autopurge *) output reg signed [47:0] P,
653 (* techmap_autopurge *) output PATTERNBDETECT,
654 (* techmap_autopurge *) output PATTERNDETECT,
655 (* techmap_autopurge *) output [47:0] PCOUT,
656 (* techmap_autopurge *) output UNDERFLOW,
657 (* techmap_autopurge *) input signed [29:0] A,
658 (* techmap_autopurge *) input [29:0] ACIN,
659 (* techmap_autopurge *) input [3:0] ALUMODE,
660 (* techmap_autopurge *) input signed [17:0] B,
661 (* techmap_autopurge *) input [17:0] BCIN,
662 (* techmap_autopurge *) input [47:0] C,
663 (* techmap_autopurge *) input CARRYCASCIN,
664 (* techmap_autopurge *) input CARRYIN,
665 (* techmap_autopurge *) input [2:0] CARRYINSEL,
666 (* techmap_autopurge *) input CEA1,
667 (* techmap_autopurge *) input CEA2,
668 (* techmap_autopurge *) input CEAD,
669 (* techmap_autopurge *) input CEALUMODE,
670 (* techmap_autopurge *) input CEB1,
671 (* techmap_autopurge *) input CEB2,
672 (* techmap_autopurge *) input CEC,
673 (* techmap_autopurge *) input CECARRYIN,
674 (* techmap_autopurge *) input CECTRL,
675 (* techmap_autopurge *) input CED,
676 (* techmap_autopurge *) input CEINMODE,
677 (* techmap_autopurge *) input CEM,
678 (* techmap_autopurge *) input CEP,
679 (* techmap_autopurge *) input CLK,
680 (* techmap_autopurge *) input [24:0] D,
681 (* techmap_autopurge *) input [4:0] INMODE,
682 (* techmap_autopurge *) input MULTSIGNIN,
683 (* techmap_autopurge *) input [6:0] OPMODE,
684 (* techmap_autopurge *) input [47:0] PCIN,
685 (* techmap_autopurge *) input RSTA,
686 (* techmap_autopurge *) input RSTALLCARRYIN,
687 (* techmap_autopurge *) input RSTALUMODE,
688 (* techmap_autopurge *) input RSTB,
689 (* techmap_autopurge *) input RSTC,
690 (* techmap_autopurge *) input RSTCTRL,
691 (* techmap_autopurge *) input RSTD,
692 (* techmap_autopurge *) input RSTINMODE,
693 (* techmap_autopurge *) input RSTM,
694 (* techmap_autopurge *) input RSTP
695 );
696 parameter integer ACASCREG = 1;
697 parameter integer ADREG = 1;
698 parameter integer ALUMODEREG = 1;
699 parameter integer AREG = 1;
700 parameter AUTORESET_PATDET = "NO_RESET";
701 parameter A_INPUT = "DIRECT";
702 parameter integer BCASCREG = 1;
703 parameter integer BREG = 1;
704 parameter B_INPUT = "DIRECT";
705 parameter integer CARRYINREG = 1;
706 parameter integer CARRYINSELREG = 1;
707 parameter integer CREG = 1;
708 parameter integer DREG = 1;
709 parameter integer INMODEREG = 1;
710 parameter integer MREG = 1;
711 parameter integer OPMODEREG = 1;
712 parameter integer PREG = 1;
713 parameter SEL_MASK = "MASK";
714 parameter SEL_PATTERN = "PATTERN";
715 parameter USE_DPORT = "FALSE";
716 parameter USE_MULT = "MULTIPLY";
717 parameter USE_PATTERN_DETECT = "NO_PATDET";
718 parameter USE_SIMD = "ONE48";
719 parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
720 parameter [47:0] PATTERN = 48'h000000000000;
721 parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
722 parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
723 parameter [0:0] IS_CLK_INVERTED = 1'b0;
724 parameter [4:0] IS_INMODE_INVERTED = 5'b0;
725 parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
726
727 parameter _TECHMAP_CELLTYPE_ = "";
728 localparam techmap_guard = (_TECHMAP_CELLTYPE_ != "");
729
730 `define DSP48E1_INST(__CELL__) """
731 __CELL__ #(
732 .ACASCREG(ACASCREG),
733 .ADREG(ADREG),
734 .ALUMODEREG(ALUMODEREG),
735 .AREG(AREG),
736 .AUTORESET_PATDET(AUTORESET_PATDET),
737 .A_INPUT(A_INPUT),
738 .BCASCREG(BCASCREG),
739 .BREG(BREG),
740 .B_INPUT(B_INPUT),
741 .CARRYINREG(CARRYINREG),
742 .CARRYINSELREG(CARRYINSELREG),
743 .CREG(CREG),
744 .DREG(DREG),
745 .INMODEREG(INMODEREG),
746 .MREG(MREG),
747 .OPMODEREG(OPMODEREG),
748 .PREG(PREG),
749 .SEL_MASK(SEL_MASK),
750 .SEL_PATTERN(SEL_PATTERN),
751 .USE_DPORT(USE_DPORT),
752 .USE_MULT(USE_MULT),
753 .USE_PATTERN_DETECT(USE_PATTERN_DETECT),
754 .USE_SIMD(USE_SIMD),
755 .MASK(MASK),
756 .PATTERN(PATTERN),
757 .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
758 .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
759 .IS_CLK_INVERTED(IS_CLK_INVERTED),
760 .IS_INMODE_INVERTED(IS_INMODE_INVERTED),
761 .IS_OPMODE_INVERTED(IS_OPMODE_INVERTED)
762 ) _TECHMAP_REPLACE_ (
763 .ACOUT(ACOUT),
764 .BCOUT(BCOUT),
765 .CARRYCASCOUT(CARRYCASCOUT),
766 .CARRYOUT(CARRYOUT),
767 .MULTSIGNOUT(MULTSIGNOUT),
768 .OVERFLOW(OVERFLOW),
769 .P(oP),
770 .PATTERNBDETECT(PATTERNBDETECT),
771 .PATTERNDETECT(PATTERNDETECT),
772 .PCOUT(oPCOUT),
773 .UNDERFLOW(UNDERFLOW),
774 .A(iA),
775 .ACIN(ACIN),
776 .ALUMODE(ALUMODE),
777 .B(iB),
778 .BCIN(BCIN),
779 .C(iC),
780 .CARRYCASCIN(CARRYCASCIN),
781 .CARRYIN(CARRYIN),
782 .CARRYINSEL(CARRYINSEL),
783 .CEA1(CEA1),
784 .CEA2(CEA2),
785 .CEAD(CEAD),
786 .CEALUMODE(CEALUMODE),
787 .CEB1(CEB1),
788 .CEB2(CEB2),
789 .CEC(CEC),
790 .CECARRYIN(CECARRYIN),
791 .CECTRL(CECTRL),
792 .CED(CED),
793 .CEINMODE(CEINMODE),
794 .CEM(CEM),
795 .CEP(CEP),
796 .CLK(CLK),
797 .D(iD),
798 .INMODE(INMODE),
799 .MULTSIGNIN(MULTSIGNIN),
800 .OPMODE(OPMODE),
801 .PCIN(PCIN),
802 .RSTA(RSTA),
803 .RSTALLCARRYIN(RSTALLCARRYIN),
804 .RSTALUMODE(RSTALUMODE),
805 .RSTB(RSTB),
806 .RSTC(RSTC),
807 .RSTCTRL(RSTCTRL),
808 .RSTD(RSTD),
809 .RSTINMODE(RSTINMODE),
810 .RSTM(RSTM),
811 .RSTP(RSTP)
812 );
813 """
814
815 wire [29:0] iA;
816 wire [17:0] iB;
817 wire [47:0] iC;
818 wire [24:0] iD;
819
820 wire pA, pB, pC, pD, pAD, pM, pP;
821 wire [47:0] oP, mP;
822 wire [47:0] oPCOUT, mPCOUT;
823
824 generate
825 if (USE_MULT == "MULTIPLY" && USE_DPORT == "FALSE") begin
826 // Disconnect the A-input if MREG is enabled, since
827 // combinatorial path is broken
828 if (AREG == 0 && MREG == 0 && PREG == 0)
829 assign iA = A, pA = 1'bx;
830 else
831 $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
832 if (BREG == 0 && MREG == 0 && PREG == 0)
833 assign iB = B, pB = 1'bx;
834 else
835 $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
836 if (CREG == 0 && PREG == 0)
837 assign iC = C, pC = 1'bx;
838 else
839 $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
840 if (DREG == 0)
841 assign iD = D;
842 else if (techmap_guard)
843 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
844 assign pD = 1'bx;
845 if (ADREG == 1 && techmap_guard)
846 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
847 assign pAD = 1'bx;
848 if (PREG == 0) begin
849 if (MREG == 1)
850 $__ABC9_REG rM (.Q(pM));
851 else
852 assign pM = 1'bx;
853 assign pP = 1'bx;
854 end else begin
855 assign pM = 1'bx;
856 $__ABC9_REG rP (.Q(pP));
857 end
858
859 if (MREG == 0 && PREG == 0)
860 assign mP = oP, mPCOUT = oPCOUT;
861 else
862 assign mP = 1'bx, mPCOUT = 1'bx;
863 $__ABC9_DSP48E1_MULT_P_MUX muxP (
864 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
865 );
866 $__ABC9_DSP48E1_MULT_PCOUT_MUX muxPCOUT (
867 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
868 );
869
870 `DSP48E1_INST($__ABC9_DSP48E1_MULT )
871 end
872 else if (USE_MULT == "MULTIPLY" && USE_DPORT == "TRUE") begin
873 // Disconnect the A-input if MREG is enabled, since
874 // combinatorial path is broken
875 if (AREG == 0 && ADREG == 0 && MREG == 0 && PREG == 0)
876 assign iA = A, pA = 1'bx;
877 else
878 $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
879 if (BREG == 0 && MREG == 0 && PREG == 0)
880 assign iB = B, pB = 1'bx;
881 else
882 $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
883 if (CREG == 0 && PREG == 0)
884 assign iC = C, pC = 1'bx;
885 else
886 $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
887 if (DREG == 0 && ADREG == 0)
888 assign iD = D, pD = 1'bx;
889 else
890 $__ABC9_REG #(.WIDTH(25)) rD (.I(D), .O(iD), .Q(pD));
891 if (PREG == 0) begin
892 if (MREG == 1) begin
893 assign pAD = 1'bx;
894 $__ABC9_REG rM (.Q(pM));
895 end else begin
896 if (ADREG == 1)
897 $__ABC9_REG rAD (.Q(pAD));
898 else
899 assign pAD = 1'bx;
900 assign pM = 1'bx;
901 end
902 assign pP = 1'bx;
903 end else begin
904 assign pAD = 1'bx, pM = 1'bx;
905 $__ABC9_REG rP (.Q(pP));
906 end
907
908 if (MREG == 0 && PREG == 0)
909 assign mP = oP, mPCOUT = oPCOUT;
910 else
911 assign mP = 1'bx, mPCOUT = 1'bx;
912 $__ABC9_DSP48E1_MULT_DPORT_P_MUX muxP (
913 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
914 );
915 $__ABC9_DSP48E1_MULT_DPORT_PCOUT_MUX muxPCOUT (
916 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
917 );
918
919 `DSP48E1_INST($__ABC9_DSP48E1_MULT_DPORT )
920 end
921 else if (USE_MULT == "NONE" && USE_DPORT == "FALSE") begin
922 // Disconnect the A-input if MREG is enabled, since
923 // combinatorial path is broken
924 if (AREG == 0 && PREG == 0)
925 assign iA = A, pA = 1'bx;
926 else
927 $__ABC9_REG #(.WIDTH(30)) rA (.I(A), .O(iA), .Q(pA));
928 if (BREG == 0 && PREG == 0)
929 assign iB = B, pB = 1'bx;
930 else
931 $__ABC9_REG #(.WIDTH(18)) rB (.I(B), .O(iB), .Q(pB));
932 if (CREG == 0 && PREG == 0)
933 assign iC = C, pC = 1'bx;
934 else
935 $__ABC9_REG #(.WIDTH(48)) rC (.I(C), .O(iC), .Q(pC));
936 if (DREG == 1 && techmap_guard)
937 $error("Invalid DSP48E1 configuration: DREG enabled but USE_DPORT == \"FALSE\"");
938 assign pD = 1'bx;
939 if (ADREG == 1 && techmap_guard)
940 $error("Invalid DSP48E1 configuration: ADREG enabled but USE_DPORT == \"FALSE\"");
941 assign pAD = 1'bx;
942 if (MREG == 1 && techmap_guard)
943 $error("Invalid DSP48E1 configuration: MREG enabled but USE_MULT == \"NONE\"");
944 assign pM = 1'bx;
945 if (PREG == 1)
946 $__ABC9_REG rP (.Q(pP));
947 else
948 assign pP = 1'bx;
949
950 if (MREG == 0 && PREG == 0)
951 assign mP = oP, mPCOUT = oPCOUT;
952 else
953 assign mP = 1'bx, mPCOUT = 1'bx;
954 $__ABC9_DSP48E1_P_MUX muxP (
955 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oP), .Mq(pM), .P(mP), .Pq(pP), .O(P)
956 );
957 $__ABC9_DSP48E1_PCOUT_MUX muxPCOUT (
958 .Aq(pA), .Bq(pB), .Cq(pC), .Dq(pD), .ADq(pAD), .I(oPCOUT), .Mq(pM), .P(mPCOUT), .Pq(pP), .O(PCOUT)
959 );
960
961 `DSP48E1_INST($__ABC9_DSP48E1 )
962 end
963 else
964 $error("Invalid DSP48E1 configuration");
965 endgenerate
966 `undef DSP48E1_INST
967 endmodule