aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/docs/usrp3
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/docs/usrp3')
-rw-r--r--fpga/docs/usrp3/build_instructions.md240
-rw-r--r--fpga/docs/usrp3/sim/libs_axi.md266
-rw-r--r--fpga/docs/usrp3/sim/libs_general.md188
-rw-r--r--fpga/docs/usrp3/sim/running_testbenches.md133
-rw-r--r--fpga/docs/usrp3/sim/writing_testbenches.md471
-rw-r--r--fpga/docs/usrp3/simulation.md11
-rw-r--r--fpga/docs/usrp3/vivado_env_utils.md87
7 files changed, 1396 insertions, 0 deletions
diff --git a/fpga/docs/usrp3/build_instructions.md b/fpga/docs/usrp3/build_instructions.md
new file mode 100644
index 000000000..e51585d97
--- /dev/null
+++ b/fpga/docs/usrp3/build_instructions.md
@@ -0,0 +1,240 @@
+# Generation 3 USRP Build Documentation
+
+## Dependencies and Requirements
+
+### Dependencies
+
+The USRP FPGA build system requires a UNIX-like environment with the following dependencies
+
+- [Xilinx Vivado 2019.1](https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/2019-1.html) (For 7 Series FPGAs)
+- [Xilinx ISE 14.7](http://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/design-tools/v2012_4---14_7.html) (For all other FPGAs)
+- [GNU Make 3.6+](https://www.gnu.org/software/make/)
+- [GNU Bash 4.0+](https://www.gnu.org/software/bash/)
+- [Python 2.7.x](https://www.python.org/)
+- [Doxygen](http://www.stack.nl/~dimitri/doxygen/index.html) (Optional: To build the manual)
+- [ModelSim](https://www.mentor.com/products/fv/modelsim/) (Optional: For simulation)
+
+The following USRPs work with the free WebPack versions:
+- USRP E310/E312/E313
+
+### What FPGA does my USRP have?
+
+- USRP B200: Spartan 6 XC6SLX75
+- USRP B200mini: Spartan 6 XC6SLX75
+- USRP B210: Spartan 6 XC6SLX150
+- USRP X300: Kintex 7 XC7K325T (7 Series)
+- USRP X310: Kintex 7 XC7K410T (7 Series)
+- USRP E310: Zynq-7000 XC7Z020 (7 Series)
+- USRP E320: Zynq-7000 XC7Z045 (7 Series)
+- USRP N300: Zynq-7000 XC7Z035 (7 Series)
+- USRP N310/N320: Zynq-7000 XC7Z100 (7 Series)
+
+### Requirements
+
+- [Xilinx Vivado Release Notes](https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_1/ug973-vivado-release-notes-install-license.pdf)
+- [Xilinx ISE Platform Requirements](http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_7/irn.pdf)
+
+## Build Environment Setup
+
+### Download and Install Xilinx Tools
+
+Download and install Xilinx Vivado or Xilinx ISE based on the target USRP.
+- The recommended installation directory is `/opt/Xilinx/` for Linux and `C:\Xilinx` in Windows
+- Please check the Xilinx Requirements document above for the FPGA technology used by your USRP device.
+- You may need to acquire a synthesis and implementation license from Xilinx to build some USRP designs.
+- You may need to acquire a simulation license from Xilinx to run some testbenches
+
+### Download and Install ModelSim (Optional)
+
+Download and install Mentor ModelSim using the link above.
+- The recommended installation directory is `/opt/mentor/modelsim` for Linux and `C:\mentor\modelsim` in Windows
+- Supported versions are PE, DE, SE, DE-64 and SE-64
+- You may need to acquire a license from Mentor Graphics to run ModelSim
+
+### Setting up build dependencies on Ubuntu
+
+You can install all the dependencies through the package manager:
+
+ sudo apt-get install python bash build-essential doxygen
+
+Your actual command may differ.
+
+### Setting up build dependencies on Fedora
+
+You can install all the dependencies through the package manager:
+
+ sudo yum -y install python bash make doxygen
+
+Your actual command may differ.
+
+### Setting up build dependencies on Windows (using Cygwin)
+
+**NOTE**: Windows is only supported with Vivado. The build system does not support Xilinx ISE in Windows.
+
+Download the latest version on [Cygwin](https://cygwin.com/install.html) (64-bit is preferred on a 64-bit OS)
+and install it using [these instructions](http://x.cygwin.com/docs/ug/setup-cygwin-x-installing.html).
+The following additional packages are also required and can be selected in the GUI installer
+
+ python patch patchutils bash make doxygen
+
+## Build Instructions (Xilinx Vivado only)
+
+### Makefile based Builder
+
+- Navigate to `usrp3/top/{project}` where project is:
+ + x300: For USRP X300 and USRP X310
+ + e31x: For USRP E310
+ + e320: For USRP E320
+ + n3xx: For USRP N300/N310/N320
+
+- To add vivado to the PATH and to setup up the Ettus Xilinx build environment run
+ + `source setupenv.sh` (If Vivado is installed in the default path /opt/Xilinx/Vivado) _OR_
+ + `source setupenv.sh --vivado-path=<VIVADO_PATH>` (where VIVADO_PATH is a non-default installation path)
+
+- To build a binary configuration bitstream run `make <target>`
+ where the target is specific to each product. To get a list of supported targets run
+ `make help`.
+
+- The build output will be specific to the product and will be located in the
+ `usrp3/top/{project}/build` directory. Run `make help` for more information.
+
+### Environment Utilies
+
+The build environment also defines many ease-of-use utilites. Please use the \subpage md_usrp3_vivado_env_utils "Vivado Utility Reference" page for
+a list and usage information
+
+## Build Instructions (Xilinx ISE only)
+
+### Makefile based Builder
+
+- To add xtclsh to the PATH and to setup up the Xilinx build environment run
+ + `source <install_dir>/Xilinx/14.7/ISE_DS/settings64.sh` (64-bit platform)
+ + `source <install_dir>/Xilinx/14.7/ISE_DS/settings32.sh` (32-bit platform)
+
+- Navigate to `usrp3/top/{project}` where project is:
+ + b200: For USRP B200 and USRP B210
+ + b200mini: For USRP B200mini
+
+- To build a binary configuration bitstream run `make <target>`
+ where the target is specific to each product. To get a list of supported targets run
+ `make help`.
+
+- The build output will be specific to the product and will be located in the
+ `usrp3/top/{project}/build` directory. Run `make help` for more information.
+
+## Targets and Outputs
+
+### B2x0 Targets and Outputs
+
+#### Supported Targets
+- B200: Builds the USRP B200 design.
+- B210: Builds the USRP B210 design.
+
+#### Outputs
+- `build/usrp_<product>_fpga.bit` : Configuration bitstream with header
+- `build/usrp_<product>_fpga.bin` : Configuration bitstream without header
+- `build/usrp_<product>_fpga.syr` : Xilinx system report
+- `build/usrp_<product>_fpga.twr` : Xilinx timing report
+
+### X3x0 Targets and Outputs
+
+#### Supported Targets
+- X310_1G: USRP X310. 1GigE on both SFP+ ports. DRAM TX FIFO (experimental!).
+- X300_1G: USRP X300. 1GigE on both SFP+ ports. DRAM TX FIFO (experimental!).
+- X310_HG: USRP X310. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. DRAM TX FIFO (experimental!).
+- X300_HG: USRP X300. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. DRAM TX FIFO (experimental!).
+- X310_XG: USRP X310. 10GigE on both SFP+ ports. DRAM TX FIFO (experimental!).
+- X300_XG: USRP X300. 10GigE on both SFP+ ports. DRAM TX FIFO (experimental!).
+- X310_HA: USRP X310. 1GigE on SFP+ Port0, Aurora on SFP+ Port1. DRAM TX FIFO.
+- X300_HA: USRP X300. 1GigE on SFP+ Port0, Aurora on SFP+ Port1. DRAM TX FIFO.
+- X310_XA: USRP X310. 10GigE on SFP+ Port0, Aurora on SFP+ Port1. DRAM TX FIFO.
+- X300_XA: USRP X300. 10GigE on SFP+ Port0, Aurora on SFP+ Port1. DRAM TX FIFO.
+- X310_RFNOC_HG: USRP X310. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. RFNoC CEs enabled
+- X300_RFNOC_HG: USRP X300. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. RFNoC CEs enabled
+- X310_RFNOC_XG: USRP X310. 10GigE on both SFP+ ports. RFNoC CEs enabled.
+- X300_RFNOC_XG: USRP X300. 10GigE on both SFP+ ports. RFNoC CEs enabled.
+- X310_RFNOC_HLS_HG: USRP X310. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. RFNoC CEs enabled + Vivado HLS
+- X300_RFNOC_HLS_HG: USRP X300. 1GigE on SFP+ Port0, 10Gig on SFP+ Port1. RFNoC CEs enabled + Vivado HLS
+
+#### Outputs
+- `build/usrp_<product>_fpga_<image_type>.bit` : Configuration bitstream with header
+- `build/usrp_<product>_fpga_<image_type>.bin` : Configuration bitstream without header
+- `build/usrp_<product>_fpga_<image_type>.lvbitx` : Configuration bitstream for PCIe (NI-RIO)
+- `build/usrp_<product>_fpga_<image_type>.rpt` : System, utilization and timing summary report
+
+### E310 Targets and Outputs
+
+#### Supported Targets
+- E310_SG1 or E310 : Builds the USRP E310 speed grade 1.
+- E310_SG3 or E310_sg3: Builds the USRP E310 speed grade 3.
+- E310_SG1_RFNOC or E310_RFNOC: Builds the USRP E310 RFNoC image for speed grade 1.
+- E310_SG3_RFNOC or E310_RFNOC_sg3: Builds the USRP E310 RFNoC image for speed grade 3.
+
+#### Outputs
+- `build/usrp_<product>_fpga.bit` : Configuration bitstream with header
+- `build/usrp_<product>_fpga.dts` : Device tree overlay
+- `build/usrp_<product>_fpga.rpt` : System, utilization and timing summary report
+
+### E320 Targets and Outputs
+
+#### Supported Targets
+- E320_1G: 1GigE on SFP+ Port.
+- E320_XG: 10GigE on SFP+ Port.
+- E320_AA: Aurora on SFP+ Port.
+- E320_RFNOC_1G: 1GigE on SFP+ Port. RFNOC CEs enabled.
+- E320_RFNOC_XG: 10GigE on SFP+ Port. RFNOC CEs enabled.
+- E320_RFNOC_AA: Aurora on SFP+ Port. RFNOC CEs enabled.
+
+#### Outputs
+- `build/usrp_<product>_fpga.bit` : Configuration bitstream with header
+- `build/usrp_<product>_fpga.dts` : Device tree overlay
+- `build/usrp_<product>_fpga.rpt` : System, utilization and timing summary report
+
+### N3XX Targets and Outputs
+
+#### Supported Targets
+
+The targets depend on the actual hardware the FPGA image is being deployed to.
+Unlike the X300 Series, the daughterboards are an integral part of the module
+and not meant to be removed. Therefore, the target is specific to the
+combination of motherboard and daughterboards.
+
+- N300_AA: Aurora on both SFP+ ports
+- N300_HA: 1GigE on SFP0, Aurora on SFP1
+- N300_HG: 1GigE on SFP0, 10GigE on SFP1
+- N300_WX: White Rabbing on SFP0, 10GigE on SFP1
+- N300_XA: 10GigE on SFP0, Aurora on SFP1
+- N300_XG: 10GigE on both SFP+ ports
+- N310_AA: Aurora on both SFP+ ports
+- N310_HA: 1GigE on SFP0, Aurora on SFP1
+- N310_HG: 1GigE on SFP0, 10GigE on SFP1
+- N310_WX: White Rabbing on SFP0, 10GigE on SFP1
+- N310_XA: 10GigE on SFP0, Aurora on SFP1
+- N310_XG: 10GigE on both SFP+ ports
+- N320_AQ: 10GigE on both SFP+ ports, Aurora on QSFP+ ports
+- N320_HG: 1GigE on SFP0, 10GigE on SFP1
+- N320_XG: 10GigE on both SFP+ ports
+- N320_XQ: White Rabbit on SFP0, 10 GigE on QSFP0 and QSFP1
+
+For the N320 targets see also the N320 manual page on the UHD manual.
+
+All targets also support an RFNOC version (e.g. `N300_RFNOC_XG`), which enables
+custom selection of RFNoC blocks.
+
+
+#### Outputs
+- `build/usrp_<product>_fpga.bit` : Configuration bitstream with header
+- `build/usrp_<product>_fpga.dts` : Device tree overlay
+- `build/usrp_<product>_fpga.rpt` : System, utilization and timing summary report
+
+### Additional Build Options
+
+It is possible to make a target and specific additional options in the form VAR=VALUE in
+the command. For example: `make B210 PROJECT_ONLY=1`
+
+Here are the supported options:
+
+- `PROJECT_ONLY=1` : Only create a Xilinx project for the specified target(s). Useful for use with the ISE GUI. (*NOTE*: this option is only valid for Xilinx ISE)
+- `EXPORT_ONLY=1` : Export build targets from a GUI build to the build directory. Requires the project in build-\*_\* to be built. (*NOTE*: this option is only valid for Xilinx ISE)
+- `GUI=1` : Run the Vivado build in GUI mode instead of batch mode. After the build is complete, Vivado provides an option to save the fully configured project for customization (*NOTE*: this option is only valid for Xilinx Vivado)
+
diff --git a/fpga/docs/usrp3/sim/libs_axi.md b/fpga/docs/usrp3/sim/libs_axi.md
new file mode 100644
index 000000000..a260aabdd
--- /dev/null
+++ b/fpga/docs/usrp3/sim/libs_axi.md
@@ -0,0 +1,266 @@
+# AXI Interface Libraries
+
+## AXI4 Stream (sim\_axis\_lib.vh)
+
+Defines ``axis_t``, an AXI Stream bus interface that implements several tasks to send and
+receive data on the bus.
+
+### Definition
+
+ interface axis_t #(parameter DWIDTH = 64)
+ (input clk);
+ logic [DWIDTH-1:0] tdata;
+ logic tvalid;
+ logic tlast;
+ logic tready;
+
+ modport master (output tdata, output tvalid, output tlast, input tready);
+ modport slave (input tdata, input tvalid, input tlast, output tready);
+
+
+### Operations
+
+#### push\_word
+
+ // Push a word onto the AXI-Stream bus and wait for it to transfer
+ // Args:
+ // - word: The data to push onto the bus
+ // - eop (optional): End of packet (asserts tlast)
+
+#### push\_bubble
+
+ // Push a bubble cycle onto the AXI-Stream bus
+
+#### pull\_word
+
+ // Wait for a sample to be transferred on the AXI Stream
+ // bus and return the data and last
+ // Args:
+ // - word: The data pulled from the bus
+ // - eop: End of packet (tlast)
+
+#### wait\_for\_bubble
+
+ // Wait for a bubble cycle on the AXI Stream bus
+
+#### wait\_for\_pkt
+
+ // Wait for a packet to finish on the bus
+
+#### push\_rand\_pkt
+
+ // Push a packet with random data onto to the AXI Stream bus
+ // Args:
+ // - num_samps: Packet size.
+
+#### push\_ramp\_pkt
+
+ // Push a packet with a ramp on to the AXI Stream bus
+ // Args:
+ // - num_samps: Packet size.
+ // - ramp_start: Start value for the ramp
+ // - ramp_inc: Increment per clock cycle
+
+## Compressed VITA [CHDR] (sim\_chdr\_lib.vh)
+
+Defines ``cvita_stream_t``, an AXI Stream bus interface that implements the CHDR protocol and
+several tasks to send and receive data on the bus.
+
+### CHDR
+
+ typedef enum logic [1:0] {
+ DATA=2'b00, FC=2'b01, CMD=2'b10, RESP=2'b11
+ } cvita_pkt_t;
+
+ typedef struct packed {
+ logic [31:0] sid;
+ logic [15:0] length;
+ logic [11:0] seqno;
+ logic eob;
+ logic has_time;
+ cvita_pkt_t pkt_type;
+ logic [63:0] timestamp;
+ } cvita_hdr_t;
+
+#### Operations
+
+ - ``flatten_chdr_no_ts``: Flatten header struct to a 64-bit bus. No timestamp.
+ - ``unflatten_chdr_no_ts``: Decode a 64-bit header and populate the ``cvita_hdr_t`` struct. No timestamp.
+ - ``unflatten_chdr``: Decode a 64-bit header and populate the ``cvita_hdr_t`` struct. Timestamp supported.
+
+### CVITA Stream Type
+
+#### Definition
+
+ interface cvita_stream_t (input clk);
+ axis_t #(.DWIDTH(64)) axis (.clk(clk));
+
+#### push\_hdr
+
+ // Push a CVITA header into the stream
+ // Args:
+ // - hdr: The header to push
+
+#### push\_data
+
+ // Push a word onto the AXI-Stream bus and wait for it to transfer
+ // Args:
+ // - word: The data to push onto the bus
+ // - eop: End of packet (asserts tlast)
+
+#### push\_bubble
+
+ // Push a bubble cycle on the AXI-Stream bus
+
+#### pull\_word
+
+ // Wait for a sample to be transferred on the AXI Stream
+ // bus and return the data and last
+ // Args:
+ // - word: The data pulled from the bus
+ // - eop: End of packet (tlast)
+
+#### wait\_for\_bubble
+
+ // Wait for a bubble cycle on the AXI Stream bus
+
+#### wait\_for\_pkt
+
+ // Wait for a packet to finish on the bus
+
+#### wait\_for\_pkt\_get\_info
+
+ // Wait for a packet to finish on the bus and extract the header and payload statistics.
+
+ typedef struct packed {
+ logic [31:0] count;
+ logic [63:0] sum;
+ logic [63:0] min;
+ logic [63:0] max;
+ logic [63:0] crc;
+ } cvita_stats_t;
+
+#### push\_rand\_pkt
+
+ // Push a packet with random data onto to the AXI Stream bus
+ // Args:
+ // - num_samps: Packet size.
+ // - hdr: Header to attach to packet (length will be ignored)
+ // - timestamp: Optional timestamp
+
+#### push\_ramp\_pkt
+
+ // Push a packet with a ramp on to the AXI Stream bus
+ // Args:
+ // - num_samps: Packet size.
+ // - ramp_start: Start value for the ramp
+ // - ramp_inc: Increment per clock cycle
+ // - hdr: Header to attach to packet (length will be ignored)
+ // - timestamp: Optional timestamp
+
+## Memory Mapped AXI4 (sim\_axi4\_lib.vh)
+
+Defines the following interfaces to group signals in the AXI4 bus.
+WIP: No functions or tasks implemented yet.
+
+#### Address
+
+ interface axi4_addr_t #(parameter AWIDTH=32, parameter IDWIDTH=4)
+ (input clk);
+
+ logic [IDWIDTH-1:0] id;
+ logic [AWIDTH-1:0] addr;
+ logic [7:0] len;
+ logic [2:0] size;
+ logic [1:0] burst;
+ logic lock;
+ logic [3:0] cache;
+ logic [2:0] prot;
+ logic [3:0] qos;
+ logic [3:0] region;
+ logic user;
+ logic valid;
+ logic ready;
+
+ modport master (output id,addr,len,size,burst,lock,cache,prot,qos,valid, input ready);
+ modport slave (input id,addr,len,size,burst,lock,cache,prot,qos,valid, output ready);
+
+ endinterface
+
+#### Write Data
+
+ interface axi4_wdata_t #(parameter DWIDTH=64)
+ (input clk);
+
+ logic [DWIDTH-1:0] data;
+ logic [(DWIDTH/8)-1:0] strb;
+ logic last;
+ logic user;
+ logic valid;
+ logic ready;
+
+ modport master(output data,strb,last,valid, input ready);
+ modport slave(input data,strb,last,valid, output ready);
+
+ endinterface
+
+#### Write Response
+
+ interface axi4_resp_t #(parameter IDWIDTH=4)
+ (input clk);
+
+ logic ready;
+ logic [IDWIDTH-1:0] id;
+ logic [1:0] resp;
+ logic user;
+ logic valid;
+
+ modport master(output ready, input id,resp,valid);
+ modport slave(input ready, output id,resp,valid);
+
+ endinterface
+
+#### Read Data
+
+ interface axi4_rdata_t #(parameter DWIDTH=64, parameter IDWIDTH=4)
+ (input clk);
+
+ logic ready;
+ logic [IDWIDTH-1:0] id;
+ logic [DWIDTH-1:0] data;
+ logic [1:0] resp;
+ logic user;
+ logic last;
+ logic valid;
+
+ modport master(output ready, input id,data,resp,last,valid);
+ modport slave(input ready, output id,data,resp,last,valid);
+
+ endinterface
+
+#### Meta: AXI4 Writer
+
+ interface axi4_wr_t #(parameter DWIDTH=64, parameter AWIDTH=32, parameter IDWIDTH=4)
+ (input clk);
+
+ axi4_addr_t #(.AWIDTH(AWIDTH), .IDWIDTH(IDWIDTH)) addr (.clk(clk));
+ axi4_wdata_t #(.DWIDTH(DWIDTH)) data (.clk(clk));
+ axi4_resp_t #(.IDWIDTH(IDWIDTH)) resp (.clk(clk));
+
+ modport master(output addr, output data, input resp);
+ modport slave(input addr, input data, output resp);
+
+ endinterface
+
+#### Meta: AXI4 Reader
+
+ interface axi4_rd_t #(parameter DWIDTH=64, parameter AWIDTH=32, parameter IDWIDTH=4)
+ (input clk);
+
+ axi4_addr_t #(.AWIDTH(AWIDTH), .IDWIDTH(IDWIDTH)) addr (.clk(clk));
+ axi4_rdata_t #(.DWIDTH(DWIDTH), .IDWIDTH(IDWIDTH)) data (.clk(clk));
+
+ modport master(output addr, output data);
+ modport slave(input addr, input data);
+
+ endinterface
diff --git a/fpga/docs/usrp3/sim/libs_general.md b/fpga/docs/usrp3/sim/libs_general.md
new file mode 100644
index 000000000..4bc154dc2
--- /dev/null
+++ b/fpga/docs/usrp3/sim/libs_general.md
@@ -0,0 +1,188 @@
+# General Purpose Libraries
+
+## Execution and Reporting (sim\_exec\_report.vh)
+
+Macros to do boilerplate testbench initialization and utilities to define test cases
+
+#### TEST\_BENCH\_INIT
+
+ // Initializes state for a test bench.
+ // This macro *must be* called within the testbench module but
+ // outside the primary initial block
+ // Its sets up boilerplate code for:
+ // - Logging to console
+ // - Test execution tracking
+ // - Gathering test results
+ // - Bounding execution time based on the SIM_RUNTIME_US vdef
+ //
+ // Usage: `TEST_BENCH_INIT(test_name,min_tc_run_count,ns_per_tick)
+ // where
+ // - tb_name: Name of the testbench. (Only used during reporting)
+ // - min_tc_run_count: Number of test cases in testbench. (Used to detect stalls and inf-loops)
+ // - ns_per_tick: The time_unit_base from the timescale declaration
+ //
+
+#### TEST\_CASE\_START
+
+ // Indicates the start of a test case
+ // This macro *must be* called inside the primary initial block
+ //
+ // Usage: `TEST_CASE_START(test_name)
+ // where
+ // - test_name: The name of the test.
+ //
+
+#### TEST\_CASE\_DONE
+ // Indicates the end of a test case
+ // This macro *must be* called inside the primary initial block
+ // The pass/fail status of test case is determined based on the
+ // the user specified outcome and the number of fatal or error
+ // ASSERTs triggered in the test case.
+ //
+ // Usage: `TEST_CASE_DONE(test_result)
+ // where
+ // - test_result: User specified outcome
+ //
+
+#### ASSERT\_FATAL
+
+ // Wrapper around a an assert.
+ // ASSERT_FATAL throws an error assertion and halts the simulator
+ // if cond is not satisfied
+ //
+ // Usage: `ASSERT_FATAL(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+#### ASSERT\_ERROR
+
+ // Wrapper around a an assert.
+ // ASSERT_ERROR throws an error assertion and fails the test case
+ // if cond is not satisfied. The simulator will *not* halt
+ //
+ // Usage: `ASSERT_ERROR(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+#### ASSERT\_WARNING
+
+ // Wrapper around a an assert.
+ // ASSERT_WARNING throws an warning assertion but does not fail the
+ // test case if cond is not satisfied. The simulator will *not* halt
+ //
+ // Usage: `ASSERT_WARNING(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+## Clocks and Resets (sim\_clks\_rsts.vh)
+
+Shortcut macros to create typical clock and reset signals.
+
+#### DEFINE\_CLK
+
+ // Generates a persistent clock that starts at t=0 and runs forever
+ //
+ // Usage: `DEFINE_CLK(clk_name,period,duty_cycle)
+ // where
+ // - clk_name: The clock net to be generated
+ // - period: Period of the clock in simulator ticks
+ // - duty_cycle: Percentage duty cycle
+ //
+
+#### DEFINE\_LATE\_START\_CLK
+
+ // Generates a clock that starts at the specified time and runs forever
+ //
+ // Usage: `DEFINE_LATE_START_CLK(clk_name,period,duty_cycle,start_time,start_time_res)
+ // where
+ // - clk_name: The clock net to be generated
+ // - period: Period of the clock in simulator ticks
+ // - duty_cycle: Percentage duty cycle
+ // - start_time: Start time for clock in simulator ticks
+ // - start_time_res: Start time resolution (must be > timescale increment and < start_time)
+ //
+
+#### DEFINE_RESET
+
+ // Generates an active high reset
+ //
+ // Usage: `DEFINE_RESET(reset_name,reset_time,reset_duration)
+ // where
+ // - reset_name: The reset net to be generated
+ // - reset_time: Time at which reset will be asserted (i.e. rst=1)
+ // - reset_duration: Duration of reset assertion
+ //
+
+#### DEFINE_RESET_N
+
+ // Generates an active low reset
+ //
+ // Usage: `DEFINE_RESET_N(reset_name,reset_time,reset_duration)
+ // where
+ // - reset_name: The reset net to be generated
+ // - reset_time: Time at which reset will be asserted (i.e. rst=0)
+ // - reset_duration: Duration of reset assertion
+ //
+
+## File I/O (sim\_file\_io.sv)
+
+### interface data\_file\_t
+
+Defines a ``data_file_t`` interface with the following functions:
+
+#### ctor
+
+ // Create a handle to a data_file with
+ // - FILENAME: Name of the file
+ // - FORMAT: Data format (HEX, DEC, OCT, BIN, FLOAT)
+ // - DWIDTH: Width of each element stored in the file (one line per word)
+ //
+
+#### open
+
+ // Open the data file for reading or writing.
+ //
+ // Usage: open(mode)
+ // where
+ // - mode: RW mode (Choose from: READ, WRITE, APPEND)
+ //
+
+#### close
+
+ // Close an open data file. No-op if file isn't already open
+ //
+ // Usage: close()
+ //
+
+#### is_eof
+
+ // Is end-of-file reached.
+ //
+ // Usage: is_eof() Returns eof
+ // where
+ // - eof: A boolean
+ //
+
+#### readline
+
+ // Read a line from the datafile
+ //
+ // Usage: readline() Returns data
+ // where
+ // - data: A logic array of width DWIDTH containing the read word
+ //
+
+#### writeline
+
+ // Write a line to the datafile
+ //
+ // Usage: writeline(data)
+ // where
+ // - data: A logic array of width DWIDTH to write to the file
+ // \ No newline at end of file
diff --git a/fpga/docs/usrp3/sim/running_testbenches.md b/fpga/docs/usrp3/sim/running_testbenches.md
new file mode 100644
index 000000000..2e2068e5e
--- /dev/null
+++ b/fpga/docs/usrp3/sim/running_testbenches.md
@@ -0,0 +1,133 @@
+# Running a Testbench
+
+Each executable testbench has its own Makefile that automatically pulls in support
+for all supported simulators. The build infrastructure supports the following simulators:
+
+ - Xilinx Vivado (XSim)
+ - Mentor Graphics ModelSim (may require an additional license)
+
+
+In general running ``make <sim_target>`` will run the
+simulation and report results in the console. Running ``make help`` will print out
+all supported simulator targets. Currently, the following targets will work:
+
+ Supported Targets:
+ ipclean: Cleanup all IP intermediate files
+ clean: Cleanup all simulator intermediate files
+ cleanall: Cleanup everything!
+ xsim: Run the simulation using the Xilinx Vivado Simulator
+ xclean: Cleanup Xilinx Vivado Simulator intermediate files
+ vsim: Run the simulation using Modelsim
+ vclean: Cleanup Modelsim intermediate files
+
+
+## Using Xilinx Vivado XSim
+
+XSim is the built-in simulator in the Xilinx Vivado toolchain. If you already met the
+prerequisites for building an FPGA image, then you don't need to install anything else.
+
+Follow these steps to run a testbench:
+
+ - Navigate to the directory that contains the top level testbench and Makefile
+ - Run the setenv.sh script for the USRP product that you are trying to simulate
+
+ ``$ source <repo>/usrp3/top/<product>/setupenv.sh``
+
+ This step is required even if the simulation is generic because the toolchain requires
+ an FPGA part number to load simulation models.
+ - Run the simulator specific target
+
+ ``$ make xsim``
+
+
+## Using Mentor Graphics ModelSim
+
+ModelSim is a third-party simulation tool that is compatible with Vivado and the USRP
+FPGA build infrastructure.
+
+Use the following one-time setup to install and configure Modelsim on your system
+
+ - Install Modelsim from the [Mentor Graphics](http://www.mentor.com/) website.
+ It is recommended that you install it to the default location (/opt/mentor/modelsim)
+ - Run the setenv.sh script for the USRP product that you are trying to simulate
+
+ ``$ source <repo>/usrp3/top/<product>/setupenv.sh``
+
+ This step is required even if the simulation is generic because the toolchain requires
+ an FPGA part number to load simulation models.
+ - Build the Xilinx simulation libraries
+ ``$ build_simlibs``
+
+
+To validate that everything was install properly run ``setupenv.sh`` again. You should see the following
+
+ Setting up X3x0 FPGA build environment (64-bit)...
+ - Vivado: Found (/opt/Xilinx/Vivado/2014.4/bin)
+ - Modelsim: Found (/opt/mentor/modelsim/modeltech/bin)
+ - Modelsim Compiled Libs: Found (/opt/Xilinx/Vivado/2014.4/modelsim)
+
+ Environment successfully initialized.
+
+Follow these steps to run a testbench:
+
+ - Navigate to the directory that contains the top level testbench and Makefile
+ - Run the setenv.sh script for the USRP product that you are trying to simulate
+
+ ``$ source <repo>/usrp3/top/<product>/setupenv.sh``
+
+ This step is required even if the simulation is generic because the toolchain requires
+ an FPGA part number to load simulation models.
+ - Run the simulator specific target
+
+ ``$ make vsim``
+
+
+## Troubleshooting
+
+#### Vivado Not Found
+
+If running the setupenv.sh script return an error like the following:
+
+ Vivado: Not found! (ERROR.. Builds and simulations will not work)
+
+then it is possible that Vivado was not installed or it was not installed in the default
+location. If Vivado is installed in a non-default location, just run the following:
+
+ ``$ source <repo>/usrp3/top/<product>/setupenv.sh --vivado-path=<PATH>``
+
+#### Modelsim Not Found
+
+If running the setupenv.sh script return an error like the following:
+
+ Setting up X3x0 FPGA build environment (64-bit)...
+ - Vivado: Found (/opt/Xilinx/Vivado/2014.4/bin)
+ - Modelsim: Not found! (WARNING.. Simulations with vsim will not work)
+
+ Environment successfully initialized.
+
+or something like this (even when Modelsim is installed)
+
+ Setting up X3x0 FPGA build environment (64-bit)...
+ - Vivado: Found (/opt/Xilinx/Vivado/2014.4/bin)
+
+ Environment successfully initialized.
+
+then it is possible that Modelsim was not installed or it was not installed in the default
+location. If Modelsim is installed in a non-default location, just run the following:
+
+ ``$ source <repo>/usrp3/top/<product>/setupenv.sh --modelsim-path=<PATH>``
+
+#### Modelsim Simulation Libraries Not Found
+
+If running the setupenv.sh script return an error like the following:
+
+ Setting up X3x0 FPGA build environment (64-bit)...
+ - Vivado: Found (/opt/Xilinx/Vivado/2014.4/bin)
+ - Modelsim: Found (/opt/mentor/modelsim/modeltech/bin)
+ - Modelsim Compiled Libs: Not found! (Run build_simlibs to generate them.)
+
+ Environment successfully initialized.
+
+just run the following
+
+ $ build_simlibs \ No newline at end of file
diff --git a/fpga/docs/usrp3/sim/writing_testbenches.md b/fpga/docs/usrp3/sim/writing_testbenches.md
new file mode 100644
index 000000000..cfbbcdbce
--- /dev/null
+++ b/fpga/docs/usrp3/sim/writing_testbenches.md
@@ -0,0 +1,471 @@
+# Writing a Testbench
+
+Writing a unit test or system level test is easy with the Vivado makefile infrastructure!
+Most of the overhead of building and running a testbench is handled by the build tools.
+Even recurring tasks like reporting and monitoring are implemented by framework libraries.
+
+Each executable FPGA unit test must have the following components:
+
+1. A Makefile
+2. A Testbench top-level module
+
+## Testbench Makefile
+
+The Testbench Makefile tell the build tools what to build, where to build it, dependency information and runtime information.
+The build infrastructure will handle the how-to part for each supported simulation tool.
+
+Here is a sample Makefile (you are encouraged to use this as a starting point)
+
+ #
+ # Copyright 2015 Ettus Research LLC
+ #
+
+ #-------------------------------------------------
+ # Top-of-Makefile
+ #-------------------------------------------------
+ # Define BASE_DIR to point to the "top" dir
+ BASE_DIR = $(abspath ../../..)
+ # Include viv_sim_preample 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 makefiles and sources for the DUT and its dependencies
+ include $(BASE_DIR)/../lib/fifo/Makefile.srcs
+ include $(BASE_DIR)/../lib/axi/Makefile.srcs
+ include $(BASE_DIR)/../lib/control/Makefile.srcs
+
+ DESIGN_SRCS = $(abspath \
+ $(FIFO_SRCS) \
+ $(AXI_SRCS) \
+ $(CONTROL_LIB_SRCS) \
+ )
+
+ #-------------------------------------------------
+ # IP Specific
+ #-------------------------------------------------
+ # If simulation contains IP, define the IP_DIR and point
+ # it to the base level IP directory
+ IP_DIR = ../../ip
+
+ # Include makefiles and sources for all IP components
+ # *after* defining the IP_DIR
+ include $(IP_DIR)/ddr3_32bit/Makefile.inc
+ include $(IP_DIR)/axi_intercon_2x64_128/Makefile.inc
+ include $(IP_DIR)/fifo_short_2clk/Makefile.inc
+ include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
+ include $(IP_DIR)/axi4_bram_1kx64/Makefile.inc
+
+ DESIGN_SRCS += $(abspath \
+ $(IP_DDR3_32BIT_SRCS) \
+ $(IP_AXI_INTERCON_2X64_128_SRCS) \
+ $(IP_FIFO_4K_2CLK_SRCS) \
+ $(IP_FIFO_SHORT_2CLK_SRCS) \
+ $(IP_AXI4_BRAM_1KX64_SRCS) \
+ )
+
+ #-------------------------------------------------
+ # Testbench Specific
+ #-------------------------------------------------
+ include $(BASE_DIR)/../sim/general/Makefile.srcs
+ include $(BASE_DIR)/../sim/axi/Makefile.srcs
+
+ # Define only one toplevel module
+ SIM_TOP = dram_fifo_tb
+ # Simulation runtime in microseconds
+ SIM_RUNTIME_US = 80
+
+ SIM_SRCS = \
+ $(abspath dram_fifo_tb.sv) \
+ $(abspath axis_dram_fifo_single.sv) \
+ $(IP_DDR3_32BIT_SIM_OUTS) \
+ $(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
+
+You will notice that the Makefile has 5 distinct sections.
+
+### Section 1: Boilerplate
+
+ #-------------------------------------------------
+ # Top-of-Makefile
+ #-------------------------------------------------
+ # Define BASE_DIR to point to the "top" dir
+ BASE_DIR = $(abspath ../../..)
+ # Include viv_sim_preample after defining BASE_DIR
+ include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
+
+Before declaring any variables or using any recipes, the following must be done (in order):
+
+- Define `BASE_DIR` to tell the build system where the `<repo>/usrp3/top` directory is relative to the
+ current testbench directory.
+- Include `viv_sim_preamble.mak` to initialize boilerplate variables and functions
+
+### Section 2: Design Specific
+
+ #-------------------------------------------------
+ # Design Specific
+ #-------------------------------------------------
+ # Define part using PART_ID (<device>/<package>/<speedgrade>)
+ ARCH = kintex7
+ PART_ID = xc7k410t/ffg900/-2
+
+ # Include makefiles and sources for the DUT and its dependencies
+ include $(BASE_DIR)/../lib/fifo/Makefile.srcs
+ include $(BASE_DIR)/../lib/axi/Makefile.srcs
+ include $(BASE_DIR)/../lib/control/Makefile.srcs
+
+ DESIGN_SRCS = $(abspath \
+ $(FIFO_SRCS) \
+ $(AXI_SRCS) \
+ $(CONTROL_LIB_SRCS) \
+ )
+
+This section contains pointers to sources and other variables for the DUT to function. In the
+example above, we are including all sources from the lib/fifo, lib/axi, lib/control directories.
+
+The following makefile variables are special and must be defined:
+
+- `ARCH`: The architecture targeted for the simulation.
+- `PART_ID`: The exact part targeted for the simulation. Format: `<device>/<package>/<speedgrade>`
+- `DESIGN_SRCS`: Space-separated paths to the DUT and all of its dependencies.
+
+### Section 3: IP Specific
+
+ #-------------------------------------------------
+ # IP Specific
+ #-------------------------------------------------
+ # If simulation contains IP, define the IP_DIR and point
+ # it to the base level IP directory
+ IP_DIR = ../../ip
+
+ # Include makefiles and sources for all IP components
+ # *after* defining the IP_DIR
+ include $(IP_DIR)/ddr3_32bit/Makefile.inc
+ include $(IP_DIR)/axi_intercon_2x64_128/Makefile.inc
+ include $(IP_DIR)/fifo_short_2clk/Makefile.inc
+ include $(IP_DIR)/fifo_4k_2clk/Makefile.inc
+ include $(IP_DIR)/axi4_bram_1kx64/Makefile.inc
+
+ DESIGN_SRCS += $(abspath \
+ $(IP_DDR3_32BIT_SRCS) \
+ $(IP_AXI_INTERCON_2X64_128_SRCS) \
+ $(IP_FIFO_4K_2CLK_SRCS) \
+ $(IP_FIFO_SHORT_2CLK_SRCS) \
+ $(IP_AXI4_BRAM_1KX64_SRCS) \
+ )
+
+If the DUT depends on any Xilinx IP then this section is required. It tell the tools
+which IP cores need to be built in order to run the simulation. The IP specific Makefile
+includes handle the "how" part of building IP. As long as the correct Mafefile is included
+and the IP XCI sources are added to `DESIGN_SRCS`, the IP intermediates will be built correctly.
+
+The `IP_DIR` variable must be defined to point to the base ip directory that contains XCI sources.
+
+### Section 4: Testbench Specific
+
+ #-------------------------------------------------
+ # Testbench Specific
+ #-------------------------------------------------
+ include $(BASE_DIR)/../sim/general/Makefile.srcs
+ include $(BASE_DIR)/../sim/axi/Makefile.srcs
+
+ # Define only one toplevel module
+ SIM_TOP = dram_fifo_tb
+ # Simulation runtime in microseconds
+ SIM_RUNTIME_US = 80
+
+ SIM_SRCS = \
+ $(abspath dram_fifo_tb.sv) \
+ $(abspath axis_dram_fifo_single.sv) \
+ $(IP_DDR3_32BIT_SIM_OUTS) \
+ $(SIM_GENERAL_SRCS) \
+ $(SIM_AXI_SRCS)
+
+This section contains all sources and parameters for the actual testbench. Any simulation
+dependency makefiles can be included here.
+
+The following variables must be defined:
+
+- `SIM_TOP`: The toplevel module name for the simulation project
+- `SIM_RUNTIME_US`: The maximum runtime of the simulation in microseconds. At this time $finish will be called to terminate the testbench.
+- `SIM_SRCS`: This is similar to DESIGN_SRCS except that that should contain a path to `SIM_TOP` and all of its dependencies.
+
+### Section 5: Tool Support
+
+ #-------------------------------------------------
+ # 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
+
+Now that the Makefile knows all the basic information about the testbench, include tool-specific
+makefiles to implement simulation targets. Currently the following simulator makefiles exits:
+
+- ``<repo>/tools/make/viv_simulator.mak``
+
+Please refer to the next section for more information about targets
+
+
+## Testbench Top Level
+
+The top-level module will instantiate the DUT and implement self-checking behavior.
+Test benches could be written in any language (SystemVerilog, Verilog, VHDL) but
+to take advantage of our repository of simulation libraries, it is recommended that SystemVerilog be used.
+
+Here is a sample SystemVerilog top module (you are encouraged to use this as a starting point)
+
+ //
+ // Copyright 2015 Ettus Research LLC
+ //
+
+ `timescale 1ns/1ps
+ `define NS_PER_TICK 1
+ `define NUM_TEST_CASES 3
+
+ `include "sim_clks_rsts.vh"
+ `include "sim_exec_report.vh"
+ `include "sim_cvita_lib.sv"
+
+ module example_fifo_tb();
+ `TEST_BENCH_INIT("example_fifo_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ // Define all clocks and resets
+ `DEFINE_CLK(bus_clk, 1000/166.6667, 50) //166MHz bus_clk
+ `DEFINE_RESET(bus_rst, 0, 100) //100ns for GSR to deassert
+
+ cvita_stream_t chdr_i (.clk(bus_clk));
+ cvita_stream_t chdr_o (.clk(bus_clk));
+
+ // Initialize DUT
+ axi_fifo #(.WIDTH(65), .SIZE(24)) dut_single (
+ .clk(bus_clk),
+ .reset(bus_rst),
+ .clear(1'b0),
+
+ .i_tdata({chdr_i.axis.tlast, chdr_i.axis.tdata}),
+ .i_tvalid(chdr_i.axis.tvalid),
+ .i_tready(chdr_i.axis.tready),
+
+ .o_tdata({chdr_o.axis.tlast, chdr_o.axis.tdata}),
+ .o_tvalid(chdr_o.axis.tvalid),
+ .o_tready(chdr_o.axis.tready),
+
+ .space(),
+ .occupied()
+ );
+
+ //Testbench variables
+ cvita_hdr_t header, header_out;
+ cvita_stats_t stats;
+
+ //------------------------------------------
+ //Main thread for testbench execution
+ //------------------------------------------
+ initial begin : tb_main
+
+ `TEST_CASE_START("Wait for reset");
+ while (bus_rst) @(posedge bus_clk);
+ `TEST_CASE_DONE((~bus_rst));
+
+ repeat (200) @(posedge bus_clk);
+
+ header = '{
+ pkt_type:DATA, has_time:0, eob:0, seqno:12'h666,
+ length:0, sid:$random, timestamp:64'h0};
+
+ `TEST_CASE_START("Fill up empty FIFO then drain (short packet)");
+ chdr_o.axis.tready = 0;
+ chdr_i.push_ramp_pkt(16, 64'd0, 64'h100, header);
+ chdr_o.axis.tready = 1;
+ chdr_o.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.sid==header_out.sid, "Bad packet: Wrong SID");
+ `ASSERT_ERROR(chdr_i.axis.tready, "Bus not ready");
+ `TEST_CASE_DONE(1);
+
+ header = '{
+ pkt_type:DATA, has_time:1, eob:0, seqno:12'h666,
+ length:0, sid:$random, timestamp:64'h0};
+
+ `TEST_CASE_START("Concurrent read and write (single packet)");
+ chdr_o.axis.tready = 1;
+ fork
+ begin
+ chdr_i.push_ramp_pkt(20, 64'd0, 64'h100, header);
+ end
+ begin
+ chdr_o.wait_for_pkt_get_info(header_out, stats);
+ end
+ join
+ `ASSERT_ERROR(stats.count==20, "Bad packet: Length mismatch");
+ `TEST_CASE_DONE(1);
+ end
+ endmodule
+
+
+Each testbench should have the following basic components:
+
+### Timescale Defines and Includes
+
+ `timescale 1ns/1ps
+ `define NS_PER_TICK 1
+ `define NUM_TEST_CASES 3
+
+ `include "sim_clks_rsts.vh"
+ `include "sim_exec_report.vh"
+ `include "sim_cvita_lib.sv"
+
+In addition to the timescale, the infrastructure needs to know the number of
+nanoseconds per simulator tick. This can be a floating point number.
+
+
+In addition to the timescale, you may include any Verilog/SystemVerilog headers here.
+
+### Main Module Definition
+
+ `include "sim_exec_report.vh"
+
+ module example_fifo_tb();
+ `TEST_BENCH_INIT("example_fifo_tb",`NUM_TEST_CASES,`NS_PER_TICK)
+
+ ...
+
+ //------------------------------------------
+ //Main thread for testbench execution
+ //------------------------------------------
+ initial begin : tb_main
+
+ ...
+
+ end
+ endmodule
+
+The name of the main module must match the ``SIM_TOP`` variable value in the Makefile.
+To register this module with the framework, the ``TEST_BENCH_INIT`` macro must be called.
+This macro is defined in ``<repo>/usrp3/sim/general/sim_exec_report.vh``.
+
+``TEST_BENCH_INIT``:
+
+ // Initializes state for a test bench.
+ // This macro *must be* called within the testbench module but
+ // outside the primary initial block
+ // Its sets up boilerplate code for:
+ // - Logging to console
+ // - Test execution tracking
+ // - Gathering test results
+ // - Bounding execution time based on the SIM_RUNTIME_US vdef
+ //
+ // Usage: `TEST_BENCH_INIT(test_name,min_tc_run_count,ns_per_tick)
+ // where
+ // - tb_name: Name of the testbench. (Only used during reporting)
+ // - min_tc_run_count: Number of test cases in testbench. (Used to detect stalls and inf-loops)
+ // - ns_per_tick: The time_unit_base from the timescale declaration
+
+The testbench must also have at least one initial block that consists tests cases (covered later).
+For the sake of convention it should be called ``tb_main``. *All test cases must live in ``tb_main``*. You may
+have other initial block but they must not call macros from ``sim_exec_report.vh`` because the code
+there is not thread-safe.
+
+### Test Cases
+
+A test case in this context is defined as an independent entity that validates an aspect of the DUT behavior
+and which is independent from other test cases i.e. the result of one test case should ideally not affect others.
+
+
+Test cases are wrapped in the ``TEST_CASE_START`` and ``TEST_CASE_DONE`` macros:
+
+ `TEST_CASE_START("Fill up empty FIFO then drain (short packet)");
+ chdr_o.axis.tready = 0;
+ chdr_i.push_ramp_pkt(16, 64'd0, 64'h100, header);
+ chdr_o.axis.tready = 1;
+ chdr_o.wait_for_pkt_get_info(header_out, stats);
+ `ASSERT_ERROR(stats.count==16, "Bad packet: Length mismatch");
+ `ASSERT_ERROR(header.sid==header_out.sid, "Bad packet: Wrong SID");
+ `ASSERT_ERROR(chdr_i.axis.tready, "Bus not ready");
+ `TEST_CASE_DONE(1);
+
+Here are the signatures of the two macros:
+
+``TEST_CASE_START``:
+
+ // Indicates the start of a test case
+ // This macro *must be* called inside the primary initial block
+ //
+ // Usage: `TEST_CASE_START(test_name)
+ // where
+ // - test_name: The name of the test.
+ //
+
+``TEST_CASE_DONE``:
+
+ // Indicates the end of a test case
+ // This macro *must be* called inside the primary initial block
+ // The pass/fail status of test case is determined based on the
+ // the user specified outcome and the number of fatal or error
+ // ASSERTs triggered in the test case.
+ //
+ // Usage: `TEST_CASE_DONE(test_result)
+ // where
+ // - test_result: User specified outcome
+ //
+
+In addition to the test case status, it is also possible to have asserts within
+a test case. We have wrappers for the different kinds of SystemVerilog asserts
+that additionally fail the test case in case the assert fails. An assert triggered
+in a test case will not affect the outcome of another (except for a fatal assert which
+halts the simulator). Supported assert macros:
+
+ // Wrapper around a an assert.
+ // ASSERT_FATAL throws an error assertion and halts the simulator
+ // if cond is not satisfied
+ //
+ // Usage: `ASSERT_FATAL(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+
+ // Wrapper around a an assert.
+ // ASSERT_ERROR throws an error assertion and fails the test case
+ // if cond is not satisfied. The simulator will *not* halt
+ //
+ // Usage: `ASSERT_ERROR(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+
+ // Wrapper around a an assert.
+ // ASSERT_WARNING throws an warning assertion but does not fail the
+ // test case if cond is not satisfied. The simulator will *not* halt
+ //
+ // Usage: `ASSERT_WARNING(cond,msg)
+ // where
+ // - cond: Condition for the assert
+ // - msg: Message for the assert
+ //
+
+### Optional Libraries
+
+It is encouraged to use (and create) reusable libraries in product specific
+test benches. Libraries can provide macros, modules, tasks and functions for
+ease-of-use with particular protocols and subsystems.
+
+The \ref md_usrp3_sim_writing_testbenches page has more information.
diff --git a/fpga/docs/usrp3/simulation.md b/fpga/docs/usrp3/simulation.md
new file mode 100644
index 000000000..16afed462
--- /dev/null
+++ b/fpga/docs/usrp3/simulation.md
@@ -0,0 +1,11 @@
+# Simulation
+
+## Instructions
+
+ - \subpage md_usrp3_sim_running_testbenches "Running Testbenches"
+ - \subpage md_usrp3_sim_writing_testbenches "Writing Testbenches"
+
+## Library Reference
+
+ - \subpage md_usrp3_sim_libs_general "General Purpose"
+ - \subpage md_usrp3_sim_libs_axi "AXI"
diff --git a/fpga/docs/usrp3/vivado_env_utils.md b/fpga/docs/usrp3/vivado_env_utils.md
new file mode 100644
index 000000000..ad5c6266e
--- /dev/null
+++ b/fpga/docs/usrp3/vivado_env_utils.md
@@ -0,0 +1,87 @@
+# Vivado Environment Utilities
+
+## Environment Setup
+
+- Navigate to `usrp3/top/{project}` where project is:
+ + x300: For USRP X300 and USRP X310
+ + e3xx: For USRP E310
+ + e320: For USRP E320
+ + n3xx: For USRP N300/N310/N320
+
+- To setup up the Ettus Research Xilinx build environment run
+ + `source setupenv.sh` (If Vivado is installed in the default path /opt/Xilinx/Vivado) _OR_
+ + `source setupenv.sh --vivado-path=<VIVADO_PATH>` (where VIVADO_PATH is a non-default installation path)
+
+- This should not only enable building USRP FPGAs but also make the following utlities available
+
+## ModelSim Specific
+
+The setupenv.sh script will search the system for ModelSim installations and setup everything to run it natively and
+within Vivado. The currently support versions of ModelSim are PE, DE, SE, DE-64, SE-64.
+
+The following functions are also available in the environment:
+
+ build_simlibs: Build ModelSim simulation libraries for Vivado
+
+## IP Management
+
+### Create Vivado IP
+
+ viv_create_new_ip: Create a new Vivado IP instance and a Makefile for it
+
+ Usage: viv_create_new_ip <IP Name> <IP Location> <IP VLNV> <Product>
+ - <IP Name>: Name of the IP instance
+ - <IP Location>: Base location for IP
+ - <IP VLNV>: The vendor, library, name, and version (VLNV) string for the IP as defined by Xilinx
+ - <Product>: Product to generate IP for
+
+### Modify existing Vivado IP
+
+ viv_modify_ip: Modify an existing Vivado IP instance
+
+ Usage: viv_modify_ip <IP XCI Path>
+ - <IP XCI Path>: Path to the IP XCI file.
+
+### List supported Vivado IP
+
+ viv_ls_ip: List the items in the Vivado IP catalog
+
+ Usage: viv_ls_ip <Product>
+ - <Product>: Product to generate IP for.
+
+### Upgrade IP to the environment version of Vivado
+
+ viv_upgrade_ip: Upgrade one or more Xilinx IP targets
+
+ Usage: viv_upgrade_ip <IP Directory> [--recursive]
+ - <IP Directory>: Path to the IP XCI file.
+
+## Hardware Management
+
+### Launch Vivado Hardware Console
+
+ viv_hw_console: Launch the Tcl hardware console
+
+ Usage: viv_upgrade_ip
+
+### List connected JTAG devices
+
+ viv_jtag_list: List all devices (and their addresses) that are connected to the system using the Xilinx platform cable
+
+ Usage: viv_jtag_list
+
+### Program device over JTAG
+
+ viv_jtag_program: Downloads a bitfile to an FPGA device using Vivado
+
+ Usage: viv_jtag_program <Bitfile Path> [<Device Address> = 0:0]
+ - <Bitfile Path>: Path to a .bit FPGA configuration file
+ - <Device Address>: Address to the device in the form <Target>:<Device>
+ Run viv_jtag_list to get a list of connected devices
+
+### Probe Xilinx bitfile
+
+ probe_bitfile: Probe a Xilinx bit file and report header information
+
+ Usage: probe_bitfile <Bitfile Path>
+ - <Bitfile Path>: Path to a .bit FPGA configuration file