如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
来源:互联网 发布:六宫格切图软件 编辑:程序博客网 时间:2024/05/28 15:20
转载:
真 OO无双
http://www.cnblogs.com/oomusou/archive/2009/10/31/verilog_signed_overflow.htmAbstract
若要將原本用軟體實現的演算法用硬體電路實現,馬上會遇到2個很基本的問題:一個是如何處理負數?另一個是如何處理overflow?雖然很基本,但一旦有問題卻很難debug。
Introduction
使用環境:NC-Verilog 5.4 + Debussy 5.4 v9
一般在開發演算法階段,我們會使用C/C++這些高階語言開發,C/C++處理負數乘加運算都很方便與直覺,也不用太擔心overflow的問題,主要是int是4 byte(32 bit)夠大,要overflow也不太容易,若一旦要用硬體電路實現,馬上就面臨2個基本的問題,硬體要怎麼處理負數?要怎麼處理overflow?
Verilog在宣告reg與wire時,雖然能使用+ – * /,並合成出相對的加法器、乘法器與除法器,但這些都是無號數(unsigned integer)運算,也就是說只能做大於或等於0的整數加減乘除運算,無法處理負數運算;除此之外,不像C/C++的int就是32 bit,為了節省硬體cost,我們會根據值域,小心的宣告reg與wire的bit數,如只有4 bit或8 bit而已,這樣經過運算後,可能在某個boundary test pattern下,一不小心就overflow了。
在(原創) 無號數及有號數的乘加運算電路設計 (IC Design) (Verilog) (OS) (Linux)與(原創) 如何設計乘加電路? (SOC) (Verilog) (MegaCore)中,我都曾經討論過這個問題,這次打算更仔細重新討論,並將overflow議題一並考慮。
本文先討論加法運算部分,乘法部分將另開專文討論之‧
Verilog的運算
Verilog所提供的運算分unsigned與signed兩種:
- Unsigned:不含signed bit
- 以4 bit來說,值域從0000~1111,也就是0 ~ 15
- Signed:含signed bit(MSB為signed bit,1為負,0為正,負數使用2補數表示)
- 以4 bit來說,值域從1000~0111,也就是-8 ~ +7
- 以4 bit來說,值域從1000~0111,也就是-8 ~ +7
二進位signed加法運算
在真正開始使用Verilog做signed加法運算前,我們先來看看實際上二進位singed加法是如何運算?
Normal Condition (沒有Overflow)
(+6) + (-3) = (+3)
為了節省resource,我們故意使用4 bit的+6與3 bit的-3相加,若直接將兩個signed值相加,答案為-7,很顯然答案並不正確‧
因為4 bit與3 bit相加,結果可能進位到5 bit,正確的作法是將4 bit的+6做signed extension到5 bit,且3 bit的-3也要做signed extension到5 bit後,然後才相加,若最後進位到6 bit,則不考慮6 bit的值‧
在此補充一下何謂Singed Extension?簡單的說,當以較多bit顯示signed型態的值時,重複signed bit補齊‧
就意義上來說,就是3 bit的signed值若要以5 bit表示時,必須補上signed bit才能在5 bit表示,所以101要變成11101‧
Boundary Condition (正Overflow)
(+7) + (+3) = (+10)
為了節省resource,我們一樣故意使用4 bit的+7與3 bit的+3相加,若直接將兩個signed值相加,答案為-6,很顯然答案並不正確。
根據上個例子的經驗,+7與+3必須做signed extension才能相加,這樣才能得到正確答案+10‧
不過現在問題來了,+10必須動到5 bit才能顯示,若輸出的值域為4 bit,只能-8 ~ +7,+10很顯然已經正overflow了‧
若只能以4 bit表示,因為是正的,MSB必須是0(SUM[3]=0),所以若MSB是1就表示由進位而來,也就是正overflow了(此例的SUM[3]為1,所以已經正overflow),再加上因為目前運算結果為5 bit,且是正,所以SUM[5]必須為0。
也就是說,若SUM[5]=0且SUM[4]=1時,為正overflow,所以01010對於4 bit來說,是正overflow。
Boundary Condition (負Overflow)
(-5) + (-4) = (-9)
同樣為了節省resource,我們故意使用4 bit的-5與3 bit的-4相加,若直接將兩個signed值相加,答案為-1,很顯然的答案並不正確‧
根據前面兩個例子,-5與-4一樣必須做signed extension才能相加,這樣才能得到正確答案-9‧進位到6 bit的1要捨去,所以答案是10111‧
問題一樣來了,-9必須動到5 bit才能顯示,若輸出的值域是4 bit,只能-8 ~ +7,-9很顯然已經是負overflow了‧
若只能以4 bit表示,因為是負的,MSB必須是1(SUM[3]=1),所以若MSB是0就表示由進位而來,也就是負overflow了(此例的SUM[3]為0,所以已經負overflow),再加上因為目前運算結果為5 bit,且是負,所以SUM[5]必須為1‧
也就是說,若SUM[5]為1且SUM[4]為0時,為負overflow,所以10111對於4 bit來說,是負overflow‧
二進位Signed加法運算Summary
根據之前三個實際的例子,我們得到以下結論
- m bit + m bit => (m+1) bit
- m bit + n bit => (m+1) bit,其中n < m
- m bit與n bit都必須先做signed extension到(m+1) bit才能相加
- 若結果有到(m+2) bit則忽略之,實際的結果為(m+1) bit
- 若Sum[m+1] ^ Sum[m]為1,表示有overflow
- 若Sum[m+1]為0且Sum[m]為1,則為正overflow
- 若Sum[m+1]為1且Sum[m]為0,則為負overflow
使用Verilog實現
signed_add.v / Verilog
Filename : signed_add.vSimulator : NC-Verilog 5.4 + Debussy 5.4 v9Description : signed add & overflowRelease : Oct/24/2009 1.0*/module signed_add ( clk, rst_n, a_i, b_i, sum_o);input clk;input rst_n;input [3:0] a_i;input [2:0] b_i;output [3:0] sum_o;reg [4:0] sum_t;always@(posedge clk or negedge rst_n) if (~rst_n) sum_t <= 5'h0; else sum_t <= {a_i[3], a_i} + {{2{b_i[2]}}, b_i}; assign sum_o = (~sum_t[4] & sum_t[3]) ? 4'b0111 : // + overflow ( sum_t[4] & ~sum_t[3]) ? 4'b1000 : // - overflow sum_t[3:0];endmodule
input [3:0] a_i;input [2:0] b_i;output [3:0] sum_o;輸入一個為3 bit,一個為4 bit,輸出為4 bit,與之前舉的例子一樣
29行
sum_t <= {a_i[3], a_i} + {{2{b_i[2]}}, b_i};
將4 bit的a_i做signed extension到5 bit,將3 bit的b_i做signed extension到5 bit‧
(~sum_t[4] & sum_t[3]) ? 4'b0111 : // + overflow
判斷是否為正overflow,若sum_t[4]為0且sum_t[3]為1,則為正overflow
( sum_t[4] & ~sum_t[3]) ? 4'b1000 : // - overflow判斷是否為負overflow,若sum_t[4]為1且sum_t[3]為0,則為負overflow‧
Filename : signed_add_tb.vSimulator : NC-Verilog 5.4 + Debussy 5.4 v9Description : signed add & overflow testbenchRelease : Oct/24/2009 1.0*/`include "signed_add.v"module signed_add_tb;reg clk;reg rst_n;reg [3:0] a_i;reg [2:0] b_i;wire [3:0] sum_o;// 4 bit// -8 ~ +7// 3 bit// -4 ~ +3initial begin //a_i <= 4'b0000; //b_i <= 3'b000; a_i <= 4'd0; b_i <= 3'd0; // normal // (+6) + (-3) #10; //a_i <= 4'b0110; //b_i <= 3'b101; a_i <= 4'd6; b_i <= -3'd3; // overflow // 7 + 3 = 10 #20; //a_i <= 4'b0111; //b_i <= 3'b011; a_i <= 4'd7; b_i <= 3'd3; // underflow // (-5) + (-4) #20; //a_i <= 4'b1011; //b_i <= 3'b100; a_i <= -4'd5; b_i <= -3'd4; #20; //a_i <= 4'b0000; //b_i <= 3'b000; a_i <= 4'd0; b_i <= 3'd0;endinitial clk = 1'b0;always #10 clk = ~clk;initial begin rst_n = 1'b0; #5; rst_n = 1'b1;endinitial begin $fsdbDumpfile("signed_add.fsdb"); $fsdbDumpvars(0, signed_add_tb); #100; $finish;endsigned_add signed_add0 ( .clk(clk), .rst_n(rst_n), .a_i(a_i), .b_i(b_i), .sum_o(sum_o));endmodule
模擬結果
(-5) + (-4) = (-9),因為已經負overflow,所以使用4 bit最小值-8表示‧
完整程式碼下載
signed_add.7z
Conclusion
本文詳細討論了在數位電路與Verilog中,如何執行帶負數的加法,以及如何判斷overflow等課題,雖然非常基本,但在使用硬體實現演算法時卻非常重要,下一次將討論如何在數位電路與Verilog實現帶負數的乘法‧
- 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
- (筆記) 如何設計邊緣檢測電路? (SOC) (Verilog)
- 如何設計乘加電路? (SOC) (Verilog) (MegaCore)
- 如何避免Quartus II自動將未宣告的信號視為wire? (SOC) (Verilog) (Quartus II)
- (筆記) 如何使用blocking與nonblocking assignment? (SOC) (Verilog)
- 如何將值delay n個clock? (SOC) (Verilog)
- 如何實現Real Time的Sobel Edge Detector? (SOC) (Verilog) (Image Processing) (DE2-70) (TRDB-D5M) (TRDB-LTM)
- [signed][input]Verilog的有符号数输入测试
- 关于verilog-2001标准中signed类型的reg/wire
- Integer Overflow
- Java Long 在Integer的overflow的范围overflow
- 如何解决 a+b >c 和 a*b 和 a-b 的 integer overflow 问题
- Verilog testbench 与module建議的coding style(SOC) (Verilog)
- verilog 中signed数据处理,负数
- signed and unsigned of verilog
- Verilog HDL signed探索实验
- verilog中的integer和reg的差别
- verilog中的integer和reg的差别
- 【微信小程序+ES6新特性应用】字符串模板:美元符号$+大括号{}变量的写法
- 【微信小程序+ES6新特性应用】通过增强对象字面量创建方法,省略function写法
- Java中的多线程你只要看这一篇就够了
- 如何从 Trados双语文件 中获得 原文 的方法
- bzoj 1002 轮状病毒 打表
- 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
- 【Linux4.1.12源码分析】AF_INET raw socket实现原理分析
- effective C++之传值与传引用
- 广义表
- linux串口通信协议编程详解
- SSL/TLS的Java实现--JSSE
- Linux 下一个很棒的命令行工具
- RtxpIPC项目是指rtsp + rtmp的IPNC,它由RtxpSvr流媒体服务器、RtxpCam摄像机、RtxpManager后台管理平台组成。
- executeQuery和executeUpdate和execute区别