[dv/prim_esc] Improve FSM coverage
This PR adds a sequence: ping_req interrupted by esc_req to improve FSM
coverage.
It also adds a small delay to create different timings to inject signal
integrity error.
Signed-off-by: Cindy Chen <chencindy@opentitan.org>
diff --git a/hw/ip/prim/dv/prim_esc/data/prim_esc_testplan.hjson b/hw/ip/prim/dv/prim_esc/data/prim_esc_testplan.hjson
index 470140f..9e5cbaa 100644
--- a/hw/ip/prim/dv/prim_esc/data/prim_esc_testplan.hjson
+++ b/hw/ip/prim/dv/prim_esc/data/prim_esc_testplan.hjson
@@ -17,6 +17,20 @@
}
{
+ name: prim_ping_req_interrupted_by_esc_req_test
+ desc: '''Verify prim_esc will process the esc_req when ping handshake is in progress.
+
+ - Send a ping request by driving `ping_req` pin to 1.
+ - Randomly wait a few cycles before the ping handshake is completed.
+ - Send an escalation request by driving `esc_req` pin to 1.
+ - Wait for `ping_ok` to set and `esc_req_out` to set.
+ - Check the sequence completes without any signal integrity error.
+ '''
+ milestone: V1
+ tests: ["prim_esc_test"]
+ }
+
+ {
name: prim_esc_tx_integrity_errors_test
desc: '''Verify `esc_tx` signal integrity error.
@@ -24,6 +38,7 @@
- Force `esc_n` signal to stay high to trigger an integrity error.
- Verify that prim_esc_sender identifies the error by setting `integ_fail` signal.
- Release the `esc_n` signal.
+ - Send a ping request and repeat the above sequence and checkings.
'''
milestone: V1
tests: ["prim_esc_test"]
diff --git a/hw/ip/prim/dv/prim_esc/tb/prim_esc_tb.sv b/hw/ip/prim/dv/prim_esc/tb/prim_esc_tb.sv
index fb35c23..143d2da 100644
--- a/hw/ip/prim/dv/prim_esc/tb/prim_esc_tb.sv
+++ b/hw/ip/prim/dv/prim_esc/tb/prim_esc_tb.sv
@@ -7,9 +7,10 @@
// This test has five sequnces:
// 1). Random reset during escalation handshake sequence.
// 2). Escalation request sequence.
-// 3). `Esc_tx` integrity error sequence.
-// 4). Escalation reverse ping timeout sequence.
-// 5). Escalation receiver counter fail sequence.
+// 3). Ping request interrupted by escalation request sequence.
+// 4). `Esc_tx` integrity error sequence.
+// 5). Escalation reverse ping timeout sequence.
+// 6). Escalation receiver counter fail sequence.
module prim_esc_tb;
@@ -98,27 +99,59 @@
esc_req = 1;
// Drive random length of esc_req and check `esc_req_out` and `integ_fail` outputs.
main_clk.wait_clks($urandom_range(1, 20));
- if (integ_fail == 1) test_error("Esc_req unexpected signal integrity error!");
- if (esc_req_out == 0) test_error("Esc_req did not set esc_req!");
+ if (integ_fail) test_error("Esc_req unexpected signal integrity error!");
+ if (!esc_req_out) test_error("Esc_req did not set esc_req!");
esc_req = 0;
$display("Escalation request sequence finished!");
- // Sequence 3. `Esc_tx` integrity error sequence.
+ // Sequence 3. Ping request interrupted by escalation request.
+ main_clk.wait_clks($urandom_range(1, 20));
+ ping_req = 1;
+ // Wait a max of 5 clock cycle to ensure esc_req is send during ping handshake.
+ main_clk.wait_clks($urandom_range(0, 5));
+ esc_req = 1;
+ wait (ping_ok);
+ wait (esc_req_out);
+ main_clk.wait_clks($urandom_range(1, 20));
+ esc_req = 0;
+ ping_req = 0;
+ if (integ_fail) test_error("Expect no errors when esc_req interrupts ping_req");
+
+ $display("Ping request interrupted by escalation request sequence finished!");
+
+ // Sequence 4.1 `Esc_tx` integrity error sequence during escalation request.
main_clk.wait_clks($urandom_range(1, 20));
esc_req = 1;
+ // Randomly wait a few clock cycles then inject integrity error.
+ main_clk.wait_clks($urandom_range(0, 5));
// Force esc_tx signal to create a integrity fail error case.
force esc_tx.esc_n = 1;
- wait (integ_fail == 1);
+ wait (integ_fail);
release esc_tx.esc_n;
// Wait #1ps to avoid a race condition on clock edge.
#1ps;
- if (esc_req_out == 0) test_error("Signal integrity error should set esc_req!");
+ if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
esc_req = 0;
- $display("Escalation esc_p/n integrity sequence finished!");
+ $display("Escalation esc_p/n integrity sequence during escalation request finished!");
- // Sequence 4. Escalation reverse ping timeout sequence.
+ // Sequence 4.1 `Esc_tx` integrity error sequence during ping request.
+ main_clk.wait_clks($urandom_range(1, 20));
+ ping_req = 1;
+ // Force esc_tx signal to create a integrity fail error case.
+ force esc_tx.esc_n = 1;
+ wait (integ_fail);
+ release esc_tx.esc_n;
+ // Wait #1ps to avoid a race condition on clock edge.
+ #1ps;
+ if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
+ if (ping_ok) test_error("Ping error!");
+ ping_req = 0;
+
+ $display("Escalation esc_p/n integrity sequence during ping request finished!");
+
+ // Sequence 5. Escalation reverse ping timeout sequence.
// Wait at least two clock cycles for the previous sequence to finish its escalation request.
main_clk.wait_clks($urandom_range(2, 20));
ping_req = 1;
@@ -128,33 +161,32 @@
// counter reaches its max value but no ping_req has been received, design will set
// `esc_req_out` signal.
main_clk.wait_clks(TIMEOUT_CYCLES + 1);
- if (esc_req_out != 1) test_error("Design failed to detect ping request timeout!");
+ if (!esc_req_out) test_error("Design failed to detect ping request timeout!");
end
begin
// Wait for a ping handshake to complete.
- wait (ping_ok == 1);
+ wait (ping_ok);
main_clk.wait_clks(2);
ping_req = 0;
- if (integ_fail == 1) test_error("Ping_req unexpected signal integrity error!");
- if (esc_req_out == 1) test_error("Ping request should not set esc_req_out!");
+ if (integ_fail) test_error("Ping_req unexpected signal integrity error!");
+ if (esc_req_out) test_error("Ping request should not set esc_req_out!");
end
join
main_clk.apply_reset();
$display("Escalation ping request timeout sequence finished!");
- // Sequence 5. Escalation receiver counter fail sequence.
+ // Sequence 6. Escalation receiver counter fail sequence.
ping_req = 1;
// Wait until ping request is acknowledged and counter starts to increment.
- wait (ping_ok == 1);
+ wait (ping_ok);
main_clk.wait_clks(2);
ping_req = 0;
// If cnt_q[0] and cnt_q[1]'s value do not match, deisgn will set `esc_req_out` signal.
force prim_esc_tb.i_esc_receiver.cnt_q[1] = 0;
- wait (esc_req_out == 1);
- if (integ_fail == 1) begin
- test_error("Escalation receiver counter unexpected signal integrity error!");
- end
+ wait (esc_req_out);
+ if (integ_fail) test_error("Escalation receiver counter unexpected signal integrity error!");
+ release prim_esc_tb.i_esc_receiver.cnt_q[1];
$display("Escalation couter error sequence finished!");