diff --git a/src/ariane.sv b/src/ariane.sv
index a932a042ca911408047f81aac477d1b99d94a6e0..b1a75757d1b8d4bb941de06978d04bda0787b5d2 100644
--- a/src/ariane.sv
+++ b/src/ariane.sv
@@ -80,6 +80,7 @@ module ariane import ariane_pkg::*; #(
   // IF -> verifier
   // --------------
   logic                     has_mem_access_if_verif;
+  logic                     has_ctrl_flow_if_icache;
   logic                     bsp_if_perf;
 
   // --------------
@@ -280,6 +281,7 @@ module ariane import ariane_pkg::*; #(
     .fetch_entry_valid_o ( fetch_valid_if_id             ),
     .fetch_entry_ready_i ( fetch_ready_id_if             ),
     .has_mem_access_o    ( has_mem_access_if_verif       ),
+    .has_cf_o            ( has_ctrl_flow_if_icache       ),
     .branch_speculation_o( bsp_if_perf                   ),
     .*
   );
diff --git a/src/frontend/frontend.sv b/src/frontend/frontend.sv
index 991db6561e8205fbc641e80476b390c316ebeb6f..75226d9345152a067895f1e8cbc0ca7eb374308b 100644
--- a/src/frontend/frontend.sv
+++ b/src/frontend/frontend.sv
@@ -46,7 +46,8 @@ module frontend import ariane_pkg::*; #(
   input  logic               fetch_entry_ready_i, // ID acknowledged this instruction
 
   output logic               has_mem_access_o,
-  output logic               branch_speculation_o
+  output logic               branch_speculation_o,
+  output logic               has_cf_o
 );
     // Instruction Cache Registers, from I$
     logic [FETCH_WIDTH-1:0] icache_data_q;
@@ -434,7 +435,8 @@ module frontend import ariane_pkg::*; #(
       .fetch_entry_o       ( fetch_entry_o        ), // to back-end
       .fetch_entry_valid_o ( fetch_entry_valid_o  ), // to back-end
       .fetch_entry_ready_i ( fetch_entry_ready_i  ), // to back-end
-      .has_mem_access_o    ( has_mem_access_o     )  // to verifier
+      .has_mem_access_o    ( has_mem_access_o     ), // to verifier
+      .has_cf_o            ( has_cf_o             )  // to I$
     );
 
     // pragma translate_off
diff --git a/src/frontend/instr_queue.sv b/src/frontend/instr_queue.sv
index 15f3269db11af574f1296eecdccb19eab4892fdd..a31b096b995398fe8ee42f00933db9592f0581cc 100644
--- a/src/frontend/instr_queue.sv
+++ b/src/frontend/instr_queue.sv
@@ -66,7 +66,8 @@ module instr_queue (
   output logic                                               fetch_entry_valid_o,
   input  logic                                               fetch_entry_ready_i,
 
-  output logic has_mem_access_o
+  output logic has_mem_access_o,
+  output logic has_cf_o
 );
 
   typedef struct packed {
@@ -125,6 +126,11 @@ module instr_queue (
   logic [ariane_pkg::INSTR_PER_FETCH-1:0]   fifo_output_is_mem, fifo_has_no_mem;
   logic                                     output_is_mem;
 
+  // cf count
+  logic [ariane_pkg::INSTR_PER_FETCH-1:0]  input_is_cf;
+  logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_has_no_cf;
+  logic                                   output_is_cf;
+
   assign ready_o = ~(|instr_queue_full) & ~full_address;
 
   for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_unpack_taken
@@ -199,6 +205,15 @@ module instr_queue (
   assign has_mem_access_o = (|input_is_mem[ariane_pkg::INSTR_PER_FETCH-1:0]) | output_is_mem |
                             ~(&fifo_has_no_mem);
 
+  // ----------------------
+  // Memory access detector
+  // ----------------------
+  assign output_is_cf = fetch_entry_valid_o &
+                        (fetch_entry_o.instruction[6:0] inside {riscv::OpcodeJalr, riscv::OpcodeBranch});
+
+  assign has_cf_o = (|input_is_cf) | output_is_cf |
+                    ~(&fifo_has_no_cf);
+
   // duplicate the entries for easier selection e.g.: 3 2 1 0 3 2 1 0
   for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input
     assign instr[i] = instr_i[i];
@@ -215,6 +230,7 @@ module instr_queue (
     assign instr_data_in[i].ex = exception_i; // exceptions hold for the whole fetch packet
     assign instr_data_in[i].ex_vaddr = exception_addr_i;
     assign input_is_mem_in[i] = input_is_mem[i + idx_is_q];
+    assign input_is_cf[i] = !(cf[i + idx_is_q] inside {ariane_pkg::NoCF, ariane_pkg::Jump});
     /* verilator lint_on WIDTH */
   end
 
@@ -330,6 +346,8 @@ module instr_queue (
                                     (instr_data_out[i].instr[6:0] == riscv::OpcodeStoreFp) |
                                     (instr_data_out[i].instr[6:0] == riscv::OpcodeAmo));
 
+    assign fifo_output_is_cf[i] = !(instr_data_out[i].cf inside {ariane_pkg::NoCF, ariane_pkg::Jump});
+
     fifo_v3 #(
       .DEPTH ( ariane_pkg::FETCH_FIFO_DEPTH ),
       .dtype (logic)
@@ -346,6 +364,23 @@ module instr_queue (
       .data_o (),
       .pop_i (pop_instr[i] & fifo_output_is_mem[i])
     );
+
+    fifo_v3 #(
+      .DEPTH (ariane_pkg::FETCH_FIFO_DEPTH),
+      .dtype (logic)
+    ) i_fifo_cf (
+      .clk_i (clk_i),
+      .rst_ni (rst_ni),
+      .flush_i (flush_i),
+      .testmode_i (1'b0),
+      .full_o (),
+      .empty_o (fifo_has_no_cf[i]),
+      .usage_o (),
+      .data_i (1'b1),
+      .push_i (push_instr_fifo[i] & !(instr_data_in[i].cf inside {ariane_pkg::NoCF, ariane_pkg::Jump})),
+      .data_o (),
+      .pop_i (pop_instr[i] & fifo_output_is_cf[i])
+    );
   end
   // or reduce and check whether we are retiring a taken branch (might be that the corresponding)
   // fifo is full.