Quartus II Tcl Example: Automatic Version Number
It is useful to have a version number or time stamp embedded in your FPGA design. A version number or time stamp eliminates any confusion about which version of your design is currently programmed in the FPGA. For such a number to be useful, it must be updated automatically in the design compilation flow. Also, the number must be stored in the design hardware, such as in memory or a bank of registers.
This Tcl example describes different ways to generate a version number or time stamp, as well as different ways to store it in a design. Then, it shows a script framework you can use to create a Tcl script that generates and stores the version number automatically, every time you compile a design. Finally, it shows an example of a complete script.
Get a Number
The following list shows how you can generate a version number:
Store the Number
In addition to getting the number, you must write it in a design file. The following are examples of how to store the number:
Script Framework
You can combine methods for getting and saving a number to suit your design flow. From the examples above, choose a method to get a number and a method to store the number. Copy the appropriate procedures to a Tcl file and add commands to call the procedures. The following script framework shows how your script should be written. Finally, add an assignment (described below) to your Quartus® II Settings File (.qsf ) to allow the script to run automatically.
# Insert procedure to get a number here
# Insert procedure to store the number here
# This line accommodates script automation, described later
foreach { flow project revision } $quartus(args) { break }
# Call procedure to get a number here
# Do any number format conversion necessary
# Call procedure to store the number here
Script Automation
Add the following line to your project's QSF to allow the script to run automatically before every compilation. Replace <script name > with the name of your Tcl file.
set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:<script name>
Refer to Automatic Script Execution for more information about the assignment and other ways to automatically run scripts.
Example
The following script example uses procedures from the following two examples:
# Gets SVN revision number for the specified file
proc get_subversion_revision { file_name } {
global done
# The maximum number of seconds to wait for the svn info
# command to complete
set timeout_seconds 30
# The svn info command with filename that is run
set cmd "svn info ${file_name}"
# Attempt to get the version information.
# If the command can't be run, return an error.
# Otherwise set up a file event to process the command output.
if { [catch {open "|$cmd"} input] } {
return -code error $input
} else {
fileevent $input readable [list get_revision_info $input ]
# Set up a timeout so that the process can't hang if the
# repository is down.
set timeout [after [ expr { $timeout_seconds * 1000 } ] \
[list set done -1] ]
# Don't continue until the revision number is found,
# or the operation times out. Cancel the timeout anyway.
vwait done
after cancel $timeout
}
}
# Helper procedure for the above procedure
proc get_revision_info { inp } {
global done revision_number
if { [eof $inp] } {
catch {close $inp}
set done 1
} elseif { $done } {
gets $inp line
} else {
gets $inp line
# Use a regular expression to match the line with the
# revision number.
if { [regexp {^Revision:\s+(\d+)\s*$} $line match revision_number] } {
set done 1
}
}
}
# Creates a register bank in a verilog file with the specified hex value
proc generate_verilog { hex_value } {
set num_digits [string length $hex_value]
set bit_width [expr { 4 * $num_digits } ]
set high_index [expr { $bit_width - 1 } ]
set reset_value [string repeat "0" $num_digits]
if { [catch {
set fh [open "version_reg.v" w ]
puts $fh "module version_reg (clock, reset, data_out);"
puts $fh " input clock;"
puts $fh " input reset;"
puts $fh " output \[$high_index:0\] data_out;"
puts $fh " reg \[$high_index:0\] data_out;"
puts $fh " always @ (posedge clock or negedge reset) begin"
puts $fh " if (!reset)"
puts $fh " data_out <= ${bit_width}'h${reset_value};"
puts $fh " else"
puts $fh " data_out <= ${bit_width}'h${hex_value};"
puts $fh " end"
puts $fh "endmodule"
close $fh
} res ] } {
return -code error $res
} else {
return 1
}
}
# This line accommodates script automation
foreach { flow project revision } $quartus(args) { break }
set file_name ${project}.qpf
set done 0
set revision_number ""
# Call procedure to get file revision number and handle any errors
if { [catch { get_subversion_revision $file_name } msg] } {
post_message -type critical_warning "Couldn't run command to get\
revision number. $msg"
} else {
if { -1 == $done } {
post_message -type critical_warning "Timeout getting revision number."
} elseif { [string equal "" $revision_number] } {
post_message -type critical_warning \
"Couldn't find revision number in output of svn info $file_name."
} else {
# Call procedure to store the number
if { [catch { generate_verilog $revision_number } res] } {
post_message -type critical_warning \
"Couldn't generate Verilog file. $res"
} else {
post_message "Successfully updated version number to\
version 0x${revision_number}"
}
}
}
If you name the script update_version.tcl, you must add the following line to your QSF:
set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:update_version.tcl
Design Examples Disclaimer
These design examples may only be used within Altera Corporation devices and remain the property of Altera. They are being provided on an “as-is” basis and as an accommodation; therefore, all warranties, representations, or guarantees of any kind (whether express, implied, or statutory) including, without limitation, warranties of merchantability, non-infringement, or fitness for a particular purpose, are specifically disclaimed. Altera expressly does not recommend, suggest, or require that these examples be used in combination with any other product not provided by Altera.
|