I have yet to test this on Havard's board. Bummer.
In the meantime, I thought I would dig up some details on an old CPLD VGA framebuffer experiment I did, at the request of a commenter on a hackaday post I had commented on a couple days ago.
I put this together during summer vacation 2007, mostly for fun, though I was hoping to make a standalone framebuffer device that I could pair with a CPU to make my own full homebrew computer with display capabilities. Unfortunately I never got that far. HAC-1 on this blog is another attempt at basically the same thing, though it is more of an all in one solution.
The Digilent XC2-XL board consists of a Xilinx 9572 CPLD (not used) and a 256-macrocell Cool Runner II. This is fairly large in terms of CPLDs. On DigiKey these cost at least 12 dollars apiece, and come in a 144 pin .5mm pitch QFP package, not trivial for a hobby design if you don't want to use the pre-made eval board.
The analog voltages for each color are generated by a Digilent VGA expansion board I had kicking around, originally intended for the NEXYS FPGA board. Each color gets its own 4-bit binary-weighted DAC made out of one resistor for each bit.
The remaining components are two CY7C1019 (128k x 8-bit Static RAM) chips, one PIC16F690 microcontroller to write a pattern into the framebuffer, and a 50 MHz oscillator, which can be divided down with a single flip-flop to 25 MHz which is not exactly the right pixel frequency for VGA, but close enough. The entire setup is shown here:
There are a number of ways to approach the memory architecture. One would be to run the memory arbitration at double the pixel clock speed, and read/write from the memory on alternate clock cycles. Since the PIC microcontroller with its internal 4MHz oscillator runs at 1 MIPS, it's much slower than the framebuffer. So, if we do this, we will see the image change slowly as the micro writes data in.
Another approach (the one I chose here) is page switching. The idea to have double the necessary memory capacity, and write data into one page while reading (displaying) from the other. In this way, we can have a smooth transition from frame to frame. Since I have used two external memory chips each with their own dedicated bus to the CPLD, I can simply physically switch which one is read or written to at any given time. To save IO pins, it would be better to use a single RAM chip with double the memory, and do alternate read/write operations at double clock speed, and do the page switching strictly by address offset.
Unfortunately this doesn't do much about the fact that the microcontroller I'm using here is slow, so the frame update rate is quite painfully slow either way. To make things worse, the microcontroller has to latch X address, Y address, and 8-bit data separately to complete a write operation.
But this is just for fun, and to show how difficult it can be to fully build something of this nature, depending what tricks you are willing to use. At any rate, here's a simplified block diagram of the system:
And an incremental pattern written into the framebuffer by the PIC. Note that the output is binned in the VHDL code to 160x120 pixels, by shifting the address counters to the right by two bits each.
Full VHDL source code I used in the CPLD is available here.
110 macrocells are used in this design.
Here are the design issues I faced, when trying to think of how to boil this down to one compact unit, which I never got around to finishing.
- CPLD: Want a device which can hold the required logic, with enough pins to interface the memory. If I were to design a board for one of these things, the fine-pitch QFP that the CoolRunner II comes in is difficult, though not impossible.
- Memory: Wanted SRAM (for simplicity) with enough capacity (can be expensive!) in a package I could solder by hand. TSOP-II packages are not so bad, so ISSI devices are actually feasible, and available in up to 512k x 16-bit configurations. SDRAM would be much less expensive per bit, but a bit more complicated to interface, since a state machine of some sort would be required. This might go beyond the limits of what the CoolRunner-II can do.
- CPU: The PIC 16F series microcontroller simply won't cut it, it's too slow, and the smaller ones don't have much IO. The ideal thing would be a CPU with an external memory interface, so we could do something cool like treat the framebuffer as a 2D array variable, and reading/writing a pixel could then become a single memory access cycle.