Skip to content

Phase 9: iCE40 FPGA synthesis, UART top level and timing - #4

Merged
deaneeth merged 2 commits into
mainfrom
feat/phase-9-fpga
Oct 27, 2026
Merged

deaneeth merged 2 commits into
mainfrom
feat/phase-9-fpga

Conversation

@deaneeth

Copy link
Copy Markdown
Member

Summary

Phase 9: the iCE40UP5K (iCEBreaker) build of the pipelined core.

  • fpga/ice40/fpga_top.sv: the pipeline runs a program preloaded into block RAM and prints console output over a 115200-baud UART. Five LEDs show running, done, pass, fault and overflow.
  • fpga/ice40/build.sh: Yosys with a latch check, then nextpnr. Result: 4958 of 5280 logic cells (93%), 17 of 30 block RAMs, 14.98 MHz post-route against the 12 MHz oscillator. No latches.
  • The programs view shows each program's time on the iCE40, computed from the measured clock.

RTL changes

  • The memories take an optional $readmemh image. Empty (the default) leaves simulation unchanged.
  • The data memory's read-new bypass moved out of mem_sync into a merge after the read register. The values are the same at every edge. Without this the data memory mapped to flip-flops (about 72,000 logic cells). The pipelined core's lockstep and hazard suites pass.
  • Two functions were written in the plain form Yosys reads. Their logic is the same.
  • fpga/prepare_rtl.py converts a copy of the RTL for Yosys, which cannot parse package imports in module headers, typed string parameters, or ANSI function ports. The simulators read the originals.

Verification

  • bash sim/run.sh fpga: the UART is decoded in simulation and carries 6765, and the LEDs report pass. The same test fails on the hello image.
  • Unit, pipelined and single-cycle lockstep suites pass with the new memory.
  • The WASM module rebuilds and passes its 534 checks.
  • Web: 74 unit tests and 17 browser tests pass.

Not done

  • The board is not tested. The UART and LED pins are unconstrained (--pcf-allow-unconstrained), and no bitstream is generated.
  • ECP5 is not done.
  • The FPGA CI workflow (fpga.yml) has not run on GitHub yet.

fpga/ice40/fpga_top.sv runs the 5-stage pipeline on a program preloaded into
block RAM, prints console output over a 115200-baud UART through a FIFO, and
shows the run on five LEDs. fpga/ice40/build.sh runs Yosys (with a latch
check) and nextpnr: 4958 of 5280 logic cells (93%), 17 of 30 block RAMs, and
14.98 MHz post-route against the 12 MHz oscillator. The netlist has no latches.

The memories take an optional $readmemh image (IMEM_INIT, DMEM_INIT); empty
leaves simulation unchanged. The data memory's read-new bypass moved out of
mem_sync into a merge after the read register, which gives the same values
and maps to block RAM (it had mapped to flip-flops, about 72,000 logic cells).
Two functions were written in the plain form Yosys reads. fpga/prepare_rtl.py
converts a copy of the RTL for Yosys, which cannot parse package imports in
module headers, typed string parameters or ANSI function ports.

Checks: `bash sim/run.sh fpga` decodes the UART in simulation and gets 6765 for
fib (and fails on the hello image); unit, pipeline and single-cycle lockstep
suites pass with the new memory; the WASM module rebuilds and passes its 534
checks. The programs view shows time on the iCE40 from the measured clock.
The board itself is not yet tested: the UART and LED pins are unconstrained.
The synthesis step pipes build output through tee into fpga/ice40/build/,
which build.sh creates only after tee has opened its file. tee failed on the
missing directory, and pipefail failed the step after a successful build.
@deaneeth
deaneeth merged commit 3656a51 into main Oct 27, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant