Forum: GNU Radio Costas Loop implemented on FPGA?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Reid N Kleckner (Guest)
on 2007-07-19 21:38
(Received via mailing list)
Hey all,

I'm looking at using the FPGA on the USRP to improve the performance in
some of
what my lab is doing.  To learn about the Verilog code already written
for the
FPGA, I'm trying to do phase recovery with the Costas loop at the end of
the
rx_chain.  First of all, is this a good project?  It may not be good to
have it
in the codebase for general purpose gnuradio since it's only relevant
for
certain protocols, but is there anything wrong with this approach that
makes it
brain dead?  I've read that the FPGA is using 90% of its logic cells
with it's
current implementation, and that turning off a tx_chain or an rx_chain
could
solve that problem, but I'm not there yet.

I've been hacking at it for a bit, and I drafted up a simple vlog file
here:
http://web.mit.edu/~rnk/www/costas_loop.v
and a slightly modified rx_chain here:
http://web.mit.edu/~rnk/www/rx_chain.v
I'm new to FPGAs and signals (So why am I working on this?  To learn.),
so I
have a few questions.

1. I need to store the phase shift somewhere as I correct the guess with
the
error term.  I assume that the phase accumulator in phase_acc.v needs to
do
something similar, but I don't understand how it stores its information.

2. The original C implementation of costas loop has two error terms you
can
choose from:
((sample.real()>0 ? 1.0 : -1.0) * sample.imag() -
 (sample.imag()>0 ? 1.0 : -1.0) * sample.real());
and:
(sample.real()*sample.imag());
I chose the simpler because it involved one less multiply, and I didn't
understand what the other was doing.  The point of software radio is to
allow
you to make these decisions in software, but if I had to hardcode one in
the
FPGA, which would it be?  I'm definitely not complicating this further
by
trying to get that info via USB.

3. For alpha and beta, I was just going to use a bitshift to scale the
error
term.  That'd also be hardcoded in the vlog code, but what would
reasonable
constants be?  I've seen this question asked before, and I looked at the
paper
here:
http://i.cmpnet.com/chipcenter/dsp/images/dspsourc...
and it said alpha is around 0.01 or less, so I figure a bitshift by
seven places
makes alpha about 1/128, or 0.0078125, and the paper doesn't mention
beta, so I
said eight places.

4. What's the difference between the code in
gr_pll_carriertracking_cc.cc and
gr_costas_loop_cc.cc?  They seem to do the same stuff, but maybe they're
subtly
different?

That's all.

Cheers,
Reid
Martin D. (Guest)
on 2007-07-20 01:48
(Received via mailing list)
Reid N Kleckner wrote:
> solve that problem, but I'm not there yet.
> something similar, but I don't understand how it stores its information.
>
> 2. The original C implementation of costas loop has two error terms you can
> choose from:
> ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() -
>  (sample.imag()>0 ? 1.0 : -1.0) * sample.real());
> and:
> (sample.real()*sample.imag());
> I chose the simpler because it involved one less multiply,
You could actually implement the other one without any multiplies.
multiplying with 1.0 is just oding nothing.
multiplying with -1 is just negating the value
you could rewrite the code in C like:
float val1,val2;

if(sample.real()>0)
  val1 = sample.imag();
else
  val1 = -sample.imag();

if(sample.imag()>0)
  val2 = -sample.imag();
else
  val2 = sample.imag();

output=val1+val2;



 and I didn't
> http://i.cmpnet.com/chipcenter/dsp/images/dspsourc...
> and it said alpha is around 0.01 or less, so I figure a bitshift by seven places
> makes alpha about 1/128, or 0.0078125, and the paper doesn't mention beta, so I
> said eight places.
You really want to get the values right. If the values are off your
costas loop will have weird behaviour.
I also had trouble finding the right values.
If anybody has a good clue please let us know.
In the meantime I would not hardcode the values but make them
configurable.
Just use one of the user registers to store the bitshift values.
This topic is locked and can not be replied to.