天天看点

Verilog parameter 参数

文章目录

        • 语法
        • 注意
        • 示例:支持递增或递减的计数器
        • localparam

Verilog支持使用参数来指定数据位宽或表示某些有特殊含义的常量,可以便于实现模块的通用性和以后的维护,对于同一个模块,可以通过指定不同的参数值来实现不同的功能,比如通过改变加法器模块的数据位宽来实现4/8/16位数据操作,类似函数调用时传入的不同参数。

语法

例如:

parameter msb = 7;                  // unsigned value 7
parameter e = 25, f = 9;            // defines two unsigned value
parameter r = 5.7;                  // real parameter
parameter byte_size = 8,		    //unsigned value
          byte_mask = byte_size - 1;// = 7
parameter average_delay = (r + f) / 2;
parameter signed [3:0] mux_selector = 0;//signed 
parameter real r1 = 3.5e17;	//si
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]
           

注意

  • 如果参数在声明时没有指定type和range,则默认为最后赋值给参数的type和range;
  • 如果参数有指定range,但没有type,则它的符号默认为unsigned,并且range和符号都不会被后面的声明所覆盖;
  • 如果参数有指定range,并且指定为有符号type,则它的range和符号都不会被后面的声明所覆盖;

定义为parameter类型的数据是常量,不能对它进行赋值操作。

示例#:支持不同数据宽度的FIFO模块

// Verilog 1995 style port declaration
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];

// Design code goes here ...
endmodule

//Verilog 2001 style port declaration
module design_ip #(
    parameter BUS_WIDTH=32,
    parameter DATA_WIDTH=64
)(
    input [BUS_WIDTH-1:0] addr,
    // Other port declarations
);
           

参数的传入可以通过以下两种方式,第二种方式灵活性更高,一般用于Testbench文件。

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
           

如果以上两种方式同时存在,并且有多个defparam定义同一个参数,则以最后一个defparam为准。

示例:支持递增或递减的计数器

通过指定数据宽度和递增或递减,可以实现任意数据宽度的递增或递减计数器。

module counte #(
    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
           

宽度为2的计数器,由于没有指定DOWN的值,则默认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
           

4位宽度的递减计数器

module design_top (   
    input clk,
    input rstn,
    input en,
    output [3:0] out
);

counter #(
    .N(4)
    .DOWN(1)
)u0(
    .clk(clk),
    .rstn(rstn),
    .en(en)
);

endmodule
           

localparam

localparam和parameter非常类似,只不过localparam不能直接进行传递,只能通过parameter来进行间接传递参数。localparam一般用于状态机状态定义,或其他间接性参数。

例如:

parameter       X = 3;
localparam      Y = X*2;
           

FROM:verilog-parameters