diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index e9319f9d3c1070bc604662e481e352d26d4800f3..2bbabf3fe0f1ba6c1daae5405fbe4f05923282c4 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -113,15 +113,25 @@ time_stats_t softmodem_stats_rx_sf; // total rx time
 
 void tx_func(void *param) {
 
-  processingData_L1_t *info = (processingData_L1_t *) param;
+  processingData_L1tx_t *info = (processingData_L1tx_t *) param;
   PHY_VARS_gNB *gNB = info->gNB;
   int frame_tx = info->frame_tx;
   int slot_tx = info->slot_tx;
 
-  phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
+  phy_procedures_gNB_TX(info,
+                        frame_tx,
+                        slot_tx,
+                        1);
+  if ((frame_tx&127) == 0) dump_pdsch_stats(gNB);
 
-  // start FH TX processing
+  // If the later of the 2 L1 tx thread finishes first,
+  // we wait for the earlier one to finish and start the RU thread
+  // to avoid realtime issues with USRP
   notifiedFIFO_elt_t *res; 
+  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+  pushNotifiedFIFO(gNB->resp_L1_tx,res);
+
+  // Start RU TX processing.
   res = pullTpool(gNB->resp_RU_tx, gNB->threadPool);
   processingData_RU_t *syncMsg = (processingData_RU_t *)NotifiedFifoData(res);
   syncMsg->frame_tx = frame_tx;
@@ -257,7 +267,6 @@ void rx_func(void *param) {
   LOG_D(PHY,"%s() Exit proc[rx:%d%d tx:%d%d]\n", __FUNCTION__, frame_rx, slot_rx, frame_tx, slot_tx);
 
   // Call the scheduler
-
   start_meas(&gNB->ul_indication_stats);
   pthread_mutex_lock(&gNB->UL_INFO_mutex);
   gNB->UL_INFO.frame     = frame_rx;
@@ -269,10 +278,9 @@ void rx_func(void *param) {
   stop_meas(&gNB->ul_indication_stats);
   
   notifiedFIFO_elt_t *res; 
-
   if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT) {
     res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
-    processingData_L1_t *syncMsg = (processingData_L1_t *)NotifiedFifoData(res);
+    processingData_L1tx_t *syncMsg = (processingData_L1tx_t *)NotifiedFifoData(res);
     syncMsg->gNB = gNB;
     syncMsg->frame_rx = frame_rx;
     syncMsg->slot_rx = slot_rx;
@@ -327,7 +335,6 @@ static void *process_stats_thread(void *param) {
 
   PHY_VARS_gNB *gNB  = (PHY_VARS_gNB *)param;
 
-  reset_meas(&gNB->phy_proc_tx);
   reset_meas(&gNB->dlsch_encoding_stats);
   reset_meas(&gNB->phy_proc_rx);
   reset_meas(&gNB->ul_indication_stats);
@@ -339,7 +346,8 @@ static void *process_stats_thread(void *param) {
   while(!oai_exit)
   {
     sleep(1);
-    print_meas(&gNB->phy_proc_tx, "L1 Tx processing", NULL, NULL);
+    print_meas(gNB->phy_proc_tx_0, "L1 Tx processing thread 0", NULL, NULL);
+    print_meas(gNB->phy_proc_tx_1, "L1 Tx processing thread 1", NULL, NULL);
     print_meas(&gNB->dlsch_encoding_stats, "DLSCH encoding", NULL, NULL);
     print_meas(&gNB->phy_proc_rx, "L1 Rx processing", NULL, NULL);
     print_meas(&gNB->ul_indication_stats, "UL Indication", NULL, NULL);
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index be6d13daad99a6d8863032cb4b07551f46a53b7d..a01be1ebaa30f84f58d353f6c2a624516cec9cc3 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -1270,12 +1270,27 @@ void *ru_thread( void *param ) {
   wait_sync("ru_thread");
 
   notifiedFIFO_elt_t *msg = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1,rx_func);
-  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_L1_tx,tx_func);
-  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
-  processingData_L1_t *syncMsg;
-  notifiedFIFO_elt_t *res; 
   pushNotifiedFIFO(gNB->resp_L1,msg); // to unblock the process in the beginning
+
+  // we create 2 threads for L1 tx processing
+  notifiedFIFO_elt_t *msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  processingData_L1tx_t *msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  reset_meas(&msgDataTx->phy_proc_tx);
+  gNB->phy_proc_tx_0 = &msgDataTx->phy_proc_tx;
+  pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
+
+  msgL1Tx = newNotifiedFIFO_elt(sizeof(processingData_L1tx_t),0,gNB->resp_L1_tx,tx_func);
+  msgDataTx = (processingData_L1tx_t *)NotifiedFifoData(msgL1Tx);
+  init_DLSCH_struct(gNB, msgDataTx);
+  reset_meas(&msgTx->phy_proc_tx);
+  gNB->phy_proc_tx_1 = &msgDataTx->phy_proc_tx;
   pushNotifiedFIFO(gNB->resp_L1_tx,msgL1Tx); // to unblock the process in the beginning
+
+  processingData_L1_t *syncMsg;
+  notifiedFIFO_elt_t *res;
+
+  notifiedFIFO_elt_t *msgRUTx = newNotifiedFIFO_elt(sizeof(processingData_L1_t),0,gNB->resp_RU_tx,ru_tx_func);
   pushNotifiedFIFO(gNB->resp_RU_tx,msgRUTx); // to unblock the process in the beginning
 
   if(!emulate_rf) {
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 1c4b9bd09c9334ee0700c84798fc98b4479641ec..af878cb3dfa89c3cad79c6e159a9e177109a5df5 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -546,6 +546,20 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) {
   LOG_I(PHY,"gNB %d configured\n",Mod_id);
 }
 
+void init_DLSCH_struct(PHY_VARS_gNB *gNB, processingData_L1tx_t *msg) {
+  NR_DL_FRAME_PARMS *fp = &msg->gNB->frame_parms;
+  nfapi_nr_config_request_scf_t *cfg = &msg->gNB->gNB_config;
+  uint16_t grid_size = cfg->carrier_config.dl_grid_size[fp->numerology_index].value;
+  memset(msg->num_pdsch_rnti, 0, sizeof(uint16_t)*80);
+
+  for (i=0; i<NUMBER_OF_NR_DLSCH_MAX; i++) {
+    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,NUMBER_OF_NR_DLSCH_MAX);
+    for (j=0; j<2; j++) {
+      msg->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size);
+      AssertFatal(msg->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i);
+    }
+  }
+}
 
 void init_nr_transport(PHY_VARS_gNB *gNB) {
   int i;
@@ -570,16 +584,6 @@ void init_nr_transport(PHY_VARS_gNB *gNB) {
     AssertFatal(gNB->pucch[i]!=NULL,"Can't initialize pucch %d \n", i);
   }
 
-  for (i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-
-    LOG_I(PHY,"Allocating Transport Channel Buffers for DLSCH %d/%d\n",i,gNB->number_of_nr_dlsch_max);
-
-    for (j=0; j<2; j++) {
-      gNB->dlsch[i][j] = new_gNB_dlsch(fp,1,16,NSOFT,0,grid_size);
-      AssertFatal(gNB->dlsch[i][j]!=NULL,"Can't initialize dlsch %d \n", i);
-    }
-  }
-
   for (i=0; i<gNB->number_of_nr_ulsch_max; i++) {
 
     LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH  %d/%d\n",i,gNB->number_of_nr_ulsch_max);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 03bd0ddf6cffc715982fe69d38e95d597442b437..f043ce6551bdd72559178db627dd5dc941887fe5 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -111,10 +111,11 @@ void nr_pdsch_codeword_scrambling_optim(uint8_t *in,
 }
 
 
-uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
+uint8_t nr_generate_pdsch(processingData_L1tx_t *msgTx,
 			  int frame,
 			  int slot) {
 
+  PHY_VARS_gNB *gNB = msgTx->gNB;
   NR_gNB_DLSCH_t *dlsch;
   uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot];
   int32_t** txdataF = gNB->common_vars.txdataF;
@@ -132,9 +133,8 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
   time_stats_t *dlsch_interleaving_stats=&gNB->dlsch_interleaving_stats;
   time_stats_t *dlsch_segmentation_stats=&gNB->dlsch_segmentation_stats;
 
-  for (int dlsch_id=0;dlsch_id<gNB->number_of_nr_dlsch_max;dlsch_id++) {
-    dlsch = gNB->dlsch[dlsch_id][0];
-    if (dlsch->slot_tx[slot] == 0) continue;
+  for (int dlsch_id=0; dlsch_id<msgTx->num_pdsch_slot; dlsch_id++) {
+    dlsch = msgTx->dlsch[dlsch_id][0];
 
     NR_DL_gNB_HARQ_t *harq = &dlsch->harq_process;
     nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &harq->pdsch_pdu.pdsch_pdu_rel15;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
index 6af8f28eac15faab7a9b6c89f7273764100d5ed3..9f03d342616502a2dbd186136fef2cbb7b001bcb 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
@@ -63,9 +63,7 @@ void nr_pdsch_codeword_scrambling(uint8_t *in,
                                   uint32_t n_RNTI,
                                   uint32_t* out);
 
-void nr_fill_dlsch(PHY_VARS_gNB *gNB,
-                   int frame,
-                   int slot,
+void nr_fill_dlsch(processingData_L1tx_t *msgTx,
                    nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                    unsigned char *sdu); 
 
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
index 543002827d65b9f36e9414c11d36e0705161b5b3..dbf764324dbbd9f16b3a4f604e3cf7e55cf24690 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c
@@ -254,48 +254,20 @@ void nr_emulate_dlsch_payload(uint8_t* pdu, uint16_t size) {
     *(pdu+i) = (uint8_t)rand();
 }
 
-int16_t find_nr_dlsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) {
- 
-   uint16_t i;
-   int16_t first_free_index=-1;
- 
-   AssertFatal(gNB!=NULL,"gNB is null\n");
-   for (i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-     AssertFatal(gNB->dlsch[i]!=NULL,"gNB->dlsch[%d] is null\n",i);
-     AssertFatal(gNB->dlsch[i][0]!=NULL,"gNB->dlsch[%d][0] is null\n",i);
-     LOG_D(PHY,"searching for rnti %x : dlsch_index %d=> harq_mask %x, rnti %x, first_free_index %d\n", rnti,i,
-	   gNB->dlsch[i][0]->harq_mask,gNB->dlsch[i][0]->rnti,first_free_index);
-     if ((gNB->dlsch[i][0]->harq_mask >0) &&
-	 (gNB->dlsch[i][0]->rnti==rnti))       return i;
-     else if ((gNB->dlsch[i][0]->harq_mask == 0) && (first_free_index==-1)) first_free_index=i;
-   }
-   if (type == SEARCH_EXIST) return -1;
-   if (first_free_index != -1)
-     gNB->dlsch[first_free_index][0]->rnti = 0;
-   return first_free_index;
-   
-}
-
-
-void nr_fill_dlsch(PHY_VARS_gNB *gNB,
-                   int frame,
-                   int slot,
+void nr_fill_dlsch(processingData_L1tx_t *msgTx,
                    nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                    uint8_t *sdu) {
 
   nfapi_nr_dl_tti_pdsch_pdu_rel15_t *rel15 = &pdsch_pdu->pdsch_pdu_rel15;
  
-  int dlsch_id = find_nr_dlsch(rel15->rnti,gNB,SEARCH_EXIST);
-  AssertFatal( (dlsch_id>=0) && (dlsch_id<gNB->number_of_nr_dlsch_max),
-              "illegal or no dlsch_id found!!! rnti %04x dlsch_id %d\n",rel15->rnti,dlsch_id);
-  NR_gNB_DLSCH_t  *dlsch = gNB->dlsch[dlsch_id][0];
+  AssertFatal(msgTx->num_pdsch_slot < NUMBER_OF_NR_DLSCH_MAX,
+              "Number of PDSCH PDUs %d exceeded the limit\n",msgTx->num_pdsch_slot);
+  NR_gNB_DLSCH_t  *dlsch = msgTx->dlsch[msgTx->num_pdsch_slot][0];
   NR_DL_gNB_HARQ_t *harq  = &dlsch->harq_process;
   /// DLSCH struct
   memcpy((void*)&harq->pdsch_pdu, (void*)pdsch_pdu, sizeof(nfapi_nr_dl_tti_pdsch_pdu));
-  gNB->num_pdsch_rnti[slot]++;
+  msgTx->num_pdsch_slot++;
   AssertFatal(sdu!=NULL,"sdu is null\n");
   harq->pdu = sdu;
-
-
 }
 
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index d1fb886341ee5a494862525234fbe6b626eba548..9aea468a0ddab31738ae5360b82e1484a31bec83 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -759,7 +759,6 @@ typedef struct PHY_VARS_gNB_s {
   //  nfapi_nr_dl_tti_pdcch_pdu    *pdcch_pdu;
   //  nfapi_nr_ul_dci_request_pdus_t  *ul_dci_pdu;
   uint16_t num_pdsch_rnti[80];
-  NR_gNB_SSB_t       ssb[64];
   NR_gNB_PBCH        pbch;
   nr_cce_t           cce_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL];
   NR_gNB_COMMON      common_vars;
@@ -850,7 +849,8 @@ typedef struct PHY_VARS_gNB_s {
   /*
   time_stats_t phy_proc;
   */
-  time_stats_t phy_proc_tx;
+  time_stats_t *phy_proc_tx_0;
+  time_stats_t *phy_proc_tx_1;
   time_stats_t phy_proc_rx;
   time_stats_t rx_prach;
   /*
@@ -940,6 +940,21 @@ typedef struct processingData_L1 {
   int slot_tx;
   openair0_timestamp timestamp_tx;
   PHY_VARS_gNB *gNB;
-} processingData_L1_t;
+};
+
+typedef struct processingData_L1tx {
+  int frame_rx;
+  int frame_tx;
+  int slot_rx;
+  int slot_tx;
+  openair0_timestamp timestamp_tx;
+  PHY_VARS_gNB *gNB;
+  nfapi_nr_dl_tti_pdcch_pdu pdcch_pdu;
+  nfapi_nr_ul_dci_request_pdus_t ul_pdcch_pdu;
+  NR_gNB_DLSCH_t *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];
+  NR_gNB_SSB_t ssb[64];
+  uint16_t num_pdsch_slot;
+  time_stats_t phy_proc_tx;
+} processingData_L1tx_t;
 
 #endif
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index bac52845ff9a9815a70be2cc01a52f2797b39b1f..99eaedd1e0cad967e547496705aa5b435127629b 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -43,7 +43,7 @@ extern int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req);
 
 extern uint8_t nfapi_mode;
 
-void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot,
                              nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu)
 {
 
@@ -53,11 +53,11 @@ void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
   uint8_t i_ssb = dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.SsbBlockIndex;
 
   LOG_D(PHY,"%d.%d : ssb index %d pbch_pdu: %x\n",frame,slot,i_ssb,dl_tti_pdu->ssb_pdu.ssb_pdu_rel15.bchPayload);
-  if (gNB->ssb[i_ssb].active)
+  if (msgTx->ssb[i_ssb].active)
     AssertFatal(1==0,"SSB PDU with index %d already active\n",i_ssb);
   else {
-    gNB->ssb[i_ssb].active = true;
-    memcpy((void*)&gNB->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu));
+    msgTx->ssb[i_ssb].active = true;
+    memcpy((void*)&msgTx->ssb[i_ssb].ssb_pdu,&dl_tti_pdu->ssb_pdu,sizeof(dl_tti_pdu->ssb_pdu));
   }
 }
 
@@ -127,7 +127,6 @@ void handle_nfapi_nr_ul_dci_pdu(PHY_VARS_gNB *gNB,
 
 }
 
-
 void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
 			       int frame, int slot,
 			       nfapi_nr_dl_tti_csi_rs_pdu *csirs_pdu) {
@@ -151,13 +150,13 @@ void handle_nfapi_nr_csirs_pdu(PHY_VARS_gNB *gNB,
 }
 
 
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
                             nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu)
 {
 
 
-  nr_fill_dlsch(gNB,frame,slot,pdsch_pdu,sdu);
+  nr_fill_dlsch(msgTx,pdsch_pdu,sdu);
 
 }
 
@@ -178,12 +177,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
 
   gNB         = RC.gNB[Mod_id];
 
-  // we wait for the L1 Tx processing to finish before copying MAC PDUs to PHY
-  {
-    notifiedFIFO_elt_t *res;
-    res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
-    pushNotifiedFIFO(gNB->resp_L1_tx,res);
-  }
+  notifiedFIFO_elt_t *res;
+  res = pullTpool(gNB->resp_L1_tx, gNB->threadPool);
+  processingData_L1tx_t *msgTx = (processingData_L1tx_t *)NotifiedFifoData(res);
 
   uint8_t number_dl_pdu             = (DL_req==NULL) ? 0 : DL_req->dl_tti_request_body.nPDUs;
   uint8_t number_ul_dci_pdu         = (UL_dci_req==NULL) ? 0 : UL_dci_req->numPdus;
@@ -197,11 +193,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
 	  number_ul_dci_pdu,number_ul_tti_pdu);
 
   int pdcch_received=0;
-  gNB->num_pdsch_rnti[slot]=0;
-  for (int i=0; i<gNB->number_of_nr_dlsch_max; i++) {
-    gNB->dlsch[i][0]->rnti=0;
-    gNB->dlsch[i][0]->harq_mask=0;
-  }
+  msgTx->num_pdsch_slot=0;
 
   for (int i=0;i<number_dl_pdu;i++) {
     nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu = &DL_req->dl_tti_request_body.dl_tti_pdu_list[i];
@@ -210,7 +202,7 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
       case NFAPI_NR_DL_TTI_SSB_PDU_TYPE:
 
         if(NFAPI_MODE != NFAPI_MODE_VNF)
-        handle_nr_nfapi_ssb_pdu(gNB,frame,slot,
+        handle_nr_nfapi_ssb_pdu(msgTx,frame,slot,
                                 dl_tti_pdu);
 
       break;
@@ -218,11 +210,9 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
       case NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE:
 	AssertFatal(pdcch_received == 0, "pdcch_received is not 0, we can only handle one PDCCH PDU per slot\n");
         if(NFAPI_MODE != NFAPI_MODE_VNF)
-        handle_nfapi_nr_pdcch_pdu(gNB,
-				  frame, slot,
-				  &dl_tti_pdu->pdcch_pdu);
+          msgTx->pdcch_pdu = dl_tti_pdu->pdcch_pdu;
  
-	pdcch_received = 1;
+        pdcch_received = 1;
 
       break;
       case NFAPI_NR_DL_TTI_CSI_RS_PDU_TYPE:
@@ -241,16 +231,15 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
 		    pduIndex,TX_req->pdu_list[pduIndex].num_TLV);
         uint8_t *sdu = (uint8_t *)TX_req->pdu_list[pduIndex].TLVs[0].value.direct;
         if(NFAPI_MODE != NFAPI_MODE_VNF)
-        handle_nr_nfapi_pdsch_pdu(gNB,frame,slot,&dl_tti_pdu->pdsch_pdu, sdu);
+        handle_nr_nfapi_pdsch_pdu(msgTx,&dl_tti_pdu->pdsch_pdu, sdu);
       }
     }
   }
 
-  //  if (UL_tti_req!=NULL) memcpy(&gNB->UL_tti_req,UL_tti_req,sizeof(nfapi_nr_ul_tti_request_t));
   if(NFAPI_MODE != NFAPI_MODE_VNF)
-    for (int i=0;i<number_ul_dci_pdu;i++) {
-      handle_nfapi_nr_ul_dci_pdu(gNB, frame, slot, &UL_dci_req->ul_dci_pdu_list[i]);
-    }
+    msgTx->ul_pdcch_pdu = UL_dci_req->ul_dci_pdu_list[number_ul_dci_pdu-1]; // copy the last pdu
+
+  pushNotifiedFIFO(gNB->resp_L1_tx,res);
 
   if(NFAPI_MODE != NFAPI_MODE_VNF)
     for (int i = 0; i < number_ul_tti_pdu; i++) {
diff --git a/openair1/SCHED_NR/fapi_nr_l1.h b/openair1/SCHED_NR/fapi_nr_l1.h
index 19c98e4ec00515465bea4c99468a0fadcadfdac7..3dbbf5f450358c021c9ebbe711fe47f11014790e 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.h
+++ b/openair1/SCHED_NR/fapi_nr_l1.h
@@ -37,7 +37,7 @@
 #include "nfapi_nr_interface_scf.h"
 
 // added
-void handle_nr_nfapi_ssb_pdu(PHY_VARS_gNB *gNB,
+void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,
 						int frame,int slot,
 						nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu);
 
@@ -51,7 +51,7 @@ void handle_nfapi_nr_pdcch_pdu(PHY_VARS_gNB *gNB,
 			       int frame, int subframe,
 			       nfapi_nr_dl_tti_pdcch_pdu *dcl_dl_pdu);
 
-void handle_nr_nfapi_pdsch_pdu(PHY_VARS_gNB *gNB,int frame,int slot,
+void handle_nr_nfapi_pdsch_pdu(processingData_L1tx_t *msgTx,
 			       nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
                             uint8_t *sdu);
 
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 6fa37fcd996012bce1f30bd2b69d8bc2b496de95..3ba66db73d380ca1e4724eabbcecabfe2704b2c1 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -124,10 +124,12 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_
 }
 
 
-void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
-                           int frame,int slot,
+void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
+                           int frame,
+                           int slot,
                            int do_meas) {
   int aa;
+  PHY_VARS_gNB *gNB = msgTx->gNB,
   NR_DL_FRAME_PARMS *fp=&gNB->frame_parms;
   nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config;
   int offset = gNB->CC_id;
@@ -138,7 +140,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,1);
 
-  if (do_meas==1) start_meas(&gNB->phy_proc_tx);
+  if (do_meas==1) start_meas(gNB->phy_proc_tx);
 
   // clear the transmit data array and beam index for the current slot
   for (aa=0; aa<cfg->carrier_config.num_tx_ant.value; aa++) {
@@ -149,56 +151,48 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,1);
   if (NFAPI_MODE == NFAPI_MONOLITHIC || NFAPI_MODE == NFAPI_MODE_PNF) { 
     for (int i=0; i<fp->Lmax; i++) {
-      if (gNB->ssb[i].active) {
-        nr_common_signal_procedures(gNB,frame,slot,gNB->ssb[i].ssb_pdu);
-        gNB->ssb[i].active = false;
+      if (msgTx->ssb[i].active) {
+        nr_common_signal_procedures(gNB,frame,slot,msgTx->ssb[i].ssb_pdu);
+        msgTx->ssb[i].active = false;
       }
     }
   }
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_COMMON_TX,0);
 
-  int pdcch_pdu_id=find_nr_pdcch(frame,slot,gNB,SEARCH_EXIST);
-  int ul_pdcch_pdu_id=find_nr_ul_dci(frame,slot,gNB,SEARCH_EXIST);
-
   LOG_D(PHY,"[gNB %d] Frame %d slot %d, pdcch_pdu_id %d, ul_pdcch_pdu_id %d\n",
 	gNB->Mod_id,frame,slot,pdcch_pdu_id,ul_pdcch_pdu_id);
 
+  int num_ul_dci = msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
+  int num_dl_dci = msgTx->pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci;
+
   if (pdcch_pdu_id >= 0 || ul_pdcch_pdu_id >= 0) {
     LOG_D(PHY, "[gNB %d] Frame %d slot %d Calling nr_generate_dci_top (number of UL/DL DCI %d/%d)\n",
-	  gNB->Mod_id, frame, slot,
-	  gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu.pdcch_pdu_rel15.numDlDci,
-	  gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu.pdcch_pdu_rel15.numDlDci);
+	  gNB->Mod_id, frame, slot, num_dl_dci, num_ul_dci);
   
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,1);
 
     nr_generate_dci_top(gNB,
-			pdcch_pdu_id>=0 ? &gNB->pdcch_pdu[pdcch_pdu_id].pdcch_pdu : NULL,
-			ul_pdcch_pdu_id>=0 ? &gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].pdcch_pdu.pdcch_pdu : NULL,
+			num_dl_dci > 0 ? &msgTx->pdcch_pdu.pdcch_pdu : NULL,
+			num_ul_dci > 0 ? &msgTx->ul_pdcch_pdu.pdcch_pdu.pdcch_pdu : NULL,
 			gNB->nr_gold_pdcch_dmrs[slot],
 			&gNB->common_vars.txdataF[0][txdataF_offset],
 			AMP, fp);
 
-    // free up entry in pdcch tables
-    if (pdcch_pdu_id>=0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
-    if (ul_pdcch_pdu_id>=0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;
-
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_gNB_PDCCH_TX,0);
-    if (pdcch_pdu_id >= 0) gNB->pdcch_pdu[pdcch_pdu_id].frame = -1;
-    if (ul_pdcch_pdu_id >= 0) gNB->ul_pdcch_pdu[ul_pdcch_pdu_id].frame = -1;
   }
  
-  for (int i=0; i<gNB->num_pdsch_rnti[slot]; i++) {
+  for (int i=0; i<msgTx->num_pdsch_slot; i++) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,1);
-    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", gNB->num_pdsch_rnti[slot],frame,slot);
-    nr_generate_pdsch(gNB,frame, slot);
+    LOG_D(PHY, "PDSCH generation started (%d) in frame %d.%d\n", msgTx->num_pdsch_slot,frame,slot);
+    nr_generate_pdsch(msgTx, frame, slot);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DLSCH,0);
   }
 
   for (int i=0;i<NUMBER_OF_NR_CSIRS_MAX;i++){
     NR_gNB_CSIRS_t *csirs = &gNB->csirs_pdu[i];
     if ((csirs->active == 1) &&
-	(csirs->frame == frame) &&
-	(csirs->slot == slot) ) {
+        (csirs->frame == frame) &&
+        (csirs->slot == slot) ) {
       LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
       nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = csirs->csirs_pdu.csi_rs_pdu_rel15;
       nr_generate_csi_rs(gNB, AMP, csi_params, gNB->gNB_config.cell_config.phy_cell_id.value, slot);
@@ -206,7 +200,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
     }
   }
 
-  if (do_meas==1) stop_meas(&gNB->phy_proc_tx);
+  if (do_meas==1) stop_meas(gNB->phy_proc_tx);
 
   if ((frame&127) == 0) dump_pdsch_stats(gNB);