aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/sim
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2020-01-23 16:10:22 -0800
committerMartin Braun <martin.braun@ettus.com>2020-01-28 09:35:36 -0800
commitbafa9d95453387814ef25e6b6256ba8db2df612f (patch)
tree39ba24b5b67072d354775272e687796bb511848d /fpga/usrp3/lib/sim
parent3075b981503002df3115d5f1d0b97d2619ba30f2 (diff)
downloaduhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.gz
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.tar.bz2
uhd-bafa9d95453387814ef25e6b6256ba8db2df612f.zip
Merge FPGA repository back into UHD repository
The FPGA codebase was removed from the UHD repository in 2014 to reduce the size of the repository. However, over the last half-decade, the split between the repositories has proven more burdensome than it has been helpful. By merging the FPGA code back, it will be possible to create atomic commits that touch both FPGA and UHD codebases. Continuous integration testing is also simplified by merging the repositories, because it was previously difficult to automatically derive the correct UHD branch when testing a feature branch on the FPGA repository. This commit also updates the license files and paths therein. We are therefore merging the repositories again. Future development for FPGA code will happen in the same repository as the UHD host code and MPM code. == Original Codebase and Rebasing == The original FPGA repository will be hosted for the foreseeable future at its original local location: https://github.com/EttusResearch/fpga/ It can be used for bisecting, reference, and a more detailed history. The final commit from said repository to be merged here is 05003794e2da61cabf64dd278c45685a7abad7ec. This commit is tagged as v4.0.0.0-pre-uhd-merge. If you have changes in the FPGA repository that you want to rebase onto the UHD repository, simply run the following commands: - Create a directory to store patches (this should be an empty directory): mkdir ~/patches - Now make sure that your FPGA codebase is based on the same state as the code that was merged: cd src/fpga # Or wherever your FPGA code is stored git rebase v4.0.0.0-pre-uhd-merge Note: The rebase command may look slightly different depending on what exactly you're trying to rebase. - Create a patch set for your changes versus v4.0.0.0-pre-uhd-merge: git format-patch v4.0.0.0-pre-uhd-merge -o ~/patches Note: Make sure that only patches are stored in your output directory. It should otherwise be empty. Make sure that you picked the correct range of commits, and only commits you wanted to rebase were exported as patch files. - Go to the UHD repository and apply the patches: cd src/uhd # Or wherever your UHD repository is stored git am --directory fpga ~/patches/* rm -rf ~/patches # This is for cleanup == Contributors == The following people have contributed mainly to these files (this list is not complete): Co-authored-by: Alex Williams <alex.williams@ni.com> Co-authored-by: Andrej Rode <andrej.rode@ettus.com> Co-authored-by: Ashish Chaudhari <ashish@ettus.com> Co-authored-by: Ben Hilburn <ben.hilburn@ettus.com> Co-authored-by: Ciro Nishiguchi <ciro.nishiguchi@ni.com> Co-authored-by: Daniel Jepson <daniel.jepson@ni.com> Co-authored-by: Derek Kozel <derek.kozel@ettus.com> Co-authored-by: EJ Kreinar <ej@he360.com> Co-authored-by: Humberto Jimenez <humberto.jimenez@ni.com> Co-authored-by: Ian Buckley <ian.buckley@gmail.com> Co-authored-by: Jörg Hofrichter <joerg.hofrichter@ni.com> Co-authored-by: Jon Kiser <jon.kiser@ni.com> Co-authored-by: Josh Blum <josh@joshknows.com> Co-authored-by: Jonathon Pendlum <jonathan.pendlum@ettus.com> Co-authored-by: Martin Braun <martin.braun@ettus.com> Co-authored-by: Matt Ettus <matt@ettus.com> Co-authored-by: Michael West <michael.west@ettus.com> Co-authored-by: Moritz Fischer <moritz.fischer@ettus.com> Co-authored-by: Nick Foster <nick@ettus.com> Co-authored-by: Nicolas Cuervo <nicolas.cuervo@ettus.com> Co-authored-by: Paul Butler <paul.butler@ni.com> Co-authored-by: Paul David <paul.david@ettus.com> Co-authored-by: Ryan Marlow <ryan.marlow@ettus.com> Co-authored-by: Sugandha Gupta <sugandha.gupta@ettus.com> Co-authored-by: Sylvain Munaut <tnt@246tNt.com> Co-authored-by: Trung Tran <trung.tran@ettus.com> Co-authored-by: Vidush Vishwanath <vidush.vishwanath@ettus.com> Co-authored-by: Wade Fife <wade.fife@ettus.com>
Diffstat (limited to 'fpga/usrp3/lib/sim')
-rw-r--r--fpga/usrp3/lib/sim/Makefile.srcs26
-rw-r--r--fpga/usrp3/lib/sim/arm_deframer/Makefile47
-rw-r--r--fpga/usrp3/lib/sim/arm_deframer/arm_deframer_tb.sv112
-rw-r--r--fpga/usrp3/lib/sim/axi/axis_shift_register/Makefile49
-rw-r--r--fpga/usrp3/lib/sim/axi/axis_shift_register/axis_shift_register_tb.sv325
-rw-r--r--fpga/usrp3/lib/sim/axi/axis_width_conv/Makefile35
-rw-r--r--fpga/usrp3/lib/sim/axi/axis_width_conv/axis_width_conv_tb.sv322
-rw-r--r--fpga/usrp3/lib/sim/axi_packet_gate/Makefile46
-rw-r--r--fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv347
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/gtk.conf.gtkw64
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/simulation_script.v82
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/gtk.conf.gtkw64
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/simulation_script.v83
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain/ddc_chain_tb.v94
-rwxr-xr-xfpga/usrp3/lib/sim/dsp/ddc_chain/run_isim18
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/.gitignore4
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/DDC.sav101
-rwxr-xr-xfpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/run_isim17
-rwxr-xr-xfpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/simcmds.tcl9
-rw-r--r--fpga/usrp3/lib/sim/dsp/ddc_chain_x300/ddc_chain_x300_tb.v64
-rw-r--r--fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/.gitignore4
-rwxr-xr-xfpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/run_isim17
-rwxr-xr-xfpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/simcmds.tcl9
-rw-r--r--fpga/usrp3/lib/sim/dsp/hb47_int/hb47_int_tb.v136
-rw-r--r--fpga/usrp3/lib/sim/dsp/mult_add_clip/Makefile45
-rw-r--r--fpga/usrp3/lib/sim/dsp/mult_add_clip/mult_add_clip_tb.sv137
-rw-r--r--fpga/usrp3/lib/sim/dsp/rx_frontend/rx_frontend_tb.v50
-rw-r--r--fpga/usrp3/lib/sim/dsp/variable_delay_line/Makefile47
-rw-r--r--fpga/usrp3/lib/sim/dsp/variable_delay_line/variable_delay_line_tb.sv117
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_dram_fifo/default.wcfg412
-rwxr-xr-xfpga/usrp3/lib/sim/fifo/axi_dram_fifo/run_isim16
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/default.wcfg412
-rwxr-xr-xfpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/run_isim17
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/simulation_script.v118
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/Default.wcfg388
-rwxr-xr-xfpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/run_isim19
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/simulation_script.v96
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_fifo/Makefile34
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_fifo/axi_fifo_tb.sv134
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_fifo_2clk/axi_fifo_2clk_tb.sv121
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_fifo_2clk_sim.v230
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_fifo_32_64/axi_fifo_32_64_tb.v121
-rw-r--r--fpga/usrp3/lib/sim/fifo/axi_packet_gate/axi_packet_gate_tb.v112
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/Makefile53
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/cap_pattern_verifier_tb.sv199
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_dual_mode_tb.v780
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_tb.v350
-rwxr-xr-xfpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.build21
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.v115
-rwxr-xr-xfpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.build21
-rw-r--r--fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.v103
-rw-r--r--fpga/usrp3/lib/sim/io_port2/pcie_dma_ctrl/pcie_dma_ctrl_tb.v92
-rw-r--r--fpga/usrp3/lib/sim/io_port2/pcie_iop2_msg_arbiter/pcie_iop2_msg_arbiter_tb.v110
-rw-r--r--fpga/usrp3/lib/sim/io_port2/pcie_wb_reg_core/pcie_wb_reg_core_tb.v243
-rw-r--r--fpga/usrp3/lib/sim/packet_proc/chdr_chunker/chdr_chunker_tb.v190
-rw-r--r--fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/Makefile33
-rw-r--r--fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/chdr_dechunker_tb.sv200
-rw-r--r--fpga/usrp3/lib/sim/packet_proc/ip_hdr_checksum/ip_hdr_checksum_tb.v43
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/axi_pipe/axi_pipe_tb.v74
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/axi_rate_change/Makefile37
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/axi_rate_change/axi_rate_change_tb.sv323
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/axi_rate_change/wave.do115
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/axi_wrapper/axi_wrapper_tb.v144
-rwxr-xr-xfpga/usrp3/lib/sim/rfnoc/axi_wrapper/build_axi_wrapper_tb1
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/chdr_deframer/chdr_deframer_tb.v87
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/chdr_framer/chdr_framer_tb.v80
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/display_samples.grc413
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/gen_samples.grc381
-rwxr-xr-xfpga/usrp3/lib/sim/rfnoc/moving_sum/build_moving_sum_tb1
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/moving_sum/moving_sum_tb.v43
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/mult/mult_tb.v75
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/mult_add/mult_add_tb.v90
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/null_source/null_source_tb.v80
-rwxr-xr-xfpga/usrp3/lib/sim/rfnoc/window/build_window_tb1
-rw-r--r--fpga/usrp3/lib/sim/rfnoc/window/window_tb.v341
-rw-r--r--fpga/usrp3/lib/sim/simple_gemac/ll8_to_axi64/ll8_to_axi64_tb.v100
-rw-r--r--fpga/usrp3/lib/sim/simple_gemac/simple_gemac_tb.v208
-rwxr-xr-xfpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper.build1
-rw-r--r--fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper_tb.v213
-rw-r--r--fpga/usrp3/lib/sim/wishbone/simple_uart/simple_uart_tb.v132
80 files changed, 10194 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/sim/Makefile.srcs b/fpga/usrp3/lib/sim/Makefile.srcs
new file mode 100644
index 000000000..b76175cd9
--- /dev/null
+++ b/fpga/usrp3/lib/sim/Makefile.srcs
@@ -0,0 +1,26 @@
+#
+# Copyright 2016 Ettus Research
+#
+
+# Minimal set of sources in lib directory needed for simulation
+include $(BASE_DIR)/../lib/fifo/Makefile.srcs
+include $(BASE_DIR)/../lib/axi/Makefile.srcs
+include $(BASE_DIR)/../lib/control/Makefile.srcs
+include $(BASE_DIR)/../lib/timing/Makefile.srcs
+include $(BASE_DIR)/../lib/packet_proc/Makefile.srcs
+include $(BASE_DIR)/../lib/dsp/Makefile.srcs
+include $(BASE_DIR)/../lib/rfnoc/Makefile.srcs
+
+# Use sim version of axi_fifo_2clk
+FIFO_SRCS := $(filter-out %/axi_fifo_2clk.v,$(FIFO_SRCS))
+FIFO_SRCS += $(abspath $(BASE_DIR)/../lib/sim/fifo/axi_fifo_2clk_sim.v)
+
+SIM_DESIGN_SRCS = $(abspath \
+$(FIFO_SRCS) \
+$(AXI_SRCS) \
+$(CONTROL_LIB_SRCS) \
+$(TIMING_SRCS) \
+$(PACKET_PROC_SRCS) \
+$(DSP_SRCS) \
+$(RFNOC_SRCS) \
+)
diff --git a/fpga/usrp3/lib/sim/arm_deframer/Makefile b/fpga/usrp3/lib/sim/arm_deframer/Makefile
new file mode 100644
index 000000000..eb7231d5e
--- /dev/null
+++ b/fpga/usrp3/lib/sim/arm_deframer/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright 2015 Ettus Research LLC
+#
+
+#-------------------------------------------------
+# Top-of-Makefile
+#-------------------------------------------------
+# Define BASE_DIR to point to the "top" dir
+BASE_DIR = $(abspath ../../../top)
+# Include viv_sim_preamble after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# IP Specific
+#-------------------------------------------------
+# If simulation contains IP, define the IP_DIR and point
+# it to the base level IP directory
+LIB_IP_DIR = $(BASE_DIR)/../lib/ip
+
+# Include makefiles and sources for all IP components
+# *after* defining the IP_DIR
+
+DESIGN_SRCS += $(abspath \
+../../packet_proc/arm_deframer.v \
+../../fifo/axi_mux4.v \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = arm_deframer_tb
+
+SIM_SRCS = $(abspath \
+$(SIM_PROTORFNOC_SRCS) \
+arm_deframer_tb.sv \
+)
+
+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/fpga/usrp3/lib/sim/arm_deframer/arm_deframer_tb.sv b/fpga/usrp3/lib/sim/arm_deframer/arm_deframer_tb.sv
new file mode 100644
index 000000000..4e252b5b4
--- /dev/null
+++ b/fpga/usrp3/lib/sim/arm_deframer/arm_deframer_tb.sv
@@ -0,0 +1,112 @@
+/////////////////////////////////////////////////////////////////////
+//
+// Copyright 2016-2017 Ettus Research
+//
+// Arm Deframer Testbench
+//
+// Arm Deframer adds a 6 bit padding to the ethernet frame
+//
+//////////////////////////////////////////////////////////////////////
+
+`timescale 1ns/1ps
+`define SIM_RUNTIME_US 0.0001
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 3
+`include "sim_axis_lib.svh"
+`include "sim_exec_report.vh"
+`include "sim_rfnoc_lib.svh"
+`include "sim_set_rb_lib.svh"
+
+// NOTE: The tesbench is not self-checking
+module arm_deframer_tb();
+ `TEST_BENCH_INIT("arm_deframer_tb",`NUM_TEST_CASES,`NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e6/166.67e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(rst, 0, 100);
+
+ axis_master #(.DWIDTH(68)) m_axis (.clk(clk));
+ axis_slave #(.DWIDTH(68)) s_axis (.clk(clk));
+
+ reg clear;
+ wire [63:0] c2e_tdata_int;
+ wire [3:0] c2e_tuser_int;
+ wire c2e_tlast_int;
+ wire c2e_tvalid_int;
+ wire c2e_tready_int;
+
+ arm_deframer inst_arm_deframer (
+ .clk (clk),
+ .reset (rst),
+ .clear (clear),
+ .s_axis_tdata (m_axis.axis.tdata[63:0]),
+ .s_axis_tuser (m_axis.axis.tdata[67:64]),
+ .s_axis_tlast (m_axis.axis.tlast),
+ .s_axis_tvalid (m_axis.axis.tvalid),
+ .s_axis_tready (m_axis.axis.tready),
+ .m_axis_tdata (c2e_tdata_int),
+ .m_axis_tuser (c2e_tuser_int),
+ .m_axis_tlast (c2e_tlast_int),
+ .m_axis_tvalid (c2e_tvalid_int),
+ .m_axis_tready (c2e_tready_int)
+ );
+
+ axi_mux4 #(.PRIO(0), .WIDTH(68)) eth_mux
+ (.clk(clk), .reset(reset), .clear(clear),
+ .i0_tdata({c2e_tuser_int,c2e_tdata_int}), .i0_tlast(c2e_tlast_int), .i0_tvalid(c2e_tvalid_int), .i0_tready(c2e_tready_int),
+ .i1_tdata(), .i1_tlast(), .i1_tvalid(), .i1_tready(),
+ .i2_tdata(), .i2_tlast(), .i2_tvalid(), .i2_tready(),
+ .i3_tdata(), .i3_tlast(), .i3_tvalid(1'b0), .i3_tready(),
+ .o_tdata(s_axis.axis.tdata), .o_tlast(s_axis.axis.tlast), .o_tvalid(s_axis.axis.tvalid), .o_tready(1'b1/*s_axis.axis.tready*/));
+
+ reg [63:0] out_tdata;
+ reg [3:0] tuser;
+ reg tlast;
+
+ initial begin
+ forever begin
+ s_axis.pull_word({tuser,out_tdata}, tlast);
+ $display("tuser = %d, out_tdata = %x, last = %d", tuser, out_tdata, tlast);
+ end
+ end
+
+ initial begin : tb_main
+ `TEST_CASE_START("Wait for reset");
+ m_axis.reset;
+ while (rst) @(posedge clk);
+ `TEST_CASE_DONE(~rst);
+
+ `TEST_CASE_START("Send frame");
+ repeat (10) @(posedge clk);
+ for (int j = 0; j < 2; j ++) begin
+ @(posedge clk);
+ $display("----------New Frame---------------");
+ for (int i = 0; i < 9; i ++) begin
+ m_axis.push_word({4'h0,64'h1111111111111111 * i}, 1'b0);
+ //m_axis.push_bubble();
+ end
+ m_axis.push_word({4'h1,64'h9999999999999999}, 1'b1);
+ //m_axis.push_bubble();
+ end
+ @(posedge clk);
+ @(posedge clk);
+ `TEST_CASE_DONE(1);
+ repeat (10) @(posedge clk);
+
+ `TEST_CASE_START("Send frame with bubble");
+ repeat (10) @(posedge clk);
+ for (int j = 0; j < 2; j ++) begin
+ @(posedge clk);
+ $display("----------New Frame---------------");
+ for (int i = 0; i < 9; i ++) begin
+ m_axis.push_word({4'h0,64'h1111111111111111 * i}, 1'b0);
+ m_axis.push_bubble();
+ end
+ m_axis.push_word({4'h1,64'h9999999999999999}, 1'b1);
+ m_axis.push_bubble();
+ end
+ @(posedge clk);
+ @(posedge clk);
+ `TEST_CASE_DONE(1);
+ `TEST_BENCH_DONE;
+ end
+endmodule
diff --git a/fpga/usrp3/lib/sim/axi/axis_shift_register/Makefile b/fpga/usrp3/lib/sim/axi/axis_shift_register/Makefile
new file mode 100644
index 000000000..8a65a6024
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi/axis_shift_register/Makefile
@@ -0,0 +1,49 @@
+#
+# Copyright 2018 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_preamble 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/axi/Makefile.srcs
+include $(BASE_DIR)/../lib/fifo/Makefile.srcs
+include $(BASE_DIR)/../lib/control/Makefile.srcs
+
+DESIGN_SRCS = $(abspath \
+$(AXI_SRCS) \
+$(FIFO_SRCS) \
+$(CONTROL_LIB_SRCS) \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = axis_shift_register_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+axis_shift_register_tb.sv \
+)
+
+# 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/fpga/usrp3/lib/sim/axi/axis_shift_register/axis_shift_register_tb.sv b/fpga/usrp3/lib/sim/axi/axis_shift_register/axis_shift_register_tb.sv
new file mode 100644
index 000000000..1ce868069
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi/axis_shift_register/axis_shift_register_tb.sv
@@ -0,0 +1,325 @@
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 8
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_axis_lib.svh"
+
+module axis_shift_register_tb();
+ `TEST_BENCH_INIT("axis_shift_register_tb", `NUM_TEST_CASES, `NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/100.0e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ localparam WIDTH = 32;
+ localparam integer NUM_INST = 4;
+
+ logic [WIDTH:0] i_tdata[0:NUM_INST-1];
+ logic i_tlast[0:NUM_INST-1], i_tvalid[0:NUM_INST-1];
+ wire i_tready[0:NUM_INST-1];
+ wire [WIDTH:0] o_tdata[0:NUM_INST-1];
+ wire o_tlast[0:NUM_INST-1], o_tvalid[0:NUM_INST-1];
+ logic o_tready[0:NUM_INST-1];
+ wire [15:0] stage_stb[0:NUM_INST-1], stage_eop[0:NUM_INST-1];
+ wire [WIDTH-1:0] sb_dout, sb_din;
+ wire sb_keep;
+ reg [WIDTH-1:0] sb_shreg[0:2];
+ always @(posedge clk) begin
+ if (stage_stb[2][0])
+ sb_shreg[0] <= sb_dout;
+ if (stage_stb[2][1])
+ sb_shreg[1] <= sb_shreg[0];
+ if (stage_stb[2][2])
+ sb_shreg[2] <= sb_shreg[1];
+ end
+ assign sb_din = sb_shreg[2];
+
+ axis_shift_register #(
+ .WIDTH(WIDTH), .NSPC(1), .LATENCY(2),
+ .SIDEBAND_DATAPATH(0), .GAPLESS(0),
+ .PIPELINE("NONE")
+ ) inst_0 (
+ .clk(clk), .reset(reset),
+ .s_axis_tdata(i_tdata[0]), .s_axis_tkeep(i_tdata[0][WIDTH]), .s_axis_tlast(i_tlast[0]),
+ .s_axis_tvalid(i_tvalid[0]), .s_axis_tready(i_tready[0]),
+ .m_axis_tdata(o_tdata[0]), .m_axis_tkeep(o_tdata[0][WIDTH]), .m_axis_tlast(o_tlast[0]),
+ .m_axis_tvalid(o_tvalid[0]), .m_axis_tready(o_tready[0]),
+ .stage_stb(stage_stb[0]), .stage_eop(stage_eop[0]),
+ .m_sideband_data(), .m_sideband_keep(), .s_sideband_data()
+ );
+
+ axis_shift_register #(
+ .WIDTH(WIDTH), .NSPC(1), .LATENCY(9),
+ .SIDEBAND_DATAPATH(0), .GAPLESS(0),
+ .PIPELINE("BOTH")
+ ) inst_1 (
+ .clk(clk), .reset(reset),
+ .s_axis_tdata(i_tdata[1]), .s_axis_tkeep(i_tdata[1][WIDTH]), .s_axis_tlast(i_tlast[1]),
+ .s_axis_tvalid(i_tvalid[1]), .s_axis_tready(i_tready[1]),
+ .m_axis_tdata(o_tdata[1]), .m_axis_tkeep(o_tdata[1][WIDTH]), .m_axis_tlast(o_tlast[1]),
+ .m_axis_tvalid(o_tvalid[1]), .m_axis_tready(o_tready[1]),
+ .stage_stb(stage_stb[1]), .stage_eop(stage_eop[1]),
+ .m_sideband_data(), .m_sideband_keep(), .s_sideband_data()
+ );
+
+ axis_shift_register #(
+ .WIDTH(WIDTH/2), .NSPC(2), .LATENCY(3),
+ .SIDEBAND_DATAPATH(1), .GAPLESS(0),
+ .PIPELINE("NONE")
+ ) inst_2 (
+ .clk(clk), .reset(reset),
+ .s_axis_tdata(i_tdata[2]), .s_axis_tkeep(i_tdata[2][WIDTH]), .s_axis_tlast(i_tlast[2]),
+ .s_axis_tvalid(i_tvalid[2]), .s_axis_tready(i_tready[2]),
+ .m_axis_tdata(o_tdata[2]), .m_axis_tkeep(o_tdata[2][WIDTH]), .m_axis_tlast(o_tlast[2]),
+ .m_axis_tvalid(o_tvalid[2]), .m_axis_tready(o_tready[2]),
+ .stage_stb(stage_stb[2]), .stage_eop(stage_eop[2]),
+ .m_sideband_data(sb_dout), .m_sideband_keep(sb_keep), .s_sideband_data(sb_din)
+ );
+
+ axis_shift_register #(
+ .WIDTH(WIDTH/8), .NSPC(8), .LATENCY(14),
+ .SIDEBAND_DATAPATH(0), .GAPLESS(1),
+ .PIPELINE("NONE")
+ ) inst_3 (
+ .clk(clk), .reset(reset),
+ .s_axis_tdata(i_tdata[3]), .s_axis_tkeep(i_tdata[3][WIDTH]), .s_axis_tlast(i_tlast[3]),
+ .s_axis_tvalid(i_tvalid[3]), .s_axis_tready(i_tready[3]),
+ .m_axis_tdata(o_tdata[3]), .m_axis_tkeep(o_tdata[3][WIDTH]), .m_axis_tlast(o_tlast[3]),
+ .m_axis_tvalid(o_tvalid[3]), .m_axis_tready(o_tready[3]),
+ .stage_stb(stage_stb[3]), .stage_eop(stage_eop[3]),
+ .m_sideband_data(), .m_sideband_keep(), .s_sideband_data()
+ );
+
+ logic [15:0] prev_stage_stb[0:NUM_INST-1];
+ initial begin : tb_main
+ string s;
+
+ `TEST_CASE_START("Wait for Reset");
+ for (int k = 0; k < NUM_INST; k=k+1) begin
+ o_tready[k] = 1'b1;
+ i_tvalid[k] = 1'b0;
+ prev_stage_stb[k] = 0;
+ end
+ while (reset) @(posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ `TEST_CASE_START("Check module with LATENCY=2, PIPELINE=NONE");
+ `ASSERT_ERROR(o_tvalid[0] == 1'b0, "Output incorrectly active when idle");
+ `ASSERT_ERROR(i_tready[0] == 1'b1, "Input was not ready when idle");
+ `ASSERT_ERROR(stage_stb[0][1:0] === 0, "Incorrect stage_stb when idle");
+ for (int j = 0; j < 2; j=j+1) begin
+ i_tdata[0] = j;
+ i_tlast[0] = j % 2;
+ i_tvalid[0] = 1'b1;
+ @(posedge clk);
+ i_tvalid[0] = 1'b0;
+ prev_stage_stb[0][1:0] = {prev_stage_stb[0][0], 1'b1};
+ `ASSERT_ERROR(stage_stb[0][1:0] == prev_stage_stb[0][1:0], "Incorrect stage_stb");
+ `ASSERT_ERROR(i_tready[0] == 1'b1, "Input was not ready during fill-up");
+ `ASSERT_ERROR(o_tvalid[0] == 1'b0, "Output incorrectly active during fill-up");
+ end
+ for (int j = 0; j < 2; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[0] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[0] == j % 2, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[0] == j, "Incorrect tdata");
+ end
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=9, PIPELINE=BOTH");
+ prev_stage_stb[1] = 0;
+ `ASSERT_ERROR(o_tvalid[1] == 1'b0, "Output incorrectly active when idle");
+ `ASSERT_ERROR(i_tready[1] == 1'b1, "Input was not ready when idle");
+ `ASSERT_ERROR(stage_stb[1][1:0] === 0, "Incorrect stage_stb when idle");
+ for (int j = 0; j < 9; j=j+1) begin
+ i_tdata[1] = -j;
+ i_tlast[1] = 1'b1;
+ i_tvalid[1] = 1'b1;
+ @(posedge clk);
+ i_tvalid[1] = 1'b0;
+ prev_stage_stb[1][8:0] = {prev_stage_stb[1][7:0], 1'b1};
+ `ASSERT_ERROR(stage_eop[1][8:0] == prev_stage_stb[1][8:0], "Incorrect stage_eop");
+ `ASSERT_ERROR(stage_stb[1][8:0] == prev_stage_stb[1][8:0], "Incorrect stage_stb");
+ `ASSERT_ERROR(i_tready[1] == 1'b1, "Input was not ready during fill-up");
+ `ASSERT_ERROR(o_tvalid[1] == 1'b0, "Output incorrectly active during fill-up");
+ end
+ for (int j = 0; j < 9; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[1] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[1] == 1'b1, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[1] == -j, "Incorrect tdata");
+ end
+ @(posedge clk);
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=9, PIPELINE=BOTH (backpressure)");
+ prev_stage_stb[1] = 0;
+ o_tready[1] = 1'b0;
+ `ASSERT_ERROR(o_tvalid[1] == 1'b0, "Output incorrectly active when idle");
+ `ASSERT_ERROR(i_tready[1] == 1'b1, "Input was not ready when idle");
+ `ASSERT_ERROR(stage_stb[1][1:0] === 0, "Incorrect stage_stb when idle");
+ for (int j = 0; j < 9; j=j+1) begin
+ i_tdata[1] = -j;
+ i_tlast[1] = 1'b1;
+ i_tvalid[1] = 1'b1;
+ @(posedge clk);
+ i_tvalid[1] = 1'b0;
+ prev_stage_stb[1][8:0] = {prev_stage_stb[1][7:0], 1'b1};
+ `ASSERT_ERROR(stage_stb[1][8:0] == prev_stage_stb[1][8:0], "Incorrect stage_stb");
+ `ASSERT_ERROR(stage_eop[1][8:0] == prev_stage_stb[1][8:0], "Incorrect stage_eop");
+ `ASSERT_ERROR(i_tready[1] == 1'b1, "Input was not ready during fill-up");
+ `ASSERT_ERROR(o_tvalid[1] == 1'b0, "Output incorrectly active during fill-up");
+ end
+ o_tready[1] = 1'b1;
+ for (int j = 0; j < 9; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[1] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[1] == 1'b1, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[1] == -j, "Incorrect tdata");
+ end
+ @(posedge clk);
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=9, PIPELINE=BOTH (steady-state)");
+ prev_stage_stb[1] = 0;
+ fork
+ begin
+ for (int j = 0; j < 50; j=j+1) begin
+ i_tdata[1] = j;
+ i_tlast[1] = j % 2;
+ i_tvalid[1] = 1'b1;
+ @(posedge clk);
+ i_tvalid[1] = 1'b0;
+ prev_stage_stb[1][8:0] = {prev_stage_stb[1][7:0], 1'b1};
+ `ASSERT_ERROR(stage_stb[1][8:0] == prev_stage_stb[1][8:0], "Incorrect stage_stb");
+ end
+ end
+ begin
+ o_tready[1] = 1'b1;
+ repeat(9) @(posedge clk);
+ for (int j = 0; j < 50; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[1] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[1] == j % 2, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[1] == j, "Incorrect tdata");
+ end
+ @(posedge clk);
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=9, PIPELINE=BOTH (gaps)");
+ prev_stage_stb[1] = 0;
+ fork
+ begin
+ for (int j = 0; j < 50; j=j+1) begin
+ i_tdata[1] = j;
+ i_tlast[1] = j % 2;
+ i_tvalid[1] = 1'b1;
+ @(posedge clk);
+ while (~i_tready[1]) @(posedge clk);
+ i_tvalid[1] = 1'b0;
+ end
+ end
+ begin
+ o_tready[1] = 1'b1;
+ repeat(9) @(posedge clk);
+ for (int j = 0; j < 20; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[1] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[1] == j % 2, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[1] == j, "Incorrect tdata");
+ end
+ o_tready[1] = 1'b0;
+ repeat(4) @(posedge clk);
+ o_tready[1] = 1'b1;
+ for (int j = 20; j < 50; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[1] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[1] == j % 2, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[1] == j, "Incorrect tdata");
+ end
+ @(posedge clk);
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=3, SIDEBAND=1 (gaps)");
+ prev_stage_stb[2] = 0;
+ fork
+ begin
+ for (int j = 0; j < 50; j=j+1) begin
+ i_tdata[2] = j;
+ i_tlast[2] = j % 4 == 0;
+ i_tvalid[2] = 1'b1;
+ @(posedge clk);
+ while (~i_tready[2]) @(posedge clk);
+ i_tvalid[2] = 1'b0;
+ end
+ end
+ begin
+ o_tready[2] = 1'b1;
+ repeat(3) @(posedge clk);
+ for (int j = 0; j < 20; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[2] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[2] == j % 4 == 0, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[2] == j, "Incorrect tdata");
+ end
+ o_tready[2] = 1'b0;
+ repeat(4) @(posedge clk);
+ o_tready[2] = 1'b1;
+ for (int j = 20; j < 50; j=j+1) begin
+ @(posedge clk);
+ `ASSERT_ERROR(o_tvalid[2] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[2] == j % 4 == 0, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[2] == j, "Incorrect tdata");
+ end
+ @(posedge clk);
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check module with LATENCY=14, GAPLESS=1");
+ prev_stage_stb[3] = 0;
+ o_tready[3] = 1'b0;
+ fork
+ begin
+ for (int j = 0; j < 50; j=j+1) begin
+ i_tdata[3] = j;
+ i_tlast[3] = j % 4 == 0;
+ i_tvalid[3] = 1'b1;
+ @(posedge clk);
+ prev_stage_stb[3][13:0] = {prev_stage_stb[3][12:0], 1'b1};
+ `ASSERT_ERROR(stage_stb[3][13:0] == prev_stage_stb[3][13:0], "Incorrect stage_stb");
+ while (~i_tready[3]) @(posedge clk);
+ i_tvalid[3] = 1'b0;
+ if (j > 16) repeat($urandom_range(0, 15)) @(posedge clk);
+ `ASSERT_ERROR(stage_stb[3][13:0] == prev_stage_stb[3][13:0] || stage_stb[3][13:0] == 14'd0, "Incorrect stage_stb");
+ end
+ end
+ begin
+ for (int j = 0; j < 50 - 14; j=j+1) begin
+ while (~o_tvalid[3]) @(posedge clk);
+ @(negedge clk);
+ `ASSERT_ERROR(o_tvalid[3] == 1'b1, "Output was not active");
+ `ASSERT_ERROR(o_tlast[3] == j % 4 == 0, "Incorrect tlast");
+ `ASSERT_ERROR(o_tdata[3] == j, "Incorrect tdata");
+ o_tready[3] = 1'b1;
+ @(negedge clk);
+ o_tready[3] = 1'b0;
+ @(posedge clk);
+ end
+ end
+ join
+ `TEST_CASE_DONE(1);
+ `TEST_BENCH_DONE;
+ end
+endmodule
diff --git a/fpga/usrp3/lib/sim/axi/axis_width_conv/Makefile b/fpga/usrp3/lib/sim/axi/axis_width_conv/Makefile
new file mode 100644
index 000000000..2e7d0ba0c
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi/axis_width_conv/Makefile
@@ -0,0 +1,35 @@
+#
+# Copyright 2018 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_preamble after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = axis_width_conv_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+axis_width_conv_tb.sv \
+)
+
+# 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/fpga/usrp3/lib/sim/axi/axis_width_conv/axis_width_conv_tb.sv b/fpga/usrp3/lib/sim/axi/axis_width_conv/axis_width_conv_tb.sv
new file mode 100644
index 000000000..0b1f4414c
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi/axis_width_conv/axis_width_conv_tb.sv
@@ -0,0 +1,322 @@
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 13
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_axis_lib.svh"
+
+module axis_width_conv_tb();
+ `TEST_BENCH_INIT("axis_width_conv_tb", `NUM_TEST_CASES, `NS_PER_TICK);
+
+ `DEFINE_CLK(clk50, 20.000, 50);
+ `DEFINE_CLK(clk200, 5.000, 50);
+ `DEFINE_LATE_START_CLK(clk166, 6.000, 50, 0.37, 0.01)
+ `DEFINE_RESET(areset, 0, 100);
+
+ localparam WORD_W = 8;
+ localparam integer NINST = 6;
+ localparam integer IN_WORDS[0:NINST-1] = {1, 4, 4, 8, 8, 17};
+ localparam integer OUT_WORDS[0:NINST-1] = {4, 1, 3, 2, 8, 19};
+ localparam integer MAX_IN_WORDS = 20;
+ localparam integer MAX_OUT_WORDS = 20;
+ localparam integer MAX_SPP = 100;
+
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[0])) m0 (.clk(clk50));
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[1])) m1 (.clk(clk50));
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[2])) m2 (.clk(clk50));
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[3])) m3 (.clk(clk50));
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[4])) m4 (.clk(clk50));
+ axis_master #(.DWIDTH((WORD_W+1)*IN_WORDS[5])) m5 (.clk(clk50));
+
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[0])) s0 (.clk(clk50));
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[1])) s1 (.clk(clk50));
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[2])) s2 (.clk(clk200));
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[3])) s3 (.clk(clk166));
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[4])) s4 (.clk(clk166));
+ axis_slave #(.DWIDTH((WORD_W+1)*OUT_WORDS[5])) s5 (.clk(clk50));
+
+ // An integer 1-to-4 upsizer
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[0]), .OUT_WORDS(OUT_WORDS[0]),
+ .SYNC_CLKS(1), .PIPELINE("INOUT")
+ ) dut0 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m0.axis.tdata[(IN_WORDS[0]*WORD_W)-1:0]),
+ .s_axis_tkeep (m0.axis.tdata[IN_WORDS[0]*WORD_W+:IN_WORDS[0]]),
+ .s_axis_tlast (m0.axis.tlast),
+ .s_axis_tvalid(m0.axis.tvalid),
+ .s_axis_tready(m0.axis.tready),
+ .m_axis_aclk (clk50),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s0.axis.tdata[(OUT_WORDS[0]*WORD_W)-1:0]),
+ .m_axis_tkeep (s0.axis.tdata[OUT_WORDS[0]*WORD_W+:OUT_WORDS[0]]),
+ .m_axis_tlast (s0.axis.tlast),
+ .m_axis_tvalid(s0.axis.tvalid),
+ .m_axis_tready(s0.axis.tready)
+ );
+
+ // An integer 4-to-1 downsizer
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[1]), .OUT_WORDS(OUT_WORDS[1]),
+ .SYNC_CLKS(1), .PIPELINE("IN")
+ ) dut1 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m1.axis.tdata[(IN_WORDS[1]*WORD_W)-1:0]),
+ .s_axis_tkeep (m1.axis.tdata[IN_WORDS[1]*WORD_W+:IN_WORDS[1]]),
+ .s_axis_tlast (m1.axis.tlast),
+ .s_axis_tvalid(m1.axis.tvalid),
+ .s_axis_tready(m1.axis.tready),
+ .m_axis_aclk (clk50),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s1.axis.tdata[(OUT_WORDS[1]*WORD_W)-1:0]),
+ .m_axis_tkeep (s1.axis.tdata[OUT_WORDS[1]*WORD_W+:OUT_WORDS[1]]),
+ .m_axis_tlast (s1.axis.tlast),
+ .m_axis_tvalid(s1.axis.tvalid),
+ .m_axis_tready(s1.axis.tready)
+ );
+
+ // A rational integer 4-to-3 downsizer
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[2]), .OUT_WORDS(OUT_WORDS[2]),
+ .SYNC_CLKS(0), .PIPELINE("OUT")
+ ) dut2 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m2.axis.tdata[(IN_WORDS[2]*WORD_W)-1:0]),
+ .s_axis_tkeep (m2.axis.tdata[IN_WORDS[2]*WORD_W+:IN_WORDS[2]]),
+ .s_axis_tlast (m2.axis.tlast),
+ .s_axis_tvalid(m2.axis.tvalid),
+ .s_axis_tready(m2.axis.tready),
+ .m_axis_aclk (clk200),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s2.axis.tdata[(OUT_WORDS[2]*WORD_W)-1:0]),
+ .m_axis_tkeep (s2.axis.tdata[OUT_WORDS[2]*WORD_W+:OUT_WORDS[2]]),
+ .m_axis_tlast (s2.axis.tlast),
+ .m_axis_tvalid(s2.axis.tvalid),
+ .m_axis_tready(s2.axis.tready)
+ );
+
+ // An integer 4-to-1 downsizer but with 2 words per cycle
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[3]), .OUT_WORDS(OUT_WORDS[3]),
+ .SYNC_CLKS(0), .PIPELINE("NONE")
+ ) dut3 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m3.axis.tdata[(IN_WORDS[3]*WORD_W)-1:0]),
+ .s_axis_tkeep (m3.axis.tdata[IN_WORDS[3]*WORD_W+:IN_WORDS[3]]),
+ .s_axis_tlast (m3.axis.tlast),
+ .s_axis_tvalid(m3.axis.tvalid),
+ .s_axis_tready(m3.axis.tready),
+ .m_axis_aclk (clk166),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s3.axis.tdata[(OUT_WORDS[3]*WORD_W)-1:0]),
+ .m_axis_tkeep (s3.axis.tdata[OUT_WORDS[3]*WORD_W+:OUT_WORDS[3]]),
+ .m_axis_tlast (s3.axis.tlast),
+ .m_axis_tvalid(s3.axis.tvalid),
+ .m_axis_tready(s3.axis.tready)
+ );
+
+ // A passthrough module (no up/down sizing) but with 8 words per cycle
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[4]), .OUT_WORDS(OUT_WORDS[4]),
+ .SYNC_CLKS(0), .PIPELINE("INOUT")
+ ) dut4 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m4.axis.tdata[(IN_WORDS[4]*WORD_W)-1:0]),
+ .s_axis_tkeep (m4.axis.tdata[IN_WORDS[4]*WORD_W+:IN_WORDS[4]]),
+ .s_axis_tlast (m4.axis.tlast),
+ .s_axis_tvalid(m4.axis.tvalid),
+ .s_axis_tready(m4.axis.tready),
+ .m_axis_aclk (clk166),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s4.axis.tdata[(OUT_WORDS[4]*WORD_W)-1:0]),
+ .m_axis_tkeep (s4.axis.tdata[OUT_WORDS[4]*WORD_W+:OUT_WORDS[4]]),
+ .m_axis_tlast (s4.axis.tlast),
+ .m_axis_tvalid(s4.axis.tvalid),
+ .m_axis_tready(s4.axis.tready)
+ );
+
+ // A rational integer 17-to-19 upsizer
+ axis_width_conv #(
+ .WORD_W(WORD_W), .IN_WORDS(IN_WORDS[5]), .OUT_WORDS(OUT_WORDS[5]),
+ .SYNC_CLKS(1), .PIPELINE("INOUT")
+ ) dut5 (
+ .s_axis_aclk (clk50),
+ .s_axis_rst (areset),
+ .s_axis_tdata (m5.axis.tdata[(IN_WORDS[5]*WORD_W)-1:0]),
+ .s_axis_tkeep (m5.axis.tdata[IN_WORDS[5]*WORD_W+:IN_WORDS[5]]),
+ .s_axis_tlast (m5.axis.tlast),
+ .s_axis_tvalid(m5.axis.tvalid),
+ .s_axis_tready(m5.axis.tready),
+ .m_axis_aclk (clk50),
+ .m_axis_rst (areset),
+ .m_axis_tdata (s5.axis.tdata[(OUT_WORDS[5]*WORD_W)-1:0]),
+ .m_axis_tkeep (s5.axis.tdata[OUT_WORDS[5]*WORD_W+:OUT_WORDS[5]]),
+ .m_axis_tlast (s5.axis.tlast),
+ .m_axis_tvalid(s5.axis.tvalid),
+ .m_axis_tready(s5.axis.tready)
+ );
+
+ // Push a test ramp packet into the specific instance of the module
+ // - words: The size of the packet in words
+ // - inst: The instance number of the module to send to
+ // - gaps: If 1 then insert bubble cycles randomly in the stream
+ task push_test_pkt(input integer words, input integer inst, input logic gaps);
+ begin
+ logic [(MAX_IN_WORDS*WORD_W)-1:0] data = 0;
+ logic [MAX_IN_WORDS-1:0] keep = 0;
+ logic last = 0;
+ integer nspc = IN_WORDS[inst];
+ integer lines = words/nspc;
+ integer residue = words % nspc;
+ if (residue != 0) begin
+ lines = lines + 1;
+ end
+ for (int l = 0; l < lines; l=l+1) begin
+ last = (l == lines-1);
+ for (int p = 0; p < nspc; p=p+1) begin
+ data[p*WORD_W+:WORD_W] = (l*nspc)+p;
+ end
+ keep = (last && (residue != 0)) ? (1<<residue)-1 : (1<<nspc)-1;
+ if (inst == 0)
+ m0.push_word({keep[IN_WORDS[0]-1:0], data[(IN_WORDS[0]*WORD_W)-1:0]}, last);
+ else if (inst == 1)
+ m1.push_word({keep[IN_WORDS[1]-1:0], data[(IN_WORDS[1]*WORD_W)-1:0]}, last);
+ else if (inst == 2)
+ m2.push_word({keep[IN_WORDS[2]-1:0], data[(IN_WORDS[2]*WORD_W)-1:0]}, last);
+ else if (inst == 3)
+ m3.push_word({keep[IN_WORDS[3]-1:0], data[(IN_WORDS[3]*WORD_W)-1:0]}, last);
+ else if (inst == 4)
+ m4.push_word({keep[IN_WORDS[4]-1:0], data[(IN_WORDS[4]*WORD_W)-1:0]}, last);
+ else
+ m5.push_word({keep[IN_WORDS[5]-1:0], data[(IN_WORDS[5]*WORD_W)-1:0]}, last);
+
+ // Keep tvalid deasserted randomly introduce gaps
+ if (gaps) begin
+ integer r = $urandom_range(0, 100);
+ if (r < 20) repeat(r) @(posedge clk50);
+ end
+// $display("PUSH(%02d)[%03d]: D{%0x}, K{%0b}, L{%0b}", inst, l, data, keep, last);
+ end
+ end
+ endtask
+
+ // Pull a test ramp packet from the specific instance of the module
+ // - words: The size of the packet in words
+ // - inst: The instance number of the module to send to
+ // - gaps: If 1 then insert bubble cycles randomly in the stream
+ // - ok: If 1 then all sanity checks have passed
+ task pull_test_pkt(input integer words, input integer inst, input logic gaps, output logic ok);
+ begin
+ logic [(MAX_OUT_WORDS*WORD_W)-1:0] pull_data = 0;
+ logic [MAX_OUT_WORDS-1:0] pull_keep = 0;
+ logic pull_last = 0;
+
+ logic [(MAX_OUT_WORDS*WORD_W)-1:0] data = 0;
+ logic [MAX_OUT_WORDS-1:0] keep = 0;
+ logic last = 0;
+ logic [(MAX_OUT_WORDS*WORD_W)-1:0] mask = 0;
+ integer nspc = OUT_WORDS[inst];
+ integer lines = words/nspc;
+ integer residue = words % nspc;
+ if (residue != 0) begin
+ lines = lines + 1;
+ end
+ for (int l = 0; l < lines; l=l+1) begin
+ last = (l == lines-1);
+ for (int p = 0; p < nspc; p=p+1) begin
+ data[p*WORD_W+:WORD_W] = (l*nspc)+p;
+ end
+ keep = (last && (residue != 0)) ? (1<<residue)-1 : (1<<nspc)-1;
+ mask = (last && (residue != 0)) ? (1<<(residue*WORD_W))-1 : (1<<(nspc*WORD_W))-1;
+ if (inst == 0)
+ s0.pull_word({pull_keep[OUT_WORDS[0]-1:0], pull_data[(OUT_WORDS[0]*WORD_W)-1:0]}, pull_last);
+ else if (inst == 1)
+ s1.pull_word({pull_keep[OUT_WORDS[1]-1:0], pull_data[(OUT_WORDS[1]*WORD_W)-1:0]}, pull_last);
+ else if (inst == 2)
+ s2.pull_word({pull_keep[OUT_WORDS[2]-1:0], pull_data[(OUT_WORDS[2]*WORD_W)-1:0]}, pull_last);
+ else if (inst == 3)
+ s3.pull_word({pull_keep[OUT_WORDS[3]-1:0], pull_data[(OUT_WORDS[3]*WORD_W)-1:0]}, pull_last);
+ else if (inst == 4)
+ s4.pull_word({pull_keep[OUT_WORDS[4]-1:0], pull_data[(OUT_WORDS[4]*WORD_W)-1:0]}, pull_last);
+ else
+ s5.pull_word({pull_keep[OUT_WORDS[5]-1:0], pull_data[(OUT_WORDS[5]*WORD_W)-1:0]}, pull_last);
+
+ // Keep tready deasserted randomly introduce gaps
+ if (gaps) begin
+ integer r = $urandom_range(0, 100);
+ if (r < 20) repeat(r) @(posedge clk50);
+ end
+ // Check data, keep and last
+ ok = ((data&mask) == (pull_data&mask)) && (keep == (pull_keep&((1<<nspc)-1))) && (last == pull_last);
+// $display("PULL(%02d)[%03d]: D{%0x =? %0x}, K{%0b =? %0b}, L{%0b =? %0b} ... %s",
+// inst, l, (data&mask), (pull_data&mask), keep, (pull_keep&((1<<nspc)-1)), last, pull_last, (ok?"OK":"FAIL"));
+ end
+ end
+ endtask
+
+ initial begin : tb_main
+ string s;
+
+ `TEST_CASE_START("Wait for Reset");
+ m0.reset();
+ m1.reset();
+ m2.reset();
+ m3.reset();
+ m4.reset();
+ m5.reset();
+ s0.reset();
+ s1.reset();
+ s2.reset();
+ s3.reset();
+ s4.reset();
+ s5.reset();
+ while (areset) @(posedge clk50);
+ `TEST_CASE_DONE(~areset);
+
+ // Iterate through two modes:
+ // - g == 0: Gapless send and receive. Transfer as fast as possible
+ // - g == 1: Sender and receiver AXI streams will have random bubbles
+ for (int g = 0; g < 2; g=g+1) begin
+ // Iterate through the various instances of the module
+ for (int i = 0; i < NINST; i=i+1) begin
+ $sformat(s, "Testing Instance %0d (%0s gaps)", i, (g==0?"without":"with"));
+ `TEST_CASE_START(s);
+ fork
+ begin
+ // Send packets of increasing size (up to MAX_SPP) to test all
+ // configurations of tkeep and tlast.
+ for (int n = 1; n <= MAX_SPP; n=n+1) begin
+ push_test_pkt(n, i, g);
+ end
+ end
+ begin
+ logic ok;
+ // Receive packets of increasing size and validate tlast, tkeep and tdata
+ for (int n = 1; n <= MAX_SPP; n=n+1) begin
+ pull_test_pkt(n, i, g, ok);
+ $sformat(s, "Packet Validation Failed! (Size=%0d)", n);
+ `ASSERT_ERROR(ok, s);
+ end
+ end
+ join
+ // Gaps to separate the tests in the wfm viewer
+ repeat (100) @(posedge clk50);
+ `TEST_CASE_DONE(1'b1);
+ end
+ end
+
+ `TEST_BENCH_DONE;
+ end
+endmodule
diff --git a/fpga/usrp3/lib/sim/axi_packet_gate/Makefile b/fpga/usrp3/lib/sim/axi_packet_gate/Makefile
new file mode 100644
index 000000000..625a02877
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi_packet_gate/Makefile
@@ -0,0 +1,46 @@
+#
+# Copyright 2016 Ettus Research
+#
+
+#-------------------------------------------------
+# Top-of-Makefile
+#-------------------------------------------------
+# Define BASE_DIR to point to the "top" dir
+BASE_DIR = $(abspath ../../../top)
+# Include viv_sim_preamble 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/control/Makefile.srcs
+include $(BASE_DIR)/../lib/fifo/Makefile.srcs
+
+DESIGN_SRCS = $(abspath \
+$(CONTROL_LIB_SRCS) \
+$(FIFO_SRCS) \
+$(LIB_DIR)/fifo/axi_packet_gate.v \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = axi_packet_gate_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+axi_packet_gate_tb.sv \
+)
+
+# 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/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv b/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv
new file mode 100644
index 000000000..0463a1e28
--- /dev/null
+++ b/fpga/usrp3/lib/sim/axi_packet_gate/axi_packet_gate_tb.sv
@@ -0,0 +1,347 @@
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 7
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_axis_lib.svh"
+
+module axi_packet_gate_tb();
+ `TEST_BENCH_INIT("axi_packet_gate_tb", `NUM_TEST_CASES, `NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/166.67e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ localparam MAX_PKT_SIZE = 64;
+
+ // +1 for terror
+ axis_master #(.DWIDTH(32+1)) m_axis (.clk(clk));
+ axis_slave #(.DWIDTH(32)) s_axis (.clk(clk));
+
+ axi_packet_gate #(
+ .WIDTH(32),
+ .SIZE($clog2(MAX_PKT_SIZE)),
+ .USE_AS_BUFF(1)
+ ) dut (
+ .clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata(m_axis.axis.tdata[31:0]),
+ .i_tvalid(m_axis.axis.tvalid),
+ .i_tlast(m_axis.axis.tlast),
+ .i_terror(m_axis.axis.tdata[32]), // Use MSB as terror
+ .i_tready(m_axis.axis.tready),
+ .o_tdata(s_axis.axis.tdata),
+ .o_tvalid(s_axis.axis.tvalid),
+ .o_tlast(s_axis.axis.tlast),
+ .o_tready(s_axis.axis.tready)
+ );
+
+ /********************************************************
+ ** Verification
+ ********************************************************/
+ task random_wait(int unsigned min_cycles, int unsigned max_cycles);
+ begin
+ int unsigned num_cycles;
+ do begin
+ num_cycles = $random() & (2**($clog2(max_cycles))-1);
+ end while ((num_cycles < min_cycles) || (num_cycles > max_cycles));
+
+ if (num_cycles != 0) begin
+ for (int unsigned i = 0; i < num_cycles; i++) begin
+ @(posedge clk);
+ end
+ @(negedge clk); // Realign with negedge
+ end
+ end
+ endtask
+
+ initial begin : tb_main
+ string s;
+ logic error, last;
+ int cnt, check;
+
+ /********************************************************
+ ** Test 1 -- Reset
+ ********************************************************/
+ `TEST_CASE_START("Wait for Reset");
+ m_axis.reset();
+ s_axis.reset();
+ while (reset) @(posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ /********************************************************
+ ** Test 2 -- Fill / Empty FIFO
+ ********************************************************/
+ `TEST_CASE_START("Fill and empty FIFO");
+ error = 0;
+ last = 0;
+ cnt = 0;
+ $display("Write %0d words to FIFO", MAX_PKT_SIZE);
+ for (int i = 0; i < MAX_PKT_SIZE; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE-1);
+ cnt++;
+ end
+ $display("Done writing to FIFO");
+ if (m_axis.axis.tready) begin
+ $display("FIFO not full, fill remaining space");
+ // Continue filling until FIFO is full
+ while (m_axis.axis.tready) begin
+ m_axis.push_word({error,cnt}, 0);
+ cnt++;
+ end
+ $display("Done filling remaining space");
+ $display("Expected FIFO size: %0d, Actual: %0d",MAX_PKT_SIZE,cnt);
+ end
+ // On the first packet, output is held off until a full packet is received
+ repeat(MAX_PKT_SIZE) @(posedge clk);
+ $display("Empty FIFO and check output");
+ for (int i = 0; i < cnt; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == i, s);
+ if (i == cnt-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ /********************************************************
+ ** Test 3 -- Check gating
+ ********************************************************/
+ `TEST_CASE_START("Check gating");
+ error = 0;
+ last = 0;
+ cnt = 0;
+
+ $display("Write %0d words to FIFO and check out valid", MAX_PKT_SIZE);
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ m_axis.push_word({error,cnt}, 0);
+ cnt++;
+ end
+ // On the first packet, output is held off until a full packet is received
+ repeat(10) @(posedge clk);
+ `ASSERT_FATAL(~s_axis.axis.tvalid, "Saw output before a full packet input");
+ for (int i = MAX_PKT_SIZE/2; i < MAX_PKT_SIZE; i++) begin
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE-1);
+ cnt++;
+ end
+ repeat(10) @(posedge clk);
+ `ASSERT_FATAL(s_axis.axis.tvalid, "Did not see output even after full packet input");
+ $display("Empty FIFO and check output");
+ for (int i = 0; i < cnt; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == i, s);
+ if (i == cnt-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ /********************************************************
+ ** Test 4 -- Ensure no bleed
+ ********************************************************/
+ `TEST_CASE_START("Ensure no bleed");
+ error = 0;
+ last = 0;
+ cnt = 0;
+
+ $display("Write %0d words to FIFO (full packet)", MAX_PKT_SIZE/2);
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ m_axis.push_word({error,cnt}, i == (MAX_PKT_SIZE/2)-1);
+ cnt++;
+ end
+ $display("Write %0d words to FIFO (partial packet)", MAX_PKT_SIZE/4);
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ m_axis.push_word({error,cnt}, 0);
+ cnt++;
+ end
+ // On the first packet, output is held off until a full packet is received
+ repeat(10) @(posedge clk);
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == i, s);
+ if (i == (MAX_PKT_SIZE/2)-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ repeat(10) @(posedge clk);
+ `ASSERT_FATAL(~s_axis.axis.tvalid, "Partial packet bled through with full packet");
+ for (int i = MAX_PKT_SIZE/4; i < MAX_PKT_SIZE/2; i++) begin
+ m_axis.push_word({error,cnt}, i == (MAX_PKT_SIZE/2)-1);
+ cnt++;
+ end
+ repeat(10) @(posedge clk);
+ `ASSERT_FATAL(s_axis.axis.tvalid, "Did not see output even after full packet input");
+ $display("Empty FIFO and check output");
+ for (int i = MAX_PKT_SIZE/2; i < cnt; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == i, s);
+ if (i == cnt-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ /********************************************************
+ ** Test 5 -- Back to back small packets
+ ********************************************************/
+ `TEST_CASE_START("Back to back small packets");
+ error = 0;
+ last = 0;
+ cnt = 0;
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1);
+ cnt++;
+ end
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1);
+ cnt++;
+ end
+ fork
+ begin
+ for (int k = 0; k < 8; k++) begin
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/2-1);
+ cnt++;
+ end
+ end
+ end
+ begin
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ for (int k = 0; k < 10; k++) begin
+ for (int i = 0; i < MAX_PKT_SIZE/2; i++) begin
+ `ASSERT_FATAL(s_axis.axis.tvalid, "tvalid not asserted!");
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == (i+k*MAX_PKT_SIZE/2), s);
+ if (i == MAX_PKT_SIZE/2-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ end
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ #2000; // Delay to make the tests visually distinct in waveform viewer
+
+ /********************************************************
+ ** Test 6 -- Drop error packet
+ ** - Send packet, drop a packet, send another packet
+ ********************************************************/
+ `TEST_CASE_START("Drop error packet");
+ cnt = 0;
+ $display("Write packet with %0d words to FIFO", MAX_PKT_SIZE/4);
+ error = 0;
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1);
+ cnt++;
+ end
+ $display("Write error packet with %0d words to FIFO", MAX_PKT_SIZE/4);
+ error = 1;
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1);
+ cnt++;
+ end
+ $display("Write packet with %0d words to FIFO", MAX_PKT_SIZE/4);
+ error = 0;
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ $sformat(s, "FIFO prematurely full at %0d (tready not asserted!)", i);
+ `ASSERT_FATAL(m_axis.axis.tready, s);
+ m_axis.push_word({error,cnt}, i == MAX_PKT_SIZE/4-1);
+ cnt++;
+ end
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == i, s);
+ if (i == MAX_PKT_SIZE/4-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ for (int i = 0; i < MAX_PKT_SIZE/4; i++) begin
+ $sformat(s, "FIFO prematurely empty at %0d (tvalid not asserted!)", i);
+ `ASSERT_FATAL(s_axis.axis.tvalid, s);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", i, check);
+ `ASSERT_FATAL(check == (i+MAX_PKT_SIZE/2), s);
+ if (i == MAX_PKT_SIZE/4-1) begin
+ `ASSERT_FATAL(last, "tlast not asserted on final word!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ #2000;
+
+ /********************************************************
+ ** Test 7 -- Random read / writes
+ ********************************************************/
+ `TEST_CASE_START("Random read / writes");
+ error = 0;
+ last = 0;
+ cnt = 0;
+ fork
+ begin
+ for (int k = 1; k <= 5000*MAX_PKT_SIZE; k++) begin
+ m_axis.push_word({error,k}, (k % 16) == 0);
+ random_wait(0,16);
+ end
+ end
+ begin
+ for (int k = 1; k <= 5000*MAX_PKT_SIZE; k++) begin
+ random_wait(0,16);
+ s_axis.pull_word(check, last);
+ $sformat(s, "FIFO output incorrect! Expected: %0d, Actual: %0d", k, check);
+ `ASSERT_FATAL(check == k, s);
+ if ((k % 16) == 0) begin
+ `ASSERT_FATAL(last, "tlast not asserted!");
+ end else begin
+ `ASSERT_FATAL(~last, "tlast asserted prematurely!");
+ end
+ end
+ end
+ join
+ `TEST_CASE_DONE(1);
+
+ `TEST_BENCH_DONE;
+
+ end
+endmodule
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/gtk.conf.gtkw b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/gtk.conf.gtkw
new file mode 100644
index 000000000..27c2c836e
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/gtk.conf.gtkw
@@ -0,0 +1,64 @@
+[*]
+[*] GTKWave Analyzer v3.3.40 (w)1999-2012 BSI
+[*] Wed Jul 15 02:18:40 2015
+[*]
+[dumpfile] "/disk2/ianb/ettus/fpgadev-b200/fpgadev/usrp3/lib/dsp/sim/sim_ddc_chain/dc_in_cordic_run/waves.vcd"
+[dumpfile_mtime] "Wed Jul 15 02:13:19 2015"
+[dumpfile_size] 238141440
+[savefile] "/disk2/ianb/ettus/fpgadev-b200/fpgadev/usrp3/lib/dsp/sim/sim_ddc_chain/dc_in_cordic_run/gtk.conf.gtkw"
+[timestart] 0
+[size] 2488 1221
+[pos] -1 -1
+*-24.083374 129800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] ddc_chain_tb.
+[treeopen] ddc_chain_tb.dut_i0.
+[sst_width] 331
+[signals_width] 280
+[sst_expanded] 1
+[sst_vpaned_height] 370
+@28
+ddc_chain_tb.dut_i0.clk
+ddc_chain_tb.dut_i0.rst
+ddc_chain_tb.dut_i0.set_stb
+@22
+#{ddc_chain_tb.dut_i0.set_addr[7:0]} ddc_chain_tb.dut_i0.set_addr[7] ddc_chain_tb.dut_i0.set_addr[6] ddc_chain_tb.dut_i0.set_addr[5] ddc_chain_tb.dut_i0.set_addr[4] ddc_chain_tb.dut_i0.set_addr[3] ddc_chain_tb.dut_i0.set_addr[2] ddc_chain_tb.dut_i0.set_addr[1] ddc_chain_tb.dut_i0.set_addr[0]
+#{ddc_chain_tb.dut_i0.set_data[31:0]} ddc_chain_tb.dut_i0.set_data[31] ddc_chain_tb.dut_i0.set_data[30] ddc_chain_tb.dut_i0.set_data[29] ddc_chain_tb.dut_i0.set_data[28] ddc_chain_tb.dut_i0.set_data[27] ddc_chain_tb.dut_i0.set_data[26] ddc_chain_tb.dut_i0.set_data[25] ddc_chain_tb.dut_i0.set_data[24] ddc_chain_tb.dut_i0.set_data[23] ddc_chain_tb.dut_i0.set_data[22] ddc_chain_tb.dut_i0.set_data[21] ddc_chain_tb.dut_i0.set_data[20] ddc_chain_tb.dut_i0.set_data[19] ddc_chain_tb.dut_i0.set_data[18] ddc_chain_tb.dut_i0.set_data[17] ddc_chain_tb.dut_i0.set_data[16] ddc_chain_tb.dut_i0.set_data[15] ddc_chain_tb.dut_i0.set_data[14] ddc_chain_tb.dut_i0.set_data[13] ddc_chain_tb.dut_i0.set_data[12] ddc_chain_tb.dut_i0.set_data[11] ddc_chain_tb.dut_i0.set_data[10] ddc_chain_tb.dut_i0.set_data[9] ddc_chain_tb.dut_i0.set_data[8] ddc_chain_tb.dut_i0.set_data[7] ddc_chain_tb.dut_i0.set_data[6] ddc_chain_tb.dut_i0.set_data[5] ddc_chain_tb.dut_i0.set_data[4] ddc_chain_tb.dut_i0.set_data[3] ddc_chain_tb.dut_i0.set_data[2] ddc_chain_tb.dut_i0.set_data[1] ddc_chain_tb.dut_i0.set_data[0]
+@10420
+#{ddc_chain_tb.dut_i0.rx_fe_i[23:0]} ddc_chain_tb.dut_i0.rx_fe_i[23] ddc_chain_tb.dut_i0.rx_fe_i[22] ddc_chain_tb.dut_i0.rx_fe_i[21] ddc_chain_tb.dut_i0.rx_fe_i[20] ddc_chain_tb.dut_i0.rx_fe_i[19] ddc_chain_tb.dut_i0.rx_fe_i[18] ddc_chain_tb.dut_i0.rx_fe_i[17] ddc_chain_tb.dut_i0.rx_fe_i[16] ddc_chain_tb.dut_i0.rx_fe_i[15] ddc_chain_tb.dut_i0.rx_fe_i[14] ddc_chain_tb.dut_i0.rx_fe_i[13] ddc_chain_tb.dut_i0.rx_fe_i[12] ddc_chain_tb.dut_i0.rx_fe_i[11] ddc_chain_tb.dut_i0.rx_fe_i[10] ddc_chain_tb.dut_i0.rx_fe_i[9] ddc_chain_tb.dut_i0.rx_fe_i[8] ddc_chain_tb.dut_i0.rx_fe_i[7] ddc_chain_tb.dut_i0.rx_fe_i[6] ddc_chain_tb.dut_i0.rx_fe_i[5] ddc_chain_tb.dut_i0.rx_fe_i[4] ddc_chain_tb.dut_i0.rx_fe_i[3] ddc_chain_tb.dut_i0.rx_fe_i[2] ddc_chain_tb.dut_i0.rx_fe_i[1] ddc_chain_tb.dut_i0.rx_fe_i[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.rx_fe_q[23:0]} ddc_chain_tb.dut_i0.rx_fe_q[23] ddc_chain_tb.dut_i0.rx_fe_q[22] ddc_chain_tb.dut_i0.rx_fe_q[21] ddc_chain_tb.dut_i0.rx_fe_q[20] ddc_chain_tb.dut_i0.rx_fe_q[19] ddc_chain_tb.dut_i0.rx_fe_q[18] ddc_chain_tb.dut_i0.rx_fe_q[17] ddc_chain_tb.dut_i0.rx_fe_q[16] ddc_chain_tb.dut_i0.rx_fe_q[15] ddc_chain_tb.dut_i0.rx_fe_q[14] ddc_chain_tb.dut_i0.rx_fe_q[13] ddc_chain_tb.dut_i0.rx_fe_q[12] ddc_chain_tb.dut_i0.rx_fe_q[11] ddc_chain_tb.dut_i0.rx_fe_q[10] ddc_chain_tb.dut_i0.rx_fe_q[9] ddc_chain_tb.dut_i0.rx_fe_q[8] ddc_chain_tb.dut_i0.rx_fe_q[7] ddc_chain_tb.dut_i0.rx_fe_q[6] ddc_chain_tb.dut_i0.rx_fe_q[5] ddc_chain_tb.dut_i0.rx_fe_q[4] ddc_chain_tb.dut_i0.rx_fe_q[3] ddc_chain_tb.dut_i0.rx_fe_q[2] ddc_chain_tb.dut_i0.rx_fe_q[1] ddc_chain_tb.dut_i0.rx_fe_q[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.i_cordic_clip[23:0]} ddc_chain_tb.dut_i0.i_cordic_clip[23] ddc_chain_tb.dut_i0.i_cordic_clip[22] ddc_chain_tb.dut_i0.i_cordic_clip[21] ddc_chain_tb.dut_i0.i_cordic_clip[20] ddc_chain_tb.dut_i0.i_cordic_clip[19] ddc_chain_tb.dut_i0.i_cordic_clip[18] ddc_chain_tb.dut_i0.i_cordic_clip[17] ddc_chain_tb.dut_i0.i_cordic_clip[16] ddc_chain_tb.dut_i0.i_cordic_clip[15] ddc_chain_tb.dut_i0.i_cordic_clip[14] ddc_chain_tb.dut_i0.i_cordic_clip[13] ddc_chain_tb.dut_i0.i_cordic_clip[12] ddc_chain_tb.dut_i0.i_cordic_clip[11] ddc_chain_tb.dut_i0.i_cordic_clip[10] ddc_chain_tb.dut_i0.i_cordic_clip[9] ddc_chain_tb.dut_i0.i_cordic_clip[8] ddc_chain_tb.dut_i0.i_cordic_clip[7] ddc_chain_tb.dut_i0.i_cordic_clip[6] ddc_chain_tb.dut_i0.i_cordic_clip[5] ddc_chain_tb.dut_i0.i_cordic_clip[4] ddc_chain_tb.dut_i0.i_cordic_clip[3] ddc_chain_tb.dut_i0.i_cordic_clip[2] ddc_chain_tb.dut_i0.i_cordic_clip[1] ddc_chain_tb.dut_i0.i_cordic_clip[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.q_cordic_clip[23:0]} ddc_chain_tb.dut_i0.q_cordic_clip[23] ddc_chain_tb.dut_i0.q_cordic_clip[22] ddc_chain_tb.dut_i0.q_cordic_clip[21] ddc_chain_tb.dut_i0.q_cordic_clip[20] ddc_chain_tb.dut_i0.q_cordic_clip[19] ddc_chain_tb.dut_i0.q_cordic_clip[18] ddc_chain_tb.dut_i0.q_cordic_clip[17] ddc_chain_tb.dut_i0.q_cordic_clip[16] ddc_chain_tb.dut_i0.q_cordic_clip[15] ddc_chain_tb.dut_i0.q_cordic_clip[14] ddc_chain_tb.dut_i0.q_cordic_clip[13] ddc_chain_tb.dut_i0.q_cordic_clip[12] ddc_chain_tb.dut_i0.q_cordic_clip[11] ddc_chain_tb.dut_i0.q_cordic_clip[10] ddc_chain_tb.dut_i0.q_cordic_clip[9] ddc_chain_tb.dut_i0.q_cordic_clip[8] ddc_chain_tb.dut_i0.q_cordic_clip[7] ddc_chain_tb.dut_i0.q_cordic_clip[6] ddc_chain_tb.dut_i0.q_cordic_clip[5] ddc_chain_tb.dut_i0.q_cordic_clip[4] ddc_chain_tb.dut_i0.q_cordic_clip[3] ddc_chain_tb.dut_i0.q_cordic_clip[2] ddc_chain_tb.dut_i0.q_cordic_clip[1] ddc_chain_tb.dut_i0.q_cordic_clip[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.i_cic[23:0]} ddc_chain_tb.dut_i0.i_cic[23] ddc_chain_tb.dut_i0.i_cic[22] ddc_chain_tb.dut_i0.i_cic[21] ddc_chain_tb.dut_i0.i_cic[20] ddc_chain_tb.dut_i0.i_cic[19] ddc_chain_tb.dut_i0.i_cic[18] ddc_chain_tb.dut_i0.i_cic[17] ddc_chain_tb.dut_i0.i_cic[16] ddc_chain_tb.dut_i0.i_cic[15] ddc_chain_tb.dut_i0.i_cic[14] ddc_chain_tb.dut_i0.i_cic[13] ddc_chain_tb.dut_i0.i_cic[12] ddc_chain_tb.dut_i0.i_cic[11] ddc_chain_tb.dut_i0.i_cic[10] ddc_chain_tb.dut_i0.i_cic[9] ddc_chain_tb.dut_i0.i_cic[8] ddc_chain_tb.dut_i0.i_cic[7] ddc_chain_tb.dut_i0.i_cic[6] ddc_chain_tb.dut_i0.i_cic[5] ddc_chain_tb.dut_i0.i_cic[4] ddc_chain_tb.dut_i0.i_cic[3] ddc_chain_tb.dut_i0.i_cic[2] ddc_chain_tb.dut_i0.i_cic[1] ddc_chain_tb.dut_i0.i_cic[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.q_cic[23:0]} ddc_chain_tb.dut_i0.q_cic[23] ddc_chain_tb.dut_i0.q_cic[22] ddc_chain_tb.dut_i0.q_cic[21] ddc_chain_tb.dut_i0.q_cic[20] ddc_chain_tb.dut_i0.q_cic[19] ddc_chain_tb.dut_i0.q_cic[18] ddc_chain_tb.dut_i0.q_cic[17] ddc_chain_tb.dut_i0.q_cic[16] ddc_chain_tb.dut_i0.q_cic[15] ddc_chain_tb.dut_i0.q_cic[14] ddc_chain_tb.dut_i0.q_cic[13] ddc_chain_tb.dut_i0.q_cic[12] ddc_chain_tb.dut_i0.q_cic[11] ddc_chain_tb.dut_i0.q_cic[10] ddc_chain_tb.dut_i0.q_cic[9] ddc_chain_tb.dut_i0.q_cic[8] ddc_chain_tb.dut_i0.q_cic[7] ddc_chain_tb.dut_i0.q_cic[6] ddc_chain_tb.dut_i0.q_cic[5] ddc_chain_tb.dut_i0.q_cic[4] ddc_chain_tb.dut_i0.q_cic[3] ddc_chain_tb.dut_i0.q_cic[2] ddc_chain_tb.dut_i0.q_cic[1] ddc_chain_tb.dut_i0.q_cic[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.i_hb1[46:0]} ddc_chain_tb.dut_i0.\new_hb.i_hb1[46] ddc_chain_tb.dut_i0.\new_hb.i_hb1[45] ddc_chain_tb.dut_i0.\new_hb.i_hb1[44] ddc_chain_tb.dut_i0.\new_hb.i_hb1[43] ddc_chain_tb.dut_i0.\new_hb.i_hb1[42] ddc_chain_tb.dut_i0.\new_hb.i_hb1[41] ddc_chain_tb.dut_i0.\new_hb.i_hb1[40] ddc_chain_tb.dut_i0.\new_hb.i_hb1[39] ddc_chain_tb.dut_i0.\new_hb.i_hb1[38] ddc_chain_tb.dut_i0.\new_hb.i_hb1[37] ddc_chain_tb.dut_i0.\new_hb.i_hb1[36] ddc_chain_tb.dut_i0.\new_hb.i_hb1[35] ddc_chain_tb.dut_i0.\new_hb.i_hb1[34] ddc_chain_tb.dut_i0.\new_hb.i_hb1[33] ddc_chain_tb.dut_i0.\new_hb.i_hb1[32] ddc_chain_tb.dut_i0.\new_hb.i_hb1[31] ddc_chain_tb.dut_i0.\new_hb.i_hb1[30] ddc_chain_tb.dut_i0.\new_hb.i_hb1[29] ddc_chain_tb.dut_i0.\new_hb.i_hb1[28] ddc_chain_tb.dut_i0.\new_hb.i_hb1[27] ddc_chain_tb.dut_i0.\new_hb.i_hb1[26] ddc_chain_tb.dut_i0.\new_hb.i_hb1[25] ddc_chain_tb.dut_i0.\new_hb.i_hb1[24] ddc_chain_tb.dut_i0.\new_hb.i_hb1[23] ddc_chain_tb.dut_i0.\new_hb.i_hb1[22] ddc_chain_tb.dut_i0.\new_hb.i_hb1[21] ddc_chain_tb.dut_i0.\new_hb.i_hb1[20] ddc_chain_tb.dut_i0.\new_hb.i_hb1[19] ddc_chain_tb.dut_i0.\new_hb.i_hb1[18] ddc_chain_tb.dut_i0.\new_hb.i_hb1[17] ddc_chain_tb.dut_i0.\new_hb.i_hb1[16] ddc_chain_tb.dut_i0.\new_hb.i_hb1[15] ddc_chain_tb.dut_i0.\new_hb.i_hb1[14] ddc_chain_tb.dut_i0.\new_hb.i_hb1[13] ddc_chain_tb.dut_i0.\new_hb.i_hb1[12] ddc_chain_tb.dut_i0.\new_hb.i_hb1[11] ddc_chain_tb.dut_i0.\new_hb.i_hb1[10] ddc_chain_tb.dut_i0.\new_hb.i_hb1[9] ddc_chain_tb.dut_i0.\new_hb.i_hb1[8] ddc_chain_tb.dut_i0.\new_hb.i_hb1[7] ddc_chain_tb.dut_i0.\new_hb.i_hb1[6] ddc_chain_tb.dut_i0.\new_hb.i_hb1[5] ddc_chain_tb.dut_i0.\new_hb.i_hb1[4] ddc_chain_tb.dut_i0.\new_hb.i_hb1[3] ddc_chain_tb.dut_i0.\new_hb.i_hb1[2] ddc_chain_tb.dut_i0.\new_hb.i_hb1[1] ddc_chain_tb.dut_i0.\new_hb.i_hb1[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.q_hb1[46:0]} ddc_chain_tb.dut_i0.\new_hb.q_hb1[46] ddc_chain_tb.dut_i0.\new_hb.q_hb1[45] ddc_chain_tb.dut_i0.\new_hb.q_hb1[44] ddc_chain_tb.dut_i0.\new_hb.q_hb1[43] ddc_chain_tb.dut_i0.\new_hb.q_hb1[42] ddc_chain_tb.dut_i0.\new_hb.q_hb1[41] ddc_chain_tb.dut_i0.\new_hb.q_hb1[40] ddc_chain_tb.dut_i0.\new_hb.q_hb1[39] ddc_chain_tb.dut_i0.\new_hb.q_hb1[38] ddc_chain_tb.dut_i0.\new_hb.q_hb1[37] ddc_chain_tb.dut_i0.\new_hb.q_hb1[36] ddc_chain_tb.dut_i0.\new_hb.q_hb1[35] ddc_chain_tb.dut_i0.\new_hb.q_hb1[34] ddc_chain_tb.dut_i0.\new_hb.q_hb1[33] ddc_chain_tb.dut_i0.\new_hb.q_hb1[32] ddc_chain_tb.dut_i0.\new_hb.q_hb1[31] ddc_chain_tb.dut_i0.\new_hb.q_hb1[30] ddc_chain_tb.dut_i0.\new_hb.q_hb1[29] ddc_chain_tb.dut_i0.\new_hb.q_hb1[28] ddc_chain_tb.dut_i0.\new_hb.q_hb1[27] ddc_chain_tb.dut_i0.\new_hb.q_hb1[26] ddc_chain_tb.dut_i0.\new_hb.q_hb1[25] ddc_chain_tb.dut_i0.\new_hb.q_hb1[24] ddc_chain_tb.dut_i0.\new_hb.q_hb1[23] ddc_chain_tb.dut_i0.\new_hb.q_hb1[22] ddc_chain_tb.dut_i0.\new_hb.q_hb1[21] ddc_chain_tb.dut_i0.\new_hb.q_hb1[20] ddc_chain_tb.dut_i0.\new_hb.q_hb1[19] ddc_chain_tb.dut_i0.\new_hb.q_hb1[18] ddc_chain_tb.dut_i0.\new_hb.q_hb1[17] ddc_chain_tb.dut_i0.\new_hb.q_hb1[16] ddc_chain_tb.dut_i0.\new_hb.q_hb1[15] ddc_chain_tb.dut_i0.\new_hb.q_hb1[14] ddc_chain_tb.dut_i0.\new_hb.q_hb1[13] ddc_chain_tb.dut_i0.\new_hb.q_hb1[12] ddc_chain_tb.dut_i0.\new_hb.q_hb1[11] ddc_chain_tb.dut_i0.\new_hb.q_hb1[10] ddc_chain_tb.dut_i0.\new_hb.q_hb1[9] ddc_chain_tb.dut_i0.\new_hb.q_hb1[8] ddc_chain_tb.dut_i0.\new_hb.q_hb1[7] ddc_chain_tb.dut_i0.\new_hb.q_hb1[6] ddc_chain_tb.dut_i0.\new_hb.q_hb1[5] ddc_chain_tb.dut_i0.\new_hb.q_hb1[4] ddc_chain_tb.dut_i0.\new_hb.q_hb1[3] ddc_chain_tb.dut_i0.\new_hb.q_hb1[2] ddc_chain_tb.dut_i0.\new_hb.q_hb1[1] ddc_chain_tb.dut_i0.\new_hb.q_hb1[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.i_hb2[46:0]} ddc_chain_tb.dut_i0.\new_hb.i_hb2[46] ddc_chain_tb.dut_i0.\new_hb.i_hb2[45] ddc_chain_tb.dut_i0.\new_hb.i_hb2[44] ddc_chain_tb.dut_i0.\new_hb.i_hb2[43] ddc_chain_tb.dut_i0.\new_hb.i_hb2[42] ddc_chain_tb.dut_i0.\new_hb.i_hb2[41] ddc_chain_tb.dut_i0.\new_hb.i_hb2[40] ddc_chain_tb.dut_i0.\new_hb.i_hb2[39] ddc_chain_tb.dut_i0.\new_hb.i_hb2[38] ddc_chain_tb.dut_i0.\new_hb.i_hb2[37] ddc_chain_tb.dut_i0.\new_hb.i_hb2[36] ddc_chain_tb.dut_i0.\new_hb.i_hb2[35] ddc_chain_tb.dut_i0.\new_hb.i_hb2[34] ddc_chain_tb.dut_i0.\new_hb.i_hb2[33] ddc_chain_tb.dut_i0.\new_hb.i_hb2[32] ddc_chain_tb.dut_i0.\new_hb.i_hb2[31] ddc_chain_tb.dut_i0.\new_hb.i_hb2[30] ddc_chain_tb.dut_i0.\new_hb.i_hb2[29] ddc_chain_tb.dut_i0.\new_hb.i_hb2[28] ddc_chain_tb.dut_i0.\new_hb.i_hb2[27] ddc_chain_tb.dut_i0.\new_hb.i_hb2[26] ddc_chain_tb.dut_i0.\new_hb.i_hb2[25] ddc_chain_tb.dut_i0.\new_hb.i_hb2[24] ddc_chain_tb.dut_i0.\new_hb.i_hb2[23] ddc_chain_tb.dut_i0.\new_hb.i_hb2[22] ddc_chain_tb.dut_i0.\new_hb.i_hb2[21] ddc_chain_tb.dut_i0.\new_hb.i_hb2[20] ddc_chain_tb.dut_i0.\new_hb.i_hb2[19] ddc_chain_tb.dut_i0.\new_hb.i_hb2[18] ddc_chain_tb.dut_i0.\new_hb.i_hb2[17] ddc_chain_tb.dut_i0.\new_hb.i_hb2[16] ddc_chain_tb.dut_i0.\new_hb.i_hb2[15] ddc_chain_tb.dut_i0.\new_hb.i_hb2[14] ddc_chain_tb.dut_i0.\new_hb.i_hb2[13] ddc_chain_tb.dut_i0.\new_hb.i_hb2[12] ddc_chain_tb.dut_i0.\new_hb.i_hb2[11] ddc_chain_tb.dut_i0.\new_hb.i_hb2[10] ddc_chain_tb.dut_i0.\new_hb.i_hb2[9] ddc_chain_tb.dut_i0.\new_hb.i_hb2[8] ddc_chain_tb.dut_i0.\new_hb.i_hb2[7] ddc_chain_tb.dut_i0.\new_hb.i_hb2[6] ddc_chain_tb.dut_i0.\new_hb.i_hb2[5] ddc_chain_tb.dut_i0.\new_hb.i_hb2[4] ddc_chain_tb.dut_i0.\new_hb.i_hb2[3] ddc_chain_tb.dut_i0.\new_hb.i_hb2[2] ddc_chain_tb.dut_i0.\new_hb.i_hb2[1] ddc_chain_tb.dut_i0.\new_hb.i_hb2[0]
+#{ddc_chain_tb.dut_i0.\new_hb.q_hb2[46:0]} ddc_chain_tb.dut_i0.\new_hb.q_hb2[46] ddc_chain_tb.dut_i0.\new_hb.q_hb2[45] ddc_chain_tb.dut_i0.\new_hb.q_hb2[44] ddc_chain_tb.dut_i0.\new_hb.q_hb2[43] ddc_chain_tb.dut_i0.\new_hb.q_hb2[42] ddc_chain_tb.dut_i0.\new_hb.q_hb2[41] ddc_chain_tb.dut_i0.\new_hb.q_hb2[40] ddc_chain_tb.dut_i0.\new_hb.q_hb2[39] ddc_chain_tb.dut_i0.\new_hb.q_hb2[38] ddc_chain_tb.dut_i0.\new_hb.q_hb2[37] ddc_chain_tb.dut_i0.\new_hb.q_hb2[36] ddc_chain_tb.dut_i0.\new_hb.q_hb2[35] ddc_chain_tb.dut_i0.\new_hb.q_hb2[34] ddc_chain_tb.dut_i0.\new_hb.q_hb2[33] ddc_chain_tb.dut_i0.\new_hb.q_hb2[32] ddc_chain_tb.dut_i0.\new_hb.q_hb2[31] ddc_chain_tb.dut_i0.\new_hb.q_hb2[30] ddc_chain_tb.dut_i0.\new_hb.q_hb2[29] ddc_chain_tb.dut_i0.\new_hb.q_hb2[28] ddc_chain_tb.dut_i0.\new_hb.q_hb2[27] ddc_chain_tb.dut_i0.\new_hb.q_hb2[26] ddc_chain_tb.dut_i0.\new_hb.q_hb2[25] ddc_chain_tb.dut_i0.\new_hb.q_hb2[24] ddc_chain_tb.dut_i0.\new_hb.q_hb2[23] ddc_chain_tb.dut_i0.\new_hb.q_hb2[22] ddc_chain_tb.dut_i0.\new_hb.q_hb2[21] ddc_chain_tb.dut_i0.\new_hb.q_hb2[20] ddc_chain_tb.dut_i0.\new_hb.q_hb2[19] ddc_chain_tb.dut_i0.\new_hb.q_hb2[18] ddc_chain_tb.dut_i0.\new_hb.q_hb2[17] ddc_chain_tb.dut_i0.\new_hb.q_hb2[16] ddc_chain_tb.dut_i0.\new_hb.q_hb2[15] ddc_chain_tb.dut_i0.\new_hb.q_hb2[14] ddc_chain_tb.dut_i0.\new_hb.q_hb2[13] ddc_chain_tb.dut_i0.\new_hb.q_hb2[12] ddc_chain_tb.dut_i0.\new_hb.q_hb2[11] ddc_chain_tb.dut_i0.\new_hb.q_hb2[10] ddc_chain_tb.dut_i0.\new_hb.q_hb2[9] ddc_chain_tb.dut_i0.\new_hb.q_hb2[8] ddc_chain_tb.dut_i0.\new_hb.q_hb2[7] ddc_chain_tb.dut_i0.\new_hb.q_hb2[6] ddc_chain_tb.dut_i0.\new_hb.q_hb2[5] ddc_chain_tb.dut_i0.\new_hb.q_hb2[4] ddc_chain_tb.dut_i0.\new_hb.q_hb2[3] ddc_chain_tb.dut_i0.\new_hb.q_hb2[2] ddc_chain_tb.dut_i0.\new_hb.q_hb2[1] ddc_chain_tb.dut_i0.\new_hb.q_hb2[0]
+@20000
+-
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/simulation_script.v b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/simulation_script.v
new file mode 100644
index 000000000..bc11b8b01
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_2/simulation_script.v
@@ -0,0 +1,82 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// 10MHz master_clock_rate
+always #50 clk <= ~clk;
+
+ initial
+ begin
+ reset <= 1'b0;
+ i_in <= 0;
+ q_in <= 0;
+ run <= 0;
+ set_stb <= 0;
+ set_addr <= 0;
+ set_data <= 0;
+
+
+ @(posedge clk);
+ // Into Reset...
+ reset <= 1'b1;
+ repeat(10) @(posedge clk);
+ // .. and back out of reset.
+ reset <= 1'b0;
+ repeat(10) @(posedge clk);
+ // Now program DSP configuration via settings regs.
+ write_setting_bus(SR_DSP_RX_FREQ,42949672); // 100kHz @ 10MHz MCR
+ // (1 << 15) * std::pow(2, ceil_log2(rate_pow))*2./(1.648*rate_pow)
+ write_setting_bus(SR_DSP_RX_SCALE_IQ, 39767); // Should include CORDIC and CIC gain compensation.
+ write_setting_bus(SR_DSP_RX_DECIM, 1<<9|1); // Decim = 2
+ write_setting_bus(SR_DSP_RX_MUX, 0);
+ write_setting_bus(SR_DSP_RX_COEFFS,0);
+ repeat(10) @(posedge clk);
+
+ // Set complex data inputs to DC unit circle position.
+ i_in <= 12'h7ff;
+ q_in <= 12'h0;
+ run <= 1'b1;
+ repeat(100) @(posedge clk);
+ // Set complex data inputs to simulate ADC saturation of front end
+ i_in <= 12'h7ff;
+ q_in <= 12'h100;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h200;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h300;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h400;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h500;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h600;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h700;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h7FF;
+ // Now test small signal performance
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h001;
+ q_in <= 12'h000;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h000;
+ q_in <= 12'h001;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'hfff;
+ q_in <= 12'h000;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h000;
+ q_in <= 12'hfff;
+
+ repeat(100000) @(posedge clk);
+ $finish();
+
+ end // initial begin
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/gtk.conf.gtkw b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/gtk.conf.gtkw
new file mode 100644
index 000000000..27c2c836e
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/gtk.conf.gtkw
@@ -0,0 +1,64 @@
+[*]
+[*] GTKWave Analyzer v3.3.40 (w)1999-2012 BSI
+[*] Wed Jul 15 02:18:40 2015
+[*]
+[dumpfile] "/disk2/ianb/ettus/fpgadev-b200/fpgadev/usrp3/lib/dsp/sim/sim_ddc_chain/dc_in_cordic_run/waves.vcd"
+[dumpfile_mtime] "Wed Jul 15 02:13:19 2015"
+[dumpfile_size] 238141440
+[savefile] "/disk2/ianb/ettus/fpgadev-b200/fpgadev/usrp3/lib/dsp/sim/sim_ddc_chain/dc_in_cordic_run/gtk.conf.gtkw"
+[timestart] 0
+[size] 2488 1221
+[pos] -1 -1
+*-24.083374 129800000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] ddc_chain_tb.
+[treeopen] ddc_chain_tb.dut_i0.
+[sst_width] 331
+[signals_width] 280
+[sst_expanded] 1
+[sst_vpaned_height] 370
+@28
+ddc_chain_tb.dut_i0.clk
+ddc_chain_tb.dut_i0.rst
+ddc_chain_tb.dut_i0.set_stb
+@22
+#{ddc_chain_tb.dut_i0.set_addr[7:0]} ddc_chain_tb.dut_i0.set_addr[7] ddc_chain_tb.dut_i0.set_addr[6] ddc_chain_tb.dut_i0.set_addr[5] ddc_chain_tb.dut_i0.set_addr[4] ddc_chain_tb.dut_i0.set_addr[3] ddc_chain_tb.dut_i0.set_addr[2] ddc_chain_tb.dut_i0.set_addr[1] ddc_chain_tb.dut_i0.set_addr[0]
+#{ddc_chain_tb.dut_i0.set_data[31:0]} ddc_chain_tb.dut_i0.set_data[31] ddc_chain_tb.dut_i0.set_data[30] ddc_chain_tb.dut_i0.set_data[29] ddc_chain_tb.dut_i0.set_data[28] ddc_chain_tb.dut_i0.set_data[27] ddc_chain_tb.dut_i0.set_data[26] ddc_chain_tb.dut_i0.set_data[25] ddc_chain_tb.dut_i0.set_data[24] ddc_chain_tb.dut_i0.set_data[23] ddc_chain_tb.dut_i0.set_data[22] ddc_chain_tb.dut_i0.set_data[21] ddc_chain_tb.dut_i0.set_data[20] ddc_chain_tb.dut_i0.set_data[19] ddc_chain_tb.dut_i0.set_data[18] ddc_chain_tb.dut_i0.set_data[17] ddc_chain_tb.dut_i0.set_data[16] ddc_chain_tb.dut_i0.set_data[15] ddc_chain_tb.dut_i0.set_data[14] ddc_chain_tb.dut_i0.set_data[13] ddc_chain_tb.dut_i0.set_data[12] ddc_chain_tb.dut_i0.set_data[11] ddc_chain_tb.dut_i0.set_data[10] ddc_chain_tb.dut_i0.set_data[9] ddc_chain_tb.dut_i0.set_data[8] ddc_chain_tb.dut_i0.set_data[7] ddc_chain_tb.dut_i0.set_data[6] ddc_chain_tb.dut_i0.set_data[5] ddc_chain_tb.dut_i0.set_data[4] ddc_chain_tb.dut_i0.set_data[3] ddc_chain_tb.dut_i0.set_data[2] ddc_chain_tb.dut_i0.set_data[1] ddc_chain_tb.dut_i0.set_data[0]
+@10420
+#{ddc_chain_tb.dut_i0.rx_fe_i[23:0]} ddc_chain_tb.dut_i0.rx_fe_i[23] ddc_chain_tb.dut_i0.rx_fe_i[22] ddc_chain_tb.dut_i0.rx_fe_i[21] ddc_chain_tb.dut_i0.rx_fe_i[20] ddc_chain_tb.dut_i0.rx_fe_i[19] ddc_chain_tb.dut_i0.rx_fe_i[18] ddc_chain_tb.dut_i0.rx_fe_i[17] ddc_chain_tb.dut_i0.rx_fe_i[16] ddc_chain_tb.dut_i0.rx_fe_i[15] ddc_chain_tb.dut_i0.rx_fe_i[14] ddc_chain_tb.dut_i0.rx_fe_i[13] ddc_chain_tb.dut_i0.rx_fe_i[12] ddc_chain_tb.dut_i0.rx_fe_i[11] ddc_chain_tb.dut_i0.rx_fe_i[10] ddc_chain_tb.dut_i0.rx_fe_i[9] ddc_chain_tb.dut_i0.rx_fe_i[8] ddc_chain_tb.dut_i0.rx_fe_i[7] ddc_chain_tb.dut_i0.rx_fe_i[6] ddc_chain_tb.dut_i0.rx_fe_i[5] ddc_chain_tb.dut_i0.rx_fe_i[4] ddc_chain_tb.dut_i0.rx_fe_i[3] ddc_chain_tb.dut_i0.rx_fe_i[2] ddc_chain_tb.dut_i0.rx_fe_i[1] ddc_chain_tb.dut_i0.rx_fe_i[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.rx_fe_q[23:0]} ddc_chain_tb.dut_i0.rx_fe_q[23] ddc_chain_tb.dut_i0.rx_fe_q[22] ddc_chain_tb.dut_i0.rx_fe_q[21] ddc_chain_tb.dut_i0.rx_fe_q[20] ddc_chain_tb.dut_i0.rx_fe_q[19] ddc_chain_tb.dut_i0.rx_fe_q[18] ddc_chain_tb.dut_i0.rx_fe_q[17] ddc_chain_tb.dut_i0.rx_fe_q[16] ddc_chain_tb.dut_i0.rx_fe_q[15] ddc_chain_tb.dut_i0.rx_fe_q[14] ddc_chain_tb.dut_i0.rx_fe_q[13] ddc_chain_tb.dut_i0.rx_fe_q[12] ddc_chain_tb.dut_i0.rx_fe_q[11] ddc_chain_tb.dut_i0.rx_fe_q[10] ddc_chain_tb.dut_i0.rx_fe_q[9] ddc_chain_tb.dut_i0.rx_fe_q[8] ddc_chain_tb.dut_i0.rx_fe_q[7] ddc_chain_tb.dut_i0.rx_fe_q[6] ddc_chain_tb.dut_i0.rx_fe_q[5] ddc_chain_tb.dut_i0.rx_fe_q[4] ddc_chain_tb.dut_i0.rx_fe_q[3] ddc_chain_tb.dut_i0.rx_fe_q[2] ddc_chain_tb.dut_i0.rx_fe_q[1] ddc_chain_tb.dut_i0.rx_fe_q[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.i_cordic_clip[23:0]} ddc_chain_tb.dut_i0.i_cordic_clip[23] ddc_chain_tb.dut_i0.i_cordic_clip[22] ddc_chain_tb.dut_i0.i_cordic_clip[21] ddc_chain_tb.dut_i0.i_cordic_clip[20] ddc_chain_tb.dut_i0.i_cordic_clip[19] ddc_chain_tb.dut_i0.i_cordic_clip[18] ddc_chain_tb.dut_i0.i_cordic_clip[17] ddc_chain_tb.dut_i0.i_cordic_clip[16] ddc_chain_tb.dut_i0.i_cordic_clip[15] ddc_chain_tb.dut_i0.i_cordic_clip[14] ddc_chain_tb.dut_i0.i_cordic_clip[13] ddc_chain_tb.dut_i0.i_cordic_clip[12] ddc_chain_tb.dut_i0.i_cordic_clip[11] ddc_chain_tb.dut_i0.i_cordic_clip[10] ddc_chain_tb.dut_i0.i_cordic_clip[9] ddc_chain_tb.dut_i0.i_cordic_clip[8] ddc_chain_tb.dut_i0.i_cordic_clip[7] ddc_chain_tb.dut_i0.i_cordic_clip[6] ddc_chain_tb.dut_i0.i_cordic_clip[5] ddc_chain_tb.dut_i0.i_cordic_clip[4] ddc_chain_tb.dut_i0.i_cordic_clip[3] ddc_chain_tb.dut_i0.i_cordic_clip[2] ddc_chain_tb.dut_i0.i_cordic_clip[1] ddc_chain_tb.dut_i0.i_cordic_clip[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.q_cordic_clip[23:0]} ddc_chain_tb.dut_i0.q_cordic_clip[23] ddc_chain_tb.dut_i0.q_cordic_clip[22] ddc_chain_tb.dut_i0.q_cordic_clip[21] ddc_chain_tb.dut_i0.q_cordic_clip[20] ddc_chain_tb.dut_i0.q_cordic_clip[19] ddc_chain_tb.dut_i0.q_cordic_clip[18] ddc_chain_tb.dut_i0.q_cordic_clip[17] ddc_chain_tb.dut_i0.q_cordic_clip[16] ddc_chain_tb.dut_i0.q_cordic_clip[15] ddc_chain_tb.dut_i0.q_cordic_clip[14] ddc_chain_tb.dut_i0.q_cordic_clip[13] ddc_chain_tb.dut_i0.q_cordic_clip[12] ddc_chain_tb.dut_i0.q_cordic_clip[11] ddc_chain_tb.dut_i0.q_cordic_clip[10] ddc_chain_tb.dut_i0.q_cordic_clip[9] ddc_chain_tb.dut_i0.q_cordic_clip[8] ddc_chain_tb.dut_i0.q_cordic_clip[7] ddc_chain_tb.dut_i0.q_cordic_clip[6] ddc_chain_tb.dut_i0.q_cordic_clip[5] ddc_chain_tb.dut_i0.q_cordic_clip[4] ddc_chain_tb.dut_i0.q_cordic_clip[3] ddc_chain_tb.dut_i0.q_cordic_clip[2] ddc_chain_tb.dut_i0.q_cordic_clip[1] ddc_chain_tb.dut_i0.q_cordic_clip[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.i_cic[23:0]} ddc_chain_tb.dut_i0.i_cic[23] ddc_chain_tb.dut_i0.i_cic[22] ddc_chain_tb.dut_i0.i_cic[21] ddc_chain_tb.dut_i0.i_cic[20] ddc_chain_tb.dut_i0.i_cic[19] ddc_chain_tb.dut_i0.i_cic[18] ddc_chain_tb.dut_i0.i_cic[17] ddc_chain_tb.dut_i0.i_cic[16] ddc_chain_tb.dut_i0.i_cic[15] ddc_chain_tb.dut_i0.i_cic[14] ddc_chain_tb.dut_i0.i_cic[13] ddc_chain_tb.dut_i0.i_cic[12] ddc_chain_tb.dut_i0.i_cic[11] ddc_chain_tb.dut_i0.i_cic[10] ddc_chain_tb.dut_i0.i_cic[9] ddc_chain_tb.dut_i0.i_cic[8] ddc_chain_tb.dut_i0.i_cic[7] ddc_chain_tb.dut_i0.i_cic[6] ddc_chain_tb.dut_i0.i_cic[5] ddc_chain_tb.dut_i0.i_cic[4] ddc_chain_tb.dut_i0.i_cic[3] ddc_chain_tb.dut_i0.i_cic[2] ddc_chain_tb.dut_i0.i_cic[1] ddc_chain_tb.dut_i0.i_cic[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.q_cic[23:0]} ddc_chain_tb.dut_i0.q_cic[23] ddc_chain_tb.dut_i0.q_cic[22] ddc_chain_tb.dut_i0.q_cic[21] ddc_chain_tb.dut_i0.q_cic[20] ddc_chain_tb.dut_i0.q_cic[19] ddc_chain_tb.dut_i0.q_cic[18] ddc_chain_tb.dut_i0.q_cic[17] ddc_chain_tb.dut_i0.q_cic[16] ddc_chain_tb.dut_i0.q_cic[15] ddc_chain_tb.dut_i0.q_cic[14] ddc_chain_tb.dut_i0.q_cic[13] ddc_chain_tb.dut_i0.q_cic[12] ddc_chain_tb.dut_i0.q_cic[11] ddc_chain_tb.dut_i0.q_cic[10] ddc_chain_tb.dut_i0.q_cic[9] ddc_chain_tb.dut_i0.q_cic[8] ddc_chain_tb.dut_i0.q_cic[7] ddc_chain_tb.dut_i0.q_cic[6] ddc_chain_tb.dut_i0.q_cic[5] ddc_chain_tb.dut_i0.q_cic[4] ddc_chain_tb.dut_i0.q_cic[3] ddc_chain_tb.dut_i0.q_cic[2] ddc_chain_tb.dut_i0.q_cic[1] ddc_chain_tb.dut_i0.q_cic[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.i_hb1[46:0]} ddc_chain_tb.dut_i0.\new_hb.i_hb1[46] ddc_chain_tb.dut_i0.\new_hb.i_hb1[45] ddc_chain_tb.dut_i0.\new_hb.i_hb1[44] ddc_chain_tb.dut_i0.\new_hb.i_hb1[43] ddc_chain_tb.dut_i0.\new_hb.i_hb1[42] ddc_chain_tb.dut_i0.\new_hb.i_hb1[41] ddc_chain_tb.dut_i0.\new_hb.i_hb1[40] ddc_chain_tb.dut_i0.\new_hb.i_hb1[39] ddc_chain_tb.dut_i0.\new_hb.i_hb1[38] ddc_chain_tb.dut_i0.\new_hb.i_hb1[37] ddc_chain_tb.dut_i0.\new_hb.i_hb1[36] ddc_chain_tb.dut_i0.\new_hb.i_hb1[35] ddc_chain_tb.dut_i0.\new_hb.i_hb1[34] ddc_chain_tb.dut_i0.\new_hb.i_hb1[33] ddc_chain_tb.dut_i0.\new_hb.i_hb1[32] ddc_chain_tb.dut_i0.\new_hb.i_hb1[31] ddc_chain_tb.dut_i0.\new_hb.i_hb1[30] ddc_chain_tb.dut_i0.\new_hb.i_hb1[29] ddc_chain_tb.dut_i0.\new_hb.i_hb1[28] ddc_chain_tb.dut_i0.\new_hb.i_hb1[27] ddc_chain_tb.dut_i0.\new_hb.i_hb1[26] ddc_chain_tb.dut_i0.\new_hb.i_hb1[25] ddc_chain_tb.dut_i0.\new_hb.i_hb1[24] ddc_chain_tb.dut_i0.\new_hb.i_hb1[23] ddc_chain_tb.dut_i0.\new_hb.i_hb1[22] ddc_chain_tb.dut_i0.\new_hb.i_hb1[21] ddc_chain_tb.dut_i0.\new_hb.i_hb1[20] ddc_chain_tb.dut_i0.\new_hb.i_hb1[19] ddc_chain_tb.dut_i0.\new_hb.i_hb1[18] ddc_chain_tb.dut_i0.\new_hb.i_hb1[17] ddc_chain_tb.dut_i0.\new_hb.i_hb1[16] ddc_chain_tb.dut_i0.\new_hb.i_hb1[15] ddc_chain_tb.dut_i0.\new_hb.i_hb1[14] ddc_chain_tb.dut_i0.\new_hb.i_hb1[13] ddc_chain_tb.dut_i0.\new_hb.i_hb1[12] ddc_chain_tb.dut_i0.\new_hb.i_hb1[11] ddc_chain_tb.dut_i0.\new_hb.i_hb1[10] ddc_chain_tb.dut_i0.\new_hb.i_hb1[9] ddc_chain_tb.dut_i0.\new_hb.i_hb1[8] ddc_chain_tb.dut_i0.\new_hb.i_hb1[7] ddc_chain_tb.dut_i0.\new_hb.i_hb1[6] ddc_chain_tb.dut_i0.\new_hb.i_hb1[5] ddc_chain_tb.dut_i0.\new_hb.i_hb1[4] ddc_chain_tb.dut_i0.\new_hb.i_hb1[3] ddc_chain_tb.dut_i0.\new_hb.i_hb1[2] ddc_chain_tb.dut_i0.\new_hb.i_hb1[1] ddc_chain_tb.dut_i0.\new_hb.i_hb1[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.q_hb1[46:0]} ddc_chain_tb.dut_i0.\new_hb.q_hb1[46] ddc_chain_tb.dut_i0.\new_hb.q_hb1[45] ddc_chain_tb.dut_i0.\new_hb.q_hb1[44] ddc_chain_tb.dut_i0.\new_hb.q_hb1[43] ddc_chain_tb.dut_i0.\new_hb.q_hb1[42] ddc_chain_tb.dut_i0.\new_hb.q_hb1[41] ddc_chain_tb.dut_i0.\new_hb.q_hb1[40] ddc_chain_tb.dut_i0.\new_hb.q_hb1[39] ddc_chain_tb.dut_i0.\new_hb.q_hb1[38] ddc_chain_tb.dut_i0.\new_hb.q_hb1[37] ddc_chain_tb.dut_i0.\new_hb.q_hb1[36] ddc_chain_tb.dut_i0.\new_hb.q_hb1[35] ddc_chain_tb.dut_i0.\new_hb.q_hb1[34] ddc_chain_tb.dut_i0.\new_hb.q_hb1[33] ddc_chain_tb.dut_i0.\new_hb.q_hb1[32] ddc_chain_tb.dut_i0.\new_hb.q_hb1[31] ddc_chain_tb.dut_i0.\new_hb.q_hb1[30] ddc_chain_tb.dut_i0.\new_hb.q_hb1[29] ddc_chain_tb.dut_i0.\new_hb.q_hb1[28] ddc_chain_tb.dut_i0.\new_hb.q_hb1[27] ddc_chain_tb.dut_i0.\new_hb.q_hb1[26] ddc_chain_tb.dut_i0.\new_hb.q_hb1[25] ddc_chain_tb.dut_i0.\new_hb.q_hb1[24] ddc_chain_tb.dut_i0.\new_hb.q_hb1[23] ddc_chain_tb.dut_i0.\new_hb.q_hb1[22] ddc_chain_tb.dut_i0.\new_hb.q_hb1[21] ddc_chain_tb.dut_i0.\new_hb.q_hb1[20] ddc_chain_tb.dut_i0.\new_hb.q_hb1[19] ddc_chain_tb.dut_i0.\new_hb.q_hb1[18] ddc_chain_tb.dut_i0.\new_hb.q_hb1[17] ddc_chain_tb.dut_i0.\new_hb.q_hb1[16] ddc_chain_tb.dut_i0.\new_hb.q_hb1[15] ddc_chain_tb.dut_i0.\new_hb.q_hb1[14] ddc_chain_tb.dut_i0.\new_hb.q_hb1[13] ddc_chain_tb.dut_i0.\new_hb.q_hb1[12] ddc_chain_tb.dut_i0.\new_hb.q_hb1[11] ddc_chain_tb.dut_i0.\new_hb.q_hb1[10] ddc_chain_tb.dut_i0.\new_hb.q_hb1[9] ddc_chain_tb.dut_i0.\new_hb.q_hb1[8] ddc_chain_tb.dut_i0.\new_hb.q_hb1[7] ddc_chain_tb.dut_i0.\new_hb.q_hb1[6] ddc_chain_tb.dut_i0.\new_hb.q_hb1[5] ddc_chain_tb.dut_i0.\new_hb.q_hb1[4] ddc_chain_tb.dut_i0.\new_hb.q_hb1[3] ddc_chain_tb.dut_i0.\new_hb.q_hb1[2] ddc_chain_tb.dut_i0.\new_hb.q_hb1[1] ddc_chain_tb.dut_i0.\new_hb.q_hb1[0]
+@20000
+-
+@10420
+#{ddc_chain_tb.dut_i0.\new_hb.i_hb2[46:0]} ddc_chain_tb.dut_i0.\new_hb.i_hb2[46] ddc_chain_tb.dut_i0.\new_hb.i_hb2[45] ddc_chain_tb.dut_i0.\new_hb.i_hb2[44] ddc_chain_tb.dut_i0.\new_hb.i_hb2[43] ddc_chain_tb.dut_i0.\new_hb.i_hb2[42] ddc_chain_tb.dut_i0.\new_hb.i_hb2[41] ddc_chain_tb.dut_i0.\new_hb.i_hb2[40] ddc_chain_tb.dut_i0.\new_hb.i_hb2[39] ddc_chain_tb.dut_i0.\new_hb.i_hb2[38] ddc_chain_tb.dut_i0.\new_hb.i_hb2[37] ddc_chain_tb.dut_i0.\new_hb.i_hb2[36] ddc_chain_tb.dut_i0.\new_hb.i_hb2[35] ddc_chain_tb.dut_i0.\new_hb.i_hb2[34] ddc_chain_tb.dut_i0.\new_hb.i_hb2[33] ddc_chain_tb.dut_i0.\new_hb.i_hb2[32] ddc_chain_tb.dut_i0.\new_hb.i_hb2[31] ddc_chain_tb.dut_i0.\new_hb.i_hb2[30] ddc_chain_tb.dut_i0.\new_hb.i_hb2[29] ddc_chain_tb.dut_i0.\new_hb.i_hb2[28] ddc_chain_tb.dut_i0.\new_hb.i_hb2[27] ddc_chain_tb.dut_i0.\new_hb.i_hb2[26] ddc_chain_tb.dut_i0.\new_hb.i_hb2[25] ddc_chain_tb.dut_i0.\new_hb.i_hb2[24] ddc_chain_tb.dut_i0.\new_hb.i_hb2[23] ddc_chain_tb.dut_i0.\new_hb.i_hb2[22] ddc_chain_tb.dut_i0.\new_hb.i_hb2[21] ddc_chain_tb.dut_i0.\new_hb.i_hb2[20] ddc_chain_tb.dut_i0.\new_hb.i_hb2[19] ddc_chain_tb.dut_i0.\new_hb.i_hb2[18] ddc_chain_tb.dut_i0.\new_hb.i_hb2[17] ddc_chain_tb.dut_i0.\new_hb.i_hb2[16] ddc_chain_tb.dut_i0.\new_hb.i_hb2[15] ddc_chain_tb.dut_i0.\new_hb.i_hb2[14] ddc_chain_tb.dut_i0.\new_hb.i_hb2[13] ddc_chain_tb.dut_i0.\new_hb.i_hb2[12] ddc_chain_tb.dut_i0.\new_hb.i_hb2[11] ddc_chain_tb.dut_i0.\new_hb.i_hb2[10] ddc_chain_tb.dut_i0.\new_hb.i_hb2[9] ddc_chain_tb.dut_i0.\new_hb.i_hb2[8] ddc_chain_tb.dut_i0.\new_hb.i_hb2[7] ddc_chain_tb.dut_i0.\new_hb.i_hb2[6] ddc_chain_tb.dut_i0.\new_hb.i_hb2[5] ddc_chain_tb.dut_i0.\new_hb.i_hb2[4] ddc_chain_tb.dut_i0.\new_hb.i_hb2[3] ddc_chain_tb.dut_i0.\new_hb.i_hb2[2] ddc_chain_tb.dut_i0.\new_hb.i_hb2[1] ddc_chain_tb.dut_i0.\new_hb.i_hb2[0]
+#{ddc_chain_tb.dut_i0.\new_hb.q_hb2[46:0]} ddc_chain_tb.dut_i0.\new_hb.q_hb2[46] ddc_chain_tb.dut_i0.\new_hb.q_hb2[45] ddc_chain_tb.dut_i0.\new_hb.q_hb2[44] ddc_chain_tb.dut_i0.\new_hb.q_hb2[43] ddc_chain_tb.dut_i0.\new_hb.q_hb2[42] ddc_chain_tb.dut_i0.\new_hb.q_hb2[41] ddc_chain_tb.dut_i0.\new_hb.q_hb2[40] ddc_chain_tb.dut_i0.\new_hb.q_hb2[39] ddc_chain_tb.dut_i0.\new_hb.q_hb2[38] ddc_chain_tb.dut_i0.\new_hb.q_hb2[37] ddc_chain_tb.dut_i0.\new_hb.q_hb2[36] ddc_chain_tb.dut_i0.\new_hb.q_hb2[35] ddc_chain_tb.dut_i0.\new_hb.q_hb2[34] ddc_chain_tb.dut_i0.\new_hb.q_hb2[33] ddc_chain_tb.dut_i0.\new_hb.q_hb2[32] ddc_chain_tb.dut_i0.\new_hb.q_hb2[31] ddc_chain_tb.dut_i0.\new_hb.q_hb2[30] ddc_chain_tb.dut_i0.\new_hb.q_hb2[29] ddc_chain_tb.dut_i0.\new_hb.q_hb2[28] ddc_chain_tb.dut_i0.\new_hb.q_hb2[27] ddc_chain_tb.dut_i0.\new_hb.q_hb2[26] ddc_chain_tb.dut_i0.\new_hb.q_hb2[25] ddc_chain_tb.dut_i0.\new_hb.q_hb2[24] ddc_chain_tb.dut_i0.\new_hb.q_hb2[23] ddc_chain_tb.dut_i0.\new_hb.q_hb2[22] ddc_chain_tb.dut_i0.\new_hb.q_hb2[21] ddc_chain_tb.dut_i0.\new_hb.q_hb2[20] ddc_chain_tb.dut_i0.\new_hb.q_hb2[19] ddc_chain_tb.dut_i0.\new_hb.q_hb2[18] ddc_chain_tb.dut_i0.\new_hb.q_hb2[17] ddc_chain_tb.dut_i0.\new_hb.q_hb2[16] ddc_chain_tb.dut_i0.\new_hb.q_hb2[15] ddc_chain_tb.dut_i0.\new_hb.q_hb2[14] ddc_chain_tb.dut_i0.\new_hb.q_hb2[13] ddc_chain_tb.dut_i0.\new_hb.q_hb2[12] ddc_chain_tb.dut_i0.\new_hb.q_hb2[11] ddc_chain_tb.dut_i0.\new_hb.q_hb2[10] ddc_chain_tb.dut_i0.\new_hb.q_hb2[9] ddc_chain_tb.dut_i0.\new_hb.q_hb2[8] ddc_chain_tb.dut_i0.\new_hb.q_hb2[7] ddc_chain_tb.dut_i0.\new_hb.q_hb2[6] ddc_chain_tb.dut_i0.\new_hb.q_hb2[5] ddc_chain_tb.dut_i0.\new_hb.q_hb2[4] ddc_chain_tb.dut_i0.\new_hb.q_hb2[3] ddc_chain_tb.dut_i0.\new_hb.q_hb2[2] ddc_chain_tb.dut_i0.\new_hb.q_hb2[1] ddc_chain_tb.dut_i0.\new_hb.q_hb2[0]
+@20000
+-
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/simulation_script.v b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/simulation_script.v
new file mode 100644
index 000000000..19836cc98
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/dc_in_cordic_decim_6/simulation_script.v
@@ -0,0 +1,83 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// 10MHz master_clock_rate
+always #50 clk <= ~clk;
+
+ initial
+ begin
+ reset <= 1'b0;
+ i_in <= 0;
+ q_in <= 0;
+ run <= 0;
+ set_stb <= 0;
+ set_addr <= 0;
+ set_data <= 0;
+
+
+ @(posedge clk);
+ // Into Reset...
+ reset <= 1'b1;
+ repeat(10) @(posedge clk);
+ // .. and back out of reset.
+ reset <= 1'b0;
+ repeat(10) @(posedge clk);
+ // Now program DSP configuration via settings regs.
+ write_setting_bus(SR_DSP_RX_FREQ,42949672); // 100kHz @ 10MHz MCR
+ write_setting_bus(SR_DSP_RX_SCALE_IQ, 62842); // Should include CORDIC and CIC gain compensation.
+ // write_setting_bus(SR_DSP_RX_SCALE_IQ, ((1<<16) * 1.647 * 0.5 * 1.22)); // Should include CORDIC and CIC gain compensation.
+ write_setting_bus(SR_DSP_RX_DECIM, 1<<9|3); // Decim = 6
+ write_setting_bus(SR_DSP_RX_MUX, 0);
+ write_setting_bus(SR_DSP_RX_COEFFS,0);
+ repeat(10) @(posedge clk);
+
+ // Set complex data inputs to DC unit circle position.
+ i_in <= 12'h7ff;
+ q_in <= 12'h0;
+ run <= 1'b1;
+ repeat(100) @(posedge clk);
+ // Set complex data inputs to simulate ADC saturation of front end
+ i_in <= 12'h7ff;
+ q_in <= 12'h100;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h200;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h300;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h400;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h500;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h600;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h700;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h7ff;
+ q_in <= 12'h7FF;
+ // Now test small signal performance
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h001;
+ q_in <= 12'h000;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h000;
+ q_in <= 12'h001;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'hfff;
+ q_in <= 12'h000;
+ repeat(1000) @(posedge clk);
+ i_in <= 12'h000;
+ q_in <= 12'hfff;
+
+
+ repeat(100000) @(posedge clk);
+ $finish();
+
+ end // initial begin
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/ddc_chain_tb.v b/fpga/usrp3/lib/sim/dsp/ddc_chain/ddc_chain_tb.v
new file mode 100644
index 000000000..fe8bbb000
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/ddc_chain_tb.v
@@ -0,0 +1,94 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module ddc_chain_tb();
+
+ initial $dumpfile("waves.vcd");
+ initial $dumpvars(2,ddc_chain_tb.dut_i0);
+
+
+ // Need these declarations to use the task libarary.
+`ifndef CHDR_IN_NUMBER
+ `define CHDR_IN_NUMBER 1
+`endif
+`ifndef CHDR_OUT_NUMBER
+ `define CHDR_OUT_NUMBER 1
+`endif
+
+ reg [63:0] data_in[`CHDR_IN_NUMBER-1:0];
+ reg last_in[`CHDR_IN_NUMBER-1:0];
+ reg valid_in[`CHDR_IN_NUMBER-1:0];
+ wire ready_in[`CHDR_IN_NUMBER-1:0];
+ wire [63:0] data_out[`CHDR_OUT_NUMBER-1:0];
+ wire last_out[`CHDR_OUT_NUMBER-1:0];
+ wire valid_out[`CHDR_OUT_NUMBER-1:0];
+ reg ready_out[`CHDR_OUT_NUMBER-1:0];
+ //
+
+`include "../../../../../sim/radio_setting_regs.v"
+`include "../../../../../sim/task_library.v"
+
+ localparam DSPNO = 0;
+ localparam WIDTH = 24;
+ localparam NEW_HB_DECIM = 1;
+ localparam DEVICE = "SPARTAN6";
+
+ reg clk = 0;
+ reg reset;
+
+ reg set_stb;
+ reg [7:0] set_addr;
+ reg [31:0] set_data;
+
+ wire [WIDTH-1:0] rx_fe_i, rx_fe_q;
+ wire [31:0] sample;
+ reg run;
+ wire strobe;
+
+ reg [11:0] i_in, q_in;
+
+ assign rx_fe_i = {i_in,12'h0};
+ assign rx_fe_q = {q_in,12'h0};
+
+ //
+ // DUT
+ //
+ ddc_chain
+ #(
+ .BASE(SR_RX_DSP),
+ .DSPNO(DSPNO),
+ .WIDTH(WIDTH),
+ .NEW_HB_DECIM(NEW_HB_DECIM),
+ .DEVICE("SPARTAN6")
+ )
+ dut_i0 (
+ .clk(clk),
+ .rst(reset),
+ .clr(1'b0),
+ .set_stb(set_stb),
+ .set_addr(set_addr),
+ .set_data(set_data),
+
+ // From RX frontend
+ .rx_fe_i(rx_fe_i),
+ .rx_fe_q(rx_fe_q),
+
+ // To RX control
+ .sample(sample),
+ .run(run),
+ .strobe(strobe),
+ .debug()
+ );
+
+
+
+ //
+ // Include testbench
+ //
+`include "simulation_script.v"
+
+endmodule //
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain/run_isim b/fpga/usrp3/lib/sim/dsp/ddc_chain/run_isim
new file mode 100755
index 000000000..d43ccf230
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain/run_isim
@@ -0,0 +1,18 @@
+rm -rf fuse* *.exe isim
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../.. \
+ --sourcelibdir ../../../../control \
+ --sourcelibdir ../../../../../top/b200/coregen_dsp \
+ --sourcelibdir ../../../../../top/b200/coregen \
+ --sourcelibdir ${XILINX}/verilog/src/unimacro \
+ ddc_chain_tb.v
+
+
+
+fuse work.ddc_chain_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o testbench.exe
+
+# run the simulation script
+./testbench.exe #-gui #-tclbatch simcmds.tcl
+
+
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/.gitignore b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/.gitignore
new file mode 100644
index 000000000..7826d75e2
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/.gitignore
@@ -0,0 +1,4 @@
+fuse*
+isim*
+*.exe
+*.wcfg
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/DDC.sav b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/DDC.sav
new file mode 100644
index 000000000..96ec87c67
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/DDC.sav
@@ -0,0 +1,101 @@
+[*]
+[*] GTKWave Analyzer v3.3.35 (w)1999-2012 BSI
+[*] Thu Dec 5 01:04:45 2013
+[*]
+[dumpfile] "/home/matt/fpgadev/usrp3/sim/ddc_chain_x300/dctest/ddc_chain_x300_tb.vcd"
+[dumpfile_mtime] "Wed Dec 4 23:01:47 2013"
+[dumpfile_size] 12968759
+[savefile] "/home/matt/fpgadev/usrp3/sim/ddc_chain_x300/dctest/DDC.sav"
+[timestart] 0
+[size] 1600 843
+[pos] -1 -1
+*-22.573410 5990000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+[treeopen] ddc_chain_x300_tb.
+[treeopen] ddc_chain_x300_tb.ddc_chain.
+[treeopen] ddc_chain_x300_tb.ddc_chain.clip_i.
+[sst_width] 231
+[signals_width] 313
+[sst_expanded] 1
+[sst_vpaned_height] 229
+@420
+#{ddc_chain_x300_tb.ddc_chain.i_cic[23:0]} ddc_chain_x300_tb.ddc_chain.i_cic[23] ddc_chain_x300_tb.ddc_chain.i_cic[22] ddc_chain_x300_tb.ddc_chain.i_cic[21] ddc_chain_x300_tb.ddc_chain.i_cic[20] ddc_chain_x300_tb.ddc_chain.i_cic[19] ddc_chain_x300_tb.ddc_chain.i_cic[18] ddc_chain_x300_tb.ddc_chain.i_cic[17] ddc_chain_x300_tb.ddc_chain.i_cic[16] ddc_chain_x300_tb.ddc_chain.i_cic[15] ddc_chain_x300_tb.ddc_chain.i_cic[14] ddc_chain_x300_tb.ddc_chain.i_cic[13] ddc_chain_x300_tb.ddc_chain.i_cic[12] ddc_chain_x300_tb.ddc_chain.i_cic[11] ddc_chain_x300_tb.ddc_chain.i_cic[10] ddc_chain_x300_tb.ddc_chain.i_cic[9] ddc_chain_x300_tb.ddc_chain.i_cic[8] ddc_chain_x300_tb.ddc_chain.i_cic[7] ddc_chain_x300_tb.ddc_chain.i_cic[6] ddc_chain_x300_tb.ddc_chain.i_cic[5] ddc_chain_x300_tb.ddc_chain.i_cic[4] ddc_chain_x300_tb.ddc_chain.i_cic[3] ddc_chain_x300_tb.ddc_chain.i_cic[2] ddc_chain_x300_tb.ddc_chain.i_cic[1] ddc_chain_x300_tb.ddc_chain.i_cic[0]
+@28
+ddc_chain_x300_tb.ddc_chain.strobe_cic
+@420
+#{ddc_chain_x300_tb.ddc_chain.i_hb1[46:0]} ddc_chain_x300_tb.ddc_chain.i_hb1[46] ddc_chain_x300_tb.ddc_chain.i_hb1[45] ddc_chain_x300_tb.ddc_chain.i_hb1[44] ddc_chain_x300_tb.ddc_chain.i_hb1[43] ddc_chain_x300_tb.ddc_chain.i_hb1[42] ddc_chain_x300_tb.ddc_chain.i_hb1[41] ddc_chain_x300_tb.ddc_chain.i_hb1[40] ddc_chain_x300_tb.ddc_chain.i_hb1[39] ddc_chain_x300_tb.ddc_chain.i_hb1[38] ddc_chain_x300_tb.ddc_chain.i_hb1[37] ddc_chain_x300_tb.ddc_chain.i_hb1[36] ddc_chain_x300_tb.ddc_chain.i_hb1[35] ddc_chain_x300_tb.ddc_chain.i_hb1[34] ddc_chain_x300_tb.ddc_chain.i_hb1[33] ddc_chain_x300_tb.ddc_chain.i_hb1[32] ddc_chain_x300_tb.ddc_chain.i_hb1[31] ddc_chain_x300_tb.ddc_chain.i_hb1[30] ddc_chain_x300_tb.ddc_chain.i_hb1[29] ddc_chain_x300_tb.ddc_chain.i_hb1[28] ddc_chain_x300_tb.ddc_chain.i_hb1[27] ddc_chain_x300_tb.ddc_chain.i_hb1[26] ddc_chain_x300_tb.ddc_chain.i_hb1[25] ddc_chain_x300_tb.ddc_chain.i_hb1[24] ddc_chain_x300_tb.ddc_chain.i_hb1[23] ddc_chain_x300_tb.ddc_chain.i_hb1[22] ddc_chain_x300_tb.ddc_chain.i_hb1[21] ddc_chain_x300_tb.ddc_chain.i_hb1[20] ddc_chain_x300_tb.ddc_chain.i_hb1[19] ddc_chain_x300_tb.ddc_chain.i_hb1[18] ddc_chain_x300_tb.ddc_chain.i_hb1[17] ddc_chain_x300_tb.ddc_chain.i_hb1[16] ddc_chain_x300_tb.ddc_chain.i_hb1[15] ddc_chain_x300_tb.ddc_chain.i_hb1[14] ddc_chain_x300_tb.ddc_chain.i_hb1[13] ddc_chain_x300_tb.ddc_chain.i_hb1[12] ddc_chain_x300_tb.ddc_chain.i_hb1[11] ddc_chain_x300_tb.ddc_chain.i_hb1[10] ddc_chain_x300_tb.ddc_chain.i_hb1[9] ddc_chain_x300_tb.ddc_chain.i_hb1[8] ddc_chain_x300_tb.ddc_chain.i_hb1[7] ddc_chain_x300_tb.ddc_chain.i_hb1[6] ddc_chain_x300_tb.ddc_chain.i_hb1[5] ddc_chain_x300_tb.ddc_chain.i_hb1[4] ddc_chain_x300_tb.ddc_chain.i_hb1[3] ddc_chain_x300_tb.ddc_chain.i_hb1[2] ddc_chain_x300_tb.ddc_chain.i_hb1[1] ddc_chain_x300_tb.ddc_chain.i_hb1[0]
+@28
+ddc_chain_x300_tb.ddc_chain.strobe_hb1
+@420
+#{ddc_chain_x300_tb.ddc_chain.i_hb2[46:0]} ddc_chain_x300_tb.ddc_chain.i_hb2[46] ddc_chain_x300_tb.ddc_chain.i_hb2[45] ddc_chain_x300_tb.ddc_chain.i_hb2[44] ddc_chain_x300_tb.ddc_chain.i_hb2[43] ddc_chain_x300_tb.ddc_chain.i_hb2[42] ddc_chain_x300_tb.ddc_chain.i_hb2[41] ddc_chain_x300_tb.ddc_chain.i_hb2[40] ddc_chain_x300_tb.ddc_chain.i_hb2[39] ddc_chain_x300_tb.ddc_chain.i_hb2[38] ddc_chain_x300_tb.ddc_chain.i_hb2[37] ddc_chain_x300_tb.ddc_chain.i_hb2[36] ddc_chain_x300_tb.ddc_chain.i_hb2[35] ddc_chain_x300_tb.ddc_chain.i_hb2[34] ddc_chain_x300_tb.ddc_chain.i_hb2[33] ddc_chain_x300_tb.ddc_chain.i_hb2[32] ddc_chain_x300_tb.ddc_chain.i_hb2[31] ddc_chain_x300_tb.ddc_chain.i_hb2[30] ddc_chain_x300_tb.ddc_chain.i_hb2[29] ddc_chain_x300_tb.ddc_chain.i_hb2[28] ddc_chain_x300_tb.ddc_chain.i_hb2[27] ddc_chain_x300_tb.ddc_chain.i_hb2[26] ddc_chain_x300_tb.ddc_chain.i_hb2[25] ddc_chain_x300_tb.ddc_chain.i_hb2[24] ddc_chain_x300_tb.ddc_chain.i_hb2[23] ddc_chain_x300_tb.ddc_chain.i_hb2[22] ddc_chain_x300_tb.ddc_chain.i_hb2[21] ddc_chain_x300_tb.ddc_chain.i_hb2[20] ddc_chain_x300_tb.ddc_chain.i_hb2[19] ddc_chain_x300_tb.ddc_chain.i_hb2[18] ddc_chain_x300_tb.ddc_chain.i_hb2[17] ddc_chain_x300_tb.ddc_chain.i_hb2[16] ddc_chain_x300_tb.ddc_chain.i_hb2[15] ddc_chain_x300_tb.ddc_chain.i_hb2[14] ddc_chain_x300_tb.ddc_chain.i_hb2[13] ddc_chain_x300_tb.ddc_chain.i_hb2[12] ddc_chain_x300_tb.ddc_chain.i_hb2[11] ddc_chain_x300_tb.ddc_chain.i_hb2[10] ddc_chain_x300_tb.ddc_chain.i_hb2[9] ddc_chain_x300_tb.ddc_chain.i_hb2[8] ddc_chain_x300_tb.ddc_chain.i_hb2[7] ddc_chain_x300_tb.ddc_chain.i_hb2[6] ddc_chain_x300_tb.ddc_chain.i_hb2[5] ddc_chain_x300_tb.ddc_chain.i_hb2[4] ddc_chain_x300_tb.ddc_chain.i_hb2[3] ddc_chain_x300_tb.ddc_chain.i_hb2[2] ddc_chain_x300_tb.ddc_chain.i_hb2[1] ddc_chain_x300_tb.ddc_chain.i_hb2[0]
+@28
+ddc_chain_x300_tb.ddc_chain.strobe_hb2
+@420
+#{ddc_chain_x300_tb.ddc_chain.i_hb3[47:0]} ddc_chain_x300_tb.ddc_chain.i_hb3[47] ddc_chain_x300_tb.ddc_chain.i_hb3[46] ddc_chain_x300_tb.ddc_chain.i_hb3[45] ddc_chain_x300_tb.ddc_chain.i_hb3[44] ddc_chain_x300_tb.ddc_chain.i_hb3[43] ddc_chain_x300_tb.ddc_chain.i_hb3[42] ddc_chain_x300_tb.ddc_chain.i_hb3[41] ddc_chain_x300_tb.ddc_chain.i_hb3[40] ddc_chain_x300_tb.ddc_chain.i_hb3[39] ddc_chain_x300_tb.ddc_chain.i_hb3[38] ddc_chain_x300_tb.ddc_chain.i_hb3[37] ddc_chain_x300_tb.ddc_chain.i_hb3[36] ddc_chain_x300_tb.ddc_chain.i_hb3[35] ddc_chain_x300_tb.ddc_chain.i_hb3[34] ddc_chain_x300_tb.ddc_chain.i_hb3[33] ddc_chain_x300_tb.ddc_chain.i_hb3[32] ddc_chain_x300_tb.ddc_chain.i_hb3[31] ddc_chain_x300_tb.ddc_chain.i_hb3[30] ddc_chain_x300_tb.ddc_chain.i_hb3[29] ddc_chain_x300_tb.ddc_chain.i_hb3[28] ddc_chain_x300_tb.ddc_chain.i_hb3[27] ddc_chain_x300_tb.ddc_chain.i_hb3[26] ddc_chain_x300_tb.ddc_chain.i_hb3[25] ddc_chain_x300_tb.ddc_chain.i_hb3[24] ddc_chain_x300_tb.ddc_chain.i_hb3[23] ddc_chain_x300_tb.ddc_chain.i_hb3[22] ddc_chain_x300_tb.ddc_chain.i_hb3[21] ddc_chain_x300_tb.ddc_chain.i_hb3[20] ddc_chain_x300_tb.ddc_chain.i_hb3[19] ddc_chain_x300_tb.ddc_chain.i_hb3[18] ddc_chain_x300_tb.ddc_chain.i_hb3[17] ddc_chain_x300_tb.ddc_chain.i_hb3[16] ddc_chain_x300_tb.ddc_chain.i_hb3[15] ddc_chain_x300_tb.ddc_chain.i_hb3[14] ddc_chain_x300_tb.ddc_chain.i_hb3[13] ddc_chain_x300_tb.ddc_chain.i_hb3[12] ddc_chain_x300_tb.ddc_chain.i_hb3[11] ddc_chain_x300_tb.ddc_chain.i_hb3[10] ddc_chain_x300_tb.ddc_chain.i_hb3[9] ddc_chain_x300_tb.ddc_chain.i_hb3[8] ddc_chain_x300_tb.ddc_chain.i_hb3[7] ddc_chain_x300_tb.ddc_chain.i_hb3[6] ddc_chain_x300_tb.ddc_chain.i_hb3[5] ddc_chain_x300_tb.ddc_chain.i_hb3[4] ddc_chain_x300_tb.ddc_chain.i_hb3[3] ddc_chain_x300_tb.ddc_chain.i_hb3[2] ddc_chain_x300_tb.ddc_chain.i_hb3[1] ddc_chain_x300_tb.ddc_chain.i_hb3[0]
+@28
+ddc_chain_x300_tb.ddc_chain.strobe_hb3
+@420
+ddc_chain_x300_tb.ddc_chain.i_unscaled[23:0]
+#{ddc_chain_x300_tb.ddc_chain.i_scaled[42:0]} ddc_chain_x300_tb.ddc_chain.i_scaled[42] ddc_chain_x300_tb.ddc_chain.i_scaled[41] ddc_chain_x300_tb.ddc_chain.i_scaled[40] ddc_chain_x300_tb.ddc_chain.i_scaled[39] ddc_chain_x300_tb.ddc_chain.i_scaled[38] ddc_chain_x300_tb.ddc_chain.i_scaled[37] ddc_chain_x300_tb.ddc_chain.i_scaled[36] ddc_chain_x300_tb.ddc_chain.i_scaled[35] ddc_chain_x300_tb.ddc_chain.i_scaled[34] ddc_chain_x300_tb.ddc_chain.i_scaled[33] ddc_chain_x300_tb.ddc_chain.i_scaled[32] ddc_chain_x300_tb.ddc_chain.i_scaled[31] ddc_chain_x300_tb.ddc_chain.i_scaled[30] ddc_chain_x300_tb.ddc_chain.i_scaled[29] ddc_chain_x300_tb.ddc_chain.i_scaled[28] ddc_chain_x300_tb.ddc_chain.i_scaled[27] ddc_chain_x300_tb.ddc_chain.i_scaled[26] ddc_chain_x300_tb.ddc_chain.i_scaled[25] ddc_chain_x300_tb.ddc_chain.i_scaled[24] ddc_chain_x300_tb.ddc_chain.i_scaled[23] ddc_chain_x300_tb.ddc_chain.i_scaled[22] ddc_chain_x300_tb.ddc_chain.i_scaled[21] ddc_chain_x300_tb.ddc_chain.i_scaled[20] ddc_chain_x300_tb.ddc_chain.i_scaled[19] ddc_chain_x300_tb.ddc_chain.i_scaled[18] ddc_chain_x300_tb.ddc_chain.i_scaled[17] ddc_chain_x300_tb.ddc_chain.i_scaled[16] ddc_chain_x300_tb.ddc_chain.i_scaled[15] ddc_chain_x300_tb.ddc_chain.i_scaled[14] ddc_chain_x300_tb.ddc_chain.i_scaled[13] ddc_chain_x300_tb.ddc_chain.i_scaled[12] ddc_chain_x300_tb.ddc_chain.i_scaled[11] ddc_chain_x300_tb.ddc_chain.i_scaled[10] ddc_chain_x300_tb.ddc_chain.i_scaled[9] ddc_chain_x300_tb.ddc_chain.i_scaled[8] ddc_chain_x300_tb.ddc_chain.i_scaled[7] ddc_chain_x300_tb.ddc_chain.i_scaled[6] ddc_chain_x300_tb.ddc_chain.i_scaled[5] ddc_chain_x300_tb.ddc_chain.i_scaled[4] ddc_chain_x300_tb.ddc_chain.i_scaled[3] ddc_chain_x300_tb.ddc_chain.i_scaled[2] ddc_chain_x300_tb.ddc_chain.i_scaled[1] ddc_chain_x300_tb.ddc_chain.i_scaled[0]
+@200
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_cic[23:0]} ddc_chain_x300_tb.ddc_chain.i_cic[23] ddc_chain_x300_tb.ddc_chain.i_cic[22] ddc_chain_x300_tb.ddc_chain.i_cic[21] ddc_chain_x300_tb.ddc_chain.i_cic[20] ddc_chain_x300_tb.ddc_chain.i_cic[19] ddc_chain_x300_tb.ddc_chain.i_cic[18] ddc_chain_x300_tb.ddc_chain.i_cic[17] ddc_chain_x300_tb.ddc_chain.i_cic[16] ddc_chain_x300_tb.ddc_chain.i_cic[15] ddc_chain_x300_tb.ddc_chain.i_cic[14] ddc_chain_x300_tb.ddc_chain.i_cic[13] ddc_chain_x300_tb.ddc_chain.i_cic[12] ddc_chain_x300_tb.ddc_chain.i_cic[11] ddc_chain_x300_tb.ddc_chain.i_cic[10] ddc_chain_x300_tb.ddc_chain.i_cic[9] ddc_chain_x300_tb.ddc_chain.i_cic[8] ddc_chain_x300_tb.ddc_chain.i_cic[7] ddc_chain_x300_tb.ddc_chain.i_cic[6] ddc_chain_x300_tb.ddc_chain.i_cic[5] ddc_chain_x300_tb.ddc_chain.i_cic[4] ddc_chain_x300_tb.ddc_chain.i_cic[3] ddc_chain_x300_tb.ddc_chain.i_cic[2] ddc_chain_x300_tb.ddc_chain.i_cic[1] ddc_chain_x300_tb.ddc_chain.i_cic[0]
+@20000
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_hb1[46:0]} ddc_chain_x300_tb.ddc_chain.i_hb1[46] ddc_chain_x300_tb.ddc_chain.i_hb1[45] ddc_chain_x300_tb.ddc_chain.i_hb1[44] ddc_chain_x300_tb.ddc_chain.i_hb1[43] ddc_chain_x300_tb.ddc_chain.i_hb1[42] ddc_chain_x300_tb.ddc_chain.i_hb1[41] ddc_chain_x300_tb.ddc_chain.i_hb1[40] ddc_chain_x300_tb.ddc_chain.i_hb1[39] ddc_chain_x300_tb.ddc_chain.i_hb1[38] ddc_chain_x300_tb.ddc_chain.i_hb1[37] ddc_chain_x300_tb.ddc_chain.i_hb1[36] ddc_chain_x300_tb.ddc_chain.i_hb1[35] ddc_chain_x300_tb.ddc_chain.i_hb1[34] ddc_chain_x300_tb.ddc_chain.i_hb1[33] ddc_chain_x300_tb.ddc_chain.i_hb1[32] ddc_chain_x300_tb.ddc_chain.i_hb1[31] ddc_chain_x300_tb.ddc_chain.i_hb1[30] ddc_chain_x300_tb.ddc_chain.i_hb1[29] ddc_chain_x300_tb.ddc_chain.i_hb1[28] ddc_chain_x300_tb.ddc_chain.i_hb1[27] ddc_chain_x300_tb.ddc_chain.i_hb1[26] ddc_chain_x300_tb.ddc_chain.i_hb1[25] ddc_chain_x300_tb.ddc_chain.i_hb1[24] ddc_chain_x300_tb.ddc_chain.i_hb1[23] ddc_chain_x300_tb.ddc_chain.i_hb1[22] ddc_chain_x300_tb.ddc_chain.i_hb1[21] ddc_chain_x300_tb.ddc_chain.i_hb1[20] ddc_chain_x300_tb.ddc_chain.i_hb1[19] ddc_chain_x300_tb.ddc_chain.i_hb1[18] ddc_chain_x300_tb.ddc_chain.i_hb1[17] ddc_chain_x300_tb.ddc_chain.i_hb1[16] ddc_chain_x300_tb.ddc_chain.i_hb1[15] ddc_chain_x300_tb.ddc_chain.i_hb1[14] ddc_chain_x300_tb.ddc_chain.i_hb1[13] ddc_chain_x300_tb.ddc_chain.i_hb1[12] ddc_chain_x300_tb.ddc_chain.i_hb1[11] ddc_chain_x300_tb.ddc_chain.i_hb1[10] ddc_chain_x300_tb.ddc_chain.i_hb1[9] ddc_chain_x300_tb.ddc_chain.i_hb1[8] ddc_chain_x300_tb.ddc_chain.i_hb1[7] ddc_chain_x300_tb.ddc_chain.i_hb1[6] ddc_chain_x300_tb.ddc_chain.i_hb1[5] ddc_chain_x300_tb.ddc_chain.i_hb1[4] ddc_chain_x300_tb.ddc_chain.i_hb1[3] ddc_chain_x300_tb.ddc_chain.i_hb1[2] ddc_chain_x300_tb.ddc_chain.i_hb1[1] ddc_chain_x300_tb.ddc_chain.i_hb1[0]
+@20000
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_hb2[46:0]} ddc_chain_x300_tb.ddc_chain.i_hb2[46] ddc_chain_x300_tb.ddc_chain.i_hb2[45] ddc_chain_x300_tb.ddc_chain.i_hb2[44] ddc_chain_x300_tb.ddc_chain.i_hb2[43] ddc_chain_x300_tb.ddc_chain.i_hb2[42] ddc_chain_x300_tb.ddc_chain.i_hb2[41] ddc_chain_x300_tb.ddc_chain.i_hb2[40] ddc_chain_x300_tb.ddc_chain.i_hb2[39] ddc_chain_x300_tb.ddc_chain.i_hb2[38] ddc_chain_x300_tb.ddc_chain.i_hb2[37] ddc_chain_x300_tb.ddc_chain.i_hb2[36] ddc_chain_x300_tb.ddc_chain.i_hb2[35] ddc_chain_x300_tb.ddc_chain.i_hb2[34] ddc_chain_x300_tb.ddc_chain.i_hb2[33] ddc_chain_x300_tb.ddc_chain.i_hb2[32] ddc_chain_x300_tb.ddc_chain.i_hb2[31] ddc_chain_x300_tb.ddc_chain.i_hb2[30] ddc_chain_x300_tb.ddc_chain.i_hb2[29] ddc_chain_x300_tb.ddc_chain.i_hb2[28] ddc_chain_x300_tb.ddc_chain.i_hb2[27] ddc_chain_x300_tb.ddc_chain.i_hb2[26] ddc_chain_x300_tb.ddc_chain.i_hb2[25] ddc_chain_x300_tb.ddc_chain.i_hb2[24] ddc_chain_x300_tb.ddc_chain.i_hb2[23] ddc_chain_x300_tb.ddc_chain.i_hb2[22] ddc_chain_x300_tb.ddc_chain.i_hb2[21] ddc_chain_x300_tb.ddc_chain.i_hb2[20] ddc_chain_x300_tb.ddc_chain.i_hb2[19] ddc_chain_x300_tb.ddc_chain.i_hb2[18] ddc_chain_x300_tb.ddc_chain.i_hb2[17] ddc_chain_x300_tb.ddc_chain.i_hb2[16] ddc_chain_x300_tb.ddc_chain.i_hb2[15] ddc_chain_x300_tb.ddc_chain.i_hb2[14] ddc_chain_x300_tb.ddc_chain.i_hb2[13] ddc_chain_x300_tb.ddc_chain.i_hb2[12] ddc_chain_x300_tb.ddc_chain.i_hb2[11] ddc_chain_x300_tb.ddc_chain.i_hb2[10] ddc_chain_x300_tb.ddc_chain.i_hb2[9] ddc_chain_x300_tb.ddc_chain.i_hb2[8] ddc_chain_x300_tb.ddc_chain.i_hb2[7] ddc_chain_x300_tb.ddc_chain.i_hb2[6] ddc_chain_x300_tb.ddc_chain.i_hb2[5] ddc_chain_x300_tb.ddc_chain.i_hb2[4] ddc_chain_x300_tb.ddc_chain.i_hb2[3] ddc_chain_x300_tb.ddc_chain.i_hb2[2] ddc_chain_x300_tb.ddc_chain.i_hb2[1] ddc_chain_x300_tb.ddc_chain.i_hb2[0]
+@20000
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_hb3[47:0]} ddc_chain_x300_tb.ddc_chain.i_hb3[47] ddc_chain_x300_tb.ddc_chain.i_hb3[46] ddc_chain_x300_tb.ddc_chain.i_hb3[45] ddc_chain_x300_tb.ddc_chain.i_hb3[44] ddc_chain_x300_tb.ddc_chain.i_hb3[43] ddc_chain_x300_tb.ddc_chain.i_hb3[42] ddc_chain_x300_tb.ddc_chain.i_hb3[41] ddc_chain_x300_tb.ddc_chain.i_hb3[40] ddc_chain_x300_tb.ddc_chain.i_hb3[39] ddc_chain_x300_tb.ddc_chain.i_hb3[38] ddc_chain_x300_tb.ddc_chain.i_hb3[37] ddc_chain_x300_tb.ddc_chain.i_hb3[36] ddc_chain_x300_tb.ddc_chain.i_hb3[35] ddc_chain_x300_tb.ddc_chain.i_hb3[34] ddc_chain_x300_tb.ddc_chain.i_hb3[33] ddc_chain_x300_tb.ddc_chain.i_hb3[32] ddc_chain_x300_tb.ddc_chain.i_hb3[31] ddc_chain_x300_tb.ddc_chain.i_hb3[30] ddc_chain_x300_tb.ddc_chain.i_hb3[29] ddc_chain_x300_tb.ddc_chain.i_hb3[28] ddc_chain_x300_tb.ddc_chain.i_hb3[27] ddc_chain_x300_tb.ddc_chain.i_hb3[26] ddc_chain_x300_tb.ddc_chain.i_hb3[25] ddc_chain_x300_tb.ddc_chain.i_hb3[24] ddc_chain_x300_tb.ddc_chain.i_hb3[23] ddc_chain_x300_tb.ddc_chain.i_hb3[22] ddc_chain_x300_tb.ddc_chain.i_hb3[21] ddc_chain_x300_tb.ddc_chain.i_hb3[20] ddc_chain_x300_tb.ddc_chain.i_hb3[19] ddc_chain_x300_tb.ddc_chain.i_hb3[18] ddc_chain_x300_tb.ddc_chain.i_hb3[17] ddc_chain_x300_tb.ddc_chain.i_hb3[16] ddc_chain_x300_tb.ddc_chain.i_hb3[15] ddc_chain_x300_tb.ddc_chain.i_hb3[14] ddc_chain_x300_tb.ddc_chain.i_hb3[13] ddc_chain_x300_tb.ddc_chain.i_hb3[12] ddc_chain_x300_tb.ddc_chain.i_hb3[11] ddc_chain_x300_tb.ddc_chain.i_hb3[10] ddc_chain_x300_tb.ddc_chain.i_hb3[9] ddc_chain_x300_tb.ddc_chain.i_hb3[8] ddc_chain_x300_tb.ddc_chain.i_hb3[7] ddc_chain_x300_tb.ddc_chain.i_hb3[6] ddc_chain_x300_tb.ddc_chain.i_hb3[5] ddc_chain_x300_tb.ddc_chain.i_hb3[4] ddc_chain_x300_tb.ddc_chain.i_hb3[3] ddc_chain_x300_tb.ddc_chain.i_hb3[2] ddc_chain_x300_tb.ddc_chain.i_hb3[1] ddc_chain_x300_tb.ddc_chain.i_hb3[0]
+@20000
+-
+@8420
+ddc_chain_x300_tb.ddc_chain.i_unscaled[23:0]
+@20000
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_scaled[42:0]} ddc_chain_x300_tb.ddc_chain.i_scaled[42] ddc_chain_x300_tb.ddc_chain.i_scaled[41] ddc_chain_x300_tb.ddc_chain.i_scaled[40] ddc_chain_x300_tb.ddc_chain.i_scaled[39] ddc_chain_x300_tb.ddc_chain.i_scaled[38] ddc_chain_x300_tb.ddc_chain.i_scaled[37] ddc_chain_x300_tb.ddc_chain.i_scaled[36] ddc_chain_x300_tb.ddc_chain.i_scaled[35] ddc_chain_x300_tb.ddc_chain.i_scaled[34] ddc_chain_x300_tb.ddc_chain.i_scaled[33] ddc_chain_x300_tb.ddc_chain.i_scaled[32] ddc_chain_x300_tb.ddc_chain.i_scaled[31] ddc_chain_x300_tb.ddc_chain.i_scaled[30] ddc_chain_x300_tb.ddc_chain.i_scaled[29] ddc_chain_x300_tb.ddc_chain.i_scaled[28] ddc_chain_x300_tb.ddc_chain.i_scaled[27] ddc_chain_x300_tb.ddc_chain.i_scaled[26] ddc_chain_x300_tb.ddc_chain.i_scaled[25] ddc_chain_x300_tb.ddc_chain.i_scaled[24] ddc_chain_x300_tb.ddc_chain.i_scaled[23] ddc_chain_x300_tb.ddc_chain.i_scaled[22] ddc_chain_x300_tb.ddc_chain.i_scaled[21] ddc_chain_x300_tb.ddc_chain.i_scaled[20] ddc_chain_x300_tb.ddc_chain.i_scaled[19] ddc_chain_x300_tb.ddc_chain.i_scaled[18] ddc_chain_x300_tb.ddc_chain.i_scaled[17] ddc_chain_x300_tb.ddc_chain.i_scaled[16] ddc_chain_x300_tb.ddc_chain.i_scaled[15] ddc_chain_x300_tb.ddc_chain.i_scaled[14] ddc_chain_x300_tb.ddc_chain.i_scaled[13] ddc_chain_x300_tb.ddc_chain.i_scaled[12] ddc_chain_x300_tb.ddc_chain.i_scaled[11] ddc_chain_x300_tb.ddc_chain.i_scaled[10] ddc_chain_x300_tb.ddc_chain.i_scaled[9] ddc_chain_x300_tb.ddc_chain.i_scaled[8] ddc_chain_x300_tb.ddc_chain.i_scaled[7] ddc_chain_x300_tb.ddc_chain.i_scaled[6] ddc_chain_x300_tb.ddc_chain.i_scaled[5] ddc_chain_x300_tb.ddc_chain.i_scaled[4] ddc_chain_x300_tb.ddc_chain.i_scaled[3] ddc_chain_x300_tb.ddc_chain.i_scaled[2] ddc_chain_x300_tb.ddc_chain.i_scaled[1] ddc_chain_x300_tb.ddc_chain.i_scaled[0]
+@20000
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_clip[23:0]} ddc_chain_x300_tb.ddc_chain.i_clip[23] ddc_chain_x300_tb.ddc_chain.i_clip[22] ddc_chain_x300_tb.ddc_chain.i_clip[21] ddc_chain_x300_tb.ddc_chain.i_clip[20] ddc_chain_x300_tb.ddc_chain.i_clip[19] ddc_chain_x300_tb.ddc_chain.i_clip[18] ddc_chain_x300_tb.ddc_chain.i_clip[17] ddc_chain_x300_tb.ddc_chain.i_clip[16] ddc_chain_x300_tb.ddc_chain.i_clip[15] ddc_chain_x300_tb.ddc_chain.i_clip[14] ddc_chain_x300_tb.ddc_chain.i_clip[13] ddc_chain_x300_tb.ddc_chain.i_clip[12] ddc_chain_x300_tb.ddc_chain.i_clip[11] ddc_chain_x300_tb.ddc_chain.i_clip[10] ddc_chain_x300_tb.ddc_chain.i_clip[9] ddc_chain_x300_tb.ddc_chain.i_clip[8] ddc_chain_x300_tb.ddc_chain.i_clip[7] ddc_chain_x300_tb.ddc_chain.i_clip[6] ddc_chain_x300_tb.ddc_chain.i_clip[5] ddc_chain_x300_tb.ddc_chain.i_clip[4] ddc_chain_x300_tb.ddc_chain.i_clip[3] ddc_chain_x300_tb.ddc_chain.i_clip[2] ddc_chain_x300_tb.ddc_chain.i_clip[1] ddc_chain_x300_tb.ddc_chain.i_clip[0]
+@20000
+-
+@28
+ddc_chain_x300_tb.ddc_chain.strobe_unscaled
+ddc_chain_x300_tb.ddc_chain.strobe_scaled
+ddc_chain_x300_tb.ddc_chain.strobe_clip
+ddc_chain_x300_tb.ddc_chain.strobe
+ddc_chain_x300_tb.ddc_chain.clip_i.clip.overflow
+@8420
+#{ddc_chain_x300_tb.ddc_chain.round_i.out[15:0]} ddc_chain_x300_tb.ddc_chain.round_i.out[15] ddc_chain_x300_tb.ddc_chain.round_i.out[14] ddc_chain_x300_tb.ddc_chain.round_i.out[13] ddc_chain_x300_tb.ddc_chain.round_i.out[12] ddc_chain_x300_tb.ddc_chain.round_i.out[11] ddc_chain_x300_tb.ddc_chain.round_i.out[10] ddc_chain_x300_tb.ddc_chain.round_i.out[9] ddc_chain_x300_tb.ddc_chain.round_i.out[8] ddc_chain_x300_tb.ddc_chain.round_i.out[7] ddc_chain_x300_tb.ddc_chain.round_i.out[6] ddc_chain_x300_tb.ddc_chain.round_i.out[5] ddc_chain_x300_tb.ddc_chain.round_i.out[4] ddc_chain_x300_tb.ddc_chain.round_i.out[3] ddc_chain_x300_tb.ddc_chain.round_i.out[2] ddc_chain_x300_tb.ddc_chain.round_i.out[1] ddc_chain_x300_tb.ddc_chain.round_i.out[0]
+@20000
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_cordic[24:0]} ddc_chain_x300_tb.ddc_chain.i_cordic[24] ddc_chain_x300_tb.ddc_chain.i_cordic[23] ddc_chain_x300_tb.ddc_chain.i_cordic[22] ddc_chain_x300_tb.ddc_chain.i_cordic[21] ddc_chain_x300_tb.ddc_chain.i_cordic[20] ddc_chain_x300_tb.ddc_chain.i_cordic[19] ddc_chain_x300_tb.ddc_chain.i_cordic[18] ddc_chain_x300_tb.ddc_chain.i_cordic[17] ddc_chain_x300_tb.ddc_chain.i_cordic[16] ddc_chain_x300_tb.ddc_chain.i_cordic[15] ddc_chain_x300_tb.ddc_chain.i_cordic[14] ddc_chain_x300_tb.ddc_chain.i_cordic[13] ddc_chain_x300_tb.ddc_chain.i_cordic[12] ddc_chain_x300_tb.ddc_chain.i_cordic[11] ddc_chain_x300_tb.ddc_chain.i_cordic[10] ddc_chain_x300_tb.ddc_chain.i_cordic[9] ddc_chain_x300_tb.ddc_chain.i_cordic[8] ddc_chain_x300_tb.ddc_chain.i_cordic[7] ddc_chain_x300_tb.ddc_chain.i_cordic[6] ddc_chain_x300_tb.ddc_chain.i_cordic[5] ddc_chain_x300_tb.ddc_chain.i_cordic[4] ddc_chain_x300_tb.ddc_chain.i_cordic[3] ddc_chain_x300_tb.ddc_chain.i_cordic[2] ddc_chain_x300_tb.ddc_chain.i_cordic[1] ddc_chain_x300_tb.ddc_chain.i_cordic[0]
+@20000
+-
+-
+@8420
+#{ddc_chain_x300_tb.ddc_chain.i_cordic_clip[23:0]} ddc_chain_x300_tb.ddc_chain.i_cordic_clip[23] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[22] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[21] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[20] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[19] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[18] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[17] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[16] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[15] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[14] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[13] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[12] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[11] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[10] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[9] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[8] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[7] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[6] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[5] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[4] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[3] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[2] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[1] ddc_chain_x300_tb.ddc_chain.i_cordic_clip[0]
+@20000
+-
+@20001
+-
+[pattern_trace] 1
+[pattern_trace] 0
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/run_isim b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/run_isim
new file mode 100755
index 000000000..6a3e532c6
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/run_isim
@@ -0,0 +1,17 @@
+rm -rf fuse* *.exe isim
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../../lib/dsp \
+ --sourcelibdir ../../../lib/control \
+ --sourcelibdir ../../../top/x300/coregen_dsp \
+ --sourcelibdir ${XILINX}/verilog/src/unimacro \
+ ../../../lib/dsp/ddc_chain_x300_tb.v
+
+
+
+fuse work.ddc_chain_x300_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o ddc_chain_x300_tb.exe
+
+# run the simulation scrip
+./ddc_chain_x300_tb.exe -tclbatch simcmds.tcl # -gui
+
+
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/simcmds.tcl b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/simcmds.tcl
new file mode 100755
index 000000000..3dcfd3eaf
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/dctest/simcmds.tcl
@@ -0,0 +1,9 @@
+# file: simcmds.tcl
+
+# create the simulation script
+#vcd dumpfile isim.vcd
+#vcd dumpvars -m /bus_clk_gen_tb -l 0
+#wave add /
+run 1 s
+quit
+
diff --git a/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/ddc_chain_x300_tb.v b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/ddc_chain_x300_tb.v
new file mode 100644
index 000000000..901844d66
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/ddc_chain_x300/ddc_chain_x300_tb.v
@@ -0,0 +1,64 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module ddc_chain_x300_tb();
+
+`ifdef ISIM
+`else //iverilog implied.
+// xlnx_glbl glbl (.GSR(),.GTS());
+`endif
+
+ localparam SR_TX_DSP = 8;
+
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("ddc_chain_x300_tb.vcd");
+ initial $dumpvars(0,ddc_chain_x300_tb);
+ reg run = 0;
+ wire strobe;
+
+ initial
+ begin
+ #1000 reset = 0;
+ @(posedge clk);
+ set_addr <= 0; set_data <= 32'd8434349; set_stb <= 1; @(posedge clk); // CORDIC
+ set_addr <= 1; set_data <= 18'd19800; set_stb <= 1; @(posedge clk); // Scale factor
+ set_addr <= 2; set_data <= 10'h003; set_stb <= 1; @(posedge clk); // Decim control
+ set_addr <= 3; set_data <= 0; set_stb <= 1; @(posedge clk); // Swap iq
+ set_addr <= 4; set_data <= 0; set_stb <= 1; @(posedge clk); // filter taps
+ set_stb <= 0;
+
+ repeat(10)
+ @(posedge clk);
+ run <= 1'b1;
+ #30000;
+ $finish;
+ end
+
+ reg [7:0] set_addr;
+ reg [31:0] set_data;
+ reg set_stb = 1'b0;
+
+ wire [15:0] i_out, q_out;
+ wire [23:0] rx_fe_i, rx_fe_q;
+
+ assign rx_fe_i = 24'd8388607;
+ assign rx_fe_q = 24'd8388607;
+ //assign rx_fe_q = 0;
+
+ ddc_chain_x300 #(.BASE(0), .DSPNO(0), .WIDTH(24)) ddc_chain
+ (.clk(clk), .rst(reset), .clr(1'b0),
+ .set_stb(set_stb),.set_addr(set_addr),.set_data(set_data),
+ .rx_fe_i(rx_fe_i),.rx_fe_q(rx_fe_q),
+ .sample({i_out,q_out}), .run(run), .strobe(strobe),
+ .debug() );
+
+endmodule // new_tx_tb
diff --git a/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/.gitignore b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/.gitignore
new file mode 100644
index 000000000..7826d75e2
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/.gitignore
@@ -0,0 +1,4 @@
+fuse*
+isim*
+*.exe
+*.wcfg
diff --git a/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/run_isim b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/run_isim
new file mode 100755
index 000000000..0672e32a6
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/run_isim
@@ -0,0 +1,17 @@
+rm -rf fuse* *.exe isim
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../../lib/dsp \
+ --sourcelibdir ../../../lib/control \
+ --sourcelibdir ../../../top/x300/coregen_dsp \
+ --sourcelibdir ${XILINX}/verilog/src/unimacro \
+ ../../../lib/dsp/duc_chain_x300_tb.v
+
+
+
+fuse work.duc_chain_x300_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o duc_chain_x300_tb.exe
+
+# run the simulation scrip
+./duc_chain_x300_tb.exe -tclbatch simcmds.tcl # -gui
+
+
diff --git a/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/simcmds.tcl b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/simcmds.tcl
new file mode 100755
index 000000000..3dcfd3eaf
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/duc_chain_x300/dctest/simcmds.tcl
@@ -0,0 +1,9 @@
+# file: simcmds.tcl
+
+# create the simulation script
+#vcd dumpfile isim.vcd
+#vcd dumpvars -m /bus_clk_gen_tb -l 0
+#wave add /
+run 1 s
+quit
+
diff --git a/fpga/usrp3/lib/sim/dsp/hb47_int/hb47_int_tb.v b/fpga/usrp3/lib/sim/dsp/hb47_int/hb47_int_tb.v
new file mode 100644
index 000000000..b64b5b7dc
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/hb47_int/hb47_int_tb.v
@@ -0,0 +1,136 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module hb47_int_tb();
+
+ wire GSR, GTS;
+ glbl glbl( );
+
+ reg clk = 0;
+ reg rst;
+ reg bypass;
+ reg run;
+
+ wire stb_in;
+ reg stb_out;
+ reg [7:0] cpo;
+
+ reg [17:0] data_in;
+
+ wire [17:0] data_out_dsp48a;
+ wire [17:0] data_out_dsp48e;
+
+ reg [15:0] freq = 500;
+
+ integer x = 0, y =0;
+
+
+
+ always #100 clk = ~clk;
+
+ // SPARTAN6 / DSP48A
+ hb47_int
+ #(.WIDTH(18),
+ .DEVICE("SPARTAN6"))
+ hb47_int_i0
+ (
+ .clk(clk),
+ .rst(rst),
+ .bypass(bypass),
+ .stb_in(stb_in),
+ .data_in(data_in),
+ .output_rate(cpo),
+ .stb_out(stb_out),
+ .data_out(data_out_dsp48a)
+ );
+
+ // SERIES7 / DSP48E
+ hb47_int
+ #(.WIDTH(18),
+ .DEVICE("7SERIES"))
+ hb47_int_i1
+ (
+ .clk(clk),
+ .rst(rst),
+ .bypass(bypass),
+ .stb_in(stb_in),
+ .data_in(data_in),
+ .output_rate(cpo),
+ .stb_out(stb_out),
+ .data_out(data_out_dsp48e)
+ );
+
+ always @(negedge clk)
+ if (data_out_dsp48a !== data_out_dsp48e)
+ $display("Output missmatch at %t",$time);
+
+
+
+ cic_strober #(.WIDTH(2))
+ hb1_strober(.clock(clk),.reset(rst),.enable(run),.rate(2'd2),
+ .strobe_fast(stb_out),.strobe_slow(stb_in) );
+
+ initial
+ begin
+ rst <= 1;
+ bypass <= 0;
+ run <= 0;
+ data_in <= 0;
+ stb_out <= 1;
+ cpo <= 1;
+
+ repeat(10) @(posedge clk);
+ rst <= 0;
+ run <= 1;
+
+ for (x=0; x<100000; x=x+1) begin
+ for (y=0; y<10000; y=y+1)
+ begin
+ while (stb_in == 1'b0) @(posedge clk);
+ triangle_wave(freq,data_in);
+ @(posedge clk);
+
+ end
+ freq = freq * 2;
+ end
+
+ $finish;
+ end // initial begin
+
+
+
+
+ reg signed [18:0] phase_acc = 0;
+ reg direction = 0;
+
+
+ task triangle_wave;
+ input [15:0] inc;
+ output [17:0] data_out;
+
+ begin
+ if (direction) begin
+ phase_acc = phase_acc - inc;
+ if (phase_acc < -19'sh20000) begin
+ direction = 0;
+ phase_acc = phase_acc + inc;
+ end
+ end else begin
+ phase_acc = phase_acc + inc;
+ if (phase_acc > 19'sh1ffff) begin
+ direction = 1;
+ phase_acc = phase_acc - inc;
+ end
+ end
+ data_out = phase_acc[17:0];
+ end
+
+ endtask // triangle_wave
+
+
+
+endmodule // hb47_int_tb
diff --git a/fpga/usrp3/lib/sim/dsp/mult_add_clip/Makefile b/fpga/usrp3/lib/sim/dsp/mult_add_clip/Makefile
new file mode 100644
index 000000000..f0cdb3704
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/mult_add_clip/Makefile
@@ -0,0 +1,45 @@
+#
+# Copyright 2018 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_preamble 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/dsp/Makefile.srcs
+
+DESIGN_SRCS = $(abspath \
+$(DSP_SRCS) \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = mult_add_clip_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+mult_add_clip_tb.sv \
+)
+
+# 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/fpga/usrp3/lib/sim/dsp/mult_add_clip/mult_add_clip_tb.sv b/fpga/usrp3/lib/sim/dsp/mult_add_clip/mult_add_clip_tb.sv
new file mode 100644
index 000000000..47cd1a369
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/mult_add_clip/mult_add_clip_tb.sv
@@ -0,0 +1,137 @@
+//
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Checks a few cases of A*B+C against precomputed values
+// Configurations checked include widths and binary points for
+// rx_frontend_gen3 and tx_frontend_gen3. All latencies for those
+// configurations are checked.
+
+
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 2
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+
+module mult_add_clip_tb();
+ `TEST_BENCH_INIT("mult_add_clip_tb", `NUM_TEST_CASES, `NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/200e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ // {RX config, TX config}
+ localparam integer AW[0:1] = {18,16};
+ localparam integer A_PT[0:1] = {17,15};
+ localparam integer BW[0:1] = {18,18};
+ localparam integer B_PT[0:1] = {17,17};
+ localparam integer CW[0:1] = {24,16};
+ localparam integer C_PT[0:1] = {23,15};
+ localparam integer OW = 24;
+ localparam integer O_PT = 23;
+ localparam integer NUM_LATENCY = 4;
+ localparam integer NUM_CASES = 2;
+
+ localparam [23:0] A_VECTOR[0:7] = {24'h000000,
+ 24'h800000,
+ 24'h7fffff,
+ 24'h111111,
+ 24'h333333,
+ 24'h111111,
+ 24'h333333,
+ 24'h333333};
+ localparam [17:0] B_VECTOR[0:7] = {18'h00000,
+ 18'h1ffff,
+ 18'h1ffff,
+ 18'h10000,
+ 18'h3ffff,
+ 18'h3ffff,
+ 18'h10000,
+ 18'h10000};
+ localparam [23:0] C_VECTOR[0:7] = {24'h000000,
+ 24'h880000,
+ 24'h70ffff,
+ 24'h000000,
+ 24'h000000,
+ 24'h101010,
+ 24'h101010,
+ 24'hfffff1};
+ localparam [OW-1:0] O_VECTOR_RX[0:7] = {24'h000000,
+ 24'h800000,
+ 24'h7fffff,
+ 24'h088880,
+ 24'hffffe6,
+ 24'h101007,
+ 24'h29a990,
+ 24'h199971};
+ localparam [OW-1:0] O_VECTOR_TX[0:7] = {24'h000000,
+ 24'h800000,
+ 24'h7fffff,
+ 24'h088880,
+ 24'hffffe6,
+ 24'h100ff7,
+ 24'h29a980,
+ 24'h199880};
+
+ logic [23:0] a;
+ logic [17:0] b;
+ logic [23:0] c;
+ wire [OW-1:0] o[0:NUM_LATENCY*NUM_CASES-1];
+
+ task check_result(integer samp, integer inst);
+ begin
+ string s;
+ if ((samp >= inst) && (samp-inst < 8)) begin
+ $sformat(s, "Incorrect data for RX. Samp = %0d, Latency = %0d, Data = %06x, Expected = %06x", samp, inst, o[inst], O_VECTOR_RX[samp-inst]);
+ `ASSERT_ERROR(o[inst] == O_VECTOR_RX[samp-inst], s);
+ $sformat(s, "Incorrect data for TX. Samp = %0d, Latency = %0d, Data = %06x, Expected = %06x", samp, inst, o[inst+NUM_LATENCY], O_VECTOR_TX[samp-inst]);
+ `ASSERT_ERROR(o[inst+NUM_LATENCY] == O_VECTOR_TX[samp-inst], s);
+ end
+ end
+ endtask
+
+ genvar k, l;
+ generate for (k = 0; k < NUM_CASES; k = k + 1) begin: inst
+ for (l = 0; l < NUM_LATENCY; l = l + 1) begin: latency
+ mult_add_clip #(
+ .WIDTH_A(AW[k]),
+ .BIN_PT_A(A_PT[k]),
+ .WIDTH_B(BW[k]),
+ .BIN_PT_B(B_PT[k]),
+ .WIDTH_C(CW[k]),
+ .BIN_PT_C(C_PT[k]),
+ .WIDTH_O(OW),
+ .BIN_PT_O(O_PT),
+ .LATENCY(l+1)
+ ) dut (
+ .clk(clk), .reset(reset), .CE(1'b1),
+ .A(a[23 -: AW[k]]),
+ .B(b[17 -: BW[k]]),
+ .C(c[23 -: CW[k]]),
+ .O(o[k*NUM_LATENCY+l])
+ );
+ end
+ end endgenerate
+
+ initial begin : tb_main
+ `TEST_CASE_START("Wait for Reset");
+ while (reset) @ (posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ `TEST_CASE_START("Check products");
+ for (int i = 0; i < (8 + NUM_LATENCY); i = i + 1) begin
+ @(negedge clk);
+ for (int j = 0; j < NUM_LATENCY; j = j + 1) begin
+ check_result(i-1, j); // i-1 because inst = latency - 1
+ end
+ a = A_VECTOR[i % 8];
+ b = B_VECTOR[i % 8];
+ c = C_VECTOR[i % 8];
+ end
+ `TEST_CASE_DONE(1);
+ `TEST_BENCH_DONE;
+ end
+
+endmodule // mult_add_clip_tb
diff --git a/fpga/usrp3/lib/sim/dsp/rx_frontend/rx_frontend_tb.v b/fpga/usrp3/lib/sim/dsp/rx_frontend/rx_frontend_tb.v
new file mode 100644
index 000000000..60a866033
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/rx_frontend/rx_frontend_tb.v
@@ -0,0 +1,50 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ns
+module rx_frontend_tb();
+
+ reg clk, rst;
+
+ initial rst = 1;
+ initial #1000 rst = 0;
+ initial clk = 0;
+ always #5 clk = ~clk;
+
+ initial $dumpfile("rx_frontend_tb.vcd");
+ initial $dumpvars(0,rx_frontend_tb);
+
+ reg [15:0] adc_in;
+ wire [23:0] adc_out;
+
+ always @(posedge clk)
+ begin
+ if(adc_in[15])
+ $write("-%d,",-adc_in);
+ else
+ $write("%d,",adc_in);
+ if(adc_out[23])
+ $write("-%d\n",-adc_out);
+ else
+ $write("%d\n",adc_out);
+ end
+
+ rx_frontend #(.BASE(0), .IQCOMP_EN(1)) rx_frontend
+ (.clk(clk),.rst(rst),
+ .set_stb(0),.set_addr(0),.set_data(0),
+ .adc_a(adc_in), .adc_ovf_a(0),
+ .adc_b(0), .adc_ovf_b(0),
+ .i_out(adc_out),.q_out(),
+ .run(), .debug());
+
+ always @(posedge clk)
+ if(rst)
+ adc_in <= 0;
+ else
+ adc_in <= adc_in + 4;
+ //adc_in <= (($random % 473) + 23)/4;
+
+endmodule // rx_frontend_tb
diff --git a/fpga/usrp3/lib/sim/dsp/variable_delay_line/Makefile b/fpga/usrp3/lib/sim/dsp/variable_delay_line/Makefile
new file mode 100644
index 000000000..90733cb5d
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/variable_delay_line/Makefile
@@ -0,0 +1,47 @@
+#
+# Copyright 2018 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_preamble 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/dsp/Makefile.srcs
+include $(BASE_DIR)/../lib/control/Makefile.srcs
+
+DESIGN_SRCS = $(abspath \
+$(DSP_SRCS) \
+$(CONTROL_LIB_SRCS) \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = variable_delay_line_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+variable_delay_line_tb.sv \
+)
+
+# 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/fpga/usrp3/lib/sim/dsp/variable_delay_line/variable_delay_line_tb.sv b/fpga/usrp3/lib/sim/dsp/variable_delay_line/variable_delay_line_tb.sv
new file mode 100644
index 000000000..1691f5b8c
--- /dev/null
+++ b/fpga/usrp3/lib/sim/dsp/variable_delay_line/variable_delay_line_tb.sv
@@ -0,0 +1,117 @@
+//
+// Copyright 2018 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 4
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_axis_lib.svh"
+
+module variable_delay_line_tb();
+ `TEST_BENCH_INIT("variable_delay_line_tb", `NUM_TEST_CASES, `NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/166.67e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ localparam WIDTH = 32;
+ localparam [WIDTH-1:0] DEFAULT = 32'hDEADBEEF;
+ localparam integer NUM_INST = 24;
+ localparam integer DELAYS[0:NUM_INST-1] = {3, 14, 15, 16, 17, 30, 31, 32, 33, 127, 256, 511,
+ 3, 14, 15, 16, 17, 30, 31, 32, 33, 127, 256, 511};
+
+ logic in_stb [0:NUM_INST-1];
+ logic [WIDTH-1:0] in_samp [0:NUM_INST-1];
+ wire [WIDTH-1:0] out_samp [0:NUM_INST-1];
+ logic [31:0] out_delay[0:NUM_INST-1];
+
+ task push_samp(logic [WIDTH-1:0] word, integer inst);
+ begin
+ //$display("D[%0d]: push(0x%08x)", inst, word);
+ in_samp[inst] = word;
+ in_stb[inst] = 1'b1;
+ @(posedge clk);
+ in_stb[inst] = 1'b0;
+ end
+ endtask
+
+ task change_delay(logic [31:0] delay, integer inst);
+ begin
+ out_delay[inst] = delay;
+ @(posedge clk); // First stage
+ if (inst/(NUM_INST/2) == 1) @(posedge clk); // Pipeline stage
+ @(negedge clk);
+ //$display("D[%0d]: cd(%0d) = 0x%08x", inst, delay, out_samp[inst]);
+ end
+ endtask
+
+ genvar d;
+ generate for (d = 0; d < NUM_INST; d=d+1) begin: inst
+ variable_delay_line #(
+ .WIDTH(WIDTH), .DEPTH(DELAYS[d]),
+ .DYNAMIC_DELAY(1), .DEFAULT_DATA(DEFAULT), .OUT_REG(d / (NUM_INST/2))
+ ) dut (
+ .clk(clk), .clk_en(1'b1), .reset(reset),
+ .data_in(in_samp[d]), .stb_in(in_stb[d]),
+ .delay(out_delay[d]), .data_out(out_samp[d])
+ );
+ end endgenerate
+
+ initial begin : tb_main
+ string s;
+
+ `TEST_CASE_START("Wait for Reset");
+ for (int k = 0; k < NUM_INST; k=k+1) begin
+ in_stb[k] = 1'b0;
+ out_delay[k] = 0;
+ end
+ while (reset) @(posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ `TEST_CASE_START("Check startup state of delay line");
+ for (int k = 0; k < NUM_INST; k=k+1) begin
+ $display("Validating delay line with DEPTH=%0d, OUT_REG=%0d...", DELAYS[k], k/(NUM_INST/2));
+ for (int j = 0; j < DELAYS[k]; j=j+1) begin
+ change_delay(j, k);
+ `ASSERT_ERROR(out_samp[k] == DEFAULT, "Transient delay value incorrect");
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check partially filled delay line");
+ for (int k = 0; k < NUM_INST; k=k+1) begin
+ $display("Validating delay line with DEPTH=%0d, OUT_REG=%0d...", DELAYS[k], k/(NUM_INST/2));
+ for (int i = 0; i < DELAYS[k]; i=i+1) begin
+ push_samp(i, k);
+ for (int j = 0; j < DELAYS[k]; j=j+1) begin
+ change_delay(j, k);
+ $sformat(s, "Incorrect data. Samp = %0d, Delay = %0d, Data = %08x", i, j, out_samp[k]);
+ `ASSERT_ERROR(out_samp[k] == (j>i ? DEFAULT : i - j), s);
+ end
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Check steady state delay line");
+ for (int k = 0; k < NUM_INST; k=k+1) begin
+ $display("Validating delay line with DEPTH=%0d, OUT_REG=%0d...", DELAYS[k], k/(NUM_INST/2));
+ for (int i = 0; i < DELAYS[k]; i=i+1) begin
+ push_samp(i + DELAYS[k], k);
+ for (int j = 0; j < DELAYS[k]; j=j+1) begin
+ change_delay(j, k);
+ $sformat(s, "Incorrect data. Samp = %0d, Delay = %0d, Data = %08x", i, j, out_samp[k]);
+ `ASSERT_ERROR(out_samp[k] == DELAYS[k] + i - j, s);
+ end
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+
+ `TEST_BENCH_DONE;
+
+ end
+endmodule
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/default.wcfg b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/default.wcfg
new file mode 100644
index 000000000..796071597
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/default.wcfg
@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wave_config>
+ <wave_state>
+ </wave_state>
+ <db_ref_list>
+ <db_ref path="./isim.wdb" id="1" type="auto">
+ <top_modules>
+ <top_module name="axi_dram_fifo_tb" />
+ <top_module name="glbl" />
+ </top_modules>
+ </db_ref>
+ </db_ref_list>
+ <WVObjectSize size="38" />
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/clk" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">clk</obj_property>
+ <obj_property name="ObjectShortName">clk</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">reset</obj_property>
+ <obj_property name="ObjectShortName">reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/clear" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">clear</obj_property>
+ <obj_property name="ObjectShortName">clear</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/count_rx" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">count_rx[31:0]</obj_property>
+ <obj_property name="ObjectShortName">count_rx[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/count_tx" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">count_tx[31:0]</obj_property>
+ <obj_property name="ObjectShortName">count_tx[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tlast</obj_property>
+ <obj_property name="ObjectShortName">i_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">input_state[2:0]</obj_property>
+ <obj_property name="ObjectShortName">input_state[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_ctrl_ready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">write_ctrl_ready</obj_property>
+ <obj_property name="ObjectShortName">write_ctrl_ready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_ctrl_valid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">write_ctrl_valid</obj_property>
+ <obj_property name="ObjectShortName">write_ctrl_valid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/occupied_input" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">occupied_input[5:0]</obj_property>
+ <obj_property name="ObjectShortName">occupied_input[5:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group92" type="group">
+ <obj_property name="label">INPUT TIMEOUT</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_count[7:0]</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_count[7:0]</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_reset</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_triggered" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_triggered</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_triggered</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group60" type="group">
+ <obj_property name="label">AXI_WADDR</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/write_addr_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_addr_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">write_addr_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awaddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awaddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awaddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awsize" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awsize[2:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awsize[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awburst" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awburst[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awburst[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/write_data_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_data_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">write_data_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group61" type="group">
+ <obj_property name="label">AXI_WDATA</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wstrb" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wstrb[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wstrb[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wlast</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group62" type="group">
+ <obj_property name="label">AXI_WRESP</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bresp" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bresp[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bresp[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bready</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#00ff00</obj_property>
+ <obj_property name="label">/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/space" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">space[10:0]</obj_property>
+ <obj_property name="ObjectShortName">space[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/occupied" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">occupied[10:0]</obj_property>
+ <obj_property name="ObjectShortName">occupied[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#00ffff</obj_property>
+ </wvobject>
+ <wvobject fp_name="group63" type="group">
+ <obj_property name="label">AXI_RADDR</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_addr_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_addr_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">read_addr_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_araddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arsize" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arsize[2:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arsize[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arburst" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arburst[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arburst[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group64" type="group">
+ <obj_property name="label">AXI_RDATA</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_data_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_data_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">read_data_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rresp" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rresp[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rresp[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rlast</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_ctrl_valid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">read_ctrl_valid</obj_property>
+ <obj_property name="ObjectShortName">read_ctrl_valid</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_ctrl_ready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">read_ctrl_ready</obj_property>
+ <obj_property name="ObjectShortName">read_ctrl_ready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_data_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_data_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">read_data_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">output_state[2:0]</obj_property>
+ <obj_property name="ObjectShortName">output_state[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/space_output" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">space_output[5:0]</obj_property>
+ <obj_property name="ObjectShortName">space_output[5:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group80" type="group">
+ <obj_property name="label">DRAM FIFO OUT</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_output" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_output[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_output[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_output" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_output</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_output</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_output" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_output</obj_property>
+ <obj_property name="ObjectShortName">o_tready_output</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/update_write" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">update_write</obj_property>
+ <obj_property name="ObjectShortName">update_write</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ff00ff</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">write_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/update_read" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">update_read</obj_property>
+ <obj_property name="ObjectShortName">update_read</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ff00ff</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">read_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group68" type="group">
+ <obj_property name="label">Output TImeout</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_count[7:0]</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_count[7:0]</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_reset</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_triggered" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_triggered</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_triggered</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group76" type="group">
+ <obj_property name="label">Extract TLAST</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_i0" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_i0[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_i0[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_i0" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_i0</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_i0</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_i0" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_i0</obj_property>
+ <obj_property name="ObjectShortName">o_tready_i0</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_i1" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_i1[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_i1[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_i1</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tready_i1</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tlast_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tlast_i1</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast</obj_property>
+ <obj_property name="ObjectShortName">o_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+</wave_config>
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/run_isim b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/run_isim
new file mode 100755
index 000000000..5d32efcdd
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/run_isim
@@ -0,0 +1,16 @@
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+#vlogcomp --define SIM_SCRIPT=true --define ISIM=true -work work ../../../packet_proc/source_flow_control_tb.v
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../axi \
+ --sourcelibdir ../../fifo \
+ --sourcelibdir ../../../top/b250/coregen \
+ ../../axi/axi_dram_fifo_tb.v
+
+
+
+fuse work.axi_dram_fifo_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o axi_dram_fifo_tb.exe
+
+# run the simulation scrip
+./axi_dram_fifo_tb.exe -gui #-tclbatch simcmds.tcl
+#./source_flow_control_tb.exe
+
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/default.wcfg b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/default.wcfg
new file mode 100644
index 000000000..796071597
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/default.wcfg
@@ -0,0 +1,412 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wave_config>
+ <wave_state>
+ </wave_state>
+ <db_ref_list>
+ <db_ref path="./isim.wdb" id="1" type="auto">
+ <top_modules>
+ <top_module name="axi_dram_fifo_tb" />
+ <top_module name="glbl" />
+ </top_modules>
+ </db_ref>
+ </db_ref_list>
+ <WVObjectSize size="38" />
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/clk" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">clk</obj_property>
+ <obj_property name="ObjectShortName">clk</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">reset</obj_property>
+ <obj_property name="ObjectShortName">reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/clear" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">clear</obj_property>
+ <obj_property name="ObjectShortName">clear</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/count_rx" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">count_rx[31:0]</obj_property>
+ <obj_property name="ObjectShortName">count_rx[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/count_tx" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">count_tx[31:0]</obj_property>
+ <obj_property name="ObjectShortName">count_tx[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tlast</obj_property>
+ <obj_property name="ObjectShortName">i_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">input_state[2:0]</obj_property>
+ <obj_property name="ObjectShortName">input_state[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_ctrl_ready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">write_ctrl_ready</obj_property>
+ <obj_property name="ObjectShortName">write_ctrl_ready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_ctrl_valid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">write_ctrl_valid</obj_property>
+ <obj_property name="ObjectShortName">write_ctrl_valid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/occupied_input" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">occupied_input[5:0]</obj_property>
+ <obj_property name="ObjectShortName">occupied_input[5:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group92" type="group">
+ <obj_property name="label">INPUT TIMEOUT</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_count[7:0]</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_count[7:0]</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_reset</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/input_timeout_triggered" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">input_timeout_triggered</obj_property>
+ <obj_property name="ObjectShortName">input_timeout_triggered</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group60" type="group">
+ <obj_property name="label">AXI_WADDR</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/write_addr_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_addr_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">write_addr_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awaddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awaddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awaddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awsize" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awsize[2:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awsize[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awburst" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awburst[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awburst[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_awready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_awready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_awready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/write_data_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_data_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">write_data_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group61" type="group">
+ <obj_property name="label">AXI_WDATA</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wstrb" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wstrb[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wstrb[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wlast</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_wready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_wready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_wready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group62" type="group">
+ <obj_property name="label">AXI_WRESP</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bresp" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bresp[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bresp[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_bready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_bready</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#00ff00</obj_property>
+ <obj_property name="label">/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_bready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/space" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">space[10:0]</obj_property>
+ <obj_property name="ObjectShortName">space[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/occupied" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">occupied[10:0]</obj_property>
+ <obj_property name="ObjectShortName">occupied[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#00ffff</obj_property>
+ </wvobject>
+ <wvobject fp_name="group63" type="group">
+ <obj_property name="label">AXI_RADDR</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_addr_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_addr_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">read_addr_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_araddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arsize" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arsize[2:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arsize[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arburst" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arburst[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arburst[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group64" type="group">
+ <obj_property name="label">AXI_RDATA</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_data_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_data_state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">read_data_state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rid" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rid[0:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rid[0:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rresp" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rresp[1:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rresp[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rlast</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_ctrl_valid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">read_ctrl_valid</obj_property>
+ <obj_property name="ObjectShortName">read_ctrl_valid</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ffff00</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_ctrl_ready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">read_ctrl_ready</obj_property>
+ <obj_property name="ObjectShortName">read_ctrl_ready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_dma_master_i/read_data_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_data_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">read_data_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">output_state[2:0]</obj_property>
+ <obj_property name="ObjectShortName">output_state[2:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/space_output" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">space_output[5:0]</obj_property>
+ <obj_property name="ObjectShortName">space_output[5:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group80" type="group">
+ <obj_property name="label">DRAM FIFO OUT</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_output" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_output[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_output[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_output" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_output</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_output</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_output" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_output</obj_property>
+ <obj_property name="ObjectShortName">o_tready_output</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/update_write" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">update_write</obj_property>
+ <obj_property name="ObjectShortName">update_write</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ff00ff</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/write_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">write_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">write_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/update_read" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">update_read</obj_property>
+ <obj_property name="ObjectShortName">update_read</obj_property>
+ <obj_property name="UseCustomSignalColor">true</obj_property>
+ <obj_property name="CustomSignalColor">#ff00ff</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/read_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">read_count[3:0]</obj_property>
+ <obj_property name="ObjectShortName">read_count[3:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group68" type="group">
+ <obj_property name="label">Output TImeout</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_count" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_count[7:0]</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_count[7:0]</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_reset</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/output_timeout_triggered" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">output_timeout_triggered</obj_property>
+ <obj_property name="ObjectShortName">output_timeout_triggered</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group76" type="group">
+ <obj_property name="label">Extract TLAST</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_i0" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_i0[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_i0[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_i0" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_i0</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_i0</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_i0" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_i0</obj_property>
+ <obj_property name="ObjectShortName">o_tready_i0</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata_i1" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata_i1[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata_i1[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid_i1</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tready_i1</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tlast_i1" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast_i1</obj_property>
+ <obj_property name="ObjectShortName">o_tlast_i1</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast</obj_property>
+ <obj_property name="ObjectShortName">o_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+</wave_config>
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/run_isim b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/run_isim
new file mode 100755
index 000000000..03eead1f7
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/run_isim
@@ -0,0 +1,17 @@
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+#vlogcomp --define SIM_SCRIPT=true --define ISIM=true -work work ../../../packet_proc/source_flow_control_tb.v
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../../lib/axi \
+ --sourcelibdir ../../../lib/fifo \
+ --sourcelibdir ../../../lib/control \
+ --sourcelibdir ../../../top/x300/coregen \
+ ../../../lib/axi/axi_dram_fifo_tb.v
+
+
+
+fuse work.axi_dram_fifo_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o axi_dram_fifo_tb.exe
+
+# run the simulation scrip
+./axi_dram_fifo_tb.exe # -gui #-tclbatch simcmds.tcl
+
+
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/simulation_script.v b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/simulation_script.v
new file mode 100644
index 000000000..974b4e096
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_1/simulation_script.v
@@ -0,0 +1,118 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+reg [31:0] count_rx, count_tx;
+reg status;
+reg fail;
+
+
+//
+// Use task library
+//
+`define USE_TASKS
+
+ initial
+ begin
+ clk <= 1'b0;
+ reset <= 1'b0;
+ clear <= 1'b0;
+ i_tdata_r <= 0;
+ i_tlast_r <= 0;
+ i_tvalid_r <= 0;
+ o_tready_r <= 0;
+ end
+
+ always
+ #5 clk <= ~clk;
+
+ initial
+ begin
+ count_tx = 2;
+ count_rx = 2;
+ status = 0;
+
+
+ @(negedge clk);
+ reset <= 1'b1;
+ repeat(10) @(negedge clk);
+ reset <= 1'b0;
+ repeat(10) @(negedge clk);
+
+ // Send 40 packets.
+ repeat(40) begin
+ send_raw_packet(count_tx);
+ repeat(2) @(posedge clk);
+ count_tx = count_tx + 1;
+ @(posedge clk);
+ end
+ repeat(100) @(posedge clk);
+
+
+ // Recieve 40 packets
+ repeat(40) begin
+ receive_raw_packet(count_rx,fail);
+ status = status || fail;
+ repeat(2) @(posedge clk);
+ count_rx = count_rx + 1;
+ @(posedge clk);
+ end
+ repeat(100) @(posedge clk);
+
+ count_tx = 2;
+ count_rx = 2;
+
+ // Send 40 packets.
+ repeat(40) begin
+ send_raw_packet(count_tx);
+ repeat(2) @(posedge clk);
+ count_tx = count_tx + 1;
+ @(posedge clk);
+ end
+ repeat(100) @(posedge clk);
+ // Now fork so send and receive run concurrently
+ fork
+ begin
+ // Send 40 packets.
+ repeat(40) begin
+ send_raw_packet(count_tx);
+ repeat(2) @(posedge clk);
+ count_tx = count_tx + 1;
+ @(posedge clk);
+ end
+ end
+ begin
+ // Recieve 80 packets
+ repeat(80) begin
+ receive_raw_packet(count_rx,status);
+ status = status || fail;
+ repeat(2) @(posedge clk);
+ count_rx = count_rx + 1;
+ @(posedge clk);
+ if (status !== 0) begin
+ repeat(100) @(posedge clk);
+ $display("FAILED.");
+ $finish;
+ end
+ end
+ end
+ join
+ // Now single threaded agian.
+ repeat(100) @(posedge clk);
+
+ $display;
+ // Should not be able to get to here with FAIL status but check anyhow
+ if (status != 0)
+ $display("FAILED.");
+ else
+ $display("PASSED.");
+
+ @(posedge clk);
+ $finish;
+
+ end
+
+ //initial
+ // o_tready = 1;
+
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/Default.wcfg b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/Default.wcfg
new file mode 100644
index 000000000..3e6d96fb4
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/Default.wcfg
@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<wave_config>
+ <wave_state>
+ </wave_state>
+ <db_ref_list>
+ <db_ref path="./isim.wdb" id="1" type="auto">
+ <top_modules>
+ <top_module name="axi_dram_fifo_tb" />
+ <top_module name="glbl" />
+ </top_modules>
+ </db_ref>
+ </db_ref_list>
+ <WVObjectSize size="14" />
+ <wave_markers>
+ <marker time="31415100000" label="" />
+ <marker time="30385518000" label="" />
+ <marker time="23065100000" label="" />
+ <marker time="18355382000" label="" />
+ </wave_markers>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/clk" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">clk</obj_property>
+ <obj_property name="ObjectShortName">clk</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/reset" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">reset</obj_property>
+ <obj_property name="ObjectShortName">reset</obj_property>
+ </wvobject>
+ <wvobject fp_name="group31" type="group">
+ <obj_property name="label">chdr_test_pattern</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/start" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">start</obj_property>
+ <obj_property name="ObjectShortName">start</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/i_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tlast</obj_property>
+ <obj_property name="ObjectShortName">i_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/o_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast</obj_property>
+ <obj_property name="ObjectShortName">o_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_chdr_test_pattern_i/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group11" type="group">
+ <obj_property name="label">embed_tlast</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/i_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tlast</obj_property>
+ <obj_property name="ObjectShortName">i_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_embed_tlast_i/state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group18" type="group">
+ <obj_property name="label">fast_fifo_i0</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/state" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">state[1:0]</obj_property>
+ <obj_property name="ObjectShortName">state[1:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="DisplayName">FullPathName</obj_property>
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i0/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ <obj_property name="label">o_tready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group25" type="group">
+ <obj_property name="label">fifo_i1</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i1/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group79" type="group">
+ <obj_property name="label">AXI write bus</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_awaddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_awaddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">axi_awaddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_awlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_awlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">axi_awlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_awvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_awvalid</obj_property>
+ <obj_property name="ObjectShortName">axi_awvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_awready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_awready</obj_property>
+ <obj_property name="ObjectShortName">axi_awready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_wdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_wdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">axi_wdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_wvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_wvalid</obj_property>
+ <obj_property name="ObjectShortName">axi_wvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_wready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_wready</obj_property>
+ <obj_property name="ObjectShortName">axi_wready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_bvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_bvalid</obj_property>
+ <obj_property name="ObjectShortName">axi_bvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_bready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">axi_bready</obj_property>
+ <obj_property name="ObjectShortName">axi_bready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/space" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">space[10:0]</obj_property>
+ <obj_property name="ObjectShortName">space[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/occupied" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">occupied[10:0]</obj_property>
+ <obj_property name="ObjectShortName">occupied[10:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="group71" type="group">
+ <obj_property name="label">AXI read bus</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_araddr" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_araddr[31:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arlen" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arlen[7:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_arready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_arready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_arready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rvalid</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/m_axi_rready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">m_axi_rready</obj_property>
+ <obj_property name="ObjectShortName">m_axi_rready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group43" type="group">
+ <obj_property name="label">fifo_i2</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fifo_i2/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group50" type="group">
+ <obj_property name="label">fast_fifo_i1</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/fast_fifo_i1/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group58" type="group">
+ <obj_property name="label">axi_fast_extract</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/i_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">i_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/i_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tvalid</obj_property>
+ <obj_property name="ObjectShortName">i_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/i_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">i_tready</obj_property>
+ <obj_property name="ObjectShortName">i_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/o_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast</obj_property>
+ <obj_property name="ObjectShortName">o_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/axi_fast_extract_tlast_i0/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ </wvobject>
+ <wvobject fp_name="group63" type="group">
+ <obj_property name="label">dram_fifo_output</obj_property>
+ <obj_property name="DisplayName">label</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tdata" type="array" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="ObjectShortName">o_tdata[63:0]</obj_property>
+ <obj_property name="Radix">HEXRADIX</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tlast" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tlast</obj_property>
+ <obj_property name="ObjectShortName">o_tlast</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tvalid" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tvalid</obj_property>
+ <obj_property name="ObjectShortName">o_tvalid</obj_property>
+ </wvobject>
+ <wvobject fp_name="/axi_dram_fifo_tb/axi_dram_fifo_i1/o_tready" type="logic" db_ref_id="1">
+ <obj_property name="ElementShortName">o_tready</obj_property>
+ <obj_property name="ObjectShortName">o_tready</obj_property>
+ </wvobject>
+ </wvobject>
+</wave_config>
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/run_isim b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/run_isim
new file mode 100755
index 000000000..46141fcae
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/run_isim
@@ -0,0 +1,19 @@
+/bin/rm -r isim
+
+vlogcomp -work work ${XILINX}/verilog/src/glbl.v
+
+vlogcomp -work work --sourcelibext .v \
+ --sourcelibdir ../../../lib/axi \
+ --sourcelibdir ../../../lib/fifo \
+ --sourcelibdir ../../../lib/control \
+ --sourcelibdir ../../../top/x300/coregen \
+ ../../../lib/axi/axi_dram_fifo_tb.v
+
+
+
+fuse work.axi_dram_fifo_tb work.glbl -L unisims_ver -L xilinxcorelib_ver -o axi_dram_fifo_tb.exe
+
+# run the simulation scrip
+./axi_dram_fifo_tb.exe -gui #-tclbatch simcmds.tcl
+
+
diff --git a/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/simulation_script.v b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/simulation_script.v
new file mode 100644
index 000000000..66de106d7
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_dram_fifo/sim_sram_2/simulation_script.v
@@ -0,0 +1,96 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+wire fail;
+wire done;
+reg start;
+reg [15:0] control;
+
+
+
+axi_chdr_test_pattern axi_chdr_test_pattern_i
+ (
+ .clk(clk),
+ .reset(reset),
+
+ //
+ // CHDR friendly AXI stream input
+ //
+ .i_tdata(i_tdata),
+ .i_tlast(i_tlast),
+ .i_tvalid(i_tvalid),
+ .i_tready(i_tready),
+ //
+ // CHDR friendly AXI Stream output
+ //
+ .o_tdata(o_tdata),
+ .o_tlast(o_tlast),
+ .o_tvalid(o_tvalid),
+ .o_tready(o_tready),
+ //
+ // Test flags
+ //
+ .start(start),
+ .fail(fail),
+ .done(done),
+ .control(control)
+ );
+
+
+ always
+ #5 clk <= ~clk;
+
+ initial
+ begin
+ clk <= 1'b0;
+ reset <= 1'b0;
+ clear <= 1'b0;
+ start <= 1'b0;
+ control <= 16'h0101;
+
+
+ @(negedge clk);
+ reset <= 1'b1;
+ repeat(10) @(negedge clk);
+ reset <= 1'b0;
+ repeat(10) @(negedge clk);
+ // Now activate BIST
+ start <= 1'b1;
+
+ // Wait until simulation is done.
+ while(!done)
+ @(negedge clk);
+
+ $display;
+
+ if (fail)
+ $display("FAILED.");
+ else
+ $display("Done 1st pass.");
+
+ @(posedge clk);
+ start <= 1'b0;
+ repeat(10) @(negedge clk);
+ // Now activate BIST
+ start <= 1'b1;
+
+ // Wait until simulation is done.
+ while(!done)
+ @(negedge clk);
+
+ $display;
+
+ if (fail)
+ $display("FAILED.");
+ else
+ $display("PASSED.");
+
+ $finish;
+
+ end
+
+ //initial
+ // o_tready = 1;
+
diff --git a/fpga/usrp3/lib/sim/fifo/axi_fifo/Makefile b/fpga/usrp3/lib/sim/fifo/axi_fifo/Makefile
new file mode 100644
index 000000000..3cd861176
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_fifo/Makefile
@@ -0,0 +1,34 @@
+#
+# Copyright 2016 Ettus Research
+#
+
+#-------------------------------------------------
+# Top-of-Makefile
+#-------------------------------------------------
+# Define BASE_DIR to point to the "top" dir
+BASE_DIR = $(abspath ../../../../top)
+# Include viv_sim_preamble after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = axi_fifo_tb
+
+SIM_SRCS = $(abspath \
+axi_fifo_tb.sv \
+$(LIB_DIR)/fifo/axi_fifo.v \
+$(LIB_DIR)/fifo/axi_fifo_flop.v \
+$(LIB_DIR)/fifo/axi_fifo_flop2.v \
+$(LIB_DIR)/fifo/axi_fifo_short.v \
+$(LIB_DIR)/fifo/axi_fifo_bram.v \
+)
+
+#-------------------------------------------------
+# 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/fpga/usrp3/lib/sim/fifo/axi_fifo/axi_fifo_tb.sv b/fpga/usrp3/lib/sim/fifo/axi_fifo/axi_fifo_tb.sv
new file mode 100644
index 000000000..c2832cade
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_fifo/axi_fifo_tb.sv
@@ -0,0 +1,134 @@
+//
+// Copyright 2016 Ettus Research
+//
+
+`timescale 1ns/1ps
+`define SIM_TIMEOUT_US 1000
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 4
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_cvita_lib.svh"
+`include "sim_axis_lib.svh"
+`include "sim_set_rb_lib.svh"
+
+module axi_fifo_tb();
+ /*********************************************
+ ** Setup Testbench
+ *********************************************/
+ `TEST_BENCH_INIT("axi_fifo_tb",`NUM_TEST_CASES,`NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/166.67e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ // 4 variants: axi_fifo_flop, axi_fifo_flop2, axi_fifo_short, axi_fifo_bram
+ localparam NUM_FIFOS = 4;
+ localparam integer FIFO_SIZES[NUM_FIFOS-1:0] = '{0,1,5,8};
+ localparam NUM_ITERATIONS = 10000;
+
+ /*********************************************
+ ** DUTs
+ ** - Instances of all variations of AXI FIFO
+ *********************************************/
+ reg [NUM_FIFOS-1:0] clear;
+ axis_master #(.DWIDTH(32), .NUM_STREAMS(NUM_FIFOS)) m_axis(.clk(clk));
+ axis_slave #(.DWIDTH(32), .NUM_STREAMS(NUM_FIFOS)) s_axis(.clk(clk));
+
+ genvar n;
+ generate
+ for (n = 0; n < NUM_FIFOS; n = n + 1) begin
+ axi_fifo #(
+ .SIZE(FIFO_SIZES[n]),
+ .WIDTH(32))
+ axi_fifo (
+ .clk(clk), .reset(reset), .clear(clear[n]),
+ .i_tdata(m_axis.axis.tdata[32*n +: 32]), .i_tvalid(m_axis.axis.tvalid[n]), .i_tready(m_axis.axis.tready[n]),
+ .o_tdata(s_axis.axis.tdata[32*n +: 32]), .o_tvalid(s_axis.axis.tvalid[n]), .o_tready(s_axis.axis.tready[n]),
+ .space(), .occupied());
+ end
+ endgenerate
+
+ /*********************************************
+ ** Testbench
+ *********************************************/
+ int write_word = 0;
+ int read_word = 0;
+ logic last;
+ string s;
+
+ initial begin
+ clear = 'd0;
+
+ /********************************************************
+ ** Test 1 -- Reset
+ ********************************************************/
+ `TEST_CASE_START("Wait for Reset");
+ m_axis.reset();
+ s_axis.reset();
+ while (reset) @(posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ /********************************************************
+ ** Test 2 -- Check filling FIFOs
+ ********************************************************/
+ `TEST_CASE_START("Check filling FIFOs");
+ for (int i = 0; i < NUM_FIFOS; i++) begin
+ $display("Testing FIFO %0d, SIZE %0d",i,2**FIFO_SIZES[i]);
+ for (int k = 0; k < 2**FIFO_SIZES[i]; k++) begin
+ $sformat(s,"FIFO size should be %0d entries, but detected %0d!",2**FIFO_SIZES[i],k);
+ `ASSERT_FATAL(m_axis.axis.tready[i],s);
+ m_axis.push_word(k,0,i);
+ end
+ $sformat(s,"FIFO depth appears to be greater than %0d entries! Might be due to output registering.",2**FIFO_SIZES[i]);
+ `ASSERT_WARN(~m_axis.axis.tready[i],s);
+ end
+ `TEST_CASE_DONE(1);
+
+ /********************************************************
+ ** Test 3 -- Check emptying FIFOs
+ ********************************************************/
+ `TEST_CASE_START("Check emptying FIFOs");
+ for (int i = 0; i < NUM_FIFOS; i++) begin
+ $display("Testing FIFO %0d, SIZE %0d",i,2**FIFO_SIZES[i]);
+ for (int k = 0; k < 2**FIFO_SIZES[i]; k = k + 1) begin
+ $sformat(s,"FIFO prematurely empty! Occured after %0d reads!",k);
+ `ASSERT_FATAL(s_axis.axis.tvalid[i],s);
+ s_axis.pull_word(read_word,last,i);
+ $sformat(s,"Read invalid FIFO word! Expected: %0d, Actual: %0d",k,read_word);
+ `ASSERT_FATAL(read_word == k,s);
+ end
+ `ASSERT_FATAL(~s_axis.axis.tvalid[i],"FIFO not empty after reading all entries!");
+ end
+ `TEST_CASE_DONE(1);
+
+ /********************************************************
+ ** Test 4 -- Randomized Write / Read Timing
+ ********************************************************/
+ `TEST_CASE_START("Randomized Write / Read");
+ for (int i = 0; i < NUM_FIFOS; i++) begin
+ $display("Testing FIFO %0d, SIZE %0d",i,2**FIFO_SIZES[i]);
+ fork
+ begin
+ write_word = 0;
+ for (int k = 0; k < NUM_ITERATIONS; k++) begin
+ while ($signed($random()) > 0) @(posedge clk);
+ m_axis.push_word(write_word,0,i);
+ write_word++;
+ end
+ end
+ begin
+ for (int k = 0; k < NUM_ITERATIONS; k++) begin
+ while ($signed($random()) > 0) @(posedge clk);
+ s_axis.pull_word(read_word,last,i);
+ $sformat(s,"Read invalid FIFO word! Expected: %0d, Actual: %0d",read_word,k);
+ `ASSERT_FATAL(read_word == k,s);
+ end
+ end
+ join
+ end
+ `TEST_CASE_DONE(1);
+ `TEST_BENCH_DONE;
+ end
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk/axi_fifo_2clk_tb.sv b/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk/axi_fifo_2clk_tb.sv
new file mode 100644
index 000000000..c2c69b963
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk/axi_fifo_2clk_tb.sv
@@ -0,0 +1,121 @@
+//
+// Copyright 2016 Ettus Research
+//
+
+module axi_fifo_2clk_tb();
+
+ localparam WIDTH = 32;
+ localparam SIZE = 5;
+
+ reg s_axis_clk;
+ reg s_axis_rst;
+ reg [WIDTH-1:0] s_axis_tdata;
+ reg s_axis_tvalid;
+ reg s_axis_tlast;
+ wire s_axis_tready;
+ reg m_axis_clk;
+ reg m_axis_rst;
+ wire [WIDTH-1:0] m_axis_tdata;
+ wire m_axis_tvalid;
+ wire m_axis_tlast;
+ reg m_axis_tready;
+ wire [SIZE:0] s_axis_occupied;
+ wire s_axis_full;
+ wire s_axis_empty;
+ wire [SIZE:0] m_axis_occupied;
+ wire m_axis_full;
+ wire m_axis_empty;
+
+ axi_fifo_2clk #(.SIZE(SIZE),.WIDTH(WIDTH)) axi_fifo_2clk (
+ .s_axis_clk(s_axis_clk),
+ .s_axis_rst(s_axis_rst),
+ .s_axis_tdata(s_axis_tdata),
+ .s_axis_tvalid(s_axis_tvalid),
+ .s_axis_tlast(s_axis_tlast),
+ .s_axis_tready(s_axis_tready),
+ .m_axis_clk(m_axis_clk),
+ .m_axis_rst(m_axis_rst),
+ .m_axis_tdata(m_axis_tdata),
+ .m_axis_tvalid(m_axis_tvalid),
+ .m_axis_tlast(m_axis_tlast),
+ .m_axis_tready(m_axis_tready),
+ .s_axis_occupied(s_axis_occupied),
+ .s_axis_full(s_axis_full),
+ .s_axis_empty(s_axis_empty),
+ .m_axis_occupied(m_axis_occupied),
+ .m_axis_full(m_axis_full),
+ .m_axis_empty(m_axis_empty));
+
+ `define S_AXIS_CLK_PERIOD 7
+ initial begin
+ s_axis_clk = 1'b0;
+ forever begin
+ #(`S_AXIS_CLK_PERIOD/2) s_axis_clk = ~s_axis_clk;
+ end
+ end
+
+ `define S_AXIS_RESET_PERIOD 70
+ initial begin
+ s_axis_rst = 1'b1;
+ #(`S_AXIS_RESET_PERIOD) s_axis_rst = 1'b0;
+ end
+
+ `define M_AXIS_CLK_PERIOD 10
+ initial begin
+ m_axis_clk = 1'b0;
+ forever begin
+ #(`M_AXIS_CLK_PERIOD/2) m_axis_clk = ~m_axis_clk;
+ end
+ end
+
+ `define M_AXIS_RESET_PERIOD 100
+ initial begin
+ m_axis_rst = 1'b1;
+ #(`M_AXIS_RESET_PERIOD) m_axis_rst = 1'b0;
+ end
+
+ initial begin
+ @(posedge m_axis_clk);
+ @(posedge s_axis_clk);
+ s_axis_tdata = 'd0;
+ s_axis_tlast = 1'b0;
+ s_axis_tvalid = 1'b0;
+ m_axis_tready = 1'b0;
+ assert(~s_axis_full && ~m_axis_full) else $error("FIFO is full during reset!");
+ assert(s_axis_empty == 1'b1 && m_axis_empty == 1'b1) else $error("FIFO is not empty during reset!");
+ assert(s_axis_occupied == 0 && m_axis_occupied == 0) else $error("FIFO is occupied during reset!");
+ while (s_axis_rst) @(negedge s_axis_rst);
+ while (m_axis_rst) @(negedge m_axis_rst);
+ @(posedge m_axis_clk);
+ @(posedge s_axis_clk);
+ assert(~s_axis_full && ~m_axis_full) else $error("FIFO is full after reset!");
+ assert(s_axis_empty == 1'b1 && m_axis_empty == 1'b1) else $error("FIFO is not empty after reset!");
+ assert(s_axis_occupied == 0 && m_axis_occupied == 0) else $error("FIFO is occupied after reset!");
+ // Fill FIFO
+ while (~s_axis_tready) @(posedge s_axis_clk);
+ for (int i = 0; i < 1 << DEPTH_LOG2; i++) begin
+ s_axis_tdata = i+1'b1;
+ s_axis_tvalid = 1'b1;
+ @(posedge s_axis_clk);
+ end
+ repeat (6) @(posedge s_axis_clk);
+ assert(s_axis_full && m_axis_full) else $error("Incorrect FIFO full flag!");
+ assert(~s_axis_empty && ~m_axis_empty) else $error("Incorrect FIFO empty flag!");
+ assert(s_axis_occupied == (1 << DEPTH_LOG2) && m_axis_occupied == (1 << DEPTH_LOG2)) else $error("Incorrect FIFO occupied count!");
+ // Empty FIFO
+ s_axis_tdata = 'd0;
+ s_axis_tvalid = 1'b0;
+ @(posedge m_axis_clk);
+ while (~m_axis_tvalid) @(posedge m_axis_clk);
+ for (int i = 0; i < 1 << DEPTH_LOG2; i++) begin
+ m_axis_tready = 1'b1;
+ @(posedge m_axis_clk);
+ assert(m_axis_tdata == i+1'b1) else $error("Incorrect FIFO data! (read)");
+ end
+ repeat (6) @(posedge m_axis_clk);
+ assert(~s_axis_full && ~m_axis_full) else $error("Incorrect FIFO full flag!");
+ assert(s_axis_empty && m_axis_empty) else $error("Incorrect FIFO empty flag!");
+ assert(s_axis_occupied == 0 && m_axis_occupied == 0) else $error("Incorrect FIFO occupied count!");
+ end
+
+endmodule \ No newline at end of file
diff --git a/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk_sim.v b/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk_sim.v
new file mode 100644
index 000000000..cf31ae2d9
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_fifo_2clk_sim.v
@@ -0,0 +1,230 @@
+//
+// Copyright 2016 Ettus Research
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+module axi_fifo_2clk #(
+ parameter SYNC_STAGES = 2,
+ parameter SIZE = 10,
+ parameter WIDTH = 32,
+ parameter PIPELINE = "<UNUSED>")
+(
+ input reset,
+ input i_aclk,
+ input [WIDTH-1:0] i_tdata,
+ input i_tvalid,
+ output reg i_tready = 1'b0,
+ input o_aclk,
+ output [WIDTH-1:0] o_tdata,
+ output reg o_tvalid = 1'b0,
+ input o_tready
+);
+
+ localparam FIFOSIZE = (SIZE < 5) ? 5 : SIZE;
+
+ // Synchronizers
+ wire o_rst_sync, i_rst_sync;
+ synchronizer #(
+ .INITIAL_VAL(1'b1),
+ .WIDTH(1),
+ .STAGES(SYNC_STAGES))
+ synchronizer_i_rst (
+ .clk(i_aclk), .rst(1'b0),
+ .in(reset), .out(i_rst_sync));
+ synchronizer #(
+ .INITIAL_VAL(1'b1),
+ .WIDTH(1),
+ .STAGES(SYNC_STAGES))
+ synchronizer_o_rst (
+ .clk(o_aclk), .rst(1'b0),
+ .in(reset), .out(o_rst_sync));
+
+ // Gray counter encode / decode + synchronizers
+ reg [FIFOSIZE-1:0] wr_addr, rd_addr;
+ wire [FIFOSIZE-1:0] wr_addr_sync, rd_addr_sync;
+ wire [FIFOSIZE-1:0] wr_addr_gray_sync, wr_addr_gray, rd_addr_gray_sync, rd_addr_gray;
+ synchronizer #(
+ .INITIAL_VAL(0),
+ .WIDTH(FIFOSIZE),
+ .STAGES(SYNC_STAGES))
+ synchronizer_rd_addr_gray (
+ .clk(i_aclk), .rst(o_rst_sync),
+ .in(rd_addr_gray), .out(rd_addr_gray_sync));
+ synchronizer #(
+ .INITIAL_VAL(0),
+ .WIDTH(FIFOSIZE),
+ .STAGES(SYNC_STAGES))
+ synchronizer_wr_addr_gray (
+ .clk(o_aclk), .rst(i_rst_sync),
+ .in(wr_addr_gray), .out(wr_addr_gray_sync));
+ bin2gray #(.WIDTH(FIFOSIZE))
+ bin2gray_wr_addr (.bin(wr_addr), .gray(wr_addr_gray));
+ bin2gray #(.WIDTH(FIFOSIZE))
+ bin2gray_rd_addr (.bin(rd_addr), .gray(rd_addr_gray));
+ gray2bin #(.WIDTH(FIFOSIZE))
+ gray2bin_wr_addr (.gray(wr_addr_gray_sync), .bin(wr_addr_sync));
+ gray2bin #(.WIDTH(FIFOSIZE))
+ gray2bin_rd_addr (.gray(rd_addr_gray_sync), .bin(rd_addr_sync));
+
+ reg [FIFOSIZE:0] i_occupied;
+ reg [FIFOSIZE:0] i_space;
+ reg i_full;
+ reg i_empty;
+ reg [FIFOSIZE:0] o_occupied;
+ reg [FIFOSIZE:0] o_space;
+ reg o_full;
+ reg o_empty;
+
+ reg [WIDTH:0] mem[0:2**(FIFOSIZE)-1];
+ integer i;
+ initial begin
+ for (i = 0; i < 1 << FIFOSIZE; i = i + 1) begin
+ mem[i] = 'd0;
+ end
+ end
+
+ // Write
+ always @(posedge i_aclk) begin
+ if (i_rst_sync) begin
+ wr_addr <= 'd0;
+ end else begin
+ if (i_tvalid & i_tready) begin
+ mem[wr_addr] <= i_tdata;
+ wr_addr <= wr_addr + 1'b1;
+ end
+ end
+ end
+
+ // Write ready, full, empty, occupied signals
+ always @(posedge i_aclk) begin
+ if (i_rst_sync) begin
+ i_tready <= 1'b0;
+ i_full <= 1'b0;
+ i_empty <= 1'b1;
+ i_occupied <= 'd0;
+ i_space <= (1'b1 << FIFOSIZE);
+ end else begin
+ if ((rd_addr_sync-1'b1 == wr_addr) & i_tvalid & i_tready) begin
+ i_tready <= 1'b0;
+ i_full <= 1'b1;
+ end else if ((rd_addr_sync != wr_addr) & i_full) begin
+ i_tready <= 1'b1;
+ i_full <= 1'b0;
+ end
+ if ((rd_addr_sync == wr_addr) & ~i_full) begin
+ i_tready <= 1'b1;
+ if (~i_tvalid) begin
+ i_empty <= 1'b1;
+ end
+ end else begin
+ i_empty <= 1'b0;
+ end
+ if (i_tvalid) begin
+ if (wr_addr == rd_addr_sync) begin
+ if (i_full) begin
+ i_occupied <= 1'b1 << FIFOSIZE;
+ i_space <= 'd0;
+ end else begin
+ i_occupied <= 'd1;
+ i_space <= (1'b1 << FIFOSIZE)-1'b1;
+ end
+ end else if (wr_addr > rd_addr_sync) begin
+ i_occupied <= wr_addr - rd_addr_sync + 1'b1;
+ i_space <= (1'b1 << FIFOSIZE) - (wr_addr - rd_addr_sync + 1'b1);
+ end else begin
+ i_occupied <= wr_addr+1'b1 + (1'b1 << FIFOSIZE)-1'b1 - rd_addr_sync + 1'b1;
+ i_space <= rd_addr_sync - wr_addr - 1'b1;
+ end
+ end else begin
+ if (wr_addr == rd_addr_sync) begin
+ if (i_full) begin
+ i_occupied <= 1'b1 << FIFOSIZE;
+ i_space <= 'd0;
+ end else begin
+ i_occupied <= 'd0;
+ i_space <= 1'b1 << FIFOSIZE;
+ end
+ end else if (wr_addr > rd_addr_sync) begin
+ i_occupied <= wr_addr - rd_addr_sync;
+ i_space <= (1'b1 << FIFOSIZE) - (wr_addr - rd_addr_sync);
+ end else begin
+ i_occupied <= wr_addr+1'b1 + (1'b1 << FIFOSIZE)-1'b1 - rd_addr_sync;
+ i_space <= rd_addr_sync - wr_addr;
+ end
+ end
+ end
+ end
+
+ // Read
+ always @(posedge o_aclk) begin
+ if (o_rst_sync) begin
+ rd_addr <= 'd0;
+ end else begin
+ if (o_tvalid & o_tready) begin
+ rd_addr <= rd_addr + 1'b1;
+ end
+ end
+ end
+
+ assign o_tdata = mem[rd_addr];
+
+ // Read valid, full, empty, occupied signals
+ always @(posedge o_aclk) begin
+ if (o_rst_sync) begin
+ o_tvalid <= 1'b0;
+ o_full <= 1'b0;
+ o_empty <= 1'b1;
+ o_occupied <= 'd0;
+ o_space <= 'd0;
+ end else begin
+ if ((rd_addr+1'b1 == wr_addr_sync) & o_tready & o_tvalid) begin
+ o_tvalid <= 1'b0;
+ o_empty <= 1'b1;
+ end else if ((rd_addr != wr_addr_sync) & o_empty) begin
+ o_tvalid <= 1'b1;
+ o_empty <= 1'b0;
+ end
+ if ((rd_addr == wr_addr_sync) & ~o_empty & ~o_tready) begin
+ o_full <= 1'b1;
+ end else begin
+ o_full <= 1'b0;
+ end
+ if (o_tready) begin
+ if (wr_addr_sync == rd_addr) begin
+ if (~o_empty) begin
+ o_occupied <= (1'b1 << FIFOSIZE) - 1'b1;
+ o_space <= 'd1;
+ end else begin
+ o_occupied <= 'd0;
+ o_space <= (1'b1 << FIFOSIZE);
+ end
+ end else if (wr_addr_sync > rd_addr) begin
+ o_occupied <= wr_addr_sync - rd_addr - 1'b1;
+ o_space <= (1'b1 << FIFOSIZE) - (wr_addr_sync - rd_addr - 1'b1);
+ end else begin
+ o_occupied <= wr_addr_sync+1'b1 + (1'b1 << FIFOSIZE)-1'b1 - rd_addr - 1'b1;
+ o_space <= rd_addr - wr_addr_sync + 1'b1;
+ end
+ end else begin
+ if (wr_addr_sync == rd_addr) begin
+ if (~o_empty) begin
+ o_occupied <= 1'b1 << FIFOSIZE;
+ o_space <= 'd0;
+ end else begin
+ o_occupied <= 'd0;
+ o_space <= 1'b1 << FIFOSIZE;
+ end
+ end else if (wr_addr_sync > rd_addr) begin
+ o_occupied <= wr_addr_sync - rd_addr;
+ o_space <= (1'b1 << FIFOSIZE) - (wr_addr_sync - rd_addr);
+ end else begin
+ o_occupied <= wr_addr_sync+1'b1 + (1'b1 << FIFOSIZE)-1'b1 - rd_addr;
+ o_space <= rd_addr - wr_addr_sync;
+ end
+ end
+ end
+ end
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/fifo/axi_fifo_32_64/axi_fifo_32_64_tb.v b/fpga/usrp3/lib/sim/fifo/axi_fifo_32_64/axi_fifo_32_64_tb.v
new file mode 100644
index 000000000..b3acab3ca
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_fifo_32_64/axi_fifo_32_64_tb.v
@@ -0,0 +1,121 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+`timescale 1ns/1ps
+
+module axi_fifo_32_64_tb();
+
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("axi_fifo_32_64_tb.vcd");
+ initial $dumpvars(0,axi_fifo_32_64_tb);
+
+ task send_packet;
+ input [63:0] data_start;
+ input [2:0] user;
+ input [31:0] len;
+
+ begin
+ @(posedge clk);
+ {i_tuser, i_tlast, i_tdata} <= { 3'd0, 1'b0, data_start };
+ repeat(len-1)
+ begin
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
+ end
+ i_tuser <= user;
+ i_tlast <= 1;
+ @(posedge clk);
+ i_tvalid <= 1'b0;
+ @(posedge clk);
+ end
+ endtask // send_packet
+
+ initial
+ begin
+ #1000 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ reg [63:0] i_tdata;
+ reg [2:0] i_tuser;
+ reg i_tlast;
+ reg i_tvalid;
+ wire i_tready;
+
+ wire [63:0] i_tdata_int;
+ wire [2:0] i_tuser_int;
+ wire i_tlast_int, i_tvalid_int, i_tready_int;
+
+ wire [63:0] o_tdata;
+ wire [31:0] o_tdata_int, o_tdata_int2;
+ wire [2:0] o_tuser;
+ wire [1:0] o_tuser_int, o_tuser_int2;
+ wire o_tlast, o_tlast_int, o_tvalid, o_tvalid_int, o_tready, o_tready_int;
+ wire o_tlast_int2, o_tvalid_int2, o_tready_int2;
+
+ localparam RPT_COUNT = 16;
+
+ initial
+ begin
+ i_tvalid <= 0;
+
+ while(reset)
+ @(posedge clk);
+ @(posedge clk);
+
+ send_packet(64'hA0000000_A0000001, 3'd7, 4);
+ @(posedge clk);
+ end // initial begin
+
+ axi_fifo #(.WIDTH(68), .SIZE(10)) fifo
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({i_tlast,i_tuser,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata({i_tlast_int,i_tuser_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int));
+
+ axi_fifo64_to_fifo32 dut
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata(i_tdata_int), .i_tuser(i_tuser_int), .i_tlast(i_tlast_int), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
+ .o_tdata(o_tdata_int), .o_tuser(o_tuser_int), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));
+
+ /*
+ axi_fifo #(.WIDTH(35), .SIZE(10)) fifo_middle
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({o_tlast_int,o_tuser_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
+ .o_tdata({o_tlast_int2,o_tuser_int2,o_tdata_int2}), .o_tvalid(o_tvalid_int2), .o_tready(o_tready_int2));
+*/
+ assign o_tdata_int2 = o_tdata_int;
+ assign o_tlast_int2 = o_tlast_int;
+ assign o_tuser_int2 = o_tuser_int;
+ assign o_tvalid_int2 = o_tvalid_int;
+ assign o_tready_int = o_tready_int2;
+
+ axi_fifo32_to_fifo64 dut2
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata(o_tdata_int2), .i_tuser(o_tuser_int2), .i_tlast(o_tlast_int2), .i_tvalid(o_tvalid_int2), .i_tready(o_tready_int2),
+ .o_tdata(o_tdata), .o_tuser(o_tuser), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
+
+ assign o_tready = 1'b1;
+
+ always @(posedge clk)
+ if(i_tvalid & i_tready)
+ $display("IN: TUSER %x\tTLAST %x\tTDATA %x", i_tuser, i_tlast, i_tdata);
+
+ always @(posedge clk)
+ if(o_tvalid_int & o_tready_int)
+ $display("\t\t\t\t\t\tMIDDLE: TUSER %x\tTLAST %x\tTDATA %x", o_tuser_int, o_tlast_int, o_tdata_int);
+
+ always @(posedge clk)
+ if(o_tvalid & o_tready)
+ $display("\t\t\t\t\t\t\t\t\t\t\tOUT: TUSER %x\tTLAST %x\tTDATA %x", o_tuser, o_tlast, o_tdata);
+
+endmodule // axi_fifo_32_64_tb
diff --git a/fpga/usrp3/lib/sim/fifo/axi_packet_gate/axi_packet_gate_tb.v b/fpga/usrp3/lib/sim/fifo/axi_packet_gate/axi_packet_gate_tb.v
new file mode 100644
index 000000000..9df01baf0
--- /dev/null
+++ b/fpga/usrp3/lib/sim/fifo/axi_packet_gate/axi_packet_gate_tb.v
@@ -0,0 +1,112 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module axi_packet_gate_tb();
+
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("axi_packet_gate_tb.vcd");
+ initial $dumpvars(0,axi_packet_gate_tb);
+
+ task send_packet;
+ input [63:0] data_start;
+ input [2:0] user;
+ input [31:0] len;
+ input error;
+
+ begin
+ // Send a packet
+ @(posedge clk);
+ {i_terror, i_tuser, i_tlast, i_tdata} <= { 1'b0, user, 1'b0, data_start };
+ repeat(len-1)
+ begin
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tdata <= i_tdata + 1;
+ end
+ i_tlast <= 1;
+ i_terror <= error;
+ i_tdata <= i_tdata + 1;
+ @(posedge clk);
+ i_tvalid <= 1'b0;
+
+ @(posedge clk);
+ end
+ endtask // send_packet
+
+
+ initial
+ begin
+ #1000 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ wire [63:0] o_tdata;
+ reg [63:0] i_tdata;
+ wire [2:0] o_tuser;
+ reg [2:0] i_tuser;
+ reg i_tlast;
+ wire o_tlast;
+ wire o_tvalid, i_tready;
+ reg i_tvalid, o_tready;
+ reg i_terror;
+
+ localparam RPT_COUNT = 16;
+
+ initial
+ begin
+ i_tvalid <= 0;
+ o_tready <= 0;
+
+ while(reset)
+ @(posedge clk);
+ @(posedge clk);
+
+ send_packet(64'hA0,3'd0, 16, 0);
+ send_packet(64'hB0,3'd0, 16, 0);
+ o_tready <= 1;
+ send_packet(64'hC0,3'd0, 16, 1);
+ send_packet(64'hD0,3'd0, 16, 0);
+ send_packet(64'hE0,3'd0, 16, 0);
+ send_packet(64'hF0,3'd0, 16, 0);
+
+ @(posedge clk);
+
+ end // initial begin
+
+ wire i_terror_int, i_tlast_int, i_tready_int, i_tvalid_int;
+ wire [2:0] i_tuser_int;
+ wire [63:0] i_tdata_int;
+ wire o_tlast_int, o_tready_int, o_tvalid_int;
+ wire [2:0] o_tuser_int;
+ wire [63:0] o_tdata_int;
+
+ axi_fifo #(.WIDTH(69), .SIZE(10)) fifo
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({i_terror,i_tlast,i_tuser,i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata({i_terror_int,i_tlast_int,i_tuser_int,i_tdata_int}), .o_tvalid(i_tvalid_int), .o_tready(i_tready_int));
+
+ axi_packet_gate #(.WIDTH(67), .SIZE(10)) dut
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({i_tuser_int,i_tdata_int}), .i_terror(i_terror_int), .i_tlast(i_tlast_int), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int),
+ .o_tdata({o_tuser_int,o_tdata_int}), .o_tlast(o_tlast_int), .o_tvalid(o_tvalid_int), .o_tready(o_tready_int));
+
+ axi_fifo #(.WIDTH(68), .SIZE(10)) fifo_out
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({o_tlast_int,o_tuser_int,o_tdata_int}), .i_tvalid(o_tvalid_int), .i_tready(o_tready_int),
+ .o_tdata({o_tlast,o_tuser,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready));
+
+ always @(posedge clk)
+ if(o_tvalid & o_tready)
+ $display("TUSER %x\tTLAST %x\tTDATA %x",o_tuser,o_tlast, o_tdata);
+
+endmodule // axi_packet_gate_tb
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/Makefile b/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/Makefile
new file mode 100644
index 000000000..d80b63901
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/Makefile
@@ -0,0 +1,53 @@
+#
+# Copyright 2015 Ettus Research LLC
+# Copyright 2016 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_preamble after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# Design Specific
+#-------------------------------------------------
+# Define part using PART_ID (<device>/<package>/<speedgrade>)
+ARCH = kintex7
+PART_ID = xc7k410t/ffg900/-2
+
+include $(BASE_DIR)/../lib/control/Makefile.srcs
+
+DESIGN_SRCS = $(abspath \
+$(CONTROL_LIB_SRCS) \
+)
+
+DESIGN_SRCS += $(abspath \
+../../../io_cap_gen/cap_pattern_verifier.v \
+)
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+include $(BASE_DIR)/../sim/general/Makefile.srcs
+include $(BASE_DIR)/../sim/axi/Makefile.srcs
+
+# Define only one toplevel module
+SIM_TOP = cap_pattern_verifier_tb
+
+SIM_SRCS = \
+$(abspath cap_pattern_verifier_tb.sv) \
+$(SIM_GENERAL_SRCS) \
+$(SIM_AXI_SRCS)
+
+#-------------------------------------------------
+# 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/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/cap_pattern_verifier_tb.sv b/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/cap_pattern_verifier_tb.sv
new file mode 100644
index 000000000..53aae3719
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/cap_pattern_verifier/cap_pattern_verifier_tb.sv
@@ -0,0 +1,199 @@
+//
+// Copyright 2015 Ettus Research LLC
+// Copyright 2015 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+//
+
+
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 10
+
+`include "sim_clks_rsts.vh"
+`include "sim_exec_report.vh"
+`include "sim_axis_lib.svh"
+
+
+module cap_pattern_verifier_tb();
+ `TEST_BENCH_INIT("cap_pattern_verifier_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ // Define all clocks and resets
+ `DEFINE_CLK(clk, 5, 50) //100MHz sys_clk to generate DDR3 clocking
+ `DEFINE_RESET(rst, 0, 100) //100ns for GSR to deassert
+
+ axis_master data0 (.clk(clk));
+ axis_master data1 (.clk(clk));
+ assign data0.axis.tready = 1;
+ assign data1.axis.tready = 1;
+
+ wire [31:0] count0, errors0, count1, errors1;
+ wire locked0, failed0, locked1, failed1;
+
+ cap_pattern_verifier #(
+ .WIDTH(14),
+ .PATTERN("RAMP"),
+ .RAMP_START(14'h0000),
+ .RAMP_STOP(14'h3FFF),
+ .RAMP_INCR(14'h0001),
+ .NTH_CYCLE(1)
+ ) dut0 (
+ .clk(clk),
+ .rst(rst),
+ .valid(data0.axis.tvalid),
+ .data(data0.axis.tdata[13:0]),
+ .count(count0),
+ .errors(errors0),
+ .locked(locked0),
+ .failed(failed0)
+ );
+
+ cap_pattern_verifier #(
+ .WIDTH(14),
+ .PATTERN("RAMP"),
+ .RAMP_START(14'h0100),
+ .RAMP_STOP(14'h0FFF),
+ .RAMP_INCR(14'h0001),
+ .NTH_CYCLE(1)
+ ) dut1 (
+ .clk(clk),
+ .rst(rst),
+ .valid(data1.axis.tvalid),
+ .data(data1.axis.tdata[13:0]),
+ .count(count1),
+ .errors(errors1),
+ .locked(locked1),
+ .failed(failed1)
+ );
+
+ //------------------------------------------
+ //Main thread for testbench execution
+ //------------------------------------------
+ initial begin : tb_main
+ localparam ASYNC_RST_LEN = 10;
+ localparam OUTPUT_LATENCY = 2;
+
+ `TEST_CASE_START("Wait for reset");
+ while (rst) @(posedge clk);
+ @(posedge clk);
+ `TEST_CASE_DONE((rst==0));
+
+ repeat (10) @(posedge clk);
+
+ `TEST_CASE_START("Check reset state");
+ `ASSERT_ERROR(count0==0,"Invalid state: count");
+ `ASSERT_ERROR(errors0==0,"Invalid state: errors");
+ `ASSERT_ERROR(~locked0,"Invalid state: locked");
+ `ASSERT_ERROR(~failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Simple ramp");
+ data0.push_ramp_pkt(100, 64'd0, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==100,"Invalid state: count");
+ `ASSERT_ERROR(errors0==0,"Invalid state: errors");
+ `ASSERT_ERROR(locked0,"Invalid state: locked");
+ `ASSERT_ERROR(~failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ rst <= 1;
+ @(posedge clk);
+ rst <= 0;
+ repeat (ASYNC_RST_LEN) @(posedge clk);
+
+ `TEST_CASE_START("Multiple ramp iterations");
+ data0.push_ramp_pkt(65536, 64'd0, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==65536,"Invalid state: count");
+ `ASSERT_ERROR(errors0==0,"Invalid state: errors");
+ `ASSERT_ERROR(locked0,"Invalid state: locked");
+ `ASSERT_ERROR(~failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ #(`NS_PER_TICK*0.3333)
+ rst <= 1;
+ #(`NS_PER_TICK*3.25)
+ rst <= 0;
+ repeat (ASYNC_RST_LEN+1) @(posedge clk);
+
+ `TEST_CASE_START("Simple ramp after async reset");
+ data0.push_ramp_pkt(100, 64'd0, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==100,"Invalid state: count");
+ `ASSERT_ERROR(errors0==0,"Invalid state: errors");
+ `ASSERT_ERROR(locked0,"Invalid state: locked");
+ `ASSERT_ERROR(~failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ rst <= 1;
+ @(posedge clk);
+ rst <= 0;
+ repeat (ASYNC_RST_LEN) @(posedge clk);
+
+ `TEST_CASE_START("Simple failure");
+ data0.push_ramp_pkt(9, 64'd0, 64'h1);
+ data0.push_ramp_pkt(100, 64'd10, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==109,"Invalid state: count");
+ `ASSERT_ERROR(errors0==1,"Invalid state: errors");
+ `ASSERT_ERROR(locked0,"Invalid state: locked");
+ `ASSERT_ERROR(failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Late start success");
+ data1.push_ramp_pkt(4096, 64'd0, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count1==4096-256,"Invalid state: count");
+ `ASSERT_ERROR(errors1==0,"Invalid state: errors");
+ `ASSERT_ERROR(locked1,"Invalid state: locked");
+ `ASSERT_ERROR(~failed1,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ rst <= 1;
+ @(posedge clk);
+ rst <= 0;
+ repeat (ASYNC_RST_LEN) @(posedge clk);
+
+ `TEST_CASE_START("Late failure overshoot");
+ data1.push_ramp_pkt(4097, 64'd0, 64'h1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count1==4097-256,"Invalid state: count");
+ `ASSERT_ERROR(errors1==1,"Invalid state: errors");
+ `ASSERT_ERROR(locked1,"Invalid state: locked");
+ `ASSERT_ERROR(failed1,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Metastable data in reset");
+ @(posedge clk);
+ rst <= 1;
+ data0.push_word(14'hXXXX, 1'b0);
+ data0.push_word(14'hXXXX, 1'b1);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==0,"Invalid state: count");
+ `ASSERT_ERROR(errors0==0,"Invalid state: errors");
+ `ASSERT_ERROR(~locked0,"Invalid state: locked");
+ `ASSERT_ERROR(~failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ `TEST_CASE_START("Metastable data out of reset");
+ rst <= 0;
+ repeat (ASYNC_RST_LEN) @(posedge clk);
+ data0.push_word(14'h0000, 1'b0);
+ data0.push_word(14'h0001, 1'b0);
+ data0.push_word(14'h0002, 1'b0);
+ data0.push_word(14'hXXXX, 1'b0);
+ data0.push_word(14'hXXXX, 1'b0);
+ data0.push_word(14'h0005, 1'b0);
+ repeat (OUTPUT_LATENCY) @(posedge clk);
+ `ASSERT_ERROR(count0==6,"Invalid state: count");
+ `ASSERT_ERROR(errors0==2,"Invalid state: errors");
+ `ASSERT_ERROR(locked0,"Invalid state: locked");
+ `ASSERT_ERROR(failed0,"Invalid state: failed");
+ `TEST_CASE_DONE(1);
+
+ `TEST_BENCH_DONE;
+
+ end
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_dual_mode_tb.v b/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_dual_mode_tb.v
new file mode 100644
index 000000000..ecb744086
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_dual_mode_tb.v
@@ -0,0 +1,780 @@
+//
+// Copyright 2016 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: cat_io_lvds_dual_mode_tb
+//
+// Description: Testbench for cat_io_lvds_dual_mode.
+//
+
+`timescale 1ns/1ps
+
+module cat_io_lvds_dual_mode_tb();
+
+ localparam CLK_PERIOD = 10;
+ localparam CLK200_PERIOD = 2.5;
+
+ localparam USE_CLOCK_IDELAY = 1;
+ localparam USE_DATA_IDELAY = 1;
+ localparam DATA_IDELAY_MODE = "FIXED";
+ localparam CLOCK_IDELAY_MODE = "FIXED";
+ localparam INPUT_CLOCK_DELAY = 16;
+ localparam INPUT_DATA_DELAY = 0;
+ localparam USE_CLOCK_ODELAY = 1;
+ localparam USE_DATA_ODELAY = 1;
+ localparam DATA_ODELAY_MODE = "FIXED";
+ localparam CLOCK_ODELAY_MODE = "FIXED";
+ localparam OUTPUT_CLOCK_DELAY = 31;
+ localparam OUTPUT_DATA_DELAY = 0;
+
+ reg [8*19:0] test_status;
+ reg check_enabled; // Controls when output checking is performed
+
+ reg clk = 0;
+ reg rx_clk = 0;
+ reg clk200 = 0;
+
+ reg reset;
+ reg mimo;
+ reg tx_ch;
+ reg [5:0] rx_d;
+ reg rx_frame;
+ reg [7:0] rx_count = 0;
+
+ // Each channel's data begins with a unique identifier (A../B.. or C../D..)
+ // followed by a count, which should always be sequential.
+ wire [11:0] i0 = { 4'hA, rx_count };
+ wire [11:0] q0 = { 4'hB, rx_count };
+ wire [11:0] i1 = { 4'hC, rx_count };
+ wire [11:0] q1 = { 4'hD, rx_count };
+
+ wire radio_clk;
+
+ reg [11:0] tx_i0;
+ reg [11:0] tx_q0;
+ reg [11:0] tx_i1;
+ reg [11:0] tx_q1;
+
+ wire [11:0] rx_i0;
+ wire [11:0] rx_q0;
+ wire [11:0] rx_i1;
+ wire [11:0] rx_q1;
+
+ wire rx_aligned;
+
+ wire tx_clk_p, tx_clk_n;
+ wire tx_frame_p, tx_frame_n;
+ wire [5:0] tx_d_p, tx_d_n;
+
+ reg [4:0] ctrl_in_data_delay;
+ reg [4:0] ctrl_in_clk_delay;
+ reg ctrl_ld_in_data_delay;
+ reg ctrl_ld_in_clk_delay;
+
+ reg [4:0] ctrl_out_data_delay;
+ reg [4:0] ctrl_out_clk_delay;
+ reg ctrl_ld_out_data_delay;
+ reg ctrl_ld_out_clk_delay;
+
+
+ //---------------------------------------------------------------------------
+ // Clock Generation
+ //---------------------------------------------------------------------------
+
+ // IODELAYCTRL reference clock
+ always #(CLK200_PERIOD) clk200 = ~clk200;
+
+ // Create an internal clock we'll use to drive the data
+ always #(CLK_PERIOD) clk = ~clk;
+
+ // RF interface clock. Half the rate of clk and out of phase
+ always @(negedge clk) rx_clk <= ~rx_clk;
+
+
+ //---------------------------------------------------------------------------
+ // Tasks
+ //---------------------------------------------------------------------------
+
+ // Output a single burst of 2*len samples. In MIMO mode, this consists of len
+ // samples on each channel. In SISO mode, this consists of 2*len samples on
+ // the same channel.
+ task Burst;
+ input [31:0] len;
+ input do_mimo;
+ begin
+ repeat(len)
+ begin
+ mimo <= do_mimo;
+
+ // Channel 0 sample
+ @(posedge clk);
+ rx_d <= i0[11:6];
+ rx_frame <= 1;
+ @(posedge clk);
+ rx_d <= q0[11:6];
+ rx_frame <= 1;
+ @(posedge clk);
+ rx_d <= i0[5:0];
+ rx_frame <= do_mimo;
+ @(posedge clk);
+ rx_d <= q0[5:0];
+ rx_frame <= do_mimo;
+
+ // Channel 1 sample / Second channel 0 sample
+ @(posedge clk);
+ rx_d <= i1[11:6];
+ rx_frame <= ~do_mimo;
+ @(posedge clk);
+ rx_d <= q1[11:6];
+ rx_frame <= ~do_mimo;
+ @(posedge clk);
+ rx_d <= i1[5:0];
+ rx_frame <= 0;
+ @(posedge clk);
+ rx_d <= q1[5:0];
+ rx_frame <= 0;
+
+ rx_count <= rx_count + 1;
+ end
+ end
+ endtask // Burst
+
+
+ // Test receiving/transmitting 2*len samples, checking len-2 for correctness.
+ // The output is checked by the Tx and Rx Output Checkers below. We have to
+ // be a little bit careful when we enable output checking, because it takes a
+ // few clock cycles for data to propagate through, and we don't want to check
+ // the outputs when the outputs are not valid.
+ task TestBurst;
+ input [31:0] len;
+ input do_mimo;
+ begin
+ if (len <= 2) begin
+ $display("ERROR @%0t in %m: In TestBurst, len must be > 2", $time);
+ $finish;
+ end
+
+ // Input several bursts, to fill the pipeline and cause results on the
+ // outputs before we start checking.
+ Burst(1, do_mimo);
+
+ // Enable output checking
+ check_enabled <= 1'b1;
+
+ // Do the requested length, minus 1
+ Burst(len-2, do_mimo);
+
+ // Disable output checking
+ check_enabled <= 1'b0;
+
+ // Give an extra output to allow data to propagate to the output
+ Burst(1, do_mimo);
+ end
+ endtask // TestBurst
+
+
+ //---------------------------------------------------------------------------
+ // Test Procedure
+ //---------------------------------------------------------------------------
+
+ initial
+ begin
+ // Initial values
+ check_enabled <= 1'b0;
+ test_status <= "Reset";
+ reset = 1;
+ mimo = 1;
+ ctrl_in_clk_delay = INPUT_CLOCK_DELAY;
+ ctrl_in_data_delay = INPUT_DATA_DELAY;
+ ctrl_ld_in_data_delay = 1'b0;
+ ctrl_ld_in_clk_delay = 1'b0;
+ ctrl_out_clk_delay = OUTPUT_CLOCK_DELAY;
+ ctrl_out_data_delay = OUTPUT_DATA_DELAY;
+ ctrl_ld_out_data_delay = 1'b0;
+ ctrl_ld_out_clk_delay = 1'b0;
+ repeat(10) @(negedge rx_clk);
+ reset = 0;
+ @(negedge rx_clk);
+
+ //-----------------------------------------------------------------------
+ // Test Changing Delays
+
+ test_status <= "Load IO delays";
+
+ if (CLOCK_IDELAY_MODE == "VAR_LOAD") begin
+ ctrl_ld_in_clk_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_in_clk_delay = 1'b0;
+ @(negedge rx_clk);
+ end
+
+ if (DATA_IDELAY_MODE == "VAR_LOAD") begin
+ ctrl_ld_in_data_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_in_data_delay = 1'b0;
+ @(negedge rx_clk);
+ end
+
+ if (CLOCK_ODELAY_MODE == "VAR_LOAD") begin
+ ctrl_ld_out_clk_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_out_clk_delay = 1'b0;
+ @(negedge rx_clk);
+ end
+
+ if (DATA_ODELAY_MODE == "VAR_LOAD") begin
+ ctrl_ld_out_data_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_out_data_delay = 1'b0;
+ @(negedge rx_clk);
+ end
+
+ //-----------------------------------------------------------------------
+ // Startup
+
+ test_status <= "Startup";
+
+ // Pump a few clock cycles to get things started (flush out X values)
+ Burst(2,1);
+
+ //-----------------------------------------------------------------------
+ // Test MIMO
+
+ // Input data until the Rx circuit aligns
+ test_status <= "Wait align 1";
+ while (!rx_aligned) begin
+ Burst(1,1);
+ end
+
+ // Input some new samples
+ test_status <= "Burst 1 (MIMO)";
+ TestBurst(30, 1);
+
+ // Reset and do another burst
+ test_status <= "Reset 2";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns
+ test_status <= "Wait align 2";
+ while (!rx_aligned) begin
+ Burst(1,1);
+ end
+
+ // Input some new samples
+ test_status <= "Burst 2 (MIMO)";
+ TestBurst(23, 1);
+
+ //-----------------------------------------------------------------------
+ // Test SISO (transmit channel 0)
+
+ tx_ch <= 1'b0;
+
+ // Reset and do another burst
+ test_status <= "Reset 3";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns in SISO mode
+ test_status <= "Wait align 3";
+ while (!rx_aligned) begin
+ Burst(1,0);
+ end
+
+ // Test SISO mode
+ test_status <= "Burst 3 (SISO, Ch 0)";
+ TestBurst(25, 0);
+
+ // Reset and do another burst
+ test_status <= "Reset 4";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns in SISO mode
+ test_status <= "Wait align 4";
+ while (!rx_aligned) begin
+ Burst(1,0);
+ end
+
+ // Test SISO mode
+ test_status <= "Burst 4 (SISO, Ch 0)";
+ TestBurst(27, 0);
+
+ //-----------------------------------------------------------------------
+ // Test SISO (transmit channel 1)
+
+ tx_ch <= 1'b1;
+
+ // Reset and do another burst
+ test_status <= "Reset 5";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns in SISO mode
+ test_status <= "Wait align 5";
+ while (!rx_aligned) begin
+ Burst(1,0);
+ end
+
+ // Test SISO mode
+ test_status <= "Burst 5 (SISO, Ch 1)";
+ TestBurst(25, 0);
+
+ // Reset and do another burst
+ test_status <= "Reset 6";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns in SISO mode
+ test_status <= "Wait align 6";
+ while (!rx_aligned) begin
+ Burst(1,0);
+ end
+
+ // Test SISO mode
+ test_status <= "Burst 6 (SISO, Ch 1)";
+ TestBurst(27, 0);
+
+ //-----------------------------------------------------------------------
+ // Done
+
+ test_status <= "Finished";
+ repeat(50) @(negedge rx_clk);
+
+ $finish;
+ end
+
+
+ //---------------------------------------------------------------------------
+ // Rx Output Checker
+ //---------------------------------------------------------------------------
+ //
+ // In MIMO mode, we expect to see:
+ //
+ // rx_i0: A00, A01, A02, A03, ...
+ // rx_q0: B00, B01, B02, B03, ...
+ // rx_i1: C00, C01, C02, C03, ...
+ // rx_q1: D00, D01, D02, D03, ...
+ //
+ // In SISO mode, we expect to see (with twice the clock rate):
+ //
+ // rx_i0: A00, C00, A01, C01, ...
+ // rx_q0: B00, D00, B01, D01, ...
+ // rx_i1: A00, C00, A01, C01, ...
+ // rx_q1: B00, D00, B01, D01, ...
+ //
+ //---------------------------------------------------------------------------
+
+ reg first_rx_check = 1'b1;
+ reg [11:0] rx_i0_del1, rx_i0_del2;
+ reg [11:0] rx_q0_del1, rx_q0_del2;
+ reg [11:0] rx_i1_del1, rx_i1_del2;
+ reg [11:0] rx_q1_del1, rx_q1_del2;
+
+ always @(posedge radio_clk)
+ begin
+ if (check_enabled) begin
+ if (!first_rx_check) begin
+
+ if (mimo) begin
+
+ // Check prefix for channel 0
+ if (rx_i0[11:8] != 4'hA || rx_q0[11:8] != 4'hB) begin
+ $display("ERROR @%0t in %m: Rx channel 0 didn't have expected A/B prefix in MIMO mode", $time);
+ $finish;
+ end
+
+ // Check prefix for channel 1
+ if (rx_i1[11:8] != 4'hC || rx_q1[11:8] != 4'hD) begin
+ $display("ERROR @%0t in %m: Rx channel 1 didn't have expected C/D in MIMO mode", $time);
+ $finish;
+ end
+
+ // All outputs should have the same count in MIMO mode
+ if (! (rx_i0[7:0] == rx_q0[7:0] &&
+ rx_i0[7:0] == rx_i1[7:0] &&
+ rx_i0[7:0] == rx_q1[7:0]) ) begin
+ $display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in MIMO mode", $time);
+ $finish;
+ end
+
+ // Make sure the count increments
+ if (rx_i0[7:0] != rx_i0_del1[7:0] + 8'd1 || rx_q0[7:0] != rx_q0_del1[7:0] + 8'd1 ||
+ rx_i1[7:0] != rx_i1_del1[7:0] + 8'd1 || rx_q1[7:0] != rx_q1_del1[7:0] + 8'd1) begin
+ $display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
+ $finish;
+ end
+
+ end else begin // if (mimo)
+
+ // In SISO mode, both outputs should be the same
+ if (rx_i0 != rx_i1 || rx_q0 != rx_q1) begin
+ $display("ERROR @%0t in %m: Rx channel 0 and 1 don't match in SISO mode", $time);
+ $finish;
+ end
+
+ // Check channel 0 prefix. No need to check channel 1, since we
+ // already checked that the channels match.
+ if (!((rx_i0[11:8] == 4'hA && rx_q0[11:8] == 4'hB) ||
+ (rx_i0[11:8] == 4'hC && rx_q0[11:8] == 4'hD))) begin
+ $display("ERROR @%0t in %m: Rx data didn't have expected A/B or C/D prefix in SISO mode", $time);
+ $finish;
+ end
+
+ // Make sure we're alternating between channel data. No need to check
+ // channel 1, since we already checked that the channels match.
+ if (!((rx_i0[11:8] == 4'hA && rx_i0_del1[11:8] == 4'hC) ||
+ (rx_i0[11:8] == 4'hC && rx_i0_del1[11:8] == 4'hA) ||
+ (rx_q0[11:8] == 4'hB && rx_q0_del1[11:8] == 4'hD) ||
+ (rx_q0[11:8] == 4'hD && rx_q0_del1[11:8] == 4'hB))) begin
+ $display("ERROR @%0t in %m: Rx data not toggling between channel data in SISO mode", $time);
+ $finish;
+ end
+
+ // Make sure the counts are the same for both I and Q. No need to
+ // check channel 1, since we already checked that the channels match.
+ if (rx_i0[7:0] != rx_q0[7:0]) begin
+ $display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in SISO mode", $time);
+ $finish;
+ end
+
+ // Make sure the count increments every other clock cycle. No need to
+ // check channel 1, since we already checked that the channels match.
+ if (!(
+ rx_i0[7:0] != rx_i0_del2[7:0] + 8'd1 && (rx_i0[7:0] == rx_i0_del1[7:0] || rx_i0[7:0] == rx_i0_del1[7:0] + 8'd1) &&
+ rx_q0[7:0] != rx_q0_del2[7:0] + 8'd1 && (rx_q0[7:0] == rx_q0_del1[7:0] || rx_q0[7:0] == rx_q0_del1[7:0] + 8'd1)
+ )) begin
+ $display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
+ $finish;
+ end
+
+ end // if (mimo)
+ end // if (!first_rx_check)
+
+ // Make sure we've captured at least one set of values, so we have a
+ // previous set to look back to.
+ first_rx_check <= 1'b0;
+
+ end else begin // if (check_enabled)
+ first_rx_check <= 1'b1;
+ end // if (check_enabled)
+
+ // Save values seen this cycle
+ rx_i0_del1 <= rx_i0;
+ rx_q0_del1 <= rx_q0;
+ rx_i1_del1 <= rx_i1;
+ rx_q1_del1 <= rx_q1;
+ rx_i0_del2 <= rx_i0_del2;
+ rx_q0_del2 <= rx_q0_del2;
+ rx_i1_del2 <= rx_i1_del2;
+ rx_q1_del2 <= rx_q1_del2;
+ end
+
+
+ //---------------------------------------------------------------------------
+ // Tx Output Checker
+ //---------------------------------------------------------------------------
+ //
+ // The code implements a loopback, so the output should match the input. In
+ // SISO mode, however, the frame signal may not be aligned.
+ //
+ //---------------------------------------------------------------------------
+
+ reg first_tx_check;
+ reg [11:0] tx_i0_del1;
+ reg [11:0] tx_q0_del1;
+ reg [11:0] tx_i1_del1;
+ reg [11:0] tx_q1_del1;
+ reg tx_frame_del1;
+
+ reg [11:0] tx_i0_check;
+ reg [11:0] tx_q0_check;
+ reg [11:0] tx_i1_check;
+ reg [11:0] tx_q1_check;
+ reg [7:0] tx_frame_check;
+
+
+ always @(posedge tx_clk_p)
+ begin
+ tx_frame_del1 <= tx_frame_p;
+ end
+
+
+ always @(posedge tx_clk_p)
+ begin
+ if (tx_frame_p && !tx_frame_del1) begin
+ //-----------------------------------------------------------------------
+ // Grab two samples from the output, starting at frame boundary
+ //-----------------------------------------------------------------------
+
+ // Channel 0 sample
+ tx_i0_check[11:6] <= tx_d_p;
+ tx_frame_check[7] <= tx_frame_p;
+ @(posedge tx_clk_n);
+ tx_q0_check[11:6] <= tx_d_p;
+ tx_frame_check[6] <= tx_frame_p;
+ @(posedge tx_clk_p);
+ tx_i0_check[5:0] <= tx_d_p;
+ tx_frame_check[5] <= tx_frame_p;
+ @(posedge tx_clk_n);
+ tx_q0_check[5:0] <= tx_d_p;
+ tx_frame_check[4] <= tx_frame_p;
+
+ // Channel 1 sample / Second channel 0 sample
+ @(posedge tx_clk_p);
+ tx_i1_check[11:6] <= tx_d_p;
+ tx_frame_check[3] <= tx_frame_p;
+ @(posedge tx_clk_n);
+ tx_q1_check[11:6] <= tx_d_p;
+ tx_frame_check[2] <= tx_frame_p;
+ @(posedge tx_clk_p);
+ tx_i1_check[5:0] <= tx_d_p;
+ tx_frame_check[1] <= tx_frame_p;
+ @(posedge tx_clk_n);
+ tx_q1_check[5:0] <= tx_d_p;
+ tx_frame_check[0] <= tx_frame_p;
+
+ #1 // Minimum delay for *_check registers to update in simulation
+
+ if (check_enabled) begin
+ if (!first_tx_check) begin
+
+ if (mimo) begin
+ //-----------------------------------------------------------------
+ // Check MIMO output
+ //-----------------------------------------------------------------
+
+ // Check that the frame signal is correct
+ if (tx_frame_check != 8'b11110000) begin
+ $display("ERROR @%0t in %m: Tx frame was not correct in MIMO mode", $time);
+ $finish;
+ end
+
+ // Check prefix for channel 0
+ if (tx_i0_check[11:8] != 4'hA || tx_q0_check[11:8] != 4'hB) begin
+ $display("ERROR @%0t in %m: Tx channel 0 didn't have expected A/B prefix in MIMO mode", $time);
+ $finish;
+ end
+
+ // Check prefix for channel 1
+ if (tx_i1_check[11:8] != 4'hC || tx_q1_check[11:8] != 4'hD) begin
+ $display("ERROR @%0t in %m: Tx channel 1 didn't have expected C/D in MIMO mode", $time);
+ $finish;
+ end
+
+ // All outputs should have the same count in MIMO mode
+ if (! (tx_i0_check[7:0] == tx_q0_check[7:0] &&
+ tx_i0_check[7:0] == tx_i1_check[7:0] &&
+ tx_i0_check[7:0] == tx_q1_check[7:0]) ) begin
+ $display("ERROR @%0t in %m: Rx data counts didn't match on all outputs in MIMO mode", $time);
+ $finish;
+ end
+
+ // Make sure the count increments
+ if (tx_i0_check[7:0] != tx_i0_del1[7:0] + 8'd1 || tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd1 ||
+ tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd1 || tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd1) begin
+ $display("ERROR @%0t in %m: Rx data count didn't increment as expected", $time);
+ $finish;
+ end
+
+ end else begin
+ //-----------------------------------------------------------------
+ // Check SISO Output
+ //-----------------------------------------------------------------
+
+ // Check that the frame signal is correct
+ if (tx_frame_check != 8'b11001100) begin
+ $display("ERROR @%0t in %m: Tx frame was not correct in SISO mode", $time);
+ $finish;
+ end
+
+
+ // In SISO mode, the data we get depends on which channel is
+ // selected.
+ //
+ // Channel 0: Channel 1:
+ // ...,A01,B01,A02,B02,... OR ...,C01,D01,C02,D02,...
+ //
+ // So we should receive
+ //
+ // A01 A03 A05
+ // ... B01 B03 B05 ...
+ // A02 B04 A06
+ // B02 B04 A07
+ //
+ // or
+ // C01 C03 C05
+ // ... D01 D03 D05 ...
+ // C02 C04 C06
+ // D02 D04 D07
+ //
+
+ // Check prefixes
+ if (!(
+ // Either A,B on channel 0 or C,D on channel 1
+ ((tx_ch == 0 &&
+ tx_i0_check[11:8] == 4'hA &&
+ tx_q0_check[11:8] == 4'hB) ||
+ (tx_ch == 1 &&
+ tx_i0_check[11:8] == 4'hC &&
+ tx_q0_check[11:8] == 4'hD)) &&
+ // Samples 0 and 1 prefixes equal samples 2 and 3 prefixes
+ (tx_i0_check[11:8] == tx_i1_check[11:8] &&
+ tx_q0_check[11:8] == tx_q1_check[11:8])
+ )) begin
+ $display("ERROR @%0t in %m: Tx channel didn't have expected prefixes in SISO mode", $time);
+ $finish;
+ end
+
+ // Check that the data count matches between samples
+ if (!(
+ tx_i0_check[7:0] == tx_q0_check[7:0] &&
+ tx_i1_check[7:0] == tx_q1_check[7:0] &&
+ tx_i0_check[7:0] == tx_i1_check[7:0] - 8'd1
+ )) begin
+ $display("ERROR @%0t in %m: Tx channel data counts didn't correlate in SISO mode", $time);
+ $finish;
+ end
+
+ // Make sure the count increments form one burst to the next
+ if (tx_i0_check[7:0] != tx_i0_del1[7:0] + 8'd2 ||
+ tx_q0_check[7:0] != tx_q0_del1[7:0] + 8'd2 ||
+ tx_i1_check[7:0] != tx_i1_del1[7:0] + 8'd2 ||
+ tx_q1_check[7:0] != tx_q1_del1[7:0] + 8'd2) begin
+ $display("ERROR @%0t in %m: Tx data count didn't increment as expected", $time);
+ $finish;
+ end
+
+ end
+
+ end else begin // if (!first_tx_check)
+ // Make sure we've captured at least one set of values, so we have a
+ // previous set to look back to.
+ first_tx_check <= 1'b0;
+ end // if (!first_tx_check)
+
+ // Save values seen this cycle
+ tx_i0_del1 <= tx_i0_check;
+ tx_q0_del1 <= tx_q0_check;
+ tx_i1_del1 <= tx_i1_check;
+ tx_q1_del1 <= tx_q1_check;
+
+ end else begin // if (check_enabled)
+ first_tx_check <= 1'b1;
+
+ end // if (check_enabled)
+
+ end // if (tx_frame_p && !tx_frame_del1)
+
+ end
+
+
+ //---------------------------------------------------------------------------
+ // Tx Input Data Generation
+ //---------------------------------------------------------------------------
+ //
+ // Input a known data pattern similar to the Rx patten.
+ //
+ // I0: A01 A02 A03
+ // Q0: ... B01 B02 B03 ...
+ // I1: C01 C02 C03
+ // Q1: D01 D02 D03
+ //
+ //---------------------------------------------------------------------------
+
+ reg [7:0] tx_count = 0;
+
+ // Loop the Rx interface of DUT back to its Tx interface
+ always @(posedge radio_clk) begin
+ tx_i0 <= { 4'hA, tx_count };
+ tx_q0 <= { 4'hB, tx_count };
+ tx_i1 <= { 4'hC, tx_count };
+ tx_q1 <= { 4'hD, tx_count };
+ tx_count <= tx_count + 7'd1;
+ end
+
+
+ //---------------------------------------------------------------------------
+ // DUT
+ //---------------------------------------------------------------------------
+
+ cat_io_lvds_dual_mode #(
+ .INVERT_FRAME_RX (0),
+ .INVERT_DATA_RX (6'b00_0000),
+ .INVERT_FRAME_TX (0),
+ .INVERT_DATA_TX (6'b00_0000),
+ .USE_CLOCK_IDELAY (USE_CLOCK_IDELAY),
+ .USE_DATA_IDELAY (USE_DATA_IDELAY),
+ .DATA_IDELAY_MODE (DATA_IDELAY_MODE),
+ .CLOCK_IDELAY_MODE (CLOCK_IDELAY_MODE),
+ .INPUT_CLOCK_DELAY (INPUT_CLOCK_DELAY),
+ .INPUT_DATA_DELAY (INPUT_DATA_DELAY),
+ .USE_CLOCK_ODELAY (USE_CLOCK_ODELAY),
+ .USE_DATA_ODELAY (USE_DATA_ODELAY),
+ .DATA_ODELAY_MODE (DATA_ODELAY_MODE),
+ .CLOCK_ODELAY_MODE (CLOCK_ODELAY_MODE),
+ .OUTPUT_CLOCK_DELAY (OUTPUT_CLOCK_DELAY),
+ .OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY)
+ ) cat_io_lvds_dual_mode_dut (
+ .rst (reset),
+ .clk200 (clk200),
+
+ // Data and frame timing
+ .a_mimo (mimo),
+ .a_tx_ch (tx_ch),
+
+ // Delay control interface
+ .ctrl_clk (rx_clk),
+ //
+ .ctrl_in_data_delay (ctrl_in_data_delay),
+ .ctrl_in_clk_delay (ctrl_in_clk_delay),
+ .ctrl_ld_in_data_delay (ctrl_ld_in_data_delay),
+ .ctrl_ld_in_clk_delay (ctrl_ld_in_clk_delay),
+ //
+ .ctrl_out_data_delay (ctrl_out_data_delay),
+ .ctrl_out_clk_delay (ctrl_out_clk_delay),
+ .ctrl_ld_out_data_delay (ctrl_ld_out_data_delay),
+ .ctrl_ld_out_clk_delay (ctrl_ld_out_clk_delay),
+
+ // Baseband sample interface
+ .radio_clk (radio_clk),
+ .rx_aligned (rx_aligned),
+ //
+ .rx_i0 (rx_i0),
+ .rx_q0 (rx_q0),
+ .rx_i1 (rx_i1),
+ .rx_q1 (rx_q1),
+ //
+ .tx_i0 (tx_i0),
+ .tx_q0 (tx_q0),
+ .tx_i1 (tx_i1),
+ .tx_q1 (tx_q1),
+
+ // Catalina interface
+ .rx_clk_p (rx_clk),
+ .rx_clk_n (~rx_clk),
+ .rx_frame_p (rx_frame),
+ .rx_frame_n (~rx_frame),
+ .rx_d_p (rx_d),
+ .rx_d_n (~rx_d),
+ //
+ .tx_clk_p (tx_clk_p),
+ .tx_clk_n (tx_clk_n),
+ .tx_frame_p (tx_frame_p),
+ .tx_frame_n (tx_frame_n),
+ .tx_d_p (tx_d_p),
+ .tx_d_n (tx_d_n)
+ );
+
+endmodule // cat_io_lvds_dual_mode_tb
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_tb.v b/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_tb.v
new file mode 100644
index 000000000..91cd6f938
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/cat_io_lvds/cat_io_lvds_tb.v
@@ -0,0 +1,350 @@
+//
+// Copyright 2016 Ettus Research, A National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+// Module: cat_io_lvds_tb
+//
+// Description: Testbench for cat_io_lvds.
+//
+
+`timescale 1ns/1ps
+
+module cat_io_lvds_tb();
+
+ localparam CLK_PERIOD = 10;
+ localparam CLK200_PERIOD = 2.5;
+
+ localparam FRAME_SAMPLE = 0;
+
+ localparam USE_CLOCK_IDELAY = 1;
+ localparam USE_DATA_IDELAY = 1;
+ localparam DATA_IDELAY_MODE = "VAR_LOAD";
+ localparam CLOCK_IDELAY_MODE = "VAR_LOAD";
+ localparam INPUT_CLOCK_DELAY = 0;
+ localparam INPUT_DATA_DELAY = 0;
+ localparam USE_CLOCK_ODELAY = 1;
+ localparam USE_DATA_ODELAY = 1;
+ localparam DATA_ODELAY_MODE = "VAR_LOAD";
+ localparam CLOCK_ODELAY_MODE = "VAR_LOAD";
+ localparam OUTPUT_CLOCK_DELAY = 0;
+ localparam OUTPUT_DATA_DELAY = 0;
+
+ reg [8*19:0] test_status;
+
+ reg clk = 0;
+ reg rx_clk = 0;
+ reg clk200 = 0;
+
+ reg reset;
+ reg mimo;
+ reg [5:0] rx_d;
+ reg rx_frame;
+ reg [7:0] count;
+
+// initial $dumpfile("catcap_ddr_lvds_tb.vcd");
+// initial $dumpvars(0,catcap_ddr_lvds_tb);
+
+ wire [11:0] i0 = {4'hA,count};
+ wire [11:0] q0 = {4'hB,count};
+ wire [11:0] i1 = {4'hC,count};
+ wire [11:0] q1 = {4'hD,count};
+
+ wire radio_clk;
+
+ reg [11:0] tx_i0;
+ reg [11:0] tx_q0;
+ reg [11:0] tx_i1;
+ reg [11:0] tx_q1;
+
+ wire [11:0] rx_i0;
+ wire [11:0] rx_q0;
+ wire [11:0] rx_i1;
+ wire [11:0] rx_q1;
+
+ wire rx_aligned;
+
+ wire tx_clk_p, tx_clk_n;
+ wire tx_frame_p, tx_frame_n;
+ wire [5:0] tx_d_p, tx_d_n;
+
+ reg [4:0] ctrl_in_data_delay;
+ reg [4:0] ctrl_in_clk_delay;
+ reg ctrl_ld_in_data_delay;
+ reg ctrl_ld_in_clk_delay;
+
+ reg [4:0] ctrl_out_data_delay;
+ reg [4:0] ctrl_out_clk_delay;
+ reg ctrl_ld_out_data_delay;
+ reg ctrl_ld_out_clk_delay;
+
+
+ //---------------------------------------------------------------------------
+ // Clock Generation
+ //---------------------------------------------------------------------------
+
+ // IODELAYCTRL reference clock
+ always #(CLK200_PERIOD) clk200 = ~clk200;
+
+ // Create an internal clock we'll use to drive the data
+ always #(CLK_PERIOD) clk = ~clk;
+
+ // RF interface clock. Half the rate of clk and out of phase
+ always @(negedge clk) rx_clk <= ~rx_clk;
+
+
+ //---------------------------------------------------------------------------
+ // Tasks
+ //---------------------------------------------------------------------------
+
+ task BURST;
+ input [31:0] len;
+ input do_mimo;
+ begin
+ count <= 0;
+ repeat(len)
+ begin
+ mimo <= do_mimo;
+
+ // Channel 0 sample
+ @(posedge clk);
+ rx_d <= i0[11:6];
+ rx_frame <= 1;
+ @(posedge clk);
+ rx_d <= q0[11:6];
+ rx_frame <= 1;
+ @(posedge clk);
+ rx_d <= i0[5:0];
+ rx_frame <= ~FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= q0[5:0];
+ rx_frame <= ~FRAME_SAMPLE;
+
+ if (do_mimo) begin
+ // Channel 1 sample
+ @(posedge clk);
+ rx_d <= i1[11:6];
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= q1[11:6];
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= i1[5:0];
+ rx_frame <= 0;
+ @(posedge clk);
+ rx_d <= q1[5:0];
+ rx_frame <= 0;
+ end else begin
+ if (!FRAME_SAMPLE) begin
+ // When we frame every two samples (one from each channel), in
+ // MIMO mode, we should only grab channel 0. So input garbage on
+ // channel 1 to make sure the data doesn't get used.
+ @(posedge clk);
+ rx_d <= 6'bXXXXXX;
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= 6'bXXXXXX;
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= 6'bXXXXXX;
+ rx_frame <= 0;
+ @(posedge clk);
+ rx_d <= 6'bXXXXXX;
+ rx_frame <= 0;
+ end else begin
+ // When every sample is framed, we might sync align to either
+ // channel (no way to tell them apart), so input the channel 1
+ // data, but we should only see one channel's data duplicated on
+ // both outputs.
+ @(posedge clk);
+ rx_d <= i1[11:6];
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= q1[11:6];
+ rx_frame <= FRAME_SAMPLE;
+ @(posedge clk);
+ rx_d <= i1[5:0];
+ rx_frame <= 0;
+ @(posedge clk);
+ rx_d <= q1[5:0];
+ rx_frame <= 0;
+ end
+ end
+
+ count <= count + 1;
+ end
+ end
+ endtask // BURST
+
+
+ //---------------------------------------------------------------------------
+ // Test Procedure
+ //---------------------------------------------------------------------------
+
+ initial
+ begin
+ // Initial values
+ test_status <= "Reset";
+ reset = 1;
+ mimo = 1;
+ ctrl_in_data_delay = 5'd0;
+ ctrl_in_clk_delay = 5'd8;
+ ctrl_ld_in_data_delay = 1'b0;
+ ctrl_ld_in_clk_delay = 1'b0;
+ ctrl_out_data_delay = 5'd0;
+ ctrl_out_clk_delay = 5'd16;
+ ctrl_ld_out_data_delay = 1'b0;
+ ctrl_ld_out_clk_delay = 1'b0;
+ repeat(10) @(negedge rx_clk);
+ reset = 0;
+ @(negedge rx_clk);
+
+ // Load new input delay values
+ test_status <= "Load input delays";
+ ctrl_ld_in_data_delay = 1'b1;
+ ctrl_ld_in_clk_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_in_data_delay = 1'b0;
+ ctrl_ld_in_clk_delay = 1'b0;
+
+ // Load new output delay values
+ test_status <= "Load output delays";
+ ctrl_ld_out_data_delay = 1'b1;
+ ctrl_ld_out_clk_delay = 1'b1;
+ @(negedge rx_clk);
+ ctrl_ld_out_data_delay = 1'b0;
+ ctrl_ld_out_clk_delay = 1'b0;
+
+ // Input data until the Rx circuit aligns
+ test_status <= "Wait align";
+ while (!rx_aligned) begin
+ BURST(1,1);
+ end
+
+ // Input some new samples
+ test_status <= "Burst 1 (MIMO)";
+ BURST(30, 1);
+
+ // Reset and do another burst
+ test_status <= "Reset 2";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns
+ test_status <= "Wait align 2";
+ while (!rx_aligned) begin
+ BURST(1,1);
+ end
+
+ // Input some new samples
+ test_status <= "Burst 2 (MIMO)";
+ BURST(30, 1);
+
+ // Reset and do another burst
+ test_status <= "Reset 3";
+ reset = 1;
+ repeat(20) @(negedge rx_clk);
+ reset = 0;
+ repeat(2) @(negedge rx_clk);
+
+ // Input data until the Rx circuit aligns in SISO mode
+ test_status <= "Wait align 3";
+ while (!rx_aligned) begin
+ BURST(1,0);
+ end
+
+ // Switch to SISO mode
+ test_status <= "Burst 3 (SISO)";
+ BURST(25,0);
+
+ repeat(50) @(negedge rx_clk);
+
+
+ $finish;
+ end
+
+
+ //---------------------------------------------------------------------------
+ // DUT
+ //---------------------------------------------------------------------------
+
+ // Loop the Rx interface of cat_io_lvds back to its Tx interface
+ always @(posedge radio_clk) begin
+ tx_i0 = rx_i0;
+ tx_q0 = rx_q0;
+ tx_i1 = rx_i1;
+ tx_q1 = rx_q1;
+ end
+
+ cat_io_lvds #(
+ .INVERT_FRAME_RX (0),
+ .INVERT_DATA_RX (6'b00_0000),
+ .INVERT_FRAME_TX (0),
+ .INVERT_DATA_TX (6'b00_0000),
+ .USE_CLOCK_IDELAY (USE_CLOCK_IDELAY ),
+ .USE_DATA_IDELAY (USE_DATA_IDELAY ),
+ .DATA_IDELAY_MODE (DATA_IDELAY_MODE ),
+ .CLOCK_IDELAY_MODE (CLOCK_IDELAY_MODE ),
+ .INPUT_CLOCK_DELAY (INPUT_CLOCK_DELAY ),
+ .INPUT_DATA_DELAY (INPUT_DATA_DELAY ),
+ .USE_CLOCK_ODELAY (USE_CLOCK_ODELAY ),
+ .USE_DATA_ODELAY (USE_DATA_ODELAY ),
+ .DATA_ODELAY_MODE (DATA_ODELAY_MODE ),
+ .CLOCK_ODELAY_MODE (CLOCK_ODELAY_MODE ),
+ .OUTPUT_CLOCK_DELAY (OUTPUT_CLOCK_DELAY),
+ .OUTPUT_DATA_DELAY (OUTPUT_DATA_DELAY )
+ ) cat_io_lvds_i0 (
+ .rst (reset),
+ .clk200 (clk200),
+
+ // Data and frame timing
+ .mimo (mimo),
+ .frame_sample (FRAME_SAMPLE[0]),
+
+ // Delay control interface
+ .ctrl_clk (rx_clk),
+ //
+ .ctrl_in_data_delay (ctrl_in_data_delay),
+ .ctrl_in_clk_delay (ctrl_in_clk_delay),
+ .ctrl_ld_in_data_delay (ctrl_ld_in_data_delay),
+ .ctrl_ld_in_clk_delay (ctrl_ld_in_clk_delay),
+ //
+ .ctrl_out_data_delay (ctrl_out_data_delay),
+ .ctrl_out_clk_delay (ctrl_out_clk_delay),
+ .ctrl_ld_out_data_delay (ctrl_ld_out_data_delay),
+ .ctrl_ld_out_clk_delay (ctrl_ld_out_clk_delay),
+
+ // Baseband sample interface
+ .radio_clk (radio_clk),
+ .radio_clk_2x (),
+ .rx_aligned (rx_aligned),
+ //
+ .rx_i0 (rx_i0),
+ .rx_q0 (rx_q0),
+ .rx_i1 (rx_i1),
+ .rx_q1 (rx_q1),
+ //
+ .tx_i0 (tx_i0),
+ .tx_q0 (tx_q0),
+ .tx_i1 (tx_i1),
+ .tx_q1 (tx_q1),
+
+ // Catalina interface
+ .rx_clk_p (rx_clk),
+ .rx_clk_n (~rx_clk),
+ .rx_frame_p (rx_frame),
+ .rx_frame_n (~rx_frame),
+ .rx_d_p (rx_d),
+ .rx_d_n (~rx_d),
+ //
+ .tx_clk_p (tx_clk_p),
+ .tx_clk_n (tx_clk_n),
+ .tx_frame_p (tx_frame_p),
+ .tx_frame_n (tx_frame_n),
+ .tx_d_p (tx_d_p),
+ .tx_d_n (tx_d_n)
+ );
+
+endmodule // cat_io_lvds_tb
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.build b/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.build
new file mode 100755
index 000000000..827ab0628
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.build
@@ -0,0 +1,21 @@
+
+#!/bin/sh
+
+rm -rf isim*
+rm -rf catcap_tb
+rm -rf fuse*
+\
+# --sourcelibdir ../../models \
+
+vlogcomp \
+ --sourcelibext .v \
+ --sourcelibdir ../../coregen \
+ --sourcelibdir ../../control_lib \
+ --sourcelibdir . \
+ --sourcelibdir $XILINX/verilog/src \
+ --sourcelibdir $XILINX/verilog/src/unisims \
+ --work work \
+ catcap_tb.v
+
+
+fuse -o catcap_tb catcap_tb \ No newline at end of file
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.v b/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.v
new file mode 100644
index 000000000..f300cc32f
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/catcap/catcap_tb.v
@@ -0,0 +1,115 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module catcap_tb();
+
+ wire GSR, GTS;
+ glbl glbl( );
+
+ reg clk = 0;
+ reg ddrclk = 0;
+ reg reset = 1;
+
+ always #100 clk = ~clk;
+ always @(negedge clk) ddrclk <= ~ddrclk;
+
+ initial $dumpfile("catcap_tb.vcd");
+ initial $dumpvars(0,catcap_tb);
+
+ wire [11:0] i0 = {4'hA,count};
+ wire [11:0] q0 = {4'hB,count};
+ wire [11:0] i1 = {4'hC,count};
+ wire [11:0] q1 = {4'hD,count};
+
+ reg mimo;
+ reg [11:0] pins;
+ reg frame;
+ reg [7:0] count;
+
+ initial
+ begin
+ #1000 reset = 0;
+ MIMO_BURST(4);
+ MIMO_BURST(5);
+ BURST(4);
+ BURST(5);
+ #2000;
+ $finish;
+ end
+
+ task BURST;
+ input [7:0] len;
+ begin
+ frame <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ mimo <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge ddrclk);
+ count <= 0;
+ repeat(len)
+ begin
+ @(posedge clk);
+ pins <= i0;
+ frame <= 1;
+ @(posedge clk);
+ pins <= q0;
+ frame <= 0;
+ count <= count + 1;
+ end
+ end
+ endtask // BURST
+
+ task MIMO_BURST;
+ input [7:0] len;
+ begin
+ frame <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ mimo <= 1;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge ddrclk);
+ count <= 0;
+ repeat(len)
+ begin
+ @(posedge clk);
+ pins <= i0;
+ frame <= 1;
+ @(posedge clk);
+ pins <= q0;
+ @(posedge clk);
+ pins <= i1;
+ frame <= 0;
+ @(posedge clk);
+ pins <= q1;
+ count <= count + 1;
+ end
+ @(posedge clk);
+ @(posedge clk);
+ end
+ endtask // MIMO_BURST
+
+ wire rx_clk, rx_strobe;
+ wire [11:0] i0o,i1o,q0o,q1o;
+
+ catcap_ddr_cmos catcap
+ (.data_clk(ddrclk),
+ .reset(reset),
+ .mimo(mimo),
+ .rx_frame(frame),
+ .rx_d(pins),
+ .rx_clk(rx_clk),
+ .rx_strobe(rx_strobe),
+ .i0(i0o),.q0(q0o),
+ .i1(i1o),.q1(q1o));
+
+endmodule // hb_chain_tb
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.build b/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.build
new file mode 100755
index 000000000..072495479
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.build
@@ -0,0 +1,21 @@
+
+#!/bin/sh
+
+rm -rf isim*
+rm -rf catgen_tb
+rm -rf fuse*
+\
+# --sourcelibdir ../../models \
+
+vlogcomp \
+ --sourcelibext .v \
+ --sourcelibdir ../../coregen \
+ --sourcelibdir ../../control_lib \
+ --sourcelibdir . \
+ --sourcelibdir $XILINX/verilog/src \
+ --sourcelibdir $XILINX/verilog/src/unisims \
+ --work work \
+ catgen_tb.v
+
+
+fuse -o catgen_tb catgen_tb \ No newline at end of file
diff --git a/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.v b/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.v
new file mode 100644
index 000000000..e55f2de32
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_cap_gen/catgen/catgen_tb.v
@@ -0,0 +1,103 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module catgen_tb();
+
+ wire GSR, GTS;
+ glbl glbl( );
+
+ reg clk = 0;
+ reg reset = 1;
+ wire ddrclk;
+
+ always #100 clk = ~clk;
+
+ initial $dumpfile("catgen_tb.vcd");
+ initial $dumpvars(0,catgen_tb);
+
+ wire [11:0] pins;
+ wire frame;
+
+ reg mimo;
+ reg [7:0] count;
+ reg tx_strobe;
+
+ wire [11:0] i0 = {4'hA,count};
+ wire [11:0] q0 = {4'hB,count};
+ wire [11:0] i1 = {4'hC,count};
+ wire [11:0] q1 = {4'hD,count};
+
+ initial
+ begin
+ #1000 reset = 0;
+ BURST(4);
+ BURST(5);
+ MIMO_BURST(4);
+ MIMO_BURST(5);
+ #2000;
+ $finish;
+ end
+
+ task BURST;
+ input [7:0] len;
+
+ begin
+ tx_strobe <= 0;
+ mimo <= 0;
+ count <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ repeat(len)
+ begin
+ tx_strobe <= 1;
+ @(posedge clk);
+ count <= count + 1;
+ end
+ tx_strobe <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ end
+ endtask // BURST
+
+ task MIMO_BURST;
+ input [7:0] len;
+
+ begin
+ tx_strobe <= 0;
+ mimo <= 1;
+ count <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ repeat(len)
+ begin
+ tx_strobe <= 1;
+ @(posedge clk);
+ tx_strobe <= 0;
+ @(posedge clk);
+ count <= count + 1;
+ end
+ tx_strobe <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ end
+ endtask // BURST
+
+ catgen_ddr_cmos catgen
+ (.data_clk(ddrclk),
+ .reset(reset),
+ .mimo(mimo),
+ .tx_frame(frame),
+ .tx_d(pins),
+ .tx_clk(clk),
+ .tx_strobe(tx_strobe),
+ .i0(i0),.q0(q0),
+ .i1(i1),.q1(q1));
+
+endmodule // hb_chain_tb
diff --git a/fpga/usrp3/lib/sim/io_port2/pcie_dma_ctrl/pcie_dma_ctrl_tb.v b/fpga/usrp3/lib/sim/io_port2/pcie_dma_ctrl/pcie_dma_ctrl_tb.v
new file mode 100644
index 000000000..2b6c40bdd
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_port2/pcie_dma_ctrl/pcie_dma_ctrl_tb.v
@@ -0,0 +1,92 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+`timescale 500ps/1ps
+
+module pcie_dma_ctrl_tb();
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial begin
+ #100 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ function [63:0] iop2_msg_write;
+ input [19:0] address;
+ input [31:0] data;
+ input half_wd;
+ begin
+ // {rd_response, wr_request, rd_request, half_word, 8'h00, address, data};
+ iop2_msg_write = {1'b0, 1'b1, 1'b0, half_wd, 8'h00, address, data};
+ end
+ endfunction // iop2_msg_write
+
+ function [63:0] iop2_msg_read;
+ input [19:0] address;
+ input half_wd;
+ begin
+ // {rd_response, wr_request, rd_request, half_word, 8'h00, address, data};
+ iop2_msg_read = {1'b0, 1'b0, 1'b1, half_wd, 8'h00, address, 32'h0};
+ end
+ endfunction // iop2_msg_read
+
+ wire [3:0] clear;
+ wire [63:0] frame_size;
+ reg [3:0] pkt_stb = 0;
+ reg [3:0] samp_stb = 0;
+ reg [3:0] error = 0;
+ reg [7:0] rtr_sid = 4;
+ wire [3:0] rtr_dst;
+
+ reg [63:0] regi_tdata;
+ reg regi_tvalid;
+ wire regi_tready;
+ wire [63:0] rego_tdata;
+ wire rego_tvalid;
+ reg rego_tready;
+ reg [31:0] rego_payload;
+
+ always @(posedge clk)
+ if (rego_tdata[63] & rego_tvalid & rego_tready)
+ rego_payload <= rego_tdata[31:0];
+
+ initial begin
+ regi_tvalid <= 0;
+ rego_tready <= 0;
+ while (reset) @(posedge clk);
+
+ rego_tready <= 1;
+ @(posedge clk);
+
+ regi_tdata <= iop2_msg_write(20'h304, 32'hA, 0);
+ regi_tvalid <= 1;
+ @(posedge clk);
+ while (~regi_tready) @(posedge clk);
+ regi_tvalid <= 0;
+ @(posedge clk);
+
+ end // initial begin
+
+ pcie_dma_ctrl #(
+ .NUM_STREAMS(4), .FRAME_SIZE_W(16),
+ .REG_BASE_ADDR(20'h00200), .ENABLE_ROUTER(1),
+ .ROUTER_SID_W(8), .ROUTER_DST_W(4)
+ ) dut (
+ .clk(clk), .reset(reset),
+ .regi_tdata(regi_tdata), .regi_tvalid(regi_tvalid), .regi_tready(regi_tready),
+ .rego_tdata(rego_tdata), .rego_tvalid(rego_tvalid), .rego_tready(rego_tready),
+ .set_clear(clear), .set_frame_size(frame_size), .sample_stb(samp_stb), .packet_stb(pkt_stb),
+ .stream_err(error), .rtr_sid(rtr_sid), .rtr_dst(rtr_dst)
+ );
+
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/io_port2/pcie_iop2_msg_arbiter/pcie_iop2_msg_arbiter_tb.v b/fpga/usrp3/lib/sim/io_port2/pcie_iop2_msg_arbiter/pcie_iop2_msg_arbiter_tb.v
new file mode 100644
index 000000000..fe566b1aa
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_port2/pcie_iop2_msg_arbiter/pcie_iop2_msg_arbiter_tb.v
@@ -0,0 +1,110 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+`timescale 500ps/1ps
+
+module pcie_iop2_msg_arbiter_tb();
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial begin
+ #100 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ function [63:0] iop2_msg_write;
+ input [19:0] address;
+ input [31:0] data;
+ input half_wd;
+ begin
+ // {rd_response, wr_request, rd_request, half_word, 8'h00, address, data};
+ iop2_msg_write = {1'b0, 1'b1, 1'b0, half_wd, 8'h00, address, data};
+ end
+ endfunction // iop2_msg_write
+
+ function [63:0] iop2_msg_read;
+ input [19:0] address;
+ input half_wd;
+ begin
+ // {rd_response, wr_request, rd_request, half_word, 8'h00, address, data};
+ iop2_msg_read = {1'b0, 1'b0, 1'b1, half_wd, 8'h00, address, 32'h0};
+ end
+ endfunction // iop2_msg_read
+
+ reg [63:0] msgi_tdata;
+ wire [63:0] msgo_tdata;
+ wire msgo_tvalid, msgi_tready;
+ reg msgo_tready, msgi_tvalid;
+
+ wire [63:0] basic_regi_tdata, zpu_regi_tdata;
+ wire basic_regi_tvalid, zpu_regi_tvalid;
+ reg basic_regi_tready, zpu_regi_tready;
+ reg [63:0] basic_rego_tdata, zpu_rego_tdata;
+ reg basic_rego_tvalid, zpu_rego_tvalid;
+ wire basic_rego_tready, zpu_rego_tready;
+
+ initial begin
+ //@TODO: Make this a self-checking TB
+ while (reset) @(posedge clk);
+
+ msgo_tready <= 1;
+ basic_regi_tready <= 1;
+ @(posedge clk);
+
+
+ msgi_tdata <= iop2_msg_write(20'h0, 32'hDEAD, 0);
+ msgi_tvalid <= 1;
+ while (~msgi_tready) @(posedge clk);
+ msgi_tvalid <= 0;
+ @(posedge clk);
+
+
+ msgi_tdata <= iop2_msg_read(20'h00000, 0);
+ msgi_tvalid <= 1;
+ while (~msgi_tready) @(posedge clk);
+ msgi_tvalid <= 0;
+ @(posedge clk);
+
+ zpu_rego_tdata <= {1, 31'h0, 32'h12345678};
+ zpu_rego_tvalid <= 1;
+ while (~zpu_rego_tready) @(posedge clk);
+ zpu_rego_tvalid <= 0;
+
+
+
+ end // initial begin
+
+ pcie_iop2_msg_arbiter #(
+ .E0_ADDR(20'h00000), .E0_MASK(20'hFFF00), //0x00000 - 0x000FF: Basic PCIe registers
+ .E1_ADDR(20'h00100), .E1_MASK(20'hFFF00), //0x00100 - 0x001FF: PCIe router registers
+ .E2_ADDR(20'h00200), .E2_MASK(20'hFFE00), //0x00200 - 0x003FF: DMA stream registers
+ .E3_ADDR(20'h40000), .E3_MASK(20'hC0000) //0x40000 - 0x7FFFF: Client address space
+ ) iop2_msg_arbiter (
+ .clk(clk), .reset(reset),
+ //Master
+ .regi_tdata(msgi_tdata), .regi_tvalid(msgi_tvalid), .regi_tready(msgi_tready),
+ .rego_tdata(msgo_tdata), .rego_tvalid(msgo_tvalid), .rego_tready(msgo_tready),
+ //Endpoint 0
+ .e0_regi_tdata(basic_regi_tdata), .e0_regi_tvalid(basic_regi_tvalid), .e0_regi_tready(basic_regi_tready),
+ .e0_rego_tdata(basic_rego_tdata), .e0_rego_tvalid(basic_rego_tvalid), .e0_rego_tready(basic_rego_tready),
+ //Endpoint 1
+ .e1_regi_tdata(), .e1_regi_tvalid(), .e1_regi_tready(1'b1),
+ .e1_rego_tdata(64'h0), .e1_rego_tvalid(1'b0), .e1_rego_tready(),
+ //Endpoint 2
+ .e2_regi_tdata(), .e2_regi_tvalid(), .e2_regi_tready(1'b1),
+ .e2_rego_tdata(64'h0), .e2_rego_tvalid(1'b0), .e2_rego_tready(),
+ //Endpoint 3
+ .e3_regi_tdata(zpu_regi_tdata), .e3_regi_tvalid(zpu_regi_tvalid), .e3_regi_tready(zpu_regi_tready),
+ .e3_rego_tdata(zpu_rego_tdata), .e3_rego_tvalid(zpu_rego_tvalid), .e3_rego_tready(zpu_rego_tready)
+ );
+
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/io_port2/pcie_wb_reg_core/pcie_wb_reg_core_tb.v b/fpga/usrp3/lib/sim/io_port2/pcie_wb_reg_core/pcie_wb_reg_core_tb.v
new file mode 100644
index 000000000..62bec9eb4
--- /dev/null
+++ b/fpga/usrp3/lib/sim/io_port2/pcie_wb_reg_core/pcie_wb_reg_core_tb.v
@@ -0,0 +1,243 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+`timescale 500ps/1ps
+`define CHECK_VALUE(val, expected, report) \
+ if (val == expected) \
+ $display("%s...Passed",report); \
+ else \
+ $display("%s...FAILED!!! (Val=0x%x, Exp=0x%x)",report,val,expected); \
+
+module pcie_wb_reg_core_tb();
+ reg clk = 0, reset = 1;
+ reg wb_stb_i = 0;
+ reg wb_we_i = 0;
+ reg [15:0] wb_adr_i = 0;
+ reg [31:0] wb_dat_i = 0;
+ wire wb_ack_o;
+ wire [31:0] wb_dat_o;
+
+ wire [63:0] msgo_data;
+ wire msgo_valid;
+ reg msgo_ready = 0;
+ reg [63:0] msgi_data = 0;
+ reg msgi_valid = 0;
+ wire msgi_ready;
+
+ reg [31:0] msgo_payload = 32'h0;
+ reg [31:0] msgo_ctrl = 32'h0;
+
+ reg [31:0] it;
+
+ always #10 clk = ~clk;
+
+ initial begin
+ #100 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ localparam READ = 3'b001;
+ localparam WRITE = 3'b010;
+ localparam RESPONSE = 3'b100;
+
+ task pcie_send;
+ input [2:0] op;
+ input [19:0] address;
+ input [31:0] data;
+ begin
+ //{rd_resp, wr_request, rd_request, half_word, 8'h00, address, data};
+ msgi_data <= {op, 1'b0, 8'h00, address, data};
+ msgi_valid <= 1'b1;
+
+ @(posedge clk);
+ while (~msgi_ready) @(posedge clk);
+
+ msgi_valid <= 1'b0;
+ @(posedge clk);
+ end
+ endtask // pcie_send
+
+ task pcie_recv;
+ input [2:0] op;
+ input [19:0] address;
+ input [31:0] data;
+ begin
+ while (~msgo_valid) @(posedge clk);
+
+ msgo_ready <= 1'b1;
+ @(posedge clk);
+
+ if (msgo_data[63] == op[2] || (msgo_data[62:61] == op[1:0] && msgo_data[51:32] == address))
+ msgo_payload <= msgo_data[31:0];
+ msgo_ctrl <= msgo_data[63:32];
+
+ msgo_ready <= 1'b0;
+ @(posedge clk);
+ end
+ endtask // pcie_recv
+
+ task wb_send;
+ input [2:0] op;
+ input [15:0] address;
+ input [31:0] data;
+ begin
+ wb_adr_i <= address;
+ wb_dat_i <= data;
+ wb_we_i <= op[1];
+ wb_stb_i <= 1'b1;
+
+ @(posedge clk);
+ while (~wb_ack_o) @(posedge clk);
+
+ wb_stb_i <= 1'b0;
+ end
+ endtask // pcie_send
+
+
+ initial begin
+ msgo_ready <= 1'b0;
+ msgi_valid <= 1'b0;
+ while (reset) @(posedge clk);
+ @(posedge clk);
+
+ $display("\n[TEST] ZPU Read from PCIe");
+ pcie_send(WRITE, 20'h6a000, 32'h0);
+ `CHECK_VALUE(msgo_payload, 32'h0, "Verify PCIe readback before initiating read request");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h1, "Verify PCIe status after initiating read");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h1, "Verify PCIe status after initiating second read");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h6, "Verify WB status after PCIe read request");
+ wb_send(READ, 16'h4, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h2000a000, "Verify WB control value after PCIe read request");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h4, "Verify WB status value after consuming PCIe read request");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h1, "Verify PCIe status after WB consumes request only");
+ wb_send(WRITE, 16'h0, 32'hDEADBEEF);
+ wb_send(WRITE, 16'h4, 32'h80000000);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after responding to PCIe read request");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h0, "Verify PCIe status after WB responds to read request");
+ pcie_send(READ, 20'h7a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'hdeadbeef, "Verify PCIe read data");
+
+ $display("\n[TEST] ZPU Write from PCIe");
+ pcie_send(WRITE, 20'h7b000, 32'h12345678);
+ pcie_send(READ, 20'h7a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'hdeadbeef, "Verify that PCIe read data is still intact after write");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h2, "Verify WB status value after PCIe write request");
+ wb_send(READ, 16'h0, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h12345678, "Verify WB data value after PCIe read request");
+ wb_send(READ, 16'h4, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h4000b000, "Verify WB control value after PCIe read request");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after consuming PCIe write request");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h0, "Verify PCIe status after WB consumes request");
+
+ $display("\n[TEST] Chinch Write from ZPU");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value before initiating write request");
+ wb_send(WRITE, 16'h0, 32'h00beef00);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after writing just the data reg");
+ wb_send(WRITE, 16'h4, 32'h40000200);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after initiating write");
+ pcie_recv(WRITE, 20'h200, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h00beef00, "Verify received PCIe data");
+ `CHECK_VALUE(msgo_ctrl, 32'h40000200, "Verify received PCIe control");
+ wb_send(WRITE, 16'h0, 32'h00feeb00);
+ wb_send(WRITE, 16'h4, 32'h400002fc);
+ pcie_recv(WRITE, 20'h200, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h00feeb00, "Verify second received PCIe data");
+ `CHECK_VALUE(msgo_ctrl, 32'h400002fc, "Verify second received PCIe control");
+
+ $display("\n[TEST] Chinch Read from ZPU");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value before initiating read request");
+ wb_send(WRITE, 16'h0, 32'hffffffff);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after writing just the data reg");
+ wb_send(WRITE, 16'h4, 32'h20000400);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h1, "Verify WB status value after initiating read request");
+ pcie_recv(READ, 20'h400, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'hffffffff, "Verify received PCIe data");
+ `CHECK_VALUE(msgo_ctrl, 32'h20000400, "Verify received PCIe control");
+ wb_send(READ, 16'hC, 32'h0);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h1, "Verify WB status value before PCIe responds");
+ pcie_send(RESPONSE, 20'h000, 32'hace06666);
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status value after PCIe responds");
+ wb_send(READ, 16'h8, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'hace06666, "Verify WB read value after PCIe responds");
+
+ $display("\n[TEST] WB Outbound flood");
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h0, "Verify WB status before request flood");
+ for (it = 0; it < 64; it = it + 1) begin
+ wb_send(WRITE, 16'h4, 32'h20000400);
+ end
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h11, "Verify WB status after request flood");
+ for (it = 0; it < 64; it = it + 1) begin
+ pcie_recv(READ, 20'h400, 20'h0);
+ end
+ wb_send(READ, 16'hC, 32'h0);
+ `CHECK_VALUE(wb_dat_o, 32'h1, "Verify WB status after consuming requests");
+
+ $display("\n[TEST] PCIe Transaction Status");
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h0, "Verify PCIe status before multiple reads");
+ pcie_send(WRITE, 20'h6a000, 32'h0);
+ pcie_send(WRITE, 20'h6a000, 32'h0);
+ pcie_send(WRITE, 20'h6a000, 32'h0);
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h1, "Verify PCIe status before multiple read requests and status queries");
+ wb_send(READ, 16'h4, 32'h0);
+ wb_send(WRITE, 16'h0, 32'hDEADBEEF);
+ wb_send(WRITE, 16'h4, 32'h80000000);
+ pcie_send(READ, 20'h6a000, 32'h0);
+ pcie_recv(RESPONSE, 20'h0, 20'h0);
+ `CHECK_VALUE(msgo_payload, 32'h0, "Verify PCIe status after response");
+
+ $display("\n[DONE]");
+
+
+ end // initial begin
+
+ pcie_wb_reg_core #(.WB_ADDRW(16), .WB_DATAW(32)) dut (
+ .clk(clk), .rst(reset),
+ .wb_stb_i(wb_stb_i), .wb_we_i(wb_we_i), .wb_adr_i(wb_adr_i),
+ .wb_dat_i(wb_dat_i), .wb_ack_o(wb_ack_o), .wb_dat_o(wb_dat_o),
+ .msgi_tdata(msgi_data), .msgi_tvalid(msgi_valid), .msgi_tready(msgi_ready),
+ .msgo_tdata(msgo_data), .msgo_tvalid(msgo_valid), .msgo_tready(msgo_ready),
+ .debug());
+
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/packet_proc/chdr_chunker/chdr_chunker_tb.v b/fpga/usrp3/lib/sim/packet_proc/chdr_chunker/chdr_chunker_tb.v
new file mode 100644
index 000000000..9e80f9c15
--- /dev/null
+++ b/fpga/usrp3/lib/sim/packet_proc/chdr_chunker/chdr_chunker_tb.v
@@ -0,0 +1,190 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+`timescale 1ns/10ps
+
+module chdr_chunker_tb();
+
+ // TB stimulus
+ reg clk = 0;
+ reg reset = 1;
+ reg clear = 0;
+ reg [15:0] quantum;
+
+ // Check vars
+ reg [31:0] o_xfer_count = 0, i_xfer_count = 0;
+ reg [63:0] o_last_tdata = 0;
+
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("chdr_chunker_tb.vcd");
+ initial $dumpvars(0,chdr_chunker_tb);
+
+ function check_result;
+ input [31:0] o_xfer_count_arg;
+ input [31:0] i_xfer_count_arg;
+ input [63:0] o_last_tdata_arg;
+ input error_arg;
+ begin
+ //Check vars
+ check_result = 1;
+ check_result = check_result & ((o_xfer_count_arg == o_xfer_count) !== 0);
+ check_result = check_result & ((i_xfer_count_arg == i_xfer_count) !== 0);
+ check_result = check_result & ((o_last_tdata_arg == o_last_tdata) !== 0);
+ check_result = check_result & ((error_arg == error) != 0);
+
+ if (check_result) begin
+ $display ("... Passed");
+ end else begin
+ $display ("... FAILED!!!");
+ $display ("o_xfer_count = %d (Expected %d)",o_xfer_count,o_xfer_count_arg);
+ $display ("i_xfer_count = %d (Expected %d)",i_xfer_count,i_xfer_count_arg);
+ $display ("o_last_tdata = %h (Expected %h)",o_last_tdata,o_last_tdata_arg);
+ $display ("error = %d (Expected %d)",error,error_arg);
+ end
+
+ //Reset vars
+ o_xfer_count = 0;
+ i_xfer_count = 0;
+ o_last_tdata = 64'h0;
+ end
+ endfunction
+
+ task send_packet;
+ input [63:0] data_start;
+ input [31:0] len;
+
+ begin
+ if(len < 9) begin
+ {i_tlast, i_tdata} <= { 1'b1, data_start[63:32], len[15:0], data_start[15:0] };
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ end else begin
+ {i_tlast, i_tdata} <= { 1'b0, data_start[63:32], len[15:0], data_start[15:0] };
+ i_tvalid <= 1;
+ @(posedge clk);
+ repeat(((len-1)/8)-1) begin
+ i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
+ @(posedge clk);
+ end
+ i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
+ i_tlast <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ end // else: !if(len < 9)
+ end
+ endtask // send_packet
+
+ task reset_quantum_atomic;
+ input [15:0] quant;
+ begin
+ quantum <= quant;
+ clear <= 1;
+ @(posedge clk);
+ clear <= 0;
+ @(posedge clk);
+ end
+ endtask // reset_quantum_atomic
+
+
+ initial begin
+ #100 reset = 0;
+ #200000;
+ $finish;
+ end
+
+ reg [63:0] i_tdata;
+ reg i_tlast;
+ reg i_tvalid;
+ wire i_tready;
+
+ wire [63:0] o_tdata;
+ wire o_tlast, o_tvalid, o_tready;
+ wire error;
+
+ initial begin
+ quantum <= 256;
+ i_tvalid <= 0;
+ while(reset) @(posedge clk);
+
+ $write ("Running test case: First packet after reset");
+ send_packet(64'h00000001_00000000, 128);
+ while(o_tvalid) @(posedge clk);
+ check_result(256,16,64'hFFFFFFFF_FFFFFFFF,0);
+
+ reset_quantum_atomic(8);
+
+ $write ("Running test case: sizeof(packet) < quantum");
+ send_packet(64'h00000001_00000000, 40);
+ while(o_tvalid) @(posedge clk);
+ check_result(8,5,64'hFFFFFFFF_FFFFFFFF,0);
+
+ reset_quantum_atomic(5);
+
+ $write ("Running test case: sizeof(packet) == quantum");
+ send_packet(64'h00000001_00000000, 40);
+ while(o_tvalid) @(posedge clk);
+ check_result(5,5,64'h00000030_00000008,0);
+
+ $write ("Running test case: sizeof(packet) == quantum - 64bits");
+ send_packet(64'h00000001_00000000, 32);
+ while(o_tvalid) @(posedge clk);
+ check_result(5,4,64'hFFFFFFFF_FFFFFFFF,0);
+
+ $write ("Running test case: sizeof(packet) == quantum + 64bits");
+ send_packet(64'h00000001_00000000, 48);
+ while(o_tvalid) @(posedge clk);
+ check_result(32'hxxxxxxxx,32'hxxxxxxxx,64'hxxxxxxxx_xxxxxxxx,1);
+
+ $write ("Running test case: Error reset");
+ reset_quantum_atomic(8);
+ check_result(32'hxxxxxxxx,32'hxxxxxxxx,64'hxxxxxxxx_xxxxxxxx,0);
+
+ $write ("Running test case: sizeof(packet) > quantum");
+ send_packet(64'h00000001_00000000, 80);
+ while(o_tvalid) @(posedge clk);
+ check_result(32'hxxxxxxxx,32'hxxxxxxxx,64'hxxxxxxxx_xxxxxxxx,1);
+
+ reset_quantum_atomic(8);
+
+ $write ("Running test case: sizeof(packet) == 2");
+ send_packet(64'h00000001_00000000, 8);
+ while(o_tvalid) @(posedge clk);
+ check_result(8,1,64'hFFFFFFFF_FFFFFFFF,0);
+
+ $write ("Running test case: Multiple packets back-to-back");
+ send_packet(64'h00000001_00000000, 40);
+ while(o_tvalid) @(posedge clk);
+ send_packet(64'h00000001_00000000, 16);
+ while(o_tvalid) @(posedge clk);
+ send_packet(64'h00000001_00000000, 64);
+ while(o_tvalid) @(posedge clk);
+ check_result(24,15,64'h0000004e0000000e,0);
+
+ end // initial begin
+
+
+ chdr_chunker dut (
+ .clk(clk), .reset(reset), .clear(clear), .frame_size(quantum),
+ .i_tdata(i_tdata), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready),
+ .error(error));
+
+ assign o_tready = 1;
+
+ always @(posedge clk) begin
+ if (o_tvalid & o_tready) begin
+ o_xfer_count <= o_xfer_count + 1;
+ o_last_tdata <= o_tdata;
+ end
+ if (i_tvalid & i_tready) i_xfer_count <= i_xfer_count + 1;
+ end
+
+endmodule // chdr_chunker_tb
diff --git a/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/Makefile b/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/Makefile
new file mode 100644
index 000000000..f73cbdae9
--- /dev/null
+++ b/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/Makefile
@@ -0,0 +1,33 @@
+#
+# Copyright 2016 Ettus Research
+#
+
+#-------------------------------------------------
+# 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
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = chdr_dechunker_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+chdr_dechunker_tb.sv \
+)
+
+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/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/chdr_dechunker_tb.sv b/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/chdr_dechunker_tb.sv
new file mode 100644
index 000000000..38664c20f
--- /dev/null
+++ b/fpga/usrp3/lib/sim/packet_proc/chdr_dechunker/chdr_dechunker_tb.sv
@@ -0,0 +1,200 @@
+//
+// Copyright 2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+`timescale 1ns/10ps
+
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 8
+
+`include "sim_exec_report.vh"
+
+
+module chdr_dechunker_tb();
+ `TEST_BENCH_INIT("chdr_dechunker_tb", `NUM_TEST_CASES, `NS_PER_TICK)
+
+ // TB stimulus
+ reg clk = 0;
+ reg reset = 1;
+ reg clear = 0;
+ reg [15:0] quantum;
+ wire error;
+
+ // Check vars
+ reg [31:0] o_xfer_count = 0, i_xfer_count = 0;
+ reg [63:0] o_last_tdata = 0;
+
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("chdr_dechunker_tb.vcd");
+ initial $dumpvars(0,chdr_dechunker_tb);
+
+ function check_result;
+ input [31:0] o_xfer_count_arg;
+ input [31:0] i_xfer_count_arg;
+ input [63:0] o_last_tdata_arg;
+ input error_arg;
+ begin
+ //Check vars
+ check_result = 1;
+ check_result = check_result & ((o_xfer_count_arg == o_xfer_count) !== 0);
+ check_result = check_result & ((i_xfer_count_arg == i_xfer_count) !== 0);
+ check_result = check_result & ((o_last_tdata_arg == o_last_tdata) !== 0);
+ check_result = check_result & ((error_arg == error) != 0);
+
+ if (!check_result) begin
+ $display ("o_xfer_count = %d (Expected %d)",o_xfer_count,o_xfer_count_arg);
+ $display ("i_xfer_count = %d (Expected %d)",i_xfer_count,i_xfer_count_arg);
+ $display ("o_last_tdata = %h (Expected %h)",o_last_tdata,o_last_tdata_arg);
+ $display ("error = %d (Expected %d)",error,error_arg);
+ `ASSERT_ERROR(0, "Result did not match expected value");
+ end
+
+ //Reset vars
+ o_xfer_count = 0;
+ i_xfer_count = 0;
+ o_last_tdata = 64'h0;
+ end
+ endfunction
+
+ task send_packet;
+ input [63:0] data_start;
+ input [31:0] len;
+ input [31:0] quant;
+
+ begin
+ if(quant < 2) begin
+ {i_tlast, i_tdata} <= { 1'b1, data_start[63:32], len[15:0], data_start[15:0] };
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ end else begin
+ {i_tlast, i_tdata} <= { 1'b0, data_start[63:32], len[15:0], data_start[15:0] };
+ i_tvalid <= 1;
+ @(posedge clk);
+ repeat(quant - 2) begin
+ i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
+ @(posedge clk);
+ end
+ i_tdata <= i_tdata + 64'h0000_0002_0000_0002;
+ i_tlast <= 1;
+ @(posedge clk);
+ i_tvalid <= 1'b0;
+ end // else: !if(quant < 2)
+ end
+ endtask // send_packet
+
+ task reset_quantum_atomic;
+ input [15:0] quant;
+ begin
+ quantum <= quant;
+ clear <= 1;
+ @(posedge clk);
+ clear <= 0;
+ @(posedge clk);
+ end
+ endtask // reset_quantum_atomic
+
+
+ initial begin
+ #100 reset = 0;
+ end
+
+ reg [63:0] i_tdata;
+ reg i_tlast;
+ reg i_tvalid;
+ wire i_tready;
+
+ wire [63:0] o_tdata;
+ wire o_tlast, o_tvalid, o_tready;
+
+ reg result;
+ initial begin
+ quantum <= 8;
+ i_tvalid <= 0;
+ while(reset) @(posedge clk);
+
+ `TEST_CASE_START("Running test case: First packet after reset");
+ send_packet(64'h00000001_00000000, 32, 8);
+ @(posedge clk);
+ result = check_result(4,8,64'hxxxxxxxx_xxxxxx06, 0);
+ `TEST_CASE_DONE(result);
+
+ reset_quantum_atomic(10);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) < quantum");
+ send_packet(64'h00000001_00000000, 64, 10);
+ @(posedge clk);
+ result = check_result(8,10,64'hxxxxxxxx_xxxxxx0e, 0);
+ `TEST_CASE_DONE(result);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) == quantum");
+ send_packet(64'h00000001_00000000, 80, 10);
+ @(posedge clk);
+ result = check_result(10,10,64'hxxxxxxxx_xxxxxx12, 0);
+ `TEST_CASE_DONE(result);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) == quantum - 64bits");
+ send_packet(64'h00000001_00000000, 72, 10);
+ @(posedge clk);
+ result = check_result(9,10,64'hxxxxxxxx_xxxxxx10, 0);
+ `TEST_CASE_DONE(result);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) == quantum + 64bits");
+ send_packet(64'h00000001_00000000, 88, 10);
+ @(posedge clk);
+ result = check_result(32'hxxxxxxxx,10,64'hxxxxxxxx_xxxxxxxx, 1);
+ `TEST_CASE_DONE(result);
+
+ reset_quantum_atomic(10);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) > quantum");
+ send_packet(64'h00000001_00000000, 88, 10);
+ @(posedge clk);
+ result = check_result(32'hxxxxxxxx,10,64'hxxxxxxxx_xxxxxxxx, 1);
+ `TEST_CASE_DONE(result);
+
+ reset_quantum_atomic(8);
+
+ `TEST_CASE_START("Running test case: sizeof(packet) == 2");
+ send_packet(64'h00000001_00000000, 8, 8);
+ @(posedge clk);
+ result = check_result(1,8,64'hxxxxxxxx_xxxxxx00, 0);
+ `TEST_CASE_DONE(result);
+
+ `TEST_CASE_START("Running test case: Multiple packets");
+ send_packet(64'h00000001_00000000, 8, 8);
+ send_packet(64'h00000001_00000000, 16, 8);
+ send_packet(64'h00000001_00000000, 24, 8);
+ send_packet(64'h00000001_00000000, 32, 8);
+ @(posedge clk);
+ result = check_result(10,32,64'hxxxxxxxx_xxxxxx06, 0);
+ `TEST_CASE_DONE(result);
+
+ `TEST_BENCH_DONE;
+ end // initial begin
+
+
+ chdr_dechunker dut (
+ .clk(clk), .reset(reset), .clear(clear), .frame_size(quantum),
+ .i_tdata(i_tdata), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready),
+ .error(error));
+
+ assign o_tready = 1;
+
+ always @(posedge clk) begin
+ if (o_tvalid & o_tready) begin
+ o_xfer_count <= o_xfer_count + 1;
+ o_last_tdata <= o_tdata;
+ end
+ if (i_tvalid & i_tready) i_xfer_count <= i_xfer_count + 1;
+ end
+
+endmodule // chdr_dechunker_tb
diff --git a/fpga/usrp3/lib/sim/packet_proc/ip_hdr_checksum/ip_hdr_checksum_tb.v b/fpga/usrp3/lib/sim/packet_proc/ip_hdr_checksum/ip_hdr_checksum_tb.v
new file mode 100644
index 000000000..82deca656
--- /dev/null
+++ b/fpga/usrp3/lib/sim/packet_proc/ip_hdr_checksum/ip_hdr_checksum_tb.v
@@ -0,0 +1,43 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+module ip_hdr_checksum_tb();
+
+ initial $dumpfile("ip_hdr_checksum_tb.vcd");
+ initial $dumpvars(0,ip_hdr_checksum_tb);
+
+ reg clk;
+
+ wire [159:0] in = {
+ 16'h4500,
+ 16'h0030,
+ 16'h4422,
+ 16'h4000,
+ 16'h8006,
+ 16'h0000,
+ 16'h8c7c,
+ 16'h19ac,
+ 16'hae24,
+ 16'h1e2b
+ };
+
+ wire [15:0] out;
+ ip_hdr_checksum ip_hdr_checksum
+ (.clk(clk),
+ .in(in),
+ .out(out));
+
+ initial
+ begin
+ clk <= 0;
+ #100 clk <= 1;
+ #100 clk <= 0;
+ #100 clk <= 1;
+ #100 $display("Computed 0x%x, should be 0x442e", out);
+ #100 $finish;
+ end
+
+endmodule // ip_hdr_checksum_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/axi_pipe/axi_pipe_tb.v b/fpga/usrp3/lib/sim/rfnoc/axi_pipe/axi_pipe_tb.v
new file mode 100644
index 000000000..b84657b07
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_pipe/axi_pipe_tb.v
@@ -0,0 +1,74 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+module axi_pipe_tb;
+
+ initial $dumpfile("axi_pipe_tb.vcd");
+ initial $dumpvars(0,axi_pipe_tb);
+
+ reg clk = 0;
+ always #100 clk <= ~clk;
+ reg reset = 1;
+ initial #1000 @(posedge clk) reset <= 1'b0;
+ initial #30000 $finish;
+
+ localparam LEN=10;
+ wire [LEN-1:0] enables, valids;
+
+ wire o_tlast, i_tready, o_tvalid;
+ reg i_tvalid = 0;
+ reg o_tready = 0;
+ reg i_tlast = 0;
+
+ axi_pipe #(.STAGES(LEN)) axi_pipe
+ (.clk(clk), .reset(reset), .clear(0),
+ .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready),
+ .enables(enables), .valids(valids));
+
+ initial
+ begin
+ @(negedge reset);
+ repeat (3)
+ @(posedge clk);
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ repeat (15) @(posedge clk);
+ @(posedge clk);
+ o_tready <= 1;
+ repeat (15) @(posedge clk);
+ o_tready <= 0;
+ i_tvalid <= 1;
+ repeat (15) @(posedge clk);
+ o_tready <= 1;
+ i_tvalid <= 0;
+ repeat (15) @(posedge clk);
+ o_tready <= 0;
+ i_tvalid <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ @(posedge clk);
+ i_tvalid <= 1;
+ @(posedge clk);
+ @(posedge clk);
+ i_tlast <= 1;
+ @(posedge clk);
+ i_tvalid <= 0;
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ @(posedge clk);
+ o_tready <= 1;
+
+ end
+
+endmodule // axi_pipe
diff --git a/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/Makefile b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/Makefile
new file mode 100644
index 000000000..fcf21b755
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/Makefile
@@ -0,0 +1,37 @@
+#
+# Copyright 2016 Ettus Research
+#
+
+#-------------------------------------------------
+# Top-of-Makefile
+#-------------------------------------------------
+# Define BASE_DIR to point to the "top" dir
+BASE_DIR = $(abspath ../../../../top)
+# Include viv_sim_preamble after defining BASE_DIR
+include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+#-------------------------------------------------
+# Testbench Specific
+#-------------------------------------------------
+# Define only one toplevel module
+SIM_TOP = axi_rate_change_tb
+
+# Add test bench, user design under test, and
+# additional user created files
+SIM_SRCS = $(abspath \
+axi_rate_change_tb.sv \
+$(LIB_DIR)/control/ram_2port.v \
+$(LIB_DIR)/fifo/axi_packet_gate.v \
+$(LIB_DIR)/rfnoc/axi_rate_change.v \
+$(LIB_DIR)/rfnoc/axi_drop_partial_packet.v \
+)
+
+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/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/axi_rate_change_tb.sv b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/axi_rate_change_tb.sv
new file mode 100644
index 000000000..b16c2d26d
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/axi_rate_change_tb.sv
@@ -0,0 +1,323 @@
+`timescale 1ns/1ps
+`define NS_PER_TICK 1
+`define NUM_TEST_CASES 4
+
+`include "sim_exec_report.vh"
+`include "sim_clks_rsts.vh"
+`include "sim_cvita_lib.svh"
+`include "sim_axis_lib.svh"
+`include "sim_set_rb_lib.svh"
+
+module axi_rate_change_tb();
+ `TEST_BENCH_INIT("axi_rate_change_tb",`NUM_TEST_CASES,`NS_PER_TICK);
+ localparam CLK_PERIOD = $ceil(1e9/166.67e6);
+ `DEFINE_CLK(clk, CLK_PERIOD, 50);
+ `DEFINE_RESET(reset, 0, 100);
+
+ localparam SR_N_ADDR = 0;
+ localparam SR_M_ADDR = 1;
+ localparam SR_CONFIG_ADDR = 2;
+ localparam MAX_N = 16;
+ localparam MAX_M = 16;
+
+ logic [15:0] src_sid = 16'h0000;
+ logic [15:0] dst_sid = 16'h0010;
+ settings_bus_master sb (.clk(clk));
+ axis_master #(.DWIDTH(32+128)) m_axis (.clk(clk));
+ axis_slave #(.DWIDTH(32+128)) s_axis (.clk(clk));
+ logic clear, clear_user;
+ logic [31:0] m_axis_data_tdata, s_axis_data_tdata;
+ logic m_axis_data_tlast, m_axis_data_tvalid, m_axis_data_tready;
+ logic s_axis_data_tlast, s_axis_data_tvalid, s_axis_data_tready;
+ logic warning_long_throttle, error_extra_outputs, error_drop_pkt_lockup;
+ axi_rate_change #(
+ .WIDTH(32),
+ .MAX_N(MAX_N),
+ .MAX_M(MAX_M),
+ .SR_N_ADDR(SR_N_ADDR),
+ .SR_M_ADDR(SR_M_ADDR),
+ .SR_CONFIG_ADDR(SR_CONFIG_ADDR))
+ axi_rate_change (
+ .clk(clk), .reset(reset), .clear(clear), .clear_user(clear_user),
+ .src_sid(src_sid), .dst_sid(dst_sid),
+ .set_stb(sb.settings_bus.set_stb), .set_addr(sb.settings_bus.set_addr), .set_data(sb.settings_bus.set_data),
+ .i_tdata(m_axis.axis.tdata[31:0]), .i_tlast(m_axis.axis.tlast), .i_tvalid(m_axis.axis.tvalid), .i_tready(m_axis.axis.tready), .i_tuser(m_axis.axis.tdata[159:32]),
+ .o_tdata(s_axis.axis.tdata[31:0]), .o_tlast(s_axis.axis.tlast), .o_tvalid(s_axis.axis.tvalid), .o_tready(s_axis.axis.tready), .o_tuser(s_axis.axis.tdata[159:32]),
+ .m_axis_data_tdata(m_axis_data_tdata), .m_axis_data_tlast(m_axis_data_tlast),
+ .m_axis_data_tvalid(m_axis_data_tvalid), .m_axis_data_tready(m_axis_data_tready),
+ .s_axis_data_tdata(s_axis_data_tdata), .s_axis_data_tlast(s_axis_data_tlast),
+ .s_axis_data_tvalid(s_axis_data_tvalid), .s_axis_data_tready(s_axis_data_tready),
+ .warning_long_throttle(warning_long_throttle),
+ .error_extra_outputs(error_extra_outputs),
+ .error_drop_pkt_lockup(error_drop_pkt_lockup));
+
+ // Simulate user logic that can handle various decimation / interpolation rates
+ // - Generates a word count sequence that is checked in the test_rate() task.
+ // - Introduces a single clock cycle delay which is useful for testing that
+ // the DUT is not reliant on user logic having a large built in delay.
+ integer rate_n, rate_m, count_n, count_m, count_in, count_out;
+ always @(posedge clk) begin
+ if (reset | clear_user | clear) begin
+ s_axis_data_tlast <= 1'b0;
+ count_n <= 1;
+ count_m <= 1;
+ count_in <= 0;
+ count_out <= 0;
+ end else begin
+ // Rate change = N/M
+ if (m_axis_data_tvalid & m_axis_data_tready) begin
+ if (count_n == rate_n) begin
+ count_n <= 1;
+ count_in <= count_in + 1;
+ end else begin
+ count_n <= count_n + 1;
+ end
+ end
+ if (count_in != count_out) begin
+ if (s_axis_data_tvalid & s_axis_data_tready) begin
+ if (count_m == rate_m) begin
+ count_m <= 1;
+ count_out <= count_out + 1;
+ end else begin
+ count_m <= count_m + 1;
+ end
+ end
+ end
+ end
+ end
+
+ assign s_axis_data_tdata = {count_out[15:0], count_m[15:0]};
+ assign s_axis_data_tvalid = (count_in != count_out);
+ assign m_axis_data_tready = s_axis_data_tready;
+
+ // Used with test 3 to count output clock cycles
+ int clock_cnt;
+ logic clock_cnt_en = 1'b0;
+ logic clock_cnt_start = 1'b0;
+ always @(posedge clk) begin
+ if (clock_cnt_en == 1'b1) begin
+ // Wait until output data starts
+ if (s_axis.axis.tvalid & ~clock_cnt_start) begin
+ clock_cnt_start <= 1'b1;
+ clock_cnt <= clock_cnt + 1;
+ end else if (clock_cnt_start) begin
+ clock_cnt <= clock_cnt + 1;
+ end
+ end else begin
+ clock_cnt_start <= 1'b0;
+ clock_cnt <= 0;
+ end
+ end
+
+ /********************************************************
+ ** Verification
+ ********************************************************/
+ task random_wait(int unsigned min_cycles, int unsigned max_cycles);
+ begin
+ int unsigned num_cycles;
+ do begin
+ num_cycles = $random() & (2**($clog2(max_cycles))-1);
+ end while ((num_cycles < min_cycles) || (num_cycles > max_cycles));
+
+ if (num_cycles != 0) begin
+ for (int unsigned i = 0; i < num_cycles; i++) begin
+ @(posedge clk);
+ end
+ @(negedge clk); // Realign with negedge
+ end
+ end
+ endtask
+
+ task test_rate(int n, int m, int num_words, int spp = 16, bit rand_delay_in = 0, bit rand_delay_out = 0);
+ begin
+ clear = 1'b1;
+ @(posedge clk);
+ @(posedge clk);
+ clear = 1'b0;
+ @(posedge clk);
+ @(posedge clk);
+ rate_n = n;
+ rate_m = m;
+ sb.write(SR_N_ADDR, n);
+ sb.write(SR_M_ADDR, m);
+ @(posedge clk);
+ fork
+ begin
+ cvita_hdr_t send_header;
+ int words_left_to_send, words_to_send;
+ logic [31:0] words_sent;
+ real timestamp;
+ timestamp = 0.0;
+ words_sent = 0;
+ words_left_to_send = num_words;
+
+ while (words_left_to_send > 0) begin
+ // Setup header
+ send_header = '{default:0};
+ send_header.has_time = 1;
+ send_header.timestamp = longint'(timestamp);
+ send_header.eob = (words_left_to_send <= spp);
+ if (words_left_to_send >= spp) begin
+ send_header.length = 16+4*spp;
+ words_to_send = spp;
+ words_left_to_send -= spp;
+ end else begin
+ send_header.length = 16+4*words_left_to_send;
+ words_to_send = words_left_to_send;
+ words_left_to_send = 0;
+ end
+ // Send packet
+ for (int i = 0; i < words_to_send; i++) begin
+ if (rand_delay_in) random_wait(0,2*spp);
+ m_axis.push_word({send_header,words_sent + i},i == words_to_send-1);
+ end
+ words_sent += words_to_send;
+ // Update seq num, timestamp
+ send_header.seqnum++;
+ timestamp += (1.0*m/n)*words_to_send;
+ end
+ end
+ begin
+ string s;
+ cvita_hdr_t recv_header;
+ logic last, expected_eob;
+ real timestamp;
+ logic [63:0] expected_timestamp;
+ logic [31:0] word;
+ logic [15:0] word_cnt_div_m, word_cnt_div_m_frac;
+ logic [15:0] word_cnt_div_spp_frac;
+ int words_left_to_recv, words_recvd;
+ timestamp = 0.0;
+ expected_timestamp = 0; // Timestamp starts at 0
+ word_cnt_div_spp_frac = 0;
+ word_cnt_div_m = 0;
+ word_cnt_div_m_frac = 0;
+ words_recvd = 0;
+ words_left_to_recv = $floor(num_words/n)*m; // Order matters!
+
+ while (words_left_to_recv > 0) begin
+ s_axis.pull_word({recv_header,word},last);
+ word_cnt_div_spp_frac++;
+ word_cnt_div_m_frac++;
+ words_recvd++;
+ words_left_to_recv--;
+ timestamp += 1.0*n;
+ // Check packet length
+ if ((word_cnt_div_spp_frac == spp) || (words_left_to_recv == 0)) begin
+ `ASSERT_FATAL(last == 1, "Incorrect packet length! Last not asserted!");
+ word_cnt_div_spp_frac = 0;
+ end else begin
+ $sformat(s, "Incorrect packet length! Expected: %0d, Actual %0d", spp, words_recvd);
+ `ASSERT_FATAL(last == 0, s);
+ end
+ // Check for EOB
+ if (last) begin
+ words_recvd = 0;
+ expected_eob = (words_left_to_recv == 0);
+ $sformat(s, "Incorrect EOB state! Expected: %0d, Actual %0d", expected_eob, recv_header.eob);
+ `ASSERT_FATAL(recv_header.eob == expected_eob, s);
+ end
+ // Check timestamp
+ if (last) begin
+ $sformat(s, "Incorrect timestamp! Expected: %0d, Actual %0d", expected_timestamp, recv_header.timestamp);
+ `ASSERT_FATAL(recv_header.timestamp == expected_timestamp, s);
+ expected_timestamp = longint'(timestamp);
+ end
+ // Check word
+ $sformat(s, "Incorrect packet data! Expected: 0x%08h, Actual: 0x%08h", {word_cnt_div_m, word_cnt_div_m_frac}, word);
+ `ASSERT_FATAL(((word[31:16] == word_cnt_div_m) && (word[15:0] == word_cnt_div_m_frac)), s);
+ // Track number of received words, do at end of loop
+ if (word_cnt_div_m_frac == m) begin
+ word_cnt_div_m_frac = 0;
+ word_cnt_div_m++;
+ end
+ end
+ end
+ join
+ end
+ endtask
+
+ initial begin : tb_main
+ string s;
+ cvita_hdr_t tmp_header;
+ logic [63:0] word;
+ logic last;
+ integer spp, number_words;
+ spp = 16;
+
+ /********************************************************
+ ** Test 1 -- Reset
+ ********************************************************/
+ `TEST_CASE_START("Wait for Reset");
+ sb.reset();
+ m_axis.reset();
+ s_axis.reset();
+ while (reset) @(posedge clk);
+ `TEST_CASE_DONE(~reset);
+
+ /********************************************************
+ ** Test 2 -- Test various rates
+ ** - Try many decimation / interpolation rates (including
+ ** fractional rates) and use randomized delays.
+ ********************************************************/
+ `TEST_CASE_START("Check various rates");
+ for (int _n = 1; _n <= MAX_N; _n++) begin
+ for (int _m = 1; _m <= MAX_M; _m++) begin
+ $display("Testing rate %0d:%0d", _n, _m);
+ test_rate(_n, _m, _n*spp*3, spp, 1, 1);
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ #2000; // Delay to make the tests visually distinct in waveform viewer
+
+ /********************************************************
+ ** Test 3 -- Test partial packets
+ ** - Send packets with extra data that is less than SPP.
+ ** Module should output the maximum number of samples
+ ** possible while dropping the "partial" sample.
+ ********************************************************/
+ `TEST_CASE_START("Test partial packets");
+ for (int _n = 1; _n <= MAX_N; _n++) begin
+ for (int _m = 1; _m <= MAX_M; _m++) begin
+ $display("Testing rate %0d:%0d", _n, _m);
+ test_rate(_n, _m, _n*spp + spp-1, spp, 1, 1);
+ end
+ end
+ `TEST_CASE_DONE(1);
+
+ #2000;
+
+ /********************************************************
+ ** Test 3 -- Test for bubble states
+ ** - Send many packets at full rate and make sure number
+ ** of input clock cycles == output clock cycles. If
+ ** they do not match, then the module likely has
+ ** bubble states that would prevent it from running
+ ** continuously at full rate.
+ ********************************************************/
+ `TEST_CASE_START("Test for bubble states");
+ clock_cnt_en = 1'b1;
+ number_words = 100000;
+ test_rate(1, 1, number_words, spp, 0, 0);
+ $sformat(s, "Incorrect number of clock cycles -- Possible bubble states detected! Expected: %0d, Actual: %0d", number_words, clock_cnt);
+ `ASSERT_FATAL(clock_cnt == number_words, s);
+ clock_cnt_en = 1'b0;
+ `TEST_CASE_DONE(1);
+
+ `TEST_BENCH_DONE;
+
+ end
+
+ // The warning, error signals should never assert.
+ initial begin
+ while (reset) @(posedge clk);
+ forever begin
+ @(posedge clk);
+ `ASSERT_FATAL(~warning_long_throttle, "Throttle state deadlock!");
+ `ASSERT_FATAL(~error_extra_outputs, "Extra outputs detected!");
+ `ASSERT_FATAL(~error_drop_pkt_lockup, "Drop packet deadlock!");
+ end
+ end
+
+endmodule
diff --git a/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/wave.do b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/wave.do
new file mode 100644
index 000000000..f16b9d5a7
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_rate_change/wave.do
@@ -0,0 +1,115 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/clk
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/reset
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/clear
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/clear_user
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/active
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_tuser
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_frac
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/in_pkt_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_reg_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_reg_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_reg_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_reg_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/i_reg_tuser
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/m_axis_data_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/m_axis_data_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/m_axis_data_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/m_axis_data_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/s_axis_data_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/s_axis_data_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/s_axis_data_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/s_axis_data_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/out_payload_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/payload_length_out
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_m
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_fifo_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_fifo_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/word_cnt_div_n_fifo_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/first_pkt_out
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/vita_time_out
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/vita_time_accum
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/vita_time_reg
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/header_fifo_out_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/header_fifo_out_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_reg_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_reg_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_reg_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_reg_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_reg_tuser
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/o_tuser
+add wave -noupdate -divider {AXI Drop Partial Packet}
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_terror
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_tlast_int
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/i_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/in_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/large_pkt
+add wave -noupdate {/axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/o_tdata[32]}
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/o_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/o_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/o_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/o_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/small_pkt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/flush
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/hold_last_sample
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/in_pkt_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/out_pkt_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/release_due_to_error
+add wave -noupdate -divider {AXI Drop Packet}
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/hold
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/i_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/i_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/i_terror
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/i_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/i_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/empty
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/full
+add wave -noupdate -radix unsigned /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/rd_addr
+add wave -noupdate -radix unsigned /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/wr_addr
+add wave -noupdate -radix unsigned /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/in_pkt_cnt
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/int_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/int_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/int_tlast
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/int_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/mem
+add wave -noupdate -radix hexadecimal /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/o_tdata
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/o_tvalid
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/o_tready
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/o_tlast
+add wave -noupdate -radix unsigned /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/out_pkt_cnt
+add wave -noupdate -radix unsigned /axi_rate_change_tb/axi_rate_change/axi_drop_partial_packet/axi_drop_packet/prev_wr_addr
+add wave -noupdate /axi_rate_change_tb/axi_rate_change/n
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {1112517 ps} 0} {{Cursor 2} {1974349848 ps} 0}
+quietly wave cursor active 2
+configure wave -namecolwidth 633
+configure wave -valuecolwidth 184
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ns
+update
+WaveRestoreZoom {1974303474 ps} {1974374671 ps}
diff --git a/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/axi_wrapper_tb.v b/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/axi_wrapper_tb.v
new file mode 100644
index 000000000..7a15d1d86
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/axi_wrapper_tb.v
@@ -0,0 +1,144 @@
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module axi_wrapper_tb();
+
+ xlnx_glbl glbl (.GSR(),.GTS());
+
+ localparam STR_SINK_FIFOSIZE = 9;
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("axi_wrapper_tb.vcd");
+ initial $dumpvars(0,axi_wrapper_tb);
+
+ initial #1000000 $finish;
+
+ wire [31:0] set_data;
+ wire [7:0] set_addr;
+ wire set_stb;
+
+ wire [63:0] noci_tdata[PORTS-1:0];
+ wire noci_tlast[PORTS-1:0];
+ wire noci_tvalid[PORTS-1:0];
+ wire noci_tready[PORTS-1:0];
+
+ wire [63:0] noco_tdata[PORTS-1:0];
+ wire noco_tlast[PORTS-1:0];
+ wire noco_tvalid[PORTS-1:0];
+ wire noco_tready[PORTS-1:0];
+
+ reg [63:0] src_tdata;
+ reg src_tlast, src_tvalid;
+ wire src_tready;
+
+ localparam PORTS = 4;
+
+ wire [63:0] s1o_tdata, s1i_tdata;
+ wire s1o_tlast, s1i_tlast, s1o_tvalid, s1i_tvalid, s1o_tready, s1i_tready;
+
+ wire [31:0] pre_tdata, post_tdata;
+ wire pre_tlast, post_tlast, pre_tvalid, post_tvalid, pre_tready, post_tready;
+ wire [127:0] pre_tuser, post_tuser;
+
+ axi_wrapper #(.BASE(8), .NUM_AXI_CONFIG_BUS(1), .CONFIG_BUS_FIFO_DEPTH(5), .SIMPLE_MODE(1)) axi_wrapper_ce1
+ (.clk(clk), .reset(reset),
+ .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ .i_tdata(src_tdata), .i_tlast(src_tlast), .i_tvalid(src_tvalid), .i_tready(src_tready),
+ .o_tdata(s1i_tdata), .o_tlast(s1i_tlast), .o_tvalid(s1i_tvalid), .o_tready(s1i_tready),
+ .m_axis_data_tdata(pre_tdata),
+ .m_axis_data_tuser(pre_tuser),
+ .m_axis_data_tlast(pre_tlast),
+ .m_axis_data_tvalid(pre_tvalid),
+ .m_axis_data_tready(pre_tready),
+ .s_axis_data_tdata(post_tdata),
+ .s_axis_data_tuser(post_tuser),
+ .s_axis_data_tlast(post_tlast),
+ .s_axis_data_tvalid(post_tvalid),
+ .s_axis_data_tready(post_tready)
+ );
+
+ axi_fifo #(.WIDTH(33)) afifo
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({pre_tlast,pre_tdata}), .i_tvalid(pre_tvalid), .i_tready(pre_tready),
+ .o_tdata({post_tlast,post_tdata}), .o_tvalid(post_tvalid), .o_tready(post_tready));
+
+ assign s1i_tready = 1'b1;
+
+
+ task SendPacket;
+ input [3:0] flags;
+ input [11:0] seqnum;
+ input [15:0] len;
+ input [31:0] sid;
+ input [63:0] data;
+
+ begin
+ @(posedge clk);
+ src_tdata <= { flags, seqnum, len+16'd8 + (flags[1] ? 16'd8 : 16'd0), sid };
+ src_tlast <= 0;
+ src_tvalid <= 1;
+ @(posedge clk);
+ while(~src_tready)
+ @(posedge clk);
+
+ // send time if flags request it
+ if(flags[1])
+ begin
+ src_tdata <= 64'h0123_4567_89ab_cdef;
+ src_tlast <= 0;
+ src_tvalid <= 1;
+ @(posedge clk);
+ while(~src_tready)
+ @(posedge clk);
+ end
+
+ src_tdata <= data;
+ repeat(len[15:3] + (len[2]|len[1]|len[0])- 1 )
+ begin
+ @(posedge clk);
+ while(~src_tready)
+ @(posedge clk);
+ src_tdata <= src_tdata + 64'd1;
+ end
+ src_tlast <= 1;
+ @(posedge clk);
+ while(~src_tready)
+ @(posedge clk);
+ src_tvalid <= 0;
+ @(posedge clk);
+ end
+ endtask // SendPacket
+
+ initial
+ begin
+ src_tdata <= 64'd0;
+ src_tlast <= 1'b0;
+ src_tvalid <= 1'b0;
+ @(negedge reset);
+ @(posedge clk);
+
+ @(posedge clk);
+
+ #10000;
+ SendPacket(4'h0, 12'd7, 16'd64, 32'h0002_0003, 64'hAAAA_AAAA_0000_0000); // data packet
+ SendPacket(4'h0, 12'd8, 16'd68, 32'h0004_0005, 64'hBBBB_BBBB_0000_0000); // data packet
+ //SendPacket(4'h0, 12'd2, 16'd8, 32'h0000_0001, 64'hCCCC_CCCC_0000_0000); // data packet
+ //SendPacket(4'h0, 12'd3, 16'd8, 32'h0000_0001, 64'hDDDD_DDDD_0000_0000); // data packet
+ //SendPacket(4'h0, 12'd4, 16'd8, 32'h0000_0001, 64'hEEEE_EEEE_0000_0000); // data packet
+ //SendPacket(4'h0, 12'd5, 16'd8, 32'h0000_0001, 64'hFFFF_FFFF_0000_0000); // data packet
+ //SendPacket(4'h0, 12'd6, 16'd8, 32'h0000_0001, 64'h2222_2222_0000_0000); // data packet
+ end
+
+endmodule // axi_wrapper_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/build_axi_wrapper_tb b/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/build_axi_wrapper_tb
new file mode 100755
index 000000000..49b8fe312
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/axi_wrapper/build_axi_wrapper_tb
@@ -0,0 +1 @@
+iverilog -o axi_wrapper_tb axi_wrapper_tb.v -y . -y ../control/ -y ../fifo/ -y /opt/Xilinx/14.6/ISE_DS/ISE/verilog/src/unisims/ -y ../packet_proc/ -y ../timing/ -y ../vita/ -y ../../top/x300/coregen -y /opt/Xilinx/14.4/ISE_DS/ISE/verilog/src/XilinxCoreLib -y ../coregen/ -y ../ -y ../../../usrp2/models/ -Wall
diff --git a/fpga/usrp3/lib/sim/rfnoc/chdr_deframer/chdr_deframer_tb.v b/fpga/usrp3/lib/sim/rfnoc/chdr_deframer/chdr_deframer_tb.v
new file mode 100644
index 000000000..312ca478d
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/chdr_deframer/chdr_deframer_tb.v
@@ -0,0 +1,87 @@
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+//`timescale 1ns
+module chdr_deframer_tb();
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial $dumpfile("chdr_deframer_tb.vcd");
+ initial $dumpvars(0,chdr_deframer_tb);
+
+ reg [63:0] i_tdata;
+ reg i_tlast, i_tvalid;
+ wire i_tready;
+
+ wire [31:0] o_tdata;
+ wire [127:0] o_tuser;
+ wire o_tlast, o_tvalid;
+
+ reg o_tready = 1;
+
+ wire [63:0] int_tdata;
+ wire int_tlast, int_tvalid, int_tready;
+
+ axi_fifo #(.SIZE(10), .WIDTH(65)) fifo
+ (.clk(clk), .reset(reset), .clear(0),
+ .i_tdata({i_tlast, i_tdata}), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata({int_tlast, int_tdata}), .o_tvalid(int_tvalid), .o_tready(int_tready));
+
+ chdr_deframer chdr_deframer
+ (.clk(clk), .reset(reset), .clear(0),
+ .i_tdata(int_tdata), .i_tlast(int_tlast), .i_tvalid(int_tvalid), .i_tready(int_tready),
+ .o_tdata(o_tdata), .o_tuser(o_tuser), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
+
+ reg [63:0] hdr, vtime, data;
+
+ initial
+ begin
+ clk = 0;
+ reset = 1;
+ i_tlast = 0;
+ i_tvalid = 0;
+ hdr = 64'hFF00_AAB9_BEEF_0000;
+ vtime = 64'h8888_7777_6666_0000;
+ data = 64'hEEEE_0000_FFFF_0001;
+ #1000 reset = 0;
+ repeat (10)
+ @(posedge clk);
+ repeat (6)
+ begin
+ #1 i_tdata = hdr;
+ #1 i_tlast = 0;
+ #1 i_tvalid = 1;
+ @(posedge clk);
+ #1 i_tdata = vtime;
+ @(posedge clk);
+ #1 hdr = hdr + 1;
+ #1 vtime = vtime + 1;
+ repeat (10)
+ begin
+ #1 i_tdata = data;
+ #1 data = data + 64'h0000_0002_0000_0002;
+ @(posedge clk);
+ end
+ #1 i_tdata = data;
+ #1 data = data + 64'h0000_0002_0000_0002;
+ #1 i_tlast <= 1;
+ @(posedge clk);
+ end // repeat (20)
+ #1 i_tvalid <= 0;
+ #200000 $finish;
+ end
+
+ always @(posedge clk)
+ if(o_tvalid & o_tready)
+ if(o_tlast)
+ $display("%x LAST",o_tdata);
+ else
+ $display("%x",o_tdata);
+
+endmodule // chdr_deframer_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/chdr_framer/chdr_framer_tb.v b/fpga/usrp3/lib/sim/rfnoc/chdr_framer/chdr_framer_tb.v
new file mode 100644
index 000000000..71b507e35
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/chdr_framer/chdr_framer_tb.v
@@ -0,0 +1,80 @@
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+//`timescale 1ns
+module chdr_framer_tb();
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial $dumpfile("chdr_framer_tb.vcd");
+ initial $dumpvars(0,chdr_framer_tb);
+
+ reg [31:0] i_tdata;
+ reg [127:0] i_tuser;
+ reg i_tlast, i_tvalid;
+ wire i_tready;
+
+ wire [63:0] o_tdata;
+ wire o_tlast, o_tvalid;
+
+ reg o_tready = 0;
+
+ chdr_framer #(.SIZE(10)) chdr_framer
+ (.clk(clk), .reset(reset), .clear(0),
+ .i_tdata(i_tdata), .i_tuser(i_tuser), .i_tlast(i_tlast), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata(o_tdata), .o_tlast(o_tlast), .o_tvalid(o_tvalid), .o_tready(o_tready));
+
+ always
+ begin
+ #1 o_tready = 1;
+ repeat (200)
+ @(posedge clk);
+ #1 o_tready = 0;
+ repeat (120)
+ @(posedge clk);
+ end
+
+
+ initial
+ begin
+ clk = 0;
+ reset = 1;
+ i_tlast = 0;
+ i_tvalid = 0;
+ i_tdata = 32'hBEEF_0000;
+ i_tuser = 128'hF123_4567_89ab_cdef_0011_2233_4455_0000;
+ #1000 reset = 0;
+ repeat (10)
+ @(posedge clk);
+ #1 i_tvalid = 1;
+ repeat (400)
+ begin
+ #1 i_tlast = 0;
+ repeat (22)
+ begin
+ #1 i_tdata = i_tdata + 1;
+ @(posedge clk);
+ end
+ #1 i_tdata = i_tdata + 1;
+ #1 i_tlast = 1;
+ @(posedge clk);
+ #1 i_tuser <= i_tuser + 1;
+ end // repeat (20)
+ #1 i_tvalid <= 0;
+ #100000 $finish;
+ end
+
+ always @(posedge clk)
+ if(o_tvalid & o_tready)
+ if(o_tlast)
+ $display("%x LAST",o_tdata);
+ else
+ $display("%x",o_tdata);
+
+endmodule // chdr_framer_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/display_samples.grc b/fpga/usrp3/lib/sim/rfnoc/display_samples.grc
new file mode 100644
index 000000000..d900da4cc
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/display_samples.grc
@@ -0,0 +1,413 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Wed May 28 15:07:06 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>top_block</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_interleaved_short_to_complex</key>
+ <param>
+ <key>id</key>
+ <value>blocks_interleaved_short_to_complex_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vector_input</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(296, 296)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(524, 220)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_source</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_source_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>output.dat</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>short</value>
+ </param>
+ <param>
+ <key>repeat</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(165, 203)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(751, 242)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_scopesink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_scopesink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>Scope Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>v_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>v_offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>t_scale</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ac_couple</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>xy_mode</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>num_inputs</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>trig_mode</key>
+ <value>wxgui.TRIG_MODE_AUTO</value>
+ </param>
+ <param>
+ <key>y_axis_label</key>
+ <value>Counts</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(750, 134)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>blocks_file_source_0</source_block_id>
+ <sink_block_id>blocks_interleaved_short_to_complex_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_interleaved_short_to_complex_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>wxgui_scopesink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/fpga/usrp3/lib/sim/rfnoc/gen_samples.grc b/fpga/usrp3/lib/sim/rfnoc/gen_samples.grc
new file mode 100644
index 000000000..568c538ba
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/gen_samples.grc
@@ -0,0 +1,381 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+ <timestamp>Wed May 28 15:55:45 2014</timestamp>
+ <block>
+ <key>options</key>
+ <param>
+ <key>id</key>
+ <value>top_block</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value></value>
+ </param>
+ <param>
+ <key>author</key>
+ <value></value>
+ </param>
+ <param>
+ <key>description</key>
+ <value></value>
+ </param>
+ <param>
+ <key>window_size</key>
+ <value>1280, 1024</value>
+ </param>
+ <param>
+ <key>generate_options</key>
+ <value>wx_gui</value>
+ </param>
+ <param>
+ <key>category</key>
+ <value>Custom</value>
+ </param>
+ <param>
+ <key>run_options</key>
+ <value>prompt</value>
+ </param>
+ <param>
+ <key>run</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>max_nouts</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>realtime_scheduling</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 10)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>variable</key>
+ <param>
+ <key>id</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>value</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(10, 170)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_complex_to_interleaved_short</key>
+ <param>
+ <key>id</key>
+ <value>blocks_complex_to_interleaved_short_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(631, 265)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_file_sink</key>
+ <param>
+ <key>id</key>
+ <value>blocks_file_sink_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>file</key>
+ <value>test.dat</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>short</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>unbuffered</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>append</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(769, 142)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>wxgui_fftsink2</key>
+ <param>
+ <key>id</key>
+ <value>wxgui_fftsink2_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>title</key>
+ <value>FFT Plot</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>baseband_freq</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>y_per_div</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>y_divs</key>
+ <value>10</value>
+ </param>
+ <param>
+ <key>ref_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>ref_scale</key>
+ <value>2.0</value>
+ </param>
+ <param>
+ <key>fft_size</key>
+ <value>1024</value>
+ </param>
+ <param>
+ <key>fft_rate</key>
+ <value>15</value>
+ </param>
+ <param>
+ <key>peak_hold</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>average</key>
+ <value>False</value>
+ </param>
+ <param>
+ <key>avg_alpha</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>win</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>win_size</key>
+ <value></value>
+ </param>
+ <param>
+ <key>grid_pos</key>
+ <value></value>
+ </param>
+ <param>
+ <key>notebook</key>
+ <value></value>
+ </param>
+ <param>
+ <key>freqvar</key>
+ <value>None</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(626, 319)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>blocks_throttle</key>
+ <param>
+ <key>id</key>
+ <value>blocks_throttle_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samples_per_second</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>vlen</key>
+ <value>1</value>
+ </param>
+ <param>
+ <key>ignoretag</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(433, 164)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
+ <key>analog_sig_source_x</key>
+ <param>
+ <key>id</key>
+ <value>analog_sig_source_x_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>type</key>
+ <value>complex</value>
+ </param>
+ <param>
+ <key>samp_rate</key>
+ <value>samp_rate</value>
+ </param>
+ <param>
+ <key>waveform</key>
+ <value>analog.GR_COS_WAVE</value>
+ </param>
+ <param>
+ <key>freq</key>
+ <value>123.2435</value>
+ </param>
+ <param>
+ <key>amp</key>
+ <value>32000</value>
+ </param>
+ <param>
+ <key>offset</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(218, 177)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <connection>
+ <source_block_id>analog_sig_source_x_0</source_block_id>
+ <sink_block_id>blocks_throttle_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>blocks_complex_to_interleaved_short_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_complex_to_interleaved_short_0</source_block_id>
+ <sink_block_id>blocks_file_sink_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+ <connection>
+ <source_block_id>blocks_throttle_0</source_block_id>
+ <sink_block_id>wxgui_fftsink2_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
+</flow_graph>
diff --git a/fpga/usrp3/lib/sim/rfnoc/moving_sum/build_moving_sum_tb b/fpga/usrp3/lib/sim/rfnoc/moving_sum/build_moving_sum_tb
new file mode 100755
index 000000000..f7fd1e9c7
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/moving_sum/build_moving_sum_tb
@@ -0,0 +1 @@
+iverilog -o moving_sum_tb -y . -y ../control/ -y ../fifo/ moving_sum_tb.v -y /opt/Xilinx/14.4/ISE_DS/ISE/verilog/src/unisims/ -Wall
diff --git a/fpga/usrp3/lib/sim/rfnoc/moving_sum/moving_sum_tb.v b/fpga/usrp3/lib/sim/rfnoc/moving_sum/moving_sum_tb.v
new file mode 100644
index 000000000..4ce455af5
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/moving_sum/moving_sum_tb.v
@@ -0,0 +1,43 @@
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module moving_sum_tb();
+
+ //xlnx_glbl glbl (.GSR(),.GTS());
+
+ localparam STR_SINK_FIFOSIZE = 9;
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("moving_sum_tb.vcd");
+ initial $dumpvars(0,moving_sum_tb);
+
+ initial #1000000 $finish;
+
+ wire [15:0] i_tdata;
+ wire [25:0] o_tdata;
+ wire i_tvalid, i_tready, o_tvalid, o_tready;
+
+ moving_sum #(.MAX_LEN_LOG2(10), .WIDTH(16)) moving_sum
+ (.clk(clk), .reset(reset), .clear(0),
+ .len(20),
+ .i_tdata(i_tdata), .i_tlast(), .i_tvalid(i_tvalid), .i_tready(i_tready),
+ .o_tdata(o_tdata), .o_tlast(), .o_tvalid(o_tvalid), .o_tready(o_tready));
+
+ assign i_tdata = 1;
+ assign i_tvalid = 1;
+ assign o_tready = 1;
+
+
+endmodule // moving_sum_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/mult/mult_tb.v b/fpga/usrp3/lib/sim/rfnoc/mult/mult_tb.v
new file mode 100644
index 000000000..32b0d47fd
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/mult/mult_tb.v
@@ -0,0 +1,75 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module mult_tb();
+
+ xlnx_glbl glbl (.GSR(),.GTS());
+
+ localparam STR_SINK_FIFOSIZE = 9;
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("mult_tb.vcd");
+ initial $dumpvars(0,mult_tb);
+
+ initial #1000000 $finish;
+
+ localparam AW=25;
+ localparam BW=18;
+ localparam PW=48;
+
+ wire [AW-1:0] a_tdata;
+ wire [BW-1:0] b_tdata;
+ wire [PW-1:0] p_tdata;
+
+ wire a_tlast, a_tvalid, a_tready, b_tlast, b_tvalid, b_tready;
+ wire p_tlast, p_tvalid;
+ reg p_tready = 0;
+
+ reg ai_tvalid = 0;
+ reg bi_tvalid = 0;
+
+ counter #(.WIDTH(AW)) ca
+ (.clk(clk), .reset(reset), .clear(0),
+ .max(20),
+ .i_tlast(0), .i_tvalid(ai_tvalid), .i_tready(),
+ .o_tdata(a_tdata), .o_tlast(a_tlast), .o_tvalid(a_tvalid), .o_tready(a_tready));
+
+ counter #(.WIDTH(BW)) cb
+ (.clk(clk), .reset(reset), .clear(0),
+ .max(20),
+ .i_tlast(0), .i_tvalid(bi_tvalid), .i_tready(),
+ .o_tdata(b_tdata), .o_tlast(b_tlast), .o_tvalid(b_tvalid), .o_tready(b_tready));
+
+ mult #(.WIDTH_A(AW), .WIDTH_B(BW), .WIDTH_P(PW), .LATENCY(4)) mult
+ (.clk(clk), .reset(reset),
+ .a_tdata(a_tdata), .a_tlast(a_tlast), .a_tvalid(a_tvalid), .a_tready(a_tready),
+ .b_tdata(b_tdata), .b_tlast(b_tlast), .b_tvalid(b_tvalid), .b_tready(b_tready),
+ .p_tdata(p_tdata), .p_tlast(p_tlast), .p_tvalid(p_tvalid), .p_tready(p_tready));
+
+ initial
+ begin
+ @(negedge reset);
+ repeat (100)
+ @(posedge clk);
+ ai_tvalid <= 1;
+ repeat (10)
+ @(posedge clk);
+ bi_tvalid <= 1;
+ repeat (10)
+ @(posedge clk);
+ p_tready <= 1;
+ end
+
+endmodule // mult_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/mult_add/mult_add_tb.v b/fpga/usrp3/lib/sim/rfnoc/mult_add/mult_add_tb.v
new file mode 100644
index 000000000..23e772aba
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/mult_add/mult_add_tb.v
@@ -0,0 +1,90 @@
+//
+// Copyright 2014 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module mult_add_tb();
+
+ xlnx_glbl glbl (.GSR(),.GTS());
+
+ localparam STR_SINK_FIFOSIZE = 9;
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("mult_add_tb.vcd");
+ initial $dumpvars(0,mult_add_tb);
+
+ initial #1000000 $finish;
+
+ localparam AW=25;
+ localparam BW=18;
+ localparam PW=48;
+
+ wire [AW-1:0] a_tdata;
+ wire [BW-1:0] b_tdata;
+ wire [PW-1:0] pin_tdata;
+ wire [PW-1:0] pout_tdata;
+
+ wire a_tlast, a_tvalid, a_tready, b_tlast, b_tvalid, b_tready;
+ wire pin_tlast, pin_tvalid;
+ wire pout_tlast, pout_tvalid;
+ wire pin_tready;
+ reg pout_tready = 0;
+
+ reg ai_tvalid = 0;
+ reg bi_tvalid = 0;
+ reg pi_tvalid = 0;
+
+ counter #(.WIDTH(AW)) ca
+ (.clk(clk), .reset(reset), .clear(0),
+ .max(25'd20),
+ .i_tlast(0), .i_tvalid(ai_tvalid), .i_tready(),
+ .o_tdata(a_tdata), .o_tlast(a_tlast), .o_tvalid(a_tvalid), .o_tready(a_tready));
+
+ counter #(.WIDTH(BW)) cb
+ (.clk(clk), .reset(reset), .clear(0),
+ .max(18'd20),
+ .i_tlast(0), .i_tvalid(bi_tvalid), .i_tready(),
+ .o_tdata(b_tdata), .o_tlast(b_tlast), .o_tvalid(b_tvalid), .o_tready(b_tready));
+
+ counter #(.WIDTH(PW)) cp
+ (.clk(clk), .reset(reset), .clear(0),
+ .max(48'd20),
+ .i_tlast(0), .i_tvalid(pi_tvalid), .i_tready(),
+ .o_tdata(pin_tdata), .o_tlast(pin_tlast), .o_tvalid(pin_tvalid), .o_tready(pin_tready));
+
+ mult_add #(.WIDTH_A(AW), .WIDTH_B(BW), .WIDTH_P(PW),
+ .LATENCY(3), .CASCADE_IN(1), .CASCADE_OUT(1)) mult_add
+ (.clk(clk), .reset(reset),
+ .a_tdata(a_tdata), .a_tlast(a_tlast), .a_tvalid(a_tvalid), .a_tready(a_tready),
+ .b_tdata(b_tdata), .b_tlast(b_tlast), .b_tvalid(b_tvalid), .b_tready(b_tready),
+ .c_tdata(pin_tdata), .c_tlast(pin_tlast), .c_tvalid(pin_tvalid), .c_tready(pin_tready),
+ .p_tdata(pout_tdata), .p_tlast(pout_tlast), .p_tvalid(pout_tvalid), .p_tready(pout_tready));
+
+ initial
+ begin
+ @(negedge reset);
+ repeat (100)
+ @(posedge clk);
+ ai_tvalid <= 1;
+ repeat (10)
+ @(posedge clk);
+ bi_tvalid <= 1;
+ repeat (10)
+ @(posedge clk);
+ pi_tvalid <= 1;
+ repeat (10)
+ @(posedge clk);
+ pout_tready <= 1;
+ end
+
+endmodule // mult_add_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/null_source/null_source_tb.v b/fpga/usrp3/lib/sim/rfnoc/null_source/null_source_tb.v
new file mode 100644
index 000000000..c9cf29111
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/null_source/null_source_tb.v
@@ -0,0 +1,80 @@
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module null_source_tb();
+
+ reg clk, reset;
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("null_source_tb.vcd");
+ initial $dumpvars(0,null_source_tb);
+
+ //initial #10000000 $finish;
+
+ reg [31:0] set_data;
+ reg [7:0] set_addr;
+ reg set_stb=0;
+
+ wire [63:0] src_tdata;
+ wire src_tlast, src_tvalid;
+ wire src_tready;
+
+ assign src_tready = 1'b1;
+
+ localparam PORTS = 4;
+
+ null_source #(.BASE(0)) axi_wrapper_ce1
+ (.clk(clk), .reset(reset),
+ .set_stb(set_stb), .set_addr(set_addr), .set_data(set_data),
+ .o_tdata(src_tdata), .o_tlast(src_tlast), .o_tvalid(src_tvalid), .o_tready(src_tready) );
+
+ initial
+ begin
+
+ @(negedge reset);
+ @(posedge clk);
+ #100000;
+ @(posedge clk);
+ set_stb <= 1;
+ set_addr <= 0;
+ set_data <= 32'hDEADBEEF;
+ @(posedge clk);
+ set_stb <= 1;
+ set_addr <= 1; // Len
+ set_data <= 32'h8;
+ @(posedge clk);
+ set_stb <= 1;
+ set_addr <= 2;
+ set_data <= 32'h20; // Rate
+ @(posedge clk);
+ set_stb <= 1;
+ set_addr <= 3;
+ set_data <= 1; // enable
+ @(posedge clk);
+ set_stb <= 0;
+ @(posedge clk);
+ #1000000;
+ @(posedge clk);
+ set_stb <= 1;
+ set_addr <= 3;
+ set_data <= 0; // disable
+ @(posedge clk);
+ set_stb <= 0;
+ #1000000;
+
+ $finish;
+
+
+ end
+
+endmodule // null_source_tb
diff --git a/fpga/usrp3/lib/sim/rfnoc/window/build_window_tb b/fpga/usrp3/lib/sim/rfnoc/window/build_window_tb
new file mode 100755
index 000000000..1af299fd4
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/window/build_window_tb
@@ -0,0 +1 @@
+iverilog -o window_tb window_tb.v -y ../coregen -y ../../../usrp2/models -y . -y ../control/ -y ../fifo/ -y /opt/Xilinx/14.6/ISE_DS/ISE/verilog/src/unisims/ -y ../packet_proc/ -y ../timing/ -y ../vita/
diff --git a/fpga/usrp3/lib/sim/rfnoc/window/window_tb.v b/fpga/usrp3/lib/sim/rfnoc/window/window_tb.v
new file mode 100644
index 000000000..2449057c8
--- /dev/null
+++ b/fpga/usrp3/lib/sim/rfnoc/window/window_tb.v
@@ -0,0 +1,341 @@
+`timescale 1ns/1ps
+
+//
+// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+module window_tb();
+ xlnx_glbl glbl (.GSR(),.GTS());
+
+ localparam STR_SINK_FIFOSIZE = 11;
+
+ reg clk, reset;
+
+ localparam PORTS = 5;
+
+ wire [63:0] noci_tdata[PORTS-1:0];
+ wire [PORTS-1:0] noci_tlast;
+ wire [PORTS-1:0] noci_tvalid;
+ wire [PORTS-1:0] noci_tready;
+
+ wire [63:0] noco_tdata[PORTS-1:0];
+ wire [PORTS-1:0] noco_tlast;
+ wire [PORTS-1:0] noco_tvalid;
+ wire [PORTS-1:0] noco_tready;
+
+ wire [63:0] src_tdata;
+ wire src_tlast, src_tvalid;
+ wire src_tready;
+
+ reg [63:0] cmdout_tdata;
+ reg cmdout_tlast, cmdout_tvalid;
+ wire cmdout_tready;
+
+ wire [63:0] dst_tdata;
+ wire dst_tlast, dst_tvalid;
+ wire dst_tready = 1;
+
+ reg set_stb_xbar;
+ reg [15:0] set_addr_xbar;
+ reg [31:0] set_data_xbar;
+
+ always
+ #100 clk = ~clk;
+
+ initial clk = 0;
+ initial reset = 1;
+ initial #1000 reset = 0;
+
+ initial $dumpfile("window_tb.vcd");
+ initial $dumpvars(0,window_tb);
+
+ initial #3000000 $finish;
+
+
+ axi_crossbar #(.FIFO_WIDTH(64), .DST_WIDTH(16), .NUM_INPUTS(PORTS), .NUM_OUTPUTS(PORTS)) crossbar
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .local_addr(8'd0),
+ .pkt_present({noci_tvalid[4],noci_tvalid[3],noci_tvalid[2],noci_tvalid[1],noci_tvalid[0]}),
+
+ .i_tdata({noci_tdata[4],noci_tdata[3],noci_tdata[2],noci_tdata[1],noci_tdata[0]}),
+ .i_tlast({noci_tlast[4],noci_tlast[3],noci_tlast[2],noci_tlast[1],noci_tlast[0]}),
+ .i_tvalid({noci_tvalid[4],noci_tvalid[3],noci_tvalid[2],noci_tvalid[1],noci_tvalid[0]}),
+ .i_tready({noci_tready[4],noci_tready[3],noci_tready[2],noci_tready[1],noci_tready[0]}),
+
+ .o_tdata({noco_tdata[4],noco_tdata[3],noco_tdata[2],noco_tdata[1],noco_tdata[0]}),
+ .o_tlast({noco_tlast[4],noco_tlast[3],noco_tlast[2],noco_tlast[1],noco_tlast[0]}),
+ .o_tvalid({noco_tvalid[4],noco_tvalid[3],noco_tvalid[2],noco_tvalid[1],noco_tvalid[0]}),
+ .o_tready({noco_tready[4],noco_tready[3],noco_tready[2],noco_tready[1],noco_tready[0]}),
+
+ .set_stb(set_stb_xbar), .set_addr(set_addr_xbar), .set_data(set_data_xbar),
+ .rb_rd_stb(1'b0), .rb_addr(4'd0), .rb_data());
+
+ // Generator on port 0
+ wire set_stb_0;
+ wire [7:0] set_addr_0;
+ wire [31:0] set_data_0;
+
+ noc_shell #(.STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) noc_shell_0
+ (.bus_clk(clk), .bus_rst(reset),
+ .i_tdata(noco_tdata[0]), .i_tlast(noco_tlast[0]), .i_tvalid(noco_tvalid[0]), .i_tready(noco_tready[0]),
+ .o_tdata(noci_tdata[0]), .o_tlast(noci_tlast[0]), .o_tvalid(noci_tvalid[0]), .o_tready(noci_tready[0]),
+ .clk(clk), .reset(reset),
+ .set_data(set_data_0), .set_addr(set_addr_0), .set_stb(set_stb_0), .rb_data(64'd0),
+
+ .cmdout_tdata(64'h0), .cmdout_tlast(1'b0), .cmdout_tvalid(1'b0), .cmdout_tready(),
+ .ackin_tdata(), .ackin_tlast(), .ackin_tvalid(), .ackin_tready(1'b1),
+
+ .str_sink_tdata(), .str_sink_tlast(), .str_sink_tvalid(), .str_sink_tready(1'b1), // unused port
+ .str_src_tdata(src_tdata), .str_src_tlast(src_tlast), .str_src_tvalid(src_tvalid), .str_src_tready(src_tready)
+ );
+
+ file_source #(.BASE(8), .FILENAME("test.dat")) file_source
+ (.clk(clk), .reset(reset),
+ .set_data(set_data_0), .set_addr(set_addr_0), .set_stb(set_stb_0),
+ .o_tdata(src_tdata), .o_tlast(src_tlast), .o_tvalid(src_tvalid), .o_tready(src_tready));
+
+ // Simple FIR on port 1
+ wire [31:0] set_data_1;
+ wire [7:0] set_addr_1;
+ wire set_stb_1;
+ wire [63:0] s1o_tdata, s1i_tdata;
+ wire s1o_tlast, s1i_tlast, s1o_tvalid, s1i_tvalid, s1o_tready, s1i_tready;
+
+ wire [31:0] pre_tdata, post_tdata;
+ wire pre_tlast, pre_tvalid, pre_tready;
+ wire post_tlast, post_tvalid, post_tready;
+
+ wire [15:0] pre_i = pre_tdata[31:16];
+ wire [15:0] pre_q = pre_tdata[15:0];
+ wire [15:0] post_i = post_tdata[31:16];
+ wire [15:0] post_q = post_tdata[15:0];
+
+ noc_shell #(.STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) noc_shell_1
+ (.bus_clk(clk), .bus_rst(reset),
+ .i_tdata(noco_tdata[1]), .i_tlast(noco_tlast[1]), .i_tvalid(noco_tvalid[1]), .i_tready(noco_tready[1]),
+ .o_tdata(noci_tdata[1]), .o_tlast(noci_tlast[1]), .o_tvalid(noci_tvalid[1]), .o_tready(noci_tready[1]),
+ .clk(clk), .reset(reset),
+ .set_data(set_data_1), .set_addr(set_addr_1), .set_stb(set_stb_1), .rb_data(64'd0),
+
+ .cmdout_tdata(64'h0), .cmdout_tlast(1'b0), .cmdout_tvalid(1'b0), .cmdout_tready(),
+ .ackin_tdata(), .ackin_tlast(), .ackin_tvalid(), .ackin_tready(1'b1),
+
+ .str_sink_tdata(s1o_tdata), .str_sink_tlast(s1o_tlast), .str_sink_tvalid(s1o_tvalid), .str_sink_tready(s1o_tready),
+ .str_src_tdata(s1i_tdata), .str_src_tlast(s1i_tlast), .str_src_tvalid(s1i_tvalid), .str_src_tready(s1i_tready)
+ );
+
+ wire [31:0] axis_config_tdata1;
+ wire axis_config_tvalid1, axis_config_tready1, axis_config_tlast1;
+
+ axi_wrapper #(.BASE(8)) axi_wrapper_ce1
+ (.clk(clk), .reset(reset),
+ .set_stb(set_stb_1), .set_addr(set_addr_1), .set_data(set_data_1),
+ .i_tdata(s1o_tdata), .i_tlast(s1o_tlast), .i_tvalid(s1o_tvalid), .i_tready(s1o_tready),
+ .o_tdata(s1i_tdata), .o_tlast(s1i_tlast), .o_tvalid(s1i_tvalid), .o_tready(s1i_tready),
+ .m_axis_data_tdata(pre_tdata),
+ .m_axis_data_tlast(pre_tlast),
+ .m_axis_data_tvalid(pre_tvalid),
+ .m_axis_data_tready(pre_tready),
+ .s_axis_data_tdata(post_tdata),
+ .s_axis_data_tlast(post_tlast),
+ .s_axis_data_tvalid(post_tvalid),
+ .s_axis_data_tready(post_tready),
+ .m_axis_config_tdata(axis_config_tdata1),
+ .m_axis_config_tlast(axis_config_tlast1),
+ .m_axis_config_tvalid(axis_config_tvalid1),
+ .m_axis_config_tready(axis_config_tready1)
+ );
+
+ window #(.BASE(0)) window
+ (.clk(clk), .reset(reset), .clear(clear),
+ .set_stb(set_stb_1), .set_addr(set_addr_1), .set_data(set_data_1),
+ .i_tdata(pre_tdata), .i_tlast(pre_tlast), .i_tvalid(pre_tvalid), .i_tready(pre_tready),
+ .o_tdata(post_tdata), .o_tlast(post_tlast), .o_tvalid(post_tvalid), .o_tready(post_tready));
+
+ assign axis_config_tready1 = 1'b1;
+
+ // Dumper on port 2
+ noc_shell #(.STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) noc_shell_2
+ (.bus_clk(clk), .bus_rst(reset),
+ .i_tdata(noco_tdata[2]), .i_tlast(noco_tlast[2]), .i_tvalid(noco_tvalid[2]), .i_tready(noco_tready[2]),
+ .o_tdata(noci_tdata[2]), .o_tlast(noci_tlast[2]), .o_tvalid(noci_tvalid[2]), .o_tready(noci_tready[2]),
+
+ .clk(clk), .reset(reset),
+ .set_data(), .set_addr(), .set_stb(), .rb_data(64'd0),
+
+ .cmdout_tdata(64'h0), .cmdout_tlast(1'b0), .cmdout_tvalid(1'b0), .cmdout_tready(),
+ .ackin_tdata(), .ackin_tlast(), .ackin_tvalid(), .ackin_tready(1'b1),
+
+ .str_sink_tdata(dst_tdata), .str_sink_tlast(dst_tlast), .str_sink_tvalid(dst_tvalid), .str_sink_tready(dst_tready),
+ .str_src_tdata(64'd0), .str_src_tlast(1'd0), .str_src_tvalid(1'b0), .str_src_tready() // unused port
+ );
+
+ // Control Source on port 3
+ noc_shell #(.STR_SINK_FIFOSIZE(STR_SINK_FIFOSIZE)) noc_shell_3
+ (.bus_clk(clk), .bus_rst(reset),
+ .i_tdata(noco_tdata[3]), .i_tlast(noco_tlast[3]), .i_tvalid(noco_tvalid[3]), .i_tready(noco_tready[3]),
+ .o_tdata(noci_tdata[3]), .o_tlast(noci_tlast[3]), .o_tvalid(noci_tvalid[3]), .o_tready(noci_tready[3]),
+
+ .clk(clk), .reset(reset),
+ .set_data(), .set_addr(), .set_stb(), .rb_data(64'd0),
+
+ .cmdout_tdata(cmdout_tdata), .cmdout_tlast(cmdout_tlast), .cmdout_tvalid(cmdout_tvalid), .cmdout_tready(cmdout_tready),
+ .ackin_tdata(), .ackin_tlast(), .ackin_tvalid(), .ackin_tready(1'b1),
+
+ .str_sink_tdata(), .str_sink_tlast(), .str_sink_tvalid(), .str_sink_tready(1'b1), // unused port
+ .str_src_tdata(64'd0), .str_src_tlast(1'd0), .str_src_tvalid(1'b0), .str_src_tready() // unused port
+ );
+
+ // ////////////////////////////////////////////////////////////////////////////////////
+
+ task SetXbar;
+ input [15:0] start_reg;
+ input [7:0] start_val;
+
+ begin
+ repeat (PORTS)
+ begin
+ repeat (1)
+ begin
+ SetXbar_reg(start_reg,start_val);
+ start_reg <= start_reg + 1;
+ @(posedge clk);
+ end
+ start_val <= start_val + 1;
+ @(posedge clk);
+ end
+ end
+ endtask // SetXbar
+
+ task SetXbar_reg;
+ input [15:0] addr;
+ input [31:0] data;
+ begin
+ @(posedge clk);
+ set_stb_xbar <= 1'b1;
+ set_addr_xbar <= addr;
+ set_data_xbar <= data;
+ @(posedge clk);
+ set_stb_xbar <= 1'b0;
+ @(posedge clk);
+ end
+ endtask // set_xbar
+
+ task SendCtrlPacket;
+ input [11:0] seqnum;
+ input [31:0] sid;
+ input [63:0] data;
+
+ begin
+ @(posedge clk);
+ cmdout_tdata <= { 4'h8, seqnum, 16'h16, sid };
+ cmdout_tlast <= 0;
+ cmdout_tvalid <= 1;
+ while(~cmdout_tready) #1;
+
+ @(posedge clk);
+ cmdout_tdata <= data;
+ cmdout_tlast <= 1;
+ while(~cmdout_tready) #1;
+
+ @(posedge clk);
+ cmdout_tvalid <= 0;
+ @(posedge clk);
+ end
+ endtask // SendCtrlPacket
+
+ initial
+ begin
+ cmdout_tdata <= 64'd0;
+ cmdout_tlast <= 1'b0;
+ cmdout_tvalid <= 1'b0;
+
+ @(negedge reset);
+ @(posedge clk);
+ SetXbar(256,0);
+
+ @(posedge clk);
+ // Port 0
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'h0, 32'h0000_0003}); // Command packet to set up source control window size
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'h1, 32'h0000_0001}); // Command packet to set up source control window enable
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'h3, 32'h8000_0001}); // Command packet to set up flow control
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'h8, 32'h0000_0001}); // Command packet to set up SID
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'hA, 32'h0000_0002}); // Command packet to set up Rate
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'hB, 32'h0000_0001}); // Command packet to set up send_time_field
+ SendCtrlPacket(12'd0, 32'h0003_0000, {32'h9, 32'h0000_0200}); // Command packet to set up Len
+ #10000;
+ // Port 1
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h0, 32'h0000_0013}); // Command packet to set up source control window size
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h1, 32'h0000_0001}); // Command packet to set up source control window enable
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h3, 32'h8000_0001}); // Command packet to set up flow control
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h8, 32'h0001_0002}); // Rewrite SID, send on to port 2
+
+
+ #10000;
+ // Port 2
+ SendCtrlPacket(12'd0, 32'h0003_0002, {32'h0, 32'h0000_0003}); // Command packet to set up source control window size
+ SendCtrlPacket(12'd0, 32'h0003_0002, {32'h1, 32'h0000_0001}); // Command packet to set up source control window enable
+ SendCtrlPacket(12'd0, 32'h0003_0002, {32'h3, 32'h8000_0001}); // Command packet to set up flow control
+
+ #1000000;
+ // WINDOW filter
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd0}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd1}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd2}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd3}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd4}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd5}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd6}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd7}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h11, 32'd8}); // frame_len (FFTsize)
+
+ #1000000;
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h10, 32'd100000}); // frame_len (FFTsize)
+ SendCtrlPacket(12'd0, 32'h0003_0001, {32'h11, 32'd100000}); // frame_len (FFTsize)
+
+ end
+
+ reg in_packet = 0;
+
+ integer outfile;
+
+ initial
+ begin
+ outfile = $fopen("output.dat","wb");
+ //src_tready <= 1'b1;
+ end
+
+ wire signed [15:0] a,b,c,d;
+ assign a = src_tdata[63:48];
+ assign b = src_tdata[47:32];
+ assign c = src_tdata[31:16];
+ assign d = src_tdata[15:0];
+
+ always @(posedge clk)
+ if(src_tready & src_tvalid)
+ begin
+ if(src_tlast)
+ in_packet <= 0;
+ else
+ in_packet <= 1;
+ if(in_packet)
+ begin
+ //$fwrite(outfile,"%u",{q_out[15:0],i_out[15:0]}); // Correct endianness for GR
+ //$write("%d,%d,%d,%d,",a,b,c,d);
+ $fwrite(outfile,"%u",{dst_tdata[47:32],dst_tdata[63:48]});
+ $fwrite(outfile,"%u",{dst_tdata[15:0],dst_tdata[31:16]});
+ end
+ end
+
+endmodule // window_tb
diff --git a/fpga/usrp3/lib/sim/simple_gemac/ll8_to_axi64/ll8_to_axi64_tb.v b/fpga/usrp3/lib/sim/simple_gemac/ll8_to_axi64/ll8_to_axi64_tb.v
new file mode 100644
index 000000000..ef10a7c9a
--- /dev/null
+++ b/fpga/usrp3/lib/sim/simple_gemac/ll8_to_axi64/ll8_to_axi64_tb.v
@@ -0,0 +1,100 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+`timescale 1ns/1ps
+
+module ll8_to_axi64_tb();
+
+ reg clk = 0;
+ reg reset = 1;
+
+ always #10 clk = ~clk;
+
+ initial $dumpfile("ll8_to_axi64_tb.vcd");
+ initial $dumpvars(0,ll8_to_axi64_tb);
+
+ initial
+ begin
+ #1000 reset = 0;
+ #2000000;
+ $finish;
+ end
+
+ wire [63:0] tdata, tdata_int;
+ wire [3:0] tuser, tuser_int;
+ wire tlast, tlast_int;
+ wire tvalid, tvalid_int, tready, tready_int;
+
+ reg [7:0] ll_data;
+ reg ll_eof, ll_error, ll_src_rdy;
+ wire ll_dst_rdy;
+
+ wire [7:0] ll_data2;
+ wire ll_eof2, ll_src_rdy2, ll_dst_rdy2;
+
+ localparam RPT_COUNT = 12;
+
+ initial
+ begin
+ ll_src_rdy <= 0;
+
+ while(reset)
+ @(posedge clk);
+
+ @(posedge clk);
+
+ {ll_error, ll_eof, ll_data} <= { 1'b0, 1'b0, 8'hA0 };
+ repeat(RPT_COUNT-1)
+ begin
+ ll_src_rdy <= 1;
+ @(posedge clk);
+ ll_data <= ll_data + 1;
+ end
+ ll_eof <= 1;
+ ll_data <= ll_data + 1;
+ @(posedge clk);
+
+ {ll_error, ll_eof, ll_data} <= { 1'b0, 1'b0, 8'hC0 };
+ repeat(RPT_COUNT-1)
+ begin
+ ll_src_rdy <= 1;
+ @(posedge clk);
+ ll_data <= ll_data + 1;
+ end
+ ll_eof <= 1; ll_error <= 1;
+ ll_data <= ll_data + 1;
+ @(posedge clk);
+ ll_src_rdy <= 1'b0;
+
+ end
+
+ ll8_to_axi64 #(.START_BYTE(6), .LABEL(8'h89)) ll8_to_axi64
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .ll_data(ll_data), .ll_eof(ll_eof), .ll_error(ll_error), .ll_src_rdy(ll_src_rdy), .ll_dst_rdy(ll_dst_rdy),
+ .axi64_tdata(tdata), .axi64_tlast(tlast), .axi64_tuser(tuser), .axi64_tvalid(tvalid), .axi64_tready(tready) );
+
+ axi_fifo_short #(.WIDTH(69)) axi_fifo_short
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .i_tdata({tlast,tuser,tdata}), .i_tvalid(tvalid), .i_tready(tready),
+ .o_tdata({tlast_int,tuser_int,tdata_int}), .o_tvalid(tvalid_int), .o_tready(tready_int));
+
+ axi64_to_ll8 #(.START_BYTE(6)) axi64_to_ll8
+ (.clk(clk), .reset(reset), .clear(1'b0),
+ .axi64_tdata(tdata_int), .axi64_tlast(tlast_int), .axi64_tuser(tuser_int), .axi64_tvalid(tvalid_int), .axi64_tready(tready_int),
+ .ll_data(ll_data2), .ll_eof(ll_eof2), .ll_src_rdy(ll_src_rdy2), .ll_dst_rdy(ll_dst_rdy2) );
+
+ /*
+ always @(posedge clk)
+ if(ll_src_rdy2 & ll_dst_rdy2)
+ $display("EOF %x\tDATA %x",ll_eof2, ll_data2);
+
+ */
+ assign ll_dst_rdy2 = 1;
+
+ always @(posedge clk)
+ if(tvalid_int & tready_int)
+ $display("TERR %x\tTUSER %x\tTLAST %x\tTDATA %x",tuser_int[3],tuser_int[2:0], tlast_int, tdata_int);
+
+endmodule // ll8_to_axi64_tb
diff --git a/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_tb.v b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_tb.v
new file mode 100644
index 000000000..c65db6c98
--- /dev/null
+++ b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_tb.v
@@ -0,0 +1,208 @@
+//
+// Copyright 2011 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+
+
+module simple_gemac_tb;
+`include "eth_tasks.v"
+
+ reg clk = 0;
+ reg reset = 1;
+
+ initial #1000 reset = 0;
+ always #50 clk = ~clk;
+
+ wire GMII_RX_DV, GMII_RX_ER, GMII_TX_EN, GMII_TX_ER, GMII_GTX_CLK;
+ wire [7:0] GMII_RXD, GMII_TXD;
+
+ wire rx_valid, rx_error, rx_ack;
+ wire tx_ack, tx_valid, tx_error;
+
+ wire [7:0] rx_data, tx_data;
+
+ reg [15:0] pause_time;
+ reg pause_req = 0;
+
+ wire GMII_RX_CLK = GMII_GTX_CLK;
+
+ reg [7:0] FORCE_DAT_ERR = 0;
+ reg FORCE_ERR = 0;
+
+ // Loopback
+ assign GMII_RX_DV = GMII_TX_EN;
+ assign GMII_RX_ER = GMII_TX_ER | FORCE_ERR;
+ assign GMII_RXD = GMII_TXD ^ FORCE_DAT_ERR;
+
+ wire [47:0] ucast_addr = 48'hF1F2_F3F4_F5F6;
+ wire [47:0] mcast_addr = 0;
+ wire pass_ucast =1, pass_mcast=0, pass_bcast=1, pass_pause=0, pass_all=0;
+
+ simple_gemac simple_gemac
+ (.clk125(clk), .reset(reset),
+ .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),
+ .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
+ .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV),
+ .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),
+ .pause_req(pause_req), .pause_time(pause_time), .pause_en(1),
+ .ucast_addr(ucast_addr), .mcast_addr(mcast_addr),
+ .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast),
+ .pass_pause(pass_pause), .pass_all(pass_all),
+ .rx_clk(rx_clk), .rx_data(rx_data),
+ .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),
+ .tx_clk(tx_clk), .tx_data(tx_data),
+ .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack)
+ );
+
+ wire rx_ll_sof, rx_ll_eof, rx_ll_src_rdy, rx_ll_dst_rdy;
+ wire rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2;
+ reg rx_ll_dst_rdy2 = 1;
+ wire [7:0] rx_ll_data, rx_ll_data2;
+ wire rx_ll_error, rx_ll_error2;
+
+ rxmac_to_ll8 rx_adapt
+ (.clk(clk), .reset(reset), .clear(0),
+ .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack),
+ .ll_data(rx_ll_data), .ll_sof(rx_ll_sof), .ll_eof(rx_ll_eof), .ll_error(rx_ll_error),
+ .ll_src_rdy(rx_ll_src_rdy), .ll_dst_rdy(rx_ll_dst_rdy));
+
+ ll8_shortfifo rx_sfifo
+ (.clk(clk), .reset(reset), .clear(0),
+ .datain(rx_ll_data), .sof_i(rx_ll_sof), .eof_i(rx_ll_eof),
+ .error_i(rx_ll_error), .src_rdy_i(rx_ll_src_rdy), .dst_rdy_o(rx_ll_dst_rdy),
+ .dataout(rx_ll_data2), .sof_o(rx_ll_sof2), .eof_o(rx_ll_eof2),
+ .error_o(rx_ll_error2), .src_rdy_o(rx_ll_src_rdy2), .dst_rdy_i(rx_ll_dst_rdy2));
+
+ wire tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy;
+ reg tx_ll_sof2=0, tx_ll_eof2=0;
+ reg tx_ll_src_rdy2 = 0;
+ wire tx_ll_dst_rdy2;
+ wire [7:0] tx_ll_data;
+ reg [7:0] tx_ll_data2 = 0;
+ wire tx_ll_error;
+ wire tx_ll_error2 = 0;
+
+ ll8_shortfifo tx_sfifo
+ (.clk(clk), .reset(reset), .clear(clear),
+ .datain(tx_ll_data2), .sof_i(tx_ll_sof2), .eof_i(tx_ll_eof2),
+ .error_i(tx_ll_error2), .src_rdy_i(tx_ll_src_rdy2), .dst_rdy_o(tx_ll_dst_rdy2),
+ .dataout(tx_ll_data), .sof_o(tx_ll_sof), .eof_o(tx_ll_eof),
+ .error_o(tx_ll_error), .src_rdy_o(tx_ll_src_rdy), .dst_rdy_i(tx_ll_dst_rdy));
+
+ ll8_to_txmac ll8_to_txmac
+ (.clk(clk), .reset(reset), .clear(clear),
+ .ll_data(tx_ll_data), .ll_sof(tx_ll_sof), .ll_eof(tx_ll_eof),
+ .ll_src_rdy(tx_ll_src_rdy), .ll_dst_rdy(tx_ll_dst_rdy),
+ .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack));
+
+ initial $dumpfile("simple_gemac_tb.vcd");
+ initial $dumpvars(0,simple_gemac_tb);
+
+ integer i;
+ reg [7:0] pkt_rom[0:65535];
+ reg [1023:0] ROMFile;
+
+ initial
+ for (i=0;i<65536;i=i+1)
+ pkt_rom[i] <= 8'h0;
+
+ initial
+ begin
+ @(negedge reset);
+ repeat (10)
+ @(posedge clk);
+ SendFlowCtrl(16'h0007); // Send flow control
+ @(posedge clk);
+ #30000;
+ @(posedge clk);
+ SendFlowCtrl(16'h0009); // Increas flow control before it expires
+ #10000;
+ @(posedge clk);
+ SendFlowCtrl(16'h0000); // Cancel flow control before it expires
+ @(posedge clk);
+
+ SendPacket_to_ll8(8'hAA,10); // This packet gets dropped by the filters
+ repeat (10)
+ @(posedge clk);
+
+ SendPacketFromFile_ll8(60,0,0); // The rest are valid packets
+ repeat (10)
+ @(posedge clk);
+
+ SendPacketFromFile_ll8(61,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_ll8(62,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_ll8(63,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_ll8(64,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_ll8(59,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_ll8(58,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_ll8(100,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_ll8(200,150,30); // waiting 14 empties the fifo, 15 underruns
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_ll8(100,0,30);
+ #10000 $finish;
+ end
+
+ // Force a CRC error
+ initial
+ begin
+ #90000;
+ @(posedge clk);
+ FORCE_DAT_ERR <= 8'h10;
+ @(posedge clk);
+ FORCE_DAT_ERR <= 8'h00;
+ end
+
+ // Force an RX_ER error (i.e. link loss)
+ initial
+ begin
+ #116000;
+ @(posedge clk);
+ FORCE_ERR <= 1;
+ @(posedge clk);
+ FORCE_ERR <= 0;
+ end
+
+ // Cause receive fifo to fill, causing an RX overrun
+ initial
+ begin
+ #126000;
+ @(posedge clk);
+ rx_ll_dst_rdy2 <= 0;
+ repeat (30) // Repeat of 14 fills the shortfifo, but works. 15 overflows
+ @(posedge clk);
+ rx_ll_dst_rdy2 <= 1;
+ end
+
+ // Tests: Send and recv flow control, send and receive good packets, RX CRC err, RX_ER, RX overrun, TX underrun
+ // Still need to test: CRC errors on Pause Frames
+
+ always @(posedge clk)
+ if(rx_ll_src_rdy2 & rx_ll_dst_rdy2)
+ begin
+ if(rx_ll_sof2 & ~rx_ll_eof2)
+ $display("RX-PKT-START %d",$time);
+ $display("RX-PKT SOF %d EOF %d ERR%d DAT %x",rx_ll_sof2,rx_ll_eof2,rx_ll_error2,rx_ll_data2);
+ if(rx_ll_eof2 & ~rx_ll_sof2)
+ $display("RX-PKT-END %d",$time);
+ end
+
+endmodule // simple_gemac_tb
diff --git a/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper.build b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper.build
new file mode 100755
index 000000000..14e8500b3
--- /dev/null
+++ b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper.build
@@ -0,0 +1 @@
+iverilog -Wimplict -Wportbind -y ../fifo/ -y ../models/ -y . -y miim -y ../control -y ../coregen/ -y ../control_lib/ -o simple_gemac_wrapper_tb simple_gemac_wrapper_tb.v
diff --git a/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper_tb.v b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper_tb.v
new file mode 100644
index 000000000..b89589234
--- /dev/null
+++ b/fpga/usrp3/lib/sim/simple_gemac/simple_gemac_wrapper/simple_gemac_wrapper_tb.v
@@ -0,0 +1,213 @@
+//
+// Copyright 2011 Ettus Research LLC
+// Copyright 2018 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+
+
+
+
+module simple_gemac_wrapper_tb;
+`include "eth_tasks_f36.v"
+
+ reg reset = 1;
+ initial #1000 reset = 0;
+ wire wb_rst = reset;
+
+ reg eth_clk = 0;
+ always #50 eth_clk = ~eth_clk;
+
+ reg wb_clk = 0;
+ always #173 wb_clk = ~wb_clk;
+
+ reg sys_clk = 0;
+ always #77 sys_clk = ~ sys_clk;
+
+ wire GMII_RX_DV, GMII_RX_ER, GMII_TX_EN, GMII_TX_ER, GMII_GTX_CLK;
+ wire [7:0] GMII_RXD, GMII_TXD;
+
+ wire rx_valid, rx_error, rx_ack;
+ wire tx_ack, tx_valid, tx_error;
+
+ wire [7:0] rx_data, tx_data;
+
+ wire GMII_RX_CLK = GMII_GTX_CLK;
+
+ reg [7:0] FORCE_DAT_ERR = 0;
+ reg FORCE_ERR = 0;
+
+ // Loopback
+ assign GMII_RX_DV = GMII_TX_EN;
+ assign GMII_RX_ER = GMII_TX_ER | FORCE_ERR;
+ assign GMII_RXD = GMII_TXD ^ FORCE_DAT_ERR;
+
+
+ wire [31:0] wb_dat_o;
+ reg [31:0] wb_dat_i;
+ reg [7:0] wb_adr;
+ reg wb_stb=0, wb_cyc=0, wb_we=0;
+ wire wb_ack;
+
+ reg [35:0] tx_f36_data=0;
+ reg tx_f36_src_rdy = 0;
+ wire tx_f36_dst_rdy;
+ wire [35:0] rx_f36_data;
+ wire rx_f36_src_rdy;
+ wire rx_f36_dst_rdy = 1;
+
+ simple_gemac_wrapper simple_gemac_wrapper
+ (.clk125(eth_clk), .reset(reset),
+ .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN),
+ .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
+ .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV),
+ .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD),
+
+ .sys_clk(sys_clk), .rx_f36_data(rx_f36_data), .rx_f36_src_rdy(rx_f36_src_rdy), .rx_f36_dst_rdy(rx_f36_dst_rdy),
+ .tx_f36_data(tx_f36_data), .tx_f36_src_rdy(tx_f36_src_rdy), .tx_f36_dst_rdy(tx_f36_dst_rdy),
+
+ .wb_clk(wb_clk), .wb_rst(wb_rst), .wb_stb(wb_stb), .wb_cyc(wb_cyc), .wb_ack(wb_ack), .wb_we(wb_we),
+ .wb_adr(wb_adr), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o),
+
+ .mdio(), .mdc(),
+ .debug() );
+
+ initial $dumpfile("simple_gemac_wrapper_tb.vcd");
+ initial $dumpvars(0,simple_gemac_wrapper_tb);
+
+ integer i;
+ reg [7:0] pkt_rom[0:65535];
+ reg [1023:0] ROMFile;
+
+ initial
+ for (i=0;i<65536;i=i+1)
+ pkt_rom[i] <= 8'h0;
+
+ initial
+ begin
+ @(negedge reset);
+ repeat (10)
+ @(posedge wb_clk);
+ WishboneWR(0,6'b111101);
+ WishboneWR(4,16'hA0B0);
+ WishboneWR(8,32'hC0D0_A1B1);
+ WishboneWR(12,16'h0000);
+ WishboneWR(16,32'h0000_0000);
+
+ @(posedge eth_clk);
+ SendFlowCtrl(16'h0007); // Send flow control
+ @(posedge eth_clk);
+ #30000;
+ @(posedge eth_clk);
+ SendFlowCtrl(16'h0009); // Increase flow control before it expires
+ #10000;
+ @(posedge eth_clk);
+ SendFlowCtrl(16'h0000); // Cancel flow control before it expires
+ @(posedge eth_clk);
+
+ repeat (1000)
+ @(posedge sys_clk);
+ SendPacket_to_fifo36(32'hA0B0C0D0,10); // This packet gets dropped by the filters
+ repeat (1000)
+ @(posedge sys_clk);
+
+ SendPacket_to_fifo36(32'hAABBCCDD,100); // This packet gets dropped by the filters
+ repeat (10)
+ @(posedge sys_clk);
+/*
+ SendPacketFromFile_f36(60,0,0); // The rest are valid packets
+ repeat (10)
+ @(posedge clk);
+
+ SendPacketFromFile_f36(61,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_f36(62,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_f36(63,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_f36(64,0,0);
+ repeat (10)
+ @(posedge clk);
+ SendPacketFromFile_f36(59,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_f36(58,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_f36(100,0,0);
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_f36(200,150,30); // waiting 14 empties the fifo, 15 underruns
+ repeat (1)
+ @(posedge clk);
+ SendPacketFromFile_f36(100,0,30);
+ */
+ #100000 $finish;
+ end
+
+ // Force a CRC error
+ initial
+ begin
+ #90000;
+ @(posedge eth_clk);
+ FORCE_DAT_ERR <= 8'h10;
+ @(posedge eth_clk);
+ FORCE_DAT_ERR <= 8'h00;
+ end
+
+ // Force an RX_ER error (i.e. link loss)
+ initial
+ begin
+ #116000;
+ @(posedge eth_clk);
+ FORCE_ERR <= 1;
+ @(posedge eth_clk);
+ FORCE_ERR <= 0;
+ end
+/*
+ // Cause receive fifo to fill, causing an RX overrun
+ initial
+ begin
+ #126000;
+ @(posedge clk);
+ rx_ll_dst_rdy2 <= 0;
+ repeat (30) // Repeat of 14 fills the shortfifo, but works. 15 overflows
+ @(posedge clk);
+ rx_ll_dst_rdy2 <= 1;
+ end
+ */
+ // Tests: Send and recv flow control, send and receive good packets, RX CRC err, RX_ER, RX overrun, TX underrun
+ // Still need to test: CRC errors on Pause Frames, MDIO, wishbone
+
+ task WishboneWR;
+ input [7:0] adr;
+ input [31:0] value;
+ begin
+ wb_adr <= adr;
+ wb_dat_i <= value;
+ wb_stb <= 1;
+ wb_cyc <= 1;
+ wb_we <= 1;
+ while (~wb_ack)
+ @(posedge wb_clk);
+ @(posedge wb_clk);
+ wb_stb <= 0;
+ wb_cyc <= 0;
+ wb_we <= 0;
+ end
+ endtask // WishboneWR
+ /*
+ always @(posedge clk)
+ if(rx_ll_src_rdy2 & rx_ll_dst_rdy2)
+ begin
+ if(rx_ll_sof2 & ~rx_ll_eof2)
+ $display("RX-PKT-START %d",$time);
+ $display("RX-PKT SOF %d EOF %d ERR%d DAT %x",rx_ll_sof2,rx_ll_eof2,rx_ll_error2,rx_ll_data2);
+ if(rx_ll_eof2 & ~rx_ll_sof2)
+ $display("RX-PKT-END %d",$time);
+ end
+ */
+endmodule // simple_gemac_wrapper_tb
diff --git a/fpga/usrp3/lib/sim/wishbone/simple_uart/simple_uart_tb.v b/fpga/usrp3/lib/sim/wishbone/simple_uart/simple_uart_tb.v
new file mode 100644
index 000000000..3a1ddda29
--- /dev/null
+++ b/fpga/usrp3/lib/sim/wishbone/simple_uart/simple_uart_tb.v
@@ -0,0 +1,132 @@
+//
+// Copyright 2016 Ettus Research, a National Instruments Company
+//
+// SPDX-License-Identifier: LGPL-3.0-or-later
+//
+module simple_uart_tb();
+
+ localparam SUART_CLKDIV = 0;
+ localparam SUART_TXLEVEL = 1;
+ localparam SUART_RXLEVEL = 2;
+ localparam SUART_TXCHAR = 3;
+ localparam SUART_RXCHAR = 4;
+
+ reg clk;
+ reg rst;
+
+ reg we_i;
+ reg stb_i;
+ reg cyc_i;
+ wire ack_o;
+ reg [2:0] adr_i;
+ reg [31:0] dat_i;
+ wire [31:0] dat_o;
+ wire rx_int_o;
+ wire tx_int_o;
+ wire tx_o;
+ reg rx_i;
+ wire baud_o;
+
+ reg [31:0] read_data;
+
+
+ initial
+ clk = 0;
+
+ // 200MHz clock
+ always
+ #2.5 clk = ~clk;
+
+ initial begin
+ rst <= 0;
+ we_i <= 0;
+ stb_i <= 0;
+ cyc_i <= 0;
+ adr_i <= 0;
+ dat_i <= 0;
+ rx_i <= 0;
+ end
+
+
+ task write_wb;
+ input [31:0] data_in;
+ input [2:0] addr_in;
+
+ begin
+ @(negedge clk);
+ dat_i <= data_in;
+ adr_i <= addr_in;
+ we_i <= 1;
+ stb_i <= 1;
+ cyc_i <= 1;
+ @(negedge clk);
+ while (ack_o == 0) begin
+ @(negedge clk);
+ end
+ dat_i <= 0;
+ adr_i <= 0;
+ we_i <= 0;
+ stb_i <= 0;
+ cyc_i <= 0;
+ end
+ endtask // write_wb
+
+
+ task read_wb;
+ output [31:0] data_out;
+ input [2:0] addr_in;
+
+ begin
+ @(negedge clk);
+ adr_i <= addr_in;
+ we_i <= 0;
+ stb_i <= 1;
+ cyc_i <= 1;
+ @(negedge clk);
+ while (ack_o == 0) begin
+ @(negedge clk);
+ end
+ data_out <= dat_o;
+ adr_i <= 0;
+ stb_i <= 0;
+ cyc_i <= 0;
+ end
+ endtask // write_wb
+
+ initial begin
+ @(negedge clk);
+ rst <= 1;
+ repeat(10) @(negedge clk);
+ rst <= 0;
+ repeat(10) @(negedge clk);
+ write_wb(4'h0620,SUART_CLKDIV);
+ repeat(10) @(negedge clk);
+ read_wb(read_data,SUART_TXLEVEL);
+ repeat(10) @(negedge clk);
+ end // initial begin
+
+
+
+ simple_uart
+ #(.CLKDIV_DEFAULT(16'd0))
+ simple_uart_i
+ (
+ .clk_i(clk),
+ .rst_i(rst),
+ .we_i(we_i),
+ .stb_i(stb_i),
+ .cyc_i(cyc_i),
+ .ack_o(ack_o),
+ .adr_i(adr_i),
+ .dat_i(dat_i),
+ .dat_o(dat_o),
+ .rx_int_o(rx_int_o),
+ .tx_int_o(tx_int_o),
+ .tx_o(tx_o),
+ .rx_i(rx_i),
+ .baud_o(baud_o)
+ );
+
+
+
+endmodule // simple_uart_tb