Exploring FPGA Graphics
projectf.io
projectf.io
Looking through the linked site, it's nice to see that the verilog snippets are very similar to the simplified HDL in nand2tetris - almost identical in how pins and parts are composed.
I'm looking forward to getting hold of an ice40 board as mentioned (with the SRAM). There's a project out there which implements nand2tetris on ice40, and these seem available at the moment for a reasonable price.
So now with this VGA project, that's two reasons to order that nice ice40 board :-)
This is definitely going to be my next project. It even uses Arty and the VGA module for it which I already happen to have (it only has a few bits for R, G, and B color though so it’s not perfect for images and gradients). There was example code[1] to use with it and it generates an image but I wasn’t sure how to make a frame buffer for it which this tutorial has!
I recently reviewed graphics rendering techniques (Computer Graphics from Scratch from No Starch Press) so that fits too. This’ll be fun!
[1] https://digilent.com/reference/learn/programmable-logic/tuto...
(They have a different board with HDMI in and out and a framebuffer example to go with it: https://digilent.com/reference/learn/programmable-logic/tuto...
Also I just ran across someone who did HDMI output directly from the pins of yet another variety of Arty board https://domipheus.com/blog/hdmi-over-pmod-using-the-arty-spa...
On second thought, I’d rather stick with understandable VGA and hooking up a keyboard in a matrix… could use some other microcontroller and interface between the two with fewer pins, just not USB. Or PS/2 keyboard… Ben Eater has a tutorial as always)
I was initially looking at the Arty board, as it was referenced by a text book - all the exercises were based on it. It's a bit more pricey than the ice40 (enough to force a comparison against other boards), but it certainly looks more capable.
I'd be happy to field any questions you have.
The Ti chip you're using for DVI looks interesting too, not heard of that before.
It looks like you're going to use the FPGAs BRAM for double buffering? I started implementing double buffering for led strips in VHDL, but need to get back to finishing the SPI controller for it.
The TI TFP410 chip is on the 1BitSquared DVI Pmod board: https://docs.icebreaker-fpga.org/hardware/pmod/dvi/
I've also got designs that generate DVI on the FPGA with TMDS encoding (no external IC required). I've never polished or written them up, but you can see an example here:
* https://github.com/projf/projf-explore/blob/main/graphics/fp...
* https://github.com/projf/projf-explore/blob/main/lib/display...
I'm using BRAM for framebuffers as it allows me to focus on the graphics rather than memory controllers and access. BRAM gives you dual ports and true random I/O; DRAM is much more complex.
> "游ゴシック", YuGothic, "ヒラギノ角ゴ Pro", "Hiragino Kaku Gothic Pro", "メイリオ", Meiryo, sans-serif;
I have noticed the font renders thinner on Windows.
I plan to look at the design over the winter: some things could definitely be improved.
BTW the article is wonderful, thank you for making it. I have an Arty board but I will be running through it in Verilator.
Once you've got a design working in Verilator, I strongly recommend running it on an actual board if you can: nothing beats the feeling of running on hardware :)
It’s really simple to set up: https://projectf.io/posts/verilog-sim-verilator-sdl/
This was my biggest shock when first working with FPGAs, while naively using a software mentality. Most everything had to be re-written once the simulations were done.
E.g. we could save power by only sending parts of the display image that change.
VGA is a walk in the park that's sane and easy to understand for beginners. You just need to modulate the 3 primary colors between 0-255 for 8 bit color, and two clock signals, and the monitor will display a picture.
VGA is also very simple to debug since as long as there's some signal on the color and clock lines, the monitor will display something allowing you visually see what's wrong, while on digital, if some part of the handshake failed, you get no picture on the monitor so there's no way to figure out what's wrong without specialized knowledge and equipment.
A CRT is basically it's own oscilloscope of the signals on the VGA cable making development a joy.
HDMI 2.0 requires bidirectional communication between source and sink through SCDC registers to set parameters such as scramble_enable, clock ratio, and to read status flags such as clock detection, channel lock status, bit error rates etc.
* VGA using a Pmod board (you could also create your own register ladder)
* DVI using the TI TFP410 on the DVI Pmod board
* DVI generated on FPGA with a Verilog TMDS encoder (no IC required)
* SDL simulation on a PC
DVI is a subset of HDMI, so works on modern TVs and monitors.
You can find the source on GitHub: https://github.com/projf/projf-explore/tree/main/graphics/fp...
In sending the entire frame with every refresh you get pixel addressing "for free", since you just send the data for each pixel sequentially in a predefined order. If you only wanted to update a single pixel, you would need to effectively send an instruction saying "set pixel x to rgb: a, b, c" or whatever, including both the pixel colour values and the pixel address. You'd also need some sort of edge detection for when a pixel is supposed to change which adds a delay.
This is fine for one pixel, but if every pixel on the screen changes at once then suddenly you are going to be sending a hell of a lot of instructions that not only contain the colour values as in the "old crt style" method, but also the address of every individual pixel too, which will then have to be decoded by the screen-side hardware.
All in all, you'll be using a lot more bandwidth and will need a much faster clock to do all of that in the same period of time. In the old school way, you just have a pixel clock that matches the pixel rate and some serdes for serialisation/deserialisation on each end which imo is considerably simpler.
That solution is far from what we have now, and much more like a serial LCD controller.
* source side, you'd need a shadow buffer as well, and you need double the read BW to detect the difference between previous and the current frame.
All of that is technically achievable, but none of it matter for desktop monitors: the power savings are just too low to matter.
Laptops are a different matter. Many laptop LCD panels already support self-refresh. (Google "Panel Self Refresh")
But that's for cases where the screen is static: the user is staring at the screen, not moving their mouse, the cursor is static. The benefit is not just putting the link but also putting the GPU to sleep.
That's the low hanging fruit. Partial screen update doesn't save a lot more, because you'd need to power up the GPU for that.
DVI, HDMI, DisplayPort or heaven forbid Thunderbolt are a hot mess - to generate a signal out of these without the usage of dedicated chips, you need a ton of logic and parts: output format negotiation, extremely strict timing requirements that completely rule out bitbanging, signal conditioning, specially shielded cables, shielded traces on the circuit board.
[1] https://hackaday.com/2014/06/10/640x480-vga-on-an-arduino/
https://en.wikipedia.org/wiki/Cathode-ray_tube#Construction_...
https://en.wikipedia.org/wiki/Video_Graphics_Array
https://en.wikipedia.org/wiki/Extended_Display_Identificatio...
Because it's extremely simple electronically. It was designed to be simple to work with very slow electronic hardware made of discrete components. So it's basically child's play to generate it with a modern FPGA as there are huge error bars even if you make some small mistakes.
Also blanking areas are still important because at the end of a pixel row there is still some amount of extra electronic stuff happening that is slightly slower than jumping to the next pixel. Even on LCDs or OLEDs.
Even 4K HDR HDMI 2.1 still has something akin to blanking intervals.
What happened to that guy?
Any idea how far he got with this?
I hope I can find time to play with it.
As a pure software guy I'm just mystified and awed by FPGAs and the possibilities of the design.