【Vivado】加减法器的实现(不用+符号)(verilgo语言)

​​​​​​​
1. 用组合逻辑设计一个一位全加器。
  代码文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:35:00
// Design Name: 
// Module Name: adder
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder(
    input ia,  // 1位二进制加数
    input ib, // 1位二进制加数
    input cin, // 低位来的进位信号
    output cout, // 向高位的进位信号
    output sum // 1位和数
);
    
    assign cout = (ia&ib) | (ia&cin) | (ib&cin);  // 当三个输入其中两个为1时,产生进位
    assign sum = ia^ib^cin; // 和数等于三个输入异或的值
    
endmodule
 

  仿真文件: 

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:40:57
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder_test(

   );
   
   reg a,b,cin; // 定义程序的输入为reg型
   wire cout,s; // 因为要对cout和s进行assign赋值,所以定义为wire型
   adder add(a, b, cin, cout, s); // 实例化adder模块
   
   initial begin  // 给输入赋初值
        a = 1;
        b = 1;
        cin = 1;
        #100  // 使赋值持续100ns
        a = 1;
        b = 0;
        cin = 1;
        #100 // 使赋值持续100ns
        a = 1;
        b = 0;
        cin = 0;
   end
   
endmodule

 接下来直接点击 Run Simulation 进行行为仿真,得到下图结果:

2. 在一位全加器的基础上,设计一个用于无符号数 计算的四位串行加法器。
  很简单,按照一位全加器的逻辑依次计算即可。
  代码文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:35:00
// Design Name: 
// Module Name: adder
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder_4(
    input [3:0] a,  // 4位无符号数
    input [3:0] b, // 4位无符号数
    input cin, // 最低位传来的进位信号
    output [3:0] s, // 四位和的补码形式
    output cf // 进位标志
);
wire [3:0] co;
assign co[0] = (a[0]&b[0]) | (a[0]&cin) | (b[0]&cin);
assign s[0] = a[0]^b[0]^cin;
assign co[1] = (a[1]&b[1]) | (a[1]&co[0]) | (b[1]&co[0]);
assign s[1] = a[1]^b[1]^co[0];
assign co[2] = (a[2]&b[2]) | (a[2]&co[1]) | (b[2]&co[1]);
assign s[2] = a[2]^b[2]^co[1];
assign co[3] = (a[3]&b[3]) | (a[3]&co[2]) | (b[3]&co[2]);
assign s[3] = a[3]^b[3]^co[2];
assign cf=co[3];
  
endmodule

仿真文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:40:57
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder_4_test(

   );
   
   reg [3:0] a;
   reg [3:0] b;
   reg cin; // 定义程序的输入为reg型
   wire cf;
   wire [3:0] s; // 因为要对cf和s进行assign赋值,所以定义为wire型
   adder_4 adder4(a, b, cin, s, cf); // 实例化adder模块
   
   initial begin  // 给输入赋初值
        a = 4'b0001;
        b = 4'b0011;
        cin = 1;
        #100  // 使赋值持续100ns
        a = 4'b1000;
        b = 4'b1010;
        cin = 0;
        #100 // 使赋值持续100ns
        a = 4'b0011;
        b = 4'b0110;
        cin = 0;
        #100
        a = 4'b0111;
        b = 4'b0000;
        cin = 1;
   end
   
endmodule
 

 同样按照第一个的操作跑行为仿真。

3. 在一位全加器的基础上,设计一个用于有符号数 计算的四位串行加法器。
  这里增加要求输出overflow。即溢出时,该值为1.
  这里代码采用生成和传递的方法进行编写,详细解析可以查看《计算机组成与设计(RIVS-C版)》的附录部分,找找有水龙头图片那块应该就是。
  代码文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:35:00
// Design Name: 
// Module Name: adder
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder_4_s(
    input [3:0] a,  // 4位有符号数补码
    input [3:0] b, // 4位有符号数补码
    input cin, // 最低位传来的进位信号
    output  [3:0] s, // 四位和的补码形式
    output  overflow // 溢出标志
);
 wire [3:0] p;
 wire [3:0]g;
 wire [3:0]c;
 assign p=a^b; //生成
 assign g=a&b; //传递
 //进位链
 assign c[0]=cin;
 assign c[1]=g[0]|(p[0]&c[0]);
 assign c[2]=g[1]|(p[1]&c[1]);
 assign c[3]=g[2]|(p[2]&c[2]);

 //和
 assign s=p^c;
 //符号位
 assign a_sign=a[3];
 assign b_sign=b[3];
 assign s_sign=s[3];
 //溢出检测:输入符号位相同而输出的符号位不同
 assign overflow=(a_sign & b_sign & ~s_sign)|(~a_sign & ~b_sign & s_sign);

endmodule

仿真文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:40:57
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module adder_4_s_test(

   );
   
   reg [3:0] a;
   reg [3:0] b;
   reg cin; // 定义程序的输入为reg型
   wire overflow;
   wire [3:0] s; // 因为要对overflow和s进行assign赋值,所以定义为wire型
   adder_4_s adder4(a, b, cin, s, overflow); // 实例化adder模块
   
   initial begin  // 给输入赋初值
        a = 4'b0001;
        b = 4'b0011;
        cin = 1;
        #100  // 使赋值持续100ns
        a = 4'b1000;
        b = 4'b1010;
        cin = 0;
        #100 // 使赋值持续100ns
        a = 4'b0011;
        b = 4'b0110;
        cin = 0;
        #100
        a = 4'b0111;
        b = 4'b0000;
        cin = 1;
   end
   
endmodule

 同样步骤进行行为模拟:

可以在下图的右上角小齿轮处跟换数字的表示方法:

 4. 在四位有符号串行加法器的基础上,增加减法的功能。

  增加 operator 输入对加减法的功能进行选择。因为wire类型数据的限制,代码的判断只能使用三目运算符或者case选择。注意加减法器在实现减法功能时其实是将b取补码,也就是~b+1.

代码文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:35:00
// Design Name: 
// Module Name: adder
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module full_add_sub4(
input [3:0] a,
input [3:0] b,
input cin,
input operator,
output overflow,
output [3:0]result
);
wire [3:0]bb;
assign bb=operator?~b+1:b;

wire [3:0] p;
wire [3:0]g;
wire [3:0]c;
assign p=a^bb; //生成
assign g=a&bb; //传递
//进位链
assign c[0]=cin;
assign c[1]=g[0]|(p[0]&c[0]);
assign c[2]=g[1]|(p[1]&c[1]);
assign c[3]=g[2]|(p[2]&c[2]);

//和
assign result=p^c;
//符号位
assign a_sign=a[3];
assign b_sign=bb[3];
assign s_sign=result[3];
//溢出检测:输入符号位相同而输出的符号位不同
assign overflow=operator?(a_sign & ~b_sign & ~s_sign)|(~a_sign & b_sign & s_sign):(a_sign & b_sign & ~s_sign)|(~a_sign & ~b_sign & s_sign);


endmodule

仿真文件:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/10/17 19:40:57
// Design Name: 
// Module Name: test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module add_sub_test(

   );
   
   reg [3:0] a;
   reg [3:0] b;
   reg cin; // 定义程序的输入为reg型
   reg op;
   wire overflow;
   wire [3:0] result; // 因为要对overflow和s进行assign赋值,所以定义为wire型
   add_sub add_sub1(a, b, cin, op, result, overflow); // 实例化adder模块
   
   initial begin  // 给输入赋初值
        a = 4'b0001;
        b = 4'b0011;
        op = 0;
        cin = 1;
        #100  // 使赋值持续100ns
        a = 4'b1000;
        b = 4'b1010;
        op = 0;
        cin = 0;
        #100 // 使赋值持续100ns
        a = 4'b0111;
        b = 4'b1000;
        op = 0;
        cin = 1;
        #100
        a = 4'b0001;
        b = 4'b0011;
        op = 1;
        cin = 0;
        #100  // 使赋值持续100ns
        a = 4'b1000;
        b = 4'b1010;
        op = 1;
        cin = 0;
        #100 // 使赋值持续100ns
        a = 4'b0111;
        b = 4'b1000;
        op = 1;
        cin = 0;
   end
   
endmodule

输出结果显示:

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值