先放上连接规则的简图,再详细解释
1. 构建模型——污水处理之流水模型
我们先将上述结构构件一个简单模型,以帮助我们理解。
- 污水:输入数据
- 净水:输出数据
- 双向数据暂不讨论,取输入和输出的交集即可
- 污水处理厂:模块(设计块/激励块)
2. 结构——放大模型,展现细节
这里只对input和output进行展现,先暂时不管inout。
在展现之前,先来明确对于几个重要概念的理解
2.0 深入理解规则才能打破规则!
问题1:net类型和reg类型究竟有什么区别?
问题2:为什么这几个接口的类型要这样限定?
2.1 net与reg的区别——水管阀门模型
我们将数据比喻为水,数据的处理过程就像水在水管中流动一样。
-
net类型:无阀门的水管,只能让水流动,不能储存。
-
reg类型:双阀门的水管,即可以让水流动,也能存储水。
- reg类型需要接收数据,则打开阀门A,水满之后关闭阀门A,就实现了存储数据
- 需要使用数据的时候,则可以打开阀门B
- 需要让数据流入后直接流出,则可以同时打开A和B,这时候就和net类型的功能一样
-
需要强调的是:reg和net是一类数据类型的总称,将这个类型分别类比为两种水管;这是粗略的模型,具体细分的数据类型再进一步展开即可。
2.2 构建结构——污水处理模型细节化
下面我们来逐一分析一下:
- ①输入端口的外部:
可以是reg或者net,因为外部的污水可以是从别处直接流过来的,也可以是之前被保存起来,然后再开闸流过来的 - ②输入端口的外部:
来者不拒!外面流过来污水,就必须接收! - ③输出端口的内部:
- 净水可以直接留到外面去
- 净水也可以被保留起来,它可能会被回环用于污水处理过程,这是由其实际需求而被规定的,如果有需求就用,没有就不用。
- ④输出端口的外部:
输出的净水不能被封闭起来,一定要被排出去,否则就堵死了!
接下来,我们继续优化这个模型,增加结构的细节!
好的我想你是能够理解这个图形的,对于输出端口,内部可能回环再利用,外部可能直接输出,也可能返回来在进入输入,这些都可能发生的,具体怎么设定,看实际需求。
另外,对于①和③,也可以是无阀门的管道,这点我再强调一遍。
2.3 三种模式——端口与外部信号的连接模式
- 进去之后全部出去(与门)
- 进去后部分出去,部分回来(T触发器)
- 多门路互相影响(SR锁存器)
2.4 reg与net 的使用原则
- 对于内部接口的设置
- 不写就默认wire
- 特殊需求:输出显式使用reg
- 对于外部接口的设置
看实际需求和使用习惯!
这一部分简单看看就可以,不用深入了解,这些原则的使用方法,应该由大量实践得出。
3. 回归Verilog——结构的实现
我想,你通过污水处理结构,已经能够对Verilog端口连接规则有了理解,并且,事实上你非常轻松地理解了它!
下面让我们上升一个抽象层次,看一看具体在Verilog中是如何使用端口连接规则的。
以下采用
- EDA工具:Vivado 2017.4
- 代码风格:ANSI C风格
- 端口连接:命名端口连接
3.1 内部模块的端口设计
module show(input a,input [3:0] b,output c,output reg d);
……<模块内容>
……
endmodule
注:也可以使用 input a,b 的形式,对于代码风格,也需要参考EDA工具的支持情况,不同工具的使用规则可能不一样。
3.2 模块与外部信号的连接
对于外部信号而言,不是reg就是net类型,怎么着都应该能够输入进如其他的模块实例,因此,也就能够进一步理解,为什么输入端口的外部允许reg和net类型的数据了。
这里只讲解命名端口连接规则,先给出实例,模块show为底层模块,而模块show_up为其上一级模块。
module show_up(input aa,input [3:0] bb,output cc,output reg dd;);show s1( //调用模块实例并且进行端口连接.a(aa),.b(bb),.c(cc),// .d(dd) 非法连接!reg类型的外部信号,不能连到输出端口上// 可以选择不连接,或者修改为net类型);
……
<模块内容>
……
endmodule
需要注意的几个问题:
- 警惕输出端口非法连接
外部信号与模块端口连接的时候,reg类型的输出信号不能与输出信号连接,可以有以下修改方式(由需求决定):- 将reg类型变为net类型
- 增加一个wire类型的输出与之相连,reg类型的输出不进行端口连接
- 模块实例的端口可以不连接
- 模块内外两部分的位宽要匹配,否则可能出现问题
4. 实战经验
对于一整个设计模型而言,如果子模块的输出端口均与它的上级模块连接,那么,整个设计系统中,只有叶单元的(内部)输出端口可以是reg类型,其余是上层单元只能是net类型!
这个不做过多解释,我相信你能够想明白,只需要你在设计模块端口的时候注意这个问题!
一般情况下,输出端口默认wire即可,除非特殊情况采用reg!