首页 > 其他分享 >Verilog:参数(parameter)的使用

Verilog:参数(parameter)的使用

时间:2024-10-23 23:16:19浏览次数:8  
标签:value begin data module 参数 Verilog parameter

相关阅读

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

标签:value,begin,data,module,参数,Verilog,parameter
From: https://blog.csdn.net/weixin_45791458/article/details/143085525

相关文章

  • 如何在verilog设计的磁盘阵列控制器中实现不同RAID级别(如RAID 0、RAID 1等)的切换?
    以下是一种在Verilog设计的磁盘阵列控制器中实现不同RAID级别(以RAID0和RAID1为例)切换的方法:添加控制信号在磁盘阵列控制器模块中添加一个输入信号,例如raid_mode,用于选择RAID模式。假设raid_mode=0表示RAID0模式,raid_mode=1表示RAID1模式。moduleraid_contr......
  • 曲线与平面曲线 | 正则曲线、弧长参数、切线方程&曲率
    目录曲线正则曲线切向量弧长弧长参数切线方程曲率例题曲线对函数y=f(x)......
  • 层、块以及参数管理
    此Blog仅作为日常学习工作中记录使用,Blog中有不足之处欢迎指出​ 在研究过程中发现,比单层神经网络大,比整个深度神经网络模型小的组件往往更具价值。以计算机视觉为例,ResNet-152具有数百层,这些层是由层组(groupsoflayers)的重复模式组成。​ 块(block)可以描述单个层、由多个层组......
  • 信号模拟源参数下发:一帧ROM数据+一帧PN16数据+1000帧AOC数据
    背景:裸数据的封装,通过PCIE通道传输,需要进行封装和提取。白话思路:分别开启模块的使能信号,使用状态机控制其使能的开启,随着地址增加,输出参数值。遇到的几个问题:(1)PN16程序设置使能开启接口(ena_1),ROM自带使能开启接口;(2)状态机的控制信号:地址控制使能的开启;(3)使能信号总是需要提......
  • 三周精通FastAPI:6 路径参数和数值校验
    路径参数和数值校验¶与使用 Query 为查询参数声明更多的校验和元数据的方式相同,你也可以使用 Path 为路径参数声明相同类型的校验和元数据。导入路径Path¶首先,从 fastapi 导入 Path:fromtypingimportAnnotatedfromfastapiimportFastAPI,Path,Querya......
  • 三周精通FastAPI:7 查询参数模型
    查询参数模型如果你有一组相关的查询参数,你可以创建一个Pydantic模型来声明它们。这将允许您在多个地方重用模型,并一次声明所有参数的验证和元数据。......
  • verilog实现一个5bit序列检测器
    以下是用Verilog实现一个5bit序列检测器的代码:modulefive_bit_sequence_detector(inputclk,inputreset,input[4:0]in,outputregdetected);//定义状态参数localparamIDLE=4'b0000;localparamSTATE1=4'b0001;local......
  • YOLOv11模型改进-注意力-引入简单无参数注意力模块SimAM 提升小目标和遮挡检测
                本篇文章将介绍一个新的改进机制——卷积和注意力融合模块SimAM ,并阐述如何将其应用于YOLOv11中,显著提升模型性能。首先,SimAM是一种用于卷积神经网络的简单且无参数的注意力模块,它基于神经科学理论定义能量函数来计算3-D注意力权重,能有效提升网络......
  • jmeter参数化代码实现
    jmeter参数化代码实现csv组件参数化很方便,单机压测时喜欢使用,但分布式传递可能需要多次上传参数化文件,假设参数化数据不多,可以直接写道内存里,以ip举例:预处理JSR233-groovy,代码记录如下:步骤1:初始化IP列表if(props.get("ipList")==null){String[]ipList=["192.168......
  • mysql innodb_data_file_path参数忘记设置或者重新调整办法
    目录mysqlinnodb_data_file_path参数忘记设置或者重新调整办法mysqlinnodb_data_file_path参数忘记设置或者重新调整办法my.cnf文件中,默认配置为innodb_data_file_path=ibdata1:10M:autoextend目前该文件已经扩大到了1g多:-rw-r-----1mysqlmysql14701035524月161......