DisplayPort

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was started in August 2015.

2160p.jpg

DisplayPort is another digital interface to talk to LCD (and other) displays. It has some major differences from HDMI.

  • It has a 1Mb/s control channel
  • Rather than being clocking at the pixel clock the display interface run at fixed bit rates of either 2.70Gb/s or 1.62Gb/s.
  • There can be either one, two or four lanes of data, for a total bandwidth of 10.80Gb/s
  • There is a 'training' process that allows the best voltage swing and pre-emphasis settings to be negotiated.
  • Later releases have support for multiple displays.
  • The data is (usually) scrambled to reduce EMI issues.

There isn't an openly available reference implementation, so this is breaking new ground for Open Source FPGA designs.

Contents

Source

All the project source will live on GitHub, at https://github.com/hamsternz/FPGA_DisplayPort

Display port test.jpg

Usage for the initial test pattern

This is 800x600 over a single 2.7Gb/s channel.

+-------------------------------+----------------------------+------------+------------+---------+------+-----+--------+--------+--------------+
|            Instance           |           Module           | Total LUTs | Logic LUTs | LUTRAMs | SRLs | FFs | RAMB36 | RAMB18 | DSP48 Blocks |
+-------------------------------+----------------------------+------------+------------+---------+------+-----+--------+--------+--------------+
| top_level                     |                      (top) |        607 |        576 |      16 |   15 | 679 |      0 |      1 |            0 |
|   (top_level)                 |                      (top) |          0 |          0 |       0 |    0 |  17 |      0 |      0 |            0 |
|   i_aux_channel               |                aux_channel |        328 |        312 |      16 |    0 | 298 |      0 |      0 |            0 |
|     (i_aux_channel)           |                aux_channel |        131 |        131 |       0 |    0 | 115 |      0 |      0 |            0 |
|     i_aux_messages            |            dp_aux_messages |         46 |         46 |       0 |    0 |  21 |      0 |      0 |            0 |
|     i_channel                 |              aux_interface |        151 |        135 |      16 |    0 | 162 |      0 |      0 |            0 |
|   i_data_to_8b10b             |              data_to_8b10b |         38 |         38 |       0 |    0 |  61 |      0 |      0 |            0 |
|   i_edid_decode               |                edid_decode |         38 |         38 |       0 |    0 |  80 |      0 |      0 |            0 |
|   i_idle_pattern_inserter     |      idle_pattern_inserter |         26 |         26 |       0 |    0 |  57 |      0 |      0 |            0 |
|   i_link_signal_mgmt          |           link_signal_mgmt |          2 |          2 |       0 |    0 |  10 |      0 |      0 |            0 |
|   i_scrambler                 |                  scrambler |         17 |         17 |       0 |    0 |  16 |      0 |      0 |            0 |
|   i_scrambler_reset_inserter  |   scrambler_reset_inserter |         29 |         29 |       0 |    0 |  27 |      0 |      0 |            0 |
|   i_test_source               |                test_source |         69 |         69 |       0 |    0 |  39 |      0 |      1 |            0 |
|   i_train_channel0            | training_and_channel_delay |         38 |         23 |       0 |   15 |  41 |      0 |      0 |            0 |
|   i_tx0                       |                Transceiver |         22 |         22 |       0 |    0 |  33 |      0 |      0 |            0 |
|     (i_tx0)                   |                Transceiver |          0 |          0 |       0 |    0 |   0 |      0 |      0 |            0 |
|     i_gtx_tx_reset_controller |    gtx_tx_reset_controller |         22 |         22 |       0 |    0 |  33 |      0 |      0 |            0 |
+-------------------------------+----------------------------+------------+------------+---------+------+-----+--------+--------+--------------+

Usage for 2080p

1. Utilization by Hierarchy
---------------------------
This is 3840x2160@30 over two channels.
+-----------------------------------------------+-------------------------------------------+------------+------------+---------+------+-----+--------+--------+--------------+
|                    Instance                   |                   Module                  | Total LUTs | Logic LUTs | LUTRAMs | SRLs | FFs | RAMB36 | RAMB18 | DSP48 Blocks |
+-----------------------------------------------+-------------------------------------------+------------+------------+---------+------+-----+--------+--------+--------------+
| top_level                                     |                                     (top) |        752 |        710 |      16 |   26 | 927 |      0 |      0 |            0 |
|   (top_level)                                 |                                     (top) |          0 |          0 |       0 |    0 |  16 |      0 |      0 |            0 |
|   g_per_channel[0].i_data_to_8b10b            |                             data_to_8b10b |         38 |         38 |       0 |    0 |  61 |      0 |      0 |            0 |
|   g_per_channel[0].i_scrambler                |                                 scrambler |         18 |         18 |       0 |    0 |  16 |      0 |      0 |            0 |
|   g_per_channel[0].i_train_channel            |                training_and_channel_delay |         30 |         16 |       0 |   14 |  46 |      0 |      0 |            0 |
|   g_per_channel[1].i_data_to_8b10b            |                           data_to_8b10b_0 |         38 |         38 |       0 |    0 |  61 |      0 |      0 |            0 |
|   g_per_channel[1].i_scrambler                |                               scrambler_1 |         18 |         18 |       0 |    0 |  16 |      0 |      0 |            0 |
|   g_per_channel[1].i_train_channel            |              training_and_channel_delay_2 |         28 |         15 |       0 |   13 |  49 |      0 |      0 |            0 |
|   i_aux_channel                               |                               aux_channel |        333 |        317 |      16 |    0 | 300 |      0 |      0 |            0 |
|     (i_aux_channel)                           |                               aux_channel |        133 |        133 |       0 |    0 | 117 |      0 |      0 |            0 |
|     i_aux_messages                            |                           dp_aux_messages |         47 |         47 |       0 |    0 |  21 |      0 |      0 |            0 |
|     i_channel                                 |                             aux_interface |        153 |        137 |      16 |    0 | 162 |      0 |      0 |            0 |
|   i_dp_reg_decode                             |                        dp_register_decode |          1 |          1 |       0 |    0 |   3 |      0 |      0 |            0 |
|   i_edid_decode                               |                               edid_decode |         38 |         38 |       0 |    0 |  80 |      0 |      0 |            0 |
|   i_idle_pattern_inserter                     |                     idle_pattern_inserter |         44 |         44 |       0 |    0 |  73 |      0 |      0 |            0 |
|   i_insert_main_stream_attrbutes_two_channels | insert_main_stream_attrbutes_two_channels |         41 |         41 |       0 |    0 |  39 |      0 |      0 |            0 |
|   i_link_signal_mgmt                          |                          link_signal_mgmt |          4 |          4 |       0 |    0 |  16 |      0 |      0 |            0 |
|   i_scrambler_reset_inserter                  |                  scrambler_reset_inserter |         42 |         42 |       0 |    0 |  41 |      0 |      0 |            0 |
|   i_test_source                               |         test_source_3840_2160_YCC_422_ch2 |         36 |         36 |       0 |    0 |  42 |      0 |      0 |            0 |
|   i_tx0                                       |                               Transceiver |         44 |         44 |       0 |    0 |  68 |      0 |      0 |            0 |
|     (i_tx0)                                   |                               Transceiver |          0 |          0 |       0 |    0 |   0 |      0 |      0 |            0 |
|     g_tx[0].i_gtx_tx_reset_controller         |                   gtx_tx_reset_controller |         23 |         23 |       0 |    0 |  35 |      0 |      0 |            0 |
|     g_tx[1].i_gtx_tx_reset_controller         |                 gtx_tx_reset_controller_3 |         21 |         21 |       0 |    0 |  33 |      0 |      0 |            0 |
+-----------------------------------------------+-------------------------------------------+------------+------------+---------+------+-----+--------+--------+--------------+

Configuration process

Detect sink

This should be achieved using the HotPlug Detect signal. At the moment I perform an EDID read of the first byte.

Read EDID data

The maximum payload on the AUX channel is 16 data bytes, so the EDID is read back as eight 16-word read transactions.

Read Sink characteristics

The DisplayPort has plenty of registers that describe features supported by the sink. Reading these allows the sink's capabilities to be discovered. These are different to the actual display's capabilities (which are discovered from EDID)

Configure for desired channel settings

This is where you tell the sink how many channels you will be using, and what the coding on the link will be.

Power the transceivers

Transceivers usually take a while to power up and come on line.

Start clock recovery training

A "1010101010" symbol is transmitted on all links, and then the sink is monitored to see if it is being received OK, and what adjustments it would like to be made (e.g. increased voltage swing).

As luck would have it, this is a valid 8b/10b symbol, and of course the scrambler has to be turned off during this process.

Switch to alignment training

A special sequence of 10 symbols, which include both versions of the 8B/10B comma character, and once again the scrambler has to be turned off during this process.

There is also the option of using a pseudo-random bit sequence for this, but I haven't investigated it.

Switch to the 'idle pattern'

Once the main links are all trained and aligned, the source must start sending the idle pattern. This is a special "nothing going on" sequence, that keeps the channels alive. It consists of a Blank Start (BS) symbol, and VB-ID that indicates vertical blanking and no video, and zeros for the Mvid and MAud fields. The BS sequence has to be sent every 8192 symbols, on all links.

This MUST be sent at least 5 times before switching over to an active video stream, or changing video timings.

Switch to the main video signal

Once the idle pattern has been sent, the source can switch over to the active video stream. It is not explicitly detailed when to cut over to the video stream, but I guess it should be during the vertical banking interval but before the Main Stream Attributes (MSA) are sent. The MSA details the current video mode's timings and are sent across the video links as an embedded data packet (much like audio samples might be).

Switching to the main video link is also were the scrambler should be enabled. The scrambler prevents long runs of identical bit patterns occurring on the link, reducing the EMI spectrum.

Watching the link

Should for any reason the sink require the source to take any action it will waggle the Hot Plug Detect signal for about a millisecond. On seeing this the source should read the link status registers and take any required actions.

Status

Working! - 800x600 and 2160p displays working

Notes that might help

  • Get a Saleae Logic Analyser to debug the AUX channel it speaks - Manchester Coding.

Aux channel.png

  • The Scrambler is the same one used in PCIe. It is well documented in that spec, much better than in the Display Port documentation. At least two monitors are known to work if you leave the scrambler turned off
  • 800x600 is a perfect start resolution. The 40MHz pixil clock allows for a nice regular pattern - you can send 8 pixels per 54 link clocks, and the total horizontal timing also divides by 8. When you use 54 symbol TUs this prevents minimal challenges
  • I not put anything into the Mvid field, and it still works. However, I have always tweaked the pixel rate so that each line time is an integer number of 270MHz clocks
  • The use of small M and N numbers never worked for me. Values like 8/54 should be legal (depending on the value Synchronous bit in MISC0), but it doesn't work for me
  • In fact the Synchronous bit in MISC0 doesn't seem to do much at all
  • The bit ordering out of the Xilinx transceivers seems to be against what is in the document. It took me ages make sure that this wasn't an issue when it wouldn't work. My Viewsonic monitor fails to get symbol lock when the bit ordering is wrong (as it damn well should!)
  • It seems that the second stage of training (for the symbol alignment and equalizer settings) doesn't care what you send. I had the wrong pattern and it still locked
  • I'm still not convinced that I don't have clock domain issues between the transceiver channels
  • Start with one channel of data - but plan for four!

Helpful hints for other implementers

http://www.alterawiki.com/wiki/DisplayPort_Design_Example_(TX-Only) contains a screenshot of the AUX channel data. This is what I used as a base for my configuration process (but it is now quite different).

http://www.futureplus.com/download/presentation/dp_anal_at_la.pdf contains some screen dumps from a commercial protocol analyser

http://www.saleae.com/ - The Manchester protocol analyser on these relatively inexpensive devices can be used to decode the AUX channel. Highly recommended.

http://www.xilinx.com/support/documentation/user_guides/ug476_7Series_Transceivers.pdf is quite informative on the transceivers. 8b/10b tables are included in Appendix C.

https://en.wikipedia.org/wiki/8b/10b_encoding - the encoding system on the main link

https://en.wikipedia.org/wiki/Manchester_code - the encoding used on the AUX channel

A valid DisplayPort Main Stream Attribute block

Main stream attributes for 800x800@60Hz F = M/N * 270MHz

Attribute Value(dec) width(bits) Hex - in brackets are coded values
M 77672 24 012F68
N 524288 24 080000
H total 1056 16 0420
V total 628 16 0274
H start 216 16 00D8
V start 27 16 001B
H sync width 128 16 0080
V sync width 4 16 0004
H polarity act low 0 1
V polarity act low 0 1
H active 800 16 0320
V active 600 16 0258
Sync clock 1 1
YCCnRGB 0 1
422n444 0 1
Range_Reduced 0 1
Depth 8 3 (001)
InterlacedEven 0 1
Indicator3d No 3D 2 (00)

NOTE the Sync Clock description in the spec doesn't seem to match reality....

Personal tools