aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcin Koƛcielnicki <koriakin@0x04.net>2019-11-21 13:05:30 +0100
committerMarcelina Koƛcielnicka <mwk@0x04.net>2020-01-29 01:40:00 +0100
commit7e0e42f907260e76e3c7cb01c907a0cf61a6e326 (patch)
tree1a948b1efc41c7d639feff064eb9e8713c2486eb
parent7939727d14f44b5d56ca3806d0907e9fceea2882 (diff)
downloadyosys-7e0e42f907260e76e3c7cb01c907a0cf61a6e326.tar.gz
yosys-7e0e42f907260e76e3c7cb01c907a0cf61a6e326.tar.bz2
yosys-7e0e42f907260e76e3c7cb01c907a0cf61a6e326.zip
xilinx: Add simulation model for DSP48 (Virtex 4).
-rw-r--r--techlibs/xilinx/cells_sim.v230
-rw-r--r--techlibs/xilinx/cells_xtra.py2
-rw-r--r--techlibs/xilinx/cells_xtra.v43
-rw-r--r--techlibs/xilinx/tests/.gitignore3
-rw-r--r--techlibs/xilinx/tests/test_dsp48_model.sh14
-rw-r--r--techlibs/xilinx/tests/test_dsp48_model.v287
6 files changed, 534 insertions, 45 deletions
diff --git a/techlibs/xilinx/cells_sim.v b/techlibs/xilinx/cells_sim.v
index 22dca3c47..eb145593e 100644
--- a/techlibs/xilinx/cells_sim.v
+++ b/techlibs/xilinx/cells_sim.v
@@ -2155,7 +2155,235 @@ assign PCOUT = P;
endmodule
-// TODO: DSP48 (Virtex 4).
+module DSP48 (
+ input signed [17:0] A,
+ input signed [17:0] B,
+ input signed [47:0] C,
+ input signed [17:0] BCIN,
+ input signed [47:0] PCIN,
+ input CARRYIN,
+ input [6:0] OPMODE,
+ input SUBTRACT,
+ input [1:0] CARRYINSEL,
+ output signed [47:0] P,
+ output signed [17:0] BCOUT,
+ output signed [47:0] PCOUT,
+ (* clkbuf_sink *)
+ input CLK,
+ input CEA,
+ input CEB,
+ input CEC,
+ input CEM,
+ input CECARRYIN,
+ input CECINSUB,
+ input CECTRL,
+ input CEP,
+ input RSTA,
+ input RSTB,
+ input RSTC,
+ input RSTM,
+ input RSTCARRYIN,
+ input RSTCTRL,
+ input RSTP
+);
+
+parameter integer AREG = 1;
+parameter integer BREG = 1;
+parameter integer CREG = 1;
+parameter integer MREG = 1;
+parameter integer PREG = 1;
+parameter integer CARRYINREG = 1;
+parameter integer CARRYINSELREG = 1;
+parameter integer OPMODEREG = 1;
+parameter integer SUBTRACTREG = 1;
+parameter B_INPUT = "DIRECT";
+parameter LEGACY_MODE = "MULT18X18S";
+
+wire signed [17:0] A_OUT;
+wire signed [17:0] B_OUT;
+wire signed [47:0] C_OUT;
+wire signed [35:0] M_MULT;
+wire signed [35:0] M_OUT;
+wire signed [47:0] P_IN;
+wire [6:0] OPMODE_OUT;
+wire [1:0] CARRYINSEL_OUT;
+wire CARRYIN_OUT;
+wire SUBTRACT_OUT;
+reg INT_CARRYIN_XY;
+reg INT_CARRYIN_Z;
+reg signed [47:0] XMUX;
+reg signed [47:0] YMUX;
+wire signed [47:0] XYMUX;
+reg signed [47:0] ZMUX;
+reg CIN;
+
+// The B input multiplexer.
+wire signed [17:0] B_MUX;
+assign B_MUX = (B_INPUT == "DIRECT") ? B : BCIN;
+
+// The cascade output.
+assign BCOUT = B_OUT;
+assign PCOUT = P;
+
+// The registers.
+reg signed [17:0] A0_REG;
+reg signed [17:0] A1_REG;
+reg signed [17:0] B0_REG;
+reg signed [17:0] B1_REG;
+reg signed [47:0] C_REG;
+reg signed [35:0] M_REG;
+reg signed [47:0] P_REG;
+reg [6:0] OPMODE_REG;
+reg [1:0] CARRYINSEL_REG;
+reg SUBTRACT_REG;
+reg CARRYIN_REG;
+reg INT_CARRYIN_XY_REG;
+
+initial begin
+ A0_REG = 0;
+ A1_REG = 0;
+ B0_REG = 0;
+ B1_REG = 0;
+ C_REG = 0;
+ M_REG = 0;
+ P_REG = 0;
+ OPMODE_REG = 0;
+ CARRYINSEL_REG = 0;
+ SUBTRACT_REG = 0;
+ CARRYIN_REG = 0;
+ INT_CARRYIN_XY_REG = 0;
+end
+
+always @(posedge CLK) begin
+ if (RSTA) begin
+ A0_REG <= 0;
+ A1_REG <= 0;
+ end else if (CEA) begin
+ A0_REG <= A;
+ A1_REG <= A0_REG;
+ end
+ if (RSTB) begin
+ B0_REG <= 0;
+ B1_REG <= 0;
+ end else if (CEB) begin
+ B0_REG <= B_MUX;
+ B1_REG <= B0_REG;
+ end
+ if (RSTC) begin
+ C_REG <= 0;
+ end else if (CEC) begin
+ C_REG <= C;
+ end
+ if (RSTM) begin
+ M_REG <= 0;
+ end else if (CEM) begin
+ M_REG <= M_MULT;
+ end
+ if (RSTP) begin
+ P_REG <= 0;
+ end else if (CEP) begin
+ P_REG <= P_IN;
+ end
+ if (RSTCTRL) begin
+ OPMODE_REG <= 0;
+ CARRYINSEL_REG <= 0;
+ SUBTRACT_REG <= 0;
+ end else begin
+ if (CECTRL) begin
+ OPMODE_REG <= OPMODE;
+ CARRYINSEL_REG <= CARRYINSEL;
+ end
+ if (CECINSUB)
+ SUBTRACT_REG <= SUBTRACT;
+ end
+ if (RSTCARRYIN) begin
+ CARRYIN_REG <= 0;
+ INT_CARRYIN_XY_REG <= 0;
+ end else begin
+ if (CECINSUB)
+ CARRYIN_REG <= CARRYIN;
+ if (CECARRYIN)
+ INT_CARRYIN_XY_REG <= INT_CARRYIN_XY;
+ end
+end
+
+// The register enables.
+assign A_OUT = (AREG == 2) ? A1_REG : (AREG == 1) ? A0_REG : A;
+assign B_OUT = (BREG == 2) ? B1_REG : (BREG == 1) ? B0_REG : B_MUX;
+assign C_OUT = (CREG == 1) ? C_REG : C;
+assign M_OUT = (MREG == 1) ? M_REG : M_MULT;
+assign P = (PREG == 1) ? P_REG : P_IN;
+assign OPMODE_OUT = (OPMODEREG == 1) ? OPMODE_REG : OPMODE;
+assign SUBTRACT_OUT = (SUBTRACTREG == 1) ? SUBTRACT_REG : SUBTRACT;
+assign CARRYINSEL_OUT = (CARRYINSELREG == 1) ? CARRYINSEL_REG : CARRYINSEL;
+assign CARRYIN_OUT = (CARRYINREG == 1) ? CARRYIN_REG : CARRYIN;
+
+// The multiplier.
+assign M_MULT = A_OUT * B_OUT;
+
+// The post-adder inputs.
+always @* begin
+ case (OPMODE_OUT[1:0])
+ 2'b00: XMUX <= 0;
+ 2'b10: XMUX <= P;
+ 2'b11: XMUX <= {{12{A_OUT[17]}}, A_OUT, B_OUT};
+ default: XMUX <= 48'hxxxxxxxxxxxx;
+ endcase
+ case (OPMODE_OUT[1:0])
+ 2'b01: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17];
+ 2'b11: INT_CARRYIN_XY <= ~A_OUT[17];
+ // TODO: not tested in hardware.
+ default: INT_CARRYIN_XY <= A_OUT[17] ~^ B_OUT[17];
+ endcase
+end
+
+always @* begin
+ case (OPMODE_OUT[3:2])
+ 2'b00: YMUX <= 0;
+ 2'b11: YMUX <= C_OUT;
+ default: YMUX <= 48'hxxxxxxxxxxxx;
+ endcase
+end
+
+assign XYMUX = (OPMODE_OUT[3:0] == 4'b0101) ? M_OUT : (XMUX + YMUX);
+
+always @* begin
+ case (OPMODE_OUT[6:4])
+ 3'b000: ZMUX <= 0;
+ 3'b001: ZMUX <= PCIN;
+ 3'b010: ZMUX <= P;
+ 3'b011: ZMUX <= C_OUT;
+ 3'b101: ZMUX <= {{17{PCIN[47]}}, PCIN[47:17]};
+ 3'b110: ZMUX <= {{17{P[47]}}, P[47:17]};
+ default: ZMUX <= 48'hxxxxxxxxxxxx;
+ endcase
+ // TODO: check how all this works on actual hw.
+ if (OPMODE_OUT[1:0] == 2'b10)
+ INT_CARRYIN_Z <= ~P[47];
+ else
+ case (OPMODE_OUT[6:4])
+ 3'b001: INT_CARRYIN_Z <= ~PCIN[47];
+ 3'b010: INT_CARRYIN_Z <= ~P[47];
+ 3'b101: INT_CARRYIN_Z <= ~PCIN[47];
+ 3'b110: INT_CARRYIN_Z <= ~P[47];
+ default: INT_CARRYIN_Z <= 1'bx;
+ endcase
+end
+
+always @* begin
+ case (CARRYINSEL_OUT)
+ 2'b00: CIN <= CARRYIN_OUT;
+ 2'b01: CIN <= INT_CARRYIN_Z;
+ 2'b10: CIN <= INT_CARRYIN_XY;
+ 2'b11: CIN <= INT_CARRYIN_XY_REG;
+ default: CIN <= 1'bx;
+ endcase
+end
+
+// The post-adder.
+assign P_IN = SUBTRACT_OUT ? (ZMUX - (XYMUX + CIN)) : (ZMUX + XYMUX + CIN);
+
+endmodule
// TODO: DSP48E (Virtex 5).
diff --git a/techlibs/xilinx/cells_xtra.py b/techlibs/xilinx/cells_xtra.py
index d5c58c5d7..06e982a0e 100644
--- a/techlibs/xilinx/cells_xtra.py
+++ b/techlibs/xilinx/cells_xtra.py
@@ -209,7 +209,7 @@ CELLS = [
# Cell('MULT18X18SIO', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3E
# Cell('DSP48A', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 3A DSP
# Cell('DSP48A1', port_attrs={'CLK': ['clkbuf_sink']}), # Spartan 6
- Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4
+ # Cell('DSP48', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 4
Cell('DSP48E', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 5
#Cell('DSP48E1', port_attrs={'CLK': ['clkbuf_sink']}), # Virtex 6 / Series 7
Cell('DSP48E2', port_attrs={'CLK': ['clkbuf_sink']}), # Ultrascale
diff --git a/techlibs/xilinx/cells_xtra.v b/techlibs/xilinx/cells_xtra.v
index c3e5c72f9..54e48f1a6 100644
--- a/techlibs/xilinx/cells_xtra.v
+++ b/techlibs/xilinx/cells_xtra.v
@@ -5476,49 +5476,6 @@ module URAM288_BASE (...);
input SLEEP;
endmodule
-module DSP48 (...);
- parameter integer AREG = 1;
- parameter integer BREG = 1;
- parameter B_INPUT = "DIRECT";
- parameter integer CARRYINREG = 1;
- parameter integer CARRYINSELREG = 1;
- parameter integer CREG = 1;
- parameter LEGACY_MODE = "MULT18X18S";
- parameter integer MREG = 1;
- parameter integer OPMODEREG = 1;
- parameter integer PREG = 1;
- parameter integer SUBTRACTREG = 1;
- output [17:0] BCOUT;
- output [47:0] P;
- output [47:0] PCOUT;
- input [17:0] A;
- input [17:0] B;
- input [17:0] BCIN;
- input [47:0] C;
- input CARRYIN;
- input [1:0] CARRYINSEL;
- input CEA;
- input CEB;
- input CEC;
- input CECARRYIN;
- input CECINSUB;
- input CECTRL;
- input CEM;
- input CEP;
- (* clkbuf_sink *)
- input CLK;
- input [6:0] OPMODE;
- input [47:0] PCIN;
- input RSTA;
- input RSTB;
- input RSTC;
- input RSTCARRYIN;
- input RSTCTRL;
- input RSTM;
- input RSTP;
- input SUBTRACT;
-endmodule
-
module DSP48E (...);
parameter SIM_MODE = "SAFE";
parameter integer ACASCREG = 1;
diff --git a/techlibs/xilinx/tests/.gitignore b/techlibs/xilinx/tests/.gitignore
index 848f88d53..0d9c28fde 100644
--- a/techlibs/xilinx/tests/.gitignore
+++ b/techlibs/xilinx/tests/.gitignore
@@ -12,4 +12,7 @@ test_dsp48a_model_ref.v
test_dsp48a1_model_ref.v
test_dsp48a1_model_uut.v
test_dsp48a1_model
+test_dsp48_model_ref.v
+test_dsp48_model_uut.v
+test_dsp48_model
*.vcd
diff --git a/techlibs/xilinx/tests/test_dsp48_model.sh b/techlibs/xilinx/tests/test_dsp48_model.sh
new file mode 100644
index 000000000..9a73f9b0c
--- /dev/null
+++ b/techlibs/xilinx/tests/test_dsp48_model.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -ex
+if [ -z $ISE_DIR ]; then
+ ISE_DIR=/opt/Xilinx/ISE/14.7
+fi
+sed 's/DSP48 /DSP48_UUT /; /DSP48_UUT/,/endmodule/ p; d;' < ../cells_sim.v > test_dsp48_model_uut.v
+if [ ! -f "test_dsp48_model_ref.v" ]; then
+ cp $ISE_DIR/ISE_DS/ISE/verilog/src/unisims/DSP48.v test_dsp48_model_ref.v
+fi
+for tb in mult_allreg mult_noreg mult_inreg
+do
+ iverilog -s $tb -s glbl -o test_dsp48_model test_dsp48_model.v test_dsp48_model_uut.v test_dsp48_model_ref.v $ISE_DIR/ISE_DS/ISE/verilog/src/glbl.v
+ vvp -N ./test_dsp48_model
+done
diff --git a/techlibs/xilinx/tests/test_dsp48_model.v b/techlibs/xilinx/tests/test_dsp48_model.v
new file mode 100644
index 000000000..d69c00e93
--- /dev/null
+++ b/techlibs/xilinx/tests/test_dsp48_model.v
@@ -0,0 +1,287 @@
+`timescale 1ns / 1ps
+
+module testbench;
+ parameter integer AREG = 1;
+ parameter integer BREG = 1;
+ parameter integer CREG = 1;
+ parameter integer MREG = 1;
+ parameter integer PREG = 1;
+ parameter integer CARRYINREG = 1;
+ parameter integer CARRYINSELREG = 1;
+ parameter integer OPMODEREG = 1;
+ parameter integer SUBTRACTREG = 1;
+ parameter B_INPUT = "DIRECT";
+ parameter LEGACY_MODE = "NONE";
+
+ reg CLK;
+ reg CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL;
+ reg RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL;
+ reg [17:0] A;
+ reg [17:0] B;
+ reg [47:0] C;
+ reg [17:0] BCIN;
+ reg [47:0] PCIN;
+ reg CARRYIN;
+ reg [6:0] OPMODE;
+ reg SUBTRACT;
+ reg [1:0] CARRYINSEL;
+
+ output [47:0] P, REF_P;
+ output [17:0] BCOUT, REF_BCOUT;
+ output [47:0] PCOUT, REF_PCOUT;
+
+ integer errcount = 0;
+
+ reg ERROR_FLAG = 0;
+
+ task clkcycle;
+ begin
+ #5;
+ CLK = ~CLK;
+ #10;
+ CLK = ~CLK;
+ #2;
+ ERROR_FLAG = 0;
+ if (REF_BCOUT !== BCOUT) begin
+ $display("ERROR at %1t: REF_BCOUT=%b UUT_BCOUT=%b DIFF=%b", $time, REF_BCOUT, BCOUT, REF_BCOUT ^ BCOUT);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ 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_PCOUT !== PCOUT) begin
+ $display("ERROR at %1t: REF_PCOUT=%b UUT_PCOUT=%b DIFF=%b", $time, REF_PCOUT, PCOUT, REF_PCOUT ^ PCOUT);
+ errcount = errcount + 1;
+ ERROR_FLAG = 1;
+ end
+ #3;
+ end
+ endtask
+
+ reg config_valid = 0;
+ task drc;
+ begin
+ config_valid = 1;
+
+ if (OPMODE[1:0] == 2'b10 && PREG != 1) config_valid = 0;
+ if (OPMODE[1:0] == 2'b00 && CARRYINSEL == 2'b10) config_valid = 0;
+ if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b10) config_valid = 0;
+ if (OPMODE[1:0] == 2'b00 && CARRYINSEL == 2'b11) config_valid = 0;
+ if (OPMODE[1:0] == 2'b10 && CARRYINSEL == 2'b11) config_valid = 0;
+ if (OPMODE[3:2] == 2'b10) 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) config_valid = 0;
+ if (OPMODE[6:4] == 3'b111) config_valid = 0;
+ if (OPMODE[6:4] == 3'b000 && CARRYINSEL == 2'b01) config_valid = 0;
+ if (OPMODE[6:4] == 3'b011 && CARRYINSEL == 2'b01) config_valid = 0;
+
+ // Xilinx models consider these combinations invalid for an unknown reason.
+ if (CARRYINSEL == 2'b01 && OPMODE[3:2] == 2'b00) config_valid = 0;
+ if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000011) config_valid = 0;
+ if (CARRYINSEL == 2'b10 && OPMODE == 7'b0000101) config_valid = 0;
+ if (CARRYINSEL == 2'b10 && OPMODE == 7'b0100011) config_valid = 0;
+ if (CARRYINSEL == 2'b10 && OPMODE == 7'b0111111) config_valid = 0;
+ if (CARRYINSEL == 2'b10 && OPMODE == 7'b1100011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0000101) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0011111) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0010011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0100101) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0101111) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0110011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b0111111) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b1010011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b1011111) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100011) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b1100101) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE == 7'b1101111) config_valid = 0;
+
+ if (CARRYINSEL == 2'b10 && OPMODE[3:0] == 4'b0101 && MREG == 1) config_valid = 0;
+ if (CARRYINSEL == 2'b11 && OPMODE[3:0] == 4'b0101 && MREG == 0) config_valid = 0;
+ end
+ endtask
+
+ initial begin
+ $dumpfile("test_dsp48_model.vcd");
+ $dumpvars(0, testbench);
+
+ #2;
+ CLK = 1'b0;
+ {CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = 8'b11111111;
+ {A, B, C, PCIN, OPMODE, SUBTRACT, CARRYIN, CARRYINSEL} = 0;
+ {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 7'b1111111;
+ repeat (10) begin
+ #10;
+ CLK = 1'b1;
+ #10;
+ CLK = 1'b0;
+ #10;
+ CLK = 1'b1;
+ #10;
+ CLK = 1'b0;
+ end
+ {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = 0;
+
+ repeat (100000) begin
+ clkcycle;
+ config_valid = 0;
+ while (!config_valid) begin
+ A = $urandom;
+ B = $urandom;
+ C = {$urandom, $urandom};
+ BCIN = $urandom;
+ PCIN = {$urandom, $urandom};
+
+ {CEA, CEB, CEC, CEM, CEP, CECARRYIN, CECINSUB, CECTRL} = $urandom | $urandom | $urandom;
+ {RSTA, RSTB, RSTC, RSTM, RSTP, RSTCARRYIN, RSTCTRL} = $urandom & $urandom & $urandom & $urandom & $urandom & $urandom;
+ {CARRYIN, CARRYINSEL, OPMODE, SUBTRACT} = $urandom;
+
+ drc;
+ end
+ end
+
+ if (errcount == 0) begin
+ $display("All tests passed.");
+ $finish;
+ end else begin
+ $display("Caught %1d errors.", errcount);
+ $stop;
+ end
+ end
+
+ DSP48 #(
+ .AREG (AREG),
+ .BREG (BREG),
+ .CREG (CREG),
+ .MREG (MREG),
+ .PREG (PREG),
+ .CARRYINREG (CARRYINREG),
+ .CARRYINSELREG (CARRYINSELREG),
+ .OPMODEREG (OPMODEREG),
+ .SUBTRACTREG (SUBTRACTREG),
+ .B_INPUT (B_INPUT),
+ .LEGACY_MODE (LEGACY_MODE)
+ ) ref (
+ .A (A),
+ .B (B),
+ .C (C),
+ .BCIN (BCIN),
+ .PCIN (PCIN),
+ .CARRYIN (CARRYIN),
+ .OPMODE (OPMODE),
+ .SUBTRACT (SUBTRACT),
+ .CARRYINSEL (CARRYINSEL),
+ .BCOUT (REF_BCOUT),
+ .P (REF_P),
+ .PCOUT (REF_PCOUT),
+ .CEA (CEA),
+ .CEB (CEB),
+ .CEC (CEC),
+ .CEM (CEM),
+ .CEP (CEP),
+ .CECARRYIN (CECARRYIN),
+ .CECINSUB (CECINSUB),
+ .CECTRL (CECTRL),
+ .CLK (CLK),
+ .RSTA (RSTA),
+ .RSTB (RSTB),
+ .RSTC (RSTC),
+ .RSTM (RSTM),
+ .RSTP (RSTP),
+ .RSTCARRYIN (RSTCARRYIN),
+ .RSTCTRL (RSTCTRL)
+ );
+
+ DSP48_UUT #(
+ .AREG (AREG),
+ .BREG (BREG),
+ .CREG (CREG),
+ .MREG (MREG),
+ .PREG (PREG),
+ .CARRYINREG (CARRYINREG),
+ .CARRYINSELREG (CARRYINSELREG),
+ .OPMODEREG (OPMODEREG),
+ .SUBTRACTREG (SUBTRACTREG),
+ .B_INPUT (B_INPUT),
+ .LEGACY_MODE (LEGACY_MODE)
+ ) uut (
+ .A (A),
+ .B (B),
+ .C (C),
+ .BCIN (BCIN),
+ .PCIN (PCIN),
+ .CARRYIN (CARRYIN),
+ .OPMODE (OPMODE),
+ .SUBTRACT (SUBTRACT),
+ .CARRYINSEL (CARRYINSEL),
+ .BCOUT (BCOUT),
+ .P (P),
+ .PCOUT (PCOUT),
+ .CEA (CEA),
+ .CEB (CEB),
+ .CEC (CEC),
+ .CEM (CEM),
+ .CEP (CEP),
+ .CECARRYIN (CECARRYIN),
+ .CECINSUB (CECINSUB),
+ .CECTRL (CECTRL),
+ .CLK (CLK),
+ .RSTA (RSTA),
+ .RSTB (RSTB),
+ .RSTC (RSTC),
+ .RSTM (RSTM),
+ .RSTP (RSTP),
+ .RSTCARRYIN (RSTCARRYIN),
+ .RSTCTRL (RSTCTRL)
+ );
+endmodule
+
+module mult_noreg;
+ testbench #(
+ .AREG (0),
+ .BREG (0),
+ .CREG (0),
+ .MREG (0),
+ .PREG (0),
+ .CARRYINREG (0),
+ .CARRYINSELREG (0),
+ .OPMODEREG (0),
+ .SUBTRACTREG (0),
+ .B_INPUT ("DIRECT")
+ ) testbench ();
+endmodule
+
+module mult_allreg;
+ testbench #(
+ .AREG (1),
+ .BREG (1),
+ .CREG (1),
+ .MREG (1),
+ .PREG (1),
+ .CARRYINREG (1),
+ .CARRYINSELREG (1),
+ .OPMODEREG (1),
+ .SUBTRACTREG (1),
+ .B_INPUT ("CASCADE")
+ ) testbench ();
+endmodule
+
+module mult_inreg;
+ testbench #(
+ .AREG (1),
+ .BREG (1),
+ .CREG (1),
+ .MREG (0),
+ .PREG (0),
+ .CARRYINREG (1),
+ .CARRYINSELREG (0),
+ .OPMODEREG (0),
+ .SUBTRACTREG (0),
+ .B_INPUT ("DIRECT")
+ ) testbench ();
+endmodule