原创 那些年,我们拿下了FPGA-第9章拿下运算符(3)

2012-11-8 19:52 1889 13 15 分类: FPGA/CPLD 文集: 那些年,我们拿下了FPGA

 

9.1.8 三目运算符

三目运算符也叫条件运算符,跟C语言中的用法相同。当条件满足时执行一种操作,当条件不满足时,执行另外一种操作,看来三目运算符就是组合电路版的if,else,还是来看看如何表达吧。

(1)?(2)3)

具体来说,就是当(1)中所含内容为真时,执行(2)中的操作,当(1)中所含内容为假时,执行(3)中的操作,即(1)表示三目运算符的条件,(2)和(3)表示表示例如:

reg[3:0]a=4’d5;

reg [3:0]b=4’d3;

reg [3:0]c=4’b0;

 

c=(a>=0)?b:c;            //显然a>=0成立,所以?前的表达式为真,执行把b的值赋给c

 

上例中,条件成立,所以执行问号后冒号前的表达式,有人肯定会问,当条件为X或者Z时,条件运算符又如何计算呢?没错,确实可能存在这样的情况,当条件为X或者Z且执行的两个操作不同时,则结果为不确定值,若执行的两个操作相同时,则执行该操作。例如:

assign out=(a)?b:c;   

上例中,当a=1时,out=b;当a=0时,out=c;当a=X或Z,b=c=0时,a=0。

所以,三目运算符是包括三部分的,而且每个部分缺一不可,讲述着“一个都不能少”的故事,这也是我们在应用时需要注意的地方。

 

9.2给它们排个序吧      

上面我们介绍了五花八门的运算符,它们都有着自己的约定,作为有使用权的我们只能照章办事。然而,我们的程序不可能只用到一种运算符,当多种运算符相遇时,会不会因为争争抢抢而让程序乱套呢?前人也想到了这个问题,所以对各种运算符制定了优先级,可是这种优先级关系是怎么来的,就不得而知了,仿佛是一种约定俗成的东西,具体怎么排,还是看看下表吧。

 

运算符

优先级别

!~

高优先级

低优先级

<<>> 

<<= >>=

== != === !==

&

|

&&

||

?:

 

上表中列出了各种运算符的优先级,这就决定了当各种运算符执行的先后顺序,高优先级的先执行,低优先级的后执行。如果记不住各种优先级的先后顺序,还是建议大家在每执行一次操作时都加上括号,这是最可靠的方法。

 

9.3赋值语句

有了各种运算符,我们总要把运算的结果赋给其它变量啊,才能保证程序的顺畅运行。赋值语句应运而生,它就好比是搬运工,把通过各种运算符得到的结果搬到别的变量身上,这是一种值的传递。在Verilog中,有两种赋值方式,阻塞赋值和非阻塞赋值,怎么使用这两种赋值方式呢?且听娓娓道来。

 

9.3.1阻塞赋值

阻塞赋值从字面上的意思来说就是后面的赋值语句是在前一句赋值语句结束后再开始赋值的,即它总是先计算赋值符号右边(用RHS表示)的表达式,再将计算结果赋给赋值符号左边(用LHS表示),这个过程中不允许别的Verilog语句执行,直到赋值结束,别的赋值语句才能开始执行,也就是说它阻塞了其它赋值语句的执行,在状态机的状态转移描述过程中需要用阻塞赋值。

其表达式为:b=a,把a的值赋给b。例如:

moduleTBfuzhi;

always #0.5 clk=~clk;

reg data1;

initial begin

data1=0;

         data1=#2 1;

         data1=#3 0;

         data1=#5 1;

end

endmodule

上例是一个Verilog的测试程序,模块内的阻塞赋值将依次执行,见下图,图中竖着的黄线是initial模块开始执行的时刻,从开始执行的时刻开始,2个时钟周期后将data1置1,依次向后赋值,当data1=1维持3个时钟周期后data1置0,置0后5个时钟周期又将data1置1,整个过程都是在上一句赋值结束之后才开始下一句的赋值,这就是为什么“=”称为阻塞赋值,它阻止了模块内的其它赋值语句的执行。

 

 

9.6.jpg

 

9.3.2非阻塞赋值

非阻塞赋值是在赋值操作时刻开始时计算RHS表达式,赋值操作时刻结束时更新LHS,在计算某个非阻塞赋值的RHS表达式的同时,也计算其它的非阻塞赋值的RHS表达式,并且,在给某个非阻塞赋值的LHS赋值的同时,也可以给其它的非阻塞赋值的LHS赋值,也就是说非阻塞赋值允许其它Verilog语句同时进行操作,它可以分成两个过程:在非阻塞赋值开始时,计算块内所有RHS表达式的值;在非阻塞赋值结束时,给块内所有LHS赋值。

其表达式为:b<=a,将a的值赋给b。我们还是以阻塞赋值中的例子为例,对比两者的区别。

moduleTBfuzhi;

always #0.5 clk=~clk;

reg data2;

initial begin

data2<=0;

         data2<=#2 1;

         data2<=#3 0;

         data2<=#5 1;

end

endmodule

结果如下图所示,图中竖着的黄线代表非赋值开始的时刻,由图中可知,initial块内的4个非阻塞赋值都是在赋值开始时刻计算RHS的值,在开始时刻,data2被赋0,从开始时刻到2个时钟周期结束时data2赋1,从开始时刻到3个时钟周期结束时data2赋0,还是从开始时刻到5个时钟周期结束时data2赋1,即每条非阻塞赋值语句都是相对于赋值开始时刻而言,而在上节的阻塞赋值中,我们能明显看到,每条阻塞赋值都是相对于上一条阻塞赋值结束时刻而言,所以,非阻塞赋值并不影响其它非阻塞赋值的运行,这就是为什么“<=”称为非阻塞赋值,非阻塞赋值语句间是相互独立、并行的关系。

 

 

9.7.jpg

 

9.3.3 塞还是不塞

从上面两个小节中我们了解到什么是阻塞赋值,什么是非阻塞赋值,对它们的区别有了初步的认识,在这里,我们还是举一个实际应用的简单例子,进一步说明塞与不塞的不同之处。见下例:

always @(posedgeclk)                        always @(posedgeclk)

beginbegin

y= x ;                               y<= x;

z= y;                               z<= y;

endend

 

上面的程序中,左边是阻塞赋值,右边是非阻塞赋值,结果如下两图所示:

阻塞赋值的结果:

 

9.8.jpg

 

非阻塞赋值:

 

9.9.jpg

从图中可知,阻塞赋值是在一条赋值语句结束后进行下一条赋值语句,所以当always块儿结束时,y、z的值相同,本质上,在一个时钟沿触发里,x=z成立,也就是说,不要y变量,直接在进程里赋值x=z,结果是一样的;而非阻塞赋值不会因为一条语句的执行而耽误另一条语句的执行,在上例中,z<=y不会因为y<=x没有执行完就不执行,只要时钟触发进程,那么z<=y和y<=x同时执行,也就是说,y赋给z的值总是y被赋x新值之前的值,所以,非阻塞赋值会有时钟的延迟,每赋值一次,延时一个时钟。

貌似用这样的仿真结果来说明阻塞赋值和非阻塞赋值还是有点抽象,还是来看看在实际电路中,阻塞赋值和非阻塞赋值又是什么样儿。还是以上面所举两个always块儿为例,左边always块儿(阻塞赋值)综合后对应的电路如下图所示:

 

9.10.jpg

由上图可知,上例中阻塞赋值always块儿生成的电路相当于只用一个触发器来寄存a的值,又输出给b和c。右边always块儿(非阻塞赋值)综合后对应的电路如下图所示:

 

 

9.11.jpg

上图说明,当clk信号的上升沿到来时,b就等于a,c就等于b,相当于两个触发器缓存a的值,所以到c输出时相对于a的值会延时2个时钟周期。

到这儿,我们已经理解上面所述阻塞赋值和非阻塞赋值的区别,那么我们就来说说它们的使用场合吧。

(1)当用always块儿来描述组合逻辑时,应当使用阻塞赋值,例如状态机中状态转移的always块儿;

(2)对于时序逻辑的描述和建模,应当使用非阻塞赋值,大多数always块儿都使用非阻塞赋值;

(3)在同一个always模块中,最好不要混合使用阻塞赋值和非阻塞赋值;尤其在可综合电路的同一个always模块中,一定不能混合使用阻塞赋值和非阻塞赋值;

说了这么多,也不知道大家理解多少,对于阻塞赋值和非阻塞赋值的应用博大精深,可能还是要多写写代码,有了一定实战经验,对很多问题才能有更深刻的理解,不管遇到什么问题,还是希望大家再接再厉,最终肯定能把问题一个一个地攻克!

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户427466 2012-11-18 01:44

嗯,这几天整理的会多一些

用户1666390 2012-11-15 17:14

楼主更新的比较慢啊
相关推荐阅读
用户427466 2017-04-27 10:08
EXATA/Qualnet调试方法
1、exata5.3安装**** exata-5.3-windows-installer-64bit.exe或者exata-5.3-windows-installer-32bit.exe 默认安装路...
用户427466 2015-04-01 10:57
一个工程师说走就走的西藏之旅(九)
今年终于放下了手头的工作 背上背包 来一场说走就走的旅行 在这里让更多的朋友看到 路上的故事 路上的风景 路上的陌生人 川青大环线第九天 (实时状况关注微信) ...
用户427466 2015-03-28 23:50
一个工程师说走就走的西藏之旅(八)
今年终于放下了手头的工作 背上背包 来一场说走就走的旅行 在这里让更多的朋友看到 路上的故事 路上的风景 路上的陌生人 川青大环线第八天 (实时状况关注微信) ...
用户427466 2015-03-24 23:50
一个工程师说走就走的西藏之旅(七)
今年终于放下了手头的工作 背上背包 来一场说走就走的旅行 在这里让更多的朋友看到 路上的故事 路上的风景 路上的陌生人 川青大环线第七天 (实时状况关注微信) ...
用户427466 2015-03-24 23:40
一个工程师说走就走的西藏之旅(六)
今年终于放下了手头的工作 背上背包 来一场说走就走的旅行 在这里让更多的朋友看到 路上的故事 路上的风景 路上的陌生人 川青大环线第六天 (实时状况关注微信) ...
用户427466 2015-03-23 11:25
一个工程师说走就走的西藏之旅(三)
今年终于放下了手头的工作 背上背包 来一场说走就走的旅行 在这里让更多的朋友看到 路上的故事 路上的风景 路上的陌生人 川青大环线第三天 (实时状况关注微信) ...
EE直播间
更多
我要评论
2
13
关闭 站长推荐上一条 /3 下一条