集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 4801|回复: 8

【FPGA设计实例】设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别

[复制链接]
lovelyboywyl 发表于 2010-11-20 10:22:29 | 显示全部楼层 |阅读模式
阻塞赋值与非阻塞赋值,在教材中我们已经了解了它们之间在语法上的区别以及综合后所得到的电路结构上的区别。在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为赋值语句是并发执行的。实际的时序逻辑设计中,一般的情况下非阻塞赋值语句被更多地使用,有时为了在同一周期实现相互关联的操作,也使用了阻塞赋值语句。(注意:在实现组合逻辑的assign结构中,无一例外地都必须采用阻塞赋值语句。
下例通过分别采用阻塞赋值语句和非阻塞赋值语句的两个看上去非常相似的两个模块blocking.v和non_blocking.v来阐明两者之间的区别。

模块源代码:

// -------------   blocking.v ---------------

module blocking(clk,a,b,c);
  output [3:0] b,c;
  input  [3:0] a;
  input        clk;
  reg    [3:0] b,c;
  always @(posedge clk)
   begin
    b = a;
    c = b;
    $display("Blocking: a = %d, b = %d, c = %d.",a,b,c);
   end
endmodule


//-------------  non_blocking.v -------------------
module non_blocking(clk,a,b,c);

  output [3:0] b,c;
  input  [3:0] a;
  input        clk;
  reg    [3:0] b,c;
  
  always @(posedge clk)
  begin
    b <= a;
    c <= b;
    $display("Non_Blocking: a = %d, b = %d, c = %d.",a,b,c);
  end

endmodule

测试模块源代码:
//-------------  compareTop.v -----------------------------

`timescale 1ns/100ps
`include "./blocking.v"
`include "./non_blocking.v"

module compareTop;

  wire [3:0] b1,c1,b2,c2;
  reg  [3:0] a;
  reg        clk;
  
  initial
  begin
    clk = 0;
    forever #50 clk = ~clk;
  end
  
  initial
  
  begin
    a = 4'h3;
    $display("____________________________");
    # 100 a = 4'h7;
    $display("____________________________");
    # 100 a = 4'hf;
    $display("____________________________");
    # 100 a = 4'ha;
    $display("____________________________");
    # 100 a = 4'h2;
    $display("____________________________");
    # 100  $display("____________________________");
    $stop;
  end
  non_blocking  non_blocking(clk,a,b2,c2);
  blocking      blocking(clk,a,b1,c1);

endmodule
 楼主| lovelyboywyl 发表于 2010-11-20 10:25:42 | 显示全部楼层
关于阻塞和非阻塞到底是个什么东西?
 楼主| lovelyboywyl 发表于 2010-11-20 10:26:26 | 显示全部楼层
阻塞和非阻塞可以说是血脉相连,但是又有着本质的差别。理解不清或运用不当,都往往会导致设计工程达不到预期的效果,而其中的错误又很隐晦。
 楼主| lovelyboywyl 发表于 2010-11-20 10:26:52 | 显示全部楼层
阻塞语句,顾名思义,即本条语句具有影响下一条语句的作用,在同一个进程always中,一条阻塞赋值语句的执行是立刻影响着下条语句的执行情况和结果。如果该条语句没有执行完,那么下条语句不可能进入执行状态的,因此,从字面层上理解,该条语句阻塞了下面语句的执行。阻塞语句最能体现verilog HDL和C语言之间的血缘关系,比如,在时钟沿触发的always进程里,若先执行b=c,再执行a=b,那么本质上,在一个时钟沿触发里面,a=c成立,即是说,不要b变量,直接在进程里赋值a=c,结果是一样的。这和c语言中b=c,a=b性质相同。
 楼主| lovelyboywyl 发表于 2010-11-20 10:27:07 | 显示全部楼层
非阻塞语句,非阻塞语句应该来说,更能体现硬件电路的特点。这正是非阻塞语句广泛应用于时序逻辑电路的原因。接上面的例子,如果在一个时钟沿触发的always进程里面,b<=c,a<=b那么就不可能直接在进程里面赋值a<=c.因为c的值要经过两个时钟延迟才传到a里面,即c若从0变为1,那么要经过两个clk上升沿才传到a,a的值才从0变为1。两次赋值正是体现了两个时钟延迟的特点。这种特点即是非阻塞语句非阻塞的的原因导致的,就是说,a<=b,不会因为b<=c没有执行完毕而不执行,只要时钟触发进程,那么a<=b,b<=c同时执行。所以,如果c为1,b为0,a为1的话,那么在在非阻塞语句的进程里面,一个时钟沿到来,由于他们之间是同时执行的,所以把c的1赋给了b,把b的0赋给了a,但是在阻塞语句里面,c的1先给了b,然后b把新赋值的1又给了a,那么a在一个时钟之后即变成了1。(在一次触发进程里,无论是阻塞和非阻塞语句,每条语句只能执行一次)
 楼主| lovelyboywyl 发表于 2010-11-20 10:27:29 | 显示全部楼层
阻塞语句是顺序执行的,而非阻塞语句是同时执行的,那么,如何在设计里面运用好阻塞语句和非阻塞语句呢,总体上来讲,遵循大体原则:阻塞语句运用在组合逻辑电路设计里面,非阻塞语句运用在时序逻辑电路设计里面。但是一般来讲,一个设计往往包含着组合逻辑和时序逻辑。
sxtzzu 发表于 2012-8-23 16:49:26 | 显示全部楼层
好好好好好好好好好好好好好好好好好好好好好好好好
sxtzzu 发表于 2012-8-23 16:51:18 | 显示全部楼层
麻烦请教楼主,这个测试模块运行出现如下的错误提示怎么回事啊
ERROR:HDLCompilers:27 - "blocking.v" line 21 Illegal redeclaration of 'blocking'
ERROR:HDLCompilers:27 - "nonblocking.v" line 21 Illegal redeclaration of 'nonblocking'
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-27 07:39 , Processed in 0.067886 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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