[tlul] Add payload checker and generator on device side only.

- Incomplete until host side is done
- Windowed accesses also need further tweaking

Signed-off-by: Timothy Chen <timothytim@google.com>

[tlul] Enhance host / device checks

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/Makefile b/hw/Makefile
index 94719e5..c497acc 100644
--- a/hw/Makefile
+++ b/hw/Makefile
@@ -26,6 +26,7 @@
        lc_ctrl       \
        nmi_gen       \
        otp_ctrl      \
+       pattgen       \
        pinmux        \
        pwrmgr        \
        rstmgr        \
diff --git a/hw/ip/prim/prim_secded.core b/hw/ip/prim/prim_secded.core
index 2fea1c0..87a248e 100644
--- a/hw/ip/prim/prim_secded.core
+++ b/hw/ip/prim/prim_secded.core
@@ -14,6 +14,8 @@
       - rtl/prim_secded_28_22_enc.sv
       - rtl/prim_secded_39_32_dec.sv
       - rtl/prim_secded_39_32_enc.sv
+      - rtl/prim_secded_64_57_dec.sv
+      - rtl/prim_secded_64_57_enc.sv
       - rtl/prim_secded_72_64_dec.sv
       - rtl/prim_secded_72_64_enc.sv
       - rtl/prim_secded_hamming_22_16_dec.sv
diff --git a/hw/ip/prim/rtl/prim_secded_64_57_dec.sv b/hw/ip/prim/rtl/prim_secded_64_57_dec.sv
new file mode 100644
index 0000000..6ed256a
--- /dev/null
+++ b/hw/ip/prim/rtl/prim_secded_64_57_dec.sv
@@ -0,0 +1,88 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+//
+// SECDED Decoder generated by
+// util/design/secded_gen.py -m 7 -k 57 -s 2871209727 -c hsiao
+
+module prim_secded_64_57_dec (
+  input        [63:0] in,
+  output logic [56:0] d_o,
+  output logic [6:0] syndrome_o,
+  output logic [1:0] err_o
+);
+
+
+  // Syndrome calculation
+  assign syndrome_o[0] = ^(in & 64'h0303FFF800007FFF);
+  assign syndrome_o[1] = ^(in & 64'h057C1FF801FF801F);
+  assign syndrome_o[2] = ^(in & 64'h09BDE1F87E0781E1);
+  assign syndrome_o[3] = ^(in & 64'h11DEEE3B8E388E22);
+  assign syndrome_o[4] = ^(in & 64'h21EF76CDB2C93244);
+  assign syndrome_o[5] = ^(in & 64'h41F7BB56D5525488);
+  assign syndrome_o[6] = ^(in & 64'h81FBDDA769A46910);
+
+  // Corrected output calculation
+  assign d_o[0] = (syndrome_o == 7'h7) ^ in[0];
+  assign d_o[1] = (syndrome_o == 7'hb) ^ in[1];
+  assign d_o[2] = (syndrome_o == 7'h13) ^ in[2];
+  assign d_o[3] = (syndrome_o == 7'h23) ^ in[3];
+  assign d_o[4] = (syndrome_o == 7'h43) ^ in[4];
+  assign d_o[5] = (syndrome_o == 7'hd) ^ in[5];
+  assign d_o[6] = (syndrome_o == 7'h15) ^ in[6];
+  assign d_o[7] = (syndrome_o == 7'h25) ^ in[7];
+  assign d_o[8] = (syndrome_o == 7'h45) ^ in[8];
+  assign d_o[9] = (syndrome_o == 7'h19) ^ in[9];
+  assign d_o[10] = (syndrome_o == 7'h29) ^ in[10];
+  assign d_o[11] = (syndrome_o == 7'h49) ^ in[11];
+  assign d_o[12] = (syndrome_o == 7'h31) ^ in[12];
+  assign d_o[13] = (syndrome_o == 7'h51) ^ in[13];
+  assign d_o[14] = (syndrome_o == 7'h61) ^ in[14];
+  assign d_o[15] = (syndrome_o == 7'he) ^ in[15];
+  assign d_o[16] = (syndrome_o == 7'h16) ^ in[16];
+  assign d_o[17] = (syndrome_o == 7'h26) ^ in[17];
+  assign d_o[18] = (syndrome_o == 7'h46) ^ in[18];
+  assign d_o[19] = (syndrome_o == 7'h1a) ^ in[19];
+  assign d_o[20] = (syndrome_o == 7'h2a) ^ in[20];
+  assign d_o[21] = (syndrome_o == 7'h4a) ^ in[21];
+  assign d_o[22] = (syndrome_o == 7'h32) ^ in[22];
+  assign d_o[23] = (syndrome_o == 7'h52) ^ in[23];
+  assign d_o[24] = (syndrome_o == 7'h62) ^ in[24];
+  assign d_o[25] = (syndrome_o == 7'h1c) ^ in[25];
+  assign d_o[26] = (syndrome_o == 7'h2c) ^ in[26];
+  assign d_o[27] = (syndrome_o == 7'h4c) ^ in[27];
+  assign d_o[28] = (syndrome_o == 7'h34) ^ in[28];
+  assign d_o[29] = (syndrome_o == 7'h54) ^ in[29];
+  assign d_o[30] = (syndrome_o == 7'h64) ^ in[30];
+  assign d_o[31] = (syndrome_o == 7'h38) ^ in[31];
+  assign d_o[32] = (syndrome_o == 7'h58) ^ in[32];
+  assign d_o[33] = (syndrome_o == 7'h68) ^ in[33];
+  assign d_o[34] = (syndrome_o == 7'h70) ^ in[34];
+  assign d_o[35] = (syndrome_o == 7'h1f) ^ in[35];
+  assign d_o[36] = (syndrome_o == 7'h2f) ^ in[36];
+  assign d_o[37] = (syndrome_o == 7'h4f) ^ in[37];
+  assign d_o[38] = (syndrome_o == 7'h37) ^ in[38];
+  assign d_o[39] = (syndrome_o == 7'h57) ^ in[39];
+  assign d_o[40] = (syndrome_o == 7'h67) ^ in[40];
+  assign d_o[41] = (syndrome_o == 7'h3b) ^ in[41];
+  assign d_o[42] = (syndrome_o == 7'h5b) ^ in[42];
+  assign d_o[43] = (syndrome_o == 7'h6b) ^ in[43];
+  assign d_o[44] = (syndrome_o == 7'h73) ^ in[44];
+  assign d_o[45] = (syndrome_o == 7'h3d) ^ in[45];
+  assign d_o[46] = (syndrome_o == 7'h5d) ^ in[46];
+  assign d_o[47] = (syndrome_o == 7'h6d) ^ in[47];
+  assign d_o[48] = (syndrome_o == 7'h75) ^ in[48];
+  assign d_o[49] = (syndrome_o == 7'h79) ^ in[49];
+  assign d_o[50] = (syndrome_o == 7'h3e) ^ in[50];
+  assign d_o[51] = (syndrome_o == 7'h5e) ^ in[51];
+  assign d_o[52] = (syndrome_o == 7'h6e) ^ in[52];
+  assign d_o[53] = (syndrome_o == 7'h76) ^ in[53];
+  assign d_o[54] = (syndrome_o == 7'h7a) ^ in[54];
+  assign d_o[55] = (syndrome_o == 7'h7c) ^ in[55];
+  assign d_o[56] = (syndrome_o == 7'h7f) ^ in[56];
+
+  // err_o calc. bit0: single error, bit1: double error
+  assign err_o[0] = ^syndrome_o;
+  assign err_o[1] = ~err_o[0] & (|syndrome_o);
+
+endmodule : prim_secded_64_57_dec
diff --git a/hw/ip/prim/rtl/prim_secded_64_57_enc.sv b/hw/ip/prim/rtl/prim_secded_64_57_enc.sv
new file mode 100644
index 0000000..f0f85f8
--- /dev/null
+++ b/hw/ip/prim/rtl/prim_secded_64_57_enc.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
+//
+// SECDED Encoder generated by
+// util/design/secded_gen.py -m 7 -k 57 -s 2871209727 -c hsiao
+
+module prim_secded_64_57_enc (
+  input        [56:0] in,
+  output logic [63:0] out
+);
+
+  always_comb begin : p_encode
+    out = 64'(in);
+    out[57] = ^(out & 64'h0103FFF800007FFF);
+    out[58] = ^(out & 64'h017C1FF801FF801F);
+    out[59] = ^(out & 64'h01BDE1F87E0781E1);
+    out[60] = ^(out & 64'h01DEEE3B8E388E22);
+    out[61] = ^(out & 64'h01EF76CDB2C93244);
+    out[62] = ^(out & 64'h01F7BB56D5525488);
+    out[63] = ^(out & 64'h01FBDDA769A46910);
+  end
+
+endmodule : prim_secded_64_57_enc
diff --git a/hw/ip/tlul/adapter_reg.core b/hw/ip/tlul/adapter_reg.core
index 4a92858..1e65ca6 100644
--- a/hw/ip/tlul/adapter_reg.core
+++ b/hw/ip/tlul/adapter_reg.core
@@ -10,6 +10,7 @@
     depend:
       - lowrisc:prim:all
       - lowrisc:tlul:common
+      - lowrisc:tlul:payload_chk
     files:
       - rtl/tlul_adapter_reg.sv
     file_type: systemVerilogSource
diff --git a/hw/ip/tlul/payload_chk.core b/hw/ip/tlul/payload_chk.core
new file mode 100644
index 0000000..0a06045
--- /dev/null
+++ b/hw/ip/tlul/payload_chk.core
@@ -0,0 +1,61 @@
+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:tlul:payload_chk:0.1"
+description: "TL-UL to Register interface adapter"
+
+filesets:
+  files_rtl:
+    depend:
+      - lowrisc:prim:all
+      - lowrisc:prim:secded
+      - lowrisc:tlul:common
+    files:
+      - rtl/tlul_payload_chk.sv
+      - rtl/tlul_gen_payload_chk.sv
+    file_type: systemVerilogSource
+
+  files_verilator_waiver:
+    depend:
+      # common waivers
+      - lowrisc:lint:common
+    file_type: vlt
+
+  files_ascentlint_waiver:
+    depend:
+      # common waivers
+      - lowrisc:lint:common
+    file_type: waiver
+
+  files_veriblelint_waiver:
+    depend:
+      # common waivers
+      - lowrisc:lint:common
+      - lowrisc:lint:comportable
+
+parameters:
+  SYNTHESIS:
+    datatype: bool
+    paramtype: vlogdefine
+
+
+targets:
+  default: &default_target
+    filesets:
+      - tool_verilator   ? (files_verilator_waiver)
+      - tool_ascentlint  ? (files_ascentlint_waiver)
+      - tool_veriblelint ? (files_veriblelint_waiver)
+      - files_rtl
+    toplevel: tlul_payload_chk
+
+  lint:
+    <<: *default_target
+    default_tool: verilator
+    parameters:
+      - SYNTHESIS=true
+    tools:
+      verilator:
+        mode: lint-only
+        verilator_options:
+          - "-Wall"
diff --git a/hw/ip/tlul/rtl/tlul_adapter_host.sv b/hw/ip/tlul/rtl/tlul_adapter_host.sv
index 9248a09..b57f0f9 100644
--- a/hw/ip/tlul/rtl/tlul_adapter_host.sv
+++ b/hw/ip/tlul/rtl/tlul_adapter_host.sv
@@ -46,6 +46,8 @@
 
   logic [top_pkg::TL_AIW-1:0] tl_source;
   logic [top_pkg::TL_DBW-1:0] tl_be;
+  tl_h2d_t                    tl_out;
+  tl_a_user_t tl_user;
 
   if (MAX_REQS == 1) begin : g_single_req
     assign tl_source = '0;
@@ -83,7 +85,7 @@
   // bits set. For writes the supplied be_i is used as the mask.
   assign tl_be = ~we_i ? {top_pkg::TL_DBW{1'b1}} : be_i;
 
-  assign tl_o = '{
+  assign tl_out = '{
     a_valid:   req_i,
     a_opcode:  (~we_i) ? Get           :
                (&be_i) ? PutFullData   :
@@ -94,11 +96,33 @@
     a_source:  tl_source,
     a_address: {addr_i[31:WordSize], {WordSize{1'b0}}},
     a_data:    wdata_i,
-    a_user:    '{parity_en: '0, parity: '0, tl_type: type_i},
-
+    a_user:    '{default: '0, chk_en: CheckDis, chk_data: '0, tl_type: type_i},
     d_ready:   1'b1
   };
 
+  logic [H2DCmdMaxWidth-1:0] unused_cmd;
+  logic [H2DCmdChkWidth-1:0] chk_cmd;
+
+  prim_secded_64_57_enc u_enc (
+    .in(H2DCmdMaxWidth'(extract_h2d_cmd_chk(tl_out))),
+    .out({chk_cmd, unused_cmd})
+  );
+
+  assign tl_user = '{
+    default: '0,
+    tl_type:  type_i,
+    chk_en:   CheckEn,
+    chk_cmd:  chk_cmd,
+    chk_data: '0
+  };
+
+  // override user bits.
+  always_comb begin
+    tl_o = tl_out;
+    tl_o.a_user = tl_user;
+  end
+
+
   assign gnt_o   = tl_i.a_ready;
 
   assign valid_o = tl_i.d_valid;
diff --git a/hw/ip/tlul/rtl/tlul_adapter_reg.sv b/hw/ip/tlul/rtl/tlul_adapter_reg.sv
index 08a730d..bda0119 100644
--- a/hw/ip/tlul/rtl/tlul_adapter_reg.sv
+++ b/hw/ip/tlul/rtl/tlul_adapter_reg.sv
@@ -113,9 +113,8 @@
   ////////////////////
   assign err_internal = addr_align_err | malformed_meta_err | tl_err ;
 
-  // malformed_meta_err
-  //    Raised if not supported feature is turned on or user signal has malformed
-  assign malformed_meta_err = (tl_i.a_user.parity_en == 1'b1);
+  // Don't allow unsupported values.
+  assign malformed_meta_err = tl_a_user_chk(tl_i.a_user);
 
   // addr_align_err
   //    Raised if addr isn't aligned with the size
diff --git a/hw/ip/tlul/rtl/tlul_adapter_sram.sv b/hw/ip/tlul/rtl/tlul_adapter_sram.sv
index 2c5e377..666e556 100644
--- a/hw/ip/tlul/rtl/tlul_adapter_sram.sv
+++ b/hw/ip/tlul/rtl/tlul_adapter_sram.sv
@@ -145,7 +145,7 @@
       d_sink   : 1'b0,
       d_data   : (d_valid && rspfifo_rvalid && reqfifo_rdata.op == OpRead)
                  ? rspfifo_rdata.data : '0,
-      d_user   : '0,
+      d_user   : TL_D_USER_DEFAULT,
       d_error  : d_valid && d_error,
 
       a_ready  : (gnt_i | error_internal) & reqfifo_wready & sramreqfifo_wready
diff --git a/hw/ip/tlul/rtl/tlul_gen_payload_chk.sv b/hw/ip/tlul/rtl/tlul_gen_payload_chk.sv
new file mode 100644
index 0000000..aec7da1
--- /dev/null
+++ b/hw/ip/tlul/rtl/tlul_gen_payload_chk.sv
@@ -0,0 +1,38 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "prim_assert.sv"
+
+/**
+ * Tile-Link UL payload checker generator
+ */
+
+module tlul_gen_payload_chk import tlul_pkg::*; (
+  // TL-UL interface
+  input  tl_d2h_t tl_i,
+  output tl_d2h_t tl_o
+);
+
+  tl_d2h_rsp_chk_t rsp;
+  logic [D2HRspMaxWidth-1:0] unused_payload;
+  logic [D2HRspChkWidth-1:0] chk;
+  assign rsp = extract_d2h_rsp_chk(tl_i);
+
+  prim_secded_64_57_enc u_gen (
+    .in(D2HRspMaxWidth'(rsp)),
+    .out({chk, unused_payload})
+  );
+
+  always_comb begin
+    tl_o = tl_i;
+    if (tl_i.d_user.chk_en == CheckDis) begin
+      tl_o.d_user.chk_en = CheckEn;
+      tl_o.d_user.chk_rsp = chk;
+    end
+  end
+
+
+  `ASSERT_INIT(PayLoadWidthCheck, $bits(tl_d2h_rsp_chk_t) <= D2HRspMaxWidth)
+
+endmodule // tlul_payload_chk
diff --git a/hw/ip/tlul/rtl/tlul_payload_chk.sv b/hw/ip/tlul/rtl/tlul_payload_chk.sv
new file mode 100644
index 0000000..91ce7ec
--- /dev/null
+++ b/hw/ip/tlul/rtl/tlul_payload_chk.sv
@@ -0,0 +1,39 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+`include "prim_assert.sv"
+
+/**
+ * Tile-Link UL payload checker
+ */
+
+module tlul_payload_chk import tlul_pkg::*; (
+  // TL-UL interface
+  input  tl_h2d_t tl_i,
+
+  // error output
+  output logic err_o
+);
+
+  logic [1:0] err;
+  tl_h2d_cmd_chk_t cmd;
+  assign cmd = extract_h2d_cmd_chk(tl_i);
+
+  prim_secded_64_57_dec u_chk (
+    .in({tl_i.a_user.chk_cmd, H2DCmdMaxWidth'(cmd)}),
+    .d_o(),
+    .syndrome_o(),
+    .err_o(err)
+  );
+
+  // TODO: The chk_en qualification here should be removed long term under a
+  // compile time option.
+  assign err_o = (tl_i.a_user.chk_en == CheckDis) ? 1'b0 : |err;
+
+  logic unused_tl;
+  assign unused_tl = |tl_i;
+
+  `ASSERT_INIT(PayLoadWidthCheck, $bits(tl_h2d_cmd_chk_t) <= H2DCmdMaxWidth)
+
+endmodule // tlul_payload_chk
diff --git a/hw/ip/tlul/rtl/tlul_pkg.sv b/hw/ip/tlul/rtl/tlul_pkg.sv
index 46c66ba..0c40799 100644
--- a/hw/ip/tlul/rtl/tlul_pkg.sv
+++ b/hw/ip/tlul/rtl/tlul_pkg.sv
@@ -37,12 +37,45 @@
     DataType      = 2'b10
   } tl_type_e;
 
+  // Even though it is codified this way, all values
+  // NOT CheckDis is considered CheckEn
+  typedef enum logic [1:0] {
+    CheckDis      = 2'b01,
+    CheckEn       = 2'b10
+  } tl_chk_en_e;
+
+  parameter int H2DCmdMaxWidth = 57;
+  parameter int H2DCmdChkWidth = 7;
+  parameter int D2HRspMaxWidth = 57;
+  parameter int D2HRspChkWidth = 7;
+
+  //parameter int H2DPayLoadFullWidth = H2DPayLoadMaxWidth + H2DPayLoadChkWidth;
+  parameter int DataMaxWidth = 32;
+  parameter int DataChkWidth = 7;
+
   typedef struct packed {
-    tl_type_e   tl_type;
-    logic       parity_en;
-    logic [7:0] parity; // Use only lower TL_DBW bit
+    logic [2:0]                    rsvd1;    // Reserved for future use
+    tl_type_e                      tl_type;
+    tl_chk_en_e                    chk_en;
+    logic [H2DCmdChkWidth-1:0]     chk_cmd;
+    logic [DataChkWidth-1:0]       chk_data;
   } tl_a_user_t;
 
+  parameter tl_a_user_t TL_A_USER_DEFAULT = '{
+    rsvd1: '0,
+    tl_type: DataType,
+    // This value is temporary
+    chk_en: CheckDis,
+    chk_cmd:  '0,
+    chk_data: '0
+  };
+
+  typedef struct packed {
+    logic   [top_pkg::TL_AW-1:0]  addr;
+    tl_a_op_e                     opcode;
+    logic  [top_pkg::TL_DBW-1:0]  mask;
+  } tl_h2d_cmd_chk_t;
+
   typedef struct packed {
     logic                         a_valid;
     tl_a_op_e                     a_opcode;
@@ -65,6 +98,18 @@
   };
 
   typedef struct packed {
+    logic [4:0]                    rsvd1;    // Reserved for future use
+    tl_chk_en_e                    chk_en;
+    logic [D2HRspChkWidth-1:0]     chk_rsp;
+  } tl_d_user_t;
+
+  parameter tl_d_user_t TL_D_USER_DEFAULT = '{
+    rsvd1: '0,
+    chk_en: CheckDis,
+    chk_rsp: '0
+  };
+
+  typedef struct packed {
     logic                         d_valid;
     tl_d_op_e                     d_opcode;
     logic                  [2:0]  d_param;
@@ -72,15 +117,57 @@
     logic  [top_pkg::TL_AIW-1:0]  d_source;
     logic  [top_pkg::TL_DIW-1:0]  d_sink;
     logic   [top_pkg::TL_DW-1:0]  d_data;
-    logic  [top_pkg::TL_DUW-1:0]  d_user;
+    tl_d_user_t                   d_user;
     logic                         d_error;
 
     logic                         a_ready;
+
   } tl_d2h_t;
 
+  typedef struct packed {
+    tl_d_op_e                     opcode;
+    logic  [top_pkg::TL_SZW-1:0]  size;
+    logic  [top_pkg::TL_AIW-1:0]  source;
+    logic                         error;
+  } tl_d2h_rsp_chk_t;
+
   localparam tl_d2h_t TL_D2H_DEFAULT = '{
     a_ready:  1'b1,
     d_opcode: tl_d_op_e'('0),
     default:  '0
   };
+
+  // Check user for unsupported values
+  function automatic logic tl_a_user_chk(tl_a_user_t user);
+    logic malformed_err;
+    logic unused_user;
+    unused_user = |user;
+    malformed_err = ~(user.tl_type inside {InstrType, DataType}) |
+                    ~(user.chk_en inside {CheckDis, CheckEn});
+    return malformed_err;
+  endfunction // tl_a_user_chk
+
+  // extract variables used for command checking
+  function automatic tl_h2d_cmd_chk_t extract_h2d_cmd_chk(tl_h2d_t tl);
+    tl_h2d_cmd_chk_t payload;
+    logic unused_tlul;
+    unused_tlul = ^tl;
+    payload.addr = tl.a_address;
+    payload.opcode = tl.a_opcode;
+    payload.mask = tl.a_mask;
+    return payload;
+  endfunction // extract_h2d_payload
+
+  // extract variables used for response checking
+  function automatic tl_d2h_rsp_chk_t extract_d2h_rsp_chk(tl_d2h_t tl);
+    tl_d2h_rsp_chk_t payload;
+    logic unused_tlul;
+    unused_tlul = ^tl;
+    payload.opcode = tl.d_opcode;
+    payload.size   = tl.d_size;
+    payload.source = tl.d_source;
+    payload.error  = tl.d_error;
+    return payload;
+  endfunction // extract_d2h_rsp_chk
+
 endpackage
diff --git a/util/reggen/reg_top.sv.tpl b/util/reggen/reg_top.sv.tpl
index e29c1f8..5f37a67 100644
--- a/util/reggen/reg_top.sv.tpl
+++ b/util/reggen/reg_top.sv.tpl
@@ -64,9 +64,23 @@
   tlul_pkg::tl_h2d_t tl_reg_h2d;
   tlul_pkg::tl_d2h_t tl_reg_d2h;
 
+  // incoming payload check
+  logic chk_err;
+  tlul_payload_chk u_chk (
+    .tl_i,
+    .err_o(chk_err)
+  );
+
+  // outgoing payload generation
+  tlul_pkg::tl_d2h_t tl_o_pre;
+  tlul_gen_payload_chk u_gen_chk (
+    .tl_i(tl_o_pre),
+    .tl_o
+  );
+
 % if num_wins == 0:
   assign tl_reg_h2d = tl_i;
-  assign tl_o       = tl_reg_d2h;
+  assign tl_o_pre   = tl_reg_d2h;
 % else:
   tlul_pkg::tl_h2d_t tl_socket_h2d [${num_dsp}];
   tlul_pkg::tl_d2h_t tl_socket_d2h [${num_dsp}];
@@ -97,7 +111,7 @@
     .clk_i,
     .rst_ni,
     .tl_h_i (tl_i),
-    .tl_h_o (tl_o),
+    .tl_h_o (tl_o_pre),
     .tl_d_o (tl_socket_h2d),
     .tl_d_i (tl_socket_d2h),
     .dev_select_i (reg_steer)
@@ -122,6 +136,9 @@
       reg_steer = ${i};
     end
   % endfor
+    if (chk_err) begin
+      reg_steer = ${num_dsp-1};
+    end
   end
 % endif
 
@@ -145,7 +162,7 @@
   );
 
   assign reg_rdata = reg_rdata_next ;
-  assign reg_error = (devmode_i & addrmiss) | wr_err ;
+  assign reg_error = (devmode_i & addrmiss) | wr_err | chk_err;
 
   // Define SW related signals
   // Format: <reg>_<field>_{wd|we|qs}