Many thanks,
Guy.
Standard answer for severely memory-limited application: use a
phase accumulator and CORDIC to calculate sin/cos from the
phase angle. Needs quite a lot of FPGA fabric resource, but a
fully pipelined implementation is very convenient since it
needs no dedicated memory at all (each pipeline stage uses
one fixed value from an arctan lookup table, and this value
will end up being hard-wired). Note that CORDIC gives you
both cos and sin outputs with no extra effort, which is
likely to be useful for your downconverter.
If your target technology has some spare hardware multipliers,
CORDIC may not be the optimal solution. But it's easy to
implement and well-understood. If you have access to a clock
that's some exact multiple of your 16.758MHz sample rate,
then you can make the hardware more compact too.
--
Jonathan Bromley
Guy Eschemann wrote:
DDS and analog filter on the msb.
The size of lookup table you need will depend a lot on the spurious-
free dynamic range (SFDR) you need for your application. The usual
method for dealing with mismatched sample/signal rates is to use a
phase accumulator with excess precision, and use the MSBs to address
the LUT. You can also use the LSBs to perform some higher-order
correction if need be. The circuit you're describing is a classic DDS
(Direct Digital Synthesizer), and the frequencies you're talking about
shouldn't present too much of a challenge.
In a radio up/down-conversion application, the slight inaccuracy of a
lookup-table approach is probably acceptable, given the inherent noise
and uncertainty of the channel.
Cheers,
-Ben-
I agree with the phase accumulator. I would have thought
of a look-up table for the sin/cos, though. If one big
table is too big, then a smaller table and linear interpolation
using either another table or a mutliplier.
-- glen
DDS is one way, but if you only want one frequency, you should also
check the humble VCO.
The assumed ratio is 7.182 ( uses 2.333333' )
You can get that with a VCO and 4.3KHz compare Freq,
or you can get within 25ppm, with a 212126.58 compare Freq.
(/79; *11), and that's only 11 flipflops..
-jg
Expanding this a little, there is no reason you cannot do the converse
in a FPGA, with a Digital Frequency Synthesizer
- here, you would multiply 16.758 by 11, then divide by 79, and that
79 could index a sine-rom if needed.
-jg
When you say VCO, are you suggesting that the OP use a PLL to generate
the a multiple of the 2.333... frequency and then use a much smaller
sine table? That's not a bad idea actually. But that would put the
samples in the new clock domain and I believe the OP needs the samples
in the 16.758 MHz clock domain. I suppose a multirate filter could be
used to convert the sample rate, but I expect that would be a lot more
logic than the CORDEC approach.
Rick
Also, you only need a quarter of a cycle in the LUT. The other four
quandrants can be generated by inverting addresses and/or sign.
Curt
And when the quantization noise isn't noise but spectral lines inside
the bandwidth of the analog filter you'll need some dithering.
Jonathan,
my clock is a multiple of the sample rate. I forgot to mention that.
Thanks for your help,
Guy.
Thanks for your suggestions, Glen and Curt. I think I need to do more
research on this before I discard the LUT-based solution.
Guy.
Rick, as you guessed it, I do need to have the samples in the 16.758
MHz domain.
Guy.
Why not just output a square wave at the frequency you want then filter
outside? You can get cheap sharp filters that should do the trick.
at ~16Mhz the first harmonic is 3*16 = 48Mhz and is already 1/3 of the
fundamental.
If you really want to do it in FPGA maybe you can use a table with
interpolation which would reduce the memory footprint at a cost of cycles.
The more precise the interpolation the more cycles.
Similarly,
http://www.research.scea.com/research/pdfs/RGREENfastermath_GDC02.pdf
Remember that the sin/cos are symmetric so you only have to calcuate 1/2 the
table. In fact one can use any fractional part of the table and calculate
the reet using the angle identity formulas: