diff options
Diffstat (limited to 'techlibs/intel_alm')
| -rw-r--r-- | techlibs/intel_alm/Makefile.inc | 23 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/alm_map.v | 56 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/alm_sim.v | 482 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/arith_alm_map.v | 64 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/bram_m10k.txt | 33 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/bram_m10k_map.v | 31 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/bram_m20k.txt | 33 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/bram_m20k_map.v | 31 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/dff_map.v | 124 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/dff_sim.v | 48 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/lutram_mlab.txt | 20 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/lutram_mlab_map.v | 29 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/megafunction_bb.v | 108 | ||||
| -rw-r--r-- | techlibs/intel_alm/common/quartus_rename.v | 23 | ||||
| -rw-r--r-- | techlibs/intel_alm/cyclone10gx/quartus_rename.v | 54 | ||||
| -rw-r--r-- | techlibs/intel_alm/cyclonev/quartus_rename.v | 54 | ||||
| -rw-r--r-- | techlibs/intel_alm/synth_intel_alm.cc | 240 | 
17 files changed, 1453 insertions, 0 deletions
| diff --git a/techlibs/intel_alm/Makefile.inc b/techlibs/intel_alm/Makefile.inc new file mode 100644 index 000000000..66204c8fc --- /dev/null +++ b/techlibs/intel_alm/Makefile.inc @@ -0,0 +1,23 @@ + +OBJS += techlibs/intel_alm/synth_intel_alm.o + +# Techmap +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_map.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/alm_sim.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v)) + +# RAM +bramtypes := m10k m20k +$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype).txt))) +$(foreach bramtype, $(bramtypes), $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/bram_$(bramtype)_map.v))) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab.txt)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/lutram_mlab_map.v)) + +families := cyclonev cyclone10gx + +# Miscellaneous +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/megafunction_bb.v)) +$(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/quartus_rename.v)) +$(foreach family, $(families), $(eval $(call add_share_file,share/intel_alm/$(family),techlibs/intel_alm/$(family)/quartus_rename.v))) diff --git a/techlibs/intel_alm/common/alm_map.v b/techlibs/intel_alm/common/alm_map.v new file mode 100644 index 000000000..fe646c5d6 --- /dev/null +++ b/techlibs/intel_alm/common/alm_map.v @@ -0,0 +1,56 @@ +module \$lut (A, Y); + +parameter WIDTH = 1; +parameter LUT = 0; + +input [WIDTH-1:0] A; +output Y; + +generate +    if (WIDTH == 1) begin +        generate +            if (LUT == 2'b00) begin +                assign Y = 1'b0; +            end +            else if (LUT == 2'b01) begin +                MISTRAL_NOT _TECHMAP_REPLACE_( +                    .A(A[0]), .Q(Y) +                ); +            end +            else if (LUT == 2'b10) begin +                assign Y = A; +            end +            else if (LUT == 2'b11) begin +                assign Y = 1'b1; +            end +        endgenerate +    end else +    if (WIDTH == 2) begin +        MISTRAL_ALUT2 #(.LUT(LUT)) _TECHMAP_REPLACE_( +            .A(A[0]), .B(A[1]), .Q(Y) +        ); +    end else +    if (WIDTH == 3) begin +        MISTRAL_ALUT3 #(.LUT(LUT)) _TECHMAP_REPLACE_( +            .A(A[0]), .B(A[1]), .C(A[2]), .Q(Y) +        ); +    end else +    if (WIDTH == 4) begin +        MISTRAL_ALUT4 #(.LUT(LUT)) _TECHMAP_REPLACE_( +            .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .Q(Y) +        ); +    end else +    if (WIDTH == 5) begin +        MISTRAL_ALUT5 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( +            .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .Q(Y) +        ); +    end else +    if (WIDTH == 6) begin +        MISTRAL_ALUT6 #(.LUT(LUT)) _TECHMAP_REPLACE_ ( +            .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]), .E(A[4]), .F(A[5]), .Q(Y) +        ); +    end else begin +        wire _TECHMAP_FAIL_ = 1'b1; +    end +endgenerate +endmodule diff --git a/techlibs/intel_alm/common/alm_sim.v b/techlibs/intel_alm/common/alm_sim.v new file mode 100644 index 000000000..69768d9f7 --- /dev/null +++ b/techlibs/intel_alm/common/alm_sim.v @@ -0,0 +1,482 @@ +`default_nettype none + +(* abc9_lut=2, lib_whitebox *) +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); + +parameter [63:0] LUT = 64'h0000_0000_0000_0000; + +`ifdef cyclonev +specify +    (A => Q) = 602; +    (B => Q) = 584; +    (C => Q) = 510; +    (D => Q) = 510; +    (E => Q) = 339; +    (F => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 275; +    (B => Q) = 272; +    (C => Q) = 175; +    (D => Q) = 165; +    (E => Q) = 162; +    (F => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {F, E, D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); + +parameter [31:0] LUT = 32'h0000_0000; + +`ifdef cyclonev +specify +    (A => Q) = 584; +    (B => Q) = 510; +    (C => Q) = 510; +    (D => Q) = 339; +    (E => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 272; +    (B => Q) = 175; +    (C => Q) = 165; +    (D => Q) = 162; +    (E => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {E, D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT4(input A, B, C, D, output Q); + +parameter [15:0] LUT = 16'h0000; + +`ifdef cyclonev +specify +    (A => Q) = 510; +    (B => Q) = 510; +    (C => Q) = 339; +    (D => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 175; +    (B => Q) = 165; +    (C => Q) = 162; +    (D => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {D, C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT3(input A, B, C, output Q); + +parameter [7:0] LUT = 8'h00; + +`ifdef cyclonev +specify +    (A => Q) = 510; +    (B => Q) = 339; +    (C => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 165; +    (B => Q) = 162; +    (C => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {C, B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_ALUT2(input A, B, output Q); + +parameter [3:0] LUT = 4'h0; + +`ifdef cyclonev +specify +    (A => Q) = 339; +    (B => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 162; +    (B => Q) = 53; +endspecify +`endif + +assign Q = LUT >> {B, A}; + +endmodule + + +(* abc9_lut=1, lib_whitebox *) +module MISTRAL_NOT(input A, output Q); + +`ifdef cyclonev +specify +    (A => Q) = 94; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => Q) = 53; +endspecify +`endif + +assign Q = ~A; + +endmodule + +(* abc9_box, lib_whitebox *) +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, (* abc9_carry *) input CI, output SO, (* abc9_carry *) output CO); + +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +`ifdef cyclonev +specify +    (A => SO) = 1283; +    (B => SO) = 1167; +    (C => SO) = 866; +    (D0 => SO) = 756; +    (D1 => SO) = 756; +    (CI => SO) = 355; +    (A => CO) = 950; +    (B => CO) = 1039; +    (C => CO) = 820; +    (D0 => CO) = 1006; +    (D1 => CO) = 1006; +    (CI => CO) = 23; +endspecify +`endif +`ifdef cyclone10gx +specify +    (A => SO) = 644; +    (B => SO) = 477; +    (C => SO) = 416; +    (D0 => SO) = 380; +    (D1 => SO) = 431; +    (CI => SO) = 276; +    (A => CO) = 525; +    (B => CO) = 433; +    (C => CO) = 712; +    (D0 => CO) = 653; +    (D1 => CO) = 593; +    (CI => CO) = 16; +endspecify +`endif + +wire q0, q1; + +assign q0 = LUT0 >> {D0, C, B, A}; +assign q1 = LUT1 >> {D1, C, B, A}; + +assign {CO, SO} = q0 + !q1 + CI; + +endmodule + + +/* +// A, B, C0, C1, E0, E1, F0, F1: data inputs +// CARRYIN: carry input +// SHAREIN: shared-arithmetic input +// CLK0, CLK1, CLK2: clock inputs +// +// COMB0, COMB1: combinational outputs +// FF0, FF1, FF2, FF3: DFF outputs +// SUM0, SUM1: adder outputs +// CARRYOUT: carry output +// SHAREOUT: shared-arithmetic output +module MISTRAL_ALM( +    input A, B, C0, C1, E0, E1, F0, F1, CARRYIN, SHAREIN, // LUT path +    input CLK0, CLK1, CLK2, AC0, AC1,                     // FF path +    output COMB0, COMB1, SUM0, SUM1, CARRYOUT, SHAREOUT, +    output FF0, FF1, FF2, FF3 +); + +parameter LUT0 = 16'b0000; +parameter LUT1 = 16'b0000; +parameter LUT2 = 16'b0000; +parameter LUT3 = 16'b0000; + +parameter INIT0 = 1'b0; +parameter INIT1 = 1'b0; +parameter INIT2 = 1'b0; +parameter INIT3 = 1'b0; + +parameter C0_MUX = "C0"; +parameter C1_MUX = "C1"; + +parameter F0_MUX = "VCC"; +parameter F1_MUX = "GND"; + +parameter FEEDBACK0 = "FF0"; +parameter FEEDBACK1 = "FF2"; + +parameter ADD_MUX = "LUT"; + +parameter DFF01_DATA_MUX = "COMB"; +parameter DFF23_DATA_MUX = "COMB"; + +parameter DFF0_CLK = "CLK0"; +parameter DFF1_CLK = "CLK0"; +parameter DFF2_CLK = "CLK0"; +parameter DFF3_CLK = "CLK0"; + +parameter DFF0_AC  = "AC0"; +parameter DFF1_AC  = "AC0"; +parameter DFF2_AC  = "AC0"; +parameter DFF3_AC  = "AC0"; + +// Feedback muxes from the flip-flop outputs. +wire ff_feedback_mux0, ff_feedback_mux1; + +// C-input muxes which can be set to also use the F-input. +wire c0_input_mux, c1_input_mux; + +// F-input muxes which can be set to a constant to allow LUT5 use. +wire f0_input_mux, f1_input_mux; + +// Adder input muxes to select between shared-arithmetic mode and arithmetic mode. +wire add0_input_mux, add1_input_mux; + +// Combinational-output muxes for LUT #1 and LUT #3 +wire lut1_comb_mux, lut3_comb_mux; + +// Sum-output muxes for LUT #1 and LUT #3 +wire lut1_sum_mux, lut3_sum_mux; + +// DFF data-input muxes +wire dff01_data_mux, dff23_data_mux; + +// DFF clock selectors +wire dff0_clk, dff1_clk, dff2_clk, dff3_clk; + +// DFF asynchronous-clear selectors +wire dff0_ac, dff1_ac, dff2_ac, dff3_ac; + +// LUT, DFF and adder output wires for routing. +wire lut0_out, lut1a_out, lut1b_out, lut2_out, lut3a_out, lut3b_out; +wire dff0_out, dff1_out, dff2_out, dff3_out; +wire add0_sum, add1_sum, add0_carry, add1_carry; + +generate +    if (FEEDBACK0 === "FF0") +        assign ff_feedback_mux0 = dff0_out; +    else if (FEEDBACK0 === "FF1") +        assign ff_feedback_mux0 = dff1_out; +    else +        $error("Invalid FEEDBACK0 setting!"); + +    if (FEEDBACK1 == "FF2") +        assign ff_feedback_mux1 = dff2_out; +    else if (FEEDBACK1 == "FF3") +        assign ff_feedback_mux1 = dff3_out; +    else +        $error("Invalid FEEDBACK1 setting!"); + +    if (C0_MUX === "C0") +        assign c0_input_mux = C0; +    else if (C0_MUX === "F1") +        assign c0_input_mux = F1; +    else if (C0_MUX === "FEEDBACK1") +        assign c0_input_mux = ff_feedback_mux1; +    else +        $error("Invalid C0_MUX setting!"); + +    if (C1_MUX === "C1") +        assign c1_input_mux = C1; +    else if (C1_MUX === "F0") +        assign c1_input_mux = F0; +    else if (C1_MUX === "FEEDBACK0") +        assign c1_input_mux = ff_feedback_mux0; +    else +        $error("Invalid C1_MUX setting!"); + +    // F0 == VCC is LUT5 +    // F0 == F0 is LUT6 +    // F0 == FEEDBACK is unknown +    if (F0_MUX === "VCC") +        assign f0_input_mux = 1'b1; +    else if (F0_MUX === "F0") +        assign f0_input_mux = F0; +    else if (F0_MUX === "FEEDBACK0") +        assign f0_input_mux = ff_feedback_mux0; +    else +        $error("Invalid F0_MUX setting!"); + +    // F1 == GND is LUT5 +    // F1 == F1 is LUT6 +    // F1 == FEEDBACK is unknown +    if (F1_MUX === "GND") +        assign f1_input_mux = 1'b0; +    else if (F1_MUX === "F1") +        assign f1_input_mux = F1; +    else if (F1_MUX === "FEEDBACK1") +        assign f1_input_mux = ff_feedback_mux1; +    else +        $error("Invalid F1_MUX setting!"); + +    if (ADD_MUX === "LUT") begin +        assign add0_input_mux = ~lut1_sum_mux; +        assign add1_input_mux = ~lut3_sum_mux; +    end else if (ADD_MUX === "SHARE") begin +        assign add0_input_mux = SHAREIN; +        assign add1_input_mux = lut1_comb_mux; +    end else +        $error("Invalid ADD_MUX setting!"); + +    if (DFF01_DATA_MUX === "COMB") +        assign dff01_data_mux = COMB0; +    else if (DFF01_DATA_MUX === "SUM") +        assign dff01_data_mux = SUM0; +    else +        $error("Invalid DFF01_DATA_MUX setting!"); + +    if (DFF23_DATA_MUX === "COMB") +        assign dff23_data_mux = COMB0; +    else if (DFF23_DATA_MUX === "SUM") +        assign dff23_data_mux = SUM0; +    else +        $error("Invalid DFF23_DATA_MUX setting!"); + +    if (DFF0_CLK === "CLK0") +        assign dff0_clk = CLK0; +    else if (DFF0_CLK === "CLK1") +        assign dff0_clk = CLK1; +    else if (DFF0_CLK === "CLK2") +        assign dff0_clk = CLK2; +    else +        $error("Invalid DFF0_CLK setting!"); + +    if (DFF1_CLK === "CLK0") +        assign dff1_clk = CLK0; +    else if (DFF1_CLK === "CLK1") +        assign dff1_clk = CLK1; +    else if (DFF1_CLK === "CLK2") +        assign dff1_clk = CLK2; +    else +        $error("Invalid DFF1_CLK setting!"); + +    if (DFF2_CLK === "CLK0") +        assign dff2_clk = CLK0; +    else if (DFF2_CLK === "CLK1") +        assign dff2_clk = CLK1; +    else if (DFF2_CLK === "CLK2") +        assign dff2_clk = CLK2; +    else +        $error("Invalid DFF2_CLK setting!"); + +    if (DFF3_CLK === "CLK0") +        assign dff3_clk = CLK0; +    else if (DFF3_CLK === "CLK1") +        assign dff3_clk = CLK1; +    else if (DFF3_CLK === "CLK2") +        assign dff3_clk = CLK2; +    else +        $error("Invalid DFF3_CLK setting!"); + +    if (DFF0_AC === "AC0") +        assign dff0_ac = AC0; +    else if (DFF0_AC === "AC1") +        assign dff0_ac = AC1; +    else +        $error("Invalid DFF0_AC setting!"); + +    if (DFF1_AC === "AC0") +        assign dff1_ac = AC0; +    else if (DFF1_AC === "AC1") +        assign dff1_ac = AC1; +    else +        $error("Invalid DFF1_AC setting!"); + +    if (DFF2_AC === "AC0") +        assign dff2_ac = AC0; +    else if (DFF2_AC === "AC1") +        assign dff2_ac = AC1; +    else +        $error("Invalid DFF2_AC setting!"); + +    if (DFF3_AC === "AC0") +        assign dff3_ac = AC0; +    else if (DFF3_AC === "AC1") +        assign dff3_ac = AC1; +    else +        $error("Invalid DFF3_AC setting!"); + +endgenerate + +// F0 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT0)) lut0 (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut0_out)); + +// F2 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_comb (.A(A), .B(B), .C(C0), .D(c1_input_mux), .Q(lut1_comb_mux)); +MISTRAL_ALUT4 #(.LUT(LUT1)) lut1_sum  (.A(A), .B(B), .C(C0), .D(E0), .Q(lut1_sum_mux)); + +// F1 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT2)) lut2 (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut2_out)); + +// F3 on the Quartus diagram +MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_comb (.A(A), .B(B), .C(C1), .D(c0_input_mux), .Q(lut3_comb_mux)); +MISTRAL_ALUT4 #(.LUT(LUT3)) lut3_sum  (.A(A), .B(B), .C(C1), .D(E1), .Q(lut3_sum_mux)); + +MISTRAL_FF #(.INIT(INIT0)) dff0 (.D(dff01_data_mux), .CLK(dff0_clk), .ACn(dff0_ac), .Q(dff0_out)); +MISTRAL_FF #(.INIT(INIT1)) dff1 (.D(dff01_data_mux), .CLK(dff1_clk), .ACn(dff1_ac), .Q(dff1_out)); +MISTRAL_FF #(.INIT(INIT2)) dff2 (.D(dff23_data_mux), .CLK(dff2_clk), .ACn(dff2_ac), .Q(dff2_out)); +MISTRAL_FF #(.INIT(INIT3)) dff3 (.D(dff23_data_mux), .CLK(dff3_clk), .ACn(dff3_ac), .Q(dff3_out)); + +// Adders +assign {add0_carry, add0_sum} = CARRYIN + lut0_out + lut1_sum_mux; +assign {add1_carry, add1_sum} = add0_carry + lut2_out + lut3_sum_mux; + +// COMBOUT outputs on the Quartus diagram +assign COMB0 = E0 ? (f0_input_mux ? lut3_comb_mux : lut1_comb_mux) +                    : (f0_input_mux ? lut2_out : lut0_out); + +assign COMB1 = E1 ? (f1_input_mux ? lut3_comb_mux : lut1_comb_mux) +                    : (f1_input_mux ? lut2_out : lut0_out); + +// SUMOUT output on the Quartus diagram +assign SUM0 = add0_sum; +assign SUM1 = add1_sum; + +// COUT output on the Quartus diagram +assign CARRYOUT = add1_carry; + +// SHAREOUT output on the Quartus diagram +assign SHAREOUT = lut3_comb_mux; + +// REGOUT outputs on the Quartus diagram +assign FF0 = dff0_out; +assign FF1 = dff1_out; +assign FF2 = dff2_out; +assign FF3 = dff3_out; + +endmodule +*/ diff --git a/techlibs/intel_alm/common/arith_alm_map.v b/techlibs/intel_alm/common/arith_alm_map.v new file mode 100644 index 000000000..ddf81d9d0 --- /dev/null +++ b/techlibs/intel_alm/common/arith_alm_map.v @@ -0,0 +1,64 @@ +`default_nettype none + +module \$alu (A, B, CI, BI, X, Y, CO); + +parameter A_SIGNED = 0; +parameter B_SIGNED = 0; +parameter A_WIDTH = 1; +parameter B_WIDTH = 1; +parameter Y_WIDTH = 1; + +parameter _TECHMAP_CONSTMSK_CI_ = 0; +parameter _TECHMAP_CONSTVAL_CI_ = 0; + +input [A_WIDTH-1:0] A; +input [B_WIDTH-1:0] B; +input CI, BI; +output [Y_WIDTH-1:0] X, Y, CO; + +wire [Y_WIDTH-1:0] A_buf, B_buf; +\$pos #(.A_SIGNED(A_SIGNED), .A_WIDTH(A_WIDTH), .Y_WIDTH(Y_WIDTH)) A_conv (.A(A), .Y(A_buf)); +\$pos #(.A_SIGNED(B_SIGNED), .A_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) B_conv (.A(B), .Y(B_buf)); + +wire [Y_WIDTH-1:0] AA = A_buf; +wire [Y_WIDTH-1:0] BB = BI ? ~B_buf : B_buf; +wire [Y_WIDTH-1:0] BX = B_buf; +wire [Y_WIDTH:0] ALM_CARRY; + +// Start of carry chain +generate +    if (_TECHMAP_CONSTMSK_CI_ == 1) begin +        assign ALM_CARRY[0] = _TECHMAP_CONSTVAL_CI_; +    end else begin +        MISTRAL_ALUT_ARITH #( +            .LUT0(16'b1010_1010_1010_1010), // Q = A +            .LUT1(16'b0000_0000_0000_0000), // Q = 0 (LUT1's input to the adder is inverted) +        ) alm_start ( +            .A(CI), .B(1'b1), .C(1'b1), .D0(1'b1), .D1(1'b1), +            .CI(1'b0), +            .CO(ALM_CARRY[0]) +        ); +    end +endgenerate + +// Carry chain +genvar i; +generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice +    // TODO: mwk suggests that a pass could merge pre-adder logic into this. +    MISTRAL_ALUT_ARITH #( +        .LUT0(16'b1010_1010_1010_1010), // Q = A +        .LUT1(16'b1100_0011_1100_0011), // Q = C ? B : ~B (LUT1's input to the adder is inverted) +    ) alm_i ( +        .A(AA[i]), .B(BX[i]), .C(BI), .D0(1'b1), .D1(1'b1), +        .CI(ALM_CARRY[i]), +        .SO(Y[i]), +        .CO(ALM_CARRY[i+1]) +    ); + +    // ALM carry chain is not directly accessible, so calculate the carry through soft logic if really needed. +    assign CO[i] = (AA[i] && BB[i]) || ((Y[i] ^ AA[i] ^ BB[i]) && (AA[i] || BB[i])); +end endgenerate + +assign X = AA ^ BB; + +endmodule diff --git a/techlibs/intel_alm/common/bram_m10k.txt b/techlibs/intel_alm/common/bram_m10k.txt new file mode 100644 index 000000000..837e3a330 --- /dev/null +++ b/techlibs/intel_alm/common/bram_m10k.txt @@ -0,0 +1,33 @@ +bram __MISTRAL_M10K_SDP +    init   0   # TODO: Re-enable when I figure out how BRAM init works +    abits 13   @D8192x1 +    dbits  1   @D8192x1 +    abits 12   @D4096x2 +    dbits  2   @D4096x2 +    abits 11   @D2048x4 @D2048x5 +    dbits  4   @D2048x4 +    dbits  5   @D2048x5 +    abits 10   @D1024x8 @D1024x10 +    dbits  8   @D1024x8 +    dbits 10   @D1024x10 +    abits  9   @D512x16 @D512x20 +    dbits 16   @D512x16 +    dbits 20   @D512x20 +    abits  8   @D256x32 @D256x40 +    dbits 32   @D256x32 +    dbits 40   @D256x40 +    groups 2 +    ports  1 1 +    wrmode 1 0 +    # read enable; write enable + byte enables (only for multiples of 8) +    enable 1 1 +    transp 0 0 +    clocks 1 1 +    clkpol 1 1 +endbram + + +match __MISTRAL_M10K_SDP +    min efficiency 5 +    make_transp +endmatch diff --git a/techlibs/intel_alm/common/bram_m10k_map.v b/techlibs/intel_alm/common/bram_m10k_map.v new file mode 100644 index 000000000..e5566010d --- /dev/null +++ b/techlibs/intel_alm/common/bram_m10k_map.v @@ -0,0 +1,31 @@ +module __MISTRAL_M10K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
 +
 +parameter CFG_ABITS = 10;
 +parameter CFG_DBITS = 10;
 +parameter CFG_ENABLE_A = 1;
 +parameter CFG_ENABLE_B = 1;
 +
 +input CLK1;
 +input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
 +input [CFG_DBITS-1:0] A1DATA;
 +output [CFG_DBITS-1:0] B1DATA;
 +input [CFG_ENABLE_A-1:0] A1EN, B1EN;
 +
 +altsyncram #(
 +    .operation_mode("dual_port"),
 +    .ram_block_type("m10k"),
 +    .widthad_a(CFG_ABITS),
 +    .width_a(CFG_DBITS),
 +    .widthad_b(CFG_ABITS),
 +    .width_b(CFG_DBITS),
 +) _TECHMAP_REPLACE_ (
 +    .address_a(A1ADDR),
 +    .data_a(A1DATA),
 +    .wren_a(A1EN),
 +    .address_b(B1ADDR),
 +    .q_b(B1DATA),
 +    .clock0(CLK1),
 +    .clock1(CLK1)
 +);
 +
 +endmodule diff --git a/techlibs/intel_alm/common/bram_m20k.txt b/techlibs/intel_alm/common/bram_m20k.txt new file mode 100644 index 000000000..b4c5a5372 --- /dev/null +++ b/techlibs/intel_alm/common/bram_m20k.txt @@ -0,0 +1,33 @@ +bram __MISTRAL_M20K_SDP +    init   1   # TODO: Re-enable when I figure out how BRAM init works +    abits 14   @D16384x1 +    dbits  1   @D16384x1 +    abits 13   @D8192x2 +    dbits  2   @D8192x2 +    abits 12   @D4096x4 @D4096x5 +    dbits  4   @D4096x4 +    dbits  5   @D4096x5 +    abits 11   @D2048x8 @D2048x10 +    dbits  8   @D2048x8 +    dbits 10   @D2048x10 +    abits 10   @D1024x16 @D1024x20 +    dbits 16   @D1024x16 +    dbits 20   @D1024x20 +    abits  9   @D512x32 @D512x40 +    dbits 32   @D512x32 +    dbits 40   @D512x40 +    groups 2 +    ports  1 1 +    wrmode 1 0 +    # read enable; write enable + byte enables (only for multiples of 8) +    enable 1 1 +    transp 0 0 +    clocks 1 1 +    clkpol 1 1 +endbram + + +match __MISTRAL_M20K_SDP +    min efficiency 5 +    make_transp +endmatch diff --git a/techlibs/intel_alm/common/bram_m20k_map.v b/techlibs/intel_alm/common/bram_m20k_map.v new file mode 100644 index 000000000..92f41310f --- /dev/null +++ b/techlibs/intel_alm/common/bram_m20k_map.v @@ -0,0 +1,31 @@ +module __MISTRAL_M20K_SDP(CLK1, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
 +
 +parameter CFG_ABITS = 10;
 +parameter CFG_DBITS = 20;
 +parameter CFG_ENABLE_A = 1;
 +parameter CFG_ENABLE_B = 1;
 +
 +input CLK1;
 +input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
 +input [CFG_DBITS-1:0] A1DATA;
 +output [CFG_DBITS-1:0] B1DATA;
 +input [CFG_ENABLE_A-1:0] A1EN, B1EN;
 +
 +altsyncram #(
 +    .operation_mode("dual_port"),
 +    .ram_block_type("m20k"),
 +    .widthad_a(CFG_ABITS),
 +    .width_a(CFG_DBITS),
 +    .widthad_b(CFG_ABITS),
 +    .width_b(CFG_DBITS),
 +) _TECHMAP_REPLACE_ (
 +    .address_a(A1ADDR),
 +    .data_a(A1DATA),
 +    .wren_a(A1EN),
 +    .address_b(B1ADDR),
 +    .q_b(B1DATA),
 +    .clock0(CLK1),
 +    .clock1(CLK1)
 +);
 +
 +endmodule
 diff --git a/techlibs/intel_alm/common/dff_map.v b/techlibs/intel_alm/common/dff_map.v new file mode 100644 index 000000000..f7f2fe3c3 --- /dev/null +++ b/techlibs/intel_alm/common/dff_map.v @@ -0,0 +1,124 @@ +`default_nettype none + +// D flip-flops +module \$_DFF_P_ (input D, C, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_P_ with INIT=1"); +endmodule + +module \$_DFF_N_ (input D, C, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_N_ with INIT=1"); +endmodule + +// D flip-flops with reset +module \$_DFF_PP0_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_PP0_ with INIT=1"); +endmodule + +module \$_DFF_PN0_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_PN0_ with INIT=1"); +endmodule + +module \$_DFF_NP0_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_NP0_ with INIT=1"); +endmodule + +module \$_DFF_NN0_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFF_NN0_ with INIT=1"); +endmodule + +// D flip-flops with set +module \$_DFF_PP1_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b1; +if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    wire Q_tmp; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); +    assign Q = ~Q_tmp; +end else $error("Unsupported flop: $_DFF_PP1_ with INIT=0"); +endmodule + +module \$_DFF_PN1_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b1; +if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    wire Q_tmp; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); +end else $error("Unsupported flop: $_DFF_PN1_ with INIT=0"); +endmodule + +module \$_DFF_NP1_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b1; +if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    wire Q_tmp; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(~R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); +    assign Q = ~Q_tmp; +end else $error("Unsupported flop: $_DFF_NP1_ with INIT=0"); +endmodule + +module \$_DFF_NN1_ (input D, C, R, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b1; +if (_TECHMAP_WIREINIT_Q_ !== 1'b0) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    wire Q_tmp; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(~D), .CLK(~C), .ACLR(R), .ENA(1'b1), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q_tmp)); +    assign Q = ~Q_tmp; +end else $error("Unsupported flop: $_DFF_NN1_ with INIT=0"); +endmodule + +// D flip-flops with clock enable +module \$_DFFE_PP_ (input D, C, E, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFFE_PP_ with INIT=1"); +endmodule + +module \$_DFFE_PN_ (input D, C, E, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFFE_PN_ with INIT=1"); +endmodule + +module \$_DFFE_NP_ (input D, C, E, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFFE_NP_ with INIT=1"); +endmodule + +module \$_DFFE_NN_ (input D, C, E, output Q); +parameter _TECHMAP_WIREINIT_Q_ = 1'b0; +if (_TECHMAP_WIREINIT_Q_ !== 1'b1) begin +    wire _TECHMAP_REMOVEINIT_Q_ = 1'b1; +    MISTRAL_FF _TECHMAP_REPLACE_(.DATAIN(D), .CLK(~C), .ACLR(1'b1), .ENA(~E), .SCLR(1'b0), .SLOAD(1'b0), .SDATA(1'b0), .Q(Q)); +end else $error("Unsupported flop: $_DFFE_NN_ with INIT=1"); +endmodule diff --git a/techlibs/intel_alm/common/dff_sim.v b/techlibs/intel_alm/common/dff_sim.v new file mode 100644 index 000000000..07865905f --- /dev/null +++ b/techlibs/intel_alm/common/dff_sim.v @@ -0,0 +1,48 @@ +// DATAIN: synchronous data input +// CLK: clock input (positive edge) +// ACLR: asynchronous clear (negative-true) +// ENA: clock-enable +// SCLR: synchronous clear +// SLOAD: synchronous load +// SDATA: synchronous load data +// +// Q: data output +// +// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements. +module MISTRAL_FF( +    input DATAIN, CLK, ACLR, ENA, SCLR, SLOAD, SDATA, +    output reg Q +); + +`ifdef cyclonev +specify +    (posedge CLK => (Q : DATAIN)) = 262; +    $setup(DATAIN, posedge CLK, 522); +endspecify +`endif +`ifdef cyclone10gx +specify +    (posedge CLK => (Q : DATAIN)) = 219; +    $setup(DATAIN, posedge CLK, 268); +endspecify +`endif + +initial begin +    // Altera flops initialise to zero. +	Q = 0; +end + +always @(posedge CLK, negedge ACLR) begin +    // Asynchronous clear +    if (!ACLR) Q <= 0; +    // Clock-enable +	else if (ENA) begin +        // Synchronous clear +        if (SCLR) Q <= 0; +        // Synchronous load +        else if (SLOAD) Q <= SDATA; +        else Q <= DATAIN; +    end +end + +endmodule diff --git a/techlibs/intel_alm/common/lutram_mlab.txt b/techlibs/intel_alm/common/lutram_mlab.txt new file mode 100644 index 000000000..1d6174d85 --- /dev/null +++ b/techlibs/intel_alm/common/lutram_mlab.txt @@ -0,0 +1,20 @@ +bram __MISTRAL_MLAB
 +    init   0   # TODO: Re-enable when I figure out how LUTRAM init works
 +    abits  5
 +    dbits  16  @D32x16
 +    dbits  18  @D32x18
 +    dbits  20  @D32x20
 +    groups 2
 +    ports  1 1
 +    wrmode 1 0
 +    # read enable
 +    enable 1 0
 +    transp 1 0
 +    clocks 1 2
 +    clkpol 1 1
 +endbram
 +
 +match __MISTRAL_MLAB
 +    min efficiency 5
 +    make_outreg
 +endmatch
 diff --git a/techlibs/intel_alm/common/lutram_mlab_map.v b/techlibs/intel_alm/common/lutram_mlab_map.v new file mode 100644 index 000000000..3a9c8590e --- /dev/null +++ b/techlibs/intel_alm/common/lutram_mlab_map.v @@ -0,0 +1,29 @@ +module __MISTRAL_MLAB(CLK1, CLK2, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA);
 +
 +parameter CFG_ABITS = 5;
 +parameter CFG_DBITS = 20;
 +
 +input CLK1, CLK2;
 +input [CFG_ABITS-1:0] A1ADDR, B1ADDR;
 +input [CFG_DBITS-1:0] A1DATA;
 +input A1EN;
 +output [CFG_DBITS-1:0] B1DATA;
 +
 +altsyncram #(
 +    .operation_mode("dual_port"),
 +    .ram_block_type("mlab"),
 +    .widthad_a(CFG_ABITS),
 +    .width_a(CFG_DBITS),
 +    .widthad_b(CFG_ABITS),
 +    .width_b(CFG_DBITS),
 +) _TECHMAP_REPLACE_ (
 +    .address_a(A1ADDR),
 +    .data_a(A1DATA),
 +    .wren_a(A1EN),
 +    .address_b(B1ADDR),
 +    .q_b(B1DATA),
 +    .clock0(CLK1),
 +    .clock1(CLK1),
 +);
 +
 +endmodule
 diff --git a/techlibs/intel_alm/common/megafunction_bb.v b/techlibs/intel_alm/common/megafunction_bb.v new file mode 100644 index 000000000..21ba73a09 --- /dev/null +++ b/techlibs/intel_alm/common/megafunction_bb.v @@ -0,0 +1,108 @@ +// Intel megafunction declarations, to avoid Yosys complaining. +`default_nettype none + +(* blackbox *) +module altera_std_synchronizer(clk, din, dout, reset_n); + +parameter depth = 2; + +input clk; +input reset_n; +input din; +output dout; + +endmodule + +(* blackbox *) +module altiobuf_in(datain, dataout); + +parameter enable_bus_hold = "FALSE"; +parameter use_differential_mode = "FALSE"; +parameter number_of_channels = 1; + +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; + +endmodule + +(* blackbox *) +module altiobuf_out(datain, dataout); + +parameter enable_bus_hold = "FALSE"; +parameter use_differential_mode = "FALSE"; +parameter use_oe = "FALSE"; +parameter number_of_channels = 1; + +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; + +endmodule + +(* blackbox *) +module altiobuf_bidir(dataio, oe, datain, dataout); + +parameter number_of_channels = 1; +parameter enable_bus_hold = "OFF"; + +inout [number_of_channels-1:0] dataio; +input [number_of_channels-1:0] datain; +output [number_of_channels-1:0] dataout; +input [number_of_channels-1:0] oe; + +endmodule + +(* blackbox *) +module altsyncram(clock0, clock1, address_a, data_a, rden_a, wren_a, byteena_a, q_a, addressstall_a, address_b, data_b, rden_b, wren_b, byteena_b, q_b, addressstall_b, clocken0, clocken1, clocken2, clocken3, aclr0, aclr1, eccstatus); + +parameter lpm_type = "altsyncram"; +parameter operation_mode = "dual_port"; +parameter ram_block_type = "auto"; +parameter intended_device_family = "auto"; +parameter power_up_uninitialized = "false"; +parameter read_during_write_mode_mixed_ports = "dontcare"; +parameter byte_size = 8; +parameter widthad_a = 1; +parameter width_a = 1; +parameter width_byteena_a = 1; +parameter numwords_a = 1; +parameter clock_enable_input_a = "clocken0"; +parameter widthad_b = 1; +parameter width_b = 1; +parameter numwords_b = 1; +parameter address_aclr_b = "aclr0"; +parameter address_reg_b = ""; +parameter outdata_aclr_b = "aclr0"; +parameter outdata_reg_b = ""; +parameter clock_enable_input_b = "clocken0"; +parameter clock_enable_output_b = "clocken0"; + +input clock0, clock1; +input [widthad_a-1:0] address_a; +input [width_a-1:0] data_a; +input rden_a; +input wren_a; +input [(width_a/8)-1:0] byteena_a; +input addressstall_a; + +output [width_a-1:0] q_a; + +input wren_b; +input rden_b; +input [widthad_b-1:0] address_b; +input [width_b-1:0] data_b; +input [(width_b/8)-1:0] byteena_b; +input addressstall_b; + +output [width_b-1:0] q_b; + +input clocken0; +input clocken1; +input clocken2; +input clocken3; + +input aclr0; +input aclr1; + +output eccstatus; + +endmodule diff --git a/techlibs/intel_alm/common/quartus_rename.v b/techlibs/intel_alm/common/quartus_rename.v new file mode 100644 index 000000000..e69eefeb7 --- /dev/null +++ b/techlibs/intel_alm/common/quartus_rename.v @@ -0,0 +1,23 @@ +module __MISTRAL_VCC(output Q); + +MISTRAL_ALUT2 #(.LUT(4'b1111)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); + +endmodule + + +module __MISTRAL_GND(output Q); + +MISTRAL_ALUT2 #(.LUT(4'b0000)) _TECHMAP_REPLACE_ (.A(1'b1), .B(1'b1), .Q(Q)); + +endmodule + + +module MISTRAL_FF(input D, CLK, ACn, ALD, AD, EN, output reg Q); + +parameter INIT = 1'b0; + +localparam [1023:0] INIT_STR = (INIT !== 1'b1) ? "low" : "high"; + +dffeas #(.power_up(INIT_STR), .is_wysiwyg("true")) _TECHMAP_REPLACE_ (.d(D), .clk(CLK), .clrn(ACn), .aload(ALD), .asdata(AD), .ena(EN), .q(Q)); + +endmodule diff --git a/techlibs/intel_alm/cyclone10gx/quartus_rename.v b/techlibs/intel_alm/cyclone10gx/quartus_rename.v new file mode 100644 index 000000000..3fbc508ed --- /dev/null +++ b/techlibs/intel_alm/cyclone10gx/quartus_rename.v @@ -0,0 +1,54 @@ +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); +parameter LUT = 64'h0000_0000_0000_0000; + +cyclone10gx_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); +parameter LUT = 32'h0000_0000; + +cyclone10gx_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT4(input A, B, C, D, output Q); +parameter LUT = 16'h0000; + +cyclone10gx_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT3(input A, B, C, output Q); +parameter LUT = 8'h00; + +cyclone10gx_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT2(input A, B, output Q); +parameter LUT = 4'h0; + +cyclone10gx_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); + +endmodule + + +module MISTRAL_NOT(input A, output Q); + +NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); + +endmodule + + +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +cyclone10gx_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); + +endmodule diff --git a/techlibs/intel_alm/cyclonev/quartus_rename.v b/techlibs/intel_alm/cyclonev/quartus_rename.v new file mode 100644 index 000000000..6eff375e1 --- /dev/null +++ b/techlibs/intel_alm/cyclonev/quartus_rename.v @@ -0,0 +1,54 @@ +module MISTRAL_ALUT6(input A, B, C, D, E, F, output Q); +parameter LUT = 64'h0000_0000_0000_0000; + +cyclonev_lcell_comb #(.lut_mask(LUT)) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .dataf(F), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT5(input A, B, C, D, E, output Q); +parameter LUT = 32'h0000_0000; + +cyclonev_lcell_comb #(.lut_mask({2{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .datae(E), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT4(input A, B, C, D, output Q); +parameter LUT = 16'h0000; + +cyclonev_lcell_comb #(.lut_mask({4{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT3(input A, B, C, output Q); +parameter LUT = 8'h00; + +cyclonev_lcell_comb #(.lut_mask({8{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .combout(Q)); + +endmodule + + +module MISTRAL_ALUT2(input A, B, output Q); +parameter LUT = 4'h0; + +cyclonev_lcell_comb #(.lut_mask({16{LUT}})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .combout(Q)); + +endmodule + + +module MISTRAL_NOT(input A, output Q); + +NOT _TECHMAP_REPLACE_ (.IN(A), .OUT(Q)); + +endmodule + + +module MISTRAL_ALUT_ARITH(input A, B, C, D0, D1, CI, output SO, CO); +parameter LUT0 = 16'h0000; +parameter LUT1 = 16'h0000; + +cyclonev_lcell_comb #(.lut_mask({16'h0, LUT1, 16'h0, LUT0})) _TECHMAP_REPLACE_ (.dataa(A), .datab(B), .datac(C), .datad(D0), .dataf(D1), .cin(CI), .sumout(SO), .cout(CO)); + +endmodule diff --git a/techlibs/intel_alm/synth_intel_alm.cc b/techlibs/intel_alm/synth_intel_alm.cc new file mode 100644 index 000000000..ee7cb361b --- /dev/null +++ b/techlibs/intel_alm/synth_intel_alm.cc @@ -0,0 +1,240 @@ +/* + *  yosys -- Yosys Open SYnthesis Suite + * + *  Copyright (C) 2012  Claire Wolf <claire@symbioticeda.com> + *  Copyright (C) 2019  Dan Ravensloft <dan.ravensloft@gmail.com> + * + *  Permission to use, copy, modify, and/or distribute this software for any + *  purpose with or without fee is hereby granted, provided that the above + *  copyright notice and this permission notice appear in all copies. + * + *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/celltypes.h" +#include "kernel/log.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct SynthIntelALMPass : public ScriptPass { +	SynthIntelALMPass() : ScriptPass("synth_intel_alm", "synthesis for ALM-based Intel (Altera) FPGAs.") {} + +	void help() YS_OVERRIDE +	{ +		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| +		log("\n"); +		log("    synth_intel_alm [options]\n"); +		log("\n"); +		log("This command runs synthesis for ALM-based Intel FPGAs.\n"); +		log("\n"); +		log("    -top <module>\n"); +		log("        use the specified module as top module (default='top')\n"); +		log("\n"); +		log("    -family <family>\n"); +		log("        target one of:\n"); +		log("        \"cyclonev\"    - Cyclone V (default)\n"); +		log("        \"cyclone10gx\" - Cyclone 10GX\n"); +		log("\n"); +		log("    -quartus\n"); +		log("        output a netlist using Quartus cells instead of MISTRAL_* cells\n"); +		log("\n"); +		log("    -vqm <file>\n"); +		log("        write the design to the specified Verilog Quartus Mapping File. Writing of an\n"); +		log("        output file is omitted if this parameter is not specified. Implies -quartus.\n"); +		log("\n"); +		log("    -run <from_label>:<to_label>\n"); +		log("        only run the commands between the labels (see below). an empty\n"); +		log("        from label is synonymous to 'begin', and empty to label is\n"); +		log("        synonymous to the end of the command list.\n"); +		log("\n"); +		log("    -nolutram\n"); +		log("        do not use LUT RAM cells in output netlist\n"); +		log("\n"); +		log("    -nobram\n"); +		log("        do not use block RAM cells in output netlist\n"); +		log("\n"); +		log("    -noflatten\n"); +		log("        do not flatten design before synthesis\n"); +		log("\n"); +		log("The following commands are executed by this synthesis command:\n"); +		help_script(); +		log("\n"); +	} + +	string top_opt, family_opt, bram_type, vout_file; +	bool flatten, quartus, nolutram, nobram; + +	void clear_flags() YS_OVERRIDE +	{ +		top_opt = "-auto-top"; +		family_opt = "cyclonev"; +		bram_type = "m10k"; +		vout_file = ""; +		flatten = true; +		quartus = false; +		nolutram = false; +		nobram = false; +	} + +	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE +	{ +		string run_from, run_to; +		clear_flags(); + +		size_t argidx; +		for (argidx = 1; argidx < args.size(); argidx++) { +			if (args[argidx] == "-family" && argidx + 1 < args.size()) { +				family_opt = args[++argidx]; +				continue; +			} +			if (args[argidx] == "-top" && argidx + 1 < args.size()) { +				top_opt = "-top " + args[++argidx]; +				continue; +			} +			if (args[argidx] == "-vqm" && argidx + 1 < args.size()) { +				quartus = true; +				vout_file = args[++argidx]; +				continue; +			} +			if (args[argidx] == "-run" && argidx + 1 < args.size()) { +				size_t pos = args[argidx + 1].find(':'); +				if (pos == std::string::npos) +					break; +				run_from = args[++argidx].substr(0, pos); +				run_to = args[argidx].substr(pos + 1); +				continue; +			} +			if (args[argidx] == "-quartus") { +				quartus = true; +				continue; +			} +			if (args[argidx] == "-nolutram") { +				nolutram = true; +				continue; +			} +			if (args[argidx] == "-nobram") { +				nobram = true; +				continue; +			} +			if (args[argidx] == "-noflatten") { +				flatten = false; +				continue; +			} +			break; +		} +		extra_args(args, argidx, design); + +		if (!design->full_selection()) +			log_cmd_error("This command only operates on fully selected designs!\n"); + +		if (family_opt == "cyclonev") { +			bram_type = "m10k"; +		} else if (family_opt == "cyclone10gx") { +			bram_type = "m20k"; +		} else { +			log_cmd_error("Invalid family specified: '%s'\n", family_opt.c_str()); +		} + +		log_header(design, "Executing SYNTH_INTEL_ALM pass.\n"); +		log_push(); + +		run_script(design, run_from, run_to); + +		log_pop(); +	} + +	void script() YS_OVERRIDE +	{ +		if (help_mode) { +			family_opt = "<family>"; +			bram_type = "<bram_type>"; +		} + +		if (check_label("begin")) { +			run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str())); +			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str())); +			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str())); + +			// Misc and common cells +			run("read_verilog -lib +/intel/common/altpll_bb.v"); +			run("read_verilog -lib +/intel_alm/common/megafunction_bb.v"); +			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); +		} + +		if (flatten && check_label("flatten", "(unless -noflatten)")) { +			run("proc"); +			run("flatten"); +			run("tribuf -logic"); +			run("deminout"); +		} + +		if (check_label("coarse")) { +			run("synth -run coarse -lut 6"); +			run("techmap -map +/intel_alm/common/arith_alm_map.v"); +		} + +		if (!nobram && check_label("map_bram", "(skip if -nobram)")) { +			run(stringf("memory_bram -rules +/intel_alm/common/bram_%s.txt", bram_type.c_str())); +			run(stringf("techmap -map +/intel_alm/common/bram_%s_map.v", bram_type.c_str())); +		} + +		if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { +			run("memory_bram -rules +/intel_alm/common/lutram_mlab.txt", "(for Cyclone V / Cyclone 10GX)"); +			run("techmap -map +/intel_alm/common/lutram_mlab_map.v", "(for Cyclone V / Cyclone 10GX)"); +		} + +		if (check_label("map_ffram")) { +			run("memory_map"); +			run("opt -full"); +		} + +		if (check_label("map_ffs")) { +			run("dff2dffe -direct-match $_DFF_*"); +			run("zinit"); +			run("techmap -map +/techmap.v -map +/intel_alm/common/dff_map.v"); +			run("opt -full -undriven -mux_undef"); +			run("clean -purge"); +		} + +		if (check_label("map_luts")) { +			run("read_verilog -icells -specify -lib +/abc9_model.v"); +			run("abc9 -maxlut 6 -W 200"); +			run("techmap -map +/intel_alm/common/alm_map.v"); +			run("opt -fast"); +			run("autoname"); +			run("clean"); +		} + +		if (check_label("check")) { +			run("hierarchy -check"); +			run("stat"); +			run("check"); +		} + +		if (check_label("quartus")) { +			if (quartus || help_mode) { +				run("hilomap -singleton -hicell __MISTRAL_VCC Q -locell __MISTRAL_GND Q"); +				run("techmap -map +/intel_alm/common/quartus_rename.v"); +				run(stringf("techmap -map +/intel_alm/%s/quartus_rename.v", family_opt.c_str())); +			} +		} + +		if (check_label("vqm")) { +			if (!vout_file.empty() || help_mode) { +				run(stringf("write_verilog -attr2comment -defparam -nohex -decimal %s", help_mode ? "<file-name>" : vout_file.c_str())); +			} +		} +	} +} SynthIntelALMPass; + +PRIVATE_NAMESPACE_END | 
