[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Discuss-gnuradio] Decimation questions
Re: [Discuss-gnuradio] Decimation questions
Tue, 12 Aug 2008 08:27:39 -0400
On Tue, Aug 12, 2008 at 8:03 AM, Sebastiaan Heunis <address@hidden> wrote:
> 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.
> 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
> 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.
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.
> 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
> .strobe(sample_strobe),.phase(phase) );
> and this in the phase_acc part:
> setting_reg #(FREQADDR)
> always @(posedge clk)
> 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?
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
Hope this helps.