define, parameter, localparam, specparam, defpara用法简析

1.概述

在Verilog中,parameter既不属于变量范畴也不属于线网范畴,经常用来定义一个标志符代表一个常量,当一个模块被另一个模块引用例化时,高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块,而不用单独为只有参数不同的多个模块再新建文件。通过使用参数,可以提高程序的可读性、可复用性和可维护性。

目前常用的参数主要分为两大类:module参数(parameter和localparam)和specify参数(specparam)

`define:        作用 -> 常用于定义常量可以跨模块、跨文件;

                        范围 -> 整个工程;

parameter:       作用 -> 常用于模块间参数传递;

                        范围 -> 本module内有效的定义;

localparam        作用 -> 常用于状态机的参数定义;

                        范围 -> 本module内有效的定义,不可用于参数传递;
                        
specparam         作用->关键字 specparam 在 specify 块中定义延迟数值常量,然后赋值给路径延迟

				        范围->specparam 定义的常量只能在 specify 块内部使用


				        其中: Verilog specify 块语句:https://www.runoob.com/w3cnote/verilog2-specify.html

宏定义 'define

若直接在module中通过localparam或者parameter进行参数定义的话,会带来两个问题:

  • 代码长度增加,不够美观;

  • 不利于参数和代码修改;

用一个指定的标识符(即名字)来代表一个字符串,它的一般形式为:

`define 标识符(宏名) 字符串(宏内容)    

如:`define signal string

它的作用是指定用标识符signal来代替string这个字符串,在编译预处理时,把程序中在该命令以后所有的signal都替换成string。这种方法使用户能以一个简单的名字代替一个长的字符串,也可以用一个有含义的名字来代替没有含义的数字和符号,因此把这个标识符(名字)称为“宏名”,在编译预处理时将宏名替换成字符串的过程称为“宏展开”。

verilog中define八点说明:原文链接

  • 宏名建议使用大写字母,以与变量名相区别

  • 'define命令可以出现在模块定义里面,也可以出现在模块定义外面。宏名的有效范围为定义命令之后到原文件结束。通常,`define命令写在模块定义的外面,作为程序的一部分,在此程序内有效

  • 在引用已定义的宏名时,必须在宏名的前面加上符号“`”,表示该名字是一个经过宏定义的名字

  • 宏定义是用宏名代替一个字符串,也就是作简单的置换,不作语法检查

  • 宏定义不是Verilog HDL语句,不必在行末加分号

  • 在进行宏定义时,可以引用已定义的宏名,可以层层置换

  • 宏名和宏内容必须在同一行中进行声明。如果在宏内容中包含有注释行,注释行不会作为被置换的内容

parameter

parameter是Verilog数据类型中的一种,不过与常规的reg或wire不同,parameter不是变量,而是常量。
parameter因其常量特性,无法在仿真的过程中进行修改,不过在编译的时候,我们可以使用defparam对其进行修改。

  • parameter可以被声明为integer,real,realtime,time四种类型
  • 也可以在parameter后加上signed使其变为有符号数
  • 可以声明parameter的位宽或者使用表达式来计算它的实际值

以下的例子对于声明parameter来说都是合法的。

parameter msb = 7; // defines msb as a constant value 7,
parameter e = 25, f = 9; // defines two constant numbers
parameter r = 5.7; // declares r as a real parameter
parameter byte_size = 8,
byte_mask = byte_size - 1;
parameter average_delay = (r + f) / 2;
parameter signed [3:0] mux_selector = 0;
//参数声明时指定为有符号变量类型和范围,那么参数不受被赋予的值的符号类型和范围影响
parameter real r1 = 3.5e17;
//参数声明时指定了类型,但是没有指定范围,那么参数的范围将由被赋予的值的范围决定,但是类型由参数声明时指定的类型决定
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]

parameter定义常量,可以定义在模块内部或外部

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

localparam

  • localparam指定的参数不能通过defparam进行修改

  • localparam指定的参数不能通过模块例化进行修改;

  • localparam指定的参数可通过parameter赋值进行间接的修改,此时可利用parameter的修改方式实现localparam的修改;

  • 在这里插入图片描述

上述代码中MSB和LSB均可以通过defparam和模块例化的方式进行修改,但是FIFO_MSB和FIFO_LSB仅能通过MSB、LSB、SIZE进行修改或者直接赋值为常量。也就是说,如果要对localparam进行重新修改,那么只能通过parameter间接的进行修改,其参数化是通过parameter体现的

specparam

路径延迟用关键字 specify 和 endspecify 描述,关键字之间组成 specify 块语句。specify 是模块中独立的一部分,不能出现在其他语句块(initial, always 等)中。specify 块语句主要有以下功能:

  • 指定所有路径中引脚到引脚的延迟;

  • 定义 specparam 常量;

  • 在电路中设置时序检查。

实例:

   specify
      specparam ab_2_out = 2.5 ;
      specparam cd_2_out = 3.5 ;
     
     //每条路径都有一个源引脚和目的引脚,将这些路径的延迟依次用 specify 语句描述出来,称为并行连接。
      (a => out) = ab_2_out ;
      (b => out) = ab_2_out ;
      (c => out) = cd_2_out ;
      (d => out) = cd_2_out ;
   endspecify

parameter,localparameter,specparam参数的异同点

在这里插入图片描述

Verilog 带参数例化

链接:参数覆盖有两种方式:1)使用关键字 defparam,2)带参数值模块例化

原文链接:
https://developer.aliyun.com/article/12283

https://blog.csdn.net/Times_poem/article/details/51371940
https://www.cnblogs.com/xgcl-wei/p/9090918.html
https://www.runoob.com/w3cnote/verilog-defparam.html
https://blog.csdn.net/weixin_43698385/article/details/124745762?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-17-124745762-blog-108027613.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-17-124745762-blog-108027613.pc_relevant_default&utm_relevant_index=19

在Verilog中,defineparameter都是用来定义常量的关键字,但它们有不同的应用场景和作用。 1. define 在Verilog中,define用于定义预处理器宏,它可以将一段代码中所有出现该宏的地方替换为指定的文本。define通常用于定义一些简单的常量或者简化代码的书写。define的语法如下: ``` `define <macro_name> <macro_value> ``` 其中,`<macro_name>`是宏的名称,`<macro_value>`是宏的值。例如: ``` `define WIDTH 16 ``` 这个宏定义了一个名为WIDTH的常量,值为16。在代码中,我们可以用`WIDTH`来代替16。 2. parameter parameter用于在模块内部定义常量,它可以在模块实例化时被修改。parameter通常用于定义一些需要在多个模块中使用的常量。parameter的语法如下: ``` parameter <parameter_name> = <parameter_value>; ``` 其中,`<parameter_name>`是参数的名称,`<parameter_value>`是参数的值。例如: ``` parameter WIDTH = 16; ``` 这个参数定义了一个名为WIDTH的常量,初始值为16。在模块内部,我们可以使用`WIDTH`来访问这个常量。在实例化该模块时,也可以通过修改WIDTH的值来改变模块的行为。 总的来说,defineparameter都是用于定义常量的关键字,但它们的作用和应用场景不同。define用于在代码中定义简单的常量或简化代码的书写,而parameter用于在模块内部定义常量,在模块实例化时可以被修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值