Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Vivado For this part you will implement the complex multiplier that intentionall

ID: 2268392 • Letter: V

Question

Vivado

For this part you will implement the complex multiplier that intentionally targets usage of the DSP slices. After understanding some of the DSP internals, you will realize that you can make some optimizations to your design from part 1 to utilize more of these DSPs. Rewrite the complex multiplier from part1 in a new file, part2.v, such that you use more DSP slices. The above picture provides a good idea of the stages of your complex multiplication in part2. Again, run synthesis and report on the same information from part1 in results.txt. You may use the provided testbench to help validate your design. Note that in order to accurately test your design, however many cycles your complex multiplication takes should be the value of the parameter PART2_CYCLES at the top of the testbench.v file.

top.v

module top(
input clk,
input rst,
output c_real,
output c_img
);
  
wire [35:0] c_real, c_img;
reg [17:0] a_real, a_img;
reg [17:0] b_real, b_img;

  
////////////////////////////////
//DO NOT MODIFY ABOVE THIS LINE
////////////////////////////////

///////////////////////////////////////////////
//Use this instantiation to guide your own part2 module definition
part1 p1(.clk(clk), .ar(a_real), .ai(a_img), .br(b_real), .bi(b_img), .pr(c_real), .pi(c_img));
//part2 p2(.clk(clk), .ar(a_real), .ai(a_img), .br(b_real), .bi(b_img), .pr(c_real), .pi(c_img));
  
////////////////////////////////
//DO NOT MODIFY BELOW THIS LINE
////////////////////////////////
  
always@(posedge clk)
begin
if(rst)
begin
a_real <= 0;
a_img <= 0;
b_real <= 0;
b_img <= 0;
end
else
begin
a_real <= a_real + 18'd3;
a_img <= ~(a_real);
b_img <= b_img + 18'd1;
b_real <= ~(b_img);
end
end
  
endmodule

testbench.v

module testbench
#(
parameter PART1_CYCLES = 6,
parameter PART2_CYCLES = 3, // NOTE: you are allowed to modify this.  
parameter PERIOD = 4,
parameter MAX_RAND = 10
);

reg signed [17:0] A1, a1, B1, b1;
reg signed [17:0] A2, a2, B2, b2;
wire signed [35:0] re1, im1, re2, im2;
reg clk;

// calculates (A+a*i)*(B+b*i) = re + im*i
part1 p1(clk,A1,a1,B1,b1,re1,im1);
part2 p2(clk,A2,a2,B2,b2,re2,im2);


initial clk = 0;
always #(PERIOD/2) clk = ~clk;
initial #1000 $finish();

reg signed [27:0] A1_var, a1_var, B1_var, b1_var, A2_var, a2_var, B2_var, b2_var;
reg signed [35:0] re1_expect, im1_expect, re2_expect, im2_expect;

always #100 begin
A1_var = $random % MAX_RAND;
a1_var = $random % MAX_RAND;
B1_var = $random % MAX_RAND;
b1_var = $random % MAX_RAND;
A2_var = $random % MAX_RAND;
a2_var = $random % MAX_RAND;
B2_var = $random % MAX_RAND;
b2_var = $random % MAX_RAND;
re1_expect = (A1_var*B1_var - a1_var*b1_var);
im1_expect = (A1_var*b1_var + a1_var*B1_var);
re2_expect = (A2_var*B2_var - a2_var*b2_var);
im2_expect = (A2_var*b2_var + a2_var*B2_var);
end

always @ (A1_var, a1_var, B1_var, b1_var) begin
A1 <= A1_var;
a1 <= a1_var;
B1 <= B1_var;
b1 <= b1_var;
end

always @ (A2_var, a2_var, B2_var, b2_var) begin
A2 <= A2_var;
a2 <= a2_var;
B2 <= B2_var;
b2 <= b2_var;
end

always @ (A1_var, a1_var, B1_var, b1_var) begin
#(PART1_CYCLES*PERIOD);
if (re1 != re1_expect) $display("ERROR: Part 1: %d != %d", re1, re1_expect);
if (im1 != im1_expect) $display("ERROR: Part 1: %d != %d", im1, im1_expect);
end

always @ (A2_var, a2_var, B2_var, b2_var) begin
#(PART2_CYCLES*PERIOD);
if (re2 != re2_expect) $display("ERROR: Part 2: %d != %d", re2, re2_expect);
if (im2 != im2_expect) $display("ERROR: Part 2: %d != %d", im2, im2_expect);
end

endmodule

part1.v

// Complex Multiplier (pr+i.pi) = (ar+i.ai)*(br+i.bi)

module part1 # (parameter AWIDTH = 18, BWIDTH = 18)
(
input clk,
input signed [AWIDTH-1:0] ar, ai,
input signed [BWIDTH-1:0] br, bi,
output signed [AWIDTH+BWIDTH-1:0] pr, pi
);

reg signed [AWIDTH-1:0] ai_d, ai_dd, ai_ddd, ai_dddd;
reg signed [AWIDTH-1:0] ar_d, ar_dd, ar_ddd, ar_dddd;
reg signed [BWIDTH-1:0] bi_d, bi_dd, bi_ddd, br_d, br_dd, br_ddd;
reg signed [AWIDTH:0] addcommon;
reg signed [BWIDTH:0] addr, addi;
reg signed [AWIDTH+BWIDTH-1:0] mult0, multr, multi, pr_int, pi_int;
reg signed [AWIDTH+BWIDTH-1:0] common, commonr1, commonr2;


always @(posedge clk)
begin
ar_d <= ar;
ar_dd <= ar_d;
ai_d <= ai;
ai_dd <= ai_d;
br_d <= br;
br_dd <= br_d;
br_ddd <= br_dd;
bi_d <= bi;
bi_dd <= bi_d;
bi_ddd <= bi_dd;
end

// Common factor (ar ai) x bi, shared for the calculations of the real and imaginary final products
always @(posedge clk)
begin
addcommon <= ar_d - ai_d; //(a-b)
mult0 <= addcommon * bi_dd; //(a-b)*d = ad-bd
common <= mult0;
end

// Real product
always @(posedge clk)
begin
ar_ddd <= ar_dd;
ar_dddd <= ar_ddd;
addr <= br_ddd - bi_ddd; //(c-d)
multr <= addr * ar_dddd; //(c-d)*a = ac-ad
commonr1 <= common;
pr_int <= multr + commonr1; //ac-bd
end

// Imaginary product
always @(posedge clk)
begin
ai_ddd <= ai_dd;
ai_dddd <= ai_ddd;
addi <= br_ddd + bi_ddd;
multi <= addi * ai_dddd;
commonr2 <= common;
pi_int <= multi + commonr2;
end

assign pr = pr_int;
assign pi = pi_int;

endmodule // cmult

Explanation / Answer

module top(
input clk,
input rst,
output c_real,
output c_img
);
  
wire [35:0] c_real, c_img;
reg [17:0] a_real, a_img;
reg [17:0] b_real, b_img;
part1 p1(.clk(clk), .ar(a_real), .ai(a_img), .br(b_real), .bi(b_img), .pr(c_real), .pi(c_img));
//part2 p2(.clk(clk), .ar(a_real), .ai(a_img), .br(b_real), .bi(b_img), .pr(c_real), .pi(c_img));
always@(posedge clk)
begin
if(rst)
begin
a_real <= 0;
a_img <= 0;
b_real <= 0;
b_img <= 0;
end
else
begin
a_real <= a_real + 18'd3;
a_img <= ~(a_real);
b_img <= b_img + 18'd1;
b_real <= ~(b_img);
end
end
  
endmodule

testbench.v

module testbench
#(
parameter PART1_CYCLES = 6,
parameter PART2_CYCLES = 3, // NOTE: you are allowed to modify this.  
parameter PERIOD = 4,
parameter MAX_RAND = 10
);

reg signed [17:0] A1, a1, B1, b1;
reg signed [17:0] A2, a2, B2, b2;
wire signed [35:0] re1, im1, re2, im2;
reg clk;

// calculates (A+a*i)*(B+b*i) = re + im*i
part1 p1(clk,A1,a1,B1,b1,re1,im1);
part2 p2(clk,A2,a2,B2,b2,re2,im2);


initial clk = 0;
always #(PERIOD/2) clk = ~clk;
initial #1000 $finish();

reg signed [27:0] A1_var, a1_var, B1_var, b1_var, A2_var, a2_var, B2_var, b2_var;
reg signed [35:0] re1_expect, im1_expect, re2_expect, im2_expect;

always #100 begin
A1_var = $random % MAX_RAND;
a1_var = $random % MAX_RAND;
B1_var = $random % MAX_RAND;
b1_var = $random % MAX_RAND;
A2_var = $random % MAX_RAND;
a2_var = $random % MAX_RAND;
B2_var = $random % MAX_RAND;
b2_var = $random % MAX_RAND;
re1_expect = (A1_var*B1_var - a1_var*b1_var);
im1_expect = (A1_var*b1_var + a1_var*B1_var);
re2_expect = (A2_var*B2_var - a2_var*b2_var);
im2_expect = (A2_var*b2_var + a2_var*B2_var);
end

always @ (A1_var, a1_var, B1_var, b1_var) begin
A1 <= A1_var;
a1 <= a1_var;
B1 <= B1_var;
b1 <= b1_var;
end

always @ (A2_var, a2_var, B2_var, b2_var) begin
A2 <= A2_var;
a2 <= a2_var;
B2 <= B2_var;
b2 <= b2_var;
end

always @ (A1_var, a1_var, B1_var, b1_var) begin
#(PART1_CYCLES*PERIOD);
if (re1 != re1_expect) $display("ERROR: Part 1: %d != %d", re1, re1_expect);
if (im1 != im1_expect) $display("ERROR: Part 1: %d != %d", im1, im1_expect);
end

always @ (A2_var, a2_var, B2_var, b2_var) begin
#(PART2_CYCLES*PERIOD);
if (re2 != re2_expect) $display("ERROR: Part 2: %d != %d", re2, re2_expect);
if (im2 != im2_expect) $display("ERROR: Part 2: %d != %d", im2, im2_expect);
end

endmodule

part1.v

// Complex Multiplier (pr+i.pi) = (ar+i.ai)*(br+i.bi)

module part1 # (parameter AWIDTH = 18, BWIDTH = 18)
(
input clk,
input signed [AWIDTH-1:0] ar, ai,
input signed [BWIDTH-1:0] br, bi,
output signed [AWIDTH+BWIDTH-1:0] pr, pi
);

reg signed [AWIDTH-1:0] ai_d, ai_dd, ai_ddd, ai_dddd;
reg signed [AWIDTH-1:0] ar_d, ar_dd, ar_ddd, ar_dddd;
reg signed [BWIDTH-1:0] bi_d, bi_dd, bi_ddd, br_d, br_dd, br_ddd;
reg signed [AWIDTH:0] addcommon;
reg signed [BWIDTH:0] addr, addi;
reg signed [AWIDTH+BWIDTH-1:0] mult0, multr, multi, pr_int, pi_int;
reg signed [AWIDTH+BWIDTH-1:0] common, commonr1, commonr2;


always @(posedge clk)
begin
ar_d <= ar;
ar_dd <= ar_d;
ai_d <= ai;
ai_dd <= ai_d;
br_d <= br;
br_dd <= br_d;
br_ddd <= br_dd;
bi_d <= bi;
bi_dd <= bi_d;
bi_ddd <= bi_dd;
end

// Common factor (ar ai) x bi, shared for the calculations of the real and imaginary final products
always @(posedge clk)
begin
addcommon <= ar_d - ai_d; //(a-b)
mult0 <= addcommon * bi_dd; //(a-b)*d = ad-bd
common <= mult0;
end

// Real product
always @(posedge clk)
begin
ar_ddd <= ar_dd;
ar_dddd <= ar_ddd;
addr <= br_ddd - bi_ddd; //(c-d)
multr <= addr * ar_dddd; //(c-d)*a = ac-ad
commonr1 <= common;
pr_int <= multr + commonr1; //ac-bd
end

// Imaginary product
always @(posedge clk)
begin
ai_ddd <= ai_dd;
ai_dddd <= ai_ddd;
addi <= br_ddd + bi_ddd;
multi <= addi * ai_dddd;
commonr2 <= common;
pi_int <= multi + commonr2;
end

assign pr = pr_int;
assign pi = pi_int;

endmodule // cmult