[alert_handler/prim] Add FPV testbenches for diff rx/tx prims
diff --git a/hw/formal/formal.core b/hw/formal/formal.core
index 979b6b9..15bc5a0 100644
--- a/hw/formal/formal.core
+++ b/hw/formal/formal.core
@@ -11,6 +11,8 @@
files_rtl_generic:
depend:
- lowrisc:fpv:prim_lfsr_fpv
+ - lowrisc:fpv:prim_alert_rxtx_fpv
+ - lowrisc:fpv:prim_esc_rxtx_fpv
- lowrisc:ip:rv_timer
- lowrisc:ip:hmac
- lowrisc:systems:top_earlgrey
diff --git a/hw/ip/prim/fpv/prim_alert_rxtx_fpv.core b/hw/ip/prim/fpv/prim_alert_rxtx_fpv.core
new file mode 100644
index 0000000..81b534a
--- /dev/null
+++ b/hw/ip/prim/fpv/prim_alert_rxtx_fpv.core
@@ -0,0 +1,27 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:fpv:prim_alert_rxtx_fpv:0.1"
+description: "ALERT_HANDLER FPV target"
+filesets:
+ files_fpv:
+ depend:
+ - lowrisc:prim:all
+ files:
+ - vip/prim_alert_rxtx_async_assert.sv
+ - vip/prim_alert_rxtx_assert.sv
+ - tb/prim_alert_rxtx_async_tb.sv
+ - tb/prim_alert_rxtx_tb.sv
+ - tb/prim_alert_rxtx_async_bind.sv
+ - tb/prim_alert_rxtx_bind.sv
+ file_type: systemVerilogSource
+
+targets:
+ default: &default_target
+ toplevel:
+ - prim_alert_rxtx_async_tb
+ - prim_alert_rxtx_tb
+ filesets:
+ - files_fpv
+ default_tool: jg
diff --git a/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core b/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core
new file mode 100644
index 0000000..d65b9d2
--- /dev/null
+++ b/hw/ip/prim/fpv/prim_esc_rxtx_fpv.core
@@ -0,0 +1,23 @@
+CAPI=2:
+# Copyright lowRISC contributors.
+# Licensed under the Apache License, Version 2.0, see LICENSE for details.
+# SPDX-License-Identifier: Apache-2.0
+name: "lowrisc:fpv:prim_esc_rxtx_fpv:0.1"
+description: "ALERT_HANDLER FPV target"
+filesets:
+ files_fpv:
+ depend:
+ - lowrisc:prim:all
+ files:
+ - vip/prim_esc_rxtx_assert.sv
+ - tb/prim_esc_rxtx_bind.sv
+ - tb/prim_esc_rxtx_tb.sv
+ file_type: systemVerilogSource
+
+targets:
+ default: &default_target
+ toplevel:
+ - prim_esc_rxtx_tb
+ filesets:
+ - files_fpv
+ default_tool: jg
diff --git a/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_bind.sv b/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_bind.sv
new file mode 100644
index 0000000..9b6f65b
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_bind.sv
@@ -0,0 +1,27 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+module prim_alert_rxtx_async_bind;
+
+ bind prim_alert_rxtx_async_tb prim_alert_rxtx_async_assert prim_alert_rxtx_async_assert (
+ .clk_i,
+ .rst_ni,
+ .ping_err_pi,
+ .ping_err_ni,
+ .ping_skew_i,
+ .ack_err_pi,
+ .ack_err_ni,
+ .ack_skew_i,
+ .alert_err_pi,
+ .alert_err_ni,
+ .alert_skew_i,
+ .alert_i,
+ .ping_en_i,
+ .ping_ok_o,
+ .integ_fail_o,
+ .alert_o
+ );
+
+endmodule : prim_alert_rxtx_async_bind
diff --git a/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_tb.sv b/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_tb.sv
new file mode 100644
index 0000000..c8439d3
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_alert_rxtx_async_tb.sv
@@ -0,0 +1,97 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Testbench module for alert sender/receiver pair. Intended to use with
+// a formal tool.
+
+module prim_alert_rxtx_async_tb (
+ input clk_i,
+ input rst_ni,
+ // for sigint error and skew injection only
+ input ping_err_pi,
+ input ping_err_ni,
+ input [1:0] ping_skew_i,
+ input ack_err_pi,
+ input ack_err_ni,
+ input [1:0] ack_skew_i,
+ input alert_err_pi,
+ input alert_err_ni,
+ input [1:0] alert_skew_i,
+ // normal I/Os
+ input alert_i,
+ input ping_en_i,
+ output logic ping_ok_o,
+ output logic integ_fail_o,
+ output logic alert_o
+);
+
+ // asynchronous case
+ localparam bit AsyncOn = 1'b1;
+
+ logic ping_pd;
+ logic ping_nd;
+ logic ack_pd;
+ logic ack_nd;
+ logic alert_pd;
+ logic alert_nd;
+ logic [1:0] ping_pq;
+ logic [1:0] ping_nq;
+ logic [1:0] ack_pq;
+ logic [1:0] ack_nq;
+ logic [1:0] alert_pq;
+ logic [1:0] alert_nq;
+
+ // for the purposes of FPV, we currently emulate the asynchronous transition
+ // only in terms of the skew it may introduce (which is limited to +- 1 cycle)
+
+ prim_alert_sender #(
+ .AsyncOn ( AsyncOn )
+ ) i_prim_alert_sender (
+ .clk_i ,
+ .rst_ni ,
+ .alert_i ,
+ .ping_pi ( ping_pq[ping_skew_i[0]] ^ ping_err_pi ),
+ .ping_ni ( ping_nq[ping_skew_i[1]] ^ ping_err_ni ),
+ .ack_pi ( ack_pq[ack_skew_i[0]] ^ ack_err_pi ),
+ .ack_ni ( ack_nq[ack_skew_i[1]] ^ ack_err_ni ),
+ .alert_po ( alert_pd ),
+ .alert_no ( alert_nd )
+ );
+
+ prim_alert_receiver #(
+ .AsyncOn ( AsyncOn )
+ ) i_prim_alert_receiver (
+ .clk_i ,
+ .rst_ni ,
+ .ping_en_i ,
+ .ping_ok_o ,
+ .integ_fail_o ,
+ .alert_o ,
+ .ping_po ( ping_pd ),
+ .ping_no ( ping_nd ),
+ .ack_po ( ack_pd ),
+ .ack_no ( ack_nd ),
+ .alert_pi ( alert_pq[alert_skew_i[0]] ^ alert_err_pi ),
+ .alert_ni ( alert_nq[alert_skew_i[1]] ^ alert_err_ni )
+ );
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin : p_skew_delay
+ if (!rst_ni) begin
+ ping_pq <= '0;
+ ping_nq <= '1;
+ ack_pq <= '0;
+ ack_nq <= '1;
+ alert_pq <= '0;
+ alert_nq <= '1;
+ end else begin
+ ping_pq <= {ping_pq [$high(ping_pq )-1:0], ping_pd};
+ ping_nq <= {ping_nq [$high(ping_nq )-1:0], ping_nd};
+ ack_pq <= {ack_pq [$high(ack_pq )-1:0], ack_pd};
+ ack_nq <= {ack_nq [$high(ack_nq )-1:0], ack_nd};
+ alert_pq <= {alert_pq[$high(alert_pq)-1:0], alert_pd};
+ alert_nq <= {alert_nq[$high(alert_nq)-1:0], alert_nd};
+ end
+ end
+
+endmodule : prim_alert_rxtx_async_tb
diff --git a/hw/ip/prim/fpv/tb/prim_alert_rxtx_bind.sv b/hw/ip/prim/fpv/tb/prim_alert_rxtx_bind.sv
new file mode 100644
index 0000000..3081b6e
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_alert_rxtx_bind.sv
@@ -0,0 +1,24 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+module prim_alert_rxtx_bind;
+
+ bind prim_alert_rxtx_tb prim_alert_rxtx_assert prim_alert_rxtx_assert (
+ .clk_i,
+ .rst_ni,
+ .ping_err_pi,
+ .ping_err_ni,
+ .ack_err_pi,
+ .ack_err_ni,
+ .alert_err_pi,
+ .alert_err_ni,
+ .alert_i,
+ .ping_en_i,
+ .ping_ok_o,
+ .integ_fail_o,
+ .alert_o
+ );
+
+endmodule : prim_alert_rxtx_bind
diff --git a/hw/ip/prim/fpv/tb/prim_alert_rxtx_tb.sv b/hw/ip/prim/fpv/tb/prim_alert_rxtx_tb.sv
new file mode 100644
index 0000000..25fd560
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_alert_rxtx_tb.sv
@@ -0,0 +1,67 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Testbench module for alert sender/receiver pair. Intended to use with
+// a formal tool.
+
+module prim_alert_rxtx_tb (
+ input clk_i,
+ input rst_ni,
+ // for sigint error injection only
+ input ping_err_pi,
+ input ping_err_ni,
+ input ack_err_pi,
+ input ack_err_ni,
+ input alert_err_pi,
+ input alert_err_ni,
+ // normal I/Os
+ input alert_i,
+ input ping_en_i,
+ output logic ping_ok_o,
+ output logic integ_fail_o,
+ output logic alert_o
+);
+
+ // synchronous case
+ localparam bit AsyncOn = 1'b0;
+
+ logic ping_p;
+ logic ping_n;
+ logic ack_p;
+ logic ack_n;
+ logic alert_p;
+ logic alert_n;
+
+ prim_alert_sender #(
+ .AsyncOn ( AsyncOn )
+ ) i_prim_alert_sender (
+ .clk_i ,
+ .rst_ni ,
+ .alert_i ,
+ .ping_pi ( ping_p ^ ping_err_pi ),
+ .ping_ni ( ping_n ^ ping_err_ni ),
+ .ack_pi ( ack_p ^ ack_err_pi ),
+ .ack_ni ( ack_n ^ ack_err_ni ),
+ .alert_po ( alert_p ),
+ .alert_no ( alert_n )
+ );
+
+ prim_alert_receiver #(
+ .AsyncOn ( AsyncOn )
+ ) i_prim_alert_receiver (
+ .clk_i ,
+ .rst_ni ,
+ .ping_en_i ,
+ .ping_ok_o ,
+ .integ_fail_o ,
+ .alert_o ,
+ .ping_po ( ping_p ),
+ .ping_no ( ping_n ),
+ .ack_po ( ack_p ),
+ .ack_no ( ack_n ),
+ .alert_pi ( alert_p ^ alert_err_pi ),
+ .alert_ni ( alert_n ^ alert_err_ni )
+ );
+
+endmodule : prim_alert_rxtx_tb
diff --git a/hw/ip/prim/fpv/tb/prim_esc_rxtx_bind.sv b/hw/ip/prim/fpv/tb/prim_esc_rxtx_bind.sv
new file mode 100644
index 0000000..698e17d
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_esc_rxtx_bind.sv
@@ -0,0 +1,22 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+
+module prim_esc_rxtx_bind;
+
+ bind prim_esc_rxtx_tb prim_esc_rxtx_assert prim_esc_rxtx_assert (
+ .clk_i ,
+ .rst_ni ,
+ .resp_err_pi ,
+ .resp_err_ni ,
+ .esc_err_pi ,
+ .esc_err_ni ,
+ .esc_en_i ,
+ .ping_en_i ,
+ .ping_ok_o ,
+ .integ_fail_o,
+ .esc_en_o
+ );
+
+endmodule : prim_esc_rxtx_bind
diff --git a/hw/ip/prim/fpv/tb/prim_esc_rxtx_tb.sv b/hw/ip/prim/fpv/tb/prim_esc_rxtx_tb.sv
new file mode 100644
index 0000000..86ce372
--- /dev/null
+++ b/hw/ip/prim/fpv/tb/prim_esc_rxtx_tb.sv
@@ -0,0 +1,52 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Testbench module for escalation sender/receiver pair. Intended to use with
+// a formal tool.
+
+module prim_esc_rxtx_tb (
+ input clk_i,
+ input rst_ni,
+ // for sigint error injection only
+ input resp_err_pi,
+ input resp_err_ni,
+ input esc_err_pi,
+ input esc_err_ni,
+ // normal I/Os
+ input esc_en_i,
+ input ping_en_i,
+ output logic ping_ok_o,
+ output logic integ_fail_o,
+ output logic esc_en_o
+);
+
+ logic resp_p;
+ logic resp_n;
+ logic esc_p;
+ logic esc_n;
+
+ prim_esc_sender i_prim_esc_sender (
+ .clk_i ,
+ .rst_ni ,
+ .ping_en_i ,
+ .ping_ok_o ,
+ .integ_fail_o ,
+ .esc_en_i ,
+ .resp_pi ( resp_p ^ resp_err_pi ),
+ .resp_ni ( resp_n ^ resp_err_ni ),
+ .esc_po ( esc_p ),
+ .esc_no ( esc_n )
+ );
+
+ prim_esc_receiver i_prim_esc_receiver (
+ .clk_i ,
+ .rst_ni ,
+ .esc_en_o ,
+ .resp_po ( resp_p ),
+ .resp_no ( resp_n ),
+ .esc_pi ( esc_p ^ esc_err_pi ),
+ .esc_ni ( esc_n ^ esc_err_ni )
+ );
+
+endmodule : prim_esc_rxtx_tb
diff --git a/hw/ip/prim/fpv/vip/prim_alert_rxtx_assert.sv b/hw/ip/prim/fpv/vip/prim_alert_rxtx_assert.sv
new file mode 100644
index 0000000..abf3b20
--- /dev/null
+++ b/hw/ip/prim/fpv/vip/prim_alert_rxtx_assert.sv
@@ -0,0 +1,87 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Assertions for alert sender/receiver pair. Intended to use with
+// a formal tool.
+
+module prim_alert_rxtx_assert (
+ input clk_i,
+ input rst_ni,
+ // for sigint error injection only
+ input ping_err_pi,
+ input ping_err_ni,
+ input ack_err_pi,
+ input ack_err_ni,
+ input alert_err_pi,
+ input alert_err_ni,
+ // normal I/Os
+ input alert_i,
+ input ping_en_i,
+ input ping_ok_o,
+ input integ_fail_o,
+ input alert_o
+);
+
+ logic error_present;
+ assign error_present = ping_err_pi | ping_err_ni |
+ ack_err_pi | ack_err_ni |
+ alert_err_pi | alert_err_ni;
+
+ // note: we can only detect sigint errors where one wire is flipped.
+ `ASSUME_FPV(PingErrorsAreOH_M, $onehot0({ping_err_pi, ping_err_ni}), clk_i, !rst_ni)
+ `ASSUME_FPV(AckErrorsAreOH_M, $onehot0({ack_err_pi, ack_err_ni}), clk_i, !rst_ni)
+ `ASSUME_FPV(AlertErrorsAreOH_M, $onehot0({alert_err_pi, alert_err_ni}), clk_i, !rst_ni)
+
+ // ping will stay high until ping ok received, then it must be deasserted
+ // TODO: this excludes the case where no ping ok will be returned due to an error
+ `ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> !ping_en_i, clk_i, !rst_ni)
+ `ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=> (ping_en_i && !ping_ok_o) or
+ (ping_en_i && ping_ok_o ##1 $fell(ping_en_i)), clk_i, !rst_ni || error_present)
+
+ sequence FullHandshake_S;
+ $rose(prim_alert_rxtx_tb.alert_p) ##1
+ $rose(prim_alert_rxtx_tb.ack_p) && $stable(prim_alert_rxtx_tb.alert_p) ##1
+ $fell(prim_alert_rxtx_tb.alert_p) && $stable(prim_alert_rxtx_tb.ack_p) ##1
+ $fell(prim_alert_rxtx_tb.ack_p) && $stable(prim_alert_rxtx_tb.alert_p) ;
+ endsequence
+
+ // note: injected errors may lockup the FSMs, and hence the full HS can
+ // only take place if both FSMs are in a sane state
+ `ASSERT(PingHs_A, ##1 $changed(prim_alert_rxtx_tb.ping_p) &&
+ (prim_alert_rxtx_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_sender.Idle ) &&
+ (prim_alert_rxtx_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_receiver.Idle )|=> FullHandshake_S,
+ clk_i, !rst_ni || error_present)
+ `ASSERT(AlertHs_A, alert_i &&
+ (prim_alert_rxtx_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_sender.Idle) &&
+ (prim_alert_rxtx_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_receiver.Idle) |=>
+ FullHandshake_S, clk_i, !rst_ni || error_present)
+
+ // transmission of pings
+ `ASSERT(AlertPing_A, !error_present ##1 $rose(ping_en_i) |->
+ ##[1:9] ping_ok_o, clk_i, !rst_ni || error_present)
+ // transmission of alerts in case of no collision with ping enable
+ `ASSERT(AlertCheck0_A, !ping_en_i [*3] ##0 $rose(alert_i) &&
+ (prim_alert_rxtx_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_sender.Idle) |=>
+ alert_o, clk_i, !rst_ni || error_present || ping_en_i)
+ // transmission of alerts in the general case which can include ping collisions
+ `ASSERT(AlertCheck1_A, alert_i |-> ##[1:9] alert_o, clk_i, !rst_ni || error_present)
+
+ // basic liveness of FSMs in case no errors are present
+ `ASSERT(FsmLivenessSender_A,
+ (prim_alert_rxtx_tb.i_prim_alert_sender.state_q !=
+ prim_alert_rxtx_tb.i_prim_alert_sender.Idle) |->
+ strong(##[1:$] (prim_alert_rxtx_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_sender.Idle)), clk_i, !rst_ni || error_present)
+ `ASSERT(FsmLivenessReceiver_A,
+ (prim_alert_rxtx_tb.i_prim_alert_receiver.state_q !=
+ prim_alert_rxtx_tb.i_prim_alert_receiver.Idle) |->
+ strong(##[1:$] (prim_alert_rxtx_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_tb.i_prim_alert_receiver.Idle)),clk_i, !rst_ni || error_present)
+
+endmodule : prim_alert_rxtx_assert
diff --git a/hw/ip/prim/fpv/vip/prim_alert_rxtx_async_assert.sv b/hw/ip/prim/fpv/vip/prim_alert_rxtx_async_assert.sv
new file mode 100644
index 0000000..7e8532b
--- /dev/null
+++ b/hw/ip/prim/fpv/vip/prim_alert_rxtx_async_assert.sv
@@ -0,0 +1,119 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Assertions for alert sender/receiver pair for the asynchronous case.
+// Intended to use with a formal tool.
+
+module prim_alert_rxtx_async_assert (
+ input clk_i,
+ input rst_ni,
+ // for sigint error and skew injection only
+ input ping_err_pi,
+ input ping_err_ni,
+ input [1:0] ping_skew_i,
+ input ack_err_pi,
+ input ack_err_ni,
+ input [1:0] ack_skew_i,
+ input alert_err_pi,
+ input alert_err_ni,
+ input [1:0] alert_skew_i,
+ // normal I/Os
+ input alert_i,
+ input ping_en_i,
+ input ping_ok_o,
+ input integ_fail_o,
+ input alert_o
+);
+
+ logic error_present;
+ assign error_present = ping_err_pi | ping_err_ni |
+ ack_err_pi | ack_err_ni |
+ alert_err_pi | alert_err_ni;
+
+ // used to check that an error has never occured so far
+ // this is used to check the handshake below. the handshake can lock up
+ // the protocol FSMs causing the handshake to never complete.
+ // note that this will block any ping messages and hence it can be
+ // eventually detected by the alert handler.
+ logic error_setreg_d, error_setreg_q;
+ assign error_setreg_d = error_present | error_setreg_q;
+
+ always_ff @(posedge clk_i or negedge rst_ni) begin : p_reg
+ if (!rst_ni) begin
+ error_setreg_q <= 1'b0;
+ end else begin
+ error_setreg_q <= error_setreg_d;
+ end
+ end
+
+ // Note: we can only detect sigint errors where one wire is flipped.
+ `ASSUME_FPV(PingErrorsAreOH_M, $onehot0({ping_err_pi, ping_err_ni}), clk_i, !rst_ni)
+ `ASSUME_FPV(AckErrorsAreOH_M, $onehot0({ack_err_pi, ack_err_ni}), clk_i, !rst_ni)
+ `ASSUME_FPV(AlertErrorsAreOH_M, $onehot0({alert_err_pi, alert_err_ni}), clk_i, !rst_ni)
+
+ // ping will stay high until ping ok received, then it must be deasserted
+ // TODO: this excludes the case where no ping ok will be returned due to an error
+ `ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> !ping_en_i, clk_i, !rst_ni)
+ `ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=>
+ (ping_en_i && !ping_ok_o) or
+ (ping_en_i && ping_ok_o ##1 $fell(ping_en_i)),
+ clk_i, !rst_ni || error_present)
+
+ // Note: the sequence lengths of the handshake and the following properties needs to
+ // be parameterized accordingly if different clock ratios are to be used here.
+ // TODO: tighten bounds if possible
+ sequence FullHandshake_S;
+ $rose(prim_alert_rxtx_async_tb.alert_pd) ##[3:5]
+ $rose(prim_alert_rxtx_async_tb.ack_pd) &&
+ $stable(prim_alert_rxtx_async_tb.alert_pd) ##[3:5]
+ $fell(prim_alert_rxtx_async_tb.alert_pd) &&
+ $stable(prim_alert_rxtx_async_tb.ack_pd) ##[3:5]
+ $fell(prim_alert_rxtx_async_tb.ack_pd) &&
+ $stable(prim_alert_rxtx_async_tb.alert_pd);
+ endsequence
+
+ // note: injected errors may lockup the FSMs, and hence the full HS can
+ // only take place if both FSMs are in a sane state
+ `ASSERT(PingHs_A, ##1 $changed(prim_alert_rxtx_async_tb.ping_pd) &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_sender.Idle) &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_receiver.Idle) |-> ##[0:5] FullHandshake_S,
+ clk_i, !rst_ni || error_setreg_q)
+ `ASSERT(AlertHs_A, alert_i &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_sender.Idle) &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_receiver.Idle) |-> ##[0:5] FullHandshake_S,
+ clk_i, !rst_ni || error_setreg_q)
+
+ // transmission of pings
+ // this bound is relatively large as in the worst case, we need to resolve
+ // staggered differential signal patterns on all three differential channels
+ `ASSERT(AlertPing_A, $rose(ping_en_i) |-> ##[1:23] ping_ok_o,
+ clk_i, !rst_ni || error_setreg_q)
+ // transmission of first alert assertion (no ping collision)
+ `ASSERT(AlertCheck0_A, !ping_en_i [*10] ##1 $rose(alert_i) &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_sender.Idle) |->
+ ##[3:5] alert_o, clk_i, !rst_ni || ping_en_i || error_setreg_q)
+ // eventual transmission of alerts in the general case which can include ping collisions
+ `ASSERT(AlertCheck1_A, alert_i |-> ##[1:25] alert_o,
+ clk_i, !rst_ni || error_setreg_q)
+
+ // basic liveness of FSMs in case no errors are present
+ `ASSERT(FsmLivenessSender_A, !error_present [*2] ##1 !error_present &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_sender.state_q !=
+ prim_alert_rxtx_async_tb.i_prim_alert_sender.Idle) |->
+ strong(##[1:$] (prim_alert_rxtx_async_tb.i_prim_alert_sender.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_sender.Idle)), clk_i, !rst_ni || error_present)
+ `ASSERT(FsmLivenessReceiver_A, !error_present [*2] ##1 !error_present &&
+ (prim_alert_rxtx_async_tb.i_prim_alert_receiver.state_q !=
+ prim_alert_rxtx_async_tb.i_prim_alert_receiver.Idle) |->
+ strong(##[1:$] (prim_alert_rxtx_async_tb.i_prim_alert_receiver.state_q ==
+ prim_alert_rxtx_async_tb.i_prim_alert_receiver.Idle)),clk_i, !rst_ni || error_present)
+
+ // TODO: add FSM liveness of 3x diff decoder instances
+
+endmodule : prim_alert_rxtx_async_assert
diff --git a/hw/ip/prim/fpv/vip/prim_esc_rxtx_assert.sv b/hw/ip/prim/fpv/vip/prim_esc_rxtx_assert.sv
new file mode 100644
index 0000000..9e2dc01
--- /dev/null
+++ b/hw/ip/prim/fpv/vip/prim_esc_rxtx_assert.sv
@@ -0,0 +1,68 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// Assertions for escalation sender/receiver pair. Intended to use with
+// a formal tool.
+
+module prim_esc_rxtx_assert (
+ input clk_i,
+ input rst_ni,
+ // for sigint error injection only
+ input resp_err_pi,
+ input resp_err_ni,
+ input esc_err_pi,
+ input esc_err_ni,
+ // normal I/Os
+ input esc_en_i,
+ input ping_en_i,
+ input ping_ok_o,
+ input integ_fail_o,
+ input esc_en_o
+);
+
+ logic error_present;
+ assign error_present = resp_err_pi | resp_err_ni |
+ esc_err_pi | esc_err_ni;
+
+ // ping will stay high until ping ok received, then it must be deasserted
+ // TODO: this escludes the case where no ping ok will be returned due to an error
+ `ASSUME_FPV(PingDeassert_M, ping_en_i && ping_ok_o |=> ping_en_i, clk_i, !rst_ni)
+ `ASSUME_FPV(PingEnStaysAsserted0_M, ping_en_i |=>
+ (ping_en_i && !ping_ok_o) or (ping_en_i && ping_ok_o ##1 $fell(ping_en_i)),
+ clk_i, !rst_ni || error_present)
+
+ // assume that the ping enable and escalation enable signals will eventually be deasserted (and
+ // esc will stay low for more than 2 cycles)
+ `ASSUME_FPV(FiniteEsc_M, esc_en_i |-> strong(##[1:$] !esc_en_i [*2]), clk_i, !rst_ni)
+ `ASSUME_FPV(FinitePing_M, ping_en_i |-> strong(##[1:$] !ping_en_i), clk_i, !rst_ni)
+
+ // ping response mus occur within 4 cycles (given that no
+ // error occured within the previous cycles)
+ `ASSERT(PingRespCheck_A, !error_present [*4] ##1 $rose(ping_en_i) |->
+ ##[0:4] ping_ok_o, clk_i, !rst_ni || error_present)
+
+ // be more specific (i.e. use throughout)
+ `ASSERT(EscRespCheck_A, ##1 esc_en_i |-> ##[0:1] prim_esc_rxtx_tb.resp_p ##1
+ !prim_esc_rxtx_tb.resp_p, clk_i, !rst_ni || error_present)
+
+ // check correct transmission of escalation within 0-1 cycles
+ `ASSERT(EscCheck_A, ##1 esc_en_i |-> ##[0:1] esc_en_o, clk_i, !rst_ni || error_present)
+
+ // check that a single error on the diffpairs is detected
+ `ASSERT(SingleSigIntDetected0_A, {esc_err_pi, esc_err_ni} == '0 ##1
+ $onehot({resp_err_pi, resp_err_ni}) |-> integ_fail_o, clk_i, !rst_ni)
+ `ASSERT(SingleSigIntDetected1_A, $onehot({esc_err_pi, esc_err_ni}) ##1
+ {resp_err_pi, resp_err_ni} == '0 |-> integ_fail_o, clk_i, !rst_ni)
+
+ // basic liveness of FSMs in case no errors are present
+ `ASSERT(FsmLivenessSender_A, (prim_esc_rxtx_tb.i_prim_esc_sender.state_q !=
+ prim_esc_rxtx_tb.i_prim_esc_sender.Idle) |->
+ strong(##[1:$] (prim_esc_rxtx_tb.i_prim_esc_sender.state_q
+ == prim_esc_rxtx_tb.i_prim_esc_sender.Idle)), clk_i, !rst_ni || error_present)
+ `ASSERT(FsmLivenessReceiver_A, (prim_esc_rxtx_tb.i_prim_esc_receiver.state_q !=
+ prim_esc_rxtx_tb.i_prim_esc_receiver.Idle) |->
+ strong(##[1:$] (prim_esc_rxtx_tb.i_prim_esc_receiver.state_q
+ == prim_esc_rxtx_tb.i_prim_esc_receiver.Idle)), clk_i, !rst_ni || error_present)
+
+endmodule : prim_esc_rxtx_assert