Verilog语言关键字模块例化实例讲解

目录
  • 关键字:例化,generate,全加器,层次访问
    • 命名端口连接
    • 顺序端口连接
    • 端口连接规则
    • 用 generate 进行模块例化
    • 层次访问

关键字:例化,generate,全加器,层次访问

在一个模块中引用另一个模块,对其端口进行相关连接,叫做模块例化。模块例化建立了描述的层次。信号端口可以通过位置或名称关联,端口连接也必须遵循一些规则。

命名端口连接

这种方法将需要例化的模块端口与外部信号按照其名字进行连接,端口顺序随意,可以与引用 module 的声明端口顺序不一致,只要保证端口名字与外部信号匹配即可。

下面是例化一次 1bit 全加器的例子:

full_adder1  u_adder0(
    .Ai     (a[0]),
    .Bi     (b[0]),
    .Ci     (c==1'b1 ? 1'b0 : 1'b1),
    .So     (so_bit0),
    .Co     (co_temp[0]));

如果某些输出端口并不需要在外部连接,例化时 可以悬空不连接,甚至删除。一般来说,input 端口在例化时不能删除,否则编译报错,output 端口在例化时可以删除。例如:

//output 端口 Co 悬空
full_adder1  u_adder0(
    .Ai     (a[0]),
    .Bi     (b[0]),
    .Ci     (c==1'b1 ? 1'b0 : 1'b1),
    .So     (so_bit0),
    .Co     ());
 
//output 端口 Co 删除
full_adder1  u_adder0(
    .Ai     (a[0]),
    .Bi     (b[0]),
    .Ci     (c==1'b1 ? 1'b0 : 1'b1),
    .So     (so_bit0));

顺序端口连接

这种方法将需要例化的模块端口按照模块声明时端口的顺序与外部信号进行匹配连接,位置要严格保持一致。例如例化一次 1bit 全加器的代码可以改为:

full_adder1  u_adder1(
    a[1], b[1], co_temp[0], so_bit1, co_temp[1]);

虽然代码从书写上可能会占用相对较少的空间,但代码可读性降低,也不易于调试。有时候在大型的设计中可能会有很多个端口,端口信号的顺序时不时的可能也会有所改动,此时再利用顺序端口连接进行模块例化,显然是不方便的。所以平时,建议采用命名端口方式对模块进行例化。

端口连接规则

输入端口

模块例化时,从模块外部来讲, input 端口可以连接 wire 或 reg 型变量。这与模块声明是不同的,从模块内部来讲,input 端口必须是 wire 型变量。

输出端口

模块例化时,从模块外部来讲,output 端口必须连接 wire 型变量。这与模块声明是不同的,从模块内部来讲,output 端口可以是 wire 或 reg 型变量。

输入输出端口

模块例化时,从模块外部来讲,inout 端口必须连接 wire 型变量。这与模块声明是相同的。

悬空端口

模块例化时,如果某些信号不需要与外部信号进行连接交互,我们可以将其悬空,即端口例化处保留空白即可,上述例子中有提及。

output 端口正常悬空时,我们甚至可以在例化时将其删除。

input 端口正常悬空时,悬空信号的逻辑功能表现为高阻状态(逻辑值为 z)。但是,例化时一般不能将悬空的 input 端口删除,否则编译会报错,例如:

//下述代码编译会报Warning
full_adder4  u_adder4(
    .a      (a),
    .b      (b),
    .c      (),
    .so     (so),
    .co     (co));
//如果模块full_adder4有input端口c,则下述代码编译是会报Error
full_adder4  u_adder4(
    .a      (a),
    .b      (b),
    .so     (so),
    .co     (co));

一般来说,建议 input 端口不要做悬空处理,无其他外部连接时赋值其常量,例如:

full_adder4  u_adder4(
    .a      (a),
    .b      (b),
    .c      (1'b0),
    .so     (so),
    .co     (co));

位宽匹配

当例化端口与连续信号位宽不匹配时,端口会通过无符号数的右对齐或截断方式进行匹配。

假如在模块 full_adder4 中,端口 a 和端口 b 的位宽都为 4bit,则下面代码的例化结果会导致:u_adder4.a = {2'bzz, a[1:0]}, u_adder4.b = b[3:0] 。

full_adder4  u_adder4(
    .a      (a[1:0]),      //input a[3:0]
    .b      (b[5:0]),      //input b[3:0]
    .c      (1'b0),
    .so     (so),
    .co     (co));

端口连续信号类型

连接端口的信号类型可以是,1)标识符,2)位选择,3)部分选择,4)上述类型的合并,5)用于输入端口的表达式。

当然,信号名字可以与端口名字一样,但他们的意义是不一样的,分别代表的是 2 个模块内的信号。

用 generate 进行模块例化

当例化多个相同的模块时,一个一个的手动例化会比较繁琐。用 generate 语句进行多个模块的重复例化,可大大简化程序的编写过程。

重复例化 4 个 1bit 全加器组成一个 4bit 全加器的代码如下:

module full_adder4(
    input [3:0]   a ,   //adder1
    input [3:0]   b ,   //adder2
    input         c ,   //input carry bit

    output [3:0]  so ,  //adding result
    output        co    //output carry bit
    );

    wire [3:0]    co_temp ;
    //第一个例化模块一般格式有所差异,需要单独例化
    full_adder1  u_adder0(
        .Ai     (a[0]),
        .Bi     (b[0]),
        .Ci     (c==1'b1 ? 1'b1 : 1'b0),
        .So     (so[0]),
        .Co     (co_temp[0]));

    genvar        i ;
    generate
        for(i=1; i<=3; i=i+1) begin: adder_gen
        full_adder1  u_adder(
            .Ai     (a[i]),
            .Bi     (b[i]),
            .Ci     (co_temp[i-1]), //上一个全加器的溢位是下一个的进位
            .So     (so[i]),
            .Co     (co_temp[i]));
        end
    endgenerate

    assign co    = co_temp[3] ;

endmodule
`timescale 1ns/1ns

module test ;
    reg  [3:0]   a ;
    reg  [3:0]   b ;
    //reg          c ;
    wire [3:0]   so ;
    wire         co ;

    //简单驱动
    initial begin
        a = 4'd5 ;
        b = 4'd2 ;
        #10 ;
        a = 4'd10 ;
        b = 4'd8 ;
    end

    full_adder4  u_adder4(
               .a      (a),
               .b      (b),
               .c      (1'b0),   //端口可以连接常量
               .so     (so),
               .co     (co));

    initial begin
        forever begin
            #100;
            if ($time >= 1000)  $finish ;
        end
    end

endmodule // test

仿真结果如下,可知 4bit 全加器工作正常:

层次访问

每一个例化模块的名字,每个模块的信号变量等,都使用一个特定的标识符进行定义。在整个层次设计中,每个标识符都具有唯一的位置与名字。

Verilog 中,通过使用一连串的 . 符号对各个模块的标识符进行层次分隔连接,就可以在任何地方通过指定完整的层次名对整个设计中的标识符进行访问。

层次访问多见于仿真中。

例如,有以下层次设计,则叶单元、子模块和顶层模块间的信号就可以相互访问。

//u_n1模块中访问u_n3模块信号:
a = top.u_m2.u_n3.c ;
//u_n1模块中访问top模块信号
if (top.p == 'b0) a = 1'b1 ;
//top模块中访问u_n4模块信号
assign p = top.u_m2.u_n4.d ;

以上就是Verilog语言关键字模块例化实例讲解的详细内容,更多关于Verilog语言关键字模块例化的资料请关注我们其它相关文章!

(0)

相关推荐

  • Verilog语言的循环语句示例详解

    目录 关键词:while, for, repeat, forever while 循环 for 循环 repeat 循环 forever 循环 关键词:while, for, repeat, forever Verilog 循环语句有 4 种类型,分别是 while,for,repeat,和 forever 循环.循环语句只能在 always 或 initial 块中使用,但可以包含延迟表达式. while 循环 while 循环语法格式如下: while (condition) begin -

  • Verilog关键词的多分支语句实例详解

    目录 关键词:case,选择器 case 语句 casex/casez 语句 关键词:case,选择器 case 语句是一种多路条件分支的形式,可以解决 if 语句中有多个条件选项时使用不方便的问题. case 语句 case 语句格式如下: case(case_expr) condition1 : true_statement1 ; condition2 : true_statement2 ; -- default : default_statement ; endcase case 语句执行

  • Verilog语言关键字模块例化实例讲解

    目录 关键字:例化,generate,全加器,层次访问 命名端口连接 顺序端口连接 端口连接规则 用 generate 进行模块例化 层次访问 关键字:例化,generate,全加器,层次访问 在一个模块中引用另一个模块,对其端口进行相关连接,叫做模块例化.模块例化建立了描述的层次.信号端口可以通过位置或名称关联,端口连接也必须遵循一些规则. 命名端口连接 这种方法将需要例化的模块端口与外部信号按照其名字进行连接,端口顺序随意,可以与引用 module 的声明端口顺序不一致,只要保证端口名字与外

  • R语言箱线图创建实例讲解

    箱线图是数据集中的数据分布良好的度量. 它将数据集分成三个四分位数. 此图表表示数据集中的最小值,最大值,中值,第一四分位数和第三四分位数. 它还可用于通过绘制每个数据集的箱线图来比较数据集之间的数据分布. R语言中使用boxplot()函数来创建箱线图. 语法 在R语言中创建箱线图的基本语法是 - boxplot(x, data, notch, varwidth, names, main) 以下是所使用的参数的描述 - x是向量或公式. 数据是数据帧. notch是逻辑值. 设置为TRUE以绘

  • 基于python select.select模块通信的实例讲解

    要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值. select()方法接收并监控3个通信列表, 第一个是所有的输入的data,就是指外部发过来的数据,第2个是监控和接收所有要发出去的data(outgoing data),第3个监控错误信息在网上一直在找这个select.select的参数解释, 但实在是没有, 哎...自己硬着头皮分析了一下. readable, writable, exceptional = select.select(inputs, ou

  • R语言操作X轴日期实例讲解

    R语言操作X轴日期: 需要用到程序包library(lubridate):程序包是在R的安装包C:\R-3.4.4\bin\x64\RGui.exe里根据命令安装的 将日期改为xxxx/xx/01: firstDay='2020/02/12' : 可用 day(firstDay)<-01; //此时firstDay的数据为:'2020/02/01':day()是获取日,month()获取月份,year()获取年份 都需要'lubridate'包 可以通过write.table(firstDay,

  • R语言基础统计方法图文实例讲解

    tidyr > tdata <- data.frame(names=rownames(tdata),tdata)行名作为第一列 > gather(tdata,key="Key",value="Value",cyl:disp,mpg)创key列和value列,cyl和disp放在一列中 -号减去不需要转换的列 > spread(gdata,key="Key",value="Value") 根据value将

  • R语言对CSV文件操作实例讲解

    在 R 语言中,我们可以从存储在 R 语言环境外的文件中读取数据. 我们还可以将数据写入将被操作系统存储和访问的文件. R 语言可以读取和写入各种文件格式,如​csv​,​excel​,​xml​等. 在本章中,我们将学习从​csv​文件读取数据,然后将数据写入​csv​文件. 该文件应该存在于当前工作目录中,以便 R 语言可以读取它. 当然我们也可以设置我们自己的目录并从那里读取文件. 获取和设置工作目录 您可以使用​getwd()​函数检查R语言工作区指向的目录. 您还可以使用​setwd(

  • C语言杨氏矩阵查找算法实例讲解

    目录 一.杨氏矩阵介绍 二.查找算法 1.查找思路 2.步骤 3.代码 三.杨氏矩阵例题 代码 特别注意 四.总结 本文以C语言实现,介绍杨氏矩阵中通用的查找算法. 一.杨氏矩阵介绍 杨氏矩阵种,每一行的数都从左到右递增,每一列的数都从上到下递增.如下图是一个简单的杨氏矩阵: 有一个数字矩阵,矩阵的每行从左到右是递增的,矩阵从上到下是递增的,请编写程序在这样的矩阵中查找某个数字是否存在. 要求:时间复杂度小于O(N) 二.查找算法 1.查找思路 杨氏矩阵是很有特点的,它有规律递增的特点决定了针对

  • 用R语言绘制ROC曲线的实例讲解

    1 roc曲线的意义 ROC曲线就是用来判断诊断的正确性,最理想的就是曲线下的面积为1,比较理想的状态就是曲线下的面积在0.8-0.9之间,0.5的话对实验结果没有什么影响. 如图: 2代码部分 install.packages("pROC") install.packages("ggplot2") library(pROC) library(ggplot2) #建立曲线 data(aSAH) rocobj1<-roc(aSAHo u t c o m e ,

  • 易语言编写登录小程序实例讲解

    我们首先来看下源码内容 .程序集 窗口程序集_启动窗口 .子程序 _按钮1_被单击 .如果真 (编辑框1.内容 = "" 或 编辑框2.内容 = "") 信息框 ("用户名或密码不能为空!", 0, , ) 编辑框1.获取焦点 () 标签3.可视 = 假 标签4.可视 = 假 返回 () .如果真结束 .如果真 (编辑框1.内容 = "123" 且 编辑框2.内容 = "123") 信息框 ("登

  • python模块之time模块(实例讲解)

    time 表示时间的三种形式 时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行"type(time.time())",返回的是float类型. 格式化的时间字符串(Format String): '1999-12-06' 时间格式化符号 ''' %y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-2

随机推荐