(原創) 無號數及有號數的乘加運算電路設計 (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
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
由於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
一個很重要的觀念:要做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[3]『重複』4次後,再與原來的i_a『合併』,i_b和i_c的原理一樣。
Testbench
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
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)