|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
Verilog语法中最基本的数据类型有 线网(wire),寄存器(reg)和整数(integer)三种类型,这三种数据类型是可综合的数据类型,在Verilog 程序设计中被广泛使用。其它还有可以用于仿真的数据类型如 timer,real,字符串等变量都可以看作reg类型的扩展。wire,reg ,integer,timer,real是声明变量类型的关键字。变量必须先声明后使用,声明后变量的数据类型也就确定了。变量声明是模块(module)内惟一的,不能在同一个模块或函数内重复声明。- I+ j/ W7 g% X b/ k& y
- 线网(wire):
6 W' K( Q; k! w 线网(wire)类型表示逻辑单元或实例之间的连线,一般由逻辑单元的输出驱动。没有连接驱动的wire型变量的值为高阻’z’。
+ D4 s# j4 D+ m, h1 W- wire类型变量的使用:
- wire型变量的声明与赋值8 e, u, z% t' Z8 B: ]+ {+ v
wire类型的变量只能由assign语句赋值,或在声明时赋初值。而且赋值的机会只有一次。) w# @# u& D9 w
变量声明实例:
. b. j1 ~3 R9 K; w9 |/ S5 x6 Xwire a, b;
0 d, f7 H5 t3 r. i1 nwire c = 0;- Z# w6 R* L; g% k- g! S& r
wire d = 1'b1;2 B( Z" { M- z f
assign a = c;6 g0 i* X4 G2 e8 f/ l- e. N
声明a, b为线网类型,并将c的值赋给a, 此时a的为0;而且a只有这一次赋值机会。
u7 s* M; n- B O# ?/ h O变量c在声明的时候赋初值为0,此后c就一直保留该值,不能再给c赋值,也不能再次声明。8 S) {& r! X E8 y" K) M& b
注意:wire类型的变量不能重复赋值。4 A! y; k& f- S
Wire 型变量作为中间变量可以实现桥接的作用。在下面的例子中可以看出,wire型变量起到变量之间值传递的作用。
7 O% }: W: z3 x6 w4 x# v* q实例1:
5 Y* U8 c- ]' c' s) M# `module wire_bridge. {. k. j c' S' J% a9 y5 b
(
0 I1 Y O' G+ g) h0 ^3 V* Sinput a,b,ci,
! e8 K6 d" x- T* S" Uoutput y,co# b2 {4 M! B$ b3 Y: r) G" w! @
);
. @- R# `& p/ \( ^$ Swire d, e, f;" f8 ?8 ]: z' C" Z
assign d = a ^ b;
3 o6 u9 V8 T5 H2 w# Fassign e = a & b;
, y1 r6 \" U: Y6 S5 qassign f = ci & d;# c% o3 |: \7 A7 h2 `; |! P- }
assign y = d ^ ci;; a7 z! t4 G. X: O+ l
assign co = e | f;
$ \% v: u% Y! dendmodule
! @5 Z' M; |1 A6 l9 F& Uwire变量在逻辑电路中的对应关系,简单的说就是起到连线的作用。
`$ J& j" t3 w在例化模块之间传递变量。
( j" h9 v4 e4 p _' O) J# @! i) _1 R$ _实例2:
( K1 J0 X- e8 y' f8 g0 cmodule fadder4
# U# f2 L# f, _) @# b0 C! D(
7 T# V/ i0 i: j3 `input ci,3 c/ C( T4 F# ]' @9 _9 n
input [3:0] a,7 M1 Z o. u6 n
input [3:0] b,
- k3 U& t3 v9 g0 ~4 g
- q: n; R6 n- a% f1 aoutput [3:0] y,7 ?) T' L2 _0 I% W
output co
% z0 G7 ~9 o5 A; H);
+ T K* u/ S, F5 swire co1,co2,co3;
; t7 N( s8 C, N) J( R// 例化 一位全加器,并重复使用4次
! m3 s; m0 K, |: Tfadder1 fadder1_inst1) g# {% l' R- G. j
(* v. q4 D5 @- U3 Q, H* o( G' }# _
.ci (ci),
* L2 k; P' j- v& Y- ^, s }/ I' {.a (a[0]),
; S4 \( w5 \5 y.b (b[0]),
1 A5 k i# R- a8 K5 J. N: S.y (y[0]),
( {5 n, L7 g% u8 r.co (co1)
' J8 O( k3 g0 f: i2 V1 }& e# |( e);
6 P3 U# t& [/ I" E1 p% vfadder1 fadder1_inst2$ C4 a2 D+ _0 C& h
(
7 b; v% j. o0 h; o9 `.ci (co1), q! N8 [2 w* a' W( F5 W& Q
.a (a[1]),
& `5 ~# \, K% M$ Q0 h6 N.b (b[1]),
! T" | N% F/ ?0 ^! { Z.y (y[1]),
A2 x5 Q7 }4 Z* Q.co (co2)5 H/ e" P6 O, ]$ Z2 }- O
);: ~* B, b8 w* {8 i" w
1 G8 `/ u5 n1 Q& s0 N& nfadder1 fadder1_inst3. H4 u; | ?$ a0 U
(
1 X0 A( m* I2 h5 \.ci (co2),
/ {$ x8 l1 [: t.a (a[2]),/ T/ ]0 o1 H- D m/ R) E
.b (b[2]),
& q @2 h6 P4 R0 v* R% b" q) _+ G.y (y[2]),' N: Z* c) J* m* N" j; Z: E
.co (co3)
% S; q0 r; \: K; K);3 P, f; V& L7 o2 g# _2 z
! z5 Z- Z" o5 s* Ffadder1 fadder1_inst4% R5 [; C9 ?; q: G' V8 K) a" k7 P
(
2 r7 k. g8 S3 E0 r& H.ci (co3),3 a# v8 B$ \: }) ]! b- C( z
.a (a[3]),
. N" @. R3 s$ ^4 ]3 h4 a/ w.b (b[3]),) G8 \4 M# C9 K& d' U5 ?1 L {
.y (y[3]),
/ G; B" b. c+ }.co (co)6 ], B: R t3 e( }
);
* n9 O. r8 }' j* c1 nendmodule; B; @" d, W% z
wire型变量只能在并发语句或例化模块中被赋值,如实例1中的 d,e,f和实例2中co1,co2,co3; 但wire型变量可以根据需要在并发语句或顺序语句中赋值给其他变量。
: Y/ Q- v) f" Q4 ?5 [& G+ y对wire型变量的变量赋值,只能采用并发语句赋值。变量定义时初始化时赋值和例化模块的输出赋值,wire型变量不能在顺序语句中被赋值。
: u% X( T" E. l$ X! q8 t) ?6 Y寄存器(reg )类型:7 X2 i V/ B, I# a* Z, S8 o
寄存器(reg)是一种具有记忆功能的数据类型。用来表示存储单元,它会保持数据原有的值,直到被改写。一般分为锁存器和触发器两种。但无论哪一种建模,它们都只能在顺序语句中被赋值,而不能在并发语句中赋值。
2 |( S9 K0 P% \0 ]+ ]例:1 E3 P0 Q# ^1 Y2 F1 ^. |$ {8 L& c4 ~* L
reg a;reg b;always@(*)begin a <= 1’b1; b <= 1’b0;end5 l/ ^9 x& x# Z
而 assign a = 1’b1; 就是错误的;因为a是reg型变量。
6 D+ R% F' @1 Z与wire类型变量不同的时,在reg型变量声明时可以赋初值,而后续的顺序语句可以对该变量继续赋值,从而修改原值。而wire型变量只有一次赋值机会。
0 e: j, R0 k0 \9 H注意:在同一个顺序过程语句中可以对reg型变量多次赋值,后面的赋值会替代前面的赋值,充分利用这一特点,可以是程序更简洁。但不允许在多个顺序过程语句中对同一个reg型变量都赋值。; l1 v8 T* d+ _, p6 {& R3 z% m. X
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
2 n7 r$ |1 B e3 X# L上面的例子红色部分是有问题的,虽然reg 型变量允许被多次赋值,但不能在不同的顺序过程中多次赋值。上面的代码可以修改如下:
$ j# h( {- b$ h; ?8 I# M u$ F5 Nmodule reg_assign& C% C# L/ X$ Q4 A/ {0 L
($ b; d! k8 p& r- S/ v
input clk,
- j2 z& D" b! m% F+ N6 Zinput a,- q* O6 G+ p) b( Y
input b,. K) P" q2 H' r9 Y/ M, W
input sel,
1 T- y* D8 ?% _: ^/ Y1 p; Doutput c! X9 X, \6 l2 h' l4 O( k
);* G8 Y K$ R8 z: z5 C4 r
reg ma;
" ~2 P: ?( N( y//顺序过程语句1( ]' S: [6 Q6 u
always @(posedge clk)
* t" ~$ r; J" H4 i6 I3 d) Nbegin. U4 Y6 O7 o6 }! [4 x
if(sel)" M3 Y, X9 X$ k5 `/ Y
ma <= a;
5 B- h: Y1 ~1 n7 A0 _else
% `7 l- R1 D) s" ~ma <= b;
$ l% s/ |* A @5 x* D3 zend$ A$ G9 T5 H* s$ y
8 f0 u, Y0 ?) z- k8 e& v
assign c = ma;
1 V5 s- A1 r8 Y/ B7 }2 ], ~2 H' o: h* s, }- G
endmodule
& k% J: [/ j, W, |; f- Awire型变量与reg型变量都可以使用向量(vector)进行声明;
% o1 y" B) X3 s9 E/ O& w" y9 i( g/ Z* G
. ~2 b4 \: }& p9 f) L如 : wire [3:0] a, b;4 o% m/ ~. Y3 {, Q
! ]! f3 p' }: ^, C/ U9 Creg [3:0] c, d;
`9 w9 j8 _8 ~' k3 N/ V, C% U6 a
向量的运算遵循运算符的规则,细节参见verilog 运算符。
$ H' L6 S( E. |& Z5 h4 h8 B6 Y' _ |
|