一、参数的用途
Veilog中参数的关键词为parameter、localparam,它们在verilog模块的主要用途有两个:第一是便于阅读;第二是便于进行模块的修改。
便于阅读很好理解,将代码中常用的数值参数化,用对应的逻辑含义来进行参数命名,这样变提高了代码的逻辑可读性。
便于修改主要是两个方面,一方面是在要对代码中多处重复出现的同一值进行修改时,容易出现漏改错改的现象,使用参数后,便只用修改参数声明时处的值便可以进行统一修改,即提高了效率又保证了准确性;第二方面是在进行模块调用的时候,不同的设计中可能需要不同信号位宽,信号默认值等性质,引入参数后便使得模块的特性变为可变的,提高了模块的通用性。
二、parameter的声明和传递
在介绍参数的声明和传递之前,先弄清参数的本质,在Verilog中参数的本质就是对数值的替代,EDA工具在对电路描述代码中进行仿真和综合时,就是将参数原位替换成对应的数值后再进行处理的。
2.1 参数的声明
参数声明的语法格式:
list_of_param_assignments(参数赋值列表,后同)为逗号分隔的赋值列表,其中赋值的右侧应为常量表达式,仅包含常数和先前定义的参数的表达式;
parameter参数的一个要点是其声明的位置,在不同的位置定义,其使用范围是不同的。使用代码2-1来进行介绍,parameter在Verilog模块中存在两个声明位置,一个是在模块名和模块端口列表之间进行参数声明,在该处声明后的参数可在模块端口列表及模块的内部描述逻辑中使用,其具体声明方式如代码中的W1、W2部分所示;另一个声明位置则是在模块内部的任意地方,在模块内部声明的参数则不能在端口列表中使用。
module parameter_example
#( parameter W1 = 10,
parameter W2 = 5)
(input [W1-1:0] a,
output [W2-1:0] b);
parameter VALUE1 = 5;
parameter HIGH = 1'b1;
parameter LOW = 1'b0;
......
endmodule
代码2-1
需要特别指出的是,上述代码仅为说明在端口和内部声明parameter的区别,而实际上上述代码中模块内部的parameter是伪parameter,它们实际上已经变成了localparam。原因是Verilog标准规定:
如果module_parameter_port_list(模块参数端口列表)中出现任何param_assignments(参数声明),则模块中出现的任何param_assignments都将成为本地参数,并且将不能通过任何方法来改变其localpara属性。
举例,在vivado中会产生如下警告:
parameter表示常数,在电路运行时修改它们的值是非法的。不过,可以在编译时修改模块参数(parameter),使其值与声明赋值中指定的值不同,通过使用 defparam 语句或模块实例语句(见示例代码2-2)来实现。
模块实例语句参数传递的形式如代码2-2中的#部分所示,除了以#开始以及括号后没有分号,其他与端口的形式一致。有两点需要说明,第一是不管在哪个位置进行声明的parameter,其在模块调用时均可进行参数传递(但是只要模块头部声明了parameter,则模块内部的parameter则当作localparam,不能对其进行重写);第二点是对未进行传递的参数来说,其数值为其声明时的数值。
module parameter_trans_example
(input [8:0] a,
output [3:0] b);
parameter_example
#(.W1(9),
.W2(4),
) u_parameter_example
( .a(a),
.b(b)
);
......
endmodule
代码2-2
2.2 localparam的声明
localparam的声明方式与模块内部的parameter的声明方式一样,此处不再重复。这里主要讲讲localparam与parameter的区别,第一是localparam只能在模块内部声明;第二是parameter能够在例化的时候或者使用 defparam 语句进行修改而localparam不能;不过localparam参数可以引用(在其前面声明的)parameter参数,其值便可间接随parameter参数改变而改变。其实我认为parameter的应用场景完全能够覆盖localparam,由于学识和眼界所限制,尚不明白localparam的独特用处或者或存在历史背景,等以后有新认知再补充。
三、参考资料
1. IEEE Std 1364-2005。