Knowledge Base Article

How do I implement a 25x18 complex multiplier in only 3 varialbe-precision DSP blocks?

Description

All 28-nm device families, including Stratix® V, Arria® V, and Cyclone® V, can support a 25x18 complex multiplier structure using 3 variable-precision DSP blocks.

There is a limitation in the Quartus® II software when using the Megacore® that implements this structure using 4 DSP blocks.

Resolution

To workaround this limitation use the Complex 25x18 Multiply code template found in the Quartus II software templates to infer your complex multiplier.  To use this code template you will first need to open a new design file, then select this template from the templates available in the Quartus II software.  This template is found in the Verilog or VHDL templates under Full Designs > Arithmetic > DSP Features (Stratix-V, Arria-V and Cyclone-V). 

For your convenience, this code template for Verilog is below:

// Quartus II Verilog Template
// Complex 25x18 multiply
// For use with the Stratix V, Arria-V, Cyclone-V and later device families

module complex_25x18(x_r, x_i, y_r, y_i, clock, ena1, ena0, reset, p_r, p_i);
//This template is applicable to complex 25x18 mode on Stratix-V
input [24:0] x_r;
input [24:0] x_i;
input [17:0] y_r;
input [17:0] y_i;
//Stratix-V DSP supports up to 3 clock/ena pairs and 2 async reset signals
input clock;
input ena1;
input ena0;
input reset;
output [43:0] p_r;
output [43:0] p_i;

//All inputs/outputs have to be signed.
//All input registers must use the same {clock, ena, reset}
//All output registers must use the same {clock, ena, reset}
reg signed [24:0] x_r_reg, x_i_reg;
reg signed [17:0] y_r_reg, y_i_reg;
reg signed [43:0] p_r, p_i;

wire signed [25:0] a1;
wire signed [18:0] a2;
wire signed [18:0] a3;
wire signed [43:0] p1;
wire signed [43:0] p2;
wire signed [43:0] p3;

assign a1 = x_r_reg - x_i_reg;
assign p1 = a1 * y_i_reg;
assign a2 = y_r_reg - y_i_reg;
assign p2 = a2 * x_r_reg;
assign a3 = y_r_reg y_i_reg;
assign p3 = a3 * x_i_reg;

always @(posedge clock or posedge reset)
begin
 if (reset == 1\'b1)
 begin
  x_r_reg <= 0;
  x_i_reg <= 0;
  y_r_reg <= 0;
  y_i_reg <= 0;
  p_r <= 0;
  p_i <= 0;
 end
 else
 begin
  if (ena0 == 1\'b1)
  begin
   x_r_reg <= x_r;
   x_i_reg <= x_i;
   y_r_reg <= y_r;
   y_i_reg <= y_i;
  end
  if (ena1 == 1\'b1)
  begin
   p_r <= p1 p2;
   p_i <= p1 p3;
  end
 end
end

endmodule

Updated 3 months ago
Version 2.0
No CommentsBe the first to comment