USRP Hardware Driver and USRP Manual Version: 4.2.0.0
UHD and USRP Manual
Simulation Libraries

Several simulation libraries are available for use in your testbenches, in the form of SystemVerilog packages, classes, and interfaces. The bus functional models (BFM) are implemented as SystemVerilog classes and use SystemVerilog interfaces to connect to your device under test (DUT). These classes provide member functions and tasks for communicating with the BFMs.

A few commonly used SystemVerilog packages are described below. See each package file for additional documentation.

PktTestExec

PktTestExec.sv contains utilities for testbench reporting, assertions, and simulation timeouts. The associated header file, test_exec.svh, contains macros for use with PkgTestExec. These macros are used to implement SystemVerilog assertions. The header also defines timeunit and timeprecision.

Note: The timeunit must be 1ns in order for PkgTestExec to use and report times correctly.

PkgTestExec Tasks and Functions

Below are some of the methods available in PkgTestExec. See PkgTestExec.sv for additional documentation.

  • start_tb(string tb_name, realtime time_limit = 10ms)
    Called at the start of the testbench. A time limit can be specified to prevent the testbench from never ending.
  • end_tb(bit finish = 1)
    Called at the end of the testbench. Displays final results and optionally calls $finish.
  • start_test(string test_name, realtime time_limit = 0)
    Called at the start of a test. A time limit can be given to cause an error if the test takes longer than expected or never ends.
  • end_test(int test_result = 1)
    Called at the end of a test. A pass (1) or fail (0) can be passed to indicate if the test passed or failed. Any failed assertion, using the test_exec.svh macros, will also be considered when deciding if the test passed or failed. If any fatal or error assertions failed during the test then it will be considered to have failed.
  • start_timeout(
        output timeout_t  handle,
        input  realtime   timeout_delay,
        input  string     message = "Timeout",
        input  severity_t severity = SEV_ERROR)
    Called to start a timeout countdown. If the timeout is not ended before the indicated simulation time elapses then an assertion of the given severity will be thrown. This is very useful for ensuring that tests complete in a timely manner and to report which timeout was exceeded.
  • end_timeout(timeout_t handle)
    Called to end a timeout countdown when it is no longer needed.

Macros

The following macros are defined in test_exec.svh. These update internal variables to track the state of the testbench and to report the final results.

  • ASSERT_FATAL(EXPR, MESSAGE)
    Encapsulates a SystemVerilog $assert with a $fatal severity.
  • ASSERT_ERROR(EXPR, MESSAGE)
    Encapsulates a SystemVerilog $assert with a $error severity.
  • ASSERT_WARNING(EXPR, MESSAGE)
    Encapsulates a SystemVerilog $assert with a $warning severity.
  • ASSERT_INFO(EXPR, MESSAGE)
    Encapsulates a SystemVerilog $assert with an $info severity.

Where:

  • EXPR is the condition for the assertion (what you expect to be true)
  • MESSAGE is the message string to report if the assertion fails

PkgChdrUtils

The PkgChdrUtils package includes various definitions and functions for interacting with the RFNoC network protocol, called the Condensed Hierarchical Datagram for RFNoC (CHDR). See PkgChdrUtils.sv for additional documentation.

PkgChdrData

The PkgChdrData package contains the CHDR and item data types, as well as utilities, that are useful for interacting with RFNoC data. An item refers to an RF data sample or whatever unit of data an RFNoC block expects.

For example, the CHDR protocol data word type (chdr_word_t) and the RF sample data type (item_t) can be defined using the following example:

localparam CHDR_W = 64;    // CHDR bus width
localparam ITEM_W = 32;    // RF data sample size (sc16)
typedef ChdrData #(CHDR_W, ITEM_W)::chdr_word_t chdr_word_t;
typedef ChdrData #(CHDR_W, ITEM_W)::item_t      item_t;

SystemVerilog queues are used to store CHDR words and data samples. A queue of CHDR words or data samples can be reorganized into queues of different data widths using the following example:

chdr_word_t chdr_words[$];  // Queue of CHDR packet words
item_t      samples[$];     // Queue of RF data samples
logic [7:0] bytes[$];       // Queue of bytes

// Convert the CHDR words to samples
samples = ChdrData#(CHDR_W, ITEM_W)::chdr_to_item(chdr_words);

// Convert the samples to CHDR words
chdr_words = ChdrData#(CHDR_W, ITEM_W)::item_to_chdr(samples);

// Convert the samples to a queue of bytes
bytes = ChdrData#(ITEM_W, 8)::chdr_to_item(samples);

// Convert the bytes to a queue of samples
bytes = ChdrData#(ITEM_W, 8)::item_to_chdr(samples);

PkgRfnocBlockCtrlBfm

The PkgRfnocBlockCtrlBfm package contains the RfnocBlockCtrlBfm bus functional model (BFM) used to emulate a software block controller for an RFNoC block. This is the BFM used to interact with an RFNoC block in simulation. See the testbench example for an example of how to instantiate and connect the BFM to your DUT.

To be used, the BFM must be connected to the RFNoC block using an RfnocBackendIf interface for the RFNoC backend interface and AxiStreamIf interfaces for the AXIS-CHDR ports.

Once connected, several member functions are available through the BFM. A few examples are shown below, but many more are available. Refer to PkgRfnocBlockCtrlBfm.sv for additional documentation.

  • RfnocBlockCtrlBfm::run()
    Start the BFMs running. This should be called at the start of the testbench after start_tb() and before the BFM is used.
  • RfnocBlockCtrlBfm::reg_read(input ctrl_address_t addr, output ctrl_word_t word)
    Read a register from the RFNoC block.
  • RfnocBlockCtrlBfm::reg_write(ctrl_address_t addr, ctrl_word_t word)
    Write to a register on the RFNoC block.
  • send_items(int port, item_t items[$], chdr_word_t metadata[$] = {}, packet_info_t pkt_info = 0)
    Enqueue a packet of samples (or other data items) to be sent by the BFM to the RFNoC block on the indicated block port.
  • recv(int port, output chdr_word_t data[$], output int data_bytes)
    Recv a packet of samples (or other data items) from the indicated port on the RFNoC block.
  • set_master_stall_prob(int stall_probability = DEF_STALL_PROB)
    Set the probability, as value from 0-100, of the BFM's AXI-Stream master stalling (deasserting TVALID) between transfers.
  • set_slave_stall_prob(int stall_probability = DEF_STALL_PROB)
    Set the probability, as value from 0-100, of the BFM's AXI-Stream slave stalling (deasserting TREADY) on a given clock cycle.

The level of push-back on the flow control used by the AXI-Stream interfaces of the BFM are controlled by setting a probability. This allows you to easily test underflow and overflow tolerance in your testbenches.

Low-level tasks and functions are also available for inputting raw packets directly.

sim_clock_gen

The sim_clock_gen module makes it easy create clocks and synchronous resets, and to interact with them. See sim_clock_gen.sv for additional documentation.

Some features include:

  • Start and stop the clock
  • Change the frequency
  • Change the duty cycle
  • Kill the clock (prevent any new simulation events)
  • Wait for n rising/falling clock edges

PkgAxiStream

The PkgAxiStreamBfm package contains the AxistreamPacket and AxiStreamBfm classes which are used to model AXI4-Stream interfaces in the testbenches. AxiStreamIf is the interface used for AXI-Stream. The RFNoC CHDR BFMs inherit from AxiStreamBfm in order to implement the AXI-Stream interfaces used by RFNoC.

The AXI-Stream BFMs provide typical SystemVerilog put(), get(), try_put(), and try_get() tasks and functions for interacting with the models. Many other useful functions are also available. See the package file for details.