Here's the hardware as-built. Click here for a nicer pdf version. It took a few more ICs than I originally thought, but it's still very simple.
All five waveforms (vsync, hsync, red, green, blue) are stored as a sequence of bytes in a 512k x 8 SRAM; one byte for each pixel clock in the entire frame - blanking intervals and all. Five 74AC163 synchronous binary counters cycle the addresses into the SRAM. The output of the SRAM is latched in a 74ACT574 register - the ACT part is used here since the SRAM has TTL-level outputs. The vsync and hsync signals are output through 61.9 ohm resistors, source-terminating the 75-ohm cables. The color signals are each formed with a simple 3-resistor DAC, providing a total palette of 64 colors, again matched to 75 ohms. Gamma correction is willfully ignored.
I used a 74AC02 quad NOR gate as a pair of MUXes for the clock and reset signals to the counters. When loading data into the SRAM, the PIC bitbangs the clock and reset lines to address sequential locations. After the PIC finishes loading the data, it switches control of the clock and reset lines back to the free-running circuit.
The address reset circuit is fed by a synchronous edge detector (a 74AC74 flip-flop and a 74AC00 NAND gate) that detects the rising edge of the vsync pulse to reset the counter. This arrangement means that the vertical back porch has to be stored first in the SRAM, but this is easily handled by the PIC software.
Finally, since the 74AC logic edges are so fast, and the counters and flip-flops edge sensitive, I took extra care routing the clock signals around the board. The 25.175 MHz dot clock comes from a pre-packaged oscillator "can". I used a 74AC244 octal buffer as a clock-distribution amp, with each of the seven clock lines required on the board driven by a dedicated buffer. To prevent distortions of the clock signals, each line was run with a twisted-pair of wire-wrap wire. These home-brew pairs have an impedance of about 102 ohms, so 86.6 ohm resistors were used to source-terminate each of them at the 74AC244 outputs. The resulting clock signals look good at each of the clocked ICs around the board - this is not the place where you want ringing and possible double-triggering.
It might not have been obvious from other photos of the board, but most of the ICs are SOIC/SOJ and are mounted on some adapters I designed and had made at OSH Park:
These worked really well. The pads are spaced out just enough to make soldering manageable. I've soldered directly to SOIC pins before, and I don't like it. Too small. The boards assume the standard corner power pins for logic ICs and include sites for MLCC bypass caps.
Oh, and as for power consumption - when the PIC is calculating the fractals and loading the SRAM, the circuit draws around 19 mA. Once the VGA generation starts, this jumps to 128 mA. Still not too bad, I guess - you could run it off a USB port if you asked the USB host nicely for more than 100 mA.
EDIT 20170103
I updated the schematic to include the CE_bar line on the SRAM, which just gets tied low.
I have also been thinking about the whole clock distribution/twisted pair thing. It might be avoided by using a 74HC gate as the clock driver - with the slower edge rates, maybe you don't need to worry so much about wire lengths. I discussed why 74AC163's were required a few logs ago, but that doesn't mean everything has to be 74AC. If I build another one, this would be an interesting place to try to simplify even more. Maybe a 74HC02 substituted for the 74AC02 could serve as the MUXes and clock driver.
I found a reference that says 74HC edge rates can be as short as 5ns. This is 1.5m of wire at a velocity factor of 1. 1/6 of this length is 25cm. That might make it doable, assuming the rest of the timing still holds.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
The clock rate isn't the main point: the whole circuit depends on a few ns of stable address data for operation (all counters stable at the same time). It might have been a bit easier with split horizontal and vertical counters, but that adds some complexity to the approach.
I guess that TP made the clock distribution much more manageable: no "now-it-works-now-it-doesn't magic hands effect" due to ringing and random damping.
As a side note: the frame buffer method chosen is amazingly simple. I would have tried to build a simple circuit around something akin to this VRAM chip: http://www.micross.com/pdf/SMJ44C251B.pdf, which would have spared me the effort of building synchronous counters, but which would have required managing more complexity. Chapeau!
Are you sure? yes | no
I thought of using SPI RAM for video buffer - counters, serializer is built-in and easier to mux. Newer chips support 1/2/4 bit wide ports.
Are you sure? yes | no
The advantage of the dual-port would be writing to the RAM and generating output at the same time. This simple system has to blank the video while you load the SRAM.
Are you sure? yes | no
How fast does your clock need to be before you should start using twisted pairs and not just a single wire?
Are you sure? yes | no
It is the track length - propagation time on the wire vs rise and fall time that determines whether or not you can get away without a controlled impedance/termination(s).
Rule of thumb of that ratio is 1/6. That number is dependent on how much overshoot/undershoot you an tolerate. For serious work, you would run a simulation with track length, bus topology, driver and load characteristics.
Are you sure? yes | no
Yes, I said "fast" above, when I should have mentioned edge rates. I measured the edge rates of these 74AC gates at 1.15 ns (they may be faster, that's about the risetime of my 'scope). That equates to a wire length of 35 cm in free space. 1/6 of this is about 6 cm. The board is 12cm on a side, so any wire longer than half the board could be problematic.
Even wires shorter than this can be a problem if their inductance resonates with the input capacitance of the gate inputs and causes ringing. But, ringing anywhere but the clock lines won't cause that much trouble as long as it has died down by the next clock edge.
Are you sure? yes | no