Verilog中用parameter来定义常量,即用parameter来定义一个标识符来代表一个常量,称为符号常量,即标识符形式的常量,采用标识符代表一个常量可以提高程序的可读性和可维护性。另一个很有用的用途就是可以利用defparam或者在模块实例化的时候进行参数传递(即重写)

一、parameter声明常量

    parameter定义常量,可以定义在模块内部或外部;常用于定义位宽或时间延迟(易变),此处以加一个常数的电路进行示例,如下:

定义方式为: parameter 标识符 = (位宽)常数;// 位宽默认为32位,如果指定位宽则以指定值为准

parameter在模块内部定义常量:

module param_idef(
    input clk,
    input [2:0]din,
    output reg [3:0]sum
    );

parameter ADD = 2'd1;
always@(posedge clk)
begin
    sum <= din+ADD;
end
endmodule

parameter在模块外部定义常量:

module param_odef
#(parameter ADD2 = 2'd1)
(
    input clk,
    input [2:0]din,
    output reg [3:0]sum
    );

always@(posedge clk)
begin
    sum <= din+ADD2;
end
endmodule

 测试文件如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: CLL
// 
// Create Date: 2020/02/22 12:22:02
// Design Name: 
// Module Name: param_tsb
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module param_tsb(

    );
//
reg clk;
reg [2:0]din;
wire [3:0]sum1,sum2;
//
initial
begin
    clk = 1'b1;
    forever #10 clk = ~clk;
end
//
initial
begin
    din = 3'd3;
    #80 din = 3'd1;
    #40 din = 3'd0;
end

param_idef inst1(
    .clk(clk),
    .din(din),
    .sum(sum1)
);
param_odef inst2(
    .clk(clk),
    .din(din),
    .sum(sum2)
);
endmodule

输出为:

clear标签 python parameter标签_赋值

简单验证了两种定义方式的正确性;

二、parameter用于提高程序的可读性和可维护性

可维护性:

与软件编程类似,通过改变parameter定义的常量值,实现代码所有用到这一标识符部分的值,便于修改与维护;

可读性:

标识符按照常量实际意义取名,增强可读性;

三、参数传递(重写)

子模块利用parameter定义常量,被顶层调用时默认为子模块中参数;

模块调用修改参数:

参数改变时,可在顶层模块调用子模块时进行参数修改;如:

module Top(...);//这是一个顶层模块
         Decode #(4,0) U_D1(); //使得Width = 4, Polarity = 0;
         Decode #(5) U_D2(); //使得 Width = 5,Polarity 不变,即为1;
     endmodule

     module Decode(A,F);    //这是一个子模块
         parameter Width = 1, Polarity = 1;
         ......
     endmodule

利用defparam修改参数:

参数改变时,也可在利用defparam进行参数修改;如:

module Top(...);//这是一个顶层模块
defparam    U_D1.Width = 4;
         defparam    U_D1.Polarity = 0;//使得U_D1的Width = 4, Polarity = 0;        defparam    U_D2.Width = 5;//使得U_D2的Width = 5,Polarity 不变,即为1;
         Decode U_D1();
         Decode U_D2();
     endmodule     module Decode(A,F);    //这是一个子模块
         parameter Width = 1, Polarity = 1;
         ......
     endmodule

四、仿真验证:

设计一个位宽可变半加器,默认位宽为4bit,并且位宽可调;

半加器设计如下:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: CLL
// 
// Create Date: 2020/02/22 14:05:33
// Design Name: 
// Module Name: counter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module counter
#(parameter W = 3)
(
    input [W:0]din1,
    input [W:0]din2,
    output [W:0]sum,
    output cout
    );
assign {cout,sum} = din1+din2;
endmodule

修改参数仿真如下:

例化1为默认参数,位宽应为4;

例化2实例化时传递参数,传递位宽为6;(注意参数传递位置,在模块名称counter之后,实例名称istN之前)

例化3利用defparam传递参数,传递位宽为6;(注意参数赋值与例化时端口赋值一样,可以位置赋值,也可以按照名称赋值;仿真采用名称赋值;也可部分参数赋值,未赋值参数保持默认)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: CLL
// 
// Create Date: 2020/02/22 14:10:50
// Design Name: 
// Module Name: count_inst
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module count_inst(
    input [3:0]din1,
    input [3:0]din1_2,
    input [5:0]din2,
    input [5:0]din2_2,
    input [5:0]din3,
    input [5:0]din3_2,
    output [3:0]sum1,
    output cout1,
    output [5:0]sum2,
    output cout2,
    output [5:0]sum3,
    output cout3
    );
// adder1 4bit,默认
    counter inst1(
        .din1(din1),
        .din2(din1_2),
        .sum(sum1),
        .cout(cout1)
    );
// adder2 6bit,例化传递
    counter  #(.W(5)) inst2(
        .din1(din2),
        .din2(din2_2),
        .sum(sum2),
        .cout(cout2)
    );
// adder3 6bit,defparam传递
defparam inst3.W = 5;
    counter inst3(
        .din1(din3),
        .din2(din3_2),
        .sum(sum3),
        .cout(cout3)
    );

endmodule

对应RTL电路如下:

clear标签 python parameter标签_标识符_02

通过例化结果的位宽,证明验证通过;

五、参考文献:

Verilog 参数Parameter篇

Verilog中的parameter

Verilog基础知识0(`define、parameter、localparam三者的区别及举例)

【Verilog HDL】参数(Parameter)的作用案例