Verilog:参数(parameter)的使用

news2024/11/28 20:50:59

相关阅读

Verilog基础icon-default.png?t=O83Ahttps://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482


        参数(parameter)一般用于定义常数,常用于进行可配置的参数化设计中,本文将对参数的使用进行详细介绍。

        首先来看看参数的BNF范式(语法),有关BNF范式相关内容,可以参考之前的文章。

图1 参数的定义

        参数可分为两大类:局部参数和普通参数,分别由关键词local_parameterparameter声明。它们俩的区别在于,局部参数不允许使用defparam语句或在模块实例化时(在elaboration阶段)进行参数覆盖,普通参数在满足一定条件时允许参数覆盖。需要注意的是参数代表常量,在运行时修改它们的值是非法的。

        list_of_param_assignments是一个逗号分隔的赋值列表(这允许在一条语句中定义多个参数),其中赋值的右侧应该是常量表达式,只包含常数和之前已定义的参数。

localparam的声明位置

        local_parameter可以在下面这些位置声明:

1、模块中

module example_module (
    input wire clk,
    input wire rst,
    output wire [3:0] out
);

localparam integer WIDTH = 4;  // 在模块中声明localparam
localparam [WIDTH-1:0] MAX_VALUE = 15;

reg [WIDTH-1:0] counter;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        counter <= 0;
    end else if (counter < MAX_VALUE) begin
        counter <= counter + 1;
    end else begin
        counter <= 0;
    end
end

assign out = counter;

endmodule

2、命名块中

module example_module (
    input wire clk,
    input wire rst,
    output wire [3:0] out
);

reg [3:0] counter;

always @(posedge clk or posedge rst) begin
    if (rst) begin
        counter <= 0;
    end else begin
        // 命名块
        begin: COUNTER_LOGIC
            localparam integer MAX_COUNT = 10;  // 在命名块中声明localparam

            if (counter < MAX_COUNT) begin
                counter <= counter + 1;
            end else begin
                counter <= 0;
            end
        end
    end
end

assign out = counter;

endmodule

3、任务中

module example_module;

  reg [3:0] value;

  task example_task;
    localparam integer MAX_VALUE = 10;  // 在任务内部声明localparam

    input reg [3:0] in_value;
    output reg [3:0] out_value;
    begin
      if (in_value < MAX_VALUE) begin
        out_value = in_value + 1;
      end else begin
        out_value = 0;
      end
    end
  endtask

  initial begin
    value = 5;
    example_task(value, value);
  end

endmodule

4、函数中

module example_module;

  reg [3:0] input_value;
  reg [3:0] output_value;

  function [3:0] example_function;
    localparam integer MAX_VALUE = 8;  // 在函数内部声明localparam

    input [3:0] in_value;
    begin   
      if (in_value < MAX_VALUE) begin
        example_function = in_value + 1;
      end else begin
        example_function = 0;
      end
    end
  endfunction

  initial begin
    input_value = 5;
    output_value = example_function(input_value);
    $display("Output Value: %d", output_value);
  end

endmodule

5、在生成块中

module example_module (
    output reg [7:0] out
);

  generate
    if (1) begin: GEN_BLOCK_LOW
      localparam integer WIDTH = 8;  // 在生成块中声明localparam
      always @(*) begin
        out =  WIDTH;
      end
    end else begin: GEN_BLOCK_HIGH
      localparam integer WIDTH = 16;  // 在生成块中声明另一个localparam
      always @(*) begin
        out =  WIDTH;
      end
    end
  endgenerate

endmodule

parameter的声明位置

        parameter可以在下面这些位置声明:

1、模块参数列表中

module example_module #(
    parameter integer WIDTH = 8,  // 在模块参数声明列表中声明parameter
    parameter integer DEPTH = 16
)(
    input wire [WIDTH-1:0] data_in,
    output reg [WIDTH-1:0] data_out
);

  reg [WIDTH-1:0] memory [0:DEPTH-1];

  always @(*) begin
    data_out = memory[data_in % DEPTH];
  end

endmodule

2、模块中

module example_module (
    input wire [3:0] select,
    output reg [7:0] out
);

  parameter integer WIDTH = 8;    // 在模块内部声明parameter
  parameter integer OFFSET = 5;

  always @(*) begin
    out = (select * WIDTH) + OFFSET;
  end

endmodule

3、命名块中

module example_module (
    input wire [3:0] select,
    output reg [7:0] out
);

  always @(*) begin
    // 命名块
    begin : MY_BLOCK
      parameter integer MULTIPLIER = 4;  // 在命名块中声明 parameter
      parameter integer OFFSET = 2;

      out = (select * MULTIPLIER) + OFFSET;
    end
  end

endmodule

4、任务中

module example_module;

  reg [3:0] value;

  task example_task;
    parameter integer MAX_VALUE = 10;    // 在任务内部声明parameter
    input reg [3:0] current_value;
    output reg [3:0] next_value;
    begin
      if (current_value < MAX_VALUE) begin
        next_value = current_value + 1;
      end else begin
        next_value = 0;
      end
    end
  endtask

  initial begin
    value = 5;
    example_task(value, value);
    $display("Value after increment: %d", value);
  end

endmodule

5、函数中

module example_module;

  reg [3:0] input_value;
  reg [3:0] output_value;

  function [3:0] example_function;
    input [3:0] in_value;
    parameter integer MAX_VALUE = 8;  // 在函数内部声明的parameter
    begin
      if (in_value < MAX_VALUE) begin
        example_function = in_value + 1;
      end else begin
        example_function = 0;
      end
    end
  endfunction

  initial begin
    input_value = 5;
    output_value = example_function(input_value); 
    $display("Output Value: %d", output_value); 
  end

endmodule

符号、位宽和类型

        参数声明时可以指定可选的有符号、位宽和类型,但如果指定了符号和位宽,则不能指定类型,也就是说有以下搭配:

  • 不指定有符号、位宽和类型:参数为无符号的,参数的位宽由所有参数覆盖完成后,最后赋给参数的结果相同。
  • 指定有符号,不指定位宽和类型:参数为有符号的,参数的位宽由所有参数覆盖完成后,最后赋给参数的结果相同。
  • 指定位宽,不指定有符号和类型:参数为无符号的,参数的位宽由指定位宽决定。
  • 指定有符号和位宽,不指定类型:参数为有符号的,参数的位宽由指定位宽决定。
  • 指定类型,不指定有符号和位宽:参数是否有符号和位宽取决于具体的类型(例如对于time类型是无符号的且位宽至少64位,而对于integer类型,是有符号的且位宽至少32位)。

参数的覆盖

        模块参数列表和模块中定义的参数在满足一定条件时,可以进行参数覆盖(本文只涉及在模块实例化时的参数覆盖)。

        模块参数列表中定义的参数可以像端口连接类似,使用位置参数覆盖或命名端口覆盖,如例1所示。

// 例1
module top_module;
    reg  input_data;
    wire output_data;

    // 位置端口覆盖PARAM1和PARAM3,保留PARAM2的默认值
    my_module #(12, ,64)
    ) instance1 (
        .data_in(input_data[11:0]), 
        .data_out(output_data)    
    );

    // 命名端口覆盖PARAM1和PARAM3,保留PARAM2的默认值
    my_module #(
        .PARAM1(12),     // 覆盖PARAM1为12
        .PARAM3(64)      // 覆盖PARAM3为64
    ) instance1 (
        .data_in(input_data), 
        .data_out(output_data)      
    );

endmodule

module my_module #(
    parameter PARAM1 = 8,        
    parameter PARAM2 = 16,      
    parameter PARAM3 = 32       
)(
    input data_in,  
    output reg data_out 
);

    initial $display("%d, %d, %d",PARAM1, PARAM2, PARAM3);
endmodule

        模块中定义的参数,在模块列表中没有定义参数时,可以使用位置参数覆盖或命名端口覆盖,在进行位置参数覆盖时顺序与参数定义的顺序相同,但需要注意的是,如果想不覆盖某个参数,则需要将该参数的值重新写一遍,而不像位置端口连接,如果想表示某个端口没连接,直接留空即可,如例2所示。

// 例2
module top_module;
    reg  input_data;
    wire output_data;

    // 位置端口覆盖PARAM1和PARAM3,保留PARAM2的默认值
    my_module #(12, 16, 64)
    ) instance1 (
        .data_in(input_data), 
        .data_out(output_data)    
    );

    // 命名端口覆盖PARAM1和PARAM3,保留PARAM2的默认值
    my_module #(
        .PARAM1(12),     // 覆盖PARAM1为12
        .PARAM3(64)      // 覆盖PARAM3为64
    ) instance1 (
        .data_in(input_data), 
        .data_out(output_data)      
    );

endmodule

module my_module (                    // 此处不能定义参数,否则模块中定义的参数无法覆盖
    input data_in,  
    output reg data_out 
);

    parameter PARAM1 = 8;       
    parameter PARAM2 = 16;      
    parameter PARAM3 = 32;    
    initial $display("%d, %d, %d",PARAM1, PARAM2, PARAM3);
endmodule

        参数覆盖的过程,就和普通的赋值一样,右侧表达式中操作数的位宽可能会受到左侧参数位宽(如有)的影响,而右侧表达式的符号不受左侧参数的符号影响,详情见以下两文。

Verilog基础:表达式位宽的确定(位宽拓展)-CSDN博客文章浏览阅读1.1w次,点赞137次,收藏181次。我们可以首先找到被加入上下文环境的操作数,a和b作为+操作符的操作数,是上下文决定的,(a+b)作为整体位与移位操作符的左边也是上下文决定的,(a+b)>>1作为整体是=操作符的右操作数,也是上下文决定的,因此answer(因为=),a,b(因为三层上下文嵌套)都被加入上下文环境中,这三个变量的位宽都是一样的,所以他们三个在运算前不会有拓展。因此首先执行a+b,根据规则,结果为16位,进位被丢失,然后再右移一位,最高位补0,最后赋值给同为16位的answer。很多时候方法很简单。改成a+b+17'b0;_verilog动态位宽https://chenzhang.blog.csdn.net/article/details/128772558?spm=1001.2014.3001.5502Verilog基础:表达式符号的确定-CSDN博客文章浏览阅读846次,点赞15次,收藏39次。文章介绍了Verilog中处理表达式符号的重要性和规则,包括$signed和$unsigned函数的作用。强调了位选、域选、拼接操作的结果通常为无符号数,以及在加法操作中,如果上下文操作数包含无符号数,则结果也会是无符号的,可能导致预期外的结果。解决这个问题的方法是确保所有操作数的符号一致。https://blog.csdn.net/weixin_45791458/article/details/128840843?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522677A413D-10AF-4A54-82E7-5B5203BB4177%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=677A413D-10AF-4A54-82E7-5B5203BB4177&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-5-128840843-null-null.nonecase&utm_term=%E8%A1%A8%E8%BE%BE%E5%BC%8F&spm=1018.2226.3001.4450

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2222303.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Hadoop 安装教程——单节点模式和分布式模式配置

文章目录 一、预备知识1.1 Hadoop 发行版本1.2 部署方式 二、预备条件2.1 环境准备2.2 创建新用户(可选)2.3 配置 SSH 无密码登录2.4 下载 Hadoop2.5 编辑 hadoop-env.sh 脚本2.6 编辑 dfs 和 yarn 脚本 三、单节点模式部署3.1 官方使用案例3.2 查看运行结果 四、伪分布模式部署…

用哪种建站程序做谷歌SEO更容易?

做网站很容易&#xff0c;但做一个能带来流量和订单的网站就没那么简单了。尤其是在谷歌SEO优化方面&#xff0c;不同的建站程序对SEO的支持程度也不同。在这方面&#xff0c;WordPress和Shopify无疑是最佳选择。 WordPress作为一个内容管理系统&#xff08;CMS&#xff09;&am…

关键词提取技术:TF-IDF 详解

1. 什么是TF-IDF&#xff1f; TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09; 是一种统计方法&#xff0c;用于评估单词在文档集或语料库中的重要性。它是自然语言处理和信息检索中的核心技术之一。 TF-IDF主要基于以下两个概念&#xff1a; TF&a…

Java毕业设计 基于SSM jsp餐厅卫生安全系统

Java毕业设计 基于SSM jsp餐厅卫生安全系统 这篇博文将介绍一个基于SSM框架和jsp开发的餐厅卫生安全系统&#xff0c;适合用于Java毕业设计。 功能介绍 餐厅人员: 注册 登录 首页 图片轮播 窗口信息 窗口详情 文明窗口 差评窗口 系统公告 个人中心 管理员&#xff1a;…

亚信安全DeepSecurity中标知名寿险机构云主机安全项目

近日&#xff0c;亚信安全DeepSecurity成功中标国内知名寿险机构的云主机安全项目。亚信安全凭借在云主机安全防护领域的突出技术优势&#xff0c;结合安全运营的能力&#xff0c;以“实战化”为指导&#xff0c;为用户提供无惧威胁攻击、无忧安全运营的一站式云安全体系&#…

Anaconda和Pycharm超详细安装教程(2024版本+Win11)

一、安装Anaconda 1.1 下载Anaconda 在官方网站(Free Download | Anaconda)上下载适用于你的操作系统的 Anaconda 安装包。(这里以windows为例) 1.2 安装Anaconda 打开下载的安装包,并按照安装向导的指示进行安装。在安装过程中,你可以选择默认的安装选项,也可以根据…

Visual Studio安装图文详解教程

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 教程说明 本教程旨在详细介绍 Visual Studio 社区版的安装过程及其注意事项。 Visual Studio简介 Visual Studio 社区版功能完备且可扩展的免费 IDE&#xff0c;可用于创…

NVR接入录像回放平台EasyCVR视频融合平台语音对讲配置

国标GB28181视频平台EasyCVR视频融合平台可拓展性强、视频能力灵活&#xff0c;平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制、语音对讲、智能分析接入等功能。其中&#xff0c;在语音对讲方面&#xff0c;NVR接入录像回放平台目前…

4种鼓励创业创新的方法

随着市场趋于饱和&#xff0c;许多企业&#xff0c;尤其是初创企业&#xff0c;很难在竞争中保持领先地位。技术为企业彻底改变其营销和管理策略铺平了道路。另一个经过实践检验的成功渗透特定市场的方法是在办公室内部激发创新&#xff0c;从员工到品牌皆如此。 那么究竟如何…

【设计模式-原型】

**原型模式&#xff08;Prototype Pattern&#xff09;**是一种创建型设计模式&#xff0c;旨在通过复制现有对象的方式来创建新对象&#xff0c;而不是通过实例化类来创建对象。该模式允许对象通过克隆&#xff08;复制&#xff09;来创建新的实例&#xff0c;因此避免了重新创…

LabVIEW提高开发效率技巧----插入式架构

随着LabVIEW项目规模的扩大和系统复杂性的增加&#xff0c;传统的单一代码架构难以应对后期维护和功能扩展的需求。插入式架构&#xff08;Plug-In Architecture&#xff09;作为一种模块化设计方式&#xff0c;通过动态加载和运行子VI&#xff0c;使系统功能更加灵活、模块化&…

Oracle OCP认证考试考点详解082系列01

题记&#xff1a; 本篇博文是Oracle OCP认证考试考点详解082系列的第一篇&#xff0c;本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 1. 第一题&#xff1a; 1. 题目 2. 解析及答案 关于Oracle数据库中节…

6.1 特征值介绍

一、特征值和特征向量介绍 本章会开启线性代数的新内容。前面的第一部分是关于 A x b A\boldsymbol x\boldsymbol b Axb&#xff1a;平衡、均衡和稳定状态&#xff1b;现在的第二部分是关于变化的。时间会加入进来 —— 连续时间的微分方程 d u / d t A u \pmb{\textrm{d}…

通过AWS Bedrock探索 Claude 的虚拟桌面魔力:让 AI 代替你动手完成任务!

前言 大家好&#xff0c;昨夜Anthropic 发布了更新。现在 Claude 3.5 Sonnet&#xff08;V2&#xff09; 和 Claude 3.5 Haiku&#xff0c;以及名为 computer use 的新功能已经作为公开测试版发布了。 Introducing computer use, a new Claude 3.5 Sonnet, and Claude 3.5 Ha…

生成对抗网络基本原理

生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;简称GANs&#xff09;是由Ian Goodfellow等人在2014年提出的一种深度学习模型&#xff0c;它在生成模型领域引起了革命性的变化。GANs的核心思想是通过引入一个对抗过程来生成新的数据样本&#xff0c;这个…

【1024程序员节】MybatisPlus入门(一)MybatisPlus简介

一、MyBatis简介 MyBatisPlus&#xff08;简称MP&#xff09;是基于MyBatis框架基础上开发的增强型工具&#xff0c;旨在简化开发、提高效率 - 官网&#xff1a;https://mybatis.plus/ https://mp.baomidou.com/ MyBatisPlus特性&#xff1a; - 无侵入&#xff1a;只做增强…

接口测试 —— Postman 变量了解一下!

Postman变量是在Postman工具中使用的一种特殊功能&#xff0c;用于存储和管理动态数据。它们可以用于在请求的不同部分、环境或集合之间共享和重复使用值。 Postman变量有以下几种类型&#xff1a; 1、环境变量&#xff08;Environment Variables&#xff09;: 环境变量是在…

C语言程序设计:现代设计方法习题笔记《chapter3》

第一题 ​ 代码示例&#xff1a; #include<stdio.h>int main() {printf("Enter a date&#xff08;mm/dd/yyyy&#xff09;: ");int day, month, year;scanf_s("%d/%d/%d", &month, &day, &year);printf("%04d%02d%02d", yea…

stm32F103 实现呼吸灯效果

目录 硬件连接 软件实现步骤 初始化系统时钟。 配置 GPIO 引脚。 配置定时器以生成 PWM 信号。 在主循环中调整 PWM 占空比以实现呼吸效果。 示例代码 1. 初始化系统时钟 2. 配置 GPIO 引脚 3. 配置定时器以生成 PWM 信号 4. 在主循环中调整 PWM 占空比以实现呼吸效…

【读书笔记-《网络是怎样连接的》- 2】Chapter2_1-协议栈通信详细过程

第二章从协议栈这部分来看网络中的通信如何实现&#xff0c;准备从两部分来进行分解。本篇是第一部分&#xff1a;详细介绍TCP协议栈收发数据的过程。 首先来看下面的图。从应用程序到网卡需要经过如下几部分&#xff0c;上面的部分通过委托下面的部分来完成工作。首先是应用程…