Skip to content

4. Understand the MiSTer core

sy2002 edited this page Jul 9, 2022 · 21 revisions

Before you start porting, you should first understand how the MiSTer core works for an end-user. In the optimal case, you own a MiSTer and can actually experiment and play with the core. But this is not mandatory. There are also a lot of YouTube videos about many cores. It is important that you get an overall "feeling" for the core and how it behaves. And even more important: About the disk mounting, ROM loading and configuration options that are available to the end user, because this helps you to understand a lot of things, including MiSTer's core configuration string (CONF_STR). The core configuration string is used to generate the menu shown to the end-user (similar to M2M's OSM) and therefore CONF_STR is paramount to understanding many of the parameters, wiring and default values that the core needs to run.

So you have played enough with the core and/or watched some YouTube videos and you feel you have understood the "end user view" of the MiSTer core you want to port to MEGA65? Great - then let's start to dive in at the deep end.

Understand MiSTer and the MiSTer framework

MiSTer has an excellent documentation for developers where you can learn how to port a core TO MiSTer. What we want to achieve here is learn how to port a core FROM MiSTer. Nevertheless your MiSTer2MEGA65 porting experience will be much smoother if you start from first principles. Please read the following chapters of the MiSTer documentation before you proceeed:

  1. Porting Cores
  2. Core Configuration String
  3. Overview of emu module
  4. sys - hps_io
  5. sys - video_freak
  6. sys - video_mixer
  7. sys - arcade_video

Don't worry if you are not understanding everything written in these seven chapters. It is more important that you have a high-level overview of the concepts and that you have seen most of them now at least once and that you know where to look in case you get stuck at a later stage of your porting adventure.

Step #1 - Examine the structure of the core

Now it is time to examine the structure of the actual core you want to port. As an easy start, we suggest to go to the core's GitHub repository and browse the source code there. You might want to use the MiSTer Wiki as a starting point to find the repository of the core: Scroll down a bit and you will see the list of cores on the right side.

MiSTer is a very structured project, so we can rely on certain files and folders to be always present:

  • rtl folder: Contains the actual core. Many MiSTer cores are enhanced versions of MiST cores or other cores. Therefore the MiSTer team encapsulates everything related to the core itself inside the rtl folder.

  • sys folder: This is the MiSTer framework that provides similar services than the MiSTer2MEGA65 framework.

  • *.sv file in the root folder that is named like the core: This is your starting point for any porting effort, because you will be able to study the "wiring" of the MiSTer core: How does MiSTer actually connect different parts of the core with its own framework? Which kind of glue logic is necessary? What options does MiSTer offer to the users? ROMs? Drives? (Hint: The *.sv file is actually not the top-file used to synthesize a MiSTer core. Instead, sys/sys_top.v is used. But this does not matter for our porting purposes.)

Step #2 - Learn more about the environment the core needs to run

The MiSTer framework is similar to our M2M framework in being a hardware abstraction layer. The core lives in its own bubble while not being aware of the fact, that it is not connected to the "real" hardware that it expects.

What we need to find out as a next step is: What is the environment that the core needs to run? Examples of "environment" are:

  • Clocking and clock speed
  • RAM
  • ROM
  • Keyboard
  • Other peripherals (drives, joysticks, mouses, paddles, ...)

Additionally, you need to learn how the video and audio output of the core work and what settings, switches and parameters can and need to be configured.

To learn everything about the environment, open the *.sv file in the root folder of the core and start looking for the instantiation of the "actual" core. The *.sv file usually contains a ton of glue logic and instantiations of all the hardware needed to support the core. Additionally it contains stuff that is needed for the MiSTer framework. We need to ignore all of this for now and instead locate the right module, the "Actual core". Here are four examples:

Example core Root *.sv file Actual core module
Apple II Apple-II.sv apple2_top
Arkanoid Arcade-Arkanoid.sv Arkanoid
Commodore 64 c64.sv fpga64_sid_iec
GameBoy Gameboy.sv gb

We will continue to use these four example throughout this chapter.

Please note that it will be this "actual" core (instead of the emu module from MiSTer's root *.sv file) that you will instantiate at a later stage inside M2M's main.vhd. We will get into the details in chapter 6. Basic wiring.

Instead of continuing to talk about the *.sv file, in the following sections we use emu module instead.

Clocking and clock speed

MiSTer's system clock runs at 50 MHz. M2M's system clock runs at 100 MHz. Therefore both frameworks need to use PLLs or MMCMs to generate the clock or clocks needed by the retro core.

Most MiSTer cores instantiate a clocking module called pll within the emu module. Start by having a look at this instantiation to answer the following questions:

  • How many clocks are being generated?
  • What are the names of the clock signals used inside emu?
  • Which clocks are used for the core itself?
  • Which clocks are used for video output, RAM, other components?
  • Is there a mechanism for any dynamic clock reconfiguration?

There is no recipe for answering these questions other than to read the source code in the emu module. It is important that you take a thorough look at CONF_STR while doing so because some of the menu items that the end user can choose from are impacting the clock handling.

Last but not least, you need to learn more about the actual speed of the clock(s). Please be aware that very often it is crucial for compatibility and timing that you try to hit the actual clock speed "down to the Hertz" (or at least very close). In most MiSTer cores, the folder with the file(s) where you can learn more is called rtl/pll. Also, in most MiSTer cores the name of the clock signal generated in the emu module's pll section already gives you a first hint of what is going on.

Here are some examples to make this more tangible:

Example: Apple II

pll pll
(
  .refclk(CLK_50M),
  .rst(0),
  .outclk_0(CLK_VIDEO),
  .outclk_1(clk_sys)
);

We learn that there are two clocks: A video clock CLK_VIDEO and the actual core clock clk_sys. Since the names are not suggesting any actual clock speed, let's have a look at rtl/pll/pll_0002.v:

.number_of_clocks(2),
.output_clock_frequency0("57.272727 MHz"),
.phase_shift0("0 ps"),
.duty_cycle0(50),
.output_clock_frequency1("14.318181 MHz"),
.phase_shift1("0 ps"),
.duty_cycle1(50),

So we have two clocks that are not phase-shifted and that have the standard duty cycle of 50% high and 50% low. The video clock has the "odd" frequency of 57.272727 MHz and the core has the "odd" frequency of 14.318181 MHz.

When you encounter something like this, it often makes sense to check, if one clock is a multiple of the other. In our case the video clock is 4x the core clock.

Now search in the emu module where CLK_VIDEO is being used (other than outputting it to the MiSTer framework): You will notice that there is a clock divider which drives the clock enable signal for the pixel clock: ce_pix. And this clock divider either divides the video clock by 8 or by 4 depending on status[16]. As you might already know after having read MiSTer's documentation on the Core Configuration String, status[16] is a bit that reflects the end-user's choice in the MiSTer on-screen-menu. 16 decimal is 0x10 hexadecimal and the CONF_STR configuration reveals that we need to look for the letter G to find out the appropriate option and therefore the meaning:

"OG,Pixel Clock,Double,Normal;",

At this moment, we can only guess what this means and make a mental note to revert back, as soon as we look at the video output.

Now search for clk_sys in the emu module as this is the speed of the actual retro core. To our surprise we find this:

apple2_top apple2_top
(
  .CLK_14M(clk_sys),
  .CLK_50M(CLK_50M),

So for some reason, the "actual" core needs a 50 MHz clock signal (which happens to be MiSTer's framework clock speed) additionally to the 14.318181 MHz core speed. (The latter one is clear and does not need further investigation.)

This is a good moment to dive one level deeper and open rtl/apple2_top.vhd and check what's going on regarding the 50 MHz signal. You will find that there is an instantiation of something called superserial. If you are an Apple II pro and already know what this is: Great! Otherwise Wikipedia comes to the rescue: So this is a serial interface for the Apple II. The open question that remains is: Does superserial genuinely needs 50 MHz - or - does it need 50 MHz because the MiSTer framework runs at 50 MHz and therefore some interface logic between superserial and some MiSTer framework components which run at 50 MHz exists. In the first case we are fine and in the latter case we need to make a mental note that additional glue logic or other mechanisms (other than just providing a 50 MHz clock) might be needed to support superserial on MiSTer2MEGA.

To answer this question: Let's open the file rtl/ssc/super_serial_card.v and search for CLK_50M. We find this code segment:

// 14.31818
// 50 MHz / 27 = 1.852 MHz
always @(posedge CLK_50M)
begin
        if(RESET)
                CLK_6551 <= 5'd0;
        else
                case(CLK_6551)
                5'd26:
                        CLK_6551 <= 5'd0;
                default:
                        CLK_6551 <= CLK_6551 + 1'b1;
                endcase
end

We can derive two hints from this code segment:

  1. There seems to be a chip called 6551
  2. 50 MHz / 27 = 1.852 MHz

Searching the web for 6551 datasheet for example reveals this data sheet. We learn that the 6551 is an asynchroneous communication interface adapter from Commodore's MOS Technology and that the 6551 prefers to run at 1.8432 MHz. Close enough to the 1.852 MHz, so all good: superserial genuinely needs the 50 MHz to generate this 6551 clock signal so there is no MiSTer framework specific reason. We will be able to support this in M2M without any additional tricks.

Example: Arkanoid

pll pll
(
  .refclk(CLK_50M),
  .rst(0),
  .outclk_0(CLK_48M),
  .reconfig_to_pll(reconfig_to_pll),
  .reconfig_from_pll(reconfig_from_pll),
  .locked(locked)
);

Without the need to even look at the files in rtl/pll we can deduce the following from this module instantiation:

  • The core only needs one clock, which seems to be running at 48 MHz.
  • There seems to be a dynamic reconfiguration of the clock speed.

A best practice is to start looking inside the emu module, where the clock is being used. In the Arkanoid example we quickly find two points of interest:

  • The instantiation of arcade_video: We make a mental note that the pixel clock is derived from the 48 MHz clock. (There are more details to that; for example as you can see in the MiSTer documentation arcade_video also uses a clock enable signal called ce_pix, which is being generated in emu.)
  • The actual Arkanoid core uses the CLK_48M input.

While browsing through the instantiation of the Arkanoid core, you will notice that some signals seem to control overclocking. Also in the core's CONF_STR there is an option to switch the game speed between "Native" and "60Hz Adjust". So these are great hints what the purpose of the two signals reconfig_to_pll and reconfig_from_pll might be used for.

Searching through the emu module using the search string reconfig_to_pll quickly brings us to the instatiation of pll_cfg and the comment that is written there says it all:

//Reconfigure PLL to apply an ~1.4% overclock to Arkanoid to bring video timings in spec for 60Hz VSync

So it looks like we're having an anti-flicker mechanism so that the game looks smooth on 60 Hz screen setups: This is for example needed for smooth HDMI outputs, because most HDMI screens are not supporting "odd" vertical sync frequencies.

In the last step, we open rtl/pll/pll_0002.v and by looking at the line

.output_clock_frequency0("48.000000 MHz"),

we confirm, that the clock frequency is actually 48.0 MHz. We need the exact frequency later in our porting process, for example for defining the M2M constant CORE_CLK_SPEED in M2M's globals.vhd.

Example: Commodore 64

pll pll
(
  .refclk(CLK_50M),
  .outclk_0(clk48),
  .outclk_1(clk64),
  .outclk_2(clk_sys),
  .reconfig_to_pll(reconfig_to_pll),
  .reconfig_from_pll(reconfig_from_pll),
  .locked(pll_locked)
);

So we have three different clocks plus the ability to reconfigure the clock speed. Let's start to investigate the latter feature by looking at CONF_STR. This line within the configuration string shows us, that the core can be switched between PAL and NTSC:

"P1O2,Video Standard,PAL,NTSC;",

Codebase64 explains us that the PAL master clock in a C64 runs at 17.734475 MHz and a NTSC master clock runs at 14.31818 MHz This is already a string hint why dynamic clock reconfigration might be used in the C64 core. Let's confirm this and look where the reconfig_to_pll is being used. We quickly find out that there is a MiSTer framework component called pll_cfg that allows the dynamic reconfiguration of the PLL. And there, we see that the emu module's cfg_write signal that is wired to pll_cfg's mgmt_write input.

To understand when and how the PLL is being reconfigured so that we understand better what frequencies are used by the C64 core, let's search for cfg_write in the emu module's source code: We find a big

always @(posedge CLK_50M) begin

section and within this section we see a lot of hints referring to NTSC, so we can consider our therory as confirmed, that the two modes PAL and NTSC are one of maybe many possible reasons why we have dynamic PLL reconfiguration.

Looking at other entries in CONF_STR we find this:

  "oEF,Turbo mode,Off,C128,Smart;",
  "d6oGH,Turbo speed,2x,3x,4x;",

So there seems to be a "Turbo mode", which is also confirmed when we look at the fpga64_sid_iec fpga64 instantiation which refers to the status flags controled by the CONF_STR menu:

.turbo_mode({status[47] & ~disk_access, status[46]}),
.turbo_speed(status[49:48]),

The question is: Are there additional clocks needed for the turbo mode? The CONF_STR documentation tells us, that when o is used as a lower-case letter, E means 46 and F means 47. So since the 2-bit turbo mode flag is set by using status[46] and status[47] we just need to check: Where else are these status flags used? A search in the emu module reveals: Nowhere else. So we can ignore the turbo mode for now in the context of clocking.

Now, we need to learn more about clk48, clk64 and clk_sys:

  • As the name might suggest, clk_sys is the "actual" core's clock: You will see this when you search for clk_sys in the emu module source code. You will also notice that it drives a large number of components such as the tape drive, the IEC disk drive, the cartridge emulation, the RAM Expansion Unit (REU) and the mouse.

  • The only use of clk48 is to drive the Yamaha OPL based Sound Expander, which is controled by the CONF_STR entry "P1OC,Sound Expander,Disabled,OPL2;",.

  • clk64 is used to drive the pixel clock:

    assign CLK_VIDEO = clk64;

    Additionally it is used by MiSTer's sdram component.

Example: Game Boy

Learnings and best practices around clocking

  • Always look in the emu module where the clock signals are used. By doing so, you will sometimes find additional features or quirks of the core.

  • Locking at the clock signal can quickly turn into a huge rabbit hole: Make sure that you focus on the above-mentioned main-questions at this point in time.

  • The Arkanoid and C64 examples show: Some cores have complex clocking set-ups including dynamic frequency reconfiguration. The best practice is: Choose a simple "default" configuration, for example for Arkanoid without the flicker-fix and for the C64 choose PAL and ignore NTSC for getting started (or the other way round). Ignore any "Turbo mode" and other "artificial" and "non-retro" clock speeds and modes. The message is: It is already complex enough to get a first vital sign from your core while porting. So why bother supporting each and every bell and whistle? Focus is the key to success; you can always add more features later.

  • This "focus" best practice is also true for any fancy peripherals such as the Apple II "Super Serial Card" or the C64 OPL based "SFX Sound Expander": It does not harm to do your first steps without supporting all thinkable and unthinkable peripherals.

  • You might have noticed, that the core clock and the video clock (often referred to as pixel clock) are often linked to each other, sometimes via multiples of the speed and sometimes by using a clock divider to drive a clock enable signal. Therefore, to understand the clocking, you need to understand what a "pixel clock" actually is. Here is a good article that explains it. A pixel clocks is also often referred to as "dot clock". Here is another good article about it.

RAM and ROM

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

Video output

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

Audio output

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

Settings, switches and parameters

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

Keyboard

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

Other peripherals (drives, joysticks, mouses, paddles, ...)

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO

@TODO TODO TODO TODO TODO TODO TODO TODO