verilog HDL中wire和reg的区别 下载本文

reg 型变量如果没有赋予初始值,默认初始值为不定态“X”。

在理解这两种基本的数据类型之后,我们来看看verilog语言中的赋值语句。verilog语言中的赋值语句有两种,一种是持续赋值语句(assign语句),另一种是过程赋值语句(always语句)。

持续赋值语句(assign语句)主要用于对wire型变量的赋值,因为wire(线型)的值不能存住,需要一直给值,所以需要用持续赋值。

例如:assign c = a + b; 只要a和b有任意变化,都可以立即反映到c上,也就是说c的值是根据a,b的值随时变化的。

过程赋值语句(always语句)主要用于reg 型变量的赋值 ,因为always语句被执行是需要满足触发条件的,所以always过程块里面的内容不是每时每刻都被执行,因此需要将被赋值的对象定义成寄存器类型,以便这个值能被保持住。

过程赋值又分为 阻塞赋值 “=” 和 非阻塞赋值 “<=” 两种。这里的非阻塞赋值符号 “<=” 与 “小于等于” 符号相同,他们在不同的语境下表示不同含义,要注意区分,例如在“if-else”等判断语句中,一般都表示为“小于等于”。 接下来对这两种赋值作具体讲解...

① 阻塞赋值 “=“ 。 阻塞赋值和我们平时理解的赋值差不多,不用太多解释,就是按照语句的顺序,一句句往下顺序执行。一个赋值语句执行完,然后执行下一个赋值语句。 ② 非阻塞赋值 “<=” 。非阻塞赋值就比较特别了,在同一个always过程块中,非阻塞赋值语句都是同时并发执行的,并且在过程块结束时才执行赋值操作。也就是说,在同一个always过程块中,非阻塞赋值语句被执行没有先后顺序,在过程快结束时,大家一起被赋值。

给大家举一个具体的例子:

module test (clk, a1, a2, b1, b2, c1, c2); // test为module名称,括号内的是端口列表,包含所有输入输出的变量名称

input clk, a1, a2; // 定义输入变量,这里没有定义位宽,默认为1位宽度 output b1, b2, c1, c2; // 定义输出变量,这里没有定义位宽,默认为1位宽度 reg b1 = 0 , b2 = 0, c1 = 0 , c2 = 0; // 注意!因为这些变量将会在always过程块中被赋值,所以必须定义成 reg 型

// 注意!这里省略了对输入信号clk, a1, a2 的类型定义,它们默认为1位的wire 型(因为输入信号是随时要变化,所以必须用wire型)

always @ (posedge clk) // always 用 clk 上升沿触发 begin

b1 = a1; // 这里采用的是阻塞赋值 c1 = b1; end

always @ (posedge clk) // always 用 clk 上升沿触发 begin

b2 <= a2; // 这里采用的是非阻塞赋值 c2 <= b2; end

endmodule // endmodule 别忘了,与 module 成对使用 仿真输入值设置图如下:

我们只需给输入信号赋值,输出信号根据输入信号的变化而变化。 仿真初始值图.PNG

下面请看用quartus 2 软件仿真的波形图 q2 fangzhen.PNG quartus2 function.PNG

首先请看这两张图的区别,第一张是时序仿真波形图(timing),黄色标记部分因为延时而产生,第二张图为功能仿真波形图(function),不考虑器件的延时。

在①时刻,第一个时钟上升沿到来(posedge clk), 两个always过程块同时被触发(这就是PFGA器件强大的一点,可以并发执行)

a1,b1,c1采用的是阻塞赋值。阻塞赋值语句顺序执行,先执行 b1 = a1; 由于 a1 此刻的值为 1,所以b1 变为 1,然后执行 c1 = b1;由于b1的值刚才已经变成 1 了,所以c1也变成了 1 。

a2,b2,c2采用的是非阻塞赋值。非阻塞赋值语句并发执行,也就是说 b2 <= a2; c2 <= b2; 这两句同时执行。由于a2 此刻的值为1,所以 b2 变为1,与此同时,b2 的当前值也将赋值给 c2 , b2 的当前值是是多少呢? 这里一定要分清楚了,b2 的当前值是 0,并不

是 1 ,因为在 b2 还没有变为 1 之前,b2 的值就要赋值给 c2 了,所以 c2 的值仍然是 0 。

直到在②时刻,第二个时钟上升沿到来,两个always再一次被同时触发,这次在执行 c2 <= b2; 这条赋值语句时,b2 的当前值为 1 ,所以 c2 才被赋值为 1 。

大家可以根据上面的分析方法,自己分析一下在③、④时刻 b1,b2,c1,c2 应该分别为什么值,与波形图对照着理解一下。

其实verilog语言和 c语言大同小异,比较着来学习,会比较容易......

希望这篇文章对初学者会有帮助,其实我也是初学者,希望各位高手提出批评指点..... O(∩_∩)O~

****************************************************************************** [原]Verilog中wire和reg数据类型的区别

2013-8-2阅读858 评论0

对模块中所用到的所有信号(包括端口信号、节点信号等)都必须进行数据类型的定义。如果信号的数据类型没有定义,综合器将其默认为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中reg和wire类型的区别

reg相当于存储单元,wire相当于物理连线

Verilog 中变量的物理数据分为线型和寄存器型。这两种类型的变量在定义时要设置位宽,缺省为1位。变量的每一位可以是0,1,X,Z。其中x代表一个未被预置初始状态的变量或者是由于由两个或多个驱动装置试图将之设定为不同的值而引起的冲突型线型变量。z代表高阻状态或浮空量。

线型数据包括wire,wand,wor等几种类型在被一个以上激励源驱动时,不同的线型数据有各自决定其最终值的分辨办法。

两者的区别是:即存器型数据保持最后一次的赋值,而线型数据需要持续的驱动 输入端口可以由net/reg驱动,但输入端口只能是net;输出端口可以使net/reg类型,输出端口只能驱动net;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型 用关键词inout声明一个双向端口, inout端口不能声明为寄存器类型,只能是net类型。