VHDL:添加和减去的问题

时间:2014-11-11 23:23:40

标签: vhdl

使用此代码可能会遇到什么问题?我认为如果加法的结果大于15位可以表示的结果(32767),或者如果我在减法中得到负数,则可能存在问题。

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;

entity test is
    port(   input:  in std_logic_vector(14 downto 0);
            sel : out boolean;
            output: out std_logic_vector(14 downto 0));
end test;


architecture test of test is

constant first : integer := 1050;
constant second : integer := 33611;

begin

 output <= input - first;
 output <= input + second;
 sel <= input < first;

end test;

2 个答案:

答案 0 :(得分:2)

你遇到的主要问题是没有传达设计意图,因此不可能区分正确的结果和不正确的结果 - 从这个意义上讲,无论它做什么都必须正确!

我在一个方面不同于大卫的观点:他说'std_logic_vector是一个无符号的代表&#34;我建议std_logic_vector既没有签名也没有签名;它只是一个小包。如果它碰巧遵循未签名的规则,那就是您所包含的一组库的意外。

相反,我会删除非标准库:

use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

并专门使用标准库:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

然后 - 如果输入和输出端口用于表示无符号数字,那么最好的办法是这样说......

port(   input  : in unsigned(14 downto 0);
        sel    : out boolean;
        output : out unsigned(14 downto 0));

(如果不允许更改端口类型,可以在内部使用无符号信号,并在它们和端口之间键入转换。)

现在关于表达式,它们可能溢出(在&#34;第二个&#34;显然会!)的情况下。

在模拟中,这些溢出的OUGHT被报告为算术错误。 (注意:至少有一个模拟器以溢出检查作为默认设置运行!只是愚蠢......)

作为设计者,您可以确定溢出的正确语义是什么:

  • 他们代表错误。在启用溢出检查的情况下进行模拟,检测并修复错误。
  • 允许使用,例如负数表示大的正数。在代码中表达这一点,例如as output <= (input - first) mod 2**output'length;现在,任何阅读代码的人都知道允许溢出,并且只是包装。
  • 溢出应该饱和到正极限或负极限。通过写output <= saturate(input - first);来表明这一点我将把Saturate函数写为练习...

答案 1 :(得分:0)

添加运算符“+”和“ - ”按位执行 - std_logic_vector是一种数组类型,其基本元素类型为std_ulogic,它将'bits'表示为包含元值的多级值系统。他们的结果受到两个操作数中较长时间的限制。 (他们没有溢出)。

请参阅包std_logic_unsigned的来源:

function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
        -- pragma label_applies_to plus
        constant length: INTEGER := maximum(L'length, R'length);
        variable result  : STD_LOGIC_VECTOR (length-1 downto 0);
    begin
        result  := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus
        return   std_logic_vector(result);
    end;

使用std_logic_arith中的unsigned add:

  function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is
    -- pragma label_applies_to plus
    -- synopsys subpgm_id 236
    constant length: INTEGER := max(L'length, R'length);
    begin
    return unsigned_plus(CONV_UNSIGNED(L, length),
                 CONV_UNSIGNED(R, length)); -- pragma label plus
    end;

这使用了std_logic_arith中的unsigned_plus:

function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is
variable carry: STD_ULOGIC;
variable BV, sum: UNSIGNED (A'left downto 0);

-- pragma map_to_operator ADD_UNS_OP
-- pragma type_function LEFT_UNSIGNED_ARG
    -- pragma return_port_name Z

begin
if (A(A'left) = 'X' or B(B'left) = 'X') then
        sum := (others => 'X');
        return(sum);
end if;
carry := '0';
BV := B;

for i in 0 to A'left loop
    sum(i) := A(i) xor BV(i) xor carry;
    carry := (A(i) and BV(i)) or
        (A(i) and carry) or
        (carry and BV(i));
end loop;
return sum;
end;

std_logic_vector是一个无符号表示,没有负数的概念,它是一个包的位。如果要表示已签名的操作,则应使用包numeric_std,并为关系类型转换或使用操作数,并添加类型为signed的运算符。

据说你可以使用带有Synopsys的std_logic_unsigned包的std_logic_vector或使用IEEE numeric_std包的unsigned来获得相同的答案。

(您显示的代码不需要您的最后两个使用条款。)

你不需要使用子句使numeric_std或std_logic_arith可见的原因是因为你没有使用有符号或无符号类型,而且std_logic_unsigned包有它自己的std_logic_arith的use子句,否则就会声明你所拥有的一切在您的设计规范中使用(“+”,“ - ”和“&lt;”)。