使用此代码可能会遇到什么问题?我认为如果加法的结果大于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;
答案 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被报告为算术错误。 (注意:至少有一个模拟器以溢出检查作为默认设置运行!只是愚蠢......)
作为设计者,您可以确定溢出的正确语义是什么:
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;”)。