Verilog中Parameter用法-常量定义与参数传递(例化传递、defparam传递)
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;
aaa@qq.com(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
);
aaa@qq.com(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
输出为:
简单验证了两种定义方式的正确性;
二、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电路如下:
通过例化结果的位宽,证明验证通过;
五、参考文献:
Verilog基础知识0(`define、parameter、localparam三者的区别及举例)
【Verilog HDL】参数(Parameter)的作用案例