Jump to content
  • 0

Back the FFT again


mohamed shffat

Question

Hello everyone 

I'm back to work with the FFT core , even after some debugging for the core i still have the same problem here , which is no peaks at the output of the FFT except a peaks at 0 and the N-1th points of the frame , which are the first and the last points ! These results makes no sense and up to now i couldn't find any way to solve it , i have tried to scale the FFT and to control the input data which comes from the XADC , and many other ways but i still have the same problem . 

The picture below shows the results and the output of both XADC and FFT , which the sampling freq of the XADC is about 960 KSPS and i applied all the possible fundamental freqs starts from 10khz up to 480 Khz which is the maximum i can use , and i have tried the FFT core with scaled and unscaled mode , with natural and reversed order at the output , while i have tried the streaming and real time mode without changing , but the results are still for all cases above . 

Please if someone can helps me to know what's the problem here i would appreciate the help really . 

Note : the results shown in the pic below are not from the simulation , but they are real results taken by the ILA debugging core .

Regards all . 

Mohamed 

Simulation.png

Link to comment
Share on other sites

5 answers to this question

Recommended Posts

@mohamed shffat,

So ... it doesn't look like you've followed by advice in the previous thread: separate every component, and test
each of them individually.

In the code you posted, you have five components:

  1. XADC
  2. FFT
  3. Squaring the outputs
  4. Taking the square root
  5. Running the answer through a FIFO

Each of these components has errors within it, except possibly the XADC--for which I'm not familiar enough with it to know.

We'll start with the FFT. You need to set the m_axis_data_tready value to 1'b1 to tell the FFT that it is able to produce a new output.  It may never change it's output without that.  While this could cause a problem of the type you are describing, given the code you posted you have other more certain problems.  There's a second
possible problem with your FFT in that you haven't created a shift schedule.  That may come back to bite you later, but it's not what's consuming your attention right now.

Moving on to the squaring of the outputs: You aren't gating all of your operations by the FFT_Valid_out strobe.  This means that, if nothing else, your code is not portable across different implementation speeds--such as running your code where every cock presents a new and valid input to the FFT, and where every thousandth clock presents a new and valid input to the FFT.  There are two ways to do this: One is to have a CE (circuit enable) line that goes to *every* component in your squaring operation.  Components are then *only* allowed to change any registers (intermediate, output, doesn't matter) when the CE line is high.  *Everything* gets gated by CE.  The other way to do this is to take the CE line (it would come from your FFT_Valid_out strobe, which would in itself be a processed version of your s_axis_tdata_ready strobe by the FFT), and propagate it through your operation.  So, for example, if FFT_Valid_out was good on clock one, the output of your magnitude squared process would then be valid on clock four.  In both fashions, the data rate determines how often your CE line is high: once every clock, once every other clock, once every thousandth clock, etc.

Your square root operation has the same problem as well--no tracking of the CE line through the operation.  While your operation might work for for a CE value true every one in a thousandth clock, and so by the next CE value everything will have settled, this only works for slow data rates--not for the fast ones.  What happens on the CE value true every third or fourth clock?  Such as if your data rate were your clock rate divided by 3.5?

Now, moving on to the FIFO: Read through what's going on there again.  You are only writing to the FIFO when it is empty, and only reading from it when it is full.  What happens when the FIFO is neither full nor empty?  You will neither read nor write to the FIFO.  Hence I expect you will write your first value into the FIFO, and then the
FIFO will freeze and never accept any more values.  What you want to do is to write to the FIFO any time your CE line, as captured from the end of your CORDIC logic, is true.  This is the error I expect your are struggling with now.  The others will be uncovered as you struggle to work your way through this.

The problem with all of this is that, as I understand things, you have no insight into any of this.  This is a failure of your engineering process.  Bugs such as I describe above are common.  They even plague me when I build things.  The difference, though, is first that I instrument everything, and second that I separate components and test them individually, as I had suggested in the previous post.  That's what you need to do here:

Separate your five components into components/modules/whatever that you can test individually.  Test them individually.  Make certain the component works on its own before then trying to draw conclusions from the combined module.

  1. Test a sine wave generator.  Does it generate a sine wave?
  2. Test the FIFO.  Does it capture the output of the sine wave without missing samples?
  3. Test the square component: Does it square all the values in your sine wave?
  4. Test the square root: Does it properly rectify your sine wave?
  5. Repeat all of the tests above for a sine wave that changes on every sample, and again on one that only changes one sample in a thousand.  Gosh, it'd be a good test to try one that changes on every 3.5th sample!  (build a 4 bit counter, add 7 to it on every clock, use the high order bit as your CE line--a good test for understanding this, then try adding 3 to it on every clock, etc.)  Make certain you only ever get one valid sample out at a time--no repeated samples, no missing samples.
  6. Then, and *only* then, place your sine wave into your FFT.  (Not the XADC output, but your test signal output)
  7. Adjust the frequency of the sine wave.  Does it still work?
  8. Swap the sine wave for an impulse generated once every N data samples, where N is your FFT size.  Are you getting that rectified sine wave back out again?
  9. Now, and *only* now, add the XADC into the circuit.  Only at this point do you know the FFT works.  Testing with the XADC in your circuit before this point will do nothing but confuse you.   You'll spend time futzing with your function generator settings, changing frequencies, amplitudes, etc. and not realizing that your FFT and your FIFO are frozen because of some logic error.  Spend your time wisely: get things working without the XADC rather than wasting your time with it and not knowing what's going wrong.

Sorry if this is long, but I hope the length helps you realize one the multitude of problems you are currently struggling with, and two how your current testing methodology is making that difficult for you to see.


Dan

Link to comment
Share on other sites

On 12/15/2016 at 3:12 PM, D@n said:

@mohamed shffat,

So ... it doesn't look like you've followed by advice in the previous thread: separate every component, and test
each of them individually.

In the code you posted, you have five components:

  1. XADC
  2. FFT
  3. Squaring the outputs
  4. Taking the square root
  5. Running the answer through a FIFO

Each of these components has errors within it, except possibly the XADC--for which I'm not familiar enough with it to know.

We'll start with the FFT. You need to set the m_axis_data_tready value to 1'b1 to tell the FFT that it is able to produce a new output.  It may never change it's output without that.  While this could cause a problem of the type you are describing, given the code you posted you have other more certain problems.  There's a second
possible problem with your FFT in that you haven't created a shift schedule.  That may come back to bite you later, but it's not what's consuming your attention right now.

Moving on to the squaring of the outputs: You aren't gating all of your operations by the FFT_Valid_out strobe.  This means that, if nothing else, your code is not portable across different implementation speeds--such as running your code where every cock presents a new and valid input to the FFT, and where every thousandth clock presents a new and valid input to the FFT.  There are two ways to do this: One is to have a CE (circuit enable) line that goes to *every* component in your squaring operation.  Components are then *only* allowed to change any registers (intermediate, output, doesn't matter) when the CE line is high.  *Everything* gets gated by CE.  The other way to do this is to take the CE line (it would come from your FFT_Valid_out strobe, which would in itself be a processed version of your s_axis_tdata_ready strobe by the FFT), and propagate it through your operation.  So, for example, if FFT_Valid_out was good on clock one, the output of your magnitude squared process would then be valid on clock four.  In both fashions, the data rate determines how often your CE line is high: once every clock, once every other clock, once every thousandth clock, etc.

Your square root operation has the same problem as well--no tracking of the CE line through the operation.  While your operation might work for for a CE value true every one in a thousandth clock, and so by the next CE value everything will have settled, this only works for slow data rates--not for the fast ones.  What happens on the CE value true every third or fourth clock?  Such as if your data rate were your clock rate divided by 3.5?

Now, moving on to the FIFO: Read through what's going on there again.  You are only writing to the FIFO when it is empty, and only reading from it when it is full.  What happens when the FIFO is neither full nor empty?  You will neither read nor write to the FIFO.  Hence I expect you will write your first value into the FIFO, and then the
FIFO will freeze and never accept any more values.  What you want to do is to write to the FIFO any time your CE line, as captured from the end of your CORDIC logic, is true.  This is the error I expect your are struggling with now.  The others will be uncovered as you struggle to work your way through this.

The problem with all of this is that, as I understand things, you have no insight into any of this.  This is a failure of your engineering process.  Bugs such as I describe above are common.  They even plague me when I build things.  The difference, though, is first that I instrument everything, and second that I separate components and test them individually, as I had suggested in the previous post.  That's what you need to do here:

Separate your five components into components/modules/whatever that you can test individually.  Test them individually.  Make certain the component works on its own before then trying to draw conclusions from the combined module.

  1. Test a sine wave generator.  Does it generate a sine wave?
  2. Test the FIFO.  Does it capture the output of the sine wave without missing samples?
  3. Test the square component: Does it square all the values in your sine wave?
  4. Test the square root: Does it properly rectify your sine wave?
  5. Repeat all of the tests above for a sine wave that changes on every sample, and again on one that only changes one sample in a thousand.  Gosh, it'd be a good test to try one that changes on every 3.5th sample!  (build a 4 bit counter, add 7 to it on every clock, use the high order bit as your CE line--a good test for understanding this, then try adding 3 to it on every clock, etc.)  Make certain you only ever get one valid sample out at a time--no repeated samples, no missing samples.
  6. Then, and *only* then, place your sine wave into your FFT.  (Not the XADC output, but your test signal output)
  7. Adjust the frequency of the sine wave.  Does it still work?
  8. Swap the sine wave for an impulse generated once every N data samples, where N is your FFT size.  Are you getting that rectified sine wave back out again?
  9. Now, and *only* now, add the XADC into the circuit.  Only at this point do you know the FFT works.  Testing with the XADC in your circuit before this point will do nothing but confuse you.   You'll spend time futzing with your function generator settings, changing frequencies, amplitudes, etc. and not realizing that your FFT and your FIFO are frozen because of some logic error.  Spend your time wisely: get things working without the XADC rather than wasting your time with it and not knowing what's going wrong.

Sorry if this is long, but I hope the length helps you realize one the multitude of problems you are currently struggling with, and two how your current testing methodology is making that difficult for you to see.


Dan

Ok sir , thanks too much for telling me about the errors and the mistakes and thanks also for your advices . 

Unfortunately i'm neither expert on HDL or FPGA . I'm new in this field and i'm only trying to learn a new thing , beside i don't have that much time to work continuously for this project because of my study , that's why i failed on my engineering process most probably .

 I will follow your advice here sir , and hopefully it will work successfully . 

Thanks for everything sir :lol:

Greetings 

Mohamed 

Link to comment
Share on other sites

@mohamed shffat,

Not a problem, we all start somewhere.  ;)  (Please don't feel embarrassed or anything other than encouraged by my comments ...)

The "Fundamental Assumption" of all engineering debugging is that there is only one error/problem.

This assumption is rarely ever true in practice, yet it remains the fundamental assumption.  Without it debugging would be impossible.  Therefore, you want to arrange things in your project so that this assumption will be true.  That's why we break things into the smallest components we can and then try to test them individually.  Making the problem with HDL even more difficult is the fact that it can be *really* difficult to get any insight into what is going on within a design.  That's where the creativity comes to play in the process.

Be encouraged, those reading here are rooting for you,

Dan

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...