-
wire
表示直通,即输入有变化,输出马上
无条件地
反映(如与、非门的简单连接)。
reg
表示
一定要有触发
,输出才会反映输入的状态。
reg
相当于存储单元,
wire
相当于物理连线。
reg
表示一定要有触发,没有输入的时候可以
保持原来的值,但不直接与实际的硬件电路对应。
两者的区别是:寄存器型数据保持最后一次的赋值,而线型数据需要持续的驱动。
wire
使用在连续赋值语句中,而
reg<
/p>
使用在过程赋值语句(
initial
,
always
)中。
wire
若
无驱动器连接,其值为
z
< br>,
reg
默认初始值为不定值
x
。
在连续赋值语句中,
表达式右侧的计算结果可以立即更新表达式的左侧。
在理解上,
相当于一个逻辑之后直接连了一条线,这个逻辑对应于表达
式的右侧,而这条线就对应于
wire
。
在过程赋值语句中,
表达式右侧的计算结果在某种条件的触发下放到一个变量当中,<
/p>
而这个变量可以声明成
reg
类型的。根
据触发条件的不同,
过程赋值语句
可以建模不同的硬
件结构:
如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一
个触发器;如
果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存
器;如果这个
条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻
辑。
对组合逻辑输出变
量,可以直接用
assign
。即如果不指定为
reg
类型,那么就默认为
1
位
wire
类型,故无需指定
1
位
wire
类型的变量。当然专门指定出
p>
wire
类型,可能是多位或
为使程序易读
。
wire
只能被
assign
连续赋值,
reg
只能在
initial
和
always
中
赋值。
输入端口可以由
wire/reg
驱动,但输入端口只能是
wire
;输出端口可以是
wire/reg
类型,输出端口只能驱动
wire
;若输出端口在过
程块中赋值则为
reg
型,若在过程块外赋值
< br>则为
net
型(
wire/tr
i
)。用关键词
inout
声明一个双
向端口
, inout
端口不能声明为
reg
类
型,只能是
wire
类型。
默认信号是
wire
类型,
reg
p>
类型要申明。这里所说的默认是指输出信号申明成
output
p>
时为
wire
。如果是模块内部信号,必须
申明成
wire
或者
reg.
对于
always
语句而言,赋值要申明成
reg
,连续赋值<
/p>
assign
的时候要用
wire
。
模块调用时
信号类型确定方法总结如下:
?
p>
信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其它的信号为
p>
内部信号。
?
对
于端口信号,输入端口只能是
net
类型。输出端口可以是
p>
net
类型,也可以是
register<
/p>
类
型。
若输出端口在过程块中赋值则为<
/p>
register
类型;
若在过程块外赋
值
(
包括实例化语句)
,
则为
net
类型。
?
内部信号类型与输出端口相同,
可以是
p>
net
或
register
类型。
判断方法也与输出端口相同。
若在过程块中赋值
,则为
register
类型;若在过程块外赋值,则为
net
类型。
?
若信号既需要在过程块中赋值,又
需要在过程块外赋值。这种情况是有可能出现的,如决
断信号。这时需要一个中间信号转
换。
下面所列是常出的错误及相应的错误信息
(error
message)
?
用过程语句给一个
net
类型的或忘记声明类型的信号赋值。
信息:
illegal
……
assignment.
?<
/p>
将实例的输出连接到声明为
register
类型的信号上。
信息:
?
将模块的输入信
号声明为
register
类型。
信息:
incompatible declaration,
……
**************************************************
****************************
wire
与
reg
的区别
?
什么时候用
wire?
什么时候用
reg?
简单来说硬件描述语言有两种用途:
1
、仿真,
2
、综合。
< br>
对于
wire
和
reg
,也要从这两个角度来考虑。
从仿真的角度来说,
HDL
语言面对的是编译器(如
Modelsim
等),相当于软件思路。
这时:
wire
对应于连续赋值,如
assign
reg
对应于过程赋值,如
always
,
initial
从综合的角度来说,
HDL
p>
语言面对的是综合器(如
DC
等),要从电
路的角度来考虑。
这时:
1
、
wire
型的变量
综合出来一般是一根导线;
2
、
p>
reg
变量在
always
块中有两种情况:
(1)
、
always
后的敏感表中是(
a
or b or c
)形式的,也就是不带时钟边沿的,综合出来
还是组合逻辑
(2)
、
always
后的敏感表中是(
posedge
clk
)形式的,也就是带边沿的,综合出来一般是
时序逻辑,
会包含触发器(
Flip
-
Flop<
/p>
)
在设计中,输入信号一般来说你是不
知道上一级是寄存器输出还是组合逻辑输出,那么对
于本级来说就是一根导线,也就是
wire
型
。而输出信号则由你自己来决定是寄存器输出还
是组合逻辑输出,
wire
型、
reg
型都可以。但一
般的,整个设计的外部输出(即最顶层模块
的输出),要求是寄存器输出,较稳定、扇出
能力也较好。
为什么在
verilo
g
中要定义
wire?
有几种情况变
量需要定义成
wire
。
第一。
assign
语句
例如:
reg a,b;
wire and_result;
...
assign and_result =a&&b;
你可以试试把
wire
定义成
reg
。综合器会报错。
第二。元件例化时候的输出必须用
wire
例如:
wire dout;
ram u_ram
(
...
.out(dout)
...
);
wire
按照国外的教材上面的定义:
wire
为无逻辑连线。只做连线,
w
ire
本身是不带逻辑性的,所以输入什么输出就是什么。
所以
你尝试着用
always
语句对
wir
e
变量赋值。综合器就会报错。
那么你可能会问。
assign c =a&&b
不是就是对
wire
的赋值吗?
其实并非如此。
综合器综合时将
a&&b
综合成
ab
经过一个与门。<
/p>
而
c
只是连接到与门输出的线。
正真综合出与门的是
&&
。而不是
c
。
< br>
Abstract
Verilog
< br>初學者最常見的問題:『什麼時候該用
wire?
什麼時
候又該用
reg?
』
Introduction
大體上來說,
wire
和
reg
都類似於
C/C++
的變數,但若此變數要放在
beg
in...end
內,該變數
就須使用
reg
,在
begin...end
之
外,則使用
wire
。
另外使用
wire
時,須搭配
assign
;
reg
則不必。
p>
input
,
o
uput
,
inout
預設值都是
p>
wire
。
若<
/p>
wire
和
reg
用錯地方,
compiler
都會提醒,所以不必太擔心。<
/p>
一個很重要的觀念,在
Verilog
中使用
reg
,並不表示合成後就是暫
存器
(register)
。若在
組合
電路中使用
reg
,合成後仍只是
ne
t
,唯有在循序電路中使用
reg
,合
成後才會以
flip-flop
形式表示成
register
。
*****
**************************************************
***********************
【转载】
Verilog HDL
初级入门知识简单讲解(
wire
和
reg
类型的区别,
always
和
assign
< br>的区别,
“
阻塞
”
赋值
和
“
非阻塞赋值
”
的区别
)
很多刚学
Verilog HDL
(
硬件描述语言)的朋友肯定会对阻塞赋值和非阻塞赋值比较
疑惑,那我们就一起来抛开这
层迷雾吧。
首先我们要理解两种变量类型
Net
Type
(连线型)和
Register
Type
(寄存器型)。
(有些参考书上有分为
3
种类型,这个无关紧要)
p>
verilog
数据类型
.PNG
Net Type
(连线型),从名字上理解就是
p>
“
导线
”
呗,导线
的这头和导线的另一头始终
是直接连通的,这头是什么值,那头就是什么值,所以输出随
着输入随时变化的。连线型
中
wire
最常见。
Register
Type
(寄存器型),寄存器就不像普通导线了,它可以把值
给存住,你只要
给它赋一次值,
它都会存住那个值,
直到你给它赋一个新的值它才会改变。
寄存器型中
reg
最常见。
最常用到的是
wire
和
reg
这两种类型,其他的对我
们初学者来说一般很少用到,可
以暂时跳过,以后慢慢学下去自然会理解。
注意:
wire
型变量如果没有赋予初始值,默认初始值为高阻态
“
Z
”
。
reg
型变量如果没有赋予初始值,默认初始值为不定态
“
X
”
。
在理解这两种基本的数据类型之后,我们来看看
verilog
语言中的赋值语句。
veri
log
语言中的赋值语句有两种,一种是持续赋值语句(
ass
ign
语句),另一种是过程赋值语句
(
always
语句)。
持续赋值语句(
assign
语句)主
要用于对
wire
型变量的赋值,因为
wire
(线型)的值
不能存住,需要一直给值,所以需要用持
续赋值。
例如:
assign c = a + b;
只要
a
和
b
有任意变化,都可以立即反映到
c
上,
也就是说
c
的值是根据
a
,
b
的值随时变化的。
过程赋值语句(
always
语句)主要用于
reg
型变量的赋值
,因为
always
语句被执行
是需要满足触发条件的,所以
always
过程块里面的内容不是每时每刻都被执行,因此需
要
将被赋值的对象定义成寄存器类型,以便这个值能被保持住。
过程赋值又分为
阻塞赋值
“
=
”
和
非阻塞赋值
“
<=
”
两种。这里的非阻塞赋值符号
“
<=
”
与
“
小于等于
”
符号相同,他们在不同的语境下表示不同含义,要注意区分,例如在
“
if-else
”
等判断语句中
,一般都表示为
“
小于等于
”
。
接下来对这两种赋值作具体讲解
...
①
阻塞赋值
“
=
“
。
阻塞赋值和我们平时理解的赋值差
不多,
不用太多解释,
就是按
照语句的
顺序,一句句往下顺序执行。一个赋值语句执行完,然后执行下一个赋值语句。
②
非阻塞赋值
“
<=
”
<
/p>
。
非阻塞赋值就比较特别了,
在同一个<
/p>
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; //
注意!因为这些变量将会在
p>
always
过程
块中被赋值,所以必须定
义成
reg
型
//
注意!这里省略了对输入信号
clk, a1, a2
的类型定义,它们默认为
1
位的
wire
型(因
为输入信号是随时要变化,所以必
须用
wire
型)