FPGA Intellectual Property
PCI Express*, Networking and Connectivity, Memory Interfaces, DSP IP, and Video IP
6343 Discussions

Inphase (I) and Quadrature (Q) components of signals

Altera_Forum
Honored Contributor II
4,575 Views

Hi All, 

 

How to calculate the Inphase (I) and Quadrature (Q) components of signals, such as RF signals? I would like to shift the RF signals to a specific baseband frequency and then derive the I an Q components from signals. I sort of know I can use NCO megacore function to do these. But I would like to know the actual steps to achieve these and math theory behind it. Tutorial links or reference articles would be appeiciated. 

 

Many Thank, 

 

Lee
0 Kudos
22 Replies
Altera_Forum
Honored Contributor II
1,440 Views

Hi Lee, 

 

I/Q demodulation is simply a direct implementation of the Fourier frequency shift theorem, i.e., multiplication by a complex-valued exponential in the time-domain results in a frequency shift in the frequency-domain. The complex-valued exponential can be split into cos + j*sin (Euler's rule), and that is what you implement in hardware. 

 

Take a look at these FPGA-DSP notes for more details ... 

 

http://www.ovro.caltech.edu/~dwh/correlator/pdf/esc-104paper_hawkins.pdf 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Thanks a lot Dave. I will have a look.

0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Dave, 

 

Thank you very much for the document. That is closely related to my project, DDC. I got two questions. 

 

Q1. Does the center frequency of Eq 37 mean the carrier frequency of signals, on page 63 of ESC-104? For example, for 20MHz carrier frequency signals with bandwidth of 1 MHz and sampling frequency 40 MHz, the normalized frequency, fo, will be 20/40. Is it correct?  

 

Q2. Why Eq 37 used -j not +j? Does it matter? 

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

Q1. Does the center frequency of Eq 37 mean the carrier frequency of signals, on page 63 of ESC-104? 

 

--- Quote End ---  

 

Yes. 

 

 

--- Quote Start ---  

 

For example, for 20MHz carrier frequency signals with bandwidth of 1 MHz and sampling frequency 40 MHz, the normalized frequency, fo, will be 20/40. Is it correct?  

 

--- Quote End ---  

 

That is a special case. Since the carrier is at Nyquist/2 (the center of the sampled band) you do not need an NCO, you can simply use a phasor that rotates 1, -j, -1, j, etc., see slide 117 

 

http://www.ovro.caltech.edu/~dwh/correlator/pdf/esc-104slides_hawkins.pdf 

 

The input data to this phase should use a signed-symmetric format, so that the products with -1 or -j do not cause a positive-valued over-flow (or cause 1-bit of bit-growth). 

 

 

--- Quote Start ---  

 

Q2. Why Eq 37 used -j not +j? Does it matter? 

 

--- Quote End ---  

 

Inside an FPGA there are two data streams, the real-part Y_I[n] and the imaginary-part Y_Q[n], that complex-valued pair can be represented as (Y_I[n], Y_Q[n]) or equivalently Y_I[n] + j*Y_Q[n]. The quadrature component Y_Q[n] = -sin(2*pi*f0*n), i.e., the negative sign is absorbed into the component, rather than the higher-level representation of the two data streams inside the FPGA. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Thanks for the quick reply!

0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

Thanks for the quick reply! 

--- Quote End ---  

 

 

adding to Dave's response: 

 

If your input is real only, the frequency of mixing can be positive or negative. You get one sideband on zero, the other need filter. 

 

For Fs/2 case I don't see how you can get sin/cos. You only get real frequency.
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

For Fs/2 case I don't see how you can get sin/cos. You only get real frequency. 

--- Quote End ---  

 

 

Sorry, Kaz is right, I misread your 40MHz as the sampled bandwidth, rather than the sampling frequency. 

 

If you are sampling a signal centered on 20MHz at 40MHz clock frequency, then you will likely have aliasing. So you have probably not understood how you need to sample your signal.  

 

As shown in the slides, you can use a NCO at Fs/2 (1, -1, 1, -1, sequence) to flip sidebands, however, that would not apply in your case, since the signal would alias and be corrupted. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

As shown in the slides, you can use a NCO at Fs/2 (1, -1, 1, -1, sequence) to flip sidebands, however, that would not apply in your case, since the signal would alias and be corrupted. 

--- Quote End ---  

 

 

Hi Dave, 

 

Can you please explain more about why the signal would alias and be corrupted? 

 

I am trying to replicate the example shown in Figure 36 of your document using "NCO megaCore 13.1 version" but every time I change the 'Desired Output Frequency' value, the Frequency Response plot never changed. I think the version 13.1 NCO has bugs. Have you tried version 13.1 Quartus? I noticed that you used version 12.1 sp1. I might need to use this version instead. 

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

Can you please explain more about why the signal would alias and be corrupted? 

 

--- Quote End ---  

 

You stated that your carrier frequency was 20MHz and your sampling frequency was 40MHz. If we assume that your signal of interest is centered on 20MHz and it has some non-zero bandwidth, then if you sample this signal at 40MHz, the Nyquist rate is 20MHz, i.e., the upper-sideband component of the signal will alias on top of the lower-sideband component.  

 

This would be much clearer to you if you created an example for yourself using MATLAB. Eg., you could create a signal sampled at 160MHz, and look at its Fourier transform, then "sample" that signal at 80MHz by keeping every second sample, and look at the Fourier transform, and then "sample" at 40MHz by keeping every forth sample. 

 

But this is starting to get way off-topic, since this forum is really about Altera FPGAs :) 

 

If you have no idea how to create a signal in MATLAB, just ask, and I'll create one for you. Give me an idea of what you need to sample, so that I can create a fake signal that looks similar. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

I am trying to replicate the example shown in Figure 36 of your document using "NCO megaCore 13.1 version" but every time I change the 'Desired Output Frequency' value, the Frequency Response plot never changed. I think the version 13.1 NCO has bugs. Have you tried version 13.1 Quartus? I noticed that you used version 12.1 sp1. I might need to use this version instead. 

 

--- Quote End ---  

 

I don't have 13.1 on the machine I am typing on now, I do on my machine at work, along with 14.0, so I'll take a look and write down the steps needed tomorrow. 

 

What FPGA would you like me to target as an example? 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi All, 

 

I just got reply from Altera techinical support staff. He said that he is aware of this issue but this bug has not been fixed in 13.1.4. But the workaround is simple. 

 

Every time you enter the frequency value in “Clock rate” and “Desired Output Frequency”, you have to hit an enter button of your keyboard. 

For example: 

1. Key in XX into “Clock Rate”, then hit “enter” key on your keyboard. 

2. Key in XX into “Desired Output Frequency”, then hit “enter” key on your keyboard. 

 

Cheers, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

If you have no idea how to create a signal in MATLAB, just ask, and I'll create one for you. Give me an idea of what you need to sample, so that I can create a fake signal that looks similar. 

--- Quote End ---  

 

 

Hi Dave, 

 

It would be great if you can create the Matlab code. I got both 2012 Simulink and matlab installed. We have a Cyclone III/Stratix Altera FPGA installed in a RF radar receiver. One of center frequencies of signals is 20 MHz with the bandwitdth 1MHz. The sampling frequency is 40MHz.  

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Dave, 

 

I'm a bit confused with the Eq 37 (from your FPGA-DSP document) and the NCO megaCore function?  

The fo in Eq 37 is a normalised frequency, the center frequency divided by the sampling frequency. Does that mean NCO should generate the cosine and sinusoid components with frequency of fo not the centre frequency? For example, the signal's centre frequency is 2.5MHz and the sampling frequency is 80MHz. So the normalised frequency fo = 2.5/80 = 0.0313. So in the NCO, the "Desired output frequnecy" shoud be set to 0.0313 not 2.5 MHz. Is it correct? 

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

I'm a bit confused with the Eq 37 (from your FPGA-DSP document)  

 

--- Quote End ---  

 

Whenever you are confused, try and create the equivalent code in MATLAB and plot the data. For example, plot a single period of a complex-valued exponential ... 

N = 1024; n = ; x = exp(-j*2*pi*n/N); x_re = real(x); x_im = imag(x); figure(1) subplot(2,1,1) plot(n,x_re) subplot(2,1,2) plot(n,x_im)  

and you'll see that the real part is a cosine and the imaginary part is a negative sinsuoid - just like Eq 37. 

 

 

--- Quote Start ---  

 

The fo in Eq 37 is a normalised frequency, the center frequency divided by the sampling frequency. Does that mean NCO should generate the cosine and sinusoid components with frequency of fo not the centre frequency? 

 

--- Quote End ---  

 

If your FPGA is operating at 80MHz, and its generating a 2.5MHz sinusoid, then the normalized frequency is 2.5/80 = 0.03125. Another way to think of it, is that each 2.5MHz period is 400ns long, and that is equivalent to 400ns x 80MHz = 32 samples. So as long as your NCO phasor has a multiple of 32 samples, your 2.5MHz output signal will always quantize to a whole number, i.e., your frequency tuning word will not have any fractional component when represented as a fractional integer. See slides 113+114 for an example ... 

 

http://www.ovro.caltech.edu/~dwh/correlator/pdf/esc-104slides_hawkins.pdf 

 

 

--- Quote Start ---  

 

For example, the signal's centre frequency is 2.5MHz and the sampling frequency is 80MHz. So the normalised frequency fo = 2.5/80 = 0.0313. So in the NCO, the "Desired output frequnecy" shoud be set to 0.0313 not 2.5 MHz. Is it correct? 

 

--- Quote End ---  

 

Not unless the Quartus NCO GUI has changed. Figure 36 on p64 shows that the parameters can be entered in terms of frequencies. 

 

http://www.ovro.caltech.edu/~dwh/correlator/pdf/esc-104paper_hawkins.pdf 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Dave, 

 

Thanks. Yes, the NCO definitely generates 32 samples for each sine and cosine cycle. But the amplitude of values is between -3.25*10^4 and 3.25*10^4. I'm using the NCO function in DSP Builder (simulink) to display the values. I connected the 16 bit sine and cosine outputs to simulink Scope to display the values. I think the reason of having these big amplitudes is because these values are displayed as signed integer. To fix the issue, I used Output AlteraBlockset to specify [Number of Bits].[] = 1 for the sign bit and [].[Number of Bits] = 15 for the fraction part of the floating point number. So MSB is the sign bit and the rest of 15 bits is the fraction number. However, the output values are all negative and the cycle lenght is not correct, either. Or should I use another tool to check these values? 

 

Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

 

--- Quote Start ---  

 

But the amplitude of values is between -3.25*10^4 and 3.25*10^4. 

 

--- Quote End ---  

 

Don't think in decimal, think in power-of-2 3.25e4 = 2^15, so you're simply displaying a 16-bit signed integer number. 

 

 

--- Quote Start ---  

 

I'm using the NCO function in DSP Builder (simulink) to display the values. I connected the 16 bit sine and cosine outputs to simulink Scope to display the values. I think the reason of having these big amplitudes is because these values are displayed as signed integer. To fix the issue, 

 

--- Quote End ---  

 

Why do you think this is an "issue"? Its merely a scale factor. 

 

 

--- Quote Start ---  

 

I used Output AlteraBlockset to specify [Number of Bits].[] = 1 for the sign bit and [].[Number of Bits] = 15 for the fraction part of the floating point number. So MSB is the sign bit and the rest of 15 bits is the fraction number. 

 

--- Quote End ---  

 

What you are trying to do sounds reasonable, however, I don't use Simulink, so I cannot comment on whether this is the correct way to convert to fractional integer. 

 

 

--- Quote Start ---  

 

However, the output values are all negative and the cycle lenght is not correct, either. Or should I use another tool to check these values? 

 

--- Quote End ---  

 

It sounds like there is something wrong with your method of conversion to fractional integer. I'd take a look at the MATLAB documentation and try to find an example that works :) 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Dave, 

 

I can use NCO megaCore function to generate I and Q data now. Got a question for CIC and FIR MegaCore functions. Should the inputs to these two filters in unsigned/sign integer number format or unsigned/sign fractional number format (p4-1, FIR Compiler User Guide attached)? I think unsigned/sign fractional format means a number is always smaller than 1. So floating number input such as 12.111 is not allowed. Is is corret? 

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Lee, 

 

--- Quote Start ---  

 

I can use NCO megaCore function to generate I and Q data now. Got a question for CIC and FIR MegaCore functions. Should the inputs to these two filters in unsigned/sign integer number format or unsigned/sign fractional number format (p4-1, FIR Compiler User Guide attached)? I think unsigned/sign fractional format means a number is always smaller than 1. So floating number input such as 12.111 is not allowed. Is is corret? 

 

--- Quote End ---  

 

Altera has a habit of changing their IP cores, so any answer I give could be wrong :) 

 

The best way to answer these questions is to create a Modelsim simulation and provide the simulation test stimulus and check the response. Then repeat that sequence with the MATLAB model. 

 

In fact, the cores usually provide a simple (usually quite useless) testbench. You should be able to determine the appropriate data format using those testbenches. 

 

Cheers, 

Dave
0 Kudos
Altera_Forum
Honored Contributor II
1,440 Views

Hi Dave, 

 

Thanks for the reply. I am trying to compile the testbench, automatically generated by NCO MegaCore function using Quartus 13.1 but an error message:  

"Error (10533): VHDL Wait Statement error at ncoIPDesign_tb.vhd(111): Wait Statement must contain condition clause with UNTIL keyword" 

 

I really cannot finger out what's wrong with this "wait for" statement. I tried lines 113 to 116 but got the same error. Do you know how to fix it? I have attached the nco and testbench VHDL codes. 

 

Many Thanks, 

Lee
0 Kudos
Altera_Forum
Honored Contributor II
1,301 Views

Hi Lee, 

 

 

--- Quote Start ---  

 

Thanks for the reply. I am trying to compile the testbench, automatically generated by NCO MegaCore function using Quartus 13.1 but an error message:  

"Error (10533): VHDL Wait Statement error at ncoIPDesign_tb.vhd(111): Wait Statement must contain condition clause with UNTIL keyword" 

 

--- Quote End ---  

 

 

I get a completely different error. Here's what I typed at the Modelsim prompt 

 

cd {C:\temp\alteraforum-leeying} vlib work vmap work ./work vcom -2008 ncoIPDesign.vhd vcom -2008 ncoIPDesign_tb.vhd vsim ncoIPDesign_tb  

 

and that produced the following output 

 

# vsim ncoIPDesign_tb # Loading std.standard# Loading std.textio(body)# Loading ieee.std_logic_1164(body)# Loading ieee.std_logic_arith(body)# Loading ieee.std_logic_signed(body)# Loading work.ncoipdesign_tb(tb)# Loading work.ncoipdesign(syn)# ** Warning: (vsim-3473) Component instance "ncoIPDesign_st_inst : ncoIPDesign_st" is not bound.  

 

This error is because the VHDL code you sent does not implement anything. Chances are that the files you posted are for synthesis only - note how the architecture of work.ncoipdesign(syn) is called syn. I would expect the IP to also generate a .vho file for simulation. 

 

You need to re-read the NCO handbook simulation section, it will typically give you instructions on how to simulate a design. 

 

Cheers, 

Dave
0 Kudos
Reply