Arithmetic operation of Fixed point with Std_logic_vector in VHDL


I am writing a code in VHDL for arithmetic operations with the signals. I declared signals as follows:

    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 ;

In Detail:

  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); 

So is it a right method to do arithmetic operations of std_logiC-vector with fixed-Point?

so lets take an example, z= 0x01-0x11. this will give negative output (0xF0): But I don't want negative output. I want to see this value as positive one. I even tried to change these signal types as unsigned, but still couldn't succeed. Actually I have some complex mathematical operations in vhdl, so I am just giving an example here to make my point understandable. I don't want to use signed values. How to send the positive unsigned output ?

Further another example: if my output is bf978000, It will be shown as negative number -1.18. I want it to be positive , not negative.

Let me take another example:

z= 2+ [0.2 * (4-10) ] = 0.8 . 0.8 in fixed point format ( 0x000000cd) (24 integer, 8 fractional format ): 0.2 is 0x00000033 in fixed point format . (24 integer, 8 fractional format ) but I am getting [0x00000002 + (0x00000033 * (0x00000004-0x0000000A) ] = FFFFFED0. (which is negative number). How to represent that output as 0.8 again.

asked on Stack Overflow May 26, 2015 by (unknown user) • edited Oct 10, 2018 by Cœur

2 Answers


If you can use z <= x - y directly, it sounds like you are use one of the Synopsys packages like ieee.std_logic_unsigned, but instead you may consider using the VHDL standard package ieee.numeric_std, which is used in the example below.

The std_logic_vector does not by default have any numeric representation; it is just an array of std_logic. The unsigned type in ieee.numeric_std package can indicate a numeric representation of a std_logic_vector doing unsigned(x). So the above expression using unsigned subtraction will be:

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

Any underrun/overrun, as with "z = 0x01-0x11", will result in wrapping without any indication.

answered on Stack Overflow May 26, 2015 by Morten Zilmer

I think your question needs some refinement. I don't know why it's tagged verilog, the hexadecimal numbers you've shown are not signed, and std_logic_vector is not arithmetic in the first place (adding such interpretation is done with std_logic_arith or similar, but it's preferable to use unsigned and signed from numeric_std). As such, there must be more to your code for the subtraction to even work, and the negative numbers shown must be from something else; a simulator, perhaps? Simulators and waveform viewers tend to have their own settings for how to interpret signals.

So, expand your sample to show the environment you're using, and explain what operation you're actually seeking. Did you mean to take the absolute value of the difference, or use saturated arithmetic?

answered on Stack Overflow May 26, 2015 by Yann Vernier

User contributions licensed under CC BY-SA 3.0