cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
tishi
Observer
Observer
673 Views
Registered: ‎02-12-2019

Why vivado 2018 infers a*b+c as two DSP48E1

Hi, all

I recently switched tools from vivado 2016 to 2018, my project  failed with timing, all path with DSP48E1 failed with timing. 

I start to dig out the difference, I found one thing, 

The below test code synthesized as 1 dsp48e1 in vivado 2016, but 2 in vivado 2018.

dsp111.jpgdsp222.jpg

 

 


module multacc(
clk ,
rst ,
en ,
a ,
b ,
c,
subadd ,
p
);
//ALUMODE = subadd
//OPMODE = 0100101
//preg=1
//rst->RSTP en->CEP

parameter a_bits = 6'd16;
parameter b_bits = 6'd8;
parameter c_bits = 6'd26;
parameter p_bits = 6'd26;

input clk ;
input rst ;
input en ;
input a ;
input b ;
input c;
input subadd ;
(* use_dsp48 = "yes" *)
output p ;

wire clk;
wire rst;
wire en;
wire signed [a_bits-1:0] a ;
wire signed [b_bits-1:0] b ;
wire signed [c_bits-1:0] c ;
wire subadd ;
(* use_dsp48 = "yes" *)
reg signed [p_bits-1:0] p ;

reg signed [a_bits-1:0] a_r ;
reg signed [b_bits-1:0] b_r ;
reg signed [c_bits-1:0] c_r ;
reg subadd_r ;


always @(posedge clk)
begin
a_r <= a;
b_r <= b;
c_r <= c;
subadd_r <= subadd;
end


always @(posedge clk)
//if (rst) begin
// p <= 0;
//end else if (en) begin
if (subadd)
p <= c-a*b;
else
p <= a*b+c;
//end

endmodule

 

 


module substractor
(
input wire clk,
input wire rst,
input wire [15:0] a ,
input wire signed [7:0] b ,
input wire signed [25:0] c,
input wire subadd,
output reg [25:0] d
);

reg [15:0] a_r;
reg [7:0] b_r;
reg [25:0] c_r;
reg subadd_r;

wire [25:0] d_w;

always @(posedge clk)
begin
a_r <= a;
b_r <= b;
c_r <= c;
d <= d_w;
end

multacc multacc_inst(
.clk(clk) ,
.rst(rst) ,
.en(1) ,
.a(a_r) ,
.b(b_r) ,
.c(c_r),
.subadd(subadd_r) ,
.p(d_w)
);


endmodule

0 Kudos
7 Replies
florentw
Moderator
Moderator
581 Views
Registered: ‎11-09-2015

HI @tishi 

Are you upgrading the project or creating a new project in 2018.x?

Can you make sure the synthesis settings are the same in both projects?


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**
0 Kudos
tishi
Observer
Observer
547 Views
Registered: ‎02-12-2019

For unknown reason, actually the synthesized result is wrong, you can see from the schematic, subadd is unconnected, the following is not supported by one DSP.

if (subadd)
    p <= c-a*b;
else
    p <= a*b+c;

but below can,

if (subadd)
    p <= a*b-c;
else
    p <= a*b+c;

 

 

0 Kudos
tishi
Observer
Observer
546 Views
Registered: ‎02-12-2019

Correct my previous reply,

the synthesized result of vivado 2016 is wrong.

florentw
Moderator
Moderator
530 Views
Registered: ‎11-09-2015

HI @tishi 

Ok then it just means that the issue was fixed in the later version


Florent
Product Application Engineer - Xilinx Technical Support EMEA
**~ Don't forget to reply, give kudos, and accept as solution.~**
0 Kudos
benmen
Visitor
Visitor
454 Views
Registered: ‎12-30-2019

you should have 2 stages of pipelining on the input of DSP48, adding one more pipeline stage would probably help in your case. Internally the DSP48 does the multiplication after 2 stages and the addition in the 3rd stage. So it would make sense to buffer your add operand 3 times, and then add this to the result of the multiplication. Something like this
//stage 1
a_d <= a;
b_d <= b;
c_d <= c;

//stage 2
a_dd < =a_d;
b_dd <= b_d;
c_dd <= c_d;

//stage 3
p <= a_dd * b_dd;
c_ddd <= c_dd;

//stage 4
r <= p + c_ddd;

0 Kudos
tishi
Observer
Observer
149 Views
Registered: ‎02-12-2019

Actually, it is very easy to implement o <= c±in1*in2

the below code works, vivado just fail to infer.

 

`timescale 1ns / 10ps // timescale time_unit/time_presicion
module test(

    input wire clk,

input wire rst,

input wire sub,             //0=add,1=sub

    input wire signed [24:0] in1,

    input wire signed [17:0] in2,

    input wire signed [47:0] c,

 

    output wire signed [47:0]  o,

    output wire signed [29:0] acout,

    output wire signed [17:0] bcout,

    output wire [3:0] carryout,

    output wire [3:0] carrycasout,

    output wire signed [47:0] pcout

);

 

 

 

DSP48E1 #(

.A_INPUT("DIRECT"),

.B_INPUT("DIRECT"),

.USE_DPORT("FALSE"),

.USE_MULT("MULTIPLY"),       

.USE_SIMD("ONE48"),               

 

.AUTORESET_PATDET("NO_RESET"),    // "NO_RESET", "RESET_MATCH", "RESET_NOT_MATCH"

.MASK(48'h3fffffffffff),          // 48-bit mask value for pattern detect (1=ignore)

.PATTERN(48'h000000000000),       // 48-bit pattern match for pattern detect

.SEL_MASK("MASK"),           // "C", "MASK", "ROUNDING_MODE1", "ROUNDING_MODE2"

.SEL_PATTERN("PATTERN"),          // Select pattern value ("PATTERN" or "C")

.USE_PATTERN_DETECT("NO_PATDET"),  // Enable pattern detect ("PATDET" or "NO_PATDET")

 

// Register Control Attributes: Pipeline Register Configuration

.ACASCREG(0),            //

.ADREG(1),               // Number of pipeline stages for pre-adder (0 or 1)

 

.ALUMODEREG(0),          // Number of pipeline stages for ALUMODE (0 or 1)

 

.AREG(0),                 // Number of pipeline stages for A (0, 1 or 2)  

 

.BCASCREG(0),            // Number of pipeline stages between B/BCIN and BCOUT (0, 1 or 2)

 

.BREG(0),                         // Number of pipeline stages for B (0, 1 or 2)

 

.CARRYINREG(0),                   // Number of pipeline stages for CARRYIN (0 or 1)

.CARRYINSELREG(0),                // Number of pipeline stages for CARRYINSEL (0 or 1)

.CREG(0),                         // Number of pipeline stages for C (0 or 1)

.DREG(0),                         // Number of pipeline stages for D (0 or 1)

.INMODEREG(1),                    // Number of pipeline stages for INMODE (0 or 1)

.MREG(0),                         // Number of multiplier pipeline stages (0 or 1)

.OPMODEREG(0),                    // Number of pipeline stages for OPMODE (0 or 1)

.PREG(1)                          // Number of pipeline stages for P (0 or 1)

 

   )

DSP48E1_inst (

// Cascade: 30-bit (each) output: Cascade Ports

.ACOUT(acout),                   // 30-bit output: A port cascade output

.BCOUT(bcout),                   // 18-bit output: B port cascade output

.CARRYCASCOUT(carrycasout),     // 1-bit output: Cascade carry output

.MULTSIGNOUT(),       // 1-bit output: Multiplier sign cascade output

.PCOUT(pcout),                   // 48-bit output: Cascade output

//这些引脚空着就好

 

// Control: 1-bit (each) output: Control Inputs/Status Bits

.OVERFLOW(),             // 1-bit output: Overflow in add/acc output

.PATTERNBDETECT(),        // 1-bit output: Pattern bar detect output

.PATTERNDETECT(),   // 1-bit output: Pattern detect output

.UNDERFLOW(),           // 1-bit output: Underflow in add/acc output

//这些引脚也空着,没用

 

// Data: 4-bit (each) output: Data Ports

.CARRYOUT(carryout),                               // 4-bit output: Carry output

.P(o),                           // 48-bit output: Primary data output

//P输出48bit的

 

// Cascade: 30-bit (each) input: Cascade Ports

.ACIN(30'b0),                     // 30-bit input: A cascade data input

.BCIN(18'b0),                     // 18-bit input: B cascade input

.CARRYCASCIN(1'b0),              // 1-bit input: Cascade carry input

.MULTSIGNIN(1'b0),         // 1-bit input: Multiplier sign input

.PCIN(48'b0),                     // 48-bit input: P cascade input

//这些引脚很重要,做流水线时,数据又这几个引脚输入。

 

// Control: 4-bit (each) input: Control Inputs/Status Bits

.ALUMODE(sub?4'b0011:4’b0000),  // 4-bit input: ALU control input

.CARRYINSEL(3'b0),         // 3-bit input: Carry select input

.CLK(clk),                       // 1-bit input: Clock input

.INMODE(5'b0),                 // 5-bit input: INMODE control input

.OPMODE(7'b0110101),                 // 7-bit input: Operation mode input

 

 

// Data: 30-bit (each) input: Data Ports

.A(in1),                           // 30-bit input: A data input

.B(in2),                           // 18-bit input: B data input

//.C(48'hffffffffffff),              // 48-bit input: C data input

.C(c),              // 48-bit input: C data input

 

.CARRYIN(1'b0),                      // 1-bit input: Carry input signal

.D(25'b0),                           // 25-bit input: D data input

 

 

// Reset/Clock Enable: 1-bit (each) input: Reset/Clock Enable Inputs

.CEA1(1'b0),                      // 1-bit input: Clock enable input for 1st stage AREG

.CEA2(1'b0),                      // 1-bit input: Clock enable input for 2nd stage AREG

.CEAD(1'b0),                      // 1-bit input: Clock enable input for ADREG

.CEALUMODE(1'b0),                 // 1-bit input: Clock enable input for ALUMODE

.CEB1(1'b0),                      // 1-bit input: Clock enable input for 1st stage BREG

.CEB2(1'b0),                      // 1-bit input: Clock enable input for 2nd stage BREG

.CEC(1'b0),                       // 1-bit input: Clock enable input for CREG

.CECARRYIN(1'b0),                 // 1-bit input: Clock enable input for CARRYINREG

.CECTRL(1'b0),                    // 1-bit input: Clock enable input for OPMODEREG and CARRYINSELREG

.CED(1'b0),                       // 1-bit input: Clock enable input for DREG

.CEINMODE(1'b0),                  // 1-bit input: Clock enable input for INMODEREG

.CEM(1'b0),                       // 1-bit input: Clock enable input for MREG

.CEP(1'b1),                       // 1-bit input: Clock enable input for PREG

 

 

.RSTA(rst),

.RSTALLCARRYIN(rst),

.RSTALUMODE(rst),

.RSTB(rst),

.RSTC(rst),

.RSTCTRL(rst),

.RSTD(rst),

.RSTINMODE(rst),

.RSTM(rst),

.RSTP(rst)

);

 

endmodule

 

module bitstream_tb;

reg rst;

reg dec_clk;

 

reg           subadd;

reg signed [24:0] a;

reg signed [17:0] b;

reg signed [47:0] d;

reg signed [47:0] c;

 

wire signed [47:0] p;

 

wire signed [29:0] ac;

wire signed [17:0] bc;

wire [3:0] co;

wire [3:0] ccas;

wire signed [47:0] pc;

 

initial begin

    rst = 0;

    #200 a = 10;

    #0 b = 20;

    #0 d = 45;

#0 c = 400;

#0 subadd = 0;

#2 subadd = 1;

    #50 rst = 1;

    #1 rst = 0;

 

 

    #100 $display("p %d",p);

end

 

always

begin

    #1 dec_clk = 0;

    #1 dec_clk = 1;

end

 

test test_inst(

.clk(dec_clk),

.rst(rst),

.sub(subadd),

.in1(a),

.in2(b),

.c(c),

 

.o(p),

.acout(ac),

.bcout(bc),

.carryout(co),

.carrycasout(ccas),

.pcout(pc)

);

 

 

 

 

endmodule

0 Kudos
varunra
Xilinx Employee
Xilinx Employee
87 Views
Registered: ‎01-24-2017

Hi @tishi ,

According to UG901

varunra_0-1626931490927.png

so for your code with out attribute vivado infers single DSP(confirmed with vivado 18.3) .

varunra_1-1626931946511.png

 

 

0 Kudos