2014-01-16 265 views
2

我正在设计一个设计,我相信可能会发生一些我需要处理的溢出问题。为了解决我的问题,我需要了解VHDL如何处理二进制溢出。一些示例代码如下。VHDL如何处理溢出?

signal temp : std_logic_vector (7 downto 0) := "11111111"; 
signal temp_2 : std_logic_vector (7 downto 0) := "11111111"; 
signal result : std_logic_vector (8 downto 0) := "000000000"; 

result <= temp + temp_2 ; 

很明显,这并没有调用相关的库,但它提供了我正在使用的代码的概念。我的问题是:这个二进制加法如何工作(temp + temp_2),即运行此代码后信号result会是什么?现在,编辑中出现错误,因为result是9位,期望8位。任何关于这个二进制加法如何工作的解释都会非常有帮助!

+0

您应该使用'signed'和'unsigned'而不是'std_logic_vector'进行数学运算。增加两个'std_logic_vector's不是标准的VHDL(有一个**非标准**库允许你这样做,但你不应该使用它)。 – zennehoy

回答

6

VHDL是强类型的。任何时候你分配一个信号,你需要匹配类型和宽度。

对于类型:您不能将整数类型的信号分配给std_logic_vector信号,编译器会引发错误。您必须先将整数转换为std_logic_vector。

对于宽度:您需要始终完全匹配宽度分配。在你的情况下,这个工具对你很生气,因为你将一些8位宽的东西分配给9位宽的信号结果。

为了完成你想要的,你必须使用符号扩展。你的输入是签名还是未签名?如果它们是无符号的,只需在最高有效位位置添加一个“0”。如果他们签约,你必须确定的第7位的标志,然后再扩展到这一点位的位置8.

这里是你如何能在这两种情况下做到:

temp_extended_unsigned <= '0' & temp(7 downto 0); 
temp_extended_signed <= temp(7) & temp(7 downto 0); 

temp_2_extended_unsigned <= '0' & temp_2(7 downto 0); 
temp_2_extended_signed <= temp_2(7) & temp_2(7 downto 0); 

result <= temp_extended_unsigned + temp_2_extended_unsigned; -- unsigned case 
result <= temp_extended_signed + temp_2_extended_signed; -- signed case 

注意添加1位位置的作品加法罚款,但乘法呢?您必须考虑要执行的操作...将两个8位宽的向量相乘会产生一个16位宽的结果,因此您必须在该示例中对高8位进行符号扩展。

+4

另请注意,ieee.numeric_std包中的resize()函数可以正确地扩展带符号的向量(并且在缩小它们时也保留该符号): data_out <= resize(data_in,data_out'length); (在std_logic_arith包中有符号扩展函数SXT(),但这不是标准库,也有点隐晦。) – mbschenkel

+0

这似乎最初解决了这个问题,但现在我已经意识到它已经引入了结果中有两个时钟周期的延迟。这是因为完成二进制加法和创建新的向量所花费的时间?还是还有别的东西我失踪了? – srohrer32

+0

如果通过将其置于时钟进程中来创建注册逻辑,那么会创建额外的延迟。你可以把它放在流程之外,它会创建组合逻辑。 – Russell