From bf48bb80132cb7daa1f70a0ff93ffb688ca3dc70 Mon Sep 17 00:00:00 2001
From: Maurus Item <itemm@student.ethz.ch>
Date: Wed, 3 Jul 2024 11:45:20 +0200
Subject: [PATCH] Added different types of HCI copies.

---
 rtl/common/hci_package.sv     |  7 +++
 rtl/parity/hci_copy_sink.sv   | 68 +++++++++++++++++++-------
 rtl/parity/hci_copy_source.sv | 89 ++++++++++++++++++++++++-----------
 3 files changed, 121 insertions(+), 43 deletions(-)

diff --git a/rtl/common/hci_package.sv b/rtl/common/hci_package.sv
index 35e87d9..8ab9da3 100644
--- a/rtl/common/hci_package.sv
+++ b/rtl/common/hci_package.sv
@@ -64,4 +64,11 @@ package hci_package;
     STREAMER_IDLE, STREAMER_WORKING, STREAMER_DONE
   } hci_streamer_state_t;
 
+  typedef enum {
+    COPY,        // Full copy and comparison of all signals
+    NO_ECC,      // Do not assign and compare ecc signals
+    NO_DATA,     // Do not assign and compare data signals
+    CTRL_ONLY,   // Do not assign either ecc nor data signals
+  } hci_copy_t;
+
 endpackage // hci_package
diff --git a/rtl/parity/hci_copy_sink.sv b/rtl/parity/hci_copy_sink.sv
index 6a7de19..29378b8 100644
--- a/rtl/parity/hci_copy_sink.sv
+++ b/rtl/parity/hci_copy_sink.sv
@@ -18,50 +18,86 @@
  * stream `tcdm_main` and compare it with a copy  stream `tcdm_copy` element.
  * Together with hci_copy_sink this allows for fault detection on a chain of
  * HCI modules.
+ *
+ * How "deep" the copy is can be set with the parameter COPY_TYPE.
+ * COPY_TYPE MUST match on connected sinks and sources!
+ *
+ * The available options are:
+ * - COPY:      Fully copy of everything.
+ * - NO_ECC:    No copy of ECC signals.
+ * - NO_DATA:   No copy of data signals.
+ * - CTRL_ONLY: o copy of data or ECC signals.
  */
 
 `include "hci_helpers.svh"
 
 module hci_copy_sink
-  import hci_package::*;
-(
+  import hci_package::*; 
+#(
+  parameter hci_package::hci_copy_t  COPY_TYPE = COPY
+) (
   input logic           clk_i,
   input logic           rst_ni,
   hci_core_intf.monitor tcdm_main,
   hci_core_intf.target  tcdm_copy,
-  output logic          fault_detected_o
+  output logic          fault_o
 );
+  
+  logic fault, ctrl_fault, data_fault, ecc_fault;
+
 
+  // Control signals always assigned
   assign tcdm_copy.gnt      = tcdm_main.gnt;
-  assign tcdm_copy.r_data   = tcdm_main.r_data;
   assign tcdm_copy.r_valid  = tcdm_main.r_valid;
   assign tcdm_copy.r_user   = tcdm_main.r_user;
   assign tcdm_copy.r_id     = tcdm_main.r_id;
   assign tcdm_copy.r_opc    = tcdm_main.r_opc;
-  assign tcdm_copy.egnt     = tcdm_main.egnt;
-  assign tcdm_copy.r_evalid = tcdm_main.r_evalid;
-  assign tcdm_copy.r_ecc    = tcdm_main.r_ecc;
 
-  // Compare Signals
-  logic fault_detected;
-  assign fault_detected =
+  assign ctrl_fault = 
     ( tcdm_main.req      != tcdm_copy.req      ) |
-    ( tcdm_main.ereq     != tcdm_copy.ereq     ) |
-    ( tcdm_main.r_eready != tcdm_copy.r_eready ) |
-    ( tcdm_main.ecc      != tcdm_copy.ecc      ) |
     ( tcdm_main.add      != tcdm_copy.add      ) |
     ( tcdm_main.wen      != tcdm_copy.wen      ) |
-    ( tcdm_main.data     != tcdm_copy.data     ) |
     ( tcdm_main.be       != tcdm_copy.be       ) |
     ( tcdm_main.r_ready  != tcdm_copy.r_ready  ) |
     ( tcdm_main.user     != tcdm_copy.user     ) |
     ( tcdm_main.id       != tcdm_copy.id       );
 
+
+  // Data
+  if (COPY_TYPE == NO_DATA || COPY_TYPE = CTRL_ONLY) begin
+    assign data_fault = 1'b0;
+  end
+  else
+    assign data_fault = tcdm_main.data != tcdm_copy.data
+    assign tcdm_copy.r_data   = tcdm_main.r_data;
+  begin
+
+
+  // ECC
+  if (COPY_TYPE == NO_ECC || COPY_TYPE = CTRL_ONLY) begin
+    assign ecc_fault = 1'b0;
+  end
+  else
+    assign tcdm_copy.egnt     = tcdm_main.egnt;
+    assign tcdm_copy.r_evalid = tcdm_main.r_evalid;
+    assign tcdm_copy.r_ecc    = tcdm_main.r_ecc;
+
+    assign ecc_fault =
+      ( tcdm_main.req      != tcdm_copy.req      ) |
+      ( tcdm_main.ereq     != tcdm_copy.ereq     ) |
+      ( tcdm_main.r_eready != tcdm_copy.r_eready ) |
+      ( tcdm_main.ecc      != tcdm_copy.ecc      ) |
+  begin
+
+
+  assign fault = ctrl_fault | data_fault | ecc_fault;
+  
+  // Store in FF so critical path is broken
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
-      fault_detected_o <= '0;
+      fault_o <= '0;
     end else begin
-      fault_detected_o <= fault_detected;
+      fault_o <= fault;
     end
   end
 
diff --git a/rtl/parity/hci_copy_source.sv b/rtl/parity/hci_copy_source.sv
index 564c7dc..9664c52 100644
--- a/rtl/parity/hci_copy_source.sv
+++ b/rtl/parity/hci_copy_source.sv
@@ -18,50 +18,85 @@
  * stream `tcdm_main` and copy it to an output hci interface `tcdm_copy`.
  * Together with hci_copy_sink this allows for fault detection on a chain of
  * HCI modules.
+ *
+ * How "deep" the copy is can be set with the parameter COPY_TYPE.
+ * COPY_TYPE MUST match on connected sinks and sources!
+ *
+ * The available options are:
+ * - COPY:      Fully copy of everything.
+ * - NO_ECC:    No copy of ECC signals.
+ * - NO_DATA:   No copy of data signals.
+ * - CTRL_ONLY: o copy of data or ECC signals.
  */
 
-
 `include "hci_helpers.svh"
 
 module hci_copy_source
   import hci_package::*;
-(
+#(
+  parameter hci_package::hci_copy_t  COPY_TYPE = COPY
+) (
   input logic             clk_i,
   input logic             rst_ni,
   hci_core_intf.monitor   tcdm_main,
   hci_core_intf.initiator tcdm_copy,
-  output logic            fault_detected_o
+  output logic            fault_o
 );
+  
+  logic fault, ctrl_fault, data_fault, ecc_fault;
+
+  // Control signals always assigned
+  assign tcdm_main.req     = tcdm_copy.req;
+  assign tcdm_main.add     = tcdm_copy.add;
+  assign tcdm_main.wen     = tcdm_copy.wen;
+  assign tcdm_main.be      = tcdm_copy.be;
+  assign tcdm_main.r_ready = tcdm_copy.r_ready;
+  assign tcdm_main.user    = tcdm_copy.user;
+  assign tcdm_main.id      = tcdm_copy.id;
+
+  assign ctrl_fault = 
+    ( tcdm_copy.gnt      != tcdm_main.gnt     ) |
+    ( tcdm_copy.r_valid  != tcdm_main.r_valid ) |
+    ( tcdm_copy.r_user   != tcdm_main.r_user  ) |
+    ( tcdm_copy.r_id     != tcdm_main.r_id    ) |
+    ( tcdm_copy.r_opc    != tcdm_main.r_opc   );
+
+
+  // Data
+  if (COPY_TYPE == NO_DATA || COPY_TYPE = CTRL_ONLY) begin
+    assign data_fault = 1'b0;
+  end
+  else
+    assign data_fault = tcdm_main.r_data != tcdm_copy.r_data
+    assign tcdm_copy.data = tcdm_main.data;
+  begin
+
+
+  // ECC
+  if (COPY_TYPE == NO_ECC || COPY_TYPE = CTRL_ONLY) begin
+    assign ecc_fault = 1'b0;
+  end
+  else
+    assign tcdm_main.req      = tcdm_copy.req;
+    assign tcdm_main.ereq     = tcdm_copy.ereq;
+    assign tcdm_main.r_eready = tcdm_copy.r_eready;
+    assign tcdm_main.ecc      = tcdm_copy.ecc;
+
+    assign ecc_fault =
+      ( tcdm_copy.egnt     != tcdm_main.egnt     ) |
+      ( tcdm_copy.r_evalid != tcdm_main.r_evalid ) |
+      ( tcdm_copy.r_ecc    != tcdm_main.r_ecc    );
+  begin
 
-  assign tcdm_copy.req      = tcdm_main.req;
-  assign tcdm_copy.ereq     = tcdm_main.ereq;
-  assign tcdm_copy.r_eready = tcdm_main.r_eready;
-  assign tcdm_copy.ecc      = tcdm_main.ecc;
-  assign tcdm_copy.add      = tcdm_main.add;
-  assign tcdm_copy.wen      = tcdm_main.wen;
-  assign tcdm_copy.data     = tcdm_main.data;
-  assign tcdm_copy.be       = tcdm_main.be;
-  assign tcdm_copy.r_ready  = tcdm_main.r_ready;
-  assign tcdm_copy.user     = tcdm_main.user;
-  assign tcdm_copy.id       = tcdm_main.id;
 
-  // Compare Signals
-  assign fault_detected =
-    ( tcdm_copy.gnt      != tcdm_main.gnt      ) |
-    ( tcdm_copy.r_data   != tcdm_main.r_data   ) |
-    ( tcdm_copy.r_valid  != tcdm_main.r_valid  ) |
-    ( tcdm_copy.r_user   != tcdm_main.r_user   ) |
-    ( tcdm_copy.r_id     != tcdm_main.r_id     ) |
-    ( tcdm_copy.r_opc    != tcdm_main.r_opc    ) |
-    ( tcdm_copy.egnt     != tcdm_main.egnt     ) |
-    ( tcdm_copy.r_evalid != tcdm_main.r_evalid ) |
-    ( tcdm_copy.r_ecc    != tcdm_main.r_ecc    );
+  assign fault = ctrl_fault | data_fault | ecc_fault;
 
+  // Store in FF so critical path is broken
   always_ff @(posedge clk_i or negedge rst_ni) begin
     if (!rst_ni) begin
-      fault_detected_o <= '0;
+      fault_o <= '0;
     end else begin
-      fault_detected_o <= fault_detected;
+      fault_o <= fault;
     end
   end