diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 83b9eb7c2f02646e663d232f7efed57f78bb8678..5431febae0003d353f8a6391a6080eceef5e43da 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -239,6 +239,7 @@ add_boolean_option(UE_AUTOTEST_TRACE   False "Activate UE autotest specific logs
 add_boolean_option(UE_DEBUG_TRACE      False "Activate UE debug trace")
 add_boolean_option(UE_TIMING_TRACE     False "Activate UE timing trace")
 add_boolean_option(DISABLE_LOG_X       False "Deactivate all LOG_* macros")
+add_boolean_option(UE_NR_PHY_DEMO      False "Activate UE NR functionalities for PHY demo")
 
 add_boolean_option(DEBUG_CONSOLE False "makes debugging easier, disables stdout/stderr buffering")
 
diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai
index d4ced88c31d66b979942bffaa3838e52fc661d9a..ecaa2318c2805ac15b8ffd9a4bfc6a5cd107dae2 100755
--- a/cmake_targets/build_oai
+++ b/cmake_targets/build_oai
@@ -66,6 +66,7 @@ UE_AUTOTEST_TRACE="False"
 UE_DEBUG_TRACE="False"
 UE_TIMING_TRACE="False"
 DISABLE_LOG_X="False"
+UE_NR_PHY_DEMO="False"
 BUILD_ECLIPSE=0
 trap handle_ctrl_c INT
 
@@ -337,6 +338,10 @@ function main() {
             DISABLE_LOG_X="True"
             echo_info "Disabling all LOG_* traces"
             shift 1;;
+        --ue-nr-phy-demo)
+            UE_NR_PHY_DEMO="True"
+            echo_info "Enabling UE NR functionalities for PHY demo"
+            shift 1;;
         --uhd-images-dir)
             UHD_IMAGES_DIR=$2
             echo_info "Downloading UHD images in the indicated location"
@@ -528,6 +533,7 @@ function main() {
     echo "set (UE_DEBUG_TRACE $UE_DEBUG_TRACE)"        >>  $cmake_file
     echo "set (UE_TIMING_TRACE $UE_TIMING_TRACE)"        >>  $cmake_file
     echo "set (DISABLE_LOG_X $DISABLE_LOG_X)"        >>  $cmake_file
+    echo "set (UE_NR_PHY_DEMO $UE_NR_PHY_DEMO)"        >>  $cmake_file
     if [ "$UE" = 1 -a "$NOS1" = "0" ] ; then
      echo_info "Compiling UE S1 build : enabling Linux and NETLINK"
      echo "set (LINUX True )"              >>  $cmake_file
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 04611f7b560de9e9f8cda568b4816c9844f74b30..a74fef3bc297c09d7a5578b4485698a2f69931ee 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -1137,7 +1137,7 @@ int phy_init_lte_ue(PHY_VARS_UE *ue,
 
     for (i=0; i<fp->nb_antennas_tx; i++) {
 
-      common_vars->txdata[i]  = (int32_t*)malloc16_clear( fp->samples_per_tti*10*sizeof(int32_t) );
+      common_vars->txdata[i]  = (int32_t*)malloc16_clear( fp->samples_per_subframe*10*sizeof(int32_t) );
       common_vars->txdataF[i] = (int32_t *)malloc16_clear( fp->ofdm_symbol_size*fp->symbols_per_tti*10*sizeof(int32_t) );
     }
 
@@ -1149,7 +1149,7 @@ int phy_init_lte_ue(PHY_VARS_UE *ue,
     }
 
     for (i=0; i<fp->nb_antennas_rx; i++) {
-      common_vars->rxdata[i] = (int32_t*) malloc16_clear( (fp->samples_per_tti*10+2048)*sizeof(int32_t) );
+      common_vars->rxdata[i] = (int32_t*) malloc16_clear( (fp->samples_per_subframe*10+2048)*sizeof(int32_t) );
       for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
           common_vars->common_vars_rx_data_per_thread[th_id].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) );
       }
diff --git a/openair1/PHY/INIT/lte_parms.c b/openair1/PHY/INIT/lte_parms.c
index 730371dd616af8963d3d793152d18db11eaabcd6..9d259ae749efd21d1f6a5e5b76eacea9e01404a5 100644
--- a/openair1/PHY/INIT/lte_parms.c
+++ b/openair1/PHY/INIT/lte_parms.c
@@ -54,6 +54,12 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
     frame_parms->nb_prefix_samples0=512;
     frame_parms->nb_prefix_samples = 512;
     frame_parms->symbols_per_tti = 12;
+#ifdef UE_NR_PHY_DEMO
+    // Only numerology 2 is supported for Extended Cyclic Prefix
+    frame_parms->numerology_index = 2;
+    frame_parms->ttis_per_subframe = 4;
+    frame_parms->slots_per_tti = 2; //only slot config 1 is supported
+#endif
   } else {
     frame_parms->nb_prefix_samples0 = 160;
     frame_parms->nb_prefix_samples = 144;
@@ -98,7 +104,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
 
     if (frame_parms->threequarter_fs) {
       frame_parms->ofdm_symbol_size = 1536;
-      frame_parms->samples_per_tti = 23040;
+      frame_parms->samples_per_subframe = 23040;
+      frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
       frame_parms->first_carrier_offset = 1536-600;
       frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2;
       frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2;
@@ -106,6 +113,11 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
     else {
       frame_parms->ofdm_symbol_size = 2048;
       frame_parms->samples_per_tti = 30720;
+#ifdef UE_NR_PHY_DEMO
+      frame_parms->samples_per_subframe = 30720 * frame_parms->ttis_per_subframe;
+#else
+      frame_parms->samples_per_subframe = 30720;
+#endif
       frame_parms->first_carrier_offset = 2048-600;
     }
     frame_parms->N_RBGS = 4;
@@ -120,7 +132,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
 
 
     frame_parms->ofdm_symbol_size = 1536;
-    frame_parms->samples_per_tti = 23040;
+    frame_parms->samples_per_subframe = 23040;
+    frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
     frame_parms->first_carrier_offset = 1536-450;
     frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2;
     frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2;
@@ -135,7 +148,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
     }
 
     frame_parms->ofdm_symbol_size = 1024*osf;
-    frame_parms->samples_per_tti = 15360*osf;
+    frame_parms->samples_per_subframe = 15360*osf;
+    frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
     frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 300;
     frame_parms->nb_prefix_samples>>=(1-log2_osf);
     frame_parms->nb_prefix_samples0>>=(1-log2_osf);
@@ -152,7 +166,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
     frame_parms->ofdm_symbol_size = 512*osf;
 
 
-    frame_parms->samples_per_tti = 7680*osf;
+    frame_parms->samples_per_subframe = 7680*osf;
+    frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
     frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 150;
     frame_parms->nb_prefix_samples>>=(2-log2_osf);
     frame_parms->nb_prefix_samples0>>=(2-log2_osf);
@@ -164,7 +179,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
 
   case 15:
     frame_parms->ofdm_symbol_size = 256*osf;
-    frame_parms->samples_per_tti = 3840*osf;
+    frame_parms->samples_per_subframe = 3840*osf;
+    frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
     frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 90;
     frame_parms->nb_prefix_samples>>=(3-log2_osf);
     frame_parms->nb_prefix_samples0>>=(3-log2_osf);
@@ -174,7 +190,8 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf)
 
   case 6:
     frame_parms->ofdm_symbol_size = 128*osf;
-    frame_parms->samples_per_tti = 1920*osf;
+    frame_parms->samples_per_subframe = 1920*osf;
+    frame_parms->samples_per_tti = frame_parms->samples_per_subframe;
     frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 36;
     frame_parms->nb_prefix_samples>>=(4-log2_osf);
     frame_parms->nb_prefix_samples0>>=(4-log2_osf);
@@ -217,5 +234,6 @@ void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms)
   printf("frame_parms->nb_prefix_samples0=%d\n",frame_parms->nb_prefix_samples0);
   printf("frame_parms->first_carrier_offset=%d\n",frame_parms->first_carrier_offset);
   printf("frame_parms->samples_per_tti=%d\n",frame_parms->samples_per_tti);
+  printf("frame_parms->samples_per_subframe=%d\n",frame_parms->samples_per_subframe);
   printf("frame_parms->symbols_per_tti=%d\n",frame_parms->symbols_per_tti);
 }
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
index 6ce10723c67909058352cb4ec2b8756068de8174..2046476e5f85ebf92b0e8520d10cc550bbee7fcf 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
@@ -53,9 +53,9 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms )   // LTE_UE_COMMON *com
 
   int i,k;
 
-  sync_corr_ue0 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti);
-  sync_corr_ue1 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti);
-  sync_corr_ue2 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti);
+  sync_corr_ue0 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_subframe);
+  sync_corr_ue1 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_subframe);
+  sync_corr_ue2 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_subframe);
 
   if (sync_corr_ue0) {
 #ifdef DEBUG_PHY
@@ -353,7 +353,7 @@ int lte_sync_time(int **rxdata, ///rx data in time domain
   int result,result2;
   int sync_out[3] = {0,0,0},sync_out2[3] = {0,0,0};
   int tmp[3] = {0,0,0};
-  int length =   LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti>>1;
+  int length =   LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe>>1;
 
   //msg("[SYNC TIME] Calling sync_time.\n");
   if (sync_corr_ue0 == NULL) {
@@ -381,7 +381,7 @@ int lte_sync_time(int **rxdata, ///rx data in time domain
 #ifdef RTAI_ENABLED
 
     // This is necessary since the sync takes a long time and it seems to block all other threads thus screwing up RTAI. If we pause it for a little while during its execution we give RTAI a chance to catch up with its other tasks.
-    if ((n%frame_parms->samples_per_tti == 0) && (n>0) && (openair_daq_vars.sync_state==0)) {
+    if ((n%frame_parms->samples_per_subframe == 0) && (n>0) && (openair_daq_vars.sync_state==0)) {
 #ifdef DEBUG_PHY
       msg("[SYNC TIME] pausing for 1000ns, n=%d\n",n);
 #endif
diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
index ec7cfff7a1cd6b59f4ace20c338984c9eb4d1a77..f92b5ecf7f8d195c977cfe2bcb470195e7430af2 100644
--- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c
+++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
@@ -285,14 +285,14 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
   frame_parms->frame_type=FDD;
   init_frame_parms(frame_parms,1);
   /*
-  write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+  write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
   exit(-1);
   */
   sync_pos = lte_sync_time(ue->common_vars.rxdata,
                            frame_parms,
                            (int *)&ue->common_vars.eNb_id);
 
-  //  write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+  //  write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
   if (sync_pos >= frame_parms->nb_prefix_samples)
     sync_pos2 = sync_pos - frame_parms->nb_prefix_samples;
   else
@@ -313,7 +313,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
     ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot;
 
   if (((sync_pos2 - sync_pos_slot) >=0 ) &&
-      ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) {
+	 ((sync_pos2 - sync_pos_slot) < ((FRAME_LENGTH_COMPLEX_SAMPLES-frame_parms->samples_per_tti/2)))) {
 #ifdef DEBUG_INITIAL_SYNCH
     LOG_I(PHY,"Calling sss detection (FDD normal CP)\n");
 #endif
@@ -326,7 +326,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
     init_frame_parms(&ue->frame_parms,1);
     lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
     ret = pbch_detection(ue,mode);
-    //   write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+    //   write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
 
 #ifdef DEBUG_INITIAL_SYNCH
     LOG_I(PHY,"FDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
@@ -373,7 +373,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
       init_frame_parms(&ue->frame_parms,1);
       lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
       ret = pbch_detection(ue,mode);
-      //     write_output("rxdata3.m","rxd3",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+      //     write_output("rxdata3.m","rxd3",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
 #ifdef DEBUG_INITIAL_SYNCH
       LOG_I(PHY,"FDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
             frame_parms->Nid_cell,metric_fdd_ecp,phase_fdd_ecp,flip_fdd_ecp,ret);
@@ -396,7 +396,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
         sync_pos2 = sync_pos + FRAME_LENGTH_COMPLEX_SAMPLES - frame_parms->nb_prefix_samples;
 
       // PSS is hypothesized in 2nd symbol of third slot in Frame (S-subframe)
-      sync_pos_slot = frame_parms->samples_per_tti +
+      sync_pos_slot = frame_parms->samples_per_subframe +
                       (frame_parms->ofdm_symbol_size<<1) +
                       frame_parms->nb_prefix_samples0 +
                       (frame_parms->nb_prefix_samples);
@@ -416,7 +416,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
 
       lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
       ret = pbch_detection(ue,mode);
-      //      write_output("rxdata4.m","rxd4",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+      //      write_output("rxdata4.m","rxd4",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
 
 #ifdef DEBUG_INITIAL_SYNCH
       LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
@@ -436,7 +436,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
           sync_pos2 = sync_pos + FRAME_LENGTH_COMPLEX_SAMPLES - frame_parms->nb_prefix_samples;
 
         // PSS is hypothesized in 2nd symbol of third slot in Frame (S-subframe)
-        sync_pos_slot = frame_parms->samples_per_tti + (frame_parms->ofdm_symbol_size<<1) + (frame_parms->nb_prefix_samples<<1);
+        sync_pos_slot = frame_parms->samples_per_subframe + (frame_parms->ofdm_symbol_size<<1) + (frame_parms->nb_prefix_samples<<1);
 
         if (sync_pos2 >= sync_pos_slot)
           ue->rx_offset = sync_pos2 - sync_pos_slot;
@@ -453,7 +453,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
         lte_gold(frame_parms,ue->lte_gold_table[0],frame_parms->Nid_cell);
         ret = pbch_detection(ue,mode);
 
-	//	write_output("rxdata5.m","rxd5",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
+	//	write_output("rxdata5.m","rxd5",ue->common_vars.rxdata[0],10*frame_parms->samples_per_subframe,1,1);
 #ifdef DEBUG_INITIAL_SYNCH
         LOG_I(PHY,"TDD Extended prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
               frame_parms->Nid_cell,metric_tdd_ecp,phase_tdd_ecp,flip_tdd_ecp,ret);
@@ -606,7 +606,7 @@ int initial_sync(PHY_VARS_UE *ue, runmode_t mode)
     // do a measurement on the full frame
     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
       rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0],
-				frame_parms->samples_per_tti*10);
+				frame_parms->samples_per_subframe*10);
     */
 
     // we might add a low-pass filter here later
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index bffcd4b23ace28889a6f7b2e7f8d5aee2d8391c6..2abbd8907874210a59ba34746e2ae950ce55453a 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -628,7 +628,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
   uint16_t first_nonzero_root_idx=0;
 
 #if defined(EXMIMO) || defined(OAI_USRP)
-  prach_start =  (ue->rx_offset+subframe*ue->frame_parms.samples_per_tti-ue->hw_timing_advance-ue->N_TA_offset);
+  prach_start =  (ue->rx_offset+subframe*ue->frame_parms.samples_per_subframe-ue->hw_timing_advance-ue->N_TA_offset);
 #ifdef PRACH_DEBUG
     LOG_I(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
         prach_start,
@@ -638,13 +638,13 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
 #endif
 
   if (prach_start<0)
-    prach_start+=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
+    prach_start+=(ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
 
-  if (prach_start>=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
-    prach_start-=(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
+  if (prach_start>=(ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
+    prach_start-=(ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME);
 
 #else //normal case (simulation)
-  prach_start = subframe*ue->frame_parms.samples_per_tti-ue->N_TA_offset;
+  prach_start = subframe*ue->frame_parms.samples_per_subframe-ue->N_TA_offset;
   LOG_D(PHY,"[UE %d] prach_start %d, rx_offset %d, hw_timing_advance %d, N_TA_offset %d\n", ue->Mod_id,
     prach_start,
     ue->rx_offset,
@@ -1043,10 +1043,10 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
   } else {
 #if defined(EXMIMO) || defined(OAI_USRP)
     int j;
-    int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*ue->frame_parms.samples_per_tti;
+    int overflow = prach_start + prach_len - LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*ue->frame_parms.samples_per_subframe;
     LOG_D( PHY, "prach_start=%d, overflow=%d\n", prach_start, overflow );
 
-    for (i=prach_start,j=0; i<min(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,prach_start+prach_len); i++,j++) {
+    for (i=prach_start,j=0; i<min(ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,prach_start+prach_len); i++,j++) {
       ((int16_t*)ue->common_vars.txdata[0])[2*i] = prach[2*j]<<4;
       ((int16_t*)ue->common_vars.txdata[0])[2*i+1] = prach[2*j+1]<<4;
     }
@@ -1057,11 +1057,11 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
     }
 #if defined(EXMIMO)
     // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on
-    for (k=prach_start - (ue->frame_parms.samples_per_tti>>1) ; k<prach_start ; k++) {
+    for (k=prach_start - (ue->frame_parms.samples_per_subframe>>1) ; k<prach_start ; k++) {
       if (k<0)
-	ue->common_vars.txdata[0][k+ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
-      else if (k>(ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
-	ue->common_vars.txdata[0][k-ue->frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
+	ue->common_vars.txdata[0][k+ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
+      else if (k>(ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
+	ue->common_vars.txdata[0][k-ue->frame_parms.samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
       else
 	ue->common_vars.txdata[0][k] &= 0xFFFEFFFE;
     }
@@ -1080,7 +1080,7 @@ int32_t generate_prach( PHY_VARS_UE *ue, uint8_t eNB_id, uint8_t subframe, uint1
 #ifdef PRACH_DEBUG
   write_output("prach_txF0.m","prachtxF0",prachF,prach_len-Ncp,1,1);
   write_output("prach_tx0.m","prachtx0",prach+(Ncp<<1),prach_len-Ncp,1,1);
-  write_output("txsig.m","txs",(int16_t*)(&ue->common_vars.txdata[0][0]),2*ue->frame_parms.samples_per_tti,1,1);
+  write_output("txsig.m","txs",(int16_t*)(&ue->common_vars.txdata[0][0]),2*ue->frame_parms.samples_per_subframe,1,1);
   exit(-1);
 #endif
 
@@ -1135,7 +1135,7 @@ void rx_prach(PHY_VARS_eNB *eNB,
 
 
   for (aa=0; aa<nb_ant_rx; aa++) {
-    prach[aa] = (int16_t*)&eNB->common_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_tti-eNB->N_TA_offset];
+    prach[aa] = (int16_t*)&eNB->common_vars.rxdata[0][aa][subframe*eNB->frame_parms.samples_per_subframe-eNB->N_TA_offset];
   }
 
   // First compute physical root sequence
diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c
index d97ffbc543e080a5d594b430ccb798c85daf25d6..1e984574c2b64e4da9428faa247347025b8461b2 100644
--- a/openair1/PHY/MODULATION/slot_fep.c
+++ b/openair1/PHY/MODULATION/slot_fep.c
@@ -44,7 +44,7 @@ int slot_fep(PHY_VARS_UE *ue,
   unsigned int subframe_offset;//,subframe_offset_F;
   unsigned int slot_offset;
   int i;
-  unsigned int frame_length_samples = frame_parms->samples_per_tti * 10;
+  unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
   unsigned int rx_offset;
 
   /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id];
@@ -89,7 +89,7 @@ int slot_fep(PHY_VARS_UE *ue,
     subframe_offset = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1);
     slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_tti>>1) * (Ns%2);
   } else {
-    subframe_offset = frame_parms->samples_per_tti * (Ns>>1);
+    subframe_offset = frame_parms->samples_per_subframe * (Ns>>1);
     slot_offset = (frame_parms->samples_per_tti>>1) * (Ns%2);
   }
 
@@ -257,7 +257,7 @@ int front_end_fft(PHY_VARS_UE *ue,
   unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
   unsigned int subframe_offset;//,subframe_offset_F;
   unsigned int slot_offset;
-  unsigned int frame_length_samples = frame_parms->samples_per_tti * 10;
+  unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
   unsigned int rx_offset;
   uint8_t  threadId;
 
@@ -303,7 +303,7 @@ int front_end_fft(PHY_VARS_UE *ue,
     subframe_offset = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1);
     slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_tti>>1) * (Ns%2);
   } else {
-    subframe_offset = frame_parms->samples_per_tti * (Ns>>1);
+    subframe_offset = frame_parms->samples_per_subframe * (Ns>>1);
     slot_offset = (frame_parms->samples_per_tti>>1) * (Ns%2);
   }
 
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index ad1d788a570d85da8afb38954ceb326fa60c54ed..28aaaeb1fece25988d008b15ca6612907362b953 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -375,6 +375,12 @@ typedef struct {
   uint8_t              CC_id;
   /// timestamp transmitted to HW
   openair0_timestamp timestamp_tx;
+#ifdef UE_NR_PHY_DEMO
+  /// NR TTI index within subframe_tx [0 .. ttis_per_subframe - 1] to act upon for transmission
+  int nr_tti_tx;
+  /// NR TTI index within subframe_rx [0 .. ttis_per_subframe - 1] to act upon for reception
+  int nr_tti_rx;
+#endif
   /// subframe to act upon for transmission
   int subframe_tx;
   /// subframe to act upon for reception
diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h
index 0eb5dc6c97de931dd421bacf0c09b5af394a47e8..8276f0d757d41c6af49a237c838124a23e8bd404 100644
--- a/openair1/PHY/extern.h
+++ b/openair1/PHY/extern.h
@@ -64,9 +64,9 @@ extern unsigned char primary_synch2_tab[72];
 extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[
 extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[
 extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[
-extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[
-extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[
-extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[
+extern int *sync_corr_ue0; //!< index [0..10*samples_per_subframe[
+extern int *sync_corr_ue1; //!< index [0..10*samples_per_subframe[
+extern int *sync_corr_ue2; //!< index [0..10*samples_per_subframe[
 
 extern int flagMag;
 //extern short **txdataF_rep_tmp;
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index d09fd8d9152cd4bc9cd52a96782c2d1b1093eb3f..761cf893874ed1515701464112c15e46fa363543 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -546,6 +546,8 @@ typedef struct {
   /// Carrier offset in FFT buffer for first RE in PRB0
   uint16_t first_carrier_offset;
   /// Number of samples in a subframe
+  uint32_t samples_per_subframe;
+  /// Number of samples in a tti (same as subrame in LTE, depending on numerology in NR)
   uint32_t samples_per_tti;
   /// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
   uint16_t symbols_per_tti;
@@ -553,6 +555,14 @@ typedef struct {
   uint16_t dl_symbols_in_S_subframe;
   /// Number of SC-FDMA symbols in UL portion of S-subframe
   uint16_t ul_symbols_in_S_subframe;
+#ifdef UE_NR_PHY_DEMO
+  /// NR numerology index [0..5] as specified in 38.211 Section 4 (mu). 0=15khZ SCS, 1=30khZ, 2=60kHz, etc
+  uint8_t numerology_index;
+  /// NR number of ttis per subframe deduced from numerology (cf 38.211): 1, 2, 4, 8(not supported),16(not supported),32(not supported)
+  uint8_t ttis_per_subframe;
+  /// NR number of slots per tti . Assumption only 2 Slot per TTI is supported (Slot Config 1 in 38.211)
+  uint8_t slots_per_tti;
+#endif
   /// Number of Physical transmit antennas in node
   uint8_t nb_antennas_tx;
   /// Number of Receive antennas in node
@@ -654,7 +664,7 @@ typedef struct {
   /// \brief Holds the last subframe of received data in time domain after removal of 7.5kHz frequency offset.
   /// - first index: secotr id [0..2] (hard coded)
   /// - second index: rx antenna [0..nb_antennas_rx[
-  /// - third index: sample [0..samples_per_tti[
+  /// - third index: sample [0..samples_per_subframe[
   int32_t **rxdata_7_5kHz[3];
   /// \brief Holds the received data in the frequency domain.
   /// - first index: sector id [0..2] (hard coded)
@@ -663,7 +673,7 @@ typedef struct {
   int32_t **rxdataF[3];
   /// \brief Holds output of the sync correlator.
   /// - first index: sector id [0..2] (hard coded)
-  /// - second index: sample [0..samples_per_tti*10[
+  /// - second index: sample [0..samples_per_subframe*10[
   uint32_t *sync_corr[3];
   /// \brief Holds the beamforming weights
   /// - first index: eNB id [0..2] (hard coded)
diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h
index be63ea00cc3a7e5a4d7350651001f642026f33b0..6d0e20abacc52ae6d93305c31510fbb0124be2ae 100644
--- a/openair1/PHY/impl_defs_top.h
+++ b/openair1/PHY/impl_defs_top.h
@@ -115,7 +115,11 @@
  * @{
 */
 #define NUMBER_OF_OFDM_CARRIERS (frame_parms->ofdm_symbol_size)
+#ifdef UE_NR_PHY_DEMO
+#define NUMBER_OF_SYMBOLS_PER_FRAME (frame_parms->symbols_per_tti*(frame_parms->ttis_per_subframe)*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
+#else
 #define NUMBER_OF_SYMBOLS_PER_FRAME (frame_parms->symbols_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
+#endif
 #define NUMBER_OF_USEFUL_CARRIERS (12*frame_parms->N_RB_DL)
 #define NUMBER_OF_ZERO_CARRIERS (NUMBER_OF_OFDM_CARRIERS-NUMBER_OF_USEFUL_CARRIERS)
 #define NUMBER_OF_USEFUL_CARRIERS_BYTES (NUMBER_OF_USEFUL_CARRIERS>>2)
@@ -152,10 +156,14 @@
 #define OFDM_SYMBOL_SIZE_BYTES0 (OFDM_SYMBOL_SIZE_SAMPLES0*2)
 #define OFDM_SYMBOL_SIZE_BYTES_NO_PREFIX (OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX*2)
 
-#define SLOT_LENGTH_BYTES (frame_parms->samples_per_tti<<1) // 4 bytes * samples_per_tti/2
+#ifdef UE_NR_PHY_DEMO
+#define SLOT_LENGTH_BYTES ((frame_parms->samples_per_subframe << 2) / frame_parms->slots_per_tti) // 4 bytes * samples_per_subframe/slots_per_tti
+#else
+#define SLOT_LENGTH_BYTES (frame_parms->samples_per_subframe<<1) // 4 bytes * samples_per_subframe/2
+#endif
 #define SLOT_LENGTH_BYTES_NO_PREFIX (OFDM_SYMBOL_SIZE_BYTES_NO_PREFIX * NUMBER_OF_OFDM_SYMBOLS_PER_SLOT)
 
-#define FRAME_LENGTH_COMPLEX_SAMPLES (frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
+#define FRAME_LENGTH_COMPLEX_SAMPLES (frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
 #define FRAME_LENGTH_SAMPLES (FRAME_LENGTH_COMPLEX_SAMPLES*2)
 #define FRAME_LENGTH_SAMPLES_NO_PREFIX (NUMBER_OF_SYMBOLS_PER_FRAME*OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX)
 #define FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX (FRAME_LENGTH_SAMPLES_NO_PREFIX/2)
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index dffb7fe2bdcc157454b5e61c8937baab22258e13..ac5ed3800459fa8476cca09a78947bdd00ce9608 100644
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -142,7 +142,7 @@ void dump_dlsch_SI(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t s
         ue->pdcch_vars[0%RX_NB_TH][eNB_id]->num_pdcch_symbols,
         coded_bits_per_codeword);
 
-  write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_tti],ue->frame_parms.samples_per_tti,1,1);
+  write_output("rxsig0.m","rxs0", &ue->common_vars.rxdata[0][subframe*ue->frame_parms.samples_per_subframe],ue->frame_parms.samples_per_subframe,1,1);
 
   write_output("rxsigF0.m","rxsF0", ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF[0],nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
   write_output("rxsigF0_ext.m","rxsF0_ext", ue->pdsch_vars_SI[0]->rxdataF_ext[0],2*nsymb*ue->frame_parms.ofdm_symbol_size,1,1);
@@ -1247,7 +1247,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt
   int overflow=0;
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
   int k,l;
-  int dummy_tx_buffer[frame_parms->samples_per_tti] __attribute__((aligned(16)));
+  int dummy_tx_buffer[frame_parms->samples_per_subframe] __attribute__((aligned(16)));
 #endif
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_COMMON,VCD_FUNCTION_IN);
@@ -1257,44 +1257,44 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt
   nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
 
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case
-  ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_tti-
+  ulsch_start = (ue->rx_offset+subframe_tx*frame_parms->samples_per_subframe-
          ue->hw_timing_advance-
          ue->timing_advance-
          ue->N_TA_offset+5);
   //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
 
   if(ulsch_start < 0)
-      ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+      ulsch_start = ulsch_start + (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe);
 
-  if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti))
-      ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti);
+  if (ulsch_start > (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe))
+      ulsch_start = ulsch_start % (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe);
 
   //LOG_E(PHY,"ul-signal [subframe: %d, ulsch_start %d]\n",subframe_tx, ulsch_start);
 #else //this is the normal case
-  ulsch_start = (frame_parms->samples_per_tti*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance;
+  ulsch_start = (frame_parms->samples_per_subframe*subframe_tx)-ue->N_TA_offset; //-ue->timing_advance;
 #endif //else EXMIMO
 
 //#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
   if (empty_subframe)
   {
 //#if 1
-      overflow = ulsch_start - 9*frame_parms->samples_per_tti;
+      overflow = ulsch_start - 9*frame_parms->samples_per_subframe;
       for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
 
           if (overflow > 0)
      {
-       memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_tti-overflow));
+       memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*(frame_parms->samples_per_subframe-overflow));
        memset(&ue->common_vars.txdata[aa][0],0,4*overflow);
      }
      else
      {
-       memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_tti);
+       memset(&ue->common_vars.txdata[aa][ulsch_start],0,4*frame_parms->samples_per_subframe);
      }
       }
 /*#else
-      overflow = ulsch_start - 9*frame_parms->samples_per_tti;
+      overflow = ulsch_start - 9*frame_parms->samples_per_subframe;
       for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-          for (k=ulsch_start; k<cmin(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++) {
+          for (k=ulsch_start; k<cmin(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++) {
               ((short*)ue->common_vars.txdata[aa])[2*k] = 0;
               ((short*)ue->common_vars.txdata[aa])[2*k+1] = 0;
           }
@@ -1352,10 +1352,10 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt
 
 
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
-    overflow = ulsch_start - 9*frame_parms->samples_per_tti;
+    overflow = ulsch_start - 9*frame_parms->samples_per_subframe;
 
 
-    for (k=ulsch_start,l=0; k<cmin(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_tti); k++,l++) {
+    for (k=ulsch_start,l=0; k<cmin(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME,ulsch_start+frame_parms->samples_per_subframe); k++,l++) {
       ((short*)ue->common_vars.txdata[aa])[2*k] = ((short*)dummy_tx_buffer)[2*l]<<4;
       ((short*)ue->common_vars.txdata[aa])[2*k+1] = ((short*)dummy_tx_buffer)[2*l+1]<<4;
     }
@@ -1366,11 +1366,11 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt
     }
 #if defined(EXMIMO)
     // handle switch before 1st TX subframe, guarantee that the slot prior to transmission is switch on
-    for (k=ulsch_start - (frame_parms->samples_per_tti>>1) ; k<ulsch_start ; k++) {
+    for (k=ulsch_start - (frame_parms->samples_per_subframe>>1) ; k<ulsch_start ; k++) {
       if (k<0)
-  ue->common_vars.txdata[aa][k+frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
-      else if (k>(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
-  ue->common_vars.txdata[aa][k-frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
+  ue->common_vars.txdata[aa][k+frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
+      else if (k>(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME))
+  ue->common_vars.txdata[aa][k-frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME] &= 0xFFFEFFFE;
       else
   ue->common_vars.txdata[aa][k] &= 0xFFFEFFFE;
     }
@@ -1382,7 +1382,7 @@ void ulsch_common_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, uint8_t empt
     if( (crash == 1) && (subframe_tx == 0) )
     {
       LOG_E(PHY,"***** DUMP TX Signal [ulsch_start %d] *****\n",ulsch_start);
-      write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_tti,1,1);
+      write_output("txBuff.m","txSignal",&ue->common_vars.txdata[aa][ulsch_start],frame_parms->samples_per_subframe,1,1);
     }
     */
 
@@ -2590,12 +2590,12 @@ void phy_procedures_UE_S_TX(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t abstraction_f
 #if defined(EXMIMO) //this is the EXPRESS MIMO case
       int i;
       // set the whole tx buffer to RX
-      for (i=0; i<LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti; i++)
+      for (i=0; i<LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe; i++)
   ue->common_vars.txdata[aa][i] = 0x00010001;
 
 #else //this is the normal case
       memset(&ue->common_vars.txdata[aa][0],0,
-       (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti)*sizeof(int32_t));
+       (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe)*sizeof(int32_t));
 #endif //else EXMIMO
 
     }
@@ -2623,7 +2623,7 @@ void ue_measurement_procedures(
       LOG_D(PHY,"Calling measurements subframe %d, rxdata %p\n",subframe_rx,ue->common_vars.rxdata);
 
       lte_ue_measurements(ue,
-        (subframe_rx*frame_parms->samples_per_tti+ue->rx_offset)%(frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME),
+        (subframe_rx*frame_parms->samples_per_subframe+ue->rx_offset)%(frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME),
         (subframe_rx == 1) ? 1 : 0,
         0,
         0,
@@ -3015,7 +3015,7 @@ void ue_pbch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc, uin
     LOG_I(PHY,"[UE %d] rx_offset %d\n",ue->Mod_id,ue->rx_offset);
 
 
-    write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_tti,1,1);
+    write_output("rxsig0.m","rxs0", ue->common_vars.rxdata[0],ue->frame_parms.samples_per_subframe,1,1);
 
     write_output("H00.m","h00",&(ue->common_vars.dl_ch_estimates[0][0][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1);
     write_output("H10.m","h10",&(ue->common_vars.dl_ch_estimates[0][2][0]),((ue->frame_parms.Ncp==0)?7:6)*(ue->frame_parms.ofdm_symbol_size),1,1);
@@ -4544,8 +4544,8 @@ int phy_procedures_slot_parallelization_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *pr
     T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx));
 
     T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx), T_INT(0),
-            T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_tti],
-                    ue->frame_parms.samples_per_tti * 4));
+            T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_subframe],
+                    ue->frame_parms.samples_per_subframe * 4));
 #endif
 
     // start timers
@@ -5065,8 +5065,8 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,
   T(T_UE_PHY_DL_TICK, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx));
 
   T(T_UE_PHY_INPUT_SIGNAL, T_INT(ue->Mod_id), T_INT(frame_rx%1024), T_INT(subframe_rx), T_INT(0),
-    T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_tti],
-             ue->frame_parms.samples_per_tti * 4));
+    T_BUFFER(&ue->common_vars.rxdata[0][subframe_rx*ue->frame_parms.samples_per_subframe],
+             ue->frame_parms.samples_per_subframe * 4));
 #endif
 
   // start timers
@@ -5573,6 +5573,11 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
   int           frame_tx = proc->frame_tx;
   int           subframe_rx = proc->subframe_rx;
   int           subframe_tx = proc->subframe_tx;
+#ifdef UE_NR_PHY_DEMO
+  int           nr_tti_rx = proc->nr_tti_rx;
+  int           nr_tti_tx = proc->nr_tti_tx;
+#endif
+
 #undef DEBUG_PHY_PROC
 
   UE_L2_STATE_t ret;
@@ -5649,7 +5654,18 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
 
     if (ue->mac_enabled==1) {
       if (slot==0) {
-          //LOG_I(PHY,"[UE %d] Frame %d, subframe %d, star ue_scheduler\n", ue->Mod_id,frame_rx,subframe_tx);
+#ifdef UE_NR_PHY_DEMO
+          ret = mac_xface->ue_scheduler(ue->Mod_id,
+               frame_rx,
+               subframe_rx,
+			   nr_tti_rx,
+               frame_tx,
+               subframe_tx,
+			   nr_tti_tx,
+               subframe_select(&ue->frame_parms,subframe_tx),
+               eNB_id,
+               0/*FIXME CC_id*/);
+#else
         ret = mac_xface->ue_scheduler(ue->Mod_id,
             frame_rx,
             subframe_rx,
@@ -5658,6 +5674,7 @@ void phy_procedures_UE_lte(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,u
             subframe_select(&ue->frame_parms,subframe_tx),
             eNB_id,
             0/*FIXME CC_id*/);
+#endif
 
   if (ret == CONNECTION_LOST) {
     LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",ue->Mod_id,
diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h
index 45d7774afad0bf382481a644c4fbb4536f243a2a..fd69c540e34750b7dca6081aea23ea9f38b6777d 100644
--- a/openair2/COMMON/platform_types.h
+++ b/openair2/COMMON/platform_types.h
@@ -68,6 +68,11 @@ typedef int32_t               sdu_size_t;
 typedef uint32_t              frame_t;
 typedef int32_t               sframe_t;
 typedef uint32_t              sub_frame_t;
+#ifdef UE_NR_PHY_DEMO
+/* NR tti corresponding to 2 consecutive slots(or 1 slot if SlotConfig0) for the smaller configured numerology granularity */
+/* tti = 1ms for numerology 0, = 0.5ms for numerology 1, = 0.250 ms for numerology 2, etc ...*/
+typedef uint8_t				  nr_tti_t;
+#endif
 typedef uint8_t               module_id_t;
 typedef uint8_t               eNB_index_t;
 typedef uint16_t              ue_id_t;
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index ea264f1bfdfed36579df9d7f5b2b7e6c162b9ea7..01f8fc80f18d283084ac7a1914b47ffcaa881597 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -551,15 +551,29 @@ int phy_stats_exist(module_id_t Mod_id, int rnti);
 \param[in] eNB_index  instance of eNB
 @returns L2 state (CONNETION_OK or CONNECTION_LOST or PHY_RESYNCH)
 */
+#ifdef UE_NR_PHY_DEMO
 UE_L2_STATE_t ue_scheduler(
   const module_id_t module_idP,
   const frame_t rxFrameP,
   const sub_frame_t rxSubframe,
+  const nr_tti_t    rxNRTtiP,
   const frame_t txFrameP,
   const sub_frame_t txSubframe,
+  const nr_tti_t    txNRTtiP,
   const lte_subframe_t direction,
   const uint8_t eNB_index,
   const int CC_id);
+#else
+UE_L2_STATE_t ue_scheduler(
+  const module_id_t module_idP,
+  const frame_t rxFrameP,
+  const sub_frame_t rxSubframe,
+  const frame_t txFrameP,
+  const sub_frame_t txSubframe,
+  const lte_subframe_t direction,
+  const uint8_t eNB_index,
+  const int CC_id);
+#endif
 
 /*! \fn  int cba_access(module_id_t module_idP,frame_t frameP,sub_frame_t subframe, uint8_t eNB_index,uint16_t buflen);
 \brief determine whether to use cba resource to transmit or not
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index d7e779c607e80dfa844f2e6adf6e4e070aceadfb..86174cc6b511a738c35234b06709167f6e603be8 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -1819,16 +1819,31 @@ for (lcid=DCCH; (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE) ; lcid
 // 3. Perform SR/BSR procedures for scheduling feedback
 // 4. Perform PHR procedures
 
+#ifdef UE_NR_PHY_DEMO
 UE_L2_STATE_t
 ue_scheduler(
   const module_id_t    module_idP,
   const frame_t        rxFrameP,
   const sub_frame_t    rxSubframeP,
+  const nr_tti_t       rxNRTtiP,
   const frame_t        txFrameP,
   const sub_frame_t    txSubframeP,
+  const nr_tti_t       txNRTtiP,
   const lte_subframe_t directionP,
   const uint8_t        eNB_indexP,
   const int            CC_id)
+#else
+UE_L2_STATE_t
+ue_scheduler(
+  const module_id_t    module_idP,
+  const frame_t        rxFrameP,
+  const sub_frame_t    rxSubframeP,
+  const frame_t        txFrameP,
+  const sub_frame_t    txSubframeP,
+  const lte_subframe_t directionP,
+  const uint8_t        eNB_indexP,
+  const int            CC_id)
+#endif
 //------------------------------------------------------------------------------
 {
   int lcid; // lcid index
diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h
index effc4c78776ccf0a1de61a991be44a525fdaf609..8ffc88a6fa821156fd21efd6355f9c772b5a3d26 100644
--- a/openair2/PHY_INTERFACE/defs.h
+++ b/openair2/PHY_INTERFACE/defs.h
@@ -179,7 +179,11 @@ typedef struct {
   void (*dl_phy_sync_success) (module_id_t Mod_id,frame_t frameP, uint8_t CH_index,uint8_t first_sync);
 
   /// Only calls the PDCP for now
+#ifdef UE_NR_PHY_DEMO
+  UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, nr_tti_t rxNRTti, frame_t txFrameP,sub_frame_t txSubframe, nr_tti_t txNRTti, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
+#else
   UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, frame_t txFrameP,sub_frame_t txSubframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
+#endif
 
   /// PHY-Config-Dedicated UE
   void (*phy_config_dedicated_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index a1f3bcb57b209ec28d86b097e9213e5996cd05ed..d557dcc9de90ed45180de303a073766ad2deff90 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -1279,6 +1279,13 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
         frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
         frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
 
+#ifdef UE_NR_PHY_DEMO
+        // NR: Init to legacy LTE 20Mhz params
+        frame_parms[CC_id]->numerology_index	= 0;
+        frame_parms[CC_id]->ttis_per_subframe	= 1;
+        frame_parms[CC_id]->slots_per_tti		= 2;
+#endif
+
         downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
         downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
         downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
@@ -1923,8 +1930,8 @@ int main( int argc, char **argv ) {
             printf("Reading in from file to antenna buffer %d\n",0);
             if (fread(UE[0]->common_vars.rxdata[0],
                       sizeof(int32_t),
-                      frame_parms[0]->samples_per_tti*10,
-                      input_fd) != frame_parms[0]->samples_per_tti*10)
+                      frame_parms[0]->samples_per_subframe*10,
+                      input_fd) != frame_parms[0]->samples_per_subframe*10)
                 printf("error reading from file\n");
         }
         //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
@@ -1939,7 +1946,7 @@ int main( int argc, char **argv ) {
         // Set LSBs for antenna switch (ExpressMIMO)
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
             PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0;
-            for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
+            for (i=0; i<frame_parms[CC_id]->samples_per_subframe*10; i++)
                 for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++)
                     PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001;
         }
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 3b84e8ea97987ef9266681ad2a9623d9efebf70a..0877c336756a192f6e0feb452c65f7fc437401b9 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -318,7 +318,7 @@ static void *UE_thread_synch(void *arg) {
 #endif
             if (initial_sync( UE, UE->mode ) == 0) {
 
-                hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
+                hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe;
                 LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
                        hw_slot_offset,
                        freq_offset,
@@ -395,7 +395,7 @@ static void *UE_thread_synch(void *arg) {
                             if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
                                 fwrite((void*)&UE->common_vars.rxdata[0][0],
                                        sizeof(int32_t),
-                                       10*UE->frame_parms.samples_per_tti,
+                                       10*UE->frame_parms.samples_per_subframe,
                                        fd);
                                 LOG_I(PHY,"Dummping Frame ... bye bye \n");
                                 fclose(fd);
@@ -426,7 +426,7 @@ static void *UE_thread_synch(void *arg) {
                         if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
                             fwrite((void*)&UE->common_vars.rxdata[0][0],
                                    sizeof(int32_t),
-                                   10*UE->frame_parms.samples_per_tti,
+                                   10*UE->frame_parms.samples_per_subframe,
                                    fd);
                             LOG_I(PHY,"Dummping Frame ... bye bye \n");
                             fclose(fd);
@@ -562,14 +562,28 @@ static void *UE_thread_rxn_txnp4(void *arg) {
 #endif
         if (UE->mac_enabled==1) {
 
+#ifdef UE_NR_PHY_DEMO
             ret = mac_xface->ue_scheduler(UE->Mod_id,
                                           proc->frame_rx,
                                           proc->subframe_rx,
+										  proc->nr_tti_rx,
                                           proc->frame_tx,
                                           proc->subframe_tx,
+										  proc->nr_tti_tx,
                                           subframe_select(&UE->frame_parms,proc->subframe_tx),
                                           0,
                                           0/*FIXME CC_id*/);
+#else
+            ret = mac_xface->ue_scheduler(UE->Mod_id,
+                                          proc->frame_rx,
+                                          proc->subframe_rx,
+                                          proc->frame_tx,
+                                          proc->subframe_tx,
+                                          subframe_select(&UE->frame_parms,proc->subframe_tx),
+                                          0,
+                                          0/*FIXME CC_id*/);
+
+#endif
             if ( ret != CONNECTION_OK) {
                 char *txt;
                 switch (ret) {
@@ -637,7 +651,7 @@ void *UE_thread(void *arg) {
 
     PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
     //  int tx_enabled = 0;
-    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
+    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_subframe] __attribute__((aligned(32)));
     openair0_timestamp timestamp,timestamp1;
     void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
     int start_rx_stream = 0;
@@ -682,11 +696,11 @@ void *UE_thread(void *arg) {
                     rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
 
                 if (UE->mode != loop_through_memory)
-                    AssertFatal( UE->frame_parms.samples_per_tti*10 ==
+                    AssertFatal( UE->frame_parms.samples_per_subframe*10 ==
                                  UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                             &timestamp,
                                                             rxp,
-                                                            UE->frame_parms.samples_per_tti*10,
+                                                            UE->frame_parms.samples_per_subframe*10,
                                                             UE->frame_parms.nb_antennas_rx), "");
 		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
                 instance_cnt_synch = ++UE->proc.instance_cnt_synch;
@@ -711,7 +725,7 @@ void *UE_thread(void *arg) {
                           UE->rfdevice.trx_read_func(&UE->rfdevice,
                                               &timestamp,
                                               rxp,
-                                              UE->frame_parms.samples_per_tti,
+                                              UE->frame_parms.samples_per_subframe,
                                               UE->frame_parms.nb_antennas_rx);
                 }
 #endif
@@ -769,31 +783,31 @@ void *UE_thread(void *arg) {
                     for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
                         rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
                                  UE->frame_parms.nb_prefix_samples0+
-                                 sub_frame*UE->frame_parms.samples_per_tti];
+                                 sub_frame*UE->frame_parms.samples_per_subframe];
                     for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
-                        txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti];
+                        txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_subframe];
 
                     int readBlockSize, writeBlockSize;
                     if (sub_frame<9) {
-                        readBlockSize=UE->frame_parms.samples_per_tti;
-                        writeBlockSize=UE->frame_parms.samples_per_tti;
+                        readBlockSize=UE->frame_parms.samples_per_subframe;
+                        writeBlockSize=UE->frame_parms.samples_per_subframe;
                     } else {
                         // set TO compensation to zero
                         UE->rx_offset_diff = 0;
                         // compute TO compensation that should be applied for this frame
-                        if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti  &&
+                        if ( UE->rx_offset < 5*UE->frame_parms.samples_per_subframe  &&
                                 UE->rx_offset > 0 )
                             UE->rx_offset_diff = -1 ;
-                        if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti &&
-                                UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
+                        if ( UE->rx_offset > 5*UE->frame_parms.samples_per_subframe &&
+                                UE->rx_offset < 10*UE->frame_parms.samples_per_subframe )
                             UE->rx_offset_diff = 1;
 
                         LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset);
-                        readBlockSize=UE->frame_parms.samples_per_tti -
+                        readBlockSize=UE->frame_parms.samples_per_subframe -
                                       UE->frame_parms.ofdm_symbol_size -
                                       UE->frame_parms.nb_prefix_samples0 -
                                       UE->rx_offset_diff;
-                        writeBlockSize=UE->frame_parms.samples_per_tti -
+                        writeBlockSize=UE->frame_parms.samples_per_subframe -
                                        UE->rx_offset_diff;
                     }
 
@@ -806,7 +820,7 @@ void *UE_thread(void *arg) {
                     AssertFatal( writeBlockSize ==
                                  UE->rfdevice.trx_write_func(&UE->rfdevice,
                                          timestamp+
-                                         (2*UE->frame_parms.samples_per_tti) -
+                                         (2*UE->frame_parms.samples_per_subframe) -
                                          UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
                                          openair0_cfg[0].tx_sample_advance,
                                          txp,
@@ -845,7 +859,7 @@ void *UE_thread(void *arg) {
                     proc->subframe_tx=(sub_frame+4)%10;
                     proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
                     proc->timestamp_tx = timestamp+
-                                         (4*UE->frame_parms.samples_per_tti)-
+                                         (4*UE->frame_parms.samples_per_subframe)-
                                          UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
 
                     proc->instance_cnt_rxtx++;