Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

How to "ARCTAN" Function in VHDL

Status
Not open for further replies.
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
 

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

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/1076/1076.2-1996/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/literature/ug/ug_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.
 

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 a moderator:

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

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.
 

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 ;
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top