2 * yosys -- Yosys Open SYnthesis Suite
4 * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 // See Xilinx UG953 and UG474 for a description of the cell types below.
21 // http://www.xilinx.com/support/documentation/user_guides/ug474_7Series_CLB.pdf
22 // http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_4/ug953-vivado-7series-libraries.pdf
34 (* iopad_external_pin *)
36 parameter IOSTANDARD = "default";
37 parameter IBUF_LOW_PWR = 0;
42 (* iopad_external_pin *)
45 parameter IOSTANDARD = "default";
47 parameter SLEW = "SLOW";
63 (* invertible_pin = "IS_S0_INVERTED" *)
65 (* invertible_pin = "IS_S1_INVERTED" *)
67 (* invertible_pin = "IS_CE0_INVERTED" *)
69 (* invertible_pin = "IS_CE1_INVERTED" *)
71 (* invertible_pin = "IS_IGNORE0_INVERTED" *)
73 (* invertible_pin = "IS_IGNORE1_INVERTED" *)
76 parameter [0:0] INIT_OUT = 1'b0;
77 parameter PRESELECT_I0 = "FALSE";
78 parameter PRESELECT_I1 = "FALSE";
79 parameter [0:0] IS_CE0_INVERTED = 1'b0;
80 parameter [0:0] IS_CE1_INVERTED = 1'b0;
81 parameter [0:0] IS_S0_INVERTED = 1'b0;
82 parameter [0:0] IS_S1_INVERTED = 1'b0;
83 parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
84 parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
86 wire I0_internal = ((CE0 ^ IS_CE0_INVERTED) ? I0 : INIT_OUT);
87 wire I1_internal = ((CE1 ^ IS_CE1_INVERTED) ? I1 : INIT_OUT);
88 wire S0_true = (S0 ^ IS_S0_INVERTED);
89 wire S1_true = (S1 ^ IS_S1_INVERTED);
91 assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
99 (* invertible_pin = "IS_CE_INVERTED" *)
102 parameter [0:0] INIT_OUT = 1'b0;
103 parameter CE_TYPE = "SYNC";
104 parameter [0:0] IS_CE_INVERTED = 1'b0;
106 assign O = ((CE ^ IS_CE_INVERTED) ? I : INIT_OUT);
110 // module OBUFT(output O, input I, T);
111 // assign O = T ? 1'bz : I;
114 // module IOBUF(inout IO, output O, input I, T);
115 // assign O = IO, IO = T ? 1'bz : I;
118 module INV(output O, input I);
122 module LUT1(output O, input I0);
123 parameter [1:0] INIT = 0;
124 assign O = I0 ? INIT[1] : INIT[0];
127 module LUT2(output O, input I0, I1);
128 parameter [3:0] INIT = 0;
129 wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
130 assign O = I0 ? s1[1] : s1[0];
133 module LUT3(output O, input I0, I1, I2);
134 parameter [7:0] INIT = 0;
135 wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
136 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
137 assign O = I0 ? s1[1] : s1[0];
140 module LUT4(output O, input I0, I1, I2, I3);
141 parameter [15:0] INIT = 0;
142 wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
143 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
144 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
145 assign O = I0 ? s1[1] : s1[0];
148 module LUT5(output O, input I0, I1, I2, I3, I4);
149 parameter [31:0] INIT = 0;
150 wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
151 wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
152 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
153 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
154 assign O = I0 ? s1[1] : s1[0];
157 module LUT6(output O, input I0, I1, I2, I3, I4, I5);
158 parameter [63:0] INIT = 0;
159 wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
160 wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
161 wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
162 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
163 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
164 assign O = I0 ? s1[1] : s1[0];
167 module LUT6_2(output O6, output O5, input I0, I1, I2, I3, I4, I5);
168 parameter [63:0] INIT = 0;
169 wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
170 wire [15: 0] s4 = I4 ? s5[31:16] : s5[15: 0];
171 wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
172 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
173 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
174 assign O6 = I0 ? s1[1] : s1[0];
176 wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0];
177 wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0];
178 wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0];
179 wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0];
180 assign O5 = I0 ? s5_1[1] : s5_1[0];
183 module MUXCY(output O, input CI, DI, S);
184 assign O = S ? CI : DI;
187 (* abc_box_id = 1, lib_whitebox *)
188 module MUXF7(output O, input I0, I1, S);
189 assign O = S ? I1 : I0;
192 (* abc_box_id = 2, lib_whitebox *)
193 module MUXF8(output O, input I0, I1, S);
194 assign O = S ? I1 : I0;
197 module XORCY(output O, input CI, LI);
201 (* abc_box_id = 4, lib_whitebox *)
211 assign O = S ^ {CO[2:0], CI | CYINIT};
212 assign CO[0] = S[0] ? CI | CYINIT : DI[0];
213 assign CO[1] = S[1] ? CO[0] : DI[1];
214 assign CO[2] = S[2] ? CO[1] : DI[2];
215 assign CO[3] = S[3] ? CO[2] : DI[3];
218 `ifdef _EXPLICIT_CARRY
220 module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
221 parameter CYINIT_FABRIC = 0;
223 if(CYINIT_FABRIC) begin
224 assign CI_COMBINE = CI_INIT;
226 assign CI_COMBINE = CI;
228 assign CO_CHAIN = S ? CI_COMBINE : DI;
229 assign CO_FABRIC = S ? CI_COMBINE : DI;
230 assign O = S ^ CI_COMBINE;
233 module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
234 assign CO_CHAIN = S ? CI : DI;
235 assign CO_FABRIC = S ? CI : DI;
241 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf#L238-L250
244 (* abc_arrival=303 *)
247 (* invertible_pin = "IS_C_INVERTED" *)
250 (* invertible_pin = "IS_D_INVERTED" *)
252 (* invertible_pin = "IS_R_INVERTED" *)
255 parameter [0:0] INIT = 1'b0;
256 parameter [0:0] IS_C_INVERTED = 1'b0;
257 parameter [0:0] IS_D_INVERTED = 1'b0;
258 parameter [0:0] IS_R_INVERTED = 1'b0;
260 generate case (|IS_C_INVERTED)
261 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
262 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
267 (* abc_arrival=303 *)
270 (* invertible_pin = "IS_C_INVERTED" *)
273 (* invertible_pin = "IS_D_INVERTED" *)
275 (* invertible_pin = "IS_S_INVERTED" *)
278 parameter [0:0] INIT = 1'b1;
279 parameter [0:0] IS_C_INVERTED = 1'b0;
280 parameter [0:0] IS_D_INVERTED = 1'b0;
281 parameter [0:0] IS_S_INVERTED = 1'b0;
283 generate case (|IS_C_INVERTED)
284 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
285 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
290 (* abc_arrival=303 *)
293 (* invertible_pin = "IS_C_INVERTED" *)
296 (* invertible_pin = "IS_D_INVERTED" *)
298 (* invertible_pin = "IS_CLR_INVERTED" *)
301 parameter [0:0] INIT = 1'b0;
302 parameter [0:0] IS_C_INVERTED = 1'b0;
303 parameter [0:0] IS_D_INVERTED = 1'b0;
304 parameter [0:0] IS_CLR_INVERTED = 1'b0;
306 generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED})
307 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
308 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
309 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
310 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
315 (* abc_arrival=303 *)
318 (* invertible_pin = "IS_C_INVERTED" *)
321 (* invertible_pin = "IS_D_INVERTED" *)
323 (* invertible_pin = "IS_PRE_INVERTED" *)
326 parameter [0:0] INIT = 1'b1;
327 parameter [0:0] IS_C_INVERTED = 1'b0;
328 parameter [0:0] IS_D_INVERTED = 1'b0;
329 parameter [0:0] IS_PRE_INVERTED = 1'b0;
331 generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED})
332 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
333 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
334 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
335 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
340 (* abc_arrival=303 *)
346 parameter [0:0] INIT = 1'b0;
348 always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
352 (* abc_arrival=303 *)
358 parameter [0:0] INIT = 1'b1;
360 always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
364 (* abc_arrival=303 *)
370 parameter [0:0] INIT = 1'b0;
372 always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
376 (* abc_arrival=303 *)
382 parameter [0:0] INIT = 1'b1;
384 always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
388 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
389 (* abc_arrival=1153 *)
393 (* invertible_pin = "IS_WCLK_INVERTED" *)
396 input A0, A1, A2, A3, A4,
397 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
399 parameter INIT = 32'h0;
400 parameter IS_WCLK_INVERTED = 1'b0;
401 wire [4:0] a = {A4, A3, A2, A1, A0};
402 wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
403 reg [31:0] mem = INIT;
405 assign DPO = mem[dpra];
406 wire clk = WCLK ^ IS_WCLK_INVERTED;
407 always @(posedge clk) if (WE) mem[a] <= D;
411 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
412 (* abc_arrival=1153 *)
416 (* invertible_pin = "IS_WCLK_INVERTED" *)
419 input A0, A1, A2, A3, A4, A5,
420 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
422 parameter INIT = 64'h0;
423 parameter IS_WCLK_INVERTED = 1'b0;
424 wire [5:0] a = {A5, A4, A3, A2, A1, A0};
425 wire [5:0] dpra = {DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
426 reg [63:0] mem = INIT;
428 assign DPO = mem[dpra];
429 wire clk = WCLK ^ IS_WCLK_INVERTED;
430 always @(posedge clk) if (WE) mem[a] <= D;
434 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L957
435 (* abc_arrival=1153 *)
439 (* invertible_pin = "IS_WCLK_INVERTED" *)
444 parameter INIT = 128'h0;
445 parameter IS_WCLK_INVERTED = 1'b0;
446 reg [127:0] mem = INIT;
448 assign DPO = mem[DPRA];
449 wire clk = WCLK ^ IS_WCLK_INVERTED;
450 always @(posedge clk) if (WE) mem[A] <= D;
454 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
455 (* abc_arrival=1472 *)
457 input A0, A1, A2, A3, CE,
459 (* invertible_pin = "IS_CLK_INVERTED" *)
463 parameter [15:0] INIT = 16'h0000;
464 parameter [0:0] IS_CLK_INVERTED = 1'b0;
467 assign Q = r[{A3,A2,A1,A0}];
469 if (IS_CLK_INVERTED) begin
470 always @(negedge CLK) if (CE) r <= { r[14:0], D };
473 always @(posedge CLK) if (CE) r <= { r[14:0], D };
480 input A0, A1, A2, A3, CE,
482 (* invertible_pin = "IS_CLK_INVERTED" *)
486 parameter [15:0] INIT = 16'h0000;
487 parameter [0:0] IS_CLK_INVERTED = 1'b0;
491 assign Q = r[{A3,A2,A1,A0}];
493 if (IS_CLK_INVERTED) begin
494 always @(negedge CLK) if (CE) r <= { r[14:0], D };
497 always @(posedge CLK) if (CE) r <= { r[14:0], D };
502 // Max delay from: https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLM_R.sdf#L904-L905
503 (* abc_arrival=1472 *)
505 (* abc_arrival=1114 *)
510 (* invertible_pin = "IS_CLK_INVERTED" *)
514 parameter [31:0] INIT = 32'h00000000;
515 parameter [0:0] IS_CLK_INVERTED = 1'b0;
521 if (IS_CLK_INVERTED) begin
522 always @(negedge CLK) if (CE) r <= { r[30:0], D };
525 always @(posedge CLK) if (CE) r <= { r[30:0], D };
532 output reg CARRYCASCOUT,
533 output reg [3:0] CARRYOUT,
534 output reg MULTSIGNOUT,
536 output reg signed [47:0] P,
537 output reg PATTERNBDETECT,
538 output reg PATTERNDETECT,
541 input signed [29:0] A,
544 input signed [17:0] B,
549 input [2:0] CARRYINSEL,
563 (* clkbuf_sink *) input CLK,
580 parameter integer ACASCREG = 1;
581 parameter integer ADREG = 1;
582 parameter integer ALUMODEREG = 1;
583 parameter integer AREG = 1;
584 parameter AUTORESET_PATDET = "NO_RESET";
585 parameter A_INPUT = "DIRECT";
586 parameter integer BCASCREG = 1;
587 parameter integer BREG = 1;
588 parameter B_INPUT = "DIRECT";
589 parameter integer CARRYINREG = 1;
590 parameter integer CARRYINSELREG = 1;
591 parameter integer CREG = 1;
592 parameter integer DREG = 1;
593 parameter integer INMODEREG = 1;
594 parameter integer MREG = 1;
595 parameter integer OPMODEREG = 1;
596 parameter integer PREG = 1;
597 parameter SEL_MASK = "MASK";
598 parameter SEL_PATTERN = "PATTERN";
599 parameter USE_DPORT = "FALSE";
600 parameter USE_MULT = "MULTIPLY";
601 parameter USE_PATTERN_DETECT = "NO_PATDET";
602 parameter USE_SIMD = "ONE48";
603 parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
604 parameter [47:0] PATTERN = 48'h000000000000;
605 parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
606 parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
607 parameter [0:0] IS_CLK_INVERTED = 1'b0;
608 parameter [4:0] IS_INMODE_INVERTED = 5'b0;
609 parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
613 if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value");
614 if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value");
615 if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value");
616 if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12") $fatal(1, "Unsupported USE_SIMD value");
617 if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
618 if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value");
619 if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value");
620 if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value");
621 if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value");
625 wire signed [29:0] A_muxed;
626 wire signed [17:0] B_muxed;
629 if (A_INPUT == "CASCADE") assign A_muxed = ACIN;
630 else assign A_muxed = A;
632 if (B_INPUT == "CASCADE") assign B_muxed = BCIN;
633 else assign B_muxed = B;
636 reg signed [29:0] Ar1, Ar2;
637 reg signed [24:0] Dr;
638 reg signed [17:0] Br1, Br2;
639 reg signed [47:0] Cr;
640 reg [4:0] INMODEr = 5'b0;
641 reg [6:0] OPMODEr = 7'b0;
642 reg [3:0] ALUMODEr = 4'b0;
643 reg [2:0] CARRYINSELr = 3'b0;
646 // Configurable A register
650 always @(posedge CLK)
655 if (CEA1) Ar1 <= A_muxed;
656 if (CEA2) Ar2 <= Ar1;
658 end else if (AREG == 1) begin
659 //initial Ar1 = 30'b0;
661 always @(posedge CLK)
666 if (CEA1) Ar1 <= A_muxed;
667 if (CEA2) Ar2 <= A_muxed;
670 always @* Ar1 <= A_muxed;
671 always @* Ar2 <= A_muxed;
674 // Configurable B register
678 always @(posedge CLK)
683 if (CEB1) Br1 <= B_muxed;
684 if (CEB2) Br2 <= Br1;
686 end else if (BREG == 1) begin
687 //initial Br1 = 25'b0;
689 always @(posedge CLK)
694 if (CEB1) Br1 <= B_muxed;
695 if (CEB2) Br2 <= B_muxed;
698 always @* Br1 <= B_muxed;
699 always @* Br2 <= B_muxed;
703 if (CREG == 1) initial Cr = 48'b0;
704 if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end
705 else always @* Cr <= C;
707 if (CREG == 1) initial Dr = 25'b0;
708 if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end
709 else always @* Dr <= D;
712 if (INMODEREG == 1) initial INMODEr = 5'b0;
713 if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end
714 else always @* INMODEr <= INMODE;
715 if (OPMODEREG == 1) initial OPMODEr = 7'b0;
716 if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end
717 else always @* OPMODEr <= OPMODE;
718 if (ALUMODEREG == 1) initial ALUMODEr = 4'b0;
719 if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end
720 else always @* ALUMODEr <= ALUMODE;
721 if (CARRYINSELREG == 1) initial CARRYINSELr = 3'b0;
722 if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end
723 else always @* CARRYINSELr <= CARRYINSEL;
728 if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1;
729 else assign ACOUT = Ar2;
730 if (BCASCREG == 1 && BREG == 2) assign BCOUT = Br1;
731 else assign BCOUT = Br2;
734 // A/D input selection and pre-adder
735 wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2;
736 wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed;
737 wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0;
738 wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated);
739 reg signed [24:0] ADr;
742 if (ADREG == 1) initial ADr = 25'b0;
743 if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end
744 else always @* ADr <= AD_result;
748 wire signed [24:0] A_MULT;
749 wire signed [17:0] B_MULT = INMODEr[4] ? Br1 : Br2;
751 if (USE_DPORT == "TRUE") assign A_MULT = ADr;
752 else assign A_MULT = Ar12_gated;
755 wire signed [42:0] M = A_MULT * B_MULT;
756 wire signed [42:0] Mx = (CARRYINSEL == 3'b010) ? 43'bx : M;
757 reg signed [42:0] Mr = 43'b0;
759 // Multiplier result register
761 if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= Mx; end
762 else always @* Mr <= Mx;
765 wire signed [42:0] Mrx = (CARRYINSELr == 3'b010) ? 43'bx : Mr;
767 // X, Y and Z ALU inputs
768 reg signed [47:0] X, Y, Z;
774 2'b01: begin X = $signed(Mrx);
776 if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01");
781 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
784 2'b11: X = $signed({Ar2, Br2});
791 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling?
793 if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01");
796 2'b10: Y = {48{1'b1}};
807 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010");
813 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
814 if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
817 3'b101: Z = $signed(PCIN[47:17]);
818 3'b110: Z = $signed(P[47:17]);
824 wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17];
825 reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0;
827 if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end
828 else always @* CARRYINr = CARRYIN;
830 if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end
831 else always @* A24_xnor_B17 = A24_xnor_B17d;
838 3'b000: cin_muxed = CARRYINr;
839 3'b001: cin_muxed = ~PCIN[47];
840 3'b010: cin_muxed = CARRYCASCIN;
841 3'b011: cin_muxed = PCIN[47];
842 3'b100: cin_muxed = CARRYCASCOUT;
843 3'b101: cin_muxed = ~P[47];
844 3'b110: cin_muxed = A24_xnor_B17;
845 3'b111: cin_muxed = P[47];
846 default: cin_muxed = 1'bx;
850 wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed;
853 wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z;
854 wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv;
855 wire [47:0] maj_xyz = (X & Y) | (X & Z_muxinv) | (Y & Z_muxinv);
857 wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz;
858 wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 : maj_xyz;
860 wire [48:0] maj_xyz_simd_gated;
861 wire [3:0] int_carry_in, int_carry_out, ext_carry_out;
863 assign int_carry_in[0] = 1'b0;
864 wire [3:0] carryout_reset;
867 if (USE_SIMD == "FOUR12") begin
868 assign maj_xyz_simd_gated = {
869 maj_xyz_gated[47:36],
870 1'b0, maj_xyz_gated[34:24],
871 1'b0, maj_xyz_gated[22:12],
872 1'b0, maj_xyz_gated[10:0],
875 assign int_carry_in[3:1] = 3'b000;
876 assign ext_carry_out = {
878 maj_xyz_gated[35] ^ int_carry_out[2],
879 maj_xyz_gated[23] ^ int_carry_out[1],
880 maj_xyz_gated[11] ^ int_carry_out[0]
882 assign carryout_reset = 4'b0000;
883 end else if (USE_SIMD == "TWO24") begin
884 assign maj_xyz_simd_gated = {
885 maj_xyz_gated[47:24],
886 1'b0, maj_xyz_gated[22:0],
889 assign int_carry_in[3:1] = {int_carry_out[2], 1'b0, int_carry_out[0]};
890 assign ext_carry_out = {
893 maj_xyz_gated[23] ^ int_carry_out[1],
896 assign carryout_reset = 4'b0x0x;
898 assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin};
899 assign int_carry_in[3:1] = int_carry_out[2:0];
900 assign ext_carry_out = {
904 assign carryout_reset = 4'b0xxx;
908 for (i = 0; i < 4; i = i + 1)
909 assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]}
910 + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i];
913 wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum;
914 wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx :
915 ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out);
916 wire CARRYCASCOUTd = ext_carry_out[3];
917 wire MULTSIGNOUTd = Mrx[42];
922 initial CARRYOUT = carryout_reset;
923 initial CARRYCASCOUT = 1'b0;
924 initial MULTSIGNOUT = 1'b0;
925 always @(posedge CLK)
928 CARRYOUT <= carryout_reset;
929 CARRYCASCOUT <= 1'b0;
931 end else if (CEP) begin
933 CARRYOUT <= CARRYOUTd;
934 CARRYCASCOUT <= CARRYCASCOUTd;
935 MULTSIGNOUT <= MULTSIGNOUTd;
940 CARRYOUT = CARRYOUTd;
941 CARRYCASCOUT = CARRYCASCOUTd;
942 MULTSIGNOUT = MULTSIGNOUTd;
950 wire PATTERNDETECTd, PATTERNBDETECTd;
952 if (USE_PATTERN_DETECT == "PATDET") begin
953 // TODO: Support SEL_PATTERN != "PATTERN" and SEL_MASK != "MASK
954 assign PATTERNDETECTd = &(~(Pd ^ PATTERN) | MASK);
955 assign PATTERNBDETECTd = &((Pd ^ PATTERN) | MASK);
957 assign PATTERNDETECTd = 1'b1;
958 assign PATTERNBDETECTd = 1'b1;
962 reg PATTERNDETECTPAST, PATTERNBDETECTPAST;
963 initial PATTERNDETECT = 1'b0;
964 initial PATTERNBDETECT = 1'b0;
965 initial PATTERNDETECTPAST = 1'b0;
966 initial PATTERNBDETECTPAST = 1'b0;
967 always @(posedge CLK)
969 PATTERNDETECT <= 1'b0;
970 PATTERNBDETECT <= 1'b0;
971 PATTERNDETECTPAST <= 1'b0;
972 PATTERNBDETECTPAST <= 1'b0;
973 end else if (CEP) begin
974 PATTERNDETECT <= PATTERNDETECTd;
975 PATTERNBDETECT <= PATTERNBDETECTd;
976 PATTERNDETECTPAST <= PATTERNDETECT;
977 PATTERNBDETECTPAST <= PATTERNBDETECT;
979 assign OVERFLOW = &{PATTERNDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT};
980 assign UNDERFLOW = &{PATTERNBDETECTPAST, ~PATTERNBDETECT, ~PATTERNDETECT};
983 PATTERNDETECT = PATTERNDETECTd;
984 PATTERNBDETECT = PATTERNBDETECTd;
986 assign OVERFLOW = 1'bx, UNDERFLOW = 1'bx;