CW-Lite/CW-Pro Custom Bitstream Loading (ADVANCED/DEBUG)

This came up on github issue, how do you reload the ChipWHisperer FPGA on the new CW5? I’m documenting here until we move to somewhere better.

The ChipWhisperer-Lite/Pro use an FPGA bitstream built into the Python codebase (ensures consistent SW/FPGA match). In CW4 there was a GUI widget to switch modes, that is no missing in CW5, and the method of switching wasn’t documented.

Currently this still uses the “old” API under the hood, so it’s fairly terrible. But at least so people can do this I made this topic which will be integrated into documentation.

Background on CW-Lite/Pro Bitstream

Be aware there is a wrinkle in the bitstream. There is a script called “generate_reconfig_dicts.py” you need to run, which generates the ‘partial reconfiguration’ information used to allow the ‘glitch offset’ and ‘glitch width’ feature to work. Because the Spartan 6 does not officially support partial reconfiguration, this is done with a slow/complex method since there is no support from Xilinx for doing partial reconfiguration.

When you run this, it generates two .p (Python Pickle) files which contain the bitstream information. This must be exactly matched to your bitstream - the partial reconfig files will only work with the specific .bit file they were generated against.

To avoid confusion, ChipWhisperer software can take in a zip-file that contains the FPGA .bit file, and the two .p files. There is an example of such a zip-file in the repo (cwlite_firmware.zip and cw1200_firmware.zip).

Setting Bitsream Mode

There is thus three possilbe modes you can set:

  1. Use just a .bit file (i.e., as generated by ISE in a single sythesis run).

This is typically used for debugging. However, if you need glitch offset/width to work you can’t use this option.

  1. Use a .zip file containing the .bit along with the two .p files.

This is used for debug when you want the clock glitching to work.

  1. Use ‘builtin’.

This option uses a zipfile that is encoded into a Python object. Encoding the zip-file into the Python module ensures it is distributed correctly with the rest of ChipWhisperer (this is what everyone uses by default).

The API for the actual switching is done in ChipWhispererFWLoader.py. You can access it using the following types of APIs (for CW-Pro change 0xACE2 to 0xACE3):

#scope.cwFirmwareConfig 
print("Mode: " + str(scope.scopetype.cwFirmwareConfig[0xACE2].loader._release_mode))
print("Mode: " + str(scope.scopetype.cwFirmwareConfig[0xACE2].loader.fpga_bitstream()))

#Set your bit-file
scope.scopetype.cwFirmwareConfig[0xACE2].loader.save_bsLoc("/path/to/cwlite_interface.bit")
scope.scopetype.cwFirmwareConfig[0xACE2].loader.setFPGAMode("debug")

#If you re-built as a zip-file
scope.scopetype.cwFirmwareConfig[0xACE2].loader.save_bsLoc("/path/to/cwlite_firmware.zip")
scope.scopetype.cwFirmwareConfig[0xACE2].loader.setFPGAMode("zipfile")

#Set back to normal
scope.scopetype.cwFirmwareConfig[0xACE2].loader.setFPGAMode("builtin")

After doing that, unplug & replug the ChipWhisperer (power cycle forces the FPGA to clear). Then just reconnect and you should be using the new one. You can check with the first two print commands to check the FPGA bitstream and mode in use.

If you are doing a bunch of development there is a command to just reload the FPGA, and not need the power cycle. By default ChipWhisperer is not re-configuring the FPGA if already configured, but there is a flag to override that. However for just some quick tests the above is likely the easiest.

The API will eventually be improved, as the above is all fairly terrible due to it’s connection to the old GUI methods! But for now…