Verilog HDL 的parameter既不属于变量,也不属于网络,而是常量。parameter有两种类型:模块参数(module parameter)和指定参数(specify parameter),这两类参数都接受位宽范围说明。重新声明已由网络、参数或变量声明的名称是非法的。
如下所示为模块参数(parameter、localparam)的标准声明:
参数赋值列表(list_of_param_assignments)应是以逗号分隔的赋值列表,其中赋值的右侧应是常量表达式,即只包含常量数字和先前定义的参数的表达式。
list_of_param_assignments 可以作为一组 module_items 出现在模块中,也可以在模块声明中的 module_parameter_port_list 中出现(后文详细描述)。
parameter代表常量,因此在运行时修改parameter的值是非法的。不过,模块参数可以在编译时修改,使其值与声明赋值中指定的值不同,这样就可以定制模块实例。Verilog规定可以使用 defparam 语句或在模块实例语句中修改参数。参数的典型用途是指定变量的延迟和宽度。有关参数值传递的详情,我们后文再详细介绍。
模块参数可以有类型说明和位宽范围说明。模块参数的类型和位宽范围应符合以下规则:
- 没有类型或范围说明的参数声明,应默认为分配给参数的最终常数值类型和范围。
- 有范围说明但无类型说明的参数,其范围应为参数声明的范围,且无符号。符号和范围不受数值覆盖的影响。
- 有类型说明但无范围说明的参数应为指定类型。有符号参数在被任何值覆盖后,默认值应为分配给该参数的最终值的范围。
- 有符号类型说明和范围说明的参数应为有符号参数,并应是其声明的范围。符号和范围不受数值覆盖的影响。
- 无范围规范、有符号类型规范或无类型规范的参数,其隐含范围的 lsb 等于 0,msb 等于分配给参数的最终值位宽大小减1。
- 无范围规范、有符号类型规范或无类型规范的参数,如果分配给它的最终值没有位宽大小,则其隐含范围的 lsb 应等于0,msb 应至少等于31。
-允许对非实数类型的参数进行位选择和部分选择。
Verilog标准说了这么多参数规定,头都晕了,我们还是看几个具体的正确用法吧!
以上这些parameter的声明用法都是正确的,大家根据需求喜欢用哪种就用哪种吧~
接下来我们还要说一下局部参数:
Verilog HDL 局部参数localparam除了不能直接通过 defparam 语句或模块实例参数值赋值修改外,其它与参数parameter用法完全相同。局部参数可以分配包含参数的常量表达式,这些常量表达式可以通过 defparam 语句或模块实例参数值分配进行修改,且允许对非实数类型的局部参数进行位选择和部分选择。
接下来我们再说一下指定参数(specparam),其标准声明语法为:
关键字 specparam 声明了一种特殊类型的参数,该参数仅用于提供定时和延迟值,但可以出现在任何未分配给参数的表达式中,也不属于声明范围规范的一部分。指定参数(也称 specparam)既可以在指定块(specify block)中使用,也可以在主模块体中使用。
在指定块外声明的指定参数应在引用前声明。指定参数的赋值可以是任何常量表达式。指定参数可以作为常量表达式的一部分,用于随后的指定参数声明。与模块参数不同,指定参数不能在语言内部修改,但可以通过 SDF 注释进行修改。
指定参数(specparam)和模块参数(parameter、localparam)不可互换。此外,模块参数不得分配给包含任何指定参数的常量表达式。表1总结了这两种参数声明的区别:
表1:模块参数与指定参数区别
指定参数可以有范围规定。指定参数的范围应符合以下规则:
- 没有范围说明的specparam声明,在应用任何值覆盖后,默认值应为分配给specparam的最终值的范围。
- 有范围说明的specparam应为specparam声明的范围。该范围不受参数值覆盖的影响。
比如下面的例子:
关键字 specify 和 endspecify 之间声明了四个指定参数。第一行声明的指定参数 tRise_clk_q 和 tFall_clk_q 值分别为 150 和 200;第二行声明的指定参数 tRise_control 和 tFall_control 值分别为 40 和 50。
再比如下面的例子:
点赞加关注博主(ID:FPGA小飞)的博文,咱们一起系统学习verilog最终标准IEEE Std 1364-2005吧!