diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index dcb73d043f811658895172c4b878112cb1e8eb42..4df0cc51e17d48bf400a22596d8a75b151be9135 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1276,6 +1276,9 @@ set(PHY_SRC_UE
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
+  ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold_ue.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
   ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
   ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c
index 3b5a2f1840f6e9c240464b35d3bc3c3e26e565f9..54eab75810f1a2190fc7b0ad5e618782c6aec2db 100644
--- a/openair1/PHY/MODULATION/slot_fep.c
+++ b/openair1/PHY/MODULATION/slot_fep.c
@@ -190,11 +190,11 @@ int slot_fep_pbch(PHY_VARS_NR_UE *ue,
 #if UE_TIMING_TRACE
         start_meas(&ue->dlsch_channel_estimation_stats);
 #endif
-      /*  nr_pbch_channel_estimation(ue,eNB_id,0,
+        nr_pbch_channel_estimation(ue,eNB_id,0,
                                   Ns,
                                   aa,
                                   l,
-                                  symbol);*/
+                                  symbol);
       }
 
 
diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
new file mode 100644
index 0000000000000000000000000000000000000000..b02afcc9b74f8b1da7c0b83d1a215dae46cd32b8
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c
@@ -0,0 +1,158 @@
+/*
+ * 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.0  (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
+ */
+
+/*! \file PHY/NR_REFSIG/nr_dl_dmrs.c
+* \brief Top-level routines for generating DMRS from 38-211
+* \author
+* \date 2018
+* \version 0.1
+* \company Eurecom
+* \email:
+* \note
+* \warning
+*/
+
+//#define DEBUG_DL_DMRS
+//#define NR_PBCH_DMRS_LENGTH_DWORD 5
+//#define NR_PBCH_DMRS_LENGTH 144
+
+#ifdef USER_MODE
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+#include "refsig_defs_ue.h"
+#include "PHY/defs_nr_UE.h"
+#include "log.h"
+
+/*Table 7.4.1.1.2-1/2 from 38.211 */
+int wf1[8][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1}};
+int wt1[8][2] = {{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1}};
+int wf2[12][2] = {{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,-1},{1,1},{1,1},{1,1},{1,-1},{1,1},{1,1}};
+int wt2[12][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1},{1,-1}};
+
+short nr_mod_table[14] = {0,0,23170,23170,-23170,-23170,23170,23170,23170,-23170,-23170,23170,-23170,-23170};
+//extern short nr_mod_table[NR_MOD_TABLE_SIZE_SHORT];
+
+
+int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
+						unsigned int ncp,
+						unsigned int Ns,
+						unsigned int nr_gold_pdsch[2][20][2][21],
+						int32_t *output,
+						unsigned short p,
+						int length_dmrs,
+						unsigned short nb_pdsch_rb)
+{
+  int32_t qpsk[4],nqpsk[4],*qpsk_p, n;
+  int w,mprime,ind,l,ind_dword,ind_qpsk_symb,kp,lp, config_type, k;
+  short pamp;
+
+  typedef int array_of_w[2];
+  array_of_w *wf;
+  array_of_w *wt;
+
+  config_type = 1;
+  printf("dmrs config type %d port %d\n", config_type, p);
+
+  // Compute the correct pilot amplitude, sqrt_rho_b = Q3.13
+  pamp = 23170; //ONE_OVER_SQRT2_Q15;
+
+  // This includes complex conjugate for channel estimation
+  ((short *)&qpsk[0])[0] = pamp;
+  ((short *)&qpsk[0])[1] = -pamp;
+  ((short *)&qpsk[1])[0] = -pamp;
+  ((short *)&qpsk[1])[1] = -pamp;
+  ((short *)&qpsk[2])[0] = pamp;
+  ((short *)&qpsk[2])[1] = pamp;
+  ((short *)&qpsk[3])[0] = -pamp;
+  ((short *)&qpsk[3])[1] = pamp;
+
+  ((short *)&nqpsk[0])[0] = -pamp;
+  ((short *)&nqpsk[0])[1] = pamp;
+  ((short *)&nqpsk[1])[0] = pamp;
+  ((short *)&nqpsk[1])[1] = pamp;
+  ((short *)&nqpsk[2])[0] = -pamp;
+  ((short *)&nqpsk[2])[1] = -pamp;
+  ((short *)&nqpsk[3])[0] = pamp;
+  ((short *)&nqpsk[3])[1] = -pamp;
+
+  wf = (config_type==0) ? wf1 : wf2;
+  wt = (config_type==0) ? wt1 : wt2;
+
+  if (config_type > 1)
+      LOG_E(PHY,"Bad PDSCH DMRS config type %d\n", config_type);
+
+  if ((p>=1000) && (p<((config_type==0) ? 1008 : 1012))) {
+      if (/*ue->frame_parms.Ncp == NORMAL*/ncp ==0) {
+
+        // r_n from 38.211 7.4.1.1
+        for (n=0; n<nb_pdsch_rb*((config_type==0) ? 3:2); n++) {
+        	for (lp =0; lp<length_dmrs; lp++){
+        		for (kp=0; kp<2; kp++){
+        			w = (wf[p-1000][kp])*(wt[p-1000][lp]);
+        			qpsk_p = (w==1) ? qpsk : nqpsk;
+
+        			ind = 2*n+kp;
+        			ind_dword = ind>>4;
+        			ind_qpsk_symb = ind&0xf;
+
+        			output[k] = qpsk_p[(ue->nr_gold_pdsch[0][Ns][lp][ind_dword]>>(2*ind_qpsk_symb))&3];
+
+
+#ifdef DEBUG_DL_DMRS
+          LOG_I(PHY,"Ns %d, p %d, ind_dword %d, ind_qpsk_symbol %d\n",
+                Ns,p,idx_dword,idx_qpsk_symb);
+          LOG_I(PHY,"index = %d\n",(nr_gold_pdsch[0][Ns][lprime][ind_dword]>>(2*ind_qpsk_symb))&3);
+#endif
+
+          	  	  	k++;
+        		}
+        	}
+        }
+      } else {
+        LOG_E(PHY,"extended cp not supported for PDSCH DMRS yet\n");
+      }
+  } else {
+    LOG_E(PHY,"Illegal p %d PDSCH DMRS port\n",p);
+  }
+
+  return(0);
+}
+
+int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch,
+					int32_t *output	)
+{
+	int m;
+
+	/// BPSK modulation
+    for (m=0; m<NR_PBCH_DMRS_LENGTH; m++) {
+      output[m<<1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1)];
+      output[(m<<1)+1] = nr_mod_table[((1 + ((nr_gold_pbch[m>>5]&(1<<(m&0x1f)))>>(m&0x1f)))<<1) + 1];
+#ifdef DEBUG_PBCH
+    printf("nr_gold_pbch[m>>5] %x\n",nr_gold_pbch[m>>5]);
+    printf("m %d  output %d %d\n", m, output[2*m], output[2*m+1]);
+#endif
+    }
+
+  return(0);
+}
+
diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
new file mode 100644
index 0000000000000000000000000000000000000000..1386f9846b3049515ea7a622d70ca961a7f8685a
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
@@ -0,0 +1,115 @@
+/*
+ * 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 "refsig_defs_ue.h"
+
+void nr_gold_pbch(PHY_VARS_NR_UE* ue)
+{
+
+  unsigned int n, x1, x2;
+  unsigned char Nid, i_ssb, i_ssb2;
+  unsigned char Lmax, l, n_hf, N_hf;
+
+  Nid = ue->frame_parms.Nid_cell;
+
+  Lmax = 8; //(fp->dl_CarrierFreq < 3e9)? 4:8;
+  N_hf = (Lmax == 4)? 2:1;
+
+  for (n_hf = 0; n_hf < N_hf; n_hf++) {
+
+    for (l = 0; l < Lmax ; l++) {
+      i_ssb = l & (Lmax-1);
+      i_ssb2 = (i_ssb<<2) + n_hf;
+
+      x1 = 1 + (1<<31);
+      x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3);
+      x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+      // skip first 50 double words (1600 bits)
+      for (n = 1; n < 50; n++) {
+        x1 = (x1>>1) ^ (x1>>4);
+        x1 = x1 ^ (x1<<31) ^ (x1<<28);
+        x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+        x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+      }
+
+      for (n=0; n<NR_PBCH_DMRS_LENGTH_DWORD; n++) {
+        x1 = (x1>>1) ^ (x1>>4);
+        x1 = x1 ^ (x1<<31) ^ (x1<<28);
+        x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+        x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+        ue->nr_gold_pbch[n_hf][l][n] = x1 ^ x2;
+      }
+
+    }
+  }
+
+}
+
+void nr_gold_pdsch(PHY_VARS_NR_UE* ue,unsigned short lbar,unsigned int nr_gold_pdsch[2][20][2][21],unsigned int Nid_cell, unsigned short *n_idDMRS, unsigned short length_dmrs)
+{
+
+  unsigned char ns,l;
+  unsigned int n,x1,x2,x2tmp0,x2tmp1, x2tmp2,x2s;
+  int nscid;
+  unsigned int nid;
+
+  /// to be updated from higher layer
+  //unsigned short lbar = 0;
+
+  for (nscid=0; nscid<2; nscid++) {
+    if (n_idDMRS)
+      nid = n_idDMRS[nscid];
+    else
+      nid = Nid_cell;
+
+    for (ns=0; ns<20; ns++) {
+
+      for (l=0; l<length_dmrs; l++) {
+
+    	x2tmp0 = ((14*ns+(lbar+l)+1)*((nid<<1)+1))<<17;
+        x2 = (x2tmp0+(nid<<1))%(1<<31);  //cinit
+
+        x1 = 1+ (1<<31);
+        x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+        // skip first 50 double words (1600 bits)
+        for (n=1; n<50; n++) {
+          x1 = (x1>>1) ^ (x1>>4);
+          x1 = x1 ^ (x1<<31) ^ (x1<<28);
+          x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+          x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+            //printf("x1 : %x, x2 : %x\n",x1,x2);
+        }
+
+        for (n=0; n<14; n++) {
+          x1 = (x1>>1) ^ (x1>>4);
+          x1 = x1 ^ (x1<<31) ^ (x1<<28);
+          x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
+          x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
+          nr_gold_pdsch[nscid][ns][l][n] = x1^x2;
+            //printf("n=%d : c %x\n",n,x1^x2);
+        }
+
+      }
+    }
+  }
+}
diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d4db86ef9bcf3bfb9538bfe57a883da290ef866
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
@@ -0,0 +1,53 @@
+/*
+ * 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
+ */
+
+/* Definitions for LTE Reference signals */
+/* Author R. Knopp / EURECOM / OpenAirInterface.org */
+#ifndef __NR_REFSIG_DEFS__H__
+#define __NR_REFSIG_DEFS__H__
+#include "PHY/defs_nr_UE.h"
+
+
+/*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS.
+@param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables
+ */
+int nr_pbch_dmrs_rx(unsigned int *nr_gold_pbch,	int32_t *output	);
+
+/*int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue,
+						unsigned int ncp,
+						unsigned int Ns,
+						unsigned int nr_gold_pdsch[2][20][2][21],
+						int32_t *output,
+						unsigned short p,
+						int length_dmrs,
+						unsigned short nb_pdsch_rb);*/
+
+void nr_gold_pbch(PHY_VARS_NR_UE* ue);
+
+void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
+					unsigned short lbar,
+					unsigned int nr_gold_pdsch[2][20][2][21],
+					unsigned int Nid_cell,
+					unsigned short *n_idDMRS,
+					unsigned short length_dmrs);
+
+
+#endif
diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
new file mode 100644
index 0000000000000000000000000000000000000000..a37a591d2f57d3f79439fc85c9e42bbb9e28ee05
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
@@ -0,0 +1,86 @@
+short filt16a_l0[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r0[16] = {
+0,0,0,0,0,4096,8192,12288,16384,20480,24576,28672,0,0,0,0};
+
+short filt16a_m0[16] = {
+0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,-12288,0,0,0,0};
+
+short filt16a_l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r1[16] = {
+0,0,0,0,0,0,4096,8192,12288,16384,20480,24576,0,0,0,0};
+
+short filt16a_m1[16] = {
+-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,-8192,0,0,0,0};
+
+short filt16a_l2[16] = {
+24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r2[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16a_m2[16] = {
+-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16a_l3[16] = {
+28672,24576,20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r3[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16a_m3[16] = {
+-12288,-8192,-4096,0,4096,8192,12288,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16a_l0_dc[16] = {
+16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r0_dc[16] = {
+0,0,0,0,0,3276,9830,13107,16384,19660,22937,26214,0,0,0,0};
+
+short filt16a_m0_dc[16] = {
+0,4096,8192,12288,16384,13107,6553,3276,0,-3277,-6554,-9831,0,0,0,0};
+
+short filt16a_l1_dc[16] = {
+16384,12288,8192,4096,0,-4096,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r1_dc[16] = {
+0,0,0,0,0,0,6553,9830,13107,16384,19660,22937,0,0,0,0};
+
+short filt16a_m1_dc[16] = {
+-4096,0,4096,8192,12288,16384,9830,6553,3276,0,-3277,-6554,0,0,0,0};
+
+short filt16a_l2_dc[16] = {
+26214,22937,19660,16384,13107,9830,6553,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r2_dc[16] = {
+0,0,0,0,0,0,0,4096,8192,12288,16384,20480,0,0,0,0};
+
+short filt16a_m2_dc[16] = {
+-6554,-3277,0,3276,6553,6553,16384,12288,8192,4096,0,-4096,0,0,0,0};
+
+short filt16a_l3_dc[16] = {
+26214,22937,19660,16384,13107,9830,3276,0,0,0,0,0,0,0,0,0};
+
+short filt16a_r3_dc[16] = {
+0,0,0,0,0,0,0,0,4096,8192,12288,16384,0,0,0,0};
+
+short filt16a_m3_dc[16] = {
+-9831,-6554,-3277,0,3276,6553,9830,16384,12288,8192,4096,0,0,0,0,0};
+
+short filt16a_1[16] = {
+16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384};
+
+short filt16a_2l0[16] = {
+16384,12288,8192,4096,-4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2r0[16] = {
+0,4096,8192,12288,16384,20480,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2l1[16] = {
+20480,16384,12288,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16a_2r1[16] = {
+-4096,0,4096,8192,12288,16384,0,0,0,0,0,0,0,0,0,0};
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
new file mode 100644
index 0000000000000000000000000000000000000000..2a9b847e1e60af22f18ef84c455b9f3bcdadb20f
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -0,0 +1,262 @@
+/*
+ * 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.0  (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
+ */
+
+#ifdef USER_MODE
+#include <string.h>
+#endif
+//#include "defs.h"
+//#include "SCHED/defs.h"
+#include "PHY/defs_nr_UE.h"
+#include "filt16a_32.h"
+#include "T.h"
+#define DEBUG_CH
+
+int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol)
+{
+  int pilot[2][200] __attribute__((aligned(16)));
+  unsigned char nu,aarx;
+  unsigned short k;
+  unsigned int rb,pilot_cnt;
+  int16_t ch[2],*pil,*rxF,*dl_ch,*dl_ch_prev,*fl,*fm,*f2l,*fr,f1,*f2r,*fl_dc,*fm_dc,*fr_dc;
+  int ch_offset,symbol_offset;
+
+  uint16_t Nid_cell = (eNB_offset == 0) ? ue->frame_parms.Nid_cell : ue->measurements.adj_cell_id[eNB_offset-1];
+
+  uint8_t nushift;
+  uint8_t previous_thread_id = ue->current_thread_id[Ns>>1]==0 ? (RX_NB_TH-1):(ue->current_thread_id[Ns>>1]-1);
+  int **dl_ch_estimates         =ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[eNB_offset];
+  int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF;
+
+
+  // recompute nushift with eNB_offset corresponding to adjacent eNB on which to perform channel estimation
+  nushift =  Nid_cell%4;
+
+  if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
+    ch_offset     = ue->frame_parms.ofdm_symbol_size ;
+  else
+    ch_offset     = ue->frame_parms.ofdm_symbol_size*symbol;
+
+  symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol;
+
+  k = nushift;
+
+#ifdef DEBUG_CH
+  printf("PBCH Channel Estimation : ThreadId %d, eNB_offset %d cell_id %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d\n",ue->current_thread_id[Ns>>1], eNB_offset,Nid_cell,ch_offset,ue->frame_parms.ofdm_symbol_size,
+         ue->frame_parms.Ncp,l,Ns,k);
+#endif
+
+  switch (k) {
+  case 0:
+        fl = filt16a_l0;
+        fm = filt16a_m0;
+        fr = filt16a_r0;
+        fl_dc = filt16a_l0;
+        fm_dc = filt16a_m0;
+        fr_dc = filt16a_r0;
+        f1 = filt16a_1;
+        f2l = filt16a_2l0;
+        f2r = filt16a_2r0;
+        break;
+
+  case 1:
+        fl = filt16a_l1;
+        fm = filt16a_m1;
+        fr = filt16a_r1;
+        fl_dc = filt16a_l1;
+        fm_dc = filt16a_m1;
+        fr_dc = filt16a_r1;
+        f1 = filt16a_1;
+        f2l = filt16a_2l1;
+        f2r = filt16a_2r1;
+        break;
+
+  case 2:
+        fl = filt16a_l2;
+        fm = filt16a_m2;
+        fr = filt16a_r2;
+        fl_dc = filt16a_l2;
+        fm_dc = filt16a_m2;
+        fr_dc = filt16a_r2;
+        f1 = filt16a_1;
+        f2l = filt16a_2l0;
+        f2r = filt16a_2r0;
+        break;
+
+  case 3:
+        fl = filt16a_l3;
+        fm = filt16a_m3;
+        fr = filt16a_r3;
+        fl_dc = filt16a_l3;
+        fm_dc = filt16a_m3;
+        fr_dc = filt16a_r3;
+        f1 = filt16a_1;
+        f2l = filt16a_2l1;
+        f2r = filt16a_2r1;
+        break;
+
+  default:
+    msg("pbch_channel_estimation: k=%d -> ERROR\n",k);
+    return(-1);
+    break;
+  }
+
+
+
+  // generate pilot
+  nr_pbch_dmrs_rx(ue->nr_gold_pbch,
+					  &pilot[p][0]);
+
+  for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
+
+    pil   = (int16_t *)&pilot[p][0];
+    rxF   = (int16_t *)&rxdataF[aarx][((symbol_offset+k+ue->frame_parms.first_carrier_offset))];
+    dl_ch = (int16_t *)&dl_ch_estimates[(p<<1)+aarx][ch_offset];
+
+    memset(dl_ch,0,4*(ue->frame_parms.ofdm_symbol_size));
+    if (ue->high_speed_flag==0) // multiply previous channel estimate by ch_est_alpha
+      multadd_complex_vector_real_scalar(dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),
+                                         ue->ch_est_alpha,dl_ch-(ue->frame_parms.ofdm_symbol_size<<1),
+                                         1,ue->frame_parms.ofdm_symbol_size);
+#ifdef DEBUG_CH
+    printf("k %d, first_carrier %d\n",k,ue->frame_parms.first_carrier_offset);
+#endif
+    if ((ue->frame_parms.N_RB_DL&1)==0) {
+
+      // Treat first 2 pilots specially (left edge)
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+      printf("ch 0 %d\n",((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1]));
+      printf("pilot 0 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+      multadd_real_vector_complex_scalar(fl,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      pil+=2;
+      rxF+=8;
+      for (int i= 0; i<8; i++)
+      printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i));
+      //dl_ch+=6;
+      printf("after dl_ch %d %d\n", dl_ch, *(dl_ch));
+
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+      printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+      multadd_real_vector_complex_scalar(fm,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      //printf("after dl_ch %d %d\n", dl_ch, *(dl_ch));
+      for (int i= 0; i<16; i++)
+            printf("dl_ch %d %d\n", dl_ch+i, *(dl_ch+i));
+
+      pil+=2;
+      rxF+=8;
+      //dl_ch+=6;
+      printf("after 6 dl_ch %d %d\n", dl_ch, *(dl_ch));
+
+      ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+      ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+
+      #ifdef DEBUG_CH
+            printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+      #endif
+
+      multadd_real_vector_complex_scalar(fr,
+                                         ch,
+                                         dl_ch,
+                                         16);
+      pil+=2;
+      rxF+=8;
+      dl_ch+=16;
+
+      for (pilot_cnt=6; pilot_cnt<((ue->frame_parms.N_RB_DL)-1); pilot_cnt+=6) {
+
+
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+	printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+        multadd_real_vector_complex_scalar(fl,
+                                           ch,
+                                           dl_ch,
+                                           16);
+
+        for (int i= 0; i<8; i++)
+                    printf("pilot_cnt %d dl_ch %d %d\n", pilot_cnt, dl_ch+i, *(dl_ch+i));
+
+        pil+=2;
+        rxF+=8;
+        //dl_ch+=6;
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+#ifdef DEBUG_CH
+	printf("pilot %d : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",pilot_cnt+1,rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+#endif
+        multadd_real_vector_complex_scalar(fm,
+                                           ch,
+                                           dl_ch,
+                                           16);
+        pil+=2;
+        rxF+=8;
+        //dl_ch+=6;
+
+        ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15);
+        ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15);
+
+        #ifdef DEBUG_CH
+              printf("pilot 1 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]);
+        #endif
+
+        multadd_real_vector_complex_scalar(fr,
+                                           ch,
+                                           dl_ch,
+                                           16);
+        pil+=2;
+        rxF+=8;
+        dl_ch+=16;
+
+      }
+
+
+    }
+
+
+    printf("dl_ch %d\n", dl_ch);
+
+
+  }
+
+  return(0);
+}
+
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
new file mode 100644
index 0000000000000000000000000000000000000000..7ec222727b7381fb22d742c05487f69b61bb214d
--- /dev/null
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
@@ -0,0 +1,60 @@
+/*
+ * 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
+ */
+
+#ifndef __LTE_ESTIMATION_DEFS__H__
+#define __LTE_ESTIMATION_DEFS__H__
+
+
+#include "PHY/defs_nr_UE.h"
+#include "PHY/defs_gNB.h"
+/** @addtogroup _PHY_PARAMETER_ESTIMATION_BLOCKS_
+ * @{
+ */
+
+/*!\brief Timing drift hysterisis in samples*/
+#define SYNCH_HYST 2
+
+/*!
+\brief This function performs channel estimation including frequency and temporal interpolation
+\param phy_vars_ue Pointer to UE PHY variables
+\param eNB_id Index of target eNB
+\param eNB_offset Offset for interfering eNB (in terms cell ID mod 3)
+\param Ns slot number (0..19)
+\param p antenna port
+\param l symbol within slot
+\param symbol symbol within frame
+*/
+int nr_dl_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol);
+
+int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
+                              uint8_t eNB_id,
+                              uint8_t eNB_offset,
+                              unsigned char Ns,
+                              unsigned char p,
+                              unsigned char l,
+                              unsigned char symbol);
+#endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index 45c93ea53abf7381907ad4193eceb46d712e773b..ccc031ed8434e762c67cb7217a2891f0a8c7776e 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -42,6 +42,7 @@
 
 #include "PHY/NR_REFSIG/pss_nr.h"
 #include "PHY/NR_REFSIG/sss_nr.h"
+#include "PHY/NR_REFSIG/refsig_defs_ue.h"
 
 extern openair0_config_t openair0_cfg[];
 static  nfapi_config_request_t config_t;
@@ -256,7 +257,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
 
     set_default_frame_parms_single(config,&ue->frame_parms);
     nr_init_frame_parms_ue(config,&ue->frame_parms);
-    //generate_dmrs_pbch(ue->dmrs_pbch_bitmap_nr, frame_parms->Nid_cell);
+
+    nr_gold_pbch(ue);
     ret = pbch_detection(ue,mode);
     //   write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
index 8844938a66584ba4c33f2d2e929adb90b3eb2751..6c2db526a1cf5a1564ad1ccedfce738494a849f0 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
@@ -67,8 +67,8 @@ uint16_t nr_pbch_extract(int **rxdataF,
   uint8_t i,j,aarx,aatx;
   int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
 
-  int rx_offset = frame_parms->ofdm_symbol_size-3*12;
-  int ch_offset = frame_parms->N_RB_DL*6-3*12;
+  int rx_offset = frame_parms->ofdm_symbol_size-10*12;
+  int ch_offset = frame_parms->N_RB_DL*6-10*12;
   int nushiftmod4 = frame_parms->nushift%4;
 
   for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index 4c41852bad9953392d983a0720f46ad02b7f6bf6..bf8020ecdae251e1adcdab1453759d7f779eabe8 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -769,14 +769,14 @@ typedef struct {
 
 #endif
 
-  /// UE-specific reference symbols (p=5), TM 7
-  uint32_t lte_gold_uespec_port5_table[20][38];
+  /// PBCH DMRS sequence
+  uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD];
 
-  /// ue-specific reference symbols
-  uint32_t lte_gold_uespec_table[2][20][2][21];
+  /// PDSCH DMRS
+  uint32_t nr_gold_pdsch[2][20][2][21];
 
-  /// mbsfn reference symbols
-  uint32_t lte_gold_mbsfn_table[10][3][42];
+  /// PDCCH DMRS
+  uint32_t nr_gold_pdcch[10][3][42];
 
   uint32_t X_u[64][839];