LED Display 2014-2015

LED Display is an attempt to create a clear, bright, and cost-effective medium for displaying video to be viewed during any time of day and from a distance. Some of the goals of the project for the 2014-2015 academic year is to improve the quality of the video, to add HDMI input, and to extend the size and resolution of the display.

Problem Statement
The past senior design project LED Video Player allowed us to drive full-motion video to LED panels using an FPGA.

The system we're developing now will send an HDMI video signal directly to an FPGA. The FPGA will then pass a scaled down copy of the video to the LED panels. This will allow "plug-and-play" usage with any HDMI source, without the need for a computer, and with little to no configuration required.

Upon completion of this project we will be able to drive real-time video to multiple LED panels from any HDMI signal that's in a supported resolution.

Background
LED panels are used around the world for businesses large and small. However the choices are a little lacking when it comes to inexpensive solutions that are easy to use, open source, and that work with commodity hardware such as the Adafruit LED panels. Filling this gap would be nice for small businesses who aren't afraid to get their hands a little dirty, as well as provide an excellent starting codebase for LED enthusiasts.

The previous LED Video Player project was a good start, but it had some downsides and required custom software. In our LED Display project we hope to make sending video to a LED panel as easy as plugging in an HDMI cable.

Previous Work
Main page: LED Video Player.

Interview with Dr. Robert Rinker
Our interview with Dr. Rinker was totally laid back. We made sure we were all on the same page with the general project direction, but we did not lay down super detailed requirements or specifications.

Dr. Rinker was happy with our initial (and in the end final) FPGA choice, the Digilent Atlys. He was concerned with the difficulty of FPGA development and for that reason didn't want the project goals to be too difficult.

Existing Work
The HDMI2USB project on github has a lot of existing opensource HDMI HDL. In particular the HDL for recieving HDMI video and for acting as an EDID slave has proven to be very useful.

HDMI Basics
HDMI is based on DVI, and as we’re only concerned with unencrypted uncompressed video, a lot of our work will actually be DVI work in disguise.

A typical HDMI connector looks like this:



Features:


 * 1) Hot plug detect detects when the cable is plugged in or not.
 * 2) DDC is an I2C based protocol and stands for Display Data Channel. Having this working is a requirement for being an HDMI sink, as it’s what tells the source the # display capabilities and whatnot.
 * 3) CEC stands for Consumer Electronics Control. It’s a bus that can chain multiple HDMI devices together for things like allowing a remote to operate all devices at the same time.
 * 4) TMDS is a differential signalled pair of wires that send over bytes of data using an 8b/10b encoding. There are three different TMDS pairs.

TMDS
TMDS stands for transition minimized differential signalling. The “transition minimized” refers to trying to minimize transition between zero and one, as well as trying to keep the 0’s and 1’s balanced. Apparently these properties are beneficial somehow.

The “differential signalling” refers to sending a signal over a pair of wires. One wire carries the complement signal of the other wire. This can help protect against interference as the interference will probably effect both wires similarly.

There are three TMDS channels (or six for the Type B cable), one for each color out of Red, Green Blue. Each one of these needs to be 8/10 encoded seperately. The pixel clock is also sent over a DS pair, but isn’t 8/10 encoded.

Here is a block diagram of a TMDS receiver:



8/10b Encoding
HDMI uses an 8/10 encoding where an 8 bit word is transformed into a 10 bit word with properties good for the “transition minimized” goal.

As each 8-bit color needs 10 bits to transmit, this means the bits have to be sent 10x the speed of the pixel clock.

The algorithm is a bit involved, but comes down to some simple combinatorial logic. Basically it chooses either XOR or XNOR to encode the 2nd through 8th bits based on what will minimize transitions. Then it sometimes inverts the signal to keep 1’s and 0’s balanced.

DDC
DDC is an I2C based protocol which allows an HDMI video sink to convey it's supported display modes (among other things) to the HDMI video source.

This information is conveyed in the form of an EDID blob, which is either 128 or 256 bytes.

It's possible for an HDMI video source to send a signal without receiving any EDID data, but to be robust and portable this has to be implemented.

Fortunately the HDMI2USB project includes a working EDID HDL module.

Implementation
For implementation purposes we decided to use the Digilent Atlys. The Atlys is a pretty heavyweight FPGA, but the ideal board to develop an HDMI based project on. This is because there's a lot of existing work for it, and it's beefy enough to have more than we need.

Once the problem is well understood, it would be easy to "port" the FPGA design to a cheaper board.

EDID
EDID is a binary format, so it's hard to create one with a text editor and writing a program to create them would be slightly involved.

However, there are tools out there that can be used to generate EDID files.

For instance one comes with recent Linux kernels in the Documentation/EDID/ folder. It's only dependencies are gcc and Make, and it allows one to easily create custom EDIDs.

Here is one such EDID file created with that tool that supports a 640x480@60 resolution. [TODO: dropbox is a terrible place for wiki-links]

The HDMI2USB project includes a working EDID HDL module. (The Atlys or Xilinx demos might too, but I haven't looked)

The edidslave module can be used almost as is, except as there's no need for the dvi_only flag-- it can be set to a constant 1 or removed entirely for our purposes.

The ROM to load is specified by the edidrom.hex file. It's easy to convert binary files to .hex files with a short C++ program.

HDMI
Generating HDMI is easy, but recieving HDMI Video is harder, so we are using some existing HDL. We are using the Xilinx HDMI HDL to receive HDMI.

Current Status


Currently we can receive a 640x480 60 fps HDMI signal over HDMI using the HDMI2USB / Xilinx HDL. With this signal we can buffer the top 32x32 pixels of each frame and drive one 32x32 panel. We have no pulse-width modulation capabilities at the moment, however, so we are working with only eight colors. There is also a little flicker, though we have some ideas as to how this can be solved.

That is, two immediate major unresolved issues are:


 * 1) Buffering video frame data (one or two frames) on the FPGA (not just the top-left 32x32) so that it can be manipulated (scaled) in a convenient manner.
 * 2) Complete the interfacing with the LED panels over the ATLYS's VHDC connector. Add PWM, fix flickering and add the capability to chain panels together.

Buffering Video
A 640x480 24 bpp video frame requires 7372800 bits, just under a megabyte of data. It would be nice to use the Atlys's fast Block RAM for this, but there are only around 2100000 bits of Block RAM. This is enough to store several rows of video data, but not nearly enough to store the entire input buffer.

This means that if storing an entire input video frame is needed, then the Atlys's DDR2 module might need to be used. Another approach is to utilize the block ram but only store a certain fraction of each frame (such as every fourth pixel, which would require only one sixteenth of the space to store). We plan to begin by testing the latter alternative before attempting to figure out DDR2.

DDR2

According to the Atlys reference manual there are 128 MB of DDR2 RAM available up to a 800MHz clock rate. These numbers should be more than enough for the projects needs.

Xilinx ISE contains a Memory Interface Generator (MIG) for generating HDL that can be used to control DDR2 RAM. There are instructions on how to use the MIG with the Atlys FPGA both in the Atlys reference manual and in a blog post by Joel Williams

Block Ram

The 2.1 megabits of block RAM on the Atlys are not enough to store an entire video frame, as stated above. Some of the strategies we are considering for buffering using block ram are: Keeping only every second, third, fourth, etc. pixel to cut the memory requirement down by n^2. This has the disadvantage of decreasing scaling quality, as not every pixel will be considered. Storing only 16 rows at a time then scaling on that row before using it to drive the panels. This solves the disadvantage of the first option, but at the cost of ease of implementation.

Interfacing With LED Video
At the beginning of the project we could interface an FPGA with a 2x2 grid of 32x32 LED Panels. However this functionality needs to be ported to the Atlys.

The Atlys's main general-purpose output takes the form of a VHDC connector. This gives lots of terminals to connect (40) to but they are tiny and spaced close together. The possibility of using jumper wires was considered but proved infeasible; instead we have a breakout PCB to get easier access to the terminals as pins. From there, we have soldered headers onto the PCB and are able to use jumpers to drive the panels.

The existing HDL code from the old project will need to be ported to the VHDC IO on the ATLYS, updated, and tested. Currently we are reimplementing the HDL in Verilog (the old code is in VHDL) and changing the way the pulse-width modulation occurs: instead of driving individual pixels for a certain fraction of 256 cycles, we will drive a single row eight times, each time twice as long s the last and corresponding to the next higher order bit in the color component of each pixel.

Team Information
Colin Clifford - Computer Science

Peter Brown - Electrical Engineering



Document Archive
Design Failure Mode Effects Analysis

Design Report

Detailed Design Review Slideshow

Game of Life Snapshot Demo Sourcecode