本应用笔记指导用户完成RFNoC架构的基本信息,安装必要的软件以开发自定义RFNoC模块,也称为计算引擎(CE),并逐步完成使用示例创建自定义RFNoC模块的步骤。 目前,USRP X300 / X310和USRP E310 / E312硬件支持RFNoC。 但是,本文档仅涵盖了USRP X300 / X310的RFNoC。
第一部分涉及安装工具和验证正确的工具安装,以便进行RFNoC开发。 后面的部分涉及创建自定义RFNoC块,使用内置的测试平台架构,使用自定义块构建FPGA映像,最后在GNU Radio中测试新块。
要求
RFNoC仅在USRP E310 / E312和USRP X300 / X310上受支持。
为了构建定制的USRP FPGA映像和RFNoC块,需要以下硬件和软件。
Ubuntu 14.04.5或16.04.1(首选):目前PyBOMBS(可用于安装软件构建工具)在Ubuntu中运行最为可靠,因此,我们建议使用此分发版。此外,构建过程中使用的大多数脚本都是特定于Linux(Ubuntu)的。建议使用具有多核和8GB + RAM的PC。
Xilinx Vivado工具(版本2017.4):具体版本取决于FPGA代码的分支和状态。默认安装位置为/ opt / Xilinx / Vivado。安装完所有软件构建工具后,可以在{USER_PREFIX} / src / uhd-fpga / usrp3 / top / {DEVICE}目录中的setupenv.sh文件中找到下载代码的特定版本。更多信息可以在这里找到。
软件构建工具:如果UHD可以或已经从开发PC上的源代码编译,则存在所有必需的软件构建组件(可以使用PyBOMBS来设置所有这些,并且在下一步中给出了如何执行此操作的说明)。
X3xx系列或E3xx系列设备或任何未来的USRP
注意:
所需的Xilinx Vivado版本将取决于所使用的USRP设备。
X3xx系列设备:Design Edition或System Edition。
E3xx系列设备:Design Edition,System Edition或免费的WebPack Edition。
可以使用其他操作系统,但本应用笔记中未提供有关如何继续操作的确切步骤。
在某些Linux发行版(例如Ubuntu)中,dash设置为默认shell,这可能会导致一些问题。建议通过在终端中运行以下命令将shell设置为bash。在第一个命令提示时选择<否>,第二个命令将验证将使用该bash。
$ sudo dpkg-reconfigure dash
$ ll /bin/sh
创建开发环境
虽然本应用笔记贯穿了将GNU Radio集成到RFNoC开发流程中的过程,但它并不需要在RFNoC框架内使用或开发,但它使得在RFNoC之上使用框架变得更加容易。 可视化和其他功能等方面。 GNU Radio是免费提供的,有关它的更多信息可以在这里找到。
要设置开发环境/沙箱,需要以下软件包:
UHD
GNU电台
GR-ettus
使用PyBOMBS创建开发环境
设置它的最简单方法是将所有内容安装到专用目录中。 PyBOMBS是最简单的方法。 如果尚未安装,可以使用以下命令设置PyBOMBS:
$ sudo apt-get install git
$ sudo apt-get install python-setuptools python-dev python-pip build-essential
$ sudo pip install git+https://github.com/gnuradio/pybombs.git
$ pybombs recipes add gr-recipes git+https://github.com/gnuradio/gr-recipes.git
$ pybombs recipes add ettus git+https://github.com/EttusResearch/ettus-pybombs.git
这些命令将执行以下操作:
安装Git
安装pip和其他Python依赖项
从其Git存储库安装最新的PyBOMBS
添加用于安装GNU Radio特定软件的gr-recipes配方
添加用于安装Ettus Research特定软件的ettus配方
从这里开始,PyBOMBS可以通过运行以下命令来设置和安装开发环境:
$ pybombs prefix init ~/rfnoc -R rfnoc -a rfnoc
该指令完成以下操作:
在用户主目录中创建一个名为rfnoc的目录(任何有效的目录名都可以)
为前缀指定rfnoc([-a alias]的别名,例如-a rfnoc),这是为此路径指定的名称。 此名称将用于使用PyBOMBS的其他步骤。 创建第一个前缀并省略别名时,前缀将被设置为默认值。
使用rfnoc前缀配方(与gqrx之类的包配方相对)将UHD,FPGA,GNU Radio和gr-ettus源克隆到〜/ rfnoc目录中,以及编译和安装所有软件
注意:用户可以指定使用PyBOMBS时构建使用的核心数。 默认设置为4.例如,例如设置用于3的核心数:
$ pybombs config makewidth 3
该值将写入配置文件,然后应用于后续PyBOMBS命令。 通过指定--config makewidth = X参数,可以暂时为特定构建覆盖此值,其中“X”是整数。 如果用户只有4个内核,建议在pybombs命令中使用此参数将内核数量限制为<4(例如3),以便计算机保持响应。 以下是两个示例,一个使用较少的内核,另一个使用更多内核:
$ pybombs --config makewidth=3 prefix init ~/rfnoc -R rfnoc -a rfnoc
$ pybombs --config makewidth=7 prefix init ~/rfnoc -R rfnoc -a rfnoc
然后,有必要设置PyBOMBS环境,以便系统/终端会话将环境变量指向这个新创建的前缀,这可以通过以下命令完成:
$ cd ~/rfnoc
$ source ./setup_env.sh
运行上一个命令后,此终端会话将可以访问环境变量,这些变量允许完全使用刚刚与PyBOMBS一起安装的软件集。 如果在其他终端中需要访问软件,则必须在其中运行相同的命令。
手动创建开发环境
作为使用PyBOMBS的替代方法,手动安装和配置软件是通过遵循GNU Radio,UHD和gr-ettus的单独安装说明并确保链接器和编译器可以访问它们来完成的。
注意:此处的应用说明是在Linux平台上手动安装UHD和GNU Radio的过程。
要手动下载软件,请使用以下git clone命令,这些命令将选择正确的分支:
$ git clone --recursive -b rfnoc-devel https://github.com/EttusResearch/uhd.git
$ git clone --recursive -b maint https://github.com/gnuradio/gnuradio.git # master branch is also fine instead of maint
$ git clone -b master https://github.com/EttusResearch/gr-ettus.git
$ git clone -b rfnoc-devel https://github.com/EttusResearch/fpga.git
如果已经安装了UHD,GNU Radio和/或gr-ettus,那么检查所提到的分支并将它们更新就足够了(git pull)。 此后,重建每个存储库(重建顺序:UHD,GNU Radio,gr-ettus)。
验证环境
使用“--version”标志运行命令“uhd_config_info”将验证安装是否已成功完成。
注意:此命令的版本字符串输出可能不同,但它应与下面的输出类似。
$ uhd_config_info --version
linux; GNU C++ version 5.4.0 20160609; Boost_105800; UHD_4.0.0.rfnoc-devel-161- g83150fdd
4.0.0.rfnoc-devel-161-g83150fdd
测试默认FPGA映像并从现有块构建
建议花一点时间查看Ettus Research默认映像,该映像是使用一组RFNoC块预先构建的,以及使用一组独特的预构建RFNoC块构建自定义映像。 要获取默认图像,请运行以下命令:
$ uhd_images_downloader
Ettus Research会偶尔更新默认镜像,并且可以在运行git pull并重新安装以拉出最新镜像后随时运行uhd_images_downloader。 镜像存储在{USER_PREFIX} / share / uhd / images目录中。
以下镜像具有相应的RFNoC块(计算引擎):
Image Name | Included Blocks |
---|---|
usrp_x300_fpga_HG.bit
|
2x DDC, 2x DUC |
usrp_x300_fpga_RFNOC_HG.bit
|
DUC, DDC (one channel), fosphor, window, fft, 2x AXI FIFOs |
usrp_x310_fpga_RFNOC_HG.bit
|
DUC, DDC (one channel), fosphor, window, fft, 2x AXI FIFOs, Keep One in N, FIR, Siggen |
usrp_e310_fpga.bit
|
1x DDC, 1x DUC |
usrp_e310_fpga_RFNOC.bit (sg1 version)
|
|
有关将图像闪烁到设备的说明,请参见此处的X3xx系列和此处的E3xx系列。
注意:FPGA映像特定于USRP设备而非USRP系列。 例如,USRP X300 FPGA映像不适用于USRP X310,反之亦然。 加载与USRP设备不对应的图像可能会破坏设备。
按照上述步骤,现在应该可以使用以下步骤:
已下载并安装了UHD / RFNoC代码
FPGA代码可用
X3xx或E3xx系列设备上的有效RFNoC映像
检查默认镜像
在USRP连接到PC的情况下,运行以下命令,验证USRP上的当前映像。
$ uhd_usrp_probe
如果RFNoC映像成功加载到USRP上,则会有大量输出文本(RFNoC代码目前非常详细)。 对于USRP X310,输出的最后一行应类似于以下内容(例如usrp_x310_fpga_HG):
| | _____________________________________________________
| | /
| | | RFNoC blocks on this device:
| | |
| | | * DmaFIFO_0
| | | * Radio_0
| | | * Radio_1
| | | * DDC_0
| | | * DDC_1
| | | * DUC_0
| | | * DUC_1
对于usrp_x310_fpga_RFNOC_HG.bit
image:
| | _____________________________________________________
| | /
| | | RFNoC blocks on this device:
| | |
| | | * DmaFIFO_0
| | | * Radio_0
| | | * Radio_1
| | | * DDC_0
| | | * DUC_0
| | | * FFT_0
| | | * Window_0
| | | * FIR_0
| | | * SigGen_0
| | | * KeepOneInN_0
| | | * fosphor_0
| | | * FIFO_0
| | | * FIFO_1
注意:实际名称和块数可能不同。块列表应该从DmaFIFO_x和Radio_x开始,然后应该跟随几行块ID。
使用预先构建的RFNoC块构建自定义映像
由于RFNoC模块数量不断增加,用户可以选择使用一组预先构建的RFNoC模块构建FPGA映像。以下步骤描述了执行此操作的过程,这样做还将验证正确的工具安装。由于编译可能需要几个小时,因此建议用户在继续本指南的其余部分的同时开始此过程。
注意:FPGA编译可以在后台运行,但它们非常耗费资源。如果用户想要使用正在编译的同一台计算机来完成本应用笔记的其余部分,则建议计算机具有足够的资源。
启动编译的脚本称为uhd_image_builder.py,位于{USER_PREFIX} / src / uhd-fpga / usrp3 / tools / scripts目录中。输入以下命令运行帮助菜单:
$ cd {USER_PREFIX}/src/uhd-fpga/usrp3/tools/scripts
$ ./uhd_image_builder.py --help
有关此脚本的更详细讨论将在下一节中给出。 目前,通过使用以下参数运行脚本来编译具有2个RFNoC块(窗口和fft)和一些FIFO的FPGA映像。
X310 USRP示例:
$ ./uhd_image_builder.py window fft -d x310 -t X310_RFNOC_HG -m 5 --fill-with-fifos
带速度等级3(sg3)FPGA的E310 USRP示例:
$ ./uhd_image_builder.py window fft -d e310 -t E310_RFNOC_sg3 -m 5 --fill-with-fifos
在成功编译过程结束时,将新映像写入USRP。 如果图像是为USRP X310编译的,则以下命令将加载新图像。 在运行命令之前,将USRP的{IP_Address}和{USER_PREFIX}更新为适当的配置值。
$ uhd_image_loader --args "type=x300,addr={IP_ADDRESS}" --fpga-path {USER_PREFIX}/src/uhd-fpga/usrp3/top/x300/build/usrp_x310_fpga_RFNOC_HG.bit
注意:FPGA映像特定于USRP设备而非USRP系列。 例如,USRP X300 FPGA映像不适用于USRP X310,反之亦然。 加载与USRP设备不对应的图像可能会破坏设备。 有关将自定义映像闪存到设备的其他说明,请参见此处的X3xx系列和此处的E3xx系列。
将映像成功写入USRP后,重新启动它并运行“uhd_usrp_probe”实用程序以查看新编译的块。
$ uhd_usrp_probe
The final lines of output for the image built for the X310 is as follows:
| | _____________________________________________________
| | /
| | | RFNoC blocks on this device:
| | |
| | | * DmaFIFO_0
| | | * Radio_0
| | | * Radio_1
| | | * Window_0
| | | * FFT_0
| | | * FIFO_0
| | | * FIFO_1
| | | * FIFO_2
UHD的rfnoc-devel分支中包含的以下新示例是如何使用UHD的RFNoC的良好参考。
以下示例基于rx_samples_to_file.cpp。 该示例可以配置为在无线电和主机之间放置RFNoC模块。
rfnoc_rx_to_file.cpp
下一个示例将空源链接到另一个块,并将数据流式传输到主机。
rfnoc_nullsource_ce_rx.cpp
GNU Radio + RFNoC入门
以更直观的方式开始使用RFNoC的好方法是使用GNU Radio。 gr-ettus out-of-tree模块(OOT)允许用户在其本地GNU Radio / GNU Radio Companion(GRC)安装中使用RFNoC块。该GNU Radio OOT包含允许您通过GRC配置FPGA的块。
注意:随着gr-ettus OOT的成熟,他们将被升级为gr-uhd。此外,gr-ettus是Ettus Research用于传播gr-uhd的实验或欠发育特征的容器。它不是gr-uhd的替代品(事实上,后者是gr-ettus的要求)。
可以从gr-ettus / examples / rfnoc运行示例,前提是将适当的RFNoC块编译到当前在USRP上运行的FPGA映像中。
使用RFNoC块构建GNU Radio流程图的几条规则:
您总是需要在流程图中使用Device3对象(它没有连接,请参见下面的截图)。
您应该至少将两个RFNoC模块连接在一起。进入GNU无线电块 - > RFNoC块 - >不建议使用GNU无线电块(它可以工作,但性能欠佳)。
GNU Radio流程图rfnoc_ddc.grc是一个可以使用默认RFNoC映像运行的示例。下面是流程图的截图及其产生的内容。
注意:复制块:在RFNoC域中,数据流不能像在GNU无线电域中那样容易地拆分。上面屏幕截图中描述的“复制”块用作流分割器。当“启用”时,它的主要目的是复制它在输入端获得的样本并将它们放入输出中,但这里它也是RFNoC域和GNURadio域之间的边界。在上面的流程图中,在传递此边界之后,可以轻松地将数据流拆分为两个接收器以使它们同时运行(标准GNU无线电功能)。可以将GNU Radio模块直接连接到RFNoC模块而无需“复制”模块,但一次只能工作一个(其他模块必须被禁用)。从RFNoC域分割数据流的另一种方法是使用“RFNoC:分流”块,它将拆分RFNoC域中的流,但这在这里并不是很有用,因为我们无论如何都要进入GNURadio域。
使用RFNoC Modtool启动自定义RFNoC模块
下图显示了RFNoC协议栈的基本结构。 为了构建具有GNU Radio集成的定制RFNoC模块,三个部分中的每一部分都需要相应的代码。 创建了一个名为RFNoC Modtool的工具,以最大限度地减少实施新RFNoC模块所需的工作量。 RFNoC Modtool创建了一个自定义GNU Radio OOT模块,其中包含每个部分的基本结构和必要文件。 RFNoC Modtool目前是GNU Radio OOT模块gr-ettus的一部分。
RFNoC Modtool利用率
注:控制台输出可能会有所不同,具体取决于用户运行的UHD版本。 但是,功能应该相同或相似。
由于RFNoC Modtool具有与GNU Radio提供的gr_modtool [gr_modtool]类似的功能,过去使用过gr_modtool的人会发现RFNoC Modtool很熟悉。
要检查该工具的使用情况,请运行以下命令:
$ rfnocmodtool help
linux; GNU C++ version 5.4.0 20160609; Boost_105800; UHD_4.0.0.rfnoc-devel-162-g335a1317
Usage:
rfnocmodtool [options] -- Run with the given options.
rfnocmodtool help -- Show a list of commands.
rfnocmodtool help -- Shows the help for a given command.
List of possible commands:
Name Aliases Description
=====================================================================
disable dis Disable block (comments out CMake entries for files)
info getinfo,inf Return information about a given module
remove rm,del Remove block (delete files and remove Makefile entries)
makexml mx Make XML file for GRC block bindings
add insert Add block to the out-of-tree module.
newmod nm,create Create a new out-of-tree module
rename mv Rename a block in the out-of-tree module.
创建RFNoC OOT模块
要开始生成RFNoC OOT模块,请导航到源位置(即cd~ / {USER_PREFIX} / src)并键入:
$ rfnocmodtool newmod [NAME OF THE MODULE]
其中[NAME OF THE MODULE]是用户提供新模块的名称。 在下文中,将创建一个名为“tutorial”的模块。 如果用户没有按照newmod命令写入模块的名称,则工具将以交互方式请求它。 运行此命令将创建一个文件夹,其中包含功能模块可能需要的基本文件夹。
$ rfnocmodtool newmod tutorial
linux; GNU C++ version 5.4.0 20160609; Boost_105800; UHD_4.0.0.rfnoc-devel-162-g335a1317
Creating out-of-tree module in ./rfnoc-tutorial... Done.
Use 'rfnocmodtool add' to add a new block to this currently empty module.
要查看创建了哪些文件和目录,请运行:
$ ls rfnoc-tutorial/
apps cmake CMakeLists.txt docs examples grc include lib MANIFEST.md python README.md rfnoc swig
与gr_modtool相比,这包括一个名为rfnoc的文件夹,它是UHD / FPGA文件所在的位置。
将自定义块添加到OOT模块
要将块添加到模块,请导航到刚创建的文件夹,然后使用rfnocmodtool的add命令。 继续上面的示例,运行以下命令:
$ cd rfnoc-tutorial
$ rfnocmodtool add [NAME OF THE BLOCK]
出于演示目的,将创建名为gain的块。 增益块将使通过它的样本乘以常数。 和以前一样,如果没有给出名称,工具会询问用户名称。 有几个参数可以传递给工具,但运行没有任何这些参数的工具将提供以下交互式解析输出:
$ rfnocmodtool add gain
linux; GNU C++ version 5.4.0 20160609; Boost_105800; UHD_4.0.0.rfnoc-devel-162-g335a1317
RFNoC module name identified: tutorial
Block/code identifier: gain
Enter valid argument list, including default arguments:
Block NoC ID (Hexadecimal): 1111222233334444
Skip Block Controllers Generation? [UHD block ctrl files] [y/N] N
Skip Block interface files Generation? [GRC block ctrl files] [y/N] N
点击每个选项上的输入将采用默认值。
以下是有效参数列表项的说明:
NoC ID:此ID是十六进制数,用作硬件部分和设计软件部分之间的标识。它可以长达16 0-9 A-F位。如果未提供NoC ID,则将其设置为随机数。
Block Controllers Generation:块控制器是C ++控件,用户可以将其应用于设计的UHD部分。在这些文件中,用户可以在此设计层上添加更多控件。根据块的复杂性,可以使用NoCScript添加所有必要的控件(有关NoCScript的更多详细信息,请参阅标记为UHD Integration的部分)。在这种情况下,不需要生成cpp / hpp块控制文件。默认是生成,因为如果不编辑它们将被忽略。
Block Interface:通过生成这些块接口文件并添加必要的逻辑,为GNU Radio接口的设计添加更多设计特定功能。根据块的复杂性,可以使用NoC-Script添加所有必要的控件。在这种情况下,不需要块接口文件。默认是生成,因为如果不编辑它们将被忽略。
注意:如果用户不打算使用块控制器或不确定是否需要它们,则设计中存在它们不会造成任何损害。 建议添加它们。 这使得在未来的开发阶段可以在其中添加更多功能。
完成解析后,将生成/编辑以下文件:
Adding file 'lib/gain_impl.h'...
Adding file 'lib/gain_impl.cc'...
Adding file 'include/tutorial/gain.h'...
Adding file 'include/tutorial/gain_block_ctrl.hpp'...
Adding file 'lib/gain_block_ctrl_impl.cpp'...
Editing swig/tutorial_swig.i...
Adding file 'python/qa_gain.py'...
Editing python/CMakeLists.txt...
Adding file 'grc/tutorial_gain.xml'...
Adding file 'rfnoc/blocks/gain.xml'...
Adding file 'rfnoc/fpga-src/noc_block_gain.v'...
rfnoc/testbenches/noc_block_gain_tb folder created
Adding file 'rfnoc/testbenches/noc_block_gain_tb/noc_block_gain_tb.sv'...
Adding file 'rfnoc/testbenches/noc_block_gain_tb/Makefile'...
Adding file 'rfnoc/testbenches/noc_block_gain_tb/CMakeLists.txt'...
RFNoC FPGA用户接口(API)
FPGA中的RFNoC模块或计算引擎(CE)使用NoC Shell实例与RFNoC的其余部分进行接口。 NoC Shell实现了RFNoC的核心功能:数据包复用和解复用,流控制和设置寄存器总线(即写/读控制/状态寄存器)。 NoC Shell具有与RFNoC AXI流交叉开关和用户界面的接口。 NoC Shell AXI流接口期望CHDR数据包具有正确的报头。 有关CHDR和SID的信息,请参见手册。
注意:AXI Stream是ARM AMBA标准接口。 Xilinx有一个AXI参考指南,详细介绍了该标准。
许多设计都希望使用仅带有样本数据的AXI Stream接口。 但是,如前所述,NoC Shell块需要CHDR数据包。 为了简化用户代码的接口,AXI Wrapper模块提供了剥离和插入CHDR标头所需的逻辑,有效地将打包的样本数据转换为流样本数据,反之亦然。 示例RFNoC块noc_block_fft.v和noc_block_fir.v显示了如何使用AXI Wrapper在计算引擎中实现现有的基于Xilinx AXI流的IP。
注意:AXI Wrapper还支持AXI Stream总线进行配置。 这些总线通过设置寄存器总线驱动,没有背压。 它们还为每个总线消耗两个用户寄存器地址。
AXI流信号:
m_axis_data_tdata:输入样本数据包
数据来自主机或其他CE
s_axis_data_tdata:输出样本数据包
数据转到另一个CE或主机
m_axis_data_tready:CE的输入信号
用于通知CE下游CE已准备好接收数据
s_axis_data_tready:输出到CE的信号
用于通知上游CE CE已准备好接收数据
m_axis_data_tvalid:CE的输入信号
用于指示上游CE具有有效数据
s_axis_data_tvalid:输出到CE的信号
用于向下游CE指示CE具有有效数据
m_axis_data_tlast:CE的输入信号
用于分隔来自上游CE的数据包
s_axis_data_tlast:输出到CE的信号
用于将数据包分隔到下游CE
设置总线信号:
set_stb:断言写入set_data以在set_address中注册
set_addr:要设置的寄存器地址
set_data:要设置的数据
rb_data:要回读的数据
rb_strobe:断言从set_address中的寄存器读取rb_data
对于增益示例块,需要以下架构:
打开文件rfnoc-tutorial / rfnoc / fpga-src / noc_block_gain.v,其中包含运行$ rfnocmodtool add gain命令时创建的RFNoC块骨架代码,并修改以下内容(BOLD表示对骨架代码的更改)。
localparam [7:0] SR_GAIN = SR_USER_REG_BASE;
localparam [7:0] SR_TEST_REG_1 = SR_USER_REG_BASE + 8'd1;
wire [15:0] gain;
setting_reg #(
.my_addr(SR_GAIN), .awidth(8), .width(16))
sr_gain (
.clk(ce_clk), .rst(ce_rst),
.strobe(set_stb), .addr(set_addr), .in(set_data), .out(gain), .changed());
always @(posedge ce_clk) begin
case(rb_addr)
8'd0 : rb_data <= {48'd0, gain};
8'd1 : rb_data <= {32'd0, test_reg_1};
default : rb_data <= 64'h0BADC0DE0BADC0DE;
endcase
end
wire [31:0] pipe_in_tdata;
wire pipe_in_tvalid, pipe_in_tlast;
wire pipe_in_tready;
wire [31:0] pipe_out_tdata;
wire pipe_out_tvalid, pipe_out_tlast;
wire pipe_out_tready;
// Adding FIFO to ensure Pipeline
axi_fifo_flop #(.WIDTH(32+1))
pipeline0_axi_fifo_flop (
.clk(ce_clk),
.reset(ce_rst),
.clear(clear_tx_seqnum),
.i_tdata({m_axis_data_tlast,m_axis_data_tdata}),
.i_tvalid(m_axis_data_tvalid),
.i_tready(m_axis_data_tready),
.o_tdata({pipe_in_tlast,pipe_in_tdata}),
.o_tvalid(pipe_in_tvalid),
.o_tready(pipe_in_tready));
wire [15:0] i = pipe_in_tdata[31:16];
wire [15:0] q = pipe_in_tdata[15:0];
wire [31:0] i_mult_gain = i*gain;
wire [31:0] q_mult_gain = q*gain;
wire [31:0] mult_gain = {i_mult_gain[15:0], q_mult_gain[15:0]};
axi_fifo_flop #(.WIDTH(32+1))
pipeline1_axi_fifo_flop (
.clk(ce_clk),
.reset(ce_rst),
.clear(clear_tx_seqnum),
.i_tdata({pipe_in_tlast,mult_gain}),
.i_tvalid(pipe_in_tvalid),
.i_tready(pipe_in_tready),
.o_tdata({pipe_out_tlast,pipe_out_tdata}),
.o_tvalid(pipe_out_tvalid),
.o_tready(pipe_out_tready));
/* Output Signals */
assign pipe_out_tready = s_axis_data_tready;
assign s_axis_data_tvalid = pipe_out_tvalid;
assign s_axis_data_tlast = pipe_out_tlast;
assign s_axis_data_tdata = pipe_out_tdata;
以下是上述Verilog创建的代码的框图:
注意:为了满足时序要求,FIFO块被添加到乘法过程的任一侧。
创建和运行HDL测试平台
为了使编码迭代过程更加高效,建议在将所有RFNoC模块编译成FPGA映像之前为其创建测试平台。这允许在设计的早期检测缺陷和/或错误。 RFNoC Modtool为使用$ rfnocmodtool add命令添加的每个OOT块的测试平台提供结构和文件(例如noc_block_ {USER_BLOCK_NAME} _tb)。
下图显示了RFNoC Modtool创建的通用测试平台架构。这种架构允许用户在RFNoC架构中内置的完全相同的环境中测试他们的自定义块。测试平台架构的其他好处包括:
通过多个块进行测试(例如FILTER - > FFT - > AVE)
使用多个流进行测试(例如RFNoC块ADD / SUB需要2个流,一个将添加一个常量,一个将从中减去一个常量)
数据传输抽象(例如RFNoC Sim Lib API调用tb_streamer.send和tb_streamer.recv来处理所有AXI流信令)
注意:noc_block_tb块是noc_block_export_io的实例,它在测试平台中用于与RFNoC体系结构通信。 这使得可以将“RFNoC”与用户的自定义块进行通信,因此自定义块具有完整的RFNoC体验(信令,流量控制,寻址等)
从最初创建增益块的添加自定义块到OOT模块部分,生成的最后一个文件是:
rfnoc/testbenches/noc_block_gain_tb folder created
Adding file 'rfnoc/testbenches/noc_block_gain_tb/noc_block_gain_tb.sv'...
Adding file 'rfnoc/testbenches/noc_block_gain_tb/Makefile'...
Adding file 'rfnoc/testbenches/noc_block_gain_tb/CMakeLists.txt'...
noc_block_gain_tb是生成的文件夹,用于包含与增益块的测试平台相关的所有文件。 每次创建新的OOT块时,也会生成一个新文件夹。
这个文件夹里面有以下三个文件:
CMakeLists.txt:这是一个空文件,到目前为止,只是为了增加编译器的范围。
noc_block_gain_tb.sv:这是一个System Verilog文件,其中包含用户自定义测试。 这是唯一需要修改的文件。
Makefile:此文件确定运行模拟的指令。
noc_block_gain_tb.sv测试平台框架代码创建以下体系结构:
打开文件rfnoc-tutorial / rfnoc / testbenches / noc_block_gain_tb / noc_block_gain_tb.sv并修改以下行:
在“Verification”部分下方:
initial begin : tb_main
string s;
logic [31:0] random_word;
logic [63:0] readback;
logic [15:0] gain;
In the “Test 4 -- Write / readback user registers” section:
`TEST_CASE_START("Write / readback user registers");
random_word = $random();
tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_GAIN, random_word[15:0]);
tb_streamer.read_user_reg(sid_noc_block_gain, 0, readback);
$sformat(s, "User register 0 incorrect readback! Expected: %0d, Actual %0d", readback[15:0], random_word[15:0]);
`ASSERT_ERROR(readback[15:0] == random_word[15:0], s);
In the “Test 5 -- Test sequence” section:
`TEST_CASE_START("Test sequence");
gain = 100;
tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_GAIN, gain);
fork
begin
cvita_payload_t send_payload;
for (int i = 0; i < SPP/2; i++) begin
send_payload.push_back(64'(i));
end
tb_streamer.send(send_payload);
end
begin
cvita_payload_t recv_payload;
cvita_metadata_t md;
logic [63:0] expected_value;
tb_streamer.recv(recv_payload,md);
for (int i = 0; i < SPP/2; i++) begin
expected_value = i*gain;
测试#4验证我们可以写入和回读增益值。 测试#5写入增益寄存器,以斜坡(1,2,3,4等)的形式将样本集发送到RFNoC增益模块,最后从增益模块读取值并将它们与预期值进行比较。 以下步骤将允许用户运行此测试平台。
在rfnoc-tutorial目录中,创建一个build
目录并通过运行以下命令输入:
$ mkdir build && cd build/
下一步是运行cmake。 如果使用PyBOMBS创建开发沙箱,cmake将自动检测fpga存储库的位置。 如果未使用PyBOMBS,则用户必须提供fpga存储库的安装位置。
如果使用PyBOMBS,请运行:
$ cmake ../
如果未使用PyBOMBS,请运行:
$ cmake [-DUHD_FPGA_DIR=/PATH/TO/FPGA/REPOSITORY] ../
Final output from the $ cmake ../
command:
-- Configuring done
-- Generating done
-- Build files have been written to: /home/widow/rfnoc/src/rfnoc-tutorial/build
以下命令将修改必要的文件并设置模拟工具的正确路径。 从现在开始,每次添加新块时,此命令都将自动运行。 请记住,只为每个OOT模块(不是RFNoC块,但是OOT模块)创建一次以下命令:
$ make test_tb
Scanning dependencies of target test_tb
Built target test_tb
可以通过运行命令来执行测试平台:
$ make noc_block_[name_of_your_block]_tb
可以通过运行以下命令来运行增益块测试平台:
$ make noc_block_gain_tb
模拟将开始。 最终输出应如下所示:
========================================================
TESTBENCH STARTED: noc_block_gain
========================================================
[TEST CASE 1] (t=000000000) BEGIN: Wait for Reset...
[TEST CASE 1] (t=000001002) DONE... Passed
[TEST CASE 2] (t=000001002) BEGIN: Check NoC ID...
Read GAIN NOC ID: 1111222233334444
[TEST CASE 2] (t=000001238) DONE... Passed
[TEST CASE 3] (t=000001238) BEGIN: Connect RFNoC blocks...
Connecting noc_block_tb (SID: 1:0) to noc_block_gain (SID: 0:0)
Connecting noc_block_gain (SID: 0:0) to noc_block_tb (SID: 1:0)
[TEST CASE 3] (t=000005457) DONE... Passed
[TEST CASE 4] (t=000005457) BEGIN: Write / readback user registers...
[TEST CASE 4] (t=000006888) DONE... Passed
[TEST CASE 5] (t=000006888) BEGIN: Test sequence...
[TEST CASE 5] (t=000007633) DONE... Passed
========================================================
TESTBENCH FINISHED: noc_block_gain
- Time elapsed: 7700 ns
- Tests Expected: 5
- Tests Run: 5
- Tests Passed: 5
Result: PASSED
========================================================
$finish called at time : 7700 ns : File "/home/widow/rfnoc/src/rfnoc-tutorial/rfnoc/testbenches/noc_block_gain_tb/noc_block_gain_tb.sv" Line 10
INFO: [USF-XSim-96] XSim completed. Design snapshot 'noc_block_gain_tb_behav' loaded.
INFO: [USF-XSim-97] XSim simulation ran for 1000000000us
launch_simulation: Time (s): cpu = 00:00:10 ; elapsed = 00:00:12 . Memory (MB): peak = 966.387 ; gain = 54.848 ; free physical = 3080 ; free virtual = 29888
# if [string equal $vivado_mode "batch"] {
# puts "BUILDER: Closing project"
# close_project
# } else {
# puts "BUILDER: In GUI mode. Leaving project open."
# }
BUILDER: Closing project
****** Webtalk v2015.4 (64-bit)
**** SW Build 1412921 on Wed Nov 18 09:44:32 MST 2015
**** IP Build 1412160 on Tue Nov 17 13:47:24 MST 2015
** Copyright 1986-2015 Xilinx, Inc. All Rights Reserved.
source /home/widow/rfnoc/src/rfnoc-tutorial/rfnoc/testbenches/noc_block_gain_tb/xsim_proj/xsim_proj.hw/webtalk/labtool_webtalk.tcl -notrace
INFO: [Common 17-206] Exiting Webtalk at Tue Jan 10 23:26:20 2017...
INFO: [Common 17-206] Exiting Vivado at Tue Jan 10 23:26:22 2017...
Built target noc_block_gain_tb
创建每个自定义块后,可以使用make指令从构建目录运行模拟。
使用自定义用户块构建FPGA映像
在本节中,我们将介绍如何在合并用户自定义RFNoC模块的同时启动FPGA构建。第一部分提供了构建RFNoC映像的一般信息。其余两节分别展示了如何使用命令行界面和使用图形界面(即将推出)启动FPGA构建。
关于FPGA图像中块数的讨论
每个设备都可以添加最大数量的块。每个设备可以使用的最大计算引擎(CE / RFNoC块)数量为16,但可添加的自定义块数量取决于设备。
如果使用X3xx系列中的设备,从16个CE开始,将有6个将始终添加,不需要直接定制:AXI总线1 CE,以太网接口1 CE,2个无线电和2 Dma FIFOS 。因此,该应用程序将只允许X3xx系列上的10个自定义块。
如果使用E3xx系列中的设备,则总是添加2个CE引擎,不需要直接定制:AXI总线为1 CE,1个为无线电。这实际上允许14个插槽用于自定义块。但是,考虑到E3xx系列器件上FPGA的大小,该应用程序仅允许6个自定义块。
注意:具有较高资源利用率的块可能会填满FPGA并迫使用户包含更少的块。
通过从scripts目录运行uhd_images_builder.py实用程序来验证当前的最大值。
$ cd {USER_PREFIX}/src/uhd-fpga/usrp3/tools/scripts
$ uhd_image_builder.py --help
关于FPGA图像目标的讨论
RFNoC目标名称遵循{DEVICE} _RFNOC_ {BUILD_TYPE}模式,具有以下构建类型:
HG:
1GigE on SFP+ Port0, 10Gig on SFP+ PortXG:
10GigE on both SFP+ portsHLS:
Vivado High Level Synthesis enabledsgX:
Speed grade for E300 devices (1 or 3)Some examples are:
X310_RFNOC_HG
X300_RFNOC_HG
X310_RFNOC_XG
X300_RFNOC_XG
X310_RFNOC_HLS_HG
X300_RFNOC_HLS_HG
E310_RFNOC
(this is for the speed grade 1 FPGA version of E310, append _sg3
for speed grade 3)注意:E310,E312和E313都具有相同的FPGA硬件,因此将使用E310_RFNOC_ {BUILD_TYPE}目标。 USRP E3xx设备具有sg1或sg3硬件,请访问此处以了解如何区分。
有关构建目标的其他信息可以在USRP3的构建说明中找到,可在此处找到。
使用命令行构建映像
脚本uhd_image_builder.py用于生成NoC块实例化文件并构建FPGA映像。 输入以下命令运行帮助菜单:
$ cd {USER_PREFIX}/src/uhd-fpga/usrp3/tools/scripts
$ ./uhd_image_builder.py --help
usage: uhd_image_builder.py [-h] [-I INCLUDE_DIR [INCLUDE_DIR ...]]
[-m MAX_NUM_BLOCKS] [--fill-with-fifos]
[-o OUTFILE] [-d DEVICE] [-t TARGET] [-g] [-c]
[blocks [blocks ...]]
Generate the NoC block instantiation file
positional arguments:
blocks List block names to instantiate.
optional arguments:
-h, --help show this help message and exit
-I INCLUDE_DIR [INCLUDE_DIR ...], --include-dir INCLUDE_DIR [INCLUDE_DIR ...]
Path directory of the RFNoC Out-of-Tree module
-m MAX_NUM_BLOCKS, --max-num-blocks MAX_NUM_BLOCKS
Maximum number of blocks (Max. Allowed for x310|x300:
10, for e300: 6)
--fill-with-fifos If the number of blocks provided was smaller than the
max number, fill the rest with FIFOs
-o OUTFILE, --outfile OUTFILE
Output /path/filename - By running this directive, you
won't build your IP
-d DEVICE, --device DEVICE
Device to be programmed [x300, x310, e310]
-t TARGET, --target TARGET
Build target - image type [X3X0_RFNOC_HG,
X3X0_RFNOC_XG, E310_RFNOC_sg3...]
-g, --GUI Open Vivado GUI during the FPGA building process
-c, --clean-all Cleans the IP before a new build
下是脚本用法的详细信息,后面是一个示例:
块:第一个参数是用户希望编译到新图像中的RFNoC块的名称,这些块由空格分隔。 它们可以是用户的OOT模块中的自定义块,也可以是Ettus提供的自定义块或组合。 在{USER_PREFIX} /src/uhd-fpga/usrp3/lib/rfnoc/Makefile.srcs文件中列出了Ettus Research提供的块(以及FPGA构建所需的其他源)。
可以通过以下模式识别这些块:
noc_block_{NAME}.v
但是,由于所有RFNoC块都具有相同的noc_block_前缀,为简单起见,在uhd_image_builder.py实用程序中列出块时,将省略此前缀。 作为添加块的错误和正确方法的示例,请在添加noc_block_null_source_sink和noc_block_siggen块时考虑以下示例:
方法不正确:
$ ./uhd_image_builder.py noc_block_null_source_sink noc_block_siggen ...
Correct method:
$ ./uhd_image_builder.py null_source_sink siggen ...
注意:RFNoC Modtool生成的块遵循相同的命名约定。
有越来越多的预建块。 这是一个示例:
axi_fifo_loopback
axi_dma_fifo
fir_filter
fft
null_source_sink
schmidl_cox
packet_resizer
split_stream
vector_iir
addsub
window
keep_one_in_n
pfb
export_io
conv_encoder_qpsk
siggen
logpwr
fosphor
moving_avg
ddc
duc
RFNoC相关块通常位于fpga / usrp3 / lib / rfnoc /中。
Block | Filename | Description |
---|---|---|
FIFO | noc_block_axi_fifo_loopback.v | Simple FIFO loopback / passthrough block. |
FFT | noc_block_fft.v | Xilinx coregen based Fast Fourier Transform up to length 4096. |
FIR | noc_block_fir_filter.v | Xilinx coregen based Finite Impulse Response Filter, 41 taps, reconfigurable tap coefficients. |
Window | noc_block_window.v | Windowing block for use with FFT block. |
Vector IIR | noc_block_vector_iir.v | Single pole IIR with configurable coefficients that filters data along vectors (i.e. parallel streams of samples). Useful with FFT output. |
Keep One in N | noc_block_keep_one_in_n.v | Keeps one packet every N packets. |
AddSub | noc_block_addsub.v | Example of using multiple block ports in a single RFNoC block to add and subtract streams. |
Null Source Sink | noc_block_null_source_sink.v | Generates dummy packets and can consume packets at a configurable rate. Useful for testing. |
Packet Resizer | noc_block_packet_resizer.v | Resizes input packets to a configurable size (larger or smaller than source packets). |
Split Stream | noc_block_split_stream.v | Replicates an input stream to a configurable number of output streams. |
注意:可以添加到FPGA映像中的块数量有限制,有关详细信息,请参阅本应用笔记中标记为FPGA映像中块数的讨论部分。
-I INCLUDE_DIR:-I指令提供顶级OOT目录的路径,该目录包含用户rfnoc / fpga-src目录,其中包含自定义块。 Xilinx Vivado工具需要此路径。在fpga-src目录中有一个名为Makefile.srcs的文件,它包含OOT模块的路径和所有自定义OOT块的列表。这是一个自动生成的文件,每次将新块添加到OOT模块时都会对其进行修改。建议不要手动修改此文件。如果存在具有驻留在不同目录中的各种自定义块的多个OOT模块,则包括它们的方式是通过空格分隔不同路径(例如-I / first / OOT / path / / second / OOT / path /)。
重要提示:请务必使用“/”字符终止OOT的路径。否则可能无法识别路径。
-d DEVICE:-d指令指示构建所用USRP设备的脚本。如果不包含-d,则默认为-d x310。第3代USRP及更高版本支持RFNoC。
-t TARGET:-t指令指示脚本在哪种类型的映像上为所选设备构建。每个USRP设备都有几个构建选项可供选择。有关构建目标的详细信息,请参阅此处的USRP3构建说明。如果未包含-t,则将为给定设备选择默认目标。例如,默认的X310_RFNOC_HG目标为-d x310设备构建。有关目标的更多详细信息,请参见本应用笔记中标记为FPGA映像目标的讨论部分。
-m MAX_NUM_BLOCKS:-m指令指定要在FPGA映像上构建的最大RFNoC块数。 RFNoC映像不需要使用RFNoC块填充所有可用插槽。
--fill-with-fifos:--fill-with-fifos指令将用FIFOS填充空的RFNoC块插槽。例如,如果用户按名称指示三个RFNoC块并且还指定-m 5,那么另外两个插槽将与FIFO一起存档。
-o OUTFILE:使用-o指令生成RFNoC块实例化文件,并将其保存在具有给定用户要检查的给定名称的所需路径中。如果提供此指令,则不会构建FPGA映像。 uhd_image_builder.py脚本的目的是自动生成实例化文件并填充Xilinx Vivado工具构建FPGA映像所需的源文件,但是,可能只希望看到添加自定义OOT模块的效果fpga /目录,或用于检查实例化文件。如果未提供该指令,则会覆盖rfnoc_ce_auto_inst_x3x0.v文件,并且FPGA映像构建过程将自动启动(标准使用)。
-g, - GUI:在FPGA构建过程中打开Vivado GUI
-c, - clean-all:在新构建之前清除IP
以下是如何创建包含本应用笔记前面创建的增益块的X310 FPGA映像:
$ cd {USER_PREFIX}/src/uhd-fpga/usrp3/tools/scripts
$ ./uhd_image_builder.py gain ddc fft -I {USER_PREFIX}/src/rfnoc-tutorial/ -d x310 -t X310_RFNOC_HG -m 6 --fill-with-fifos
注意:
FPGA映像构建过程可能需要一个多小时。
FPGA映像特定于USRP设备而非USRP系列。例如,USRP X300 FPGA映像不适用于USRP X310,反之亦然。加载与USRP设备不对应的图像可能会破坏设备。有关将自定义映像闪存到设备的其他说明,请参见此处的X3xx系列和此处的E3xx系列。
[环境设置] - uhd_image_builder.py脚本还将通过自动运行位于{USER_PREFIX} / src / uhd-fpga / usrp3 / top / {device}目录中的setupenv.sh脚本来设置Xilinx Vivado环境。 setupenv.sh脚本假定Xilinx Vivado安装在/ opt / Xilinx / Vivado的默认位置。如果安装位于不同的目录中,则需要修改setupenv_base.sh脚本。该脚本位于:{USER_PREFIX} /src/uhd-fpga/usrp3/tools/scripts/setupenv_base.sh
除了自定义增益模块外,还增加了一个DDC和FFT模块以及三个FIFO。 DDC,FFT和FIFO块已经在脚本的路径中,因此不需要指定它们的路径(它们随Ettus Research FPGA代码一起提供)。添加三个FIFO的原因是因为最大块数被指定为6(-m 6),并且由于仅有3个块被特别命名,所以其他三个时隙被FIFO填充。
注意:有关将图像闪烁到设备的说明,请参见此处的X3xx系列和此处的E3xx系列。 FPGA映像特定于USRP设备而非USRP系列。 例如,USRP X300 FPGA映像不适用于USRP X310,反之亦然。 加载与USRP设备不对应的图像可能会破坏设备。
将新编译的映像加载到USRP X3xx后,运行以下命令将显示FPGA上可用的RFNoC块:
$ uhd_usrp_probe
| | _____________________________________________________
| | /
| | | RFNoC blocks on this device:
| | |
| | | * DmaFIFO_0
| | | * Radio_0
| | | * Radio_1
| | | * Block_0
| | | * DDC_0
| | | * FFT_0
| | | * FIFO_0
| | | * FIFO_1
| | | * FIFO_2
注意:自定义块被称为Block_0而不是gain_0的原因是因为仍然需要更新主机端软件/文件,以便此块填充其正确的名称。 以下部分(UHD集成)将逐步完成更新这些主机端文件的过程。
使用图形界面
用于FPGA生成和构建的图形用户界面随uhd_image_builder.py脚本一起提供。 这个直观的应用程序有助于设置自定义FPGA构建。
该实用程序与uhd_image_builder.py位于相同的脚本目录中。
要运行它,请输入以下命令:
$ cd {USER_PREFIX}/src/uhd-fpga/usrp3/tools/scripts/
$ ./uhd_image_builder_gui
然后将启动该应用程序:
1.选择构建目标:在此面板中列出可用的构建目标。此列表可能会有所不同,具体取决于该用户使用的FPGA存储库的哪个分支。仅列出了RFNoC目标。构建类型描述是:
HG:SFP +端口0上的1GigE,SFP +端口1上的10Gig
XG:两个SFP +端口上的10GigE
HLS:启用Vivado高级综合
sgX:E300设备的速度等级(1或3)
2.可用块列表:在此面板中列出了可包含在自定义设计中的可用块。该列表分离了Ettus Research提供的RFNoC模块和OOT模块以及用户添加的相应模块。鉴于X3xx和E3xx设备之间的硬件差异,当从左侧面板中选择不同的设备时,此列表将动态更改。这意味着必须单独为每个设备添加OOT模块。这是通过使用应用程序的Add OOT Blocks功能来完成的,详细信息在#7(添加OOT块)中进行了解释。
3.当前设计中的块:此部分提供有关给定USRP的MAX块数的信息(基于目标选择)。每个设备都可以添加最大数量的块。有关详细信息,请参阅本应用笔记中标记为“关于FPGA映像中块数的讨论”部分。
4.当前设计中的块:将通过添加可用块中的元素来填充此面板。此处列出的所有块都将编译到FPGA自定义映像中。每个设备都可以添加最大数量的块。有关详细信息,请参阅本应用笔记中标记为“关于FPGA映像中块数的讨论”部分。
5.添加按钮(>>):手动将中央面板中的块添加到设计中。
6.删除按钮(<<):从当前设计中删除块(左下方面板)
7.填写FIFO:通过选中此框,设计将填充任何可用/未指定的块插槽和FIFO。将被实例化的FIFO块的数量基于#3中解释的块数量的规则。当某些实现需要少于最大块数时,许多用户选择用FIFO块填充其设计。
8.打开Vivado GUI:在FPGA构建过程中打开Vivado GUI。这允许用户使用所有IP保存Vivado项目,并在Vivado GUI中进行开发。
9.清理IP:在新构建之前清除IP(重新编译所有IP)。
10.添加OOT块:通过将应用程序指向Makefile.srcs文件手动添加RFNoC Modtool生成的OOT模块,该文件位于{USER_PREFIX} / src / {USER-OOT-moddir} / rfnoc / fpga-srcs /目录。添加此文件后,块将显示在“适用于XXXX设备的OOT块”下
11.显示实例化文件:应用程序自动生成将由Vivado用于构建FPGA映像的实例化文件。通过单击此按钮,可以在开始构建之前查看和编辑此实例化文件。
12.从GRC导入:如果用户的GNU Radio流程图中已包含RFNoC块,则该应用程序可以读取流程图中的RFNoC块,并使用必要的RFNoC块填充应用程序当前设计部分中的块。注意:从开始构建之前,从.grc文件中提取的所有RFNoC块必须位于可用块列表中。
13.生成.bit文件:单击此按钮启动构建。
14. uhd_image_builder命令:带有参数的命令行命令在此处动态构建,因为用户选择了不同的选项。用户可以保存此命令以在下次构建/编译FPGA映像时使用,以避免再次选择所有选项。
注意:有关编译开始后期望的内容以及最终输出的其他信息,请参阅上一节的后一部分。
UHD集成
尽管FPGA上进行了数据处理,但主机软件仍然有很多责任让RFNoC应用程序正常运行。例如,它需要知道RFNoC块中哪些设置寄存器可用,或者块具有哪种输入和输出。所有这些信息都包含在Block Declaration中,这是一个UHD可读的XML文件。通常,需要在XML文件中嵌入一些简单的逻辑,我们可以使用一种名为Noc-Script的简单脚本语言来完成。每次执行应用程序时,都会立即将块声明文件的更改导入到UHD中,因此不需要设置软件开发工具链。
块声明文件声明的事物列表包括:
阻止名称和Noc-ID
寄存器
输入和输出(包括类型)
在某些情况下,需要额外的C ++代码才能从软件中正确控制块。在这种情况下,需要块控制器文件以及声明文件。在大多数情况下,UHD提供的默认块控制器就足够了,因此不需要编写C ++代码。编写自定义块控制器需要更多的努力,并且意味着必须设置编程工具链。编写自定义C ++块控制器的一个常见原因是,如果设置寄存器需要大量计算,这在块声明文件中是不可行的(例如,使用Noc-Script)。
块声明和块控制器(如果需要)的骨架代码可以通过RFNoC Modtool生成。
因为增益块不需要除了简单地读取和写入单个寄存器之外的任何内容,所以默认块控制器就足够了这个例子。但是,我们需要添加有关寄存器的信息。
打开位于/ rfnoc-tutorial / rfnoc / blocks目录中的gain.xml文件,并添加以下内容:
gain
gain
1111222233334444
GAIN
128
gain
double
1.0
GE($gain, 0.0) AND LE($gain, 32767.0)
Invalid gain.
SR_WRITE("GAIN", IROUND($gain))
in0
sc16
GNU无线电集成
GNU Radio是围绕块的概念构建的,与RFNoC类似。将RFNoC映射到应用程序时,会对每个RFNoC块映射到单个GNU Radio块进行简单约束。因此,在创建混合GNU Radio / RFNoC应用程序时,RFNoC和GNU Radio中发生的事件之间存在非常明显的1:1映射。
由于大多数RFNoC块从GNU Radio的角度来看彼此非常相似,因此通常不需要为另一个块编写C ++代码。相反,RFNoC提供的默认块可以使用适当的配置。但是,在某些情况下,可能需要或甚至需要编写自定义GNU Radio块以更具体地控制底层RFNoC块。 GNU Radio允许用C ++或Python编写块,但由于UHD和RFNoC没有Python API,因此需要用C ++编写RFNoC块的自定义包装器。 RFNoC Modtool将为此创建框架文件。
使用GNU Radio的最流行和最有效的方式是通过图形界面GNU Radio Companion(GRC)。 GRC需要对每个GNU Radio块进行单独描述才能在图形用户界面中使用,对于包含在GNU Radio块中的RFNoC块也是如此(即使使用通用RFNoC块包装器)。对于GNU Radio 3.7及更早版本,块的GRC绑定被编写为带有散布的Cheetah或Python语句的XML文件。有关如何编写这些文件的更详细教程,请参阅GNU Radio文档和相关教程。
GNU无线电广告代码
C ++或Python,虽然RFNoC块需要用C ++编写(如果有的话)
GNU Radio如何与RFNoC接口?
通过gr-ettus中的C ++基础架构代码
gr-ettus提供了一个基本的RFNoC块类
用户扩展其RFNoC块的基类
许多块可以“按原样”使用基类
没有C ++或Python代码!
rfnoc教程/ LIB / gain_impl.cc
增益块不需要任何额外的功能
GNU Radio Companion Bindings
XML
描述GRC的GNU Radio块
没有重新编译
GNU Radio Companion的要求
GNU Radio不是绝对必要的
关于如何编写它们的教程:
http://gnuradio.org/redmine/projects/gnuradio/wiki/GNURadioCompanion
RFNoC Modtool生成的骨架文件
打开位于rfnoc-tutorial / grc目录中的tutorial-gain.xml文件,编辑如下:
RFNoC: gain
tutorial_gain
tutorial
import tutorial
tutorial.gain(
self.device3,
uhd.stream_args( \# TX Stream Args
cpu_format="fc32",
otw_format="sc16",
args="gr_vlen={0},{1}".format(${grvlen}, "" if $grvlen == 1 else "spp={0}".format($grvlen)),
),
uhd.stream_args( \# RX Stream Args
cpu_format="fc32",
otw_format="sc16",
args="gr_vlen={0},{1}".format(${grvlen}, "" if $grvlen == 1 else "spp={0}".format($grvlen)),
),
$block_index, $device_index,
)
self.$(id).set_arg("gain", $gain)
set_arg("gain", $gain)
.
.
.
Gain
gain
1.0
real
in
complex
$grvlen
rfnoc
编译,安装和验证:
$ cd {USER_PREFIX}/src/rfnoc-tutorial/build
$ make install
$ uhd_usrp_probe
| | _____________________________________________________
| | /
| | | RFNoC blocks on this device:
| | |
| | | * DmaFIFO_0
| | | * Radio_0
| | | * Radio_1
| | | * gain_0
| | | * DDC_0
| | | * FFT_0
| | | * FIFO_0
| | | * FIFO_1
| | | * FIFO_2
注意:在没有出现gain_0但Block_0出现的情况下:很可能,块的XML块声明文件(参见UHD集成部分)包含与硬件中定义的任何NoC-ID不匹配的NoC-ID 部分设计。 用户必须确定描述文件是最新的并且NoC-ID在SW和HW侧匹配。 请参阅UHD集成部分以更新这些主机端文件。
测试出自定义块
此时,自定义增益RFNoc块(计算引擎)可以在GNU Radio流程图中使用。 下面是使用我们的新块以及它生成的输出应用程序的示例GRC流程图。
注意:复制块:在RFNoC域中,数据流不能像在GNU无线电域中那样容易地拆分。上面屏幕截图中描述的“复制”块用作流分割器。当“启用”时,它的主要目的是复制它在输入端获得的样本并将其放入输出中,但这里它也是RFNoC域和GNURadio域之间的边界。在上面的流程图中。在通过此边界之后,可以轻松地将数据流拆分为两个接收器以使它们同时运行(标准GNU无线电功能)。可以将GNU Radio模块直接连接到RFNoC模块而无需“复制”模块,但一次只能工作一个(其他模块必须被禁用)。从RFNoC域分割数据流的另一种方法是使用“RFNoC:分流”块,它将拆分RFNoC域中的流,但这在这里并不是很有用,因为我们无论如何都要进入GNURadio域。
故障排除
Xilinx Vivado
编译问题
合成失败
验证是否已安装所有正确的Xilinx必备软件。
其他有用的信息可以在以下Xilinx论坛帖子中找到:
https://forums.xilinx.com/t5/Synthesis/Synthesis-failed-without-reporting-any-error/td-p/686000
https://forums.xilinx.com/t5/Installation-and-Licensing/Vivado-on-Linux-synthesis-fails-with-no-error-message/td-p/732143
环境设置
uhd_image_builder.py脚本还将通过自动运行位于{USER_PREFIX} / src / uhd-fpga / usrp3 / top / {device}目录中的setupenv.sh来设置Xilinx Vivado环境。 setupenv.sh脚本假定Xilinx Vivado安装在/ opt / Xilinx / Vivado的默认位置。如果安装位于不同的目录中,则需要修改setupenv_base.sh脚本。该脚本位于:{USER_PREFIX} /src/uhd-fpga/usrp3_rfnoc/tools/scripts/setupenv_base.sh。
参考文件
以下参考文件包含在下面链接的gain_src.tar.gz存档中:
gain.xml
noc_block_gain.v
noc_block_gain_tb.sv
tutorial_gain.xml
rfnoc_gain.grc
媒体:获得src.tar.gz
链接和其他资源
RFNoC附加资源
视频:RFNoC入门视频教程
USRP邮件列表
RFNoC软件资源
RFNoC简介
RFNoC Deep Dive:FPGA
RFNoC Deep Dive:主机端
视频:RFNoC于2015年在Wireless @ Virginia Tech上发布
解释上面的Intro,FPGA和Host演示文稿的幻灯片(按此顺序)。
视频:这是2016年GRCon16上Martin Braun为我们设计的RFNoC生活
GNU无线电资源
GNU Radio OutOfTree模块教程
GNU无线电安装
GNU Radio教程
UHD资源
USRP邮件列表
UHD软件资源
USRP3构建说明
UHD手册
其他资源
Xilinx - AXI参考指南
UHD + GNU无线电应用笔记(Linux)
PyBOMBS