Verilog | 参数化模块调用

本文详细介绍了Verilog中模块参数化调用的三种方式:`define、parameter和localparam,以及defparam和带参数值模块例化。强调了参数的作用域和用法,并通过实例说明了在模块实例化时如何改写参数值。同时指出defparam在某些情况下的限制,如不能同时修改端口声明和实体参数,且通常不可综合。建议使用带参数值模块例化来改写模块参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上接 模块与端口

一、 概述

        在进行模块调用时,有时需要修改模块中的参数,这个时候就需要进行参数化模块调用。

        众所周知,参数都是有各自的作用域的。

  • `define:      作用 -> 经常使用于定义常量能够跨模块、跨文件;

                             范围 -> 整个工程;

  • defparam:      作用 -> 改写模块在端口声明时声明的参数,或模块实体中声明的参数;

                          范围 - > 作用于例化模块;

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

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

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

                             范围 -> 本module内有效的定义,且不可用于参数传递;

二、 用法

        当一个模块被另一个模块引用例化时,高层模块可以对低层模块的参数值进行改写。这样就允许在编译时将不同的参数传递给多个相同名字的模块,而不用单独为只有参数不同的多个模块再新建文件。参数覆盖有 2 种方式:1)使用关键字 defparam,2)带参数值模块例化

  1. 使用关键字 defparam

    defparam module_name.parameter1;
    module_name inst_name( 
        port_map
        );

  2. 带参数值模块例化和模块例化基本一样,有两种调用方法:
     

    module_name #( 
        parameter1, //例化时,例化的参数顺序必须和模块顺序一致
        parameter2
        ) 
    inst_name( 
        port_map
        );
    module_name #( 
        .parameter_name(para_value),//必须指定当前例化的端口名称,顺序可以自由排序
        .parameter_name(para_value)
        ) 
    inst_name (
        port map
        );

三、 两者区别

(1)所有参数都是模块在端口声明时声明的参数或参数都是模块实体中声明的参数,这两种模块参数改写的方式可混用。

(2) 利用 defparam带参数例化 都既可以改写模块在端口声明时声明的参数,也可以改写模块实体中声明的参数。但是 defparam 不能同时修改两种参数,也不能在有端口声明参数的情况下修改模块实体中生命的参数。

例如:

module  ram
    #(  parameter       AW = 2 ,
        parameter       DW = 3 )
    (
        input                   CLK ,
        input [AW-1:0]          A ,
        input [DW-1:0]          D ,
        input                   EN ,
        input                   WR ,    //1 for write and 0 for read
        output reg [DW-1:0]     Q    );
 
    parameter            MASK = 3 ;
 
    reg [DW-1:0]         mem [0:(1<<AW)-1] ;
    always @(posedge CLK) begin
        if (EN && WR) begin
            mem[A]  <= D ;
        end
        else if (EN && !WR) begin
            Q       <= mem[A] ;
        end
    end
 
endmodule

此时再用 defparam 改写参数 MASK 值时,编译报 Error;

//都采用defparam时会报Error
defparam     u_ram.AW = 4 ;
defparam     u_ram.DW = 4 ;
defparam     u_ram.MASK = 7 ;
ram   u_ram  (......);
 
//模块实体中parameter用defparam改写也会报Error
defparam     u_ram.MASK = 7 ;
ram #(.AW(4), .DW(4))   u_ram (......);

(3)defparam 一般也不可综合。

(4)建议编写模块时,将需要修改的参数写入到模块端口声明之前的地方(用关键字井号 # 表示),例化时使用带参数值模块例化的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值