Close

Rev 2 PCB, TMDS and SERDES working

A project log for HDMI PMOD

An HDMI breakout board for the high-speed PMOD slots on the Arty A7 35T

alexander-wranovskyAlexander Wranovsky 04/27/2021 at 22:380 Comments

Oops... PCB v2

Shortly after my last post, I did a quick connectivity check, and I found that I screwed up the HDMI connector footprint! The pin numbers ended up being reversed from what they should have been. I'm not sure whether I did that, or if I downloaded the footprint that way, but shame on me for not double checking.

After fixing the footprint, I reordered and reassembled the board. Much better now!

For those curious, I tested this by hooking up an HDMI to DVI cable, and then checking with an ohmmeter. I compared the actual pinout with a diagram for DVI.

Setting up TMDS IO and SERDES

Before this, I had never directly instantiated any of the Xilinx primitives or done any advanced IO stuff away from work, so I wanted a way to test it separately from the display logic. To do this, I made a project that sets up the clocks with a PLL, a SERDES module for serializing the data, and an output buffer. I also made a linear feedback shift register to generate a pseudo-random sequence of 10-bit integers. An OUT_FIFO module is also present to separate the pixel clock domain from a potential logic clock domain in future designs.

The result is a random bit pattern clocked out at 250 megabits/s (twice the 125 MHz TMDS clock, since the OSERDES modules are configured in DDR mode). I recently purchased an SDS2352X-E oscilloscope from Siglent to measure precisely this type of signal. With a bandwidth of 350 MHz, we're able to capture the fundamental at 125 MHz loud and clear, and probably around 80% of the third harmonic at 375 MHz. On top of that, it has optional 50 Ohm inputs, which is essential when making DIY probes for high-speed stuff. For around $850 brand-new, it's the best budget high-speed scope I could find without trolling eBay.

Nothing works the first try

This being such a simple design, I thought I could get away without simulating it. That, however, quickly proved to be wrong. I loaded a bitstream onto my board, hooked up the scope, and... nothing. Normally I would pull out Verilator at this point, but this design directly instantiates Xilinx primitives that Verilator has no model for. To get around this, I used xsim, which is the simulator that comes bundled with Vivado. Lucky for me, FuseSoC/Edalize has an xsim backend, which makes using it as easy as adding a couple lines to my core config file. I think I could potentially compile some of the models for Verilator but using xsim was definitely the path of least resistance here.

Once setting up xsim, I ran the simulation. The results surprised me to say the least. Everything seemed to work just fine! The clocks were running, the SERDES module was serializing, and the differential outputs were swinging. As frustrating as this was, it narrowed down the problem to some sort of inconsistency between my dev board PCB and my design.

Sure enough, this was it. My scope can only terminate to ground, so I had configured the design for 2.5V LVDS instead of 3.3V TMDS, which requires pullup resistors to 3.3V. The IO bank for this PMOD, though, is hardwired for 3.3V. This means the 2.5V configuration was probably putting the IO bank into an over-voltage protection mode! Switching the configuration to 3.3V TMDS and terminating to 3.3V fixed the problem.

Test setup

Here's an image to do the talking for me.

The circuit diagram for a single end of the differential pair is pictured below. If I were using LVDS, I could have hooked up the SMA cable and connector directly to the PMOD interface, but TMDS termination requires that I have a high impedance between my scope and the circuit under test. I picked a 2450 Ohm resistor because it gives an attenuation close to 50:1, which is one of the options that my scope lets me select. In reality though, the resistor I had available was closer to 2.2 kOhm, which gives an attenuation of 45:1.

If you have never used one of these transmission line probes before, they are surprisingly high bandwidth at the expense of loading down your circuit more than the typical 10 Meg passive probe. They do require a 50 Ohm input on your scope, however.

Test Results

If I had $100K to burn on a 20 GHz scope, I'm sure you would see some nasty reflections along the edge; however, with a -3 dB bandwidth of 350 MHz, the waveform looks mighty fine for some through-hole resistors on a breadboard. Since I don't have a differential probe, I connect each end of the differential pair into a separate channel on the scope. Then, I use the math function to subtract them. With the hodge-podge breadboard setup, there was quite a bit of noise common to both ends of the pair, which gets cancelled out nicely when you find the difference between them.

Keen readers may also notice that this is not a true eye diagram. To get an actual eye diagram, you also need a reference clock. When you trigger on the edge of your data signal in infinite persistence mode, all of the edges will line up neatly right in the center of the screen. In reality though, the receiving device needs to generate a clock signal so that it knows where the center of the bit is. The frequency of the data signal may vary from this generated clock in a phenomenon known as jitter, which will cause the edges to not line up so neatly. Fancy scopes from big-name vendors will include software to generate this reference clock post-capture, and then generate an eye diagram. Alternatively, you can also probe the clock signal and trigger on that. The nice thing about this scope is that it has a long record length of 28 megapoints, which makes it possible to generate reference clock, should I choose to write the software to do so. It also has an external trigger input for a clock signal should I need to go that route in the future. 

Final Thoughts

The next step is to generate actual images! There is plenty of code online to do so, so hopefully my next post will be soon. Additionally, I plan to not get sidetracked. Between the last two post I worked on a different project writing a FuseSoC core for the Digilent PMOD AD1.

Discussions