第五篇 加法器

实验五 加法器

5.1 实验目的

  1. 掌握半加器和全加器的基本原理

  2. 掌握串行进位加法器的基本原理

  3. 掌握使用全加器实现串行进位加法器的基本原理

  4. 熟悉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)。

  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
    $$

  2. 溢出标志位

    两个符号相反的数相加不会产生溢出,但两个符号相同的数相加,而和 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 实验任务

  1. 使用Verilog HDL硬件描述语言设计实现2个3位二进制数的加减法运算;

  2. 并将此功能添加到实验四实现的计算器应用中。

5.4 设计实现

5.4.1 设计思路

在实验四实现的计算器中使用如下输入:

  • 使用SW[3:0]作为操作数a;

  • 使用SW[7:4]作为操作数b;

为了减少使用滑动开关的数量,更方便的设计有限状态机作为控制器,在本实验中,我们只使用一组滑动开关SW[3:0]​​来输入操作数a、b,如下图所示。

image-20240516170449569

image-20240516170712645

操作数b其实是来自上一个操作数a经过一个寄存器后的输出,计算器的数据通路部分框图如图所示。左上角增加了一个4位的输入寄存器。

image-20240516182011337

图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)是一致的。

    image-20240516200931551

    图5.11 calculator子模块RTL视图

5.5 实验步骤

5.5.1工程创建和代码输入
  1. 点击电脑右下角的开始菜单找到Quartus软件,双击Quartus (Quartus Prime 17.1)打开Quartus Prime软件。

  2. 点击菜单File-->New Project Wizard弹出工程创建的对话框。在弹出的对话框中点击Next。

  3. 在您的DE1-SOC 工作文件夹下创建一个lab5的文件夹,并将工程路径指向该文件夹,且工程的名称命名calculator。如下图所示。

img

​​

图5.13 创建Quartus工程

  1. 选择DE1-SOC对应的FPGA器件5CSEMA5F31C6,点击Next。

  1. 连续点击3次Next得到如下界面,通过器件过滤器筛选选中DE1-SoC的Cyclone V 5CSEMA5F31C6器件,点击Next两次后得到工程的生成报告窗口,检查无误后点击Finish完成工程创建。

img

  1. 完成创建工程后,打开后的工程Quartus Prime工程界面如下图所示。

​​

图5.14 Qaurtus软件打开lab5工程

  1. 在lab5文件夹下新建v文件夹。

img

​​

图5.15 在lab5文件夹下新建v文件夹

  1. 实验四 锁存器触发器寄存器中的c1.v、c2.v、c3.v、c4.v、reg4bits.v、decod7seg.v、calculator.v文件拷贝至本实验的工程路径,如图5.16所示。

img

​​

图5.16 拷贝文件到v文件夹中

  1. 新建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

image-20240516183153923

图5.17 修改reg6bits.v文件

  1. 参考代码5.5修改calculator.v文件(可以直接将代码5.5覆盖calculator.v的原始内容)。

img

​​

图5.18 修改calculator.v文件

  1. 点击Quartus软件工具栏的Assignments --> Settings --> Files,将前面拷贝的文件添加至本实验的Quartus工程,如图5.19所示。

image-20240516183528889

图5.19 添加拷贝的文件到Quartus工程

  1. 点击Quartus软件工具栏的File --> New --> Verilog HDL File,点击OK,新建一个空白Verilog HDL文件,再点击File --> Save As ...保存,命名为mux2x1.v,保存在v文件夹中,如图5.20所示。同样的步骤再依次创建mux8x1.v、fa.v、c5.v文件。

image-20240515162541561

图5.20 新建.v文件

  1. 依次将代码5.1、代码5.2、代码5.3、代码5.4中的设计代码添加到mux2x1.v、mux8x1.v、fa.v、c5.v文件中,并保存。

image-20240515164307275

图5.21 mux2x1.v

image-20240515164331066

图5.22 mux8x1.v

image-20240515164353754

图5.23 fa.v

image-20240515164420274

图5.24 c5.v

  1. 点击Quartus软件工具栏的Processing --> Start --> Start Analysis & Synthesis或点击

    image-20210603145513555

    按钮对Verilog HDL代码执行语法检查和综合。如果在该过程中提示有错误,请检查Verilog HDL代码语法,确保与上述代码块完全一致。

image-20240515171038490

图5.26 对Verilog代码进行分析和综合

5.5.2 仿真
  1. 点击Quartus软件工具栏的File --> New --> Verilog HDL File,点击OK,新建一个空白Verilog HDL文件,再点击File --> Save As ...保存,命名为calculator_tb.v,保存在v文件夹中,如图5.27所示。

image-20240515171818978

图5.27 新建并保存test bench文件

  1. 在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

image-20240517100306813

图5.28 Quartus软件中的calculator_tb.v文件

  1. 点击Quartus软件工具栏的Assignments --> Settings,在弹出的Settings窗口中,选中Simulation栏,Tool name选择ModelSim-Altera,设置Quartus自动调用ModelSim。然后选择添加Test Bench文件,如图5.29所示。

image-20240515172139261

图5.29 设置Quartus仿真选项

  1. 依次执行下面的步骤添加calculator_tb.v文件:

  • 在弹出的Test Benches窗口中点击New

  • 在弹出的New Test Bench Settings窗口中,在Test bench name栏填入calculator_tb

  • 点击

    图标;

image-20240515172353027

图5.30 添加Test Bench文件

  • 在弹出的Select File窗口,选中第一步中创建的calculator_tb.v文件;

  • 点击Open

image-20240515172443950

图5.31 添加Test Bench文件

  • 在File name栏会出现选中的calculator_tb.v文件;

  • 点击Add添加test bench文件(添加后该文件会出现在下面的框格中)

  • 点击OK,退出当前窗口;

image-20240515173943400

图5.32 添加Test Bench文件

  • 返回到Test Benches窗口,在Existing test bench settings框格中会出现前面设置好的test bench文件;

  • 点击OK,退出当前窗口;

  • 返回到Simulation设置界面,可以看到Compile test bench栏成功添加了calculator_tb仿真文件;

  • 点击Apply应用新的设置;

  • 点击OK或者Close关闭设置窗口。

image-20240515174040188

图5.33 添加Test Bench文件

  1. 点击Quartus软件工具栏的Tools --> Run Simulation Tool --> RTL Simulation启动ModelSim仿真,如图5.34所示。

image-20240515174817983

图5.34 点击Wave选项卡切换到仿真波形窗口

再点击Wave选项卡切换到仿真波形窗口,此时还看不到完整的仿真波形,可以通过点击如图5.35所示的Zoom Full按钮来显示完整的波形。

image-20240517100444711

图5.35 Zoom Full按钮

完整的仿真波形如图5.36所示。

image-20240517101244020

图5.36 calculator仿真波形

上面这个波形里面看不到操作数b的波形。接下来我们将中间信号b添加到波形当中。点击calculator_inst,选择信号b,右击,选择Add Wave。

image-20240517112429218

然后点击Restart按钮。

image-20240517113149491

接下来弹出的Restart对话框中点击OK。

image-20240517112534837

然后点击Run All和Zoo Full(F)按钮可以看到波形如下:

image-20240517153555181

下面对仿真波形进行分析:

  1. 0-30ns复位完成。

  2. 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。

  3. 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。

  4. 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。

  5. 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。

  6. 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。

  7. 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。

  8. 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。

  1. 点击Quartus菜单Assignments——Pin Planner进行引脚分配。

img

图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页。

img

image-20240517165745573

img

image-20240517165857589

img

image-20240517170725526

  1. 点击Quartus软件工具栏的Processing --> Start Compilation或点击

    image-20210603145755433

    按钮编译lab5工程,并检查是否生成calculator.sof。

image-20240517171733209

图5.39 编译Verilog代码生成sof文件

  1. 连接好DE1-SOC开发板的电源和USB Blaster下载口,给板子开机。

  2. 点击Quartus软件工具栏的Tools --> Programmer

    image-20210603150014201

    按钮打开Programmer窗口,点击Hardware Setup选择USB-Blaster[USB-0],点击Auto Detect选择5CSEBA6器件,左键单击选中5CSEBA6器件再点击Change File,选择calculator.sof,勾选program/configure,点击Start下载calculator.sof。

image-20240517172243811

图5.40 Hardware Setup窗口

img

图5.41 选择5CSEBA6器件

img

图5.42 提示弹窗

烧录完成后,Progress进度条显示100%,如下图所示。

img

图5.43 烧录完成

5.5.4 实验现象观察
  1. 在lab5当中要用到的外设KEY、SW、LEDR和HEX如下图所示。

    image-20240517173820132

  2. 通过切换滑动开关SW到 up 或 down 位置,并按下按键KEY1KEY0,观察数码管HEX1~HEX0以及LEDR7~LEDR0的状态来测试设计的功能。

    本实验重点验证加法器的功能,因此将SW9~SW7拨动并保持为"up、down、down",即选择执行加(减)法运算。

    • 当拨动SW6为"down",SW3~SW0为"down、down、down、down",按下KEY1LEDR5~LEDR0显示为熄灭、熄灭、熄灭、熄灭、熄灭、熄灭,HEX0*上显示十六进制数字 0;

    1. 计算和:a = (0000)_B = (0)_D,b = (0000)_B = (0)_D;

    ​ 则:carry\_out = 0,s = a + b = (0000)_B = (0)_H。

    1. 溢出位:a = (0000)_B = (+0)_D,b = (0000)_B = (+0)_D;

    ​ 则:overflow = 0。

    图5.52 运行结果(1)

    • 当拨动SW6为"down",SW3~SW0为"down、up、up、down"时,按下KEY1LEDR5~LEDR0显示为点亮、熄灭、点亮、点亮、熄灭、熄灭,HEX0上显示十六进制数字 c;

    1. 计算和:a = (0110)_B = (6)_D,b = (0110)_B = (12)_D;

    ​ 则:carry\_out = 1,s = a + b = (1100)_B = (12)_H。

    1. 溢出位:a = (0110)_B = (+6)_D,b = (0110)_B = (+6)_D;

    ​ 则:overflow = 1​。

    图5.52 运行结果(1)

    • 当拨动SW6为"up",SW3~SW0为"down、down、up、down"时,按下KEY1LEDR5~LEDR0显示为熄灭、熄灭、熄灭、点亮、熄灭、熄灭,HEX0上显示十六进制数字 4;

    1. 计算和:a = (0010)_B = (2)_D,b = (0110)_B = (6)_D;

    ​ 则:carry\_out = 0,s = a - b = (1100)_B = (-4)_H。

    1. 溢出位:a = (0010)_B = (+2)_D,b = (0110)_B = (+6)_D;

    ​ 则:overflow = 0。

    图5.56 运行结果(5)

    • 当拨动SW16为"up",SW3~SW0为"up、down、down、down"时,按下KEY1LEDR5~LEDR0显示为熄灭、点亮、点亮、点亮、点亮、熄灭,HEX0*上显示十六进制数字 E;

    1. 计算和:a = (1000)_B = (8)_D,b = (0110)_B = (6)_D;

    ​ 则:carry\_out = 1,s = a - b = (0010)_B = (2)_H。

    1. 溢出位:a = (1000)_B = (-8)_D,b = (0010)_B = (+2)_D;

    ​ 则:overflow = 0。

    图5.57 运行结果(6)

5.6 实验小结

通过本实验,可掌握使用组合逻辑电路实现多位数的加(减)法运算,并验证加法器的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/847411.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《MySQL索引》学习笔记

《MySQL索引》学习笔记 MySQL的体系结构存储引擎简介InnoDB简介MyISAM简介 索引索引结构BTreeHash索引思考索引分类 索引语法SQL性能分析索引使用最左前缀法则 索引失效的情况范围查询索引列运算字符串不加引号模糊查询or连接的条件数据分布影响 SQL提示覆盖索引前缀索引单列索…

操作系统复习-linux的进程管理

linux的进程管理 linux进程的相关概念 进程的类型 前台进程 前台进程就是具有终端&#xff0c;可以和用户交互的进程&#xff0c;会占用终端shell&#xff0c;不可以输入其他的命令。 后台进程 前台进程就是具有终端&#xff0c;可以和用户交互的进程。 不会占用终端shell&a…

macOS的word没有zotero怎么办

打开zotero,首选项,引用,重新安装加载项 然后到word里 点模板和加载项 把zotero勾上,OK了

Java学习【认识异常】

Java学习【认识异常】 认识异常异常的种类异常的作用 异常的处理方式JVM默认的处理方式捕获异常finally 多个异常的处理异常中的方法抛出异常 自定义异常 认识异常 在Java中&#xff0c;将程序执行过程中发生的不正常行为称为异常 异常的种类 Error代表的是系统级别的错误&a…

ClickHouse 使用技巧总结

文章目录 数据导入、导出技巧外部文件导入导技巧使用集成表引擎导入、导出数据 建表技巧表引擎选择技巧分区键选择技巧数据结构选择技巧分区技巧 高级技巧物化视图投影位图变更数据捕获 常见报错及处理方法 数据导入、导出技巧 外部文件导入导技巧 ClickHouse作为OLAP即席分析…

每日一题《leetcode--206.反转链表》

https://leetcode.cn/problems/reverse-linked-list/ 这道题可以定义一个新结点newhead&#xff0c;newhead指向NULL。此时遍历所给链表将遍历的每个结点头插到newhead上。 struct ListNode* reverseList(struct ListNode* head) {struct ListNode* curhead;struct ListNode* n…

Go语言垃圾回收(GC原理)

1. GC回收机制 1.1 V1.3标记清除法 (1)概述 1.STW暂停 STW(暂停业务逻辑,找出可达和不可达对象) 2.对可达对象做上标记 标记完成之后,对象5和对象6不可达,被GC清除.之后STW结束. (2).缺点 STW :让程序暂停,程序出现卡顿.标记需要扫描整个heap.清除数据会产生heap碎片. 1.…

YYDS练手 130道python练习题 完整版PDF

近年来&#xff0c;Python在编程语言界里赚足了风头&#xff0c;无论是受欢迎程度&#xff0c;还是薪资待遇&#xff0c;都非常可观&#xff0c;相应的&#xff0c;Python岗位要求也越来越高&#xff0c;无论你是零基础还是老前辈&#xff0c;在Python面试中都不能轻视。 不打…

对比WPF和Avalonia的边框渲染差异

众所周知&#xff0c;诸如Border、Rectangle等元素&#xff0c;是具有边框的。但在WPF和Avalonia中&#xff0c;边框的渲染机制有所不同。 如下代码&#xff0c;Border的边框和背景色均为黑色&#xff0c;并且将透明度设为0.5&#xff1a; <Border Width"100" H…

模拟实现C++vector

一&#xff1a;C库中对于vector的介绍 vector的底层其实就是数据结构中的顺序表&#xff0c;顺序表的底层就是变长数组&#xff0c;是一段连续的物理空间 在下面的实现中&#xff0c;重点实现的是其中的迭代器和插入删除&#xff0c;下标访问等功能&#xff0c;模拟实现模板类…

Vue中使用vuex进行全局数据共享处理

1、简介 在之前的博文中&#xff0c;介绍了如何进行组件之间的数据传递&#xff0c;但是对于所有组件共享的变量来说&#xff0c;使用组件之间的数据传递实现复杂&#xff0c;因此本文引入vuex进行全局数据共享。 2、vuex的下载配置 2.1、vuex的下载 # 对于vue2来说&#xf…

IP地址开启HTTPS方法

可以使用IP地址申请SSL证书&#xff0c;申请之前必须是公网IP地址&#xff0c;不支持内网IP地址申请。 申请过程需要确定IP地址外网可以访问&#xff0c;这里特别注意只是申请过程中可以访问。访问验证过程必须采取80端口、443端口两者选择1个&#xff0c;不可以用其它端口进行…

下载视频怎么转换MP4?wmv转换mp4,推荐这3种方法

在数字化时代&#xff0c;我们经常需要从网上下载各种视频&#xff0c;但有时候下载的视频并不是我们想要的格式&#xff0c;比如WMV。为了能在更多的设备上播放或进行编辑&#xff0c;我们可能需要将其转换为更通用的MP4格式。 那么&#xff0c;下载的视频如何转换成MP4呢&am…

第三篇 编译器和译码器

实验三 编码器和译码器 3.1 实验目的 上一章节我们学习了简单组合逻辑电路——多路数据选择器&#xff0c;在本章节我们将学习另外一种数字系统中常见的简单组合逻辑电路——编码器和译码器。然后通过一个设计一个简易的计算器让大家进一步巩固FPGA开发的流程和方法。 本节您…

“神经网络之父”和“深度学习鼻祖”Geoffrey Hinton

“神经网络之父”和“深度学习鼻祖”Geoffrey Hinton在神经网络领域数十年如一日的研究&#xff0c;对深度学习的推动和贡献显著。 一、早期贡献与突破 反向传播算法的引入&#xff1a;Hinton是将反向传播&#xff08;Backpropagation&#xff09;算法引入多层神经网络训练的…

【C++进阶】深入STL之vector:构建高效C++程序的基石

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;模拟实现string &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀STL之vector &#x1f4d2;1.ve…

网络编程(七)

网络编程&#xff08;七&#xff09; UNIX域套接字&#xff08;本地间进程间通信的技术&#xff09;&#xff08;S文件&#xff09;基于TCP传输基于UDP传输 UNIX域套接字&#xff08;本地间进程间通信的技术&#xff09;&#xff08;S文件&#xff09; socket同样也可以用于本…

OpenCV-绘制虚线

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 功能函数 // 绘制虚线 void DrawDottedLine(cv::Mat &input, cv::Point p1, cv::Point p2, cv::Scalar color, int thickne…

Android Graphics 显示系统 - Android Jank detection with FrameTimeline

“ 最近有公司同事在处理UI卡顿及FPS自动化监测的问题&#xff0c;我也顺便看了一点相关的内容&#xff0c;其中在Perfetto的官方说明文档中有一篇关于利用FrameTimeLine进行Jank监测的解读&#xff0c;个人觉得蛮有意思的&#xff0c;借助工具翻译该篇文章并加上本人拙劣的解读…

C++系列-类模板

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 类模板的定义格式&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<iostream> using namespace std; template<class T> class Stack { public:Stack(size_…