Skip to content
Schneider & Andre Schneider & Andre International Commercial Litigation
London · Lincoln's Inn Fields Frankfurt am Main Zürich Twenty-three years restoring justice across 31 jurisdictions.
Schneider & Andre — Cross-Border Disputes Notes

How to use a 1.77 inch TFT with a Zynq FPGA?

·By admin

How to Use a 1.77 Inch TFT with a Zynq FPGA

To use a 1.77 inch TFT display with a Zynq FPGA, you need to interface the display’s parallel RGB or SPI interface to the FPGA’s GPIO pins, configure the FPGA logic to generate the correct timing signals, and write a driver to send pixel data. The most common approach is to use the SPI interface for initialization and control, then switch to RGB mode for high-speed pixel streaming. For a 1.77 inch spi mcu rgb tft display, the typical resolution is 128x160 pixels, with a 16-bit color depth (RGB565) requiring 128x160x2 = 40,960 bytes of frame buffer memory. The Zynq FPGA, with its ARM Cortex-A9 processor and programmable logic, can handle this using a combination of AXI DMA for data transfer and custom RTL for timing generation.

First, examine the display’s datasheet. Most 1.77 inch TFTs use a controller like the ST7735S or ILI9163. These controllers support both SPI (for commands and slow data) and parallel RGB (for fast pixel updates). The SPI interface runs at up to 10 MHz, while the RGB interface requires a pixel clock (PCLK) of around 2-4 MHz for 60 fps refresh. The display’s pinout typically includes: CS (chip select), DC (data/command), RESET, SCLK (SPI clock), MOSI (SPI data), and for RGB mode: VSYNC, HSYNC, PCLK, and 8 or 16 RGB data lines. Check the specific module—some 1.77 inch displays use a 16-pin or 24-pin FPC connector. Measure the voltage levels: most operate at 3.3V, but the backlight LED may need 20 mA at 3.0V.

For the Zynq FPGA, you have two main paths: use the PS (processing system) with AXI GPIO or use the PL (programmable logic) with a custom controller. The PS approach is simpler but slower—you can bit-bang SPI via AXI GPIO at around 1 MHz, which is fine for initialization but not for video. The PL approach gives you full control. I recommend using the PL to implement a SPI master and an RGB timing generator. For a 128x160 display at 60 Hz, the RGB timing requires: VSYNC pulse width of 1 line, back porch of 2 lines, front porch of 2 lines, total vertical period of 165 lines; HSYNC pulse width of 1 pixel, back porch of 2 pixels, front porch of 2 pixels, total horizontal period of 132 pixels. The pixel clock frequency is 165 * 132 * 60 = 1.3068 MHz, but many displays tolerate 2-4 MHz.

Now, let’s break down the hardware connection. Use a Zynq board like the ZedBoard or PYNQ-Z1. Connect the display’s SPI pins to PMOD or Arduino headers. For example, assign SCLK to bank 34 pin 13, MOSI to pin 14, CS to pin 15, DC to pin 16, and RESET to pin 17. For RGB mode, you need 8 data lines (D0-D7) plus VSYNC, HSYNC, and PCLK. Use a 3.3V regulator if the board’s supply is 3.3V already. Add a 10 µF capacitor near the display’s power pin to filter noise. The backlight can be driven by a GPIO with a 100 ohm resistor in series to limit current to 20 mA. If the display uses a 16-bit parallel interface, you’ll need 16 data lines, which may consume 22 GPIOs total—check your board’s available pins.

In the FPGA logic, create a top-level module with two sub-modules: spi_ctrl and rgb_ctrl. The spi_ctrl module handles initialization: send a reset pulse (low for 10 ms), then send commands to set the display to RGB mode. For the ST7735S, the sequence is: SWRESET (0x01), SLPOUT (0x11) with 150 ms delay, COLMOD (0x3A) set to 0x05 for 16-bit color, DISPON (0x29). Use a state machine that reads command bytes from a block RAM initialized with the init sequence. Each byte is sent via SPI at 1 MHz, with DC set low for commands and high for data. The SPI clock polarity is typically CPOL=0, CPHA=0 (mode 0).

After initialization, the rgb_ctrl module takes over. It generates VSYNC, HSYNC, and PCLK signals based on the timing parameters. The pixel data comes from a frame buffer stored in the Zynq’s DDR memory. Use the AXI HP ports to stream data from the PS to the PL. Configure a VDMA (Video Direct Memory Access) IP core in Vivado: set the stream width to 16 bits, the frame buffer size to 128*160*2 = 40,960 bytes, and enable circular buffer mode. The VDMA reads from DDR and outputs an AXI4-Stream. Connect this stream to a simple FIFO (width 16, depth 512) to buffer pixels. Then, the rgb_ctrl module reads from the FIFO on each PCLK rising edge when HSYNC and VSYNC are active.

Here’s a concrete example of timing parameters for a 1.77 inch display with 128x160 resolution at 60 Hz:

ParameterValueUnit
Horizontal resolution128pixels
HSYNC pulse width1PCLK cycles
H back porch2PCLK cycles
H front porch2PCLK cycles
Total horizontal period133PCLK cycles
Vertical resolution160lines
VSYNC pulse width1HSYNC lines
V back porch2HSYNC lines
V front porch2HSYNC lines
Total vertical period165HSYNC lines
Pixel clock frequency1.3068MHz

To generate the pixel clock, use the Zynq’s MMCM (Mixed-Mode Clock Manager) in the PL. Configure it to output 1.3068 MHz from a 100 MHz reference clock. The MMCM can divide down to 1 MHz with good jitter performance. Alternatively, use a counter-based clock divider if you don’t need precise frequency—simply divide the 100 MHz clock by 76 to get 1.315 MHz, which is within tolerance. The display’s datasheet typically allows a PCLK range of 0.5-4 MHz.

Now, the software side on the Zynq PS. Write a bare-metal or Linux driver. For bare-metal, use Xilinx SDK to create a project that initializes the VDMA and writes a test pattern. For example, fill the frame buffer with a gradient: for each pixel at (x, y), set R = x*2, G = y*2, B = 0, pack into 16-bit RGB565. The VDMA automatically streams the data to the PL. For Linux, use the Xilinx VDMA driver, which exposes a /dev/video0 device. You can use ffmpeg or a custom C program to write frames. The frame buffer address must be physically contiguous—allocate it using CMA (Contiguous Memory Allocator) or use the XDMA driver.

One common issue is the display’s SPI command sequence. Some 1.77 inch modules require a specific initialization table for gamma correction, frame rate, and display inversion. For the ST7735S, the gamma curve is set by commands 0xE0 and 0xE1 with 16 bytes each. The default values from the datasheet work for most applications. If you see color inversion, send the command 0x21 (INVON) to invert the display. Also, check the MADCTL (0x36) register to set the orientation: 0x00 for portrait, 0x60 for landscape, 0xC0 for reverse portrait. The display’s pixel ordering can be set to RGB or BGR via the COLMOD command—some modules use BGR, so you may need to swap bytes in the pixel data.

For debugging, use a logic analyzer to capture the SPI signals. The initialization sequence should be correct: after reset, the display should show a white screen. If it stays black, check the backlight enable pin. Some modules have a separate BL pin that needs a PWM signal—use a 1 kHz PWM with 50% duty cycle from a PL counter. If the display shows random pixels, the RGB timing is likely off. Measure the VSYNC and HSYNC signals with an oscilloscope—they should be clean pulses with the correct polarity. The ST7735S expects VSYNC active low, HSYNC active low, and PCLK active on the rising edge. Check the datasheet’s timing diagram for exact setup and hold times.

Performance-wise, the Zynq can easily drive this display at 60 fps. The PL’s RGB controller consumes about 100 LUTs and 50 FFs, plus the VDMA uses a few BRAMs. The PS’s ARM core can run at 667 MHz, so even software rendering is feasible. For a full video stream, use the PS’s NEON SIMD unit to convert YUV to RGB565 at 30 fps. The VDMA’s bandwidth is 40,960 bytes per frame, at 60 fps that’s 2.46 MB/s, well within the HP port’s 1.2 GB/s limit. The SPI initialization takes about 200 ms, after which the display runs continuously.

Another approach is to use the Zynq’s PL directly as a frame buffer generator. Write a simple VHDL module that generates a color bar pattern: divide the screen into 8 vertical stripes, each with a different color. This eliminates the need for DDR memory and is a good test. The module increments a pixel counter, and when it reaches 128, it increments a line counter. The color is selected based on the line counter’s high bits. This uses only 20 LUTs and runs at 1.3 MHz. You can then switch to the VDMA-based approach for real data.

For the physical layout, keep the SPI and RGB traces short—less than 10 cm to avoid signal integrity issues. The Zynq’s GPIO pins have a slew rate control; set it to slow for the PCLK to reduce EMI. Use a ground plane under the display connector. If the display has a touch panel, it’s usually resistive and uses a separate SPI interface—you can connect it to the Zynq’s second SPI controller. The touch controller’s XPT2046 requires 4-wire SPI and returns 12-bit ADC values. Poll it at 100 Hz for touch input.

To summarize the key steps: 1) Read the display’s datasheet for pinout and timing. 2) Connect the display to the Zynq’s PL pins. 3) Implement SPI initialization in PL logic. 4) Implement RGB timing generator in PL. 5) Configure VDMA in Vivado to stream from DDR. 6) Write PS software to fill the frame buffer. 7) Test with a simple pattern. 8) Debug with an oscilloscope. This setup works reliably for embedded graphics, data visualization, or simple UI applications. The Zynq’s flexibility allows you to add hardware acceleration for image processing, like scaling or rotation, in the PL without affecting the display’s refresh rate.