{"id":26758543,"url":"https://github.com/wdevore/rangerrisc-risc-v","last_synced_at":"2026-02-06T02:02:51.303Z","repository":{"id":75435811,"uuid":"581710774","full_name":"wdevore/RangerRisc-RISC-V","owner":"wdevore","description":"This is the debug variant of RangerRisc a RISC-V Multicycle RV32I variant.","archived":false,"fork":false,"pushed_at":"2022-12-26T22:17:13.000Z","size":23120,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-28T16:36:05.369Z","etag":null,"topics":["risc-v"],"latest_commit_sha":null,"homepage":"","language":"SystemVerilog","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/wdevore.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}},"created_at":"2022-12-24T03:16:12.000Z","updated_at":"2025-03-17T01:07:51.000Z","dependencies_parsed_at":"2023-02-23T16:45:52.957Z","dependency_job_id":null,"html_url":"https://github.com/wdevore/RangerRisc-RISC-V","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/wdevore/RangerRisc-RISC-V","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wdevore%2FRangerRisc-RISC-V","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wdevore%2FRangerRisc-RISC-V/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wdevore%2FRangerRisc-RISC-V/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wdevore%2FRangerRisc-RISC-V/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wdevore","download_url":"https://codeload.github.com/wdevore/RangerRisc-RISC-V/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wdevore%2FRangerRisc-RISC-V/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265453622,"owners_count":23768173,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["risc-v"],"created_at":"2025-03-28T16:29:28.151Z","updated_at":"2026-02-06T02:02:51.210Z","avatar_url":"https://github.com/wdevore.png","language":"SystemVerilog","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RangerRisc-RISC-V Multicyle\nRanger Risc softcore SystemVerilog RISC-V Multicycle variant.\n\nThe video shows BlackiceEdge hosting RangerRisc. The softcore RISC-V assembly program is counting and displaying on the 7seg. The blade shows the interrupt count and the Blue LED flicking shows the interrupt signal.\n\nOn the upper PMOD is the Interrupt signal coming from the Pico RP2040. On the lower PMOD is the UART channel for talking to a UART client (written in Go.)\n\n![hardware mov](risc_interrupts.gif)\n\nThe repo contains two variations: a *debug* version with controls signals routed out via UART and a *release* version that is trimmed down.\n\n**NOTE** This repo does **NOT** contain the *Simulation* code base. For simulation please see the [RISC-V-RV32I-MultiCycle](https://github.com/wdevore/RISC-V-RV32I-MultiCycle) repo under the *simulation* folder.\n\n## Directories\n- *assemblies* Contains all assembly code examples. Note most of them are *more* compatible with the 48Hz clock.\n- *debug* Contains the *debug* variant which contains a bunch of exposed signals for displaying.\n- *definitions* has common definitions\n- *modules* has all the common modules\n- *rams* generally contains only a single *code.ram* file\n- *release* This the stripped down variant and can run about 1.23MHz faster\n- *tools* contains two Go programs: an Assembler and UART client\n  - gen-instr (i.e. the Assembler)\n    - The assembly.json is configured for *release* variant.\n  - go-uart (the UART client for talking with fpga)\n\nSometimes you need to re-upload the bitstream image for it to boot correctly.\n\n## Debug version\nThe **Top** module contains a huge amount of code to support transmitting data from the fpga to a UART client. This includes UART, blade port and 7seg port.\n\nIt consumes about 3500 LUTs!:\n\n```\nInfo: Max frequency for clock 'clk$SB_IO_IN_$glb_clk': 47.49 MHz (PASS at 18.00 MHz)\nInfo: Max frequency for clock    'cpu_clock_$glb_clk': 19.19 MHz (PASS at 18.00 MHz)\n\nInfo: Device utilisation:\nInfo: \t         ICESTORM_LC:  3501/ 7680    45%\nInfo: \t        ICESTORM_RAM:    12/   32    37%\nInfo: \t               SB_IO:    23/  256     8%\nInfo: \t               SB_GB:     7/    8    87%\nInfo: \t        ICESTORM_PLL:     1/    2    50%\nInfo: \t         SB_WARMBOOT:     0/    1     0%\n```\n\n## Release version\nThis version is trimmed down. It doesn't have UART or exposed core signals. This saves **905** LUTs.\n\nAlso, a slightly higher clock can be used resulting in a boost of: **1.23MHz**. Note however, the makefile is still configured for 18MHz.\n\nThis version is also *hardcoded* to **18MHz**, hence, make sure your assembly code compensates for the higher clock. For example, any counting code should have some form of delay added.\n\n```\nInfo: Max frequency for clock 'clk$SB_IO_IN_$glb_clk': 197.75 MHz (PASS at 18.00 MHz)\nInfo: Max frequency for clock    'clk_18MHz_$glb_clk': 20.42 MHz (PASS at 18.00 MHz)\n\nInfo: Device utilisation:\nInfo: \t         ICESTORM_LC:  2596/ 7680    33%\nInfo: \t        ICESTORM_RAM:    12/   32    37%\nInfo: \t               SB_IO:    21/  256     8%\nInfo: \t               SB_GB:     7/    8    87%\nInfo: \t        ICESTORM_PLL:     1/    2    50%\nInfo: \t         SB_WARMBOOT:     0/    1     0%\n```\n\n# Terminal #1 minicom\nThis terminal is for connecting to the Pico using:\n\n```minicom -b 115200 -o -D /dev/ttyUSB0```\n\nOnce the Pico has been programmed with the control software via *build/io_uart*. You can use \"h\" or \"l\" for manual high/low control of the active pin. Or you can use \"t\" to toggle the active pin.\n\n![minicom](pico_io_control.png)\n\n# Terminal #2 go-uart\nThis terminal is for talking to the fpga's UART module. The two most commonly used commands are \"s\" and \"c\" or \"k\" (48Hz) or \"l\" (18MHz).\n\n![Go program control](go-uart.png)\n\n# Hardware rig\nUp top is the Pico for generating an interrupt on Pin 15 which is routed to the left pmod.\n\nOn the right pmod is the UART connections for talking between the fpga and the Go control program.\n\n![hardware](hardware_rig.jpg)\n\n# Logical Layout diagram\n![Diagram](RV32I_RangerRisc.png)\n\n# Core FSM\n![FSM Diagram](RV32I_FSM.png)\n\n# CSRs\n![CSR Diagram](CSR_Diagrams.png)\n\n# Test harness during Synthesis\n![CSR Diagram](Synth_test_harness.png)\n\n# Usage\nSuper high level usage guide:\n\n1) Program the Pico and connect the Pico's UART and\n2) Connect Pin 15 to the left fpga pmod\n3) Connect second USB-UART to fpga via pmods (on the right).\n4) Connect fpga to USB. The BlackiceEdge shows up as ttyACM0\n5) cd into RangerRisc-RISC-V\u003c...\u003e and run ```make```\n6) go to the *go-uart* bin directory and run ```go run .```\n7) use the commands to direct the fpga top module\n8) use minicom to direct the pico to toggle a pin to generate interrupts.\n\n## Assembly\nNihongo/Hardware/Risc-v/TopReference/risc-v-asm-manual.pdf\n\n### Notes:\nThe instructions themselves need to have the offset specified in byte-address form, however, the memory addresses can be defined as byte-address using \"$\" or word-address using \"@\".\n\nIf an instruction references an address that is defined in word-address form then it is converted to byte-address form even if it refers to a word-address. This is per the RISC-V ISA specs.\n\n## Setup and running programs\nYou need to do several things in order for the cpu to run code on the FPGA. Open 3 terminals: one for the assembler, another for HDL toolchain and another for the go UART client.\n\n1) Create or modify your ```\u003cfile\u003e.asm``` program and make sure you update the assembler's assembly.json file. The assemlby files are typically stored in the *assemblies* under the application root folder.\n2) Open a terminal and *cd* to *\\\u003cpath to\\\u003e/tools/gen-instr/assembler* folder\n3) Run the assembler ```go run . \u003cfile\u003e.asm``` to produce the *code.ram* file that is embedded into the fpga bit stream via the ```$readmemh``` command.\n4) Open another terminal and *cd* to *\\\u003cpath to\\\u003e/Synthesis/ranger_risc* folder and run ```make```.\n5) Open another terminal and *cd* to *\\\u003cpath to\\\u003e/tools/go-uart* and run ```go run .```\n\n### Assembler json\nupdate the *inputPath* and *inputFile* keys to the .asm file you are targeting. Also, update the *RamDir* to direct the assembled ram code to a destination.\n\nThen run ```go run .``` or ```go run . \u003cfile\u003e.asm```\n\n### Example assembly code\n```\nMain: @\n    lw x1, 0x28(x0)     // 0x28 BA = 0x0A WA\n    ebreak              // Stop\n\nData: @00A\n    d: DEADBEEF         // data to load\n\nRVector: @0C0           // 0x300 BA = 0xC0 WA\n    @: Main             // Reset vector\n```\n\nThe *RVector*'s value is what is defined in the makefile entry:\n\n```RESET_BOOT_VECTOR = \"32'h00000300\" # @0C0```\n\nAfter running the assembler you get a helpful yet extra *code.out* for cross reference:\n\n```\n@00000000 02802083 lw x1, 0x28(x0)     // 0x28 BA = 0x0A WA\n@00000001 00100073 ebreak              // Stop\n@0000000A DEADBEEF d: DEADBEEF         // data to load\n@000000C0 00000000 @: Main             // Reset vector\n```\n\n# Makefile\nThere are two ways we can setup a macro for injecting dynamic definitions in verilog code. I prefer #1.\n\n1) Create a file, for example, **definitions.sv** with a ``` `define ROM_PATH \"../rams/\"```\n2) Or, add a variable and macro definition to a makefile:\n```Makefile\nCODE_PATH = \"\\\"../rams/\\\"\"\n...\n\t-DRAMROM_PATH=${CODE_PATH} \\\n```\nThen define a **localparam** as: ```localparam RomPath = `RAMROM_PATH;``` some place you need it, for example, memory.sv.\n\nHere is an example:\n```Makefile\nCODE_PATH = \"\\\"../rams/\\\"\"\n\n.PHONY: all\n\nall: build route upload\n\ncompile: build route\n\nbuild: ${MODULES_FILES} ${PINS_CONSTRAINTS}\n\t@echo \"##### Building...\"\n\t${ICESTORM_TOOLCHAIN}/bin/yosys -p ${YOSYS_COMMAND} \\\n\t-l ${BUILD_BIN}/yo.log \\\n\t-q \\\n\t-defer \\\n\t-DRESET_VECTOR=${RESET_BOOT_VECTOR} \\\n\t-DRAMROM_PATH=${CODE_PATH} \\\n\t-DUSE_ROM \\\n\t-DDEBUG_MODE \\\n\t${MODULES_FILES}\n```\n\n# PLLs\nFolknology has an excellent page for describing how to use the \u003cspan style=\"color: blue;\"\u003e*simple mode*\u003c/span\u003e capability of the lattice iCE40 fpga: https://github.com/mystorm-org/BlackIce-II/wiki/PLLs\n\nWe need an ~18MHz clock because nextpnr has trouble routing anything faster. So we use *icepll* to generate our control parameters:\n\n```icepll -i 25 - o 18```\n\nThis will generate:\n```\nF_PLLIN:    25.000 MHz (given)\nF_PLLOUT:   18.000 MHz (requested)\nF_PLLOUT:   17.969 MHz (achieved)\n\nFEEDBACK: SIMPLE\nF_PFD:   25.000 MHz\nF_VCO:  575.000 MHz\n\nDIVR:  0 (4'b0000)\nDIVF: 22 (7'b0010110)\nDIVQ:  5 (3'b101)\n\nFILTER_RANGE: 2 (3'b010)\n```\n\nHowever, *icepll* can also generate example code too:\n\n```icepll -i 25 -o 18 -m -f pll.v```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwdevore%2Frangerrisc-risc-v","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwdevore%2Frangerrisc-risc-v","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwdevore%2Frangerrisc-risc-v/lists"}