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

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 

 

Link to comment
Share on other sites

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. 

Link to comment
Share on other sites

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 ?

Link to comment
Share on other sites

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

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...