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