Verilog 中定义信号为什么要区分 wire 和 reg 两种类型?

作者:young cc
链接:https://www.zhihu.com/question/21021718/answer/56339195
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

两者差别很大,完全不能取消。
在Verilog中,wire永远是wire,就是相当于一条连线,用来连接电路,不能存储数据,无驱动能力,是组合逻辑,只能在assign左侧赋值,不能在always @ 中赋值;
reg可以综合成register,latch,甚至wire(当其只是中间变量的时候),可以用于组合逻辑或者时序逻辑,能存储数据,有驱动能力,在always @模块表达式左侧被赋值。
两个共同具有性质:都能用于assign与always @模块表达式的右侧。

-----------------------------------------------------------------------------
看到一篇讲两者区别的很棒的文章http://inst.eecs.berkeley.edu/~cs150/Documents/Nets.pdf
等有空上传一张Synopsys DC中将reg综合成wire的综合结果图吧。
558 条评论
分享
收藏感谢
11 人赞同了该回答

我对“虽然reg不一定综合出来register,但这属于综合工具对代码描述的硬件行为的一种解读”不是很同意的,综合工具在一定的程度上就是反应你的设计意图,至于为什么不想要的结构,原因有二:其一是你代码写的规范;其二你没有理解你的代码会综合出什么硬件的预期。例如我定义:
reg a ;
reg b;
[email protected] (*) begin

if (<condition>)
a = tmp ;
b = a ;

end
在这段代码中a是不会综合出寄存器的,而b却会,原因在于a是中间变量,就是一条线,所以综合出来的不是寄存器,而是一条线。而在condtion不满足的情况下b要保值,所以b会综合成寄存器。绝不是综合工具对代码描述的硬件行为的一种解读。
=================
wire也不一定真的是 wire(也可能是 register)
这是绝对不可能发生的事情。从verilog的语言上讲只有值和语句的关系。值分成常量和变量两种,而常量是用过wire类型来体现的,这种情况下wire是直接接到高低电平上的,所以不可能是寄存器;再者语句分为过程语句和连续赋值语句,而连续赋值语句是一定不会综合出寄存器的,因为他会马上被引用,没有机会保值;而过程语句大家都知道赋值的变量一定是reg类型的,所以这种情况也被否决掉了。综上所述“wire也可能是 register”这是绝对不可能发生的事情。
118 条评论
分享
收藏感谢
35 人赞同了该回答

谢邀。实在不好意思拖延症又犯了,这么久才回答。

这是一个历史遗留问题。在 Verilog 被 Cadence 买下之前(大约上世纪八九十年代的样子),Verilog 只是一个用来做仿真的 HDL,不可综合。在那个年代,仿真器看到 wire 和 reg 会区别处理(实际上至今也是这样)。不知道你有没有发现,reg 类型信号的跳变,是依靠输入和敏感列表的,而且在非阻塞赋值中也存在一种并行的概念(同样条件下 B <= A、C <= B 的时候,A 的值不会直接到 C 去)。而 wire 只需要输入就足够了。这样区分两种类型也是为了更好地模拟真实硬件中时序逻辑和组合逻辑的行为。
仿真器对 wire 类型会在每个 delta time 都进行计算并赋值,而 reg 类型只有在满足敏感列表条件时才会计算。
而如今随着 SV 的推出 Verilog 都已经到 2005 了,但当初的这一习惯继承了下来。虽然 reg 不一定综合出来 register,但这属于综合工具对代码描述的硬件行为的一种解读。always @ (*) 当中这个敏感列表依然存在,仿真器依然会依照敏感列表的指示去干活,不论你的敏感列表是不是*。反过来看 wire,虽然 RTL 代码中这个 wire 信号可能就是综合后网表中某个寄存器的 Q 端,但是在行为级描述中你对这根 wire 重命名也确实是在描述一种硬件行为。

P.S. 其实我上学的时候一开始也有同样的疑问。
357 条评论
分享
收藏感谢

请学习 systemverilog 2012
其实就是新版 verilog 换个名字

没有multiple driven 就用 logic
有就用 wire

reg 很迷惑的 因为不一定会综合成 寄存器
0添加评论
分享
收藏感谢
14 人赞同了该回答
这学期刚学习了大规模集成电路,刚开始的时候也有题煮的疑惑,在此分享一点自己的理解,希望能帮到你。如果有不对的地方也希望大家指正。毕竟只是初学者为了应付考试的理解~
首先我理解的是,Verilog作为一门行为描述语言,你可以把每一段程序都理解为“用语言描述一个模块”,而实际上,一个模块的组成无非就是“引脚”+“内部的各种电路”。
有个这种准备之后就好理解wire 和 reg 了。Verilog中,把没有定义类型的信号默认设置为wire,除非特殊声明一次。如:
input[7:0] a, b;
reg [7:0] a;
以上例子,由于“input”就是模块管脚的声明,他有两个管脚a,b,用作输入。而再把a定义成寄存器类型,方便功能定义中进行操作。所以此时a 为reg型 b 为 默认wire 型。
所以说,可以粗略地把wire型理解为“从管脚输入的、原始的信号序列”,他在导体上以电信号的形式流动,而把reg型理解为“用寄存器存着从管脚输入的信号”,因为之后在寄存器中存住的数字信息,才能进行诸如移位、赋值等操作。
打个比方,你在一个房间里,房间有两个水管,一个流入一个流出,你可以直接把水管的水从输入管接到输出管,但你就没办法用这些水了。如果你想用这些水来炒菜、洗澡、打水仗、等等,你就要用一个名为reg的盆去接水,这样这些水才能被你用。
144 条评论
分享
收藏感谢
7 人赞同了该回答

很简单
你用verilog写一个simulation的testbench
你会发现input永远是reg,output永远是wire

你再写一个always block
你会发现output永远是reg,说白了只有reg才能在always block里面变值

附赠一张slide&amp;amp;lt;img src=&quot;https://pic1.zhimg.com/50/593577bf077dcbfcbfeac8278eab0cbc_hd.jpg&quot; data-rawwidth=&quot;433&quot; data-rawheight=&quot;293&quot; class=&quot;origin_image zh-lightbox-thumb&quot; width=&quot;433&quot; data-original=&quot;https://pic1.zhimg.com/593577bf077dcbfcbfeac8278eab0cbc_r.jpg&quot;&amp;amp;gt;Verilog 中定义信号为什么要区分 wire 和 reg 两种类型?
72 条评论
分享
收藏感谢
For system verilog, you can use logic for both wire and reg.
0添加评论
分享
收藏感谢
6 人赞同了该回答
&amp;lt;img src=&quot;https://pic1.zhimg.com/50/v2-2cfb9e0b5763173697280818f52baa1f_hd.jpg&quot; data-rawwidth=&quot;348&quot; data-rawheight=&quot;216&quot; class=&quot;content_image&quot; width=&quot;348&quot;&amp;gt;Verilog 中定义信号为什么要区分 wire 和 reg 两种类型?

看了young cc推荐的文章,在语法层面做个小总结,希望对大家有所帮助~~

62 条评论
分享
收藏感谢
1 人赞同了该回答
网络数据类型表示结构实体(例如门)之间的物理连接。网络类型的变量不能储存值,而且它必需受到驱动器(例如门或连续赋值语句,assign)的驱动。如果没有驱动器连接到网络类型的变量上,则该变量就是高阻的,即其值为z。常用的网络数据类型包括wire型和tri型。这两种变量都是用于连接器件单元,它们具有相同的语法格式和功能。之所以提供这两种名字来表达相同的概念是为了与模型中所使用的变量的实际情况相一致。 wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。如果wire型或tri型变量没有定义逻辑强度(logic strength) ,在多驱动源的情况下, 逻辑值会发生冲突从而产生不确定值。
====================================================
wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。Verilog程序模块中输入输出信号
类型缺省时自动定义为wire型。wire型信号可以用作任何方程式的输入,也可以用作“assign”语句
或实例元件的输出。
====================================================
寄存器是数据储存单元的抽象。 寄存器数据类型的关键字是reg.通过赋值语句可以改变寄存器储存的值,其作用与改变触发器储存的值相当。Verilog HDL语言提供了功能强大的结构语句使设计者能有效地控制是否执行这些赋值语句。这些控制结构用来描述硬件触发条件,例如时钟的上升沿和多路器的选通信号。在行为模块介绍这一节中我们还要详细地介绍这些控制结构。reg类型数据的缺省初始值为不定值x。
=====================================================
别想那么复杂,好好体会。
学而不思则罔,思而不学则殆。
=====================================================
以上摘自《夏宇闻Verilog经典教程》
1添加评论
分享
收藏感谢
1 人赞同了该回答

你在哪本书看到wire也能综合出register的?看我不打死那个作者。

本质上为什么要有reg和wire,因为电路需要有记忆性的单元(比如FF)以及无记忆性的单元(比如导线)

reg可以合成导线的前提是这个过程块是描述组合逻辑的,那就不需要记忆性单元了。
但是如果条件分支没写全就会合出latch



所以在systemverilog里面都统一定义成logic就好了,非常适合啥都不懂的小白
1添加评论
分享
收藏感谢
1 人赞同了该回答

因为verilog是硬件描述语言

你设计的是硬件电路
你设计的是硬件电路
你设计的是硬件电路

硬件电路,特别是时序硬件电路,里面的基本构成:寄存器 逻辑门 连线
1添加评论
分享
收藏感谢

组合逻辑:输出只和输入有关;无反馈,无记忆元件。

时序逻辑电路:输出和输入以及电路前一时刻状态有关。有反馈,有记忆元件。

主要数据类型:net 表示器件之间的物理连接,线网类型,由模块或者门驱动的连线,驱动信号的改变会立即传到输出的连线上;register表示抽象的存储单元,成为寄存器/变量类型;parameter 表示常数,即参数类型,在编译的时候可以改变。

在连续赋值语句中,表达式右侧的计算结果可以立即更新表达式左侧的值,相当于一个逻辑之后连接了一根线,这个了逻辑对应于表达式的右侧,这条线相当于wire。而在过程赋值语句中,表达式右侧的计算结果在某种条件下的触发下放到一个变量中去的,这个变量被声明成reg类型。但是根据触发条件的不同,过程语句可以建模不同的硬件结构;如果触发条件是时钟的边沿,其硬件模型为触发器;如果触发条件是某一信号的高电平或者低电平,其硬件模型就是锁存器,该硬件模型就是一个组合逻辑。

题主说的reg不一定综合成寄存器,指的应该就是reg综合成触发器这种情况吧。我觉得我上面写的这样去理解比较容易。锁存器跟触发器可是有本质区别,从电路角度来讲,触发器是由两个锁存器构成的。

我今天也是在纠结这个问题,查了一下资料,做了一下笔记,也终于搞明白了。再延伸一下,如果理解了reg为什么可以用来实现组合逻辑和时序逻辑,也就彻底能明白阻塞赋值和非阻塞赋值的区别了。

0添加评论
分享
收藏感谢

刚才看到有人说wire类型不储存值,那我也有个疑惑,既然不储存值为什么可以进行if (rst==0) 这种类型的判断呢?谢谢

0添加评论
分享
收藏感谢

题主思考的很对,确实没有必要。

所以在 SystemVerilog 中引入了 logic 类型,完全不需要 wire 和 reg 类型即可进行设计。但是作为designer而言,内心是要 wire 与 reg,组合逻辑与时序逻辑 的区分的,你需要知道你写出来的代码哪部分只是wire,哪部分则是reg,哪部分会综合成组合逻辑,哪部分又会综合成时序逻辑。即从硬件的角度是思考设计代码。

0添加评论
分享
收藏感谢

1.

“”wire也不一定真的是 wire(也可能是 register)” 这个是要毁我三观吗?!!!!

reg型可能会综合成wire,wire绝对不可能综合成register。在elaborate阶段就会报错。


2.

verilog为什么会有wire和reg型。首先回答一个问题,verilog是什么?

verilog是一种HDL, hardware description language,硬件描述语言。

他的目的就是为了描述硬件的行为的。硬件里面有什么,verilog语言就需要建模什么。这个是核心。verilog描述一个硬件的物质世界的抽象语言。

那我们看看硬件里面有什么,不就是金属线连接一些MOS管吗? Ok, 金属线用什么描述,wire型。那个数字电路中最基本的单元D 触发器用什么呢? reg型。


3. 为什么申明的reg型,综合出来有可能是wire型。

综合工具会根据你语言描述的上下文去推断电路结构,在自己的通用库也就是GTECH库中寻找基本的单元去替换verilog的语言描述。比如:

reg a;

assign a=b|c;

综合工具一看这里a是一个电平触发的,不是时钟沿触发,这里不需要D flip flop。然后再看后面,喔,这是一个或门。然后从GTECH库中找一个或门出来。

至于为什么reg可以有wire的行为,但是wire却没有reg的行为,IEEE 协议是这样规定的,综合工具就要按照IEEE来。detail原因我也不知道。