一、写在前面
本专栏为作者在 【数字IC手撕代码】 【数字IC笔试面经分享】 【数字IC工具解析】 以外开设的第四个独立专栏,旨在学习并提供有关Verilog硬件描述语言中非基础性的高阶语法特性知识,因本身专栏的独特定位,因此作者并不会涉及基础Verilog语言如阻塞式非阻塞赋值,过程块,数据类型等内容;同时受限于作者知识有限,本专栏也不会涉及System Verilog的相关内容,若按照IEEE的相关标准来看,本专栏将会聚焦Verilog-2005,即“IEEE Std 1364™-2005”以及之前的有关内容,提供相关的IC设计领域语法特性。以下为Verilog的进阶框图,有更多学习需求的读者可以检索相关英文标准进行学习。
二、什么是parameter
在IEEE Standard2005中,parameter处于第四章“Data Types”的第十节,parameter是Verilog数据类型中的一种,不过与常规的reg或wire不同,parameter不是变量,而是常量。
parameter因其常量特性,无法在仿真的过程中进行修改,不过在编译的时候,我们可以使用defparam对其进行修改。
三、如何声明parameter
parameter可以被声明为integer,real,realtime,time四种类型
也可以在parameter后加上signed使其变为有符号数
甚至可以声明parameter的位宽或者使用表达式来计算它的实际值
以下的例子对于声明parameter来说都是合法的。
parameter msb = 7; // defines msb as a constant value 7 parameter e = 25, f = 9; // defines two constant numbers parameter r = 5.7; // declares r as a real parameter parameter byte_size = 8, byte_mask = byte_size - 1; parameter average_delay = (r + f) / 2; parameter signed [3:0] mux_selector = 0; parameter real r1 = 3.5e17; parameter p1 = 13'h7e; parameter [31:0] dec_const = 1'b1; // value converted to 32 bits parameter newconst = 3'h4; // implied range of [2:0] parameter newconst = 4; // implied range of at least [31:0]
四、如何修改parameter的值
4.1 defparam语句修改parameter值
如果想修改已经定义好的parameter的值,我们可以使用defparam语句来进行修改,以下两个module,在子模块中A和B同时被声明为了位宽为3,大小为2的paramter常量,这个值在顶层模块中通过defparam的索引,最终同时被修改为了3.1415并进行了打印
module foo(a,b); real r1,r2; parameter [2:0] A = 3'h2; parameter B = 3'h2; initial begin r1 = A; r2 = B; $display("r1 is %f r2 is %f",r1,r2); end endmodule // foo
module bar; wire a,b; defparam f1.A = 3.1415; defparam f1.B = 3.1415; foo f1(a,b); endmodule // bar
4.2 例化端口时修改parameter的值
除了defparam以外,我们还可以通过端口例化的形式进行修改,以下的module是一个省略了具体逻辑功能的SRAM模块,通过“#”在端口声明的parameter变量可以在例化的时候进行修改。
module myram #( parameter WORD_SIZE = 1, parameter ADDR_SIZE = 1 ) ( input wire [ADDR_SIZE-1:0] addr, inout wire [WORD_SIZE-1:0] data, // ... );
module myram_tb; myram #( .ADDR_SIZE(2), .WORD_SIZE(2) ) top ( /* wires */ )
五、parameter与localparameter的区别
谈到parameter,一个不可能回避的问题就是区分parameter与localparameter。他们的区别如下
parameter可以用于参数传递,因此它在顶层模块中可以被defparam修改
localparam不可以用于参数传递,所以它在顶层模块中不能被defparam修改
根据他们的特点,一般在module内部进行状态机的声明的时候,我们更多的选择localparam,而在涉及到位宽可变的IP设计时,我们会选择使用parameter变量。
六、往期【Verilog】高级教程文章
多维数组:灭霸打个响指的功夫,看懂Verilog多维数组
clog2系统函数: 关于Verilog自动计算位宽的系统函数$clog2,这些是你不得不知道的
UDP用户原语:玩转UDP用户原语,这篇文章就够了
$monitor系统函数:放学前的最后几分钟,看懂Verilog中的monitor系统函数
generate语句:一把王者的时间,学会Verilog中的generate语句
parameter常量:玩转parameter与localparameter,这篇文章就够了
inout双向端口:通俗易懂的带你解读inout双向端口
task与function区别:芯片人必会的task与function区别详解