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";
65 input IGNORE0, input IGNORE1);
67 parameter [0:0] INIT_OUT = 1'b0;
68 parameter PRESELECT_I0 = "FALSE";
69 parameter PRESELECT_I1 = "FALSE";
70 parameter [0:0] IS_CE0_INVERTED = 1'b0;
71 parameter [0:0] IS_CE1_INVERTED = 1'b0;
72 parameter [0:0] IS_S0_INVERTED = 1'b0;
73 parameter [0:0] IS_S1_INVERTED = 1'b0;
74 parameter [0:0] IS_IGNORE0_INVERTED = 1'b0;
75 parameter [0:0] IS_IGNORE1_INVERTED = 1'b0;
77 wire I0_internal = ((CE0 ^ IS_CE0_INVERTED) ? I0 : INIT_OUT);
78 wire I1_internal = ((CE1 ^ IS_CE1_INVERTED) ? I1 : INIT_OUT);
79 wire S0_true = (S0 ^ IS_S0_INVERTED);
80 wire S1_true = (S1 ^ IS_S1_INVERTED);
82 assign O = S0_true ? I0_internal : (S1_true ? I1_internal : INIT_OUT);
92 parameter [0:0] INIT_OUT = 1'b0;
93 parameter CE_TYPE = "SYNC";
94 parameter [0:0] IS_CE_INVERTED = 1'b0;
96 assign O = ((CE ^ IS_CE_INVERTED) ? I : INIT_OUT);
100 // module OBUFT(output O, input I, T);
101 // assign O = T ? 1'bz : I;
104 // module IOBUF(inout IO, output O, input I, T);
105 // assign O = IO, IO = T ? 1'bz : I;
108 module INV(output O, input I);
112 module LUT1(output O, input I0);
113 parameter [1:0] INIT = 0;
114 assign O = I0 ? INIT[1] : INIT[0];
117 module LUT2(output O, input I0, I1);
118 parameter [3:0] INIT = 0;
119 wire [ 1: 0] s1 = I1 ? INIT[ 3: 2] : INIT[ 1: 0];
120 assign O = I0 ? s1[1] : s1[0];
123 module LUT3(output O, input I0, I1, I2);
124 parameter [7:0] INIT = 0;
125 wire [ 3: 0] s2 = I2 ? INIT[ 7: 4] : INIT[ 3: 0];
126 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
127 assign O = I0 ? s1[1] : s1[0];
130 module LUT4(output O, input I0, I1, I2, I3);
131 parameter [15:0] INIT = 0;
132 wire [ 7: 0] s3 = I3 ? INIT[15: 8] : INIT[ 7: 0];
133 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
134 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
135 assign O = I0 ? s1[1] : s1[0];
138 module LUT5(output O, input I0, I1, I2, I3, I4);
139 parameter [31:0] INIT = 0;
140 wire [15: 0] s4 = I4 ? INIT[31:16] : INIT[15: 0];
141 wire [ 7: 0] s3 = I3 ? s4[15: 8] : s4[ 7: 0];
142 wire [ 3: 0] s2 = I2 ? s3[ 7: 4] : s3[ 3: 0];
143 wire [ 1: 0] s1 = I1 ? s2[ 3: 2] : s2[ 1: 0];
144 assign O = I0 ? s1[1] : s1[0];
147 module LUT6(output O, input I0, I1, I2, I3, I4, I5);
148 parameter [63:0] INIT = 0;
149 wire [31: 0] s5 = I5 ? INIT[63:32] : INIT[31: 0];
150 wire [15: 0] s4 = I4 ? s5[31:16] : s5[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_2(output O6, output O5, 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 O6 = I0 ? s1[1] : s1[0];
166 wire [15: 0] s5_4 = I4 ? INIT[31:16] : INIT[15: 0];
167 wire [ 7: 0] s5_3 = I3 ? s5_4[15: 8] : s5_4[ 7: 0];
168 wire [ 3: 0] s5_2 = I2 ? s5_3[ 7: 4] : s5_3[ 3: 0];
169 wire [ 1: 0] s5_1 = I1 ? s5_2[ 3: 2] : s5_2[ 1: 0];
170 assign O5 = I0 ? s5_1[1] : s5_1[0];
173 module MUXCY(output O, input CI, DI, S);
174 assign O = S ? CI : DI;
177 (* abc_box_id = 1, lib_whitebox *)
178 module MUXF7(output O, input I0, I1, S);
179 assign O = S ? I1 : I0;
182 (* abc_box_id = 2, lib_whitebox *)
183 module MUXF8(output O, input I0, I1, S);
184 assign O = S ? I1 : I0;
188 (* abc_box_id = 3, lib_whitebox *)
189 module \$__XILINX_MUXF78 (output O, input I0, I1, I2, I3, S0, S1);
190 assign O = S1 ? (S0 ? I3 : I2)
195 module XORCY(output O, input CI, LI);
199 (* abc_box_id = 4, lib_whitebox *)
209 assign O = S ^ {CO[2:0], CI | CYINIT};
210 assign CO[0] = S[0] ? CI | CYINIT : DI[0];
211 assign CO[1] = S[1] ? CO[0] : DI[1];
212 assign CO[2] = S[2] ? CO[1] : DI[2];
213 assign CO[3] = S[3] ? CO[2] : DI[3];
216 `ifdef _EXPLICIT_CARRY
218 module CARRY0(output CO_CHAIN, CO_FABRIC, O, input CI, CI_INIT, DI, S);
219 parameter CYINIT_FABRIC = 0;
221 if(CYINIT_FABRIC) begin
222 assign CI_COMBINE = CI_INIT;
224 assign CI_COMBINE = CI;
226 assign CO_CHAIN = S ? CI_COMBINE : DI;
227 assign CO_FABRIC = S ? CI_COMBINE : DI;
228 assign O = S ^ CI_COMBINE;
231 module CARRY(output CO_CHAIN, CO_FABRIC, O, input CI, DI, S);
232 assign CO_CHAIN = S ? CI : DI;
233 assign CO_FABRIC = S ? CI : DI;
239 module FDRE (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
240 parameter [0:0] INIT = 1'b0;
241 parameter [0:0] IS_C_INVERTED = 1'b0;
242 parameter [0:0] IS_D_INVERTED = 1'b0;
243 parameter [0:0] IS_R_INVERTED = 1'b0;
245 generate case (|IS_C_INVERTED)
246 1'b0: always @(posedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
247 1'b1: always @(negedge C) if (R == !IS_R_INVERTED) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
251 module FDSE (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
252 parameter [0:0] INIT = 1'b1;
253 parameter [0:0] IS_C_INVERTED = 1'b0;
254 parameter [0:0] IS_D_INVERTED = 1'b0;
255 parameter [0:0] IS_S_INVERTED = 1'b0;
257 generate case (|IS_C_INVERTED)
258 1'b0: always @(posedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
259 1'b1: always @(negedge C) if (S == !IS_S_INVERTED) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
263 module FDCE (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
264 parameter [0:0] INIT = 1'b0;
265 parameter [0:0] IS_C_INVERTED = 1'b0;
266 parameter [0:0] IS_D_INVERTED = 1'b0;
267 parameter [0:0] IS_CLR_INVERTED = 1'b0;
269 generate case ({|IS_C_INVERTED, |IS_CLR_INVERTED})
270 2'b00: always @(posedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
271 2'b01: always @(posedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
272 2'b10: always @(negedge C, posedge CLR) if ( CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
273 2'b11: always @(negedge C, negedge CLR) if (!CLR) Q <= 1'b0; else if (CE) Q <= D ^ IS_D_INVERTED;
277 module FDPE (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
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_PRE_INVERTED = 1'b0;
283 generate case ({|IS_C_INVERTED, |IS_PRE_INVERTED})
284 2'b00: always @(posedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
285 2'b01: always @(posedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
286 2'b10: always @(negedge C, posedge PRE) if ( PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
287 2'b11: always @(negedge C, negedge PRE) if (!PRE) Q <= 1'b1; else if (CE) Q <= D ^ IS_D_INVERTED;
291 module FDRE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, R);
292 parameter [0:0] INIT = 1'b0;
294 always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
297 module FDSE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, S);
298 parameter [0:0] INIT = 1'b1;
300 always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
303 module FDCE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, CLR);
304 parameter [0:0] INIT = 1'b0;
306 always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
309 module FDPE_1 (output reg Q, (* clkbuf_sink *) input C, input CE, D, PRE);
310 parameter [0:0] INIT = 1'b1;
312 always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
324 input A0, A1, A2, A3, A4,
325 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4
327 parameter INIT = 32'h0;
328 parameter IS_WCLK_INVERTED = 1'b0;
329 wire [4:0] a = {A4, A3, A2, A1, A0};
330 wire [4:0] dpra = {DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
331 reg [31:0] mem = INIT;
333 assign DPO = mem[dpra];
334 wire clk = WCLK ^ IS_WCLK_INVERTED;
335 always @(posedge clk) if (WE) mem[a] <= D;
347 input A0, A1, A2, A3, A4, A5,
348 input DPRA0, DPRA1, DPRA2, DPRA3, DPRA4, DPRA5
350 parameter INIT = 64'h0;
351 parameter IS_WCLK_INVERTED = 1'b0;
352 wire [5:0] a = {A5, A4, A3, A2, A1, A0};
353 wire [5:0] dpra = {DPRA5, DPRA4, DPRA3, DPRA2, DPRA1, DPRA0};
354 reg [63:0] mem = INIT;
356 assign DPO = mem[dpra];
357 wire clk = WCLK ^ IS_WCLK_INVERTED;
358 always @(posedge clk) if (WE) mem[a] <= D;
372 parameter INIT = 128'h0;
373 parameter IS_WCLK_INVERTED = 1'b0;
374 reg [127:0] mem = INIT;
376 assign DPO = mem[DPRA];
377 wire clk = WCLK ^ IS_WCLK_INVERTED;
378 always @(posedge clk) if (WE) mem[A] <= D;
383 input A0, A1, A2, A3, CE,
388 parameter [15:0] INIT = 16'h0000;
389 parameter [0:0] IS_CLK_INVERTED = 1'b0;
392 assign Q = r[{A3,A2,A1,A0}];
394 if (IS_CLK_INVERTED) begin
395 always @(negedge CLK) if (CE) r <= { r[14:0], D };
398 always @(posedge CLK) if (CE) r <= { r[14:0], D };
405 input A0, A1, A2, A3, CE,
410 parameter [15:0] INIT = 16'h0000;
411 parameter [0:0] IS_CLK_INVERTED = 1'b0;
415 assign Q = r[{A3,A2,A1,A0}];
417 if (IS_CLK_INVERTED) begin
418 always @(negedge CLK) if (CE) r <= { r[14:0], D };
421 always @(posedge CLK) if (CE) r <= { r[14:0], D };
434 parameter [31:0] INIT = 32'h00000000;
435 parameter [0:0] IS_CLK_INVERTED = 1'b0;
441 if (IS_CLK_INVERTED) begin
442 always @(negedge CLK) if (CE) r <= { r[30:0], D };
445 always @(posedge CLK) if (CE) r <= { r[30:0], D };
452 output reg CARRYCASCOUT,
453 output reg [3:0] CARRYOUT,
454 output reg MULTSIGNOUT,
456 output reg signed [47:0] P,
457 output PATTERNBDETECT,
458 output PATTERNDETECT,
461 input signed [29:0] A,
464 input signed [17:0] B,
469 input [2:0] CARRYINSEL,
483 (* clkbuf_sink *) input CLK,
500 parameter integer ACASCREG = 1;
501 parameter integer ADREG = 1;
502 parameter integer ALUMODEREG = 1;
503 parameter integer AREG = 1;
504 parameter AUTORESET_PATDET = "NO_RESET";
505 parameter A_INPUT = "DIRECT";
506 parameter integer BCASCREG = 1;
507 parameter integer BREG = 1;
508 parameter B_INPUT = "DIRECT";
509 parameter integer CARRYINREG = 1;
510 parameter integer CARRYINSELREG = 1;
511 parameter integer CREG = 1;
512 parameter integer DREG = 1;
513 parameter integer INMODEREG = 1;
514 parameter integer MREG = 1;
515 parameter integer OPMODEREG = 1;
516 parameter integer PREG = 1;
517 parameter SEL_MASK = "MASK";
518 parameter SEL_PATTERN = "PATTERN";
519 parameter USE_DPORT = "FALSE";
520 parameter USE_MULT = "MULTIPLY";
521 parameter USE_PATTERN_DETECT = "NO_PATDET";
522 parameter USE_SIMD = "ONE48";
523 parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
524 parameter [47:0] PATTERN = 48'h000000000000;
525 parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
526 parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
527 parameter [0:0] IS_CLK_INVERTED = 1'b0;
528 parameter [4:0] IS_INMODE_INVERTED = 5'b0;
529 parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
533 if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value");
534 //if (PREG != 0) $fatal(1, "Unsupported PREG value");
535 if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value");
536 if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value");
537 if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value");
538 if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12") $fatal(1, "Unsupported USE_SIMD value");
539 if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
540 if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value");
541 if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value");
542 if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value");
543 if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value");
547 wire signed [29:0] A_muxed;
548 wire signed [17:0] B_muxed;
551 if (A_INPUT == "CASCADE") assign A_muxed = ACIN;
552 else assign A_muxed = A;
554 if (B_INPUT == "CASCADE") assign B_muxed = BCIN;
555 else assign B_muxed = B;
558 reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0;
559 reg signed [24:0] Dr = 25'b0;
560 reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0;
561 reg signed [47:0] Cr = 48'b0;
562 reg [4:0] INMODEr = 5'b0;
563 reg [6:0] OPMODEr = 7'b0;
564 reg [3:0] ALUMODEr = 4'b0;
565 reg [2:0] CARRYINSELr = 3'b0;
568 // Configurable A register
570 always @(posedge CLK)
575 if (CEA1) Ar1 <= A_muxed;
576 if (CEA2) Ar2 <= Ar1;
578 end else if (AREG == 1) begin
579 always @(posedge CLK)
584 if (CEA1) Ar1 <= A_muxed;
585 if (CEA2) Ar2 <= A_muxed;
588 always @* Ar1 <= A_muxed;
589 always @* Ar2 <= A_muxed;
592 // Configurable B register
594 always @(posedge CLK)
599 if (CEB1) Br1 <= B_muxed;
600 if (CEB2) Br2 <= Br1;
602 end else if (BREG == 1) begin
603 always @(posedge CLK)
608 if (CEB1) Br1 <= B_muxed;
609 if (CEB2) Br2 <= B_muxed;
612 always @* Br1 <= B_muxed;
613 always @* Br2 <= B_muxed;
617 if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end
618 else always @* Cr <= C;
620 if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end
621 else always @* Dr <= D;
624 if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end
625 else always @* INMODEr <= INMODE;
626 if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end
627 else always @* OPMODEr <= OPMODE;
628 if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end
629 else always @* ALUMODEr <= ALUMODE;
630 if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end
631 else always @* CARRYINSELr <= CARRYINSEL;
636 if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1;
637 else assign ACOUT = Ar2;
638 if (BCASCREG == 1 && BREG == 2) assign BCOUT = Br1;
639 else assign BCOUT = Br2;
642 // A/D input selection and pre-adder
643 wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2;
644 wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed;
645 wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0;
646 wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated);
647 reg signed [24:0] ADr = 25'b0;
650 if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end
651 else always @* ADr <= AD_result;
655 wire signed [24:0] A_MULT;
656 wire signed [17:0] B_MULT = INMODEr[4] ? Br1 : Br2;
658 if (USE_DPORT == "TRUE") assign A_MULT = ADr;
659 else assign A_MULT = Ar12_gated;
662 wire signed [42:0] M = A_MULT * B_MULT;
663 wire signed [42:0] Mx = (CARRYINSEL == 3'b010) ? 43'bx : M;
664 reg signed [42:0] Mr = 43'b0;
666 // Multiplier result register
668 if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= Mx; end
669 else always @* Mr <= Mx;
672 wire signed [42:0] Mrx = (CARRYINSELr == 3'b010) ? 43'bx : Mr;
674 // X, Y and Z ALU inputs
675 reg signed [47:0] X, Y, Z;
681 2'b01: begin X = $signed(Mrx);
683 if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01");
688 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
691 2'b11: X = $signed({Ar2, Br2});
698 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling?
700 if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01");
703 2'b10: Y = {48{1'b1}};
714 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010");
720 if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
721 if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
724 3'b101: Z = $signed(PCIN[47:17]);
725 3'b110: Z = $signed(P[47:17]);
731 wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17];
732 reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0;
734 if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end
735 else always @* CARRYINr = CARRYIN;
737 if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end
738 else always @* A24_xnor_B17 = A24_xnor_B17d;
745 3'b000: cin_muxed = CARRYINr;
746 3'b001: cin_muxed = ~PCIN[47];
747 3'b010: cin_muxed = CARRYCASCIN;
748 3'b011: cin_muxed = PCIN[47];
749 3'b100: cin_muxed = CARRYCASCOUT;
750 3'b101: cin_muxed = ~P[47];
751 3'b110: cin_muxed = A24_xnor_B17;
752 3'b111: cin_muxed = P[47];
753 default: cin_muxed = 1'bx;
757 wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed;
760 wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z;
761 wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv;
762 wire [47:0] maj_xyz = (X & Y) | (X & Z_muxinv) | (Y & Z_muxinv);
764 wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz;
765 wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 : maj_xyz;
767 wire [48:0] maj_xyz_simd_gated;
768 wire [3:0] int_carry_in, int_carry_out, ext_carry_out;
770 assign int_carry_in[0] = 1'b0;
771 wire [3:0] carryout_reset;
774 if (USE_SIMD == "FOUR12") begin
775 assign maj_xyz_simd_gated = {
776 maj_xyz_gated[47:36],
777 1'b0, maj_xyz_gated[34:24],
778 1'b0, maj_xyz_gated[22:12],
779 1'b0, maj_xyz_gated[10:0],
782 assign int_carry_in[3:1] = 3'b000;
783 assign ext_carry_out = {
785 maj_xyz_gated[35] ^ int_carry_out[2],
786 maj_xyz_gated[23] ^ int_carry_out[1],
787 maj_xyz_gated[11] ^ int_carry_out[0]
789 assign carryout_reset = 4'b0000;
790 end else if (USE_SIMD == "TWO24") begin
791 assign maj_xyz_simd_gated = {
792 maj_xyz_gated[47:24],
793 1'b0, maj_xyz_gated[22:0],
796 assign int_carry_in[3:1] = {int_carry_out[2], 1'b0, int_carry_out[0]};
797 assign ext_carry_out = {
800 maj_xyz_gated[23] ^ int_carry_out[1],
803 assign carryout_reset = 4'b0x0x;
805 assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin};
806 assign int_carry_in[3:1] = int_carry_out[2:0];
807 assign ext_carry_out = {
811 assign carryout_reset = 4'b0xxx;
815 for (i = 0; i < 4; i = i + 1)
816 assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]}
817 + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i];
820 wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum;
822 initial CARRYOUT = carryout_reset;
823 initial CARRYCASCOUT = 1'b0;
824 initial MULTSIGNOUT = 1'b0;
825 wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx :
826 ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out);
827 wire CARRYCASCOUTd = ext_carry_out[3];
828 wire MULTSIGNOUTd = Mrx[42];
832 always @(posedge CLK)
835 CARRYOUT <= carryout_reset;
836 CARRYCASCOUT <= 1'b0;
838 end else if (CEP) begin
840 CARRYOUT <= CARRYOUTd;
841 CARRYCASCOUT <= CARRYCASCOUTd;
842 MULTSIGNOUT <= MULTSIGNOUTd;
847 CARRYOUT = CARRYOUTd;
848 CARRYCASCOUT = CARRYCASCOUTd;
849 MULTSIGNOUT = MULTSIGNOUTd;