SystemVerilog Assertions (SVA) as executable specifications. Use when defining timing requirements, protocol specifications, or formal properties for RTL verification.
SVA methodology treating assertions as executable specifications, not testbench utilities.
Specifications SHALL be written as SystemVerilog Assertions
sim/assertions/
āāā spec/ # Timing-related specifications (REQUIRED location)
ā āāā uart_timing_spec.sva
ā āāā axi4_protocol_spec.sva
ā āāā frame_parser_timing_spec.sva
āāā functional/ # Functional correctness assertions
ā āāā Frame_Parser_Assertions.sv
ā āāā Uart_Tx_Assertions.sv
āāā bind/ # Bind statements
āāā bind_Frame_Parser.sv
āāā bind_Uart_Tx.sv
Critical Rules:
module Frame_Parser (/*...*/);
// ā Never embed assertions in DUT
assert property (@(posedge clk) frame_valid |-> byte_count >= 4);
endmodule
// File: sim/assertions/functional/Frame_Parser_Assertions.sv
module Frame_Parser_Assertions (
input logic clk,
input logic rst,
input logic frame_valid,
input logic [7:0] byte_count
);
// Property definition
property p_frame_minimum_length;
@(posedge clk) disable iff (rst)
frame_valid |-> byte_count >= 4;
endproperty
// Assertion
a_frame_minimum_length: assert property (p_frame_minimum_length)
else $error("Frame length violation: byte_count=%0d", byte_count);
// Optional coverage
c_frame_minimum_length: cover property (p_frame_minimum_length);
endmodule
// File: sim/assertions/bind/bind_Frame_Parser.sv
`ifdef ENABLE_ASSERTIONS
bind Frame_Parser Frame_Parser_Assertions u_assertions (
.clk(clk),
.rst(rst),
.frame_valid(frame_valid),
.byte_count(byte_count)
);
`endif
Enable at compile time:
dsim +define+ENABLE_ASSERTIONS -f dsim_config.f
Example: UART protocol timing spec
// File: sim/assertions/spec/uart_timing_spec.sva
module uart_timing_spec (
input logic clk,
input logic rst,
input logic tx_start,
input logic tx_done,
input logic [15:0] baud_counter
);
// Specification: TX duration must match baud rate
property p_tx_duration;
int start_time;
@(posedge clk) disable iff (rst)
(tx_start, start_time = $time) |->
##[1:$] (tx_done && ($time - start_time >= baud_counter * 10));
endproperty
a_tx_duration: assert property (p_tx_duration)
else $error("TX duration too short");
// Specification: No overlapping TX operations
property p_no_tx_overlap;
@(posedge clk) disable iff (rst)
tx_start |-> !tx_start throughout ##[1:$] tx_done;
endproperty
a_no_tx_overlap: assert property (p_no_tx_overlap)
else $error("TX overlap detected");
endmodule
Use p_ prefix for properties, a_ for assertions, c_ for coverage:
property p_handshake_valid_before_ready;
@(posedge clk) disable iff (rst)
ready |-> valid;
endproperty
a_handshake: assert property (p_handshake_valid_before_ready)
else $error("Ready asserted without valid");
c_handshake: cover property (p_handshake_valid_before_ready);
Good (specification-focused):
// Specifies: "Request must be followed by acknowledge within 10 cycles"
property p_request_ack_latency;
@(posedge clk) disable iff (rst)
request |-> ##[1:10] acknowledge;
endproperty
Bad (implementation-focused):
// ā References internal state machine states
property p_state_machine_transition;
@(posedge clk) disable iff (rst)
(state == WAIT_ACK) |-> ##[1:10] (state == IDLE);
endproperty
// Fixed delay: exactly N cycles later
##N expr // expr true N cycles after trigger
// Range delay: between M and N cycles
##[M:N] expr // expr true M to N cycles after trigger
// Unbounded delay: eventually
##[1:$] expr // expr true sometime in the future
// Overlapping implication (same cycle)
antecedent |-> consequent
// Non-overlapping implication (next cycle)
antecedent |=> consequent
// Example: handshake protocol
property p_valid_ready_handshake;
@(posedge clk) disable iff (rst)
valid && ready |-> ##1 !valid; // Valid drops after handshake
endproperty
// Consecutive repetition
signal[*N] // signal true for exactly N cycles
signal[*M:N] // signal true for M to N cycles
// Go-to repetition (allows gaps)
signal[->N] // signal becomes true N times (eventually)
// Example: burst detection
property p_burst_transfer;
@(posedge clk) disable iff (rst)
burst_start |-> valid[*4]; // 4 consecutive valid cycles
endproperty
// Condition must hold throughout sequence
property p_hold_valid_until_ready;
@(posedge clk) disable iff (rst)
valid |-> valid throughout ##[1:$] ready;
endproperty
Example specification for AXI4-Lite write channel:
// File: sim/assertions/spec/axi4_protocol_spec.sva
module axi4_protocol_spec (
input logic clk,
input logic rst,
input logic awvalid, awready,
input logic wvalid, wready,
input logic bvalid, bready
);
// AXI4 Rule: AWVALID stable until AWREADY
property p_awvalid_stable;
@(posedge clk) disable iff (rst)
(awvalid && !awready) |=> $stable(awvalid);
endproperty
a_awvalid_stable: assert property (p_awvalid_stable)
else $error("AXI4 violation: AWVALID changed before AWREADY");
// AXI4 Rule: BVALID after both AW and W handshakes
property p_bvalid_ordering;
logic aw_done, w_done;
@(posedge clk) disable iff (rst)
(awvalid && awready, aw_done = 1) ##0
(wvalid && wready, w_done = 1) ##0
(aw_done && w_done) |-> ##[1:$] bvalid;
endproperty
a_bvalid_ordering: assert property (p_bvalid_ordering)
else $error("AXI4 violation: BVALID ordering incorrect");
endmodule
python mcp_server/mcp_client.py --workspace . --tool run_uvm_simulation \
--test-name axiuart_basic_test --mode run --waves \
--compile-args "+define+ENABLE_ASSERTIONS"
Investigate assertion failures BEFORE waveform inspection:
a_setup_time: assert property (p_setup_time_met)
else $error("[%0t] Setup time violation: data=0x%h, required_stable=%0d cycles",
$time, data_signal, SETUP_CYCLES);
// Cover all specified behaviors
c_normal_operation: cover property (p_normal_frame_processing);
c_error_recovery: cover property (p_error_frame_recovery);
c_back_to_back: cover property (p_back_to_back_frames);
// Cover corner cases
c_minimum_latency: cover property (
@(posedge clk) disable iff (rst)
request |-> ##1 acknowledge
);
c_maximum_latency: cover property (
@(posedge clk) disable iff (rst)
request |-> ##10 acknowledge
);
`ifdef ENABLE_ASSERTIONS
module My_Module_Assertions (/*...*/);
// Assertions here
endmodule
bind My_Module My_Module_Assertions u_assertions (.*);
`endif
// Error (test fails)
assert property (p_critical) else $error("Critical failure");
// Warning (logged but test continues)
assert property (p_recommended) else $warning("Recommended practice violated");
// Info (just notification)
assert property (p_performance) else $info("Suboptimal performance detected");
// Fatal (simulation stops immediately)
assert property (p_safety_critical) else $fatal(1, "Safety violation - halting");
Follow detailed guidelines in:
sim/assertions/
āāā spec/
ā āāā <module>_timing_spec.sva # Timing specifications
āāā functional/
ā āāā <Module>_Assertions.sv # Functional properties
āāā bind/
āāā bind_<Module>.sv # Bind statements
MCP server can enable/disable assertions dynamically. See mcp-workflow skill for detailed command sequences.
dsim-debugging skillrtl-coding-standards skill for module structureAssertion design principles:
bindp_ prefix for properties, a_ for assertions, c_ for coverage+define+ENABLE_ASSERTIONS at compile time