Skip to content

Instantly share code, notes, and snippets.

@abeln94
Last active November 21, 2023 18:20
Show Gist options
  • Save abeln94/a9060066a764b609b754941b7ab901d5 to your computer and use it in GitHub Desktop.
Save abeln94/a9060066a764b609b754941b7ab901d5 to your computer and use it in GitHub Desktop.
FPGA utilities

FPGA Utilities

Utilities for Windows to manage multiple PYNQ-Z2 with different identifiers.

By default, all the PYNQ-Z2 boards have the same internal identifier, which means that Vivado cannot differentiate between them.

By using the Id-renamer python script you can easily change it. All the other scripts require the boards to have different ids, otherwise only one of them will be programmed.

For an alternative without modifying the id, check the FPGA device tool repo.

This script will program a given bitstream into all available PYNQ-Z2 boards using Vivado.

The boards must have different ids with the prefix "1234-tul", unless modified.

This script will program a given SDK into all available PYNQ-Z2 using Vivado SDK. Optionally, it will also program the bitstream.

The boards must have different ids with the prefix "1234-tul", unless modified.

@echo off
REM This script will program a given bitstream into all available boards using Vivado.
REM You can specify the bitstream with one of the following methods:
REM - Command line: bitstream as parameter > FPGA_programmer "C:\Users\user\bitstream.bit"
REM - Drag and drop a bitstream file into this one.
REM - Double-click the file: a file chooser dialog will be shown to pick it.
REM MIT License
REM Copyright (c) 2023 Abel Naya
REM Permission is hereby granted, free of charge, to any person obtaining a copy
REM of this software and associated documentation files (the "Software"), to deal
REM in the Software without restriction, including without limitation the rights
REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
REM copies of the Software, and to permit persons to whom the Software is
REM furnished to do so, subject to the following conditions:
REM The above copyright notice and this permission notice shall be included in all
REM copies or substantial portions of the Software.
REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
REM SOFTWARE
powershell -command " cd '%~dp0'; $SCRIPT = '%~f0'; $ARGUMENTS = '%*'; Invoke-Expression (Get-Content -Path $SCRIPT -Delimiter 'POWERSHELL_SCRIPT_DELIMITER')[2] "
goto:eof
---------------------------------------------------------------------------------------------------
The text above is bat(ch) that calls powershell, the text below is powershell that will be run afterwards.
---------------------------------------------------------------------------------------------------
POWERSHELL_SCRIPT_DELIMITER
# Find Vivado
$Vivado = Get-ChildItem -Path "C:/Xilinx/Vivado/" | ForEach-Object { "C:/Xilinx/Vivado/$_/bin/vivado.bat" } | Where-Object { Test-Path $_ } | Select-Object -First 1
Write-Host "Vivado detected: $Vivado"
# choose bitstream if not provided
if (!$ARGUMENTS) {
Write-Host "No bitstream specified. Opening file picker..."
Add-Type -assembly System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog
$FileBrowser.Title = "Choose bitstream"
$FileBrowser.Filter = 'Bitstream|*.bit|All|*.*'
$FileBrowser.RestoreDirectory = $false
if($FileBrowser.ShowDialog() -ne "OK") { exit }
$ARGUMENTS = $FileBrowser.FileName
}
# run vivado
Write-Host "Launching Vivado..."
(Get-Content -Path $SCRIPT -Delimiter "START_OF_TCL_SCRIPT")[2] | & $Vivado -mode tcl -nolog -nojournal -verbose -tclargs $ARGUMENTS.Split()
#POWERSHELL_SCRIPT_DELIMITER
---------------------------------------------------------------------------------------------------
The text above is powershell, the text below is TCL that will be run in Vivado.
---------------------------------------------------------------------------------------------------
START_OF_TCL_SCRIPT
# get bitstream file
set bitfile [lindex $argv 0]
if { [file exists $bitfile] == 1 } {
puts "Using bitfile: $bitfile"
} else {
puts "Invalid bitfile: $bitfile"
puts ""
quit
}
# initialize hardware manager
puts "Initializing Vivado..."
load_features labtools
if { [catch {open_hw_manager} error] } { open_hw }
connect_hw_server -url TCP:localhost:3121
refresh_hw_server
puts "Vivado prepared"
puts ""
# get devices
set targets [get_hw_targets]
puts "[llength $targets] devices detected."
puts ""
foreach {hw_target} $targets {
# program device
puts "Preparing $hw_target..."
current_hw_target $hw_target
open_hw_target
set hw_device [lindex [get_hw_devices] 1]
current_hw_device $hw_device
# configure program
puts "Programming $hw_target..."
set_property PROGRAM.FILE $bitfile $hw_device
program_hw_devices $hw_device
close_hw_target
puts "Prorammed"
puts ""
}
# end
puts "Done"
"""
This script will replace the identifier of a pynq-z2 board.
All pynq-z2 boards have the same internal identifier (1234-tul), which makes them undistinguishable from one another.
With this script you can replace the default id with another one.
This makes them distinguishable to tools like Vivado.
Installation instructions (for windows):
1- Prepare a python instalation with the 'pyftdi' package installed
2- Connect one board to the computer.
3- Open the device manager
4- Right click on 'Universal Serial Bus controllers -> USB Serial Converter A'
5- Click Update driver
6- Click 'Browse my computer for drivers'
7- Click 'Let me pick from a list of available drivers on my computer'
8- Select 'TUL (Interface 0) (libusb-win32)'.
If more than one entry is present, choose any of them.
If this driver is not in the list, you need to download zadig and install it from there.
9- Accept and close the device manager.
Usage instructions
1- Edit the script and choose the identifier you want.
2- Run the script
"""
from pyftdi.eeprom import FtdiEeprom
from pyftdi.misc import hexdump
from pyftdi.ftdi import Ftdi
# log devices
Ftdi.show_devices()
# variable
eeprom = FtdiEeprom()
# connect to device with default serial
eeprom.open('ftdi://ftdi:2232:1234-tul/1')
# dump current data
print(hexdump(eeprom.data))
# save config
#with open('a1','w') as f: eeprom.save_config(f)
# load config
#with open('a1') as f: eeprom.load_config(f)
# change serial
eeprom.set_serial_number("1234-tul-a1") # <---------------- NEW IDENTIFIER
# dump changed data
print(hexdump(eeprom.data))
# program
eeprom.commit(dry_run=False)
@echo off
REM This script will program a given SDK into all available boards using Vivado SDK.
REM Takes as input 2 required files (TCL, ELF) and an extra optional one (BIT)
REM You can either:
REM - Double click the file, this will ask to choose each file one by one.
REM - Drag-and-drop the required files into the script.
REM - Call from command line with the files as parameters.
REM
REM For the last two options: the script will filter and automatically pick the required ones based on their extension.
REM This means that you can call the script with more files than needed, even invalid ones, and the script will pick the first one for each type (and ask if a required one is missing).
REM Note: the optional bitstream will only be asked if there are no parameters, otherwise it will be assumed to not program a bitstream.
REM
REM Examples:
REM
REM $ SDK_programmer.bat "C:\Files\ps7_init.tcl" "C:\Files\sdk.elf"
REM This will not ask for any file, and will not program a bitstream
REM
REM $ SDK_programmer.bat "C:\Files\sdk.elf" "C:\Files\bitstream.bit"
REM This will ask for the missing tcl file
REM
REM $ SDK_programmer.bat "C:\Files\invalid.txt"
REM This will ask for the tcl and elf files, but not the bitstream
REM
REM $ SDK_programmer.bat
REM This is equivalent to double clicking the file. Will ask to choose all files, including the bitstream.
REM
REM Final note:
REM If you have a folder with a bunch of files, and among them are some/all of the required ones, you can select them all and drag-and-drop into the script. It will pick them automatically (and ask if there is a missing one).
REM MIT License
REM Copyright (c) 2023 Abel Naya
REM Permission is hereby granted, free of charge, to any person obtaining a copy
REM of this software and associated documentation files (the "Software"), to deal
REM in the Software without restriction, including without limitation the rights
REM to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
REM copies of the Software, and to permit persons to whom the Software is
REM furnished to do so, subject to the following conditions:
REM The above copyright notice and this permission notice shall be included in all
REM copies or substantial portions of the Software.
REM THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
REM IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
REM FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
REM AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
REM LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
REM OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
REM SOFTWARE
set ARGS= %*
set ARGS=%ARGS:$=\$%
set ARGS=%ARGS:"=\"%
powershell -command "&{ cd '%~dp0'; $SCRIPT = '%~f0'; $PS_ARGS = $args; Invoke-Expression (Get-Content -Path $SCRIPT -Delimiter 'POWERSHELL_SCRIPT_DELIMITER')[2] }" %ARGS%
REM pause
goto:eof
---------------------------------------------------------------------------------------------------
The text above is bat(ch) that calls powershell, the text below is powershell that will be run afterwards.
---------------------------------------------------------------------------------------------------
POWERSHELL_SCRIPT_DELIMITER
# Find SDK
$SDK = Get-ChildItem -Path "C:/Xilinx/SDK/" | ForEach-Object { "C:/Xilinx/SDK/$_/bin/xsct.bat" } | Where-Object { Test-Path $_ } | Select-Object -First 1
Write-Host "SDK detected: $SDK"
# function to choose file
function ChooseFile($name,$optional) {
$optional_label = If ($optional) {"optional"} Else {"required"}
Write-Host "Mising $optional_label .$name file. Opening file picker..."
Add-Type -assembly System.Windows.Forms
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog
$FileBrowser.Title = "Choose $optional_label $name"
$FileBrowser.Filter = "$name|*.$name|All|*.*"
$FileBrowser.RestoreDirectory = $false
if($FileBrowser.ShowDialog() -ne "OK") {
if($optional){ return "" }
Write-Host "Canceled required file, exiting"
exit
}
# return
$FileBrowser.FileName
}
# get files
$TCL = $PS_ARGS | Where { $_.EndsWith('.tcl') } | Select -First 1
if (!$TCL) { $TCL = ChooseFile tcl }
$ELF = $PS_ARGS | Where { $_.EndsWith('.elf') } | Select -First 1
if (!$ELF) { $ELF = ChooseFile elf }
# bitstream is optional, ask only if there were no parameters at all
$BIT = $PS_ARGS | Where { $_.EndsWith('.bit') } | Select -First 1
if (!$PS_ARGS) { $BIT = ChooseFile bit True }
# run vivado
Write-Host "Launching SDK..."
(Get-Content -Path $SCRIPT -Delimiter "START_OF_TCL_SCRIPT")[2] `
-replace 'PS_TCL',($TCL -replace "\\",'\\') `
-replace 'PS_ELF',($ELF -replace "\\",'\\') `
-replace 'PS_BIT',($BIT -replace "\\",'\\') `
| & $SDK
#POWERSHELL_SCRIPT_DELIMITER
---------------------------------------------------------------------------------------------------
The text above is powershell, the text below is TCL that will be run in Vivado.
---------------------------------------------------------------------------------------------------
START_OF_TCL_SCRIPT
# get files
set TCL "PS_TCL"
if { [file exists $TCL] == 1 } {
puts "Using tcl: $TCL"
} else {
puts "Invalid tcl: $TCL"
puts ""
exit
}
set ELF "PS_ELF"
if { [file exists $TCL] == 1 } {
puts "Using elf: $ELF"
} else {
puts "Invalid elf: $ELF"
puts ""
exit
}
set BIT "PS_BIT"
if { [file exists $BIT] == 1 } {
puts "Using bitstream: $BIT"
} else {
puts "No bitstream will be programmed"
set BIT ""
}
puts "Preparing SDK"
connect
source $TCL
set TCL_name [lindex [split [file tail $TCL] '_'] 0]
puts "SDK prepared"
puts "Detecting boards..."
# load boards
set boards [targets -filter {name == "ARM Cortex-A9 MPCore #0" && jtag_cable_serial =~ "1234-tul*A"} -target-properties]
puts "[llength $boards] boards detected."
foreach {board} $boards {
puts ""
puts "Programming board [dict get $board jtag_cable_serial]"
puts "Stopping board"
target [dict get $board target_id]
rst
if {$BIT != ""} {
puts "Programming bitstream"
target [expr [dict get $board target_id] + 2]
fpga $BIT
target [dict get $board target_id]
}
puts "Programming processor"
${TCL_name}_init
${TCL_name}_post_config
dow $ELF
con
puts "Programmed board [dict get $board jtag_cable_serial]"
puts ""
}
# end
disconnect
puts "Done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment