|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
Verilog语法中最基本的数据类型有 线网(wire),寄存器(reg)和整数(integer)三种类型,这三种数据类型是可综合的数据类型,在Verilog 程序设计中被广泛使用。其它还有可以用于仿真的数据类型如 timer,real,字符串等变量都可以看作reg类型的扩展。wire,reg ,integer,timer,real是声明变量类型的关键字。变量必须先声明后使用,声明后变量的数据类型也就确定了。变量声明是模块(module)内惟一的,不能在同一个模块或函数内重复声明。3 l, B6 j% C/ b8 S* L& R
- 线网(wire):8 D/ ~2 v6 T9 z7 }& c
线网(wire)类型表示逻辑单元或实例之间的连线,一般由逻辑单元的输出驱动。没有连接驱动的wire型变量的值为高阻’z’。
) b* Z7 c" y6 R4 O6 l- wire类型变量的使用:
- wire型变量的声明与赋值
. P! o T4 Q N' ~ k* Nwire类型的变量只能由assign语句赋值,或在声明时赋初值。而且赋值的机会只有一次。
8 D$ J [6 s/ V# m- F! z! c 变量声明实例:
6 X% z/ m$ m2 G2 c# zwire a, b; 3 Y$ H" _* [& G+ l2 M$ _
wire c = 0;% k: E: s* C! \: ^/ M: B) d
wire d = 1'b1;
# X' E9 ?' @3 k9 W' a1 b! p* t" Sassign a = c;% a: R$ G3 z" ?7 ]7 b9 |
声明a, b为线网类型,并将c的值赋给a, 此时a的为0;而且a只有这一次赋值机会。8 |5 f/ G+ v* F9 ]& R2 u
变量c在声明的时候赋初值为0,此后c就一直保留该值,不能再给c赋值,也不能再次声明。2 G. k5 n& t o/ L7 Z; }
注意:wire类型的变量不能重复赋值。
: D7 z- | y0 ]2 R4 F6 ~1 A+ y$ u- 桥接
/ Y$ m" y4 I. P3 [% B2 s Wire 型变量作为中间变量可以实现桥接的作用。在下面的例子中可以看出,wire型变量起到变量之间值传递的作用。
$ B7 n7 z+ Z5 R4 y& e实例1:. b8 t3 m7 u, Q% O5 v
module wire_bridge9 J7 O8 a5 L4 b) {
(5 L% g A1 d1 ^) m, `$ V7 X3 z
input a,b,ci,
" G" N+ g \# u. i7 Soutput y,co
, r7 a. H, N( f& w, s6 N);, q. P8 S9 N! k2 T1 a/ O" g
wire d, e, f;
9 y3 e3 Z0 a/ l: C& d6 \assign d = a ^ b;
8 R* K3 m" x' B: T& Massign e = a & b;5 ?+ X" |( T @! g$ c' Y
assign f = ci & d;: t* T) R' d5 F( a( I6 u7 U
assign y = d ^ ci;4 z1 s0 y: |. I2 V" q
assign co = e | f; @5 G F3 o4 l {
endmodule+ o$ ]* m+ F m& X, P4 t
wire变量在逻辑电路中的对应关系,简单的说就是起到连线的作用。
, p0 ^# g7 C3 A8 e, r在例化模块之间传递变量。1 Q2 _8 U- _/ m& a9 `
实例2:, M. J9 D9 l# [0 X' v; ~
module fadder4
, s; H6 s/ h5 V! r8 ]( J5 l(
! c2 p3 L ?8 T+ n5 einput ci,
C1 x6 X2 c+ j2 R8 e9 O$ X% J" i9 [+ minput [3:0] a,
' r5 }; b# G) C3 Rinput [3:0] b,
7 V# i6 i3 m1 A
3 C# Q. m9 n" d) Coutput [3:0] y,
, ~" K5 k p' D4 j; loutput co
8 O F) H C# @% i# Y. X9 r);
5 y9 H4 H, a- A: U% Kwire co1,co2,co3;
, z' y( b' F4 k7 v; ?3 Q$ E// 例化 一位全加器,并重复使用4次' f; k' P: V; F/ `4 y( q4 G
fadder1 fadder1_inst18 h7 y s/ S3 E5 P
(# g( ~ U, \) l" b9 o- y1 v
.ci (ci),: }# c7 N v w
.a (a[0]),
! T& ?1 S& h: v. g B.b (b[0]),
6 s1 G1 i) I9 q" { v C j- Q.y (y[0]),
( L+ R! o, K. f! E6 ]) H9 V: Q.co (co1)- N( T# _1 j$ J' L: x/ I+ e
);
# O. j3 {4 q5 Gfadder1 fadder1_inst2
6 ^6 X0 g" f8 p& H) J" D(: T% p' x% y1 z) C! @
.ci (co1),
2 i$ t: K9 G: y.a (a[1]),
3 v+ V* v6 O$ O.b (b[1]),! h5 v, a) y* c1 t6 V N
.y (y[1]),9 T& C$ f2 M: p1 t' n! n4 ^
.co (co2)
& ^8 d0 U5 Q% [1 S);9 v5 D z( n' i( q9 u5 l* l
. R5 h9 ^6 L. _' u0 H% I9 V
fadder1 fadder1_inst3
. P9 O& ]! q7 c(
, l( R* J, h- q1 E/ x! @* y.ci (co2),
' Q: M7 c- ~' g0 [5 f$ f& _4 y9 `.a (a[2])," A+ a M1 G/ H
.b (b[2]),$ G8 Z/ z+ e+ g0 s" h* {" ]
.y (y[2]),% ?1 U; ^6 _- X6 ~( K$ f& n
.co (co3)' ]8 A: w, g8 Y* h& \
);% ~7 t) u) I$ a9 A& A9 R
9 q3 _3 H; }- q, i6 C) m. g ^3 efadder1 fadder1_inst4
) @3 ^5 o2 h+ U# n(: o# F" ^4 s, f8 ]( E
.ci (co3),$ ]: e$ @1 p9 N. i6 P; r( `5 L( G% L
.a (a[3]),
5 x" x* ^5 N/ U4 G5 o' T.b (b[3]),
, A+ O3 v9 [' m7 T9 W.y (y[3]),& \& h; f7 U/ b* U
.co (co)
7 r1 M# C9 Q3 P# l);
: R* K% F, @9 b! |: \( Wendmodule( l* |" Q4 @, a2 T8 N! |
wire型变量只能在并发语句或例化模块中被赋值,如实例1中的 d,e,f和实例2中co1,co2,co3; 但wire型变量可以根据需要在并发语句或顺序语句中赋值给其他变量。/ `, x) k- a' U7 w, S! Q
对wire型变量的变量赋值,只能采用并发语句赋值。变量定义时初始化时赋值和例化模块的输出赋值,wire型变量不能在顺序语句中被赋值。, F A' s2 b7 y% C) o6 E+ [6 U
寄存器(reg )类型:
/ {- |. p" z, z6 d5 {! F' J3 Y8 t寄存器(reg)是一种具有记忆功能的数据类型。用来表示存储单元,它会保持数据原有的值,直到被改写。一般分为锁存器和触发器两种。但无论哪一种建模,它们都只能在顺序语句中被赋值,而不能在并发语句中赋值。
9 ]5 h C* Z% `' w c( L! E例:$ ?) P* b! y" x; d. G! [5 m4 i
reg a;reg b;always@(*)begin a <= 1’b1; b <= 1’b0;end& Q. c9 r. w, X/ w! B, ^" S. A
而 assign a = 1’b1; 就是错误的;因为a是reg型变量。
1 |5 F3 F' a6 U7 F与wire类型变量不同的时,在reg型变量声明时可以赋初值,而后续的顺序语句可以对该变量继续赋值,从而修改原值。而wire型变量只有一次赋值机会。
" S9 G, L0 y" p4 a* C注意:在同一个顺序过程语句中可以对reg型变量多次赋值,后面的赋值会替代前面的赋值,充分利用这一特点,可以是程序更简洁。但不允许在多个顺序过程语句中对同一个reg型变量都赋值。4 V7 M1 D" }3 T; S% o
module reg_assign( input clk, input a, input b, input sel, output c);reg ma;//顺序过程语句1always @(posedge clk)begin if(sel) ma <= a;end//顺序过程语句2always @(posedge clk)begin if(!sel) ma <= b;endassign c = ma;endmodule# Q' D3 Z/ ?! ^5 Q D
上面的例子红色部分是有问题的,虽然reg 型变量允许被多次赋值,但不能在不同的顺序过程中多次赋值。上面的代码可以修改如下:
" U8 l& l g, g+ @* emodule reg_assign
5 {0 l# m& \. n# C' h8 `(
( x' _! V3 M" G: q4 Minput clk,1 {% A+ V1 y: ^" u3 O0 x
input a,6 A+ X% F9 @; U8 H
input b,9 b! m# L5 V7 C/ H
input sel,
* P+ |/ E- |' q! {& H7 i: e) houtput c
0 k4 f* x1 j) y* C, ?8 _);( _* k$ k1 L0 l9 j% r9 ~
reg ma;
; x. q; Q$ f5 J+ H& `/ ?- B//顺序过程语句1
! ~1 V1 J! q3 C( ?always @(posedge clk)% N6 r* f( r5 E% V0 ~
begin
e; r/ ]9 A8 t* B+ Rif(sel)
3 A6 _) o8 j5 K( b' e: s+ ema <= a;% f/ K5 q" x* L4 U4 z
else
! k8 `/ V) B7 ]0 lma <= b;9 h& F. g( }) i8 O7 D& @* u6 c
end
) o6 i. A4 H7 _, |3 h$ K$ n, U
3 [9 `6 E- [/ F0 _. q; I4 e# [0 ^ hassign c = ma;
/ N6 S* e8 x1 t1 n
* w _- u8 R) z* }4 v; Oendmodule" A0 l: [- U( f
wire型变量与reg型变量都可以使用向量(vector)进行声明;
8 L$ M6 y9 S3 ]+ }
4 y' v: ^4 o; X$ h如 : wire [3:0] a, b;+ L) M6 e' \" g0 T5 h7 `
$ P: Y1 U+ N# t7 q8 S+ z6 Jreg [3:0] c, d;6 j6 Y8 ]3 n- r3 Y+ x
U/ [2 k4 E% j向量的运算遵循运算符的规则,细节参见verilog 运算符。
: X C# x# J. } |
|