微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > Verilog HDL基础之:赋值语句和块语句

Verilog HDL基础之:赋值语句和块语句

时间:06-05 来源:互联网 点击:

非阻塞赋值和阻塞赋值

在Verilog HDL语言中,信号有两种赋值方式:非阻塞(Non_Blocking)赋值方式和阻塞(Blocking)赋值方式。

(1)非阻塞赋值方式。

典型语句:b = a;

① 块结束后才完成赋值操作。

② b的值并不是立刻就改变的。

③ 这是一种比较常用的赋值方法,特别在编写可综合模块时。

(2)阻塞赋值方式。

典型语句:b = a;

① 赋值语句执行完后,块才结束。

② b的值在赋值语句执行完后立刻就改变。

③ 可能会产生意想不到的结果。

非阻塞赋值方式和阻塞赋值方式的区别常给设计人员带来问题。问题主要是给“always”块内的reg型信号的赋值方式不易把握。到目前为止,前面所举的例子中的“always”模块内的reg型信号都是采用下面的这种赋值方式:

b = a;

这种方式的赋值并不是马上执行的,也就是说“always”块内的下一条语句执行后,b并不等于a,而是保持原来的值。“always”块结束后,才进行赋值。而另一种赋值方式阻塞赋值方式,如下所示:

b = a;

这种赋值方式是马上执行的,也就是说执行下一条语句时,b已等于a。尽管这种方式看起来很直观,但是可能引起麻烦。下面举例说明。

例1:非阻塞赋值。

always @( posedge clk ) begin

b=a;

c=b;

end

例1中的“always”块中用了非阻塞赋值方式,定义了两个reg型信号b和c。clk信号的上升沿到来时,b就等于a,c就等于b,这里应该用到了两个触发器。需要注意的是赋值是在“always”块结束后执行的,c应为原来b的值。这个“always”块实际描述的电路功能如图1所示。

例2:阻塞型赋值。

always @(posedge clk) begin

b=a;

c=b;

end

例2中的“always”块用了阻塞赋值方式。clk信号的上升沿到来时,将发生如下的变化:b马上取a的值,c马上取b的值(即等于a)。综合的电路如图2所示。

图1 非阻塞赋值综合电路 图2 阻塞赋值综合电路

它只用了一个触发器来寄存a的值,并同时输出给b和c。这不是设计者的初衷,如果采用例3.5所示的非阻塞赋值方式就可以避免这种错误。

块语句

块语句通常用来将两条或多条语句组合在一起,使其在格式上看更像一条语句。块语句有两种:一种是begin_end语句,通常用来标识顺序执行的语句,用它来标识的块称为顺序块;另一种是fork_join语句,通常用来标识并行执行的语句,用它来标识的块称为并行块。下面进行详细的介绍。

1.顺序块

顺序块有以下特点。

(1)块内的语句是按顺序执行的,即只有上面一条语句执行完后下面的语句才能执行。

(2)每条语句的延迟时间是相对于前一条语句的仿真时间而言的。

(3)直到最后一条语句执行完,程序流程控制才跳出该语句块。

顺序块的格式如下:

begin

语句1;

语句2;

......

语句n;

end

或者:

begin:块名

块内声明语句

语句1;

语句2;

......

语句n;

end

其中:

(1)块名即该块的名字,是一个标识符,其作用后面再详细介绍。

(2)块内声明语句可以是参数声明语句,reg型变量声明语句,integer型变量声明语句或者real型变量声明语句。

下面举例说明。

例3:顺序块。

begin

areg = breg;

creg = areg; //creg的值为breg的值

end

从该例可以看出,第一条赋值语句先执行,areg的值更新为breg的值。然后程序流程控制转到第二条赋值语句,creg的值更新为areg的值。因为这两条赋值语句之间没有任何延迟时间,creg的值实为breg的值。当然可以在顺序块里延迟控制时间来分开两个赋值语句的执行时间,如例4所示。

例4:加延时顺序块。

begin

areg = breg;

#10 creg = areg; //在两条赋值语句间延迟10个时间单位

end

2.并行块

并行块有以下4个特点。

(1)块内语句是同时执行的,即程序流程控制一进入该并行块,块内语句则开始同时并行地执行。

(2)块内每条语句的延迟时间是相对于程序流程控制进入到块内时的仿真时间的。

(3)延迟时间是用来给赋值语句提供执行时序的。

(4)当按时间时序排序在最后的语句执行完后或一个disable语句执行时,程序流程控制跳出该程序块。

并行块的格式如下:

fork

语句1;

语句2;

.......

语句n;

join

或者:

fork:块名

块内声明语句

语句1;

语句2;

......

语句n;

join

其中:

(1)块名即标识该块的一个名字,相当于一个标识符。

(2)块内说明语句可以是参数说明语句、reg型变量声明语句、integer型变量声明语句、real型变量声明语句、ime型变量声明语句或者事件(event)说明语句。

下面举例说明。

例5:并行块1。

fork

#50 r = h35; //在绝对时间50单位后,r被赋值

#100 r = hE2; //在绝对时

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top