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] 数字电子技术基础(第五版) 阎石主编

  • 相关阅读:
    洛谷 1850 NOIP2016提高组 换教室
    2018牛客多校第三场 C.Shuffle Cards
    2018牛客多校第一场 B.Symmetric Matrix
    2018牛客多校第一场 A.Monotonic Matrix
    2018牛客多校第一场 D.Two Graphs
    2018宁夏邀请赛L Continuous Intervals
    2018宁夏邀请赛K Vertex Covers
    BZOJ
    HDU
    ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015)
  • 原文地址:https://www.cnblogs.com/OneFri/p/6034866.html
Copyright © 2011-2022 走看看