0
\$\begingroup\$

I'm building a VGA display with a Xilinx FPGA. I'm not exactly sure what's the best way to store VGA frames. The resolution is 640x480. Should I just use a 640x480 2D array or block 640x480 into following:

  1. [ 256x512 256x128 ]
  2. [ 128x512 128x128 ]
  3. [ 64x512 64x128 ]
  4. [ 32x512 32x128 ]

each 2^N X K block represents a Block RAM with N-bit address, and K bit word.

In reality, each color is 8 bits, so word widths will end up 8 times higher.

Or better yet, what are better ways to build this memory?

\$\endgroup\$
3
  • \$\begingroup\$ Which approach expresses the design intent most clearly? Does that approach meet your speed and resource constraints? If it does, is there anything to be gained from a more obscure solution? \$\endgroup\$
    – user16324
    May 13, 2017 at 16:02
  • \$\begingroup\$ The display FSM will linearly increment (and hold during retrace), so it doesn't really matter for that. Where it might get challenging is writing into the framebuffer; but that's likely a software task where you can afford multiplying the vertical component by an actual horizontal dot count, and most modern FPGAs have multipliers you may not be using anyway. But sure, there's a conceptual cleanliness to being able to just concatenate bitfields representing X and Y portions of an address. \$\endgroup\$ May 13, 2017 at 16:07
  • \$\begingroup\$ All other things being equal, I think the mapping to the FPGA fabric will take care of this detail. Its all built out of smaller blocks, not like an ASIC design where you're providing dedicated logic. \$\endgroup\$ May 13, 2017 at 16:10

1 Answer 1

2
\$\begingroup\$

I read your question as: should I (a) imply a 640 x 480 x 8-bit frame buffer RAM using an array and let the synthesis tool resolve it into Block RAMs; (b) directly instantiate Block RAMs to build the frame buffer RAM and have to yourself choose the bit-width or size of the Block RAMs to construct it.

First off, with FPGA RAM being so flexible in bit-width, you can choose a width that can be read and written conveniently and at good speed. A frame buffer is shared between at least two bus masters: the CPU/DMA/GPU that puts images into it and the display driver that reads pixels and sends them to the screen (I'll call them Draw and Display).

The more frequently each accesses the frame buffer, the less time each master gets overall. It makes sense to make the Draw interface at least as wide as the Draw's data bus. For the Display interface, the more bits it gets in one read, the more pixels it gets and the longer it can keep going on its own until it needs to read again. If Display gets 64 bits per read, it'll read eight times less often that if it gets 8 bits per read.

So your first calculations will start with Draw and what you're trying to display (if you're putting infrequently-changing text on display, you won't need such a super-fast interface as for games). If Draw has a 32-bit interface, you can consider Display with a 32-bit interface. Then, on the basis of one read per logic clock CLK, you can work out how many reads Display will need to read the frame buffer per, say, frame (or per line...or per 'n' CLKs...whatever seems relevant to you). You then know how many read/writes are available to Draw in that period. If it's not enough, consider making the RAM twice as many bits wide so Display needs to read half as often. (That may complicate the Draw interface to need read-modify-write for writes if the FPGA RAM doesn't support byte writes at that width, but one thing at a time). Calculate for that and if insufficient, consider four times as wide...and so on.

So all that was to get you to a point where you have your frame buffer arrangement..

To implement the frame buffer RAM in VHDL, I would personally create an entity called FRAME_BUFFER_RAM with an interface for Draw and another for Display. This keep the technology-specific part within that one design file, so if you change FPGAs, you only have one file to consider changing.

Within that entity, I would instantiate the Block RAMs directly because I would want direct control over how much RAM is used and in what arrangement. Block RAM is normally a precious thing and, not knowing what devices this might be put into in the future or what else they'll contain, I always keep it as little-used as possible.

Hope this helps and addresses the question you were asking.

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.