Controlling FPGA Registers Questions
- Can anyone tell me where the registers are and how I can read/write to them?
Once you create a usrp.source_c() or usrp.sink_c() object, you can call:
u = usrp.source_c() u._write_fpga_reg(regno, val)The FPGA registers are write-only. You may call:
u._read_fpga_reg(regno)but the return value will either be zero or a semi-documented set of debugging values unrelated to the register number you put. The FPGA register definitions are in: usrp/firmware/include/fpga_regs_common.h, usrp/firmware/include/fpga_regs_standard.h. NOTE: It is possible to damage your hardware by incorrectly setting these registers I believe setting_reg.v is instantiated wherever there is a register which can be written to. Being able to have access to every register makes for a very hairy problem. The FPGA registers are not set using I2C, they are set with SPI. There is already a mechanism for reading back values over SPI, but it is only set up to read back 8 values now, mostly for reading I/O pins and RSSI levels, but not every register. See serial_io.v and setting_reg.v.
- What FPGA registers are used for SPI, I2C control? Or are they just a standard registers?
All the I2C and SPI stuff is outside the FPGA. The SPI is a serial bus which is used to set registers on the daughterboards, the FPGA, and the AD9862 are controlled from the FX2 only.
- I'm trying to read and write the FPGA registers using just the libusrp. My write returns "true", but the read returns 0, regardless of which FPGA register I read/write to. Why is that ?
For example:
if (utx->_write_fpga_reg(FR_ADC_OFFSET_0,0x7777)) int readregvalue2 = (utx->_read_fpga_reg(FR_ADC_OFFSET_0));The FPGA registers are write-only. When reading, instead of the register contents, you get 'readback' register contents which are actually a number of useful signals inside the FPGA. See line numbers 304 and 305 of gnuradio/trunk/usrp/fpga/toplevel/usrp_std/usrp_std.v usrp_std.v to see what signals are read back. The typical way of dealing with write-only registers is to maintain a shadow copy in your code that you update every time you write to a register, and then if you later want to "read" the register, just look at the shadow copy. You can also use this if you want to do a read-modify-write.
- I believe that the user-defined FPGA registers don't exist in the verilog code. Do I need to add them manually? I was going to do that in usrp_std.v.
Correct. The actual registers are not instantiated (they would get pruned out anyway during synthesis if you did.) If you are writing custom FPGA code, you can instantiate any number of:
setting_reg #(FR_USER_XX) user_reg(...);
...in whatever verilog module you create, and just be sure to include: usrp/firmware/include/fpga_regs_standard.h.
The path in the include statement will vary depending on where your verilog module is in the file system. Also, if you are adding setting registers to existing modules, then the “include” may already be done it for you.
Finally, the constants FR_USER_0 through FR_USER_15 are available from C++ by including: usrp/firmware/include/fpga_regs_standard.h (again, path may vary).
- Is there a way to read from the FPGA registers from usrper?
No. From python:
# returns 32-bit int v = u._read_fpga_reg(regno)Note that there are only 4 readable registers, and I strongly suggest that you use u.read_io(which_dboard) instead of directly reading register 1 or 2.
Refer Table:
| regno | result | |
| 1 | (io_rx_a << 16) | io_tx_a | # read daughterboard i/o pins |
| 2 | (io_rx_b << 16) | io_tx_b | # read daughterboard i/o pins |
| 3 | returns const 0xaa55ff77 | # don't count on this |
| 4 | returns const 0xf0f0931a | # don't count on this |
FYI, the "normal" python interface to the usrp is defined in gr-usrp/src/usrp1.i
