Date: Sep 23, 2021
Click Count: 72
MIPI DSI is a packet-based, high-speed interface for transferring video data to LCD/OLED displays. In a way, it is similar to DisplayPort with a more power-efficient (and therefore more complex) physical layer.DSI is mainly used for mobile devices (smartphones and tablets).
I started this project as a basis for building a low cost HD projector. Later I realized that it is also useful for VR applications and as a general purpose graphics card for small uCs - that's why it uses the Arduino shield format.
LCD/OLED screen controller with MIPI DSI interface, Arduino expansion board format, HDMI to DSI adapter and built-in frame buffer.
Supports 3/4 channel MIPI DSI displays.
DSI controller supports resolutions up to 1080x1920 at 60 Hz refresh rate.
Converts HDMI video to DSI - lets you connect any MIPI DSI screen to your PC, Raspi or similar device. Convert up to 720p@60 Hz or 1080p@48 Hz.
Built-in frame buffer with simple graphics stack allows connection of small microcontrollers such as Arduino via 8-bit parallel or SPI bus
Less than $50 BOM, including 4-layer PCB (@100 pieces).
Power supply via mini USB connector.
Embedded 32-bit CPU for user applications.
12/2013: Schematic and PCB completed.
12/2013: Initial version of firmware for Iphone4/4s screen on FPGA development kit.
02/2014: Got the PCB and components.
02/2014: Assembled test PCB to drive 3-channel and 4-channel screens.
07/2014: Started HDMI <> DSI conversion.
08/2014: HDMI conversion for 640x960 Iphone4 screen.
08/2014: DSI core implements 1080p @ 60 Hz (48 Hz with HDMI conversion).
08/2014: Revision 1.1. PCB design, schematics and firmware released.
06/2015: Prototypingr Revision 2.0.
Arduino interface / drawing commands (on demand).
Testing external HDMI decoders with displays larger than 1080p.
Port Doom running on a soft core CPU.
The following diagram shows the main modules of the design.
FPGA: Xilinx Spartan-6-SLX9. Highlights: Hobby-friendly TQFP144 package and built-in SerDes, rated up to 1080 Mbits/s. The FPGA did almost everything in this project, hosting the MIPI DSI core, frame buffer controller with DDR memory, HDMI/DVI decoder. Everything is managed by the embedded Lattice Mico32 CPU.
DSI Level Adapter: A bunch of resistors that connect the FPGA's 1.8 V SSTL/LVCMOS I/O to the DSI level. more information in the FPGA section.
DSI Connector: Standard 2x15pin 2mm pitch female connector with all DSI signals, power and some GPIO pins for interfacing with the display. Since the connector pins are arranged differently between displays, the idea here is to use a miniature adapter board to host the connector and its wiring for a specific LCD.
DDR SDRAM, which provides memory for the frame buffer, as most smartphone DSI displays don't have it.
HDMI input: slow version, using the FPGA's ISERDES module (up to 1080p @ 48 Hz) or fast version (1080p @ 60 Hz), based on ADI's ADV7611 chip. The external HDMI decoder shares some pins with the SDRAM chip and the host interface, so the Full HD-60 Hz version works only as an HDMI to DSI adapter.
Host Interface: 12 pins connect to the IOH/IOL header of the Arduino expansion board. The exact functionality is not yet defined, I am considering a 4-wire SPI interface and an 8-bit parallel bus.
USB UART CP2102 chip, providing USB UART, software bootloader and JTAG functionality for the FPGA.
Main power supply: Integrated PMIC (TI/National LM26480). Voltages are: +3.3 V (HDMI input, USB, host I/F), +2.5 V (SDRAM and FPGA Vccaux), +1.8 V (DSI), +1.2 V (FPGA core).
LCD bias/backlight power: Most displays require some higher positive/negative voltages to operate. The board has a simple DC/DC converter for this purpose that can generate symmetrical voltages up to +/- 6 V. The panel-specific voltage can be adjusted by connecting a resistor between one of the DSI connector pins and ground. There is also a separate backlight LED current driver that can be programmed by another resistor. Both DC/DC converters use the TPS61041 chip.
Printed Circuit Board Design
The DSI shield consists of two PCBs - the main board, where all the cool stuff is located, and a small adapter board, usually different for each display, connected via a 30-pin 2 mm header.
The main board is a typical Arduino expansion board. I wired the design on 4 layers, with signals on 2 outer layers, a contiguous ground layer, and a separate power layer. the DDR is located directly below the FPGA to simplify wiring. the SSTL to DSI level converter resistors are placed right next to the FPGA output pins to avoid stubs. All differential pairs are calculated for Z0=100 ohms.
The adapter board simply routes the DSI channel, power and backlight signals to the display connector. There is absolutely no standard for managing DSI LCD panel connectors and power supplies, so you will need a separate adapter board for each display type. They are simple (2 layers, one connector + several resistors for setting bias voltage/backlight LED current). The following screenshot shows the layout of the Iphone 4/4S Retina display adapter.
The heart and soul of the project: Xilinx Spartan-6 - a low cost FPGA with gigabit SerDes blocks on each pin, which makes it possible to sample HDMI/DVI signals or generate DSI data streams using only a bunch of external resistors. the guts of the FPGA are shown below. It is currently only a very short description of what is in the Verilog/VHDL code.
CPU and peripherals
The CPU is responsible for initializing the display and controlling the frame buffer. It can also do some simple drawing operations (though not too fast).
I chose the Lattice Mico32 soft processor because of the maturity of the design and the fact that other successful OSHW projects use it (e.g. Milkymist). the CPU controls the following peripherals through the Wishbone interconnect.
- A small 16 kB block of RAM containing the software. The first 2 kB are reserved for the bootloader and the remaining 14 kB for the actual application.
- UART (for debugging and loading software).
- DDR memory (slow access via Wishbone to FML bridge).
- Framebuffer and DSI core (to set video mode timing)
- EDID RAM, masquerading as 2402 I2C EEPROM. tells the HDMI source the timing requirements of our display.
DDR memory and frame buffer
The memory subsystem uses Milkymist's high performance dynamic memory controller (thanks Sebastien!), connected to 32 MByte DDR RAM (16-bit, 100 MHz). the RAM is currently only used to store the displayed image, the CPU cannot execute code from it. The frame buffer core simply pumps frame data from the DDR RAM to the video overlay engine, where it is composited with HDMI video.
The HDMI/DVI decoder in the XAPP495 of the Xilinx Application Note. Inputs HDMI and outputs parallel RGB pixel, clock and sync signals. Used almost as a black box here.
As the name suggests, it puts together the image from HDMI and the frame buffer (using simple color keying) and outputs the final pixel stream from the display. Includes some elastic buffering and frame alignment logic between 3 different clock domains (HDMI clock, CPU system clock and DSI core clock).
The architecture of the DSI core is shown in the following diagram.
The pixel pipeline consists of 5 phases.
- The first stage is a large 4096 entry FIFO, which serves to move the RGB pixel data from the system clock domain to the DSI byte clock domain (= data rate divided by 8). Thanks to this, we don't need to synchronize the system with the pixel clock - the pixels can run a little faster/slower.
- The timing generator generates a series of DSI High Speed (HS) packet headers and payloads that indicate horizontal/vertical sync pulses, fade periods, or pass RGB data to the display. Display resolution and fade time are programmed by the CPU via the Wishbone interface.
- The packet assembler receives packet requests, padding them to 3 or 4 parallel bytes, adding packet headers and tails with ECC/CRC checksums.
- The lane control module (4 for the data channel and 1 for the clock channel) controls the transition between low power (LP) and high speed (HS) modes and generates LP mode signals to initialize and enable the display. At the output of the lane control module, we get the LP+/LP- signals and the 8-bit parallel data stream from the SerDes. The clock channel data output is simply fixed to 0xaa, thus generating a DDR clock at the output of the SerDes.
- SerDes blocks - Use the OSERDES2 blocks of the Spartan-6 to convert parallel 8-bit data to high-speed serial bits. Thanks to the IODELAY programmable delay lines on each FPGA pin, the correct timing between data and clock channels is also ensured.
Platform Flash In-System Programmable Configuration PROMS
Xilinx PLCC20 electronic devices
FPGA Spartan-IIE Family 150K Gates 3888 Cells 357MHz 0.15um Technology 1.8V 208-Pin HSPQFP EP
FPGA Virtex-4 FX Family 41904 Cells 90nm Technology 1.2V 1152-Pin FCBGA
FPGA Virtex-4 FX Family 41904 Cells 90nm Technology 1.2V 1152-Pin FCBGA