我有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)。
马修
答案 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)
的敏感度列表中。这里必须是影响结果信号的信号,换句话说,这是一个过程敏感的信号列表。所以应该有x11
,x21
,x31
,x13
,x23
和x33
,例如SobelOperator : process(x11, x21, x31, x13, x23, x33)