(原創) 無號數及有號數的乘加運算電路設計 (IC Design) (Verilog) (OS) (Linux)

Abstract
有號數(signed operation)由於需要2's complement,所以乘加運算方式和無號數(unsigned operation)不同,該如何實現這兩種運算呢?

Introduction
欲設計一個電路計算a * b + c,當mode=0時,採用unsigned operation,當mode=1時,採用signed operation。

Verilog

 1 /* 
 2 (C) OOMusou 2007 http://oomusou.cnblogs.com
 3 
 4 Filename    : Signed_unsigned_arithmetic.v
 5 Compiler    : ModelSim SE 6.1f
 6 Description : Demo how to do unsigned operation and signed operation
 7 Release     : 11/24/2007 1.0
 8               02/09/2008 2.0
 9 */
10 `timescale 1 ns/1 ns
11 
12 module Signed_unsigned_arithmetic (
13   i_a,
14     i_b,
15     i_c,
16     i_mode,
17     o_answer
18 );
19 
20 input  [3:0] i_a, i_b, i_c;
21 input        i_mode;
22 output [7:0] o_answer;
23 
24 wire [7:0] answer_unsigned, answer_signed;
25 
26 // for unsigned operation
27 assign answer_unsigned = i_a * i_b + {4'h0, i_c};
28 
29 // for singed operation
30 assign answer_signed = {{4{i_a[3]}}, i_a} * {{4{i_b[3]}}, i_b} + {{4{i_c[3]}}, i_c};
31 
32 assign o_answer = (i_mode == 1'b0) ? answer_unsigned : answer_signed;
33 
34 endmodule


27行為unsigned operation

assign answer_unsigned = i_a * i_b + {4'h0, i_c};


由於i_a, i_b, i_c均為4 bit,運算最多可能出現8 bit,故在21行已經宣告了answer_unsigned和answer_signed為8 bit,乘法a * b自動為8 bit,所以沒問題,但加法 + i_c時,i_c原本為4 bit,要變成8 bit,只要在左邊補4個0即可,如此8 bit + 8 bit = 8 bit。

39行為signed operation

assign answer_signed = {{4{i_a[3]}}, i_a} * {{4{i_b[3]}}, i_b} + {{4{i_c[3]}}, i_c};


一個很重要的觀念:要做signed operation時,須先將所有數字做sign extension後才能相加相乘。什麼是signed extension呢?將最高位元向左補滿,如原來是0就用0補滿,如原來是1就用1補滿。因為結果是8 bit,所以i_a、i_b和i_c都必須做signed extension成8 bit才能相加相乘。

{4{i_a[3]}}, i_a}


表示取i_a的最高位元i_a[3]『重複』4次後,再與原來的i_a『合併』,i_b和i_c的原理一樣。

Testbench

 1 /* 
 2 (C) OOMusou 2007 http://oomusou.cnblogs.com
 3  
 4 Filename    : Signed_unsigned_arithmetic_tb.v
 5 Simulator   : ModelSim SE 6.1f
 6 Description : Testbench for signed_unsigend_arithmetic.v
 7 Release     : 11/24/2007 1.0
 8               02/09/2008 2.0
 9 */
10 
11 `timescale 1 ns/1 ns
12 
13 module Signed_unsigned_arithmetic_tb;
14 reg  [3:0] i_a, i_b, i_c;
15 reg        i_mode;
16 wire [7:0] o_answer;
17 
18 Signed_unsigned_arithmetic u0 (
19   .i_a(i_a),
20   .i_b(i_b),
21   .i_c(i_c),
22   .i_mode(i_mode),
23   .o_answer(o_answer)
24 );
25 
26 initial begin
27   i_mode = 0;       // unsigned operation
28   i_a    = 4'b0010; // 2
29   i_b    = 4'b0011; // 3
30   i_c    = 4'b0100; // 4
31   // answer = 8'b0000_1010 // 10
32     
33   #50;
34   i_mode = 1;       // signed operation
35   i_a    = 4'b1111; // -1
36   i_b    = 4'b1110; // -2
37   i_c    = 4'b0011; // 3
38   // answer = 8'0000_0101 // 5
39 end
40 
41 endmodule

 

Waveform

wave.gif

Conclusion

在本例,我們看到硬體在實現算數運算時,牽涉到負數的麻煩。軟體方面,在Linux kernel中,我們會發現他們很小心的使用unsigned int,若以記憶體而言,unsigned int和int都是4 byte,其實省不到記憶體,我推測可能因為執行速度的關係。在本例,我們看到unsigned operation和signed operation在數位電路的差異,signed operation明顯比較複雜,也就是說若在C/C++只使用int,在硬體會跑signed operation,而unsigned int會跑unsigned operation,速度較快,所以推估是因為速度考量使用unsigned int。

Reference
Verilog 數位電路設計範例寶典(基礎篇),鄭羽伸,儒林圖書公司,2006

See Also
(原創) 如何用管線(Pipeline)實作無號數乘加運算? (IC Design) (Verilog)
(原創) 如何處理signed integer的加法運算與overflow? (SOC) (Verilog)
(原創) 如何設計2數相加的電路? (SOC) (Verilog)
(原創) 如何設計乘加電路? (SOC) (Verilog) (MegaCore)

posted on 2007-11-25 01:43  真 OO无双  阅读(38282)  评论(2编辑  收藏  举报

导航