diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index 2e55696fd1820523a440c37e05d9dfb20533c07b..38261eb0dd5071cde19e1063d203ffc910092ef0 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -70,7 +70,11 @@ CodingStructure::CodingStructure(CUCache& cuCache, PUCache& puCache, TUCache& tu
   , bestParent ( nullptr )
   , tmpColorSpaceCost(MAX_DOUBLE)
   , firstColorSpaceSelected(true)
+#if JVET_Z0153_IBC_EXT_REF
+  , resetIBCBuffer (true)
+#else
   , resetIBCBuffer (false)
+#endif
 {
   for( uint32_t i = 0; i < MAX_NUM_COMPONENT; i++ )
   {
diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp
index 02bdc0ea96e432cd2d55ce57a08efe7cd22fa54d..be78edb7e0e9ca53cc57a67c7cdf151f2438d3cb 100644
--- a/source/Lib/CommonLib/InterPrediction.cpp
+++ b/source/Lib/CommonLib/InterPrediction.cpp
@@ -411,7 +411,11 @@ void InterPrediction::destroy()
 }
 
 #if INTER_LIC || (TM_AMVP || TM_MRG) || JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
+#if JVET_Z0153_IBC_EXT_REF
+void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize, Reshape* reshape, const int picWidth )
+#else
 void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize, Reshape* reshape )
+#endif
 #else
 void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize )
 #endif
@@ -585,6 +589,18 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons
   }
 
 #if JVET_Z0118_GDR
+#if JVET_Z0153_IBC_EXT_REF
+  m_IBCBufferWidth = (picWidth + ctuSize - 1) / ctuSize * ctuSize;
+  m_IBCBufferHeight = 3 * ctuSize;
+  if (m_IBCBuffer0.bufs.empty())
+  {    
+    m_IBCBuffer0.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, m_IBCBufferHeight)));
+  }
+  if (m_IBCBuffer1.bufs.empty())
+  {   
+    m_IBCBuffer1.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, m_IBCBufferHeight)));
+  }  
+#else
   m_IBCBufferWidth = g_IBCBufferSize / ctuSize;
 
   if (m_IBCBuffer0.bufs.empty())
@@ -595,11 +611,18 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons
   {   
     m_IBCBuffer1.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, ctuSize)));
   }
+#endif
 #else
   if (m_IBCBuffer.bufs.empty())
   {
+#if JVET_Z0153_IBC_EXT_REF
+    m_IBCBufferWidth = (picWidth + ctuSize - 1) / ctuSize * ctuSize;
+    m_IBCBufferHeight = 3 * ctuSize;
+    m_IBCBuffer.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, m_IBCBufferHeight)));
+#else
     m_IBCBufferWidth = g_IBCBufferSize / ctuSize;
     m_IBCBuffer.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, ctuSize)));
+#endif
   }
 #endif
 }
@@ -7922,12 +7945,19 @@ void InterPrediction::xFillIBCBuffer(CodingUnit &cu)
         continue;
       }
 
+#if JVET_Z0153_IBC_EXT_REF
+      const int shiftSampleHor = ::getComponentScaleX(area.compID, cu.chromaFormat);
+      const int shiftSampleVer = ::getComponentScaleY(area.compID, cu.chromaFormat);
+      const int pux = area.x % (m_IBCBufferWidth >> shiftSampleHor);
+      const int puy = area.y % (m_IBCBufferHeight >> shiftSampleVer);
+#else
       const unsigned int lcuWidth = cu.cs->slice->getSPS()->getMaxCUWidth();
       const int shiftSampleHor = ::getComponentScaleX(area.compID, cu.chromaFormat);
       const int shiftSampleVer = ::getComponentScaleY(area.compID, cu.chromaFormat);
       const int ctuSizeLog2Ver = floorLog2(lcuWidth) - shiftSampleVer;
       const int pux = area.x & ((m_IBCBufferWidth >> shiftSampleHor) - 1);
       const int puy = area.y & (( 1 << ctuSizeLog2Ver ) - 1);
+#endif
       const CompArea dstArea = CompArea(area.compID, cu.chromaFormat, Position(pux, puy), Size(area.width, area.height));
       CPelBuf srcBuf = cu.cs->getRecoBuf(area);
 
@@ -7960,10 +7990,15 @@ void InterPrediction::xIntraBlockCopy(PredictionUnit &pu, PelUnitBuf &predBuf, c
   bool useCleanIBCBuffer   = pu.cs->isInGdrInvervalOrRecoveryPoc() && isCleanCu;
 #endif
 
+#if JVET_Z0153_IBC_EXT_REF
+  const int shiftSampleHor = ::getComponentScaleX(compID, pu.chromaFormat);
+  const int shiftSampleVer = ::getComponentScaleY(compID, pu.chromaFormat);
+#else
   const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
   const int shiftSampleHor = ::getComponentScaleX(compID, pu.chromaFormat);
   const int shiftSampleVer = ::getComponentScaleY(compID, pu.chromaFormat);
   const int ctuSizeLog2Ver = floorLog2(lcuWidth) - shiftSampleVer;
+#endif
   pu.bv = pu.mv[REF_PIC_LIST_0];
   pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT);
   int refx, refy;
@@ -7977,10 +8012,19 @@ void InterPrediction::xIntraBlockCopy(PredictionUnit &pu, PelUnitBuf &predBuf, c
     refx = pu.Cb().x + (pu.bv.hor >> shiftSampleHor);
     refy = pu.Cb().y + (pu.bv.ver >> shiftSampleVer);
   }
+#if JVET_Z0153_IBC_EXT_REF
+  refx = refx % (m_IBCBufferWidth >> shiftSampleHor);
+  refy = refy % (m_IBCBufferHeight >> shiftSampleVer);
+#else
   refx &= ((m_IBCBufferWidth >> shiftSampleHor) - 1);
   refy &= ((1 << ctuSizeLog2Ver) - 1);
+#endif
 
+#if JVET_Z0153_IBC_EXT_REF
+  if (refy + predBuf.bufs[compID].height <= (m_IBCBufferHeight >> shiftSampleVer))
+#else
   if (refx + predBuf.bufs[compID].width <= (m_IBCBufferWidth >> shiftSampleHor))
+#endif
   {
     const CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.bufs[compID].width, predBuf.bufs[compID].height));
 #if JVET_Z0118_GDR
@@ -8001,6 +8045,50 @@ void InterPrediction::xIntraBlockCopy(PredictionUnit &pu, PelUnitBuf &predBuf, c
   }
   else
   {//wrap around
+#if JVET_Z0153_IBC_EXT_REF
+#if JVET_Z0118_GDR
+    if (useCleanIBCBuffer)
+    {
+      int height = (m_IBCBufferHeight >> shiftSampleVer) - refy;
+      CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.bufs[compID].width, height));
+      CPelBuf srcBuf = m_IBCBuffer1.getBuf(srcArea);
+      PelBuf dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, 0)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+      dstBuf.copyFrom(srcBuf);
+
+      height = refy + predBuf.bufs[compID].height - (m_IBCBufferHeight >> shiftSampleVer);
+      srcArea = CompArea(compID, pu.chromaFormat, Position(refx, 0), Size(predBuf.bufs[compID].width, height));
+      srcBuf = m_IBCBuffer1.getBuf(srcArea);
+      dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, (m_IBCBufferHeight >> shiftSampleVer) - refy)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+      dstBuf.copyFrom(srcBuf);
+    }
+    else
+    {
+      int height = (m_IBCBufferHeight >> shiftSampleVer) - refy;
+      CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.bufs[compID].width, height));
+      CPelBuf srcBuf = m_IBCBuffer0.getBuf(srcArea);
+      PelBuf dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, 0)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+      dstBuf.copyFrom(srcBuf);
+
+      height = refy + predBuf.bufs[compID].height - (m_IBCBufferHeight >> shiftSampleVer);
+      srcArea = CompArea(compID, pu.chromaFormat, Position(refx, 0), Size(predBuf.bufs[compID].width, height));
+      srcBuf = m_IBCBuffer0.getBuf(srcArea);
+      dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, (m_IBCBufferHeight >> shiftSampleVer) - refy)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+      dstBuf.copyFrom(srcBuf);
+    }
+#else
+    int height = (m_IBCBufferHeight >> shiftSampleVer) - refy;
+    CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.bufs[compID].width, height));
+    CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea);
+    PelBuf dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, 0)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+    dstBuf.copyFrom(srcBuf);
+
+    height = refy + predBuf.bufs[compID].height - (m_IBCBufferHeight >> shiftSampleVer);
+    srcArea = CompArea(compID, pu.chromaFormat, Position(refx, 0), Size(predBuf.bufs[compID].width, height));
+    srcBuf = m_IBCBuffer.getBuf(srcArea);
+    dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position(0, (m_IBCBufferHeight >> shiftSampleVer) - refy)), predBuf.bufs[compID].stride, Size(predBuf.bufs[compID].width, height));
+    dstBuf.copyFrom(srcBuf);
+#endif
+#else
     int width = (m_IBCBufferWidth >> shiftSampleHor) - refx;
     CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(width, predBuf.bufs[compID].height));
 
@@ -8040,13 +8128,17 @@ void InterPrediction::xIntraBlockCopy(PredictionUnit &pu, PelUnitBuf &predBuf, c
     dstBuf = PelBuf(predBuf.bufs[compID].bufAt(Position((m_IBCBufferWidth >> shiftSampleHor) - refx, 0)), predBuf.bufs[compID].stride, Size(width, predBuf.bufs[compID].height));
     dstBuf.copyFrom(srcBuf);
 #endif    
+#endif
   }
 }
 
 void InterPrediction::resetIBCBuffer(const ChromaFormat chromaFormatIDC, const int ctuSize)
 {
+#if JVET_Z0153_IBC_EXT_REF
+  const UnitArea area = UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, m_IBCBufferHeight));
+#else
   const UnitArea area = UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, ctuSize));
-
+#endif
 #if JVET_Z0118_GDR  
   m_IBCBuffer0.getBuf(area).fill(-1);  
 #else
@@ -8071,6 +8163,26 @@ void InterPrediction::resetCurIBCBuffer(const ChromaFormat chromaFormatIDC, cons
 
 void InterPrediction::resetVPDUforIBC(const ChromaFormat chromaFormatIDC, const int ctuSize, const int vSize, const int xPos, const int yPos)
 {
+#if JVET_Z0153_IBC_EXT_REF
+  if(xPos == 0)
+  {
+    const UnitArea area = UnitArea(chromaFormatIDC, Area(0, yPos % m_IBCBufferHeight, m_IBCBufferWidth, ctuSize));
+#if JVET_Z0118_GDR
+    m_IBCBuffer0.getBuf(area).fill(-1);
+#else
+    m_IBCBuffer.getBuf(area).fill(-1);
+#endif
+  }
+  if(xPos - 3 * ctuSize >= 0)
+  {
+    const UnitArea area = UnitArea(chromaFormatIDC, Area((xPos - 3 * ctuSize) % m_IBCBufferWidth, (yPos + ctuSize) % m_IBCBufferHeight, ctuSize, ctuSize));
+#if JVET_Z0118_GDR
+    m_IBCBuffer0.getBuf(area).fill(-1);
+#else
+    m_IBCBuffer.getBuf(area).fill(-1);
+#endif
+  }
+#else
   const UnitArea area = UnitArea(chromaFormatIDC, Area(xPos & (m_IBCBufferWidth - 1), yPos & (ctuSize - 1), vSize, vSize));
 
 #if JVET_Z0118_GDR
@@ -8078,29 +8190,55 @@ void InterPrediction::resetVPDUforIBC(const ChromaFormat chromaFormatIDC, const
 #else
   m_IBCBuffer.getBuf(area).fill(-1);
 #endif
+#endif
 }
 
 bool InterPrediction::isLumaBvValid(const int ctuSize, const int xCb, const int yCb, const int width, const int height, const int xBv, const int yBv)
 {
+#if JVET_Z0153_IBC_EXT_REF
+  int refTLx = xCb + xBv;
+  int refTLy = yCb + yBv;
+#else
   if(((yCb + yBv) & (ctuSize - 1)) + height > ctuSize)
   {
     return false;
   }
   int refTLx = xCb + xBv;
   int refTLy = (yCb + yBv) & (ctuSize - 1);
+#endif
 #if JVET_Z0118_GDR
   PelBuf buf = m_IBCBuffer0.Y();
 #else
   PelBuf buf = m_IBCBuffer.Y();
 #endif
+
   for(int x = 0; x < width; x += 4)
   {
     for(int y = 0; y < height; y += 4)
     {
+#if JVET_Z0153_IBC_EXT_REF
+      if(buf.at((x + refTLx) % m_IBCBufferWidth, (y + refTLy) % m_IBCBufferHeight) == -1)
+      {
+        return false;
+      }
+      if(buf.at((x + 3 + refTLx) % m_IBCBufferWidth, (y + refTLy) % m_IBCBufferHeight) == -1)
+      {
+        return false;
+      }
+      if(buf.at((x + refTLx) % m_IBCBufferWidth, (y + 3 + refTLy) % m_IBCBufferHeight) == -1)
+      {
+        return false;
+      }
+      if(buf.at((x + 3 + refTLx) % m_IBCBufferWidth, (y + 3 + refTLy) % m_IBCBufferHeight) == -1)
+      {
+        return false;
+      }
+#else
       if(buf.at((x + refTLx) & (m_IBCBufferWidth - 1), y + refTLy) == -1) return false;
       if(buf.at((x + 3 + refTLx) & (m_IBCBufferWidth - 1), y + refTLy) == -1) return false;
       if(buf.at((x + refTLx) & (m_IBCBufferWidth - 1), y + 3 + refTLy) == -1) return false;
       if(buf.at((x + 3 + refTLx) & (m_IBCBufferWidth - 1), y + 3 + refTLy) == -1) return false;
+#endif
     }
   }
   return true;
diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h
index f78dc5b63ce98772ea91141fa102818a86865cb7..8ecf871c686fb483c02c9892c9c093e38f325d5f 100644
--- a/source/Lib/CommonLib/InterPrediction.h
+++ b/source/Lib/CommonLib/InterPrediction.h
@@ -190,6 +190,9 @@ protected:
   bool                 m_subPuMC;
 
   int                  m_IBCBufferWidth;
+#if JVET_Z0153_IBC_EXT_REF
+  int                  m_IBCBufferHeight;
+#endif
 #if JVET_Z0118_GDR
   PelStorage           m_IBCBuffer0; // for dirty
   PelStorage           m_IBCBuffer1; // for clean
@@ -367,7 +370,11 @@ public:
   virtual ~InterPrediction();
 
 #if INTER_LIC || (TM_AMVP || TM_MRG) || JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC
+#if JVET_Z0153_IBC_EXT_REF
+  void    init                (RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize, Reshape* reshape, const int picWidth);
+#else
   void    init                (RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize, Reshape* reshape);
+#endif
 #else
   void    init                (RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize);
 #endif
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 3aec3821ebb65aef4e715829122e5c2514df1247..061cf33a185d009b56d5196965b39bd38c4b1b2d 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -141,6 +141,7 @@
 #define JVET_Z0075_IBC_HMVP_ENLARGE                       1 // JVET-Z0075:Enlarged HMVP table for IBC
 #define JVET_Z0084_IBC_TM                                 1 // JVET-Z0084: add template matching in IBC modes (controlled by TM_MRG or TM_AMVP)
 #define JVET_Z0131_IBC_BVD_BINARIZATION                   1 // JVET-Z0131: Block Vector Difference Binarization
+#define JVET_Z0153_IBC_EXT_REF                            1 // JVET-Z0153: extend reference area for IBC
 
 // Inter
 #define CIIP_PDPC                                         1 // apply pdpc to megre prediction as a new CIIP mode (CIIP_PDPC) additional to CIIP mode
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 5dbfb29701a7cedf3e3837d227e78208a1b7efc6..60c741b7eca58862c000f37a712cd519945e5e51 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -2440,11 +2440,13 @@ bool PU::searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int h
     return false;
   }
 
+#if !JVET_Z0153_IBC_EXT_REF
   // Don't search the above CTU row
   if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
   {
     return false;
   }
+#endif
 
   // Don't search the below CTU row
   if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
@@ -2478,6 +2480,20 @@ bool PU::searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int h
     return false;
   }
 
+#if JVET_Z0153_IBC_EXT_REF
+  if ((refTopY >> ctuSizeLog2) + 2 < (yPos >> ctuSizeLog2))
+  {
+    return false;
+  }
+  if (((refTopY >> ctuSizeLog2) == (yPos >> ctuSizeLog2)) && ((refRightX >> ctuSizeLog2) > (xPos >> ctuSizeLog2)))
+  {
+    return false;
+  }
+  if (((refTopY >> ctuSizeLog2) + 2 == (yPos >> ctuSizeLog2)) && ((refLeftX >> ctuSizeLog2) + 2 < (xPos >> ctuSizeLog2)))
+  {
+    return false;
+  }
+#else
   // in the same CTU line
 #if CTU_256
   int numLeftCTUs = ( 1 << ( ( MAX_CU_DEPTH - ctuSizeLog2 ) << 1 ) ) - ( ( ctuSizeLog2 < MAX_CU_DEPTH ) ? 1 : 0 );
@@ -2518,6 +2534,7 @@ bool PU::searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int h
   {
     return false;
   }
+#endif
 
   // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
 #if JVET_Z0084_IBC_TM
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 10e7faf4728da293681d6b740157b0278684df64..44a5abae1ffe74e704eec77f69d5e87e01f13289 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -111,6 +111,13 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea )
     m_pcInterPred->resetIBCBuffer(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight());
     cs.resetIBCBuffer = false;
   }
+#if JVET_Z0153_IBC_EXT_REF
+  else
+  {
+    const int ctuSize = cs.slice->getSPS()->getMaxCUHeight();
+    m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, ctuSize, ctuSize, ctuArea.Y().x, ctuArea.Y().y);
+  }
+#endif
 #if JVET_Z0118_GDR
   // reset current IBC Buffer only when VB pass through
   if (cs.isInGdrInvervalOrRecoveryPoc())
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index 06d2286e716ecafb37a2f2706dabd141c5733e1f..c1c726dd4e2861ebc496df7d562bf7cf3f5388ce 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1796,7 +1796,11 @@ void DecLib::xActivateParameterSets( const InputNALUnit nalu )
     m_cLoopFilter.create(maxDepth);
     m_cIntraPred.init( sps->getChromaFormatIdc(), sps->getBitDepth( CHANNEL_TYPE_LUMA ) );
 #if INTER_LIC || (TM_AMVP || TM_MRG) || JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_Z0153_IBC_EXT_REF
+    m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc(), sps->getMaxCUHeight(), &m_cReshaper, m_pcPic->getPicWidthInLumaSamples());
+#else
     m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc(), sps->getMaxCUHeight(), &m_cReshaper);
+#endif
 #else
     m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc(), sps->getMaxCUHeight() );
 #endif
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index 0bb550839cdf10ecadd9f2ae62a45b3d8681ec37..6846ec79f3e3867931764fdbd839335ab2691949 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -328,7 +328,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
       cs.motionLut.lutAffInherit.resize(0);
 #endif // JVET_Z0118_GDR
 #endif
+#if !JVET_Z0153_IBC_EXT_REF
       cs.resetIBCBuffer = true;
+#endif
     }
 
     if( !cs.slice->isIntra() )
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 7c40a9590088ffb413f87f5c97cea1be2571c69a..d79986df4c95d8847f01dd0c5aa6c6278ed52c53 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -524,6 +524,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
                        getUseCompositeRef(),
     m_maxCUWidth, m_maxCUHeight, floorLog2(m_maxCUWidth) - m_log2MinCUSize, &m_cRdCost, cabacEstimator, getCtxCache()
                      , &m_cReshaper
+#if JVET_Z0153_IBC_EXT_REF
+                     , pps0.getPicWidthInLumaSamples()
+#endif
   );
 
   // link temporary buffets from intra search with inter search to avoid unneccessary memory overhead
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index e530cd645c664d11a967e3049f1a49614ffb5d4f..c749dd52fbb50ea8962c13efbecafd7f7c36798c 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -294,6 +294,9 @@ void InterSearch::init( EncCfg*        pcEncCfg,
                         CABACWriter*   CABACEstimator,
                         CtxCache*      ctxCache
                       , EncReshape*    pcReshape
+#if JVET_Z0153_IBC_EXT_REF
+                      , const uint32_t curPicWidthY 
+#endif
 )
 {
   CHECK(m_isInitialized, "Already initialized");
@@ -342,7 +345,11 @@ void InterSearch::init( EncCfg*        pcEncCfg,
 
   const ChromaFormat cform = pcEncCfg->getChromaFormatIdc();
 #if INTER_LIC || (TM_AMVP || TM_MRG) || JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING
+#if JVET_Z0153_IBC_EXT_REF
+  InterPrediction::init( pcRdCost, cform, maxCUHeight, m_pcReshape, curPicWidthY );
+#else
   InterPrediction::init( pcRdCost, cform, maxCUHeight, m_pcReshape );
+#endif
 #else 
   InterPrediction::init( pcRdCost, cform, maxCUHeight );
 #endif
@@ -1199,6 +1206,21 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
     if (pu.lwidth() < 16 && pu.lheight() < 16)
     {
+#if JVET_Z0153_IBC_EXT_REF
+      int verTop = - (int)lcuWidth;
+      int verBottom = std::min((int)(lcuWidth>>2), (int)(lcuWidth - (cuPelY % lcuWidth) - roiHeight));
+      int horLeft = - (int)lcuWidth*2;
+      int horRight = lcuWidth>>2;
+
+      for (int y = std::max(verTop, -cuPelY); y <= verBottom; y += 2)
+      {
+        if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
+        {
+          continue;
+        }        
+        for (int x = std::max(horLeft, -cuPelX); x <= horRight; x++)
+        {
+#else
       for (int y = std::max(srchRngVerTop, -cuPelY); y <= srchRngVerBottom; y += 2)
       {
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
@@ -1206,6 +1228,7 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
         for (int x = std::max(srchRngHorLeft, -cuPelX); x <= srchRngHorRight; x++)
         {
+#endif
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
             continue;
 
@@ -1242,13 +1265,23 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
         goto end;
       }
 
+#if JVET_Z0153_IBC_EXT_REF
+      for (int y = (std::max(verTop, -cuPelY) + 1); y <= verBottom; y += 2)
+      {
+        if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
+        {
+          continue;
+        }
 
+        for (int x = std::max(horLeft, -cuPelX); x <= horRight; x += 2)
+#else
       for (int y = (std::max(srchRngVerTop, -cuPelY) + 1); y <= srchRngVerBottom; y += 2)
       {
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
           continue;
 
         for (int x = std::max(srchRngHorLeft, -cuPelX); x <= srchRngHorRight; x += 2)
+#endif
         {
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
             continue;
@@ -1300,13 +1333,22 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct&  cS
 
       tempSadBest = sadBestCand[0];
 
-
+#if JVET_Z0153_IBC_EXT_REF
+      for (int y = (std::max(verTop, -cuPelY) + 1); y <= verBottom; y += 2)
+      {
+        if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
+        {
+          continue;
+        }
+        for (int x = (std::max(horLeft, -cuPelX) + 1); x <= horRight; x += 2)
+#else
       for (int y = (std::max(srchRngVerTop, -cuPelY) + 1); y <= srchRngVerBottom; y += 2)
       {
         if ((y == 0) || ((int)(cuPelY + y + roiHeight) >= picHeight))
           continue;
 
         for (int x = (std::max(srchRngHorLeft, -cuPelX) + 1); x <= srchRngHorRight; x += 2)
+#endif
         {
 
           if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth))
@@ -1530,6 +1572,14 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR
   const int cuPelY = pu.Y().y;
 
   const int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
+#if JVET_Z0153_IBC_EXT_REF
+  const int picWidth = pu.cs->slice->getPPS()->getPicWidthInLumaSamples();
+
+  srLeft = -cuPelX;
+  srTop = - 2 * lcuWidth - (cuPelY % lcuWidth);
+  srRight = picWidth - cuPelX - iRoiWidth;
+  srBottom = lcuWidth - (cuPelY % lcuWidth) - iRoiHeight;  
+#else
   const int ctuSizeLog2 = floorLog2(lcuWidth);
   int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
 
@@ -1538,6 +1588,7 @@ void InterSearch::xSetIntraSearchRange(PredictionUnit& pu, int iRoiWidth, int iR
 
   srRight = lcuWidth - (cuPelX % lcuWidth) - iRoiWidth;
   srBottom = lcuWidth - (cuPelY % lcuWidth) - iRoiHeight;
+#endif
 
   rcMvSrchRngLT.setHor(srLeft);
   rcMvSrchRngLT.setVer(srTop);
@@ -10650,9 +10701,11 @@ bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, in
     return false;
   }
 
+#if !JVET_Z0153_IBC_EXT_REF
   // Don't search the above CTU row
   if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
     return false;
+#endif
 
   // Don't search the below CTU row
   if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
@@ -10682,6 +10735,20 @@ bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, in
     return false;
   }
 
+#if JVET_Z0153_IBC_EXT_REF
+  if ((refTopY >> ctuSizeLog2) + 2 < (yPos >> ctuSizeLog2))
+  {
+    return false;
+  };
+  if (((refTopY >> ctuSizeLog2) == (yPos >> ctuSizeLog2)) && ((refRightX >> ctuSizeLog2) > (xPos >> ctuSizeLog2)))
+  {
+    return false;
+  }
+  if (((refTopY >> ctuSizeLog2) + 2 == (yPos >> ctuSizeLog2)) && ((refLeftX >> ctuSizeLog2) + 2 < (xPos >> ctuSizeLog2)))
+  {
+    return false;
+  }
+#else
   // in the same CTU line
 #if CTU_256
   int numLeftCTUs = ( 1 << ( ( MAX_CU_DEPTH - ctuSizeLog2 ) << 1 ) ) - ( ( ctuSizeLog2 < MAX_CU_DEPTH ) ? 1 : 0 );
@@ -10712,6 +10779,7 @@ bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, in
   }
   else
     return false;
+#endif
 
   // in the same CTU, or valid area from left CTU. Check if the reference block is already coded
   const Position refPosLT = pu.Y().topLeft().offset(xBv, yBv);
diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h
index 5172a29d49a37b6b27bff586a83adcae8678ae11..e0ec55c28b516eb669767095eb2c49ef2ce5b4e0 100644
--- a/source/Lib/EncoderLib/InterSearch.h
+++ b/source/Lib/EncoderLib/InterSearch.h
@@ -433,6 +433,9 @@ public:
                                       CABACWriter*   CABACEstimator,
                                       CtxCache*      ctxCache
                                      , EncReshape*   m_pcReshape
+#if JVET_Z0153_IBC_EXT_REF
+                                    , const uint32_t curPicWidthY
+#endif
                                     );
 
   void destroy                      ();