大家好!
请你给我解释一件奇怪的事。numeric_std库包含一个函数"+&";,附加我插入了功能说明。
--Id:A.3函数"+"(L,R:UNSIGNED(返回UNSIGNED;--结果子类型:未忽略(最大(L’LENGTH,R‘LENGTH(-1下降到0(。--结果:添加两个可能具有不同长度的未忽略矢量
例如,我们有:
a : in unsigned(2 downto 0);
b : in unsigned(1 downto 0);
result : out unsigned(2 downto 0);
因此,如果a是";111〃;并且b是"0";01〃;结果将是";000";。原因是溢出。我的问题是,为什么库允许它,为什么它不扩展结果长度?为什么编译器不警告我溢出?是否可以在没有溢出的情况下添加值?以及我应该如何防止或发现发生溢出。
谢谢!
在硬件中,我们有递增器和递减器-;"翻转";作为它们正常操作的一部分,我们有累加器,它永远不应该翻转,我们有数学单元,需要保持操作的完全精度。
在VHDL中,当我们进行操作时,它必须产生大小精确的结果。增量器、减量器和累加器都需要保持相同大小的结果,其中需要保持运算的全部精度的数学单元需要增加大小。
因此+"只能满足其中一种需求。另一部分需要通过代码来处理。
对于numeric_std+"正如您所说,结果的大小是最大数组操作数的大小。有趣的是,在ieee.fixed_pkg中,结果的大小是最大数组操作数的1+大小。
让我们来看看这对我们的数学有何影响。
signal Co : std_logic ; -- to throw away carry out
signal Incrementer_unsigned : unsigned(3 downto 0) ;
signal Incrementer_ufixed : ufixed(3 downto 0) ;
signal Accumulator_unsigned : unsigned(3 downto 0) ;
signal Next_unsigned : unsigned(3 downto 0) ;
signal Accumulator_ufixed : ufixed(3 downto 0) ;
signal Next_ufixed : ufixed(3 downto 0) ;
signal Sum_unsigned : unsigned(8 downto 0) ;
signal A_unsigned : unsigned(7 downto 0) ;
signal B_unsigned : unsigned(7 downto 0) ;
signal Sum_ufixed : ufixed(8 downto 0) ;
signal A_ufixed : ufixed(7 downto 0) ;
signal B_ufixed : ufixed(7 downto 0) ;
. . .
process (Clk)
begin
if rising_edge(Clk) then
-- Incrementer / Decrementer with unsigned or ufixed. Result same size
Incrementer_unsigned <= Incrementer_unsigned + 1 ;
(Co, Incrementer_ufixed) <= Incrementer_ufixed + 1 ;
-- Accumulator with unsigned or ufixed. Result same size
Accumulate_unsigned <= Accumulate_unsigned + Next_unsigned ;
(Co, Accumulate_ufixed) <= Accumulate_unfixed + Next_ufixed ;
-- math unit with full precision. Result size increases
Sum_unsigned <= ('0' & A_unsigned) + ('0' & B_unsigned) ;
Sum_ufixed <= A_ufixed + B_ufixed ;
end if ;
end process ;
因此,对于numeric_std,如果我们为增量器抛出警告,我们会得到许多假阳性警告,并最终忽略所有警告——这将是一个错误。
对于numeric_std,大小调整规则适用于增量器和累加器。结果的大小是预期的。对于Sum_unsigned,我们必须放大一个参数(如果它们大小相同(,我选择了放大两个参数。有一个调整大小的功能,我选择不使用。
对于fixed_pkg,对于增量器和累加器,我们不得不通过使用左侧的聚合来缩小结果以删除进位(此代码为VHDL-2008(。还有一个调整大小的功能可以处理这个问题。对于Sum_ufixed,结果的大小与我们的应用程序相匹配。
这表明,无论您选择哪种规则,编写代码的人都必须做一些事情
对于Sum_ufixed,如果我们有,结果会更加令人兴奋
signal Sum_ufixed10 : ufixed(9 downto 0) ;
. . .
Sum_ufixed10 <= (A_ufixed + B_ufixed) + (C_ufixed + D_ufixed) ;
因为当您遵循规则时,关联性相同表达式的大小最终会大一点。虽然我在下面显示了括号,但它们是一样的。
signal Sum_ufixed11 : ufixed(10 downto 0) ;
. . .
Sum_ufixed11 <= ((A_ufixed + B_ufixed) + C_ufixed) + D_ufixed ;
还要注意,两个包都支持"+"[insigned/ufixed,natural]返回unsigned/uixed,但是,natural参数不影响大小调整。我认为0和1使用起来很简单,但必须仔细检查其他值。如果整数被截断,会有一个警告,但在我看来,它可能应该是一个失败(这与数组值的情况一致(。这当然可以在IEEE工作组中进行讨论(参见http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome)。
你是对的,关于使用这个运算符的警告会很有帮助。但是,由开发人员决定他们是否需要一个滚动的添加操作,或者一个和溢出会导致不良行为的添加操作。
执行加法时,如果不希望出现溢出,则结果需要比最长的操作数长1位。然后,您可以通过查看最高有效位是否设置为"1"来检查溢出。