Module bfm

This document contains technical documentation for the bfm module. To browse the source code, visit the repository on GitHub.

This module contains a large set of Bus Functional Model (BFM) components for efficient VHDL simulation. These BFMs are used to send stimuli or check data in your testbench. Supports AXI, AXI-Lite and AXI-Stream protocols.

axi_bfm_pkg.vhd

View source code on GitHub.

Types and functions for the AXI BFMs.

axi_lite_master.vhd

View source code on GitHub.

component axi_lite_master is
  generic (
    bus_handle : bus_master_t;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_lite_m2s : out axi_lite_m2s_t;
    axi_lite_s2m : in axi_lite_s2m_t
  );
end component;

Wrapper around VUnit axi_lite_master verification component (VC). Uses convenient record types for the AXI-Lite signals. Performs protocol checking on the R and B channels to verify that the downstream AXI-Lite slave is performing everything correctly.

The instantiated verification component will create AXI-Lite read/write transactions based on VUnit VC calls, such as read_bus.

If this BFM is used for a register bus, the convenience methods in reg_operations_pkg.vhd can be useful. Note that the default value for bus_handle is the same as the default bus handle for the procedures in reg_operations_pkg.vhd.

axi_lite_read_slave.vhd

View source code on GitHub.

component axi_lite_read_slave is
  generic (
    axi_slave : axi_slave_t;
    data_width : positive range 1 to axi_lite_data_sz;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_lite_read_m2s : in axi_lite_read_m2s_t;
    axi_lite_read_s2m : out axi_lite_read_s2m_t
  );
end component;

Wrapper around VUnit axi_read_slave verification component. Uses convenient record types for the AXI-Lite signals. Performs protocol checking to verify that the upstream AXI-Lite master is performing everything correctly.

The instantiated verification component will process the incoming AXI-Lite operations and apply them to the VUnit memory model.

axi_lite_slave.vhd

View source code on GitHub.

component axi_lite_slave is
  generic (
    axi_read_slave : axi_slave_t;
    axi_write_slave : axi_slave_t;
    data_width : positive range 1 to axi_lite_data_sz;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_lite_read_m2s : in axi_lite_read_m2s_t;
    axi_lite_read_s2m : out axi_lite_read_s2m_t;
    --# {{}}
    axi_lite_write_m2s : in axi_lite_write_m2s_t;
    axi_lite_write_s2m : out axi_lite_write_s2m_t
  );
end component;

Wrapper around VUnit axi_read_slave and axi_write_slave verification components. Uses convenient record types for the AXI-Lite signals.

The instantiated verification components will process the incoming AXI-Lite operations and apply them to the VUnit memory model.

This entity instantiates axi_lite_read_slave.vhd and/or axi_lite_write_slave.vhd based on what generics are provided. See those BFMs for more details.

axi_lite_write_slave.vhd

View source code on GitHub.

component axi_lite_write_slave is
  generic (
    axi_slave : axi_slave_t;
    data_width : positive range 1 to axi_lite_data_sz;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_lite_write_m2s : in axi_lite_write_m2s_t;
    axi_lite_write_s2m : out axi_lite_write_s2m_t
  );
end component;

Wrapper around VUnit axi_write_slave verification component. Uses convenient record types for the AXI-Lite signals. Performs protocol checking to verify that the upstream AXI-Lite master is performing everything correctly.

The instantiated verification component will process the incoming AXI-Lite operations and apply them to the VUnit memory model.

axi_master.vhd

View source code on GitHub.

component axi_master is
  generic (
    bus_handle : bus_master_t;
    id_width : natural range 0 to axi_id_sz;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_read_m2s : out axi_read_m2s_t;
    axi_read_s2m : in axi_read_s2m_t;
    --# {{}}
    axi_write_m2s : out axi_write_m2s_t;
    axi_write_s2m : in axi_write_s2m_t
  );
end component;

Creates AXI read/write transactions by wrapping the VUnit axi_lite_master verification component (VC). Uses convenient record types for the AXI signals. Performs protocol checking to verify that the downstream AXI slave is performing everything correctly.

Note

This AXI BFM wraps an AXI-Lite verification component, meaning it can not be used to produce burst transactions. If you want to create burst transactions, with built-in checkers, see the axi_read_master.vhd and axi_write_master.vhd BFMs instead.

The AXI-Lite interface of the wrapped verification component is connected to the “full” AXI interface of this BFM. This wrapper is typically only used for register read/write operations on the chip top level, where the register bus is still AXI.

It is used by performing VUnit VC calls, such as read_bus, or, preferably when operating on a register bus, by using the convenience methods in reg_operations_pkg.vhd.

axi_read_master.vhd

View source code on GitHub.

component axi_read_master is
  generic (
    id_width : natural range 0 to axi_id_sz;
    data_width : positive range 8 to axi_data_sz;
    job_queue : queue_t;
    reference_data_queue : queue_t;
    ar_stall_config : stall_configuration_t;
    r_stall_config : stall_configuration_t;
    seed : natural;
    logger_name_suffix : string;
    drive_invalid_value : std_ulogic
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_read_m2s : out axi_read_m2s_t;
    axi_read_s2m : in axi_read_s2m_t;
    --# {{}}
    num_bursts_checked : out natural
  );
end component;

BFM that creates AXI read transactions and checkers based on a simple interface.

AR transactions will be created based on jobs (axi_master_bfm_job_t) that the user pushes to the job_queue VUnit queue. The data returned on the R channel will be checked against the integer_array_t data pushed by the user to the reference_data_queue. The returned RID will be checked that it is the same as the corresponding ARID.

Note

This BFM will inject random handshake jitter/stalling on the AXI channels for good verification coverage. Modify the ar_stall_config and r_stall_config generics to change the behavior. You can also set seed to something unique in order to vary the randomization in each simulation run. This can be done conveniently with the add_vunit_config() method if using tsfpga.

This BFM will also perform AXI-Stream protocol checking on the R channels to verify that the downstream AXI slave is performing everything correctly.

The byte length of the transactions (as set in the job as well as by the length of the reference_data arrays) does not need to be aligned with the data width of the bus. If unaligned, the last AXI beat will not have all byte lanes checked against reference data.

Warning

The RID check is based on the assumption that R transactions are returned in the same order as AR transactions are sent.

Also the job address is assumed to be aligned with the bus data width.

axi_read_slave.vhd

View source code on GitHub.

component axi_read_slave is
  generic (
    axi_slave : axi_slave_t;
    data_width : positive range 8 to axi_data_sz;
    id_width : natural range 0 to axi_id_sz;
    address_width : positive range 1 to axi_a_addr_sz;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_read_m2s : in axi_read_m2s_t;
    axi_read_s2m : out axi_read_s2m_t
  );
end component;

Wrapper around VUnit axi_read_slave verification component. Uses convenient record types for the AXI signals. This BFM will also perform protocol to verify that the upstream AXI master is performing everything correctly.

The instantiated verification component will process the incoming AXI operations and apply them to the VUnit memory model.

axi_slave.vhd

View source code on GitHub.

component axi_slave is
  generic (
    axi_read_slave : axi_slave_t;
    axi_write_slave : axi_slave_t;
    data_width : positive range 8 to axi_data_sz;
    id_width : natural range 0 to axi_id_sz;
    w_fifo_depth : natural;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_read_m2s : in axi_read_m2s_t;
    axi_read_s2m : out axi_read_s2m_t;
    --# {{}}
    axi_write_m2s : in axi_write_m2s_t;
    axi_write_s2m : out axi_write_s2m_t
  );
end component;

Wrapper around VUnit axi_read_slave and axi_write_slave verification components. Uses convenient record types for the AXI signals.

The instantiated verification components will process the incoming AXI operations and apply them to the VUnit memory model.

This entity instantiates axi_read_slave.vhd and/or axi_write_slave.vhd based on what generics are provided. See those BFMs for more details.

axi_slave_bfm_pkg.vhd

View source code on GitHub.

Types and convenience methods for working with VUnit axi_slave_t. Used by some BFMs.

axi_stream_master.vhd

View source code on GitHub.

component axi_stream_master is
  generic (
    data_width : positive;
    data_queue : queue_t;
    user_width : natural;
    user_queue : queue_t;
    stall_config : stall_configuration_t;
    seed : natural;
    logger_name_suffix : string;
    strobe_unit_width : positive;
    drive_invalid_value : std_ulogic
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    ready : in std_ulogic;
    valid : out std_ulogic;
    last : out std_ulogic;
    data : out std_ulogic_vector;
    strobe : out std_ulogic_vector;
    user : out std_ulogic_vector;
    --# {{}}
    num_packets_sent : out natural
  );
end component;

BFM for sending data on an AXI-Stream interface.

Data is pushed to the data_queue VUnit queue as a VUnit integer_array. Each element in the integer array should be an unsigned byte. Little endian byte order is assumed.

Note

This BFM will inject random handshake jitter/stalling for good verification coverage. Modify the stall_config generic to change the behavior. You can also set seed to something unique in order to vary the randomization in each simulation run. This can be done conveniently with the add_vunit_config() method if using tsfpga.

Unaligned packet length

The byte length of the packets (as indicated by the length of the data_queue arrays) does not need to be aligned with the data_width of the bus. If unaligned, the last data beat will not have all byte lanes set to valid data and strobe.

User signalling

This BFM optionally supports sending auxiliary data on the user port also. Enable by setting a non-zero user_width and a valid user_queue. User data is pushed as a VUnit integer_array just as for the regular data. The length of packets must be the same as what is pushed to the data_queue.

axi_stream_slave.vhd

View source code on GitHub.

component axi_stream_slave is
  generic (
    data_width : positive;
    reference_data_queue : queue_t;
    id_width : natural;
    reference_id_queue : queue_t;
    user_width : natural;
    reference_user_queue : queue_t;
    stall_config : stall_configuration_t;
    seed : natural;
    logger_name_suffix : string;
    strobe_unit_width : positive;
    enable_strobe : boolean;
    well_behaved_stall : boolean;
    disable_last_check : boolean
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    ready : out std_ulogic;
    valid : in std_ulogic;
    last : in std_ulogic;
    data : in std_ulogic_vector;
    strobe : in std_ulogic_vector;
    id : in u_unsigned;
    user : in std_ulogic_vector;
    --# {{}}
    enable : in std_ulogic;
    num_packets_checked : out natural
  );
end component;

BFM for verifying data on an AXI-Stream interface.

Reference data is pushed to the reference_data_queue VUnit queue as a VUnit integer_array. Each element in the integer array should be an unsigned byte. Little endian byte order is assumed.

Note

This BFM will inject random handshake jitter/stalling for good verification coverage. Modify the stall_config generic to change the behavior. You can also set seed to something unique in order to vary the randomization in each simulation run. This can be done conveniently with the add_vunit_config() method if using tsfpga.

Unaligned packet length

The byte length of the packets (as indicated by the length of the reference_data_queue arrays) does not need to be aligned with the data width of the bus. If unaligned, the last beat will not have all data byte lanes checked against reference data.

ID field check

An optional expected ID can be pushed as a natural to the reference_id_queue in order to enable ID check of each beat.

User field check

Furthermore, and optional check of the user field can be enabled by setting the user_width to a non-zero value and pushing reference data to the reference_user_queue. Reference user data should be a VUnit integer_array just as for the regular data.

axi_write_master.vhd

View source code on GitHub.

component axi_write_master is
  generic (
    id_width : natural range 0 to axi_id_sz;
    data_width : positive range 8 to axi_data_sz;
    job_queue : queue_t;
    data_queue : queue_t;
    aw_stall_config : stall_configuration_t;
    w_stall_config : stall_configuration_t;
    b_stall_config : stall_configuration_t;
    seed : natural;
    logger_name_suffix : string;
    enable_axi3 : boolean;
    drive_invalid_value : std_ulogic
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_write_m2s : out axi_write_m2s_t;
    axi_write_s2m : in axi_write_s2m_t;
    --# {{}}
    num_bursts_done : out natural
  );
end component;

BFM that creates AXI write transactions and checkers based on a simple interface.

AW transactions will be created based on jobs (axi_master_bfm_job_t) that the user pushes to the job_queue VUnit queue. A W burst will be created based on the integer_array_t data pushed by the user to the data_queue. Each AW transaction will result in a check that the eventually returned BID is correct.

Note

This BFM will inject random handshake jitter/stalling on the AXI channels for good verification coverage. Modify the aw_stall_config, w_stall_config and b_stall_config generics to change the behavior. You can also set seed to something unique in order to vary the randomization in each simulation run. This can be done conveniently with the add_vunit_config() method if using tsfpga.

The byte length of the transactions (as set in the job as well as by the length of the data_queue arrays) does not need to be aligned with the data width of the bus. If unaligned, the last AXI beat will have a strobe that is not ‘1’ for all byte lanes.

The job address, however, is assumed to be aligned with bus data width.

Note that data can be pushed to data_queue before the corresponding job is pushed. This data will be pushed to the AXI W channel straight away, possibly before the AW transaction (unless in AXI3 mode).

This BFM will also perform protocol checking to verify that the downstream AXI slave is performing everything correctly.

axi_write_slave.vhd

View source code on GitHub.

component axi_write_slave is
  generic (
    axi_slave : axi_slave_t;
    data_width : positive range 8 to axi_data_sz;
    id_width : natural range 0 to axi_id_sz;
    address_width : positive range 1 to axi_a_addr_sz;
    w_fifo_depth : natural;
    enable_axi3 : boolean;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    axi_write_m2s : in axi_write_m2s_t;
    axi_write_s2m : out axi_write_s2m_t;
    --# {{}}
    num_bursts_done : out natural
  );
end component;

Wrapper around VUnit axi_write_slave verification component. Uses convenient record types for the AXI signals. This BFM will also perform protocol checking to verify that the upstream AXI master is performing everything correctly.

The instantiated verification component will process the incoming AXI operations and apply them to the VUnit memory model.

bus_master_bfm_pkg.vhd

View source code on GitHub.

Types and convenience methods for working with VUnit bus_master_t. Used by some BFMs.

handshake_master.vhd

View source code on GitHub.

component handshake_master is
  generic (
    stall_config : stall_configuration_t;
    seed : natural;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    data_is_valid : in std_ulogic;
    --# {{}}
    ready : in std_ulogic;
    valid : out std_ulogic
  );
end component;

Toggle the valid signal based on probabilities set via generics. This realizes a handshake master with jitter that is compliant with the AXI-Stream standard. According to the standard, valid may be lowered only after a transaction.

This BFM can be more convenient to use than the axi_stream_master.vhd BFM in some cases. Specifically when the data is not an SLV, but instead a record. When using AXI-Stream BFMs we would need to have conversion functions to and from SLV. When using this BFM instead for the handshaking, the data can be handled as records in the testbench with no conversion necessary.

See the testbench tb_handshake_bfm for example usage.

handshake_slave.vhd

View source code on GitHub.

component handshake_slave is
  generic (
    stall_config : stall_configuration_t;
    seed : natural;
    well_behaved_stall : boolean;
    logger_name_suffix : string
  );
  port (
    clk : in std_ulogic;
    --# {{}}
    data_is_ready : in std_ulogic;
    --# {{}}
    ready : out std_ulogic;
    valid : in std_ulogic
  );
end component;

Toggle the ‘ready’ signal based on probabilities set via generics. This realizes a handshake slave with jitter that is compliant with the AXI-Stream standard. According to the standard, ‘ready’ can be lowered at any time, not just after a transaction.

This BFM can be more convenient to use than the axi_stream_slave.vhd BFM in some cases. Specifically when the data is not an SLV, but instead a record. When using AXI-Stream BFMs we would need to have conversion functions to and from SLV. When using this BFM instead for the handshaking, the data can be handled as records in the testbench with no conversion necessary.

See the testbench ‘tb_handshake_bfm’ for example usage.

integer_array_bfm_pkg.vhd

View source code on GitHub.

Convenience methods for working with VUnit integer_array_t. Used by some BFMs.

memory_bfm_pkg.vhd

View source code on GitHub.

Types and convenience methods for working with VUnit memory_t. Used by some BFMs.

queue_bfm_pkg.vhd

View source code on GitHub.

Types and convenience methods for working with VUnit queue_t. Used by some BFMs.

stall_bfm_pkg.vhd

View source code on GitHub.

Types and methods for creating random stall in a testbench or BFM.