A RISC-V microcomputer emulator running CP/M Neo in the browser
An 8-bit inspired RISC-V computer emulator, designed to give a simple environment for learning about computer architecture and operating systems.
Vemu simulates a self-contained 32-bit hardware environment inside the browser.
Vemu emulates a custom 32-bit RISC-V microcomputer:
| Component | Specification |
|---|---|
| CPU | RV32I + M extension for hardware multiplication and division |
| RAM | 64 KB, byte-addressable (0x0000–0xFEFF) |
| Memory-mapped I/O | Top page 0xFF00–0xFFFF |
| Storage | 2 MB CP/M Neo disk |
| Flash (XIP) | Read-only flash window at 0x10000 extending over the loaded disk image; kernel/CCP run in place |
| System clock | Selectable 50 kHz – 1 MHz |
| Addr | Name | Access | Description |
|---|---|---|---|
0xFF00 |
DISK_BUFFER |
R/W | 512-byte sector buffer; each read/write advances the buffer offset |
0xFF04 |
DISK_SECTOR |
W | Select sector: [15] write flag, [14:0] LBA |
0xFF08 |
KBD_DATA |
R | Pop next key, [6:0] ASCII (bit 7 cleared) |
0xFF0C |
KBD_STATUS |
R | [0] = 1 if a key is ready; read does not consume |
0xFF10 |
DSP_DATA |
W | Write a character to the text display |
0xFF14 |
CLK_KHZ |
R | System clock frequency in kHz |
0xFF18 |
TIMER_CSTR |
R/W | Timer control/status (see bit table) |
0xFF1C |
TIMER_CNTR |
R/W | 16-bit timer counter (writes set it) |
0xFF20 |
DMA_SAR |
R/W | DMA source address (16-bit) |
0xFF24 |
DMA_DAR |
R/W | DMA destination address (16-bit) |
0xFF28 |
DMA_WCR |
R/W | DMA word count (16-bit) |
0xFF2C |
DMA_CSTR |
R/W | DMA control (write) / status (read) |
Write:
| Bit | Field | Description |
|---|---|---|
| 0 | START | Write 1 toggles the transfer on/off |
| 1 | STREAM | 1 = stream mode (bus-locked) |
| 2 | SRC_INC | Auto-increment source address |
| 3 | DST_INC | Auto-increment destination address |
| 5:4 | STEP | 00 8-bit, 01 16-bit, 10 32-bit |
| 7:6 | — | Ignored |
Read: [0] RUNNING (1 = busy), [1]–[5] readback of STREAM/SRC_INC/DST_INC/STEP, [7:6] reads 0.
STEP 10 and 11 both decode to 32-bit; writing 11 reads back as 10.
| Bit | Field | Description |
|---|---|---|
| 0 | EN | 1 = Enabled |
| 1 | MOD | 0 = Continuous, 1 = One-shot |
| 2 | OVF | 1 = Overflow; write 1 to clear |
| 5:4 | PRESCALE | 00 1, 01 8, 10 64, 11 256 |
| 3 | — | — |
| 7:6 | — | — |
| Bit | Field | Description |
|---|---|---|
| 15 | WRITE | 1 = Write buffer to disk, 0 = load sector into buffer |
| 14:0 | LBA | Physical sector number |
Vemu boots CP/M Neo, a CP/M-inspited operating system.
The Disk/Flash selector chooses the boot medium; switching reboot the machine with it, and each mode keeps its own state.
- Disk (default): the kernel and CCP are copied from disk into RAM at boot. Read-write storage — save programs normally.
- Flash: the loaded disk image is exposed as read-only flash and the kernel/CCP run in place from the flash window starting at
0x10000. The window covers the disk image itself, so it grows/shrinks with the loaded image. The flash image is read-only — programs can't modify the running code — while the disk controller still handles file/volume storage independently.
Vemu bundles demo programs built on the CP/M Neo SDK: PICO, a screen-based text editor, plus MBROT and SNAKE.
PICO is a full-screen text editor built on the CP/M Neo SDK. It can open, edit, and save text files.
PICO <FILENAME> Open an existing file (or start a new one)
PICO C <FILENAME> Create a new empty file (errors if it already exists)
PICO Start an empty, unnamed buffer
| Keys | Action |
|---|---|
| Ctrl+O | Open a file (prompts for the filename) |
| Ctrl+S | Save the file. Prompts Save as: for an unnamed buffer, otherwise writes to the current filename |
| Ctrl+Q | Quit. Prompts to save if the buffer has unsaved changes |
| Arrow keys | Move the cursor up, down, left, or right |
| Any other key | Insert or type text |
For local development, run.sh serves the site on port 8080. Its optional build step recompiles the emulator core first:
./run.sh # serve http://localhost:8080
./run.sh build # rebuild the core, then servecpm-neo/bootloader.bin, cpm-neo/disk.img, and cpm-neo/disk-xip.img are
produced by the CP/M Neo build (the
XIP image is sysgen new --xip's output, renamed):
git clone https://github.com/Mazin-O3/cpm-neo
cd cpm-neo
make -C sysgen
./sysgen/build/sysgen new --disk-size=2048K --platform=vemu
cp sysgen/build/bootloader.bin sysgen/build/disk.img /path/to/vemu/cpm-neo/
./sysgen/build/sysgen new --disk-size=2048K --platform=vemu --xip
cp sysgen/build/disk.img /path/to/vemu/cpm-neo/disk-xip.imgVemu is distributed under the terms of the open-source MIT.