• 0
chcollin

My noobish questions on Atlys HDMI demo

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:

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 ?
 

Thank you very much for your help

Edited by chcollin

Share this post


Link to post
Share on other sites

17 answers to this question

Recommended Posts

  • 0

0x48000000 is the start of the DDR2 memory address. The next 128 MB of address space are the entire contents of the DDR2 memory on the Atlys. The program (hdmi_demo) is actually executing from the front of the DDR2 (0x48000000). So, assuming the program is not larger than 16MB, 0x49000000 is a safe physical address within the DDR2 that should not overlap with the program's memory. 

This was poor style to assign the address this way for many reasons. It would have been better to just declare an array of bytes big enough to contain the frame buffer, and then dereference the array to get the physical address.

0xD1000000 is the base address of the hdmi_out core's register map for controlling that IP core

Share this post


Link to post
Share on other sites
  • 0

Thank you very much @sbobrowicz, your explanation makes it a lot clearer to me. Especially the offset from the DDR starting address so that the code can be safely stored without overlapping data.

However, I might disagree about the 0xD1000000 value, or my comprehension is completely mistaken (which is highly possible as I really am beginner)
Looking at project/pcores/hdmi_out_v1_00_a/hdl/vhdl/hdmi_out.vhd, we can see that :
constant vfbc_cmd1 : std_logic_vector(31 downto 0) := "0" & FRAME_BASE_ADDR(30 downto 7) & "0000000"; --Frame base address must be 128 byte alligned and MSB used as WNR

File ./project/pcores/hdmi_out_v1_00_a/data/hdmi_out_v2_1_0.mpd reads :
PARAMETER FRAME_BASE_ADDR = 0x00000000, DT = std_logic_vector, ASSIGNMENT = REQUIRE, DESC="FRAME BASE ADDRESS", LONG_DESC="Select the physical address of the framebuffer in memory. This address must be 128 byte alligned (bits 6-0=0) and designate a region within the MPMC space large enough for the frame.

And finaly, in ./project/system.mhs, the paramater is set : 
PARAMETER FRAME_BASE_ADDR = 0xD1000000

So, to my comprehension, 0xD1000000 is the very address in memory from which the hdmi_out vfbc pim reads the frame.

However bit 31 is excluded  in the address used in vfbc_cmd1, so 0xD1000000 "turns into" 0x51000000.
It's getting closer :) ... yet not 0x4900000 !

 Where am I mistaken ?

Edited by chcollin

Share this post


Link to post
Share on other sites
  • 0

Wow, its been a long time since working with the MPMC, I forgot how much differently that works than the more modern MIG+VDMA solution.

You are right, the 0xD1000000 Address is not the register map address assigned by EDK. It is the Physical address of the DDR that the MPMC will write the video data to. I forgot that this had to be set in EDK before building the bitstream (VDMA lets you set it in software from SDK). 

So here is the magic part: since the MPMC knows that there is only 128 MB, it seems to be automatically masking out any unnecessary bits. So it is effectively only looking at bits (26 downto 7), and 0xD1000000 turns into 0x01000000. Note that providing 0x49000000 would also get masked down to 0x01000000 which is why the software works. So you can effectively think of the value that you provide to FRAME_BASE_ADDR as a relative address within the DDR physical address space.

Note that the above explanation heavily relies on the base address of the MPMC being 128MB aligned (so bits 26 downto 0 are all '0'). In this design, the MPMC is given address 0x48000000, which satisfies this requirement. I honestly have no idea how the FRAME_BASE_ADDR value will be interpreted if the MPMC were assigned a base address that is not aligned to 128 MB.

I have no idea why the project sets the FRAME_BASE_ADDR to 0xD1000000 instead of 0x49000000, or even 0x01000000. My bet is that an earlier version of the project had the MPMC base address set to 0xD1000000, but this was changed when it got updated at some point. Since nothing broke, it slipped through unnoticed. 

Share this post


Link to post
Share on other sites
  • 0

After almost one year inactive, i'm trying to play with this HDMI demo again :D

My goal is to use it as a basis for 90° rotating a 480p video source and display it on a 720p display.
To achieve this, i'm using 18K BRAMs to store lines and then read columns from the BRAMs to the VFBC writer as lines.

As there is only 2.1 Mb of BRAMs on the Atlys, I cannot store the entire frame in BRAMs (2.1 Mbits / 18Kbits = 120 BRAMs while having 480 lines to store)
Also, there are VFBC X Size and Stride alignement constraint : A minimum of 128 bytes must be writen which means that I need 64 BRAMs minimum (64 x 16 bits = 128 bytes).

Then, my first idea was to store 64 lines from the dvi_decoder to a first set of 64 BRAMs, while reading another set of 64 BRAMs and writing them to VFBC as a (64 x 640 x 16) column, and then interverting BRAM sets (write 64 lines form dvi_decoder to BRAM set A while writing 64 columns form BRAM set B to VFBC, then write 64 lines form dvi_decoder to BRAM set B while writing 64 columns form BRAM set A to VFBC, then write 64 lines form dvi_decoder to BRAM set A while writing 64 columns form BRAM set B to VFBC and so forth ...)
The problem is that there aren't 128 available BRAMs on the Atlys.

So I thought that instead of using 2 sets of 64 BRAMs, I could use 2 sets of 32 BRAMs and use a simple trick to bypass the VFBC 128 byte alignement constraint : padding 16 bit pixel data with 16 0's, so that the X size would be 32 pixel * 32 bits = 128 bytes.
The problem is that I couldn't set up MPMC to use 32 bit words instead of 16 bit words. It seems the DDR2 RAM on the Atlys does not allow this.

So this is my first question : Did I do something wrong or is it possible to set up MPMC / VFBC on Atlys so that reads and writes are 32-bit word long ?

As I couldn't set MPMC correctly to 32 bits, I had a hack idea : 
I'll keep using 2 sets of 32 BRAMs, storing frame lines as 16 bit words, but when writing to VFBC, I'll set X size to 128 and use a pixel clock x2, duplicating each pixel in the frame buffer. It was a trick to write a 32 columns of 16-bit wide pixel meanwhile the 128 alignement constraint.
The idea was to do the same trick in the hdmi_out module : read data from frame buffer at twice pixel clock and write to dvi_coder at pixel clock dropping half of the pixels (I.e dropping the duplicated pixels).
Unfortunatly, this does not work either !!! (this is very sad as I was proud of this trick :D )
The data in the frame buffer is correct : If I set VFBC_RD_CLK at pxlclk (720p = 75 MHz), then I can see all pixels duplicated and image is twice as larger.
However, when I set VFBC_RD_CLK to pxlclk_x2 (150 Mhz), It seems the VFBC PIM doesn't work.

So this is my second question : Is it possible with Atlys to read from VFBC at 150 MHz ? 

There are things that I have read in DS643 ( LogiCORE IP Multi-Port Memory Controller (MPMC) (v6.03.a) )  page 184, that I dont quite understand :
First off, there seems to have frequency limitations but those for Spartan 6 are not given...
Secondly, what is this thing about timing constraints ? To quote :

"VFBC Timing Constraints MPMC provides a Tcl script that generates the timing constraints within a UCF file automatically for the VFBC PIM. For the timing constraints to be set correctly, the clock frequency of MPMC_Clk0 must be specified in the MHS file. The MHS file must have the CLK_FREQ value set for all input clock ports. The following code snippet is an example of an MHS file PORT declaration showing the direction as Input (I) and the CLK_FREQ set: PORT display_clk_pin = display_clk, DIR = I, SIGIS = CLK, CLK_FREQ = 27000000, BUFFER_TYPE = IBUFG If the clock frequency is not set, the automatically generated VFBC timing constraints will assume the frequencies listed in Table 90, page 184 for the given device family"

Does that have a relation with the problems I am facing ?

Thanx a lot to any soul who will help my with this.

Cheers and Happy New year 

 

Edited by chcollin

Share this post


Link to post
Share on other sites
  • 0

Hi @chcollin,

I do not have experience with this project. I have reached out to more experienced engineers to see if they have any information for you. I would also reach out to xilinx about this as well.

thank you,

Jon

Share this post


Link to post
Share on other sites
  • 0

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

Share this post


Link to post
Share on other sites
  • 0

Just to keep you informed, the "double pixel" hack works.
Now i'm debugging the bram buffer thing. Hope to post a first video soon ?...

Share this post


Link to post
Share on other sites
  • 0

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

Edited by chcollin

Share this post


Link to post
Share on other sites
  • 0

Hi @chcollin,

 I have reached out to more experienced engineers to see if they have any information for you.

cheers,

Jon

Share this post


Link to post
Share on other sites
  • 0

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

Edited by chcollin

Share this post


Link to post
Share on other sites
  • 0

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

Share this post


Link to post
Share on other sites
  • 0

OK OK, forget about it, I was messing too much with mhs file ....
Finaly I could connect hdmi_in and hdmi_out modules. Now Let me synchronize both writing and reading .... :D

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now