前言
本文整理了一系列有關加法的相關數位電路,雖然即使作為數位IC工程師或是FPGA工程師並不會實際創建這些電路,通常是編譯工具進行整合,但作為硬體描述語言的基本是重中之重。
全加器
全加器是初學數位電路設計的基本電路,也是最容易入門的電路。初學者可以先了解全加器的工作原理,再去延伸到其他電路,可以學習到僅僅是通過簡單幾個邏輯閘就能完成許多工程。但實際上FPGA設計者並不會寫一個加法器模組進行調用,編譯軟體運算子已經足夠聰明能夠幫助我們進行整合,但依舊是一個很好入門的數位電路。
從真值表可以化簡為的布林代數,再變成由邏輯閘構成的數位電路(原理圖)
Verilog程式碼 :
module Full_adder(
input A_i,
input B_i,
input Cin_i,
output sum_o,
output carry_o
);
assign sum_o = A_i ^ B_i ^ Cin_i;
assign carry_o = ((A_i ^ B_i) & Cin_i) | (A_i & B_i);
endmodule
如果單位元的全加器了解之後,可以去HDLBits刷題網的全加器試題電路嘗試看看,這邊也一併介紹HDLBits全加器試題電路。
可以看到原理圖有2個16位元的加法器做連接,已經有漣漣波加法器的雛型了。可以看到有各32位元的輸入A,B及32位元的SUM及進位連接。這邊HDLBits已經提供了16位元的加法器能夠調用,這樣調用已完成模組的程式碼,能更貼近FPGA設計人員的程式風格。
Verilog程式碼 :
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire cin;
add16 u0(.a(a[15:0]),.b(b[15:0]),.cin(0),.sum(sum[15:0]),.cout(cin));
add16 u1(.a(a[31:16]),.b(b[31:16]),.cin(cin),.sum(sum[31:16]),.cout());
endmodule
仿真圖 :
漣波進位加法器
漣波進位加法器是延伸全加器的基本電路,由多級的全加器在一起構成。這邊
由HDLBits的試題進行實作。
這題是上一題的內部細化,需要用單位元的加法器組成16位元的加法器,再調用兩次模組構成32位元加法器,那麼64位元、128位元也是一樣的原理。
可以看到原理圖是由最頂層TOP_Module及第二層的兩個add16及第三層的32個add1所構成的,輸入為2組32位元的a,b,輸出為32位元的sum,進位連接在第三層的內部漣波組成16位元的add16兩組,同時第二層也有add16進位連接構成TOP_Module。一層一層的設計方式也是初學者需要適應的地方,這樣程式碼易讀性才高。這邊HDLBits給了我們add1的模組進行調用,也是單位元的加法器。
Verilog程式碼 :
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire cout;
add16 add16_lo(.a(a[15:0]),.b(b[15:0]),.cin(0),.sum(sum[15:0]),.cout(cout));
add16 add16_hi(.a(a[31:16]),.b(b[31:16]),.cin(cout),.sum(sum[31:16]),.cout());
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
// Full adder module here
assign {cout,sum} = a + b + cin;
endmodule
仿真圖:
以上就是這次的教學,也可以嘗試看看更多級的加法電路,但漣波進位會導致電路的延遲變高、工作頻率下降,因為後一級等前一級,如果千級以上的加法不就是需要等待千個延遲時間,所以在設計多級加法電路的時候,需要考慮工作頻率是否在工作範圍內,才不會出事!