VHDL:加法和减法的问题

VHDL:加法和减法的问题,vhdl,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_vect

使用此代码可能会遇到什么问题?我在想,如果加法的结果大于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;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.std_logic_unsigned.all;
使用ieee.std_logic_arith.all;
使用ieee.numeric_std.all;
实体测试是
端口(输入:标准逻辑向量(14至0);
sel:输出布尔值;
输出:输出标准逻辑向量(14到0);
结束试验;
测试的体系结构测试是
第一个常数:整数:=1050;
常数秒:整数:=33611;
开始
输出按位执行加法运算符“+”和“-”-std_logic_vector是一种数组类型,其基本元素类型为std_ulogic,将“位”表示为包含元值的多级值系统。它们的结果以两个操作数中较长的一个为界。(它们不会溢出)

请参阅包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;
它使用标准逻辑算术中的无符号加法:

  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;
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;
这使用了标准逻辑运算中的无符号加号:

  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;
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_逻辑_向量是一种无符号表示,没有负数的概念,它是一包位。如果要表示有符号的操作,应使用package numeric_std,并对关系运算符使用类型转换或操作数,并添加类型
有符号的
运算符

也就是说,使用Synopsys的std_logic_unsigned软件包的std_logic_vector或IEEE numeric_std软件包的unsigned软件包,您将得到相同的答案

(您显示的代码不需要最后两个use子句)


您不需要use子句使包numeric_std或std_logic_arith可见的原因是,您没有使用有符号或无符号类型,并且包std_logic_unsigned为std_logic_arith有自己的use子句,并且在设计规范中使用的所有内容都有声明(“+”、“-”和“)“您面临的主要问题是设计意图没有传达,因此无法区分正确结果和错误结果-从这个意义上说,无论它做什么都必须是正确的

我在一个方面与David的观点不同:他说“std_logic_vector是一种无符号表示法”,我认为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;
并专门使用标准库:

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));
(如果不允许更改端口类型,可以在内部使用无符号信号,并在它们与端口之间进行类型转换。)

现在关于表达式,它们可能会溢出(在“second”的情况下,显然会溢出!)

在模拟中,这些溢出应报告为算术错误。(注意:至少有一个模拟器运行时溢出检查为默认设置!只是哑…)

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

  • 它们代表错误。在启用溢出检查的情况下进行模拟,检测并修复错误
  • 它们是允许的,例如负数表示大正数。请在代码中表示,例如作为
    输出