I&Q on same or separate channels?

Hi all,

For the in-band code, I’m noticing that it seems like the FPGA is
packing two I’s or two Q’s, and not an I and a Q. If you take a look at
the following plot of a 10MHz sine wave, you will see what I mean. The
left plot is using the legacy receiver, the right side is using an
in-band receiver:
http://www.andrew.cmu.edu/user/gnychis/sines.png

This boils down to the following code:
http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/inband_lib/rx_buffer_inband.v

I’m guessing that Thibaud’s original assumption was that I and Q are
packed in a single channel to be read from. With a single data channel,
the code will only read from channel 0. Is this incorrect? If so, this
explains the behavior we’re seeing.

If I and Q are on separate channels, are they synchronized?

  • George

On Dec 13, 2007 4:35 PM, George N. [email protected] wrote:

http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/inband_lib/rx_buffer_inband.v

I’m guessing that Thibaud’s original assumption was that I and Q are
packed in a single channel to be read from. With a single data channel,
the code will only read from channel 0. Is this incorrect? If so, this
explains the behavior we’re seeing.

If I and Q are on separate channels, are they synchronized?

They are on separate channels, synchronized and are instantiated here:

http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v#L235

How do you feel you want to handle it?

Brian

Brian P. wrote:

They are on separate channels, synchronized and are instantiated here:

http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v#L235

How do you feel you want to handle it?

Well, that definitely explains things and why my GMSK receiver can’t
decode a transmission :wink:

I just called Leo, he’s on his way back to China for the break until
mid-January. This is something I don’t want to wait on, so I’m going to
try and tackle it myself.

His suggestion was to make the megacell 32-bits wide, and on the RX
strobe (what we’re using to signal a write), write 16 bits from the
first channel and then 16 bits from the second channel to it.

  • George

On Thu, Dec 13, 2007 at 04:35:51PM -0500, George N. wrote:

http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/inband_lib/rx_buffer_inband.v

I’m guessing that Thibaud’s original assumption was that I and Q are packed
in a single channel to be read from. With a single data channel, the code
will only read from channel 0. Is this incorrect? If so, this explains
the behavior we’re seeing.

If I and Q are on separate channels, are they synchronized?

  • George

I and Q are not on separate channels. They are interleaved,
I0, Q0, I1, Q1…

On Dec 13, 2007 5:07 PM, George N. [email protected] wrote:

Well, that definitely explains things and why my GMSK receiver can’t
decode a transmission :wink:

I just called Leo, he’s on his way back to China for the break until
mid-January. This is something I don’t want to wait on, so I’m going to
try and tackle it myself.

His suggestion was to make the megacell 32-bits wide, and on the RX
strobe (what we’re using to signal a write), write 16 bits from the
first channel and then 16 bits from the second channel to it.

Looking at the flow, each channel has a fifo1kx16 each, which you are
presumably going to make a fifo512x32?

I have a feeling you’re going to have to modify your packet_builder as
well. The packet_builder looks at the channel FIFOs sequentially and
builds a packet based on that FIFO. You need to add a state or some
extra logic in the FORWARD state that will FORWARD_I then FORWARD_Q
from the input chan_fifodata.

That seems to be the only place where it’s used, so if you make your
interface 32 bits instead of 16, and make the change to the FSM, you
should be interleaving happily.

Good luck with your modification.

Brian

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

I suspect this comment:

http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/inband_lib/rx_buffer_inband.v#L120
“TODO write this genericly”

is where the interleaving should be done… maybe :).

  • -Dan

George N. wrote:

… it seems as though they are wired to separate channels. We then use


Discuss-gnuradio mailing list
[email protected]
Discuss-gnuradio Info Page

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHYi/py9GYuuMoUJ4RAsv6AJ9BQiQXbuwj4zxo0XhiKfBa8AOQLACdGXcf
zBJa1RnYZ5ivm6PDvRCTHdk=
=9JGF
-----END PGP SIGNATURE-----

“Eric” == Eric B. [email protected] writes:

Eric> On Thu, Dec 13, 2007 at 04:35:51PM -0500, George N. wrote:


Eric> I and Q are not on separate channels. They are interleaved,
I0,
Eric> Q0, I1, Q1…

This leads again to my question some time ago about how the USB data
stream
is organized. With the partial answer from that thread my understanding
boils down to the following:

  • The FX2 has blocks/fifos of 512 bytes

  • We can put a data stream of interleaved sample in the fifo, but the
    data
    must form blocks of 512 bytes

  • If the fifo is full for some reason, the FX2 will block on a 512 byte
    boundary

  • If the FPGA detects a FIFO stall, the FPGA must restart with DATA0 of
    the
    datablock

  • On the PC side, the kernel always always receives 512 byte blocks

  • If the user process always reads 512 blocks we never get out of sync

However the last postulate gives me some headache. How do we make sure
that
the user process always fetches 512 byte blocks. Can a crashing user
process
manage to read less then 512 bytes? What if a rogue process reads less
then
512 bytes. If the user process gets out of sync with the 512 bytes for
some
reason, is there any way to resynchronize?

Uwe

Uwe Bonnes [email protected]

Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

I and Q are not on separate channels. They are interleaved,
I0, Q0, I1, Q1…

Are we sure of this? Based on Brian’s pointer to here:
http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v#L235

… it seems as though they are wired to separate channels. We then use
them as inputs to rx_buffer_input here:
http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v#L260

… but only ever read from channel 0 (I).

Is there a module we are missing that interleaves them?

  • George

Brian P. wrote:

interface 32 bits instead of 16, and make the change to the FSM, you
should be interleaving happily.

Good luck with your modification.

Taking a look at how the legacy code does it…
http://gnuradio.org/trac/browser/gnuradio/branches/developers/gnychis/inband/usrp/fpga/sdr_lib/rx_buffer.v#L137

What do you think about adopting this method? It’s using a 16-bit wide
FIFO still and just alternating between which channel it is feeding in
to the FIFO using a channel counter (store_next). In our case, we would
just alternate between channel 0 and channel 1 to have 1 full data
channel, for now. Unless there is something different in our case that
I’m unaware of. This would prevent us from having to change the
megacells and re-write some of the other state machines.

  • George

This leads again to my question some time ago about how the USB data stream
is organized. With the partial answer from that thread my understanding
boils down to the following:

Our questions are on completely different waveforms :stuck_out_tongue: I’m talking
about way before the FX2.

However the last postulate gives me some headache. How do we make sure that
the user process always fetches 512 byte blocks.

The user application does not worry about this, the lower level
interface that Eric has written to the USRP worries about this. If you
take a look at some of the code in usrp/host/lib/legacy, it is ensuring
that all reads are 512 bytes else it will print an error and return -1,
not performing the read.

Can a crashing user process manage to read less then 512 bytes?

Of course, but when the process is restarted the buffers reset in the
USRP and FX2.

What if a rogue process reads less then 512 bytes.

The low level USRP USB drivers will fail the read.

If the user process gets out of sync with the 512 bytes for some
reason, is there any way to resynchronize?

The user process can “miss” 512-bytes if it’s not reading the data fast
enough and the buffers become full… this is an overrun. The error
will be reported to the host and the host has to live with it and move
on with life.

  • George

On Fri, Dec 14, 2007 at 10:45:26AM +0100, Uwe Bonnes wrote:

  • The FX2 has blocks/fifos of 512 bytes
  • We can put a data stream of interleaved sample in the fifo, but the data
    must form blocks of 512 bytes
  • If the fifo is full for some reason, the FX2 will block on a 512 byte boundary
  • If the FPGA detects a FIFO stall, the FPGA must restart with DATA0 of the
    datablock

The FPGA never stalls part way through a packet. The flow control
between the FX2 and FPGA is based on signaling that there’s room for
an entire packet. When those flags are asserted, a 512 byte packet is
burst across the GPIF.

  • On the PC side, the kernel always always receives 512 byte blocks
  • If the user process always reads 512 blocks we never get out of sync

However the last postulate gives me some headache. How do we make sure that
the user process always fetches 512 byte blocks.

The host code in our library manages this. At the lowest level, it
never does anything that’s not a multiple of 512 bytes.

Can a crashing user process manage to read less then 512 bytes?

No.

What if a rogue process reads less then 512 bytes. If the user process
gets out of sync with the 512 bytes for some reason, is there any
way to resynchronize?

Uwe, we’ve never seen this happen since we started working on the
USRP, and that’s been something like 3 years.

If you still have doubts, I suggest that you look at the code.

Eric

On Dec 14, 2007 12:51 PM, George N. [email protected] wrote:

Taking a look at how the legacy code does it…
http://gnuradio.org/trac/browser/gnuradio/branches/developers/gnychis/inband/usrp/fpga/sdr_lib/rx_buffer.v#L137

What do you think about adopting this method? It’s using a 16-bit wide
FIFO still and just alternating between which channel it is feeding in
to the FIFO using a channel counter (store_next). In our case, we would
just alternate between channel 0 and channel 1 to have 1 full data
channel, for now. Unless there is something different in our case that
I’m unaware of. This would prevent us from having to change the
megacells and re-write some of the other state machines.

That can work too, though I am not sure you’re really saving yourself
a lot of re-writing. Are you going to put in registers to determine
if the data coming back should be real or interleaved complex?

Brian

On Fri, Dec 14, 2007 at 02:17:19AM -0500, George N. wrote:

them as inputs to rx_buffer_input here:
http://gnuradio.org/trac/browser/gnuradio/branches/features/inband-usb/usrp/fpga/toplevel/usrp_inband_usb/usrp_inband_usb.v#L260

… but only ever read from channel 0 (I).

Is there a module we are missing that interleaves them?

  • George

Sorry George, I misunderstood which definition of “channel” you were
using. Yes, in the legacy code they come from separate channels, but
those channels are paired and interleaved to define a “channel” as
seen by the host code.

Eric

On Dec 14, 2007 2:54 PM, George N. [email protected] wrote:

Shouldn’t it always be interleaved complex? When is real used?

I think single or vestigial sideband modulations use only the real
component.

More info here:

http://en.wikipedia.org/wiki/Single-sideband_modulation

Brian

That can work too, though I am not sure you’re really saving yourself
a lot of re-writing. Are you going to put in registers to determine
if the data coming back should be real or interleaved complex?

Shouldn’t it always be interleaved complex? When is real used?

  • George

I’ve got a question about the standard RX code that reflects my code…
http://gnuradio.org/trac/browser/gnuradio/branches/developers/gnychis/inband/usrp/fpga/sdr_lib/rx_buffer.v#L90

When store_next, which determines which channel to read from, reaches
the number of channels, according to the code above store_next returns
to 0. Then store_next must wait for rxstrobe to continue across the
channels again.

Two questions…

  1. why does it return back to 0 and not 1?
  2. why wait for rxstrobe to go from 0 to 1 when the fifo is driven
    by rxclk?

Thanks!
George

On Dec 16, 2007 10:59 PM, George N. [email protected] wrote:

  1. why wait for rxstrobe to go from 0 to 1 when the fifo is driven
    by rxclk?

You have to think about what this is trying to accomplish.

Everything in the Verilog code is 0 based array indexing. That
answers question #1. Question #2 is answered by understanding what
the actual statement is accomplishing:

For every received sample strobe, go through all the channels and, as
long as the received FIFO is not full, pass the data. In Verilog,
this is accomplished in the next couple of clock cycles until it
iterates through all the channels.

Does that make sense?

Brian

Brian P. wrote:

You have to think about what this is trying to accomplish.

Everything in the Verilog code is 0 based array indexing. That
answers question #1. Question #2 is answered by understanding what
the actual statement is accomplishing:

check

For every received sample strobe, go through all the channels and, as
long as the received FIFO is not full, pass the data. In Verilog,
this is accomplished in the next couple of clock cycles until it
iterates through all the channels.

Does that make sense?

Yes, it does now. I suppose I didn’t know RX strobe was the sample
strobe. :slight_smile: I definitely need my FIFO write request to reflect
store_next being 0 then. Cool, I’m starting to understand some of this!

  • George

Brian P. wrote:

On Dec 14, 2007 2:54 PM, George N. [email protected] wrote:

Shouldn’t it always be interleaved complex? When is real used?

I think single or vestigial sideband modulations use only the real component.

More info here:

http://en.wikipedia.org/wiki/Single-sideband_modulation

Since we perform modulation at the host, the block could essentially
just use the real component and ignore the imaginary component.

Is this something the standard code supports? I’m digging through it
and the only formatting specifications I’m seeing are for 8 vs. 16-bit
samples.

If it’s not supported yet, is this something we might want supported?
What we have now essentially does this, except I think we’re shipping
back the imaginary instead of the real :wink:

  • George