Skip to content

Commit cb7dbb5

Browse files
committed
[prim_esc_receiver] Register esc_req_o to avoid potential CDC issues
This is related to #24119. Signed-off-by: Pirmin Vogel <[email protected]>
1 parent 966312e commit cb7dbb5

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

hw/ip/prim/dv/prim_esc/tb/prim_esc_tb.sv

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ module prim_esc_tb;
110110
// Drive random length of esc_req and check `esc_req_out` and `integ_fail` outputs.
111111
main_clk.wait_clks($urandom_range(1, 20));
112112
if (integ_fail) test_error("Esc_req unexpected signal integrity error!");
113+
// Wait for the escalation request to pass through the output register.
114+
main_clk.wait_clks(1);
113115
if (!esc_req_out) test_error("Esc_req did not set esc_req!");
114116
esc_req = 0;
115117

@@ -148,6 +150,8 @@ module prim_esc_tb;
148150
`DV_SPINWAIT(wait (integ_fail == 1);, , , "Wait for esc_tx.esc_n integ_fail timeout");
149151
main_clk.wait_clks(1);
150152
release esc_tx.esc_n;
153+
// Wait for the escalation request to pass through the output register.
154+
main_clk.wait_clks(1);
151155
// Wait #1ps to avoid a race condition on clock edge.
152156
#1ps;
153157
if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
@@ -161,6 +165,8 @@ module prim_esc_tb;
161165
`DV_SPINWAIT(wait (integ_fail == 1);, , , "Wait for esc_rx.resp_n integ_fail timeout");
162166
main_clk.wait_clks(1);
163167
release esc_rx.resp_n;
168+
// Wait for the escalation request to pass through the output register.
169+
main_clk.wait_clks(1);
164170
// Wait #1ps to avoid a race condition on clock edge.
165171
#1ps;
166172
if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
@@ -176,8 +182,12 @@ module prim_esc_tb;
176182
release esc_tx.esc_n;
177183
// Wait #1ps to avoid a race condition on clock edge.
178184
#1ps;
179-
if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
180185
if (ping_ok) test_error("Ping error!");
186+
// Wait for the escalation request to pass through the output register.
187+
main_clk.wait_clks(1);
188+
// Wait #1ps to avoid a race condition on clock edge.
189+
#1ps;
190+
if (!esc_req_out) test_error("Signal integrity error should set esc_req!");
181191
ping_req = 0;
182192

183193
$display("[prim_esc_seq] Escalation esc_p/n integrity sequence during ping request finished!");
@@ -191,7 +201,7 @@ module prim_esc_tb;
191201
// After one ping_req, esc_receiver will start a counter to expect next ping_req. If the
192202
// counter reaches its max value but no ping_req has been received, design will set
193203
// `esc_req_out` signal.
194-
main_clk.wait_clks(TIMEOUT_CYCLES + 1);
204+
main_clk.wait_clks(TIMEOUT_CYCLES + 2);
195205
if (!esc_req_out) test_error("Design failed to detect ping request timeout!");
196206
end
197207
begin
@@ -200,6 +210,8 @@ module prim_esc_tb;
200210
main_clk.wait_clks(2);
201211
ping_req = 0;
202212
if (integ_fail) test_error("Ping_req unexpected signal integrity error!");
213+
// Wait for the escalation request to pass through the output register.
214+
main_clk.wait_clks(1);
203215
if (esc_req_out) test_error("Ping request should not set esc_req_out!");
204216
end
205217
join

hw/ip/prim/fpv/vip/prim_esc_rxtx_assert_fpv.sv

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ module prim_esc_rxtx_assert_fpv
103103
!rst_ni ||
104104
error_present)
105105

106-
// check correct transmission of escalation within 0-1 cycles
106+
// check correct transmission of escalation within 1-2 cycles
107107
`ASSERT(EscCheck_A,
108108
##1 esc_req_i
109109
|->
110-
##[0:1] esc_req_o,
110+
##[1:2] esc_req_o,
111111
clk_i,
112112
!rst_ni ||
113113
error_present)
@@ -155,7 +155,7 @@ module prim_esc_rxtx_assert_fpv
155155
!esc_req_o ##1
156156
!ping_req_i [*0 : 2**TimeoutCntDw - 4]
157157
|->
158-
!esc_req_o,
158+
##1 !esc_req_o,
159159
clk_i,
160160
!rst_ni ||
161161
error_d ||
@@ -169,7 +169,7 @@ module prim_esc_rxtx_assert_fpv
169169
!esc_req_o ##1
170170
!ping_req_i [* 2**TimeoutCntDw - 3 : $]
171171
|->
172-
esc_req_o,
172+
##1 esc_req_o,
173173
clk_i,
174174
!rst_ni ||
175175
error_d ||

hw/ip/prim/rtl/prim_esc_receiver.sv

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,21 @@ module prim_esc_receiver
126126
// - requested via the escalation sender/receiver path,
127127
// - the ping monitor timeout is reached,
128128
// - the two ping monitor counters are in an inconsistent state.
129-
logic esc_req;
129+
// Register the escalation request to avoid potential CDC issues downstream.
130+
logic esc_req, esc_req_d, esc_req_q;
131+
assign esc_req_d = esc_req || (&timeout_cnt) || timeout_cnt_error;
132+
always_ff @(posedge clk_i or negedge rst_ni) begin
133+
if (!rst_ni) begin
134+
esc_req_q <= 1'b0;
135+
end else begin
136+
esc_req_q <= esc_req_d;
137+
end
138+
end
139+
130140
prim_sec_anchor_buf #(
131141
.Width(1)
132142
) u_prim_buf_esc_req (
133-
.in_i(esc_req || (&timeout_cnt) || timeout_cnt_error),
143+
.in_i (esc_req_q),
134144
.out_o(esc_req_o)
135145
);
136146

@@ -257,7 +267,7 @@ module prim_esc_receiver
257267
`ASSERT(SigIntCheck0_A, esc_tx_i.esc_p == esc_tx_i.esc_n |=> esc_rx_o.resp_p == esc_rx_o.resp_n)
258268
`ASSERT(SigIntCheck1_A, esc_tx_i.esc_p == esc_tx_i.esc_n |=> state_q == SigInt)
259269
// auto-escalate in case of signal integrity issue
260-
`ASSERT(SigIntCheck2_A, esc_tx_i.esc_p == esc_tx_i.esc_n |=> esc_req_o)
270+
`ASSERT(SigIntCheck2_A, esc_tx_i.esc_p == esc_tx_i.esc_n |=> esc_req_d)
261271
// correct diff encoding
262272
`ASSERT(DiffEncCheck_A, esc_tx_i.esc_p ^ esc_tx_i.esc_n |=> esc_rx_o.resp_p ^ esc_rx_o.resp_n)
263273
// disable in case of signal integrity issue
@@ -271,10 +281,10 @@ module prim_esc_receiver
271281
// detect escalation pulse
272282
`ASSERT(EscEnCheck_A,
273283
esc_tx_i.esc_p && (esc_tx_i.esc_p ^ esc_tx_i.esc_n) && state_q != SigInt
274-
##1 esc_tx_i.esc_p && (esc_tx_i.esc_p ^ esc_tx_i.esc_n) |-> esc_req_o)
284+
##1 esc_tx_i.esc_p && (esc_tx_i.esc_p ^ esc_tx_i.esc_n) |-> esc_req_d)
275285
// make sure the counter does not wrap around
276286
`ASSERT(EscCntWrap_A, &timeout_cnt |=> timeout_cnt != 0)
277287
// if the counter expires, escalation should be asserted
278-
`ASSERT(EscCntEsc_A, &timeout_cnt |-> esc_req_o)
288+
`ASSERT(EscCntEsc_A, &timeout_cnt |-> esc_req_d)
279289

280290
endmodule : prim_esc_receiver

0 commit comments

Comments
 (0)