我有一个向量,我想将其除以2成2的补码。我做了以下工作,但是我不确定这是否好。如果这是正确的,有什么帮助吗?
Data_in :in std_logic_vector(15 downto 0) ;
Data_out :out std_logic_vector(15 downto 0) ;
-- these vectors in 16 it
variable tmp : integer ;
tmp := conv_integer(Data_in ) / 2 ;
Data_out <= conv_std_logic_vector (tmp,8);
-------- i will add these lines so the question would be posted
-- come on :((((((((((((((((((((
提前谢谢!
答案 0 :(得分:1)
如果这是正确的,有什么帮助吗?
这是不正确的。原因是由于在仿真期间会出现语义错误(此处未显示,该问题缺少Minimal, Complete and Verifiable example)。
Data_out <= conv_std_logic_vector (tmp,8);
右侧表达式的长度由conv_std_logic_vector(8)的第二个参数确定。在模拟目标信号的每个元素的有效值中存在一个元素时,存在要求。 (IEEE Std 1076-2008 14.7.3.4 Signal update,para 2,b))。您会收到模拟错误。
更正您的摘录中的正确长度:
Data_out <= conv_std_logic_vector (tmp, 16);
没有最小,完整和可验证的示例,就无法确定是否犯了另一个错误。
类型INTEGER具有最小范围(实际范围取决于实现,请参见5.2.3.2最小范围为–2147483647至+2147483647的预定义整数类型。没有VHDL综合工具支持更大范围的整数值。对于落入该范围内的二进制值在该范围内,使用转换为整数并除以2没什么问题。
从历史上看,您可以将班次用于两次除法。
Juergen的评论建议向右移动一位,并保留该符号,如下所示:
Data_out <= Data_in(15) & Data_in(15 downto 1);
对于数字0或更大的数字效果很好。对于较小的数字,由于二进制补码表示,它会将奇数舍入。可以通过调整班次输入,将1加上奇数个负股息来解决:
if Data_in(15) = '1' and Data_in(0) = '1' then -- odd negative numbers
Data_out <= SHIFT_RIGHT (Data_in + 1, 1);
else
Data_out <= Data_in(15) & Data_in(15 downto 1); -- SHIFT_RIGHT(Data_In, 1)
end if;
(Data_in和Data_out带有类型签名,以及IEEE软件包numeric_std中的SHIFT_RIGHT函数。)
VHDL综合工具通常可以除以2的幂。例如,使用IEEE软件包numeric_std:
Data_out <= std_logic_vector(signed(Data_in) / 2);
其中std_logic_vector值被视为二进制补码值(带符号的类型)。综合逻辑无需实际的分频器即可实现这一目标。
Xilinx Vivado(请参见UG901 Synthesis)为静态右操作数支持VHDL除以2的幂。请参阅用户指南中的表5-10 VHDL构造和支持状态。
注意:Synopsys软件包在Vivado用户指南中称为旧版软件包。自Synopsys发布其std_logic_arith,std_logic_unsigned和std_logic_signed软件包以来,综合工具已经发展为应对分区。 IEEE提供了标准的数字软件包,其中包括基于std_logic_1164的数组类型的除法运算符。
代码示例:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity signed_div_2 is
end entity;
architecture foo of signed_div_2 is
signal Data_in: signed (15 downto 0) := (1 => '0', others => '1');
signal Data_out: signed (15 downto 0);
function to_string (inp: signed) return string is
variable image_str: string (1 to inp'length);
alias input_str: signed (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) :=
character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
process
begin
report LF & HT & "Data_in = " & to_string (Data_in) &
" (" & integer'image(to_integer(Data_in)) & ")";
Data_out <= Data_in(15) & Data_in(15 downto 1);
wait for 0 ns; -- so Data_out is updated
report LF & "By right shift (wrong)" & LF & HT &
"Data_out = " & to_string (Data_out) &
" (" & integer'image(to_integer(Data_out)) & ")";
Data_out <= Data_in / 2;
wait for 0 ns; -- wait for update
report LF & "Signed divide by 2" & LF & HT &
"Data_out = " & to_string (Data_out) &
" (" & integer'image(to_integer(Data_out)) & ")";
if Data_in(15) = '1' and Data_in(0) = '1' then -- odd negative numbers
Data_out <= SHIFT_RIGHT (Data_in + 1, 1);
else
Data_out <= Data_in(15) & Data_in(15 downto 1);
end if;
wait for 0 ns; -- wait for update
report LF & "By adjusted right shift" & LF & HT &
"Data_out = " & to_string (Data_out) &
" (" & integer'image(to_integer(Data_out)) & ")";
wait; -- once only
end process;
end architecture;
已将Data_in和Data_out的类型更改为带符号,以避免大量类型转换。仿真模型可以得出:
ghdl -r signed_div_2 signed_div_2.vhdl:25:9:@0ms:(report note): Data_in = 1111111111111101 (-3) signed_div_2.vhdl:29:9:@0ms:(report note): By right shift (wrong) Data_out = 1111111111111110 (-2) signed_div_2.vhdl:34:9:@0ms:(report note): Signed divide by 2 Data_out = 1111111111111111 (-1) signed_div_2.vhdl:43:9:@0ms:(report note): By adjusted right shift Data_out = 1111111111111111 (-1)
第一份未进行调整的数据输出报告表明结果错误。
第二个Data_out报告使用带符号除以2,并且是正确的。
第三个Data_out报告使用对负负值的调整来给出正确的结果。该调整在综合中实现了一个进位树,所有正确的操作数位都是静态的,并且进位树在FPGA中得到了最佳实现。
对于无法使用除法运算符并且需要调整以将SHIFT_RIGHT函数从numeric_std移位的旧版软件包或应用程序,可以用软件包std_logic_arith中的SHR函数替换,to_integer函数将类似地被CONV_INTEGER替换,并且to_signed函数被替换通过CONV_SIGNED。
to_string函数是在-2008兼容的VHDL工具中预定义的。包含在此处以支持较旧的模拟器。