zoukankan      html  css  js  c++  java
  • verilog 实现加法器

    半加器

    如果不考虑来自低位的进位将两个1二进制数相加,称为半加。

    实现半加运算的逻辑电路称为半加器。

    真值表

    >> 逻辑表达式和 egin{align} otag s = a{b}' + {a}'b end{align} >> 逻辑表达式进位输出 egin{align} otag co = ab end{align}

    verilog code

    module halfadder(
                     output       s,  //sum
                     output       co, //carry
                     input        a,  
                     input        b
                     );
    
    assign    s  = a ^ b;
    assign    co = a & b;
    //assign     {co,s} = a + b;
    
    endmodule
    

    testbench

    module halfadder_tb;
    
    wire  s;
    wire  co;
    reg   a;
    reg   b;
    
    initial
    begin
        a = 0;
        b = 0;
        #10 a = 0 ;b = 0;
        #10 a = 0 ;b = 1;
        #10 a = 1 ;b = 0;
        #10 a = 1 ;b = 1;
        #10 $finish;
    end
    
    initial begin
      $fsdbDumpfile("test.fsdb");
      $fsdbDumpvars();
    end
    
    halfadder u_halfadder(
                          .s(s),
                          .co(co),
                          .a(a),
                          .b(b)
                          );
    
    endmodule
    


    全加器

    在将两位多位二进制数相加时,除了最低位以外,每位都应该考虑来自低位的进位,即将两个对应位的加数和来自低位的进位3个数相加。这种运算称为全加,所用的电路称为全加器。

    真值表

    逻辑表达式和

    egin{align} otag s = {({a}'{b}'{ci}' + a{b}'ci + {a}'bci + ab{ci}'})' end{align} >> 逻辑表达式进位输出 egin{align} otag co = {({a}'{b}' + {b}'{ci}' + {a}'{ci}')}' end{align}

    verilog code

    module fulladder(
                     output       s,  //sum
                     output       co, //carry to high bit
                     input        a,  
                     input        b,
                     input        ci  //carry from low bit
                     );
    //RTL level
    assign s  = ~((~a&~b&~ci)||(a&~b&ci)||(~a&b&ci)||(a&b&~ci));
    assign co = ~((~a&~b)||(~b&~ci)||(~a&~ci));
    
    //assign {co,s} = a + b + ci;
    
    endmodule
    

    testbench

    module fulladder_tb;
    
    wire  s;
    wire  co;
    reg   a;
    reg   b;
    reg   ci;
    
    initial
    begin
            ci = 0; a = 0 ;b = 0;
        #10 ci = 0; a = 0 ;b = 1;
        #10 ci = 0; a = 1 ;b = 0;
        #10 ci = 0; a = 1 ;b = 1;
        #10 ci = 1; a = 0 ;b = 0;
        #10 ci = 1; a = 0 ;b = 1;
        #10 ci = 1; a = 1 ;b = 0;
        #10 ci = 1; a = 1 ;b = 1;
        #10 $finish;
    end
    
    initial begin
      $fsdbDumpfile("test.fsdb");
      $fsdbDumpvars();
    end
    
    fulladder u_fulladder(
                          .s(s),
                          .co(co),
                          .a(a),
                          .b(b),
                          .ci(ci)
                          );
    
    endmodule
    


    多位加法器

    串行进位加法器

    依次将低位全加器的进位输出co接到全加器的进位输入端ci,就可以构成多位加法器。

    显然,每一位的相加结果都必须等到低一位的进位产生才能建立起来,因此,这种结构的电路称为串行进位加法器(或称为行波进位加法器)。

    verilog code (fulladder为上面所述的全加器)

    module serialadder(
                       output   [3:0]   s,
                       output           co,
                       input    [3:0]   a,
                       input    [3:0]   b,
                       input            ci
                       );
    wire   [3:0]   co_tmp;
    
    fulladder   u_add0(
                       .s(s[0]),  //sum
                       .co(co_tmp[0]), //carry to high bit
                       .a(a[0]),  
                       .b(b[0]),
                       .ci(ci)  //carry from low bit
                       );
    
    fulladder   u_add1(
                       .s(s[1]),  //sum
                       .co(co_tmp[1]), //carry to high bit
                       .a(a[1]),  
                       .b(b[1]),
                       .ci(co_tmp[0])  //carry from low bit
                       );
    
    fulladder   u_add2(
                       .s(s[2]),  //sum
                       .co(co_tmp[2]), //carry to high bit
                       .a(a[2]),  
                       .b(b[2]),
                       .ci(co_tmp[1])  //carry from low bit
                       );
    
    fulladder   u_add3(
                       .s(s[3]),  //sum
                       .co(co_tmp[3]), //carry to high bit
                       .a(a[3]),  
                       .b(b[3]),
                       .ci(co_tmp[2])  //carry from low bit
                       );
    
    assign   co = co_tmp[3];
    
    endmodule
    

    testbench

    module serialadder_tb;
    wire      [3:0]       s;
    wire                  co;
    reg       [3:0]       a;
    reg       [3:0]       b;
    reg                   ci;
    
    initial
    begin
              a = 4'b0000; b = 4'b0000; ci = 0; 
        #10   a = 4'b1111; b = 4'b1111; ci = 0; 
        #10   a = 4'b1100; b = 4'b1001; ci = 0; 
        #10   a = 4'b0111; b = 4'b0110; ci = 0; 
        #10   a = 4'b0101; b = 4'b0101; ci = 1; 
        #10   a = 4'b1110; b = 4'b1001; ci = 1; 
        #10   a = 4'b0010; b = 4'b0110; ci = 1; 
        #10   a = 4'b0110; b = 4'b1100; ci = 1; 
        #10   $finish;
    end
    
    initial begin
      $fsdbDumpfile("test.fsdb");
      $fsdbDumpvars();
    end
    
    serialadder u_serialadder(
                              .s(s),
                              .co(co),
                              .a(a),
                              .b(b),
                              .ci(ci)
                              );
    
    endmodule
    



    超前进位加法器

    超前进位信号的产生原理

    • ab = 1 --> co = 1
    • a + b = 1,且ci = 1 --> co =1

    两位多位数中第i位相加产生的进位输出co(i)可以表示位

    egin{align} otag co_{i} = a_{i}b_{i} + (a_{i} + b_{i})(ci_{i}) end{align}

    >> 从全加器的真值表写出第i位和s(i)的逻辑式: egin{align} otag s_{i} = a_{i}{b_{i}}'{ci_{i}}' + {a_{i}}'b_{i}{ci_{i}}' + {a_{i}}'{b_{i}}'ci_{i} + (a_{i} + b_{i})ci_{i} end{align} >> 上式变换位异或函数位: egin{align} otag s_{i} = a_{i} oplus b_{i} oplus ci_{i} end{align}

    verilog code

    module carry_look_aheadadder(
                                 output     [3:0]   s,
                                 output             co,
                                 input      [3:0]   a,
                                 input      [3:0]   b,
                                 input              ci
                                 );
    wire  [3:0]    co_tmp;
    wire  [3:0]    cin;
    
    assign  cin[3:0]  = {co_tmp[2:0],ci};
    
    //计算中间进位
    assign  co_tmp[0] = a[0]&b[0] || (a[0] || b[0])&(cin[0]);
    assign  co_tmp[1] = a[1]&b[1] || (a[1] || b[1])&(cin[1]);
    assign  co_tmp[2] = a[2]&b[2] || (a[2] || b[2])&(cin[2]);
    assign  co_tmp[3] = a[3]&b[3] || (a[3] || b[3])&(cin[3]);
    
    //计算和
    assign s[0] = a[0] ^ b[0] ^ cin[0];
    assign s[1] = a[1] ^ b[1] ^ cin[1];
    assign s[2] = a[2] ^ b[2] ^ cin[2];
    assign s[3] = a[3] ^ b[3] ^ cin[3];
    
    assign co = co_tmp[3];
    endmodule
    

    testbench

    module carry_look_aheadadder_tb;
    wire      [3:0]       s;
    wire                  co;
    reg       [3:0]       a;
    reg       [3:0]       b;
    reg                   ci;
    
    initial
    begin
              a = 4'b0000; b = 4'b0000; ci = 0; 
        #10   a = 4'b1111; b = 4'b1111; ci = 0; 
        #10   a = 4'b1100; b = 4'b1001; ci = 0; 
        #10   a = 4'b0111; b = 4'b0110; ci = 0; 
        #10   a = 4'b0101; b = 4'b0101; ci = 1; 
        #10   a = 4'b1110; b = 4'b1001; ci = 1; 
        #10   a = 4'b0010; b = 4'b0110; ci = 1; 
        #10   a = 4'b0110; b = 4'b1100; ci = 1; 
        #10   $finish;
    end
    
    initial begin
      $fsdbDumpfile("test.fsdb");
      $fsdbDumpvars();
    end
    
    carry_look_aheadadder u_carry_look_aheadadder(
                                                  .s(s),
                                                  .co(co),
                                                  .a(a),
                                                  .b(b),
                                                  .ci(ci)
                                                  );
    
    endmodule
    

    参考资料

    [1] 数字电子技术基础(第五版) 阎石主编

  • 相关阅读:
    gitolite 丢失管理密钥/访问权限 解决办法
    4/20
    socket套接字模块
    网络编程part2
    网络编程part1
    异常处理
    类的属性查找
    多继承带来的菱形问题
    property装饰器
    类的继承派生
  • 原文地址:https://www.cnblogs.com/OneFri/p/6034866.html
Copyright © 2011-2022 走看看