{"id":42307726,"url":"https://github.com/popovicu/mrav-cpu","last_synced_at":"2026-05-07T01:47:14.544Z","repository":{"id":317481231,"uuid":"1026909518","full_name":"popovicu/mrav-cpu","owner":"popovicu","description":"A fully automated, custom CPU and software stack for tiny embedded systems","archived":false,"fork":false,"pushed_at":"2025-10-01T06:10:44.000Z","size":96,"stargazers_count":22,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-01T07:11:55.587Z","etag":null,"topics":["cpu","custom","custom-cpu","embedded","fpga","microcontroller","mrav","soft-core"],"latest_commit_sha":null,"homepage":"https://popovicu.com/mrav-cpu","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/popovicu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-26T22:03:57.000Z","updated_at":"2025-10-01T06:10:47.000Z","dependencies_parsed_at":"2025-10-01T07:22:17.441Z","dependency_job_id":null,"html_url":"https://github.com/popovicu/mrav-cpu","commit_stats":null,"previous_names":["popovicu/mrav-cpu"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/popovicu/mrav-cpu","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popovicu%2Fmrav-cpu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popovicu%2Fmrav-cpu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popovicu%2Fmrav-cpu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popovicu%2Fmrav-cpu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/popovicu","download_url":"https://codeload.github.com/popovicu/mrav-cpu/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/popovicu%2Fmrav-cpu/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29167870,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T15:38:29.831Z","status":"ssl_error","status_checked_at":"2026-02-06T15:37:48.592Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpu","custom","custom-cpu","embedded","fpga","microcontroller","mrav","soft-core"],"created_at":"2026-01-27T11:12:46.283Z","updated_at":"2026-02-06T16:01:36.079Z","avatar_url":"https://github.com/popovicu.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# mrav-cpu\n\nMrav is a set of tools and libraries for deploying a tiny, minimal CPU core in a microcontroller-like setting. This monorepo enables you to generate the RTL code, run software simulations, and produce software for Mrav with maximum automation.\n\n\u003e :warning: This project is not ready for any sort of production use at this point.\n\u003e Use with caution for any non-experimental settings, and please file feature requests for any features you'd like to see for production use.\n\u003e At the moment, consider this codebase a proof of concept only. ISA is still subject to change.\n\nThe build system used in this project is Bazel, and it covers everything from RTL generation, to running tests, to building the assembler and assembling the Mrav software itself.\n\n\u003e :bulb: Concepts and implementation from this project will be documented in detail at [this page](https://popovicu.com/mrav-cpu/). This will likely never be a production-ready design, and it is more meant to illustrate some of the computer engineering ideas the author has. For a better ecosystem, consider using lightweight RISC-V cores, such as `rv32e`-based designs.\n\nThe name Mrav comes from the author's native language, Serbian, and it means 'ant'. This CPU is tiny like an ant, but capable of doing work. :)\n\n## Try it in browser first!\n\n\u003e :bulb: NEW: Browser-based playground is available at [mrav-playground.popovicu.com](https://mrav-playground.popovicu.com)! Try Mrav in the browser first to see if you like it, no downloads required.\n\n## Remote dependency\n\nIf you don't want to vendor this code into your codebase, you can depend on this repository as a remote dependency in Bazel by using `bazel_dep` in your `MODULE.bazel`. However, because `mrav-cpu` is currently not tracked in the Bazel registry system, you also need to add an explicit Git pointer to this repository, like this:\n\n```\ngit_override(\n    module_name = \"mrav_cpu\",\n    commit = \"COMMIT_HASH\",\n    remote = \"https://github.com/popovicu/mrav-cpu\",\n)\n```\n\n## ISA\n\nThere are 16 instructions in the Mrav ISA, and each instruction is 16 bits. The core accesses 16-bit memory words only. Address alignment is not enforced for simplicity.\n\nThe highest 4 bits encode the instruction. The next 4 bits encode the destination register. The final 8 bits may either be two source register IDs, an 8-bit immediate value, a source register ID + 4 unused bits, or an immediate 4-bit value + 4 unused bits.\n\n```\n╔════════════════════════════════════════════════════════════════════╗\n║                      MRAV CPU INSTRUCTION SET                      ║\n║                         16 Instructions                            ║\n╠════════════════════════════════════════════════════════════════════╣\n║ ARITHMETIC \u0026 LOGIC                                                 ║\n║  add  rd rs1 rs2    Add rs1 + rs2 → rd                             ║\n║  sub  rd rs1 rs2    Subtract rs1 - rs2 → rd                        ║\n║  xor  rd rs1 rs2    XOR rs1 ^ rs2 → rd                             ║\n║  and  rd rs1 rs2    AND rs1 \u0026 rs2 → rd                             ║\n║  or   rd rs1 rs2    OR rs1 | rs2 → rd                              ║\n║  addi rd imm8       Add immediate rd + imm8 → rd                   ║\n╠════════════════════════════════════════════════════════════════════╣\n║ MEMORY ACCESS                                                      ║\n║  lw   rd rs1        Load word from [rs1] → rd                      ║\n║  sw   rd rs1        Store word rd → [rs1]                          ║\n╠════════════════════════════════════════════════════════════════════╣\n║ IMMEDIATE LOAD                                                     ║\n║  ldhi rd imm8       Load high immediate imm8 → rd[15:8]            ║\n╠════════════════════════════════════════════════════════════════════╣\n║ BRANCHES (absolute addressing)                                     ║\n║  bz   rd imm8       Branch if rd == 0 to address imm8              ║\n║  bnz  rd imm8       Branch if rd != 0 to address imm8              ║\n╠════════════════════════════════════════════════════════════════════╣\n║ JUMPS                                                              ║\n║  jal  rd imm8       Jump to imm8, save return addr → rd            ║\n║  jalr rd rs1        Jump to [rs1], save return addr → rd           ║\n╠════════════════════════════════════════════════════════════════════╣\n║ SHIFTS                                                             ║\n║  shl  rd imm4       Shift left rd \u003c\u003c imm4 → rd                     ║\n║  shr  rd imm4       Shift right (logical) rd \u003e\u003e imm4 → rd          ║\n║  shra rd imm4       Shift right (arithmetic) rd \u003e\u003e imm4 → rd       ║\n╠════════════════════════════════════════════════════════════════════╣\n║ NOTES:                                                             ║\n║  • 16-bit instruction width, 16-bit data width                     ║\n║  • 16 general purpose registers (r0-r15)                           ║\n║  • imm8 = 8-bit immediate, imm4 = 4-bit immediate                  ║\n║  • Branch/jump immediates are absolute addresses                   ║\n╚════════════════════════════════════════════════════════════════════╝\n```\n\nAdditional description is at [the ISA doc](/docs/isa.md)\n\n\u003e :warning: Reiterating from the top: the ISA is subject to change. The author is well aware that this ISA is suboptimal in many ways.\n\n## Interrupts\n\nAt the moment, no interrupts are supported for simplicity, and interaction with the world outside of the core should be done via polling.\n\n## RTL\n\nCurrently, there is only one 'SoC'-like setup, simply called 'small'. To instantiate it, use the `mrav_small` macro:\n\n```\nload(\"//hardware/rtl/soc/build_defs:mrav_small.bzl\", \"mrav_small\")\n\nmrav_small(\n    name = \"soc\",\n    software = \":software.bin\",\n    gpio_verilog = \"//hardware/rtl/soc:gpio.sv\",\n    soc_top = \"//hardware/rtl/soc:soc.sv\",\n)\n```\n\nThis will provide a SystemVerilog bundle file which has no dependencies on anything else. Additionally, the bundle will contain the RAM memory RTL preloaded with the software machine code (`software.bin` file). Therefore, this bundle will be ready to deploy as a soft core in FPGA.\n\nCheck `//deployments/led/BUILD` file for a concrete example. You can build that RTL bundle by running:\n\n```\nbazel build //deployments/led:soc_bundle.sv\n```\n\nFor this concrete reference, this is how the bundle was used in the final SystemVerilog module:\n\n```verilog\nmodule btn_led(\n    input sysclk,\n    input [1:0]btn,   // Button inputs\n    output [1:0]led  // Led outputs\n    );\n    \n    wire [7:0] gpio;\n\n    mrav_soc mrav_soc_i(\n        .clk(sysclk),\n        .rst_n(!btn[1]),\n        .gpio(gpio)\n    );\n\n    assign led[1] = gpio[1];\n    assign led[0] = gpio[0];\n    \nendmodule\n```\n\n## Software\n\nBuilding software for Mrav does not require anything outside the Bazel build system. The tooling is based on Go. When you build a Mrav software target, Bazel will dynamically fetch the Go toolchain, build the necessary tools from this repository (e.g. the assembler) and then use the newly built assembler to produce the final software binary. This should all be transparent to the user.\n\nFor example, you can build a simple example like this:\n\n```\nbazel build //software/examples/adding\n```\n\nFor that particular example, you can also build:\n\n```\nbazel build //software/examples/adding:adding_mrav_state.txt\n```\n\nwhich will build the binary from above, run it in the simulator and then dump the simulated core's state into a text file.\n\n### Libraries\n\nMrav software also supports a simple form of a library system for the assembly files, and the example can be found here:\n\n```\n//software/examples/libraries/BUILD\n```\n\nAn implicit benefit here is that you can easily import someone else's library using Bazel's remote dependency system, like this:\n\n```\nmrav_binary(\n    name = \"program\",\n    srcs = [\n        \"program.mrav\",\n    ],\n    deps = [\n        \"@remote_dep_module//something/foo:bar_lib\",\n    ],\n    out = \"program.bin\",\n)\n```\n\n## Software simulation\n\nThe Go code for Mrav's simulation is in the `//core` Bazel package.\n\nThat package also includes the logic for binary serialization of the core's state. This comes in useful for comparing the core state between different representations, such as Go and Python (used for RTL simulation).\n\nSome simple SoC-like systems are emulated in the `//system` Bazel package and subpackages. `//system/binaries` contains Go binaries for running full system simulations. An example is `memonly` which simply consists of a Mrav core and RAM memory attached to the virtual bus.\n\nGo implementation is very portable, and can run in many contexts, including simply running the core inside a browser simulation, which is explained in more detail below.\n\n## RTL simulation \u0026 equivalence tests\n\nThe RTL is heavily tested, and the simulation is done through Python `cocotb` library which drives `verilator`.\n\n\u003e :warning: You need Verilator in one of the standard locations like `/usr/bin`, `/usr/local/bin`, etc. in order to be able to run Bazel tests.\n\nThe main simulation test is in `hardware/rtl/core_test.py`. To run this test, you can run the following:\n\n```\nbazel test --sandbox_writable_path=$HOME/.cache/ccache --test_output=all //hardware/rtl:core_test\n```\n\nThe writable path flag for `ccache` is needed because of the `cocotb` behavior.\n\nRunning the command above will transparently fetch the Go toolchain, build the assembler, assemble the software, create a simple system with the core + memory attached to the bus, preload the memory with the software, and run the simulation for the system using `verilator`.\n\nA related question arises about confirming the equivalence between the Go simulation and the RTL cycle-for-cycle simulation. There is a dedicated test for that in `testing/equivalence/equivalence_test.py`. To run this, execute the following:\n\n```\nbazel test --sandbox_writable_path=$HOME/.cache/ccache --test_output=all //testing/equivalence:equivalence_test\n```\n\nThis test is similar to the core test described above, but additionally builds and runs the Go simulation, dumping the core state to a binary protobuf representation, which is then diff'ed with the Python representation obtained through cycle-level simulation of the RTL itself.\n\n## Portability \u0026 web browser environment\n\nThe Mrav components and tools are designed to be as portable as possible, and one of the objectives was to enable running in many contexts, including the browser.\n\nThis is one of the major reasons why Go was chosen for the software stack and tooling implementation. Go is extremely well supported by the Bazel build system and enables trivial cross-compilation to different platforms.\n\nAs an example, it is possible to run the Mrav assembler in browser, by building a WASM binary. To run a sample web server for this, execute the following:\n\n```\nbazel run //software/asm/as/browser\n```\n\nThis will start a web server on `localhost:9876`. There should be a page available on http://localhost:9876/as.html with a text field to write a Mrav program and assemble it to machine code (the output will be in hex).\n\nOther tools from the Mrav suite can similarly be ported to the browser, like the system simulation. This can be particularly useful for educational purposes.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopovicu%2Fmrav-cpu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpopovicu%2Fmrav-cpu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpopovicu%2Fmrav-cpu/lists"}