对模块中所用到的所有信号(包括端口信号、节点信号等)都必须进行数据类型的定义。如果信号的数据类型没有定义,综合器将其默认为wire型。
wire表示直通,即只要输入有变化,输出马上无条件地反映;reg表示一定要有触发,输出才会反映输入。
不指定就默认为1位wire类型。专门指定出wire类型,可能是多位或为使程序易读。wire只能被assign连续赋值,reg只能在initial和always中赋值。wire使用在连续赋值语句中,而reg使用在过程赋值语句中。
在连续赋值语句中,表达式右侧的计算结果可以立即更新表达式的左侧。在理解上,相当于一个逻辑之后直接连了一条线,这个逻辑对应于表达式的右侧,而这条线就对应于wire。在过程赋值语句中,表达式右侧的计算结果在某种条件的触发下放到一个变量当中,而这个变量可以声明成reg类型的。根据触发条件的不同,过程赋值语句可以建模不同的硬件结构:如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一个触发器;如果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存器;如果这个条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻辑。
对于模块的输入输出端口要明确说明,其种类有输入端口(input),输出端口(output),输入输出端口(inout)。输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以使wire/reg类型,输出端口只能驱动wire;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型。用关键词inout声明一个双向端口, inout端口不能声明为reg类型,只能是wire类型;输入和双向端口不能声明为寄存器类型。如附图所示(DUT:design under test。wire是net的一种)。
所以如果模块的输出是reg型的,不要误以为写testbench(测试 平台)时也要用一个reg型的数据与模块输出相连,事实上恰好相反,应该用wire型与其相接,编写硬件描述语言要时刻与实际硬件联系起来。testbench为测试或仿真一个verilogHDL程序搭建了一个平台,我们给被测模块事假激励信号,通过观察被测模块的输出响应,判断其逻辑功能和时序关系是否正确。testbench无端口列表,其中激励信号(被测模块的输入信号)定义为reg类型,显示信号(被测模块的输出信号)为wire型。
====================================================================================================================
Verilog 中定义信号为什么要区分 wire 和 reg 两种类型?
Verilog 中,过程赋值语句要定义成 reg,连续赋值语句要定义成 wire,而且定义为 reg 不一定真的综合出register(也可能是纯组合逻辑),wire也不一定真的是 wire(也可能是 register)。既然如此,为何 Verilog 语法中要区分 wire 和 reg 呢?至今都没想明白有什么必要(除了制造出一些语法错误)。
31 赞同
反对,不会显示你的姓名
两者差别很大,完全不能取消。
在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的综合结果图吧。
8 赞同
反对,不会显示你的姓名
知乎用户 做过4款芯片,40次的tapout,浪费了不知…
我对“
虽然reg不一定综合出来register,但这属于综合工具对代码描述的硬件行为的一种解读 ”不是很同意的,综合工具在一定的程度上就是反应你的设计意图,至于为什么不想要的结构,原因有二:其一是你代码写的规范;其二你没有理解你的代码会综合出什么硬件的预期。例如我定义:
reg a ;
reg b;
always@ (*) begin
if (<condition>)
a = tmp ;
b = a ;
end
在这段代码中a是不会综合出寄存器的,而b却会,原因在于a是中间变量,就是一条线,所以综合出来的不是寄存器,而是一条线。而在condtion不满足的情况下b要保值,所以b会综合成寄存器。绝不是
综合工具对代码描述的硬件行为的一种解读。 ================= wire也不一定真的是 wire(也可能是 register) 这是绝对不可能发生的事情。从verilog的语言上讲只有值和语句的关系。值分成常量和变量两种,而常量是用过wire类型来体现的,这种情况下wire是直接接到高低电平上的,所以不可能是寄存器;再者语句分为过程语句和连续赋值语句,而连续赋值语句是一定不会综合出寄存器的,因为他会马上被引用,没有机会保值;而过程语句大家都知道赋值的变量一定是reg类型的,所以这种情况也被否决掉了。综上所述“
wire也可能是 register” 这是绝对不可能发生的事情。
33 赞同
反对,不会显示你的姓名
屯屯屯屯 Investment / ASIC
谢邀。实在不好意思拖延症又犯了,这么久才回答。
这是一个历史遗留问题。在 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. 其实我上学的时候一开始也有同样的疑问。
0 赞同
反对,不会显示你的姓名
For system verilog, you can use logic for both wire and reg.
9 赞同
反对,不会显示你的姓名
这学期刚学习了大规模集成电路,刚开始的时候也有题煮的疑惑,在此分享一点自己的理解,希望能帮到你。如果有不对的地方也希望大家指正。毕竟只是初学者为了应付考试的理解~
首先我理解的是,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的盆去接水,这样这些水才能被你用。
4 赞同
反对,不会显示你的姓名
很简单
你用verilog写一个simulation的testbench
你会发现input永远是reg,output永远是wire
你再写一个always block
你会发现output永远是reg,说白了只有reg才能在always block里面变值
附赠一张slide
1 赞同
反对,不会显示你的姓名
因为verilog是硬件描述语言
你设计的是硬件电路
你设计的是硬件电路
你设计的是硬件电路
硬件电路,特别是时序硬件电路,里面的基本构成:寄存器 逻辑门 连线
1 赞同
反对,不会显示你的姓名
网络数据类型表示结构实体(例如门)之间的物理连接。网络类型的变量不能储存值,而且它必需受到驱动器(例如门或连续赋值语句,assign)的驱动。如果没有驱动器连接到网络类型的变量上,则该变量就是高阻的,即其值为z。常用的网络数据类型包括wire型和tri型。这两种变量都是用于连接器件单元,它们具有相同的语法格式和功能。之所以提供这两种名字来表达相同的概念是为了与模型中所使用的变量的实际情况相一致。 wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。如果wire型或tri型变量没有定义逻辑强度(logic strength) ,在多驱动源的情况下, 逻辑值会发生冲突从而产生不确定值。
====================================================
wire型数据常用来表示用于以assign关键字指定的组合逻辑信号。Verilog程序模块中输入输出信号
类型缺省时自动定义为wire型。wire型信号可以用作任何方程式的输入,也可以用作“assign”语句
或实例元件的输出。
====================================================
寄存器是数据储存单元的抽象。 寄存器数据类型的关键字是reg.通过赋值语句可以改变寄存器储存的值,其作用与改变触发器储存的值相当。Verilog HDL语言提供了功能强大的结构语句使设计者能有效地控制是否执行这些赋值语句。这些控制结构用来描述硬件触发条件,例如时钟的上升沿和多路器的选通信号。在行为模块介绍这一节中我们还要详细地介绍这些控制结构。reg类型数据的缺省初始值为不定值x。
=====================================================
别想那么复杂,好好体会。
学而不思则罔,思而不学则殆。
=====================================================
以上摘自《夏宇闻Verilog经典教程》
1 赞同
反对,不会显示你的姓名
Andrea 台大碩士在讀/Digital IC design/二次元…
你在哪本书看到wire也能综合出register的?看我不打死那个作者。
本质上为什么要有reg和wire,因为电路需要有记忆性的单元(比如FF)以及无记忆性的单元(比如导线)
reg可以合成导线的前提是这个过程块是描述组合逻辑的,那就不需要记忆性单元了。
但是如果条件分支没写全就会合出latch
所以在systemverilog里面都统一定义成logic就好了,非常适合啥都不懂的小白
0 赞同
反对,不会显示你的姓名
reg 只能在always或者initial里面赋值,而wire可以用assign赋值。这是语法区别,设计上灵活的选用。综合只是工具去理解你的设计意图。
0 赞同
反对,不会显示你的姓名
知乎用户 二次元、阿宅、勃学
Hardware description languages need the concept of a wire. - Janick Bergeron
The variable is sufficient for ordinary sequntial programming languages.When desribing hardware, a construct that describe the behavior of a wire used to connect multiple devices together must be provided.
希望对你有帮助