verilog 實現加法器

半加器

若是不考慮來自低位的進位將兩個1二進制數相加,稱爲半加。函數

實現半加運算的邏輯電路稱爲半加器。3d

真值表

code


邏輯表達式和
\begin{align}\notag
s = a{b}' + {a}'b
\end{align}
邏輯表達式進位輸出
\begin{align}\notag
co = ab
\end{align}
blog

verilog codeci

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

testbenchinput

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個數相加。這種運算稱爲全加,所用的電路稱爲全加器。it

真值表
class

邏輯表達式和
test


\begin{align}\notag
s = {({a}'{b}'{ci}' + a{b}'ci + {a}'bci + ab{ci}'})'
\end{align}
邏輯表達式進位輸出
\begin{align}\notag
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)能夠表示位


    \begin{align}\notag
    co_{i} = a_{i}b_{i} + (a_{i} + b_{i})(ci_{i})
    \end{align}


    從全加器的真值表寫出第i位和s(i)的邏輯式:
    \begin{align}\notag
    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}
    上式變換位異或函數位:
    \begin{align}\notag
    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] 數字電子技術基礎(第五版) 閻石主編

相關文章
相關標籤/搜索