Quartus® II Tcl 示例:将所有引脚虚拟化

author-image

作者

如果在项目中采用模块化 LogicLock 区域设计流程,可以选择将模块中的所有 I/O 引脚设置为虚拟 I/O 引脚,以便于在顶层设计中轻松导入模块。此外,如果想要编译 IP 核并查看它使用了多少资源,但发现它使用了目标设备过多的引脚,将引脚虚拟化可以使核与设计相匹配。

以下简单程序将设计中的所有引脚设置为虚拟 I/O 引脚。首先对设计进行综合,确定哪些节点是引脚。接下来,将名称 ID 集合设置为与设计中的引脚相对应,然后对每个引脚应用 VIRTUAL_PIN 赋值。最后,export_assignments 命令将所有新赋值写入项目的 Quartus II 设置文件 (.qsf)。

此示例使用 get_namesget_name_info 命令,这些命令适用于 Quartus II 软件 4.0 版及更高版本(::quartus::project 包 2.0 版及更高版本)。有关适用于 Quartus II 软件 3.0 版及更高版本并具有更多高级功能的代码,请参阅此页面的最后一个示例。

load_package flow

proc make_all_pins_virtual {} {

    execute_module -tool map

    set name_ids [get_names -filter * -node_type pin]

    foreach_in_collection name_id $name_ids {
        set pin_name [get_name_info -info full_path $name_id]
        post_message "Making VIRTUAL_PIN assignment to $pin_name"
        set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
    }
    export_assignments
}

改进示例代码

可通过多种方法改进示例代码。

移除现有 VIRTUAL_PIN 赋值

可以将以下命令添加到此程序的开头,以便移除所有现有 VALUAL_PIN 赋值。这是确保赋值处于已知状态的有效步骤。将此命令添加到 execute_module 命令前面。

remove_all_instance_assignments -name VIRTUAL_PIN

手动排除特定引脚,例如时钟

为了使 Quartus II 软件在与设计相匹配的情况下执行时序优化,时钟必须连接到目标设备中的顶层 I/O 引脚,并且时钟必须应用了时钟设置。即使设计中的所有其它引脚都是虚拟 I/O 引脚,情况也是如此。因此,以上基本示例阻止 Quartus II 软件在编译期间优化时序,因为所有引脚(包括时钟)都应用了 VIRTUAL_PIN 赋值。

可以在程序中添加一个参数,接受要从 VIRTUAL_PIN 赋值中排除的信号列表。此列表通常是设计中的时钟引脚名称。以下示例接受要排除的名称列表。它还包括上述移除任何现有 VIRTUAL_PIN 赋值的命令。

load_package flow
package require cmdline

proc make_all_pins_virtual { args } {

    set options {\
        { "exclude.arg" "" "List of signals to exclude" } \
    }
    array set opts [::cmdline::getoptions quartus(args) $options]

    remove_all_instance_assignments -name VIRTUAL_PIN
    execute_module -tool map
    set name_ids [get_names -filter * -node_type pin]

    foreach_in_collection name_id $name_ids {
        set pin_name [get_name_info -info full_path $name_id]

        if { -1 == [lsearch -exact $opts(excludes) $pin_name] } {
            post_message "Making VIRTUAL_PIN assignment to $pin_name"
            set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
        } else {
            post_message "Skipping VIRTUAL_PIN assignment to $pin_name"
        }
    }
    export_assignments
}

可以使用此命令调用此程序。此示例假设设计中有两个时钟,分别名为 clk_a 和 clk_b。

make_all_pins_virtual -exclude { clk_a clk_b }

自动识别和处理时钟

上一个排除特定信号的示例的缺点在于必须手动输入这些信号。可以使用 ::quartus::advanced_timing 包中的命令确定时钟信号。此包仅可在 quartus_tan 可执行文件中加载,因此,必须使用 quartus_tan 运行以下示例的脚本。Quartus II 软件 3.0 版及更高版本支持此示例中的所有命令。

自动识别时钟的优点在于可以自动应用 USE_CLK_FOR_VIRTUAL_PIN 赋值。可以将 USE_CLK_FOR_VIRTUAL_PIN 赋值与 VIRTUAL_PIN 赋值配合使用,从而将时钟设置与设计中的时钟相关联。在使用虚拟 I/O 引脚编译设计时,这将为 Quartus II Fitter 提供有关时序要求的准确信息。有关此赋值的更多信息,请参阅“Quartus II 帮助”中的“虚拟引脚时钟逻辑选项”主题。

以下示例程序将设计中的所有 I/O 引脚都设置为虚拟 I/O 引脚。此外,还在适当的情况下进行虚拟引脚时钟设置赋值。

示例代码首先对设计进行综合。然后,它尝试在创建新的时序网表之前删除所有现有时序网表。get_timing_nodes 命令从时序网表中创建两个节点集合:pin_ids 和 clk_ids。这两个集合都具有互斥性;即使时钟可能位于 I/O 引脚上,clk_ids 集合中的所有节点都不在 pin_ids 集合中。

第一个 foreach_in_collection 循环获取设计中每个引脚的名称(不包括时钟引脚),并对其进行 VIRTUAL_PIN 赋值。

第二个 foreach_in_collection 循环获取设计中每个时钟的名称。get_instance_assignment 命令检索相应的时钟设置(如果存在)。如果时钟的时钟设置存在(字符串不为空),脚本将使用时钟设置名称的值对时钟名称进行 USE_CLOCK_FOR_VIRTUAL_PIN 赋值。

load_package flow
load_package timing
load_package advanced_timing

proc make_all_pins_virtual { } {

    remove_all_instance_assignments -name VIRTUAL_PIN
    remove_all_instance_assignments -name USE_CLK_FOR_VIRTUAL_PIN

    execute_module -tool map
    catch { delete_timing_netlist }
    create_timing_netlist -post_map
    
    set pin_ids [get_timing_nodes -type pin]
    set clk_ids [get_timing_nodes -type clk]
    
    # 对设计中的每个引脚进行 VIRTUAL_PIN 赋值
    foreach_in_collection pin_id $pin_ids {

        set pin_name [get_timing_node_info -info name $pin_id]
        post_message "Making VIRTUAL_PIN assignment to $pin_name"
        set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
    }

    # 对于设计中的每个时钟,请检查它是否有
    # 相应的 CLOCK_SETTINGS 赋值。
    foreach_in_collection clk_id $clk_ids {

        set clk_name [get_timing_node_info -info name $clk_id]
        set clk_stgs [get_instance_assignment -to $clk_name -name \ 
           CLOCK_SETTINGS]

        # 如果此时钟有时钟设置,进行
        # USE_CLK_FOR_VIRTUAL_PIN 赋值
        if { ![string equal "" $clk_stgs] } {
            post_message "Making USE_CLK_FOR_VIRTUAL_PIN assignment \
                to $clk_name with value $clk_stgs"
            set_instance_assignment -to $clk_name \
                -name USE_CLK_FOR_VIRTUAL_PIN $clk_stgs
        }
    }
    export_assignments
}