[flash_ctrl] propagate write integrity

- propagate write integrity past adapter_sram into flash_phy
- simplify the various integerity errors into local escalation

Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
index f71d0c3..1c62a2d 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl.sv.tpl
@@ -153,22 +153,22 @@
   );
 
   // FIFO Connections
-  logic                 prog_fifo_wvalid;
-  logic                 prog_fifo_wready;
-  logic                 prog_fifo_rvalid;
-  logic                 prog_fifo_ren;
-  logic [BusWidth-1:0]  prog_fifo_wdata;
-  logic [BusWidth-1:0]  prog_fifo_rdata;
-  logic [FifoDepthW-1:0] prog_fifo_depth;
-  logic                 rd_fifo_wready;
-  logic                 rd_fifo_rvalid;
-  logic                 rd_fifo_rready;
-  logic                 rd_fifo_wen;
-  logic                 rd_fifo_ren;
-  logic [BusWidth-1:0]  rd_fifo_wdata;
-  logic [BusWidth-1:0]  rd_fifo_rdata;
-  logic [FifoDepthW-1:0] rd_fifo_depth;
-  logic                 rd_fifo_full;
+  logic                    prog_fifo_wvalid;
+  logic                    prog_fifo_wready;
+  logic                    prog_fifo_rvalid;
+  logic                    prog_fifo_ren;
+  logic [BusFullWidth-1:0] prog_fifo_wdata;
+  logic [BusFullWidth-1:0] prog_fifo_rdata;
+  logic [FifoDepthW-1:0]   prog_fifo_depth;
+  logic                    rd_fifo_wready;
+  logic                    rd_fifo_rvalid;
+  logic                    rd_fifo_rready;
+  logic                    rd_fifo_wen;
+  logic                    rd_fifo_ren;
+  logic [BusWidth-1:0]     rd_fifo_wdata;
+  logic [BusWidth-1:0]     rd_fifo_rdata;
+  logic [FifoDepthW-1:0]   rd_fifo_depth;
+  logic                    rd_fifo_full;
 
   // Program Control Connections
   logic prog_flash_req;
@@ -198,7 +198,7 @@
   logic flash_req;
   logic flash_rd_done, flash_prog_done, flash_erase_done;
   logic flash_mp_err;
-  logic [BusWidth-1:0] flash_prog_data;
+  logic [BusFullWidth-1:0] flash_prog_data;
   logic flash_prog_last;
   flash_prog_e flash_prog_type;
   logic [BusWidth-1:0] flash_rd_data;
@@ -255,7 +255,7 @@
   logic sw_rvalid;
   logic adapter_rvalid;
   logic sw_wvalid;
-  logic [BusWidth-1:0] sw_wdata;
+  logic [BusFullWidth-1:0] sw_wdata;
   logic sw_wready;
 
   // lfsr for local entropy usage
@@ -339,7 +339,7 @@
     .hw_rvalid_o(hw_rvalid),
     .hw_rready_i(hw_rready),
     .hw_wvalid_i(hw_wvalid),
-    .hw_wdata_i(hw_wdata),
+    .hw_wdata_i(BusFullWidth'(hw_wdata)), // TODO: enhance for hw side later
     .hw_wready_o(hw_wready),
 
     // hardware interface does not talk to prog_fifo
@@ -468,10 +468,11 @@
   assign prog_op_valid = op_start & prog_op;
 
   tlul_adapter_sram #(
-    .SramAw(1),         //address unused
+    .SramAw(1),          //address unused
     .SramDw(BusWidth),
-    .ByteAccess(0),     //flash may not support byte access
-    .ErrOnRead(1)       //reads not supported
+    .ByteAccess(0),      //flash may not support byte access
+    .ErrOnRead(1),       //reads not supported
+    .EnableDataIntgPt(1) //passthrough data integrity
   ) u_to_prog_fifo (
     .clk_i,
     .rst_ni,
@@ -486,13 +487,13 @@
     .wmask_o     (),
     .intg_error_o(),
     .wdata_o     (sw_wdata),
-    .rdata_i     (BusWidth'(0)),
+    .rdata_i     ('0),
     .rvalid_i    (1'b0),
     .rerror_i    (2'b0)
   );
 
   prim_fifo_sync #(
-    .Width(BusWidth),
+    .Width(BusFullWidth),
     .Depth(FifoDepth)
   ) u_prog_fifo (
     .clk_i,
@@ -813,7 +814,6 @@
   assign flash_phy_req.jtag_req.tms = cio_tms_i;
   assign flash_phy_req.jtag_req.tdi = cio_tdi_i;
   assign flash_phy_req.jtag_req.trst_n = '0;
-  assign flash_phy_req.intg_err = intg_err;
   assign cio_tdo_o = flash_phy_rsp.jtag_rsp.tdo;
   assign cio_tdo_en_o = flash_phy_rsp.jtag_rsp.tdo_oe;
   assign flash_rd_err = flash_phy_rsp.rd_err;
@@ -1162,7 +1162,6 @@
   logic flash_host_rderr;
   logic [flash_ctrl_pkg::BusWidth-1:0] flash_host_rdata;
   logic [flash_ctrl_pkg::BusAddrW-1:0] flash_host_addr;
-  logic flash_host_intg_err;
 
   import prim_mubi_pkg::mubi4_test_true_loose;
   logic host_disable;
@@ -1188,7 +1187,7 @@
     .ByteAccess(0),
     .ErrOnWrite(1),
     .CmdIntgCheck(1),
-    .EnableRspIntgGen(1),
+    .EnableRspIntgGen(1), // keep until read path generate
     .EnableDataIntgGen(1)
   ) u_tl_adapter_eflash (
     .clk_i,
@@ -1203,7 +1202,7 @@
     .addr_o      (flash_host_addr),
     .wdata_o     (),
     .wmask_o     (),
-    .intg_error_o(flash_host_intg_err),
+    .intg_error_o(),
     .rdata_i     (flash_host_rdata),
     .rvalid_i    (flash_host_req_done | disabled_rvalid),
     .rerror_i    ({flash_host_rderr,1'b0} | disabled_err)
@@ -1215,7 +1214,6 @@
     .clk_i,
     .rst_ni,
     .host_req_i        (flash_host_req),
-    .host_intg_err_i   (flash_host_intg_err),
     .host_addr_i       (flash_host_addr),
     .host_req_rdy_o    (flash_host_req_rdy),
     .host_req_done_o   (flash_host_req_done),
diff --git a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
index 4600469..5e4e0b9 100644
--- a/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
+++ b/hw/ip/flash_ctrl/data/flash_ctrl_pkg.sv.tpl
@@ -33,6 +33,8 @@
   });
   parameter int WordsPerPage    = ${cfg.words_per_page}; // Number of flash words per page
   parameter int BusWidth        = top_pkg::TL_DW;
+  parameter int BusIntgWidth    = tlul_pkg::DataIntgWidth;
+  parameter int BusFullWidth    = BusWidth + BusIntgWidth;   
   parameter int MpRegions       = 8;  // flash controller protection regions
   parameter int FifoDepth       = 16; // rd / prog fifos
   parameter int InfoTypesWidth  = prim_util_pkg::vbits(InfoTypes);
@@ -381,7 +383,7 @@
     flash_part_e          part;
     logic [InfoTypesWidth-1:0] info_sel;
     logic [BusAddrW-1:0]  addr;
-    logic [BusWidth-1:0]  prog_data;
+    logic [BusFullWidth-1:0] prog_data;
     logic                 prog_last;
     flash_prog_e          prog_type;
     mp_region_cfg_t [MpRegions:0] region_cfgs;
@@ -392,7 +394,6 @@
     logic                 alert_trig;
     logic                 alert_ack;
     jtag_pkg::jtag_req_t  jtag_req;
-    logic                 intg_err;
     prim_mubi_pkg::mubi4_t flash_disable;
   } flash_req_t;
 
@@ -422,7 +423,6 @@
     alert_trig:    1'b0,
     alert_ack:     1'b0,
     jtag_req:      '0,
-    intg_err:      '0,
     flash_disable: prim_mubi_pkg::MuBi4False
   };
 
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
index b6807de..4ddd3c0 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_arb.sv
@@ -32,7 +32,7 @@
   // software interface to prog_fifo
   input sw_wvalid_i,
   output logic sw_wready_o,
-  input [BusWidth-1:0] sw_wdata_i,
+  input [BusFullWidth-1:0] sw_wdata_i,
 
   // hardware interface to rd_ctrl / erase_ctrl
   input hw_req_i,
@@ -48,7 +48,7 @@
 
   // hardware interface to prog_fifo
   input hw_wvalid_i,
-  input [BusWidth-1:0] hw_wdata_i,
+  input [BusFullWidth-1:0] hw_wdata_i,
   output logic hw_wready_o,
 
   // muxed interface to rd_ctrl / erase_ctrl
@@ -70,7 +70,7 @@
 
   // muxed interface to prog_fifo
   output logic prog_fifo_wvalid_o,
-  output logic [BusWidth-1:0] prog_fifo_wdata_o,
+  output logic [BusFullWidth-1:0] prog_fifo_wdata_o,
   input logic prog_fifo_wready_i,
 
   // flash phy initialization ongoing
diff --git a/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv b/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
index 9bc468a..e164bd7 100644
--- a/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_ctrl_prog.sv
@@ -23,14 +23,14 @@
 
   // FIFO Interface
   input                    data_rdy_i,
-  input  [BusWidth-1:0]    data_i,
+  input  [BusFullWidth-1:0] data_i,
   output logic             data_rd_o,
 
   // Flash Macro Interface
   output logic             flash_req_o,
   output logic [BusAddrW-1:0] flash_addr_o,
   output logic             flash_ovfl_o,
-  output logic [BusWidth-1:0] flash_data_o,
+  output logic [BusFullWidth-1:0] flash_data_o,
   output logic             flash_last_o, // last beat of prog data
   output flash_prog_e      flash_type_o,
   input                    flash_done_i,
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy.sv b/hw/ip/flash_ctrl/rtl/flash_phy.sv
index 6100800..fd1dfae 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy.sv
@@ -20,7 +20,6 @@
   input clk_i,
   input rst_ni,
   input host_req_i,
-  input host_intg_err_i,
   input [BusAddrW-1:0] host_addr_i,
   output logic host_req_rdy_o,
   output logic host_req_done_o,
@@ -91,9 +90,12 @@
   logic [BusWidth-1:0] rd_data [NumBanks];
   logic [NumBanks-1:0] rd_err;
 
-  // fsm error per block
+  // fsm error per bank
   logic [NumBanks-1:0] fsm_err;
 
+  // integrity error per bank
+  logic [NumBanks-1:0] intg_err;
+
   // select which bank each is operating on
   assign host_bank_sel = host_req_i ? host_addr_i[BusAddrW-1 -: BankW] : '0;
   assign ctrl_bank_sel = flash_ctrl_i.addr[BusAddrW-1 -: BankW];
@@ -114,8 +116,7 @@
   assign flash_ctrl_o.rd_data = rd_data[ctrl_bank_sel];
   assign flash_ctrl_o.rd_err = rd_err[ctrl_bank_sel];
   assign flash_ctrl_o.init_busy = init_busy;
-  // feed through host integrity error directly
-  assign flash_ctrl_o.intg_err = host_intg_err_i;
+  assign flash_ctrl_o.intg_err = |intg_err;
   assign flash_ctrl_o.fsm_err = |fsm_err;
 
 
@@ -224,7 +225,6 @@
       .clk_i,
       .rst_ni,
       // integrity error is either from host or from controller
-      .intg_err_i(host_intg_err_i | flash_ctrl_i.intg_err),
       .req_i(ctrl_req),
       .scramble_en_i(flash_ctrl_i.scramble_en),
       .ecc_en_i(flash_ctrl_i.ecc_en),
@@ -263,7 +263,8 @@
       .prim_flash_rsp_i(prim_flash_rsp[bank]),
       .ecc_single_err_o(ecc_single_err[bank]),
       .ecc_addr_o(ecc_addr[bank][BusBankAddrW-1:0]),
-      .fsm_err_o(fsm_err[bank])
+      .fsm_err_o(fsm_err[bank]),
+      .intg_err_o(intg_err[bank])
     );
   end // block: gen_flash_banks
 
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
index 977f0d2..0482767 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_core.sv
@@ -17,7 +17,6 @@
 ) (
   input                              clk_i,
   input                              rst_ni,
-  input                              intg_err_i,
   input                              host_req_i,   // host request - read only
   input                              host_scramble_en_i,
   input                              host_ecc_en_i,
@@ -34,7 +33,7 @@
   input flash_ctrl_pkg::flash_part_e part_i,
   input [InfoTypesWidth-1:0]         info_sel_i,
   input [BusBankAddrW-1:0]           addr_i,
-  input [BusWidth-1:0]               prog_data_i,
+  input [BusFullWidth-1:0]           prog_data_i,
   input                              prog_last_i,
   input flash_ctrl_pkg::flash_prog_e prog_type_i,
   input [KeySize-1:0]                addr_key_i,
@@ -54,7 +53,8 @@
   output logic                       rd_err_o,
   output logic                       ecc_single_err_o,
   output logic [BusBankAddrW-1:0]    ecc_addr_o,
-  output logic                       fsm_err_o
+  output logic                       fsm_err_o,
+  output logic                       intg_err_o
 );
 
 
@@ -351,7 +351,7 @@
 
   if (WidthMultiple == 1) begin : gen_single_prog_data
     assign flash_prog_req = reqs[PhyProg];
-    assign prog_data = prog_data_i;
+    assign prog_data = prog_data_i[BusWidth-1:0];
     assign prog_fsm_err = '0;
   end else begin : gen_prog_data
 
@@ -378,7 +378,8 @@
       .ack_o(prog_ack),
       .block_data_o(prog_data),
       .data_o(prog_full_data),
-      .fsm_err_o(prog_fsm_err)
+      .fsm_err_o(prog_fsm_err),
+      .intg_err_o
     );
   end
 
@@ -418,7 +419,7 @@
     .clk_i,
     .rst_ni,
     // both escalation and and integrity error cause the scramble keys to change
-    .intg_err_i(intg_err_i | mubi4_test_true_loose(flash_disable[ScrDisableIdx])),
+    .disable_i(mubi4_test_true_loose(flash_disable[ScrDisableIdx])),
     .calc_req_i(prog_calc_req | rd_calc_req),
     .op_req_i(prog_op_req | rd_op_req),
     .op_type_i(prog_op_req ? ScrambleOp : DeScrambleOp),
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
index 8a1cb2d..8749cf4 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_pkg.sv
@@ -32,6 +32,7 @@
 
   // flash ctrl / bus parameters
   parameter int unsigned BusWidth       = flash_ctrl_pkg::BusWidth;
+  parameter int unsigned BusFullWidth   = flash_ctrl_pkg::BusFullWidth;      
   parameter int unsigned BusBankAddrW   = flash_ctrl_pkg::BusBankAddrW;
   parameter int unsigned BusWordW       = flash_ctrl_pkg::BusWordW;
   parameter int unsigned ProgTypes      = flash_ctrl_pkg::ProgTypes;
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
index 2306941..f7f670e 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_prog.sv
@@ -28,7 +28,7 @@
   input scramble_i,
   input ecc_i,
   input [WordSelW-1:0] sel_i,
-  input [BusWidth-1:0] data_i,
+  input [BusFullWidth-1:0] data_i,
   input last_i,
   input ack_i,  // ack means request has been accepted by flash
   input done_i, // done means requested transaction has completed
@@ -44,7 +44,8 @@
   // block data does not contain ecc / metadata portion
   output logic [DataWidth-1:0] block_data_o,
   output logic [FullDataWidth-1:0] data_o,
-  output logic fsm_err_o
+  output logic fsm_err_o,
+  output logic intg_err_o
 );
 
   // Encoding generated with:
@@ -106,7 +107,42 @@
   logic plain_ecc_en;
 
   // selects empty data or real data
-  assign pack_data  = (data_sel == Actual) ? data_i : {BusWidth{1'b1}};
+  assign pack_data  = (data_sel == Actual) ? data_i[BusWidth-1:0] : {BusWidth{1'b1}};
+
+  logic data_intg_ok;
+  logic [1:0] data_err;
+
+  // TODO: for clarity purposes, tlul should have an integrity wrapper module that is
+  // instantiated here.  That way the module does not need to know exactly what is used.
+  prim_secded_inv_39_32_dec u_data_intg_chk (
+    .data_i(data_i),
+    .data_o(),
+    .syndrome_o(),
+    .err_o(data_err)
+  );
+  assign data_intg_ok = (data_err == '0);
+
+  logic data_invalid_q, data_invalid_d;
+  // hold on integrity failure indication until reset
+  assign data_invalid_d = data_invalid_q |
+                          (pack_valid & ~data_intg_ok);
+
+  always_ff @(posedge clk_i or negedge rst_ni) begin
+    if (!rst_ni) begin
+      data_invalid_q <= '0;
+    end else begin
+      data_invalid_q <= data_invalid_d;
+    end
+  end
+
+  // indication to upper layer prescence of error
+  assign intg_err_o = data_invalid_q;
+
+  // if integrity failure is seen, fake communication with flash
+  // and simply terminate
+  logic ack, done;
+  assign ack = ack_i | data_invalid_q;
+  assign done = done_i | data_invalid_q;
 
   // next idx will be aligned
   assign idx_sub_one = idx - 1'b1;
@@ -230,7 +266,8 @@
       end
 
       StReqFlash: begin
-        req_o = 1'b1;
+        // only request flash if data integrity was valid
+        req_o = ~data_invalid_q;
         last_o = last_i;
 
         // if this is the last beat of the program burst
@@ -238,16 +275,15 @@
         // if this is NOT the last beat
         //   - ack the upstream request and accept more beats
         if (last_i) begin
-          state_d = ack_i ? StWaitFlash : StReqFlash;
+          state_d = ack ? StWaitFlash : StReqFlash;
         end else begin
-          ack_o = ack_i;
-          state_d = ack_i ? StIdle : StReqFlash;
+          ack_o = ack;
+          state_d = ack ? StIdle : StReqFlash;
         end
       end
 
       StWaitFlash: begin
-
-        if (done_i) begin
+        if (done) begin
           ack_o = 1'b1;
           state_d = StIdle;
         end
@@ -270,7 +306,7 @@
     if (!rst_ni) begin
       packed_data <= '0;
       mask_q <= '0;
-    end else if (req_o && ack_i) begin
+    end else if (req_o && ack) begin
       packed_data <= '0;
     end else if (calc_req_o && calc_ack_i) begin
       packed_data <= packed_data ^ mask_i;
@@ -335,7 +371,7 @@
       done_cnt <= '0;
     end else if (txn_done) begin
       done_cnt <= '0;
-    end else if (done_i) begin
+    end else if (done) begin
       done_cnt <= done_cnt + 1'b1;
     end
   end
diff --git a/hw/ip/flash_ctrl/rtl/flash_phy_scramble.sv b/hw/ip/flash_ctrl/rtl/flash_phy_scramble.sv
index 062e06e..ddf5b4e 100644
--- a/hw/ip/flash_ctrl/rtl/flash_phy_scramble.sv
+++ b/hw/ip/flash_ctrl/rtl/flash_phy_scramble.sv
@@ -14,7 +14,7 @@
 ) (
   input clk_i,
   input rst_ni,
-  input intg_err_i,
+  input disable_i,
   input calc_req_i, // calculate galois multiplier mask
   input op_req_i,   // request primitive operation
   input cipher_ops_e op_type_i,  // sramble or de-scramble
@@ -43,7 +43,7 @@
     if (!rst_ni) begin
       addr_key_sel <= '0;
     end else if (!calc_req_i || calc_req_i && calc_ack_o) begin
-      addr_key_sel <= intg_err_i;
+      addr_key_sel <= disable_i;
     end
   end
 
@@ -94,7 +94,7 @@
     if (!rst_ni) begin
       data_key_sel <= '0;
     end else if (!op_req_i || op_req_i && op_ack_o) begin
-      data_key_sel <= intg_err_i;
+      data_key_sel <= disable_i;
     end
   end