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
on 2007-07-19 21:38
on 2007-07-20 01:48
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.