Skip to content

Commit

Permalink
Merge pull request #58 from elmsfu/dsp48
Browse files Browse the repository at this point in the history
Adding DSP48E1 high level
  • Loading branch information
mithro committed Jun 6, 2018
2 parents bb7fe0a + 131a57e commit 9de1983
Show file tree
Hide file tree
Showing 47 changed files with 912 additions and 77 deletions.
3 changes: 0 additions & 3 deletions artix7/primitives/dsp/dsp.pb_type.xml

This file was deleted.

Empty file.
Empty file.
25 changes: 25 additions & 0 deletions artix7/primitives/dsp48e1/alu/alu.sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module ALU
(X, Y, Z,
ALUMODE,
CARRYIN,
MULTSIGNIN,
OUT,
CARRYOUT,
MULTSIGNOUT
);

input wire [47:0] X;
input wire [47:0] Y;
input wire [47:0] Z;
input wire [3:0] ALUMODE;
input wire CARRYIN;
input wire MULTSIGNIN;

output wire [47:0] OUT;
output wire [3:0] CARRYOUT;
output wire MULTSIGNOUT;

endmodule // ALU



8 changes: 8 additions & 0 deletions artix7/primitives/dsp48e1/alumode_mux/Makefile.mux
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 ALUMODE mux
MUX_TYPE = routing
MUX_OUTFILE = alumode_mux
MUX_NAME = ALUMODE_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
MUX_DATA_WIDTH = 4
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MUX_COMMENT = mux used in CARRYIN selection
MUX_TYPE = routing
MUX_OUTFILE = carryin_mux
MUX_NAME = CARRYIN_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
46 changes: 46 additions & 0 deletions artix7/primitives/dsp48e1/carryinsel_logic/carryinsel_logic.sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
`include "../../../../vpr/muxes/logic/mux8/mux8.sim.v"
`include "../nreg/reg.sim.v"
`include "carryin_mux/carryin_mux.sim.v"

module CARRYINSEL_LOGIC (CARRYIN, CARRYCASCIN, CARRYCASCOUT, A, B, P, PCIN, CARRYINSEL, CIN,
RSTALLCARRYIN, CECARRYIN, CEM, CLK);

parameter MREG = 1;
parameter CARRYINREG = 1;

input wire CARRYIN;
input wire CARRYCASCIN;
input wire CARRYCASCOUT;
input wire [24:0] A;
input wire [17:0] B;
input wire [47:0] P;
input wire [47:0] PCIN;
input wire [2:0] CARRYINSEL;

output wire CIN;

input wire RSTALLCARRYIN;
input wire CECARRYIN;
input wire CEM;
input wire CLK;

`ifndef PB_TYPE
wire ROUND;
wire ROUND_REG;
wire ROUND_MUX_OUT;
assign ROUND = A[24] ~^ B[17];
REG round_reg (.D(ROUND), .Q(ROUND_REG), .CE(CEM), .CLK(CLK), .RESET(RSTALLCARRYIN));
// TODO(elms): not sure if the select is correct: "signal can be optionally registered to match the MREG pipeline delay"
CARRYIN_MUX #(.S(MREG)) round_mux (.BYPASS(ROUND), .REG(ROUND_REG), .O(ROUND_MUX_OUT));

wire CARRYIN_REG;
wire CARRYIN_MUX_OUT;

REG carryin_reg (.D(CARRYIN), .Q(CARRYIN_REG), .CE(CECARRYIN), .CLK(CLK), .RESET(RSTALLCARRYIN));
CARRYIN_MUX #(.S(CARRYINREG)) carryin_mux (.BYPASS(CARRYIN), .REG(CARRYIN_REG), .O(CARRYIN_MUX_OUT));

MUX8 carryinsel_mux (.I0(CARRYIN_MUX_OUT), .I1(~PCIN[47]), .I2(CARRYCASCIN), .I3(PCIN[47]), .I4(CARRYCASCOUT), .I5(~P[47]), .I6(ROUND_MUX_OUT), .I7(P[47]),
.S0(CARRYINSEL[0]), .S1(CARRYINSEL[1]), .S2(CARRYINSEL[2]), .O(CIN));
`endif // `ifndef PB_TYPE

endmodule // CARRYINSEL_LOGIC
8 changes: 8 additions & 0 deletions artix7/primitives/dsp48e1/carryinsel_mux/Makefile.mux
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 CARRYINSEL mux
MUX_TYPE = routing
MUX_OUTFILE = carryinsel_mux
MUX_NAME = CARRYINSEL_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
MUX_DATA_WIDTH = 3
8 changes: 8 additions & 0 deletions artix7/primitives/dsp48e1/creg_mux/Makefile.mux
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 CREG mux
MUX_TYPE = routing
MUX_OUTFILE = creg_mux
MUX_NAME = CREG_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
MUX_DATA_WIDTH = 48
216 changes: 216 additions & 0 deletions artix7/primitives/dsp48e1/dsp48e1.sim.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
// 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
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 a adder mux
MUX_TYPE = logic
MUX_OUTFILE = a_adder_mux
MUX_NAME = A_ADDER_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = A2,A1
MUX_DATA_WIDTH = 25
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
MUX_COMMENT = DSP48E1 ac output mux
MUX_TYPE = routing
MUX_OUTFILE = acout_mux
MUX_NAME = ACOUT_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_DATA_WIDTH = 30
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 a input mux
MUX_TYPE = routing
MUX_OUTFILE = ain_mux
MUX_NAME = AIN_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = A,ACIN
MUX_DATA_WIDTH = 30
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 mux that select output to feed forward to A multipler
MUX_TYPE = routing
MUX_OUTFILE = amult_mux
MUX_NAME = AMULT_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = A,ADDER_OUT
MUX_DATA_WIDTH = 25
8 changes: 8 additions & 0 deletions artix7/primitives/dsp48e1/dual_ad_preadder/amux/Makefile.mux
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 a register mux
MUX_TYPE = routing
MUX_OUTFILE = areg_mux
MUX_NAME = AREG_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
MUX_DATA_WIDTH = 30
8 changes: 8 additions & 0 deletions artix7/primitives/dsp48e1/dual_ad_preadder/dmux/Makefile.mux
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
MUX_COMMENT = DSP48E1 D register mux
MUX_TYPE = routing
MUX_OUTFILE = dreg_mux
MUX_NAME = DREG_MUX
MUX_WIDTH = 2
MUX_SPLIT_INPUTS = 1
MUX_INPUTS = BYPASS,REG
MUX_DATA_WIDTH = 25

0 comments on commit 9de1983

Please sign in to comment.