一. 整數的概念
整數在 IEEE 的規定上有短整數 short integer , 中整數 integer 和 長整數 long integer ,它們之間的關系如下:
為了方便討論,下面均以短整數作為例子。
原碼:最高為符號位,之后是數值位。
+62 的原碼表示為 00111110 -62 的原碼表示為 10111110
補碼:正數和0的補碼與原碼相同,負數的補碼是將其原碼的符號位保持不變,對數值位逐位求反,然后在最低位加一。對補碼求補就可以得到原碼。
+6 的原碼表示為 00000110 +6 的補碼表示為 00000110 -5 的原碼表示為 10000101 -5 的補碼表示為 11111011
補碼的運算規則:在FPGA的底層,有符號數都是按照補碼來存儲的。補碼有一個特別的好處就是可以將減法轉換為加法,從而將加減法統一。
7-5: 7 的補碼是 00000111,-5 的補碼是 11111011 ,7 + (-5) = 00000111 + 11111011 = (1)00000010 由于只有8位,因此將進位舍去得到加和的結果為 00000010,恰好是 2 的補碼 3-4: 3 的補碼是 00000011,-4 的補碼是 11111100 ,3 + (-4) = 00000011 + 11111100 = 11111111 得到加和的結果為 11111111,恰好是 -1 的補碼
溢出:兩個補碼相加時,如果產生的和超出了有效數字位所表示的范圍,則計算結果會出錯,解決的方法是擴大字長。
二. 簡單的加法與減法操作
通過上面的討論,我們可以很容易的看到,從理論上講在底層對補碼只用加法就可以完成加法與減法的操作,但是由于我們在上層是對行為進行描述,因此也是要用到減法的。
module adder8(sum,ina,inb); // 定義輸入輸出變量,這個加法器不考慮進位,只需要對輸入數據進行最高位擴展 output [8:0] sum; input [7:0] ina,inb; assign sum = {ina[7], ina} + {inb[7],inb}; endmodule
module subber8(dif,ina,inb); // 定義輸入輸出變量,這個減法器不考慮借位,只需要對輸入數據進行最高位擴展 output [8:0] dif; input [7:0] ina,inb; assign dif = {ina[7], ina} - {inb[7],inb}; endmodule
這是對有符號數設計的加減法器,可以看到上面的加減法都完成的很棒,并沒有產生溢出的問題。
三. 采用流水線操作的加法器(耗時角度考慮)
這是一個四級流水線加法器的框圖,上面的加法器采用5級鎖存、4級加法的結構。每一個加法器實現2位數據和上一個進位的相加,整個加法器只受2位全加器的工作速度的限制,平均完成一個加法運算只需要一個時鐘周期的時間,需要注意的是由于有四級流水線,因此這個加法器在輸出第一個計算值的時候有四個時鐘周期的延時。這里只給出無符號數的流水線加法器的模型,都寫出來太長了(其實我也沒有寫 )。代碼寫的比較繁瑣,但是邏輯更清楚,主要是當做學習流水線結構的例子,真正在工程中用的話感覺還是調IP核吧。
module pipeadder8(cout,sum,ina,inb,cin,clk,rst_n); // 定義輸入輸出變量 output [7:0] sum; output cout; input [7:0] ina,inb; input cin,clk,rst_n; reg [7:0] tmpa,tmpb,sum; reg cout; reg tmpci,firstco,secondco,thirdco; reg[1:0] firsts; reg[5:0] firsta,firstb; reg[3:0] seconds; reg[3:0] seconda,secondb; reg[5:0] thirds; reg[1:0] thirda, thirdb; // 這里進行第0級數據緩存 always@(posedge clk or negedge rst_n) begin if(!rst_n) {tmpa,tmpb,tmpci} <= {8'd0,8'd0,1'b0}; else {tmpa,tmpb,tmpci} <= {ina,inb,cin}; end // 這里進行第1級數據緩存,并且完成最低兩位以及進位位的加法 always@(posedge clk or negedge rst_n) begin if(!rst_n) {firstco,firsts,firsta,firstb} = {1'b0,2'd0,6'd0,6'd0}; else begin {firstco,firsts} <= tmpa[1:0] + tmpb[1:0] + tmpci; firsta <= tmpa[7:2]; firstb <= tmpb[7:2]; end end // 這里進行第2級數據緩存,并且完成次低兩位以及進位位的加法 always@(posedge clk or negedge rst_n) begin if(!rst_n) {secondco,seconds,seconda,secondb} = {1'b0,4'd0,4'd0,4'd0}; else begin {secondco,seconds} <= {{1'b0,firsta[1:0]} + {1'b0,firstb[1:0]} + firstco, firsts}; seconda <= firsta[5:2]; secondb <= firstb[5:2]; end end // 這里進行第3級數據緩存,并且完成次次低兩位以及進位位的加法 always@(posedge clk or negedge rst_n) begin if(!rst_n) {thirdco,thirds,thirda,thirdb} = {1'b0,6'd0,2'd0,2'd0}; else begin {thirdco,thirds} <= {{1'b0,seconda[1:0]} + {1'b0,secondb[1:0]} + secondco, seconds}; thirda <= seconda[3:2]; thirdb <= secondb[3:2]; end end // 這里進行第4級數據緩存,并且完成次次次低兩位以及進位位的加法 always@(posedge clk or negedge rst_n) begin if(!rst_n) {cout,sum} = {1'b0,8'd0}; else {cout,sum} <= {{1'b0,thirda[1:0]} + {1'b0,thirdb[1:0]} + thirdco, thirds}; end endmodule
-
FPGA
+關注
關注
1630文章
21796瀏覽量
605976 -
加法器
+關注
關注
6文章
183瀏覽量
30229 -
減法器
+關注
關注
1文章
26瀏覽量
16878
原文標題:FPGA的算法解析1:整數操作與加減法器
文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論