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

时间:2017-08-09 16:44:04

标签: vhdl fpga fixed-point intel-fpga

我正在使用 David bishop的定点库在vhdl中进行一些数学运算。我需要将最终值解码为整数。我按照下面的方法,我得到小数部分的精细值,但十进制值不正确。我还没找到问题。在小数部分,前两位数是错误的。 xx 8374.839923 xx 数字总是错误的。

当我执行此操作时,我 2 74334.738295 1 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);

开始之后,我需要在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是第1位,L5是第2位。

2 个答案:

答案 0 :(得分: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 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用户指南中,有一个关于如何剪裁一个固定或不固定值的提示)。

您可能会注意到,剪切固定值会受到符号偏差的影响,并且您需要更改所有已恢复的十进制数字的符号或使用带符号的有符号幅度(您的数字计算可能会被修复)转发给负数的结果。几十年的数学可能很麻烦。

使用ghdl时详细说明和模拟的注意事项

ghdl有三种代码生成体系结构,使用GCC后端,LLVM后端和时间代码生成器中的mcode。

来自GHDL Documentation的最新Invoking GHDL部分,用于运行命令:

run -r

  

运行/模拟设计。选项和参数与for相同   精化命令。

     
      
  • GGC / LLVM:简单地说,确定可执行文件的文件名并执行它。选项被忽略。您也可以直接执行   该程序。可执行文件必须位于当前目录中。
  •   
  • mcode:详细阐述设计并启动模拟。因此,您必须使用分析期间使用的相同选项。
  •   

在为Win32分发的mcode版本中,-e elaborate命令是多余的,运行命令(-r)必须包含与分析命令(-a)相同的选项。

对于ghdl的GCC / LLVM后端代码生成器版本,精心设计(-e)命令必须具有与分析命令(-a)相同的选项。对于--std=08,如果未单独指定库目录,则使用不同的工作库,并且将覆盖没有std选项或具有不同STD值的任何目标文件。

mcode版本没有目标文件。分析的对象仅存在于ghdl程序的内存中,随后将run(-r)命令详细说明到仿真设计模型中。

如果没有指定版本或版本,用户只能依赖ghdl文档。

您还可以注意到ghdl-0.34已在最后一天发布,并且Win32二进制映像(mcode)和64位二进制映像(llvm)可用(它们的名称包括“mingw”)。

答案 1 :(得分: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);