📅  最后修改于: 2021-01-11 14:52:34             🧑  作者: Mango
在Verilog中,参数是常量,并且不属于任何其他数据类型,例如寄存器或网络数据类型。
常数表达式是指常数或先前定义的参数。我们无法在运行时修改参数值,但是可以使用defparam语句修改参数值。
defparam语句只能在编译时修改参数。可以使用带有模块实例化的#delay规范来修改参数值。
在Verilog中,有两种方法可以在模块实例化时覆盖模块参数值。
在defparam关键字之后,将层次结构路径指定给参数和参数的新值。这个新值应该是一个常量表达式。如果右侧表达式引用了任何参数,则应在调用defparam的模块内声明它。
模块实例参数值的分配方法似乎是将延迟分配给门实例。当实例化模块中的参数出现在模块中时,此方法将覆盖它们。使用这种格式,不能跳过参数。
常量表达式可以包含先前声明的参数。当检测到先前声明的参数发生更改时,所有依赖于该值的参数都会自动更新。
考虑一下,可以对4位加法器进行参数化以接受位数的值,并且可以在模块实例化期间传递新的参数值。因此,一个N位加法器将转换为4位,8位或16位加法器。他们就像参数是一个函数调用时传递的函数。
parameter MSB = 7; // MSB is a parameter with the constant value 7
parameter REAL = 4.5; // REAL holds the real number
parameter FIFO_DEPTH = 256,
MAX_WIDTH = 32; // Declares two parameters
parameter [7:0] f_const = 2'b3; // 2 bit value is converted into 8 bits; 8'b3
有两种类型的参数,模块和指定,并且都接受范围说明。但是,它们的大小与要存储的值一样宽,因此不需要范围指定。
它可用于覆盖模块内的参数定义,并使模块在编译时具有一组不同的参数。可以使用defparam语句修改参数。通常在参数名称中使用大写字母以立即注意到它们。
下面的模块使用参数来指定设计中的总线宽度,数据宽度和FIFO的深度,并且在实例化模块或使用defparam语句时,可以使用新值覆盖这些模块。
module design_ip ( addr, wdata, write, sel, rdata);
parameter BUS_WIDTH = 32,
DATA_WIDTH = 64,
FIFO_DEPTH = 512;
input addr;
input wdata;
input write;
input sel;
output rdata;
wire [BUS_WIDTH-1:0] addr;
wire [DATA_WIDTH-1:0] wdata;
reg [DATA_WIDTH-1:0] rdata;
reg [7:0] fifo [FIFO_DEPTH];
endmodule
在新的ANSI风格的Verilog端口声明中,我们可以声明以下参数:
module design_ip
#(parameter BUS_WIDTH=32,
parameter DATA_WIDTH=64)
(input [BUS_WIDTH-1:0] addr,
// other port declarations
);
在模块实例化期间,可以使用新值覆盖参数。第一部分是名为d0的名为design_ip的模块,其中新参数在#()中传递。
第二部分是使用称为defparam的Verilog构造来设置新的参数值。第一种方法通常用于在RTL设计中传递新参数。第二种方法在测试平台仿真中用于快速更新设计参数,而无需重新实例化模块。
module tb;
// Module instantiation override
design_ip #(BUS_WIDTH = 64, DATA_WIDTH = 128) d0 ( [port list]);
// Use of defparam to override
defparam d0.FIFO_DEPTH = 128;
endmodule
模块计数器具有两个参数N和DOWN ,它们声明为默认值2和0。
N控制输出中的位数,有效控制计数器的宽度。默认情况下,它是一个2位计数器。
参数DOWN控制计数器是递增还是递减。由于参数设置为0,因此计数器将减少。
2位向上计数器
module counter
# ( parameter N = 2, parameter DOWN = 0)
(input clk, input rstn, input en, output reg [N-1:0] out);
always @ (posedge clk) begin
if (!rstn) begin
out <= 0;
end else begin
if (en)
if (DOWN)
out <= out - 1;
else
out <= out + 1;
else
out <= out;
end
end
endmodule
模块计数器使用N实例化为2,即使它不是必需的,因为默认值为2。
在模块实例化期间不传递DOWN。并且它采用默认值0,使其递增计数。
module design_top (input clk, input rstn, input en, output [1:0] out);
counter #(.N(2)) u0 (.clk(clk), .rstn(rstn), .en(en));
endmodule
默认参数用于实现计数器,其中N等于2,使其成为2位计数器,而DOWN等于0,使其成为递增计数器。计数器的输出在顶层未连接。
4位递减计数器
在这种情况下,模块计数器以N实例化为4,使其成为4位计数器。在模块实例化期间,将DOWN的值传递为1,因此实现了递减计数器。
module design_top (input clk, input rstn, input en, output [3:0] out);
counter #(.N(4), .DOWN(1))
u1 (.clk(clk), .rstn(rstn), .en(en));
endmodule
这些参数用于提供时间和延迟值,并使用specparam关键字声明。允许在指定的块和主模块体内使用。
// Use of specify block
Specify
specparam t_rise = 200, t_fall = 150;
specparam clk_to_q = 70, d_to_q = 100;
endspecify
// Within main module
module my_block ( );
specparam dhold = 2.0;
specparam ddly = 1.5;
parameter WIDTH = 32;
endmodule
Specify parameter | Module parameter |
---|---|
Specify the specparam keyword declares parameter. | The module parameter is declared by parameter. |
It can be declared inside a specific block or within the main module. | It can only be declared within the main module. |
This parameter may be assigned specparams and parameters. | This may not be assigned specparams. |
SDF can be used to override values. | Instance declaration parameter values or defparam can be used to override. |
笔记
以下是有关Verilog参数的一些重要说明,例如: