Decimation questions

Hi

I would like to ask some questions about the rx chain in the FPGA.

The following Verilog code is found in the rx_chain.v Verilog file

##################################################

phase_acc #(FREQADDR,PHASEADDR,32) rx_phase_acc
(.clk(clock),.reset(reset),.enable(enable),
.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
.strobe(sample_strobe),.phase(phase) );

##################################################

and in usrp_std.v this is found for the first rx_chain

##################################################

rx_chain #(FR_RX_FREQ_0,FR_RX_PHASE_0) rx_chain_0
( .clock(clk64),.reset(1’b0),.enable(enable_rx),
.decim_rate(decim_rate),.sample_strobe(rx_sample_strobe),.decimator_strobe(strobe_decim),.hb_strobe(hb_strobe),
.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
.i_in(ddc0_in_i),.q_in(ddc0_in_q),.i_out(bb_rx_i0),.q_out(bb_rx_q0),.debugdata(debugdata),.debugctrl(debugctrl));

##################################################

from the above FR_RX_FREQ_0 and FR_RX_PHASE_0 is passed to the
phase_acc which is used for the cordic algorithm. I know that
FR_RX_FREQ_0 holds the value of the DDC center frequency and
FR_RX_PHASE_0 holds the starting phase value.

Now I would like to know if anyone could please help me with the
following:

  1. When we use a tv_rx daughterboard, the FR_RX_FREQ_0 value is set
    to -20MHZ, right? From what I know it seems as if the Microtune
    module mixes the signal down to 20MHz.
  2. Where does FR_RX_PHASE_0 come from? Is this 0 because we start on
    the x axis with zero degrees phase when using the cordic algorithm?
  3. sample_strobe gets set to 1 in master_control.v? decimator_strobe
    is a pulse signal with 64MHz/(decimation_rate-1) pulses per second? I
    assume that this has something to do with the rate changer in the CIC
    filter that drops the sampling rate from 64MHz. I would just like to
    know why we use rate-1 in the strobe generator part in master_control?

I’m just a little confused with the strobe signals. Logic tells me
that if we’re decimating by 16, we have a decimation of 8 in the CIC
and 2 in the HBF, so strobe_decim should be 64MHz/8 and hb_strobe
should be 64MHz/(8*2).

Thank you in advance.

Sebastiaan H.

On Mon, Aug 11, 2008 at 6:28 AM, Sebastiaan H. [email protected]
wrote:

Now I would like to know if anyone could please help me with the following:

  1. When we use a tv_rx daughterboard, the FR_RX_FREQ_0 value is set
    to -20MHZ, right? From what I know it seems as if the Microtune
    module mixes the signal down to 20MHz.

A slight clarification - FR_RX_FREQ_0 is a register address. The FX2
writes to it using the SPI interface. You can see the whole thing
here:

http://gnuradio.org/trac/browser/gnuradio/trunk/usrp/fpga/sdr_lib/phase_acc.v

Other than that, I don’t think all the daughterboards have the same
tuner in them, so the IF’s might be different - but what you say
sounds good to me.

  1. Where does FR_RX_PHASE_0 come from? Is this 0 because we start on
    the x axis with zero degrees phase when using the cordic algorithm?

It comes from the host. Check the host code for more information
about what is set in this register, but I am pretty sure it’s most
likely 0 as it’s just a phase offset which can be compensated for
elsewhere in the host.

  1. sample_strobe gets set to 1 in master_control.v? decimator_strobe
    is a pulse signal with 64MHz/(decimation_rate-1) pulses per second? I
    assume that this has something to do with the rate changer in the CIC
    filter that drops the sampling rate from 64MHz. I would just like to
    know why we use rate-1 in the strobe generator part in master_control?

I’m just a little confused with the strobe signals. Logic tells me
that if we’re decimating by 16, we have a decimation of 8 in the CIC
and 2 in the HBF, so strobe_decim should be 64MHz/8 and hb_strobe
should be 64MHz/(8*2).

The (rate-1) comes from zero-based indexing, I believe. The downcount
in the strobe generator goes from (rate-1) down to 0 and pulses when
it hits 0, then resets itself. Since it’s comparing to 0 and not 1,
the starting value is (rate-1).

As for the strobe signals, I don’t see anything wrong. You are
correct - why do you think you’re wrong?

Brian

Brian

Thanks for the help so far. I’ve really figured out a lot of the
decimation stuff so far. I plan on simulating the decimation scheme
in Matlab/C++ to see exactly what happens and where unwanted effects
might be introduced. I’m supposed to investigate the current scheme
to see if it meets our needs and maybe implement another scheme if
necessary. This is a part of the master’s degree that I am doing. I
will make the decimation info available to anyone interested in it.

The value FR_RX_PHASE_0 is 0. When the USRP is initialized,
FR_RX_PHASE_0 - 3 all get the value 0 and I don’t see them being set
anywhere else when a normal downconversion is performed.
FR_DECIM_RATE gets set to decim/2 -1 when the FPGA has a halfband
filter in it. The -1 is probably due to zero indexing as you
mentioned.

FR_RX_FREQ_0 - 3 still confuses me a little. When a 7901 tv tuner
module is used, the second IF is at 20MHz. I followed the code in
db_tv_rx.py and usrp.py and saw that in this case we have
set_rx_freq(0,-20e6). In usrp_standard.cc we have the following code
in set_rx_freq:

compute_freq_control_word_fpga (double master_freq, double target_freq,
double *actual_freq, bool verbose)
{
static const int NBITS = 14;

int v = (int) rint (target_freq / master_freq * pow (2.0, 32.0));

if (0)
v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS

*actual_freq = v * master_freq / pow (2.0, 32.0);

if (verbose)
fprintf (stderr,
“compute_freq_control_word_fpga: target = %g actual = %g delta
= %g\n”,
target_freq, *actual_freq, *actual_freq - target_freq);

return (unsigned int) v;
}

v then gets written to FR_RX_FREQ_0 for channel 0. I still need to
figure out how this frequency value is used in the FPGA to generate
the sine and cosine waves used in the cordic algorithm since somehow a
20MHz signal is generated from v. From what I understand, our I and Q
signals are multiplied by a sine and cosine and then passed to the cic
filter. This leaves only the components centered at 0Hz, since the
cic low pass filters and decimates it. The hbf also lowpass filters
and decimates by a further factor of 2.

So I understand most of the Python->C+±>Verilog code. It’s just the
Verilog itself that I’m still stuck at. I did some VHDL last year, so
I’m not totally lost. What I would like to know is the following. We
have this in the rx_chain part:

phase_acc #(FREQADDR,PHASEADDR,32) rx_phase_acc
(.clk(clock),.reset(reset),.enable(enable),
.serial_addr(serial_addr),.serial_data(serial_data),.serial_strobe(serial_strobe),
.strobe(sample_strobe),.phase(phase) );

and this in the phase_acc part:

setting_reg #(FREQADDR)
sr_rxfreq0(.clock(clk),.reset(1’b0),.strobe(serial_strobe),.addr(serial_addr),.in(serial_data),.out(freq));

always @(posedge clk)
if(reset)
phase <= #1 32’b0;
else if(serial_strobe & (serial_addr == PHASEADDR))
phase <= #1 serial_data;
else if(enable & strobe)
phase <= #1 phase + freq;

From the VHDL that I know, my guess is that serial_strobe gets
asserted whenever the FX2 chip writes to the FPGA, serial_addr is an
address that the FX2 sends to the FPGA and serial_data is the value
that gets written to that address. Is this correct?

So, the setting_reg#… line above drives the freq wire with the value
that the FX2 writes to FREQADDR? This only happens once when we tune
to the desired frequency, so we just keep adding the same freq value
to phase every 1/64MHz?

When I know the above, I should be fine in figuring the rest out.

Thanks for your help.

Sebastiaan H.

On Tue, Aug 12, 2008 at 8:03 AM, Sebastiaan H. [email protected]
wrote:

Brian

Thanks for the help so far. I’ve really figured out a lot of the
decimation stuff so far. I plan on simulating the decimation scheme
in Matlab/C++ to see exactly what happens and where unwanted effects
might be introduced. I’m supposed to investigate the current scheme
to see if it meets our needs and maybe implement another scheme if
necessary. This is a part of the master’s degree that I am doing. I
will make the decimation info available to anyone interested in it.

I suggest just writing a testbench in Verilog, stimulating the input
using whatever stimulus you want and writing the results out to a
file. This will give bit-accurate, fixed-point precision without the
need for strange MATLAB/C++ conventions. You also get the exact
bit-widths that are used within the FPGA.

Writing Verilog for simulation is significantly easier than writing
for synthesis - have fun with it! There are a lot of resources out
there if you need help.

set_rx_freq(0,-20e6). In usrp_standard.cc we have the following code
v = (v >> (32 - NBITS)) << (32 - NBITS); // keep only top NBITS

v then gets written to FR_RX_FREQ_0 for channel 0. I still need to
figure out how this frequency value is used in the FPGA to generate
the sine and cosine waves used in the cordic algorithm since somehow a
20MHz signal is generated from v. From what I understand, our I and Q
signals are multiplied by a sine and cosine and then passed to the cic
filter. This leaves only the components centered at 0Hz, since the
cic low pass filters and decimates it. The hbf also lowpass filters
and decimates by a further factor of 2.

The ratio being computed here is the delta phase for each tick of a
64MHz clock for the desired frequency. It is then scaled to be a
signed 32-bit number, where 2^32 = 2*pi.

and this in the phase_acc part:
phase <= #1 phase + freq;

From the VHDL that I know, my guess is that serial_strobe gets
asserted whenever the FX2 chip writes to the FPGA, serial_addr is an
address that the FX2 sends to the FPGA and serial_data is the value
that gets written to that address. Is this correct?

It’s just a standard SPI bus. The address gets clocked in with the
serial strobe along with the data.

There should be a distinction between the interfaces with the FX2.
There is a SPI interface which connects to the serial pins and
controls registers that are written only a few times during operation,
as well as the main parallel interface which transfers the samples
that are transmitted over USB.

So, the setting_reg#… line above drives the freq wire with the value
that the FX2 writes to FREQADDR? This only happens once when we tune
to the desired frequency, so we just keep adding the same freq value
to phase every 1/64MHz?

Since you know VHDL, the FREQADDR is just a generic value which is
passed into the settings register module. It basically looks to see
if it is the addressed peripheral and, if it is, latches the data in.
Just a simple serial register that is configurable through a generic,
compile time value passed into the module.

Phase is the initial phase offset, and freq is the phase accumulation
delta which, I believe, is fed into the CORDIC and is used as a basic
NCO.

Hope this helps.

Brian