2016-01-26 167 views
2

我正在實現一個VHDL 8位定點乘法模塊,該模塊返回一個8位截斷的數字,但當我手工乘法運算來測試它時,我遇到了一個問題。當我想要乘以兩個負數時出現問題。二進制定點乘法

我試着乘以兩個正值1.67 * 0.625〜1.04(二進制乘法爲0.906)。

001.10101 -> 1.67 
000.10100 -> 0.625 
------------ 
000000.1110111010 = 000.11101 (truncated to 8bits = 0.906) 

我試過乘正數和負數(-0.875 * 3〜2.62)

111.00100 -> -0.875 
011.00000 -> 3 
---------- 
010101.0110000000 = 101.01100 (truncated to 8bits = -2.625) 

到目前爲止everythng工作正常。問題出現在我試圖乘以兩個負數的情況下。根據我所知道的(除非我錯了): - 將兩個數相乘將得到兩倍分辨率的結果(將兩個8位數相乘,得到一個16位數) - 固定點也會錯位。在這個例子中,固定之前有3個位,之後有5個位。這意味着在結果數字中,固定點將在點之前有6位數,在點之後有10位。

通過假設這以上計算正常工作。但是,當我試圖乘兩個負值(-0.875 * -1.91〜1.67)

110.00010 -> -1.91 (1.9375) 
111.00100 -> -0.875 
------------ 
101011.0011001000 = 011.00110(truncated to 8 bits = 3.1875) 

當然,我嘗試另一個負乘法(-2.64 * -0.875 = 2.31)

101.01011 -> -2.64 
111.00100 -> -0.875 
---------- 
100110.0001001100 = 110.00010 (truncated to 8bits = -1.9375) 

顯然,我我做錯了什麼,但我不明白我做錯了什麼。

PS:我還沒有實現它。我想到了我想要做的事情,然後試着用一些簡單的例子手工測試它。我也嘗試了更多的乘法。我認爲,也許他們工作是因爲我很幸運,但顯然不是,我嘗試了幾次乘法,他們的工作。所以也許我在做兩個負數的時候做錯了什麼,也許我把它截斷了?大概。

編輯: 好吧,我發現指出乘法是怎麼做時,兩個操作數是負Xilinx的文件,here是鏈接。根據這個文件,爲了這個文件,這隻能在擴展乘法時完成。乘法的最後部分和必須反轉,然後加1,它會得到正確的數字。

爲了乘法運算,我在程序員模式下使用windows'calculator,這意味着爲了乘以8位,我把數字放到計算器中,然後得到結果並截斷它。如果他們爲其他情況工作,則意味着Windows計算器正在進行直接乘法(將所有部分和相加,而不是反轉最後的部分和)。因此,這意味着,爲了獲得真實的結果,我應該從最後的結果。減去第一個操作數,然後添加倒第一個操作數+ 1

110.00010 -> -1.91 (1.9375) 
111.00100 -> -0.875 
------------ 
101011.0011001000 
Which gave me the result: 000010.0111001000 = 010.01110(truncated to 8bits =2.43) 

而且與我想出了結果的另一個爲1.875。這些產出並不是很好,但至少它們更接近我的預期。有沒有其他方法可以以更簡單的方式實現此目的?

+0

無符號或無符號您必須允許結果大小的兩倍或小一大。在十進制中1000 * 1000 = 1000000可以與9999接近,但很容易看出您必須查看最高有效數字的功率,並且只有這兩個數字的結果在1的範圍內確定結果的大小2^7 * 2^7 = 2 * 14 8位數的乘法將需要15或16位結果,或者只是嘗試0xFF * 0xFF,您將得到0xFE01。如果msbits是例如2^7 * 2^0 = 2^7那麼你需要一個8或9位數的答案,在這種情況下8 0xFF * 0x01 = 0xFF。 –

+0

@RyanVincent對不起,花了我很長的時間來回答。我正在做我的平行研究並張貼我的結果。無需檢測並處理溢出。我知道通過忽略這些標誌來做到這一點是可行的,但我想知道是否有其他方式可以做到而不忽視它們。根據我的研究,有但是更難。我想我必須在if語句中做。如果操作數[7] ='1'且操作數2 [7] ='1',那麼輸入到乘法器的兩個位都接收到'0',如果它們不同,則放入整個操作數。這很糟糕..我認爲 – morcillo

+0

@dwelch我知道這一點。但是我知道我想應用這個特定的系統永遠不會輸出高於3且低於-4的結果,這就是我爲什麼要截斷的原因。我知道結果的數字可以用8位數字表示,三位在點之前,5位在點之後。我也有兩個系統來測試。其中一個將永遠不會乘以兩個負面投入,而另一個會。我知道我的一個系統會以這種方式工作。另一個不會。這就是爲什麼我想解決這個問題。我很久以前測試了截斷,它爲第一個系統工作(工作「完美」)。 – morcillo

回答

2

你的中間結果是錯誤的,所以截斷沒有按預期工作。此外,如果中間結果的四個最高位在您的格式中相同,則截斷僅在沒有溢出的情況下才可能發生。 您應該使用簽名數據類型來執行乘法操作。

即使你的第二個例子是錯誤的。中間二進制結果010101.0110000000表示十進制數21.375這不是-0.875和3所以產品,讓我們用手工做乘法:

a  *  b  = -0.875 * 3 = -2.625 
111.00100 * 011.00000 
--------------------- 
      . 00000000 // further lines containing only zeros have been omitted 
+   .01100000 
+  011.00000 
+  0110.0000 
+ 110100.000   // add -(2^2) * b ! 
= 111101.0110000000 = -2.625 (intermediate result) 
=  101.01100  = -2.625 after truncation 

您必須添加的b二進制補碼的最後部分總和,因爲a最高位中的'1'表示值 - (2^2)= -4。這裏沒有溢出的截斷是可能的,因爲中間結果的4個最高位是相等的。

而現在的第三示例

a   b  = -1.9375 * -0.875 = 1.6953125 
110.00010 * 111.00100 
--------------------- 
      . 00000000 // further lines containing only zeros have been omitted 
+ 111111.111100100 // sign-extended partial-sum 
+ 111110.0100  // sign-extended partial-sum 
+ 000011.100   // add -4 * b 
= 000001.101100100 = 1.6953125 (intermediate result) 
~  001.10110  = 1.6875 after truncation 

b作爲是有符號數,人們總是符號擴展部分和所述中間結果的寬度。當然,這也是在第二個例子的計算中完成的,但是這並沒有什麼不同。

+0

好的。我知道我的思維方式有很大的可能性。 BUUUT,我測試了許多值(包括正值,負值和負值)。當這兩個數字都是負數時,我只遇到了問題,其他所有測試都起作用(截斷後)。我明白你告訴我的是什麼,但在我的情況下,所有乘法在截斷後都是正確的(除了兩個都是負數),我知道其中一個操作數將從0變化到1,而另一個不會高於3。我的測試工作。這是巧合嗎?我真的很喜歡你的答案。 – morcillo

+0

感謝您花時間回答我的問題。 – morcillo

+0

@morcillo你喜歡我的回答,但沒有投票贊成嗎? –