A new version of this script has been created: Updated b2vFixer.tcl for Quartus / Modelsim

Quick Summary:

I created a handy script (b2vFixer.tcl) that prepares a Quartus project with a Schematic (BDF) top-level entity for use in ModelSim.

My personal preference is to use a Schematic for the Top-Level entity of my FPGA projects. I find that by drawing out the top level it becomes self documenting and easier to understand the general interconnections of the project. One drawback of this approach is that ModelSim doesn’t support Schematic files. As I pointed out in a previous post you have to use a Quartus tool to convert the Schematic to HDL, add this file to the project, remove the schematic file from the project, and finally set the new HDL file as the top-level.

After all that work you find that Quartus only half halfheartedly converted your schematic file. You can see that instead of naming the module instances something useful, it defaults to b2v_inst#:


Which becomes less than useful in ModelSim:


To alleviate this problem, I put together a TCL script that automates the conversion, it reprocesses the converted Verilog file (improves the instance names) and updates the Top-Level entity for you.

Here you can see the improvements after you use the b2vFixer.tcl script:


Making things more clear in ModelSim:




How to use b2vFixer.tcl


1. The first step is to download and save the b2vFixer.tcl script to your project’s directory.

2. The next step is to open your project in Quartus and open the TCL Console:

3. Load the b2vFixer.tcl by typing source b2vFixer.tcl in the console:

3b. Alternatively, you can add source b2vFixer.tcl to your project’s .qsf file to have it automatically loaded for you every time you open the project:


4. Kick off the conversion process by calling the b2v function in the console:

5. You should now have the automatically generated Verilog file added to your project and the top-level entity updated. The b2vFixer changes the top-level module name by adding a _b2v suffix to the end, which allows you to keep both the Verilog and BDF file in your project. (This might slow down the compilation process. Feel free to uncomment line 180 in the source code and the BDF file will be auto removed.)

Reverting back to the Schematic

After you’re done with the simulation, it’s a breeze to return the Schematic as the top level, you just need to right click the bdf file and Set as Top-Level Entity:


Feel free to leave the auto-generated Verilog _b2v file in your project. It will be automatically overwritten next time you run the b2v function.


Known b2vFixer.tcl Limitations

1. Quartus doesn’t do the best job of keeping track of what type of file the top-level entity is (bdf or HDL) which makes it tricky for my script to know if it’s a schematic or not. Currently if the top-level ends in _b2v, then b2vFixer.tcl knows not to try and do a conversion. A fix I found for this is to always run the Quartus Heirarchy Elaboration, then the top level type can be detected correctly. The following code can do this:

execute_module -tool map -args -elaborate_hierarchy
set current_focus_entity_id [get_top_level_entity] 
puts [get_name_info -info file_location $current_focus_entity_id]

(If you added “source b2vFixer.tcl” to the qsf file like I described above, for some reason, the b2v function is being called when you use the elaborate_hierarchy tcl command. I need to look into this a little closer before the functionality can be added.)

2. You’ll probably have problems in ModelSim if you project’s top-level contains other Schematic files, b2vFixer.tcl doesn’t do any form of recursive conversion.

3. Currently b2v only works with the top-level schematic, we could probably allow it to accept an argument and convert any bdf file pretty easily.

4. Doesn’t support VHDL yet.



Download b2vFixer.tcl

Download the script here:
Download
b2vFixer.zip

Or just copy/paste the source code:

#File:           	b2vFixer.tcl
#Author:         	Chris Zeh <Chris@idle-logic.com> 
#Website:			idle-logic.com
#Version:        	0.9b
#License			MIT License (http://www.opensource.org/licenses/mit-license.php)
# ----------------------------------------------
#		Revision History
# ----------------------------------------------
#	Version		Date		Comments
# ----------------------------------------------
#	0.9b		06/07/12	Initial Release
# ----------------------------------------------
#
#Purpose:        	
#	In order to prepare a project for ModelSim-ASE (Which doesn't allow
#	schematic top-level files, this tool converts and improves the Top-Level
#	Schematic (bdf) to Verilog conversion and prepares the project for
#	ModelSim.
#	Note: VHDL conversion not yet supported.
#
#Usage:
#	From the Quartus TCL Console:
#	tcl> source b2vFixer.tcl
#	tcl> b2v
#
#	You can also add "source b2vFixer.tcl"	to the project's .qsf file for it
#	to be included automatically to the project

#Global declarations:
set lModNames {}
set lModCount {}

# --------------------------------------------------------------------------------------------
#Function:	get_inst_number
#Purpose:	Keeps track of the Modules detected during the file processing and 
#			returns the instance number. Allowing us to manage something like
#			clk_inst0 and clk_inst1 in the same project
#
#Inputs:	args[0] is the String name of the module
#			Uses the global static variables, lModNames & lModCount
#Returns:	Returns an integer with the instance number
# --------------------------------------------------------------------------------------------
proc get_inst_number args {
	#This might be a little cleaner using TCL Arrays instead of Lists.
	global lModNames
	global lModCount 
	
	set NewModName [lindex $args 0]
	
	#Check to see if the NewModule is already in our List of Modules
	set ModIndex [lsearch $lModNames $NewModName]
	if {$ModIndex == -1} {
		#Module is new
		#Append it to the list here
		lappend lModNames $NewModName
		lappend lModCount 0
		return 0
	} else {
		#Module has already been found previously
		#Increment the list count
		lset lModCount $ModIndex [expr {[lindex $lModCount $ModIndex]+1}]
		return [lindex $lModCount $ModIndex]
	}
	
	}
	
# --------------------------------------------------------------------------------------------
#Function:	start_quartus_b2v
#Purpose:	Starts the native Quartus bdf to verilog tool. Checks to see if the top level has
#			already been converted by this tool, indicated by a _b2v suffix. The top-level 
#			file checking isn't robust yet since in Quartus there doesn't appear to be an easy
#			way to detect its file type.
#
#Inputs:	None. 
#			Resets the global static variables, lModNames & lModCount
#Returns:	Returns boolean success
# --------------------------------------------------------------------------------------------
proc start_quartus_b2v args {
	if {![is_project_open]} { 
		puts "No Project Open"
		return False
	}
	#Reset the Module List/Counter
	global lModNames
	global lModCount 
	set lModNames {}
	set lModCount {}
	
	#Check to see what the current toplevel is	
	set toplevel_name [get_global_assignment -name TOP_LEVEL_ENTITY]
	puts "Top-Level Detected: $toplevel_name"
		
	#See if it is already a "toplevel_b2v" Verilog File
	set suffix_test [string range $toplevel_name end-3 end]
	if {$suffix_test == "_b2v"} {
		puts "Top Level is already a converted schematic file"
		return False
	}
	
	#Kick off the Quartus b2v tool
	set toplevel_bdf "${toplevel_name}.bdf"
	set convert_arg "--convert_bdf_to_verilog=$toplevel_bdf"
	puts "Starting Quartus native b2v tool..."
	if {[catch {execute_module -tool map -args $convert_arg} result]} {
		puts "ERROR: Issue while converting. Check for Errors in the Messages Window.\n"
		return False
	} else {
		puts "...Completed successfully \n"
		
	}
	return True
}

# --------------------------------------------------------------------------------------------
#Function:	b2v
#Purpose:	Main Function call for this program. Initiates and manages the full b2v
#			and processing. 
#
#Inputs:	None. 			
#Returns:	Returns boolean success
# --------------------------------------------------------------------------------------------
proc b2v args {
	if {![is_project_open]} { 
		puts "No Project Open"
		return
	}
	#Start the Internal Quartus Schematic (bdf) to Verilog Converter
	puts "Converting Schematic Top-Level Entity to Verilog Top-Level"
	puts "*******************************************************************"

	if { ![start_quartus_b2v]} {
		return
	}
	
	set toplevel_name [get_global_assignment -name TOP_LEVEL_ENTITY]
	
	set module_name "module ${toplevel_name}("
	set new_module_name "module ${toplevel_name}_b2v("
	set b2vFile [open "${toplevel_name}_b2v.v" w]
	set File [open [file join [pwd] "${toplevel_name}.v"]]
	
	#We will traverse the Quartus Converted b2v file, and make our adjustments.
	#Swap the default b2v_inst0 names for an inst based on the module name so vJTAG_inst0
	#	Also keep track of the module names so we can deal with duplicates, so: vJTAG_inst1, vJTAG_inst2, and so on.
	#Also, we want to swap the module name to <toplevel>_b2v, which will allow the schematic file and the converted
	#	verilog file to remain in the project. Otherwise, you get an error w/ duplicate modules at compile time.
	#	This might slow down the compile process, so if we want to pull the bdf out of the project we can use
	#	set_global_assignment -name BDF_FILE ${toplevel_name}.bdf -remove
	
	puts "Starting Quartus b2v File Processing"
	puts "-------------------------------"
	puts "Top Level Modules Found:"
	puts "-------------------------------"

	foreach {i} [split [read $File] \n] {
		set mod_name [lindex [regexp -inline -all -- {\S+} $i] 0]
		set inst_name [lindex [regexp -inline -all -- {\S+} $i] 1]
		set inst_name_trunc [string range $inst_name 0 7]

		if {$inst_name_trunc == "b2v_inst"} then {
			set inst_num [get_inst_number $mod_name]
			puts $b2vFile "${mod_name}   ${mod_name}_inst${inst_num}("
			puts "${mod_name}_inst${inst_num}"
		} elseif {$i == $module_name} then {
			
			puts $b2vFile $new_module_name
			
		} else {
			#puts $i
			puts $b2vFile $i
		}

	}
	puts "-------------------------------"
	close $File
	close $b2vFile
	
	set_global_assignment -name VERILOG_FILE ${toplevel_name}_b2v.v
	set_global_assignment -name TOP_LEVEL_ENTITY ${toplevel_name}_b2v
	#set_global_assignment -name BDF_FILE ${toplevel_name}.bdf -remove
	
	puts "Schematic to Verilog Top-Level Conversion Complete:"
	puts "	${toplevel_name}_b2v.v added to the project"
	puts "	${toplevel_name}_b2v set as TOP_LEVEL_ENTITY"
}

#Indicate the file has been loaded:
puts "------------------------------------"
puts "b2vFixer.tcl Loaded:"
puts "b2v Command now available"
puts "------------------------------------"




# --------------------------------------------------------------------------------------------
# Copyright (c) 2012 Chris Zeh
#
# Released under the MIT License (MIT) (http://www.opensource.org/licenses/mit-license.php)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
# and associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute, 
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software 
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or 
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# --------------------------------------------------------------------------------------------