实验五 加法器
5.1 实验目的
-
掌握半加器和全加器的基本原理
-
掌握串行进位加法器的基本原理
-
掌握使用全加器实现串行进位加法器的基本原理
-
熟悉Verilog 代码设计
5.2 原理介绍
5.2.1 半加器
半加器和全加器是算数运算电路中的基本单元,它们是完成1位二进制数相加的一种组合逻辑电路。
如果只考虑两个加数本身,而没有考虑低位进位的加法运算,称为半加,实现半加运算的逻辑电路称为半加器。两个1位二进制的半加运算的真值表如表5.1所示,其中,a、b是两个加数,s表示和数,c_o表示进位数。
表5.1 半加运算真值表
输入 | 输出 | ||
---|---|---|---|
a | b | co | s |
0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 |
1 | 0 | 0 | 1 |
1 | 1 | 1 | 0 |
由真值表可得逻辑表达式:
$$
\begin{cases} s = \overline{a}\,b + a\,\overline{b} = a \bigoplus b \\ c_o = a b \end{cases}
$$
由上述表达式可以得出由异或门和与门组成的半加器,如图5.1(a)所示为半加器的电路图,其输入为 a 和 b,输出为 s 和 c_o,图5.1(b)为半加器的图形符号。
(a)半加器电路 (b)半加器符号
图5.1 半加器
5.2.2 全加器
全加器是将加数、被加数和低位来的进位信号相加,并根据求和结果给出该位的进位信号。
根据全加器的功能,可列出它的真值表,如表5.2所示。其中 a 和 b 是两个加数,c_i为低位进位数,s 为本位和数(称为全加和),c_o为向高位的进位数。
表5.2 全加运算真值表
输入 | 输出 | |||
---|---|---|---|---|
a | b | ci | co | s |
0 | 0 | 0 | 0 | 0 |
0 | 0 | 1 | 0 | 1 |
0 | 1 | 0 | 0 | 1 |
0 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
1 | 0 | 1 | 1 | 0 |
1 | 1 | 0 | 1 | 0 |
1 | 1 | 1 | 1 | 1 |
根据真值表分别画出 s 和 c_o 的卡诺图,如图5.2所示。
图5.2 全加器的s和co卡诺图
进而推导出全加器的逻辑表达式为:
$$
\begin{cases} s = \overline{a}\,\overline{b}\,c_i + \overline{a}\,b\,\overline{c_i} + a\,\overline{b}\,\overline{c_i} + a\,b\,c_i \\ \,\,\,\,\,= (\,(\,\overline{a}\,\overline{b}\,c_i\,) + (\,a\,b\,c_i\,)\,) + (\,(\,\overline{a}\,b\,\overline{c_i}\,) + (\,a\,\overline{b}\,\overline{c_i}\,)\,) \\ \,\,\,\,\,= (\,a\bigodot b\,)\,c_i + (\,a\bigoplus b\,)\,\overline{c_i} \\ \,\,\,\,\,= a\bigoplus b\bigoplus c_i \\ \\ c_o = \overline{a}\,b\,c_i + a\,\overline{b}\,c_i + a\,b \\ \,\,\,\,\,\,\,= (\,a\bigoplus b\,)\,c_i + a\,b \\ \end{cases}
$$
由上述表达式可以得出由异或门、与门和或门组成的全加器,如图5.3(a)所示为全加器的电路图,其输入为 a、b 和 c_i ,输出为 s 和 c_o,图5.3(b)为全加器的图形符号。
(a)全加器电路 (b)全加器符号
图5.3 全加器
5.2.3 串行进位加法器
若有多位数相加,则可采用并行相加串行进位的方式来完成。例如,有2个4位二进制数 a_3a_2a_1a_0和 b_3b_2b_1b_0相加,可以采用4个全加器构成4位数加法器,其原理图如图5.4所示。将低位的进位输出信号接到高位的进位输入端,因此,任意1位的加法运算必须在低1位的运算完成之后才能进行,这种进位方式称为串行进位。
图5.4 4位串行进位加法器
5.2.4 串行进位加(减)法器
减法运算的原理是将减法运算变成加法运算进行的。前面介绍的加法运算器既能实现加法运算,又可实现减法运算,从而简化数字系统结构。
若 n 位二进制的原码为 N_原,则与它相对应的 2 的补码为
$$
N_补 = 2^n - N_原
$$
补码与反码的关系式
$$
N_补 = N_反 + 1
$$
设两个数 a、b 相减,利用上面两个式子可得
$$
a - b = a + b_补 - 2^n = a + b_反 + 1 - 2^n
$$
上式表明,a 减 b 可由 a 加 b 的补码并减 2^n 完成。
图5.5 基于4位串行进位加法器的加减法电路
4位加减法运算电路如图5.5所示 ,具体原理如下:
-
和
-
当 c_i = 0 时,执行加法运算。其中,第一个加数为 a_3a_2a_1a_0,第二个加数为 b_3b_2b_1b_0,加法器相加的结果 (a + b);
-
当 c_i = 1 时,执行减法运算。首先将 b 的各位反相(求反),再加1,由此求得 b 的补码,加法器相加的结果为 (a + b_反 + 1)。
-
-
进位标志位
-
当 c_i = 0 时,执行加法运算。进位标志位 c_o = c_4;
-
当 c_i = 1 时,执行减法运算。由于 2^n = 2^4 = (10000)_B,相加结果与 2^n 相减可以由加法器进位输出信号完成。当进位输出信号为1时,它与 2^n 的差为0;当进位输出信号为0时,它与 2^n 的差为1,同时还会发出借位信号;因此,只要将进位信号反相即实现了减 2^n 的运算,反相后的输出为1时需要借位,故也可将其当作借位信号。进位标志位 c_o = \overline{c_4};
进位标志位的逻辑表达式为:
$$
c_o = \overline{c_i}\,c_4 + c_i\,\overline{c_4} = c_i \bigoplus c_4
$$ -
-
溢出标志位
两个符号相反的数相加不会产生溢出,但两个符号相同的数相加,而和 s 的符号位又与加数的符号位相反,则会产生溢出。因此,我们可对最高数据位进位(c_3)和符号位进位(c_4)进行检测,判断是否产生溢出。
-
当两个正数相加时, c_3 = 0 ,若c_4 = 1,则表明改变了结果符号位,产生溢出(上溢);
-
当两个负数相加时, c_3 = 1 ,若c_4 = 0,则表明改变了结果符号位,产生溢出(下溢);
溢出标志位的逻辑表达式为:
$$
overflow = \overline{c_3}\,c_4 + c_3\,\overline{c_4} = c_3 \bigoplus c_4
$$ -
5.3 实验任务
-
使用Verilog HDL硬件描述语言设计实现2个3位二进制数的加减法运算;
-
并将此功能添加到实验四实现的计算器应用中。
5.4 设计实现
5.4.1 设计思路
在实验四实现的计算器中使用如下输入:
-
使用SW[3:0]作为操作数a;
-
使用SW[7:4]作为操作数b;
为了减少使用滑动开关的数量,更方便的设计有限状态机作为控制器,在本实验中,我们只使用一组滑动开关SW[3:0]来输入操作数a、b,如下图所示。
操作数b其实是来自上一个操作数a经过一个寄存器后的输出,计算器的数据通路部分框图如图所示。左上角增加了一个4位的输入寄存器。
图5.6 计算器系统框图
如图5.6所示为本实验实现的计算器的系统框图,本实验是在实验四的基础上,添加一个加法器子模块和一个寄存器。SW3 ~ SW0作为加法器的加数 a,SW6作为加法器的进位输入 carry\_in,加法器的结果本位和数 s 以十六进制的形式显示在数码管HEX0上,并以二进制的形式显示在LEDR3 ~ LEDR0上,溢出标志位 overflow 、进位输出 c_o分别显示在LEDR5 ~ LEDR4上。
当数据选择器的选择位输入为 100 时,计算器可实现加法器的功能。当加法器的进位输入c_i = 0时,执行 (A + B) 运算;当c_i = 1时,执行 (A - B) 运算。
5.4.2 代码实现
-
4位二选一数据选择器
module mux2x1(// 2个4位的数据输入input [3:0] x,input [3:0] y,// 3位的选择输入input s,// 1个4位的数据输出output reg [3:0] m ); always@(x, y, s) begincase(s)1'b0: m = x; // 当s = 0时,输出m = x1'b1: m = y; // 当s = 1时,输出m = yendcase end endmodule
代码5.1 mux2x1.v
mux2x1子模块的RTL代码综合出的RTL视图如图5.7所示。
图5.7 mux2x1子模块RTL视图
-
6位八选一数据选择器
module mux8x1(// 8个6位的数据输入input [5:0] r,input [5:0] t,input [5:0] u,input [5:0] v,input [5:0] w,input [5:0] x,input [5:0] y,input [5:0] z,// 3位的选择输入input [2:0] s,// 1个6位的数据输出output reg [5:0] m );always@(r, t, u, v, w, x, y, z, s) begincase(s)3'b000: m = r; // 当s = 000时,输出m = r3'b001: m = t; // 当s = 001时,输出m = t3'b010: m = u; // 当s = 010时,输出m = u3'b011: m = v; // 当s = 011时,输出m = v3'b100: m = w; // 当s = 100时,输出m = w3'b101: m = x; // 当s = 101时,输出m = x3'b110: m = y; // 当s = 110时,输出m = y3'b111: m = z; // 当s = 111时,输出m = zendcase end endmodule
代码5.2 mux8x1.v
mux8x1子模块的RTL代码综合出的RTL视图如图5.8所示。
图5.8 mux8x1子模块RTL视图
-
全加器
module fa (input a, // 加数ainput b, // 加数binput ci, // 进位输入cioutput s, // 和数soutput co // 进位输出co ); wire a_xor_b; assign a_xor_b = a ^ b; assign s = a_xor_b ^ ci; assign co = (a_xor_b & ci) | (a & b); endmodule
代码5.3 fa.v
fa子模块的RTL代码综合出的RTL视图如图5.9所示,可以看到和我们前面分析设计的结构(图5.3(a))是一致的。
图5.9 fa子模块RTL视图
-
4位串行进位加(减)法器
module c5 (input [ 3: 0] a, // 加数ainput [ 3: 0] b, // 加数binput ci, // 进位输入cioutput [ 5: 0] f // 加(减)法器运算结果 ); wire [3:0] s; // 和数s wire co; // 进位标志位co wire overflow; // 溢出标志位 wire [4:0] c; // 串行进位加法器的进位输入、进位输出 wire [3:0] m; // 等效于串行进位加法器的第二个加数 assign c[0] = ci; // 若ci = 0,执行加法运算,第二个加数为b // 若ci = 1,执行减法运算,第二个加数为将b反相 mux2x1 mux2x1_inst (.x(b), .y(~b), .s(ci), .m(m)); fa fa_inst0 (.a(a[0]), .b(m[0]), .ci(c[0]), .s(s[0]), .co(c[1])); fa fa_inst1 (.a(a[1]), .b(m[1]), .ci(c[1]), .s(s[1]), .co(c[2])); fa fa_inst2 (.a(a[2]), .b(m[2]), .ci(c[2]), .s(s[2]), .co(c[3])); fa fa_inst3 (.a(a[3]), .b(m[3]), .ci(c[3]), .s(s[3]), .co(c[4]));// 若执行加法运算(ci = 0),则进位输出c4保持不变 // 若执行减法运算(ci = 1),则将进位输出c4取反,以实现减2的n次方的运算 assign co = ci ^ c[4]; assign overflow = c[3] ^ c[4]; assign f = {overflow, co, s};endmodule
代码5.4 c5.v
c5子模块的RTL代码综合出的RTL视图如图5.10所示,可以看到和我们前面分析设计的结构(图5.5)是一致的。
图5.10 c5子模块RTL 视图
-
计算器模块
module calculator(input [ 3: 0] a,//input [ 3: 0] b,input carry_in,input [ 2: 0] sel,input en,input clk,input rst_n,output [ 6: 0] hex0_out,output [ 5: 0] ledr_out ); wire [ 3: 0] b; wire [3:0] f1,f2,f3,f4; wire [5:0] f5,f,g; wire carry_out; wire overflow;// 将输入a存入寄存器中reg4bits reg4bits_inst (.clk(clk), .rst_n(rst_n), .en(~en), .d(a), .q(b)); // a和b做与运算 c1 c1_inst (.a(a), .b(b), .f(f1)); // a和b做或运算 c2 c2_inst (.a(a), .b(b), .f(f2)); // a和b做异或运算 c3 c3_inst (.a(a), .b(b), .f(f3)); // a和b做非运算 c4 c4_inst (.a(a), .f(f4)); // a和b做加(减)法运算 c5 c5_inst (.a(a), .b(b), .ci(carry_in), .f(f5));// 在前面的f1,f2,f3,f4,f5五种运算结果中,选择一个运算结果作为计算器的输出。 // 其中,f1,f2,f3,f4需要将高位补0组成6位 mux8x1 mux8x1_inst (.r({2'd0, f1}),.t({2'd0, f2}),.u({2'd0, f3}),.v({2'd0, f4}),.w(f5),.x(6'd0), .y(6'd0), .z(6'd0),.s(sel),.m(f) );// 将运算结果f存入寄存器中reg6bits reg6bits_inst (.clk(clk), .rst_n(rst_n), .en(~en), .d(f), .q(g)); // 当执行c1、c2、c3、c4的逻辑运算时,g[3:0]为逻辑运算结果 // 当执行c5的加法运算时,g[3:0]为和数s,g[5:4]分别为溢出标志位和进位标志位 // 将g[3:0]以十六进制的形式显示在hex0_out上 decod7seg decod7seg_inst (.hex(g[3:0]), .display(hex0_out));// 将g以二进制的形式显示在ledr_out[5:0]上 assign ledr_out = g;endmodule
代码5.5 calculator.v
calculator子模块的RTL代码综合出的RTL视图如图5.11所示,可以看到和我们在5.3.1节中分析设计的结构(图5.6)是一致的。
图5.11 calculator子模块RTL视图
5.5 实验步骤
5.5.1工程创建和代码输入
-
点击电脑右下角的开始菜单找到Quartus软件,双击Quartus (Quartus Prime 17.1)打开Quartus Prime软件。
-
点击菜单File-->New Project Wizard弹出工程创建的对话框。在弹出的对话框中点击Next。
-
在您的DE1-SOC 工作文件夹下创建一个lab5的文件夹,并将工程路径指向该文件夹,且工程的名称命名calculator。如下图所示。
图5.13 创建Quartus工程
-
选择DE1-SOC对应的FPGA器件5CSEMA5F31C6,点击Next。
-
连续点击3次Next得到如下界面,通过器件过滤器筛选选中DE1-SoC的Cyclone V 5CSEMA5F31C6器件,点击Next两次后得到工程的生成报告窗口,检查无误后点击Finish完成工程创建。
-
完成创建工程后,打开后的工程Quartus Prime工程界面如下图所示。
图5.14 Qaurtus软件打开lab5工程
-
在lab5文件夹下新建v文件夹。
图5.15 在lab5文件夹下新建v文件夹
-
将实验四 锁存器触发器寄存器中的c1.v、c2.v、c3.v、c4.v、reg4bits.v、decod7seg.v、calculator.v文件拷贝至本实验的工程路径,如图5.16所示。
图5.16 拷贝文件到v文件夹中
-
新建reg6bits.v,并将如下代码保存在该文件中。
module reg6bits(input clk, // 时钟 50MHzinput rst_n, // 异步复位信号,低电平有效input en, // 同步使能信号,高电平有效input [5:0] d, // 并行输入数据output reg [5:0] q // 并行输出数据 ); //当检测到clk上升沿或rst_n下降沿时执行下面的语句 always@(posedge clk, negedge rst_n) beginif(~rst_n) // rst_n 为低电平复位,且不需要等待 clk 上升沿到来后再复位q <= 6'b000000;else if(en)q <= d;elseq <= q; end endmodule
代码5.7 reg6bits.v
图5.17 修改reg6bits.v文件
-
参考代码5.5修改calculator.v文件(可以直接将代码5.5覆盖calculator.v的原始内容)。
图5.18 修改calculator.v文件
-
点击Quartus软件工具栏的Assignments --> Settings --> Files,将前面拷贝的文件添加至本实验的Quartus工程,如图5.19所示。
图5.19 添加拷贝的文件到Quartus工程
-
点击Quartus软件工具栏的File --> New --> Verilog HDL File,点击OK,新建一个空白Verilog HDL文件,再点击File --> Save As ...保存,命名为mux2x1.v,保存在v文件夹中,如图5.20所示。同样的步骤再依次创建mux8x1.v、fa.v、c5.v文件。
图5.20 新建.v文件
-
依次将代码5.1、代码5.2、代码5.3、代码5.4中的设计代码添加到mux2x1.v、mux8x1.v、fa.v、c5.v文件中,并保存。
图5.21 mux2x1.v
图5.22 mux8x1.v
图5.23 fa.v
图5.24 c5.v
-
点击Quartus软件工具栏的Processing --> Start --> Start Analysis & Synthesis或点击
按钮对Verilog HDL代码执行语法检查和综合。如果在该过程中提示有错误,请检查Verilog HDL代码语法,确保与上述代码块完全一致。
图5.26 对Verilog代码进行分析和综合
5.5.2 仿真
-
点击Quartus软件工具栏的File --> New --> Verilog HDL File,点击OK,新建一个空白Verilog HDL文件,再点击File --> Save As ...保存,命名为calculator_tb.v,保存在v文件夹中,如图5.27所示。
图5.27 新建并保存test bench文件
-
在calculator_tb.v文件中输入如下代码,并保存。
`timescale 1ns / 1ns module calculator_tb; // 产生时钟信号 reg clk; localparam PERIOD = 20; // T = 1/frequency = 1/50MHz = 20ns initial beginclk = 1'b0;forever#(PERIOD/2) clk = ~clk; end // 产生复位信号,用作6位寄存器的异步复位 reg rst_n; initial beginrst_n = 1'b0;#(PERIOD)rst_n = 1'b1; end // 定义计算器的两个操作数a、b,加法器的进位输入carry_in,执行的运算选择位sel,6位寄存器的使能信号en reg [3:0] a; //reg [3:0] b; reg carry_in; reg [2:0] sel; reg en; initial begin#0; //sel = 3'b100;en = 1'b1;//rst_n = 1'b1;a = 4'b0000;//b = 4'b0001;carry_in = 1'b0; #(PERIOD)sel = 3'b100; //加法或减法//en = 1'b1;//rst_n = 1'b1;a = 4'b0110;//b = 4'b1101;carry_in = 1'b0; // 0110 + 0000 = 0_0_0110#(PERIOD)//sel = 3'b100;//en = 1'b1;//rst_n = 1'b1;a = 4'b0110;//b = 4'b0101;carry_in = 1'b0; // 0110 + 0110 = 1_0_1100#(PERIOD)//sel = 3'b100;//en = 1'b1;//rst_n = 1'b1;a = 4'b1010;//b = 4'b1101;carry_in = 1'b0; // 1010 + 0110 = 0_1_0000#(PERIOD) //sel = 3'b100;//en = 1'b1;//rst_n = 1'b1;a = 4'b0010;//b = 4'b0001;carry_in = 1'b1; // 0010 - 1010 = 1_1_1000#(PERIOD)//sel = 3'b100;//en = 1'b1;//rst_n = 1'b1;a = 4'b1000;//b = 4'b1010;carry_in = 1'b1; // 1000 - 0010 = 1_0_0110#(PERIOD)//sel = 3'b100;//en = 1'b1;//rst_n = 1'b1;a = 4'b1001;//b = 4'b0110;carry_in = 1'b1; // 1001 - 1000 = 0_0_0001#(PERIOD)//sel = 3'b100;//en = 1'b1; // rst_n = 1'b1;a = 4'b0100;//b = 4'b1001;carry_in = 1'b1; // 0100 - 1001 = 1_1_1011#(PERIOD) $stop; end // 例化 wire [6:0] hex0_out; wire [5:0] ledr_out; calculator calculator_inst ( /* input */ .clk (clk), /* input */ .rst_n (rst_n), /* input */ .en (en), /* input [3:0] */ .a (a), /* input [3:0] */ //.b (b), /* input */ .carry_in (carry_in), /* input [2:0] */ .sel (sel), /* output [6:0] */ .hex0_out (hex0_out), /* output [5:0] */ .ledr_out (ledr_out) ); endmodule
代码5.7 calculator_tb.v
图5.28 Quartus软件中的calculator_tb.v文件
-
点击Quartus软件工具栏的Assignments --> Settings,在弹出的Settings窗口中,选中Simulation栏,Tool name选择ModelSim-Altera,设置Quartus自动调用ModelSim。然后选择添加Test Bench文件,如图5.29所示。
图5.29 设置Quartus仿真选项
-
依次执行下面的步骤添加calculator_tb.v文件:
-
在弹出的Test Benches窗口中点击New;
-
在弹出的New Test Bench Settings窗口中,在Test bench name栏填入calculator_tb;
-
点击
图标;
图5.30 添加Test Bench文件
-
在弹出的Select File窗口,选中第一步中创建的calculator_tb.v文件;
-
点击Open;
图5.31 添加Test Bench文件
-
在File name栏会出现选中的calculator_tb.v文件;
-
点击Add添加test bench文件(添加后该文件会出现在下面的框格中)
-
点击OK,退出当前窗口;
图5.32 添加Test Bench文件
-
返回到Test Benches窗口,在Existing test bench settings框格中会出现前面设置好的test bench文件;
-
点击OK,退出当前窗口;
-
返回到Simulation设置界面,可以看到Compile test bench栏成功添加了calculator_tb仿真文件;
-
点击Apply应用新的设置;
-
点击OK或者Close关闭设置窗口。
图5.33 添加Test Bench文件
-
点击Quartus软件工具栏的Tools --> Run Simulation Tool --> RTL Simulation启动ModelSim仿真,如图5.34所示。
图5.34 点击Wave选项卡切换到仿真波形窗口
再点击Wave选项卡切换到仿真波形窗口,此时还看不到完整的仿真波形,可以通过点击如图5.35所示的Zoom Full按钮来显示完整的波形。
图5.35 Zoom Full按钮
完整的仿真波形如图5.36所示。
图5.36 calculator仿真波形
上面这个波形里面看不到操作数b的波形。接下来我们将中间信号b添加到波形当中。点击calculator_inst,选择信号b,右击,选择Add Wave。
然后点击Restart按钮。
接下来弹出的Restart对话框中点击OK。
然后点击Run All和Zoo Full(F)按钮可以看到波形如下:
下面对仿真波形进行分析:
-
0-30ns复位完成。
-
30 ~ 50 ns
-
计算和:a = (0110)_B = (6)_D,b = (0000)_B = (0)_D;
则:carry\_out = 0,s = a + b = (0110)_B = (6)_H。
-
溢出位:a = (0110)_B = (+6)_D,b = (0000)_B = (+0)_D;
则:overflow = 0。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第30ns时:
输出ledr\_out = 000110;输出hex\_out = 0000010,即在数码管上显示十六进制数字6。
-
-
50 ~ 70 ns
-
计算和:a = (0110)_B = (6)_D,b = (0110)_B = (6)_D;
则:carry\_out = 0,s = a + b = (1100)_B = (c)_H。
-
溢出位:a = (0110)_B = (+6)_D,b = (0110)_B = (6)_D;
则:overflow = 1。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第50ns时:
输出ledr\_out = 101100;输出hex\_out = 1000110,即在数码管上显示十六进制数字c。
-
-
70 ~ 90 ns
-
计算和:a = (1010)_B = (10)_D,b = (0110)_B = (6)_D;
则:carry\_out = 1,s = a + b = (0000)_B = (0)_H。
-
溢出位:a = (0110)_B = (+10)_D,b = (0110)_B = (+6)_D;
则:overflow = 0。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第70ns时:
输出ledr\_out = 010000;输出hex\_out = 1000000,即在数码管上显示十六进制数字0。
-
-
90 ~ 110 ns
-
计算和:a = (0010)_B = (2)_D,b = (1010)_B = (10)_D;
则:carry\_out = 1,s = a - b = (1000)_B = (8)_H。
-
溢出位:a = (0010)_B = (+2)_D,b = (1010)_B = (-2)_D;
则:overflow = 1。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第90ns时:
输出ledr\_out = 111000;输出hex\_out = 0000000,即在数码管上显示十六进制数字8。
-
-
110 ~ 130 ns
-
计算和:a = (1000)_B = (8)_D,b = (0010)_B = (2)_D;
则:carry\_out = 0,s = a - b = (0110)_B = (6)_H。
-
溢出位:a = (1000)_B = (+8)_D,b = (0010)_B = (+2)_D;
则:overflow = 1。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第110ns时:
输出ledr\_out = 100110;输出hex\_out = 0000010,即在数码管上显示十六进制数字6。
-
-
130 ~ 150 ns
-
计算和:a = (1001)_B = (9)_D,b = (1000)_B = (8)_D;
则:carry\_out = 0,s = a - b = (0001)_B = (1)_H。
-
溢出位:a = (1001)_B = (-1)_D,b = (1000)_B = (-0)_D;
则:overflow = 0。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第110ns时:
输出ledr\_out = 000001;输出hex\_out = 11110011,即在数码管上显示十六进制数字1。
-
-
150ns ~
-
计算和:a = (0100)_B = (4)_D,b = (1001)_B = (9)_D;
则:carry\_out =1 ,s = a - b = (1011)_B = (b)_H。
-
溢出位:a = (0100)_B = (+4)_D,b = (1001)_B = (-1)_D;
则:overflow = 1。
运算结果先是被存储到寄存器中,当 clk 上升沿到来时再输出,即在第150ns时:
输出ledr\_out = 111011;输出hex\_out = 0000011,即在数码管上显示十六进制数字b。
-
5.5.3 引脚分配、全编译与烧录
这个实验的操作数a及sel可以通过拨码开关SW0~SW3以及SW7~SW9来控制,carry_in从SW6输入。out信号分别输出到LEDR0到LEDR5,hex0_out输出到数码管0,en和rst_n连接到按键key1和key0。
-
点击Quartus菜单Assignments——Pin Planner进行引脚分配。
图4.41
关于引脚分配信息可以查看DE1-SoC_v.5.1.3_HWrevF.revG_SystemCD\UserManual\DE1-SoC_User_manual.pdf第 22、25、26、28页或者E:\CD_Package\01-DE1-SoC\DE1-SoC_v.5.1.3_HWrevF.revG_SystemCD\Schematic\DE1-SoC.pdf的第3页。
-
点击Quartus软件工具栏的Processing --> Start Compilation或点击
按钮编译lab5工程,并检查是否生成calculator.sof。
图5.39 编译Verilog代码生成sof文件
-
连接好DE1-SOC开发板的电源和USB Blaster下载口,给板子开机。
-
点击Quartus软件工具栏的Tools --> Programmer或
按钮打开Programmer窗口,点击Hardware Setup选择USB-Blaster[USB-0],点击Auto Detect选择5CSEBA6器件,左键单击选中5CSEBA6器件再点击Change File,选择calculator.sof,勾选program/configure,点击Start下载calculator.sof。
图5.40 Hardware Setup窗口
图5.41 选择5CSEBA6器件
图5.42 提示弹窗
烧录完成后,Progress进度条显示100%,如下图所示。
图5.43 烧录完成
5.5.4 实验现象观察
-
在lab5当中要用到的外设KEY、SW、LEDR和HEX如下图所示。
-
通过切换滑动开关SW到 up 或 down 位置,并按下按键KEY1或KEY0,观察数码管HEX1~HEX0以及LEDR7~LEDR0的状态来测试设计的功能。
本实验重点验证加法器的功能,因此将SW9~SW7拨动并保持为"up、down、down",即选择执行加(减)法运算。
-
当拨动SW6为"down",SW3~SW0为"down、down、down、down",按下KEY1,LEDR5~LEDR0显示为熄灭、熄灭、熄灭、熄灭、熄灭、熄灭,HEX0*上显示十六进制数字 0;
-
计算和:a = (0000)_B = (0)_D,b = (0000)_B = (0)_D;
则:carry\_out = 0,s = a + b = (0000)_B = (0)_H。
-
溢出位:a = (0000)_B = (+0)_D,b = (0000)_B = (+0)_D;
则:overflow = 0。
图5.52 运行结果(1)
-
当拨动SW6为"down",SW3~SW0为"down、up、up、down"时,按下KEY1,LEDR5~LEDR0显示为点亮、熄灭、点亮、点亮、熄灭、熄灭,HEX0上显示十六进制数字 c;
-
计算和:a = (0110)_B = (6)_D,b = (0110)_B = (12)_D;
则:carry\_out = 1,s = a + b = (1100)_B = (12)_H。
-
溢出位:a = (0110)_B = (+6)_D,b = (0110)_B = (+6)_D;
则:overflow = 1。
图5.52 运行结果(1)
-
当拨动SW6为"up",SW3~SW0为"down、down、up、down"时,按下KEY1,LEDR5~LEDR0显示为熄灭、熄灭、熄灭、点亮、熄灭、熄灭,HEX0上显示十六进制数字 4;
-
计算和:a = (0010)_B = (2)_D,b = (0110)_B = (6)_D;
则:carry\_out = 0,s = a - b = (1100)_B = (-4)_H。
-
溢出位:a = (0010)_B = (+2)_D,b = (0110)_B = (+6)_D;
则:overflow = 0。
图5.56 运行结果(5)
-
当拨动SW16为"up",SW3~SW0为"up、down、down、down"时,按下KEY1,LEDR5~LEDR0显示为熄灭、点亮、点亮、点亮、点亮、熄灭,HEX0*上显示十六进制数字 E;
-
计算和:a = (1000)_B = (8)_D,b = (0110)_B = (6)_D;
则:carry\_out = 1,s = a - b = (0010)_B = (2)_H。
-
溢出位:a = (1000)_B = (-8)_D,b = (0010)_B = (+2)_D;
则:overflow = 0。
图5.57 运行结果(6)
-
5.6 实验小结
通过本实验,可掌握使用组合逻辑电路实现多位数的加(减)法运算,并验证加法器的功能。