找回密码
 注册
关于网站域名变更的通知
查看: 154|回复: 2
打印 上一主题 下一主题

Verilog 变量声明与数据类型

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2021-12-7 14:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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. }
  • TA的每日心情
    开心
    2022-1-29 15:07
  • 签到天数: 2 天

    [LV.1]初来乍到

    2#
    发表于 2021-12-7 14:55 | 只看该作者
    Wire 型变量作为中间变量可以实现桥接的作用。

    该用户从未签到

    3#
    发表于 2021-12-7 16:07 | 只看该作者
    reg 型变量允许被多次赋值,但不能在不同的顺序过程中多次赋值。
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-11-7 00:46 , Processed in 0.156250 second(s), 23 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表