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.

FFT Implementation on Altera FPGA

Status
Not open for further replies.

beginner_EDA

Full Member level 4
Joined
Aug 14, 2013
Messages
191
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,296
Activity points
3,854
Hi,
I would like to implement 512 point FFT on Altera Cyclone IVE FPGA using VHDL/Verilog.

What are the option available for it?

1. How complex it is to implement? how much resources(logic gates from FPGA) normally it consumes?
2. Is there any reference design for this with which one can start?
3. Is it advisable to use Altera's IP Core for this due to complexity or one can design self with some effort? If yes, is FFT IP core of Altera free or paid. in case paid, how much does it cost round about?

Regards
 

You repeatedly ask forum members to do simple research for you. This is why your posts are starting to get ignored by the more helpful members (I'll admit I was also going to ignore this post too...).

Go to Altera's web site and search for the core. All your questions are answered in the documentation except for the price, which you will have to ask Altera's sales representatives about that or see if it shows up as a standard or purchased core in the megawizard.
 
You can evaluate the FFT core by simply instantiating the IP ("MegaFunction") in a design. It's available for test in the free web version, the design runs time limited while it's connected with a JTAG programmer.

The core is licensed with the Quartus retail version. A separate license probably doesn't make sense. There may be also special licenses bundled with evaluation boards.
 
You repeatedly ask forum members to do simple research for you. This is why your posts are starting to get ignored by the more helpful members (I'll admit I was also going to ignore this post too...).
Hi, I agree with your comment. I am newbie in this field and don't have already an overview of these stuffs. I find some answers on internet but have no confidence whether it is right one or not. or it will lead me to unnecessary direction which might not be the right approach or it is incomplete/very basic information. That's why I wanted to get confirmation/another feasible approach from forum members who have a lot of experience in this field before I start.

Go to Altera's web site and search for the core. All your questions are answered in the documentation except for the price, which you will have to ask Altera's sales representatives about that or see if it shows up as a standard or purchased core in the megawizard.
Thank you.
It means one must have to buy IP core for FFT? Self design is very complex and might not be doable?
 

I wouldn't bother designing the FFT unless it's an educational endeavor, it's typically cheaper if the company buys a core than have me design one, especially for some commodity core like an FFT. It's usually way more expensive to have me spend my time designing and verifying such a core, when I can instead work on the portions of a design that distinguish our product from the competition.

Just use the core, from what FvM states the core can be used for a limited time without a license to verify it works, but eventually you'll need to buy a license, if you want to ship your product.
 
Hi, One stupid question:
If someone buy a license for an IP Core which is valid for only 1 year. It means one can use this IP in his/her program to generate .sof/.pof file by means of Quartus-II only for 1 year (till license is valid), which is finally loaded on FPGA. But generated .sof/.pof file during license period (in this case 1 year) can be used for indefinite Period? It's not that generated .sof/.pof file during licensed period stop working on FPGA after licensed period expires and need another license to work.
 

Of course, the compiled files are not expiring.

Furthermore, the subscription license is providing continuous maintenance. Previous Quartus versions and IP can be used after license expiration.
 
Hi,
I am trying to understand the User Guide of FFT IP core from Altera.
https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_fft.pdf

I didn't understand how it interprets negative value at the input (sink_real and sink_imag) and output (source_real, source_imag, source_exp) and thus have problem in verifying in my code.

It should be 2's complement or?

P.S: and also What is sink_data and source_data signal for the case of Qsys here?
 

It's clearly 2's complement...
Capture.JPG
Refer to the first sentence of post #2. All I did was open your link (in acrobat reader plugin) and Ctrl-F, format, Return, V,V,V,V,V...(the next button) and found that section. It wasn't hidden.


SOURCE - generate data
SINK - absorb data

Using the definition of each word it's pretty clear what is meant.
 

It's clearly 2's complement...
View attachment 123936
Refer to the first sentence of post #2. All I did was open your link (in acrobat reader plugin) and Ctrl-F, format, Return, V,V,V,V,V...(the next button) and found that section. It wasn't hidden.

If this is the case, why I don't receive just 2 peaks(one +ve value and one -ve value with it's 2's complement) at imaginary axis(source_imag signal in this case) for Sine input as per Fourier Transform Theory. Instead I have several peaks at both real (source_real) and imaginary(source_imag) axis scaled with some exponents(source_exp) value(3Fh).

This is how I tried:


Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity Learning_FFT is
    port
    (
        clock           : in std_logic;
        reset           : in std_logic;
        source_valid    : out std_logic;
        source_exp      : out std_logic_vector(5 downto 0);
        source_real     : out std_logic_vector(15 downto 0);
        source_imag     : out std_logic_vector(15 downto 0)     
    );
end Learning_FFT;
 
 
architecture Behav of Learning_FFT is
 
signal reset_n_sig      : std_logic;
 
 
signal address_sig      : unsigned(8 downto 0);
signal rden_sig         : std_logic;
signal x_n_sig              : std_logic_vector(15 downto 0);
 
signal wr_en            : std_logic;
signal wr_data              : signed(15 downto 0);
 
 
 
 
signal sink_valid_sig   : std_logic;
signal sink_sop_sig     : std_logic;
signal sink_eop_sig     : std_logic;
 
 
signal sink_ready_sig   : std_logic;
signal source_error_sig : std_logic_vector(1 downto 0);
signal source_sop_sig   : std_logic;
signal source_eop_sig   : std_logic;
 
 
signal i : integer range 0 to 511:=0;
type memory_type is array (0 to 511) of integer range -1024 to 1023; 
-- Sine wave having 512 value generated in Matlab having offset of 512. But during taking input in my Program, I subtracted 512 to make 0 offset.
signal sine : memory_type :=(512,   571,    607,    607,    570,    511,    453,    417,    417,    454,    513,    572,    608,    607,    569,    510,
                              452416,    418,    455,    514,    573,    608,    606,    568,    509,    451,    416,    418,    456,    516,    574,
                                      608606,    567,    508,    450,    416,    418,    457,    517,    575,    609,    605,    566,    506,    449,    415,
                                      419458,    518,    576,    609,    605,    565,    505,    448,    415,    419,    459,    519,    577,    609,    604,
                                      564504,    447,    415,    420,    460,    521,    578,    609,    604,    563,    503,    446,    414,    420,    461,
                                      522579,    610,    603,    562,    502,    445,    414,    421,    462,    523,    579,    610,    603,    561,    500,
                                      444414,    421,    463,    524,    580,    610,    602,    560,    499,    443,    414,    422,    465,    525,    581,
                                      610602,    559,    498,    442,    413,    422,    466,    527,    582,    611,    601,    558,    497,    441,    413,
                                      423467,    528,    583,    611,    601,    557,    495,    441,    413,    423,    468,    529,    584,    611,    600,
                                      556494,    440,    413,    424,    469,    530,    585,    611,    600,    555,    493,    439,    413,    425,    470,
                                      532586,    611,    599,    553,    492,    438,    413,    425,    471,    533,    586,    611,    598,    552,    491,
                                      437412,    426,    472,    534,    587,    612,    598,    551,    489,    436,    412,    427,    473,    535,    588,
                                      612597,    550,    488,    436,    412,    427,    475,    536,    589,    612,    597,    549,    487,    435,    412,
                                      428476,    538,    590,    612,    596,    548,    486,    434,    412,    428,    477,    539,    590,    612,    595,
                                      547485,    433,    412,    429,    478,    540,    591,    612,    594,    545,    484,    433,    412,    430,    479,
                                      541592,    612,    594,    544,    482,    432,    412,    431,    480,    542,    593,    612,    593,    543,    481,
                                      431412,    431,    482,    543,    593,    612,    592,    542,    480,    430,    412,    432,    483,    545,    594,
                                      612592,    541,    479,    430,    412,    433,    484,    546,    595,    612,    591,    540,    478,    429,    412,
                                      434485,    547,    595,    612,    590,    538,    477,    428,    412,    434,    486,    548,    596,    612,    589,
                                      537475,    428,    412,    435,    487,    549,    597,    612,    589,    536,    474,    427,    412,    436,    489,
                                      550597,    612,    588,    535,    473,    426,    412,    437,    490,    551,    598,    612,    587,    534,    472,
                                      426413,    437,    491,    553,    599,    611,    586,    532,    471,    425,    413,    438,    492,    554,    599,
                                      611585,    531,    470,    424,    413,    439,    493,    555,    600,    611,    584,    530,    469,    424,    413,
                                      440495,    556,    600,    611,    584,    529,    468,    423,    413,    441,    496,    557,    601,    611,    583,
                                      528466,    423,    413,    442,    497,    558,    602,    611,    582,    526,    465,    422,    414,    443,    498,
                                      559602,    610,    581,    525,    464,    422,    414,    443,    499,    560,    603,    610,    580,    524,    463,
                                      421414,    444,    501,    561,    603,    610,    579,    523,    462,    421,    414,    445,    502,    562,    604,
                                      610578,    521,    461,    420,    414,    446,    503,    564,    604,    609,    577,    520,    460,    420,    415,
                                      447504,    565,    605,    609,    576,    519,    459,    419,    415,    448,    506,    566,    605,    609,    575,
                                      518458,    419,    415,    449,    507,    567,    605,    608,    574,    517,    457,    418,    416,    450,    508,
                                      568606,    608,    574,    515,    456,    418,    416,    451,    509,    569,    606,    608,    573,    514,    455,
                                      417416,    452,    511,    570,    607,    607,    572,    513,    454,    417,    417,    453,    512,    571,    607);
 
 
component RAM is
    PORT
    (
        address : IN STD_LOGIC_VECTOR (8 DOWNTO 0);
        clock       : IN STD_LOGIC  := '1';
        data        : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
        rden        : IN STD_LOGIC  := '1';
        wren        : IN STD_LOGIC ;
        q           : OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
    );
end component RAM;
 
component FFT_512 is
    PORT
    (
        clk : IN STD_LOGIC;
        reset_n : IN STD_LOGIC;
        inverse : IN STD_LOGIC;
        sink_valid  : IN STD_LOGIC;
        sink_sop    : IN STD_LOGIC;
        sink_eop    : IN STD_LOGIC;
        sink_real   : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
        sink_imag   : IN STD_LOGIC_VECTOR (15 DOWNTO 0);
        sink_error  : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
        source_ready    : IN STD_LOGIC;
        sink_ready  : OUT STD_LOGIC;
        source_error    : OUT STD_LOGIC_VECTOR (1 DOWNTO 0);
        source_sop  : OUT STD_LOGIC;
        source_eop  : OUT STD_LOGIC;
        source_valid    : OUT STD_LOGIC;
        source_exp  : OUT STD_LOGIC_VECTOR (5 DOWNTO 0);
        source_real : OUT STD_LOGIC_VECTOR (15 DOWNTO 0);
        source_imag : OUT STD_LOGIC_VECTOR (15 DOWNTO 0)
    );
end component FFT_512;
 
 
begin
       -- Data has been written into RAM first
    Memory_inst : RAM port map
    (
        address => std_logic_vector(address_sig),
        clock       => clock,
        data        => std_logic_vector(wr_data), --x"FFFF",--(others => '0'),
        rden        => rden_sig,
        wren        => wr_en,
        q           => x_n_sig
    );
 
    --Instantiating 512 Point FFT generated from IP Core. FFT Engine architecture: Quad Output and Number of                  
         --Parallel FFT engines: 1,            I/O Data Flow: Streaming
    FFT_512_inst : FFT_512 port map
    (
        clk             => clock,
        reset_n         => reset_n_sig,
        inverse         => '0',
        sink_valid      => sink_valid_sig,
        sink_sop            => sink_sop_sig,
        sink_eop            => sink_eop_sig,
        sink_real       => x_n_sig,
        sink_imag       => (others => '0'),
        sink_error      => "00",
        source_ready    => '1',
        sink_ready      => sink_ready_sig,
        source_error    => source_error_sig,
        source_sop      => source_sop_sig,
        source_eop      => source_eop_sig,
        source_valid    => source_valid,
        source_exp      => source_exp,
        source_real     => source_real,
        source_imag     => source_imag
    );
 
    reset_n_sig <= not reset;
 
 
 
    process(clock)
    begin
        if rising_edge(clock) then
            if reset = '1' then
                rden_sig <= '0';
                address_sig <= (others => '0');
            elsif sink_ready_sig = '1' then                                                 
                rden_sig <= '1';
                if rden_sig = '1' then
                    address_sig <= address_sig + 1;
                end if;
            end if;
        end if;
    end process;
 
 
 
    process(clock)
    begin
        if rising_edge(clock) then
            if reset = '1' then
                sink_valid_sig <= '0';
                sink_sop_sig <= '0';
                sink_eop_sig <= '0';
            elsif rden_sig = '1' then
                sink_valid_sig <= '1';
                if address_sig(8 downto 0) = 0 then
                    sink_sop_sig <= '1';
                else
                    sink_sop_sig <= '0';
                end if;
                if address_sig(8 downto 0) = 511 then
                    sink_eop_sig <= '1';
                    sink_valid_sig <= '0';
                else
                    sink_eop_sig <= '0';
                end if;
            end if;
        end if;
    end process;
 
 
    process(clock)
    begin
        if rising_edge(clock) then
            if reset = '1' then
                wr_en <= '0';
                wr_data <= (others => '0');
                i <= 0;
            elsif sink_ready_sig = '1' then                                         
                wr_en <= '1';
                if wr_en = '1' then
                    --wr_data <= to_signed((512 + sine(i)), 16);
                      wr_data <= to_signed((sine(i) - 512), 16); -- Here I subtract 512 to make 0 offset.
                    -- wr_data <= to_signed(512, 16);
                    i <= i+ 1;
                    if(i = 511) then
                             i <= 0;
                       end if;
                end if;
            end if;
        end if;
    end process;
    
    
end Behav;



One more thing How I distinguish from the output(source_real, source_imag, source_exp) that it's 2's complement for -ve value or it's just +ve value. Do I need to convert std_logic_vector output into signed form?

SOURCE - generate data
SINK - absorb data

Using the definition of each word it's pretty clear what is meant.

This is clear to me and I didn't mean this. There is already 2 signals(sink_real and sink_imag) for input data, similarly 3 signals(source_real, source_imag, source_exp) for output data.
Then what is the use of sink_data and source_data signal which is there additionally as a another signal.
 
Last edited:

Obviously, your test signal is far from a clean sine. In so far, additional lines should be expected. It would be however helpful if you show the output signal, otherwise we have to guess or are required to setup a test bench ourselves.

Then what is the use of sink_data and source_data signal which is there additionally as a another signal.
Which signals are you talking about, particularly?
 

Obviously, your test signal is far from a clean sine. In so far, additional lines should be expected. It would be however helpful if you show the output signal, otherwise we have to guess or are required to setup a test bench ourselves.

I tried to use modelsim for testbench but because having free version it shows some library error. When I add them from Quatus generated file. It shows another error:
near "<byte 0x8b>": illegal character found in source ...........
I think it has something to do with licence.

Currently I only have signal tap to trigger at certain condition like (like source valid=1) then observe 3 output signals(source_real, source_imag, source_exp). I am undecided to differentiate between +ve and -ve value. I saw in signaltap the -ve value is in 2's complement but MSB bit not representing any sign like 0 for +ve and 1 for -ve. I have taken 512 point FFT and data width 16 bit. Therefore, 16th bit should be representing sign bit but it is not. Therefore When I have value of a signal(source_real) in signaltap let's say FFF1h, how I know that it's +ve value or 2's complement for -ve value?

Which signals are you talking about, particularly?

https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/ug/ug_fft.pdf

sink_data signal of page 3-18 of above link.
similarly, source_data signal of page 3-19 of above link.
 

Look sharp and realize that there's an option to generate a functional simulation model in the FFT core generator ("FFT compiler Megawizard").
The synthesizable IP is encrypted and can't be used for simulation, whatever license you have.

sink_data signal of page 3-18 of above link.
similarly, source_data signal of page 3-19 of above link.
Yes, the manual also answer your question how "sink_data" and "source_data" are related to the respective complex signal components, they include them.
 

Look sharp and realize that there's an option to generate a functional simulation model in the FFT core generator ("FFT compiler Megawizard").
The synthesizable IP is encrypted and can't be used for simulation, whatever license you have.

Hi,
Is there any standard signal then to verify FFT?

I have only signaltap and I couldn't differentiate between +ve and -ve value. In other word I don't know how to decode these 3 output signals(source_real, source_imag, source_exp) from FFT core, in order to compare output with theoretically expected FFT output. For e.g. For Sine, we expect just 2 peaks in FFT.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top