Skip to content

gsmecher/mr.scrub

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mr. Scrub

An open-source, ECC-based internal scrubber for Xilinx UltraScale FPGAs.

Mr. Scrub is a small RISC-V soft core (Minimax, ~2k LUTs) that reads configuration frames through ICAP, uses the FRAME_ECCE3 primitive to detect upsets, and corrects single-bit errors in place. It is designed to be dropped into a larger FPGA design as a TMR'd sub-module.

This code was developed and deployed on Vivado 2023.2, though the open-source release has been re-targeted to Vivado 2025.1 for portability. No simulation harness (just a GUI launcher) or top-level RTL is included here -- this is an "over-the-fence" release.

You are welcome to contact me (gsmecher@threespeedlogic.com) with questions.

Repository layout

Makefile          Top-level build: firmware + TMR'd EDIF

rtl/
  scrubber.vhd    Top-level: BRAMs, ICAPE3, FRAME_ECCE3, streaming FIFO, testbench
  minimax.v       RVC-optimized RISC-V core (https://github.com/gsmecher/minimax)

src/
  scrubber.c      Main loop: ECC decode, keyhole command dispatch, upset notify
  hw.c            ICAP driver primitives
  util.S          Hand-tuned assembly (tx_stream, popcount, ctz, deinter4, ...)
  microcode.S     Minimax microcode ROM (linked into the firmware image)
  scrubber.h      Register map and function prototypes
  crt0.S          Startup + BSS/data relocation
  bare.ld         Linker script (matches the BRAM layout in scrubber.vhd)

tcl/
  export_edif.tcl Out-of-context synthesis -> EDIF
  update_mmi.xslt Splits the generated MMI for three TMR'd BRAM copies
  scrubber_tb.tcl Simulation launcher

bin/
  apply_tmr.py    SpyDrNet-TMR voter insertion
  bin2mem         .bin -> .mem converter

spydrnet/         BYU SpyDrNet (git submodule)
spydrnet-tmr/     BYU SpyDrNet-TMR (git submodule)

Dependencies

  • Vivado: 2025.1
  • Python. SpyDrNet and SpyDrNet-TMR are vendored as git submodules; fetch them after cloning with git submodule update --init.
  • Saxon-B (saxonb-xslt) for MMI transformation.

Building

From the repo root:

make
make simgui
make clean

The default target produces the two artifacts you integrate into a parent FPGA project:

  • scrubber_tmr.edif: triplicated netlist; add to your project as a source.
  • scrubber.mem: firmware image; used downstream by updatemem to patch the post-P&R bitstream without re-running synthesis.

Integration

The default make output gives you two artifacts to drop into a parent FPGA project; everything downstream of that is design- and board-specific, and the Makefile deliberately stops there. This section sketches the full integration flow so you can script it yourself.

1. Instantiate the scrubber in your parent project. Add scrubber_tmr.edif as a synthesis source so the triplicated netlist is linked in, and instantiate the scrubber entity (from rtl/scrubber.vhd) at the point in your hierarchy where you want it. Wire the control, alert-stream, and flash ports to your host and configuration flash.

2. Place and route as usual. Vivado emits a .bit and, with write_mem_info, a .mmi describing the layout of BRAMs containing memory-initialization data.

3. Patch the firmware into the bitstream with updatemem. Because the scrubber's ROM is triplicated, the MMI lists it as a single MemoryArray with three BRAM children; updatemem needs to see it as three separate arrays. tcl/update_mmi.xslt performs that split:

saxonb-xslt -xsl:tcl/update_mmi.xslt \
    -s:parent_project.mmi \
    -o:patched.mmi \
    instpath=<path/to/scrubber_rom/xpm_memory_base_inst> \
    part=xcku060-ffva1517-1-c

instpath is the hierarchical path to the scrubber's xpm_memory_base_inst ROM as it appears in your parent project's synthesized hierarchy.

Then invoke updatemem with one -data/-proc pair per TMR copy:

updatemem -force -meminfo patched.mmi \
    -bit parent_project.bit -out patched.bit \
    -data scrubber.mem -proc <instpath>-1 \
    -data scrubber.mem -proc <instpath>-2 \
    -data scrubber.mem -proc <instpath>-3

The patched bitstream contains the updated firmware without re-running synthesis or P&R. Generate a flash image (.mcs) from it with write_cfgmem in whatever geometry your board expects.

Target device

The shipped RTL targets the Kintex UltraScale KU060 (xcku060-ffva1517-1-c). Porting to another UltraScale part requires:

  • Updating PART in the Makefile.
  • Updating the IDCODE check in scrubber.c (currently 0x03919093 for KU060, per UG570 Table 1-5).
  • Re-confirming the ECC/SECDED syndrome decoding in calculate_ecc(), which follows the UltraScale configuration-frame layout.

Host interface

The scrubber exposes two host-facing interfaces at the VHDL top:

  • Control port (ctl_*): a host-initiated request/ack interface for keyhole commands, memory inspection, and scrubber-state readout.
  • Alert stream (str_*): an 8-bit AXI-Stream used to emit unsolicited packets (state changes, upset notifications). The firmware's tx_state() and tx_notify_upset() wrap an example packet framing; swap in your own framing by redefining PKT_HDR_* in scrubber.c.

License

BSD 3-Clause. See LICENSE.

Minimax (rtl/minimax.v, src/microcode.S) is separately copyrighted by Three-Speed Logic, Inc. and Sean Cross; it is vendored here under its original terms.

About

An open-source, ECC-based internal scrubber for Xilinx UltraScale FPGAs

Resources

License

Stars

4 stars

Watchers

2 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors