Verilog基础:八种命名空间(定义命名空间、文本宏命名空间、模块命名空间,块命名空间、生成块命名空间、端口命名空间、specify块命名空间、属性命名空间)详解(上)

相关阅读

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


        Verilog有八个标识符命名空间:其中两个是全局的(定义命名空间和文本宏命名空间),六个是局部的(模块命名空间,块命名空间、生成块命名空间、端口命名空间、specify块命名空间、属性命名空间)。

一、定义命名空间

        定义命名空间统一了所有编译单元中,模块(module)和原语(primitive)标识符。一旦一个名称被用来在一个编译单元内定义一个模块和原语,该名称就不能再(包括其他编译单元中)被用来声明另一个模块和原语。

        在举例说明之前,有必要首先阐述一下编译单元的概念:编译单元指的是一起编译的一个或多个Verilog源文件的集合,但定义哪些文件构成一个编译单元的确切机制是工具决定的。然而,兼容Verilog标准的工具应该提供允许选择以下两种方式:

        1、给定编译命令行上的所有文件构成单个编译单元(多文件单编译单元)。

        2、给定编译命令行上的每个文件都是一个单独的编译单元(单文件单编译单元)。

        这里的第二种方式更像C语言中编译的概念,每一个C语言源文件都是一个编译单元,编译汇编成一个目标文件,最后链接。Modelsim或Questa提供了编译时的-sfcu选项(Single-file compilation unit(default))和-mfcu选项(Multi-file compilation unit)用于支持标准。

        下面的项目在编译单元间(或内)互相可见:模块和原语。这也就解释了为什么,模块的定义和实例化没有顺序要求,如例1所示,甚至可以将模块定义和实例化放在两个不同的文件中,如例2所示。不论是否是一个编译单元,它们都是互相可见的。

// 例1
// 文件1: my_module.v
module my_module;
  // 模块内容
endmodule
 
// 文件2: top.v
module top;
  my_module inst();  // 可以在另一个文件中实例化my_module
endmodule
// 例2
// 文件:top.v
module top;
  sub_module u1();  // 这里实例化了my_module,虽然它还未定义
endmodule
 
// 之后才定义模块
module my_module;
  // 模块内容
endmodule

        回到正题,当出现了定义名称空间中标识符同名的情况(不论是否是同一类型,如例3所示),不同的仿真工具的默认行为是不同的:有些会直接报错(Aldec Riviera、Cadence Xcelium、Synopsys VCS),有些则会用后识别的标识符覆盖之前的定义并给出警告(Mentor Modelsim\Questa)。

// 例3
// 文件1: module_example.v
module my_module; // 定义名为my_module的模块
  // 模块内容
endmodule
 
primitive my_module;  // 同文件重复定义(不同类型)
  // 原语内容
endprimitive
 
// 文件2: conflicting_module.v
module my_module;  // 重复定义(同类型)
  // 模块内容
endmodule

二、文本宏命名空间

        像C语言一样,Verilog中的文本宏只在一个编译单元中,宏定义位置后生效,如例4所示。与编译单元域命名空间一样,如果是多文件单编译单元,一个文件的宏是否能在另一个文件中生效,取决于文件编译的顺序,如例5所示。

// 例4
// 文件:macro.v
 
`define WIDTH 8
module example;
  logic [`WIDTH-1:0] data;  // 使用文本宏 WIDTH
endmodule
// 例5
// 文件1:macro.v
`define WIDTH 8; // 在文本宏命名空间中定义一个宏
 
// 文件2:module.v
module my_module; // 使用多文件单编译单元编译
  logic [WIDTH-1:0] data;  // 访问文本宏命名空间中的参数WIDTH
  
  initial begin
    data = 8'hFF;
    $display("Data width is %0d bits", WIDTH);
  end
endmodule

// 当先编译module.v时,会报错;当先编译macro.v时不会报错
// 对于Modelsim,可以通过改变命令行中这两个源文件的前后顺序,改变其编译顺序

        因为宏使用时,需要用`符号作为前缀,它和其他命名空间的标识符不会出现重名现象。 当一个文本宏命名空间中,出现了两个同名宏,则在后定义的宏会在其后的范围覆盖之前的宏。

三、模块命名空间

        模块命名空间由下面结构引入:模块和原语。它统一了这些结构中的函数(function)、任务(task)、命名块(named block)、实例名(instance name)、生成块(generated block)、参数(parameter)、命名事件(named event)、genvar声明、线网声明(net declaration)和变量声明(variable declaration)的标识符(注意,这两种结构并不一定能包括所有这些元素,比如原语中不能定义函数)。

        例6给出了一些模块命名空间的标识符重名的例子(以一个模块为例)。

// 例6
// 文件:module.v
module example;

    // 定义一个参数,名称为 "my_name"
    parameter int my_name = 32;

    // 定义一个变量,名称为 "my_name"
    reg my_name;

    // 定义一个线网,名称为 "my_name"
    wire my_name;

    // 定义一个命名事件,名称为 "my_name"
    event my_name;

    // 定义一个函数,名称为 "my_name"
    function [3:0] my_name;
        input [3:0] a, b;
        begin
            my_name = a + b;
        end
    endfunction

    // 定义一个任务,名称为 "my_name"
    task my_name;
        input [3:0] a;
        begin
            $display("Value: %d", a);
        end
    endtask

    // 定义一个命名块,名称为 "my_name"
    initial begin : my_name
        my_name(4);  // 调用任务
    end

    // 定义一个生成块,名称为 "my_name"
    genvar i;
    generate
        for (i = 0; i < 4; i = i + 1) begin : my_name
            example ui();
        end
    endgenerate

endmodule

四、块命名空间

        块命名空间由下面结构引入:命名块、函数和任务。它统一了这些结构中的命名块、参数、命名事件、变量声明(注意,这五种结构并不一定能包括所有这些元素,比如函数中不能定义命名事件)。

        例7给出了一些模块命名空间的标识符重名的例子(以一个命名块为例)。

// 例7
// 文件:block.v
module ExampleModule;
    initial begin: top
 
        // 参数名为test
        parameter test = 1;
 
        // 命名事件名为test
        event test; 
 
        // 变量名为test
        reg test; 
 
        // 在命名块中定义另一个命名块test,根据Verilog语法规则,块语句必须在其他声明后
        begin: test 
            $display("This is a test");
        end
    end
endmodule

由于篇幅较长,本文分上、下两节更新

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日晨难再

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值