diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 44f854fb24825adf44a396fc007a460138d0e1b3..d5c96d2934b8c17b48e6c6ecf8275d3dac3635b7 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -16613,7 +16613,11 @@ void InterPrediction::xGetIbcFilterRefBuf(PelBuf& piPred, CodingUnit* cu, const
   {
     int filterIdx = 1;
     Mv curMv;
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+    curMv.set(bv.hor + (-refSizeX << (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleHor)), bv.ver + ((-refSizeY) << (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleVer)));
+#else
     curMv.set(bv.hor + (-refSizeX << MV_FRACTIONAL_BITS_INTERNAL), bv.ver + ((-refSizeY) << MV_FRACTIONAL_BITS_INTERNAL));
+#endif
     PelUnitBuf pcUnitBuf(cu->chromaFormat, tmpRefBuf, tmpRefBuf, tmpRefBuf);
     getPredIBCBlk(*cu->firstPU, compID, cu->slice->getPic(), curMv, pcUnitBuf, filterIdx == 1, true);
   }
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index 19525b87fe9bbf041b40a1d42618bf0258952cc0..c5c43f6f0563a5525d064bcda92e91380072664f 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -591,7 +591,7 @@ public:
   void    motionCompensation  (CodingUnit &cu,     const RefPicList &eRefPicList = REF_PIC_LIST_X
     , const bool luma = true, const bool chroma = true
   );
-#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
+#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS || JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
   inline void getPredIBCBlk(const PredictionUnit& pu, ComponentID comp, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, bool bilinearMC = false
 #if JVET_AC0112_IBC_LIC
                           , bool bypassIBCLic = false
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 77d04479dacc6376db9cc8d8484a2dac00244775..54afcbcd68da6caac343881d2b8b3a2805c8a20e 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -1988,6 +1988,40 @@ void IntraPrediction::predIntraDbv(const ComponentID compId, PelBuf &piPred, con
 {
 #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
   Mv mv = refineChromaBv(compId, pu, pcInterPred);
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (!CS::isDualITree(*pu.cs))
+  {
+    const int bvShiftHor = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleX(compId, pu.chromaFormat);
+    const int bvShiftVer = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleY(compId, pu.chromaFormat);
+    int xFrac = mv.hor & ((1 << bvShiftHor) - 1);
+    int yFrac = mv.ver & ((1 << bvShiftVer) - 1);
+
+    PelUnitBuf pcBuf(pu.chromaFormat, PelBuf(), piPred, piPred);
+    if (xFrac != 0 || yFrac != 0)
+    {
+      pcInterPred->getPredIBCBlk(pu, compId, pu.cu->slice->getPic(), mv, pcBuf, false, false);
+    }
+    else
+    {
+      int refx = pu.blocks[compId].x + (mv.hor >> bvShiftHor);
+      int refy = pu.blocks[compId].y + (mv.ver >> bvShiftVer);
+      int refStride = pu.cs->picture->getRecoBuf(compId).stride;
+      Pel *ref = pu.cs->picture->getRecoBuf(compId).buf;
+      Pel *refTarget = ref + refy * refStride + refx;
+      int iStride = piPred.stride;
+      Pel *pred = piPred.buf;
+      int iHeight = piPred.height;
+      int lineBufSize = piPred.width * sizeof(Pel);
+      for (int uiY = 0; uiY < iHeight; uiY++)
+      {
+        ::memcpy(pred, refTarget, lineBufSize);
+        refTarget += refStride;
+        pred += iStride;
+      }
+    }
+    return;
+  }
+#endif
   bool isFracMv = pu.cs->sps->getIBCFracFlag() && mv.isFracMv<false>(pu.chromaFormat);
   if (isFracMv)
   {
@@ -2050,6 +2084,50 @@ Mv IntraPrediction::refineChromaBv(const ComponentID compId, const PredictionUni
 #else
   const int shiftSampleHor = ::getComponentScaleX(compId, pu.chromaFormat);
   const int shiftSampleVer = ::getComponentScaleY(compId, pu.chromaFormat);
+#endif
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (!CS::isDualITree(cs))
+  {
+#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
+    if (pu.cs->sps->getIBCFracFlag() && pu.cu->tmpFlag && !pu.cu->tmpFlmFlag && !pu.cu->tmpFusionFlag && pu.cu->tmpIsSubPel)
+    {
+#if JVET_AF0079_STORING_INTRATMP
+      if (PU::checkIsChromaBvCandidateValid(pu, pu.mv[0], 0))
+      {
+        return pu.mv[0];
+      }
+#else
+      int pXFrac = pu.mv[0].hor;
+      int pYFrac = pu.mv[0].ver;
+      int fracOffset = (pu.cu->tmpIsSubPel == 1 ? 8 : (pu.cu->tmpIsSubPel == 2 ? 4 : 12));
+      if (pu.cu->tmpSubPelIdx == LEFT_POS || pu.cu->tmpSubPelIdx == ABOVE_LEFT_POS || pu.cu->tmpSubPelIdx == LEFT_BOTTOM_POS)
+      {
+        pXFrac -= fracOffset;
+      }
+      if (pu.cu->tmpSubPelIdx == RIGHT_POS || pu.cu->tmpSubPelIdx == ABOVE_RIGHT_POS || pu.cu->tmpSubPelIdx == RIGHT_BOTTOM_POS)
+      {
+        pXFrac += fracOffset;
+      }
+      if (pu.cu->tmpSubPelIdx == ABOVE_POS || pu.cu->tmpSubPelIdx == ABOVE_LEFT_POS || pu.cu->tmpSubPelIdx == ABOVE_RIGHT_POS)
+      {
+        pYFrac -= fracOffset;
+      }
+      if (pu.cu->tmpSubPelIdx == BOTTOM_POS || pu.cu->tmpSubPelIdx == LEFT_BOTTOM_POS || pu.cu->tmpSubPelIdx == RIGHT_BOTTOM_POS)
+      {
+        pYFrac += fracOffset;
+      }
+      Mv lumaBv = Mv(pXFrac, pYFrac);
+      if (PU::checkIsChromaBvCandidateValid(pu, lumaBv, 0))
+      {
+        return Mv(pXFrac, pYFrac);
+      }
+#endif
+    }
+    return pu.cs->sps->getIBCFracFlag() ? pu.mv[0] : Mv((pu.mv[0].hor >> bvShiftHor) << bvShiftHor, (pu.mv[0].ver >> bvShiftVer) << bvShiftVer);
+#else
+    return Mv(pu.bv.hor >> shiftSampleHor, pu.bv.ver >> shiftSampleVer);
+#endif
+  }
 #endif
   if (topCanUse == false && leftCanUse == false)
   {
@@ -3450,7 +3528,11 @@ void IntraPrediction::geneChromaFusionPred(const ComponentID compId, PelBuf &piP
   const CompArea &area = pu2.blocks[compId];
 
 #if JVET_AC0119_LM_CHROMA_FUSION
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (!pu.cs->pcv->isEncoder || !pu2.cs->slice->isIntra() || !CS::isDualITree(*pu.cs))
+#else
   if (!pu.cs->pcv->isEncoder || !pu2.cs->slice->isIntra())
+#endif
   {
 #endif
   xGetLumaRecPixels(pu2, area);
@@ -3462,7 +3544,11 @@ void IntraPrediction::geneChromaFusionPred(const ComponentID compId, PelBuf &piP
   if (pu.isChromaFusion > 1)
   {
     pu2.intraDir[1] = LM_CHROMA_IDX + pu.isChromaFusion - 2;
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+    if (!pu.cs->pcv->isEncoder || !pu2.cs->slice->isIntra() || !CS::isDualITree(*pu.cs))
+#else
     if (!pu.cs->pcv->isEncoder || !pu2.cs->slice->isIntra())
+#endif
     {
       xCflmCreateChromaPred(pu, compId, piPred);
     }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index e4bfee7e0eecf2c5ec8729ba1d43fe7504a9fc6f..09ed157f64b54f8ae03e74f848c930c16e916680 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -52,7 +52,6 @@
 #include <cassert>
 
 
-
 #define BASE_ENCODER                                      1
 #define BASE_NORMATIVE                                    1
 #define TOOLS                                             1
@@ -231,6 +230,10 @@
 #define JVET_AE0174_NONINTER_TM_TOOLS_CONTROL             1 // JVET-AE0174: Add non-inter TM sps flag to control whether template matching is used for non-inter (Intra and IBC) tools
 #define JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES    1 // JVET-AE0094: IBC with non-adjacent spatial candidates
 
+#if JVET_AC0071_DBV && JVET_V0130_INTRA_TMP
+#define JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE              1 // JVET-AF0066: Enable DBV mode in single tree configuration
+#endif
+
 // Inter
 #define CIIP_PDPC                                         1 // Apply pdpc to megre prediction as a new CIIP mode (CIIP_PDPC) additional to CIIP mode
 #define JVET_X0090_CIIP_FIX                               1 // JVET-X0090: combination of CIIP, OBMC and LMCS
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 34bbadb1cef7e737c05152f83e69421450c96286..e66b3641b5a1bdc312e25881738297846a50bb72 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -518,7 +518,7 @@ void CodingUnit::initData()
   tmpIdx        = 0;
   tmpFusionFlag = false;
   tmpFlmFlag    = false;
-  tmpIsSubPel  = -1;
+  tmpIsSubPel  = 0;
   tmpSubPelIdx = -1;
 #endif
 #endif
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 41aa7c6483cd1d74ca07f60edf0c8ea4242f165e..4ad555848c061f5096d999dbe6dd37a88adc17eb 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -2922,7 +2922,11 @@ bool PU::hasCcInsideFilterFlag(const PredictionUnit &pu, int intraMode)
 #if JVET_AC0071_DBV
 bool PU::hasChromaBvFlag(const PredictionUnit &pu)
 {
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (pu.cu->slice->getSPS()->getUseIntraDBV())
+#else
   if (CS::isDualITree(*pu.cs) && pu.cu->slice->getSPS()->getUseIntraDBV())
+#endif
   {
     return dbvModeAvail(pu);
   }
@@ -4407,6 +4411,13 @@ uint32_t PU::getCoLocatedIntraLumaMode(const PredictionUnit &pu)
 #if JVET_AC0071_DBV
 bool PU::dbvModeAvail(const PredictionUnit &pu)
 {
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (!CS::isDualITree(*pu.cs))
+  {
+    const PredictionUnit &lumaPU = PU::getCoLocatedLumaPU(pu);
+    return lumaPU.cu->tmpFlag || CU::isIBC(*lumaPU.cu);
+  }
+#endif
   CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, pu.Cb().lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, pu.Cb().size()));
   lumaArea = clipArea(lumaArea, pu.cs->picture->block(COMPONENT_Y));
   Position posList[5] = { lumaArea.center(), lumaArea.topLeft(), lumaArea.topRight(), lumaArea.bottomLeft(), lumaArea.bottomRight() };
@@ -4427,6 +4438,12 @@ bool PU::dbvModeAvail(const PredictionUnit &pu)
 
 void PU::deriveChromaBv(PredictionUnit &pu)
 {
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  if (!CS::isDualITree(*pu.cs))
+  {
+    return;
+  }
+#endif
   pu.bv.set(0, 0);
 #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
   pu.mv[0].setZero();
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 8f0926fdd03ce667a07c92cda6b00ed771cf1422..b48065f4d12deb16c8c37311744e11fa9e564d01 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -2889,6 +2889,9 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 #endif
   PartSplit ispType       = lumaUsesISP ? CU::getISPType( cu, COMPONENT_Y ) : TU_NO_ISP;
   CHECK( cu.ispMode && bestCostSoFar < 0, "bestCostSoFar must be positive!" );
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+  bool singleTreeLumaIntraTmp = !CS::isDualITree(*cu.cs) && cu.tmpFlag;
+#endif
 
 #if JVET_AD0120_LBCCP
   int  bestCCInsideFilter = 0;
@@ -4143,6 +4146,12 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
       {
         fusionStorage[i] = m_fusionStorage[i].getBuf(localArea);
       }
+#endif
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+      if (singleTreeLumaIntraTmp)
+      {
+        modeIsEnable[DBV_CHROMA_IDX] = 1;
+      }
 #endif
       for (int32_t uiMode = uiMinMode - (2 * int(testBDPCM)); uiMode < uiMaxMode; uiMode++)
       {
@@ -4880,7 +4889,11 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
           const int cccmBufferIdx = filterIdx * CCCM_NUM_MODES + uiMode;
 #endif
 #if JVET_AD0188_CCP_MERGE
+#if JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE
+          if (pu.cs->slice->isIntra())
+#else
           if (pu.cs->slice->isIntra() && CS::isDualITree(cs))
+#endif
           {
 #if JVET_AD0202_CCCM_MDF
             pu.curCand = m_ccmParamsStorage[sub][cccmBufferIdx];