【问题标题】:Arithmetic operation of Fixed point with Std_logic_vector in VHDLVHDL中带有Std_logic_vector的定点算术运算
【发布时间】:2015-05-26 08:01:29
【问题描述】:

我正在用 VHDL 编写代码,用于信号的算术运算。我声明信号如下:

    signal x : std_logic_vector (7 downto 0); 
    signal y: std_logic_vector (7 downto 0); 
    signal z: std_logic_vector (  7 downto 0);
    z<= x-y ;

详细说明:

  library ieee;
  use ieee.std_logic_1164.all;
  use ieee.numeric_std.all;
  USE ieee.std_logic_arith.conv_std_logic_vector;   
  library ieee_proposed;
  use ieee_proposed.fixed_pkg.all;
  signal heat0,heat1,heat2 : std_logic_vector(31 downto 0); 
  signal Data_In, M_AXIS_TDATA Fixed_input_tdata: std_logic_vector (31 downto 0);
  shared variable float,  h0,h1,h2,fixed1,fixed2,fixed3,fixed_shift :ufixed (23 downto -8);
  shared variable  fixed_64: ufixed (31 downto -32); 
 float := to_ufixed(unsigned (Fixed_input_tdata), 23,-8); 
 h2 :=  to_ufixed(unsigned(Data_In),23,-8); 
 heat1 <= Data_in; 
 h1 :=  to_ufixed(unsigned(heat1),23,-8);  
 heat0<= heat1;
 h0 :=  to_ufixed(unsigned(heat0),23,-8);
 heat1_mult  := std_logic_vector(unsigned(heat1) sll 1);

 fixed_shift := to_ufixed(unsigned (heat1_mult), 23,-8); 
 fixed1 := fixed_shift+h2;   
 fixed2 := h0-fixed1;   
 fixed_64 := fixed2 *float; 
 fixed3 := h1+fixed_64;--(23 downto -8);
M_AXIS_TDATA <= std_logic_vector (fixed3); 

那么用定点对std_logiC-vector进行算术运算是正确的方法吗?

让我们举个例子,z= 0x01-0x11。这将给出负输出(0xF0):但我不想要负输出。我想将此值视为正值。我什至尝试将这些信号类型更改为无符号,但仍然无法成功。实际上我在 vhdl 中有一些复杂的数学运算,所以我只是在这里举一个例子来说明我的观点。我不想使用带符号的值。如何发送正无符号输出?

再举一个例子:如果我的输出是bf978000,它将显示为负数-1.18。我希望它是积极的,而不是消极的。

让我再举一个例子:

z= 2+ [0.2 * (4-10) ] = 0.8 。 0.8 定点格式(0x000000cd)(24 整数,8 小数格式): 0.2 是定点格式的 0x00000033。 (24 位整数,8 位小数格式) 但我得到 [0x00000002 + (0x00000033 * (0x00000004-0x0000000A) ] = FFFFFED0。(这是负数)。如何再次将该输出表示为 0.8。

【问题讨论】:

  • 强烈建议使用 numeric_std 而不是 std_logic_vector 进行算术运算。此外,如果您使用的是 Xilinx ISIM,请打开其范围检查(在“Process Properties, Advanced view”中)。如果不打开这些检查,模拟几乎毫无用处。
  • 是的,我使用了数字标准。这不是波形的情况,我也检查了终端上的输出。但这对我来说是同样的问题。
  • 如果你从一个较小的数字(比如 2)中减去一个大的数字(比如 7),你期望得到什么结果?
  • 在上面的示例中,您忘记了缩放整数。 8 小数格式中的 2 将是 0x0200 而不是 0x0010(即 4,而不是 2)。在 VHDL 中尝试之前,先在基本算术中正确使用它。
  • 不一定,但是在整数和定点相遇的地方,你必须注意缩放,即注意小数点。除非 DP 在每个数字中的相同位置,否则您不能进行加法或减法。你的数字没有一个是简单的std_logic_vector。它们是有符号的、无符号的或定点的。将它们误认为 slv 是让您感到困惑的部分原因。

标签: floating-point hex vhdl fixed-point xilinx-ise


【解决方案1】:

如果您可以直接使用z &lt;= x - y,听起来您正在使用像ieee.std_logic_unsigned 这样的Synopsys 包之一,但您可以考虑使用VHDL 标准包ieee.numeric_std,它在下面的示例中使用。

std_logic_vector 默认没有任何数字表示;它只是std_logic 的数组。 ieee.numeric_std 包中的 unsigned 类型可以表示 std_logic_vector 执行 unsigned(x). 的数字表示,因此上面使用无符号减法的表达式将是:

z <= std_logic_vector(unsigned(x) - unsigned(z));

任何欠载/溢出,如“z = 0x01-0x11”,将导致没有任何指示的回绕。

【讨论】:

  • 我已经尝试过上述程序,但我的波形仍然显示负输出。
  • @NabeelAnjum: 除了zstd_logic_vector 在像z = 0x01 - 0x11 这​​样的操作之后,就“正”值而言,你有什么值?
  • 喜欢。例如 z= 2+ [0.2 * (-6) ] = 0.8 将采用定点格式(0x000000cd)(24 整数,8 小数格式):但我得到 [0x0010 + (0x00000033 * (FFFFFFFA)] 。 . 上面例子中的 -6 给我带来了问题。
  • 或者你可以说 -6 2+ [0.2 * (4-10) ] = 0.8 。在 vhdl 中:[0x0010 + (0x00000033 * (0x0004 - 0x000A)]]
  • 所以从例子看你应该做有符号算术,因此使用signed类型而不是unsigned
【解决方案2】:

我认为您的问题需要改进。我不知道为什么它被标记为verilog,你显示的十六进制数字没有签名,而且std_logic_vector首先不是算术(添加这样的解释是用std_logic_arith或类似的,但最好使用无符号和有符号的数字标准)。因此,您的代码必须有更多内容才能使减法起作用,并且显示的负数必须来自其他东西;一个模拟器,也许?模拟器和波形查看器往往有自己的设置来解释信号。

因此,扩展您的示例以显示您正在使用的环境,并说明您实际寻求的操作。你的意思是取差值的绝对值,还是使用饱和算术?

【讨论】:

  • 删除了 Verilog 标签,因为只有 VHDL 相关。
  • 我实际上是将定点数与 std_logic_vector 操作相乘。所以你可以假设:假设 (0x00000080 * (0x00000001 - 0x00000011)) 会给我负的十六进制值。所以,结果,我会得到负输出(例如 0xFFFxxxxx)> 这不应该是这种情况。 OR > 0xbf970a3d 输出实际上是 -1.18 in float 这是不可取的。
  • 从较小的数字中减去较大的数字会产生负差。如果您想要其他任何东西,则必须决定什么,例如模运算、饱和运算或取绝对值。您的代码执行模运算(这可能不合适),您似乎将其解释为负值,而您尚未透露您真正想要什么或为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-09-30
  • 1970-01-01
  • 2014-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多