本文内容、所用开发板、配件等仅限与研发和学习使用,如有侵权,请联系我们进行删除!
目录
一、概要
二、实验环境
1. 软件环境
2. 硬件设备
三、Adding an FFT BLOCK
1. 修改 x310_rfnoc_image_core.yml 文件
2. rfnoc_image_builder 生成新的fpga image
3. uhd_image_loader 下载 fpga image 到 USRP
4. 实验结果
四、Adding an FFT Block to the Recive Chain
1. 修改 x310_rfnoc_image_core.yml 文件
2. rfnoc_image_builder 生成新的fpga image
3. uhd_image_loader 下载 fpga image 到 USRP
4. 实验结果
五、参考链接
一、概要
本文主要描述了如何对USRP X系列上的FPGA和射频片上网络(RFNoC™)的软件开发。它简要介绍了如何在默认的fpga image中添加自定义的rfnoc image和连接方式并生成编译生成新的fpga image,能够在主机上做软件开发。
二、实验环境
1. 软件环境
ubuntu 20.04 ; gnuradio 3.8 ; uhd 4.1.0
2. 硬件设备
USRP HM-X310
三、Adding an FFT BLOCK
1. 修改 x310_rfnoc_image_core.yml 文件
该文件位于 <uhd安装路径>/fpga/usrp3/top/x300下,请拷贝该文件并对副本进行修改,切勿直接修改原文件。
$ cd <repo>/fpga/usrp3/top/x300/
$ cp x310_rfnoc_image_core.yml <副本>.yml
修改后的内容为:
# General parameters
# -----------------------------------------
schema: rfnoc_imagebuilder_args # Identifier for the schema used to validate this file
copyright: 'Ettus Research, A National Instruments Brand' # Copyright information used in file headers
license: 'SPDX-License-Identifier: LGPL-3.0-or-later' # License information used in file headers
version: '1.0' # File version
rfnoc_version: '1.0' # RFNoC protocol version
chdr_width: 64 # Bit width of the CHDR bus for this image
device: 'x310'
default_target: 'X310_HG'# A list of all stream endpoints in design
# ----------------------------------------
stream_endpoints:ep0: # Stream endpoint namectrl: True # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 32768 # Ingress buffer size for dataep1: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 0 # Ingress buffer size for dataep2: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 32768 # Ingress buffer size for dataep3: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 0 # Ingress buffer size for dataep4: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 4096 # Ingress buffer size for dataep5: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 4096 # Ingress buffer size for dataep_fft:ctrl: Falsedata: Truebuff_size: 32768# A list of all NoC blocks in design
# ----------------------------------
noc_blocks:duc0: # NoC block nameblock_desc: 'duc.yml' # Block device descriptor fileparameters:NUM_PORTS: 1ddc0:block_desc: 'ddc.yml'parameters:NUM_PORTS: 2radio0:block_desc: 'radio_2x64.yml'duc1:block_desc: 'duc.yml'parameters:NUM_PORTS: 1ddc1:block_desc: 'ddc.yml'parameters:NUM_PORTS: 2radio1:block_desc: 'radio_2x64.yml'replay0:block_desc: 'replay.yml'parameters:NUM_PORTS: 2MEM_ADDR_W: 30fft0:block_desc: 'fft_1x64.yml'parameters:EN_FFT_SHIFT: 1
# A list of all static connections in design
# ------------------------------------------
# Format: A list of connection maps (list of key-value pairs) with the following keys
# - srcblk = Source block to connect
# - srcport = Port on the source block to connect
# - dstblk = Destination block to connect
# - dstport = Port on the destination block to connect
connections:# ep0 to radio0(0) - RFA TX- { srcblk: ep0, srcport: out0, dstblk: duc0, dstport: in_0 }- { srcblk: duc0, srcport: out_0, dstblk: radio0, dstport: in_0 }# radio0(0) to ep0 - RFA RX- { srcblk: radio0, srcport: out_0, dstblk: ddc0, dstport: in_0 }- { srcblk: ddc0, srcport: out_0, dstblk: ep0, dstport: in0 }# radio0(1) to ep1 - RFA RX- { srcblk: radio0, srcport: out_1, dstblk: ddc0, dstport: in_1 }- { srcblk: ddc0, srcport: out_1, dstblk: ep1, dstport: in0 }# ep2 to radio1(0) - RFB TX- { srcblk: ep2, srcport: out0, dstblk: duc1, dstport: in_0 }- { srcblk: duc1, srcport: out_0, dstblk: radio1, dstport: in_0 }# radio1(0) to ep2 - RFB RX- { srcblk: radio1, srcport: out_0, dstblk: ddc1, dstport: in_0 }- { srcblk: ddc1, srcport: out_0, dstblk: ep2, dstport: in0 }# radio1(1) to ep3 - RFB RX- { srcblk: radio1, srcport: out_1, dstblk: ddc1, dstport: in_1 }- { srcblk: ddc1, srcport: out_1, dstblk: ep3, dstport: in0 }# ep4 to replay0(0)- { srcblk: ep4, srcport: out0, dstblk: replay0, dstport: in_0 }# replay0(0) to ep4- { srcblk: replay0, srcport: out_0, dstblk: ep4, dstport: in0 }# ep5 to replay0(1)- { srcblk: ep5, srcport: out0, dstblk: replay0, dstport: in_1 }# replay0(1) to ep5- { srcblk: replay0, srcport: out_1, dstblk: ep5, dstport: in0 }# BSP Connections- { srcblk: radio0, srcport: ctrl_port, dstblk: _device_, dstport: ctrlport_radio0 }- { srcblk: radio1, srcport: ctrl_port, dstblk: _device_, dstport: ctrlport_radio1 }- { srcblk: replay0, srcport: axi_ram, dstblk: _device_, dstport: dram }- { srcblk: _device_, srcport: x300_radio0, dstblk: radio0, dstport: x300_radio }- { srcblk: _device_, srcport: x300_radio1, dstblk: radio1, dstport: x300_radio }- { srcblk: _device_, srcport: time_keeper, dstblk: radio0, dstport: time_keeper }- { srcblk: _device_, srcport: time_keeper, dstblk: radio1, dstport: time_keeper }- { srcblk: ep_fft, srcport: out0, dstblk: fft0, dstport: in_0 }- { srcblk: fft0, srcport: out_0, dstblk: ep_fft, dstport: in0 }
# A list of all clock domain connections in design
# ------------------------------------------
# Format: A list of connection maps (list of key-value pairs) with the following keys
# - srcblk = Source block to connect (Always "_device"_)
# - srcport = Clock domain on the source block to connect
# - dstblk = Destination block to connect
# - dstport = Clock domain on the destination block to connect
clk_domains:- { srcblk: _device_, srcport: radio, dstblk: radio0, dstport: radio }- { srcblk: _device_, srcport: ce, dstblk: ddc0, dstport: ce }- { srcblk: _device_, srcport: ce, dstblk: duc0, dstport: ce }- { srcblk: _device_, srcport: radio, dstblk: radio1, dstport: radio }- { srcblk: _device_, srcport: ce, dstblk: ddc1, dstport: ce }- { srcblk: _device_, srcport: ce, dstblk: duc1, dstport: ce }- { srcblk: _device_, srcport: dram, dstblk: replay0, dstport: mem }- { srcblk: _device_, srcport: ce, dstblk: fft0, dstport: ce }
2. rfnoc_image_builder 生成新的fpga image
在yml文件所处位置打开命令行终端,并运行如下命令生成对应的fpga image。
rfnoc_image_builder -F <uhd安装路径>/fpga/ -y x310_rfnoc_image_core -t X310_HG
该命令运行时间较长,请耐心等待......
命令运行完成后会在 <uhd安装路径>/fpga/usrp3/top/x300 目录下, 产生[build-X310_HG]文件夹,里面有 .bin 文件。
3. uhd_image_loader 下载 fpga image 到 USRP
使用uhd_image_loader命令,将.bin文件下载到fpga中
uhd_image_loader --fpga-path="./x300.bin" --args="type=x300"
4. 实验结果
终端运行 uhd_usrp_probe, 可见成功添加了 0/FFT#0 rfnoc block, 并且在框架中是单独连接的。
四、Adding an FFT Block to the Recive Chain
1. 修改 x310_rfnoc_image_core.yml 文件
该文件位于 <uhd安装路径>/fpga/usrp3/top/x300下,请拷贝该文件并对副本进行修改,切勿直接修改原文件。
$ cd <repo>/fpga/usrp3/top/x300/
$ cp x310_rfnoc_image_core.yml <副本>.yml
通过上面的例子,我们已经成功的往fpga image中添加了自己的rfnoc block。但是,这个fft block 是单独并没有与其他的rfnoc block进行静态连接。接下来,我们需要稍微修改一下yml文件,将fft block与内置的ddc block连接,这样我们就可以通过usrp直接得道fft之后的数据了。
修改后的内容为:
# General parameters
# -----------------------------------------
schema: rfnoc_imagebuilder_args # Identifier for the schema used to validate this file
copyright: 'Ettus Research, A National Instruments Brand' # Copyright information used in file headers
license: 'SPDX-License-Identifier: LGPL-3.0-or-later' # License information used in file headers
version: '1.0' # File version
rfnoc_version: '1.0' # RFNoC protocol version
chdr_width: 64 # Bit width of the CHDR bus for this image
device: 'x310'
default_target: 'X310_HG'# A list of all stream endpoints in design
# ----------------------------------------
stream_endpoints:ep0: # Stream endpoint namectrl: True # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 32768 # Ingress buffer size for dataep1: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 0 # Ingress buffer size for dataep2: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 32768 # Ingress buffer size for dataep3: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 0 # Ingress buffer size for dataep4: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 4096 # Ingress buffer size for dataep5: # Stream endpoint namectrl: False # Endpoint passes control trafficdata: True # Endpoint passes data trafficbuff_size: 4096 # Ingress buffer size for data# A list of all NoC blocks in design
# ----------------------------------
noc_blocks:duc0: # NoC block nameblock_desc: 'duc.yml' # Block device descriptor fileparameters:NUM_PORTS: 1ddc0:block_desc: 'ddc.yml'parameters:NUM_PORTS: 2radio0:block_desc: 'radio_2x64.yml'duc1:block_desc: 'duc.yml'parameters:NUM_PORTS: 1ddc1:block_desc: 'ddc.yml'parameters:NUM_PORTS: 2radio1:block_desc: 'radio_2x64.yml'replay0:block_desc: 'replay.yml'parameters:NUM_PORTS: 2MEM_ADDR_W: 30fft0:block_desc: 'fft_1x64.yml'parameters:EN_FFT_SHIFT: 1
# A list of all static connections in design
# ------------------------------------------
# Format: A list of connection maps (list of key-value pairs) with the following keys
# - srcblk = Source block to connect
# - srcport = Port on the source block to connect
# - dstblk = Destination block to connect
# - dstport = Port on the destination block to connect
connections:# ep0 to radio0(0) - RFA TX- { srcblk: ep0, srcport: out0, dstblk: duc0, dstport: in_0 }- { srcblk: duc0, srcport: out_0, dstblk: radio0, dstport: in_0 }# radio0(0) to ep0 - RFA RX- { srcblk: radio0, srcport: out_0, dstblk: ddc0, dstport: in_0 }- { srcblk: ddc0, srcport: out_0, dstblk: fft0, dstport: in_0 }- { srcblk: fft0, srcport: out_0, dstblk: ep0, dstport: in0 }# radio0(1) to ep1 - RFA RX- { srcblk: radio0, srcport: out_1, dstblk: ddc0, dstport: in_1 }- { srcblk: ddc0, srcport: out_1, dstblk: ep1, dstport: in0 }# ep2 to radio1(0) - RFB TX- { srcblk: ep2, srcport: out0, dstblk: duc1, dstport: in_0 }- { srcblk: duc1, srcport: out_0, dstblk: radio1, dstport: in_0 }# radio1(0) to ep2 - RFB RX- { srcblk: radio1, srcport: out_0, dstblk: ddc1, dstport: in_0 }- { srcblk: ddc1, srcport: out_0, dstblk: ep2, dstport: in0 }# radio1(1) to ep3 - RFB RX- { srcblk: radio1, srcport: out_1, dstblk: ddc1, dstport: in_1 }- { srcblk: ddc1, srcport: out_1, dstblk: ep3, dstport: in0 }# ep4 to replay0(0)- { srcblk: ep4, srcport: out0, dstblk: replay0, dstport: in_0 }# replay0(0) to ep4- { srcblk: replay0, srcport: out_0, dstblk: ep4, dstport: in0 }# ep5 to replay0(1)- { srcblk: ep5, srcport: out0, dstblk: replay0, dstport: in_1 }# replay0(1) to ep5- { srcblk: replay0, srcport: out_1, dstblk: ep5, dstport: in0 }# BSP Connections- { srcblk: radio0, srcport: ctrl_port, dstblk: _device_, dstport: ctrlport_radio0 }- { srcblk: radio1, srcport: ctrl_port, dstblk: _device_, dstport: ctrlport_radio1 }- { srcblk: replay0, srcport: axi_ram, dstblk: _device_, dstport: dram }- { srcblk: _device_, srcport: x300_radio0, dstblk: radio0, dstport: x300_radio }- { srcblk: _device_, srcport: x300_radio1, dstblk: radio1, dstport: x300_radio }- { srcblk: _device_, srcport: time_keeper, dstblk: radio0, dstport: time_keeper }- { srcblk: _device_, srcport: time_keeper, dstblk: radio1, dstport: time_keeper }# A list of all clock domain connections in design
# ------------------------------------------
# Format: A list of connection maps (list of key-value pairs) with the following keys
# - srcblk = Source block to connect (Always "_device"_)
# - srcport = Clock domain on the source block to connect
# - dstblk = Destination block to connect
# - dstport = Clock domain on the destination block to connect
clk_domains:- { srcblk: _device_, srcport: radio, dstblk: radio0, dstport: radio }- { srcblk: _device_, srcport: ce, dstblk: ddc0, dstport: ce }- { srcblk: _device_, srcport: ce, dstblk: duc0, dstport: ce }- { srcblk: _device_, srcport: radio, dstblk: radio1, dstport: radio }- { srcblk: _device_, srcport: ce, dstblk: ddc1, dstport: ce }- { srcblk: _device_, srcport: ce, dstblk: duc1, dstport: ce }- { srcblk: _device_, srcport: dram, dstblk: replay0, dstport: mem }- { srcblk: _device_, srcport: ce, dstblk: fft0, dstport: ce }
2. rfnoc_image_builder 生成新的fpga image
在yml文件所处位置打开命令行终端,并运行如下命令生成对应的fpga image。
rfnoc_image_builder -F <uhd安装路径>/fpga/ -y x310_rfnoc_image_core -t X310_HG
该命令运行时间较长,请耐心等待......
命令运行完成后会在 <uhd安装路径>/fpga/usrp3/top/x300 目录下, 产生[build-X310_HG]文件夹,里面有 .bin 文件。
3. uhd_image_loader 下载 fpga image 到 USRP
使用uhd_image_loader命令,将.bin文件下载到fpga中
uhd_image_loader --fpga-path="./x300.bin" --args="type=x300"
4. 实验结果
终端运行 uhd_usrp_probe, 可见成功添加了 0/FFT#0 rfnoc block, 并且成的导入了 Rx 接收链路中。
五、参考链接
1. 北京海曼无限信息技术有限公司
2. Getting Started with RFNoC in UHD 4.0 - Ettus Knowledge Base