RIME: resident management environment for the Lattice ECP5 IcePi Zero, synthesized with nosis (no yosys)
Project description
RIME
RIME is the Resident IcePi Management Environment.
It is the resident control plane for the IcePi Zero: a persistent boot image that manages flash, SDRAM, and SD card operations over a UART protocol. The host-side CLI handles build, inspect, install, verify, doctor, janitor, compose, and reload workflows.
The short version:
- Lattice ECP5-25F: 24,288 LUTs, 56 block RAMs, 28 multipliers.
- RIME makes it dependable — safe flash updates with write-unlock gating, verified readback, one CLI for everything.
- Synthesized by nosis, a pure-Python SystemVerilog synthesizer; placed and packed with the OSS CAD Suite toolchain.
- Two firmware images:
| Image | LUTs | BRAMs | Purpose |
|---|---|---|---|
| RIME | ~5,966 (24%) | 0 | Flash + SDRAM service, SD install engine, auto-recovery FSM |
| EMBER | 9,534 (39%) | 2 | Hardware TRNG: 192 ring oscillators, AES-128-CBC, NIST health tests |
RIME includes an app shell with LED heartbeat, SD card read/write, firmware-mediated SD bundle install (sd_install_engine.sv), host-mediated staged install, inline-key write gating on destructive operations, length-prefixed responses with CRC-8 integrity, and a compositor system for stackable FPGA modules with N-way composition. Auto-recovery from SD is wired and silicon-verified (arm → boot → install → verify full cycle). EMBER's entropy subsystem is available as a composable module (EMBER-LITE).
Examples below assume the current working directory is the repository root. Board identity, layout, and toolchain paths resolve through command-line flags, environment variables, or optional local configuration rather than fixed host paths.
Hardware
RIME targets the IcePi Zero board:
| Component | Part | Detail |
|---|---|---|
| FPGA | Lattice ECP5U-25F | 24,288 LUTs, 56 block RAMs, 28 multipliers |
| Package | CABGA256 | 256-ball BGA |
| Flash | Winbond W25Q128 | 16 MB QSPI NOR, 64 KB erase sectors |
| SDRAM | Winbond W9825G6KH | 32 MB SDR, x16, 512 columns, 8192 rows, 4 banks |
| SD slot | microSD | SPI mode, SDHC/SDXC only (SDSC not supported) |
| USB bridge | FTDI FT231X | UART (VCP driver) or JTAG (WinUSB driver) |
| Clock | 50 MHz oscillator | Divided to 25 MHz system clock in fabric |
| I/O | 5 LEDs, 2 buttons | Active-low button[0] is reset |
The upstream schematic uses a generic Micron MT48LC16M16A2P KiCad symbol but the BOM populates a Winbond W9825G6KH (LCSC C62246). Both are pin-compatible 256 Mbit SDRAMs in TSOP-II 54 with identical organization: 8192 rows, 512 columns, 4 banks, 16-bit data. The SDRAM controller addresses the full 32 MB.
SDRAM
The full 32 MB SDRAM is operational. All 13 row address bits are verified functional on silicon, including row-boundary writes.
The install command auto-detects full SDRAM and uses the staged upload path: stream the entire bitstream into SDRAM over UART, then commit to flash at SPI speed with on-board verify. See docs/THROUGHPUT.md for current reference-silicon timings (regenerated by scripts/bench_report.py).
Why RIME Exists
IcePi Zero is a portable FPGA board with flash, SD, and direct host connectivity. RIME exists to turn it from "interesting FPGA hardware" into "a board you can iterate on, deploy to, and recover with confidence":
- rewrite flash safely, gated behind a write-unlock handshake
- verify readback instead of trusting writes blindly
- install from SD through the resident service or via autonomous boot-time recovery
- inspect board state, flash state, and SD state from one coherent interface
- compose multiple hardware modules into a single bitstream from the command line
Who It Is For
- firmware and FPGA iteration on a board that may need repeated updates
- portable or bench workflows where SD-based staging is useful
- setups where you want one operator surface for build, inspect, install, verify, compose, and reload
Less of a fit:
- one-off SRAM loads with no interest in persistence
- generic FPGA bring-up on non-IcePi targets
Resource Footprint
RIME service image
| Resource | Used | Available | Utilization |
|---|---|---|---|
| LUT4 | ~5,966 | 24,288 | 24% |
| DFF | ~3,500 | 24,288 | 14% |
| DP16KD (block RAM) | 0 | 56 | 0% |
| MULT18X18D | 0 | 28 | 0% |
The service provides 27 commands covering flash read/write/erase (with UNLOCK gating), SDRAM read/write/stream/commit/verify, SD card read/write/CRC/install, raw SDRAM word access, app shell identity/uptime, and diagnostics. It enters service mode via the app shell (phase 4 → phase 5).
The boot image includes the SD install engine (sd_install_engine.sv) for firmware-mediated bundle installs and the auto-recovery FSM (auto_recovery.sv) for autonomous SD-to-flash restore on boot.
EMBER — Entropy Measurement and Board-level Environmental Randomness
| Resource | Used | Available | Utilization |
|---|---|---|---|
| LUT4 | 9,534 | 24,288 | 39% |
| DFF | 1,959 | 24,288 | 8% |
| DP16KD (block RAM) | 2 | 56 | 3% |
EMBER is a hardware true random number generator. 192 ring oscillators in three thermally isolated paths (64 per path), majority-voted, Von Neumann debiased, LFSR whitened, then AES-128-CBC conditioned. NIST SP 800-90B health tests run continuously. 60-second thermal warmup.
EMBER is a standalone experiment image. When loaded, it takes 100% of the FPGA.
Compositor Modules
The compositor (icepi/compose.py) combines RIME-I (a RISC-V soft CPU) with up to 16 hardware modules into a single bitstream. Each module declares its resource budget and interfaces in a module.json manifest. The compositor validates that the combined budget fits the ECP5, assigns each module a unique address region (0x30-0x3F), generates the top-level wrapper, and builds through the standard pipeline.
python icepi_helper.py compose anvil cairn scry --clean
Modules that declare a snoop interface requirement (like SCRY) get bus observation ports wired automatically.
Current modules (LUT4 counts from per-module synth_ecp5 -noflatten, refreshed by scripts/verify_manifest_luts.py; integration may shift these by ±15%):
| Module | Type | ~LUTs | Description |
|---|---|---|---|
| RIME-I | CPU | ~4,050 | RV32I base integer (37 instructions + FENCE), multi-cycle, 14 KB BRAM |
| SLAB | Memory | ~1,300/KB | Stackable LUT Allocated Block. 1 KB distributed LUT RAM tile |
| SCRY | Debug | ~1,000 | Circular trace buffer. Passively records CPU bus transactions |
| SIFT | Filter | ~3,200 | 256-bit Bloom filter, 3 hash functions |
| MARK | Security | ~250 | Free-running LFSR sampled on demand. Timing-dependent fingerprint |
| DICE | Compute | ~300 | 256-cycle stochastic multiply/add |
| GLYPH | Crypto | ~500 | GF(2^8) multiply, inverse, exponentiation |
| PACK | Compress | ~500 | RLE compressor with 32-entry output FIFO |
| PARSE | Match | ~500 | 8-state configurable hardware NFA |
| TAPER | Math | ~250 | Saturating add, signed multiply, min/max/abs |
| MOSS | Spatial | ~1,200 | 8x8 Game of Life with toroidal wrapping |
| AUGUR | Probability | ~600 | 4-chain Metropolis-Hastings MCMC sampler |
| ANVIL | Checksum | ~50 | CRC-32 accelerator (IEEE 802.3) |
| LATCH | Timer | ~400 | Watchdog timer + event counter with timestamp |
| HEDGE | Control | ~250 | Token bucket rate limiter |
| EPOCH | Clock | ~450 | Real-time clock synthesizer from 25 MHz sys_clk |
| CAIRN | Stack | ~2,000 | 16-deep 32-bit Forth-style stack machine |
| WEAVE | Serial ALU | ~550 | Bit-serial 32-cycle add/sub/mul, 1-cycle logic |
| FLUX | PID | ~550 | Fixed-point PID controller with anti-windup |
| ORACLE | Interpolator | ~1,800 | 64-entry lookup table with linear interpolation |
| DELTA | Diff | ~500 | Byte-stream XOR differencing engine |
| VIGIL | ECC | ~150 | Hamming(7,4) SEC encoder/decoder |
| GRAIL | Merkle | ~4,000 | 8-leaf CRC-32 Merkle tree hasher |
| SENTRY | Protection | ~400 | Memory protection unit. 4 address ranges with R/W permissions |
| TIDE | Waveform | ~250 | DDS waveform generator. Square/saw/triangle/sine |
| RUNE | Font | ~510 | 8x8 bitmap font renderer. Full printable ASCII (32-126) |
| VAULT | Crypto | ~150 | AES-128 single-round (SubBytes+AddRoundKey, correct FIPS 197 S-box) |
| PRISM | Color | ~100 | RGB to grayscale/min/max/saturation/invert |
| CHORD | Audio | ~570 | 4-voice DDS synthesizer. Square/saw/tri/sine per voice |
| QUILL | Buffer | ~550 | 4-channel 8-byte circular FIFO |
| EMBER-LITE | TRNG | ~124 | 8 ring oscillators (LUT4 primitives), Von Neumann debiased |
| AXIOM | Tokenizer | ~300 | JSON token scanner with nesting depth tracking |
| SIGMA | Checksum | ~50 | Fletcher-16 streaming checksum |
| BLOOM | Bitops | ~30 | Popcount, CLZ, CTZ, bit reverse, parity |
| FORGE | Hash | ~800 | Simplified single-word iterative hash (not a standard SHA-256 digest). Uses correct SHA-256 K constants, Ch, Maj, and Σ functions but processes one 32-bit word per invocation instead of a 512-bit message block — not interoperable with SHA-256 |
| FLOCK | Simulation | ~100 | 4-agent boids with cohesion, separation, and alignment forces |
| MORTAR | Matrix | ~50 | 2x2 signed 8-bit matrix multiply |
| LACE | Address | ~50 | Linear Address from Coordinate Encoding. Z-order bit interleave (2D + 3D) |
| FLIP | Transform | ~200 | Fast Logical Interstitial Permutator. 8x8 and 32x32 bit-matrix transpose |
| APEX | Data structure | ~700 | Asynchronous Priority Evaluation matriX. 16-entry hardware priority queue |
| HALO | Buffer | ~200 | Hardware Assisted Loop Orchestrator. 64-entry ring buffer with watermark |
| HAMMER | Matching | ~250 | Hardware Accelerated Matching and Measurement Engine Register. 256-bit Hamming distance |
| CHURN | Hash | ~300 | Continuous Hash Updating and Rolling Node. 32-byte Rabin-Karp rolling hash |
| HEAT | Profiling | ~300 | Hardware Execution Activity Tracker. 16-page memory access heatmap (snoop) |
| ECHO | Debug | ~300 | Event Capture and Hardware Observer. 16-entry cycle-stamped bus logger (snoop) |
| LOGOS | Math | ~500 | Logarithmic Operations and General Optimization System. Log-domain multiply/divide/sqrt |
| ORBIT | Trig | ~600 | Optimized Rotation and Basic Iteration Toolkit. 20-iteration CORDIC |
| MIRROR | Lookup | ~1,000 | Memory Indexing and Rapid Resolution Object Router. 16-entry masked pseudo-TCAM |
| MOUNT | Crypto | ~2,500 | Modular Operation Utility for Number Theory. 256-bit Montgomery multiplier |
| DIVIDE | Math | ~400 | Direct Integer Variable-length Iterative Division Engine. 32-bit unsigned divide |
| CRANK | Math | ~400 | Cyclic Register Arithmetic Numerical Kernel. 32x32 to 64-bit iterative multiply |
| SIEVE | Bitops | ~700 | Selective Indexed Extract and Variable Embed. Bit-field extract and deposit |
| TALLY | DSP | ~400 | Triggered Accumulating Linear Logic sYnthesizer. 4-channel multiply-accumulate |
| PROOF | Crypto | ~650 | Protected Read-Once Operational Fence. Constant-time 32-byte comparison |
| ETCH | Crypto | ~600 | Encrypted Transform with Cyclic Hashing. XTEA 64-round Feistel block cipher |
| SEED | Crypto | ~500 | Secure Entropy-Enhanced Derivation. FNV-1a nonce generator |
| NOTCH | Control | ~250 | Noise-Opposing Transition and Contact Handler. 8-channel debounce filter |
| PHASE | Control | ~150 | Periodic Hardware Accumulation and Signal Encoder. Quadrature decoder |
| TEMPO | Control | ~250 | Timed Event Measurement and Period Observer. Frequency and period counter |
| CODEC | Codec | ~200 | Compact Ordered Data Encoding/Decoding Coprocessor. Base64 encode/decode |
| RANK | Sort | ~2,400 | Rapid Associative Numerical Keyed sorter. 8-element parallel sorting network |
| TRAP | Debug | ~350 | Triggered Response to Address Predicate. 4-address hardware breakpoint (snoop) |
| GAUGE | Profiling | ~250 | General Aggregated Utilization and Granular Estimator. Bus bandwidth counter (snoop) |
| DEPTH | Debug | ~350 | Dynamic Execution Profile and Thread Height tracker. Stack pointer tracker (snoop) |
| CELL | Spatial | ~700 | Configurable Elementary Local Logic automaton. 64-cell 1D Wolfram cellular automaton |
| SPARK | ML | ~300 | Simple Perceptron with Activation and Responsive Kernel. 8-input single-layer perceptron |
| HAZE | Procgen | ~150 | Hardware Approximation of Zoned Entropy. 2D gradient noise via hash and bilinear interpolation |
| CLASP | Sync | ~50 | Contested Lock with Atomic Set Protocol. 8-slot atomic test-and-set mutex |
| GPIO | I/O | ~150 | General Purpose Input/Output. 16 software-driven pins with direction and edge detect |
| PULSE | I/O | ~250 | Programmable Unified Logic for Signal Emission. 4-channel 16-bit PWM generator |
| SPOKE | I/O | ~100 | Serial Peripheral Output/Kernel Exchange. SPI master with internal loopback (no external pins) |
| WIRE | I/O | ~50 | Wired Interconnect for Register Exchange. I2C master FSM with internal loopback (no external pins) |
| FERRY | DMA | ~1,500 | Fast External Register Relay Engine. 16-word internal scratchpad copy engine |
| ARBOR | IRQ | ~150 | Arbitrated Routing for Board-level Ordered Requests. 16-source priority interrupt controller |
| PYLON | IPC | ~250 | Paired Yield-Linked Output Node. 8-deep 32-bit FIFO mailbox |
| DRUM | Sequencer | ~1,000 | Driven Register Utility for Microsequencing. 16-instruction programmable sequencer |
RIME-I is a multi-cycle RV32I soft CPU. 5-state FSM, 38 instructions (37 base integer + FENCE). Memory is 14 KB of block RAM (7 DP16KD) with firmware initialized via initial blocks and $readmemh. The RV32I assembler (gen_firmware.py) covers the full ISA.
See modules/ for manifests, HDL sources, and test scripts.
Quick Start
Minimum host requirements:
- Python 3.11 or newer
- nosis installed into the same Python (
python -m nosismust resolve) — the synthesizer - OSS CAD Suite providing
nextpnr-ecp5,ecppack, andopenFPGALoader
Install the package (runtime deps only):
python -m pip install -e .
For development (pytest, hypothesis, ruff, mypy, pre-commit):
python -m pip install -e ".[dev]"
pre-commit install
First Success Path
python icepi_helper.py status
python icepi_helper.py doctor
python icepi_helper.py build rime --clean
python icepi_helper.py install rime --slot boot --reload --build
Board Modes
The IcePi Zero shares one USB-C port between UART (serial communication) and JTAG (bitstream loading). Only one mode is active at a time.
- UART mode: all RIME commands. Normal operating mode.
- JTAG mode:
openFPGALoaderfor SRAM loads and QSPI bootstrap. Only needed for first-time setup, disaster recovery, or standalone experiment bitstreams.
python icepi_admin.py uart # switch to UART
python icepi_admin.py jtag # switch to JTAG
The UART-only workflow avoids driver switching entirely.
Service Mode
RIME boots to an app shell that responds to HELLO, PING, UPTIME, and IDENTITY. Service commands are gated until ENTER_SERVICE switches to service mode. EXIT_SERVICE returns to app mode.
Destructive operations (ERASE64, PROGRAM16) carry an inline 4-byte RIME key prefix (0x52 0x49 0x4D 0x45) in every request payload. There is no stateful unlock or expiry timer. The legacy UNLOCK command (0x03) is retained as a benign no-op for backwards compatibility.
See PROTOCOL.md for the full command specification.
Update Paths
Full SDRAM-Staged Update (default)
Stream the entire bitstream into SDRAM in 4 KB blocks over UART, then commit to flash at SPI speed with on-board verify. See docs/THROUGHPUT.md for current measured timings.
Chunked SDRAM Update (fallback)
For boards with row-aliased SDRAM, repeatedly stream 1 KB to SDRAM word 0 and commit that chunk to flash. Slower than full staging but robust against SDRAM row failures. upload_bitstream() automatically falls back to this path if the staged path fails.
SD Bundle Install
Stage a RIME bundle to raw SD space, then sd-install <lba> installs it through the resident service. The install engine (sd_install_engine.sv) parses the bundle header, erases flash sectors, and programs from SD — all on-board.
Auto-Recovery
The boot image includes an auto-recovery FSM that checks SD LBA 1 for an armed control block on every boot. If armed, it initializes SD, reads the control block, validates the checksum, and installs the staged bundle to flash. Any UART byte during recovery aborts to the app shell (the operator is never locked out).
python icepi_helper.py sd-auto-arm rime --slot boot --build
Bootstrap / Recovery
python icepi_admin.py flash-qspi rime
JTAG path. For when the resident service is absent or suspect.
Flash Layout
config/icepi-layout.json defines named flash slots, aliases, and bundle geometry.
| Slot | Offset | Size | Purpose |
|---|---|---|---|
boot |
0x000000 | 1 MB | Resident boot image |
backup |
0x100000 | 1 MB | Secondary firmware slot |
staging |
0x200000 | 1 MB | Alternate firmware slot |
scratch |
0x300000 | 13 MB | Data, manifests, experiments |
Composing Modules
# Validate resource budget without building
python icepi_helper.py compose anvil cairn scry --validate-only
# Compose and build
python icepi_helper.py compose anvil cairn scry --clean
The compositor assigns each module an address region (0x30-0x3F) and generates a complete SoC wrapper with RIME-I, BRAM, UART, and N module instantiations.
Configuration
Board selection and tool resolution come from command-line flags, environment variables, or config/board.local.json.
| Variable | Purpose |
|---|---|
ICEPI_ROOT |
Repository root override |
ICEPI_LAYOUT_FILE |
Path to flash layout JSON |
ICEPI_BOARD_CONFIG |
Path to local board identity JSON |
ICEPI_USB_SERIAL |
USB serial number filter |
ICEPI_BAUD |
UART baud rate (default 115200) |
ICEPI_OSS_CAD_ROOT |
OSS CAD Suite root directory |
ICEPI_PYTHON |
Python interpreter override |
Build System
nosis → nextpnr-ecp5 → ecppack. The build system auto-detects module dependencies by scanning instantiated names in project sources. Per-project build.json provides custom nextpnr flags.
python icepi_helper.py build --list
python icepi_helper.py build rime --clean
python icepi_helper.py build ember --clean
Testing
RIME has two regression suites that cover different failure domains and neither subsumes the other.
Board regression (UART):
python tests/regression.py # single CRC through every subsystem
python tests/regression.py --verbose # show per-step accumulator detail
Threads a CRC-32 accumulator through: app shell round-trip, protocol core, DEBUG state verification, CRC-8 frame integrity, JEDEC 3x, flash write/verify, stale-read regression, deployed-bitstream match, SDRAM round-trip, row isolation, 64-chunk fill, flash/SDRAM crosstalk, bank isolation, row boundary, 9-bit column stress, row errata scan, stream 16/64/32K, timeout recovery, 1024-byte chunked commit with host and on-board verify, SD read/write/CRC, SD_INSTALL bundle round-trip, auto-recovery arm/disarm, SD_CRC32_RANGE, staged upload with wipe_slot, address clamping, SET_WATCHDOG, inline-key rejection, 8-byte error frames, RAW_WRITE row boundary, throughput bench, and janitor cleanup. Output: one hex value (CHAIN:XXXXXXXX). If any subsystem fails, the chain diverges and the value is wrong.
Themed composition regressions (JTAG):
Seven themed composition images, each with a verification firmware that exercises every module in the image and prints labelled readbacks for host-side comparison against a Python predictor.
| Image | Modules | Regression |
|---|---|---|
| compute (Gauntlet) | divide, crank, sieve, tally, taper, weave, bloom, mortar, logos, flip, lace, orbit, mount, glyph | gauntlet.py |
| crypto (Seal) | vault, forge, vigil, grail, anvil, sigma, emberlite, mark, sentry, churn, hammer, proof, etch, seed | seal.py |
| control (Servo) | tide, chord, flux, oracle, epoch, latch, hedge, notch, phase, tempo | servo.py |
| data (Ingest) | apex, axiom, cairn, codec, delta, halo, mirror, pack, parse, quill, rank, rune, sift | ingest.py |
| observe (Profile) | scry, echo, heat, epoch, latch, prism, trap, gauge, depth | profile.py |
| sim (Evolve) | augur, cell, dice, emberlite, epoch, flock, flux, haze, moss, oracle, spark | evolve.py |
| peripheral | clasp, gpio, pulse, spoke, wire, ferry, arbor, pylon, drum | peripheral.py |
python modules/compositions/gauntlet.py --gen-only # generate firmware + sim
To run on silicon, generate the composition top.sv via icepi.compose.compose() then build with icepi_helper.py build compositions --clean and flash via JTAG.
Module torture sweep (offline, no hardware):
python modules/torture_sweep.py
Discovers every test_*_torture.py under modules/, calls each gen(), and verifies the firmware fits in the 1024-word BRAM. Any new module with a torture test is automatically included.
Offline Python tests (no hardware):
pip install -e ".[dev]"
python -m pytest tests/ --ignore=tests/regression.py -q
ruff check .
Repository Surface
| File | Role |
|---|---|
icepi_helper.py |
CLI entry point: 40+ subcommands |
icepi/commands/ |
Command implementations |
icepi_admin.py |
Admin wrapper: build, flash, driver switching, reload |
icepi/flash_service.py |
Board discovery, UART transport, protocol client |
icepi/compose.py |
N-way compositor: resource budgeting, top.sv generation |
icepi/build.py |
FPGA build pipeline: source collection, synthesis, P&R |
icepi/layout.py |
Flash layout loading, image planning |
icepi/bundle.py |
RIME bundle format: parse, validate, build |
icepi/sd.py |
SD partitions, FAT32 filesystem, auto-recovery control |
icepi/models.py |
Domain model dataclasses |
icepi/tools.py |
Path resolution, tool discovery, utilities |
PROTOCOL.md |
UART protocol specification |
config/icepi-layout.json |
Flash slot map, aliases, bundle geometry |
firmware/images/rime/top.sv |
RIME top module (clock, reset, SDRAM, SPI, SD, install engine, auto-recovery) |
firmware/images/rime/rime_service.sv |
UART protocol FSM (27 commands) |
firmware/images/rime/rime_service_defs.svh |
Extracted command IDs, capability flags, FSM state encodings |
firmware/images/ember/top.sv |
EMBER: hardware TRNG |
firmware/core/flash_spi_master.sv |
QSPI flash transaction engine |
firmware/core/sdram_controller.sv |
SDR SDRAM controller |
firmware/core/sdram_bridge.sv |
16-byte bulk SDRAM bridge |
firmware/core/sd_spi_master.sv |
SD card SPI engine |
firmware/core/sd_install_engine.sv |
Firmware-mediated SD bundle installer |
firmware/core/auto_recovery.sv |
Boot-time auto-recovery FSM |
modules/rime-i/rime_i_core.sv |
RV32I CPU core |
modules/rime-i/gen_firmware.py |
RV32I assembler (38 instructions) |
modules/rime-i/test_isa.py |
ISA torture test (37 instructions, single hash) |
modules/compositor_template.py |
Shared top.sv generator for module tests |
modules/compositor_test.py |
Shared test runner (build, JTAG flash, serial read) |
modules/torture_gen.py |
Hash-based torture test generator framework |
tests/regression.py |
Board regression: CRC chain through every subsystem |
modules/compositions/{gauntlet,seal,servo,ingest,profile,evolve,peripheral}.py |
Seven themed composition silicon regressions |
modules/compositions/verify.py |
Host verifier: build, flash, read, compare against Python predictor |
modules/torture_sweep.py |
Offline torture sweep over all module tests |
tests/test_protocol.py |
Offline protocol tests (MockSerial + Hypothesis) |
tests/test_*.py |
Offline Python tests |
Architecture
See docs/ARCHITECTURE.md for the layer diagram, data paths, FSM state table, bus muxing, module bus protocol, and test suite overview.
Contributing
See CONTRIBUTING.md for setup, module creation, register interface, and code style.
Known Limitations
- The
$signed() >>> shamtoperator has a history of miscompiling for ECP5. The CPU uses explicit sign-extension masks instead. - BRAM INITVAL propagation via
$readmemhworks forinitialblocks but not for runtime loading. Theecpbrampatch path exists for firmware-only updates without re-synthesis.
The (* keep *) annotations in top.sv and rime_service.sv are retained as a backstop against constant-folding of signals involved in combinational cycles; the primary fix was removing svc_reset_req and wdog_reset from the rst wire (which created a feedback cycle through rime_service). CRC-8 frame integrity is computed inside the service FSM to avoid a similar feedback cycle through the top-level inject chain.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rime_ecp5-0.1.0.tar.gz.
File metadata
- Download URL: rime_ecp5-0.1.0.tar.gz
- Upload date:
- Size: 1.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
faa2b456f289792ac0f9740515496bbc62f0ecd1876bd87301c32b39691b9a7c
|
|
| MD5 |
a9f30b322ecd77e1d530295e1b4d53f1
|
|
| BLAKE2b-256 |
904438128a647242e7a2241e9da9da40ce93611db21aaee42e5e811449987235
|
File details
Details for the file rime_ecp5-0.1.0-py3-none-any.whl.
File metadata
- Download URL: rime_ecp5-0.1.0-py3-none-any.whl
- Upload date:
- Size: 2.1 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
99336592b3786561a781cb7fb5a09cb563bfb6aea5a11cc876c333c8c90a9227
|
|
| MD5 |
6be3e015e79f98218446a762c16e9c2e
|
|
| BLAKE2b-256 |
aae501b2f67a8b0fda33f4243f00d48f5e8005051c427a07717632cc38e2a791
|