VDHL固定解码代码无法正常工作

问题描述:

我正在使用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

修改您与修复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

你的部门应该是整数部门;他们不是(定点部门)。而且我甚至都不会想象当应用于非整数(定点)参数时模运算符应该返回什么。无论如何,这个固定点表示相当简单,所以,如果你只是想要一个积极的定点数的整数部分的数字,你可以先将其转换为自然的,然后计算位数:

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