Verilog参数定义与仿真模块中的参数修改

文章目录

参数方式定义参数的优势

当一个模块被另一个模块引用例化时,高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块,而不用单独为只有参数不同的多个模块再新建文件。

参数覆盖有 2 种方式:1)使用关键字 defparam,2)例化时修改:带参数值模块例化。

使用参数的方式定义常量有很多好处,如:

  1. 我们在RTL代码中实例化该模块时,如果需要两个不同计数值的计数器我们不必设计两个模块,而是直接修改参数的值即可

  2. 另一个好处是在编写Testbench进行仿真时我们也需要实例化该模块,但是我们需要仿真至少0.5s的时间才能够看出到led_out效果,这会让仿真时间很长,也会导致产生的仿真文件很大,所以我们可以通过直接修改参数的方式来缩短仿真的时间而看到相同的效果,且不会影响到RTL代码模块中的实际值,因为parameter定义的是局部参数,所以只在本模块中有效。

为了更好的区分,参数名我们习惯上都是大写。

rtl模块中的参数定义

模块名后定义参数

格式:

#(

parameter CNT_MAX = 25'd100,

parameter CNT_MAX_5 = CNT_MAX - 5

)


#+()

()内用parameter 参数名 = XX

()内的参数间用逗号分隔,最后一个参数后没有逗号

举例:

Verilog 复制代码
module test
#(
parameter CNT_MAX = 25'd100,
parameter CNT_MAX_5 = CNT_MAX - 5
 )
 (
 input wire sys_clk , //系统时钟50MHz
 input wire sys_rst_n , //全局复位

 output reg led_out //输出控制led灯
 );

parameter定义参数

格式:

parameter 参数名 = XX;

不同参数定义用分号结束语句

举例:

verilog 复制代码
//=========================< Parameter >==============================
	parameter 				CNT_MAX		=	25'd100		    	;
	parameter 				CNT_MAX_5 	= 	CNT_MAX - 5			;

仿真模块中的参数修改

例化时修改

格式:

#(

.CNT_MAX (25'd24 ),

.CNT_MAX_5(25'd19)

)


#+()

()内用 .参数名(修改后的数值)

()内的参数间用逗号分隔,最后一个参数后没有逗号

举例:

Verilog 复制代码
test
 #(
 .CNT_MAX (25'd24 ),
 .CNT_MAX_5(25'd19)
 )
 counter_inst(
 .sys_clk (sys_clk ), //input sys_clk
 .sys_rst_n (sys_rst_n ), //input sys_rst_n

 .led_out (led_out ) //output led_out
 );

也可以去掉参数名,按顺序进行参数例化(但是不建议哦,不方便阅读):

verilog 复制代码
#(
 25'd24,
 25'd19
 )

defparam修改

格式:

defparam counter_inst.CNT_MAX = 25'd24 ;

defparam counter_inst.CNT_MAX_5 = 25'd19 ;


defparam 模块例化的参数名.模块中的参数 = 数值;

不同修改参数用分号结束语句

举例:

verilog 复制代码
//=========================< Parameter >==============================
defparam 			counter_inst.CNT_MAX	=		25'd24	    	;
defparam 			counter_inst.CNT_MAX_5	=		25'd19			;
	
 test counter_inst(
	.sys_clk 	(sys_clk 	), //input sys_clk
	.sys_rst_n 	(sys_rst_n 	), //input sys_rst_n
	
	.led_out 	(led_out 	) //output led_out
 );

总结与说明

  1. 参数定义 (两种方法)和仿真模块中的参数修改(两种方法)可以选择使用,共四种对应写法。
参数定义 参数修改
模块名后定义参数 例化时修改
模块名后定义参数 defparam修改
parameter定义参数 例化时修改
parameter定义参数 defparam修改
  1. 如果rtl模块中既有模块名后定义参数 又有parameter定义参数 ,用defparam修改 会报错,用例化时修改 不报错。具体看建议与区别部分(4)

  2. 使用建议用模块名后定义参数例化时修改这一对应方案。

rtl中:

Verilog 复制代码
module test
#(
parameter CNT_MAX = 25'd100,
parameter CNT_MAX_5 = CNT_MAX - 5
 )
 (
 input wire sys_clk , //系统时钟50MHz
 input wire sys_rst_n , //全局复位

 output reg led_out //输出控制led灯
 );

仿真代码中:

Verilog 复制代码
test
 #(
 .CNT_MAX (25'd24 ),
 .CNT_MAX_5(25'd19)
 )
 counter_inst(
 .sys_clk (sys_clk ), //input sys_clk
 .sys_rst_n (sys_rst_n ), //input sys_rst_n

 .led_out (led_out ) //output led_out
 );

附录:测试代码

rtl部分:

verilog 复制代码
module test
#(
parameter CNT_MAX = 25'd100,
parameter CNT_MAX_5 = CNT_MAX - 5
 )
 (
 input wire sys_clk , //系统时钟50MHz
 input wire sys_rst_n , //全局复位

 output reg led_out //输出控制led灯
 );

/* 	//=========================< Parameter >==============================
	parameter 				CNT_MAX		=	25'd100		    	;
	parameter 				CNT_MAX_5 	= 	CNT_MAX - 5			;
	 */
 reg [24:0] cnt; 

 //cnt:计数器计数,当计数到CNT_MAX的值时清零
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 cnt <= 25'b0;
 else if(cnt == CNT_MAX)
 cnt <= 25'b0;
 else
 cnt <= cnt + 1'b1;

 //led_out:输出控制一个LED灯,每当计数满标志信号有效时取反
 always@(posedge sys_clk or negedge sys_rst_n)
 if(sys_rst_n == 1'b0)
 led_out <= 1'b0;
 else if(cnt == CNT_MAX_5)
 led_out <= ~led_out;

 endmodule

仿真部分:

verilog 复制代码
`timescale 1ns/1ns
module tb_test();

//reg define
reg sys_clk;
reg sys_rst_n;

//wire define
wire led_out;

 //初始化输入信号
 initial begin
 sys_clk = 1'b1;
 sys_rst_n <= 1'b0;
 #20
 sys_rst_n <= 1'b1;
 end

 //sys_clk:每10ns电平翻转一次,产生一个50MHz的时钟信号
 always #10 sys_clk = ~sys_clk;
 
/* 	//=========================< Parameter >==============================
	defparam 			counter_inst.CNT_MAX	=		25'd25	    	;
	defparam 			counter_inst.CNT_MAX_5	=		25'd20			;
 */

 //---------------------flip_flop_inst----------------------
 test
/*  #(
 25'd24,
 25'd19
 )
  */
 #(
 .CNT_MAX (25'd23 ),
 .CNT_MAX_5(25'd20)//实例化带参数的模块时要注意格式,当我们想要修改常数在
 //当前模块的值时,直接在实例化参数名后面的括号内修改即可
 )
 counter_inst(
	.sys_clk 	(sys_clk 	), //input sys_clk
	.sys_rst_n 	(sys_rst_n 	), //input sys_rst_n
	
	.led_out 	(led_out 	) //output led_out
 );

 endmodule
相关推荐
芯路行者6 天前
4.4 HDLBits —— 更多时序逻辑电路
fpga开发·verilog·fpga·hdlbits
芯路行者7 天前
7 HDLBits —— 验证:编写测试激励文件
fpga开发·verilog·fpga·hdlbits
芯路行者7 天前
4.1 HDLBits —— 时序逻辑电路之锁存器与触发器
fpga开发·verilog·fpga·hdlbits
芯路行者7 天前
5 HDLBits —— 构建更大的电路
fpga开发·verilog·fpga·hdlbits
芯路行者7 天前
4.3 HDLBits —— 时序逻辑电路之移位寄存器
fpga开发·verilog·fpga·hdlbits
芯路行者7 天前
4.2 HDLBits —— 时序逻辑电路之计数器
fpga开发·verilog·fpga·hdlbits
鬼手点金9 天前
FPGA常用型号参考
fpga开发·verilog·vivado·xilinx·vhdl·altera·lattice
我爱C编程13 天前
基于FPGA的DSB调制解调系统verilog开发
fpga开发·verilog·fpga·dsb
北方孤寂的灵魂1 个月前
关于AXI协议详解
verilog·systemverilog·sv·数字验证
FPGA小迷弟2 个月前
vivado中的AXI Interconnect到底应该怎么用,他的底层原理是什么,一篇文档全部理清楚!!!
网络协议·tcp/ip·fpga开发·verilog·fpga