| // 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 |