Some factor that makes IP larger than what you can design:
IP from vendors are feature-rich. Even if you use a fraction of the features of an IP (through GUI configuration), they are designed to support many features and architectures which unfortunately cost on the area-side. Take your DDR example, you could design it to support only 1 burst length and save logic that way, but you can't do that for an IP with a more general use case.
They are optimized for speed and throughput. From what I've seen, lot of care is taken from vendors to ensure fast critical path. They will also register inputs/outputs and use FIFO as buffer on interfaces. It's fine if you need it in your application, otherwise it's lost space.
Nowadays, they use a standard bus like AXI or Avalon to program the core's registers. The interface is huge and can be larger than the functionality for smaller core! I use a scaler core on Xilinx, the AXI version uses 50% more logic than the former version which exposed all registers as ports!
In the end, you can do smaller if you target a specific design's need, but if you need something general, robust, feature-rich and easy to incorporate in an IP-subsystem you have to pay the cost of it!