VHDL sfixed解码代码不能正常工作
VDHL sfixed decoding code does not work properly
我正在使用 David Bishop 的定点库 在 vhdl 中做一些数学运算。我需要将最终值解码为整数。我遵循的方法如下,我确实得到了小数部分的精细值,但小数值不正确。我还找不到问题。小数部分第一个两位数字是错误的。 xx8374.839923 xx 数字总是错的。
当我执行此操作时,我得到 274334.738295 for 174334.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);
开始后,我需要在 sfixed 中解码 174334.738295,因为有时我会得到负数。这个数字将被另一个计算所取代,这里没有提供,如果那个数字是 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 是第一位,L5 是第二位
你的除法应该是整数除法;他们不是(定点划分)。而且我什至无法想象模数运算符在应用于非整数(定点)参数时应该 return 是什么。不管怎样,这个定点表示很简单,所以,如果你只想要正定点数的整数部分的数字,你可以先将其转换为自然数,然后计算数字:
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);
修改您的原始代码,修复 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;
这会产生整数部分结果(你没有在你的问题中展示你是如何做到的,新的结果:
...get 274334.738295 for 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 或 ufixed 值的提示)。
您可能会注意到,剪裁 sfixed 值会受到符号偏差的影响,并且您需要更改所有恢复的十进制数字的符号或使用带符号的幅度(您的数字计算可能不固定)符号转发到负数的结果。几十年后的数学会很麻烦。
使用ghdl时的细化和模拟注意事项
ghdl 的代码生成有三种架构,分别使用 GCC 后端、LLVM 后端和 mcode 即时代码生成器。
来自 运行 命令的最新 GHDL Documentation section on Invoking GHDL:
Runs/simulates a design. The options and arguments are the same as for
the elaboration command.
- GGC/LLVM: simply, the filename of the executable is determined and it is executed. Options are ignored. You may also directly execute
the program. The executable must be in the current directory.
- mcode: the design is elaborated and the simulation is launched. As a consequence, you must use the same options used during analysis.
在诸如为 Win32 分发的 mcode 版本中,-e 详细命令是多余的,运行 命令 (-r) 必须包含与分析命令 (-a) 相同的选项。
对于 GCC/LLVM 后端代码生成器版本的 ghdl,细化 (-e) 命令必须具有与分析命令 (-a) 相同的选项。对于 --std=08
,使用了不同的工作库,如果没有单独指定库目录,则不使用 std 选项或使用不同的 STD 值生成的任何目标文件都将被覆盖。
mcode 版本没有目标文件。分析的对象仅存在于 ghdl 程序的内存中,随后使用 运行 (-r) 命令将其详细化为模拟设计模型。
不指定版本或发布 ghdl 用户只能依赖 ghdl 文档。
您还可以注意到,ghdl-0.34 已在最后一天发布,并且提供了 Win32 二进制映像 (mcode) 和 64 位二进制映像 (llvm)(它们的名称包括 "mingw") .
我正在使用 David Bishop 的定点库 在 vhdl 中做一些数学运算。我需要将最终值解码为整数。我遵循的方法如下,我确实得到了小数部分的精细值,但小数值不正确。我还找不到问题。小数部分第一个两位数字是错误的。 xx8374.839923 xx 数字总是错的。
当我执行此操作时,我得到 274334.738295 for 174334.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);
开始后,我需要在 sfixed 中解码 174334.738295,因为有时我会得到负数。这个数字将被另一个计算所取代,这里没有提供,如果那个数字是 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 是第一位,L5 是第二位
你的除法应该是整数除法;他们不是(定点划分)。而且我什至无法想象模数运算符在应用于非整数(定点)参数时应该 return 是什么。不管怎样,这个定点表示很简单,所以,如果你只想要正定点数的整数部分的数字,你可以先将其转换为自然数,然后计算数字:
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);
修改您的原始代码,修复 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;
这会产生整数部分结果(你没有在你的问题中展示你是如何做到的,新的结果:
...get 274334.738295 for 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 或 ufixed 值的提示)。
您可能会注意到,剪裁 sfixed 值会受到符号偏差的影响,并且您需要更改所有恢复的十进制数字的符号或使用带符号的幅度(您的数字计算可能不固定)符号转发到负数的结果。几十年后的数学会很麻烦。
使用ghdl时的细化和模拟注意事项
ghdl 的代码生成有三种架构,分别使用 GCC 后端、LLVM 后端和 mcode 即时代码生成器。
来自 运行 命令的最新 GHDL Documentation section on Invoking GHDL:
Runs/simulates a design. The options and arguments are the same as for the elaboration command.
- GGC/LLVM: simply, the filename of the executable is determined and it is executed. Options are ignored. You may also directly execute the program. The executable must be in the current directory.
- mcode: the design is elaborated and the simulation is launched. As a consequence, you must use the same options used during analysis.
在诸如为 Win32 分发的 mcode 版本中,-e 详细命令是多余的,运行 命令 (-r) 必须包含与分析命令 (-a) 相同的选项。
对于 GCC/LLVM 后端代码生成器版本的 ghdl,细化 (-e) 命令必须具有与分析命令 (-a) 相同的选项。对于 --std=08
,使用了不同的工作库,如果没有单独指定库目录,则不使用 std 选项或使用不同的 STD 值生成的任何目标文件都将被覆盖。
mcode 版本没有目标文件。分析的对象仅存在于 ghdl 程序的内存中,随后使用 运行 (-r) 命令将其详细化为模拟设计模型。
不指定版本或发布 ghdl 用户只能依赖 ghdl 文档。
您还可以注意到,ghdl-0.34 已在最后一天发布,并且提供了 Win32 二进制映像 (mcode) 和 64 位二进制映像 (llvm)(它们的名称包括 "mingw") .