Jump to content
  • 0

My noobish questions on Atlys HDMI demo


chcollin

Question

Hi FPGA Gurus !

This thread is dedicated to the (probably numerous) questions I might have about the Atlys HDMI demo. It will be edited each time a question is answered or another question pops up ! ?

Question 1 (solved):

I dont understand the calculation of the Frame Base Address in hdmi_demo.h. The code reads :
/*
 * These constants refer to the configuration of the hdmi_out core parameters.
 */
#define pFrame 0x49000000 //frame base address
#define xcoFrameMax 1280  //frame width
#define ycoFrameMax 720   //frame height
#define lLineStride 0x800  //line stride

Now, if I look at the hdmi_out core, i'm ok about frame width and height and also about the line stride. However, the core FRAME BASE ADDRESS parameter is set to 0xD1000000.
If I look at the MPMC configuration, its base address parameter is set to 0x48000000.
I'm a bit confused. Could someone explain how this 0x49000000 value is obtained out of 0x48000000 and 0xD1000000 ?

Question 2 (pending):

The output signal is 1280x720 with a pixel clock at 75 MHz which is not fully HDMI compliant.
Some receivers get along with this signal but some unfortunately don't.
To get a "true" 720p signal, pixel clock should be 74.25 MHz.
Is there any way I could modify the clock generator to get this 74.25 MHz clock signal ? 

Thank you very much for your help

Link to comment
Share on other sites

Recommended Posts

Hi FPGA gurus !

This might be my forever last question :D

My project is complete, all bugs and customizations done. I wanted to get rid of the microblaze part but I realized I couldn't since HDMI In connector needs xps_iic and microblaze for the EDID thing.
So, here is my question, as I didn't find any answer to it :

How can I store the whole project into Atlys so that I don't need to download and run it from SDK every time ?

Especially, the C program needs to be run on bootup so that EDID interrupts are handled.
To resume : What's the process so that whenever I turn the Atlys on, my implementation and program run ?

Can anybody help on this ? After 2 years  I'm finally seeing the light at the end of the tunnel !!

Many many thanks in advance.

Cheers

Link to comment
Share on other sites

@chcollin,

I'm curious as to why a MicroBlaze was used for the EDID I2C connection.  That seems like a rather heavy-hitting solution for a really simple interface.  Are they doing more than just implementing the interface?  Adjusting HDMI timing (pixel clock, screen size, etc.) for example?  Or does the design use the same settings regardless?

Just curious,

Dan

Link to comment
Share on other sites

I have no hint as to why this was designed this way.
All I can say is that Microblaze handles IIC interrupts for feeding HDMI connector with supported resolution infos.
Quoting the demo documentation :

"Implementing an EDID transmitter so that attached devices will recognize the Atlys as a
display device

Input sources that require EDID packets to recognize a device must be attached after the
software has been loaded to the FPGA. This is because the IIC controller must be configured
properly in order to respond to the EDID requests which occur just as the device is plugged in.
 The transmitted EDID packet may be altered in the hdmi_demo.h header file."

I guess this was, at that time (2013), the way to use HDMI in connector.

 

In header file :

/*
* EDID array definition. Changing these values changes the EDID
* packet that is sent over the E-DDC wires. It contains information on which
* resolutions the device supports. Currently, this packet provides fairly
* generic resolution support. Note that using resolutions with widths larger
* than the line stride of the hdmi_output core results in a choppy picture.
*/

In source code :

/***    IicHandler
**
**  Parameters:
**      CallBackRef - Pointer to NULL
**
**  Return Value:
**      None
**
**  Errors:
**      None
**
**  Description:
**      This function is connected to the interrupt handler such that it is
**      called whenever an interrupt is triggered by the IIC core. It is
**      designed to behave like a monitor on an E-DDC interface. It outputs
**      the data held in rgbEdid as its EDID.
*/

 

Link to comment
Share on other sites

@chcollin,

If it helps at all, when I implemented HDMI on my own, I built an I2C core to handle the EDID.  Yeah, I still used a ZipCPU, but mostly to copy the downstream EDID info the the source port, so that the EDID info I produced would match that of the downstream monitor.

To be a bit clearer, my setup was: RPi -> Nexys Video board -> Monitor, and I wanted the RPi to be able to read the monitors EDID values.

Both EDID components are posted on line, and you can find them as part of my project here.

Dan

Link to comment
Share on other sites

Thank you @D@n, I'll have a look at your project when I have time.

However, it was not my intention to rewrite the xps_iic EDID module, as I'm totally satisfied with what I have now.
I'm just trying to understand how to store the whole project to Atlys' SPI/FLASH so that whenever I turn it on the project runs, without the need to launch it through SDK.

Cheers

Link to comment
Share on other sites

1 hour ago, chcollin said:

I might answer partially my own question as I have found this tutorial :

How To Store Your SDK Project in SPI Flash

It is for Vivado but with a little luck, this might work for ISE 14.7 too.
I'll post some time soon to tell you if I managed to have it work or if I need help ! :D

This solution seems to be suitable for AXI-based projects... whereas I'm using PLB ?
That's sad...

Link to comment
Share on other sites

I finaly managed to connect both ports between hdmi_in and hdmi_out modules, at least i believe I did as shown in the screenshot below.
However, I get mapping errors :

ERROR:MapLib:979 - LUT6 symbol "hdmi_out_0/hdmi_out_0/vfbc_cmd_data_i_13_rstpot"
   (output signal=hdmi_out_0/hdmi_out_0/vfbc_cmd_data_i_13_rstpot) has input
   signal "hdmi_in_0_FB_SELECT" which will be trimmed. See Section 5 of the Map
   Report File for details about why the input signal will become undriven.
WARNING:MapLib:701 - Signal hdmi_in_0_SW_pin<1> connected to top level port
   hdmi_in_0_SW_pin<1> has been removed.
ERROR:MapLib:978 - LUT6 symbol "hdmi_out_0/hdmi_out_0/vfbc_cmd_data_i_13_rstpot"
   (output signal=hdmi_out_0/hdmi_out_0/vfbc_cmd_data_i_13_rstpot) has an
   equation that uses input pin I0, which no longer has a connected signal.
   Please ensure that all the pins used in the equation for this LUT have
   signals that are not trimmed (see Section 5 of the Map Report File for
   details on which signals were trimmed).

This is depressing ?

 

ports.png

Link to comment
Share on other sites

Thank you @D@n,

The problem was not as difficult as I thought, as we say in french : the problem mostly resides between the seat and the keyboard :)
The fact that I am not in the eletronics nor the FPGA thing makes it sometimes difficult to me to understand how things work.

I finaly endend up adding another clock to the clock generator and modified PLL module configuration.

Reference clock is 100MHz and clock wizard allowed me to add a 22.5MHz clock to the system.
This 22.5MHz clock feeds a PLL module with multiply factor set to 33, which gives me exactly 742.5MHz.
The PLL module outputs 3 clocks :

  • CLK0 with divide factor set to 1 for pxlclk_x10
  • CLK1 with divide factor set to 10 for pxlclk (74.25MHz, 720p specs freq)
  • CLK2 with divide factor set to 5 for pxlclk_x2

Here is a screenshot of the internal clock schematics :
internalClockSchematics.png.a0d7d84cee5abf4e810d30e7b6389916.png

Bitstream generation fails if I do not deselect "Treat timing closure failure as an error" in Project Options.
A close look using Time Analyzer shows this :

================================================================================
Timing constraint: TS_clock_generator_0_clock_generator_0_SIG_PLL0_CLKOUT2 = PERIOD TIMEGRP "clock_generator_0_clock_generator_0_SIG_PLL0_CLKOUT2" TS_sys_clk_pin * 0.75 HIGH 50%;
For more information, see Period Analysis in the Timing Closure User Guide (UG612).
498357 paths analyzed, 31206 endpoints analyzed, 10 failing endpoints
10 timing errors detected. (10 setup errors, 0 hold errors, 0 component switching limit errors)
Minimum period is 734.895ns.
--------------------------------------------------------------------------------
Slack (setup path): -7.306ns (requirement - (data path - clock path skew + uncertainty))
Source: hdmi_out_0/hdmi_out_0/vfbc_rd_reset_i (FF)
Destination: MCB_DDR2/MCB_DDR2/VFBC2_INST.vfbc/VFBC1_PIM_NGC/UVFBC/rdfifo_reset_dly1_0 (FF)
Requirement: 0.135ns
Data Path Delay: 1.405ns (Levels of Logic = 1)(Component delays alone exceeds constraint)
Clock Path Skew: -5.487ns (4.455 - 9.942)
Source Clock: hdmi_out_0_VFBC_OUT_cmd_clk rising at 1319.865ns
Destination Clock: clk_75_0000MHzPLL0 rising at 1320.000ns
Clock Uncertainty: 0.549ns

Clock Uncertainty: 0.549ns ((TSJ^2 + DJ^2)^1/2) / 2 + PE
Total System Jitter (TSJ): 0.070ns
Discrete Jitter (DJ): 0.472ns
Phase Error (PE): 0.310ns

Maximum Data Path at Slow Process Corner: hdmi_out_0/hdmi_out_0/vfbc_rd_reset_i to MCB_DDR2/MCB_DDR2/VFBC2_INST.vfbc/VFBC1_PIM_NGC/UVFBC/rdfifo_reset_dly1_0
Location Delay type Delay(ns) Physical Resource
Logical Resource(s)
------------------------------------------------- -------------------
SLICE_X30Y100.BQ Tcko 0.525 hdmi_out_0_VFBC_OUT_rd_reset
hdmi_out_0/hdmi_out_0/vfbc_rd_reset_i
SLICE_X31Y99.C4 net (fanout=1) 0.507 hdmi_out_0_VFBC_OUT_rd_reset
SLICE_X31Y99.CLK Tas 0.373 MCB_DDR2/MCB_DDR2/VFBC2_INST.vfbc/VFBC1_PIM_NGC/UVFBC/rdfifo_reset_dly1<0>
MCB_DDR2/MCB_DDR2/VFBC2_INST.vfbc/VFBC1_PIM_NGC/RdDataPortIn[0]_MReset_n1_INV_0
MCB_DDR2/MCB_DDR2/VFBC2_INST.vfbc/VFBC1_PIM_NGC/UVFBC/rdfifo_reset_dly1_0
------------------------------------------------- ---------------------------
Total 1.405ns (0.898ns logic, 0.507ns route)
(63.9% logic, 36.1% route)

I guess this is due to the fact hdmi_out clock (now at 74.25MHz) does not align with MPMC clock frequency (600MHz).
I don't know if this really matters... It probably does but I don't know how to solve this.

Anyway, if I deselect the option about timing closure failure, I can generate a bitstream and try it.
The project runs.
Now if I connect the Atlys to a TV, things run smooth.
However, if I connect it to a less tolerant device (such as PC LCD monitor), here is what I get :

  • Video information now tells me video is 1280x720@60Hz (formerly it stated 1280x780@61Hz) : that's better
  • I notice slight horizontal shaking.

Supposedly, the video signal has a pixelclock @74.25MHz, total pixel per frames 1650x750 (h/v front porch, back porch and sync follow the specs).
Does anybody have any hint on why this horizontal shaking (slight but present) ?
I have a Marseille mCable HDMI cable (anti aliasing / upscaler 720p/1080p, many video corrections I wish to use on Atlys output). This device seems very strict on input signal and does not accept my generated signal as input. Obviously there is still something wrong with the TMDS signal generated though output frequency is now specs compliant.

I'd really appreciate if you could give me hints on completing this issue.

Cheers

 

Link to comment
Share on other sites

Hi @D@n,

Thank you for the interest you show regarding my project.

To sum it up :
This is a Spartan 6 PLB project with Microblaze.
It reads video from hdmi_in and stores it in RAM (after image manipulation) thanks to a Multi Port Memory Controler (MPMC) / Video Frame Buffer Controler PIM (VFBC).
RAM is then read by another VFBC that outputs (supposedly @720p, at least that's what I am trying to do now : getting a pure 720p signal, specs compliant) through hdmi_out module.

It is the MPMC that needs this 600MHz clock for internal use.
From what I have understood, it is supposed to run at 8 times the frequency of the Microblaze. 

Clock generator delivers a 75MHz clock for the Microblaze and a 600MHz clock for the MPMC.
As you may have read earlier, I've haded a 22.5MHz clock to the clock generator that feeds a PLL Module to get 74.25MHz at output (720p spec compliant frequency).

Of course, the easiest thing would be to set clock generator to output a 74.25MHz for the Microblaze and a 594MHz clock for the MPMC...
But Spartan 6 cannot do that (at least Atlys can't).

Now I was wondering :
Would it be possible to use clock generator to output a 22.5MHz clock into a PLL module to get my 74.25MHz clock and then use this clock signal as a clock-in to another PLL module that would generate all clocks for the system ? (x8/8 for the Microblaze and hdmi_out, x8/1 for the MPMC ...).
I really don't know if this would not interfere with all other components of the system -PLB bus etc)...

I might try that.

Link to comment
Share on other sites

OK,

I've been working on this, unsuccessfully ?

This is the design I've built :

1/ Clock generator : one single ouput : 22.5MHz from 100MHz internal clock (a single DCm x9/40 should achieve this but I might be generated somehow else)
2/ PLL module x33 / (1, 10, 5) to get 742.5MHz (pixel_clock_10x), 74.25MHz (pixel_clock + system_clock (PLB bus etc)), 148.50MHz (pixel_clock_2x)
3/ DCM master/slave module (master x11/10 [VCO 247.5MHz, output 24.75MHz], slave x24 /1 [VCO 594MHz, ouput 594MHz]), driving MPMC memory clock

I thought this would go smooth but unfortunatly, I'm facing MPMC clock problems.

First bitstream generation form XPS, I got an error telling me that C_MPMC_CLK_MEM_2X_PERIOD_PS could not be calculated and was out of range.
After reading MPMC documentation (page 6) :

Clock memory value is calculated automatically based on what is connected to Port MPMC_Clk_Mem_2x in XPS (for example a clock_generator output or a signal/port with MHS tag CLK_FREQ = xxxx.) The value can be overwritten; if set by the user, it is not calculated.

So I decided to modify system.mhs to give C_MPMC_CLK_MEM_2X_PERIOD_PS the value 1684 ps (which is in the range given in the doc). This value is the period for a 594MHz clock.

However, now I get the following error message :

ERROR:EDK:4061 - INSTANCE: MCB_DDR2, PARAMETER: C_MPMC_CLK_MEM_2X_PERIOD_PS -
   Given value (1684) is incorrect. The expected value is 44444. Please update the value in MHS - /opt/Xilinx/Projects/HDMI_Rotator/project/system.mhs line
   182 
ERROR:EDK:3371 - Conversion to XML failed.
make: *** [SDK/SDK_Export/hw/system.xml] Error 64

I don't know what to do with this error and where this 44444 value is taken from !
Can anybody help, please ? 

Link to comment
Share on other sites

OK, I figured it out, I had to play with the mpd file to explicit input clock freq and clock factor, so that the output frequency could be calculated.
However, this led me to another error : MPMC clock mem seems to be only PLL_ADV compatible ... so my DCM module didn't comply this specification.

Due to the limited number of DCM and PLL on the Atlys board, I finaly decided to review the entire clock design.
I ended up designing this :

1/ Removed the clock_generator_0 module as I didn't know if the module would generate clocks with DCM or PLL or both.
2/ Added a self made clock generator module. It takes at input system clock (100MHz), feeds a CLK_GEN (*9/40) (VCO 900MHz) into a DCM_SP (*11/10) (VCO 247.5MHz) to get one only output clock at 24.75MHz that fits quite well for my needs.
3/ Modified pll_module_0 : input is the 24.75MHz clock defined earlier, mult *30 and three output clocks:

  • /10 to get 74.25MHz for pixel clock and system clock
  • /5 to get pixel clock 2x
  • /1 to get pixel clock 10x

4/ Added another PLL module : input is the 24.75MHz clock defined earlier, mult *23, div /1 to get 594MHz (8 times the system clock) to clock the MPMC Memory clock.

This way, MPMC is clocked by a PLL and I have enough timing resources available on the Atlys to design this.

However, I now am facing another problem !!! (yes...)
It seems there is a constraint problem when generating bitstream.

The error message is the following :

ERROR:Place - ConstraintResolved NO placeable site for
   hdmi_out_0/hdmi_out_0/Inst_dvi_out_native/ioclk_buf
ERROR:Place - ConstraintResolved NO placeable site for
   MCB_DDR2/MCB_DDR2/mpmc_core_0/gen_spartan6_mcb.gen_spartan6_bufpll_mcb.bufpll
   _0
ERROR:Place - SIO has over-constrained componet
   hdmi_out_0/hdmi_out_0/Inst_dvi_out_native/ioclk_buf to have to placeable
   sites. Constraints come from driver constraints AND load IO constraints

I guess this is a constraint problem as I didn't had constraints regarding my "home made" clock generator nor the second PLL module...
For those interested, you can find the clock generator source files and the system.ucf file attached to this post.

If someone can help me solve this new problem, that would be very nice.

Cheers !

system.ucf dcm_720p_v2_1_0.mpd dcm_720p.vhd

Link to comment
Share on other sites

Thank you @jpeyron, I hope they'll find a solution ;)

Attached to this message, some project files related to ports and a screen shot to show you what  i did concerning bus interfaces (creation of directed bus FBSB).
Also, on picture hdmi_in.png, i don't understand why port FB_SELECT is named FBSB.{ FBSB.FB_SELECT} whereas I was expecting some expandable button like SPLB and VFBC_OUT (I just tryed to do exactly as it was done for VFBC_OUT... without success)

 

confiles.tar

bus_interface.png

hdmi_in.png

Link to comment
Share on other sites

OK guys, I might not be completly out of trouble :D:D:D

There is some sort of tearing due to the fact that hdmi_out module reads from the frame buffer while it is being written.
To correct this, I had the idea to use two frame buffers : while hdmi_in module writes vertical stripes to the first frame buffer, hdmi_out would read from the other untouched frame buffer. Then invert frame buffers.

To do this, I wanted to share a simple signal (std_logic) between hdmi_in module and hdmi_out module to describe which frame buffer to use... The problem is I don't have a single idea on how to do this as I really am not comfortable with all the MHS, MPD, UCF files ....

I "managed" to connect both modules with a custom bus ... which i'm not sure is the good thing to do. But I don't know how I can connect ports.
I've been trying all day long and feel a bit lost. I'm sure it's very easy for people comfortable with FPGA, so I would really appreciate a little help.

If you need any files from my project, don't hesitate to ask.

Please, if someone can help ...

Cheers

Link to comment
Share on other sites

Many thx @jpeyron

Nevermind, I think I have found some turnaround that I might soon try.
In hdmi_out, I do not need to read the entire frame buffer as most on the screen is blackend except for the rotated 480x640 image (in reality 960x640 since pixel are doubled at write time).

Since i'm only going to use the right half of the 1280x720 screen (left half is blakend),  I'm going to use another BRAM to store the current line at pxlclk rate.
While storing it i'll be sending black pixels at dvi_encoder until I reach the middle of the line and then whith dual port BRAM i'll start sending for pixels previously stored in BRAM while keeping storing remaining line pixels and so forth until the end of the line.

That should bring me the solution to my problem. I'll keep you informed.

Cheers

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...