Send USRP-users mailing list submissions to
[email protected]
To subscribe or unsubscribe via the World Wide Web, visit
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
or, via email, send a message with subject or body 'help' to
[email protected]
You can reach the person managing the list at
[email protected]
When replying, please edit your Subject line so it is more specific
than "Re: Contents of USRP-users digest..."
Today's Topics:
1. N210 RX Customization How-To (Tom Hartley)
2. No signal on TX/RX port (Jawad Seddar)
3. Re: No signal on TX/RX port (Jawad Seddar)
----------------------------------------------------------------------
Message: 1
Date: Thu, 4 Apr 2013 15:12:41 -0400
From: Tom Hartley <[email protected]>
To: [email protected]
Subject: [USRP-users] N210 RX Customization How-To
Message-ID: <[email protected]>
Content-Type: text/plain; charset=us-ascii
==========================================
How to customize Ettus Research USRP (Model N210) RX signal path
==========================================
This is an informal document about the nitty-gritty details involved in
customizing the Ettus Research USRP N210 FPGA. I describe in practical terms
how to modify the signal path between the front end, digital downconverter, and
packet engine. I also address how to control the 32 digital input/output pins,
how to incorporate digital inputs into the data stream, and how to create FPGA
registers that can be set from the host.
The instructions are limited in scope to the following:
- USRP N210
- Centos 6 (i.e., RedHat 6)
- Receive Path Only (my projects thus far have used other devices for
transmit)
- - - - - - - - - - - - - - - - - -
1. Setting up the host computer
Software dependencies: (Some of these might be unnecessary, TBD)
sudo yum -y install git # version control
sudo yum -y install cmake # cross platform open-source build system
sudo yum -y install boost # cross platform peer reviewed C++ libraries
sudo yum -y install python
sudo yum -y install libusb
sudo yum -y install cheetah # python-based OO template engine
sudo yum -y install doxygen # generates documentation from doumented source
code
sudo yum -y install docutils
Get uhd repository from ettus
cd /opt
git clone git://code.ettus.com/ettus/uhd.git
sudo chown -R <you> /opt/uhd # this is better than having to do "sudo"
for all subsequent operations!
Install Xilinx ISE software:
To use the larger FPGA in the N210, you need a license for the xilinx tools,
not the free WebPack.
I am using Xilinx ISE version 13.4. However, at Ettus (last I heard) they use
12.1. 13.4 exhibits more failures in meeting the 10ns clock timing constraint.
You might have fewer errors if you go back to 12.1. I refer to compile-time
errors after place-and-route, not run-time errors. The timing still seems to
work for me in run-time despite the estimation of ~ 11 ns minimum clock period
after analysis. However, it seems to me that the 13.4 version is probably not
less skilled at placing and routing the design, rather, it is probably more
skilled at modeling the device. So there might not be an advantage to 12.1.
Go to Xilinx and view the installation instructions. I recommend placing the
tools into /opt/Xilinx.
The license management UI does not work in linux. Instead, follow instructions
in the xilinx installation & licensing instructions pdf. Untar the installer
into /opt and do "sudo ./xsetup".
Add the following to your ~/.tcshrc file:
set path = ($path /opt/uhd/host/build/examples /opt/uhd/host/build/utils
/opt/uhd/host/build/examples /opt/uhd/host/build/lib /opt/uhd/host/utils )
set path = ($path /usr/local/src/boost-trunk/libs)
setenv LM_LICENSE_FILE <location of your license file or server>
setenv XILINXD_LICENSE_FILE <location of your license file or server>
You will want plenty of memory to do the compilation. Consult the ISE Release
Notes for information about memory addressing in Red Hat 32-bit vs 64-bit.
- - - - - - - - - - - - - - - - - - -
2. Adding a custom verilog file (initially, it will be a pass-through).
In my example below, the custom verilog module is iwFpgaRx. This is a modified
copy of the template file custom_dsp_rx.v. (You could include that file as-is,
but I placed it elsewhere for easier network access.)
Go to /opt/uhd/fpga/usrp2/top/N2x0. Make a copy of Makefile.N210R4 called
Makefile.custom. Make these edits:
BUILD_DIR = /opt/uhd/fpga/usrp2/top/N2x0/build-custom
CUSTOM_SRCS = /home/hartley/iwrapettus/iwFpgaRx.v
Ignore the following; I could not resolve the semantic issues with make vs
xilinx macros.
#CUSTOM_DEFS =
Xilinx wants separator = "|". If you don't get it right, xilinx tools will
proceed without your custom module and probably be "successful", but you won't
know there's a problem! Instead, go down to "Verilog Macros" line below and
do this:
"Verilog Macros" "LVDS=1|RX_DSP0_MODULE=iwFpgaRx"
For two channel operation (two parallel DDCs with two custom modules):
"Verilog Macros" "LVDS=1|RX_DSP0_MODULE=iwFpgaRx|RX_DSP1_MODULE=iwFpgaRx"
The LVDS macro is there to make the A-to-D interface correct for the R4 board.
Pay attention to whether you have R3 or R4 hardware so you don't fry it.
- - - - - - - - - - - - - - - - - - -
3. Compiling the FPGA source
Start a fresh tcsh shell and type:
cd /opt/Xilinx/13.4/ISE_DS
source ./settings64.csh # sets up path and other shell variables
cd /opt/uhd/fpga/usrp2/top/N2x0
make -f Makefile.custom bin
# Wait 1-2 hours.
# Bin file goes in build-custom/u2plus.bin ... must then be renamed to
contain n210_r4 or the net burner will reject it.
mv build-custom/u2plus.bin build-custom/n210_r4_fpga.bin
usrp_n2xx_net_burner.py --addr=192.168.10.2
--fpga=/opt/uhd/fpga/usrp2/top/N2x0/build-custom/n210_r4_fpga.bin
It frequently gets stuck in place-and-route for an additional hour or so but
then still finishes. Do not kill it (unless you have waited a whole day)! If
there is an error in the tools, make will likely keep going and then make it
quite difficult for you to figure out what the error was. You can go into the
build directory and find the Xilinx log file for each phase. Try grepping for
your custom module name.
Remove and re-apply power to the N210. (I think there is a software option for
this more recently, check it out.)
Finally,
sudo ifup eth0
(Note: When you run your UHD host code later, use a separate shell. The
xilinx tools set a different version of a runtime library which conflicts with
uhd at run time. Use one shell for xilinx and another for uhd.)
Keeping the fpga, firmware, and host in sync:
The firmware and fpga and host each keep a version number which is checked at
run time.
If you get a compatibility error, you have to look into whether you have
successfully updated all 3 components based on the same code base. Did you use
"master" or "release"? Binary images or rebuilt from source? Which library
files are on your path?
Compiling the Firmware: I have not had to modify the firmware source. I was
not able to get zpu_gcc working on my system. I tried to rebuild the zylin zpu
source for a 64 bit arch, but failed. Instead, I use the binary image firmware
from Ettus (see below). It is up to me to keep the version syncing correct.
If I have to modify the firmware someday, I will try building it on Windows.
- - - - - - - - - - - - - - - - - - -
4. Building the UHD host source:
If you are doing fpga development, use a separate shell for this. (If you run
xilinx settings64.csh before building host code, you get an error from a
standard library that xilinx uses a different version of.)
cd /opt/uhd/host
First time:
mkdir build # The first make will put all results in here
cd build
cmake ../ # Generates makefiles from templates
Each time:
make
sudo make install
sudo ldconfig
- - - - - - - - - - - - - - - - - - -
5. Creating your host application:
For my purposes, the examples "rx_samples_to_file" and "rx_multi_samples" were
good templates. Frames are obtained with rx_stream->recv(). So far I have not
done anything more sophisticated than that.
When you compile your host app, you could do a makefile if you are good at gnu
make, or integrate with ettus makefile edifice, but I found it easier to just
compile like this:
gcc -I /opt/uhd/host/include -luhd my_host_app.cpp -O2 -o my_host_app
During runtime, the uhd runtime library (/usr/local/lib64/libuhd.so) will be
dynamically linked. (If you get a compatibility error at run time, this might
mean you did not do "sudo make install" and the old version of the library is
still in place. )
Remember to do this before running:
sudo sysctl -w net.core.rmem_max=50000000
sudo sysctl -w net.core.wmem_max=1048576
- - - - - - - - - - - - - - - - - - -
6. Customizing the FPGA signal path
To understand how the modules fit together, start at "u2plus.v" and traverse
the module instantiation hierarchy:
u2plus instantiates u2plus_core
u2plus_core instantiates rx_frontend, ddc_chain, vita_rx_chain
ddc_chain instantiates dsp_rx_glue
dsp_rx_glue instantiates custom_dsp_rx or your custom module (if the verilog
macro is defined)
Look at the module in/out list for custom_dsp_rx.v. By default, there are
assign statements that tie the front end to the ddc, and tie the ddc to the
packetizer. This is a "pass through". Here you can do any of the following:
- Insert your customizations between the frontend and the ddc;
- Insert your customizations between the ddc and the packetizer;
- Bypass the ddc and put anything you want between the frontend and the
packetizer.
Here is how the timing works. "clk" is always 100MHz and everything happens
synchronously with it. frontend_i and frontend_q change on every rising edge
of the clock. "frontend" here means the A-to-D full-rate 100 MSPS samples,
after dc bias removal and I/Q balance correction. (you can bypass those pieces
elsewhere if you wish.) frontend_i is "RX_A" input path, and q is "B". ddc
output samples occur M times less often than the clock. M is determined by
software when you request a baseband sample rate. For example, in
rx_samples_to_file, with rate==5000000, M turns out to be 20 = 100 / 5. The
signal ddc_out_strobe goes high for one cycle out of every M cycles. If you
are using the DDC, you use ddc_out_strobe to check when there is a valid sample
that can be released to the packet engine. Your custom code generates
bb_sample along with the bb_strobe bit, which controls the packet engine. The
packet engine waits for bb_strobe to be high and then stores one pair of
samples from "bb_sample" (high 16 bits are i, low 16 bits are are q).
You can control the timing by making bb_strobe output different from the
ddc_out_strobe input.
For example, one thing you can do is to set bb_strobe high for N cyles,
bypassing the DDC altogether, like this:
always @(posedge clock)
if (reset | ~enable)
begin
bb_strobe_reg <= 0;
end
else
begin
bb_sample_reg[31:16] <= frontend_i[23:8];
bb_sample_reg[15:0] <= frontend_q[23:8];
if ((count >= 0) & (counter <= (N-1) ))
bb_strobe_reg <= 1;
else
bb_strobe_reg <= 0;
end
In this case, there is a counter that is incremented up to some period (PRF),
and the strobe is high for a portion of that period. The packet engine will
wrap up M samples in a packet as soon as M is reached. It is up to you to keep
the data rate low enough for the gigabit ethernet interface, which cannot
support 100 MSPS. But - here's the cool part - you do not have to enforce the
pre-ordained baseband sample rate. In this module, you can release samples at
any real-time average rate, in bursts or whatever ... and the packet engine
will store them as they come, and the UHD streamer recv() call will accept the
packets as they come. They do not have to be at regular rate that was
specified at the outset. (This may not be true in all timed modes; I don't
know; but in the simple scenario of rx_samples_to_file, I have determined that
there is no enforcement of the correct baseband rate.) This example gives
full-rate 100MSPS samples in bursts, suitable for use with the LFRX
daughterboard.
Or, if you are using the DDC and simply doing your processing on baseband
samples, you can use ddc_out_strobe to enable your logic. For example:
always @(posedge clock)
if (reset | ~enable)
// initialize
else
begin
if (ddc_out_strobe) & (count >= 0) & (count <= (N-1) )
bb_strobe_reg <= 1;
else
bb_strobe_reg <= 0;
- - - - - - - - - - - - - - - - - - -
7. User Settings Registers
You can easily create a User Settings Register in your custom module, and you
can set the value in your host app. In your verilog module, instantiate as
follows:
reg [31:0] prtCycles; // Local register set by User Settings Bus
wire [31:0] prtCycles_sr; // setting_reg module output
wire prtCycles_ch; // bit indicating the reg has just changed
setting_reg #(.my_addr(0)) sr_0 // 0 is the address you choose.
(there is an 8 bit address space)
(.clk(clock),.rst(reset),.strobe(set_stb),.addr(set_addr),.in(set_data),
.out(prtCycles_sr),.changed(prtCycles_ch));
Update the register like this: (NOT conditional on reset or ~enable because
this happens before streaming)
always @(posedge clock)
if (prtCycles_ch)
prtCycles <= prtCycles_sr;
In the host app: prior to streaming, specify the register address, value, and
motherboard = 0.
usrp->set_user_register(0, prtCycles , 0);
The register API is write-only. You cannot get information from the USRP to
the host this way.
- - - - - - - - - - - - - - - - - - -
8. Digital I/O Pins
io_rx[15:0] and io_tx[15:0] are all available as IO pins. The name simply
indicates the location of the headers on rx or tx daughterboard. All 32 can be
configured as LVCMOS inputs or outputs.
There is already a mechanism governing the IO pins, called "gpio_atr", which
you need to disable. What is ATR? From a gnuradio forum post of 2005:
'Matt's currently working on an "automatic transmit/receive switching" mode for
the USRP. It's an optional feature that we plan to use with a bunch of the
daughterboards. Depending on whether there's data in the FPGA transmit fifo or
not, specified daughterboard pins automatically change state.' This module
has a tri-state driver for these pins. See usrp-users discussions in June and
October 2012.
Therefore, in u2plus_core.v: Remove the instantiation of the gpio_atr module.
Assign gpio_readback = 0 here to avoid error. This causes the pins to be no
longer connected to the host-controlled gpio bus. I checked that there are no
other drivers of those pins, so you can safely drive them in your custom
module. The way to think of digital output pins in the fpga is: if there are
no logic elements driving a pin, it is an Input. If there are, it is an
Output. (I.e., you do not have to set a register somewhere designating that
pin as an output or input.)
Next, for both input and output, you have to make the pins visible to the scope
of your module by passing the names from the top level down. In
u2plus_core.v, ddc_chain.v, dsp_rx_glue.v, and the custom verilog module: Add
io_rx and io_tx to the module i/o lists, declaring as "inout" where required.
You can incorporate the digital input pin state into your baseband data stream
as follows. This overwrites the first sample of the frame with the tx
daughterboard pins, along with a 16-bit frame counter.
// Update the data stream
if (count == 0)
begin
bb_sample_reg[31:16] <= pulse_seq_num;
bb_sample_reg[15:0] <= io_tx[15:0];
end
else
begin
bb_sample_reg[31:16] <= frontend_i[23:8];
bb_sample_reg[15:0] <= frontend_q[23:8];
end
(It may be possible to get these values into the packet header instead, but
this is how I did it. It depends whether you care about retaining all of the
available samples, how often you need to read the digital pins, etc.)
Subsequently, take care not to connect a daughterboard that uses these pins.
Do not access the gpio bus from the host. Do not instantiate a second dsp
chain instance that would attempt to simultaneously drive the pins.
When these pins change state, the switching transients may contaminate your RX
data. This can occur even if you only drive TX daughterboard pins. You should
take care with impedance matching, shielding, et cetera. It would be nice if
you could change the pins to LVDS, but it doesn't seem that this is possible in
this IO bank (i don't remember the details). Simply lowering the drive
current spec did not help in my case. Perhaps you can design your system so
that pins do not change state during the most important phase of your data
acquisition.
- - - - - - - - - - - - - - - - - - -
9. Syncing the FPGA to 10 MHz reference clock:
Connect 0-15dBm 10MHz sinusoid to the front panel "REF" input.
Do this in the host application:
usrp->set_clock_config(uhd::clock_config_t::external(),0);
==========================================
This information should be applicable to other applications requiring
alteration of the digital signal path or using digital inputs & outputs. The
Ettus documentation is extremely sparse, perhaps for good reason; however, it
takes a typical non-expert months to work through the details that are missing
and get to this point. Note: I am not a rock star expert in any of the
topics I am addressing. I am merely a "user" who has struggled and gotten a
couple systems functioning. There may be better ways to accomplish these
things. Use this information at your own risk.
Tom Hartley
University of Massachusetts
April 2013
==========================================
------------------------------
Message: 2
Date: Fri, 5 Apr 2013 11:53:48 +0200
From: Jawad Seddar <[email protected]>
To: [email protected]
Subject: [USRP-users] No signal on TX/RX port
Message-ID:
<cae9wgf_vmwxjp8ixeicznqt1lk4cwg3+udf_dx44gkqwcdh...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
Hello,
I have 2 USRP1 each equiped with a RFX900 daughter board.
I have put antennas on each port of those cards (both RX2 and TX/RX).
When I transmit from one USRP using the TX/RX port, I can only receive on
the other USRP using the RX2 port, I don't see any signal on the TX/RX port.
Simply put, here what happens :
USRP #1 TX/RX -> USRP #2 RX2 == OK
USRP #1 TX/RX -> USRP #2 TX/RX == Not OK
The same happens the other way around (from USRP #2 to USRP #1)
I have attached the simple flow graphs I used for testing purposes as well
as the results I obtained.
Is this a normal behaviour or am I doing something wrong?
Thanks for the help,
Seddar Jawad
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: RX_side_RX2.png
Type: image/png
Size: 85688 bytes
Desc: not available
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0003.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: RX_Side_TXRX.png
Type: image/png
Size: 80757 bytes
Desc: not available
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0004.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Tx_side.png
Type: image/png
Size: 79534 bytes
Desc: not available
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0005.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: simple_rx.grc
Type: application/octet-stream
Size: 21976 bytes
Desc: not available
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0002.grc>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: simple_tx.grc
Type: application/octet-stream
Size: 23629 bytes
Desc: not available
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/22630134/attachment-0003.grc>
------------------------------
Message: 3
Date: Fri, 5 Apr 2013 16:53:14 +0200
From: Jawad Seddar <[email protected]>
To: [email protected]
Cc: [email protected]
Subject: Re: [USRP-users] No signal on TX/RX port
Message-ID:
<CAE9WgF9QETt+JPZvj4J3VE6eDQAAz=yxi0elpkywn0unzrs...@mail.gmail.com>
Content-Type: text/plain; charset="iso-8859-1"
Hi, I am using only one at any given time.
The issue is that I cannot receive on TX/RX (I am only using TX/RX and for
reception only).
Thanks for the reply anyway.
2013/4/5 Mike Jameson <[email protected]>
> Hi Jawad, I haven't got GRC in front of me but you can only use rx2 or
> tx/rx, not both at the same time. Remember to set the 'antenna' in UHF
> source block to rx2 or tx/rx. Hope that helps, Mike
> On 5 Apr 2013 10:54, "Jawad Seddar" <[email protected]> wrote:
>
>> Hello,
>>
>> I have 2 USRP1 each equiped with a RFX900 daughter board.
>> I have put antennas on each port of those cards (both RX2 and TX/RX).
>>
>> When I transmit from one USRP using the TX/RX port, I can only receive on
>> the other USRP using the RX2 port, I don't see any signal on the TX/RX port.
>>
>> Simply put, here what happens :
>> USRP #1 TX/RX -> USRP #2 RX2 == OK
>>
>> USRP #1 TX/RX -> USRP #2 TX/RX == Not OK
>>
>> The same happens the other way around (from USRP #2 to USRP #1)
>>
>> I have attached the simple flow graphs I used for testing purposes as
>> well as the results I obtained.
>>
>> Is this a normal behaviour or am I doing something wrong?
>>
>> Thanks for the help,
>> Seddar Jawad
>>
>> _______________________________________________
>> USRP-users mailing list
>> [email protected]
>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.ettus.com/pipermail/usrp-users_lists.ettus.com/attachments/20130405/647ccd92/attachment-0001.html>
------------------------------
Subject: Digest Footer
_______________________________________________
USRP-users mailing list
[email protected]
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
------------------------------
End of USRP-users Digest, Vol 32, Issue 4
*****************************************