• 加法器与减法器verilog



    减法器中也有类似于半减器、全减器、串行借位减法器之类的,但是为了实现简单和复用代码,计划采用加法器来实现减法器。

    无符号加法器

    如果两个数都是无符号的,那么可以直接相加,需要有一位作为进位。

    有符号加法器

    以4bit有符号数为例

    • 大于等于0的数的情况同无符号数一致,最高位保持为0

    • 负数与正数相加,负数的绝对值大于正数
      例如-8+7=1000+0111=01111,计算结果错误(符号位舍去后无误)
      负数的绝对值等于正数
      -7+7=1001+0111=0=10000,计算结果错误(进位舍去后无误)
      负数的绝对值小于正数
      -6+7=1010+0111=0=10001,计算结果错误(进位舍去后无误)

      若是保持输出为4位,则输出结果无误,但是为了兼容无符号加法器,不能舍去。

      处理思路是进行扩位。将4bit扩大到5bit,进位丢弃
      -8+7=11000+00111=11111 correct
      -7+7=11001+00111=00000 correct
      -6+7=11010+00111=00001 correct
      丢掉进位以后,最高位就是符号位。看似数据的范围变小了,但是本来结果就需要5位表达,所以在相加之前扩位对结果没有影响。

    • 负数与负数相加
      -8+(-8)=11000+11000=10000
      -8+(-7)=11000+11001=10001
      结果完全正确。

    有符号减法器

    继承上面的思想,再运算之前先进行扩位,即,复制最高位

    • 正数减去正数
      7-6=7+(-6)=00111+11010=00001
      可以看到转换为正数加上负数以后,计算十分简单

      问题是如何进行转换
      6=00110 取反11001 加一11010,似乎没问题
      7=00111 取反11000 加一11001,也没毛病

    • 正数减去负数
      7-(-8)=7+8=00111+01000=01111

      问题是如何进行转换
      -8=11000 取反00111 加一01000,没毛病
      -7=11001 取反00110 加一00111,没毛病

      加一的操作可以当做进位

    • 负数减去负数
      -8-(-8)=-8+8=11000+01000=00000
      -8-(-7)=-8+7=11000+00111=11111
      -7-(-8)=-7+8=11001+01000=00001
      么得问题

    • 负数减去正数
      -8-7=-8+(-7)=11000+11001=10001
      -8-8=-8+(-8)=11000+11000=10000
      -6-7=-6+(-7)=11010+11001=10011
      么得问题

      所有情况都已经推理完毕,下面就是代码部分了

      上面废话太多。事实上,因为有符号加法器是完全没有问题的,所以只要能够顺利把减法运算换成加法运算就成功了一半。需要注意的是极端情况的-8,因为运算中没有加8的情况

    加减法器

    基于串行进位加法器https://blog.csdn.net/I_LOVE_MCU/article/details/126196302
    超前进位加法器目前不支持任意位数

    module adder_substractor #(
    	parameter WIDTH = 4
    )(
    	input [WIDTH-1:0] 	in1,
    	input [WIDTH-1:0] 	in2,
    	input 				add_sub,
    	output	[WIDTH:0]	sum
    );
    wire [WIDTH:0] in1_exp;
    wire [WIDTH:0] in2_exp;
    wire cin;
    
    assign in1_exp = {in1[WIDTH-1], in1};
    assign in2_exp = add_sub? {in2[WIDTH-1], in2}: ~{in2[WIDTH-1], in2};
    assign cin = ~add_sub;
    
    // 因为对输入进行了扩位,所以WIDTH需要加1,在输出的时候会被截位,但对结果无影响
    serial_adder #(
        .WIDTH ( WIDTH+1 ))	
     u_lookahead_carry_adder (
        .in1                     ( in1_exp   ),
        .in2                     ( in2_exp   ),
        .cin                     ( cin   ),
    
        .sum                     ( sum   )
    );
    
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    TB

     `timescale  1ns / 1ps
    
    module tb_adder_substractor;
    
    // adder_substractor Parameters
    parameter PERIOD = 10;
    parameter WIDTH  = 4;
    
    // adder_substractor Inputs
    reg   [WIDTH-1:0]  in1                     = 0 ;
    reg   [WIDTH-1:0]  in2                     = 0 ;
    reg   add_sub                              = 0 ;
    
    // adder_substractor Outputs
    wire  [WIDTH:0]  sum                       ;
    
    
    // initial
    // begin
    //     forever #(PERIOD/2)  clk=~clk;
    // end
    
    // initial
    // begin
    //     #(PERIOD*2) rst_n  =  1;
    // end
    
    adder_substractor #(
        .WIDTH ( WIDTH ))
     u_adder_substractor (
        .in1                     ( in1      [WIDTH-1:0] ),
        .in2                     ( in2      [WIDTH-1:0] ),
        .add_sub                 ( add_sub              ),
    
        .sum                     ( sum      [WIDTH:0]   )
    );
    
    initial
    begin
    	in1 = -7;
    	in2 = -7;
    	add_sub = 1;
    	#10;
    	in1 = -7;
    	in2 = -7;
    	add_sub = 0;
    	#10;
    	in1 = -7;
    	in2 = 8;
    	add_sub = 0;
    	#10;
    	in1 = -7;
    	in2 = 8;
    	add_sub = 1;
    	#10;
    	in1 = 8;
    	in2 = 8;
    	add_sub = 0;
    	#10;
    	in1 = 8;
    	in2 = 8;
    	add_sub = 1;
    	#10;
    	in1 = 8;
    	in2 = -7;
    	add_sub = 0;
    	#10;
    	in1 = 8;
    	in2 = -7;
    	add_sub = 1;
    	#10;
    
        // $finish;
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    在这里插入图片描述

    Reference

    浮点数的加减法器
    https://www.cnblogs.com/mikewolf2002/p/10095995.html

  • 相关阅读:
    Django项目之图书管理系统
    剑指offer(C++)-JZ39:数组中出现次数超过一半的数字(算法-其他)
    【黑马-SpringCloud技术栈】【01】完整的微服务技术栈_微服务技术对比
    逻辑漏洞挖掘之XSS漏洞原理分析及实战演练 | 京东物流技术团队
    SSM实验室设备管理
    MYSQL之DCL
    Jetpack:002-页面与布局
    Qt 编译错误:C2228: “.key”的左边必须有类/结构/联合
    五天JavaScript基础学习全家桶
    php练习03
  • 原文地址:https://blog.csdn.net/I_LOVE_MCU/article/details/126208463