I’m working with the CW305 board and following the tutorial here:
I’m using the following code:
target = cw.target(scope, cw.targets.CW305, force=True, fpga_id=fpga_id, platform=platform)
Even with force=True, when I upload a new bitstream to the FPGA, the CW305 continues to run the previous bitstream unless I physically press the USB RST (SW3) button on the board, or power cycle the FPGA.
This is problematic because I’m accessing the PC remotely and need a software-based reset method. I cannot physically press the reset button.
So my questions is:
Is there any way to programmatically reset the FPGA (Artix-7) on CW305 so that the new bitstream takes effect immediately without needing a physical reset?
It isn’t necessary to physically reset the board. What exactly is the command you are using to program your new bitstream? If you’re doing this, it will always load our AES bitstream:
How are you determining that the FPGA is not getting programmed; are you 100% sure that it’s not? Does the red FPGA_DONE LED near the middle of the board light up briefly?
How am I determining that the FPGA isn’t getting programmed?
I’m using two different bitstreams, each of which produces a different output on the console. After loading a new bitstream, if I do not perform a hard reset, the output does not change—it continues to run the previous bitstream. This suggests the FPGA is not getting reprogrammed unless I reset the board manually.
FPGA_DONE LED behavior:
After the first successful programming (following a hard reset), the red FPGA_DONE LED turns off. When I try to program again without a hard reset, the LED does not light up at all. It only behaves correctly again after another manual reset.
M0/M1/M2 Switch Settings:
I have the switches set to 1-1-1 (for JTAG mode), as recommended. I also tried 1-0-1, but that didn’t change the behavior.
ChipWhisperer Version:
I believe I’m using firmware version 0.51.
Board Information:
I’m using the CW305 board, part number npcb-artix-cw305-05, as printed on the back of the PCB.
This is outdated; on the latest release, CW305 firmware is 0.53.
I meant which ChipWhisperer software version:
import chipwhisperer as cw
print(cw.__version__)
Here’s a quick script you can try, using two of the bitfiles in the chipwhisperer repository.
If you’re on an older CW release you’ll need to adjust the bsfile path.
import chipwhisperer as cw
fpga_id = '100t'
#fpga_id = '35t'
for attempt in ['attempt1', 'attempt2']:
bsfile = '../software/chipwhisperer/hardware/firmware/cw305/ECDSA256v1_pmul_{}_{}.bit'.format(attempt, fpga_id)
target = cw.target(None, cw.targets.CW305_ECC, force=True, bsfile=bsfile, platform='cw305')
print('FPGA buildtime for %s bitfile: %s' % (attempt, target.fpga_buildtime))
target.dis()
That’s 3 years old; try upgrading and I suspect all your issues will be resolved.
After upgrading the chipwhisperer software, don’t forget to do any suggested device firmware updates.
I updated the version to 6.0.0. However, it is not reprogramming the FPGA properly if I don’t press USB RST button. I tested the code you shared. It gives the programming time correctly two times. However, it runs the first bitstream execution when I run it. Second bitstream is not loaded without pressing reset button.
I see the following outputs.
FPGA buildtime for attempt1 bitfile: 5/18/2025, 08:32
FPGA buildtime for attempt2 bitfile: 5/18/2025, 08:32
I have two bitstreams. First bitstream gives the output as 5, the second one gives the output as 2. When I press the USB RST button or power cycle the board (turn it off and on) before loading a bitstream, the correct bitstream loads to the FPGA, and I see the expected output on the console.
However, if I do not press the USB RST button or power cycle the board before loading the bitstream, the output does not reflect the newly loaded bitstream. Instead, the FPGA appears to retain and run the previous bitstream, giving the old result.
…and when you run it with the bitstreams from the chipwhisperer repository (i.e. run my example code exactly as above), do you get the same result that I do?
I’m sorry this is taking a lot of back-and-forth but I am still unable to understand what exactly is happening here.
When I set to “100t”, it gives the following:
FPGA buildtime for attempt1 bitfile: 15/31/2063, 31:63
FPGA buildtime for attempt2 bitfile: 15/31/2063, 31:63
When I set to “35t”, it gives the following:
FPGA buildtime for attempt1 bitfile: 0/0/2000, 00:00
FPGA buildtime for attempt2 bitfile: 0/0/2000, 00:00
I see the following results when I use your code.
target = cw.target(None, cw.targets.CW305_ECC, force=True, bsfile=bsfile, platform=‘cw305’)
FPGA buildtime for attempt1 bitfile: 10/20/2023, 09:17
FPGA buildtime for attempt2 bitfile: 10/20/2023, 09:17
I see the following results when I set target as cw.targets.CW305.
target = cw.target(None, cw.targets.CW305, force=True, bsfile=bsfile, platform=‘cw305’)
FPGA buildtime for attempt1 bitfile: 0/0/2000, 00:00
FPGA buildtime for attempt2 bitfile: 0/0/2000, 00:00
This is definitely strange, we’ve never seen this before.
What if you explicitly erase the FPGA before changing bitfiles?
Run this before the cw.target() command that you use to change bitfiles: