+ Post New Thread
Results 1 to 8 of 8
  1. #1
    Newbie level 4
    Points: 150, Level: 1

    Join Date
    Sep 2017
    Posts
    7
    Helped
    0 / 0
    Points
    150
    Level
    1

    How to "ARCTAN" Function in VHDL

    I am a student and doing my final project. I need to find θ = atan (Y/X) in VHDL.
    I found a link https://standards.ieee.org/downloads...math_real.vhdl
    in this they give different Math functions. Can any one tell me how can I write a code to find the phase value θ.

    •   Alt13th March 2018, 10:33

      advertising

        
       

  2. #2
    Super Moderator
    Points: 60,133, Level: 59
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    12,292
    Helped
    2845 / 2845
    Points
    60,133
    Level
    59

    Re: How to "ARCTAN" Function in VHDL

    Hi,

    I don´t know the VHDL solution.

    Often with atan one like to get the direction of a vector. 0...360°.
    But atan repeats every 180°. You may need additional logic to get full 360° information.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  3. #3
    Advanced Member level 5
    Points: 36,062, Level: 46
    Achievements:
    7 years registered

    Join Date
    Jun 2010
    Posts
    6,589
    Helped
    1924 / 1924
    Points
    36,062
    Level
    46

    Re: How to "ARCTAN" Function in VHDL

    That package you posted is part of the VHDL standard, but it is not synthesisable (ie, you cannot use it on a chip). You can use it to calculate constants/generics in your VHDL design at elaboration time.
    For trigonometric functions, most people look into using a CORDIC function, or build a look up table (you can use math_real to calculate this).



    •   Alt13th March 2018, 11:03

      advertising

        
       

  4. #4
    Full Member level 1
    Points: 775, Level: 6

    Join Date
    Apr 2017
    Posts
    114
    Helped
    24 / 24
    Points
    775
    Level
    6

    Re: How to "ARCTAN" Function in VHDL

    Quote Originally Posted by Krishna_k View Post
    I am a student and doing my final project. I need to find θ = atan (Y/X) in VHDL.
    I found a link https://standards.ieee.org/downloads...math_real.vhdl
    in this they give different Math functions. Can any one tell me how can I write a code to find the phase value θ.
    You have to write your own 'code' to calculate atan(x) value. Another possibility is to use vendor specific IP core:
    https://www.altera.com/en_US/pdfs/li...altfp_mfug.pdf
    You may want to convert signed/unsigned value into ieee754 format, calculate atan(x) and then again do a conversion from ieee754 into signed/unsigned.



  5. #5
    Newbie level 4
    Points: 150, Level: 1

    Join Date
    Sep 2017
    Posts
    7
    Helped
    0 / 0
    Points
    150
    Level
    1

    Re: How to "ARCTAN" Function in VHDL

    Thanks all for replying

    I try to apply your given solutions but problem accrue in look up table as well as in CORDIC is there is less space remaning in FPGA board. So I have to cancle that idea.
    If am no wrong I can write a code using Taylor Series which is
    arctan(x)=x-x^3/3+x^5/5-x^7/7+ ...

    I am trying to write code but error accrue here, below code is given. It says that Type of aout is incompatible with type of 'conversion to unsigned'

    Code C - [expand]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;
    use IEEE.numeric_std.all;
     
     
    entity atan_try is
      port(
        xin : in std_logic_vector(31 downto 0);
        aout : out std_logic_vector(31 downto 0)
        );
    end atan_try;
     
    architecture Behavioral of atan_try is
     
    begin
     
    aout <= unsigned (signed(xin) - ((signed(xin)*signed(xin)*signed(xin))/3) + ((signed(xin)*signed(xin)*signed(xin)*signed(xin)*signed(xin))/5) - ((signed(xin)*signed(xin)*signed(xin)*signed(xin)*signed(xin)*signed(xin)*signed(xin))/7));
     
    end Behavioral;
    Last edited by BradtheRad; 15th March 2018 at 13:03. Reason: Added code formatted window



  6. #6
    Advanced Member level 4
    Points: 7,451, Level: 20
    Achievements:
    7 years registered Created Blog entry
    dpaul's Avatar
    Join Date
    Jan 2008
    Location
    Germay
    Posts
    1,094
    Helped
    244 / 244
    Points
    7,451
    Level
    20
    Blog Entries
    1

    Re: How to "ARCTAN" Function in VHDL

    Without looking into the internal calc....
    Yes, because aout is of type std_logic_vector and you are type casting the entire calc to unsigned.

    Try this:
    aout <= std_logic_vector( unsigned (signed(xin) - ((signed(xin)*signed(xin)*signed(xin))/3) + ((signed(xin)*signed(xin)*signed(xin)*signed(xin)* signed(xin))/5) - ((signed(xin)*signed(xin)*signed(xin)*signed(xin)* signed(xin)*signed(xin)*signed(xin))/7)) );
    .....yes, I do this for fun!



  7. #7
    Super Moderator
    Points: 244,657, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    42,502
    Helped
    12950 / 12950
    Points
    244,657
    Level
    100

    Re: How to "ARCTAN" Function in VHDL

    Besides using incompatible types, there are problems with data width and result scaling. It's also inappropriate to use division operations for the Fourier parameter scaling.

    The result of a simple chained multiply of 7 32-bit numbers has a width of 7*32 bits. You'll define a fixed point interpretation of the 32 bit input number and get a 32 bit result by respective rounding and truncation.

    Division should be replaced by a multiply with fixed point constant.

    Instead of chained asynchronous multiply, you better perform sequential multiply with x² in a clocked process.



    •   Alt15th March 2018, 18:23

      advertising

        
       

  8. #8
    Advanced Member level 5
    Points: 12,360, Level: 26

    Join Date
    Aug 2011
    Posts
    2,503
    Helped
    288 / 288
    Points
    12,360
    Level
    26

    Re: How to "ARCTAN" Function in VHDL

    This is a generic synthesize tan(x) LUT I designed once.
    You can try to do the same with arctan.

    Code:
    library ieee ;
    	use ieee.std_logic_1164.all ;
    	use ieee.numeric_std.all ;
    	use ieee.math_real.all ;
    
    entity tan_lut is
    
    generic
    (
        WIDTH_FRACTION_ANGLE    : natural := 4  ; -- 4 is 1/16
        WIDTH_FRACTION_RESULT   : natural := 10 
    ) ;
    
    port 
    (
    	IN_ANGLE    :   in  std_logic_vector ( 7 + WIDTH_FRACTION_ANGLE - 1 downto 0 )  ;   -- 90 is 1011010 ( 7 bits ). A sign bit isn't needed ( the user shall exploit the tan symmetry ).	     
    	IN_CLOCK    :   in  std_logic                                                   ;																		    
    																						
    	OUT_RESULT  :   out std_logic_vector ( WIDTH_FRACTION_RESULT downto 0 )             -- One integer bit + WIDTH_FRACTION_RESULT
    ) ; 
        
    end entity tan_lut ;
    
    architecture rtl_tan_lut of tan_lut is 
    
    type type_lut_tan_real     is array ( 0 to 2 ** ( IN_ANGLE ' length ) - 1 ) of real ;
    type type_lut_tan_slv      is array ( 0 to 2 ** ( IN_ANGLE ' length ) - 1 ) of std_logic_vector ( OUT_RESULT ' range ) ;
    
    signal lut_tan_slv     		: type_lut_tan_slv ;
    signal integer_part_of_in_angle	: unsigned ( 6 downto 0 ) ;
    
    begin 
    
    	integer_part_of_in_angle <=	unsigned ( IN_ANGLE ( IN_ANGLE ' high downto IN_ANGLE ' high - 6 ) ) ; 
    
        generate_tan_lut : for index in 0 to 2 ** ( IN_ANGLE ' length ) - 1
        generate 
                    
            lut_tan_slv ( index )  <= std_logic_vector ( to_unsigned ( integer ( ( cos ( real ( index ) * ( MATH_PI / 180.0 ) / ( real ( 2 ** WIDTH_FRACTION_ANGLE ) ) ) ) * ( real ( 2 ** WIDTH_FRACTION_RESULT ) ) ) , OUT_RESULT ' length ) ) ;  
        
        end generate ;
    
        reading_from_memory : process ( IN_CLOCK ) is
        begin 
            if rising_edge ( IN_CLOCK ) then 
                OUT_RESULT <= lut_tan_slv ( to_integer ( unsigned ( IN_ANGLE ) ) ) ;
            end if ;
        end process reading_from_memory ;
    
    end architecture rtl_tan_lut ;



--[[ ]]--