hi.. i m using spartan-2 ......... and have designed a very simpl vga controller on it ...... now i wanna interface an external ra with it .......... i m available only a sram of 32 kbit * 8 = 256 k memory which is not dual port....... i wanna store 640*480 pixels data on it ... as i nee only 8 colors ...so 3 bits for each pixel ... is it possilble to reduce memory to make according t desired requiremeents ........ and to use it although it is not dua port ..
Timeslice access between whatever is writing to your video memory, and the vga controller. You'll need some pretty fast SRAM to do this - I suspect your dot-clock is around 30MHz (33ns)? So you'll need SRAM twice as fast as this.
Use some sort if FIFO and write to the SRAM only during the blanking intervals on the vga controller. This will of course limit your bandwidth writing to the video memory.
As for memory size, my calculations give 115.2KB required for the display, though it's horribly aligned. Storing 2 pixels/byte requires
Oh, I think you're saying you only have 256k *bits*!?!
You'll have to compress the image then. Depending on the complexity of the image, you may get away with RLE - it's pretty simple to decode on-the-fly. Otherwise, well, I'm glad it's you doing it and not me! ;)
For 640x480, scanline time is 31.77us. At 4 bits/pixel, you need to fetch 320 bytes in that time, which gives you ~100ns per byte. You'd also need to pre-fetch a scanline on-chip since the actual dot clock is around 25.175MHz (2 pixels = 79ns).
But then your SRAM bandwidth utilisation is approaching 100%, which leaves no time for the CPU to update the video memory. I suppose it would be possible to output interleaved VGA, and use every other scanline to allow the CPU to update video RAM, but that has other design implications.
You don't have enough memory for a direct pixel array so you're going to have to do something else, like maybe RLE compression.
Another thing you could do is make a tiled controller, similar to that used by some 8-bit computers of the 80s, and even things like the Nintendo Gameboy Advance.
View your 640x480 screen as an array of 80x60 tiles, each one being 8x8 pixels.
Your screen is now a tile array. Each array entry is a 2 byte tile index, so thats 80x60x2 = 9600 bytes.
This leaves ~23K bytes for tile data.
A tile is 8 pixels wide @ 3-bits per pixel = 24 bits (3 bytes). A tile is 8 pixels high @ 3-bytes per row = 24 bytes / tile.
So your 32K byte memory can store the main tile array plus 965 tiles. That's pretty good - it can give the illusion of a full bitmapped display until the screen gets too busy.
The Gameboy Advance allows tiles to be horizontally and vertically flipped (using two control bits in the tile index) which improves shareability even more, at the expense of more complicated scan-out.
Every 8 VGA rows you will read in a new line out of the tile array. Each row is 80 bytes x 85ns = 6.8us.
For each entry in the tile row, read the tile data into a block RAM. You'll need 80 x 3 x 8 = 1920 bytes of block RAM (or 15K-bits). The smallest Spartan 2 has 16K-bits.
Each tile is 24 bytes, giving 24 x 80 x 85ns = 163.2us to read them all.
external memory accesses.
640x480@60Hz = 32us/row, so you're generating (8 x 32us) 256us of screen information using 170us of memory access time, assuming zero idle time.
This leaves 33% SRAM bandwidth for CPU writes (perfect case timing).
Some 8-bit micros of days gone by would assert WAIT (or equivalent CPU signal) to pause the processor during memory access conflicts. That might be applicable in this context.
If you want to get more sophisticated, for a given tile array row, only read the tile data once. So if your tile array uses tile #100 three times, don't read the tile #100's data three times - only read it once.
For sophistication++ view the block-RAM tile data as an LRU cache, and only populate tiles you haven't already got or are dirty (snoop CPU writes) and only retire tiles you're not going to use in the current tile array row.
If you were to implement this verbatim you'd need twice the block RAM, as you're reading in tile row + 1 data whilst still generating pixels from the current tile data.
Also check your clock. 640x480x60Hz uses a 25MHz pixel clock. The RAM you mentioned has an 85ns (not 80ns) access time. If you're synchronous to the pixel clock your RAM cycles will have to be 120ns... which isn't good. Use a more appropriate core clock to minimize RAM access time and, if it's not a multiple of the pixel clock, remember a FIFO across the clock domains.
You will also get memory access collisions when you want to read data from the RAM whilst the CPU is already in the middile of an access cycle. More fun to deal with.