|  | // DSP48E1 - 7 Series DSP48E1 User Guide UG479 (v1.9) September 27, 2016 | 
|  |  | 
|  | `ifndef PB_TYPE | 
|  | `include "alu/alu.sim.v" | 
|  | `include "alumode_mux/alumode_mux.sim.v" | 
|  | `include "carryinsel_logic/carryinsel_logic.sim.v" | 
|  | `include "carryinsel_mux/carryinsel_mux.sim.v" | 
|  | `include "creg_mux/creg_mux.sim.v" | 
|  | `include "dual_ad_preadder/dual_ad_preadder.sim.v" | 
|  | `include "dual_b_reg/dual_b_reg.sim.v" | 
|  | `include "inmode_mux/inmode_mux.sim.v" | 
|  | `include "mult25x18/mult25x18.sim.v" | 
|  | `include "mult_mux/mult_mux.sim.v" | 
|  | `include "nreg/nreg.sim.v" | 
|  | `include "opmode_mux/opmode_mux.sim.v" | 
|  | `include "xmux/dsp48_xmux.sim.v" | 
|  | `include "ymux/dsp48_ymux.sim.v" | 
|  | `include "zmux/dsp48_zmux.sim.v" | 
|  | `endif | 
|  |  | 
|  | // Figure 2-1: 7 Series FPGA DSP48E1 Slice | 
|  | module DSP48E1( | 
|  | A, B, C, D, | 
|  | OPMODE,ALUMODE, CARRYIN, CARRYINSEL, INMODE, | 
|  | CEA1, CEA2, CEB1, CEB2, CEC, CED, CEM, CEP, CEAD, | 
|  | CEALUMODE, CECTRL, CECARRYIN, CEINMODE, | 
|  | RSTA, RSTB, RSTC, RSTD, RSTM, RSTP, RSTCTRL, RSTALLCARRYIN, RSTALUMODE, RSTINMODE, | 
|  | CLK, | 
|  | ACIN, BCIN, PCIN, CARRYCASCIN, MULTSIGNIN, | 
|  | ACOUT, BCOUT, PCOUT, P, CARRYOUT, CARRYCASCOUT, MULTSIGNOUT, PATTERNDETECT, PATTERNBDETECT, OVERFLOW, UNDERFLOW | 
|  | ); | 
|  |  | 
|  | // Main inputs | 
|  | input wire [29:0] A; | 
|  | input wire [17:0] B; | 
|  | input wire [47:0] C; | 
|  | input wire [24:0] D; | 
|  | input wire [6:0]  OPMODE; | 
|  | input wire [3:0]  ALUMODE; | 
|  | input wire 	     CARRYIN; | 
|  | input wire [2:0]  CARRYINSEL; | 
|  | input wire [4:0]  INMODE; | 
|  |  | 
|  | // Clock enable for registers | 
|  | input wire 	     CEA1; | 
|  | input wire 	     CEA2; | 
|  | input wire 	     CEB1; | 
|  | input wire 	     CEB2; | 
|  | input wire 	     CEC; | 
|  | input wire 	     CED; | 
|  | input wire 	     CEM; | 
|  | input wire 	     CEP; | 
|  | input wire 	     CEAD; | 
|  | input wire 	     CEALUMODE; | 
|  | input wire 	     CECTRL; | 
|  | input wire 	     CECARRYIN; | 
|  | input wire 	     CEINMODE; | 
|  |  | 
|  | // Reset for registers | 
|  | input wire 	     RSTA; | 
|  | input wire 	     RSTB; | 
|  | input wire 	     RSTC; | 
|  | input wire 	     RSTD; | 
|  | input wire 	     RSTM; | 
|  | input wire 	     RSTP; | 
|  | input wire 	     RSTCTRL; | 
|  | input wire 	     RSTALLCARRYIN; | 
|  | input wire 	     RSTALUMODE; | 
|  | input wire 	     RSTINMODE; | 
|  |  | 
|  | // clock for all registers and flip-flops | 
|  | input wire 	     CLK; | 
|  |  | 
|  | // Interslice connections | 
|  | input wire [29:0] ACIN; | 
|  | input wire [17:0] BCIN; | 
|  | input wire [47:0] PCIN; | 
|  | input wire 	     CARRYCASCIN; | 
|  | input wire 	     MULTSIGNIN; | 
|  |  | 
|  | output wire [29:0] ACOUT; | 
|  | output wire [17:0] BCOUT; | 
|  | output wire [47:0] PCOUT; | 
|  | output wire [47:0] P; | 
|  |  | 
|  | // main outputs | 
|  | output wire [3:0]  CARRYOUT; | 
|  | output wire 	      CARRYCASCOUT; | 
|  | output wire 	      MULTSIGNOUT; | 
|  | output wire 	      PATTERNDETECT; | 
|  | output wire 	      PATTERNBDETECT; | 
|  | output wire 	      OVERFLOW; | 
|  | output wire 	      UNDERFLOW; | 
|  |  | 
|  | // wires for concatenating A and B registers to XMUX input | 
|  | wire [47:0] 	      XMUX_CAT; | 
|  | wire [29:0] 	      XMUX_A_CAT; | 
|  | wire [17:0] 	      XMUX_B_CAT; | 
|  |  | 
|  | // wires for multiplier inputs | 
|  | wire [24:0] 	      AMULT; | 
|  | wire [17:0] 	      BMULT; | 
|  |  | 
|  | `ifndef PB_TYPE | 
|  |  | 
|  | parameter ACASCREG = 1; | 
|  | parameter ADREG = 1; | 
|  | parameter ALUMODEREG = 1; | 
|  | parameter AREG = 1; | 
|  | parameter BCASCREG = 1; | 
|  | parameter BREG = 1; | 
|  | parameter CARRYINREG = 1; | 
|  | parameter CARRYINSELREG = 1; | 
|  | parameter CREG = 1; | 
|  | parameter DREG = 1; | 
|  | parameter INMODEREG = 1; | 
|  | parameter MREG = 1; | 
|  | parameter OPMODEREG = 1; | 
|  | parameter PREG = 1; | 
|  | parameter A_INPUT = "DIRECT"; | 
|  | parameter B_INPUT = "DIRECT"; | 
|  | parameter USE_DPORT = "FALSE"; | 
|  | parameter USE_MULT = "MULTIPLY"; | 
|  | parameter USE_SIMD = "ONE48"; | 
|  | parameter AUTORESET_PATDET = "NO_RESET"; | 
|  | parameter MASK = 001111111111111111111111111111111111111111111111; | 
|  | parameter PATTERN = 000000000000000000000000000000000000000000000000; | 
|  | parameter SEL_MASK = "MASK"; | 
|  | parameter SEL_PATTERN = "PATTERN"; | 
|  | parameter USE_PATTERN_DETECT = "NO_PATDET"; | 
|  |  | 
|  |  | 
|  | // Figure 2-10 OPMODE, ALUMODE, CARRYINSEL | 
|  | wire [6:0] 	      OPMODE_REG; | 
|  | wire [6:0] 	      OPMODE_MUX_OUT; | 
|  |  | 
|  | NREG #(.NBITS(7)) opmode_reg (.D(OPMODE), .Q(OPMODE_REG), .CE(CECTRL), .CLK(CLK), .RESET(RSTCTRL)); | 
|  | OPMODE_MUX #(.S(OPMODEREG)) opmode_mux (.BYPASS(OPMODE), .REG(OPMODE_REG), .O(OPMODE_MUX_OUT)); | 
|  |  | 
|  | // ALUMODE register | 
|  | wire [3:0]	      ALUMODE_REG; | 
|  | wire [3:0] 	      ALUMODE_MUX_OUT; | 
|  |  | 
|  | NREG #(.NBITS(4)) alu_reg (.D(ALUMODE), .Q(ALUMODE_REG), .CE(CEALUMODE), .CLK(CLK), .RESET(RSTALUMODE)); | 
|  | ALUMODE_MUX #(.S(ALUMODEREG)) alumode_mux (.BYPASS(ALUMODE), .REG(ALUMODE_REG), .O(ALUMODE_MUX_OUT)); | 
|  |  | 
|  | wire [2:0] 	      CARRYINSEL_REG; | 
|  | wire [2:0] 	      CARRYINSEL_MUX_OUT; | 
|  |  | 
|  | NREG #(.NBITS(3)) carryinsel_reg (.D(CARRYINSEL), .Q(CARRYINSEL_REG), .CE(CECTRL), .CLK(CLK), .RESET(RSTCTRL)); | 
|  | CARRYINSEL_MUX #(.S(CARRYINSELREG)) carryseling_mux (.BYPASS(CARRYSELIN), .REG(CARRYINSEL_REG), .O(CARRYINSEL_MUX_OUT)); | 
|  |  | 
|  | wire 	      CIN; | 
|  | CARRYINSEL_LOGIC #(.MREG(MREG), .CARRYINREG(CARRYINREG)) carryinsel_logic (.CARRYIN(CARRYIN), .CARRYCASCIN(CARRYCASCIN), .CARRYCASCOUT(CARRYCASCOUT), .A(A), .B(B), .P(P), .PCIN(PCIN), .CARRYINSEL(CARRYINSEL), .CIN(CIN), | 
|  | .RSTALLCARRYIN(RSTALLCARRYIN), .CECARRYIN(CECARRYIN), .CEM(CEM), .CLK(CLK)); | 
|  |  | 
|  | // INMODE register and bypass mux | 
|  | wire [4:0] 	      INMODE_REG; | 
|  | wire [4:0] 	      INMODE_MUX_OUT; | 
|  |  | 
|  | NREG #(.NBITS(5)) inmode_reg (.D(INMODE), .Q(INMODE_REG), .CE(CEINMODE), .CLK(CLK), .RESET(RSTINMODE)); | 
|  | INMODE_MUX #(.S(INMODEREG)) inmode_mux(.BYPASS(INMODE), .REG(INMODE_REG), .O(INMODE_MUX_OUT)); | 
|  |  | 
|  | // input register blocks for A, B, D | 
|  | DUAL_AD_PREADDER dual_ad_preadder (.A(A), .ACIN(ACIN), .D(D), .INMODE(INMODE_MUX_OUT), | 
|  | .ACOUT(ACOUT), .XMUX(XMUX_A_CAT), .AMULT(AMULT), | 
|  | .CEA1(CEA1), .CEA2(CEA2), .RSTA(RSTA), .CED(CED), .CEAD(CEAD), .RSTD(RSTD), .CLK(CLK)); | 
|  | DUAL_B_REG dualb_reg (.B(B), .BCIN(BCIN), .INMODE(INMODE_MUX_OUT), | 
|  | .BCOUT(BCOUT), .XMUX(XMUX_B_CAT), .BMULT(BMULT), | 
|  | .CEB1(CEB1), .CEB2(CEB2), .RSTB(RSTB), .CLK(CLK)); | 
|  |  | 
|  | // concatenate for XMUX | 
|  | assign XMUX_CAT = {XMUX_A_CAT, XMUX_B_CAT}; | 
|  |  | 
|  | // Multiplier output | 
|  | wire [85:0] 	      MULT_OUT; | 
|  | wire [85:0] 	      MULT_REG; | 
|  | wire [85:0] 	      MULT_MUX_OUT; | 
|  |  | 
|  | // 25bit by 18bit multiplier | 
|  | MULT25X18 mult25x18 (.A(AMULT), .B(BMULT), .OUT(MULT_OUT)); | 
|  | NREG #(.NBITS(86)) mult_reg (.D(MULT_OUT), .Q(MULT_REG), .CLK(CLK), .CE(CEM), .RESET(RSTM)); | 
|  | MULT_MUX #(.S(MREG)) mult_mux (.BYPASS(MULT_OUT), .REG(MULT_REG), .O(MULT_MUX_OUT)); | 
|  |  | 
|  | // Figure 2-9 | 
|  | wire [47:0] 	      C_REG; | 
|  | wire [47:0] 	      CMUX_OUT; | 
|  |  | 
|  | NREG #(.NBITS(48)) creg (.D(C), .Q(C_REG), .CLK(CLK), .CE(CEC), .RESET(RSTC)); | 
|  | CREG_MUX #(.S(CREG)) creg_mux (.BYPASS(C), .REG(C_REG), .O(CMUX_OUT)); | 
|  |  | 
|  | // signals from muxes to ALU unit | 
|  | wire [47:0] 	      X; | 
|  | wire [47:0] 	      Y; | 
|  | wire [47:0] 	      Z; | 
|  |  | 
|  | // TODO(elmsfu): take in full OPMODE to check for undefined behaviors | 
|  | // See table 2-7 for X mux selection | 
|  | DSP48_XMUX dsp48_xmux (.ZEROS(48'h000000000000), .M({5'b00000, MULT_MUX_OUT[85:43]}), .P(P), .AB_CAT(XMUX_CAT), .S(OPMODE_MUX_OUT[1:0]), .O(X)); | 
|  |  | 
|  | // See table 2-8 for Y mux selection | 
|  | DSP48_YMUX dsp48_ymux (.ZEROS(48'h000000000000), .M({5'b00000, MULT_MUX_OUT[42:0]}), .ONES(48'hFFFFFFFFFFFF), .C(CMUX_OUT), .S(OPMODE_MUX_OUT[3:2]), .O(Y)); | 
|  |  | 
|  | // See table 2-9 for Z mux selection | 
|  | // Note: Z mux actually has 7 inputs but 2 and 4 are both P | 
|  | DSP48_ZMUX dsp48_zmux (.ZEROS(48'h000000000000), .PCIN(PCIN), .P(P), .C(CMUX_OUT), .P2(P), .PCIN_UPSHIFT({ {17{PCIN[47]}}, PCIN[47:17]}), .P_UPSHIFT({ {17{P[47]}}, P[47:17]}), .S(OPMODE_MUX_OUT[6:4]), .O(Z)); | 
|  |  | 
|  | // See table 2-10 for 3 input behavior | 
|  | // See table 2-13 for 2 input behavior | 
|  | ALU alu (.X(X), .Y(Y), .Z(Z), .ALUMODE(ALUMODE_MUX_OUT), .CARRYIN(CIN), .MULTSIGNIN(MULTSIGNIN), .OUT(P), .CARRYOUT(CARRYOUT), .MULTSIGNOUT(MULTSIGNOUT)); | 
|  |  | 
|  | assign PCOUT = P; | 
|  |  | 
|  | `endif //  `ifndef PB_TYPE | 
|  |  | 
|  | endmodule // DSP48E1 |