osmo-rfds/gw/xilinx/DSP48E1.v

1551 lines
61 KiB
Verilog

///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995/2004 Xilinx, Inc.
// All Right Reserved.
///////////////////////////////////////////////////////////////////////////////
// ____ ____
// / /\/ /
// /___/ \ / Vendor : Xilinx
// \ \ \/ Version : 10.1
// \ \ Description : Xilinx Functional Simulation Library Component
// / / 18X18 Signed Multiplier Followed by Three-Input Adder plus ALU with Pipeline Registers
// /___/ /\ Filename : DSP48E1.v
// \ \ / \ Timestamp : Mon Sep 17 15:06:46 PDT 2007
// \___\/\___\
//
// Revision:
// 09/17/07 - Initial version.
// 04/15/08 - CR 468871 Negative SetupHold fix
// 05/19/08 - IR 473330 Fix for qa/qb_o_reg1 when AREG/BREG = 1
// 06/06/08 - IR 474312 fix
// 07/08/08 - CR 473297 and 475997 fix -- removed input buffers that were causing NCSIM failures when sdf was backannotated
// 07/12/08 - IR 472222 Removed SIM_MODE attribute
// 07/18/08 - IR 477318 Overflow/Underflow generate statment issue
// 07/31/08 - IR 478377 Fixed qcarryin_o_mux7
// 08/06/08 - IR 478378 Fixed mult sign extension
// 10/02/08 - IR 491365 Fixed timing constructs
// 03/02/09 - CR 510304 Carryout should output "X" during multiply
// 06/02/09 - CR 523600 Carryout "X"ed out before the register
// 07/07/09 - CR 525163 DRC checks for USE_MULT/OPMODE combinations
// 09/23/09 - CR 532623 Initalized interal registers
// 10/12/09 - CR 535687 Initalized d and ad registers
// 02/17/10 - CR 548358 Updated DRC check warning message
// 10/17/10 - CR 573535 Updated DRC check (carryinsel=100) since carrycascout is now always registered
// 12/08/10 - CR 577648 CARRYOUT "X"ed during MULT operations - GSR initialization of carryout_o_reg is overriding Xs
// 01/14/11 - CR 588861 Fixed initialization errors.
// 06/23/11 - CR 612706 Removed Power Saving Warnings to Match UG
// 09/30/11 - CR 619940 Enhanced DRC warning
// End Revision
`timescale 1 ps / 1 ps
module DSP48E1 (ACOUT, BCOUT, CARRYCASCOUT, CARRYOUT, MULTSIGNOUT, OVERFLOW, P, PATTERNBDETECT, PATTERNDETECT, PCOUT, UNDERFLOW, A, ACIN, ALUMODE, B, BCIN, C, CARRYCASCIN, CARRYIN, CARRYINSEL, CEA1, CEA2, CEAD, CEALUMODE, CEB1, CEB2, CEC, CECARRYIN, CECTRL, CED, CEINMODE, CEM, CEP, CLK, D, INMODE, MULTSIGNIN, OPMODE, PCIN, RSTA, RSTALLCARRYIN, RSTALUMODE, RSTB, RSTC, RSTCTRL, RSTD, RSTINMODE, RSTM, RSTP);
parameter integer ACASCREG = 1;
parameter integer ADREG = 1;
parameter integer ALUMODEREG = 1;
parameter integer AREG = 1;
parameter AUTORESET_PATDET = "NO_RESET"; // {NO_RESET, RESET_MATCH, RESET_NOT_MATCH}
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 MASK = 48'h3FFFFFFFFFFF;
parameter integer MREG = 1;
parameter integer OPMODEREG = 1;
parameter PATTERN = 48'h000000000000;
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";
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; // new
input CEALUMODE;
input CEB1;
input CEB2;
input CEC;
input CECARRYIN;
input CECTRL;
input CED; // new
input CEINMODE; // new
input CEM;
input CEP;
input CLK;
input [24:0] D; // new
input [4:0] INMODE; // new
input MULTSIGNIN;
input [6:0] OPMODE;
input [47:0] PCIN;
input RSTA;
input RSTALLCARRYIN;
input RSTALUMODE;
input RSTB;
input RSTC;
input RSTCTRL;
input RSTD; // new
input RSTINMODE; // new
input RSTM;
input RSTP;
tri0 GSR = glbl.GSR;
//------------------- constants -------------------------
localparam MAX_ACOUT = 30;
localparam MAX_BCOUT = 18;
localparam MAX_CARRYOUT = 4;
localparam MAX_P = 48;
localparam MAX_PCOUT = 48;
localparam MAX_A = 30;
localparam MAX_ACIN = 30;
localparam MAX_ALUMODE = 4;
localparam MAX_A_MULT = 25;
localparam MAX_B = 18;
localparam MAX_B_MULT = 18;
localparam MAX_BCIN = 18;
localparam MAX_C = 48;
localparam MAX_CARRYINSEL = 3;
localparam MAX_D = 25;
localparam MAX_INMODE = 5;
localparam MAX_OPMODE = 7;
localparam MAX_PCIN = 48;
localparam MAX_ALU_FULL = 48;
localparam MAX_ALU_HALF = 24;
localparam MAX_ALU_QUART = 12;
localparam MSB_ACOUT = MAX_ACOUT - 1;
localparam MSB_BCOUT = MAX_BCOUT - 1;
localparam MSB_CARRYOUT = MAX_CARRYOUT - 1;
localparam MSB_P = MAX_P - 1;
localparam MSB_PCOUT = MAX_PCOUT - 1;
localparam MSB_A = MAX_A - 1;
localparam MSB_ACIN = MAX_ACIN - 1;
localparam MSB_ALUMODE = MAX_ALUMODE - 1;
localparam MSB_A_MULT = MAX_A_MULT - 1;
localparam MSB_B = MAX_B - 1;
localparam MSB_B_MULT = MAX_B_MULT - 1;
localparam MSB_BCIN = MAX_BCIN - 1;
localparam MSB_C = MAX_C - 1;
localparam MSB_CARRYINSEL = MAX_CARRYINSEL - 1;
localparam MSB_D = MAX_D - 1;
localparam MSB_INMODE = MAX_INMODE - 1;
localparam MSB_OPMODE = MAX_OPMODE - 1;
localparam MSB_PCIN = MAX_PCIN - 1;
localparam MSB_ALU_FULL = MAX_ALU_FULL - 1;
localparam MSB_ALU_HALF = MAX_ALU_HALF - 1;
localparam MSB_ALU_QUART = MAX_ALU_QUART - 1;
localparam SHIFT_MUXZ = 17;
reg [29:0] a_o_mux, qa_o_mux, qa_o_reg1, qa_o_reg2, qacout_o_mux;
// new
reg [4:0] qinmode_o_mux, qinmode_o_reg;
// new
wire [24:0] a_preaddsub;
reg [17:0] b_o_mux, qb_o_mux, qb_o_reg1, qb_o_reg2, qbcout_o_mux;
reg [2:0] qcarryinsel_o_mux, qcarryinsel_o_reg1;
// new
reg [MSB_D:0] d_o_mux, qd_o_mux, qd_o_reg1;
reg [(MSB_A_MULT+MSB_B_MULT+1):0] qmult_o_mux, qmult_o_reg;
reg [47:0] qc_o_mux, qc_o_reg1;
reg [47:0] qp_o_mux, qp_o_reg1;
reg [47:0] qx_o_mux, qy_o_mux, qz_o_mux;
reg [6:0] qopmode_o_mux, qopmode_o_reg1;
reg qcarryin_o_mux0, qcarryin_o_reg0, qcarryin_o_mux7, qcarryin_o_reg7;
reg qcarryin_o_mux, qcarryin_o_reg;
reg [3:0] qalumode_o_mux, qalumode_o_reg1;
reg invalid_opmode, opmode_valid_flag, ping_opmode_drc_check = 0;
// reg [47:0] alu_o;
wire [47:0] alu_o;
reg qmultsignout_o_reg, multsignout_o_mux;
wire multsignout_o_opmode;
reg [MAX_ALU_FULL:0] alu_full_tmp;
reg [MAX_ALU_HALF:0] alu_hlf1_tmp, alu_hlf2_tmp;
reg [MAX_ALU_QUART:0] alu_qrt1_tmp, alu_qrt2_tmp, alu_qrt3_tmp, alu_qrt4_tmp;
wire pdet_o_mux, pdetb_o_mux;
wire [47:0] the_pattern;
reg [47:0] the_mask = 0;
wire carrycascout_o;
reg carrycascout_o_reg = 0;
reg carrycascout_o_mux = 0;
// reg [3:0] carryout_o = 0;
// CR 577648
// reg [3:0] carryout_o_reg = 0;
// reg [3:0] carryout_o_mux = 0;
// CR 588861
reg [3:0] carryout_o_reg = 0;
reg [3:0] carryout_o_mux;
wire [3:0] carryout_x_o;
wire pdet_o, pdetb_o;
reg pdet_o_reg1, pdet_o_reg2, pdetb_o_reg1, pdetb_o_reg2;
wire overflow_o, underflow_o;
wire [(MSB_A_MULT+MSB_B_MULT+1):0] mult_o;
// new
wire [MSB_A_MULT:0] ad_addsub, ad_mult;
reg [MSB_A_MULT:0] qad_o_reg1, qad_o_mux;
wire [MSB_B_MULT:0] b_mult;
//*** GLOBAL hidden GSR pin
always @(GSR) begin
if (GSR) begin
assign qcarryin_o_reg0 = 1'b0;
assign qcarryinsel_o_reg1 = 3'b0;
assign qopmode_o_reg1 = 7'b0;
assign qalumode_o_reg1 = 4'b0;
assign qa_o_reg1 = 30'b0;
assign qa_o_reg2 = 30'b0;
assign qb_o_reg1 = 18'b0;
assign qb_o_reg2 = 18'b0;
assign qc_o_reg1 = 48'b0;
assign qp_o_reg1 = 48'b0;
assign qmult_o_reg = 36'b0;
assign pdet_o_reg1 = 1'b0;
assign pdet_o_reg2 = 1'b0;
assign pdetb_o_reg1 = 1'b0;
assign pdetb_o_reg2 = 1'b0;
// 577648 commented out the following line
// assign carryout_o_reg = 4'b0;
assign carrycascout_o_reg = 1'b0;
assign qmultsignout_o_reg = 1'b0;
assign qd_o_reg1 = 25'b0;
assign qad_o_reg1 = 25'b0;
assign qinmode_o_reg = 5'b0;
end
else begin
deassign qcarryin_o_reg0;
deassign qcarryinsel_o_reg1;
deassign qopmode_o_reg1;
deassign qalumode_o_reg1;
deassign qa_o_reg1;
deassign qa_o_reg2;
deassign qb_o_reg1;
deassign qb_o_reg2;
deassign qc_o_reg1;
deassign qp_o_reg1;
deassign qmult_o_reg;
deassign pdet_o_reg1;
deassign pdet_o_reg2;
deassign pdetb_o_reg1;
deassign pdetb_o_reg2;
// 577648 commented out the following line
// deassign carryout_o_reg;
deassign carrycascout_o_reg;
deassign qmultsignout_o_reg;
deassign qd_o_reg1;
deassign qad_o_reg1;
deassign qinmode_o_reg;
end
end
initial begin
opmode_valid_flag <= 1;
invalid_opmode <= 1;
//-------- A_INPUT check
case (A_INPUT)
"DIRECT", "CASCADE" : ;
default : begin
$display("Attribute Syntax Error : The attribute A_INPUT on DSP48E1 instance %m is set to %s. Legal values for this attribute are DIRECT or CASCADE.", A_INPUT);
$finish;
end
endcase
//-------- ALUMODEREG check
case (ALUMODEREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute ALUMODEREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", ALUMODEREG);
$finish;
end
endcase
//-------- AREG check
case (AREG)
0, 1, 2 : ;
default : begin
$display("Attribute Syntax Error : The attribute AREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1 or 2.", AREG);
$finish;
end
endcase
//-------- (ACASCREG) and (ACASCREG vs AREG) check
case (AREG)
0 : if(AREG != ACASCREG) begin
$display("Attribute Syntax Error : The attribute ACASCREG on DSP48E1 instance %m is set to %d. ACASCREG has to be set to 0 when attribute AREG = 0.", ACASCREG);
$finish;
end
1 : if(AREG != ACASCREG) begin
$display("Attribute Syntax Error : The attribute ACASCREG on DSP48E1 instance %m is set to %d. ACASCREG has to be set to 1 when attribute AREG = 1.", ACASCREG);
$finish;
end
2 : if((AREG != ACASCREG) && ((AREG-1) != ACASCREG)) begin
$display("Attribute Syntax Error : The attribute ACASCREG on DSP48E1 instance %m is set to %d. ACASCREG has to be set to either 2 or 1 when attribute AREG = 2.", ACASCREG);
$finish;
end
default : ;
endcase
//-------- B_INPUT check
case (B_INPUT)
"DIRECT", "CASCADE" : ;
default : begin
$display("Attribute Syntax Error : The attribute B_INPUT on DSP48E1 instance %m is set to %s. Legal values for this attribute are DIRECT or CASCADE.", B_INPUT);
$finish;
end
endcase
//-------- BREG check
case (BREG)
0, 1, 2 : ;
default : begin
$display("Attribute Syntax Error : The attribute BREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1 or 2.", BREG);
$finish;
end
endcase
//-------- (BCASCREG) and (BCASCREG vs BREG) check
case (BREG)
0 : if(BREG != BCASCREG) begin
$display("Attribute Syntax Error : The attribute BCASCREG on DSP48E1 instance %m is set to %d. BCASCREG has to be set to 0 when attribute BREG = 0.", BCASCREG);
$finish;
end
1 : if(BREG != BCASCREG) begin
$display("Attribute Syntax Error : The attribute BCASCREG on DSP48E1 instance %m is set to %d. BCASCREG has to be set to 1 when attribute BREG = 1.", BCASCREG);
$finish;
end
2 : if((BREG != BCASCREG) && ((BREG-1) != BCASCREG)) begin
$display("Attribute Syntax Error : The attribute BCASCREG on DSP48E1 instance %m is set to %d. BCASCREG has to be set to either 2 or 1 when attribute BREG = 2.", BCASCREG);
$finish;
end
default : ;
endcase
//-------- CARRYINREG check
case (CARRYINREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute CARRYINREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", CARRYINREG);
$finish;
end
endcase
//-------- CARRYINSELREG check
case (CARRYINSELREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute CARRYINSELREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", CARRYINSELREG);
$finish;
end
endcase
//-------- CREG check
case (CREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute CREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, or 1.", CREG);
$finish;
end
endcase
//-------- OPMODEREG check
case (OPMODEREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute OPMODEREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", OPMODEREG);
$finish;
end
endcase
//-------- USE_MULT
case (USE_MULT)
"NONE", "MULTIPLY", "DYNAMIC" : ;
default : begin
$display("Attribute Syntax Error : The attribute USE_MULT on DSP48E1 instance %m is set to %s. Legal values for this attribute are MULTIPLY, DYNAMIC or NONE.", USE_MULT);
$finish;
end
/*
"MULT" : if (MREG != 0) begin
$display("Attribute Syntax Error : The attribute USE_MULT on DSP48E1 instance %m is set to %s. This requires attribute MREG to be set to 0.", USE_MULT);
$finish;
end
"MULT_S" : if (MREG != 1) begin
$display("Attribute Syntax Error : The attribute USE_MULT on DSP48E1 instance %m is set to %s. This requires attribute MREG to be set to 1.", USE_MULT);
$finish;
end
default : begin
$display("Attribute Syntax Error : The attribute USE_MULT on DSP48E1 instance %m is set to %s. Legal values for this attribute are NONE, MULT or MULT_S.", USE_MULT);
$finish;
end
*/
endcase
//-------- USE_PATTERN_DETECT
case (USE_PATTERN_DETECT)
"PATDET", "NO_PATDET" : ;
default : begin
$display("Attribute Syntax Error : The attribute USE_PATTERN_DETECT on DSP48E1 instance %m is set to %s. Legal values for this attribute are PATDET or NO_PATDET.", USE_PATTERN_DETECT);
$finish;
end
endcase
//-------- AUTORESET_PATDET check
case (AUTORESET_PATDET)
"NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH" : ;
default : begin
$display("Attribute Syntax Error : The attribute AUTORESET_PATDET on DSP48E1 instance %m is set to %s. Legal values for this attribute are NO_RESET or RESET_MATCH or RESET_NOT_MATCH.", AUTORESET_PATDET);
$finish;
end
endcase
//-------- SEL_PATTERN check
case(SEL_PATTERN)
"PATTERN", "C" : ;
default : begin
$display("Attribute Syntax Error : The attribute SEL_PATTERN on DSP48E1 instance %m is set to %s. Legal values for this attribute are PATTERN or C.", SEL_PATTERN);
$finish;
end
endcase
//-------- SEL_MASK check
case(SEL_MASK)
"MASK", "C", "ROUNDING_MODE1", "ROUNDING_MODE2" : ;
default : begin
$display("Attribute Syntax Error : The attribute SEL_MASK on DSP48E1 instance %m is set to %s. Legal values for this attribute are MASK or C or ROUNDING_MODE1 or ROUNDING_MODE2.", SEL_MASK);
$finish;
end
endcase
//-------- MREG check
case (MREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute MREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", MREG);
$finish;
end
endcase
//-------- PREG check
case (PREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute PREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", PREG);
$finish;
end
endcase
#100010 ping_opmode_drc_check <= 1;
//*********************************************************
//*** ADDITIONAL DRC
//*********************************************************
// CR 219407 -- (1)
// old ask vicv
/*
if((AUTORESET_PATTERN_DETECT == "TRUE") && (USE_PATTERN_DETECT == "NO_PATDET")) begin
$display("Attribute Syntax Error : The attribute USE_PATTERN_DETECT on DSP48E1 instance %m must be set to PATDET in order to use AUTORESET_PATTERN_DETECT equals TRUE. Failure to do so could make timing reports inaccurate. ");
end
*/
//*********************************************************
//*** new attribute DRC
//*********************************************************
//-------- ADREG check
case (ADREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute ADREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", ADREG);
$finish;
end
endcase
//-------- DREG check
case (DREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute DREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", DREG);
$finish;
end
endcase
//-------- INMODEREG check
case (INMODEREG)
0, 1 : ;
default : begin
$display("Attribute Syntax Error : The attribute INMODEREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0, 1.", INMODEREG);
$finish;
end
endcase
//-------- USE_DPORT
case (USE_DPORT)
"TRUE", "FALSE" : ;
default : begin
$display("Attribute Syntax Error : The attribute USE_DPORT on DSP48E1 instance %m is set to %s. Legal values for this attribute are TRUE or FALSE.", USE_DPORT);
$finish;
end
endcase
end
//*********************************************************
//********** INMODE signal registering ************
//*********************************************************
// new
always @(posedge CLK) begin
if (RSTINMODE)
qinmode_o_reg <= 5'b0;
else if (CEINMODE)
qinmode_o_reg <= INMODE;
end
generate
case (INMODEREG)
0: begin
always @(INMODE)
qinmode_o_mux <= INMODE;
end
1: begin
always @(qinmode_o_reg)
qinmode_o_mux <= qinmode_o_reg;
end
endcase
endgenerate
//*********************************************************
//*** Input register A with 2 level deep of registers
//*********************************************************
generate
case (A_INPUT)
"DIRECT" : always @(A) a_o_mux <= A;
"CASCADE" : always @(ACIN) a_o_mux <= ACIN;
endcase
endgenerate
generate
case (AREG)
1 : begin
always @(posedge CLK) begin
if (RSTA) begin
qa_o_reg1 <= 30'b0;
qa_o_reg2 <= 30'b0;
end
else begin
if (CEA1)
qa_o_reg1 <= a_o_mux;
if (CEA2)
qa_o_reg2 <= a_o_mux;
end
end
end
2 : begin
always @(posedge CLK) begin
if (RSTA) begin
qa_o_reg1 <= 30'b0;
qa_o_reg2 <= 30'b0;
end
else begin
if (CEA1)
qa_o_reg1 <= a_o_mux;
if (CEA2)
qa_o_reg2 <= qa_o_reg1;
end
end
end
endcase
endgenerate
generate
case (AREG)
0: always @(a_o_mux) qa_o_mux <= a_o_mux;
1,2 : always @(qa_o_reg2) qa_o_mux <= qa_o_reg2;
endcase
endgenerate
generate
case (ACASCREG)
1: always @(qa_o_mux or qa_o_reg1) begin
if(AREG == 2)
qacout_o_mux <= qa_o_reg1;
else
qacout_o_mux <= qa_o_mux;
end
0,2 : always @(qa_o_mux) qacout_o_mux <= qa_o_mux;
endcase
endgenerate
// new
assign a_preaddsub = qinmode_o_mux[1]? 25'b0:(qinmode_o_mux[0]?qa_o_reg1[24:0]:qa_o_mux[24:0]);
//*********************************************************
//*** Input register B with 2 level deep of registers
//*********************************************************
generate
case (B_INPUT)
"DIRECT" : always @(B) b_o_mux <= B;
"CASCADE" : always @(BCIN) b_o_mux <= BCIN;
endcase
endgenerate
generate
case (BREG)
1 : begin
always @(posedge CLK) begin
if (RSTB) begin
qb_o_reg1 <= 18'b0;
qb_o_reg2 <= 18'b0;
end
else begin
if (CEB1)
qb_o_reg1 <= b_o_mux;
if (CEB2)
qb_o_reg2 <= b_o_mux;
end
end
end
2 : begin
always @(posedge CLK) begin
if (RSTB) begin
qb_o_reg1 <= 18'b0;
qb_o_reg2 <= 18'b0;
end
else begin
if (CEB1)
qb_o_reg1 <= b_o_mux;
if (CEB2)
qb_o_reg2 <= qb_o_reg1;
end
end
end
endcase
endgenerate
generate
case (BREG)
0: always @(b_o_mux) qb_o_mux <= b_o_mux;
1,2 : always @(qb_o_reg2) qb_o_mux <= qb_o_reg2;
endcase
endgenerate
generate
case (BCASCREG)
1: always @(qb_o_mux or qb_o_reg1) begin
if(BREG == 2)
qbcout_o_mux <= qb_o_reg1;
else
qbcout_o_mux <= qb_o_mux;
end
0,2 : always @(qb_o_mux) qbcout_o_mux <= qb_o_mux;
endcase
endgenerate
// new
assign b_mult = qinmode_o_mux[4]?qb_o_reg1:qb_o_mux;
//*********************************************************
//*** Input register C with 1 level deep of register
//*********************************************************
always @(posedge CLK) begin
if (RSTC)
qc_o_reg1 <= 48'b0;
else if (CEC)
qc_o_reg1 <= C;
end
generate
case (CREG)
0 : always @(C) qc_o_mux <= C;
1 : always @(qc_o_reg1) qc_o_mux <= qc_o_reg1;
endcase
endgenerate
// new
//*********************************************************
//*** Input register D with 1 level deep of register
//*********************************************************
always @(posedge CLK) begin
if (RSTD)
qd_o_reg1 <= 25'b0;
else if (CED)
qd_o_reg1 <= D;
end
generate
case (DREG)
0 : always @(D) qd_o_mux <= D;
1 : always @(qd_o_reg1) qd_o_mux <= qd_o_reg1;
endcase
endgenerate
//*********************************************************
//*** Preaddsub AD register with 1 level deep of register
//*********************************************************
// new
assign ad_addsub = qinmode_o_mux[3]?(-a_preaddsub + (qinmode_o_mux[2]?qd_o_mux:25'b0)):(a_preaddsub + (qinmode_o_mux[2]?qd_o_mux:25'b0));
always @(posedge CLK) begin
if (RSTD)
qad_o_reg1 <= 25'b0;
else if (CEAD)
qad_o_reg1 <= ad_addsub;
end
generate
case (ADREG)
0 : always @(ad_addsub) qad_o_mux <= ad_addsub;
1 : always @(qad_o_reg1) qad_o_mux <= qad_o_reg1;
endcase
endgenerate
/*------------------------------------------------- */
/*------------------------------------------------- */
assign ad_mult = (USE_DPORT=="TRUE")? qad_o_mux : a_preaddsub;
//*********************************************************
//*********************************************************
//*************** 25x18 Multiplier ***************
//*********************************************************
// 05/26/05 -- FP -- Added warning for invalid mult when USE_MULT=NONE
// SIMD=FOUR12 and SIMD=TWO24
// Made mult_o to be "X"
always @(qopmode_o_mux) begin
if(qopmode_o_mux[3:0] == 4'b0101)
if((USE_MULT == "NONE") || (USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12"))
$display("OPMODE Input Warning : The OPMODE[3:0] %b to DSP48E1 instance %m is invalid when using attributes USE_MULT = NONE, or USE_SIMD = TWO24 or FOUR12 at %.3f ns.", qopmode_o_mux[3:0], $time/1000.0);
end
assign mult_o = ((USE_MULT == "NONE") || (USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12"))? 43'b0 : {{18{ad_mult[24]}}, ad_mult[24:0]} * {{25{b_mult[17]}}, b_mult};
always @(posedge CLK) begin
if (RSTM) begin
qmult_o_reg <= 18'b0;
end
else if (CEM) begin
qmult_o_reg <= mult_o;
end
end
generate
case (MREG)
0 : always @(mult_o) qmult_o_mux <= mult_o;
1 : always @(qmult_o_reg) qmult_o_mux <= qmult_o_reg;
endcase
endgenerate
//*** X mux
// ask jmt
always @(qp_o_mux or qa_o_mux or qb_o_mux or qmult_o_mux or qopmode_o_mux[1:0] or qcarryinsel_o_mux) begin
case (qopmode_o_mux[1:0])
2'b00 : qx_o_mux <= 48'b0;
2'b01 : qx_o_mux <= {{5{qmult_o_mux[MSB_A_MULT + MSB_B_MULT + 1]}}, qmult_o_mux};
2'b10 : qx_o_mux <= qp_o_mux;
// new DRC
2'b11 : begin
if((USE_MULT == "MULTIPLY") && (
(AREG==0 && BREG==0 && MREG==0) ||
(AREG==0 && BREG==0 && PREG==0) ||
(MREG==0 && PREG==0)))
$display("OPMODE Input Warning : The OPMODE[1:0] %b to DSP48E1 instance %m is invalid when using attributes USE_MULT = MULTIPLY at %.3f ns. Please set USE_MULT to either NONE or DYNAMIC.", qopmode_o_mux[1:0], $time/1000.0);
else
qx_o_mux <= {qa_o_mux[MSB_A:0], qb_o_mux[MSB_B:0]};
end
default : begin
end
endcase
end
//*** Y mux
// 08-06-08
// IR 478378
wire [47:0] y_mac_cascd = (qopmode_o_mux[6:4] == 3'b100) ? {48{MULTSIGNIN}} : {48{1'b1}};
always @(qc_o_mux or qopmode_o_mux[3:2] or qcarryinsel_o_mux or y_mac_cascd) begin
case (qopmode_o_mux[3:2])
2'b00 : qy_o_mux <= 48'b0;
2'b01 : qy_o_mux <= 48'b0;
// 08-06-08
2'b10 : qy_o_mux <= y_mac_cascd; // choose all ones or mult-sign-extend
2'b11 : qy_o_mux <= qc_o_mux;
default : begin
end
endcase
end
//*** Z mux
always @(qp_o_mux or qc_o_mux or PCIN or qopmode_o_mux[6:4] or qcarryinsel_o_mux) begin
// ask jmt
casex (qopmode_o_mux[6:4])
3'b000 : qz_o_mux <= 48'b0;
3'b001 : qz_o_mux <= PCIN;
3'b010 : qz_o_mux <= qp_o_mux;
3'b011 : qz_o_mux <= qc_o_mux;
3'b100 : qz_o_mux <= qp_o_mux;
3'b101 : qz_o_mux <= {{17{PCIN[47]}}, PCIN[47:17]};
// ask jmt
3'b11x : qz_o_mux <= {{17{qp_o_mux[47]}}, qp_o_mux[47:17]};
default : begin
end
endcase
end
//*** CarryInSel and OpMode with 1 level of register
always @(posedge CLK) begin
if (RSTCTRL) begin
qcarryinsel_o_reg1 <= 3'b0;
qopmode_o_reg1 <= 7'b0;
end
else if (CECTRL) begin
qcarryinsel_o_reg1 <= CARRYINSEL;
qopmode_o_reg1 <= OPMODE;
end
end
generate
case (CARRYINSELREG)
0 : always @(CARRYINSEL) qcarryinsel_o_mux <= CARRYINSEL;
1 : always @(qcarryinsel_o_reg1) qcarryinsel_o_mux <= qcarryinsel_o_reg1;
endcase
endgenerate
//CR 219047 (3)
// always @(qcarryinsel_o_mux or MULTSIGNIN or qopmode_o_mux) begin
// always @(CARRYCASCIN or MULTSIGNIN or qopmode_o_mux) begin
always @(qcarryinsel_o_mux or CARRYCASCIN or MULTSIGNIN or qopmode_o_mux) begin
if(qcarryinsel_o_mux == 3'b010) begin
if(!((MULTSIGNIN === 1'bx) || ((qopmode_o_mux == 7'b1001000) && !(MULTSIGNIN === 1'bx))
|| ((MULTSIGNIN == 1'b0) && (CARRYCASCIN == 1'b0)))) begin
$display("DRC warning : CARRYCASCIN can only be used in the current DSP48E1 instance %m if the previous DSP48E1 is performing a two input ADD operation, or the current DSP48E1 is configured in the MAC extend opmode 7'b1001000 at %.3f ns.", $time);
// CR 619940 -- Enhanced DRC warning
$display("DRC warning note : The simulation model does not know the placement of the DSP48E1 slices used, so it cannot fully confirm the above warning. It is necessary to view the placement of the DSP48E1 slices and ensure that these warnings are not being breached\n");
end
end
end
/*
// old
// ask jmt
//CR 219047 (4)
always @(qcarryinsel_o_mux) begin
if((qcarryinsel_o_mux == 3'b110) && (MULTCARRYINREG != MREG)) begin
$display("Attribute Syntax Warning : It is recommended that MREG and MULTCARRYINREG on DSP48E1 instance %m be set to the same value when using CARRYINSEL = 110 for multiply rounding.");
end
end
*/
generate
case (OPMODEREG)
0 : always @(OPMODE) qopmode_o_mux <= OPMODE;
1 : always @(qopmode_o_reg1) qopmode_o_mux <= qopmode_o_reg1;
endcase
endgenerate
//*** ALUMODE with 1 level of register
always @(posedge CLK) begin
if (RSTALUMODE)
qalumode_o_reg1 <= 4'b0;
else if (CEALUMODE)
qalumode_o_reg1 <= ALUMODE;
end
generate
case (ALUMODEREG)
0 : always @(ALUMODE) qalumode_o_mux <= ALUMODE;
1 : always @(qalumode_o_reg1) qalumode_o_mux <= qalumode_o_reg1;
endcase
endgenerate
//------------------------------------------------------------------
//*** DRC for OPMODE
//------------------------------------------------------------------
task deassign_xyz_mux;
begin
opmode_valid_flag = 1;
invalid_opmode = 1; // reset invalid opmode
end
endtask // deassign_xyz_mux
task display_invalid_opmode;
begin
if (invalid_opmode) begin
opmode_valid_flag = 0;
invalid_opmode = 0;
$display("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m at %.3f ns requires attribute PREG set to 1.", qopmode_o_mux, $time/1000.0);
end
end
endtask // display_invalid_opmode
always @(ping_opmode_drc_check or qalumode_o_mux or qopmode_o_mux or qcarryinsel_o_mux ) begin
if ($time > 100000) begin // no check at first 100ns
case (qalumode_o_mux[3:2])
2'b00 :
//-- ARITHMETIC MODES DRC
case ({qopmode_o_mux, qcarryinsel_o_mux})
10'b0000000000 : deassign_xyz_mux;
10'b0000010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0000010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0000011000 : deassign_xyz_mux;
10'b0000011010 : deassign_xyz_mux;
// CR 573535 10'b0000011100 : deassign_xyz_mux;
10'b0000011100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0000101000 : deassign_xyz_mux;
10'b0001000000 : deassign_xyz_mux;
10'b0001010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001011000 : deassign_xyz_mux;
10'b0001011010 : deassign_xyz_mux;
// CR 573535 10'b0001011100 : deassign_xyz_mux;
10'b0001011100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001100000 : deassign_xyz_mux;
10'b0001100010 : deassign_xyz_mux;
// CR 573535 10'b0001100100 : deassign_xyz_mux;
10'b0001100100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001110010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001110101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001110111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0001111000 : deassign_xyz_mux;
10'b0001111010 : deassign_xyz_mux;
// CR 573535 10'b0001111100 : deassign_xyz_mux;
10'b0001111100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0010000000 : deassign_xyz_mux;
10'b0010010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0010010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0010010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0010011000 : deassign_xyz_mux;
10'b0010011001 : deassign_xyz_mux;
10'b0010011011 : deassign_xyz_mux;
10'b0010101000 : deassign_xyz_mux;
10'b0010101001 : deassign_xyz_mux;
10'b0010101011 : deassign_xyz_mux;
10'b0010101110 : deassign_xyz_mux;
10'b0011000000 : deassign_xyz_mux;
10'b0011010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011011000 : deassign_xyz_mux;
10'b0011011001 : deassign_xyz_mux;
10'b0011011011 : deassign_xyz_mux;
10'b0011100000 : deassign_xyz_mux;
10'b0011100001 : deassign_xyz_mux;
10'b0011100011 : deassign_xyz_mux;
10'b0011110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011110101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011110111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011110001 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011110011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0011111000 : deassign_xyz_mux;
10'b0011111001 : deassign_xyz_mux;
10'b0011111011 : deassign_xyz_mux;
10'b0100000000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100000010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100011000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100011010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100011101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100011111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100101000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100101101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0100101111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101000000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101000010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101011000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101011101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101011111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101100000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101100010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101100101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101100111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101110101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101110111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101111000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101111101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0101111111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110000000 : deassign_xyz_mux;
10'b0110000010 : deassign_xyz_mux;
// CR 573535 10'b0110000100 : deassign_xyz_mux;
10'b0110000100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110011000 : deassign_xyz_mux;
10'b0110011010 : deassign_xyz_mux;
// CR 573535 10'b0110011100 : deassign_xyz_mux;
10'b0110011100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0110101000 : deassign_xyz_mux;
10'b0110101110 : deassign_xyz_mux;
10'b0111000000 : deassign_xyz_mux;
10'b0111000010 : deassign_xyz_mux;
// CR 573535 10'b0111000100 : deassign_xyz_mux;
10'b0111000100 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0111010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0111010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0111010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0111011000 : deassign_xyz_mux;
10'b0111100000 : deassign_xyz_mux;
10'b0111100010 : deassign_xyz_mux;
10'b0111110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b0111111000 : deassign_xyz_mux;
10'b1001000010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1010000000 : deassign_xyz_mux;
10'b1010010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1010010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1010010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1010011000 : deassign_xyz_mux;
10'b1010011001 : deassign_xyz_mux;
10'b1010011011 : deassign_xyz_mux;
10'b1010101000 : deassign_xyz_mux;
10'b1010101001 : deassign_xyz_mux;
10'b1010101011 : deassign_xyz_mux;
10'b1010101110 : deassign_xyz_mux;
10'b1011000000 : deassign_xyz_mux;
10'b1011010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011010101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011010111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011011000 : deassign_xyz_mux;
10'b1011011001 : deassign_xyz_mux;
10'b1011011011 : deassign_xyz_mux;
10'b1011100000 : deassign_xyz_mux;
10'b1011100001 : deassign_xyz_mux;
10'b1011100011 : deassign_xyz_mux;
10'b1011110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011110101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011110111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011110001 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011110011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1011111000 : deassign_xyz_mux;
10'b1011111001 : deassign_xyz_mux;
10'b1011111011 : deassign_xyz_mux;
10'b1100000000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100011000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100011101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100011111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100101000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100101101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1100101111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101000000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101010000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101011000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101011101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101011111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101100000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101100101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101100111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101110000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101110101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101110111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101111000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101111101 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
10'b1101111111 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
default : begin
if (invalid_opmode) begin
opmode_valid_flag = 0;
invalid_opmode = 0;
// CR 444150
if( ({qopmode_o_mux, qcarryinsel_o_mux} == 10'b0000000010) && ((OPMODEREG==1) && (CARRYINSELREG ==0)) )
$display("DRC warning : The attribute CARRYINSELREG on DSP48E1 instance %m is set to %d. It is required to have CARRYINSELREG be set to 1 to match OPMODEREG, in order to ensure that the simulation model will match the hardware behavior in all use cases.", CARRYINSELREG);
$display("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is either invalid or the CARRYINSEL %b for that specific OPMODE is invalid at %.3f ns. This warning may be due to a mismatch in the OPMODEREG and CARRYINSELREG attribute settings. It is recommended that OPMODEREG and CARRYINSELREG always be set to the same value. ", qopmode_o_mux, qcarryinsel_o_mux, $time/1000.0);
end
end
endcase // case(OPMODE)
2'b01, 2'b11 :
//-- LOGIC MODES DRC
case (qopmode_o_mux)
7'b0000000 : deassign_xyz_mux;
7'b0000010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0000011 : deassign_xyz_mux;
7'b0010000 : deassign_xyz_mux;
7'b0010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0010011 : deassign_xyz_mux;
7'b0100000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0100010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0100011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0110000 : deassign_xyz_mux;
7'b0110010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0110011 : deassign_xyz_mux;
7'b1010000 : deassign_xyz_mux;
7'b1010010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1010011 : deassign_xyz_mux;
7'b1100000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1100010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1100011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0001000 : deassign_xyz_mux;
7'b0001010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0001011 : deassign_xyz_mux;
7'b0011000 : deassign_xyz_mux;
7'b0011010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0011011 : deassign_xyz_mux;
7'b0101000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0101010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0101011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0111000 : deassign_xyz_mux;
7'b0111010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b0111011 : deassign_xyz_mux;
7'b1011000 : deassign_xyz_mux;
7'b1011010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1011011 : deassign_xyz_mux;
7'b1101000 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1101010 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
7'b1101011 : if (PREG != 1) display_invalid_opmode; else deassign_xyz_mux;
default : begin
if (invalid_opmode) begin
opmode_valid_flag = 0;
invalid_opmode = 0;
$display("OPMODE Input Warning : The OPMODE %b to DSP48E1 instance %m is invalid for LOGIC MODES at %.3f ns.", qopmode_o_mux, $time/1000.0);
end
end
endcase // case(OPMODE)
endcase // case(qalumode_o_mux)
end // if ($time > 100000)
end // always @ (qopmode_o_mux)
//--####################################################################
//--##### ALU #####
//--####################################################################
wire mult_cout = ~qp_o_mux[42];
reg [MSB_ALU_FULL:0] co;
reg [MSB_ALU_FULL:0] s;
wire [MSB_ALU_FULL:0] comux,smux;
wire [MSB_CARRYOUT:0] carryout_o_hw;
wire [MSB_CARRYOUT:0] carryout_o;
wire tmp_carrycascout_in;
always @ (qx_o_mux or qy_o_mux or qz_o_mux or qalumode_o_mux[0]) begin
if (qalumode_o_mux[0]) begin
co = ((qx_o_mux & qy_o_mux)|((~qz_o_mux) & qy_o_mux)|(qx_o_mux & (~qz_o_mux)));
s = (~qz_o_mux) ^ qx_o_mux ^ qy_o_mux;
end
else begin
co = ((qx_o_mux & qy_o_mux)|(qz_o_mux & qy_o_mux)|(qx_o_mux & qz_o_mux));
s = qz_o_mux ^ qx_o_mux ^ qy_o_mux;
end
end
assign comux = qalumode_o_mux[2] ? 0 : co;
assign smux = qalumode_o_mux[3] ? co : s;
// FINAL ADDER
wire [12:0] s0 = {comux[10:0],qcarryin_o_mux}+smux[11:0];
wire cout0 = (comux[11] + s0[12]);
assign carryout_o_hw[0] = (qalumode_o_mux[0] & qalumode_o_mux[1]) ? ~cout0 : cout0;
wire C1 = (USE_SIMD == "FOUR12") ? 1'b0 : s0[12];
wire co11_lsb = (USE_SIMD == "FOUR12") ? 1'b0 : comux[11];
wire [12:0] s1 = {comux[22:12],co11_lsb}+smux[23:12]+C1;
wire cout1 = (comux[23] + s1[12]);
assign carryout_o_hw[1] = (qalumode_o_mux[0] & qalumode_o_mux[1]) ? ~cout1 : cout1;
wire C2 = ((USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12")) ? 1'b0 : s1[12];
wire co23_lsb = ((USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12")) ?
1'b0 : comux[23];
wire [12:0] s2 = {comux[34:24],co23_lsb}+smux[35:24]+C2;
wire cout2 = (comux[35] + s2[12]);
assign carryout_o_hw[2] = (qalumode_o_mux[0] & qalumode_o_mux[1]) ? ~cout2 : cout2;
wire C3 = (USE_SIMD == "FOUR12") ? 1'b0 : s2[12];
wire co35_lsb = (USE_SIMD == "FOUR12") ? 1'b0 : comux[35];
wire [13:0] s3 = {comux[47:36],co35_lsb}+smux[47:36]+C3;
wire cout3 = s3[12];
assign carryout_o_hw[3] = (qalumode_o_mux[0] & qalumode_o_mux[1]) ? ~cout3 : cout3;
wire cout4 = s3[13];
// assign carryout_o_hw[4] = (qalumode_o_mux[0] & qalumode_o_mux[1]) ? ~cout4 : cout4;
assign alu_o = qalumode_o_mux[1] ? ~{s3[11:0],s2[11:0],s1[11:0],s0[11:0]} :
{s3[11:0],s2[11:0],s1[11:0],s0[11:0]};
// COMPUTE CARRYCASCOUT
assign carrycascout_o = cout3;
// COMPUTE MULTSIGNOUT
// 08-06-08 assign multsignout_o_opmode = (qopmode_o_mux[3:0] === 4'b100) ? MULTSIGNIN : ~qp_o_mux[42];
// IR 478378
assign multsignout_o_opmode = (qopmode_o_mux[6:4] === 3'b100) ? MULTSIGNIN : qmult_o_mux[42];
// CR 523600 -- "X" carryout for multiply and logic operations
assign carryout_o[3] = ((qopmode_o_mux[3:0] == 4'b0101) || (qalumode_o_mux[3:2] != 2'b00))? 1'bx : carryout_o_hw[3];
assign carryout_o[2] = ((qopmode_o_mux[3:0] == 4'b0101) || (qalumode_o_mux[3:2] != 2'b00))? 1'bx : (USE_SIMD == "FOUR12") ? carryout_o_hw[2] : 1'bx;
assign carryout_o[1] = ((qopmode_o_mux[3:0] == 4'b0101) || (qalumode_o_mux[3:2] != 2'b00))? 1'bx : ((USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12")) ? carryout_o_hw[1] : 1'bx;
assign carryout_o[0] = ((qopmode_o_mux[3:0] == 4'b0101) || (qalumode_o_mux[3:2] != 2'b00))? 1'bx : (USE_SIMD == "FOUR12") ? carryout_o_hw[0] : 1'bx;
//--########################### END ALU ################################
//*** CarryIn Mux and Register
//------- input 0
always @(posedge CLK) begin
if (RSTALLCARRYIN)
qcarryin_o_reg0 <= 1'b0;
else if (CECARRYIN)
qcarryin_o_reg0 <= CARRYIN;
end
generate
case (CARRYINREG)
0 : always @(CARRYIN) qcarryin_o_mux0 <= CARRYIN;
1 : always @(qcarryin_o_reg0) qcarryin_o_mux0 <= qcarryin_o_reg0;
endcase
endgenerate
//------- input 7
always @(posedge CLK) begin
if (RSTALLCARRYIN)
qcarryin_o_reg7 <= 1'b0;
// old else if (CEMULTCARRYIN)
// new
else if (CEM)
// IR 478377
qcarryin_o_reg7 <= ad_mult[24] ~^ b_mult[17]; // xnor
end
// always @(qa_o_mux[24] or qb_o_mux[17] or qcarryin_o_reg7) begin
always @(ad_mult[24] or b_mult[17] or qcarryin_o_reg7) begin
// old case (MULTCARRYINREG)
// new
case (MREG)
// IR 478377
0 : qcarryin_o_mux7 <= ad_mult[24] ~^ b_mult[17];
1 : qcarryin_o_mux7 <= qcarryin_o_reg7;
default : begin
$display("Attribute Syntax Error : The attribute MREG on DSP48E1 instance %m is set to %d. Legal values for this attribute are 0 or 1.", MREG);
$finish;
end
endcase
end
reg qcarryin_o_mux_tmp;
always @(qcarryin_o_mux0 or PCIN[47] or CARRYCASCIN or carrycascout_o_mux or qp_o_mux[47] or qcarryin_o_mux7 or qcarryinsel_o_mux) begin
case (qcarryinsel_o_mux)
3'b000 : qcarryin_o_mux_tmp <= qcarryin_o_mux0;
3'b001 : qcarryin_o_mux_tmp <= ~PCIN[47];
3'b010 : qcarryin_o_mux_tmp <= CARRYCASCIN;
3'b011 : qcarryin_o_mux_tmp <= PCIN[47];
3'b100 : qcarryin_o_mux_tmp <= carrycascout_o_mux;
3'b101 : qcarryin_o_mux_tmp <= ~qp_o_mux[47];
3'b110 : qcarryin_o_mux_tmp <= qcarryin_o_mux7;
3'b111 : qcarryin_o_mux_tmp <= qp_o_mux[47];
default : begin
end
endcase
end
// disable carryin when performing logic operation
always @(qcarryin_o_mux_tmp or qalumode_o_mux[3:2]) begin
qcarryin_o_mux <= (qalumode_o_mux[3] || qalumode_o_mux[2]) ? 1'b0 : qcarryin_o_mux_tmp;
end
//--####################################################################
//--##### AUTORESET_PATDET #####
//--####################################################################
assign the_auto_reset_patdet = ((AUTORESET_PATDET == "RESET_MATCH") && pdet_o_reg1)
||
((AUTORESET_PATDET == "RESET_NOT_MATCH") && (pdet_o_reg2 && !pdet_o_reg1));
//--####################################################################
//--##### CARRYOUT, CARRYCASCOUT. MULTSIGNOUT and PCOUT ######
//--####################################################################
//*** register with 1 level of register
always @(posedge CLK) begin
if(RSTP || the_auto_reset_patdet)
begin
carryout_o_reg <= 4'b0;
carrycascout_o_reg <= 1'b0;
qmultsignout_o_reg <= 1'b0;
qp_o_reg1 <= 48'b0;
end
else if (CEP) begin
carryout_o_reg <= carryout_o;
carrycascout_o_reg <= carrycascout_o;
qmultsignout_o_reg <= multsignout_o_opmode;
qp_o_reg1 <= alu_o;
end
end
generate
case (PREG)
0: begin
always @(carryout_o)
carryout_o_mux <= carryout_o;
always @(carrycascout_o)
carrycascout_o_mux <= carrycascout_o;
always @(multsignout_o_opmode)
multsignout_o_mux <= multsignout_o_opmode;
always @(alu_o)
qp_o_mux <= #1 alu_o;
end
1: begin
always @(carryout_o_reg)
carryout_o_mux <= carryout_o_reg;
always @(carrycascout_o_reg)
carrycascout_o_mux <= carrycascout_o_reg;
always @(qmultsignout_o_reg)
multsignout_o_mux <= qmultsignout_o_reg;
always @(qp_o_reg1)
qp_o_mux <= qp_o_reg1;
end
endcase
endgenerate
//CR 219047 (2)
// ask jmt whether i should comment this out
/*
always @(qmult_o_mux[(MSB_A_MULT+MSB_B_MULT+1)] or qopmode_o_mux[3:0]) begin
if(qopmode_o_mux[3:0] == 4'b0101)
multsignout_o_opmode = qmult_o_mux[(MSB_A_MULT+MSB_B_MULT+1)];
else
multsignout_o_opmode = 1'bx;
end
*/
// assign carryout_x_o[4] = carryout_o_mux[4];
// CR 510304 output X during multiply operation
assign carryout_x_o[3] = carryout_o_mux[3];
assign carryout_x_o[2] = (USE_SIMD == "FOUR12") ? carryout_o_mux[2] : 1'bx;
assign carryout_x_o[1] = ((USE_SIMD == "TWO24") || (USE_SIMD == "FOUR12")) ? carryout_o_mux[1] : 1'bx;
assign carryout_x_o[0] = (USE_SIMD == "FOUR12") ? carryout_o_mux[0] : 1'bx;
//--####################################################################
//--##### Pattern Detector #####
//--####################################################################
// new
// selet pattern
assign the_pattern = (SEL_PATTERN == "PATTERN") ? PATTERN : qc_o_mux;
// selet mask
always @(qc_o_mux) begin
case(SEL_MASK)
"MASK" : the_mask <= MASK;
"C" : the_mask <= qc_o_mux;
"ROUNDING_MODE1" : the_mask <= ~qc_o_mux << 1;
"ROUNDING_MODE2" : the_mask <= ~qc_o_mux << 2;
default : ;
endcase
end
//-- now do the pattern detection
assign pdet_o = &(~(the_pattern ^ alu_o) | the_mask);
assign pdetb_o = &((the_pattern ^ alu_o) | the_mask);
assign pdet_o_mux = (~opmode_valid_flag) ? 1'bx : (PREG == 1) ? pdet_o_reg1 : pdet_o;
assign pdetb_o_mux = (~opmode_valid_flag) ? 1'bx : (PREG == 1) ? pdetb_o_reg1 : pdetb_o;
//*** Output register PATTERN DETECT and UNDERFLOW / OVERFLOW
always @(posedge CLK) begin
if((RSTP) || the_auto_reset_patdet)
begin
pdet_o_reg1 <= 1'b0;
pdet_o_reg2 <= 1'b0;
pdetb_o_reg1 <= 1'b0;
pdetb_o_reg2 <= 1'b0;
end
else if(CEP)
begin
//-- the previous values are used in Underflow/Overflow
pdet_o_reg2 <= pdet_o_reg1;
pdet_o_reg1 <= pdet_o;
pdetb_o_reg2 <= pdetb_o_reg1;
pdetb_o_reg1 <= pdetb_o;
end
end
//--####################################################################
//--##### Underflow / Overflow #####
//--####################################################################
generate if ((USE_PATTERN_DETECT == "PATDET") || (PREG == 1))
begin
assign overflow_o = pdet_o_reg2 & !pdet_o_reg1 & !pdetb_o_reg1;
assign underflow_o = pdetb_o_reg2 & !pdet_o_reg1 & !pdetb_o_reg1;
end
else
begin
assign overflow_o = 1'bx;
assign underflow_o = 1'bx;
end
endgenerate
assign ACOUT = qacout_o_mux;
assign BCOUT = qbcout_o_mux;
assign CARRYCASCOUT = carrycascout_o_mux;
assign CARRYOUT = carryout_x_o;
assign MULTSIGNOUT = multsignout_o_mux;
assign OVERFLOW = overflow_o;
assign P = qp_o_mux;
assign PCOUT = qp_o_mux;
assign PATTERNDETECT = pdet_o_mux;
assign PATTERNBDETECT = pdetb_o_mux;
assign UNDERFLOW = underflow_o;
specify
(CLK *> ACOUT) = (100, 100);
(CLK *> BCOUT) = (100, 100);
(CLK *> CARRYCASCOUT) = (100, 100);
(CLK *> CARRYOUT) = (100, 100);
(CLK *> MULTSIGNOUT) = (100, 100);
(CLK *> OVERFLOW) = (100, 100);
(CLK *> P) = (100, 100);
(CLK *> PATTERNBDETECT) = (100, 100);
(CLK *> PATTERNDETECT) = (100, 100);
(CLK *> PCOUT) = (100, 100);
(CLK *> UNDERFLOW) = (100, 100);
specparam PATHPULSE$ = 0;
endspecify
endmodule // DSP48E1