stave-main-fpga-full-fw
FPGA design of the stave controller of the SuperMuSR stave v3: a Spartan-7 xc7s50csga324-1
with a MicroBlaze inside. It programs and configures the four sensor modules of the stave, drives
the offset and serpentine DACs, reads the SiPM temperatures and the stave sensors, and answers the
DAQ over a serial line.
Published on NI Packages as
supermusr-stave-v3-master.
What it does
The stave has one SPI flash shared by three images:
| Flash address | Image | Package |
|---|---|---|
0 (FIRMWARE_BL) | stave bootloader, what the FPGA loads at power up | another project (stave-bootloader) |
0x400000 (FIRMWARE_BA) | this image, stave-master.bin | supermusr-stave-v3-master |
0x800000 (FIRMWARE_SLAVE_BA) | the image of the slave FPGAs | supermusr-stave-v3-slave |
At power up the MicroBlaze application (MicroBlaze/stave/src/helloworld.c):
- pulses
PROG_Bof the four slave FPGAs and shifts the slave image from0x800000into them - sets the offset DACs and the serpentine DACs to their defaults, initialises the SHT3x humidity sensor and reads the stave serial number from the on-board EEPROM
- sends the first configuration to the slaves over their 2048-bit shift register and reads back from each one its serial number, firmware version, uptime and status
- loops: every second it recomputes the SiPM bias from the temperatures, reads the stave temperature and humidity; every 100 ms it reads one channel of the ADCs (SiPM temperatures, serpentine voltages, supply rails); and it answers the DAQ
Serial protocol
The DAQ (adc120-bridge-v2, /dev/ttyUL0) talks to the MicroBlaze over the AXI UART Lite at
115200 baud, with two 8-byte-or-less frames and a CRC-8 (polynomial 0x31, init 0xFF):
| Request | Reply |
|---|---|
set: FF id_lo id_hi <float LE> crc | FE ok 00 crc |
get: FA id_lo id_hi crc | FE ok 00 <float LE> crc |
Every value travels as a 32-bit float, so integers are exact only up to 2^24. The full register
map is in StaveController.h of adc120-bridge-v2; the ones that concern the identity of the
stave are:
| Register | Access | What |
|---|---|---|
0xFFE0..0xFFE3 | set | write the serial number into the EEPROM of module 0..3 (A0, A1, B, C) |
0xFFE8 | set | write the stave serial number into the stave EEPROM; replies ok only if the read-back matches |
0xFFF0..0xFFF3 | get | serial number of module 0..3 |
0xFFD0..0xFFD3 | get | firmware version of module 0..3 |
0xFFF8 | get | bitmask of the modules answering with the validation key 0xABBA0123 |
0xFFFA | get | stave serial number (0 if the EEPROM is blank or does not answer) |
0xFFFB | get | hardware version (HW_VER) |
0xFFFC | get | firmware version (FW_VER) |
0xFFFF | set | send the configuration to the slaves and apply the local one |
Serial numbers
- Stave: 4 bytes big-endian at address
0x0000of the AT24CM01 on the internal I²C bus (int_I2C, pins J14/J13, the same AXI IIC as the SHT3x). With the current assembly variant A1 = A2 = 0 (R51, R52 fitted, R49, R50 not fitted), so the EEPROM answers at0x50, and WP is tied to GND through R56, so it is writable. The MicroBlaze reads it at boot and after every write, so0xFFFAis always what is really in the chip - Modules: kept by each slave FPGA in its own EEPROM (see
slave-fpga-v2). A write is a shift register frame with the key0xDEADBEEF; the value read back right after is the slave's copy, the EEPROM is read again only at the next power up
Both are written and read from the DAQ, with the bridge stopped, by eeprom_sn.py in
supermusr-calibration-multi-master.
Version
FW_VER in MicroBlaze/stave/src/fw_version.h is what the DAQ reads from 0xFFFC; the bridge
reads the module registers only from version 7 on. On a tag pipeline build.sh writes the tag
into it: X.Y.Z becomes (X << 16) | (Y << 8) | Z (0.0.8 → 8, 0.1.0 → 256). The register
is a float, exact only up to 2^24, which is why the tags are incremental-dot-3 with each field in
0..255 and not the date-4-dot of other SuperMuSR repositories. Outside a tag pipeline the header
is left as committed.
Building
Needs Vivado/Vitis 2020.2 (vivado and mb-gcc on the PATH, or set XILINX_SETTINGS to the
settings64.sh of your install). No licence file is needed: xc7s50 is covered by the free
WebPACK.
./build.sh # -> stave-master.bin
./build.sh microblaze # -> firmware.elf only, for a quick check on the applicationTwo steps, the same ones the pipeline runs:
| Step | What happens |
|---|---|
| 1 | the MicroBlaze application is compiled with mb-gcc against the BSP in MicroBlaze/stavetop/export, and linked with src/lscript.ld into firmware.elf |
| 2 | vivado -mode batch -source compile.tcl replaces the ELF associated with the microblaze_0 cell of the mb block design with firmware.elf, enables the .bin output and runs impl_1 up to write_bitstream |
The output, stave-controller.runs/impl_1/stavetop.bin, is copied to stave-master.bin.
The compiler flags in build.sh are those of the Debug configuration of the Vitis project,
the one whose ELF (MicroBlaze/stave/Debug/stave.elf) the Vivado project has always used:
-O0 -g3, -mcpu=v11.0 and the rest of the MicroBlaze options. The MicroBlaze has no FPU
(XPAR_MICROBLAZE_0_USE_FPU 0): the Release configuration compiles with -mhard-float and must
not be used as it is.
The BSP is versioned, not generated here
build.sh compiles against the board support package committed under
MicroBlaze/stavetop/export/stavetop/sw/stavetop/microblaze_0 — libxil.a and the headers,
xparameters.h among them. Nothing in this build regenerates it, so whoever changes the block
design must open the platform in Vitis, run platform generate, and commit the files under
MicroBlaze/stavetop/export, or the application keeps being compiled against the old hardware
description. xsct is not used because it needs an X display that no CI image provides.
Vivado can end with exit code 0 and leave nothing behind: a failed run is reported in the log,
not in the status. build.sh therefore checks that stavetop.bin is really there and prints the
tail of vivado.log when it is not.
Layout of the repository
| Where | What |
|---|---|
stave-controller.xpr, .srcs/, .gen/ | the Vivado project: stavetop, the mb block design, the constraints |
MicroBlaze/stavetop | the platform project and its exported BSP |
MicroBlaze/stave | the application: slave programming and configuration, DACs, ADCs, SHT3x, EEPROMs, serial protocol |
python/test.py | a minimal client of the serial protocol |
TableIO.xlsx | pin table |
compile.tcl | the Vivado step: ELF association, .bin, implementation |
build.sh | the whole build: version from the tag, application with mb-gcc, then Vivado, with the checks |
Release
Releases are driven by GitLab CI and orchestrated by pippolina. The pipeline stages are:
pippolina-pre-pipeline— waits for the pippolina release lockbuild—build_master, in theharbor.nuclearinstruments.eu/xilinx/vitis-2020.2image on aheavyrunner (timeout 3h; artifacts kept even on failure, so the Vivado log comes back)release— publishes the package on NI Packages and creates the GitLab release
SuperMUSR Stave V3 SLAVE
Spartan-7 xc7s15 design of the SuperMuSR stave v3 sensor module, four per stave. It drives
the LED pulser and the SiPM bias LDOs and keeps the module serial number in an I²C EEPROM. Loaded
by the stave controller from 0x800000 of the stave flash at every power up.
License:
Trending Products
DT5571
High-performance waveform digitizer featuring 14-bit resolution and a 200 MS/s sampling rate on a single analog input.
DAQ141
High-performance, fully integrated digitizer developed by Nuclear Instruments for advanced SiPM-based muon detection systems
DT5560SE
Compact, desktop-form-factor digitizer designed for laboratory development, prototyping, and system testing
