2017-08-09 103 views
0

我正在使用David bishop的定點庫在vhdl中做了一些數學計算。我需要將最終值解碼爲整數。我遵循的方法如下,我確實得到了小數部分的精確值,但小數值不正確。我還沒找到問題。在小數部分前兩位數字是錯誤的。 xx 8374.839923 xx數字總是錯的。VDHL固定解碼代碼無法正常工作

當我執行,我得到 74334.738295爲 74334.738295

內部架構, 內部過程中,我做的聲明這些變量,

variable cp : sfixed(20 downto -19); 
variable mod10 : sfixed(4 downto 0); 
variable div10 : sfixed(4 downto 0); 

variable L0 : sfixed(4 downto 0); 
variable L1 : sfixed(4 downto -4); 
variable L2 : sfixed(4 downto -8); 
variable L3 : sfixed(4 downto -12); 
variable L4 : sfixed(4 downto -16); 
variable L5 : sfixed(4 downto -20); 
variable L6 : sfixed(4 downto -24); 

variable temp_L : sfixed(19 downto 0); 
variable temp_L1 : sfixed(20 downto -4); 
variable temp_L2 : sfixed(21 downto -8); 
variable temp_L3 : sfixed(22 downto -12); 
variable temp_L4 : sfixed(23 downto -16); 
variable temp_L5 : sfixed(24 downto -20); 
variable temp_L6 : sfixed(25 downto -24); 

開始後,我需要解碼174334.738295在sfixed,因爲有時我得到負數。這個數字被另一個計算,在此未提供,如果該號碼是174334.738295(sfixed)代替然後我需要解碼此號碼,

cp  := to_sfixed(174334.738295,20,-19); 
temp_L := cp(19 downto 0); -- remove sign bit 

mod10 :=to_sfixed(10,4,0) ;     
div10 :=to_sfixed(10,4,0) ; 

L0  := temp_L mod mod10; 
temp_L1 := temp_L/div10; 
L1  := temp_L1 mod mod10; 
temp_L2 := temp_L1/div10; 
L2  := temp_L2 mod mod10; 
temp_L3 := temp_L2/div10; 
L3  := temp_L3 mod mod10; 
temp_L4 := temp_L3/div10; 
L4  := temp_L4 mod mod10;    
temp_L5 := temp_L4/div10; 
L5  := temp_L5 mod mod10; 
temp_L6 := temp_L5/div10; 
L6  := temp_L6 mod mod10; 

L6是第1位和L5是第二位。

+0

我不知道負指標是可能的。不過,我不會使用它們。 –

+0

@Oron Port請參考David Bishop的定點lib手冊! – iopertyki

+1

固定和浮點庫是開源的,並存儲在GitHub:https://github.com/fphdl/fphdl。你可以在那裏打開一個問題,並要求更詳細的幫助。您還應該將您當前的副本與最新版本進行比較。這就是將在VHDL-2017中發佈的版本。 – Paebbels

回答

1

修改您與修復DIV10,MOD10原代碼(用下劃線獨自一人出走聲明)和生產MCVE:

library ieee; 
use ieee.fixed_pkg.all; 

entity iopertyki is 
end entity; 

architecture fum of iopertyki is 
begin 
    process 
     variable cp:  sfixed(20 downto -19); 
     variable mod_10: sfixed(4 downto 0); 
     variable div_10: sfixed(4 downto 0); 
     variable mul_10: sfixed(4 downto 0); 

     variable L0:  sfixed(4 downto 0); 
     variable L1:  sfixed(4 downto -4); 
     variable L2:  sfixed(4 downto -8); 
     variable L3:  sfixed(4 downto -12); 
     variable L4:  sfixed(4 downto -16); 
     variable L5:  sfixed(4 downto -20); 
     variable L6:  sfixed(4 downto -24); 

     variable temp_L: sfixed(19 downto 0); 
     variable temp_L1: sfixed(20 downto -4); 
     variable temp_L2: sfixed(21 downto -8); 
     variable temp_L3: sfixed(22 downto -12); 
     variable temp_L4: sfixed(23 downto -16); 
     variable temp_L5: sfixed(24 downto -20); 
     variable temp_L6: sfixed(25 downto -24); 
    begin 
     cp := to_sfixed(174334.738295,20,-19); 
     report "cp = " & to_string(cp); 
     temp_L  := cp(19 downto 0); -- remove sign bit 
     report "temp_L = " & to_string(temp_L); 
     report "integer'image temp_L = " & integer'image(to_integer(temp_L)); 
     mod_10 := to_sfixed(10,4,0);     
     div_10 := to_sfixed(10,4,0); 
     mul_10 := to_sfixed(10,4,0); 

     L0   := temp_L mod mod_10; 
     temp_L1  := temp_L/div_10; 
     L1   := temp_L1 mod mod_10; 
     temp_L2  := temp_L1/div_10; 
     L2   := temp_L2 mod mod_10; 
     temp_L3  := temp_L2/div_10; 
     L3   := temp_L3 mod mod_10; 
     temp_L4  := temp_L3/div_10; 
     L4   := temp_L4 mod mod_10;    
     temp_L5  := temp_L4/div_10; 
     L5   := temp_L5 mod mod_10; 
     temp_L6  := temp_L5/div_10; 
     L6   := temp_L6 mod mod_10; 
     -- xx8374.839923 ? 
     report " result = " & integer'image(to_integer(L6)) & 
           integer'image(to_integer(L5)) & 
           integer'image(to_integer(L4)) & 
           integer'image(to_integer(L3)) & 
           integer'image(to_integer(L2)) & 
           integer'image(to_integer(L1)) & 
           integer'image(to_integer(L0)); 

     report " no round = " & integer'image(to_integer(L6(4 downto 0))) & 
           integer'image(to_integer(L5(4 downto 0))) & 
           integer'image(to_integer(L4(4 downto 0))) & 
           integer'image(to_integer(L3(4 downto 0))) & 
           integer'image(to_integer(L2(4 downto 0))) & 
           integer'image(to_integer(L1(4 downto 0))) & 
           integer'image(to_integer(L0(4 downto 0))); 
     wait; 
    end process; 
end architecture; 

由此產生的整數部分結果(你不演示如何在這樣做您的問題,用新的結果:

...得到274334.738295爲174334.738295

可以證明to_integer四捨五入負責L5爲2,而不是1:

ghdl -a --std=08 iopertyki.vhdl 
ghdl -e --std=08 iopertyki 
ghdl -r iopertyki 

iopertyki.vhdl:91:9:@0ms:(report note): cp = 000101010100011111110.1011110100000000111 
iopertyki.vhdl:93:9:@0ms:(report note): temp_L = 00101010100011111110.0 
iopertyki.vhdl:94:9:@0ms:(report note): integer'image temp_L = 174334 
iopertyki.vhdl:113:9:@0ms:(report note): result = 0274334 
iopertyki.vhdl:121:9:@0ms:(report note): no round = 0174334 

所以這一切都告訴你只使用L6的整數部分 - 所以沒有四捨五入L1。 (有關如何剪裁固定值或不固定值的提示可以在您評論的David Bishop用戶指南中使用)。

你可能會注意到,裁剪一個sfixed值會受到符號偏差的影響,並且您需要更改所有恢復的十進制數字的符號或使用帶符號的幅度(其中您的數字計算可能被固定)標誌轉發給負數的結果。幾十年來的數學可能非常麻煩。使用ghdl當在闡述和仿真

有代碼生成的三種架構爲ghdl,使用GCC後端,一個LLVM後端和剛剛在時間碼發生器的的MCode。

從上Invoking GHDL最新GHDL Documentation部爲運行命令:

run -r

奔跑/模擬設計。選項和參數與製作命令中的 相同。

  • GGC/LLVM:簡單地說,確定可執行文件的文件名並執行它。選項被忽略。您也可以直接執行 該程序。可執行文件必須位於當前目錄中。
  • mcode:設計被闡述並且仿真被啓動。因此,您必須使用分析過程中使用的相同選項。

在一個版本的MCode諸如分佈式爲Win32的-e精心命令是多餘的,且運行命令(-r)必須包括相同的選項作爲分析命令(-a)。

對於GCC/LLVM後端codegenerator版本的ghdl,elaborate(-e)命令必須與分析命令(-a)具有相同的選項。對於--std=08,將使用不同的工作庫,如果沒有單獨指定庫目錄,則會覆蓋不帶std選項或具有不同STD值的任何目標文件。

mcode版本沒有目標文件。分析的對象只存在於ghdl程序的內存中,隨後通過run(-r)命令將其分析爲仿真設計模型。

沒有指定版本或發佈用戶只能依賴ghdl文檔。

您還可以注意到ghdl-0.34已在最後一天發佈,並且有一個Win32二進制圖像(mcode)和64位二進制圖像(llvm)可用(它們的名稱包括「mingw」)。

+0

你能告訴我你使用的模擬器是什麼? – iopertyki

+0

[ghdl](https://ghdl.readthedocs.io/en/latest/Introduction.html) – user1155120

+0

如何將定點包包含到ghdl?我得到錯誤,主庫「fixed_pkg」未在庫中找到「工作」 – iopertyki

0

你的部門應該是整數部門;他們不是(定點部門)。而且我甚至都不會想象當應用於非整數(定點)參數時模運算符應該返回什麼。無論如何,這個固定點表示相當簡單,所以,如果你只是想要一個積極的定點數的整數部分的數字,你可以先將其轉換爲自然的,然後計算位數:

library ieee; 
use ieee.numeric_std.all; 
use ieee.std_logic_1164.all; 
... 
variable n: natural; 
subtype digit is natural range 0 to 9; 
type digit_vector is array(natural range <>) of digits; 
variable digits: digit_vector(5 downto 0); 
... 
n := to_integer(u_unsigned(cp(20 downto 0))); 
for i in 0 to 5 loop 
    digits(i) := n mod 10; 
    n := n/10; 
end loop; 

或者,如果你只是想打印的cp十進制表示:

use std.textio.all; 
... 
variable l: line; 
... 
write(l, to_integer(u_unsigned(cp(20 downto 0))); 
writeline(output, n); 

,或者更簡單,使用write程序從庫本身:

variable tmp: sfixed(20 downto 0); 
... 
tmp := cp(20 downto 0); 
write(l, tmp); 
writeline(output, l); 
+0

我需要爲一個固定變量執行此操作。 – iopertyki

+0

我明白了,在我的代碼中'cp'仍然是'sfixed'。 –

+0

@ Renaud Pacalet to_unsigned不能與sifxed一起使用嗎?錯誤(10381):索引名返回一個值與其類型不匹配的「UNRESOLVED_ufixed」,目標表達式的類型 – iopertyki