Monday, 27 November 2023

MiSTer, Verilator and YGV608 video timing block

MiSTer developer JimmyStones has created a framework and a template project around the Verilator simulation tool. To say it's a game-changer is an understatement!

In a nutshell, you wrap your top-level core module in another (System)Verilog module that interfaces to the simulation framework that emulates most of the functionality of the MiSTer framework. Then you run a script to convert your Verilog code to cpp, and subsequently build the MiSTer Verilator project.

That gives you an executable that comprises a UI with simulation controls and video output! Yes - you can see your core's video output almost in real time (if you're not running a trace). And you can also capture a trace of the simulation and load it up into gtkwave to inspect signals. All without touching silicon! The only caveat is that gtkwave freezes quite a bit with large trace files.

As for MiSTer itself, it has a framework that wraps around your core to provide input, ROM download, SDRAM, SD card, video and other functions. This is essentially what the Verilator framework replaces. It provides dipswitch settings, input mapping, video scaling & rotation, video & audio processing and more.

It's been a bit of a ramp-up but quite fun to start working with these tools. After creating a project from JimmyStone's MiSTer template project and then merging in his Verilator template project, I had a NamcoND1 project that simulated showing 'noise' on the video (as it was designed to do) and showed the same on actual MiSTer hardware!

Next step was to start on the NamcoND1 design proper. The obvious starting point was the video timing core for the YGV608. So I created a top-level YGV608 component in Verilog, and a number of sub-components as per the block diagram in the YV608 datasheet. One of those sub-components is the CRT Timing block. Another requisite block was the CPU interface, which contains the on-chip registers for configuration.

I wrote, simulated, debugged and verified the horizontal timing generator in Verilator and gtkwave. To get the timing parameters for Namco Classics I started (again) to RE the ROM (I couldn't successfully load my old RE from a decade-old version of IDAPro). Fortunately one of the very first things it does is configure all the CRT Timing Registers in the YGV608, so I wrote down all the values and hard-coded them into my registers at reset.

Once that looked OK, I did the same for the vertical timing. When vertical looked OK, I did a quick hack to output the border in RED, and the active display area in GREEN. Here is where I had to make some changes to the Verilator template project to handle YGV608 video output (as opposed to Centipede video output). But it wasn't too long before I saw this...

YGV608 Video Timing output in Verilator

Next step was to build for MiSTer. Because I had changed the top-level of my core, I had to do some minor changes to the wrapper that instantiates my core but otherwise there were no changes required for the MiSTer project, except to change the parameters for the main PLL to output the correct frequency for the YGV608.

And this is what I saw when I ran it from the MiSTer menu for the very first time...

YGV608 Video Timing output on MiSTer hardware

Yes the borders are different but the Verilator video output is (still) a bit of a hack from my side of things and I haven't yet taken the time to fully understand the video output configuration properly. The point is, I think the MiSTer borders are correct!

So that has been a very successful first exercise in getting something simulated and then running on MiSTer hardware! I'm very impressed with Verilator and JimmyStone's framework. There are some limitations - for example it can't handle SystemVerilog aliases - but the productivity gains are astronomical.

So what's next? I need to load the YGV608 graphics ROMs into the Verilator project. They're loaded into MiSTer SDRAM via the framework, and there's a similar mechanism in the Verilator template project. However there's (currently) no emulation of the SDRAM so you need to instantiate some memory in the top-level Verilog wrapper to store the downloaded data and essentially replace the SDRAM. I've added the ROM file to the Verilator project, and can see it downloading on gtkwave, so now all I need to do (in theory) is instantiate some simple DPRAM for the simulation.

Once that's done I can quickly hack the YGV608 core to simply dump (some of) the ROM contents to the active display area...

No comments:

Post a Comment