首页 文章

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

提问于
浏览
1

我有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 回答

  • 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;
    

    顺便说一句,此操作称为 clipping .

    如果你想要 truncate ,那么这个过程应该写成:

    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;
    
  • 0

    正如@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

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

相关问题