aboutsummaryrefslogtreecommitdiffstats
path: root/host/utils
diff options
context:
space:
mode:
Diffstat (limited to 'host/utils')
-rw-r--r--host/utils/rfnoc_blocktool/rfnoc_create_verilog.py131
-rw-r--r--host/utils/rfnoc_blocktool/templates/Makefile48
-rw-r--r--host/utils/rfnoc_blocktool/templates/Makefile.srcs13
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako15
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako41
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako30
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako8
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako28
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako23
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako31
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako78
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako50
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako41
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako47
-rw-r--r--host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako58
-rw-r--r--host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako147
-rw-r--r--host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako151
-rw-r--r--host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako129
18 files changed, 1069 insertions, 0 deletions
diff --git a/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py b/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py
new file mode 100644
index 000000000..7b4f6cdeb
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/rfnoc_create_verilog.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# Copyright 2013-2015 Ettus Research LLC
+# Copyright 2018 Ettus Research, a National Instruments Brand
+#
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+"""
+Create a task for each file to generate from templates. A task is based on
+a named tuple to ease future extensions.
+Each task generates on result file by utilizing the BlockGenerator class.
+"""
+
+import argparse
+import datetime
+import os
+import re
+import sys
+from collections import namedtuple
+import six
+import mako.template
+import mako.lookup
+from mako import exceptions
+from ruamel import yaml
+
+
+class BlockGenerator:
+ """
+ Generates a new file from a template utilizing a YAML configuration passed
+ as argument.
+
+ Each BlockGenerator generate one file out of one template.
+ All substitution parameter used in the template must be given in the YAML
+ configuration. Exceptions: year (generated on the fly) and destination
+ (given as argument). The root object parsed from the YAML configuration is
+ config. All configuration items are represented as object members of config
+ (YAML dictionaries are resolved recursively).
+ """
+
+ def __init__(self, template_file):
+ """
+ Initializes a new generator based on template_file
+ :param template_file: file used as root template during rendering,
+ template file is assumed to be located in folder
+ 'modules' relative to this Python file.
+ """
+ self.template_file = template_file
+ self.year = datetime.datetime.now().year
+ self.parser = None
+ self.config = None
+ self.destination = None
+
+ def setup_parser(self):
+ """
+ Setup argument parser.
+
+ ArgumentParser is able to receive destination path and a file location
+ of the YAML configuration.
+ """
+ self.parser = argparse.ArgumentParser(
+ description="Generate RFNoC module out of yml description")
+ self.parser.add_argument("-c", "--config", required=True,
+ help="Path to yml configuration file")
+ self.parser.add_argument("-d", "--destination", required=True,
+ help="Destination path to write output files")
+
+ def setup(self):
+ """
+ Prepare generator for template substitution.
+
+ Results of setup are save in member variables and are accessible for
+ further template processing.
+ self.year current year (for copyright headers)
+ self.destination root path where template generation results are placed
+ self.config everything that was passed as YAML format
+ configuration
+ """
+ args = self.parser.parse_args()
+ self.year = datetime.datetime.now().year
+ self.destination = args.destination
+ os.makedirs(self.destination, exist_ok=True)
+ with open(args.config) as stream:
+ self.config = yaml.safe_load(stream)
+
+ def run(self):
+ """
+ Do template substitution for destination template using YAML
+ configuration passed by arguments.
+
+ Template substitution is done in memory. The result is written to a file
+ where the destination folder is given by the argument parser and the
+ final filename is derived from the template file by substitute template
+ by the module name from the YAML configuration.
+ """
+ lookup = mako.lookup.TemplateLookup(directories=['.'])
+ filename = os.path.join("templates", self.template_file)
+ tpl = mako.template.Template(filename=filename, lookup=lookup,
+ strict_undefined=True)
+ # Render and return
+ try:
+ block = tpl.render(**{"config": self.config,
+ "year": self.year,
+ "destination": self.destination,})
+ except:
+ print(exceptions.text_error_template().render())
+ sys.exit(1)
+
+ filename = self.template_file
+ # pylint: disable=no-member
+ filename = re.sub(r"template(.*)\.mako",
+ r"%s\1" % self.config['module_name'],
+ filename)
+ fullpath = os.path.join(self.destination, filename)
+
+ with open(fullpath, "w") as stream:
+ stream.write(block)
+
+
+if __name__ == "__main__":
+ Task = namedtuple("Task", "name")
+ TASKS = [Task(name="noc_shell_template.v.mako"),
+ Task(name="rfnoc_block_template.v.mako"),
+ Task(name="rfnoc_block_template_tb.sv.mako"),
+ Task(name="Makefile"),
+ Task(name="Makefile.srcs")]
+ for task in TASKS:
+ generator = BlockGenerator(task.name)
+ generator.setup_parser()
+ generator.setup()
+ generator.run()
diff --git a/host/utils/rfnoc_blocktool/templates/Makefile b/host/utils/rfnoc_blocktool/templates/Makefile
new file mode 100644
index 000000000..25e61c05b
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright 2019 Ettus Research, A National Instruments Company
+#
+# SPDX-License-Identifier: LGPL-3.0-or-later
+#
+
+#-------------------------------------------------
+# Top-of-Makefile
+#-------------------------------------------------
+# Define BASE_DIR to point to the "top" dir
+BASE_DIR = $(abspath ../../../../top)
+# Include viv_sim_preample after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# Design Specific
+#-------------------------------------------------
+# Include makefiles and sources for the DUT and its dependencies
+include $(BASE_DIR)/../lib/erfnoc/core/Makefile.srcs
+include $(BASE_DIR)/../lib/erfnoc/utils/Makefile.srcs
+include Makefile.srcs
+
+DESIGN_SRCS += $(abspath ${"\\"}
+$(RFNOC_CORE_SRCS) ${"\\"}
+$(RFNOC_UTIL_SRCS) ${"\\"}
+$(RFNOC_BLOCK_${config.module_name.upper()}_SRCS) ${"\\"}
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+include $(BASE_DIR)/../sim/erfnoc/Makefile.srcs
+
+SIM_TOP = rfnoc_block_${config.module_name}_tb
+
+SIM_SRCS = ${"\\"}
+$(abspath rfnoc_block_${config.module_name}_tb.sv) ${"\\"}
+$(SIM_ERFNOC_SRCS)
+
+# MODELSIM_USER_DO = $(abspath wave.do)
+
+#-------------------------------------------------
+# Bottom-of-Makefile
+#-------------------------------------------------
+# Include all simulator specific makefiles here
+# Each should define a unique target to simulate
+# e.g. xsim, vsim, etc and a common "clean" target
+include $(BASE_DIR)/../tools/make/viv_simulator.mak
diff --git a/host/utils/rfnoc_blocktool/templates/Makefile.srcs b/host/utils/rfnoc_blocktool/templates/Makefile.srcs
new file mode 100644
index 000000000..f346007af
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/Makefile.srcs
@@ -0,0 +1,13 @@
+#
+# Copyright 2018 Ettus Research, A National Instruments Company
+#
+# SPDX-License-Identifier: LGPL-3.0-or-later
+#
+
+${'##################################################'}
+# RFNoC Utility Sources
+${'##################################################'}
+RFNOC_BLOCK_${config.module_name.upper()}_SRCS = $(abspath $(addprefix $(BASE_DIR)/../lib/erfnoc/blocks/${destination}/, ${"\\"}
+rfnoc_block_${config.module_name}.v ${"\\"}
+noc_shell_${config.module_name}.v ${"\\"}
+))
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako
new file mode 100644
index 000000000..ff619b6d9
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_connect_template.mako
@@ -0,0 +1,15 @@
+<%page args="num_inputs, num_outputs"/>
+
+%for idx, input in enumerate(config['data']['inputs']):
+ .m_${input}_chdr_tdata(${input}_chdr_tdata),
+ .m_${input}_chdr_tlast(${input}_chdr_tlast),
+ .m_${input}_chdr_tvalid(${input}_chdr_tvalid),
+ .m_${input}_chdr_tready(${input}_chdr_tready)${"," if (idx < num_inputs -1) or (num_outputs > 0) else ""}
+%endfor
+
+%for idx, output in enumerate(config['data']['outputs']):
+ .s_${output}_chdr_tdata(${output}_chdr_tdata),
+ .s_${output}_chdr_tlast(${output}_chdr_tlast),
+ .s_${output}_chdr_tvalid(${output}_chdr_tvalid),
+ .s_${output}_chdr_tready(${output}_chdr_tready)${"," if (idx < num_outputs -1) else ""}
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako
new file mode 100644
index 000000000..bcb23dff6
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_modules_template.mako
@@ -0,0 +1,41 @@
+%for idx, input in enumerate(config['data']['inputs']):
+ chdr_to_chdr_data #(
+ .CHDR_W(CHDR_W)
+ ) chdr_to_chdr_data_i${idx} (
+ .axis_chdr_clk(rfnoc_chdr_clk),
+ .axis_chdr_rst(rfnoc_chdr_rst),
+ .s_axis_chdr_tdata(s_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]),
+ .s_axis_chdr_tlast(s_rfnoc_chdr_tlast[${idx}]),
+ .s_axis_chdr_tvalid(s_rfnoc_chdr_tvalid[${idx}]),
+ .s_axis_chdr_tready(s_rfnoc_chdr_tready[${idx}]),
+ .m_axis_chdr_tdata(m_${input}_chdr_tdata),
+ .m_axis_chdr_tlast(m_${input}_chdr_tlast),
+ .m_axis_chdr_tvalid(m_${input}_chdr_tvalid),
+ .m_axis_chdr_tready(m_${input}_chdr_tready),
+ .flush_en(data_i_flush_en),
+ .flush_timeout(data_i_flush_timeout),
+ .flush_active(data_i_flush_active[${idx}]),
+ .flush_done(data_i_flush_done[${idx}])
+ );
+%endfor
+
+%for idx, output in enumerate(config['data']['outputs']):
+ chdr_to_chdr_data #(
+ .CHDR_W(CHDR_W)
+ ) chdr_to_chdr_data_o${idx} (
+ .axis_chdr_clk(rfnoc_chdr_clk),
+ .axis_chdr_rst(rfnoc_chdr_rst),
+ .m_axis_chdr_tdata(m_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]),
+ .m_axis_chdr_tlast(m_rfnoc_chdr_tlast[${idx}]),
+ .m_axis_chdr_tvalid(m_rfnoc_chdr_tvalid[${idx}]),
+ .m_axis_chdr_tready(m_rfnoc_chdr_tready[${idx}]),
+ .s_axis_chdr_tdata(s_${output}_chdr_tdata),
+ .s_axis_chdr_tlast(s_${output}_chdr_tlast),
+ .s_axis_chdr_tvalid(s_${output}_chdr_tvalid),
+ .s_axis_chdr_tready(s_${output}_chdr_tready),
+ .flush_en(data_o_flush_en),
+ .flush_timeout(data_o_flush_timeout),
+ .flush_active(data_o_flush_active[${idx}]),
+ .flush_done(data_o_flush_done[${idx}])
+ );
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako
new file mode 100644
index 000000000..9453c8fd1
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_chdr_wires_template.mako
@@ -0,0 +1,30 @@
+<%page args="mode, num_inputs, num_outputs"/>\
+
+<%
+ if mode == "shell":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ in_wire = "input "
+ out_wire = "output "
+ term = ","
+ elif mode == "block":
+ sl_pre = ""
+ ma_pre = ""
+ in_wire = ""
+ out_wire = ""
+ term=";"
+%>\
+%for idx, port in enumerate(config['data']['inputs']):
+ // Payload Stream to User Logic: ${port}
+ ${out_wire}wire [CHDR_W-1:0] ${ma_pre}${port}_chdr_tdata${term}
+ ${out_wire}wire ${ma_pre}${port}_chdr_tlast${term}
+ ${out_wire}wire ${ma_pre}${port}_chdr_tvalid${term}
+ ${in_wire}wire ${ma_pre}${port}_chdr_tready${term if (term == ";") or (idx < num_inputs -1) or (num_outputs > 0) else ""}
+%endfor
+
+%for idx, port in enumerate(config['data']['outputs']):
+ ${in_wire}wire [CHDR_W-1:0] ${sl_pre}${port}_chdr_tdata${term}
+ ${in_wire}wire ${sl_pre}${port}_chdr_tlast${term}
+ ${in_wire}wire ${sl_pre}${port}_chdr_tvalid${term}
+ ${out_wire}wire ${sl_pre}${port}_chdr_tready${term if (term == ";") or (idx < num_outputs -1) else ""}
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako
new file mode 100644
index 000000000..cefc97a22
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_connect_template.mako
@@ -0,0 +1,8 @@
+ .m_axis_ctrl_tdata(m_axis_ctrl_tdata),
+ .m_axis_ctrl_tlast(m_axis_ctrl_tlast),
+ .m_axis_ctrl_tvalid(m_axis_ctrl_tvalid),
+ .m_axis_ctrl_tready(m_axis_ctrl_tready),
+ .s_axis_ctrl_tdata(s_axis_ctrl_tdata),
+ .s_axis_ctrl_tlast(s_axis_ctrl_tlast),
+ .s_axis_ctrl_tvalid(s_axis_ctrl_tvalid),
+ .s_axis_ctrl_tready(s_axis_ctrl_tready),
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako
new file mode 100644
index 000000000..4c349b11b
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_modules_template.mako
@@ -0,0 +1,28 @@
+<%!
+import math
+%>
+ axis_ctrl_endpoint #(
+ .SYNC_CLKS(${1 if config['control']['clk_domain'] == "rfnoc_ctrl" else 0}),
+ .SLAVE_FIFO_SIZE(${math.ceil(math.log2(config['control']['fifo_depth']))})
+ ) axis_ctrl_endpoint_i (
+ .rfnoc_ctrl_clk(rfnoc_ctrl_clk),
+ .rfnoc_ctrl_rst(rfnoc_ctrl_rst),
+ .axis_ctrl_clk(axis_ctrl_clk),
+ .axis_ctrl_rst(axis_ctrl_rst),
+ .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata),
+ .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast),
+ .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid),
+ .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready),
+ .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata),
+ .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast),
+ .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid),
+ .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready),
+ .s_axis_ctrl_tdata(s_axis_ctrl_tdata),
+ .s_axis_ctrl_tlast(s_axis_ctrl_tlast),
+ .s_axis_ctrl_tvalid(s_axis_ctrl_tvalid),
+ .s_axis_ctrl_tready(s_axis_ctrl_tready),
+ .m_axis_ctrl_tdata(m_axis_ctrl_tdata),
+ .m_axis_ctrl_tlast(m_axis_ctrl_tlast),
+ .m_axis_ctrl_tvalid(m_axis_ctrl_tvalid),
+ .m_axis_ctrl_tready(m_axis_ctrl_tready)
+ );
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako
new file mode 100644
index 000000000..dd15bd100
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_ctrl_wires_template.mako
@@ -0,0 +1,23 @@
+<%page args="mode"/>\
+<%
+ if mode == "shell":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ in_wire = "input "
+ out_wire = "output "
+ term = ","
+ elif mode == "block":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ in_wire = ""
+ out_wire = ""
+ term = ";"
+%>\
+ ${out_wire}wire [31:0] ${ma_pre}axis_ctrl_tdata${term}
+ ${out_wire}wire ${ma_pre}axis_ctrl_tlast${term}
+ ${out_wire}wire ${ma_pre}axis_ctrl_tvalid${term}
+ ${in_wire}wire ${ma_pre}axis_ctrl_tready${term}
+ ${in_wire}wire [31:0] ${sl_pre}axis_ctrl_tdata${term}
+ ${in_wire}wire ${sl_pre}axis_ctrl_tlast${term}
+ ${in_wire}wire ${sl_pre}axis_ctrl_tvalid${term}
+ ${out_wire}wire ${sl_pre}axis_ctrl_tready${term}
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako
new file mode 100644
index 000000000..c78946289
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_connect_template.mako
@@ -0,0 +1,31 @@
+<%page args="num_inputs, num_outputs"/>\
+\
+%for idx, input in enumerate(config['data']['inputs']):
+ // Payload Stream to User Logic: ${input}
+ .m_${input}_payload_tdata(${input}_payload_tdata),
+ .m_${input}_payload_tkeep(${input}_payload_tkeep),
+ .m_${input}_payload_tlast(${input}_payload_tlast),
+ .m_${input}_payload_tvalid(${input}_payload_tvalid),
+ .m_${input}_payload_tready(${input}_payload_tready),
+ // Context Stream to User Logic: ${input}
+ .m_${input}_context_tdata(${input}_context_tdata),
+ .m_${input}_context_tuser(${input}_context_tuser),
+ .m_${input}_context_tlast(${input}_context_tlast),
+ .m_${input}_context_tvalid(${input}_context_tvalid),
+ .m_${input}_context_tready(${input}_context_tready)${"," if (idx < num_inputs - 1) or (num_outputs > 0) else ""}
+%endfor
+
+%for idx, output in enumerate(config['data']['outputs']):
+ // Payload Stream from User Logic: ${output}
+ .s_${output}_payload_tdata(${output}_payload_tdata),
+ .s_${output}_payload_tkeep(${output}_payload_tkeep),
+ .s_${output}_payload_tlast(${output}_payload_tlast),
+ .s_${output}_payload_tvalid(${output}_payload_tvalid),
+ .s_${output}_payload_tready(${output}_payload_tready),
+ // Context Stream from User Logic: ${output}
+ .s_${output}_context_tdata(${output}_context_tdata),
+ .s_${output}_context_tuser(${output}_context_tuser),
+ .s_${output}_context_tlast(${output}_context_tlast),
+ .s_${output}_context_tvalid(${output}_context_tvalid),
+ .s_${output}_context_tready(${output}_context_tready)${"," if (idx < num_outputs -1) else ""}
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako
new file mode 100644
index 000000000..c181eeedd
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_modules_template.mako
@@ -0,0 +1,78 @@
+
+%for idx, input in enumerate(config['data']['inputs']):
+ <%
+ port_tmp = config['data']['inputs'][input]
+ %>
+ chdr_to_axis_raw_data #(
+ .CHDR_W(CHDR_W),
+ .ITEM_W(${port_tmp['item_width']}),
+ .NIPC(${port_tmp['nipc']}),
+ .SYNC_CLKS(${1 if config['data']['clk_domain'] == "rfnoc_chdr" else 0}),
+ .CONTEXT_FIFO_SIZE(${port_tmp['context_fifo_depth']}),
+ .PAYLOAD_FIFO_SIZE(${port_tmp['payload_fifo_depth']}),
+ .CONTEXT_PREFETCH_EN(1)
+ ) chdr_to_axis_raw_data_i${idx} (
+ .axis_chdr_clk(rfnoc_chdr_clk),
+ .axis_chdr_rst(rfnoc_chdr_rst),
+ .axis_data_clk(axis_data_clk),
+ .axis_data_rst(axis_data_rst),
+ .s_axis_chdr_tdata(s_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]),
+ .s_axis_chdr_tlast(s_rfnoc_chdr_tlast[${idx}]),
+ .s_axis_chdr_tvalid(s_rfnoc_chdr_tvalid[${idx}]),
+ .s_axis_chdr_tready(s_rfnoc_chdr_tready[${idx}]),
+ .m_axis_payload_tdata(m_${input}_payload_tdata),
+ .m_axis_payload_tkeep(m_${input}_payload_tkeep),
+ .m_axis_payload_tlast(m_${input}_payload_tlast),
+ .m_axis_payload_tvalid(m_${input}_payload_tvalid),
+ .m_axis_payload_tready(m_${input}_payload_tready),
+ .m_axis_context_tdata(m_${input}_context_tdata),
+ .m_axis_context_tuser(m_${input}_context_tuser),
+ .m_axis_context_tlast(m_${input}_context_tlast),
+ .m_axis_context_tvalid(m_${input}_context_tvalid),
+ .m_axis_context_tready(m_${input}_context_tready),
+ .flush_en(data_i_flush_en),
+ .flush_timeout(data_i_flush_timeout),
+ .flush_active(data_i_flush_active[${idx}]),
+ .flush_done(data_i_flush_done[${idx}])
+ );
+%endfor
+
+%for idx, output in enumerate(config['data']['outputs']):
+ <%
+ port_tmp = config['data']['outputs'][output]
+ %>
+ axis_raw_data_to_chdr #(
+ .CHDR_W(CHDR_W),
+ .ITEM_W(${port_tmp['item_width']}),
+ .NIPC(${port_tmp['nipc']}),
+ .SYNC_CLKS(${1 if config['data']['clk_domain'] == "rfnoc_chdr" else 0}),
+ .CONTEXT_FIFO_SIZE(${port_tmp['context_fifo_depth']}),
+ .PAYLOAD_FIFO_SIZE(${port_tmp['payload_fifo_depth']}),
+ .CONTEXT_PREFETCH_EN(1),
+ .MTU(MTU)
+ ) axis_raw_data_to_chdr_i${idx} (
+ .axis_chdr_clk(rfnoc_chdr_clk),
+ .axis_chdr_rst(rfnoc_chdr_rst),
+ .axis_data_clk(axis_data_clk),
+ .axis_data_rst(axis_data_rst),
+ .m_axis_chdr_tdata(m_rfnoc_chdr_tdata[(${idx}*CHDR_W)+:CHDR_W]),
+ .m_axis_chdr_tlast(m_rfnoc_chdr_tlast[${idx}]),
+ .m_axis_chdr_tvalid(m_rfnoc_chdr_tvalid[${idx}]),
+ .m_axis_chdr_tready(m_rfnoc_chdr_tready[${idx}]),
+ .s_axis_payload_tdata(s_${output}_payload_tdata),
+ .s_axis_payload_tkeep(s_${output}_payload_tkeep),
+ .s_axis_payload_tlast(s_${output}_payload_tlast),
+ .s_axis_payload_tvalid(s_${output}_payload_tvalid),
+ .s_axis_payload_tready(s_${output}_payload_tready),
+ .s_axis_context_tdata(s_${output}_context_tdata),
+ .s_axis_context_tuser(s_${output}_context_tuser),
+ .s_axis_context_tlast(s_${output}_context_tlast),
+ .s_axis_context_tvalid(s_${output}_context_tvalid),
+ .s_axis_context_tready(s_${output}_context_tready),
+ .framer_errors(),
+ .flush_en(data_o_flush_en),
+ .flush_timeout(data_o_flush_timeout),
+ .flush_active(data_o_flush_active[${idx}]),
+ .flush_done(data_o_flush_done[${idx}])
+ );
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako
new file mode 100644
index 000000000..abb8ef5e0
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/axis_raw_wires_template.mako
@@ -0,0 +1,50 @@
+<%page args="mode, num_inputs, num_outputs"/>\
+<%
+ if mode == "shell":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ in_wire = "input "
+ out_wire = "output "
+ term = ","
+ elif mode == "block":
+ sl_pre = ""
+ ma_pre = ""
+ in_wire = ""
+ out_wire = ""
+ term = ";"
+%>\
+%for idx, port in enumerate(config['data']['inputs']):
+ <%
+ port_tmp = config['data']['inputs'][port]
+ %>\
+ // Payload Stream to User Logic: ${port}
+ ${out_wire}wire [${port_tmp['item_width']*port_tmp['nipc']-1}:0] ${ma_pre}${port}_payload_tdata${term}
+ ${out_wire}wire [${port_tmp['nipc']-1}:0] ${ma_pre}${port}_payload_tkeep${term}
+ ${out_wire}wire ${ma_pre}${port}_payload_tlast${term}
+ ${out_wire}wire ${ma_pre}${port}_payload_tvalid${term}
+ ${in_wire}wire ${ma_pre}${port}_payload_tready${term}
+ // Context Stream to User Logic: ${port}
+ ${out_wire}wire [CHDR_W-1:0] ${ma_pre}${port}_context_tdata${term}
+ ${out_wire}wire [3:0] ${ma_pre}${port}_context_tuser${term}
+ ${out_wire}wire ${ma_pre}${port}_context_tlast${term}
+ ${out_wire}wire ${ma_pre}${port}_context_tvalid${term}
+ ${in_wire}wire ${ma_pre}${port}_context_tready${term if (term == ";") or (idx < num_inputs - 1) or (num_outputs > 0) else ""}
+%endfor
+
+%for idx, port in enumerate(config['data']['outputs']):
+ <%
+ port_tmp = config['data']['outputs'][port]
+ %>\
+ // Payload Stream from User Logic: ${port}
+ ${in_wire}wire [${port_tmp['item_width'] * port_tmp['nipc'] - 1}:0] ${sl_pre}${port}_payload_tdata${term}
+ ${in_wire}wire [${port_tmp['nipc'] - 1}:0] ${sl_pre}${port}_payload_tkeep${term}
+ ${in_wire}wire ${sl_pre}${port}_payload_tlast${term}
+ ${in_wire}wire ${sl_pre}${port}_payload_tvalid${term}
+ ${out_wire}wire ${sl_pre}${port}_payload_tready${term}
+ // Context Stream from User Logic: ${port}
+ ${in_wire}wire [CHDR_W-1:0] ${sl_pre}${port}_context_tdata${term}
+ ${in_wire}wire [3:0] ${sl_pre}${port}_context_tuser${term}
+ ${in_wire}wire ${sl_pre}${port}_context_tlast${term}
+ ${in_wire}wire ${sl_pre}${port}_context_tvalid${term}
+ ${out_wire}wire ${sl_pre}${port}_context_tready${term if (term == ";") or (idx < num_outputs -1) else ""}
+%endfor
diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako
new file mode 100644
index 000000000..944f4af16
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_connect_template.mako
@@ -0,0 +1,41 @@
+ // Control Port Master
+ .m_ctrlport_req_wr(m_ctrlport_req_wr),
+ .m_ctrlport_req_rd(m_ctrlport_req_rd),
+ .m_ctrlport_req_addr(m_ctrlport_req_addr),
+ .m_ctrlport_req_data(m_ctrlport_req_data),
+%if config['control']['ctrlport']['byte_mode']:
+ .m_ctrlport_req_byte_en(m_ctrlport_req_byte_en),
+%endif
+%if config['control']['ctrlport']['timed']:
+ .m_ctrlport_req_has_time(m_ctrlport_req_has_time),
+ .m_ctrlport_req_time(m_ctrlport_req_time),
+%endif
+ .m_ctrlport_resp_ack(m_ctrlport_resp_ack),
+%if config['control']['ctrlport']['has_status']:
+ .m_ctrlport_resp_status(m_ctrlport_resp_status),
+%endif
+ .m_ctrlport_resp_data(m_ctrlport_resp_data),
+%if config['control']['interface_direction'] != "slave":
+ // Control Port Slave
+ .s_ctrlport_req_wr(s_ctrlport_req_wr),
+ .s_ctrlport_req_rd(s_ctrlport_req_rd),
+ .s_ctrlport_req_addr(s_ctrlport_req_addr),
+ .s_ctrlport_req_portid(s_ctrlport_req_portid),
+ %if config['control']['interface_direction'] == "remote_master_slave":
+ .s_ctrlport_req_rem_epid(s_ctrlport_req_rem_epid),
+ .s_ctrlport_req_rem_portid(s_ctrlport_req_rem_portid),
+ %endif
+ .s_ctrlport_req_data(s_ctrlport_req_data),
+ %if config['control']['ctrlport']['byte_mode']:
+ .s_ctrlport_req_byte_en(s_ctrlport_req_byte_en),
+ %endif
+ %if config['control']['ctrlport']['timed']:
+ .s_ctrlport_req_has_time(s_ctrlport_req_has_time),
+ .s_ctrlport_req_time(s_ctrlport_req_time),
+ %endif
+ .s_ctrlport_resp_ack(s_ctrlport_resp_ack),
+ %if config['control']['ctrlport']['has_status']:
+ .s_ctrlport_resp_status(s_ctrlport_resp_status),
+ %endif
+ .s_ctrlport_resp_data(s_ctrlport_resp_data),
+%endif
diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako
new file mode 100644
index 000000000..9aecc2b80
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_modules_template.mako
@@ -0,0 +1,47 @@
+<%!
+import math
+%>
+ ctrlport_endpoint #(
+ .THIS_PORTID(THIS_PORTID),
+ .SYNC_CLKS(${1 if config['control']['clk_domain'] == "rfnoc_ctrl" else 0}),
+ .AXIS_CTRL_MST_EN(${int(config['control']['interface_direction'] != "slave")}),
+ .AXIS_CTRL_SLV_EN(1),
+ .SLAVE_FIFO_SIZE(${math.ceil(math.log2(config['control']['fifo_depth']))})
+ ) ctrlport_endpoint_i (
+ .rfnoc_ctrl_clk(rfnoc_ctrl_clk),
+ .rfnoc_ctrl_rst(rfnoc_ctrl_rst),
+ .ctrlport_clk(ctrlport_clk),
+ .ctrlport_rst(ctrlport_rst),
+ .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata),
+ .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast),
+ .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid),
+ .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready),
+ .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata),
+ .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast),
+ .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid),
+ .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready),
+ .m_ctrlport_req_wr(m_ctrlport_req_wr),
+ .m_ctrlport_req_rd(m_ctrlport_req_rd),
+ .m_ctrlport_req_addr(m_ctrlport_req_addr),
+ .m_ctrlport_req_data(m_ctrlport_req_data),
+ .m_ctrlport_req_byte_en(${"m_ctrlport_req_byte_en" if config['control']['ctrlport']['byte_mode'] else ""}),
+ .m_ctrlport_req_has_time(${"m_ctrlport_req_has_time" if config['control']['ctrlport']['timed'] else ""}),
+ .m_ctrlport_req_time(${"m_ctrlport_req_time" if config['control']['ctrlport']['timed'] else ""}),
+ .m_ctrlport_resp_ack(m_ctrlport_resp_ack),
+ .m_ctrlport_resp_status(${"m_ctrlport_resp_status" if config['control']['ctrlport']['has_status'] else "'h0"}),
+ .m_ctrlport_resp_data(m_ctrlport_resp_data),
+ .s_ctrlport_req_wr(${"s_ctrlport_req_wr" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_rd(${"s_ctrlport_req_rd" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_addr(${"s_ctrlport_req_addr" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_portid(${"s_ctrlport_req_portid" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_rem_epid(${"s_ctrlport_req_rem_epid" if config['control']['interface_direction'] == "remote_master_slave" else "'h0"}),
+ .s_ctrlport_req_rem_portid(${"s_ctrlport_req_rem_portid" if config['control']['interface_direction'] == "remote_master_slave" else "'h0"}),
+ .s_ctrlport_req_data(${"s_ctrlport_req_data" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_byte_en(${"s_ctrlport_req_byte_en" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_has_time(${"s_ctrlport_req_has_time" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_req_time(${"s_ctrlport_req_time" if config['control']['interface_direction'] != "slave" else "'h0"}),
+ .s_ctrlport_resp_ack(${"s_ctrlport_resp_ack" if config['control']['interface_direction'] != "slave" else ""}),
+ .s_ctrlport_resp_status(${"s_ctrlport_resp_status" if config['control']['interface_direction'] != "slave" else ""}),
+ .s_ctrlport_resp_data(${"s_ctrlport_resp_data" if config['control']['interface_direction'] != "slave" else ""})
+ );
+ \ No newline at end of file
diff --git a/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako
new file mode 100644
index 000000000..6d149ae6b
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/modules/ctrlport_wires_template.mako
@@ -0,0 +1,58 @@
+<%page args="mode"/>\
+\
+<%
+ if mode == "shell":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ sl_wire = "input "
+ ma_wire = "output "
+ term = ","
+ elif mode == "block":
+ sl_pre = "s_"
+ ma_pre = "m_"
+ sl_wire = ""
+ ma_wire = ""
+ term = ";"
+%>\
+ // Control Port Master
+ ${ma_wire}wire ${ma_pre}ctrlport_req_wr${term}
+ ${ma_wire}wire ${ma_pre}ctrlport_req_rd${term}
+ ${ma_wire}wire [19:0] ${ma_pre}ctrlport_req_addr${term}
+ ${ma_wire}wire [31:0] ${ma_pre}ctrlport_req_data${term}
+%if config['control']['ctrlport']['byte_mode']:
+ ${ma_wire}wire [3:0] ${ma_pre}ctrlport_req_byte_en${term}
+%endif
+%if config['control']['ctrlport']['timed']:
+ ${ma_wire}wire ${ma_pre}ctrlport_req_ha${sl_pre}time${term}
+ ${ma_wire}wire [63:0] ${ma_pre}ctrlport_req_time${term}
+%endif
+ ${sl_wire}wire ${ma_pre}ctrlport_resp_ack${term}
+%if config['control']['ctrlport']['has_status']:
+ ${sl_wire}wire [1:0] ${ma_pre}ctrlport_resp_status${term}
+%endif
+ ${sl_wire}wire [31:0] ${ma_pre}ctrlport_resp_data${term}
+
+%if config['control']['interface_direction'] != "slave":
+ // Control Port Slave
+ ${sl_wire}wire ${sl_pre}ctrlport_req_wr${term}
+ ${sl_wire}wire ${sl_pre}ctrlport_req_rd${term}
+ ${sl_wire}wire [19:0] ${sl_pre}ctrlport_req_addr${term}
+ ${sl_wire}wire [9:0] ${sl_pre}ctrlport_req_portid${term}
+ %if config['control']['interface_direction'] == "remote_master_slave":
+ ${sl_wire}wire [15:0] ${sl_pre}ctrlport_req_rem_epid${term}
+ ${sl_wire}wire [9:0] ${sl_pre}ctrlport_req_rem_portid${term}
+ %endif
+ ${sl_wire}wire [31:0] ${sl_pre}ctrlport_req_data${term}
+ %if config['control']['ctrlport']['byte_mode']:
+ ${sl_wire}wire [3:0] ${sl_pre}ctrlport_req_byte_en${term}
+ %endif
+ %if config['control']['ctrlport']['timed']:
+ ${sl_wire}wire ${sl_pre}ctrlport_req_has_time${term}
+ ${sl_wire}wire [63:0] ${sl_pre}ctrlport_req_time${term}
+ %endif
+ ${ma_wire}wire ${sl_pre}ctrlport_resp_ack${term}
+ %if config['control']['ctrlport']['has_status']:
+ ${ma_wire}wire [1:0] ${sl_pre}ctrlport_resp_status${term}
+ %endif
+ ${ma_wire}wire [31:0] ${sl_pre}ctrlport_resp_data${term}
+%endif
diff --git a/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako b/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako
new file mode 100644
index 000000000..7fb1b17d5
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/noc_shell_template.v.mako
@@ -0,0 +1,147 @@
+<%!
+import math
+%>
+//
+// Copyright 2019 Ettus Research, A National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: noc_shell_${config['module_name']}
+// Description:
+//
+// Parameters:
+//
+// Signals:
+
+module noc_shell_${config['module_name']} #(
+ parameter CHDR_W = 64,
+ parameter [9:0] THIS_PORTID = 10'd0,
+ parameter [5:0] MTU = 0
+)(
+ // Framework Interface
+ //------------------------------------------------------------
+ // RFNoC Framework Clocks and Resets
+%for clock in config['clocks']:
+ input wire ${clock['name']}_clk,
+ ${"output" if clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"] else "input"} wire ${clock['name']}_rst,
+% endfor
+
+ // RFNoC Backend Interface
+ input wire [511:0] rfnoc_core_config,
+ output wire [511:0] rfnoc_core_status,
+ <%
+ num_inputs = len(config['data']['inputs'])
+ num_outputs = len(config['data']['outputs'])
+ %>
+ // CHDR Input Ports (from framework)
+ input wire [(${num_inputs}*CHDR_W)-1:0] s_rfnoc_chdr_tdata,
+ input wire [${num_inputs-1}:0] s_rfnoc_chdr_tlast,
+ input wire [${num_inputs-1}:0] s_rfnoc_chdr_tvalid,
+ output wire [${num_inputs-1}:0] s_rfnoc_chdr_tready,
+
+ // CHDR Output Ports (to framework)
+ output wire [(${num_outputs}*CHDR_W)-1:0] m_rfnoc_chdr_tdata,
+ output wire [${num_outputs-1}:0] m_rfnoc_chdr_tlast,
+ output wire [${num_outputs-1}:0] m_rfnoc_chdr_tvalid,
+ input wire [${num_outputs-1}:0] m_rfnoc_chdr_tready,
+ // AXIS-Ctrl Input Port (from framework)
+ input wire [31:0] s_rfnoc_ctrl_tdata,
+ input wire s_rfnoc_ctrl_tlast,
+ input wire s_rfnoc_ctrl_tvalid,
+ output wire s_rfnoc_ctrl_tready,
+ // AXIS-Ctrl Output Port (to framework)
+ output wire [31:0] m_rfnoc_ctrl_tdata,
+ output wire m_rfnoc_ctrl_tlast,
+ output wire m_rfnoc_ctrl_tvalid,
+ input wire m_rfnoc_ctrl_tready,
+
+ // Client Interface
+ //------------------------------------------------------------
+ output wire ctrlport_clk,
+ output wire ctrlport_rst,
+
+%if config['control']['fpga_iface'] == "ctrlport":
+<%include file="modules/ctrlport_wires_template.mako" args="mode='shell'"/>
+%elif config['control']['fpga_iface'] == "axis_ctrl":
+<%include file="modules/axis_ctrl_wires_template.mako" args="mode='shell'"/>
+%else:
+<%include file="control wires template.mako"/>
+%endif
+
+ output wire axis_data_clk,
+ output wire axis_data_rst,
+
+%if config['data']['fpga_iface'] == "axis_chdr":
+ <%include file="modules/axis_chdr_wires_template.mako" args="mode='shell', num_inputs=num_inputs, num_outputs=num_outputs"/>
+%elif config['data']['fpga_iface'] == "axis_rawdata":
+ <%include file="modules/axis_raw_wires_template.mako" args="mode='shell', num_inputs=num_inputs, num_outputs=num_outputs"/>
+%else:
+ <%include file="data wires template.mako"/>
+%endif
+);
+
+ // ---------------------------------------------------
+ // Backend Interface
+ // ---------------------------------------------------
+ wire data_i_flush_en;
+ wire [31:0] data_i_flush_timeout;
+ wire [63:0] data_i_flush_active;
+ wire [63:0] data_i_flush_done;
+ wire data_o_flush_en;
+ wire [31:0] data_o_flush_timeout;
+ wire [63:0] data_o_flush_active;
+ wire [63:0] data_o_flush_done;
+
+
+ backend_iface #(
+ .NOC_ID(32'h${format(config['noc_id'], "08X")}),
+ .NUM_DATA_I(${num_inputs}),
+ .NUM_DATA_O(${num_outputs}),
+ .CTRL_FIFOSIZE(${math.ceil(math.log2(config['control']['fifo_depth']))}),
+ .MTU(MTU)
+ ) backend_iface_i (
+ .rfnoc_chdr_clk(rfnoc_chdr_clk),
+ .rfnoc_chdr_rst(rfnoc_chdr_rst),
+ .rfnoc_ctrl_clk(rfnoc_ctrl_clk),
+ .rfnoc_ctrl_rst(rfnoc_ctrl_rst),
+ .rfnoc_core_config(rfnoc_core_config),
+ .rfnoc_core_status(rfnoc_core_status),
+ .data_i_flush_en(data_i_flush_en),
+ .data_i_flush_timeout(data_i_flush_timeout),
+ .data_i_flush_active(data_i_flush_active),
+ .data_i_flush_done(data_i_flush_done),
+ .data_o_flush_en(data_o_flush_en),
+ .data_o_flush_timeout(data_o_flush_timeout),
+ .data_o_flush_active(data_o_flush_active),
+ .data_o_flush_done(data_o_flush_done)
+ );
+
+ // ---------------------------------------------------
+ // Control Path
+ // ---------------------------------------------------
+
+ assign ctrlport_clk = ${config['control']['clk_domain']}_clk;
+ assign ctrlport_rst = ${config['control']['clk_domain']}_rst;
+
+%if config['control']['fpga_iface'] == "axis_ctrl":
+<%include file="modules/axis_ctrl_modules_template.mako"/>
+%elif config['control']['fpga_iface'] == "ctrlport":
+<%include file="modules/ctrlport_modules_template.mako"/>
+%else:
+<%include file="control module template.mako"/>
+%endif
+
+ // ---------------------------------------------------
+ // Data Path
+ // ---------------------------------------------------
+ assign axis_data_clk = ${config['data']['clk_domain']}_clk;
+ assign axis_data_rst = ${config['data']['clk_domain']}_rst;
+%if config['data']['fpga_iface'] == "axis_rawdata":
+<%include file="modules/axis_raw_modules_template.mako"/>
+%elif config['data']['fpga_iface'] == "axis_chdr":
+<%include file="modules/axis_chdr_modules_template.mako"/>
+%else:
+<%include file="data module template.mako"/>
+%endif
+
+endmodule // noc_shell_${config['module_name']}
diff --git a/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako
new file mode 100644
index 000000000..a2e03ea92
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template.v.mako
@@ -0,0 +1,151 @@
+<%!
+import math
+%>
+//
+// Copyright 2019 Ettus Research, A National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: rfnoc_block_${config['module_name']}
+// Description:
+//
+// Parameters:
+//
+// Signals:
+
+<%
+num_inputs = len(config['data']['inputs'])
+num_outputs = len(config['data']['outputs'])
+%>
+
+module rfnoc_block_${config['module_name']} #(
+ parameter [9:0] THIS_PORTID = 10'd0,
+ parameter CHDR_W = 64,
+ parameter [5:0] MTU = ${math.ceil(math.log2(config['data']['mtu']))}
+)(
+ // RFNoC Framework Clocks and Resets
+%for clock in config['clocks']:
+ input wire ${clock['name']}_clk,
+ %if not clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ input wire ${clock['name']}_rst,
+ %endif
+%endfor
+ // RFNoC Backend Interface
+ input wire [511:0] rfnoc_core_config,
+ output wire [511:0] rfnoc_core_status,
+ // 2 CHDR Input Ports (from framework)
+ input wire [(CHDR_W*${num_inputs})-1:0] s_rfnoc_chdr_tdata,
+ input wire [1:0] s_rfnoc_chdr_tlast,
+ input wire [1:0] s_rfnoc_chdr_tvalid,
+ output wire [1:0] s_rfnoc_chdr_tready,
+ // 2 CHDR Output Ports (to framework)
+ output wire [(CHDR_W*${num_outputs})-1:0] m_rfnoc_chdr_tdata,
+ output wire [1:0] m_rfnoc_chdr_tlast,
+ output wire [1:0] m_rfnoc_chdr_tvalid,
+ input wire [1:0] m_rfnoc_chdr_tready,
+ // AXIS-Ctrl Input Port (from framework)
+ input wire [31:0] s_rfnoc_ctrl_tdata,
+ input wire s_rfnoc_ctrl_tlast,
+ input wire s_rfnoc_ctrl_tvalid,
+ output wire s_rfnoc_ctrl_tready,
+ // AXIS-Ctrl Output Port (to framework)
+ output wire [31:0] m_rfnoc_ctrl_tdata,
+ output wire m_rfnoc_ctrl_tlast,
+ output wire m_rfnoc_ctrl_tvalid,
+ input wire m_rfnoc_ctrl_tready
+);
+
+%for clock in config['clocks']:
+ %if clock['name'] in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ wire ${clock['name']}_rst;
+ %endif
+%endfor
+
+ wire ctrlport_clk;
+ wire ctrlport_rst;
+
+ wire axis_data_clk;
+ wire axis_data_rst;
+
+%if config['control']['fpga_iface'] == "ctrlport":
+<%include file="modules/ctrlport_wires_template.mako" args="mode='block'"/>
+%elif config['control']['fpga_iface'] == "axis_ctrl":
+<%include file="modules/axis_ctrl_wires_template.mako" args="mode='block'"/>
+%else:
+<%include file="control wires template.mako"/>
+%endif
+
+%if config['data']['fpga_iface'] == "axis_chdr":
+<%include file="modules/axis_chdr_wires_template.mako" args="mode='block', num_inputs=num_inputs, num_outputs=num_outputs"/>
+%elif config['data']['fpga_iface'] == "axis_rawdata":
+<%include file="modules/axis_raw_wires_template.mako" args="mode='block', num_inputs=num_inputs, num_outputs=num_outputs"/>
+%else:
+<%include file="data wires template.mako"/>
+%endif
+
+//NoC Shell
+noc_shell_${config['module_name']} #(
+ .CHDR_W (CHDR_W),
+ .THIS_PORTID (THIS_PORTID),
+ .MTU (MTU)
+) noc_shell (
+%for clock in config['clocks']:
+ .${clock['name']}_clk(${clock['name']}_clk),
+ .${clock['name']}_rst(${clock['name']}_rst),
+%endfor
+
+ // RFNoC Backend Interface
+ .rfnoc_core_config(rfnoc_core_config),
+ .rfnoc_core_status(rfnoc_core_status),
+
+ // CHDR Input Ports (from framework)
+ .s_rfnoc_chdr_tdata(s_rfnoc_chdr_tdata),
+ .s_rfnoc_chdr_tlast(s_rfnoc_chdr_tlast),
+ .s_rfnoc_chdr_tvalid(s_rfnoc_chdr_tvalid),
+ .s_rfnoc_chdr_tready(s_rfnoc_chdr_tready),
+
+ // CHDR Output Ports (to framework)
+ .m_rfnoc_chdr_tdata(m_rfnoc_chdr_tdata),
+ .m_rfnoc_chdr_tlast(m_rfnoc_chdr_tlast),
+ .m_rfnoc_chdr_tvalid(m_rfnoc_chdr_tvalid),
+ .m_rfnoc_chdr_tready(m_rfnoc_chdr_tready),
+ // AXIS-Ctrl Input Port (from framework)
+ .s_rfnoc_ctrl_tdata(s_rfnoc_ctrl_tdata),
+ .s_rfnoc_ctrl_tlast(s_rfnoc_ctrl_tlast),
+ .s_rfnoc_ctrl_tvalid(s_rfnoc_ctrl_tvalid),
+ .s_rfnoc_ctrl_tready(s_rfnoc_ctrl_tready),
+ // AXIS-Ctrl Output Port (to framework)
+ .m_rfnoc_ctrl_tdata(m_rfnoc_ctrl_tdata),
+ .m_rfnoc_ctrl_tlast(m_rfnoc_ctrl_tlast),
+ .m_rfnoc_ctrl_tvalid(m_rfnoc_ctrl_tvalid),
+ .m_rfnoc_ctrl_tready(m_rfnoc_ctrl_tready),
+
+ // Client Interface
+ //------------------------------------------------------------
+ .ctrlport_clk(ctrlport_clk),
+ .ctrlport_rst(ctrlport_rst),
+
+%if config['control']['fpga_iface'] == "ctrlport":
+<%include file="modules/ctrlport_connect_template.mako"/>\
+%elif config['control']['fpga_iface'] == "axis_ctrl":
+<%include file="modules/axis_ctrl_connect_template.mako"/>\
+%else:
+<%include file="control connect template.mako"/>\
+%endif
+
+ .axis_data_clk(axis_data_clk),
+ .axis_data_rst(axis_data_rst),
+
+%if config['data']['fpga_iface'] == "axis_chdr":
+<%include file="modules/axis_chdr_connect_template.mako" args="num_inputs=num_inputs, num_outputs=num_outputs"/>\
+%elif config['data']['fpga_iface'] == "axis_rawdata":
+<%include file="modules/axis_raw_connect_template.mako" args="num_inputs=num_inputs, num_outputs=num_outputs"/>\
+%else:
+<%include file="data connect template.mako"/>\
+%endif
+);
+
+
+//user code goes here
+
+endmodule // rfnoc_block_${config['module_name']}
diff --git a/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako
new file mode 100644
index 000000000..0bf4641b0
--- /dev/null
+++ b/host/utils/rfnoc_blocktool/templates/rfnoc_block_template_tb.sv.mako
@@ -0,0 +1,129 @@
+//
+// Copyright 2019 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: rfnoc_block_${config['module_name']}_tb
+//
+
+`default_nettype none
+
+
+module rfnoc_block_${config['module_name']}_tb;
+
+ // Simulation Timing
+ timeunit 1ns;
+ timeprecision 1ps;
+
+ import PkgTestExec::*;
+ import PkgChdrUtils::*;
+ import PkgRfnocBlockCtrlBfm::*;
+ import PkgRfnocItemUtils::*;
+
+ // Parameters
+ localparam [9:0] THIS_PORTID = 10'h17;
+ localparam [15:0] THIS_EPID = 16'hDEAD;
+ localparam int CHDR_W = 64;
+ localparam int SPP = 201;
+ localparam int LPP = ((SPP+1)/2);
+ localparam int NUM_PKTS = 50;
+
+ localparam int PORT_SRCSNK = 0;
+ localparam int PORT_LOOP = 1;
+
+ //adjust clocks to testbench needs
+ localparam int CHDR_CLK_PER = 5; // 200 MHz
+%for clock in config['clocks']:
+ %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ localparam int ${clock['name'].upper()}_CLK_PER = 5; // 200 MHz
+ %endif
+%endfor
+
+ // Clock and Reset Definition
+ bit rfnoc_chdr_clk;
+%for clock in config['clocks']:
+ %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ bit ${clock['name']}_clk;
+ %endif
+%endfor
+
+ sim_clock_gen #(CHDR_CLK_PER) rfnoc_chdr_clk_gen (.clk(rfnoc_chdr_clk), .rst());
+%for clock in config['clocks']:
+ %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ sim_clock_gen #(${clock['name'].upper()}_CLK_PER) ${clock['name']}_clk_gen (.clk(${clock['name']}_clk), .rst());
+ %endif
+%endfor
+
+ // ----------------------------------------
+ // Instantiate DUT
+ // ----------------------------------------
+
+ // Connections to DUT as interfaces:
+ RfnocBackendIf backend (rfnoc_chdr_clk, rfnoc_chdr_clk); // Required backend iface
+ AxiStreamIf #(32) m_ctrl (rfnoc_chdr_clk); // Required control iface
+ AxiStreamIf #(32) s_ctrl (rfnoc_chdr_clk); // Required control iface
+ AxiStreamIf #(CHDR_W) m0_chdr (rfnoc_chdr_clk); // Optional data iface
+ AxiStreamIf #(CHDR_W) m1_chdr (rfnoc_chdr_clk); // Optional data iface
+ AxiStreamIf #(CHDR_W) s0_chdr (rfnoc_chdr_clk); // Optional data iface
+ AxiStreamIf #(CHDR_W) s1_chdr (rfnoc_chdr_clk); // Optional data iface
+
+ // Bus functional model for a software block controller
+ RfnocBlockCtrlBfm #(.CHDR_W(CHDR_W)) blk_ctrl;
+
+ // DUT
+ rfnoc_block_${config['module_name']} #(
+ .THIS_PORTID (THIS_PORTID),
+ .CHDR_W (CHDR_W),
+ .MTU (10)
+ ) dut (
+ .rfnoc_chdr_clk (backend.chdr_clk),
+ .rfnoc_ctrl_clk (backend.ctrl_clk),
+%for clock in config['clocks']:
+ %if clock['name'] not in ["rfnoc_chdr", "rfnoc_ctrl"]:
+ .${clock['name']}_clk(${clock['name']}_clk_gen.clk),
+ .${clock['name']}_rst(${clock['name']}_clk_gen.rst),
+ %endif
+%endfor
+ .rfnoc_core_config (backend.cfg),
+ .rfnoc_core_status (backend.sts),
+ .s_rfnoc_chdr_tdata ({m1_chdr.tdata , m0_chdr.tdata }),
+ .s_rfnoc_chdr_tlast ({m1_chdr.tlast , m0_chdr.tlast }),
+ .s_rfnoc_chdr_tvalid({m1_chdr.tvalid , m0_chdr.tvalid }),
+ .s_rfnoc_chdr_tready({m1_chdr.tready , m0_chdr.tready }),
+ .m_rfnoc_chdr_tdata ({s1_chdr.tdata , s0_chdr.tdata }),
+ .m_rfnoc_chdr_tlast ({s1_chdr.tlast , s0_chdr.tlast }),
+ .m_rfnoc_chdr_tvalid({s1_chdr.tvalid, s0_chdr.tvalid}),
+ .m_rfnoc_chdr_tready({s1_chdr.tready, s0_chdr.tready}),
+ .s_rfnoc_ctrl_tdata (m_ctrl.tdata ),
+ .s_rfnoc_ctrl_tlast (m_ctrl.tlast ),
+ .s_rfnoc_ctrl_tvalid(m_ctrl.tvalid ),
+ .s_rfnoc_ctrl_tready(m_ctrl.tready ),
+ .m_rfnoc_ctrl_tdata (s_ctrl.tdata ),
+ .m_rfnoc_ctrl_tlast (s_ctrl.tlast ),
+ .m_rfnoc_ctrl_tvalid(s_ctrl.tvalid),
+ .m_rfnoc_ctrl_tready(s_ctrl.tready)
+ );
+
+ // ----------------------------------------
+ // Test Process
+ // ----------------------------------------
+ TestExec test;
+ initial begin
+ // Shared Variables
+ // ----------------------------------------
+ timeout_t timeout;
+ ctrl_word_t rvalue;
+ rvalue = 0;
+
+ // Initialize
+ // ----------------------------------------
+ test = new("noc_block_${config['module_name']}_tb.v");
+ test.start_tb();
+
+ // Finish Up
+ // ----------------------------------------
+ // Display final statistics and results
+ test.end_tb();
+ end
+
+endmodule