实验原理图
实验步骤
因为一次最多输入32位数,而要实现64位的加法器,我们采用32位加法器拼接的方式
在输入的时候需要把两个64位数分成高32位和低32位分别输入。
在运算的过程中,先对两个64位数的低32位进行运算,生成低32位的结果(result_low)和一个临时进位(cout_low_to_high)
再对两个64位数的高32位相加,并加上上一步产生的临时进位,生成高32位的结果(result_high)和最终进位(cout)
修改后的最终代码如下:
//adder.v
module adder(
input [31:0] operand1_high,
input [31:0] operand1_low,
input [31:0] operand2_high,
input [31:0] operand2_low,
input cin,
output [31:0] result_high,
output [31:0] result_low,
output cout,
wire cout_low_to_high
);
assign{cout_low_to_high ,result_low}=operand1_low+ operand2_low+cin;
assign {cout,result_high} =cout_low_to_high + operand1_high +operand2_high;
endmodule
下面对adder_display.v进行更改
//adder_display.v
64位加法需要两个开关分别输入高32位和低32位
input input_sel_num, //0:输入为加数1(add_operand1);1:输入为加数2(add_operand2)
input input_sel_high_or_low, //0:输入为低32位;1:输入为高32位
下面修改对adder的调用
首先创建寄存器,用于存储输入的数
代码如下:
reg [31:0] adder_operand1_low;
reg [31:0] adder_operand1_high;
reg [31:0] adder_operand2_low;
reg [31:0] adder_operand2_high;
wire adder_cin;
wire [31:0] adder_result_low;
wire [31:0] adder_result_high;
wire adder_cout;
接着实例化adder
代码如下:
adder adder_module(
.operand1_high(adder_operand1_high),
.operand1_low(adder_operand1_low),
.operand2_high(adder_operand2_high),
.operand2_low(adder_operand2_low),
.cin (adder_cin),
.result_low(adder_result_low),
.result_high(adder_result_high),
.cout (adder_cout)
);
assign adder_cin = sw_cin;
assign led_cout = adder_cout;
接着根据两个开关和使能端R的选择为64位数分别赋值
代码如下:
//当 input_sel_num 为0时,表示输入数为加数1,即 operand1 ;
//当 input_sel_num 为1时,表示 输入数为加数2,即 operand
//当input_Sel_high_or_low为0:输入为低32位;1:输入为高32位
always @(posedge clk)
begin
if (!resetn)
begin
adder_operand1_low <= 32'd0;
adder_operand1_high <= 32'd0;
end
else if (input_valid && !input_sel_num && !input_sel_high_or_low)
begin
adder_operand1_low <= input_value;
end
else if (input_valid && !input_sel_num && input_sel_high_or_low)
begin
adder_operand1_high <= input_value;
end
end
//当input_sel_num为1时,表示输入数为加数2,即operand2
always @(posedge clk)
begin
if (!resetn)
begin
adder_operand2_low <= 32'd0;
adder_operand2_high <= 32'd0;
end
else if (input_valid && input_sel_num && !input_sel_high_or_low)
begin
adder_operand2_low <= input_value;
end
else if (input_valid && input_sel_num && input_sel_high_or_low)
begin
adder_operand2_high <= input_value;
end
end
//-----{从触摸屏获取输入}end
//-----{输出到触摸屏显示}begin
//根据需要显示的数修改此小节,
//触摸屏上共有44块显示区域,可显示44组32位数据
//44块显示区域从1开始编号,编号为1~44,
always @(posedge clk)
begin
case(display_number)
6'd1 :
begin
display_valid <= 1'b1;
display_name <= "1_HIGH";
display_value <= adder_operand1_high;
end
6'd2 :
begin
display_valid <= 1'b1;
display_name <= "1_LOW";
display_value <= adder_operand1_low;
end
6'd3 :
begin
display_valid <= 1'b1;
display_name <= "2_HIGH";
display_value <= adder_operand2_high;
end
6'd4 :
begin
display_valid <= 1'b1;
display_name <= "2_LOW";
display_value <= adder_operand2_low;
end
6'd5 :
begin
display_valid <= 1'b1;
display_name <= "R_HIGH";
display_value <= adder_result_high;
end
6'd6 :
begin
display_valid <= 1'b1;
display_name <= "R_LOW";
display_value <= adder_result_low;
end
default :
begin
display_valid <= 1'b0;
display_name <= 40'd0;
display_value <= 32'd0;
end
endcase
end
//-----{输出到触摸屏显示}end
//----------------------{调用触摸屏模块}end---------------------//
endmodule
然后在.xdc文件中修改新加的两个拨码开关和 FPGA 上具体的接口的连接。
查图可以得到 SW2 和 SW3 对应的 Package Pin 分别是 AC22 和 AC23 。
我们把 input_sel_num 连接到 SW2 ,把 input_sel_high_or_low 连接到 SW3 ,并为其设立合理电压。
代码如下:
set_property PACKAGE_PIN AC22 [get_ports input_sel_num]
set_property IOSTANDARD LVCMOS33 [get_ports input_sel_num]
set_property PACKAGE_PIN AC23 [get_ports input_sel_high_or_low]
set_property IOSTANDARD LVCMOS33 [get_ports input_sel_high_or_low]
最后对仿真文件testbench.v进行修改
代码如下:
`timescale 1ns / 1ps //仿真单位时间为1ns,精度为1ps
module testbench;
// Inputs
reg [31:0] operand1_low;
reg [31:0] operand1_high;
reg [31:0] operand2_low;
reg [31:0] operand2_high;
reg cin;
// Outputs
wire [31:0] result_low;
wire [31:0] result_high;
wire cout;
// Instantiate the Unit Under Test (UUT)
adder uut (
.operand1_low(operand1_low),
.operand1_high(operand1_high),
.operand2_low(operand2_low),
.operand2_high(operand2_high),
.cin(cin),
.result_high(result_high),
.result_low(result_low),
.cout(cout)
);
initial begin
// Initialize Inputs
operand1_high = 0;
operand1_low = 0;
operand2_low = 0;
operand2_high = 0;
cin = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
always #10 operand1_low = $random; //$random为系统任务,产生一个随机的32位数
always #10 operand1_high = $random;
always #10 operand2_low = $random; //#10 表示等待10个单位时间(10ns),即每过10ns,赋值一个随机的32位数
always #10 operand2_high = $random;
always #10 cin = {$random} % 2; //加了拼接符,{$random}产生一个非负数,除2取余得到0或1
endmodule
实验结果分析:
用计算器验证,结果正确
烧入 FPGA 得到如下结果: