在设计中引入参数化设计可以大大提高模块的可重用性以及节约资源,下面用点灯来记录一下几种常见的设计方式和例化方式。
一、在设计中引入parameter参数
底层模块设计
实现500ms时,led自动翻转,led的闪烁周期是1s,亮500ms,灭500ms。
module param_design
(
input wire clk ,
input wire rst_n ,
output reg led
);
reg [24:0] cnt;
parameter CNT_MAX = 25'd24_999_999;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 25'd0;
else if(cnt == CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
led <= 1'b1;
else if(cnt == CNT_MAX)
led <= ~led;
else
led <= led;
endmodule
1、defparam方式传入数据
在tb中改变CNT_MAX的数值可以大大减少仿真时等待时间。
`timescale 1ns/1ns
`define clk_period 20
module param_design_tb;
//============================<端口>==============================
reg clk;
reg rst_n;
wire led;
//================================================================
//== 模块例化
//================================================================
param_design param_design_inst_0
(
.clk (clk),
.rst_n (rst_n),
.led (led)
);
defparam param_design_inst_0.CNT_MAX = 25'd24_99;
//================================================================
//== 时钟信号
//================================================================
initial clk = 1'b1;
always #(`clk_period/2) clk = ~clk;
//================================================================
//== 设计输入信号
//================================================================
initial begin
rst_n = 0;
#201;
rst_n = 1;
#20000000;
$stop;
end
endmodule
仿真结果
根据defparam传入的24_99可知2500个时钟周期翻转一次,测试结果验证了设计的正确性。
![](https://i-blog.csdnimg.cn/blog_migrate/2300e489aeb2cd01339bde5b9541180b.png)
实用顶层设计
defparam应用在顶层时,可以提高模块的可重用性。该顶层实现了两个led的亮灭。
module led_top
(
input wire clk ,
input wire rst_n ,
output wire [1:0] led
);
param_design param_design_inst0
(
.clk (clk),
.rst_n (rst_n),
.led (led[0])
);
defparam param_design_inst0.CNT_MAX = 25'd24_999_999; //500ms翻转
param_design param_design_inst1
(
.clk (clk),
.rst_n (rst_n),
.led (led[1])
);
defparam param_design_inst1.CNT_MAX = 25'd12_499_999;//250ms翻转
endmodule
2、例化时传入数据
还是同样的模块设计,采用在例化时传入数据。(要特别注意这种方式的书写方式)
`timescale 1ns/1ns
`define clk_period 20
module param_design_tb;
//============================<端口>==============================
reg clk;
reg rst_n;
wire led;
//================================================================
//== 模块例化
//================================================================
param_design
#(
.CNT_MAX(25'd24_99)
)
param_design_inst_0
(
.clk (clk),
.rst_n (rst_n),
.led (led)
);
//defparam param_design_inst_0.CNT_MAX = 25'd24_99;
//================================================================
//== 时钟信号
//================================================================
initial clk = 1'b1;
always #(`clk_period/2) clk = ~clk;
//================================================================
//== 设计输入信号
//================================================================
initial begin
rst_n = 0;
#201;
rst_n = 1;
#20000000;
$stop;
end
endmodule
二、定义端口时添加一个数据输入端口
module param_design
(
input wire clk ,
input wire rst_n ,
input wire [24:0] CNT_MAX ,
output reg led
);
reg [24:0] cnt;
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt <= 25'd0;
else if(cnt == CNT_MAX)
cnt <= 25'd0;
else
cnt <= cnt + 1'b1;
always@(posedge clk or negedge rst_n)
if(!rst_n)
led <= 1'b1;
else if(cnt == CNT_MAX)
led <= ~led;
else
led <= led;
endmodule
1、tb数据传入
`timescale 1ns/1ns
`define clk_period 20
module param_design_tb;
//============================<端口>==============================
reg clk;
reg rst_n;
reg [24:0] CNT_MAX;
wire led;
//================================================================
//== 模块例化
//================================================================
param_design param_design_inst_0
(
.clk (clk),
.rst_n (rst_n),
.CNT_MAX (25'd24_99),
.led (led)
);
//defparam param_design_inst_0.CNT_MAX = 25'd24_99;
//================================================================
//== 时钟信号
//================================================================
initial clk = 1'b1;
always #(`clk_period/2) clk = ~clk;
//================================================================
//== 设计输入信号
//================================================================
initial begin
rst_n = 0;
#201;
rst_n = 1;
#20000000;
$stop;
end
endmodule
2、仿真结果
验证方法室可行的。
![](https://i-blog.csdnimg.cn/blog_migrate/9c6a7a00f8b72bdf82a58564d2d30e33.png)
三、总结
总体分为两种引入方式,一种是使用parameter参数,一种是添加端口。
采用第一种方式时,可以采取两种方式传入数据,各有优缺点吧,defparam书写起来简单,但是模块例化过多时容易晕,而例化时传入则非常容易区分和维护,但要注意其书写方式,比较容易出现语法错误。
二是定义端口时添加一个input数据输入端口。