大多数初学者还没有真正很难掌握Verilog/SystemVerilog硬件描述语言(HDL)中wire(网络)和reg(变量)的区别。这个概念是每个经验丰富的RTL设计都应该熟悉的。但是现在有许多没有Verilog开发经验的验证工程师都在为他们的验证平台选择SystemVerilog。
验证方法往往专注于验证平台设计的面向对象的编程方面,但很少涉及这个wire和reg的区别,认为它仅适用于设计。这是不正确的。
如果你需要与DUT通信,那么你就需要了解wire和reg(网络和变量)之间的区别。
任何设计或验证芯片的人都应该具备一些基本的verilog开发技能,并了解wire和reg的概念。你需要获取的关键概念是,你将一个值写入一个变量,该值被保存到该变量的下一次赋值。这个概念被称为过程赋值,是执行代码语句的一部分。HDL可能会在赋值和其他语句之间添加一些时间的概念。
组合逻辑 | 时序逻辑 |
|
|
最初,Verilog使用关键字reg来声明表示时序逻辑硬件寄存器。后来,综合工具开始使用reg来表示时序逻辑以及组合逻辑,如上实例所示。所以,最终Verilog文档被更改为说reg只是用于声明变量的,而不仅仅是时序逻辑。
SystemVerilog重命名了reg 为logic,以避免与寄存器混淆——它只是一个数据类型(具体来说是1位,4状态数据类型)。从现在开始,忘掉它,仅使用logic。
HDL的另一个显著特点是,它对大量并行过程进行建模。在数字设计的最低水平上,每个逻辑(AND,OR,DFF)都是一个独立的并发过程。module是代表在不同抽象级别建模的进程的容器,并且通过wire相互传递值。在Verilog中,wire声明表示连接的网络。每个并发进程的输出都驱动一个网络,这被称为连续赋值,因为该进程不断更新它想要在网络上驱动的值。声明连续赋值的方法多种多样,所有这些方法都代表连续赋值行为:
wire A, B, C;
assign A = B| C; // continuous assignment construct.
or(A,B,C); // gate-level instance terminal connection
mymodule m1(A,B,C); // module instance port connection
虽然这些都是不同形式的连续赋值结构,但它们都没有像过程赋值那样直接向网络赋值。所有同时驱动到网络上的值会根据驱动强度抉择出最终结果。例如,中断请求信号可能会使用线或(wor)类型的网络来指示至少有一个设备正在驱动为“1”,否则它将解析为“0”。一些信号将具有较弱的上拉/下拉电阻,这些电阻将被更强驱动器的值覆盖。大多数技术不允许在同一网络上驱动不同的值,当这种情况发生时,网络将解析为未知的“x”态。在这种情况下,只有一个驱动程序主动赋值“0”或“1”,而其他驱动程序则通过驱动高阻抗或“z”状态关闭。其结果是,双向端口必须使用wite进行建模,才能在端口两侧有多个驱动器。
事实证明,设计中的绝大多数网络都只有一个驱动器,因此不需要强度信息。SystemVerilog添加了一项logic类型,仅允许单个连续赋值来驱动变量。每当表达式更改其值时,驱动连续赋值的表达式都会分配给变量。一旦有多个驱动或需要强度信息,必须重新使用wire。
不能将过程和连续赋值混合到同一变量。这种限制的原因是,无法确定最后一次变量更新什么时候完成,过程赋值还是连续赋值。
总之,现在应该使用4个状态变量logic(或2个状态变量的bit)的逻辑来表示所有单个驱动器的信号。任何具有多个或可能存在多个驱动的信号都应声明为wire。