Strict BFM Protocol Monitors
RouteRTL cocotb BFMs attach passive protocol monitors by default. A BFM that
drives or responds on a protocol bus should fail the test on the first monitor
violation, instead of relying on each test to call env.attach_monitors().
The constructor option is:
driver = AxiStreamSource(bus, clk, rst)
driver = AxiStreamSource(bus, clk, rst, strict_protocol=False)
Use strict_protocol=False only when the test is intentionally generating an
illegal waveform, such as an EMITS/KAT vector proving that a monitor catches a
specific clause. Normal DUT-facing tests should keep the default.
Covered BFMs
The strict path is wired into the shipped protocol BFMs for AXI-Lite, AXI4,
AXI-Stream, Avalon-MM, Avalon-ST, APB, Wishbone, native memory, OC stream TX,
XTMEM, GMII, UART, SPI, and I2C. TbEnv.attach_monitors() uses the same
fail-fast helper for monitors it attaches explicitly.
Each protocol keeps its rule set in its monitor. The BFM only composes that
monitor and converts the first recorded violation into an AssertionError.
Monitor IDs
The fail-fast wrapper reports the monitor check ID, channel, timestamp, and message. Current production monitor IDs include the violation IDs below, plus positive observation IDs used by EMITS/KAT coverage.
| Protocol | Check IDs |
|---|---|
| APB | APB_RST, APB_SETUP, APB_STAB, APB_SLVERR, APB_WAIT, APB_READ, APB_WRITE |
| Avalon-MM | AVL_RST, AVL_OVERLAP, AVL_WR_HOLD, AVL_RD_HOLD, AVL_RD_VALID, AVL_WAIT_STALL, AVL_READ, AVL_WRITE |
| Avalon-ST | AST_RST, AST_DATA_HOLD, AST_EOP_WO_SOP, AST_SOP_MID_PKT, AST_EMPTY_WO_EOP, AST_CHANNEL_MID_PKT, AST_PACKET |
| AXI4 | AXI4_RST, AXI4_BURST, AXI4_WLAST_BAD, AXI4_READ, AXI4_WRITE |
| AXI-Lite | AXI_RST_AW, AXI_RST_W, AXI_RST_B, AXI_RST_AR, AXI_RST_R, AXI_STAB_AW, AXI_STAB_W, AXI_STAB_B, AXI_STAB_AR, AXI_STAB_R, AXI_READ, AXI_WRITE |
| AXI-Stream | AXIS_RST, AXIS_VALID_STICKY, AXIS_DATA_HOLD, AXIS_TLAST, AXIS_SOF_MID_PKT, AXIS_EOP_WO_SOP, AXIS_TKEEP_PARTIAL, AXIS_TID_MID_PKT, AXIS_TDEST_MID_PKT, AXIS_SINGLE_BEAT |
| GMII | GMII_IFG_MIN, GMII_VALID_QUALIFICATION, GMII_RST, GMII_RX_ER, GMII_CLOCK_PERIOD |
| I2C | I2C_GLITCH, I2C_START, I2C_STOP |
| Native memory | NM_ACK_NO_CS, NM_WE_RE_BOTH, NM_READ, NM_WRITE |
| OC stream | OC_WR_NO_WA, OC_BE_PARTIAL, OC_SOP, OC_EOP, OC_BEAT |
| SPI | SPI_CLK_DESELECTED, SPI_SHORT_XFER, SPI_XFER |
| TSE MAC | generic Avalon-MM IDs plus TSE_BUSY_TIMEOUT, TSE_RDATA_WINDOW |
| UART | UART_BREAK, UART_FRAME_ERR, UART_PARITY_ERR, UART_BYTE |
| Wishbone | WB_RST, WB_STB_WO_CYC, WB_ACK_WO_CYC, WB_ACK_WO_STB, WB_READ, WB_WRITE |
| XTMEM | XTMEM_RST, XTMEM_REQ_HOLD, XTMEM_WDATA_HOLD, XTMEM_RDATA_HOLD, XTMEM_WDATA_NO_REQ, XTMEM_RDATA_NO_REQ, XTMEM_BURST_UNDERRUN, XTMEM_READ, XTMEM_WRITE |
Serial Notes
UART monitors do not need a free-running sample clock. They observe line edges directly and poll for violations.
SPI monitors oversample sclk, so pass a testbench clock when constructing
SPI BFMs:
master = SpiMaster(bus, config, sample_clk=dut.CLK)
If strict_protocol=True and sample_clk is omitted, the SPI BFM raises a
ValueError rather than running unmonitored.
I2C supports both separate sda/scl signals and combined I2C_PINS[1:0];
the strict monitor sees the same logical bus in either mode.