aboutsummaryrefslogtreecommitdiffstats
path: root/host/examples/rfnoc-example
diff options
context:
space:
mode:
authorWade Fife <wade.fife@ettus.com>2021-03-04 16:27:24 -0600
committerWade Fife <wade.fife@ettus.com>2021-03-17 17:46:06 -0500
commitada6a4e46770d22d528b2b6fbc2bdd71e5e3064d (patch)
tree21ba4229fb195da6fc1da4907ec00aed85a07c6c /host/examples/rfnoc-example
parent866df135adb91299d1009c1b1d2053dd3112acda (diff)
downloaduhd-ada6a4e46770d22d528b2b6fbc2bdd71e5e3064d.tar.gz
uhd-ada6a4e46770d22d528b2b6fbc2bdd71e5e3064d.tar.bz2
uhd-ada6a4e46770d22d528b2b6fbc2bdd71e5e3064d.zip
examples: Add IP to OOT RFNoC gain example
This updates the gain example to show how to use RFNoC IP, in-tree Xilinx IP, and out-of-tree Xilinx IP in a custom RFNoC block.
Diffstat (limited to 'host/examples/rfnoc-example')
-rw-r--r--host/examples/rfnoc-example/fpga/Makefile.srcs12
-rw-r--r--host/examples/rfnoc-example/fpga/ip/cmplx_mul/Makefile.inc17
-rw-r--r--host/examples/rfnoc-example/fpga/ip/cmplx_mul/cmplx_mul.xci187
-rw-r--r--host/examples/rfnoc-example/fpga/rfnoc_block_gain/Makefile26
-rw-r--r--host/examples/rfnoc-example/fpga/rfnoc_block_gain/rfnoc_block_gain.v132
5 files changed, 335 insertions, 39 deletions
diff --git a/host/examples/rfnoc-example/fpga/Makefile.srcs b/host/examples/rfnoc-example/fpga/Makefile.srcs
index f95dab6ea..88a729c97 100644
--- a/host/examples/rfnoc-example/fpga/Makefile.srcs
+++ b/host/examples/rfnoc-example/fpga/Makefile.srcs
@@ -6,16 +6,18 @@
# We first need to figure out our own path, in case this file is being included
# from somewhere else (e.g., from a fpgadev/top/$device directory)
-RFNOC_EXAMPLE_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
+OOT_FPGA_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
# One include statement for every RFNoC block with its own subdirectory, which
# itself will contain a Makefile.srcs
-include $(RFNOC_EXAMPLE_DIR)/rfnoc_block_gain/Makefile.srcs
+include $(OOT_FPGA_DIR)/rfnoc_block_gain/Makefile.srcs
+
+include $(OOT_FPGA_DIR)/ip/cmplx_mul/Makefile.inc
+LIB_IP_XCI_SRCS += $(LIB_IP_CMPLX_MUL_SRCS)
# If there are additional modules or IP (other than what is in the RFNoC block
# subdirectories) that needs to get installed in order to synthesize blocks from
# this module, list them here:
-#RFNOC_OOT_SRCS += $(abspath $(addprefix ${RFNOC_EXAMPLE_DIR},
-#my_other_module.v \
-#ip/my_ip_core/my_ip_core.xci \
+#RFNOC_OOT_SRCS += $(abspath $(addprefix ${OOT_FPGA_DIR}, \
+#$(IP_BUILD_DIR)/cmplx_mul/cmplx_mul.xci \
#))
diff --git a/host/examples/rfnoc-example/fpga/ip/cmplx_mul/Makefile.inc b/host/examples/rfnoc-example/fpga/ip/cmplx_mul/Makefile.inc
new file mode 100644
index 000000000..14d456146
--- /dev/null
+++ b/host/examples/rfnoc-example/fpga/ip/cmplx_mul/Makefile.inc
@@ -0,0 +1,17 @@
+#
+# Copyright 2021 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: LGPL-3.0-or-later
+#
+
+include $(TOOLS_DIR)/make/viv_ip_builder.mak
+
+LIB_IP_CMPLX_MUL_SRCS = $(IP_BUILD_DIR)/cmplx_mul/cmplx_mul.xci
+
+LIB_IP_CMPLX_MUL_OUTS = $(addprefix $(IP_BUILD_DIR)/cmplx_mul/, \
+cmplx_mul.xci.out \
+synth/cmplx_mul.vhd \
+)
+
+$(LIB_IP_CMPLX_MUL_SRCS) $(LIB_IP_CMPLX_MUL_OUTS) : $(OOT_FPGA_DIR)/ip/cmplx_mul/cmplx_mul.xci
+ $(call BUILD_VIVADO_IP,cmplx_mul,$(ARCH),$(PART_ID),$(OOT_FPGA_DIR)/ip,$(IP_BUILD_DIR),0)
diff --git a/host/examples/rfnoc-example/fpga/ip/cmplx_mul/cmplx_mul.xci b/host/examples/rfnoc-example/fpga/ip/cmplx_mul/cmplx_mul.xci
new file mode 100644
index 000000000..9ba4231db
--- /dev/null
+++ b/host/examples/rfnoc-example/fpga/ip/cmplx_mul/cmplx_mul.xci
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<spirit:design xmlns:xilinx="http://www.xilinx.com" xmlns:spirit="http://www.spiritconsortium.org/XMLSchema/SPIRIT/1685-2009" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <spirit:vendor>xilinx.com</spirit:vendor>
+ <spirit:library>xci</spirit:library>
+ <spirit:name>unknown</spirit:name>
+ <spirit:version>1.0</spirit:version>
+ <spirit:componentInstances>
+ <spirit:componentInstance>
+ <spirit:instanceName>cmplx_mul</spirit:instanceName>
+ <spirit:componentRef spirit:vendor="xilinx.com" spirit:library="ip" spirit:name="cmpy" spirit:version="6.0"/>
+ <spirit:configurableElementValues>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ACLKEN_INTF.POLARITY">ACTIVE_LOW</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ACLK_INTF.CLK_DOMAIN"/>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ACLK_INTF.FREQ_HZ">10000000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ACLK_INTF.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ACLK_INTF.PHASE">0.000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.ARESETN_INTF.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.CLK_DOMAIN"/>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.FREQ_HZ">100000000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TKEEP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TLAST">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TREADY">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TSTRB">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.LAYERED_METADATA">undef</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.PHASE">0.000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TDATA_NUM_BYTES">10</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TDEST_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TID_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TUSER_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.CLK_DOMAIN"/>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.FREQ_HZ">100000000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TKEEP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TLAST">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TREADY">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TSTRB">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.LAYERED_METADATA">undef</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.PHASE">0.000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TDATA_NUM_BYTES">4</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TDEST_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TID_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TUSER_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.CLK_DOMAIN"/>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.FREQ_HZ">100000000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TKEEP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TLAST">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TREADY">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TSTRB">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.LAYERED_METADATA">undef</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.PHASE">0.000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TDATA_NUM_BYTES">4</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TDEST_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TID_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TUSER_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.CLK_DOMAIN"/>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.FREQ_HZ">100000000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TKEEP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TLAST">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TREADY">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TSTRB">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.INSERT_VIP">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.LAYERED_METADATA">undef</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.PHASE">0.000</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TDATA_NUM_BYTES">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TDEST_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TID_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TUSER_WIDTH">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_A_WIDTH">16</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_B_WIDTH">16</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_ACLKEN">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_ARESETN">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_A_TLAST">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_A_TUSER">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_B_TLAST">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_B_TUSER">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_CTRL_TLAST">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_HAS_S_AXIS_CTRL_TUSER">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_LATENCY">7</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_MULT_TYPE">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_M_AXIS_DOUT_TDATA_WIDTH">80</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_M_AXIS_DOUT_TUSER_WIDTH">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OPTIMIZE_GOAL">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_OUT_WIDTH">33</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_A_TDATA_WIDTH">32</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_A_TUSER_WIDTH">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_B_TDATA_WIDTH">32</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_B_TUSER_WIDTH">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_CTRL_TDATA_WIDTH">8</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_S_AXIS_CTRL_TUSER_WIDTH">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_THROTTLE_SCHEME">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_TLAST_RESOLUTION">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_VERBOSITY">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_XDEVICE">xc7k410t</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.C_XDEVICEFAMILY">kintex7</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.HAS_NEGATE">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.ROUND">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.SINGLE_OUTPUT">0</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="MODELPARAM_VALUE.USE_DSP_CASCADES">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ACLKEN">false</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.APortWidth">16</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ARESETN">true</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.ATUSERWidth">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.BPortWidth">16</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.BTUSERWidth">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.CTRLTUSERWidth">1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.Component_Name">testerific</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.FlowControl">Blocking</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasATLAST">true</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasATUSER">false</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasBTLAST">true</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasBTUSER">false</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasCTRLTLAST">false</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.HasCTRLTUSER">false</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.LatencyConfig">Automatic</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MinimumLatency">7</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.MultType">Use_Mults</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.OptimizeGoal">Performance</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.OutTLASTBehv">Pass_A_TLAST</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.OutputWidth">33</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PARAM_VALUE.RoundMode">Truncate</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.ARCHITECTURE">kintex7</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.BASE_BOARD_PART"/>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.BOARD_CONNECTIONS"/>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.DEVICE">xc7k410t</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.PACKAGE">fbg900</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.PREFHDL">VERILOG</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SILICON_REVISION"/>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SIMULATOR_LANGUAGE">MIXED</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.SPEEDGRADE">-1</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.STATIC_POWER"/>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.TEMPERATURE_GRADE"/>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.USE_RDI_CUSTOMIZATION">TRUE</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="PROJECT_PARAM.USE_RDI_GENERATION">TRUE</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.IPCONTEXT">IP_Flow</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.IPREVISION">17</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.MANAGED">TRUE</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">.</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2019.1.1_AR73068</spirit:configurableElementValue>
+ <spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
+ </spirit:configurableElementValues>
+ <spirit:vendorExtensions>
+ <xilinx:componentInstanceExtensions>
+ <xilinx:configElementInfos>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TKEEP" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TLAST" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TREADY" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.HAS_TSTRB" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TDEST_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.M_AXIS_DOUT.TID_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TKEEP" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TLAST" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TREADY" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.HAS_TSTRB" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TDEST_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_A.TID_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TKEEP" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TLAST" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TREADY" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.HAS_TSTRB" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TDEST_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_B.TID_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TKEEP" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TREADY" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.HAS_TSTRB" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TDATA_NUM_BYTES" xilinx:valueSource="auto"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TDEST_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="BUSIFPARAM_VALUE.S_AXIS_CTRL.TID_WIDTH" xilinx:valueSource="constant"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.ARESETN" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.FlowControl" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.HasATLAST" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.HasBTLAST" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.MinimumLatency" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.OptimizeGoal" xilinx:valueSource="user"/>
+ <xilinx:configElementInfo xilinx:referenceId="PARAM_VALUE.OutTLASTBehv" xilinx:valueSource="user"/>
+ </xilinx:configElementInfos>
+ </xilinx:componentInstanceExtensions>
+ </spirit:vendorExtensions>
+ </spirit:componentInstance>
+ </spirit:componentInstances>
+</spirit:design>
diff --git a/host/examples/rfnoc-example/fpga/rfnoc_block_gain/Makefile b/host/examples/rfnoc-example/fpga/rfnoc_block_gain/Makefile
index 1ff3046ee..0239041b9 100644
--- a/host/examples/rfnoc-example/fpga/rfnoc_block_gain/Makefile
+++ b/host/examples/rfnoc-example/fpga/rfnoc_block_gain/Makefile
@@ -19,24 +19,40 @@ include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
#-------------------------------------------------
# Design Specific
#-------------------------------------------------
+
+# In-tree IP
+LIB_IP_DIR = $(BASE_DIR)/../lib/ip
+include $(LIB_IP_DIR)/complex_multiplier/Makefile.inc
+
+# Out-of-tree IP
+OOT_FPGA_DIR = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/../
+include $(OOT_FPGA_DIR)/ip/cmplx_mul/Makefile.inc
+
# Include makefiles and sources for the DUT and its
# dependencies.
+include $(BASE_DIR)/../lib/rfnoc/Makefile.srcs
include $(BASE_DIR)/../lib/rfnoc/core/Makefile.srcs
include $(BASE_DIR)/../lib/rfnoc/utils/Makefile.srcs
include Makefile.srcs
-DESIGN_SRCS += $(abspath \
-$(RFNOC_CORE_SRCS) \
-$(RFNOC_UTIL_SRCS) \
-$(RFNOC_OOT_SRCS) \
+DESIGN_SRCS += $(abspath \
+$(RFNOC_SRCS) \
+$(RFNOC_CORE_SRCS) \
+$(RFNOC_UTIL_SRCS) \
+$(RFNOC_OOT_SRCS) \
+$(LIB_IP_CMPLX_MUL_SRCS) \
+$(LIB_IP_COMPLEX_MULTIPLIER_SRCS) \
)
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
-SIM_TOP = rfnoc_block_gain_tb
+SIM_TOP = rfnoc_block_gain_tb glbl
SIM_SRCS = \
+$(abspath $(IP_BUILD_DIR)/cmplx_mul/sim/cmplx_mul.vhd) \
+$(abspath $(IP_BUILD_DIR)/complex_multiplier/sim/complex_multiplier.vhd) \
$(abspath rfnoc_block_gain_tb.sv) \
+$(VIVADO_PATH)/data/verilog/src/glbl.v \
#-------------------------------------------------
# Bottom-of-Makefile
diff --git a/host/examples/rfnoc-example/fpga/rfnoc_block_gain/rfnoc_block_gain.v b/host/examples/rfnoc-example/fpga/rfnoc_block_gain/rfnoc_block_gain.v
index 929439a52..6f050e8bc 100644
--- a/host/examples/rfnoc-example/fpga/rfnoc_block_gain/rfnoc_block_gain.v
+++ b/host/examples/rfnoc-example/fpga/rfnoc_block_gain/rfnoc_block_gain.v
@@ -17,6 +17,11 @@
// CHDR_W : AXIS-CHDR data bus width
// MTU : Maximum transmission unit (i.e., maximum packet size in
// CHDR words is 2**MTU).
+// IP_OPTION : Select which IP to use for the complex multiply. Use one of
+// the following options:
+// HDL_IP = In-tree RFNoC HDL, with a DSP48E1 primitive
+// IN_TREE_IP = In-tree "complex_multiplier" (Xilinx IP)
+// OUT_OF_TREE_IP = Out-of-tree "cmplx_mul" (Xilinx IP)
//
`default_nettype none
@@ -25,7 +30,8 @@
module rfnoc_block_gain #(
parameter [9:0] THIS_PORTID = 10'd0,
parameter CHDR_W = 64,
- parameter [5:0] MTU = 10
+ parameter [5:0] MTU = 10,
+ parameter IP_OPTION = "HDL_IP"
)(
// RFNoC Framework Clocks and Resets
input wire rfnoc_chdr_clk,
@@ -250,36 +256,104 @@ module rfnoc_block_gain #(
wire mult_tvalid;
wire mult_tready;
- // Multiply complex sample by a real-valued gain. Only input the gain
- // (real_tvalid) when we have payload data to go in (cplx_tdata). That way
- // the current gain value always applies to the current sample. This assumes
- // that real_tready and cplx_tready have identical behavior.
+ // Multiply each complex sample by a real-valued gain. Only input the gain
+ // when we have payload data to go in (m_in_payload_tdata). That way the
+ // current gain value always applies to the current sample. This assumes that
+ // the tready of both inputs have identical behavior.
//
// Note that we receive the data with I on bits [31:16] and Q on bits [15:0],
- // but this does not matter to our multiplier.
- //
- mult_rc #(
- .WIDTH_REAL (16),
- .WIDTH_CPLX (16),
- .WIDTH_P (32),
- .DROP_TOP_P (5), // Must be 5 for a normal multiply in DSP48E1
- .LATENCY (4) // Turn on all pipeline registers in the DSP48E1
- ) mult_rc_i (
- .clk (axis_data_clk),
- .reset (axis_data_rst),
- .real_tdata (reg_gain),
- .real_tlast (m_in_payload_tlast),
- .real_tvalid (m_in_payload_tvalid),
- .real_tready (),
- .cplx_tdata (m_in_payload_tdata),
- .cplx_tlast (m_in_payload_tlast),
- .cplx_tvalid (m_in_payload_tvalid),
- .cplx_tready (m_in_payload_tready),
- .p_tdata (mult_tdata),
- .p_tlast (mult_tlast),
- .p_tvalid (mult_tvalid),
- .p_tready (mult_tready)
- );
+ // but the I/Q order does not matter to our complex multiplier.
+
+ generate
+ // Use a generate statement to choose which IP to use for the multiply.
+ // These all do the same thing and we only have multiple options to show
+ // how you can use IP from different locations.
+
+ if (IP_OPTION == "HDL_IP") begin : gen_rfnoc_ip
+ // Use the RFNoC mult_rc Verilog module, which uses a DSP48E1 primitive
+ mult_rc #(
+ .WIDTH_REAL (16),
+ .WIDTH_CPLX (16),
+ .WIDTH_P (32),
+ .DROP_TOP_P (5), // Must be 5 for a normal multiply in DSP48E1
+ .LATENCY (4) // Turn on all pipeline registers in the DSP48E1
+ ) mult_rc_i (
+ .clk (axis_data_clk),
+ .reset (axis_data_rst),
+ .real_tdata (reg_gain),
+ .real_tlast (m_in_payload_tlast),
+ .real_tvalid (m_in_payload_tvalid),
+ .real_tready (),
+ .cplx_tdata (m_in_payload_tdata),
+ .cplx_tlast (m_in_payload_tlast),
+ .cplx_tvalid (m_in_payload_tvalid),
+ .cplx_tready (m_in_payload_tready),
+ .p_tdata (mult_tdata),
+ .p_tlast (mult_tlast),
+ .p_tvalid (mult_tvalid),
+ .p_tready (mult_tready)
+ );
+
+ end else if (IP_OPTION == "IN_TREE_IP") begin : gen_in_tree_ip
+ // Use the in-tree "complex_multiplier" IP, which is a Xilinx Complex
+ // Multiplier LogiCORE IP located in the UHD repository in
+ // fpga/usrp3/lib/ip/.
+
+ // The LSB of the output is clipped in this IP, so double the gain to
+ // compensate. This limits the maximum gain in this version.
+ wire [15:0] gain = 2*reg_gain;
+
+ complex_multiplier complex_multiplier (
+ .aclk (axis_data_clk),
+ .aresetn (~axis_data_rst),
+ .s_axis_a_tdata ({16'b0, gain}),
+ .s_axis_a_tlast (m_in_payload_tlast),
+ .s_axis_a_tvalid (m_in_payload_tvalid),
+ .s_axis_a_tready (),
+ .s_axis_b_tdata (m_in_payload_tdata),
+ .s_axis_b_tlast (m_in_payload_tlast),
+ .s_axis_b_tvalid (m_in_payload_tvalid),
+ .s_axis_b_tready (m_in_payload_tready),
+ .s_axis_ctrl_tdata (8'd0),
+ .s_axis_ctrl_tvalid (1'b1),
+ .s_axis_ctrl_tready (),
+ .m_axis_dout_tdata (mult_tdata),
+ .m_axis_dout_tlast (mult_tlast),
+ .m_axis_dout_tvalid (mult_tvalid),
+ .m_axis_dout_tready (mult_tready)
+ );
+
+ end else if (IP_OPTION == "OUT_OF_TREE_IP") begin : gen_oot_ip
+ // Use the out-of-tree "cmplx_mul" IP, which is a Xilinx Complex
+ // Multiplier LogiCORE IP located in the IP directory of this example.
+
+ // This IP has a 33-bit output, but because it's AXI-Stream, each
+ // component is placed in a 5-byte word. Since our gain is real only,
+ // we'll never need all 33-bits.
+ wire [79:0] m_axis_dout_tdata;
+
+ cmplx_mul cmplx_mul_i (
+ .aclk (axis_data_clk),
+ .aresetn (~axis_data_rst),
+ .s_axis_a_tdata ({16'd0, reg_gain}),
+ .s_axis_a_tlast (m_in_payload_tlast),
+ .s_axis_a_tvalid (m_in_payload_tvalid),
+ .s_axis_a_tready (),
+ .s_axis_b_tdata (m_in_payload_tdata),
+ .s_axis_b_tlast (m_in_payload_tlast),
+ .s_axis_b_tvalid (m_in_payload_tvalid),
+ .s_axis_b_tready (m_in_payload_tready),
+ .m_axis_dout_tdata (m_axis_dout_tdata),
+ .m_axis_dout_tlast (mult_tlast),
+ .m_axis_dout_tvalid (mult_tvalid),
+ .m_axis_dout_tready (mult_tready)
+ );
+
+ assign mult_tdata[31: 0] = m_axis_dout_tdata[31: 0];
+ assign mult_tdata[63:32] = m_axis_dout_tdata[71:40];
+
+ end
+ endgenerate
// Clip the results
axi_clip_complex #(