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才能相加相乘。

, 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

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

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
(原創) 如何設計乘加電路? (SOC) (Verilog) (MegaCore)

相关文章: