0
votes

How to calculate trigonometric functions: arctangent, arcsine or, at least, sine and cosine in VHDL? I have a value in IEEE 754 single-precision floating-point format (t.e. a sign, a mantissa, an exponent) (picture below). As I know, it could be implemented as a look-up table or via CORDIC algorithm. Both implementations are suitable for me. Precision up to Pi/1000 would be enought. The implementation should be synthesizable. Device - Artix-7 FPGA.

Similar code in C:

yaw   = atan2(2.0f * (q[1] * q[2] + q[0] * q[3]), q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3]);   
pitch = -asin(2.0f * (q[1] * q[3] - q[0] * q[2]));
roll  = atan2(2.0f * (q[0] * q[1] + q[2] * q[3]), q[0] * q[0] - q[1] * q[1] - q[2] * q[2] + q[3] * q[3]);
2
Trigonometric functions are not very much used in HDL except in FFT. And in that case you definitely don't want IEEE format. So before we go there it might help if you tell why you need these. This may be an X/Y problem. Also you need to tell more about what kind of precision you need. Yes, you can make a look-up table but what kind of precision do you need Pi/1000, Pi/10.000 Pi/1M ?Oldfart
@Oldfart Add advanced info to the question descriptionCaroline
Have you had a look at this frequently-cited article: Ray Andraka, "A survey of CORDIC algorithms for FPGAs," in Proc. ACM/SIGDA Conf., March 1998, pp. 191-200. (final draft online)? Side remark: While floating-point versions of CORDIC are possible, implementations typically use fixed-point arithmetic.njuffa

2 Answers

3
votes

You said "I have a value in IEEE 754 single-precision floating-point format ". I would definitely try to avoid using IEEE format numbers. It make things unnecessary complex. I don't know where that number came from or how you got that into the FPGA but the first thing to do is to try to convert that to a fixed point format.

Xilinx have off-the-shelf Cordic code for you for Arc Tan. That would make your life a lot easier. As expected it does not accept IEEE numbers but does work with "signed fractions" and precision sizes between 8 and 48 bits. You should get their Cordic IP manual and read up on what it can do. I have not seen Cordic code for asin yet.

You might need to put in some effort to control the I/O as the IP only works with streaming AXI4 interfaces.

What does surprise me is that you provide you example in C code but are talking about using VHDL. I would expect anybody familiar with C to use (System) Verilog as the langues are very, very close. Also at the risk of upsetting some people: if at all possible use System Verilog. Verilog has had several more iterations then VHDL and is much closer to how modern languages are used these days.

0
votes

I assume that the update rate of YPR is low compared to system clock.

In this case I can recommend you to have a look at Instant SoC. That is a compiler that compiles C++ code to an easy to use VHDL-file including a RISC-V processor. I have not tried to use IEEE numbers as interface. I think should calculate the quaternions with C++ also. The output that is in range +-pi can be fixed point. There is a example in Digilent vault that you can have a look at: "RISC-V on Nexys".