1

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.

13
  • 2
    Strongly advise using numeric_std instead of std_logic_vector for arithmetic. Also, if you're using Xilinx ISIM, turn its range checks on (in "Process Properties, Advanced view). Simulation is virtually useless without these checks on. Commented May 26, 2015 at 9:37
  • Yes, I used that numeric-Std. It Is not a case for waveform, I check the output on terminal too. but that is the same problem for me . Commented May 26, 2015 at 10:06
  • If you subtract a big number (say, 7) from a smaller one (say, 2), what result do you expect? Commented May 26, 2015 at 10:08
  • 1
    In your example above you are forgetting to scale the integer. 2 in your 8-fractional format would be 0x0200 not 0x0010 (which is 4, not 2). Get it right in basic arithmetic before trying it in VHDL. Commented May 26, 2015 at 10:17
  • 1
    Not necessarily, but wherever integer and fixed point meet, you MUST pay attention to scaling, i.e. keep your eye on the decimal point. You cannot add or subtract unless the DP is in the same place in each number. And NONE of your numbers are simple std_logic_vector. They are either signed, unsigned, or fixed point. Mistaking them for slv is part of what is confusing you. Commented May 26, 2015 at 10:54

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

7 Comments

I have tried now that above procedure, but my waveform is still showing me negative output.
@NabeelAnjum: What value do you except in the z as std_logic_vector after an operation like z = 0x01 - 0x11, in terms of a "positive" value ?
like. for example z= 2+ [0.2 * (-6) ] = 0.8 which will be in fixed point format ( 0x000000cd) (24 integer, 8 fractional format ): but I am getting [0x0010 + (0x00000033 * ( FFFFFFFA) ] .. -6 in the above example creates a problem for me.
or you can say for -6 that 2+ [0.2 * (4-10) ] = 0.8 . In vhdl : [0x0010 + (0x00000033 * ( 0x0004 - 0x000A) ] ]
So from the examples it looks like you should make signed arithmetic, thus use the signed type instead of unsigned.
|
1

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?

3 Comments

Removed Verilog tag, since only VHDL related.
I am actually multiplying fixed point number with std_logic_vector operations. so you can assume : Lets say (0x00000080 * (0x00000001 - 0x00000011)) will give me negative hexa- decimal value. So , as a result, i will get negative output (e.g 0xFFFxxxxx) > which should not be the case. OR > 0xbf970a3d output is actually -1.18 in float which is not desirable .
Subtracting a higher number from a lower number produces a negative difference. If you want anything else, you'll have to decide what, such as modulo arithmetic, saturated arithmetic, or taking the absolute value. Your code does modulo arithmetic (which is probably inappropriate), you seem to interpret it as a negative value, and you've yet to reveal what you actually want, or why.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.