diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index f1ffda9119dfc42a43994885835eecc61301bb86..5fc5add8c539a0b4e029763a82f96f178e59c2b8 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1257,6 +1257,7 @@ set(PHY_SRC_UE
   ${RRC_FULL_DIR}/asn1_constants.h
   # actual source
   ${OPENAIR1_DIR}/PHY/INIT/nr_init.c
+  ${OPENAIR1_DIR}/PHY/INIT/nr_init_ru.c
   ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_pss.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sss.c
diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c
new file mode 100644
index 0000000000000000000000000000000000000000..a5722196adee6926c5b40aebec491663418ee0cc
--- /dev/null
+++ b/openair1/PHY/INIT/nr_init_ru.c
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#include "defs.h"
+#include "SCHED/defs.h"
+#include "PHY/extern.h"
+#include "SIMULATION/TOOLS/defs.h"
+#include "RadioResourceConfigCommonSIB.h"
+#include "RadioResourceConfigDedicated.h"
+#include "TDD-Config.h"
+#include "LAYER2/MAC/extern.h"
+#include "MBSFN-SubframeConfigList.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "assertions.h"
+#include <math.h>
+
+int nr_phy_init_RU(RU_t *ru) {
+
+  NR_DL_FRAME_PARMS *fp = &ru->nr_frame_parms;
+  int i,j;
+  int p;
+  int re;
+
+  LOG_I(PHY,"Initializing RU signal buffers (if_south %s) nb_tx %d\n",ru_if_types[ru->if_south],ru->nb_tx);
+
+  if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so allocate memory for time-domain signals 
+    // Time-domain signals
+    ru->common.txdata        = (int32_t**)malloc16(ru->nb_tx*sizeof(int32_t*));
+    ru->common.rxdata        = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
+
+
+    for (i=0; i<ru->nb_tx; i++) {
+      // Allocate 10 subframes of I/Q TX signal data (time) if not
+      ru->common.txdata[i]  = (int32_t*)malloc16_clear( fp->samples_per_frame_wCP*sizeof(int32_t) );
+
+      LOG_I(PHY,"[INIT] common.txdata[%d] = %p (%lu bytes)\n",i,ru->common.txdata[i],
+	     fp->samples_per_subframe_wCP*sizeof(int32_t));
+
+    }
+    for (i=0;i<ru->nb_rx;i++) {
+      ru->common.rxdata[i] = (int32_t*)malloc16_clear( fp->samples_per_frame_wCP*sizeof(int32_t) );
+    }
+  } // IF5 or local RF
+  else {
+    //    LOG_I(PHY,"No rxdata/txdata for RU\n");
+    ru->common.txdata        = (int32_t**)NULL;
+    ru->common.rxdata        = (int32_t**)NULL;
+
+  }
+  if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing
+    LOG_I(PHY,"nb_tx %d\n",ru->nb_tx);
+    ru->common.rxdata_7_5kHz = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
+    for (i=0;i<ru->nb_rx;i++) {
+      ru->common.rxdata_7_5kHz[i] = (int32_t*)malloc16_clear( 2*fp->samples_per_subframe_wCP*2*sizeof(int32_t) );
+      LOG_I(PHY,"rxdata_7_5kHz[%d] %p for RU %d\n",i,ru->common.rxdata_7_5kHz[i],ru->idx);
+    }
+  
+
+    // allocate IFFT input buffers (TX)
+    ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
+    LOG_I(PHY,"[INIT] common.txdata_BF= %p (%lu bytes)\n",ru->common.txdataF_BF,
+	  ru->nb_tx*sizeof(int32_t*));
+    for (i=0; i<ru->nb_tx; i++) {
+      ru->common.txdataF_BF[i] = (int32_t*)malloc16_clear(fp->samples_per_subframe_wCP*sizeof(int32_t) );
+      LOG_I(PHY,"txdataF_BF[%d] %p for RU %d\n",i,ru->common.txdataF_BF[i],ru->idx);
+    }
+    // allocate FFT output buffers (RX)
+    ru->common.rxdataF     = (int32_t**)malloc16(ru->nb_rx*sizeof(int32_t*) );
+    for (i=0; i<ru->nb_rx; i++) {    
+      // allocate 2 subframes of I/Q signal data (frequency)
+      ru->common.rxdataF[i] = (int32_t*)malloc16_clear(sizeof(int32_t)*(2*fp->samples_per_subframe_wCP) ); 
+      LOG_I(PHY,"rxdataF[%d] %p for RU %d\n",i,ru->common.rxdataF[i],ru->idx);
+    }
+
+    /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
+    //    AssertFatal(ru->nb_rx <= sizeof(ru->prach_rxsigF) / sizeof(ru->prach_rxsigF[0]),
+    //		"nb_antennas_rx too large");
+    ru->prach_rxsigF = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*));
+    for (j=0;j<4;j++) ru->prach_rxsigF_br[j] = (int16_t**)malloc(ru->nb_rx * sizeof(int16_t*));
+
+    for (i=0; i<ru->nb_rx; i++) {
+      ru->prach_rxsigF[i] = (int16_t*)malloc16_clear( fp->ofdm_symbol_size*12*2*sizeof(int16_t) );
+      LOG_D(PHY,"[INIT] prach_vars->rxsigF[%d] = %p\n",i,ru->prach_rxsigF[i]);
+    }
+    
+    AssertFatal(RC.nb_L1_inst <= NUMBER_OF_eNB_MAX,"gNB instances %d > %d\n",
+		RC.nb_L1_inst,NUMBER_OF_eNB_MAX);
+
+    LOG_E(PHY,"[INIT] %s() RC.nb_L1_inst:%d \n", __FUNCTION__, RC.nb_L1_inst);
+
+    for (i=0; i<RC.nb_L1_inst; i++) {
+      for (p=0;p<15;p++) {
+        LOG_D(PHY,"[INIT] %s() nb_antenna_ports_eNB:%d \n", __FUNCTION__, ru->gNB_list[i]->gNB_config.rf_config.tx_antenna_ports.value);
+	if (p<ru->gNB_list[i]->gNB_config.rf_config.tx_antenna_ports.value || p==5) {
+          LOG_D(PHY,"[INIT] %s() DO BEAM WEIGHTS nb_antenna_ports_eNB:%d nb_tx:%d\n", __FUNCTION__, ru->gNB_list[i]->gNB_config.rf_config.tx_antenna_ports.value, ru->nb_tx);
+	  ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
+	  for (j=0; j<ru->nb_tx; j++) {
+	    ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
+	    // antenna ports 0-3 are mapped on antennas 0-3
+	    // antenna port 4 is mapped on antenna 0
+	    // antenna ports 5-14 are mapped on all antennas 
+	    if (((p<4) && (p==j)) || ((p==4) && (j==0))) {
+	      for (re=0; re<fp->ofdm_symbol_size; re++) 
+              {
+		ru->beam_weights[i][p][j][re] = 0x00007fff; 
+
+                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
+              }
+	    }
+	    else if (p>4) {
+	      for (re=0; re<fp->ofdm_symbol_size; re++) 
+              {
+		ru->beam_weights[i][p][j][re] = 0x00007fff/ru->nb_tx; 
+                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
+              }
+	    }  
+	    //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d] = %p (%lu bytes)\n", i,j,ru->beam_weights[i][p][j], fp->ofdm_symbol_size*sizeof(int32_t)); 
+	  } // for (j=0
+	} // if (p<ru
+      } // for p
+    } //for i
+  } // !=IF5
+  ru->common.sync_corr = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_subframe_wCP );
+
+  return(0);
+}
+
+void nr_phy_free_RU(RU_t *ru)
+{
+  int i,j;
+  int p;
+
+  LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
+
+  if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
+    for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]);
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata[i]);
+    free_and_zero(ru->common.txdata);
+    free_and_zero(ru->common.rxdata);
+  } // else: IF5 or local RF -> nothing to free()
+
+  if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata_7_5kHz[i]);
+    free_and_zero(ru->common.rxdata_7_5kHz);
+
+    // free IFFT input buffers (TX)
+    for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdataF_BF[i]);
+    free_and_zero(ru->common.txdataF_BF);
+
+    // free FFT output buffers (RX)
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdataF[i]);
+    free_and_zero(ru->common.rxdataF);
+
+    for (i = 0; i < ru->nb_rx; i++) {
+      free_and_zero(ru->prach_rxsigF[i]);
+    }
+    for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j]);
+    free_and_zero(ru->prach_rxsigF);
+    /* ru->prach_rxsigF_br is not allocated -> don't free */
+
+    for (i = 0; i < RC.nb_L1_inst; i++) {
+      for (p = 0; p < 15; p++) {
+	if (p < ru->gNB_list[i]->gNB_config.rf_config.tx_antenna_ports.value || p == 5) {
+	  for (j=0; j<ru->nb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]);
+	  free_and_zero(ru->beam_weights[i][p]);
+	}
+      }
+    }
+  }
+  free_and_zero(ru->common.sync_corr);
+}
diff --git a/targets/RT/USER/nr-ru.c b/targets/RT/USER/nr-ru.c
index e9537b625ef18a07ac7347747f05a18f76807c6a..970443f6b77510cb8701c40dcc0061f433d542df 100644
--- a/targets/RT/USER/nr-ru.c
+++ b/targets/RT/USER/nr-ru.c
@@ -122,8 +122,8 @@ static int DEFENBS[] = {0};
 extern volatile int                    oai_exit;
 
 
-extern void  phy_init_RU(RU_t*);
-extern void  phy_free_RU(RU_t*);
+extern void  nr_phy_init_RU(RU_t*);
+extern void  nr_phy_free_RU(RU_t*);
 
 void init_RU(char*);
 void stop_RU(int nb_ru);
@@ -1376,7 +1376,7 @@ static void* ru_thread( void* param ) {
     fill_rf_config(ru,ru->rf_config_file);
     nr_init_frame_parms(ru->gNB_list[0]->gNB_config, fp);
     nr_dump_frame_parms(fp);
-    phy_init_RU(ru);
+    nr_phy_init_RU(ru);
 
     ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
   }
@@ -1863,7 +1863,7 @@ void configure_ru(int idx,
 	  config->prach_FreqOffset[0],config->prach_ConfigIndex[0]);*/
 
   nr_init_frame_parms(&ru->gNB_list[0]->gNB_config, &ru->nr_frame_parms);
-  phy_init_RU(ru);
+  nr_phy_init_RU(ru);
 }
 
 void configure_rru(int idx,
@@ -1905,7 +1905,7 @@ void configure_rru(int idx,
   fill_rf_config(ru,ru->rf_config_file);
 
 
-  phy_init_RU(ru);
+  nr_phy_init_RU(ru);
 
 }
 
@@ -2016,7 +2016,7 @@ void set_function_spec_param(RU_t *ru)
     if (ru->function == gNodeB_3GPP) { // configure RF parameters only for 3GPP eNodeB, we need to get them from RAU otherwise
       fill_rf_config(ru,rf_config_file);
       init_frame_parms(&ru->frame_parms,1);
-      phy_init_RU(ru);
+      nr_phy_init_RU(ru);
     }
 
     ret = openair0_device_load(&ru->rfdevice,&ru->openair0_cfg);
diff --git a/targets/RT/USER/nr-softmodem.c b/targets/RT/USER/nr-softmodem.c
index e4e8a3046d40e5938732f686537a9f55cbcfe32f..d7c1ef000fa87efc339abe93f92c82489d10dbbc 100644
--- a/targets/RT/USER/nr-softmodem.c
+++ b/targets/RT/USER/nr-softmodem.c
@@ -782,7 +782,7 @@ void terminate_task(task_id_t task_id, module_id_t mod_id)
 }
 
 //extern void  free_transport(PHY_VARS_gNB *);
-extern void  phy_free_RU(RU_t*);
+extern void  nr_phy_free_RU(RU_t*);
 
 int stop_L1L2(module_id_t gnb_id)
 {
@@ -825,7 +825,7 @@ int stop_L1L2(module_id_t gnb_id)
     //free_transport(RC.gNB[gnb_id][cc_id]);
     phy_free_nr_gNB(RC.gNB[gnb_id][cc_id]);
   }
-  phy_free_RU(RC.ru[gnb_id]);
+  nr_phy_free_RU(RC.ru[gnb_id]);
   free_lte_top();
   return 0;
 }
@@ -1283,7 +1283,7 @@ int main( int argc, char **argv )
       }
     }
     for (int inst = 0; inst < NB_RU; inst++) {
-      phy_free_RU(RC.ru[inst]);
+      nr_phy_free_RU(RC.ru[inst]);
     }
     free_lte_top();