diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 2c098fd6b16ee3b8a2b742b07a201aa117702bd8..3e62a8d7a085f900f0fa55285d044f21c14b9156 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -2792,6 +2792,7 @@ add_executable(nr-softmodem
   ${s1ap_h}
 #  ${OPENAIR_BIN_DIR}/messages_xml.h
   ${OPENAIR_DIR}/executables/nr-gnb.c
+  ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c
   ${OPENAIR_DIR}/executables/nr-ru.c
   ${OPENAIR_DIR}/executables/nr-softmodem.c
   ${OPENAIR_DIR}/executables/softmodem-common.c
@@ -3047,6 +3048,7 @@ target_link_libraries(nr_prachsim
 
 add_executable(nr_ulschsim
   ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulschsim.c
+  ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c
   ${OPENAIR_DIR}/common/utils/utils.c
   ${OPENAIR_DIR}/common/utils/system.c
   ${OPENAIR_DIR}/common/utils/nr/nr_common.c
@@ -3061,6 +3063,7 @@ target_link_libraries(nr_ulschsim
 
 add_executable(nr_ulsim
   ${OPENAIR1_DIR}/SIMULATION/NR_PHY/ulsim.c
+  ${OPENAIR_DIR}/common/utils/threadPool/thread-pool.c
   ${OPENAIR_DIR}/common/utils/utils.c
   ${OPENAIR_DIR}/common/utils/system.c
   ${OPENAIR_DIR}/common/utils/nr/nr_common.c
diff --git a/cmake_targets/phy_simulators/CMakeLists.txt b/cmake_targets/phy_simulators/CMakeLists.txt
index 5f2d34883eea95e1905f177a53e44f82635ee7d3..cf68ca4a9db0b25fc6cb85aca67c005a2d76b409 100644
--- a/cmake_targets/phy_simulators/CMakeLists.txt
+++ b/cmake_targets/phy_simulators/CMakeLists.txt
@@ -1,11 +1,12 @@
 cmake_minimum_required(VERSION 2.8)
+project (OpenAirInterface)
 set ( CMAKE_BUILD_TYPE  )
 set ( CFLAGS_PROCESSOR_USER "" )
 set ( UE_EXPANSION False )
 set ( PRE_SCD_THREAD False )
 set ( UESIM_EXPANSION False )
 set ( ENABLE_VCD_FIFO False )
-set ( RF_BOARD "OAI_USRP")
+set ( RF_BOARD "None")
 set ( TRANSP_PRO "None")
 set ( PACKAGE_NAME "")
 set ( DEADLINE_SCHEDULER "False" )
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 27b0ed08ddbde4c335b8d670aaa98ec95f89f031..ad6e016fd44be75ea334cd1138a24a280db66a2a 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -545,6 +545,8 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
   int i;
   struct timespec abstime;
   int time_ns = 50000;
+  int wait_timer = 0;
+  bool do_last_check = 1;
   
   AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
   for (i=0; i<gNB->num_RU; i++) {
@@ -565,22 +567,36 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
     AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
   }
 
-  clock_gettime(CLOCK_REALTIME, &abstime);
-  abstime.tv_nsec = abstime.tv_nsec + time_ns;
-
-  if (abstime.tv_nsec >= 1000*1000*1000) {
-    abstime.tv_nsec -= 1000*1000*1000;
-    abstime.tv_sec  += 1;
-  }
-
   // wake up TX for subframe n+sf_ahead
   // lock the TX mutex and make sure the thread is ready
-  AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
+  while (wait_timer < 200) {
+    clock_gettime(CLOCK_REALTIME, &abstime);
+    abstime.tv_nsec = abstime.tv_nsec + time_ns;
 
-  if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
-    AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
-    LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
-    return(-1);
+    if (abstime.tv_nsec >= 1000*1000*1000) {
+      abstime.tv_nsec -= 1000*1000*1000;
+      abstime.tv_sec  += 1;
+    }
+
+    AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
+
+    if (L1_proc->instance_cnt == 0) { // L1_thread is busy so wait for a bit
+      AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
+      wait_timer += 50;
+      usleep(50);
+    }
+    else {
+      do_last_check = 0;
+      break;
+    }
+  }
+  if (do_last_check) {
+    AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
+    if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
+      AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
+      LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx);
+      return (-1);
+    }
   }
 
   ++L1_proc->instance_cnt;
@@ -793,6 +809,12 @@ void init_gNB_proc(int inst) {
   pthread_mutex_init(&sync_phy_proc.mutex_phy_proc_tx, NULL);
   pthread_cond_init(&sync_phy_proc.cond_phy_proc_tx, NULL);
   sync_phy_proc.phy_proc_CC_id = 0;
+
+  gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
+  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  char ul_pool[] = "-1,-1";
+  initTpool(ul_pool, gNB->threadPool, false);
+  initNotifiedFIFO(gNB->respDecode);
 }
 
 
diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h
index 328aeda769d48c72d3022c5d74b1fcd053104dd7..8fe31f208ea4c76db380866faa87aa2d0277add2 100644
--- a/openair1/PHY/CODING/coding_defs.h
+++ b/openair1/PHY/CODING/coding_defs.h
@@ -483,8 +483,7 @@ uint32_t nr_compute_tbs(uint16_t Qm,
 
 uint32_t nr_compute_tbslbrm(uint16_t table,
 			    uint16_t nb_rb,
-		            uint8_t Nl,
-                            uint8_t C);
+		            uint8_t Nl);
 
 void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f);
 
diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c
index a16a8d100f4e912ecfe972f2cbe7548265e8df0c..efa5abdc90004cae6cd8eab61ab899f43c5347aa 100644
--- a/openair1/PHY/CODING/nr_rate_matching.c
+++ b/openair1/PHY/CODING/nr_rate_matching.c
@@ -425,7 +425,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
     }
   }
   else {
-    if (E + F <= Ncb-ind) { //E+F doesn't contain all coded bits
+    if (E <= Ncb-ind) { //E+F doesn't contain all coded bits
       memcpy((void*)(e),(void*)(w+ind),E);
       k=E;
     }
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index e5841d326286b69d263bda5b452da055aa0d469b..a4a684c4e4e8d322614d6a8d5aa155cf54cec7b1 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -527,7 +527,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
     if (rel15->nrOfLayers < Nl)
       Nl = rel15->nrOfLayers;
 
-    Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl,dlsch->harq_processes[harq_pid]->C);
+    Tbslbrm = nr_compute_tbslbrm(rel15->mcsTable[0],nb_rb,Nl);
 
     start_meas(dlsch_rate_matching_stats);
     nr_rate_matching_ldpc(Ilbrm,
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
index a9845b6bbb44557e5b93f54203a2eaa9bc36de17..de9b5f48c3bd7d62ad86b9ecff770d19a05b6f79 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
@@ -31,6 +31,7 @@
 */
 
 #include "PHY/defs_gNB.h"
+#include "common/utils/threadPool/thread-pool.h"
 
 void free_gNB_ulsch(NR_gNB_ULSCH_t **ulsch,uint8_t N_RB_UL);
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 7980206eb4075191d057fdf2181e0920920022e2..42f88d16f4a5e9a3e6ce20ec69e2f2183d7dae97 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -52,9 +52,6 @@
 #define OAI_UL_LDPC_MAX_NUM_LLR 27000//26112 // NR_LDPC_NCOL_BG1*NR_LDPC_ZMAX = 68*384
 //#define PRINT_CRC_CHECK
 
-static uint64_t nb_total_decod =0;
-static uint64_t nb_error_decod =0;
-
 //extern double cpuf;
 
 void free_gNB_ulsch(NR_gNB_ULSCH_t **ulschptr,uint8_t N_RB_UL)
@@ -286,7 +283,177 @@ void clean_gNB_ulsch(NR_gNB_ULSCH_t *ulsch)
   static uint32_t prnt_crc_cnt = 0;
 #endif
 
-uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
+void nr_processULSegment(void* arg) {
+  ldpcDecode_t *rdata = (ldpcDecode_t*) arg;
+  PHY_VARS_gNB *phy_vars_gNB = rdata->gNB;
+  NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
+  t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
+  int length_dec;
+  int no_iteration_ldpc;
+  int Kr;
+  int Kr_bytes;
+  int K_bytes_F;
+  uint8_t crc_type;
+  int i;
+  int j;
+  int r = rdata->segment_r;
+  int A = rdata->A;
+  int E = rdata->E;
+  int Qm = rdata->Qm;
+  int rv_index = rdata->rv_index;
+  int r_offset = rdata->r_offset;
+  uint8_t kc = rdata->Kc;
+  uint32_t Tbslbrm = rdata->Tbslbrm;
+  short* ulsch_llr = rdata->ulsch_llr;
+  int max_ldpc_iterations = p_decoderParms->numMaxIter;
+  int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
+
+  int16_t  z [68*384];
+  int8_t   l [68*384];
+
+  __m128i *pv = (__m128i*)&z;
+  __m128i *pl = (__m128i*)&l;
+  
+  uint8_t  Ilbrm    = 0;
+
+  Kr = ulsch_harq->K;
+  Kr_bytes = Kr>>3;
+
+  K_bytes_F = Kr_bytes-(ulsch_harq->F>>3);
+
+  t_nrLDPC_time_stats procTime;
+  t_nrLDPC_time_stats* p_procTime     = &procTime ;
+
+  //start_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
+
+  ////////////////////////////////////////////////////////////////////////////////////////////
+  ///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
+  //////////////////////////////////////////////////////////////////////////////////////////
+
+  //////////////////////////// ulsch_llr =====> ulsch_harq->e //////////////////////////////
+
+  nr_deinterleaving_ldpc(E,
+                         Qm,
+                         ulsch_harq->e[r],
+                         ulsch_llr+r_offset);
+
+  //for (int i =0; i<16; i++)
+  //          printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,ulsch_harq->w[r][i], r_offset);
+
+  stop_meas(&phy_vars_gNB->ulsch_deinterleaving_stats);
+
+
+  /*LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
+        harq_pid,r, G,
+        Kr*3,
+        ulsch_harq->TBS,
+        Qm,
+        nb_rb,
+        n_layers,
+        pusch_pdu->pusch_data.rv_index,
+        ulsch_harq->round);*/
+  //////////////////////////////////////////////////////////////////////////////////////////
+
+
+  //////////////////////////////////////////////////////////////////////////////////////////
+  //////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
+  //////////////////////////////////////////////////////////////////////////////////////////
+
+  ///////////////////////// ulsch_harq->e =====> ulsch_harq->d /////////////////////////
+
+  //start_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
+
+  if (nr_rate_matching_ldpc_rx(Ilbrm,
+                               Tbslbrm,
+                               p_decoderParms->BG,
+                               p_decoderParms->Z,
+                               ulsch_harq->d[r],
+                               ulsch_harq->e[r],
+                               ulsch_harq->C,
+                               rv_index,
+                               (ulsch_harq->round==0)?1:0,
+                               E,
+       ulsch_harq->F,
+       Kr-ulsch_harq->F-2*(p_decoderParms->Z))==-1) {
+
+    stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
+
+    LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n");
+    rdata->decodeIterations = max_ldpc_iterations + 1;
+    return;
+  } else {
+    stop_meas(&phy_vars_gNB->ulsch_rate_unmatching_stats);
+  }
+
+  memset(ulsch_harq->c[r],0,Kr_bytes);
+
+  if (ulsch_harq->C == 1) {
+    if (A > 3824)
+      crc_type = CRC24_A;
+    else
+      crc_type = CRC16;
+
+    length_dec = ulsch_harq->B;
+  }
+  else {
+    crc_type = CRC24_B;
+    length_dec = (ulsch_harq->B+24*ulsch_harq->C)/ulsch_harq->C;
+  }
+
+  //start_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
+
+  memset(pv,0,2*ulsch_harq->Z*sizeof(int16_t));
+  memset((pv+K_bytes_F),127,ulsch_harq->F*sizeof(int16_t));
+
+  for (i=((2*p_decoderParms->Z)>>3), j = 0; i < K_bytes_F; i++, j++) {
+    pv[i]= _mm_loadu_si128((__m128i*)(&ulsch_harq->d[r][8*j]));
+  }
+
+  AssertFatal(kc!=255,"");
+  j+=(ulsch_harq->F>>3);
+  for (i=Kr_bytes; i < ((kc*p_decoderParms->Z)>>3); i++, j++) {
+    pv[i]= _mm_loadu_si128((__m128i*)(&ulsch_harq->d[r][8*j]));
+  }
+
+  for (i=0, j=0; j < ((kc*p_decoderParms->Z)>>4);  i+=2, j++) {
+    pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
+  }
+
+  //////////////////////////////////////////////////////////////////////////////////////////
+
+
+  //////////////////////////////////////////////////////////////////////////////////////////
+  ///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
+  //////////////////////////////////////////////////////////////////////////////////////////
+
+  ////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
+
+  no_iteration_ldpc = nrLDPC_decoder(p_decoderParms,
+                                     (int8_t*)&pl[0],
+                                     llrProcBuf,
+                                     ulsch_harq->p_nrLDPC_procBuf[r],
+                                     p_procTime);
+
+  if (check_crc((uint8_t*)llrProcBuf,length_dec,ulsch_harq->F,crc_type)) {
+#ifdef PRINT_CRC_CHECK
+      LOG_I(PHY, "Segment %d CRC OK\n",r);
+#endif
+    rdata->decodeIterations = no_iteration_ldpc;
+  } else {
+#ifdef PRINT_CRC_CHECK
+      LOG_I(PHY, "CRC NOK\n");
+#endif
+    rdata->decodeIterations = max_ldpc_iterations + 1;
+  }
+
+  for (int m=0; m < Kr>>3; m ++) {
+    ulsch_harq->c[r][m]= (uint8_t) llrProcBuf[m];
+  }
+
+  //stop_meas(&phy_vars_gNB->ulsch_ldpc_decoding_stats);
+}
+
+uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
                            uint8_t UE_id,
                            short *ulsch_llr,
                            NR_DL_FRAME_PARMS *frame_parms,
@@ -296,36 +463,36 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
                            uint8_t harq_pid,
                            uint32_t G) {
 
-  uint32_t A,E;
-  uint32_t ret, offset;
-  int32_t no_iteration_ldpc, length_dec;
-  uint32_t r,r_offset=0,Kr=8424,Kr_bytes,K_bytes_F,err_flag=0;
-  uint8_t crc_type;
-  int8_t llrProcBuf[OAI_UL_LDPC_MAX_NUM_LLR] __attribute__ ((aligned(32)));
+  uint32_t A;
+  uint32_t r;
+  uint32_t r_offset;
+  uint32_t offset;
+  int kc;
+  int Tbslbrm;
+  int E;
 
 #ifdef PRINT_CRC_CHECK
   prnt_crc_cnt++;
 #endif
   
 
-  NR_gNB_ULSCH_t                       *ulsch                 = gNB->ulsch[UE_id][0];
+  NR_gNB_ULSCH_t                       *ulsch                 = phy_vars_gNB->ulsch[UE_id][0];
   NR_UL_gNB_HARQ_t                     *harq_process          = ulsch->harq_processes[harq_pid];
   
   t_nrLDPC_dec_params decParams;
   t_nrLDPC_dec_params* p_decParams    = &decParams;
-  t_nrLDPC_time_stats procTime;
-  t_nrLDPC_time_stats* p_procTime     = &procTime ;
+
+  int Kr;
+  int Kr_bytes;
+    
+  phy_vars_gNB->nbDecode = 0;
+  harq_process->processedSegments = 0;
+
   if (!harq_process) {
-    printf("ulsch_decoding.c: NULL harq_process pointer\n");
-    return (ulsch->max_ldpc_iterations + 1);
+    LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n");
+    return 1; 
   }
-  t_nrLDPC_procBuf** p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf;
 
-  int16_t  z [68*384];
-  int8_t   l [68*384];
-  uint8_t  kc       = 255;
-  uint8_t  Ilbrm    = 0;
-  uint32_t Tbslbrm  = 950984;
   double   Coderate = 0.0;
   
   // ------------------------------------------------------------------
@@ -336,30 +503,16 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
   uint8_t n_layers        = pusch_pdu->nrOfLayers;
   // ------------------------------------------------------------------
 
-  uint32_t i,j;
-
-  __m128i *pv = (__m128i*)&z;
-  __m128i *pl = (__m128i*)&l;
-  
-  
    if (!ulsch_llr) {
-    printf("ulsch_decoding.c: NULL ulsch_llr pointer\n");
-    return (ulsch->max_ldpc_iterations + 1);
+    LOG_E(PHY,"ulsch_decoding.c: NULL ulsch_llr pointer\n");
+    return 1;
   }
 
-  if (!frame_parms) {
-    printf("ulsch_decoding.c: NULL frame_parms pointer\n");
-    return (ulsch->max_ldpc_iterations + 1);
-  }
-
-  // harq_process->trials[nfapi_ulsch_pdu_rel15->round]++;
-
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,1);
   harq_process->TBS = pusch_pdu->pusch_data.tb_size;
   harq_process->round = nr_rv_round_map[pusch_pdu->pusch_data.rv_index];
 
   A   = (harq_process->TBS)<<3;
-  ret = ulsch->max_ldpc_iterations + 1;
 
   LOG_D(PHY,"ULSCH Decoding, harq_pid %d TBS %d G %d mcs %d Nl %d nb_rb %d, Qm %d, n_layers %d\n",harq_pid,A,G, mcs, n_layers, nb_rb, Qm, n_layers);
 
@@ -401,12 +554,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
   NR_gNB_SCH_STATS_t *stats=NULL;
   int first_free=-1;
   for (int i=0;i<NUMBER_OF_NR_SCH_STATS_MAX;i++) {
-    if (gNB->ulsch_stats[i].rnti == 0 && first_free == -1) {
+    if (phy_vars_gNB->ulsch_stats[i].rnti == 0 && first_free == -1) {
       first_free = i;
-      stats=&gNB->ulsch_stats[i];
+      stats=&phy_vars_gNB->ulsch_stats[i];
     }
-    if (gNB->ulsch_stats[i].rnti == ulsch->rnti) {
-      stats=&gNB->ulsch_stats[i];
+    if (phy_vars_gNB->ulsch_stats[i].rnti == ulsch->rnti) {
+      stats=&phy_vars_gNB->ulsch_stats[i];
       break;
     }
   }
@@ -420,13 +573,13 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
       stats->current_RI = n_layers;
       stats->total_bytes_tx += harq_process->TBS;
     }
-    // This is a new packet, so compute quantities regarding segmentation
-    if (A > 3824)
-      harq_process->B = A+24;
-    else
-      harq_process->B = A+16;
+  }
+  if (A > 3824)
+    harq_process->B = A+24;
+  else
+    harq_process->B = A+16;
 
-  // [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F)
+// [hna] Perform nr_segmenation with input and output set to NULL to calculate only (B, C, K, Z, F)
   nr_segmentation(NULL,
                   NULL,
                   harq_process->B,
@@ -437,18 +590,18 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
                   p_decParams->BG);
 
 #ifdef DEBUG_ULSCH_DECODING
-    printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z);
-    if (!frame%100)
-      printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z);
+  printf("ulsch decoding nr segmentation Z %d\n", harq_process->Z);
+  if (!frame%100)
+    printf("K %d C %d Z %d \n", harq_process->K, harq_process->C, harq_process->Z);
 #endif
-  }
+  Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers);
+
   p_decParams->Z = harq_process->Z;
 
 
   p_decParams->numMaxIter = ulsch->max_ldpc_iterations;
   p_decParams->outMode= 0;
 
-  err_flag = 0;
   r_offset = 0;
 
   uint16_t a_segments = MAX_NUM_NR_ULSCH_SEGMENTS;  //number of segments to be allocated
@@ -460,284 +613,48 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *gNB,
 
   if (harq_process->C > a_segments) {
     LOG_E(PHY,"Illegal harq_process->C %d > %d\n",harq_process->C,a_segments);
-    return (ulsch->max_ldpc_iterations + 1);
+    return 1;
   }
 #ifdef DEBUG_ULSCH_DECODING
   printf("Segmentation: C %d, K %d\n",harq_process->C,harq_process->K);
 #endif
-
-  //opp_enabled=1;
-
   Kr = harq_process->K;
   Kr_bytes = Kr>>3;
-
-  K_bytes_F = Kr_bytes-(harq_process->F>>3);
+  offset = 0;
+  void (*nr_processULSegment_ptr)(void*) = &nr_processULSegment;
 
   for (r=0; r<harq_process->C; r++) {
-    E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
-
-
-    start_meas(&gNB->ulsch_deinterleaving_stats);
-
-    ////////////////////////////////////////////////////////////////////////////////////////////
-    ///////////////////////////////// nr_deinterleaving_ldpc ///////////////////////////////////
-    //////////////////////////////////////////////////////////////////////////////////////////
 
-    //////////////////////////// ulsch_llr =====> harq_process->e //////////////////////////////
-
-    nr_deinterleaving_ldpc(E,
-                           Qm,
-                           harq_process->e[r],
-                           ulsch_llr+r_offset);
-
-    //for (int i =0; i<16; i++)
-    //          printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
-
-    stop_meas(&gNB->ulsch_deinterleaving_stats);
-
-
-    LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rvidx %d, round %d)...\n",
-          harq_pid,r, G,
-          Kr*3,
-          harq_process->TBS,
-          Qm,
-          nb_rb,
-          n_layers,
-          pusch_pdu->pusch_data.rv_index,
-          harq_process->round);
-    //////////////////////////////////////////////////////////////////////////////////////////
-
-
-    //////////////////////////////////////////////////////////////////////////////////////////
-    //////////////////////////////// nr_rate_matching_ldpc_rx ////////////////////////////////
-    //////////////////////////////////////////////////////////////////////////////////////////
-
-    ///////////////////////// harq_process->e =====> harq_process->d /////////////////////////
-
-    start_meas(&gNB->ulsch_rate_unmatching_stats);
-
-    Tbslbrm = nr_compute_tbslbrm(0,nb_rb,n_layers,harq_process->C);
-
-    if (nr_rate_matching_ldpc_rx(Ilbrm,
-                                 Tbslbrm,
-                                 p_decParams->BG,
-                                 p_decParams->Z,
-                                 harq_process->d[r],
-                                 harq_process->e[r],
-                                 harq_process->C,
-                                 pusch_pdu->pusch_data.rv_index,
-                                 (harq_process->round==0)?1:0,
-                                 E,
-				 harq_process->F,
-				 Kr-harq_process->F-2*(p_decParams->Z))==-1) {
-
-      stop_meas(&gNB->ulsch_rate_unmatching_stats);
-
-      LOG_E(PHY,"ulsch_decoding.c: Problem in rate_matching\n");
-      return (ulsch->max_ldpc_iterations + 1);
-    } else {
-      stop_meas(&gNB->ulsch_rate_unmatching_stats);
-    }
+    E = nr_get_E(G, harq_process->C, Qm, n_layers, r);
 
+    union ldpcReqUnion id = {.s={ulsch->rnti,frame,nr_tti_rx,0,0}};
+    notifiedFIFO_elt_t *req=newNotifiedFIFO_elt(sizeof(ldpcDecode_t), id.p, phy_vars_gNB->respDecode, nr_processULSegment_ptr);
+    ldpcDecode_t * rdata=(ldpcDecode_t *) NotifiedFifoData(req);
+
+    rdata->gNB = phy_vars_gNB;
+    rdata->ulsch_harq = harq_process;
+    rdata->decoderParms = decParams;
+    rdata->ulsch_llr = ulsch_llr;
+    rdata->Kc = kc;
+    rdata->harq_pid = harq_pid;
+    rdata->segment_r = r;
+    rdata->nbSegments = harq_process->C;
+    rdata->E = E;
+    rdata->A = A;
+    rdata->Qm = Qm;
+    rdata->r_offset = r_offset;
+    rdata->Kr_bytes = Kr_bytes;
+    rdata->rv_index = pusch_pdu->pusch_data.rv_index;
+    rdata->Tbslbrm = Tbslbrm;
+    rdata->offset = offset;
+    rdata->ulsch = ulsch;
+    rdata->ulsch_id = UE_id;
+    pushTpool(phy_vars_gNB->threadPool,req);
+    phy_vars_gNB->nbDecode++;
+    LOG_D(PHY,"Added a block to decode, in pipe: %d\n",phy_vars_gNB->nbDecode);
     r_offset += E;
-
-#ifdef DEBUG_ULSCH_DECODING
-    if (r==0) {
-      write_output("decoder_llr.m","decllr",ulsch_llr,G,1,0);
-      write_output("decoder_in.m","dec",&harq_process->d[0][0],E,1,0);
-    }
-
-    printf("decoder input(segment %u) :", r);
-    int i; 
-    for (i=0;i<(3*8*Kr_bytes)+12;i++)
-      printf("%d : %d\n",i,harq_process->d[r][i]);
-    printf("\n");
-#endif
-
-
-    //    printf("Clearing c, %p\n",harq_process->c[r]);
-    memset(harq_process->c[r],0,Kr_bytes);
-
-    //    printf("done\n");
-    if (harq_process->C == 1) {
-      if (A > 3824)
-        crc_type = CRC24_A;
-      else
-        crc_type = CRC16;
-
-      length_dec = harq_process->B;
-    }
-    else {
-      crc_type = CRC24_B;
-      length_dec = (harq_process->B+24*harq_process->C)/harq_process->C;
-    }
-
-    if (err_flag == 0) {
-
-      start_meas(&gNB->ulsch_ldpc_decoding_stats);
-
-      //LOG_E(PHY,"AbsSubframe %d.%d Start LDPC segment %d/%d A %d ",frame%1024,nr_tti_rx,r,harq_process->C-1, A);
-
-      
-      memset(pv,0,2*harq_process->Z*sizeof(int16_t));
-      memset((pv+K_bytes_F),127,harq_process->F*sizeof(int16_t));
-
-      for (i=((2*p_decParams->Z)>>3), j = 0; i < K_bytes_F; i++, j++) {
-        pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
-      }
-
-      AssertFatal(kc!=255,"");
-      j+=(harq_process->F>>3);
-      for (i=Kr_bytes; i < ((kc*p_decParams->Z)>>3); i++, j++) {
-        pv[i]= _mm_loadu_si128((__m128i*)(&harq_process->d[r][8*j]));
-      }
-    
-      for (i=0, j=0; j < ((kc*p_decParams->Z)>>4);  i+=2, j++) {
-        pl[j] = _mm_packs_epi16(pv[i],pv[i+1]);
-      }
-
-      //////////////////////////////////////////////////////////////////////////////////////////
-
-
-      //////////////////////////////////////////////////////////////////////////////////////////
-      ///////////////////////////////////// nrLDPC_decoder /////////////////////////////////////
-      //////////////////////////////////////////////////////////////////////////////////////////
-
-      ////////////////////////////////// pl =====> llrProcBuf //////////////////////////////////
-
-      no_iteration_ldpc = nrLDPC_decoder(p_decParams,
-                                         (int8_t*)&pl[0],
-                                         llrProcBuf,
-                                         p_nrLDPC_procBuf[r],
-                                         p_procTime);
-
-      if (check_crc((uint8_t*)llrProcBuf,length_dec,harq_process->F,crc_type)) {
-  #ifdef PRINT_CRC_CHECK
-        //if (prnt_crc_cnt % 10 == 0)
-          LOG_I(PHY, "Segment %d CRC OK\n",r);
-  #endif
-        ret = no_iteration_ldpc;
-      } else {
-  #ifdef PRINT_CRC_CHECK
-        //if (prnt_crc_cnt%10 == 0)
-          LOG_I(PHY, "CRC NOK\n");
-  #endif
-        ret = ulsch->max_ldpc_iterations + 1;
-      }
-      nb_total_decod++;
-
-      if (no_iteration_ldpc > ulsch->max_ldpc_iterations){
-        nb_error_decod++;
-      }
-      
-      for (int m=0; m < Kr>>3; m ++) {
-        harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
-      }
-
-#ifdef DEBUG_ULSCH_DECODING
-      //printf("output decoder %d %d %d %d %d \n", harq_process->c[r][0], harq_process->c[r][1], harq_process->c[r][2],harq_process->c[r][3], harq_process->c[r][4]);
-      for (int k=0;k<A>>3;k++)
-       printf("output decoder [%d] =  0x%02x \n", k, harq_process->c[r][k]);
-      printf("no_iterations_ldpc %d (ret %u)\n",no_iteration_ldpc,ret);
-      //write_output("dec_output.m","dec0",harq_process->c[0],Kr_bytes,1,4);
-#endif
-
-      stop_meas(&gNB->ulsch_ldpc_decoding_stats);
-    }
-
-    if ((err_flag == 0) && (ret >= (ulsch->max_ldpc_iterations + 1))) {
-      // a Code segment is in error so break;
-      LOG_D(PHY,"AbsSubframe %d.%d CRC failed, segment %d/%d \n",frame%1024,nr_tti_rx,r,harq_process->C-1);
-      err_flag = 1;
-    }
+    offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
     //////////////////////////////////////////////////////////////////////////////////////////
   }
-
-  int32_t frame_rx_prev = frame;
-  int32_t tti_rx_prev = nr_tti_rx - 1;
-  if (tti_rx_prev < 0) {
-    frame_rx_prev--;
-    tti_rx_prev += frame_parms->slots_per_frame;
-  }
-  frame_rx_prev = frame_rx_prev%1024;
-
-  if (err_flag == 1) {
-
-#ifdef gNB_DEBUG_TRACE
-    LOG_I(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d) Kr %d r %d\n",
-          gNB->Mod_id, frame, nr_tti_rx, harq_pid,harq_process->status, harq_process->round,harq_process->TBS,Kr,r);
-#endif
-
-    // harq_process->harq_ack.ack = 0;
-    // harq_process->harq_ack.harq_id = harq_pid;
-    // harq_process->harq_ack.send_harq_status = 1;
-    // harq_process->errors[harq_process->round]++;
-    //harq_process->round++;
-
-    if (harq_process->round >= ulsch->Mlimit) {
-      harq_process->status = SCH_IDLE;
-      harq_process->round  = 0;
-      harq_process->handled  = 0;
-      ulsch->harq_mask &= ~(1 << harq_pid);
-    }
-
-    //   LOG_D(PHY,"[gNB %d] ULSCH: Setting NACK for nr_tti_rx %d (pid %d, pid status %d, round %d/Max %d, TBS %d)\n",
-    //         gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->status,harq_process->round,ulsch->Mlimit,harq_process->TBS);
-
-    harq_process->handled  = 1;
-    ret = ulsch->max_ldpc_iterations + 1;
-
-  } else {
-
-#ifdef gNB_DEBUG_TRACE
-    LOG_I(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d\n",
-          gNB->Mod_id,nr_tti_rx,harq_process->TBS);
-#endif
-
-    harq_process->status = SCH_IDLE;
-    harq_process->round  = 0;
-    // harq_process->handled  = 0;
-    ulsch->harq_mask &= ~(1 << harq_pid);
-    // harq_process->harq_ack.ack = 1;
-    // harq_process->harq_ack.harq_id = harq_pid;
-    // harq_process->harq_ack.send_harq_status = 1;
-
-    //  LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d (pid %d, round %d, TBS %d)\n",gNB->Mod_id,nr_tti_rx,harq_pid,harq_process->round,harq_process->TBS);
-
-
-    // Reassembly of Transport block here
-    offset = 0;
-    Kr = harq_process->K;
-    Kr_bytes = Kr>>3;
-    
-    for (r=0; r<harq_process->C; r++) {
-      
-      memcpy(harq_process->b+offset,
-	     harq_process->c[r],
-	     Kr_bytes- - (harq_process->F>>3) -((harq_process->C>1)?3:0));
-      
-      offset += (Kr_bytes - (harq_process->F>>3) - ((harq_process->C>1)?3:0));
-      
-#ifdef DEBUG_ULSCH_DECODING
-      printf("Segment %u : Kr = %u bytes\n", r, Kr_bytes);
-      printf("copied %d bytes to b sequence (harq_pid %d)\n", (Kr_bytes - (harq_process->F>>3)-((harq_process->C>1)?3:0)), harq_pid);
-      printf("b[0] = %x, c[%d] = %x\n", harq_process->b[offset], harq_process->F>>3, harq_process->c[r]);
-#endif
-      
-    }
-    if (stats) stats->total_bytes_rx += harq_process->TBS;
-  }
-
-#ifdef DEBUG_ULSCH_DECODING
-  LOG_I(PHY, "Decoder output (payload) at SFN/SF: %d/%d TBS: %d\n", frame, nr_tti_rx,harq_process->TBS);
-  for (i = 0; i < harq_process->TBS; i++) {
-	  //harq_process_ul_ue->a[i] = (unsigned char) rand();
-	  //printf("a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
-	  printf("%02x ",harq_process->b[i]);
-  }
-#endif
-
-  ulsch->last_iteration_cnt = ret;
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
-  return(ret);
+  return 1;
 }
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 36bcb2f3793d228865353c7281b8abfd09f4046f..7378f69c271a0ae9fc8c4d316ec58e0288afde31 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -478,9 +478,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_IN);
 
     if ((harq_process->Nl)<4)
-      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl,harq_process->C);
+      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl);
     else
-      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4,harq_process->C);
+      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4);
 
 
     if (nr_rate_matching_ldpc_rx(Ilbrm,
@@ -1069,7 +1069,7 @@ uint32_t  nr_dlsch_decoding_mthread(PHY_VARS_NR_UE *phy_vars_ue,
     if (harq_process->Nl < Nl)
       Nl = harq_process->Nl;
 
-    Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl,harq_process->C);
+    Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,harq_process->Nl);
 
     if (nr_rate_matching_ldpc_rx(Ilbrm,
                                  Tbslbrm,
@@ -1610,9 +1610,9 @@ void nr_dlsch_decoding_process(void *arg)
 #endif
 
     if (Nl<4)
-      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,Nl,harq_process->C);
+      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,Nl);
     else
-      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4,harq_process->C);
+      Tbslbrm = nr_compute_tbslbrm(harq_process->mcs_table,nb_rb,4);
 
     if (nr_rate_matching_ldpc_rx(Ilbrm,
                                  Tbslbrm,
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index 21f306d0f3f4c3b92aa612c32275a93da9abbfed..ee10c96c206767d34eae4a95c0921f45faab559e 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -443,7 +443,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
 
     E = nr_get_E(G, harq_process->C, mod_order, harq_process->pusch_pdu.nrOfLayers, r);
 
-    Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers,harq_process->C);
+    Tbslbrm = nr_compute_tbslbrm(0,nb_rb,harq_process->pusch_pdu.nrOfLayers);
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_RATE_MATCHING_LDPC, VCD_FUNCTION_IN);
     nr_rate_matching_ldpc(Ilbrm,
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 179ca0331f5e9fd4064a696c5c229157a5f1fb1a..4d5a46c4fd0cf620bd3d85149a1650f3c71faefa 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -263,6 +263,8 @@ typedef struct {
   int16_t e[MAX_NUM_NR_DLSCH_SEGMENTS][3*8448];
   /// Number of bits in each code block after rate matching for LDPC code (38.212 V15.4.0 section 5.4.2.1)
   uint32_t E;
+  /// Number of segments processed so far
+  uint32_t processedSegments;
   //////////////////////////////////////////////////////////////
 
 
@@ -475,7 +477,6 @@ typedef struct {
   uint8_t cl_done;
 } NR_gNB_PUSCH;
 
-
 /// Context data structure for RX/TX portion of slot processing
 typedef struct {
   /// Component Carrier index
@@ -822,7 +823,45 @@ typedef struct PHY_VARS_gNB_s {
   time_stats_t rx_dft_stats;
   time_stats_t ulsch_freq_offset_estimation_stats;
   */
+  notifiedFIFO_t *respDecode;
+  tpool_t *threadPool;
+  int nbDecode;
 
 } PHY_VARS_gNB;
 
+typedef struct LDPCDecode_s {
+  PHY_VARS_gNB *gNB;
+  NR_UL_gNB_HARQ_t *ulsch_harq;
+  t_nrLDPC_dec_params decoderParms;
+  NR_gNB_ULSCH_t *ulsch;
+  short* ulsch_llr; 
+  int ulsch_id;
+  int harq_pid;
+  int rv_index;
+  int A;
+  int E;
+  int Kc;
+  int Qm;
+  int Kr_bytes;
+  int nbSegments;
+  int segment_r;
+  int r_offset;
+  int offset;
+  int Tbslbrm;
+  int decodeIterations;
+} ldpcDecode_t;
+
+struct ldpcReqId {
+  uint16_t rnti;
+  uint16_t frame;
+  uint8_t  subframe;
+  uint8_t  codeblock;
+  uint16_t spare;
+} __attribute__((packed));
+
+union ldpcReqUnion {
+  struct ldpcReqId s;
+  uint64_t p;
+};
+
 #endif
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 6dfe967edc0b9666eaffc73d6b6a04466f8084cf..1024db37915d27c48440cc7fdcbc95a1f68bcd24 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -213,12 +213,74 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
 
 */
 
+void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
+  ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
+  NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
+  NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
+  int r = rdata->segment_r;
+
+  bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
+  ulsch_harq->processedSegments++;
+  LOG_D(PHY, "processing result of segment: %d, processed %d/%d\n",
+	rdata->segment_r, ulsch_harq->processedSegments, rdata->nbSegments);
+  gNB->nbDecode--;
+  LOG_D(PHY,"remain to decoded in subframe: %d\n", gNB->nbDecode);
+  
+  if (decodeSuccess) {
+    memcpy(ulsch_harq->b+rdata->offset,
+           ulsch_harq->c[r],
+           rdata->Kr_bytes- - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
+
+  } else {
+    if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
+      int nb=abortTpool(gNB->threadPool, req->key);
+      nb+=abortNotifiedFIFO(gNB->respDecode, req->key);
+      gNB->nbDecode-=nb;
+      LOG_D(PHY,"uplink segment error %d/%d, aborted %d segments\n",rdata->segment_r,rdata->nbSegments, nb);
+      LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
+      AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
+		  ulsch_harq->processedSegments, nb, rdata->nbSegments);
+      ulsch_harq->processedSegments=rdata->nbSegments;
+    }
+  }
+
+  // if all segments are done 
+  if (rdata->nbSegments == ulsch_harq->processedSegments) {
+    if (decodeSuccess) {
+      LOG_D(PHY,"[gNB %d] ULSCH: Setting ACK for nr_tti_rx %d TBS %d\n",
+            gNB->Mod_id,ulsch_harq->slot,ulsch_harq->TBS);
+      ulsch_harq->status = SCH_IDLE;
+      ulsch_harq->round  = 0;
+      ulsch->harq_mask &= ~(1 << rdata->harq_pid);
+
+      LOG_D(PHY, "ULSCH received ok \n");
+      nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 0);
+    } else {
+      LOG_D(PHY,"[gNB %d] ULSCH: Setting NAK for SFN/SF %d/%d (pid %d, status %d, round %d, TBS %d) r %d\n",
+            gNB->Mod_id, ulsch_harq->frame, ulsch_harq->slot,
+            rdata->harq_pid,ulsch_harq->status, ulsch_harq->round,ulsch_harq->TBS,r);
+      if (ulsch_harq->round >= ulsch->Mlimit) {
+        ulsch_harq->status = SCH_IDLE;
+        ulsch_harq->round  = 0;
+        ulsch_harq->handled  = 0;
+        ulsch->harq_mask &= ~(1 << rdata->harq_pid);
+      }
+      ulsch_harq->handled  = 1;
+
+      LOG_D(PHY, "ULSCH %d in error\n",rdata->ulsch_id);
+      nr_fill_indication(gNB,ulsch_harq->frame, ulsch_harq->slot, rdata->ulsch_id, rdata->harq_pid, 1);
+    }
+    ulsch->last_iteration_cnt = rdata->decodeIterations;
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_ULSCH_DECODING,0);
+  }
+}
+
+
 void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH_id, uint8_t harq_pid)
 {
   NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   nfapi_nr_pusch_pdu_t *pusch_pdu = &gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->ulsch_pdu;
   
-  uint8_t ret;
   uint8_t l, number_dmrs_symbols = 0;
   uint32_t G;
   uint16_t start_symbol, number_symbols, nb_re_dmrs;
@@ -270,25 +332,22 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
   //----------------------------------------------------------
 
   start_meas(&gNB->ulsch_decoding_stats);
-  ret = nr_ulsch_decoding(gNB,
-                          ULSCH_id,
-                          gNB->pusch_vars[ULSCH_id]->llr,
-                          frame_parms,
-                          pusch_pdu,
-                          frame_rx,
-                          slot_rx,
-                          harq_pid,
-                          G);
-  stop_meas(&gNB->ulsch_decoding_stats);
-
-  if (ret > gNB->ulsch[ULSCH_id][0]->max_ldpc_iterations){
-    LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id);
-    nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
-  }
-  else if(gNB->ulsch[ULSCH_id][0]->harq_processes[harq_pid]->b!=NULL){
-    LOG_D(PHY, "ULSCH received ok \n");
-    nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 0);
+  nr_ulsch_decoding(gNB,
+                    ULSCH_id,
+                    gNB->pusch_vars[ULSCH_id]->llr,
+                    frame_parms,
+                    pusch_pdu,
+                    frame_rx,
+                    slot_rx,
+                    harq_pid,
+                    G);
+
+  while (gNB->nbDecode > 0) {
+    notifiedFIFO_elt_t *req=pullTpool(gNB->respDecode, gNB->threadPool);
+    nr_postDecode(gNB, req);
+    delNotifiedFIFO_elt(req);
   }
+  stop_meas(&gNB->ulsch_decoding_stats);
 }
 
 
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 6e703c2328f42fe53074164462462fb07eb1fb42..98219b7a33cf61d5a0ec952d512a34cbadac019d 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -184,7 +184,7 @@ int main(int argc, char **argv)
 
   int frame=1,slot=1;
   int frame_length_complex_samples;
-  int frame_length_complex_samples_no_prefix;
+  //int frame_length_complex_samples_no_prefix;
   NR_DL_FRAME_PARMS *frame_parms;
   UE_nr_rxtx_proc_t UE_proc;
   NR_Sched_Rsp_t Sched_INFO;
@@ -196,7 +196,7 @@ int main(int argc, char **argv)
   int pucch_tgt_snrx10 = 200;
   int loglvl=OAILOG_INFO;
 
-  float target_error_rate = 0.01;
+  //float target_error_rate = 0.01;
   int css_flag=0;
 
   cpuf = get_cpu_freq_GHz();
@@ -358,7 +358,7 @@ int main(int argc, char **argv)
       
     case 'I':
       run_initial_sync=1;
-      target_error_rate=0.1;
+      //target_error_rate=0.1;
       slot = 0;
       break;
 
@@ -584,7 +584,7 @@ int main(int argc, char **argv)
   }
 
   frame_length_complex_samples = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
-  frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
+  //frame_length_complex_samples_no_prefix = frame_parms->samples_per_subframe_wCP*NR_NUMBER_OF_SUBFRAMES_PER_FRAME;
 
   s_re = malloc(2*sizeof(double*));
   s_im = malloc(2*sizeof(double*));
diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c
index 136da51bb64383db387ae47c3b4c46716487be97..f2662d9fe67c9109329a126efad10da9dcbc49f8 100644
--- a/openair1/SIMULATION/NR_PHY/ulschsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulschsim.c
@@ -45,6 +45,7 @@
 #include "openair1/SIMULATION/RF/rf.h"
 #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
 #include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
+#include "common/utils/threadPool/thread-pool.h"
 
 //#define DEBUG_NR_ULSCHSIM
 
@@ -67,6 +68,44 @@ PHY_VARS_NR_UE *PHY_vars_UE_g[1][1] = { { NULL } };
 uint16_t n_rnti = 0x1234;
 openair0_config_t openair0_cfg[MAX_CARDS];
 
+int nr_postDecode_sim(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
+  ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
+  NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
+  NR_gNB_ULSCH_t *ulsch = rdata->ulsch;
+  int r = rdata->segment_r;
+
+  bool decodeSuccess = (rdata->decodeIterations <= rdata->decoderParms.numMaxIter);
+  ulsch_harq->processedSegments++;
+  gNB->nbDecode--;
+
+  if (decodeSuccess) {
+    memcpy(ulsch_harq->b+rdata->offset,
+           ulsch_harq->c[r],
+           rdata->Kr_bytes- - (ulsch_harq->F>>3) -((ulsch_harq->C>1)?3:0));
+  } else {
+    if ( rdata->nbSegments != ulsch_harq->processedSegments ) {
+      int nb=abortTpool(gNB->threadPool, req->key);
+      nb+=abortNotifiedFIFO(gNB->respDecode, req->key);
+      gNB->nbDecode-=nb;
+      AssertFatal(ulsch_harq->processedSegments+nb == rdata->nbSegments,"processed: %d, aborted: %d, total %d\n",
+      ulsch_harq->processedSegments, nb, rdata->nbSegments);
+      ulsch_harq->processedSegments=rdata->nbSegments;
+      return 1;
+    }
+  }
+
+  // if all segments are done 
+  if (rdata->nbSegments == ulsch_harq->processedSegments) {
+    if (decodeSuccess) {
+      return 0;
+    } else {
+      return 1;
+      }
+
+    }
+    ulsch->last_iteration_cnt = rdata->decodeIterations;
+  return 0;
+}
 int main(int argc, char **argv)
 {
   char c;
@@ -92,7 +131,7 @@ int main(int argc, char **argv)
   NR_DL_FRAME_PARMS *frame_parms;
   double sigma;
   unsigned char qbits = 8;
-  int ret;
+  int ret=0;
   int loglvl = OAILOG_WARNING;
   uint64_t SSB_positions=0x01;
   uint16_t nb_symb_sch = 12;
@@ -338,6 +377,11 @@ int main(int argc, char **argv)
   gNB = RC.gNB[0];
   //gNB_config = &gNB->gNB_config;
 
+  gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
+  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  char tp_param[] = "n";
+  initTpool(tp_param, gNB->threadPool, true);
+  initNotifiedFIFO(gNB->respDecode);
   frame_parms = &gNB->frame_parms; //to be initialized I suppose (maybe not necessary for PBCH)
   frame_parms->nb_antennas_tx = n_tx;
   frame_parms->nb_antennas_rx = n_rx;
@@ -531,10 +575,15 @@ int main(int argc, char **argv)
                            rel15_ul->qam_mod_order,
                            rel15_ul->nrOfLayers);
 
-      ret = nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul,
+      nr_ulsch_decoding(gNB, UE_id, channel_output_fixed, frame_parms, rel15_ul,
                               frame, subframe, harq_pid, G);
+      while (gNB->nbDecode > 0) {
+        notifiedFIFO_elt_t *req=pullTpool(gNB->respDecode, gNB->threadPool);
+        ret = nr_postDecode_sim(gNB, req);
+        delNotifiedFIFO_elt(req);
+      }
 
-      if (ret > ulsch_gNB->max_ldpc_iterations)
+      if (ret)
         n_errors++;
 
       //count errors
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index fafd1fd22c191d7baa155f97aeb30c22a4240610..42cce0fb610087940f709cb118811664f6e9854f 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -55,6 +55,8 @@
 //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
 #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
 #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
+#include "common/utils/threadPool/thread-pool.h"
+
 #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
 #include "SIMULATION/LTE_PHY/common_sim.h"
 
@@ -181,6 +183,7 @@ int main(int argc, char **argv)
   int pucch_tgt_snrx10 = 200;
   int ibwps=24;
   int ibwp_rboffset=41;
+  int params_from_file = 0;
   if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0 ) {
     exit_fun("[NR_ULSIM] Error, configuration module init failed\n");
   }
@@ -417,6 +420,10 @@ int main(int argc, char **argv)
       }
       break;
 
+    case 'Q':
+      params_from_file = 1;
+      break;
+
     default:
     case 'h':
       printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n", argv[0]);
@@ -438,7 +445,7 @@ int main(int argc, char **argv)
       printf("-A Interpolation_filname Run with Abstraction to generate Scatter plot using interpolation polynomial in file\n");
       //printf("-C Generate Calibration information for Abstraction (effective SNR adjustment to remove Pe bias w.r.t. AWGN)\n");
       printf("-F Input filename (.txt format) for RX conformance testing\n");
-      printf("-G raw file containing RRC configuration (generated by gNB)\n");
+      printf("-G Offset of samples to read from file (0 default)\n");
       printf("-M Multiple SSB positions in burst\n");
       printf("-N Nid_cell\n");
       printf("-O oversampling factor (1,2,4,8,16)\n");
@@ -448,6 +455,7 @@ int main(int argc, char **argv)
       printf("-P Print ULSCH performances\n");
       printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
       printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:3}, e.g. -U 2 0 2 \n");
+      printf("-Q If -F used, read parameters from file\n");
       exit(-1);
       break;
 
@@ -494,6 +502,11 @@ int main(int argc, char **argv)
   RC.gNB = (PHY_VARS_gNB **) malloc(sizeof(PHY_VARS_gNB *));
   RC.gNB[0] = calloc(1,sizeof(PHY_VARS_gNB));
   gNB = RC.gNB[0];
+  gNB->threadPool = (tpool_t*)malloc(sizeof(tpool_t));
+  gNB->respDecode = (notifiedFIFO_t*) malloc(sizeof(notifiedFIFO_t));
+  char tp_param[] = "n";
+  initTpool(tp_param, gNB->threadPool, true);
+  initNotifiedFIFO(gNB->respDecode);
   //gNB_config = &gNB->gNB_config;
 
   //memset((void *)&gNB->UL_INFO,0,sizeof(gNB->UL_INFO));
@@ -716,6 +729,7 @@ int main(int argc, char **argv)
   //for (int i=0;i<16;i++) printf("%f\n",gaussdouble(0.0,1.0));
   snrRun = 0;
   int n_errs = 0;
+  int read_errors=0;
 
   int slot_offset = frame_parms->get_samples_slot_timestamp(slot,frame_parms,0);
   int slot_length = slot_offset - frame_parms->get_samples_slot_timestamp(slot-1,frame_parms,0);
@@ -725,35 +739,39 @@ int main(int argc, char **argv)
     // 800 samples is N_TA_OFFSET for FR1 @ 30.72 Ms/s,
     AssertFatal(frame_parms->subcarrier_spacing==30000,"only 30 kHz for file input for now (%d)\n",frame_parms->subcarrier_spacing);
   
-    fseek(input_fd,file_offset*((slot_length<<2)+4000+16),SEEK_SET);
-    fread((void*)&n_rnti,sizeof(int16_t),1,input_fd);
-    printf("rnti %x\n",n_rnti);
-    fread((void*)&nb_rb,sizeof(int16_t),1,input_fd);
-    printf("nb_rb %d\n",nb_rb);
-    int16_t dummy;
-    fread((void*)&start_rb,sizeof(int16_t),1,input_fd);
-    //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
-    printf("rb_start %d\n",start_rb);
-    fread((void*)&nb_symb_sch,sizeof(int16_t),1,input_fd);
-    //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
-    printf("nb_symb_sch %d\n",nb_symb_sch);
-    fread((void*)&start_symbol,sizeof(int16_t),1,input_fd);
-    printf("start_symbol %d\n",start_symbol);
-    fread((void*)&Imcs,sizeof(int16_t),1,input_fd);
-    printf("mcs %d\n",Imcs);
-    fread((void*)&rv_index,sizeof(int16_t),1,input_fd);
-    printf("rv_index %d\n",rv_index);
-    //    fread((void*)&harq_pid,sizeof(int16_t),1,input_fd);
-    fread((void*)&dummy,sizeof(int16_t),1,input_fd);
-    printf("harq_pid %d\n",harq_pid);
-    fread((void*)&gNB->common_vars.rxdata[0][slot_offset-delay],
-	  sizeof(int16_t),
-	  slot_length<<1,
-	  input_fd);
+    if (params_from_file) {
+      fseek(input_fd,file_offset*((slot_length<<2)+4000+16),SEEK_SET);
+      read_errors+=fread((void*)&n_rnti,sizeof(int16_t),1,input_fd);
+      printf("rnti %x\n",n_rnti);
+      read_errors+=fread((void*)&nb_rb,sizeof(int16_t),1,input_fd);
+      printf("nb_rb %d\n",nb_rb);
+      int16_t dummy;
+      read_errors+=fread((void*)&start_rb,sizeof(int16_t),1,input_fd);
+      //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
+      printf("rb_start %d\n",start_rb);
+      read_errors+=fread((void*)&nb_symb_sch,sizeof(int16_t),1,input_fd);
+      //fread((void*)&dummy,sizeof(int16_t),1,input_fd);
+      printf("nb_symb_sch %d\n",nb_symb_sch);
+      read_errors+=fread((void*)&start_symbol,sizeof(int16_t),1,input_fd);
+      printf("start_symbol %d\n",start_symbol);
+      read_errors+=fread((void*)&Imcs,sizeof(int16_t),1,input_fd);
+      printf("mcs %d\n",Imcs);
+      read_errors+=fread((void*)&rv_index,sizeof(int16_t),1,input_fd);
+      printf("rv_index %d\n",rv_index);
+      //    fread((void*)&harq_pid,sizeof(int16_t),1,input_fd);
+      read_errors+=fread((void*)&dummy,sizeof(int16_t),1,input_fd);
+      printf("harq_pid %d\n",harq_pid);
+    }
+    fseek(input_fd,file_offset*sizeof(int16_t)*2,SEEK_SET);
+    read_errors+=fread((void*)&gNB->common_vars.rxdata[0][slot_offset-delay],
+    sizeof(int16_t),
+    slot_length<<1,
+    input_fd);
+    if (read_errors==0) exit(1);
     for (int i=0;i<16;i+=2) printf("slot_offset %d : %d,%d\n",
-				   slot_offset,
-				   ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i],
-				   ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]);
+           slot_offset,
+           ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[i],
+           ((int16_t*)&gNB->common_vars.rxdata[0][slot_offset])[1+i]);
   }
   
   for (SNR = snr0; SNR < snr1; SNR += snr_step) {
@@ -764,6 +782,17 @@ int main(int argc, char **argv)
     int n_errors[4] = {0,0,0,0};;
     int round_trials[4]={0,0,0,0};
     uint32_t errors_scrambling[4] = {0,0,0,0};
+    reset_meas(&gNB->phy_proc_rx);
+    reset_meas(&gNB->rx_pusch_stats);
+    reset_meas(&gNB->ulsch_decoding_stats);
+    reset_meas(&gNB->ulsch_deinterleaving_stats);
+    reset_meas(&gNB->ulsch_rate_unmatching_stats);
+    reset_meas(&gNB->ulsch_ldpc_decoding_stats);
+    reset_meas(&gNB->ulsch_unscrambling_stats);
+    reset_meas(&gNB->ulsch_channel_estimation_stats);
+    reset_meas(&gNB->ulsch_llr_stats);
+    reset_meas(&gNB->ulsch_channel_compensation_stats);
+    reset_meas(&gNB->ulsch_rbs_extraction_stats);
 
     clear_pusch_stats(gNB);
     for (trial = 0; trial < n_trials; trial++) {
@@ -777,19 +806,6 @@ int main(int argc, char **argv)
       ulsch_ue[0]->harq_processes[harq_pid]->round = round;
       gNB->ulsch[0][0]->harq_processes[harq_pid]->round = round;
       rv_index = nr_rv_round_map[round];
-      reset_meas(&gNB->phy_proc_rx);
-      reset_meas(&gNB->rx_pusch_stats);
-      reset_meas(&gNB->ulsch_decoding_stats);
-      reset_meas(&gNB->ulsch_deinterleaving_stats);
-      reset_meas(&gNB->ulsch_rate_unmatching_stats);
-      reset_meas(&gNB->ulsch_ldpc_decoding_stats);
-      reset_meas(&gNB->ulsch_unscrambling_stats);
-      reset_meas(&gNB->ulsch_channel_estimation_stats);
-      reset_meas(&gNB->ulsch_ptrs_processing_stats);
-      reset_meas(&gNB->ulsch_llr_stats);
-      reset_meas(&gNB->ulsch_mrc_stats);
-      reset_meas(&gNB->ulsch_channel_compensation_stats);
-      reset_meas(&gNB->ulsch_rbs_extraction_stats);
 
       UE_proc.nr_tti_tx = slot;
       UE_proc.frame_tx = frame;
@@ -1124,9 +1140,9 @@ int main(int argc, char **argv)
       printStatIndent2(&gNB->ulsch_llr_stats,"ULSCH llr computation");
       printStatIndent(&gNB->ulsch_unscrambling_stats,"ULSCH unscrambling");
       printStatIndent(&gNB->ulsch_decoding_stats,"ULSCH total decoding time");
-      printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving");
-      printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx");
-      printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding");
+      //printStatIndent2(&gNB->ulsch_deinterleaving_stats,"ULSCH deinterleaving");
+      //printStatIndent2(&gNB->ulsch_rate_unmatching_stats,"ULSCH rate matching rx");
+      //printStatIndent2(&gNB->ulsch_ldpc_decoding_stats,"ULSCH ldpc decoding");
       printf("\n");
     }
 
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_mch.c b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
index 0c686a6475c57240fa31818fef6d6be699cb2656..f3a77ed7030e86615b738a8dafe795f4f115313f 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_mch.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_mch.c
@@ -211,7 +211,7 @@ schedule_MBMS_NFAPI(module_id_t module_idP, uint8_t CC_id, frame_t frameP,
 			msi_pos++;
 		   while((non_mbsfn_SubframeConfig & (0x100 >> msi_pos)) == (0x100>>msi_pos))
 			msi_pos++;
-		   	mbms_mch_i=0;
+		   mbms_mch_i=0;
 
 		   if((subframeP==0)){
 		   	x=0;
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
index c2c3398a8400a8aaa58dcb9fdf021e0a6ef8cb40..30dccea2a9680daa849c5c9b48fa260834a53dc6 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_compute_tbs_common.c
@@ -89,9 +89,8 @@ uint32_t nr_compute_tbs(uint16_t Qm,
 
 //tbslbrm calculation according to 5.4.2.1 of 38.212
 uint32_t nr_compute_tbslbrm(uint16_t table,
-                            uint16_t nb_rb,
-                            uint8_t Nl,
-                            uint8_t C)
+			    uint16_t nb_rb,
+		            uint8_t Nl)
 {
 
   uint16_t R, nb_re;
@@ -99,7 +98,7 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
   uint8_t Qm;
   int i;
   uint32_t nr_tbs=0;
-  uint32_t Ninfo, Np_info;
+  uint32_t Ninfo, Np_info, C;
   uint8_t n;
 
   for (i=0; i<7; i++) {
@@ -117,27 +116,34 @@ uint32_t nr_compute_tbslbrm(uint16_t table,
   Ninfo = (nb_re * R * Qm * Nl)>>10;
 
   if (Ninfo <=3824) {
-    n = max(3, floor(log2(Ninfo)) - 6);
-    Np_info = max(24, (Ninfo>>n)<<n);
-    for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
-      if (Tbstable_nr[i] >= Np_info){
-        nr_tbs = Tbstable_nr[i];
-        break;
-      }
-    }
-  } else {
-    n = log2(Ninfo-24)-5;
-    Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
+    	n = max(3, floor(log2(Ninfo)) - 6);
+        Np_info = max(24, (Ninfo>>n)<<n);
+        for (int i=0; i<INDEX_MAX_TBS_TABLE; i++) {
+        	if (Tbstable_nr[i] >= Np_info){
+        		nr_tbs = Tbstable_nr[i];
+        		break;
+        	}
+        }
+  }
+  else {
+    	n = log2(Ninfo-24)-5;
+        Np_info = max(3840, (ROUNDIDIV((Ninfo-24),(1<<n)))<<n);
+
+        if (R <= 256) { 
+            C = CEILIDIV((Np_info+24),3816);
+            nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
+        }
+        else {
+            if (Np_info > 8424){
+                C = CEILIDIV((Np_info+24),8424);
+                nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
+            }
+            else {
+            	nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
+            }
+
+        }
 
-    if (R <= 256) {
-        nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
-    } else {
-      if (Np_info > 8424){
-          nr_tbs = (C<<3)*CEILIDIV((Np_info+24),(C<<3)) - 24;
-      } else {
-        nr_tbs = ((CEILIDIV((Np_info+24),8))<<3) - 24;
-      }
-    }
   }
   return nr_tbs;
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
index f7ccefa1c9797854a3a64925e1f4c97547db6960..fa31c1596d0615d1bfce5278024a8e238024d59c 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
@@ -975,7 +975,7 @@ void schedule_fapi_ul_pdu(int Mod_idP,
       if (get_softmodem_params()->phy_test==1)
         pusch_pdu->rb_size = 50;
       else
-        pusch_pdu->rb_size = 5;
+        pusch_pdu->rb_size = pusch_pdu->bwp_size;
     }
     else
       AssertFatal(1==0,"Only frequency resource allocation type 1 is currently supported\n");