1// The core logic primitive of the Cyclone V/10GX is the Adaptive Logic Module 2// (ALM). Each ALM is made up of an 8-input, 2-output look-up table, covered 3// in this file, connected to combinational outputs, a carry chain, and four 4// D flip-flops (which are covered as MISTRAL_FF in dff_sim.v). 5// 6// The ALM is vertically symmetric, so I find it helps to think in terms of 7// half-ALMs, as that's predominantly the unit that synth_intel_alm uses. 8// 9// ALMs are quite flexible, having multiple modes. 10// 11// Normal (combinational) mode 12// --------------------------- 13// The ALM can implement: 14// - a single 6-input function (with the other inputs usable for flip-flop access) 15// - two 5-input functions that share two inputs 16// - a 5-input and a 4-input function that share one input 17// - a 5-input and a 3-or-less-input function that share no inputs 18// - two 4-or-less-input functions that share no inputs 19// 20// Normal-mode functions are represented as MISTRAL_ALUTN cells with N inputs. 21// It would be possible to represent a normal mode function as a single cell - 22// the vendor cyclone{v,10gx}_lcell_comb cell does exactly that - but I felt 23// it was more user-friendly to print out the specific function sizes 24// separately. 25// 26// With the exception of MISTRAL_ALUT6, you can think of two normal-mode cells 27// fitting inside a single ALM. 28// 29// Extended (7-input) mode 30// ----------------------- 31// The ALM can also fit a 7-input function made of two 5-input functions that 32// share four inputs, multiplexed by another input. 33// 34// Because this can't accept arbitrary 7-input functions, Yosys can't handle 35// it, so it doesn't have a cell, but I would likely call it MISTRAL_ALUT7(E?) 36// if it did, and it would take up a full ALM. 37// 38// It might be possible to add an extraction pass to examine all ALUT5 cells 39// that feed into ALUT3 cells to see if they can be combined into an extended 40// ALM, but I don't think it will be worth it. 41// 42// Arithmetic mode 43// --------------- 44// In arithmetic mode, each half-ALM uses its carry chain to perform fast addition 45// of two four-input functions that share three inputs. Oddly, the result of 46// one of the functions is inverted before being added (you can see this as 47// the dot on a full-adder input of Figure 1-8 in the Handbook). 48// 49// The cell for an arithmetic-mode half-ALM is MISTRAL_ALM_ARITH. One idea 50// I've had (or rather was suggested by mwk) is that functions that feed into 51// arithmetic-mode cells could be packed directly into the arithmetic-mode 52// cell as a function, which reduces the number of ALMs needed. 53// 54// Shared arithmetic mode 55// ---------------------- 56// Shared arithmetic mode looks a lot like arithmetic mode, but here the 57// output of every other four-input function goes to the input of the adder 58// the next bit along. What this means is that adding three bits together can 59// be done in an ALM, because functions can be used to implement addition that 60// then feeds into the carry chain. This means that three bits can be added per 61// ALM, as opposed to two in the arithmetic mode. 62// 63// Shared arithmetic mode doesn't currently have a cell, but I intend to add 64// it as MISTRAL_ALM_SHARED, and have it occupy a full ALM. Because it adds 65// three bits per cell, it makes addition shorter and use less ALMs, but 66// I don't know enough to tell whether it's more efficient to use shared 67// arithmetic mode to shorten the carry chain, or plain arithmetic mode with 68// the functions packed in. 69 70`default_nettype none 71 72// Cyclone V LUT output timings (picoseconds): 73// 74// CARRY A B C D E F G 75// COMBOUT - 605 583 510 512 - 97 400 (LUT6) 76// COMBOUT - 602 583 457 510 302 93 483 (LUT7) 77// SUMOUT 368 1342 1323 887 927 - 785 - 78// CARRYOUT 71 1082 1062 866 813 - 1198 - 79 80// Arria V LUT output timings (picoseconds): 81// 82// CARRY A B C D E F G 83// COMBOUT - 387 375 316 317 - 76 319 (LUT6) 84// COMBOUT - 387 375 316 317 218 76 319 (LUT7) 85// SUMOUT 249 744 732 562 576 - 511 - 86// CARRYOUT 19 629 623 530 514 - 696 - 87 88(* abc9_lut=2, lib_whitebox *) 89module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); 90 91parameter [63:0] LUT = 64'h0000_0000_0000_0000; 92 93`ifdef cyclonev 94specify 95 (A => Q) = 605; 96 (B => Q) = 583; 97 (C => Q) = 510; 98 (D => Q) = 512; 99 (E => Q) = 400; 100 (F => Q) = 97; 101endspecify 102`endif 103`ifdef arriav 104specify 105 (A => Q) = 387; 106 (B => Q) = 375; 107 (C => Q) = 316; 108 (D => Q) = 317; 109 (E => Q) = 319; 110 (F => Q) = 76; 111endspecify 112`endif 113`ifdef cyclone10gx 114specify 115 (A => Q) = 275; 116 (B => Q) = 272; 117 (C => Q) = 175; 118 (D => Q) = 165; 119 (E => Q) = 162; 120 (F => Q) = 53; 121endspecify 122`endif 123 124assign Q = LUT >> {F, E, D, C, B, A}; 125 126endmodule 127 128 129(* abc9_lut=1, lib_whitebox *) 130module MISTRAL_ALUT5(input A, B, C, D, E, output Q); 131 132parameter [31:0] LUT = 32'h0000_0000; 133 134`ifdef cyclonev 135specify 136 (A => Q) = 583; 137 (B => Q) = 510; 138 (C => Q) = 512; 139 (D => Q) = 400; 140 (E => Q) = 97; 141endspecify 142`endif 143`ifdef arriav 144specify 145 (A => Q) = 375; 146 (B => Q) = 316; 147 (C => Q) = 317; 148 (D => Q) = 319; 149 (E => Q) = 76; 150endspecify 151`endif 152`ifdef cyclone10gx 153specify 154 (A => Q) = 272; 155 (B => Q) = 175; 156 (C => Q) = 165; 157 (D => Q) = 162; 158 (E => Q) = 53; 159endspecify 160`endif 161 162assign Q = LUT >> {E, D, C, B, A}; 163 164endmodule 165 166 167(* abc9_lut=1, lib_whitebox *) 168module MISTRAL_ALUT4(input A, B, C, D, output Q); 169 170parameter [15:0] LUT = 16'h0000; 171 172`ifdef cyclonev 173specify 174 (A => Q) = 510; 175 (B => Q) = 512; 176 (C => Q) = 400; 177 (D => Q) = 97; 178endspecify 179`endif 180`ifdef arriav 181specify 182 (A => Q) = 316; 183 (B => Q) = 317; 184 (C => Q) = 319; 185 (D => Q) = 76; 186endspecify 187`endif 188`ifdef cyclone10gx 189specify 190 (A => Q) = 175; 191 (B => Q) = 165; 192 (C => Q) = 162; 193 (D => Q) = 53; 194endspecify 195`endif 196 197assign Q = LUT >> {D, C, B, A}; 198 199endmodule 200 201 202(* abc9_lut=1, lib_whitebox *) 203module MISTRAL_ALUT3(input A, B, C, output Q); 204 205parameter [7:0] LUT = 8'h00; 206 207`ifdef cyclonev 208specify 209 (A => Q) = 510; 210 (B => Q) = 400; 211 (C => Q) = 97; 212endspecify 213`endif 214`ifdef arriav 215specify 216 (A => Q) = 316; 217 (B => Q) = 317; 218 (C => Q) = 76; 219endspecify 220`endif 221`ifdef cyclone10gx 222specify 223 (A => Q) = 165; 224 (B => Q) = 162; 225 (C => Q) = 53; 226endspecify 227`endif 228 229assign Q = LUT >> {C, B, A}; 230 231endmodule 232 233 234(* abc9_lut=1, lib_whitebox *) 235module MISTRAL_ALUT2(input A, B, output Q); 236 237parameter [3:0] LUT = 4'h0; 238 239`ifdef cyclonev 240specify 241 (A => Q) = 400; 242 (B => Q) = 97; 243endspecify 244`endif 245`ifdef arriav 246specify 247 (A => Q) = 316; 248 (B => Q) = 76; 249endspecify 250`endif 251`ifdef cyclone10gx 252specify 253 (A => Q) = 162; 254 (B => Q) = 53; 255endspecify 256`endif 257 258assign Q = LUT >> {B, A}; 259 260endmodule 261 262 263(* abc9_lut=1, lib_whitebox *) 264module MISTRAL_NOT(input A, output Q); 265 266`ifdef cyclonev 267specify 268 (A => Q) = 97; 269endspecify 270`endif 271`ifdef arriav 272specify 273 (A => Q) = 76; 274endspecify 275`endif 276`ifdef cyclone10gx 277specify 278 (A => Q) = 53; 279endspecify 280`endif 281 282assign Q = ~A; 283 284endmodule 285 286// Despite the abc9_carry attributes, this doesn't seem to stop ABC9 adding illegal fanout to the carry chain that nextpnr cannot handle. 287// So we treat it as a total blackbox from ABC9's perspective for now. 288// (* abc9_box, lib_whitebox *) 289module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, /* (* abc9_carry *) */ input CI, output SO, /* (* abc9_carry *) */ output CO); 290 291parameter LUT0 = 16'h0000; 292parameter LUT1 = 16'h0000; 293 294`ifdef cyclonev 295specify 296 (A => SO) = 1342; 297 (B => SO) = 1323; 298 (C => SO) = 927; 299 (D0 => SO) = 887; 300 (D1 => SO) = 785; 301 (CI => SO) = 368; 302 303 (A => CO) = 1082; 304 (B => CO) = 1062; 305 (C => CO) = 813; 306 (D0 => CO) = 866; 307 (D1 => CO) = 1198; 308 (CI => CO) = 36; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) 309endspecify 310`endif 311`ifdef arriav 312specify 313 (A => SO) = 744; 314 (B => SO) = 732; 315 (C => SO) = 562; 316 (D0 => SO) = 576; 317 (D1 => SO) = 511; 318 (CI => SO) = 249; 319 320 (A => CO) = 629; 321 (B => CO) = 623; 322 (C => CO) = 530; 323 (D0 => CO) = 514; 324 (D1 => CO) = 696; 325 (CI => CO) = 10; // Divided by 2 to account for there being two ALUT_ARITHs in an ALM) 326endspecify 327`endif 328`ifdef cyclone10gx 329specify 330 (A => SO) = 644; 331 (B => SO) = 477; 332 (C => SO) = 416; 333 (D0 => SO) = 380; 334 (D1 => SO) = 431; 335 (CI => SO) = 276; 336 337 (A => CO) = 525; 338 (B => CO) = 433; 339 (C => CO) = 712; 340 (D0 => CO) = 653; 341 (D1 => CO) = 593; 342 (CI => CO) = 16; 343endspecify 344`endif 345 346wire q0, q1; 347 348assign q0 = LUT0 >> {D0, C, B, A}; 349assign q1 = LUT1 >> {D1, C, B, A}; 350 351assign {CO, SO} = q0 + !q1 + CI; 352 353endmodule 354 355 356/* 357// A, B, C0, C1, E0, E1, F0, F1: data inputs 358// CARRYIN: carry input 359// SHAREIN: shared-arithmetic input 360// CLK0, CLK1, CLK2: clock inputs 361// 362// COMB0, COMB1: combinational outputs 363// FF0, FF1, FF2, FF3: DFF outputs 364// SUM0, SUM1: adder outputs 365// CARRYOUT: carry output 366// SHAREOUT: shared-arithmetic output 367module MISTRAL_ALM( 368 input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path 369 input CLK0, CLK1, CLK2, AC0, AC1, // FF path 370 output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT, 371 output FF0, FF1, FF2, FF3 372); 373 374parameter LUT0 = 16'b0000; 375parameter LUT1 = 16'b0000; 376parameter LUT2 = 16'b0000; 377parameter LUT3 = 16'b0000; 378 379parameter INIT0 = 1'b0; 380parameter INIT1 = 1'b0; 381parameter INIT2 = 1'b0; 382parameter INIT3 = 1'b0; 383 384parameter C0_MUX = "C0"; 385parameter C1_MUX = "C1"; 386 387parameter F0_MUX = "VCC"; 388parameter F1_MUX = "GND"; 389 390parameter FEEDBACK0 = "FF0"; 391parameter FEEDBACK1 = "FF2"; 392 393parameter ADD_MUX = "LUT"; 394 395parameter DFF01_DATA_MUX = "COMB"; 396parameter DFF23_DATA_MUX = "COMB"; 397 398parameter DFF0_CLK = "CLK0"; 399parameter DFF1_CLK = "CLK0"; 400parameter DFF2_CLK = "CLK0"; 401parameter DFF3_CLK = "CLK0"; 402 403parameter DFF0_AC = "AC0"; 404parameter DFF1_AC = "AC0"; 405parameter DFF2_AC = "AC0"; 406parameter DFF3_AC = "AC0"; 407 408// Feedback muxes from the flip-flop outputs. 409wire ff_feedback_mux0, ff_feedback_mux1; 410 411// C-input muxes which can be set to also use the F-input. 412wire c0_input_mux, c1_input_mux; 413 414// F-input muxes which can be set to a constant to allow LUT5 use. 415wire f0_input_mux, f1_input_mux; 416 417// Adder input muxes to select between shared-arithmetic mode and arithmetic mode. 418wire add0_input_mux, add1_input_mux; 419 420// Combinational-output muxes for LUT #1 and LUT #3 421wire lut1_comb_mux, lut3_comb_mux; 422 423// Sum-output muxes for LUT #1 and LUT #3 424wire lut1_sum_mux, lut3_sum_mux; 425 426// DFF data-input muxes 427wire dff01_data_mux, dff23_data_mux; 428 429// DFF clock selectors 430wire dff0_clk, dff1_clk, dff2_clk, dff3_clk; 431 432// DFF asynchronous-clear selectors 433wire dff0_ac, dff1_ac, dff2_ac, dff3_ac; 434 435// LUT, DFF and adder output wires for routing. 436wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out; 437wire dff0_out, dff1_out, dff2_out, dff3_out; 438wire add0_sum, add1_sum, add0_carry, add1_carry; 439 440generate 441 if (FEEDBACK0 === "FF0") 442 assign ff_feedback_mux0 = dff0_out; 443 else if (FEEDBACK0 === "FF1") 444 assign ff_feedback_mux0 = dff1_out; 445 else 446 $error("Invalid FEEDBACK0 setting!"); 447 448 if (FEEDBACK1 == "FF2") 449 assign ff_feedback_mux1 = dff2_out; 450 else if (FEEDBACK1 == "FF3") 451 assign ff_feedback_mux1 = dff3_out; 452 else 453 $error("Invalid FEEDBACK1 setting!"); 454 455 if (C0_MUX === "C0") 456 assign c0_input_mux = C0; 457 else if (C0_MUX === "F1") 458 assign c0_input_mux = F1; 459 else if (C0_MUX === "FEEDBACK1") 460 assign c0_input_mux = ff_feedback_mux1; 461 else 462 $error("Invalid C0_MUX setting!"); 463 464 if (C1_MUX === "C1") 465 assign c1_input_mux = C1; 466 else if (C1_MUX === "F0") 467 assign c1_input_mux = F0; 468 else if (C1_MUX === "FEEDBACK0") 469 assign c1_input_mux = ff_feedback_mux0; 470 else 471 $error("Invalid C1_MUX setting!"); 472 473 // F0 == VCC is LUT5 474 // F0 == F0 is LUT6 475 // F0 == FEEDBACK is unknown 476 if (F0_MUX === "VCC") 477 assign f0_input_mux = 1'b1; 478 else if (F0_MUX === "F0") 479 assign f0_input_mux = F0; 480 else if (F0_MUX === "FEEDBACK0") 481 assign f0_input_mux = ff_feedback_mux0; 482 else 483 $error("Invalid F0_MUX setting!"); 484 485 // F1 == GND is LUT5 486 // F1 == F1 is LUT6 487 // F1 == FEEDBACK is unknown 488 if (F1_MUX === "GND") 489 assign f1_input_mux = 1'b0; 490 else if (F1_MUX === "F1") 491 assign f1_input_mux = F1; 492 else if (F1_MUX === "FEEDBACK1") 493 assign f1_input_mux = ff_feedback_mux1; 494 else 495 $error("Invalid F1_MUX setting!"); 496 497 if (ADD_MUX === "LUT") begin 498 assign add0_input_mux = ~lut1_sum_mux; 499 assign add1_input_mux = ~lut3_sum_mux; 500 end else if (ADD_MUX === "SHARE") begin 501 assign add0_input_mux = SHAREIN; 502 assign add1_input_mux = lut1_comb_mux; 503 end else 504 $error("Invalid ADD_MUX setting!"); 505 506 if (DFF01_DATA_MUX === "COMB") 507 assign dff01_data_mux = COMB0; 508 else if (DFF01_DATA_MUX === "SUM") 509 assign dff01_data_mux = SUM0; 510 else 511 $error("Invalid DFF01_DATA_MUX setting!"); 512 513 if (DFF23_DATA_MUX === "COMB") 514 assign dff23_data_mux = COMB0; 515 else if (DFF23_DATA_MUX === "SUM") 516 assign dff23_data_mux = SUM0; 517 else 518 $error("Invalid DFF23_DATA_MUX setting!"); 519 520 if (DFF0_CLK === "CLK0") 521 assign dff0_clk = CLK0; 522 else if (DFF0_CLK === "CLK1") 523 assign dff0_clk = CLK1; 524 else if (DFF0_CLK === "CLK2") 525 assign dff0_clk = CLK2; 526 else 527 $error("Invalid DFF0_CLK setting!"); 528 529 if (DFF1_CLK === "CLK0") 530 assign dff1_clk = CLK0; 531 else if (DFF1_CLK === "CLK1") 532 assign dff1_clk = CLK1; 533 else if (DFF1_CLK === "CLK2") 534 assign dff1_clk = CLK2; 535 else 536 $error("Invalid DFF1_CLK setting!"); 537 538 if (DFF2_CLK === "CLK0") 539 assign dff2_clk = CLK0; 540 else if (DFF2_CLK === "CLK1") 541 assign dff2_clk = CLK1; 542 else if (DFF2_CLK === "CLK2") 543 assign dff2_clk = CLK2; 544 else 545 $error("Invalid DFF2_CLK setting!"); 546 547 if (DFF3_CLK === "CLK0") 548 assign dff3_clk = CLK0; 549 else if (DFF3_CLK === "CLK1") 550 assign dff3_clk = CLK1; 551 else if (DFF3_CLK === "CLK2") 552 assign dff3_clk = CLK2; 553 else 554 $error("Invalid DFF3_CLK setting!"); 555 556 if (DFF0_AC === "AC0") 557 assign dff0_ac = AC0; 558 else if (DFF0_AC === "AC1") 559 assign dff0_ac = AC1; 560 else 561 $error("Invalid DFF0_AC setting!"); 562 563 if (DFF1_AC === "AC0") 564 assign dff1_ac = AC0; 565 else if (DFF1_AC === "AC1") 566 assign dff1_ac = AC1; 567 else 568 $error("Invalid DFF1_AC setting!"); 569 570 if (DFF2_AC === "AC0") 571 assign dff2_ac = AC0; 572 else if (DFF2_AC === "AC1") 573 assign dff2_ac = AC1; 574 else 575 $error("Invalid DFF2_AC setting!"); 576 577 if (DFF3_AC === "AC0") 578 assign dff3_ac = AC0; 579 else if (DFF3_AC === "AC1") 580 assign dff3_ac = AC1; 581 else 582 $error("Invalid DFF3_AC setting!"); 583 584endgenerate 585 586// F0 on the Quartus diagram 587MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out)); 588 589// F2 on the Quartus diagram 590MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux)); 591MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux)); 592 593// F1 on the Quartus diagram 594MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out)); 595 596// F3 on the Quartus diagram 597MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux)); 598MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux)); 599 600MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out)); 601MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out)); 602MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out)); 603MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out)); 604 605// Adders 606assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux; 607assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux; 608 609// COMBOUT outputs on the Quartus diagram 610assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux) 611 : (f0_input_mux ? lut2_out : lut0_out); 612 613assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux) 614 : (f1_input_mux ? lut2_out : lut0_out); 615 616// SUMOUT output on the Quartus diagram 617assign SUM0 = add0_sum; 618assign SUM1 = add1_sum; 619 620// COUT output on the Quartus diagram 621assign CARRYOUT = add1_carry; 622 623// SHAREOUT output on the Quartus diagram 624assign SHAREOUT = lut3_comb_mux; 625 626// REGOUT outputs on the Quartus diagram 627assign FF0 = dff0_out; 628assign FF1 = dff1_out; 629assign FF2 = dff2_out; 630assign FF3 = dff3_out; 631 632endmodule 633*/ 634