In this lesson, you will learn how to write advanced SystemVerilog assertions to enforce strict timing dependencies and handshake protocols between a processor and its external peripherals.
When a processor communicates with a peripheral (like a DMA controller or a high-speed SPI bridge), the interface relies on specific request-acknowledge handshakes. If the peripheral fails to respond within a required window, or if the bus signals transition in an invalid order, the system can enter an undefined state. We use SystemVerilog Assertions (SVA) to capture these complex timing dependencies as formal, checkable contracts.
Capturing Handshake Protocols
To verify a protocol where a proc_req must be followed by a periph_ack within 1 to 5 clock cycles, we define an assertion sequence. We use the |-> (implication) operator to ensure that whenever the request occurs, the response must follow according to our constraints:
property p_handshake_timing;
@(posedge clk) disable iff (!reset_n)
proc_req |-> ##[1:5] periph_ack;
endproperty
assert_handshake: assert property (p_handshake_timing)
else $error("Protocol Violation: Peripheral failed to acknowledge request within 5 cycles.");
Modeling Complex Dependencies
Often, a handshake isn't just a two-signal event. You might have a requirement where a data-ready signal must remain stable until the processor asserts a read-enable signal. We can model this by combining sequences:
sequence s_read_cycle;
(proc_rd_en && !data_valid) ##1 (proc_rd_en && data_valid);
endsequence
property p_stable_data;
@(posedge clk)
s_read_cycle |-> ($stable(data_bus));
endproperty
In this case, the sequence s_read_cycle waits for the transition of the data_valid flag. Once that condition is met, the property p_stable_data ensures that the data_bus does not toggle, preventing potential sampling errors or meta-stability during the read window.
By embedding these assertions directly into your RTL or verification environment, you move beyond simple simulation traces. These assertions act as live monitors, catching subtle timing violations the moment they deviate from the hardware-software interface contract, allowing you to isolate the root cause of a failure before it propagates into a system-wide crash.
Key Takeaway: Use SVA implication operators and sequence timing windows to codify your interface protocols, turning abstract timing requirements into automated, real-time hardware integrity checks.