您的位置:首页 > 其它

(原創) 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)

2009-10-31 10:48 5500 查看
Abstract
若要將原本用軟體實現的演算法用硬體電路實現,馬上會遇到2個很基本的問題:一個是如何處理負數?另一個是如何處理overflow?雖然很基本,但一旦有問題卻很難debug。

Introduction
[b]使用環境:NC-Verilog 5.4 + Debussy 5.4 v9
[/b]

一般在開發演算法階段,我們會使用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

二進位signed加法運算
在真正開始使用Verilog做signed加法運算前,我們先來看看實際上二進位singed加法是如何運算?

Normal Condition (沒有Overflow)
(+6) + (-3) = (+3)


為了節省resource,我們故意使用4 bit的+6與3 bit的-3相加,若直接將兩個signed值相加,答案為-7,很顯然答案並不正確‧

1 /*
2 (C) OOMusou 2009 http://oomusou.cnblogs.com 3
4 Filename : signed_add_tb.v
5 Simulator : NC-Verilog 5.4 + Debussy 5.4 v9
6 Description : signed add & overflow testbench
7 Release : Oct/24/2009 1.0
8 */
9
10 `include "signed_add.v"
11
12 module signed_add_tb;
13
14 reg clk;
15 reg rst_n;
16 reg [3:0] a_i;
17 reg [2:0] b_i;
18 wire [3:0] sum_o;
19
20 // 4 bit
21 // -8 ~ +7
22 // 3 bit
23 // -4 ~ +3
24 initial begin
25 //a_i <= 4'b0000;
26 //b_i <= 3'b000;
27 a_i <= 4'd0;
28 b_i <= 3'd0;
29
30 // normal
31 // (+6) + (-3)
32 #10;
33 //a_i <= 4'b0110;
34 //b_i <= 3'b101;
35 a_i <= 4'd6;
36 b_i <= -3'd3;
37
38 // overflow
39 // 7 + 3 = 10
40 #20;
41 //a_i <= 4'b0111;
42 //b_i <= 3'b011;
43 a_i <= 4'd7;
44 b_i <= 3'd3;
45
46 // underflow
47 // (-5) + (-4)
48 #20;
49 //a_i <= 4'b1011;
50 //b_i <= 3'b100;
51 a_i <= -4'd5;
52 b_i <= -3'd4;
53
54 #20;
55 //a_i <= 4'b0000;
56 //b_i <= 3'b000;
57 a_i <= 4'd0;
58 b_i <= 3'd0;
59 end
60
61
62 initial clk = 1'b0;
63 always #10 clk = ~clk;
64
65 initial begin
66 rst_n = 1'b0;
67 #5;
68 rst_n = 1'b1;
69 end
70
71 initial begin
72 $fsdbDumpfile("signed_add.fsdb");
73 $fsdbDumpvars(0, signed_add_tb);
74 #100;
75 $finish;
76 end
77
78 signed_add signed_add0 (
79 .clk(clk),
80 .rst_n(rst_n),
81 .a_i(a_i),
82 .b_i(b_i),
83 .sum_o(sum_o)
84 );
85
86
87 endmodule
模擬結果



7 + 3 = 10,因為已經正overflow,所以使用4 bit最大值+7表示‧
(-5) + (-4) = (-9),因為已經負overflow,所以使用4 bit最小值-8表示‧

完整程式碼下載
signed_add.7z

Conclusion
本文詳細討論了在數位電路與Verilog中,如何執行帶負數的加法,以及如何判斷overflow等課題,雖然非常基本,但在使用硬體實現演算法時卻非常重要,下一次將討論如何在數位電路與Verilog實現帶負數的乘法‧

See Also
(原創) 如何設計乘加電路? (SOC) (Verilog) (MegaCore)
(原創) 無號數及有號數的乘加運算電路設計 (IC Design) (Verilog) (OS) (Linux)
(原創) 如何用管線(Pipeline)實作無號數乘加運算? (IC Design) (Verilog)
(原創) 如何設計2數相加的電路? (SOC) (Verilog)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐