aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/xilinx
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/xilinx')
-rw-r--r--techlibs/xilinx/Makefile.inc1
-rw-r--r--techlibs/xilinx/cells_sim.v409
-rw-r--r--techlibs/xilinx/cells_xtra.v83
-rw-r--r--techlibs/xilinx/dsp_map.v48
-rw-r--r--techlibs/xilinx/synth_xilinx.cc27
-rw-r--r--techlibs/xilinx/tests/.gitignore5
-rw-r--r--techlibs/xilinx/tests/test_dsp_model.sh14
-rw-r--r--techlibs/xilinx/tests/test_dsp_model.v597
8 files changed, 1097 insertions, 87 deletions
diff --git a/techlibs/xilinx/Makefile.inc b/techlibs/xilinx/Makefile.inc
index b5e81a79d..5f5aa5518 100644
--- a/techlibs/xilinx/Makefile.inc
+++ b/techlibs/xilinx/Makefile.inc
@@ -39,6 +39,7 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc6s_ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/xc7_ff_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
+$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/dsp_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_map.v))
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_unmap.v))
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 6e8729256..ed421f85e 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -489,3 +489,412 @@ module SRLC32E (
always @(posedge CLK) if (CE) r <= { r[30:0], D };
endgenerate
endmodule
+
+module DSP48E1 (
+ output [29:0] ACOUT,
+ output [17:0] BCOUT,
+ output reg CARRYCASCOUT,
+ output reg [3:0] CARRYOUT,
+ output reg MULTSIGNOUT,
+ output OVERFLOW,
+ output reg signed [47:0] P,
+ output PATTERNBDETECT,
+ output PATTERNDETECT,
+ output [47:0] PCOUT,
+ output UNDERFLOW,
+ input signed [29:0] A,
+ input [29:0] ACIN,
+ input [3:0] ALUMODE,
+ input signed [17:0] B,
+ input [17:0] BCIN,
+ input [47:0] C,
+ input CARRYCASCIN,
+ input CARRYIN,
+ input [2:0] CARRYINSEL,
+ input CEA1,
+ input CEA2,
+ input CEAD,
+ input CEALUMODE,
+ input CEB1,
+ input CEB2,
+ input CEC,
+ input CECARRYIN,
+ input CECTRL,
+ input CED,
+ input CEINMODE,
+ input CEM,
+ input CEP,
+ (* clkbuf_sink *) input CLK,
+ input [24:0] D,
+ input [4:0] INMODE,
+ input MULTSIGNIN,
+ input [6:0] OPMODE,
+ input [47:0] PCIN,
+ input RSTA,
+ input RSTALLCARRYIN,
+ input RSTALUMODE,
+ input RSTB,
+ input RSTC,
+ input RSTCTRL,
+ input RSTD,
+ input RSTINMODE,
+ input RSTM,
+ input RSTP
+);
+ parameter integer ACASCREG = 1;
+ parameter integer ADREG = 1;
+ parameter integer ALUMODEREG = 1;
+ parameter integer AREG = 1;
+ parameter AUTORESET_PATDET = "NO_RESET";
+ parameter A_INPUT = "DIRECT";
+ parameter integer BCASCREG = 1;
+ parameter integer BREG = 1;
+ parameter B_INPUT = "DIRECT";
+ parameter integer CARRYINREG = 1;
+ parameter integer CARRYINSELREG = 1;
+ parameter integer CREG = 1;
+ parameter integer DREG = 1;
+ parameter integer INMODEREG = 1;
+ parameter integer MREG = 1;
+ parameter integer OPMODEREG = 1;
+ parameter integer PREG = 1;
+ parameter SEL_MASK = "MASK";
+ parameter SEL_PATTERN = "PATTERN";
+ parameter USE_DPORT = "FALSE";
+ parameter USE_MULT = "MULTIPLY";
+ parameter USE_PATTERN_DETECT = "NO_PATDET";
+ parameter USE_SIMD = "ONE48";
+ parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
+ parameter [47:0] PATTERN = 48'h000000000000;
+ parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
+ parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+ parameter [4:0] IS_INMODE_INVERTED = 5'b0;
+ parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
+
+ initial begin
+`ifdef __ICARUS__
+ if (AUTORESET_PATDET != "NO_RESET") $fatal(1, "Unsupported AUTORESET_PATDET value");
+ //if (PREG != 0) $fatal(1, "Unsupported PREG value");
+ if (SEL_MASK != "MASK") $fatal(1, "Unsupported SEL_MASK value");
+ if (SEL_PATTERN != "PATTERN") $fatal(1, "Unsupported SEL_PATTERN value");
+ if (USE_PATTERN_DETECT != "NO_PATDET") $fatal(1, "Unsupported USE_PATTERN_DETECT value");
+ if (USE_SIMD != "ONE48" && USE_SIMD != "TWO24" && USE_SIMD != "FOUR12") $fatal(1, "Unsupported USE_SIMD value");
+ if (IS_ALUMODE_INVERTED != 4'b0) $fatal(1, "Unsupported IS_ALUMODE_INVERTED value");
+ if (IS_CARRYIN_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CARRYIN_INVERTED value");
+ if (IS_CLK_INVERTED != 1'b0) $fatal(1, "Unsupported IS_CLK_INVERTED value");
+ if (IS_INMODE_INVERTED != 5'b0) $fatal(1, "Unsupported IS_INMODE_INVERTED value");
+ if (IS_OPMODE_INVERTED != 7'b0) $fatal(1, "Unsupported IS_OPMODE_INVERTED value");
+`endif
+ end
+
+ wire signed [29:0] A_muxed;
+ wire signed [17:0] B_muxed;
+
+ generate
+ if (A_INPUT == "CASCADE") assign A_muxed = ACIN;
+ else assign A_muxed = A;
+
+ if (B_INPUT == "CASCADE") assign B_muxed = BCIN;
+ else assign B_muxed = B;
+ endgenerate
+
+ reg signed [29:0] Ar1 = 30'b0, Ar2 = 30'b0;
+ reg signed [24:0] Dr = 25'b0;
+ reg signed [17:0] Br1 = 18'b0, Br2 = 18'b0;
+ reg signed [47:0] Cr = 48'b0;
+ reg [4:0] INMODEr = 5'b0;
+ reg [6:0] OPMODEr = 7'b0;
+ reg [3:0] ALUMODEr = 4'b0;
+ reg [2:0] CARRYINSELr = 3'b0;
+
+ generate
+ // Configurable A register
+ if (AREG == 2) begin
+ always @(posedge CLK)
+ if (RSTA) begin
+ Ar1 <= 30'b0;
+ Ar2 <= 30'b0;
+ end else begin
+ if (CEA1) Ar1 <= A_muxed;
+ if (CEA2) Ar2 <= Ar1;
+ end
+ end else if (AREG == 1) begin
+ always @(posedge CLK)
+ if (RSTA) begin
+ Ar1 <= 30'b0;
+ Ar2 <= 30'b0;
+ end else begin
+ if (CEA1) Ar1 <= A_muxed;
+ if (CEA2) Ar2 <= A_muxed;
+ end
+ end else begin
+ always @* Ar1 <= A_muxed;
+ always @* Ar2 <= A_muxed;
+ end
+
+ // Configurable B register
+ if (BREG == 2) begin
+ always @(posedge CLK)
+ if (RSTB) begin
+ Br1 <= 18'b0;
+ Br2 <= 18'b0;
+ end else begin
+ if (CEB1) Br1 <= B_muxed;
+ if (CEB2) Br2 <= Br1;
+ end
+ end else if (BREG == 1) begin
+ always @(posedge CLK)
+ if (RSTB) begin
+ Br1 <= 18'b0;
+ Br2 <= 18'b0;
+ end else begin
+ if (CEB1) Br1 <= B_muxed;
+ if (CEB2) Br2 <= B_muxed;
+ end
+ end else begin
+ always @* Br1 <= B_muxed;
+ always @* Br2 <= B_muxed;
+ end
+
+ // C and D registers
+ if (CREG == 1) begin always @(posedge CLK) if (RSTC) Cr <= 48'b0; else if (CEC) Cr <= C; end
+ else always @* Cr <= C;
+
+ if (DREG == 1) begin always @(posedge CLK) if (RSTD) Dr <= 25'b0; else if (CED) Dr <= D; end
+ else always @* Dr <= D;
+
+ // Control registers
+ if (INMODEREG == 1) begin always @(posedge CLK) if (RSTINMODE) INMODEr <= 5'b0; else if (CEINMODE) INMODEr <= INMODE; end
+ else always @* INMODEr <= INMODE;
+ if (OPMODEREG == 1) begin always @(posedge CLK) if (RSTCTRL) OPMODEr <= 7'b0; else if (CECTRL) OPMODEr <= OPMODE; end
+ else always @* OPMODEr <= OPMODE;
+ if (ALUMODEREG == 1) begin always @(posedge CLK) if (RSTALUMODE) ALUMODEr <= 4'b0; else if (CEALUMODE) ALUMODEr <= ALUMODE; end
+ else always @* ALUMODEr <= ALUMODE;
+ if (CARRYINSELREG == 1) begin always @(posedge CLK) if (RSTCTRL) CARRYINSELr <= 3'b0; else if (CECTRL) CARRYINSELr <= CARRYINSEL; end
+ else always @* CARRYINSELr <= CARRYINSEL;
+ endgenerate
+
+ // A and B cascsde
+ generate
+ if (ACASCREG == 1 && AREG == 2) assign ACOUT = Ar1;
+ else assign ACOUT = Ar2;
+ if (BCASCREG == 1 && BREG == 2) assign BCOUT = Br1;
+ else assign BCOUT = Br2;
+ endgenerate
+
+ // A/D input selection and pre-adder
+ wire signed [29:0] Ar12_muxed = INMODEr[0] ? Ar1 : Ar2;
+ wire signed [24:0] Ar12_gated = INMODEr[1] ? 25'b0 : Ar12_muxed;
+ wire signed [24:0] Dr_gated = INMODEr[2] ? Dr : 25'b0;
+ wire signed [24:0] AD_result = INMODEr[3] ? (Dr_gated - Ar12_gated) : (Dr_gated + Ar12_gated);
+ reg signed [24:0] ADr = 25'b0;
+
+ generate
+ if (ADREG == 1) begin always @(posedge CLK) if (RSTD) ADr <= 25'b0; else if (CEAD) ADr <= AD_result; end
+ else always @* ADr <= AD_result;
+ endgenerate
+
+ // 25x18 multiplier
+ wire signed [24:0] A_MULT;
+ wire signed [17:0] B_MULT = INMODEr[4] ? Br1 : Br2;
+ generate
+ if (USE_DPORT == "TRUE") assign A_MULT = ADr;
+ else assign A_MULT = Ar12_gated;
+ endgenerate
+
+ wire signed [42:0] M = A_MULT * B_MULT;
+ wire signed [42:0] Mx = (CARRYINSEL == 3'b010) ? 43'bx : M;
+ reg signed [42:0] Mr = 43'b0;
+
+ // Multiplier result register
+ generate
+ if (MREG == 1) begin always @(posedge CLK) if (RSTM) Mr <= 43'b0; else if (CEM) Mr <= Mx; end
+ else always @* Mr <= Mx;
+ endgenerate
+
+ wire signed [42:0] Mrx = (CARRYINSELr == 3'b010) ? 43'bx : Mr;
+
+ // X, Y and Z ALU inputs
+ reg signed [47:0] X, Y, Z;
+
+ always @* begin
+ // X multiplexer
+ case (OPMODEr[1:0])
+ 2'b00: X = 48'b0;
+ 2'b01: begin X = $signed(Mrx);
+`ifdef __ICARUS__
+ if (OPMODEr[3:2] != 2'b01) $fatal(1, "OPMODEr[3:2] must be 2'b01 when OPMODEr[1:0] is 2'b01");
+`endif
+ end
+ 2'b10: begin X = P;
+`ifdef __ICARUS__
+ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[1:0] is 2'b10");
+`endif
+ end
+ 2'b11: X = $signed({Ar2, Br2});
+ default: X = 48'bx;
+ endcase
+
+ // Y multiplexer
+ case (OPMODEr[3:2])
+ 2'b00: Y = 48'b0;
+ 2'b01: begin Y = 48'b0; // FIXME: more accurate partial product modelling?
+`ifdef __ICARUS__
+ if (OPMODEr[1:0] != 2'b01) $fatal(1, "OPMODEr[1:0] must be 2'b01 when OPMODEr[3:2] is 2'b01");
+`endif
+ end
+ 2'b10: Y = {48{1'b1}};
+ 2'b11: Y = Cr;
+ default: Y = 48'bx;
+ endcase
+
+ // Z multiplexer
+ case (OPMODEr[6:4])
+ 3'b000: Z = 48'b0;
+ 3'b001: Z = PCIN;
+ 3'b010: begin Z = P;
+`ifdef __ICARUS__
+ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] i0s 3'b010");
+`endif
+ end
+ 3'b011: Z = Cr;
+ 3'b100: begin Z = P;
+`ifdef __ICARUS__
+ if (PREG != 1) $fatal(1, "PREG must be 1 when OPMODEr[6:4] is 3'b100");
+ if (OPMODEr[3:0] != 4'b1000) $fatal(1, "OPMODEr[3:0] must be 4'b1000 when OPMODEr[6:4] i0s 3'b100");
+`endif
+ end
+ 3'b101: Z = $signed(PCIN[47:17]);
+ 3'b110: Z = $signed(P[47:17]);
+ default: Z = 48'bx;
+ endcase
+ end
+
+ // Carry in
+ wire A24_xnor_B17d = A_MULT[24] ~^ B_MULT[17];
+ reg CARRYINr = 1'b0, A24_xnor_B17 = 1'b0;
+ generate
+ if (CARRYINREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) CARRYINr <= 1'b0; else if (CECARRYIN) CARRYINr <= CARRYIN; end
+ else always @* CARRYINr = CARRYIN;
+
+ if (MREG == 1) begin always @(posedge CLK) if (RSTALLCARRYIN) A24_xnor_B17 <= 1'b0; else if (CEM) A24_xnor_B17 <= A24_xnor_B17d; end
+ else always @* A24_xnor_B17 = A24_xnor_B17d;
+ endgenerate
+
+ reg cin_muxed;
+
+ always @(*) begin
+ case (CARRYINSELr)
+ 3'b000: cin_muxed = CARRYINr;
+ 3'b001: cin_muxed = ~PCIN[47];
+ 3'b010: cin_muxed = CARRYCASCIN;
+ 3'b011: cin_muxed = PCIN[47];
+ 3'b100: cin_muxed = CARRYCASCOUT;
+ 3'b101: cin_muxed = ~P[47];
+ 3'b110: cin_muxed = A24_xnor_B17;
+ 3'b111: cin_muxed = P[47];
+ default: cin_muxed = 1'bx;
+ endcase
+ end
+
+ wire alu_cin = (ALUMODEr[3] || ALUMODEr[2]) ? 1'b0 : cin_muxed;
+
+ // ALU core
+ wire [47:0] Z_muxinv = ALUMODEr[0] ? ~Z : Z;
+ wire [47:0] xor_xyz = X ^ Y ^ Z_muxinv;
+ wire [47:0] maj_xyz = (X & Y) | (X & Z_muxinv) | (Y & Z_muxinv);
+
+ wire [47:0] xor_xyz_muxed = ALUMODEr[3] ? maj_xyz : xor_xyz;
+ wire [47:0] maj_xyz_gated = ALUMODEr[2] ? 48'b0 : maj_xyz;
+
+ wire [48:0] maj_xyz_simd_gated;
+ wire [3:0] int_carry_in, int_carry_out, ext_carry_out;
+ wire [47:0] alu_sum;
+ assign int_carry_in[0] = 1'b0;
+ wire [3:0] carryout_reset;
+
+ generate
+ if (USE_SIMD == "FOUR12") begin
+ assign maj_xyz_simd_gated = {
+ maj_xyz_gated[47:36],
+ 1'b0, maj_xyz_gated[34:24],
+ 1'b0, maj_xyz_gated[22:12],
+ 1'b0, maj_xyz_gated[10:0],
+ alu_cin
+ };
+ assign int_carry_in[3:1] = 3'b000;
+ assign ext_carry_out = {
+ int_carry_out[3],
+ maj_xyz_gated[35] ^ int_carry_out[2],
+ maj_xyz_gated[23] ^ int_carry_out[1],
+ maj_xyz_gated[11] ^ int_carry_out[0]
+ };
+ assign carryout_reset = 4'b0000;
+ end else if (USE_SIMD == "TWO24") begin
+ assign maj_xyz_simd_gated = {
+ maj_xyz_gated[47:24],
+ 1'b0, maj_xyz_gated[22:0],
+ alu_cin
+ };
+ assign int_carry_in[3:1] = {int_carry_out[2], 1'b0, int_carry_out[0]};
+ assign ext_carry_out = {
+ int_carry_out[3],
+ 1'bx,
+ maj_xyz_gated[23] ^ int_carry_out[1],
+ 1'bx
+ };
+ assign carryout_reset = 4'b0x0x;
+ end else begin
+ assign maj_xyz_simd_gated = {maj_xyz_gated, alu_cin};
+ assign int_carry_in[3:1] = int_carry_out[2:0];
+ assign ext_carry_out = {
+ int_carry_out[3],
+ 3'bxxx
+ };
+ assign carryout_reset = 4'b0xxx;
+ end
+
+ genvar i;
+ for (i = 0; i < 4; i = i + 1)
+ assign {int_carry_out[i], alu_sum[i*12 +: 12]} = {1'b0, maj_xyz_simd_gated[i*12 +: ((i == 3) ? 13 : 12)]}
+ + xor_xyz_muxed[i*12 +: 12] + int_carry_in[i];
+ endgenerate
+
+ wire signed [47:0] Pd = ALUMODEr[1] ? ~alu_sum : alu_sum;
+ initial P = 48'b0;
+ initial CARRYOUT = carryout_reset;
+ initial CARRYCASCOUT = 1'b0;
+ initial MULTSIGNOUT = 1'b0;
+ wire [3:0] CARRYOUTd = (OPMODEr[3:0] == 4'b0101 || ALUMODEr[3:2] != 2'b00) ? 4'bxxxx :
+ ((ALUMODEr[0] & ALUMODEr[1]) ? ~ext_carry_out : ext_carry_out);
+ wire CARRYCASCOUTd = ext_carry_out[3];
+ wire MULTSIGNOUTd = Mrx[42];
+
+ generate
+ if (PREG == 1) begin
+ always @(posedge CLK)
+ if (RSTP) begin
+ P <= 48'b0;
+ CARRYOUT <= carryout_reset;
+ CARRYCASCOUT <= 1'b0;
+ MULTSIGNOUT <= 1'b0;
+ end else if (CEP) begin
+ P <= Pd;
+ CARRYOUT <= CARRYOUTd;
+ CARRYCASCOUT <= CARRYCASCOUTd;
+ MULTSIGNOUT <= MULTSIGNOUTd;
+ end
+ end else begin
+ always @* begin
+ P = Pd;
+ CARRYOUT = CARRYOUTd;
+ CARRYCASCOUT = CARRYCASCOUTd;
+ MULTSIGNOUT = MULTSIGNOUTd;
+ end
+ end
+ endgenerate
+
+ assign PCOUT = P;
+
+endmodule
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index a6669b872..b8abdda64 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -137,89 +137,6 @@ module DNA_PORT (...);
input SHIFT;
endmodule
-module DSP48E1 (...);
- parameter integer ACASCREG = 1;
- parameter integer ADREG = 1;
- parameter integer ALUMODEREG = 1;
- parameter integer AREG = 1;
- parameter AUTORESET_PATDET = "NO_RESET";
- parameter A_INPUT = "DIRECT";
- parameter integer BCASCREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer CARRYINREG = 1;
- parameter integer CARRYINSELREG = 1;
- parameter integer CREG = 1;
- parameter integer DREG = 1;
- parameter integer INMODEREG = 1;
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter SEL_MASK = "MASK";
- parameter SEL_PATTERN = "PATTERN";
- parameter USE_DPORT = "FALSE";
- parameter USE_MULT = "MULTIPLY";
- parameter USE_PATTERN_DETECT = "NO_PATDET";
- parameter USE_SIMD = "ONE48";
- parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
- parameter [47:0] PATTERN = 48'h000000000000;
- parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
- parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
- parameter [0:0] IS_CLK_INVERTED = 1'b0;
- parameter [4:0] IS_INMODE_INVERTED = 5'b0;
- parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
- output [29:0] ACOUT;
- output [17:0] BCOUT;
- output CARRYCASCOUT;
- output [3:0] CARRYOUT;
- output MULTSIGNOUT;
- output OVERFLOW;
- output [47:0] P;
- output PATTERNBDETECT;
- output PATTERNDETECT;
- output [47:0] PCOUT;
- output UNDERFLOW;
- input [29:0] A;
- input [29:0] ACIN;
- input [3:0] ALUMODE;
- input [17:0] B;
- input [17:0] BCIN;
- input [47:0] C;
- input CARRYCASCIN;
- input CARRYIN;
- input [2:0] CARRYINSEL;
- input CEA1;
- input CEA2;
- input CEAD;
- input CEALUMODE;
- input CEB1;
- input CEB2;
- input CEC;
- input CECARRYIN;
- input CECTRL;
- input CED;
- input CEINMODE;
- input CEM;
- input CEP;
- (* clkbuf_sink *)
- input CLK;
- input [24:0] D;
- input [4:0] INMODE;
- input MULTSIGNIN;
- input [6:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTALLCARRYIN;
- input RSTALUMODE;
- input RSTB;
- input RSTC;
- input RSTCTRL;
- input RSTD;
- input RSTINMODE;
- input RSTM;
- input RSTP;
-endmodule
-
module EFUSE_USR (...);
parameter [31:0] SIM_EFUSE_VALUE = 32'h00000000;
output [31:0] EFUSEUSR;
diff --git a/techlibs/xilinx/dsp_map.v b/techlibs/xilinx/dsp_map.v
new file mode 100644
index 000000000..cc37f0085
--- /dev/null
+++ b/techlibs/xilinx/dsp_map.v
@@ -0,0 +1,48 @@
+module \$__MUL25X18 (input [24:0] A, input [17:0] B, output [42:0] Y);
+ parameter A_SIGNED = 0;
+ parameter B_SIGNED = 0;
+ parameter A_WIDTH = 0;
+ parameter B_WIDTH = 0;
+ parameter Y_WIDTH = 0;
+
+ wire [47:0] P_48;
+ DSP48E1 #(
+ // Disable all registers
+ .ACASCREG(0),
+ .ADREG(0),
+ .A_INPUT("DIRECT"),
+ .ALUMODEREG(0),
+ .AREG(0),
+ .BCASCREG(0),
+ .B_INPUT("DIRECT"),
+ .BREG(0),
+ .CARRYINREG(0),
+ .CARRYINSELREG(0),
+ .CREG(0),
+ .DREG(0),
+ .INMODEREG(0),
+ .MREG(0),
+ .OPMODEREG(0),
+ .PREG(0),
+ .USE_MULT("MULTIPLY"),
+ .USE_SIMD("ONE48")
+ ) _TECHMAP_REPLACE_ (
+ //Data path
+ .A({{5{A[24]}}, A}),
+ .B(B),
+ .C(48'b0),
+ .D(24'b0),
+ .P(P_48),
+
+ .INMODE(5'b00000),
+ .ALUMODE(4'b0000),
+ .OPMODE(7'b000101),
+ .CARRYINSEL(3'b000),
+
+ .ACIN(30'b0),
+ .BCIN(18'b0),
+ .PCIN(48'b0),
+ .CARRYIN(1'b0)
+ );
+ assign Y = P_48;
+endmodule
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index e0e81ef1d..3d92c3e2c 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -81,6 +81,8 @@ struct SynthXilinxPass : public ScriptPass
log(" -nowidelut\n");
log(" do not use MUXF[78] resources to implement LUTs larger than LUT6s\n");
log("\n");
+ log(" -nodsp\n");
+ log(" do not use DSP48E1s to implement multipliers and associated logic\n");
log(" -iopad\n");
log(" enable I/O buffer insertion (selected automatically by -ise)\n");
log("\n");
@@ -116,7 +118,7 @@ struct SynthXilinxPass : public ScriptPass
}
std::string top_opt, edif_file, blif_file, family;
- bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, abc9;
+ bool flatten, retime, vpr, ise, iopad, noiopad, noclkbuf, nobram, nolutram, nosrl, nocarry, nowidelut, nodsp, abc9;
bool flatten_before_abc;
int widemux;
@@ -139,6 +141,7 @@ struct SynthXilinxPass : public ScriptPass
nosrl = false;
nocarry = false;
nowidelut = false;
+ nodsp = false;
abc9 = false;
flatten_before_abc = false;
widemux = 0;
@@ -240,6 +243,10 @@ struct SynthXilinxPass : public ScriptPass
abc9 = true;
continue;
}
+ if (args[argidx] == "-nodsp") {
+ nodsp = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -293,10 +300,10 @@ struct SynthXilinxPass : public ScriptPass
run(stringf("hierarchy -check %s", top_opt.c_str()));
}
- if (check_label("coarse")) {
+ if (check_label("prepare")) {
run("proc");
- if (help_mode || flatten)
- run("flatten", "(if -flatten)");
+ if (flatten || help_mode)
+ run("flatten", "(with '-flatten')");
run("opt_expr");
run("opt_clean");
run("check");
@@ -320,6 +327,18 @@ struct SynthXilinxPass : public ScriptPass
}
run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6");
+ }
+
+ if (check_label("map_dsp"), "(skip if '-nodsp')") {
+ if (!nodsp || help_mode) {
+ // NB: Xilinx multipliers are signed only
+ run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_A_MAXWIDTH_PARTIAL=18 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18");
+ run("xilinx_dsp");
+ run("chtype -set $mul t:$__soft_mul");
+ }
+ }
+
+ if (check_label("coarse")) {
run("alumacc");
run("share");
run("opt");
diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore
index 496b87461..ef3699bd2 100644
--- a/techlibs/xilinx/tests/.gitignore
+++ b/techlibs/xilinx/tests/.gitignore
@@ -4,3 +4,8 @@ bram1_[0-9]*/
bram2.log
bram2_syn.v
bram2_tb
+dsp_work*/
+test_dsp_model_ref.v
+test_dsp_model_uut.v
+test_dsp_model
+*.vcd
diff --git a/techlibs/xilinx/tests/test_dsp_model.sh b/techlibs/xilinx/tests/test_dsp_model.sh
new file mode 100644
index 000000000..2acd97eb4
--- /dev/null
+++ b/techlibs/xilinx/tests/test_dsp_model.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -ex
+sed 's/DSP48E1/DSP48E1_UUT/; /DSP48E1_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp_model_uut.v
+if [ ! -f "test_dsp_model_ref.v" ]; then
+ cat /opt/Xilinx/Vivado/2019.1/data/verilog/src/unisims/DSP48E1.v > test_dsp_model_ref.v
+fi
+for tb in simd24_preadd_noreg_nocasc simd12_preadd_noreg_nocasc \
+ mult_allreg_nopreadd_nocasc mult_noreg_nopreadd_nocasc \
+ mult_allreg_preadd_nocasc mult_noreg_preadd_nocasc mult_inreg_preadd_nocasc \
+
+do
+ iverilog -s $tb -s glbl -o test_dsp_model test_dsp_model.v test_dsp_model_uut.v test_dsp_model_ref.v /opt/Xilinx/Vivado/2019.1/data/verilog/src/glbl.v
+ vvp -N ./test_dsp_model
+done
diff --git a/techlibs/xilinx/tests/test_dsp_model.v b/techlibs/xilinx/tests/test_dsp_model.v
new file mode 100644
index 000000000..04d5b26ab
--- /dev/null
+++ b/techlibs/xilinx/tests/test_dsp_model.v
@@ -0,0 +1,597 @@
+`timescale 1ns / 1ps
+
+module testbench;
+ parameter integer ACASCREG = 1;
+ parameter integer ADREG = 1;
+ parameter integer ALUMODEREG = 1;
+ parameter integer AREG = 1;
+ parameter AUTORESET_PATDET = "NO_RESET";
+ parameter A_INPUT = "DIRECT";
+ parameter integer BCASCREG = 1;
+ parameter integer BREG = 1;
+ parameter B_INPUT = "DIRECT";
+ parameter integer CARRYINREG = 1;
+ parameter integer CARRYINSELREG = 1;
+ parameter integer CREG = 1;
+ parameter integer DREG = 1;
+ parameter integer INMODEREG = 1;
+ parameter integer MREG = 1;
+ parameter integer OPMODEREG = 1;
+ parameter integer PREG = 1;
+ parameter SEL_MASK = "MASK";
+ parameter SEL_PATTERN = "PATTERN";
+ parameter USE_DPORT = "FALSE";
+ parameter USE_MULT = "MULTIPLY";
+ parameter USE_PATTERN_DETECT = "NO_PATDET";
+ parameter USE_SIMD = "ONE48";
+ parameter [47:0] MASK = 48'h3FFFFFFFFFFF;
+ parameter [47:0] PATTERN = 48'h000000000000;
+ parameter [3:0] IS_ALUMODE_INVERTED = 4'b0;
+ parameter [0:0] IS_CARRYIN_INVERTED = 1'b0;
+ parameter [0:0] IS_CLK_INVERTED = 1'b0;
+ parameter [4:0] IS_INMODE_INVERTED = 5'b0;
+ parameter [6:0] IS_OPMODE_INVERTED = 7'b0;
+
+ reg CLK;
+ reg CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL;
+ reg CED, CEINMODE, CEM, CEP;
+ reg RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP;
+ reg [29:0] A, ACIN;
+ reg [17:0] B, BCIN;
+ reg [47:0] C;
+ reg [24:0] D;
+ reg [47:0] PCIN;
+ reg [3:0] ALUMODE;
+ reg [2:0] CARRYINSEL;
+ reg [4:0] INMODE;
+ reg [6:0] OPMODE;
+ reg CARRYCASCIN, CARRYIN, MULTSIGNIN;
+
+ output [29:0] ACOUT, REF_ACOUT;
+ output [17:0] BCOUT, REF_BCOUT;
+ output CARRYCASCOUT, REF_CARRYCASCOUT;
+ output [3:0] CARRYOUT, REF_CARRYOUT;
+ output MULTSIGNOUT, REF_MULTSIGNOUT;
+ output OVERFLOW, REF_OVERFLOW;
+ output [47:0] P, REF_P;
+ output PATTERNBDETECT, REF_PATTERNBDETECT;
+ output PATTERNDETECT, REF_PATTERNDETECT;
+ output [47:0] PCOUT, REF_PCOUT;
+ output UNDERFLOW, REF_UNDERFLOW;
+
+ integer errcount = 0;
+
+ reg ERROR_FLAG = 0;
+
+ task clkcycle;
+ begin
+ #5;
+ CLK = ~CLK;
+ #10;
+ CLK = ~CLK;
+ #2;
+ ERROR_FLAG = 0;
+ if (REF_P !== P) begin
+ $display("ERROR at %1t: REF_P=%b UUT_P=%b DIFF=%b", $time, REF_P, P, REF_P ^ P);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ if (REF_CARRYOUT !== CARRYOUT) begin
+ $display("ERROR at %1t: REF_CARRYOUT=%b UUT_CARRYOUT=%b", $time, REF_CARRYOUT, CARRYOUT);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ #3;
+ end
+ endtask
+
+ reg config_valid = 0;
+ task drc;
+ begin
+ config_valid = 1;
+ if (AREG != 2 && INMODE[0]) config_valid = 0;
+ if (BREG != 2 && INMODE[4]) config_valid = 0;
+
+ if (USE_SIMD != "ONE48" && OPMODE[3:0] == 4'b0101) config_valid = 0;
+
+ if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0;
+ if ((OPMODE[3:2] == 2'b01) ^ (OPMODE[1:0] == 2'b01) == 1'b1) config_valid = 0;
+ if ((OPMODE[6:4] == 3'b010 || OPMODE[6:4] == 3'b110) && PREG != 1) config_valid = 0;
+ if ((OPMODE[6:4] == 3'b100) && (PREG != 1 || OPMODE[3:0] != 4'b1000 || ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11)) config_valid = 0;
+ if ((CARRYINSEL == 3'b100 || CARRYINSEL == 3'b101 || CARRYINSEL == 3'b111) && (PREG != 1)) config_valid = 0;
+ if (OPMODE[6:4] == 3'b111) config_valid = 0;
+ if ((OPMODE[3:0] == 4'b0101) && CARRYINSEL == 3'b010) config_valid = 0;
+ if (CARRYINSEL == 3'b000 && OPMODE == 7'b1001000) config_valid = 0;
+
+ if ((ALUMODE[3:2] == 2'b01 || ALUMODE[3:2] == 2'b11) && OPMODE[3:2] != 2'b00 && OPMODE[3:2] != 2'b10) config_valid = 0;
+
+
+ end
+ endtask
+
+ initial begin
+ $dumpfile("test_dsp_model.vcd");
+ $dumpvars(0, testbench);
+
+ #2;
+ CLK = 1'b0;
+ {CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = 9'b111111111;
+ {CED, CEINMODE, CEM, CEP} = 4'b1111;
+
+ {A, B, C, D} = 0;
+ {ACIN, BCIN, PCIN} = 0;
+ {ALUMODE, CARRYINSEL, INMODE} = 0;
+ {OPMODE, CARRYCASCIN, CARRYIN, MULTSIGNIN} = 0;
+
+ {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = ~0;
+ repeat (10) begin
+ #10;
+ CLK = 1'b1;
+ #10;
+ CLK = 1'b0;
+ #10;
+ CLK = 1'b1;
+ #10;
+ CLK = 1'b0;
+ end
+ {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = 0;
+
+ repeat (10000) begin
+ clkcycle;
+ config_valid = 0;
+ while (!config_valid) begin
+ A = $urandom;
+ ACIN = $urandom;
+ B = $urandom;
+ BCIN = $urandom;
+ C = {$urandom, $urandom};
+ D = $urandom;
+ PCIN = {$urandom, $urandom};
+
+ {CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL} = $urandom | $urandom | $urandom;
+ {CED, CEINMODE, CEM, CEP} = $urandom | $urandom | $urandom | $urandom;
+
+ // Otherwise we can accidentally create illegal configs
+ CEINMODE = CECTRL;
+ CEALUMODE = CECTRL;
+
+ {RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom;
+ {ALUMODE, INMODE} = $urandom;
+ CARRYINSEL = $urandom & $urandom & $urandom;
+ OPMODE = $urandom;
+ if ($urandom & 1'b1)
+ OPMODE[3:0] = 4'b0101; // test multiply more than other modes
+ {CARRYCASCIN, CARRYIN, MULTSIGNIN} = $urandom;
+
+ // So few valid options in these modes, just force one valid option
+ if (CARRYINSEL == 3'b001) OPMODE = 7'b1010101;
+ if (CARRYINSEL == 3'b010) OPMODE = 7'b0001010;
+ if (CARRYINSEL == 3'b011) OPMODE = 7'b0011011;
+ if (CARRYINSEL == 3'b100) OPMODE = 7'b0110011;
+ if (CARRYINSEL == 3'b101) OPMODE = 7'b0011010;
+ if (CARRYINSEL == 3'b110) OPMODE = 7'b0010101;
+ if (CARRYINSEL == 3'b111) OPMODE = 7'b0100011;
+
+ drc;
+ end
+ end
+
+ if (errcount == 0) begin
+ $display("All tests passed.");
+ $finish;
+ end else begin
+ $display("Caught %1d errors.", errcount);
+ $stop;
+ end
+ end
+
+ DSP48E1 #(
+ .ACASCREG (ACASCREG),
+ .ADREG (ADREG),
+ .ALUMODEREG (ALUMODEREG),
+ .AREG (AREG),
+ .AUTORESET_PATDET (AUTORESET_PATDET),
+ .A_INPUT (A_INPUT),
+ .BCASCREG (BCASCREG),
+ .BREG (BREG),
+ .B_INPUT (B_INPUT),
+ .CARRYINREG (CARRYINREG),
+ .CARRYINSELREG (CARRYINSELREG),
+ .CREG (CREG),
+ .DREG (DREG),
+ .INMODEREG (INMODEREG),
+ .MREG (MREG),
+ .OPMODEREG (OPMODEREG),
+ .PREG (PREG),
+ .SEL_MASK (SEL_MASK),
+ .SEL_PATTERN (SEL_PATTERN),
+ .USE_DPORT (USE_DPORT),
+ .USE_MULT (USE_MULT),
+ .USE_PATTERN_DETECT (USE_PATTERN_DETECT),
+ .USE_SIMD (USE_SIMD),
+ .MASK (MASK),
+ .PATTERN (PATTERN),
+ .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
+ .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
+ .IS_CLK_INVERTED (IS_CLK_INVERTED),
+ .IS_INMODE_INVERTED (IS_INMODE_INVERTED),
+ .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED)
+ ) ref (
+ .ACOUT (REF_ACOUT),
+ .BCOUT (REF_BCOUT),
+ .CARRYCASCOUT (REF_CARRYCASCOUT),
+ .CARRYOUT (REF_CARRYOUT),
+ .MULTSIGNOUT (REF_MULTSIGNOUT),
+ .OVERFLOW (REF_OVERFLOW),
+ .P (REF_P),
+ .PATTERNBDETECT(REF_PATTERNBDETECT),
+ .PATTERNDETECT (REF_PATTERNDETECT),
+ .PCOUT (REF_PCOUT),
+ .UNDERFLOW (REF_UNDERFLOW),
+ .A (A),
+ .ACIN (ACIN),
+ .ALUMODE (ALUMODE),
+ .B (B),
+ .BCIN (BCIN),
+ .C (C),
+ .CARRYCASCIN (CARRYCASCIN),
+ .CARRYINSEL (CARRYINSEL),
+ .CEA1 (CEA1),
+ .CEA2 (CEA2),
+ .CEAD (CEAD),
+ .CEALUMODE (CEALUMODE),
+ .CEB1 (CEB1),
+ .CEB2 (CEB2),
+ .CEC (CEC),
+ .CECARRYIN (CECARRYIN),
+ .CECTRL (CECTRL),
+ .CED (CED),
+ .CEINMODE (CEINMODE),
+ .CEM (CEM),
+ .CEP (CEP),
+ .CLK (CLK),
+ .D (D),
+ .INMODE (INMODE),
+ .MULTSIGNIN (MULTSIGNIN),
+ .OPMODE (OPMODE),
+ .PCIN (PCIN),
+ .RSTA (RSTA),
+ .RSTALLCARRYIN (RSTALLCARRYIN),
+ .RSTALUMODE (RSTALUMODE),
+ .RSTB (RSTB),
+ .RSTC (RSTC),
+ .RSTCTRL (RSTCTRL),
+ .RSTD (RSTD),
+ .RSTINMODE (RSTINMODE),
+ .RSTM (RSTM),
+ .RSTP (RSTP)
+ );
+
+ DSP48E1_UUT #(
+ .ACASCREG (ACASCREG),
+ .ADREG (ADREG),
+ .ALUMODEREG (ALUMODEREG),
+ .AREG (AREG),
+ .AUTORESET_PATDET (AUTORESET_PATDET),
+ .A_INPUT (A_INPUT),
+ .BCASCREG (BCASCREG),
+ .BREG (BREG),
+ .B_INPUT (B_INPUT),
+ .CARRYINREG (CARRYINREG),
+ .CARRYINSELREG (CARRYINSELREG),
+ .CREG (CREG),
+ .DREG (DREG),
+ .INMODEREG (INMODEREG),
+ .MREG (MREG),
+ .OPMODEREG (OPMODEREG),
+ .PREG (PREG),
+ .SEL_MASK (SEL_MASK),
+ .SEL_PATTERN (SEL_PATTERN),
+ .USE_DPORT (USE_DPORT),
+ .USE_MULT (USE_MULT),
+ .USE_PATTERN_DETECT (USE_PATTERN_DETECT),
+ .USE_SIMD (USE_SIMD),
+ .MASK (MASK),
+ .PATTERN (PATTERN),
+ .IS_ALUMODE_INVERTED(IS_ALUMODE_INVERTED),
+ .IS_CARRYIN_INVERTED(IS_CARRYIN_INVERTED),
+ .IS_CLK_INVERTED (IS_CLK_INVERTED),
+ .IS_INMODE_INVERTED (IS_INMODE_INVERTED),
+ .IS_OPMODE_INVERTED (IS_OPMODE_INVERTED)
+ ) uut (
+ .ACOUT (ACOUT),
+ .BCOUT (BCOUT),
+ .CARRYCASCOUT (CARRYCASCOUT),
+ .CARRYOUT (CARRYOUT),
+ .MULTSIGNOUT (MULTSIGNOUT),
+ .OVERFLOW (OVERFLOW),
+ .P (P),
+ .PATTERNBDETECT(PATTERNBDETECT),
+ .PATTERNDETECT (PATTERNDETECT),
+ .PCOUT (PCOUT),
+ .UNDERFLOW (UNDERFLOW),
+ .A (A),
+ .ACIN (ACIN),
+ .ALUMODE (ALUMODE),
+ .B (B),
+ .BCIN (BCIN),
+ .C (C),
+ .CARRYCASCIN (CARRYCASCIN),
+ .CARRYINSEL (CARRYINSEL),
+ .CEA1 (CEA1),
+ .CEA2 (CEA2),
+ .CEAD (CEAD),
+ .CEALUMODE (CEALUMODE),
+ .CEB1 (CEB1),
+ .CEB2 (CEB2),
+ .CEC (CEC),
+ .CECARRYIN (CECARRYIN),
+ .CECTRL (CECTRL),
+ .CED (CED),
+ .CEINMODE (CEINMODE),
+ .CEM (CEM),
+ .CEP (CEP),
+ .CLK (CLK),
+ .D (D),
+ .INMODE (INMODE),
+ .MULTSIGNIN (MULTSIGNIN),
+ .OPMODE (OPMODE),
+ .PCIN (PCIN),
+ .RSTA (RSTA),
+ .RSTALLCARRYIN (RSTALLCARRYIN),
+ .RSTALUMODE (RSTALUMODE),
+ .RSTB (RSTB),
+ .RSTC (RSTC),
+ .RSTCTRL (RSTCTRL),
+ .RSTD (RSTD),
+ .RSTINMODE (RSTINMODE),
+ .RSTM (RSTM),
+ .RSTP (RSTP)
+ );
+endmodule
+
+module mult_noreg_nopreadd_nocasc;
+ testbench #(
+ .ACASCREG (0),
+ .ADREG (0),
+ .ALUMODEREG (0),
+ .AREG (0),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (0),
+ .BREG (0),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .CREG (0),
+ .DREG (0),
+ .INMODEREG (0),
+ .MREG (0),
+ .OPMODEREG (0),
+ .PREG (0),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("FALSE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("ONE48"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+module mult_allreg_nopreadd_nocasc;
+ testbench #(
+ .ACASCREG (1),
+ .ADREG (1),
+ .ALUMODEREG (1),
+ .AREG (2),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (1),
+ .BREG (2),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (1),
+ .CARRYINSELREG (1),
+ .CREG (1),
+ .DREG (1),
+ .INMODEREG (1),
+ .MREG (1),
+ .OPMODEREG (1),
+ .PREG (1),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("FALSE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("ONE48"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+module mult_noreg_preadd_nocasc;
+ testbench #(
+ .ACASCREG (0),
+ .ADREG (0),
+ .ALUMODEREG (0),
+ .AREG (0),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (0),
+ .BREG (0),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .CREG (0),
+ .DREG (0),
+ .INMODEREG (0),
+ .MREG (0),
+ .OPMODEREG (0),
+ .PREG (0),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("TRUE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("ONE48"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+module mult_allreg_preadd_nocasc;
+ testbench #(
+ .ACASCREG (1),
+ .ADREG (1),
+ .ALUMODEREG (1),
+ .AREG (2),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (1),
+ .BREG (2),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (1),
+ .CARRYINSELREG (1),
+ .CREG (1),
+ .DREG (1),
+ .INMODEREG (1),
+ .MREG (1),
+ .OPMODEREG (1),
+ .PREG (1),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("TRUE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("ONE48"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+module mult_inreg_preadd_nocasc;
+ testbench #(
+ .ACASCREG (1),
+ .ADREG (0),
+ .ALUMODEREG (0),
+ .AREG (1),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (1),
+ .BREG (1),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .CREG (1),
+ .DREG (1),
+ .INMODEREG (0),
+ .MREG (0),
+ .OPMODEREG (0),
+ .PREG (0),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("TRUE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("ONE48"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+module simd12_preadd_noreg_nocasc;
+ testbench #(
+ .ACASCREG (0),
+ .ADREG (0),
+ .ALUMODEREG (0),
+ .AREG (0),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (0),
+ .BREG (0),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .CREG (0),
+ .DREG (0),
+ .INMODEREG (0),
+ .MREG (0),
+ .OPMODEREG (0),
+ .PREG (0),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("TRUE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("FOUR12"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule
+
+
+module simd24_preadd_noreg_nocasc;
+ testbench #(
+ .ACASCREG (0),
+ .ADREG (0),
+ .ALUMODEREG (0),
+ .AREG (0),
+ .AUTORESET_PATDET ("NO_RESET"),
+ .A_INPUT ("DIRECT"),
+ .BCASCREG (0),
+ .BREG (0),
+ .B_INPUT ("DIRECT"),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .CREG (0),
+ .DREG (0),
+ .INMODEREG (0),
+ .MREG (0),
+ .OPMODEREG (0),
+ .PREG (0),
+ .SEL_MASK ("MASK"),
+ .SEL_PATTERN ("PATTERN"),
+ .USE_DPORT ("TRUE"),
+ .USE_MULT ("DYNAMIC"),
+ .USE_PATTERN_DETECT ("NO_PATDET"),
+ .USE_SIMD ("TWO24"),
+ .MASK (48'h3FFFFFFFFFFF),
+ .PATTERN (48'h000000000000),
+ .IS_ALUMODE_INVERTED(4'b0),
+ .IS_CARRYIN_INVERTED(1'b0),
+ .IS_CLK_INVERTED (1'b0),
+ .IS_INMODE_INVERTED (5'b0),
+ .IS_OPMODE_INVERTED (7'b0)
+ ) testbench ();
+endmodule \ No newline at end of file