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
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.