Jump to content
Teddy Minz

Synthetizable FFT function in SystemC

Recommended Posts

Hi everyone,

As part of my job I try to implement a FFT function in my ZedBoard. I found some example including one in the SystemC folder unfortunately not synthesizable. Furthermore, I use a free version of Vivado HLS  and this tool is very restrictive (few things are synthesizable). So, I will going to have to code my own version of this function (8k/16k/32k FFT). For doing this, I started by cut the FFT's mathematical formula and try to code a exponential function. I realized I can't use the "math.h" library and then I have to code all with only logic gates. At this level, I prefer to code directly in VHDL. Does anyone have a experience with this synthesis tool and can give me a simpler way to achieve my goal ? Maybe I see the problem of the wrong angle.

Best regards

Share this post


Link to post
Share on other sites

You paint a very bleak and incorrect picture of the HLS tool. I will suggest that you need to get some training on its use. Xilinx have many examples and their documentation is quite good. Document UG902 clearly documents the HLS math library which supports all manner of synthesizable operations. For instance:

  • Trigonometric Functions: acos, atan, cospi, acospi, atan2, sin, asin, atan2pi, sincos, asinpi, cos, sinpi, tan, tanpi

  • Hyperbolic Functions: acosh, asinh, cosh, atanh, sinh, tanh

  • Exponential Functions: exp, exp10, exp2, expm1, frexp, idexp, modf

  • Logarithmic Functions: ilogb, log, log10, log1p

  • Power Functions: cbrt, hypot, pow, rsqrt, sqrt

  • Error Functions: erf, erfc

  • Gamma Functions: lgamma, lgamma_r, tgamma

  • Rounding Functions: ceil, floor, llrint, llround, lrint, lround, nearbyint, rint, round, trunc

and that's only a few. 

Perhaps your grasp of C++ and what can or cannot be synthesized is limited. For instance, dynamically allocated memory is forbidden because it is not reasonable to expect silicon to grow new logic during operation.

Please read the fine manual (RTFM).

 

Share this post


Link to post
Share on other sites

Thanks for your answer. Sorry for my question maybe evident.

Effectively, I begin with SystemC and I am not yet very comfortable with the HLS tools.

Nevertheless, is my approach good? I want to say, Is cut the FFT's mathematical formula will allow me to implement it ? Is the simpler way to do this ? The goal is to code a FFT with SystemC and not to use the logicore provided by Xilinx. I've see a fft's library but it need Xilinx's Logicore.

Share this post


Link to post
Share on other sites

I agree with @Roman Popov on the choice of inputs to the HLS tool. The sweet spot for Vivado_HLS is C++. Much simpler to code for most folks.

That said, it can be done.

Why wouldn't you want to use Xilinx' Logicore though? One of the best ways of raising the level of abstraction (which is what using C++ or SystemC do) is to reuse somebody else's effort. Tested and probably fairly optimized. Otherwise, you are effectively reinventing the wheel.

 

Share this post


Link to post
Share on other sites

I didn't use Xilinx's LogiCore because I want to compare the execution time of a VHDL design generated from SystemC-encoded FFT block with the execution time of a FFT block on CPU and precisely with a design who use Xilinx's IP. The objective isn't to have high accuracy but just an order of magnitude between this 3 methods. At the base I didn't want to reinvent the wheel. I thought I could get a SystemC-encoded FFT block and compared it fairly quickly.

Excuse me, my questions are maybe silly but I really want to understand.
If I code a FFT in pure C++ shall I have problems for testing ? When I code in SystemC I can declare input/output with "sc_in" and "sc_out" and I find them when I import my IP within Vivado. How I can do that in pure C++ ? 

Share this post


Link to post
Share on other sites

If you code your FFT as a pure C++ function, Vivado HLS will generate inputs and outputs automatically from function parameters and based on INTERFACE pragmas. And you can import generated RTL into Vivado IP integrator.  Check out Xilinx documentation, and ask on Xilinx forums. 

Please also note that you can implement FFT in a various ways (with different micro-architectures), and achieve various performance vs area numbers. And HLS also requires quite a lot of learning to achieve good results.

 

Share this post


Link to post
Share on other sites

Hi everyone,

Thanks to you, I was able to advance. I have follow your advice and I succeeded to synthesize a FFT function in pure C++ with Vivado HLS.

Now, I would like to insert this function in a structure SystemC. For do this I have create a little project "multiplication" . But I think I have difficulties to understand the "SC_CTOR"... I have try to create standard constructor like in C++ but SystemC don't like my constructor ^^

module.cpp

#include "module.h"

using namespace std;

void MULT::multiplication(void)
{
	result = A * B;
}

void MULT::afficherResult() const
{
    cout << A << " * " << B  << " = " << result << endl;
}

MULT::MULT() : A(4), B(5), result(0)
{}

MULT::MULT(int var_a, int var_b) : A(var_a), B(var_b), result(0)
{}

module.h

#include "systemc.h"
#include <iostream>

SC_MODULE(MULT)
{
public:

	// Constructeur
	MULT(int var_a, int var_b);
	MULT();
	//SC_CTOR(MULT);

    void multiplication(void);
    void afficherResult() const;


private:

	int A, B, result;
};

main.cpp

#include "module.h"

int sc_main(int argc, char* argv[])
{
	MULT mult1;

	mult1.multiplication();

	// Print result
	mult1.afficherResult();

	return 0;
}

With this code I have the following error :
Error: (E533) module name stack is empty: did you forget to add a sc_module_name parameter to your module constructor?

Why this code work if I declare a classic  C++ class but it doesn't with a SC_MODULE? With SystemC we cannot create constructor like that ?

Best regards

Share this post


Link to post
Share on other sites
55 minutes ago, Teddy Minz said:

Why this code work if I declare a classic  C++ class but it doesn't with a SC_MODULE? In SystemC we cannot create constructor like that ?

From SystemC standard:

Quote

5.2.3 Constraints on usage

...
Every class derived (directly or indirectly) from class sc_module shall have at least one constructor. Every
such constructor shall have one and only one parameter of class sc_module_name but may have further
parameters of classes other than sc_module_name. That parameter is not required to be the first parameter
of the constructor.

SystemC requires that you add sc_module_name as a parameter to module constructors, like this:

MULT(sc_module_name, int var_a, int var_b);
MULT(sc_module_name);

This is a hack that allows SystemC kernel to track lifetime of constructor.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×