Inspiration
I wanted to strengthen my understanding of digital hardware design by building a graphics accelerator from scratch. I was particularly interested in how GPUs translate drawing commands into pixel operations and how hardware designs can be verified through simulation without a physical FPGA.
What it does
It is a small 2D graphics accelerator built in SystemVerilog. It accepts rectangle commands, clips pixels outside a 64×64 display, and writes RGB332 pixel values into a framebuffer.
A Python renderer reads the simulated framebuffer and converts it into enlarged PNG images, including "CAL HACKS," a checkerboard, and vertical stripes.
How I built it
The hardware is divided into three SystemVerilog modules:
draw_engine: Converts rectangle commands into pixel-write transactions using an FSM and coordinate counters.framebuffer: Stores pixel colors in a 64×64 memory array with synchronous read and write operations.gpu_top: Integrates the drawing engine and framebuffer into a complete system.
I used Icarus Verilog for simulation and cocotb for module-level and system-level verification. Python reference models validate the framebuffer contents, while Pillow converts RGB332 pixel data into RGB888 PNG images.
Challenges I ran into
One of the biggest challenges was understanding clock-cycle timing and synchronization between modules.
Commands are accepted through a valid/ready handshake, framebuffer reads are synchronous, and the final pixel must be written at the same clock edge that transitions the drawing engine into its completion state.
I also had to account for out-of-bounds clipping, zero-sized rectangles, and uninitialized framebuffer memory when designing the verification tests.
Accomplishments that I'm proud of
I implemented and tested a complete graphics pipeline, from receiving a drawing command to generating pixel writes, storing colors in memory, and rendering the resulting image.
My verification environment covers boundary conditions, maximum-size rectangles, reset behavior, command handshaking, and randomized rectangle operations.
I also successfully generated visual outputs entirely from simulated hardware behavior, without requiring a physical FPGA.
What I learned
I strengthened my understanding of SystemVerilog FSMs, counters, synchronous memory, framebuffer addressing, and hardware module integration.
I also gained practical experience with cocotb verification, Python reference models, and debugging clock-cycle timing issues.
Most importantly, I learned how to approach a larger RTL project by breaking it into independently testable modules before integrating them into a complete system.
What's next for 2-D Graphics Accelerator
I plan to expand this project with additional graphics operations, such as DRAW_PIXEL, CLEAR_SCREEN, line rasterization, and sprite rendering.
I also want to develop a reusable cocotb verification framework that can support future RTL projects.
Eventually, I plan to synthesize it for an FPGA, evaluate resource utilization and timing, and implement a display controller capable of showing the framebuffer output in real time.
Built With
- cocotb
- python
- systemverilog
Log in or sign up for Devpost to join the conversation.