如何在vhdl中将大整数转换为较小的整数?

时间:2017-04-09 01:36:49

标签: vhdl

我有VHDL代码,我试图将像素值相乘。我有以下实体:

entity xGradient is

port(
    clk : in std_logic;
    x11, x12, x13, x21, x22, x23, x31, x32, x33 : in integer range 0 to 255;
    gradientInX : out integer range 0 to 255
);

end xGradient;

我对这些进行了以下操作:

gradientInX <= x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

您可能会注意到的问题是,从操作中获取的值超出了输出整数可能的值范围。发生这种情况时,我的模拟会崩溃。我不知道我正在做什么的正确的词,因此似乎无法弄清楚如何解决这个问题,它让我发疯。我基本上只想截断,或减小输出的大小,以确保它适合gradientInX输出端口。我尝试使用这样的过程块:

-- declared signals
signal gradientMem: integer;

--beginning of my architecture
begin 

SobelOperator : process(gradientMem)

begin
    gradientMem <= x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    if (gradientMem > 255) then
        gradientMem <= 255;
    elsif (gradientMem < 0) then
        gradientMem <= 0;
    end if;

end process SobelOperator;

然后将gradientMem分配给gradientInX,但由于某种原因它并不起作用。真的很感激任何帮助。注意:我还没有包含所有VHDL代码,因为我认为它会不必要地长。我得到的错误信息是来自操作的信号结果值超出范围(因为结果值为负且输出的范围仅为0到255)。

马修

3 个答案:

答案 0 :(得分:1)

正如@Paebbels在评论中建议的那样,很可能gradientMem的范围不足以处理操作的输出。

注意事项:在整数运算中,中间范围(大部分)被认为是32b签名,并且在赋值中检查范围。这为合成工具提供了很多推测,并且可以产生比最佳设计大得多的设计。

为了解决这个问题,ieee.numeric_std.all用于未签名和签名的类型和操作。这给出了中间矢量长度的绝对控制。这也迫使您了解通常在RTL设计中有用的附加,减法,乘法等内容。

然而,需要注意的是,在矢量形式中,操作是成对计算的,使用两者中最长的一个作为中间向量长度。

例如:

  process
    variable i1      : integer range 0 to 15 := 15;
    variable i2      : integer range 0 to 15 := 9;
    variable i3      : integer range 0 to 15 := 11;
    variable i4      : integer range 0 to 31 := 2;
    variable iSum    : integer range 0 to 63;
    variable u1      : unsigned(3 downto 0) := to_unsigned(15,4);
    variable u2      : unsigned(3 downto 0) := to_unsigned(9,4);
    variable u3      : unsigned(3 downto 0) := to_unsigned(11,4);
    variable u4      : unsigned(5 downto 0) := to_unsigned(2,6);
    variable uSum    : unsigned(5 downto 0);
  begin
    iSum := i1 + i2 + i3 + i4;
    uSum := u1 + u2 + u3 + u4;
    write(output, "int: " & to_string(iSum) & lf &
                  "us : " & to_string(to_integer(uSum)) & lf);
    wait;
  end process;

给出:

  

#int:37
  #us:5

使用括号解决问题:

uSum := (u1 + (u2 + (u3 + u4)));

答案 1 :(得分:1)

这是少数应该使用变量而不是信号的情况之一。

SobelOperator : process(x11, x21, x31, x13, x23, x33)
    variable gradientMem : integer;
begin
    gradientMem := x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    if (gradientMem > 255) then
        gradientMem := 255;
    elsif (gradientMem < 0) then
        gradientMem := 0;
    end if;
    gradientInX <= gradientMem;
end process SobelOperator;

顺便说一句,此操作称为剪辑

如果您想要截断,则该过程应该写成:

SobelOperator : process(x11, x21, x31, x13, x23, x33)
    variable gradientMem : integer;
begin
    gradientMem := x11 + 2*x21 + x31 - x13 - 2*x23 - x33;

    gradientInX <= gradientMem mod 256;
end process SobelOperator;

答案 2 :(得分:0)

错误位于流程SobelOperator : process(gradientMem)的敏感度列表中。这里必须是影响结果信号的信号,换句话说,这是一个过程敏感的信号列表。所以应该有x11x21x31x13x23x33,例如SobelOperator : process(x11, x21, x31, x13, x23, x33)