# 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 \ref md_usrp3_sim_writing_sim_top "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 \em 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.