Driving MIPI LCD with Xilinx FPGA: A Journey

Good morning everyone, I sincerely apologize for not updating the articles on my public account for almost a year due to being extremely busy. Recently, I debugged a MIPI LCD driven by Xilinx FPGA, and the process is hard to describe in words. I share this so that others can avoid pitfalls.

My screen is a vertical display with a resolution of 1080*1920, using burst transmission mode, filling BL packets between sync and data. The screen initialization is completed through LP communication, and the driving SoC is Xilinx ZU9EG. MIPI is routed from BANK66, where the same BANK has inputs for MIPI CSI Sensor and drives the MIPI DSI screen. The version of Vivado is 2023.2.2. The process of driving the screen went through three stages:

Stage One: Using Xilinx’s official MIPI DSI TX Subsystem IP core

After a lot of effort, the screen still wouldn’t light up. Upon carefully reading the datasheet, I found that this IP does not support LP mode communication. Its so-called DCS mode is sent via HS short packets. Alright, I admit I didn’t read the manual carefully, but almost all MIPI DSI LCD screens need to receive initialization commands via LANE-0 in LP mode. Clearly, this IP lacks engineering value. I immediately switched plans.

Stage Two: Using Xilinx’s DPHY physical layer IP

I am inherently lazy, so if there is an official IP available, I must use it. After much effort, I implemented the DSI and control logic, then called the D-PHY physical layer IP. When powered on, it worked well. However, the problem arose when I combined all the projects; it wouldn’t light up. After thorough investigation, I found that the init_done signal of the D-PHY IP was not raised. I checked the output signals of the IP core such as pll_locked and reset, and they were all normal. I wanted to investigate further into the core, but the IP core code was encrypted, so I couldn’t see it, which cut off this path. I tried to mask resources, and when I masked the MIPI CSI receiving module, it could be raised normally again. It turns out that when the same bank has both MIPI D-PHY IP for CSI and DSI, the init_done of the D-PHY physical layer IP connected to DSI cannot be raised. I don’t know what resources are shared here and why there is a conflict. I had no choice but to seek a manual coding solution.

Stage Three: Manual Coding

With no options left, I was forced to code manually. After much effort and chaos for several days, I manually coded the physical layer, DSI layer, and control logic, building the lower layer directly with source code, and it worked! All scenarios are applicable! A simple screen touch effect can be seen in the accompanying images of this article.

During the debugging process, I also discovered several other bugs in Vivado.

Summary of feelings: MMP, I still have to do it myself. This official IP is unreliable, completely unreliable!

Leave a Comment

×