FPGA的设计艺术(12)使用parameter构建可重用的逻辑设计

李锐博恩 2021-03-14 02:34:44 6571

前言

与大多数编程语言一样,我们应该尝试使尽可能多的代码可重用。

这使我们可以减少将来项目的开发时间,因为我们可以更轻松地将代码从一种设计移植到另一种设计。

我们在verilog中有两个可用的构造,它们可以帮助我们编写可重用的代码-parameter和generate语句。

这两种构造都允许我们创建更多的通用代码,我们在实例化组件时可以轻松地对其进行修改以满足自己的需求。

Verilog参数

在verilog中,参数是常量的局部形式,当我们实例化模块时,可以为其分配一个值。

由于参数的范围有限,因此我们可以多次调用同一个verilog模块,并为该参数分配不同的值。这使我们可以动态配置模块的行为。

我们都知道编写模块时必须定义模块的接口。然后,我们可以使用该接口互连FPGA设计中的许多不同模块。

作为此接口的一部分,我们可以声明参数以及模块的输入和输出。

下面的Verilog代码片段显示了我们用于在模块中声明参数的方法。当在这样的verilog模块中声明参数时,我们称其为参数化模块。

module <module_name> #(
  parameter <parameter_name> = <default_value> )

(

  // Port declarations

);

上面的Verilog代码中的字段用于为我们的参数提供标识符。

具体示例:

模块计数器有两个参数N和DOWN,声明其默认值分别为2和0。N控制输出的位数,有效控制计数器的宽度。默认情况下,它是一个2位的计数器。参数DOWN控制计数器是递增还是递减。默认情况下,计数器将递减,因为该参数被设置为0。

module counter
  #(    parameter N = 2,
        parameter DOWN = 0)

  ( input                           clk,
    input                           rstn,
    input                           en,
    output  reg [N-1:0] out);

  always @ (posedge clk) begin
    if (!rstn) begin
      out <= 0;
    end 
    else begin
      if (en)
        if (DOWN)
          out <= out - 1;
        else
            out <= out + 1;
      else
         out <= out;
    end
  end
endmodule

我们使用该标识符来调用代码中的参数值,就像使用普通变量一样。

在上面的示例中,我们还可以使用字段将默认值分配给我们的参数。

这很有用,因为它允许我们实例化组件,而不必专门为参数分配值。

例如,我们对上述实际示例的例化:

module design_top (    input clk,
                input rstn,
                input en,
                output [1:0] out);

    counter #(.N(2)) u0 (   .clk(clk),
                          .rstn(rstn),
                          .en(en));
endmodule

我们对一个参数分配了参数值,另一个参数没有分配,则编译工具对于另一个参数的处理是使用默认值。也就是0.

当我们在Verilog设计单元中实例化模块时,可以使用named关联或positional关联为参数分配一个值。这与将信号分配给模块上的输入或输出完全相同。

但是,当我们编写使用verilog 1995标准的代码时,只能使用位置关联将值分配给参数。

下面的Verilog代码片段显示了在实例化模块时用于为参数分配值的方法。

// Example of named association
<module_name> # (

  // If the module uses parameters they are connected here

  .<parameter_name> (<parameter_value>)

)

<instance_name> (

  // port connections

);

// Example of positional association

<module_name> # (<parameter_values>)

<instance_name> (

  // port connections

);

Verilog参数化模块示例

为了更好地理解我们如何在verilog中使用参数,让我们考虑一个基本示例。

对于此示例,让我们考虑一个需要两个同步计数器的设计 。这些计数器之一为8位宽,而另一个为12位宽。

为了实现该电路,我们可以编写两个不同的计数器组件,它们具有不同的宽度。但是,这是对我们的电路进行编码的低效率方式。

相反,我们将编写一个计数器电路,并使用一个参数来更改输出中的位数。

由于理解我们如何使用参数化模块并不重要,因此在此示例中将排除功能代码。

相反,我们将仅研究如何在verilog中声明和实例化参数化模块。

下面的Verilog代码片段显示了我们如何编写参数化计数器模块的接口。

module counter #(
  parameter BITS = 8)
(
  input wire clock,
  input wire reset,
  output reg [BITS-1 : 0] count

);

endmodule

在此示例中,我们看到了如何使用参数来调整Verilog中信号的大小。

而不是使用固定的数字声明端口宽度,我们将参数值替换为端口声明。

这是Verilog中参数最常见的用例之一。

在上面的verilog代码中,我们将BITS参数的默认值定义为8。

因此,仅当我们想要非8位的输出时,才需要为参数分配一个值。

下面的代码片段显示了当我们需要12位输出时如何实例化此模块。

在这种情况下,我们在实例化verilog模块时必须超越参数的默认值。

counter # (

  .BITS (12)

) count_12 (

  .clock  (clock),

  .reset  (reset),

  .count  (count_out)

);

尽管在上面的示例中使用了命名关联,但是我们也可以使用位置关联为verilog中的参数分配值。

下面的代码段显示了如何使用位置关联将值12分配给BITS参数。

counter # (12) count_12 (

  .clock  (clock),

  .reset  (reset),

  .count  (count_out)

);

localparam

参数的声明方式不仅有parameter这种方式,还有一种localparam的语法,不过它当然与parameter有所区别:

localparam模块内有效的定义,是局部变量,不可用于参数传递,也不能被重定义。

它用来生成循环,生成维数可扩展的模块,localparam是局部参数,但它不能被重定义,也就是说在实例化的时候不能通过层次引用进行重定义,例如parameter可以通过#(参数)来进行重新定义,但是localparam不可以,只能通过源代码来改变。

什么时候?什么场合用这种参数比较好呢?

例如我们可以在设置状态变量的时候使用它,因为状态变量属于模块专属,我们不需要对其进行传递,也不需要对其进行更改,我们也可以对CPU的总线地址等使用它,总之,一切不需要进行参数传递的地方均可以使用。

localparam的语法:

module <module_name> 

(

  // Port declarations

);

localparam <parameter_name> = <default_value> ;

endmodule 

或对于多个局部参数的定义:

module <module_name> 

(

  // Port declarations

);

  localparam <parameter_name1> = <default_value1> ,
             <parameter_name2> = <default_value2> ,
             <parameter_name3> = <default_value3> ,          
                                ;

endmodule
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包 1 收藏 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
李锐博恩
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区