Skip to content

Memory Map

The system has an internal 32-bit address space. This space is carved up as follows:

31-24 23-20 19-00
Segment Function Data

The reason is, this system being a baremetal retro machine is likely to never have a crazy amount of RAM where we would want 2GB or more of contiguous space. So the address space can be carved up to make things a little more logical and easier for the developer. This includes remapping things like physical memory cards on the Turbo Bus to a specific segment. This makes future expansion (hopefully) more elegant.

Layout

The list below is a bit of a hodgepodge of full allocation and current hardware allocation, but gives hopefully an idea of how this is intended to work.

Note that Turbo Bus is a 24-bit bus, so the addresses include the Device and Data and maps nicely to physically devices.

Segments:
  Main Memory (Segment 00):
    Base Memory:
      Low RAM (SRAM), 112K:                         00 0 00000..00 0 1BFFF
      (Reserved)                                    00 0 1C000..00 0 7FFFF
      Kernel ROM Mirror (512k):                     00 0 80000..00 0 FFFFF
    Extended (Bus) RAM (Device 0 Mirror)            00 1 00000..00 1 FFFFF
  System RAM (Segment 01):
    Kernel Vars, Traps & Vectors (DPRAM), 2K:
    Kernel Vars: (DPRAM), 1K:                       01 0 00000..01 0 003FF
    System Traps & Vectors (DPRAM), 1K:             01 0 00400..01 0 007FF
    User Vars (DPRAM), 1K                           01 2 00000..00 2 003FF
    Stack RAM (SRAM), 16K:                          01 F FC000..01 F FFFFF
  Banked RAM (Segment 02):
    Bank RAM 0 (Device 2 Mirror), 256k              02 0 00000..02 0 3FFFF
    Bank RAM 1..14 (Reserved)                       02 1 00000..02 E FFFFF
    Page Registers:                                 02 F 00000..02 F FFFFF
      Bank 0 Page Register (Device 2 Mirror):       02 F 00000..02 F 00001
      Bank 0 Num Pages (Device 2 Mirror):           02 F 00002..02 F 00003
      Bank 0 Page Size (Device 2 Mirror):           02 F 00005..02 F 00008
  ROM (Segment 03):
    Kernel ROM (Device 1 Mirror):                   03 0 00000..03 0 FFFFF
    (Reserved, Option ROMs)
    Game Cart ROM (Device 15 Mirror):               03 F 00000..03 F FFFFF
  8-bit Turbo Bus (Segment F0):                                  
    Device 0 (Bus RAM, Up to 1MB w/ A19):           F0 0 00000..F0 0 FFFFF
    Device 1 (Kernel ROM, Up to 1MB, w/ A19):       F0 1 00000..F0 1 FFFFF
    Device 2 (MCU):                                 F0 2 00000..F0 2 FFFFF
      Banked Smart RAM (256k):                      F0 2 00000..F0 2 3FFFF
      System Registers (128k):                      F0 2 40000..F0 2 5FFFF
      Smart RAM Registers (128k)                    F0 2 60000..F0 2 7FFFF
    Device 3 (Video/VERA/User):                     F0 3 00000..F0 3 FFFFF
    Device 4 (User):                                F0 4 00000..F0 4 FFFFF
    ...
    Device 7 (Cartridge ROM):                       F0 7 00000..F0 7 FFFFF
    Device 8-15 (Not Exposed On Bus):               F0 8 00000..F0 F FFFFF

  Internal FPGA System Bus (Segment FE):
    FemtoRV USB UART Data, 4B:                      FE 0 00000..FE 0 00003
    FemtoRV USB UART Control, 4B:                   FE 0 00004..FE 0 00007
  Global System Registers (Segment FF):
    System Setup (DFFs):                            FF 0 00000..FF 0 003FF
      CPU Clock Divisor:                            FF 0 00000..FF 0 00000          
      Bus Clock Divisor:                            FF 0 00001..FF 0 00001
      Turbo Bus Wait States, 8 bytes:               FF 0 00010..FF 0 00017
      Turbo Bus Read-Cache Enable, 1 byte:          FF 0 TBD
      Turbo Bus Read-Cache Invalidate, 1 byte:      FF 0 TBD
    MCU System Registers (Device 2 Mirror), 128K:   FF 1 00000..FF 1 1FFFF

In the current hardware proposal, SRAM, DPRAM and LUTs run at CPU speed which means the remapped devices, of course, run at the speed of the Turbo Bus.

System Setup Registers

These are DFFs (flip-flops) attached to LUTs and are desired over EBRs since they can be async. This is important for things like the bus wait-states. The bus controller needs to access these without artificial delay.

Note also that the setup registers are not meant to be used dynamically (like for dynamic frequency clocking on a modern system). The CPU divisor may cause a stall on a change though is otherwise generally safe.

The bus divisor and wait states should only be changed while the bus is not being used. Meaning code that changes these values should be running in Low RAM.

The cache invalidation and enable registers can be triggered at any time from anywhere since it just controls the cache flush. This will still obviously cause a delay in immediate cache misses of course.

The cache enable register may either be a non-zero value or might be a device bitmask. The latter allows for per device caching so the user has control over how to use the cache.

Wait States

At present, wait states are a single value per device and indicate how many cycles to wait whenever a wait is required for a bus transaction (e.g. settling time, SRAM recovery/hold, etc.). Future improvements could be wait states for specific steps. SRAM, for instance, has different wait states for different parts of a read or write transaction.

Wait states are based on the bus clock (not the CPU clock).

It is wise not to change wait states while the bus is active or at least do not change the wait-state for the active device on the bus.

DPRAM/EBR

EBR blocks are optionally dual port memory blocks which total up to 15kb. Proposed allocation is:

  • User Vars (1K, 2 EBRs): Roughly equivalent to the "zero page" on a 6502
  • Kernel Vars (1K, 2 EBRs): Roughly equivalent to the "zero page" on a 6502, dedicated to the kernel
  • System Traps / Vectors (1K, 2 EBRs): IRQ jump table and default IRQ handler code
  • Bus Cache (22 EBRs): 4-way 8kb instruction cache for bus (specifically RAM and ROM)
    • 16 Entry Victim Cache (880 Flip-Flops) helps handle cache contention (assumes available FFs/LUTs)

Total EBR Usage: 28 / 30 (1k remaining)

Device Remapping

To make it easier for the user/developer and allow for at least attempting future expansion and upgrades, some things are remapped. Notably in the minimal config, the MCU has a window of banked Smart RAM. If a user wants to add a bigger RAM card, they could place it at Bank RAM 0. This will come from the system config which will be stored in MCU flash or on the MCU SD Card.

How this works with the current FPGA (Upduino) in terms of LUT usage remains TBD.

Game Cartridge

Game Cartridge ROM is available in the ROM segment. At present it is remapped from special Device 7 on the TurboBus. This is so future cartridges on other busses could be used though in practice the Game Cart ROM area is special. If a cartridge is available here, it will cause the system to boot direct to the cartridge (though this can be disabled via boot settings in the MCU). This can be automagic given cartridges will need to provide a "CART" header as the first 4 bytes of the memory area. If the system finds this, and is set to auto-boot to carts, it will boot into the cart by jumping to the remapped address (0x03F00000).