ECPi Details
Lots of technical details about the Raspberry Pi Zero, ECP5 FPGA and making them work together.
ECPi Camera RGB888. View
The first ECPI camera application will input RGB888 from a Raspberry Pi Zero to the IcePi Zero FPGA at 640x480 resolution.
Digital Video Port (DVP) is a very simple, low cost, license free protocol for transmitting. images using parallel, low frequency single ended wires. The problem is that there are no DVP Cameras with a 24 bit wide data path, so only smaller, low resolution images are currently possible. One would have to use the more complex, higher frequency, proprietary MIPI CSI, but there are no open source FPGAs with MIPI CSI hard cores currently available. The Lattice Crosslink NX 17/40 is back ordered for two years. The Appicula project to support Gowin FPGAs with MIPI CSI hard cores just started and will take time to complete. There are closed source FPGAs with MIPI CSI, but they are all more expensive. And even if you did find a MIPI CSI FPGA, you would still need a microcontroller to set all of the registers in the inmage sensor. Best to use the ECPi Camera RGB888 application.
This is a reasonably simple application. On the newer (Bookworm and later) releases of the Raspberry Pi OS, you have to edit /boot/firmware/config.txt and add the following lines:
# Configure the GPU to output RGB888
dtparam=rgb888
# Set the device tree overlay sending the gpu output to the 28 pins.
dtoverlay=vc4-kms-v3d
# Set the timings for the video display.
dpi_timings=640 0 16 96 48 480 0 11 2 32 0 0 0 60 0 25175000 1
#The fields in order:
#h_active = 640
#h_sync_pol = 0 (negative)
#h_fp = 16 (front porch)
#h_sync = 96
#h_bp = 48 (back porch)
#v_active = 480
#v_sync_pol = 0 (negative)
#v_fp = 11
#v_sync = 2
#v_bp = 32
#v_offset_a = 0
#v_offset_b = 0
#pixel_rep = 0
#frame_rate = 60
i#nterlaced = 0
#pixel_freq = 25175000 (25.175 MHz)
#aspect = 1 (4:3)
These values have not yet been tested.
You also have to configure the FPGA. The signal path between the RPi Zero and the FPGA is 28 bits wide. 24 bits of RGB data plus Horizontal Sync, Vertical Sync, Blank and clock. All but the clock are registered and then sent to a dummy module where you can add your logic, and from there, the signal is sent to the GPDI/HDMI/DVI output port. The clock is handled differently. It is sent to the PLL and then through the clock tree network, such that its output is aligned with the input clock, placing both the RPi Zero DPI output and the FPGA fabric in the same clock domain.
ECPi PLL. View
The ECPi PLL uses the RPI's pixel clock as a source, and generates both the FPGA's pixel clock and the FPGA's TMDS/DVI/HDMI clock phase aligned with the input, and compensated for the FPGA's clock distribution network.
Why does dividing increase the frequency??? For anyone who is not so good at digital electronics, the dividers are just counters. Count to 5 or 25 and change the output. The magic is all in how the analog PLL does the multiplication. It has to boost the output frequency and shift its phase until the divided and delayed feedback signal matches the input signal.
- Configuring the ECP5 PLL The best source of information on configuring the pll.
- EHXPLL Yosys black box definition of the module with both default parameters and I/O wires.
- ECP5 Clock Generation
- Lattice PLL Documentation
- Lattice ECP5 DataSheet
- PLL Multiplier Divider Calculator
- YOSYS EHXPLL default values.
- IcePi Zero PLL Source
- Project Trellis ULX3S Example
- Project Trellis SocVersa5G Example
- Project Trellis soc_ecp5_evn
- More thoughts and links
ECPi Clocks. View
All you will need to know about the clocks on the Raspberry Pi Zero and the ECP5 FPGA working together in ECPi camera.
In order for the ECP5 and the RPI0 to work together their pixel clocks needs to be synchronized and in phase. If the pixel clocks are even slightly different frequencies, over time they will drift apart, there will be too much or too little data provided, and the HDMI timing requirements will be violated. The image may scroll and wrap. If the signals are out of phase, the setup and hold times will be violated leading to metastability.
For low frequencies the ECP5 can just use the RPI Zero's pixel clock. By the time it runs through the ECP5's clock tree, there will be a phase difference, but the ECP5 has dedicated circuitry to correct for that.
This page describes the different standard HDMI screen sizes, the pixel format and the required pixel clock frequency.
If that approach does not work, one could transmit the RPI Zero's oscillator to the FPGA, and have both chips generate clocks in phase at the same frequency. In this case, there are two relevant clocks: the oscillator and the pixel clock. The RPI0 19.2 Mhz oscillator can be published on general purpose clock ports such as pins 4, 5 and 6. Ideally, it should be input into the dedicated FPGA clock input ports from which it is fed directly to the PLL. It can also be routed through the FPGA fabric, but the quality degrades. Since the IcePi Zero does not hardwire the RPI0 oscillator output port directly to the FPGA PLL input port, we will be sending the signal through the fabric.
Once the two chips share an oscillator signal, we need to synchronize their pixel clocks which are generated by the two PLLs. PLLs work by first multiplying the frequency and then dividing it. The RPI0 PLL works by first multiplying the oscillator frequency by a fractional number up to many GigaHz, and then dividing it. It can be divided 3 times. The ECP5 FPGA PLL is more limited than the RPI PLL. The Lattice FPGA PLL documentations says that it also multiplies the oscillator frequency by a number but only by integers from 1 to 128. The resulting signal should not exceed 800 Mhz. That signal is then divided by a number between 1 and 128. To keep the two pixel clocks synchronised, we need to use the same multiply and divide frequencies. The resulting Pixel clock frequency should then be as close as possible to the number specified by the VESA display standards.
A 640 * 480 HDMI has a pixel clock of 25.175 Mhz. Look at the Discrete Monitor Timings (DMT) column. The RPI clock is 19.2Mhz.
This tool shows us that if we multiply by 21 and divide by 16, we get a frequency of 25.2 Mhz. Quite close to 25.175 Mhz. It is quite confusing because they call them frequency dividers, they are dividing each square wave into multiple square waves, but they actually increase the frequency.
The good news is that we can set the RPI display frequency (page 5) to be a legal FPGA frequency, and it should generate the correct multiplies and divides. We can then query what the frequency is.
vcgencmd measure_clock dpi
If you are not sure what are the legal pixel clocks, here is the video timing calculator.
The ULX3S ECP5 VHDL DVI RTL also provides some hacks if the default PLL values do not work. I wonder why those hacks work.
The ECP5's PLL does include phase adjustment circuitry, so its pixel clock can be in phase with the RPI0's output pixel clock.
There is also an issue that it may not be possible to both publish RPI0 RGB788 and the oscillator signal at the same time . The documentation warns about this,focusing on the PWM. and SPI signals. Some testing and more reading will be required.
There may be an issue with how the clocks are generated.
And of course how to configure displays has changed. I am not at all sure that one can switch one of the pins to be a clock gpio. Maybe this Korean pages says what needs to be done.
The first project will be to connect a RPI0 to an oscilliscope and see if the data is available. Can anyone recommend a USB 3 oscilliscope? Maybe time to join hackerspace Krakow.
Raspberry Pi Chips. View
This page evaluates the Raspberry Pi Chips from the perspective of a MIPI CSI to DPI bridge. Turns out they all work fine.
RGB788 Works on all RPI chips.
The gpio directive allows GPIO pins to be set to specific modes and values at boot time in a way that would previously have needed a custom dt-blob.bin file. Each line applies the same settings (or at least makes the same changes) to a set of pins, addressing either a single pin (3), a range of pins (3-4), or a comma-separated list of either (3-4,6,8).
BCM2835 used in the Raspberry Pi Zero, Raspberry Pi Zero W, Raspberry Pi Zero. The data sheet now does not even list the alternative functions.
RP3A0 used in the Raspberry Pi Zero 2 W, Raspberry Pi Zero 2 W with headers. The GPCLK0-2 overlap with the DPI0-2. Are those he high order bits, and there is a problem, or the low order bits and all is well. But it does not matter, they do that thing where the frequency jumps by 1 bit.
BCM2711: used in the compute module 4. Datasheet The GPCLK0-2 overlap with the DPI0-2. Are those he high order bits, and there is a problem, or the low order bits and all is well.
BCM2712 is the 16nm application processor used in Raspberry Pi 5, 500, 500+, and Compute Module 5.
Here is the documentation
Raspberry Pi Zero or Zero 2W?. View
This 12 minute video is an excellent technical comparison of the two products.
RPi Zero Configuration. View
There are two parts to configuring the RPI Zero. Defining the hardware connectivity and controlling the hardware.
Both are controlled from /boot/firmware/config.txt
The hardware connectivity is defined using two device tree overlays.
dpi24.dts tells the output pins to read the DPI data from the GPU. The code repository will contain dpi23.dts, where pin 4 has been excluded from the list.
There is also a need for an overlay to set the pin 4 to transmit the osciallator clock.
Here is what claude says to add to the config.txt file. enable_dpi_lcd=1 dpi_group=2 dpi_mode=87 dpi_output_format=0x6f005 dpi_timings=640 0 16 96 48 480 0 10 2 33 0 0 0 60 0 25000000 1 dtoverlay=dpi24x
#The dpi_timings fields in order:
# 640 — horizontal active pixels
# 0 — hsync polarity (0 = negative)
# 16 — horizontal front porch
# 96 — hsync pulse width
# 48 — horizontal back porch
# 480 — vertical active lines
# 0 — vsync polarity (0 = negative)
# 10 — vertical front porch
# 2 — vsync pulse width
# 33 — vertical back porch
# 0 0 0 — offsets/pixel rep (unused)
# 60 — frame rate
# 0 — interlaced (no)
# 25000000 — pixel clock (25 MHz)
# 1 — aspect ratio (4:3)
# Pixel clock is 25 MHz — close to the standard 25.175 MHz.
# Most displays accept this.
Raspberry Pi Zero Details. View
Lots of technical details and links about the Raspberry Pi Zero.
There are multiple versions of the Raspberry Pi Zero (RPI0). We recommend using the 32 bit $10 Raspberry Pi Zero which has one BCM2835 core, running the ARM1176JZF-S cpu and using these peripherals. One core is enough for this application. It is the GPU which does all of the work.
The RPI0 has a 19.2Mhz Oscillator which can be read from the GPIO clock ports. I cannot find the documentation for how the HDMI clock is generated. Maybe the oscillator is divided to several giga herz and then multiplied to the required hdmi pixel clock frequency.
More information about the internal details can be gained from the [C++ Circle library] (https://circle-rpi.readthedocs.io/_/downloads/en/48.0/pdf/#24#6) for bare metal RPI applications.
You could also choose to use the $15-20 Raspberry Pi Zero 2W w which has 4 cores using more power, but it is a 64 bit machine so its code takes up more space leaving less room for your application. Designations "H" or "with headers" means that the part comes with presoldered headers.
The Raspberry Pi form factor header has 40 header pins, with 12 power and ground pins leaving 28 pins for the 24 bit DPI output, clock, horizontal sync, vertical sync and blank. That supports RGB888.
Almost Perfect! The problem is that then the RPI0 and the FPGA are in different clock domains, and will drift apart. HDMI has tight specs, they cannot change or one risks loosing the lock. Over time the image would drift up or down on the screen and wrap. Not good. To keep the two chips in phase, they need to be driven by the same oscillator.
RPI0 can output a low-jitter 19.4Mhz clock on 3 of the low order pins. That clock can be routed to the FPGA's PLL. So in practice the MIPI CSI to FPGA DPI bridge allows RGB788, RGB878, RGB887. SInce humans are more sensitive to green, it is recommended to use either the blue or red low order pins for the clock. There is a lot of blue in the sky and in the ocean, so we are choosing red for the 7 bit color.