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.

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • 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. –  May 26 '15 at 09: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 . –  May 26 '15 at 10:06
  • If you subtract a big number (say, 7) from a smaller one (say, 2), what result do you expect? –  May 26 '15 at 10:08
  • 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) ] ] – –  May 26 '15 at 10:10
  • 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. –  May 26 '15 at 10:17
  • only 0.2 is the float point which will be represented as fixed point. other signals are simple std_logic-vector. So according to your comment , I should also use fixed point representation for other signals. So all arithematic operations has to be done in fixed point. ? –  May 26 '15 at 10:26
  • 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. –  May 26 '15 at 10:54
  • "0x0010 (which is 4, not 2)" ... it's 16 of course, still wrong. Just goes to show how easily it is to make mistakes! –  May 26 '15 at 11:20
  • yes , sorry for that, actually I want to write 0x0002 for 2. –  May 26 '15 at 16:24
  • I modified the question. Please have a look. thanks –  May 26 '15 at 16:49
  • The revised question gets the same answer. –  May 26 '15 at 21:30
  • But sorry, I don't get your answer. as I am not converting anything to fixed point or so. My code will take fixed point input and other signals:. So input is 0x00000033 (fixed point ) and other signed signals. According to the above example , (fixed_point * (FFFFFFFA)) will yield negative value. so that's what my point to convert it in positive . –  May 26 '15 at 21:48
  • Detailed code is now posted. –  May 27 '15 at 00:44

2 Answers2

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.

Morten Zilmer
  • 15,586
  • 3
  • 30
  • 49
  • I have tried now that above procedure, but my waveform is still showing me negative output. –  May 26 '15 at 09:16
  • @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 ? – Morten Zilmer May 26 '15 at 09:24
  • 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. –  May 26 '15 at 10:05
  • or you can say for -6 that 2+ [0.2 * (4-10) ] = 0.8 . In vhdl : [0x0010 + (0x00000033 * ( 0x0004 - 0x000A) ] ] –  May 26 '15 at 10:09
  • So from the examples it looks like you should make signed arithmetic, thus use the `signed` type instead of `unsigned`. – Morten Zilmer May 26 '15 at 10:16
  • modified, but still same output on wavefrom :( –  May 26 '15 at 10:24
  • It will be easier for everyone to understand the exact question if you update the question with your latest findings and comments. The problem sounds like more relate to general arithmetic and decimal point, than to VHDL. – Morten Zilmer May 26 '15 at 10:59
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?

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26
  • 1
    Removed Verilog tag, since only VHDL related. – Morten Zilmer May 26 '15 at 08:41
  • 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 . –  May 26 '15 at 09:09
  • 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. – Yann Vernier May 28 '15 at 09:08