
Borg is a tiny GPU built around a RISC-V SoC (TinyQV). It renders a 10-frame animation of a rotating RGB triangle, fully self-contained in firmware — no host-side rendering needed.
The firmware is structured like a Vulkan application:
const borg_vertex_t vertices[3] = {
{ .pos = { ... }, .color = { FP16_ONE, FP16_ZERO, FP16_ZERO } }, // red
{ .pos = { ... }, .color = { FP16_ZERO, FP16_ONE, FP16_ZERO } }, // green
{ .pos = { ... }, .color = { FP16_ZERO, FP16_ZERO, FP16_ONE } }, // blue
};
int main() {
borg_init(vert_borg, ..., frag_borg, ...);
for (int frame = 0; frame < 10; frame++) {
borg_set_angle(&draw, angle);
borg_cmd_draw(&draw, vertices, frame);
borg_present(frame);
angle = fp16_add(angle, FP16_36DEG);
}
}
In ./fpga:
make triangle
This programs the firmware, boots the FPGA, waits for all 10 frames to render, then reads back 10 PPM images (triangle_00.ppm through triangle_09.ppm).
| # | Input | Output | Bidirectional |
|---|---|---|---|
| 0 | Interrupt 0 | UART TX | Flash CS |
| 1 | Interrupt 1 | UART RTS | SD0 |
| 2 | SD1 | ||
| 3 | SCK | ||
| 4 | SD2 | ||
| 5 | SD3 | ||
| 6 | Debug UART TX | RAM A CS | |
| 7 | UART RX | Debug signal / PWM | RAM B CS / PWM |