CPLD VGA Graphics controller - Page 1
Forum section: electronics / projects

author: pyrohaz
author_rank: Regular Contributor
timestamp: August 11, 2014, 08:52:18 am
content: Ok,I'm planning to make a (simple) CPLD VGA controller that can display frames from my STM32F4 microcontroller. I'm looking to use a VGA resolution of 800x600 and a colour bit depth of 8bpp as this allows me to use my CPLD with a 100MHz clock (divided by 2 to allow for the 50MHz Pixel clock), I could just use a 50MHz crystal though. The VGA production part doesn't seem that bad, I'm wanting to use three 3bit R2R DACs for each colour and the colour will be the standard RGB332 where in the CPLD, I will shift up the blue to 3bits to ensure that full blue, red and green = white (all three voltages will be the same). Knowing that my CPLD will be running at 3.3v and the VGA maximum input voltage is 0.7v, terminated with 75ohms, my R value will be 270ohm, producing a maximum voltage of 717mV. I know this is a tad over but in my experience, the VGA interface is pretty flexible up to 1v.That side isn't too bad. The part I'm not too sure about is how to write the frame to the screenwhilesimultaneously writing to memory from my microcontroller. I've looked at dual port SRAM but its really expensive and there don't seem to be many suppliers. My second idea was to use two standard single port SRAM chips with seperate data and address lines, shared by the CPLD and the microprocessor. When the current frame buffer is being read by the CPLD, a line will be high and the microcontroller will understand that it must write to the other, the line will be low when reading form the other buffer. Writing time will be limited to the total screen refresh rate which will be 72Hz (I'm not sure if this is standardised, it just supports my 50MHz clock!). As long as the microcontroller writes the the frame buffer in that time, I'd expect the synchronisation to not be a massive issue.Could anybody give me a bit of light on this situation and how they'd implement a VGA graphics controller?BTW my STM32F4 will be running at 168MHz and my graphics library utilizes integer operations so its pretty fast!Cheers,

author: nctnico
author_rank: Super Contributor
timestamp: August 11, 2014, 09:18:59 am
content: Every now and then I make TFT rescalers for old equipment and I run into the same problem with dual port access and memory bandwidth. I deal with that by using a wider memory. If you use 32 bit memory you can reduce the memory reads by 4. I assign fixed timeslots for reading and writing. I also recommend to lower the pixel clock to the minimum the display supports. TFT is slow so a high refreshrate doesn't add anything to your system.For the processor interface I recommend to use a buffered approach where you latch the data to be written inside the PLD and write it to the memory during the 'write' timeslot. This also solves clock domain crossing issues. If the controller wants to write data before the PLD has written the data into memory use the wait pin to extend the controller's bus cycle. Chances are that the controller also needs time to fetch the next data so no waits are necessary.

author: mamalala
author_rank: Unknown
timestamp: August 11, 2014, 09:45:21 am
content: Or one could use a controller that has a graphics interface built-in. Usually they are meant to drive panels directly. Just use the CPLD to "convert" the signals that the micro generates into something that a VGA screen can understand. For example, the STM32F429 and 439 have built-in LCD-TFT engines.Greetings,Chris

author: bktemp
author_rank: Super Contributor
timestamp: August 11, 2014, 09:46:21 am
content: Have a look at how others have done that:http://elm-chan.org/works/crtc/report.htmlDisplay controllers typically implement a small fifo for output and input pixel data. Then you need a memory arbitration that coordinates the read and write access to the single memory to refill the output fifo and write the data from the input fifo.Using a small fpga is much easier because of the embedded block ram. Therefore you can implement much larger fifos. This increases the efficiency of the available memory bandwidth, because it buffers the data written during a scanline and transfers them during the blanking intervall if the fifo is large enough. Otherwise you need to implement some sort of busy or wait signal to slow down writing of new data.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: August 11, 2014, 10:21:54 am
content: Regarding the output, I would strongly encourage you to use the same approach that VGA normally does: 256 colors, mapped via palette buffer (fast internal RAM? -- you'll want an FPGA, not a CPLD) to an 18 bit (or higher) color space, and a proper video DAC (you won't get there using discrete resistors, not for good enough accuracy). You'll be missing out on so much richness and existing code/media by skimping on this.Just for testing, yes, you can leave the palette off and map color to DAC with a simple bit masking operation (i.e., the proposed 3-3-2 scheme), filling the low bits with zeroes. You don't need the brains inbetween yet, a prototype is good -- but don't make the mistake of skimping on hardware -- or of logic capacity.Most any 'multiscan' type CRT monitor should be fine with those timings (make sure you get the VSYNC, HSYNC and overscan periods correct though, or leave them adjustable*). But I doubt that LCDs will be as happy: they almost all run at 60Hz. It wouldn't be much of a stretch to connect the DDC2 lines to the MCU so you can detect which modes the monitor supports, without trying to feed it nonsense.*In the original VGA (Video Graphics Array -- yes, built with array logic no less), pretty much all timing and memory access was adjustable via registers; a typical BIOS call to change screen resolution might transmit 30 bytes or more to initialize all the registers. You're probably looking for something a bit less general than that, but it's ultimately good design to keep in mind: it keeps your hardware flexible, and your updates confined to firmware where possible.As for bus access, in the old days, the processor simply had to wait until the hardware was done. This eliminated the possible 'snow' that early (CGA, etc.) adapters had, but totally stalled the processor, at least until the end of a scan line, if it asked for VRAM access. I don't know if/when buffered methods were adopted, though it's obvious that anything since the 386 days had something going on (whether it's a FIFO to be dumped when the VRAM bus opens up, or dual ported RAM, or something else altogether), since fill rates on those platforms exceeds ISA bus capacity (consider the 1MB+ adapters, SVGA, and VESA extensions, which dominated the 486 era).Any of these methods could be used; the FIFO is a neat idea, though limited by length (if it fills up, presumably you need to stall the processor to prevent missing writes?). You could even go so far as to copy the RAM into a second chip during vertical refresh, assuming they can go fast enough that is. (But I'd guess with a 50MHz pixel clock, you'd have a hard time pulling that off, even if you added a >100MHz PLL option to get those RAMs screaming.)Note that VRAM is constantly being read, top to bottom, and data loss outside the active range doesn't matter, so you can very easily drop DRAM into there, saving a buck or two. SDRAM wouldn't even be too big of a stretch; with FIFOs on both input and output, burst / block mode accesses could be used, for much higher bandwidth overall, and (if there's bandwidth leftover), the possibility of multiple controllers reading different views of the same frame buffer (or different, or differently formatted, buffers; lots of possibility).Tim

author: amyk
author_rank: Super Contributor
timestamp: August 11, 2014, 10:36:59 am
content: According tothisyou have roughly 1.37ms to update the screen during the vertical blanking interval, and 4.8us each horizontal blanking interval (2.88ms total).

author: pyrohaz
author_rank: Regular Contributor
timestamp: August 11, 2014, 11:20:43 am
content: Quote from: nctnico on August 11, 2014, 09:18:59 amThats a really good point about using 32bit memory, unfortunately however, that'd put more stress on my processor with having to pack 4 pixels into one DWord. Its a good idea though! I'm not using the high refresh rate for better visuals, it was just a bit easier that the 800x600 mode with a refresh of 72Hz used a standard valued pixel clock that I could easily derive from my global clock.Quote from: mamalala on August 11, 2014, 09:45:21 amI should've mentioned that in my earlier post! I'm targeting the STM32F405 at 168MHzThe processors containing the integrated LCD controller are unfortunately out of my range for this project.Quote from: bktemp on August 11, 2014, 09:46:21 amI've not actually had any experience with an FPGA, I've written a small VGA controller using my Altera EPM240 MAXII CPLD, really simply outputting various colour bars (using an R2R DAC) and was wanting to expand it to using my Microcontroller to draw simple shapes etc. A 800 byte FIFO sounds like a great idea though to transfer lines and allowing the micro to write to the main buffer during that time. I'm not too bothered about having a wait signal so that might be a good idea. Writing line by line however seems a little more annoying as my graphics library is written to allow for complete frame buffer writes at once. Changing that however shouldn't be a massive problem I suppose...Quote from: T3sl4co1l on August 11, 2014, 10:21:54 amAs I stated earlier, I don't have too much FPGA knowledge though if its merely stepping up from a CPLD, I'd be prepared to learn! I'm not looking for immense colour depth as of yet considering I'll be using a relatively slow microcontroller to generate the imagery, I'm pretty happy just using 256 colours with my poor R2R DAC, for 3bits, I think I only need resistor accuracy of 0.1% which is pretty easy to get hold of. Obviously with respect to the timings, I'd be able to adjust them within the CPLD with regards to when I set the overflow point of the HSync and VSync counters.I've been reading a few forums on DRAM controllers and their usage look a fair bit out of my depth! Do you know of any material where I could learn about DRAM implementations pretty easily? I assume I'd also need to interface my microcontrollerthroughmy CPLD to access the DRAM as my micro doesn't have an integrated FMC (the STM32F429/439 does include an SDRAM driving FMC however).Talking of which, I was thinking of a line by line method of data writing involving waits, I'll write me mental data flow below:The user wants to draw a line form say 1,1 to 50, 50 in blue.The microcontroller uses the bresenham method to draw this line and will have three arrays filled with the x,y co-ordinates of the line (1,1 - 2,2 - 3,3 - 4,4 - 5,5 ...) and the colour.The microcontroller receives a signal causing an interrupt during the horizontal blanking period.The microcontroller and CPLD are initially sync'd and both count the current line (a reset signal from the microcontroller asynchronously resets the CPLD line counter, the current line is set to 0 in the micro).In this interrupt, the microcontroller checks if it needs to draw to this current scanline.If so, the microcontroller writes the X co-ordinate to the CPLD (parallel bus?) along with the pixel colour and toggles a write line.The CPLD latches the data and writes to the SRAM. This line will then be drawn on the next screen refresh.The microcontroller obviously can only write line by line and will be waiting most of the time though this wouldn't be a massive worry for me and by counting interrupts, I can keep track of what line im on (wrapping a counter at 799 of course!).If I am thinking of this correctly, this should eliminate the need for more than one SRAM chip, In the vertical blanking period, I can execute certain commands such as clearing the whole buffer (set SRAM data to zero an increment address over and over).For an 8bit VGA display at 800x600, am I right in assuming I will only need 468.75kbytes of ram, or more so that it will fit in a standard 4MBit SRAM IC?Cheers,

author: T3sl4co1l
author_rank: Super Contributor
timestamp: August 11, 2014, 08:58:01 pm
content: Quote from: pyrohaz on August 11, 2014, 11:20:43 amI've not done it myself, but there is standard IP available. If you used, say, an Altera Cyclone 3 or 4, you need a few extra supplies (at minimum, 2.5 or 3.3V for the logic banks, 1.2V for core, plus 1.2V and 2.5V (filtered) for PLLs -- these are easily obtained from LDOs), and a lot more consideration of what's going on, but you can connect to standard SDRAM. Specific pins are required (DQs), mainly. Then in the hardware design, you call out an SDRAM controller with specs matching the RAM chip, and a bus and address setup suitable for your application. Dealing with FIFOs would probably be easiest with a DMA block or two. Then some (potentially non-obvious) logic to unite it all.No, not a beginner's project by any means, but it's not nearly as overwhelming as it may seem.QuoteAlright, I already smell trouble...1. Why compute the line in its entirety, wasting memory, when the CPU is "sync'd" and can almost trivially calculate the next pixel(s) on that line, on demand?2. Software doesn't sync well. How exactly do you propose to ensure that? Well, you mentioned interrupts. Good. But what's the guaranteed latency? If your main() requires multi-word atomic accesses,you're already looking at tens of cycles wasted, plus pipeline plus cache. I don't know the actual timing of these events on an STM32F4, but on any platform, it's rarely faster than fractional microseconds. I/O is also much slower than the processor core; check the architectural diagram to see what delays and clock rates to expect.Point being, by the time the processor "knows" about something happening and is able to do something about it, you're already well into the horizontal refresh period. You don't have much time or bandwidth here.Why write during a line at all? You don't need to update a line, microseconds before it's drawn on the screen. The refresh rate is 72Hz, let the CPU do its thing for >10ms, then dump a massive buffer during vertical retrace. You won't be able to dump a full screen buffer (assuming your MCU had half a meg of RAM), but you'll get more than a few pixels per line, and all in one simple lump transfer. You can still calculate things on the fly (Bresenham's is so easy it's almost never worth precomputing -- that's kind of the point!), or write a buffer with address-value pairs, or RLE, or whatever.QuoteSo you can only update one pixel per line per frame?DON'T "wrap a counter at 799". That's shitty programming and you know it! You have VSYNC, use it. If they ever get off by one HSYNC, the whole display goes into some sort of misaligned garble-land -- all from careless design!Lesson: just because something is, strictly speaking, fully logically / mathematically equivalent to another approach, doesn't mean it need ever work in real life. Bits go missing, signals bounce, reset signals meet different delays, clock signals get skewed by bus delays, and on and on. Numerically, integers have finite size (almost always modulo 2^N), and floats have finite resolution: you can easily fall in the trap of subtracting two nearly-equal floats and continuing to operate on the residual noise as if it were an important value. Algebraic rearrangements are mathematically equivalent, but rarely numerically equivalent.Quote480kB, yes. (To be precise, 468.75KiB.) And yes, or more.More is vastly useful by allowing you to draw to a hidden page in the background, then switch the pointer offset register all at once to the new buffer, so the viewer doesn't see all the ugly updates going on.You can also implement simple row or column offsets, which come in handy for side scrolling images. This feature of EGA hardware is what allowed Carmack to write Commander Keen, back in the day when consoles had dedicated sprite and tile type graphics controllers made for the purpose, while the IBM PC had a flat* graphics buffer with piss for all CPU-VRAM bandwidth. Such games were thought impossible!*Not actually flat, it's interleaved bit planes. Kind of weird. But, linear within those planes, not like a sprite/tile system that's all over the place.Tim

author: P K
author_rank: Newbie
timestamp: August 12, 2014, 02:26:15 am
content: When I saw your topic I had to de-lurk; I'm working on a very similar project for this Hackaday prize, and I just laid out the memory bus arbitration. My requirements are a bit different: 144 macrocells, NTSC/VGA, 640x480, RRRGGGBB color.As far as I know, there are 5 ways to deal with the writes, but two of them really stand out (here's my design, if you'd like to reference the chip and the VHDL I used:http://hackaday.io/project/1943/log/6464-yes-but-why)Switching Buffers- Use two RAM chips, and when your write is done, flip the read/write RAM. This is how most video cards do it today.Interleaved write- I'm using this one in my project, and like you I'm clocked at 2x the pixel clock. The only reason I'm able to do it is because the WE pulse only has to be 8ns for the RAM I picked, ISSI's IS61LV5128ALDual Port RAM - Special hardwareZero Bus Turnaround RAM (sort of like interleaving, but you can read/write on different edges) - Special hardwareWait for the V/H blanking intervals (Doubtful on a CPLD unless data comes in very slowly)I will tell you, you're probably better off with an FPGA. I'd be lying if I said I picked the CPLD because it's the better choice - I really wanted the challenge of fitting it into 144 macrocells. (Turns out I've been making compromises to avoid theptermlimit so far, not the flip flops.) The FPGA gives you plenty of headroom, so when you want to go to higher resolutions you won't be constrained.In short: it sounds like your best move is to get two RAM chips, and switch them between write/read when your write is finished.

author: pyrohaz
author_rank: Regular Contributor
timestamp: August 12, 2014, 08:22:29 pm
content: Quote from: T3sl4co1l on August 11, 2014, 08:58:01 pmFirstly Tim, I want to thank you for investing so much of your time into helping me, this is great!I have recently had a rethink and drawing during the vertical blanking by far sounds best for this kind of thing. Thats a very good point about the interrupts. I'm going to do all the drawing within the vertical blanking period. I don't mind about visible drawing (is that the right terminology? I mean I don't mind seeing the micro drawing to the screen every frame...). If I could manage about 5 fps, the Microcontroller only really needs to be able to draw a full frame in 50ms, right? I'm not wanting to as of yet be spewing data to the screen at 30fps or whatever yet so I'm pretty happy at this lesser rate!I actually got started with the code writing last night and got my screen (some cheapo Yuraku 19" jobby) to recognize the 800x600 resolution at 72Hz - My monitor OSD tells me this for free, how convenient! All was going great... that is until I somehow managed to do the epic fail of all electronic engineers and connect the 3.3v rail directly to a low pin, blowing both my AMS1117 regulator AND the CPLD. Needless to say, I was pretty damn annoyed, thank goodness it only cost me £10withthe USB byteblaster.After that, I had a pretty large rethink to this project and decided to plant my £££ on a new CPLD board (I probably should've got an FPGA but for the price range, no FPGA offered this much functionality). Its based on the same EPM240C100T5 and cost me £27.99 with shipping - It includes an absolute ton of cool features (8x8 LED matrix onboard, 8x 7 segment LED, 4x4 matrix of push buttons, 8bit DIP switch and more!), one of these being an onboard VGA connector, much easier than wrestling with my VGA connector and breadboard. I assume it will also have the correct resistors (I can change them if not, they only look 0805/0603 from the pics). It also has an onboard DAC so maybe one day, I will be able to produce audio too! If anyone is interested in the board, I got it off WayEngineer -http://goo.gl/8qeXudUnfortunately, until I receive this board, I'm going to have to postpone this project!Quote from: P K on August 12, 2014, 02:26:15 amDamn! You sound a lot more knowledgeable in this than I am! When you figure out the colourburst with NTSC, throw some of that info my wayI managed to get PAL composite to work with my STM32F4 but I wouldn't even know where to start wrt the colour stuff. I'm pretty happy waiting for the blanking periods (as I said above) and hopefully, I can get the micro to spit out data pretty sharpish merely using the CPLD to buffer the micro output to the memory. I'm still a bit stuck however on reducing pin count. 19 address lines and 8 data lines is a lot to wire up! You RAM is looking pretty tasty however, I'd found some 10ns access time SRAM on my preliminary RS search for ~£3.50, how much are you paying/chip?

author: P K
author_rank: Newbie
timestamp: August 13, 2014, 03:00:14 am
content: With pleasure; but I'll link you to the front page of that project:http://hackaday.io/project/1943-VGAtonicYou'll need to go to "View All#Project Logs" at the bottom; the NTSC demo is in the entry called 'Proof of Video Life'. The VHDL is in the Github there (MIT license, hope it's helpful). It's got 16 colors and (depending on your monitor) 16 levels of luminance - for more, add a second output and mix them with some resistors/diodes. My general idea was to abuse VGA by having my clock off by .47% so I could do NTSC/VGA with the same frequency (spoiler: it works [!], at least for all the monitors here).I'm in Silicon Valley- I ordered my IS61LV5128ALs from Jameco; $43.39 for 10, currently.If you haven't given up on read/write interleaving, there's a scheme you might try to work out so you won't have to use the semaphores.So you've got your Pixel Clock (50 MHz?) and you've got your Logic Clock (100 MHz?), which is 2x the Pixel Clock. This scheme would occur over 4 cycles of the Logic Clock, and yourpixelrequirement would be to push out 2 pixels in that time. (Each entry in list represents one cycle, OUTPUT goes to monitor, ADDR is your address bus, DATA is the data bus)Get the active pixel, high-Z on DATA/ADDR yourreadaddress/OUTPUT the active pixelGet the next pixel, high-Z on DATA/ADDR yourreadaddress/OUTPUT the active pixelHigh-Z on DATA, OE off/ADDR yourwriteaddress/OUTPUT the 'next' pixelPULSE WE, Data write on DATA/ADDR yourwriteaddress/OUTPUT the 'next' pixelRepeat that game of chicken every time your input cache changes. You'll have to get intimate with your data sheet, but something like that will work... it's just a question about whether 4 cycles is enough, or you'll need to stretch it to 6 or 8... oh, and how big a CPLD you picked.

author: GK
author_rank: Super Contributor
timestamp: August 13, 2014, 05:48:36 am
content: I've done all of this in an EPM7064, but at lower resolutions. Keep in mind at your resolution you've got about 20nS to shift out each pixel. Is this a purely graphics design or character based as well? If character based your programmable screen RAM is in series with your character ROM (the ROM is partially addressed by the RAM). If both RAM and ROM have 10nS read, there goes your ~20nS before even factoring in CPLD propagation delays/counter speed and some practical headroom.Even in a graphics only design without the ROM you're still pushing it. In order to eliminate skew and achieve a crisp display I shift out the RGB pixel data synchronously with D flip-flops with parallel clocks. I generate a master clock with a 25% duty cycle. On negative edges the counters are clocked, on positive edges the DFF's are clocked. I therefore have 75% of a clock period avaliable for my video data to settle/ripple through the (synchronous of course) counters and the RAM/ROM and the 8-bit multiplexer for serially shifting each ROM bit, plus the logic for setting the colour.One alternative to having to use uber fast RAM for higher resolutions would be to effectively construct two or more video generators for generating the single video signal, running interlaced in parallel. This something that I've worked out but haven't gotten around to building yet.To produce composite/component video from the RGB, I use this:http://www.analog.com/static/imported-files/data_sheets/AD724.pdf

author: MrSharp
author_rank: Newbie
timestamp: September 02, 2014, 02:39:52 pm
content: Quote from: P K on August 12, 2014, 02:26:15 amThere's something I don't understand here. Let's say I draw a box in ram #1 while ram #2 is displayed. At vsync, ram #1 and ram #2 are switched and ram #1 is now displayed (I see my box). Now I want to draw a circle in the middle of my box, but there's no box in ram #2 and I end up with some of my drawing in ram #1 and some in ram #2. That will definitely flicker no? Does it mean that ram #1 (300 KB) has to be copied in ram#2 just before switching?

author: marshallh
author_rank: Unknown
timestamp: September 02, 2014, 02:56:53 pm
content: Yes, the "solution" is to redraw all the of display contents every time, and simply prevent a page flip from occuring until you're done drawing in that buffer.

author: David Hess
author_rank: Super Contributor
timestamp: September 02, 2014, 08:23:37 pm
content: Quote from: marshallh on September 02, 2014, 02:56:53 pmI was thinking just plan on drawing twice. Draw once and then page flip, duplicate what you just drew on on the last page on the new page and then add the new stuff, and repeat.So either you need a display list to remember what you last drew on the page currently being displayed or a shadow frame buffer.

author: GK
author_rank: Super Contributor
timestamp: September 03, 2014, 03:45:32 am
content: The technique is calledDouble Bufferingand is quite old hat.I recall writing double-buffered graphics demos on my Amiga 600 inBlitz BASIC.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 03, 2014, 05:20:06 am
content: There's also triple buffering, where you use each one in turn; one is always being displayed, one is being written, and one is left idle (waiting to be drawn or waiting to be displayed).Why? You draw one or two ahead, so that you can draw continuously at whatever framerate the software is limited to. If ahead, there will always be a frame available for when the vertical retrace interrupt signals a page flip; if behind, several vertical retrace events may go by, but it won't switch page until that frame is ready.Actually, for minimum latency, you'd want the page flip code to pick the newest of two pages; either zero (no frames ready, stay on the current one), one (keeping pace) or two (the renderer finished both, and is waiting for the currently displayed buffer to become free).Or you could render continuously (no thread stalling) and draw between the two available buffers, leaving a marker to indicate to the interrupt code which one is newest. That way, if the renderer goes whammo fast, it might draw N frames, and the Nth gets displayed while it's working on the N+1th.In more general terms, you can implement a buffered data exchange this way, which is good for passing periodic data (video frames, audio buffer samples, ADC samples, etc.) between independent threads without having to implement/enforce a lock (e.g., clear interrupts for synchronous read -- interrupt can't fire during the read, and your worst case interrupt latency gets abysmal) or other method. I forget what interprocess method this is called..Tim

author: DanielS
author_rank: Frequent Contributor
timestamp: September 03, 2014, 09:28:41 am
content: Writing a VGA controller for a CPLD is quite limiting with how scarce logic resources are compared to an FPGA.With an FPGA, I would use one BlockRAM to buffer data for the DAC and another BlockRAM to buffer data from the microcontroller so the frame buffer SRAM/DRAM can be accessed in interleaved bursts. Palette-based drawing would also work very nicely with FPGAs since you can program the palette in a BRAM too. FPGAs' internal SRAM is dual-ported, which affords a whole lot more freedom in how to use and manage them. On top of that, you have many of those small SRAMs to play with without the hassle of dealing with external chips.With a CPLD, you could have a main SRAM for your frame buffer and a smaller secondary SRAM to buffer microcontroller writes which you could dump in the main SRAM during horizontal and vertical blanking. The microcontroller IO would go through the CPLD to reach that secondary SRAM instead of using dual-port and some sort flow control would be necessary since the microcontroller cannot write to the buffer while the CPLD is busy dumping data to the main SRAM.One of the most useful pieces of VGA VHDL code I have written is a text overlay generator. 16kbits for the 256x8x8 character bitmap, 128kbits for the 100x75 character+color table, 1kbit for the RGBA palette. This would not fit on a CPLD.

author: Alex Eisenhut
author_rank: Super Contributor
timestamp: September 03, 2014, 11:36:26 pm
content: Say, would anyone have some pointers as to how LCD monitors manage to generate a clean pixel clock from the analog VGA connector?

author: David Hess
author_rank: Super Contributor
timestamp: September 03, 2014, 11:44:48 pm
content: Quote from: Alex Eisenhut on September 03, 2014, 11:36:26 pmI think the good ones phase lock to the VGA signal so no aliasing occurs while sampling the analog levels.

author: GK
author_rank: Super Contributor
timestamp: September 04, 2014, 01:07:15 am
content: Quote from: DanielS on September 03, 2014, 09:28:41 amI used external SRAM/ROM in my various video generators. As a whole logic required for what is an apparently complex function is in fact quite simple and surprisingly compact.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: September 04, 2014, 01:08:52 am
content: ^ Video isn't passed through an antialias filter, so the harmonics will be quite apparent.

author: David Hess
author_rank: Super Contributor
timestamp: September 04, 2014, 02:17:10 am
content: Quote from: T3sl4co1l on September 04, 2014, 01:08:52 amI assume this is in response to the question about getting a clean pixel clock from analog VGA.If the digitizer is phase locked to the sample rate of the VGA DAC, then no aliasing takes place. This is particularly useful when the VGA resolution is the same as the LCD native resolution.The early LCD monitors did not do this and looked pretty poor but the later ones and all of the ones I have used look just as good when using an analog VGA connection as they do using DVI. My Dell monitor has an "automatic adjustment" mode which synchronizes to the VGA output and saves the timing information. Without it, the display suffers aliasing.

author: hamster_nz
author_rank: Super Contributor
timestamp: September 04, 2014, 03:32:26 am
content: Quote from: David Hess on September 03, 2014, 11:44:48 pmIn my expereience, the monitors know the "standard" pixel clock rates, and take intelligent guesses for nonstandard rates. So when in my designs I use 25MHz for 640x480, rather than 25.175MHz I have to tweak the width/pixel phase on most viewsonic monitors.As somewhat an aside DVI-D and HDMI specify 25.175 as the minimum acceptible pixel clock, so some gear engineered around HDMI might have issues if your analogue VGA source uses a 25 MHz pixel clock (e.g. my Sony TV - it just shows out of signal range)

author: DanielS
author_rank: Frequent Contributor
timestamp: September 04, 2014, 04:20:39 pm
content: Quote from: GK on September 04, 2014, 01:07:15 amI never said it was "an apparently complex function" - I wrote my own VGA character generator for a Virtex2Pro and Virtex4 in about a day including a fair amount of unnecessary complexity. Yes, the logic (except for SRAM) would fit fairly easily in a CPLD but it would eat a large chunk of available IOs and FBs - the external RAM and ROM alone would likely force you to bump your CPLD selection up a notch or two just to have enough pins. With even the smallest modern FPGAs like an XC6SLX4, you still have 90% of the chip to play with and do not need external ROM/SRAM, which makes things a fair bit simpler.My comment about the scarcity of resources in CPLDs was mainly about the amount of resources left to do other stuff; particularly if you add extra SRAMs to emulate dual-port SRAM (use a couple of $3-5 1Mbits chips instead of $25 16kbits dual-port SRAMs) so the microcontroller does not need to worry about timed writes. With an XC6SLX4 (Xilinx's smallest current FPGA), you get a dozen dual-port 18kbits BlockRAMs for $22, gobs of extra logic compared to an $8 XC2C128 CPLD and many spare pins from not requiring multiple external (S)RAMs.

author: GK
author_rank: Super Contributor
timestamp: September 05, 2014, 02:05:44 am
content: Quote from: DanielS on September 04, 2014, 04:20:39 pmWow, I thought I had made a benign comment. Well it is an apparently complex function whether you said so or not, and it was not even implied that you did.I don't know why you have gotten your knickers in a twist either way.QuoteThat's awesome, you are my hero.

author: pyrohaz
author_rank: Regular Contributor
timestamp: June 17, 2015, 03:21:04 pm
content: I'm not one to resurrect a post but since I made this originally, I don't see as much of a problem. I had actually wanted to implement this for a while but I've only just got round to it! I've written an SPI driven graphics controller on by Altera Cyclone IV FPGA board, driven by an STM32F0! I went down the dual port SRAM option as the FPGA has the option for dual port RAM blocks, built in and while in the video, I was running at a resolution ox 100x75, I've now since boosted that to 160x120 (after rewriting the video interface to run at 640x480 vs 800x600). I'm actually running my LCD at 640x480 now but instead of storing each pixel individually, I'm storing "macropixels" of 4x4 pixel blocks, allowing me to store the whole frame buffer in the FPGA. This allows me to do all the heavy lifting in the FPGA and control the graphics functions from my STM32F0! I've managed video playback off an SD card at 15fps, along with fractal drawing, text drawing and image drawing too.The full description can be found at my blog:http://hsel.co.uk/2015/06/17/altera-cyclone-iv-graphics-controller-stm32f0-mcu-100x75-video/And I've made a small youtube video demonstrating a few of the features - bear in mind that this was done at 1:30 in the morning! *student life*I'm hoping to get around to releasing the code soon for others to try if they want!

author: Yansi
author_rank: Super Contributor
timestamp: June 17, 2015, 03:42:34 pm
content: If you already have 32F4, why don't you use 32F429 with LTDC (TFT controller)? Use whatever VGA DAC you will find: ADV7125 (different speeds, watch out for price!) or maybe Chrontel CH7301A DVI transmitter, which does DVI-I (both digital and analog). Or possibly convert to LVDS signalling for TFT direct drive using for example SN74LVDS84A.//I'm sorry, I haven't read the whole thread carefuly if someone has already mentioned that//PS: Using 32bit SDRAM with the STM32F429 for these highres modes is recommended.

author: pyrohaz
author_rank: Regular Contributor
timestamp: June 17, 2015, 03:45:14 pm
content: Quote from: Yansi on June 17, 2015, 03:42:34 pmThat's quite alright! Yeh the new STM32F4 chips have some awesome features (I have actually got the STM32F429 discovery board too...). The main reason however that I've designed this controller is for less capable microcontrollers, such as an *shudder* arduino, low level PIC microcontroller, my STM32F0 or my MSP430. Obviously, there are those magic few out there who've managed to get VGA working without a middle layer but I'm not one of those, plus! This was actually a fun challenge to do! Cheers for the reply though

author: Yansi
author_rank: Super Contributor
timestamp: June 17, 2015, 03:58:40 pm
content: A note: I think that any incapable microcontroler should NOT have any SCREEN. If you need it, then appropriate MCU should be used to drive the screen. Otherwise these silly combination arises, like arduino plus "STM32 graphics accelerator" as I've seen on youtube a week ago.STM32F429 is not new. Now there's STM32F746 200MHz Cortex M7. The LTDC is featuring also MIPI interface there. (and some new cool peripherals like QuadSPI).

author: pyrohaz
author_rank: Regular Contributor
timestamp: June 17, 2015, 04:05:29 pm
content: Quote from: Yansi on June 17, 2015, 03:58:40 pmI completely agree! If there is a microcontroller for the task, why not use it? I'm mainly doing this project out of interest as opposed to for any commercial usage. There are other projects like this out there though so I thought I might as well join them. I didn't mean new in a time sense, I meant more new to me (though I don't know how you'd know that if I didn't mention it...) The cortex M7 chips look great! I'm hoping once they get released in non-BGA form to get one hooked up to those cheapo 240x240 ipod nano displays that you can get off aliexpress for a pittance.

author: Yansi
author_rank: Super Contributor
timestamp: June 17, 2015, 04:23:02 pm
content: F7's are already being made in LQFP packages. We have already samples of LQFP144 and 208 beasts. I've not seen sampels of 176pin QFPs, but I'm sure they are too.But it's not sure when these will be on stock at distributors. I've asked for an estimation of date, but I didn't get any exact answer.

author: P K
author_rank: Newbie
timestamp: June 19, 2015, 04:34:25 am
content: Great to see this thread still going. I 'finished' the CPLD VGA Card I alluded to earlier in the thread as well:https://hackaday.io/project/6309-vgatonic-v2-serial-vga-graphics-cardHopefully that code helps someone. 640x480x8bpp in < 144 macrocells (~ 114 depending on your fitter options).(Of course, I'm going to try to add features.) This version works fine: 25 FPS on a Raspberry Pi 2 over SPI. There's a video in the link if your curious, but I'd really love to see some one build one. Of particular interest might be my memory controller code - I run my logic at exactly 2x the pixel clock, so I can write and read at full speed with the 4 mbit SRAM I used.