diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index a751529985597ccd3bcfd9f073b2a01d99a2f537..e02a23fd7b42d18f65556a918c8017de96adceae 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -350,6 +350,14 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
     AssertFatal(RC.nrmac[Mod_idP]->common_channels[0].vrb_map_UL,
                 "could not allocate memory for RC.nrmac[]->common_channels[0].vrb_map_UL\n");
 
+    for (int i = 0; i < MAX_NUM_BWP; ++i) {
+      RC.nrmac[Mod_idP]->pucch_index_used[i] =
+        calloc(n, sizeof(*RC.nrmac[Mod_idP]->pucch_index_used));
+      AssertFatal(RC.nrmac[Mod_idP]->pucch_index_used[i],
+                  "could not allocate memory for RC.nrmac[]->pucch_index_used[%d]\n",
+                  i);
+    }
+
     LOG_I(MAC,"Configuring common parameters from NR ServingCellConfig\n");
 
     config_common(Mod_idP,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index de0bbb3889991fb53c8a261e7babd262aae61877..01fa854b953c71aae6d1a50e2d1eaea4bf38a491 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -456,12 +456,15 @@ bool nr_acknack_scheduling(int mod_id,
   curr_pucch->frame = frame;
   curr_pucch->dai_c++;
 
+  int *pucch_index_used = RC.nrmac[mod_id]->pucch_index_used[sched_ctrl->active_ubwp->bwp_Id];
   if (curr_pucch->dai_c == 1) {
     /* FIXME for first allocation: find free resource, here assume first PUCCH
      * resource and first_ul_slot_tdd */
     const int pucch_res = 0;
     curr_pucch->resource_indicator = pucch_res;
     curr_pucch->ul_slot = first_ul_slot_tdd;
+    DevAssert(pucch_index_used[first_ul_slot_tdd] == 0);
+    pucch_index_used[first_ul_slot_tdd] += 1;
 
     /* verify that at that slot and symbol, resources are free.
      * Note: this does not handle potential mux of PUCCH in the same symbol! */
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index 44577a5298ffb85dac81cf0612a6511bb0f6dde9..e2df6faa6b831dff0258d70548b7731acbbc4393 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -549,6 +549,10 @@ typedef struct gNB_MAC_INST_s {
   time_stats_t schedule_pch;
   /// CCE lists
   int cce_list[MAX_NUM_BWP][MAX_NUM_CORESET][MAX_NUM_CCE];
+  /// PUCCH: keep track of the resources has already been used by saving the
+  /// highest index not yet been used in a given slot. Dynamically allocated
+  /// so we can have it for every slot as a function of the numerology
+  int *pucch_index_used[MAX_NUM_BWP];
 
   /// DL preprocessor for differentiated scheduling
   nr_pp_impl_dl pre_processor_dl;
diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
index 7f98dd6a3ebf113050d8a557f8ce76c4a17486ee..b5cda6ecd63e2d19f8af88f85c86b466391b59b0 100644
--- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c
@@ -104,6 +104,9 @@ void handle_nr_uci(NR_UL_IND_t *UL_info)
   }
 
   UL_info->uci_ind.num_ucis = 0;
+  // mark corresponding PUCCH resources as free
+  // NOTE: we just assume it is BWP ID 1, to be revised for multiple BWPs
+  RC.nrmac[mod_id]->pucch_index_used[1][slot] = 0;
 }