控制 FPGA 寄存器问题
一旦生成对象 usrp.source_c() 或 usrp.sink_c() ,便可调用:
u = usrp.source_c()
u._write_fpga_reg(regno,
val)
FPGA 寄存器是只写(write-only)类型的。可如下调用:
u._read_fpga_reg(regno)
但返回将只是零或一组准注释的与寄存器编号无关的诊断值。FPGA 寄存器定义(参阅如下代码):
[source:gnuradio/trunk/usrp/firmware/include/fpga_regs_common.h
usrp/firmware/include/fpga_regs_common.h],
[source:gnuradio/trunk/usrp/firmware/include/fpga_regs_common.h
usrp/firmware/include/fpga_regs_standard.h].
NOTE:不当地配置这些寄存器将可能损坏硬件,毫无疑问 setting_reg.v 是在寄存器可被写入时被实例化(初始化)。能够访读每个寄存器并非一个简单的问题。FPGA 寄存器是通过 SPI 配置,而非 I2C 配置。已有一套通过 SPI 读取数值的方法,但只能最大读取 8 个数值,它主要是用于读取 I/O 管脚和 RSSI 水平,并非所有的寄存器。 参阅:
[source:gnuradio/trunk/usrp/fpga/sdr_lib/serial_io.v - serial_io.v]
和
[source:gnuradio/trunk/usrp/fpga/sdr_lib/setting_reg.v - setting_reg.v]
- 哪些 FPGA 的寄存器用于 SPI、I2C 控制?或者说它们只是标准寄存器?
- 诸如下面例程所示,使用 libusrp 读写 FPGA 寄存器。无关乎 FPGA 的那个寄存器,返回“写”的过程都是“true”,返回“读”的过程都是 0。这是何因?
if
(utx->_write_fpga_reg(FR_ADC_OFFSET_0,0x7777))
int readregvalue2 =
(utx->_read_fpga_reg(FR_ADC_OFFSET_0));
FPGA 寄存器是只写(write-only)类型的寄存器。而当“读”操作时,读取的并非寄存器的内容,而是一组 FPGA 内的有用的信号。参看如下程序代码:
[source: gnuradio/trunk/usrp/fpga/toplevel/usrp_std/usrp_std.v - usrp_std.v]
的 304 和 305 行便可明了所读取的信号的内容。一个经典的处理“只写”类型的寄存器的方法是维护一个影子拷贝记录将每次写入寄存器的内容并更新,这样,如果日后想“读取”该寄存器的话,只需查看该影子拷贝即可。也可以据此方法来“读取”-“修改”-“写入”。
- Verilog 代码里并无用户定义的 FPGA 寄存器。需手动添加吗?需在 usrp_std.v 内完善这些吗。
正确。实际使用中的寄存器并没有被实例化(在综合过程中所作的任何实例化也随后被剔除)如想编写用户(定制)FPGA 代码,可在编写的任何 Verilog 模块中随意实例化任何所需的数目如下:
setting_reg
#(FR_USER_XX) user_reg(...);
只是确保代码表述 include 包含如下:
[source:gnuradio/trunk/usrp/firmware/include/fpga_regs_common.h
usrp/firmware/include/fpga_regs_common.h]
代码表述 include 中的路径(path)取决于 Verilog 模块在文件系统的位置不同而不同。还有,现存模块如若添加了配置寄存器(setting registers)的话,代码表述“include” 便会完成这些工作。
最后,常量 FR_USER_0 到 FR_USER_15 通过代码表述 “include” 包含如下便可使用:
[source:gnuradio/trunk/usrp/firmware/include/fpga_regs_common.h
usrp/firmware/include/fpga_regs_standard.h] (再强调一下,在此路径可能不同)。
- 可以使用 usrper 来读取 FPGA 的寄存器吗?
不,不能。基于如下的 python 代码:
# returns 32-bit int
v =
u._read_fpga_reg(regno)
不难注意到仅有 4 个可读寄存器,在此强烈建议使用 use u.read_io(which_dboard) 而非直接读取寄存器 1 或 2.
参考表格:
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), “常规”的 python 到 usrp 的接口是在 gr-usrp/src/usrp1.i 中被定义。
[ << AD9862
Codec | ^ USRP FAQ 首页 ^ | 数字下变频(DDC)>>
]
注:Controlling FPGA Registers Questions(原文出处,翻译整理仅供参考!)