【 FPGA 】常数( localparam )和参数( parameter )

举报
李锐博恩 发表于 2021/07/15 03:04:37 2021/07/15
【摘要】 在Verilog HDL中,使用localparam(局部参数)声明常量,可以使代码清晰并有助于以后的维护,例如声明数据总线的位宽和范围: localparam DATA_WIDTH = 8; DATA_RANGE = 2**DATA_WIDTH; 或定义符号端口名称: UART_PORT = 4'b0001; LCD_PORT = 4'b001...

在Verilog HDL中,使用localparam(局部参数)声明常量,可以使代码清晰并有助于以后的维护,例如声明数据总线的位宽和范围:

localparam DATA_WIDTH = 8;

DATA_RANGE = 2**DATA_WIDTH;

或定义符号端口名称:

UART_PORT = 4'b0001;

LCD_PORT = 4'b0010;

MOUSE_PORT = 4'b0100;

习惯用大写字母表示常数。

一个带进位的固定位宽加法器的例子:

未使用常数的情况:


      module adder_carry(
      input [3:0] a,
      input [3:0] b,
      output [3:0] sum,
      output cout
      );
      wire [4:0] sum_ext;
      assign sum_ext = {1'b0,a} + {1'b0,b};
      assign sum = sum_ext[3:0];
      assign cout = sum_ext[4];
      endmodule
  
 

 

如果改成8位加法器,这些位宽都要一个一个的手动更改,遇到大一点的项目,这将变得尤为困难。

我们对上述代码改进一下,使用局部常数:


      module adder_carry
      (
      input [3:0] a,
      input [3:0] b,
      output [3:0] sum,
      input cout
      );
      localparam N = 4;
      localparam N1 = N-1;
      wire [N:0] sum_ext;
      assign sum_ext = {1'b0,a} + {1'b0,b};
      assign sum = sum_ext[N1:0];
      assign cout = sum_ext[N];
      endmodule
  
 

上述代码使用了局部变量,这还不够优化,下面介绍参数的使用方法。

Verilog模块可以实例化为组件并成为更大设计模块的一部分。Verilog提供一种结构成为parameter,向模块传递信息,这种机制使得模块多功能化并能重复使用。参数在模块内不能改变,因此功能和常数类似。

在Verilog HDL 2001中,参数声明部分可以在模块的开头,即端口声明之前。如下:

module 模块名

#(parameter 参数名1 = 默认值1,

parameter 参数名2 = 默认值2)

...

);

......

endmodule

为了增强可读性以及可维护性,可以采用符号常数N来表示加法器的位数。


      module adder_carry
       #(parameter N = 4)
      (
      input [N-1:0] a,
      input [N-1:0] b,
      output [N-1:0] sum,
      input cout
      );
      localparam N1 = N-1;
      wire [N:0] sum_ext;
      assign sum_ext = {1'b0,a} + {1'b0,b};
      assign sum = sum_ext[N1:0];
      assign cout = sum_ext[N];
      endmodule
  
 

如果之后,加法器在其他代码中作为组件使用,那么就可以在组件实例化中给参数指定所需的值并将原来的默认值覆盖。

如果省略参数赋值,则采用默认参数,如下:


      module adder_instant(
      input [3:0] a4,
      input [3:0] b4,
      output [3:0] sum4,
      output cout4,
      input [7:0] a8,
      input [7:0] b8,
      output [7:0] sum8,
      output cout8
      );
      //实例化8位加法器
      adder_carry #(.N(8)) uu1(.a(a8),.b(b8),.sum(sum8),.cout(cout8));
      //实例化4位加法器
      adder_carry uu2(.a(a4),.b(b4),.sum(sum4),.cout(cout4));
      endmodule
  
 

 

 

 

 

 

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/85637429

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。