gateware

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 2b9227d768755b5e22ea411875f50c4f3a33fa12
parent 4fb8276d11d648b69cd75c91efb908fd5e868c0b
Author: Brian Swetland <swetland@frotz.net>
Date:   Wed, 21 Nov 2018 12:59:37 -0800

testbench: add vga frame extractor

It's pretty simple-minded, expecting that "clk" is the pixel clock
and that "vga_frame" will be asserted on the first pixel of a frame
and that frames must be FRAME_W x FRAME_H pixels presented with
vga_{hsync,vsync,red,grn,blu}

Diffstat:
Msrc/testbench.cpp | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 76 insertions(+), 2 deletions(-)

diff --git a/src/testbench.cpp b/src/testbench.cpp @@ -75,6 +75,68 @@ void loadmem(const char *fn) { } } +#ifdef VGA +#define FRAME_W 800 +#define FRAME_H 524 +#define FRAME_TICKS (FRAME_W * FRAME_H) +#define FRAME_BYTES (FRAME_W * FRAME_H * 3) + +static unsigned vga_ticks = 0; +static unsigned vga_frames = 0; +static unsigned char vga_data[2][FRAME_BYTES]; +static unsigned vga_active; + +static int vga_tick(int hs, int vs, int fr, int red, int grn, int blu) { + if (fr) { + //fprintf(stderr, "VGA: frame=%u active=%u ticks=%u\n", + // vga_frames, vga_active, vga_ticks); + if (vga_ticks < FRAME_TICKS) { + fprintf(stderr, "VGA: frame too small: %u ticks\n", vga_ticks); + } else if (vga_ticks > FRAME_TICKS) { + fprintf(stderr, "VGA: frame too large: %u ticks\n", vga_ticks); + } else if (memcmp(vga_data[vga_active], vga_data[!vga_active], FRAME_BYTES)) { + char tmp[256]; + sprintf(tmp, "frame%04d.ppm", vga_frames); + int fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) { + fprintf(stderr, "VGA: cannot write '%s'\n", tmp); + } else { + sprintf(tmp, "P6\n%u %u 15\n", FRAME_W, FRAME_H); + write(fd, tmp, strlen(tmp)); + write(fd, vga_data[vga_active], FRAME_BYTES); + close(fd); + } + vga_active = !vga_active; + } else { + //fprintf(stderr, "VGA: frame %u did not change\n", vga_frames); + } + vga_ticks = 0; + vga_frames++; + if (vga_frames == 5) { + return -1; + } + } + if (vga_ticks < FRAME_TICKS) { + unsigned char* pixel = vga_data[vga_active] + vga_ticks * 3; + if (hs == 0) { + pixel[0] = 0xf; + pixel[1] = 0x8; + pixel[2] = 0x0; + } else if (vs == 0) { + pixel[0] = 0xf; + pixel[1] = 0x0; + pixel[2] = 0xf; + } else { + pixel[0] = red; + pixel[1] = grn; + pixel[2] = blu; + } + } + vga_ticks++; + return 0; +} +#endif + #ifdef TRACE static vluint64_t now = 0; @@ -144,15 +206,27 @@ int main(int argc, char **argv) { tfp->dump(now); now += 10; #endif - testbench->clk = !testbench->clk; while (!Verilated::gotFinish()) { + testbench->clk = 1; + testbench->eval(); +#ifdef TRACE + tfp->dump(now); + now += 5; +#endif +#ifdef VGA + if (vga_tick(testbench->vga_hsync, testbench->vga_vsync, + testbench->vga_frame, testbench->vga_red, + testbench->vga_grn, testbench->vga_blu)) { + break; + } +#endif + testbench->clk = 0; testbench->eval(); #ifdef TRACE tfp->dump(now); now += 5; #endif - testbench->clk = !testbench->clk; } #ifdef TRACE tfp->close();