diff --git a/openpiton/ariane_verilog_wrap.sv b/openpiton/ariane_verilog_wrap.sv
index c01af03336eba2e1154b28609e0c2f4ea0f10158..c1e5833d0b66e0339aad54bb16556d3f183c1e59 100644
--- a/openpiton/ariane_verilog_wrap.sv
+++ b/openpiton/ariane_verilog_wrap.sv
@@ -23,9 +23,9 @@ module ariane_verilog_wrap #(
   parameter bit                        SwapEndianess         = 1,
   // PMA configuration
   // idempotent region
-  parameter int unsigned               NrNonIdempotentRules  =  0,
-  parameter logic [NrMaxRules*64-1:0]  NonIdempotentAddrBase = '0,
-  parameter logic [NrMaxRules*64-1:0]  NonIdempotentLength   = '0,
+  parameter int unsigned               NrNonIdempotentRules  =  1,
+  parameter logic [NrMaxRules*64-1:0]  NonIdempotentAddrBase = 64'h00C0000000,
+  parameter logic [NrMaxRules*64-1:0]  NonIdempotentLength   = 64'hFFFFFFFFFF,
   // executable regions
   parameter int unsigned               NrExecuteRegionRules  =  0,
   parameter logic [NrMaxRules*64-1:0]  ExecuteRegionAddrBase = '0,
diff --git a/src/ariane.sv b/src/ariane.sv
index 7a4fb395509e2016c079ad300410f5d365e1b117..17e8a4330c9377a673656ed022d0d8677a9a4b66 100644
--- a/src/ariane.sv
+++ b/src/ariane.sv
@@ -231,6 +231,7 @@ module ariane import ariane_pkg::*; #(
   dcache_req_i_t [2:0]      dcache_req_ports_ex_cache;
   dcache_req_o_t [2:0]      dcache_req_ports_cache_ex;
   logic                     dcache_commit_wbuffer_empty;
+  logic                     dcache_commit_wbuffer_not_ni;
 
   // --------------
   // Frontend
@@ -428,6 +429,7 @@ module ariane import ariane_pkg::*; #(
     .dcache_req_ports_i     ( dcache_req_ports_cache_ex   ),
     .dcache_req_ports_o     ( dcache_req_ports_ex_cache   ),
     .dcache_wbuffer_empty_i ( dcache_commit_wbuffer_empty ),
+    .dcache_wbuffer_not_ni_i ( dcache_commit_wbuffer_not_ni ),
     // PMP
     .pmpcfg_i               ( pmpcfg                      ),
     .pmpaddr_i              ( pmpaddr                     )
@@ -626,6 +628,7 @@ module ariane import ariane_pkg::*; #(
     .dcache_req_ports_o    ( dcache_req_ports_cache_ex   ),
     // write buffer status
     .wbuffer_empty_o       ( dcache_commit_wbuffer_empty ),
+    .wbuffer_not_ni_o      ( dcache_commit_wbuffer_not_ni ),
 `ifdef PITON_ARIANE
     .l15_req_o             ( l15_req_o                   ),
     .l15_rtrn_i            ( l15_rtrn_i                  )
@@ -672,6 +675,7 @@ module ariane import ariane_pkg::*; #(
     .axi_req_o             ( axi_req_o                   ),
     .axi_resp_i            ( axi_resp_i                  )
   );
+  assign dcache_commit_wbuffer_not_ni = 1'b1;
 `endif
 
   // -------------------
diff --git a/src/cache_subsystem/wt_cache_subsystem.sv b/src/cache_subsystem/wt_cache_subsystem.sv
index 199a2c81ba37a71babccf7c3e68f26f0beee21c6..5a0662dc4c2efa9bcc4fc34ebc15c0b6b2cc000c 100644
--- a/src/cache_subsystem/wt_cache_subsystem.sv
+++ b/src/cache_subsystem/wt_cache_subsystem.sv
@@ -48,6 +48,7 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
   output dcache_req_o_t   [2:0]          dcache_req_ports_o,     // to/from LSU
   // writebuffer status
   output logic                           wbuffer_empty_o,
+  output logic                           wbuffer_not_ni_o,
 `ifdef PITON_ARIANE
   // L15 (memory side)
   output l15_req_t                       l15_req_o,
@@ -108,6 +109,7 @@ module wt_cache_subsystem import ariane_pkg::*; import wt_cache_pkg::*; #(
     .flush_ack_o     ( dcache_flush_ack_o      ),
     .miss_o          ( dcache_miss_o           ),
     .wbuffer_empty_o ( wbuffer_empty_o         ),
+    .wbuffer_not_ni_o ( wbuffer_not_ni_o       ),
     .amo_req_i       ( dcache_amo_req_i        ),
     .amo_resp_o      ( dcache_amo_resp_o       ),
     .req_ports_i     ( dcache_req_ports_i      ),
diff --git a/src/cache_subsystem/wt_dcache.sv b/src/cache_subsystem/wt_dcache.sv
index ed160292447a4445ccf23e54b9ce1345bbee25a0..28e1d4a194a6e053f586a8081af6c269c2a0d0f8 100644
--- a/src/cache_subsystem/wt_dcache.sv
+++ b/src/cache_subsystem/wt_dcache.sv
@@ -29,6 +29,7 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
   output logic                           flush_ack_o, // send a single cycle acknowledge signal when the cache is flushed
   output logic                           miss_o,      // we missed on a ld/st
   output logic                           wbuffer_empty_o,
+  output logic                           wbuffer_not_ni_o,
 
   // AMO interface
   input  amo_req_t                       amo_req_i,
@@ -214,6 +215,7 @@ module wt_dcache import ariane_pkg::*; import wt_cache_pkg::*; #(
     .clk_i           ( clk_i               ),
     .rst_ni          ( rst_ni              ),
     .empty_o         ( wbuffer_empty_o     ),
+    .not_ni_o        ( wbuffer_not_ni_o    ),
     // TODO: fix this
     .cache_en_i      ( cache_en            ),
     // .cache_en_i      ( '0                  ),
diff --git a/src/cache_subsystem/wt_dcache_ctrl.sv b/src/cache_subsystem/wt_dcache_ctrl.sv
index 55945942be9ab323f3b321d28fb00b30218bdd75..225487039b11d7a54fe4113b460a6580303efb6b 100644
--- a/src/cache_subsystem/wt_dcache_ctrl.sv
+++ b/src/cache_subsystem/wt_dcache_ctrl.sv
@@ -112,6 +112,7 @@ module wt_dcache_ctrl import ariane_pkg::*; import wt_cache_pkg::*; #(
         IDLE: begin
           if (req_port_i.data_req) begin
             rd_req_o = 1'b1;
+            // if read ack then ack the `req_port_o`, and goto `READ` state
             if (rd_ack_i) begin
               state_d = READ;
               req_port_o.data_gnt = 1'b1;
diff --git a/src/cache_subsystem/wt_dcache_missunit.sv b/src/cache_subsystem/wt_dcache_missunit.sv
index 10dca1231c6d86eb557fe6a2852789d3a69c23e3..ae1f7a1e9b8389749ba878878a18826cda210106 100644
--- a/src/cache_subsystem/wt_dcache_missunit.sv
+++ b/src/cache_subsystem/wt_dcache_missunit.sv
@@ -184,7 +184,7 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
   end
 
   // read/write collision, stalls the corresponding request
-  // write collides with MSHR
+  // write port[NumPorts-1] collides with MSHR_Q
   assign mshr_rdwr_collision = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;
 
   // read collides with inflight TX
@@ -341,7 +341,7 @@ module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
   assign wr_cl_data_o    = mem_rtrn_i.data;
   assign wr_cl_data_be_o = (cl_write_en) ? '1 : '0;// we only write complete cachelines into the memory
 
-  // only NC responses write to the cache
+  // only non-NC responses write to the cache
   assign cl_write_en     = load_ack & ~mshr_q.nc;
 
 ///////////////////////////////////////////////////////
diff --git a/src/cache_subsystem/wt_dcache_wbuffer.sv b/src/cache_subsystem/wt_dcache_wbuffer.sv
index c5a82bf014d49049373bce9c8a82115c14d74fdd..e87d8d85d227110f5874b7737591a6e7b1ef1351 100644
--- a/src/cache_subsystem/wt_dcache_wbuffer.sv
+++ b/src/cache_subsystem/wt_dcache_wbuffer.sv
@@ -57,6 +57,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
 
   input  logic                               cache_en_i,     // writes are treated as NC if disabled
   output logic                               empty_o,        // asserted if no data is present in write buffer
+  output logic                               not_ni_o,    // asserted if no ni data is present in write buffer
    // core request ports
   input  dcache_req_i_t                      req_port_i,
   output dcache_req_o_t                      req_port_o,
@@ -118,7 +119,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
   logic check_en_d, check_en_q, check_en_q1;
   logic full, dirty_rd_en, rdy;
   logic rtrn_empty, evict;
-  logic nc_pending_d, nc_pending_q, addr_is_nc;
+  logic [DCACHE_WBUF_DEPTH-1:0] ni_pending_d, ni_pending_q;
   logic wbuffer_wren;
   logic free_tx_slots;
 
@@ -132,11 +133,14 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
 ///////////////////////////////////////////////////////
 // misc
 ///////////////////////////////////////////////////////
-
-  assign miss_nc_o = nc_pending_q;
-
-  // noncacheable if request goes to I/O space, or if cache is disabled
-  assign addr_is_nc = (~cache_en_i) | (~ariane_pkg::is_inside_cacheable_regions(ArianeCfg, {{64-DCACHE_TAG_WIDTH{1'b0}}, req_port_i.address_tag, {DCACHE_INDEX_WIDTH{1'b0}}}));
+  logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] miss_tag;
+  logic is_nc_miss;
+  logic is_ni;
+  assign miss_tag = miss_paddr_o[ariane_pkg::DCACHE_INDEX_WIDTH+:ariane_pkg::DCACHE_TAG_WIDTH];
+  assign is_nc_miss = !ariane_pkg::is_inside_cacheable_regions(ArianeCfg, {{64-DCACHE_TAG_WIDTH{1'b0}}, miss_tag, {DCACHE_INDEX_WIDTH{1'b0}}});
+  assign miss_nc_o = !cache_en_i || is_nc_miss; 
+  // Non-idempotent if request goes to NI region
+  assign is_ni = ariane_pkg::is_inside_nonidempotent_regions(ArianeCfg, {{64-DCACHE_TAG_WIDTH{1'b0}}, req_port_i.address_tag, {DCACHE_INDEX_WIDTH{1'b0}}});
 
   assign miss_we_o       = 1'b1;
   assign miss_vld_bits_o = '0;
@@ -322,7 +326,6 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
   end
 
   assign wr_ptr     = (|wbuffer_hit_oh) ? hit_ptr : next_ptr;
-  assign empty_o    = ~(|valid);
   assign rdy        = (|wbuffer_hit_oh) | (~full);
 
   // next free entry in the buffer
@@ -388,11 +391,17 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
   assign req_port_o.data_rdata  = '0;
 
   assign rd_hit_oh_d = rd_hit_oh_i;
+ 
+  logic ni_inside,ni_conflict; 
+  assign ni_inside = |ni_pending_q;
+  assign ni_conflict = is_ni && ni_inside;
+  assign not_ni_o = !ni_inside;
+  assign empty_o    = !(|valid);
 
   // TODO: rewrite and separate into MUXES and write strobe logic
   always_comb begin : p_buffer
     wbuffer_d           = wbuffer_q;
-    nc_pending_d        = nc_pending_q;
+    ni_pending_d        = ni_pending_q;
     dirty_rd_en         = 1'b0;
     req_port_o.data_gnt = 1'b0;
     wbuffer_wren        = 1'b0;
@@ -431,6 +440,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
       // if all bytes are evicted, clear the cache status flag
       if (wbuffer_d[rtrn_ptr].valid == 0) begin
         wbuffer_d[rtrn_ptr].checked = 1'b0;
+        ni_pending_d[rtrn_ptr] = 1'b0;
       end
     end
 
@@ -447,13 +457,13 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
 
     // write new word into the buffer
     if (req_port_i.data_req && rdy) begin
-      // in case we have an NC address, need to drain the buffer first
-      // in case we are serving an NC address,  we block until it is written to memory
-      if (empty_o || !(addr_is_nc || nc_pending_q)) begin
+      // in case we have an NI address, need to drain the buffer first
+      // in case we are serving an NI address,  we block until it is written to memory
+      if (!ni_conflict) begin //empty of NI operations
         wbuffer_wren              = 1'b1;
 
         req_port_o.data_gnt       = 1'b1;
-        nc_pending_d              = addr_is_nc;
+        ni_pending_d[wr_ptr]      = is_ni;
 
         wbuffer_d[wr_ptr].checked = 1'b0;
         wbuffer_d[wr_ptr].wtag    = {req_port_i.address_tag, req_port_i.address_index[DCACHE_INDEX_WIDTH-1:3]};
@@ -479,7 +489,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
     if (!rst_ni) begin
       wbuffer_q     <= '{default: '0};
       tx_stat_q     <= '{default: '0};
-      nc_pending_q  <= '0;
+      ni_pending_q  <= '0;
       check_ptr_q   <= '0;
       check_ptr_q1  <= '0;
       check_en_q    <= '0;
@@ -491,7 +501,7 @@ module wt_dcache_wbuffer import ariane_pkg::*; import wt_cache_pkg::*; #(
     end else begin
       wbuffer_q     <= wbuffer_d;
       tx_stat_q     <= tx_stat_d;
-      nc_pending_q  <= nc_pending_d;
+      ni_pending_q  <= ni_pending_d;
       check_ptr_q   <= check_ptr_d;
       check_ptr_q1  <= check_ptr_q;
       check_en_q    <= check_en_d;
diff --git a/src/ex_stage.sv b/src/ex_stage.sv
index f3a401c4017158d8031ca18fd1ab7f2521a70fb0..4806002f33c2351f04c8dd25598033f8d67006de 100644
--- a/src/ex_stage.sv
+++ b/src/ex_stage.sv
@@ -94,6 +94,7 @@ module ex_stage import ariane_pkg::*; #(
     input  dcache_req_o_t [2:0]                    dcache_req_ports_i,
     output dcache_req_i_t [2:0]                    dcache_req_ports_o,
     input  logic                                   dcache_wbuffer_empty_i,
+    input  logic                                   dcache_wbuffer_not_ni_i,
     output amo_req_t                               amo_req_o,          // request to cache subsytem
     input  amo_resp_t                              amo_resp_i,         // response from cache subsystem
     // Performance counters
@@ -297,6 +298,7 @@ module ex_stage import ariane_pkg::*; #(
         .dcache_req_ports_i,
         .dcache_req_ports_o,
         .dcache_wbuffer_empty_i,
+        .dcache_wbuffer_not_ni_i,
         .amo_valid_commit_i,
         .amo_req_o,
         .amo_resp_i,
diff --git a/src/load_store_unit.sv b/src/load_store_unit.sv
index d9edec96e8627f7509c368c793da2e485f31bb19..fe4e3003ac18556201080d92475870515227ac3f 100644
--- a/src/load_store_unit.sv
+++ b/src/load_store_unit.sv
@@ -63,6 +63,7 @@ module load_store_unit import ariane_pkg::*; #(
     input  dcache_req_o_t [2:0]      dcache_req_ports_i,
     output dcache_req_i_t [2:0]      dcache_req_ports_o,
     input  logic                     dcache_wbuffer_empty_i,
+    input  logic                     dcache_wbuffer_not_ni_i,
     // AMO interface
     output amo_req_t                 amo_req_o,
     input  amo_resp_t                amo_resp_i,
@@ -108,6 +109,7 @@ module load_store_unit import ariane_pkg::*; #(
     logic [riscv::PLEN-1:0]   mmu_paddr;
     exception_t               mmu_exception;
     logic                     dtlb_hit;
+    logic [riscv::PLEN-13:0]  dtlb_ppn;
 
     logic                     ld_valid;
     logic [TRANS_ID_BITS-1:0] ld_trans_id;
@@ -141,6 +143,7 @@ module load_store_unit import ariane_pkg::*; #(
         .lsu_paddr_o            ( mmu_paddr              ),
         .lsu_exception_o        ( mmu_exception          ),
         .lsu_dtlb_hit_o         ( dtlb_hit               ), // send in the same cycle as the request
+        .lsu_dtlb_ppn_o         ( dtlb_ppn               ), // send in the same cycle as the request
         // connecting PTW to D$ IF
         .req_port_i             ( dcache_req_ports_i [0] ),
         .req_port_o             ( dcache_req_ports_o [0] ),
@@ -210,6 +213,7 @@ module load_store_unit import ariane_pkg::*; #(
         .paddr_i               ( mmu_paddr            ),
         .ex_i                  ( mmu_exception        ),
         .dtlb_hit_i            ( dtlb_hit             ),
+        .dtlb_ppn_i            ( dtlb_ppn             ),
         // to store unit
         .page_offset_o         ( page_offset          ),
         .page_offset_matches_i ( page_offset_matches  ),
@@ -217,7 +221,7 @@ module load_store_unit import ariane_pkg::*; #(
         // to memory arbiter
         .req_port_i            ( dcache_req_ports_i [1] ),
         .req_port_o            ( dcache_req_ports_o [1] ),
-        .dcache_wbuffer_empty_i,
+        .dcache_wbuffer_not_ni_i,
         .commit_tran_id_i,
         .*
     );
diff --git a/src/load_unit.sv b/src/load_unit.sv
index ee1493d3745e1d0c9f83a0a2e7de89160c3426db..84e9b10cfdd4b5c7ca4c21b71eb4b4f3657e4d4c 100644
--- a/src/load_unit.sv
+++ b/src/load_unit.sv
@@ -34,6 +34,7 @@ module load_unit import ariane_pkg::*; #(
     input  logic [riscv::PLEN-1:0]   paddr_i,             // physical address in
     input  exception_t               ex_i,                // exception which may has happened earlier. for example: mis-aligned exception
     input  logic                     dtlb_hit_i,          // hit on the dtlb, send in the same cycle as the request
+    input  logic [riscv::PLEN-13:0]  dtlb_ppn_i,          // ppn on the dtlb, send in the same cycle as the request
     // address checker
     output logic [11:0]              page_offset_o,
     input  logic                     page_offset_matches_i,
@@ -42,10 +43,10 @@ module load_unit import ariane_pkg::*; #(
     // D$ interface
     input dcache_req_o_t             req_port_i,
     output dcache_req_i_t            req_port_o,
-    input  logic                     dcache_wbuffer_empty_i
+    input  logic                     dcache_wbuffer_not_ni_i
 );
     enum logic [3:0] { IDLE, WAIT_GNT, SEND_TAG, WAIT_PAGE_OFFSET,
-                       ABORT_TRANSACTION, ABORT_TRANSACTION_NC, WAIT_TRANSLATION, WAIT_FLUSH,
+                       ABORT_TRANSACTION, ABORT_TRANSACTION_NI, WAIT_TRANSLATION, WAIT_FLUSH,
                        WAIT_WB_EMPTY
                      } state_d, state_q;
     // in order to decouple the response interface from the request interface we need a
@@ -75,13 +76,15 @@ module load_unit import ariane_pkg::*; #(
     // directly output an exception
     assign ex_o = ex_i;
 
-    logic stall_nc;  // stall because of non-empty WB and address within non-cacheable region.
-    // should we stall the request e.g.: is it withing a non-cacheable region
-    // and the write buffer (in the cache and in the core) is not empty so that we don't forward anything
-    // from the write buffer (e.g. it would essentially be cached).
-    assign stall_nc = (~(dcache_wbuffer_empty_i | store_buffer_empty_i) & is_inside_cacheable_regions(ArianeCfg, paddr_i))
-                    // this guards the load to be executed non-speculatively (we wait until our transaction id is on port 0
-                    | (commit_tran_id_i != lsu_ctrl_i.trans_id & is_inside_nonidempotent_regions(ArianeCfg, paddr_i));
+    // Check that NI operations follow the necessary conditions
+    logic paddr_ni;
+    logic not_commit_time;
+    logic inflight_stores;
+    logic stall_ni;
+    assign paddr_ni = is_inside_nonidempotent_regions(ArianeCfg, {dtlb_ppn_i,12'd0});
+    assign not_commit_time = commit_tran_id_i != lsu_ctrl_i.trans_id;
+    assign inflight_stores = (!dcache_wbuffer_not_ni_i || !store_buffer_empty_i);
+    assign stall_ni = (inflight_stores || not_commit_time) && paddr_ni;
 
     // ---------------
     // Load Control
@@ -114,14 +117,14 @@ module load_unit import ariane_pkg::*; #(
                         if (!req_port_i.data_gnt) begin
                             state_d = WAIT_GNT;
                         end else begin
-                            if (dtlb_hit_i && !stall_nc) begin
+                            if (dtlb_hit_i && !stall_ni) begin
                                 // we got a grant and a hit on the DTLB so we can send the tag in the next cycle
                                 state_d = SEND_TAG;
                                 pop_ld_o = 1'b1;
                             // translation valid but this is to NC and the WB is not yet empty.
-                            end else if (dtlb_hit_i && stall_nc) begin
-                                state_d = ABORT_TRANSACTION_NC;
-                            end else begin
+                            end else if (dtlb_hit_i && stall_ni) begin
+                                state_d = ABORT_TRANSACTION_NI;
+                            end else begin // TLB miss
                                 state_d = ABORT_TRANSACTION;
                             end
                         end
@@ -143,17 +146,17 @@ module load_unit import ariane_pkg::*; #(
             // abort the previous request - free the D$ arbiter
             // we are here because of a TLB miss, we need to abort the current request and give way for the
             // PTW walker to satisfy the TLB miss
-            ABORT_TRANSACTION, ABORT_TRANSACTION_NC: begin
+            ABORT_TRANSACTION, ABORT_TRANSACTION_NI: begin
                 req_port_o.kill_req  = 1'b1;
                 req_port_o.tag_valid = 1'b1;
                 // either re-do the request or wait until the WB is empty (depending on where we came from).
-                state_d = (state_q == ABORT_TRANSACTION_NC) ? WAIT_WB_EMPTY :  WAIT_TRANSLATION;
+                state_d = (state_q == ABORT_TRANSACTION_NI) ? WAIT_WB_EMPTY :  WAIT_TRANSLATION;
             end
 
             // Wait until the write-back buffer is empty in the data cache.
             WAIT_WB_EMPTY: begin
                 // the write buffer is empty, so lets go and re-do the translation.
-                if (dcache_wbuffer_empty_i) state_d = WAIT_TRANSLATION;
+                if (dcache_wbuffer_not_ni_i) state_d = WAIT_TRANSLATION;
             end
 
             WAIT_TRANSLATION: begin
@@ -171,12 +174,12 @@ module load_unit import ariane_pkg::*; #(
                 // we finally got a data grant
                 if (req_port_i.data_gnt) begin
                     // so we send the tag in the next cycle
-                    if (dtlb_hit_i && !stall_nc) begin
+                    if (dtlb_hit_i && !stall_ni) begin
                         state_d = SEND_TAG;
                         pop_ld_o = 1'b1;
                     // translation valid but this is to NC and the WB is not yet empty.
-                    end else if (dtlb_hit_i && stall_nc) begin
-                        state_d = ABORT_TRANSACTION_NC;
+                    end else if (dtlb_hit_i && stall_ni) begin
+                        state_d = ABORT_TRANSACTION_NI;
                     end else begin
                     // should we not have hit on the TLB abort this transaction an retry later
                         state_d = ABORT_TRANSACTION;
@@ -202,13 +205,13 @@ module load_unit import ariane_pkg::*; #(
                             state_d = WAIT_GNT;
                         end else begin
                             // we got a grant so we can send the tag in the next cycle
-                            if (dtlb_hit_i && !stall_nc) begin
+                            if (dtlb_hit_i && !stall_ni) begin
                                 // we got a grant and a hit on the DTLB so we can send the tag in the next cycle
                                 state_d = SEND_TAG;
                                 pop_ld_o = 1'b1;
                             // translation valid but this is to NC and the WB is not yet empty.
-                            end else if (dtlb_hit_i && stall_nc) begin
-                                state_d = ABORT_TRANSACTION_NC;
+                            end else if (dtlb_hit_i && stall_ni) begin
+                                state_d = ABORT_TRANSACTION_NI;
                             end else begin
                                 state_d = ABORT_TRANSACTION;// we missed on the TLB -> wait for the translation
                             end
diff --git a/src/mmu.sv b/src/mmu.sv
index 6890c9a747ec2f404f476bd66aa12053aced4e50..768425ad57317641ef288cde1b2e60c38321166c 100644
--- a/src/mmu.sv
+++ b/src/mmu.sv
@@ -39,6 +39,7 @@ module mmu import ariane_pkg::*; #(
     // if we need to walk the page table we can't grant in the same cycle
     // Cycle 0
     output logic                            lsu_dtlb_hit_o,   // sent in the same cycle as the request if translation hits in the DTLB
+    output logic [riscv::PLEN-13:0]         lsu_dtlb_ppn_o,   // ppn (send same cycle as hit)
     // Cycle 1
     output logic                            lsu_valid_o,      // translation is valid
     output logic [riscv::PLEN-1:0]          lsu_paddr_o,      // translated address
@@ -308,6 +309,7 @@ module mmu import ariane_pkg::*; #(
         dtlb_is_1G_n          = dtlb_is_1G;
 
         lsu_paddr_o           = lsu_vaddr_q[riscv::PLEN-1:0];
+        lsu_dtlb_ppn_o        = lsu_vaddr_n[riscv::PLEN-1:12];
         lsu_valid_o           = lsu_req_q;
         lsu_exception_o       = misaligned_ex_q;
         pmp_access_type       = lsu_is_store_q ? riscv::ACCESS_WRITE : riscv::ACCESS_READ;
@@ -324,13 +326,16 @@ module mmu import ariane_pkg::*; #(
             lsu_valid_o = 1'b0;
             // 4K page
             lsu_paddr_o = {dtlb_pte_q.ppn, lsu_vaddr_q[11:0]};
+            lsu_dtlb_ppn_o = dtlb_content.ppn;
             // Mega page
             if (dtlb_is_2M_q) begin
               lsu_paddr_o[20:12] = lsu_vaddr_q[20:12];
+              lsu_dtlb_ppn_o[20:12] = lsu_vaddr_n[20:12];
             end
             // Giga page
             if (dtlb_is_1G_q) begin
                 lsu_paddr_o[29:12] = lsu_vaddr_q[29:12];
+                lsu_dtlb_ppn_o[29:12] = lsu_vaddr_n[29:12];
             end
             // ---------
             // DTLB Hit