这篇文档值得阅读  

按说阻塞与非阻塞是Verilog中最基本的东西,也是老生常谈。但是最近看到很多程序里用到阻塞语句竟然不是很明白,说到底是从来没有自己仔细分析过。当然一般情况程序中也是推荐用非阻塞的。

  一般来说大家都会用以下几个例子来说明阻塞与非阻塞:

大家可以参考http://www.cnblogs.com/crazybingo/archive/2012/03/20/2408980.html

HDL源代码 对应的RTL电路
module Shifter1(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1; always @(posedge Clk)
begin
Q1 = D;
Q2 = Q1;
Q3 = Q2;
end
endmodule

▲ 大家可以看到Q1、Q2被优化掉了

module Shifter2(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1; always @(posedge Clk)
begin
Q1 <= D;
Q2 <= Q1;
Q3 <= Q2;
end
endmodule

module Shifter3(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1; always @(posedge Clk)
begin
Q3 = Q2;
Q2 = Q1;
Q1 = D;
end
endmodule

module Shifter4(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1;
always @(posedge Clk)
begin
Q1 <= D;
Q2 = Q1;
Q3 = Q2;
end
endmodule

module Shifter5(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1; always @(posedge Clk)
begin
Q1 <= D;
Q2 <= Q1;
Q3 = Q2;
end
endmodule

module Shifter6(
Clk,
D,
Q3
);
input Clk;
input [7:0] D;
output [7:0] Q3;
reg [7:0] Q3, Q2, Q1;
always @(posedge Clk)
begin
Q1 <= D;
Q2 = Q1;
Q3 <= Q2;
end
endmodule

从上面的例子可以看出:

(1)阻塞语句定义的寄存器是可能被优化掉的

(2)阻塞语句定义的寄存器是否被优化是与语句顺序有关系的

参考文档中提到非阻塞语句执行的过程中先把每条语句当作一个事件放入事件队列中来执行的。它能很方便帮助理解非阻塞过程。

所谓非阻塞赋值,顾名思义,就是指当前语句的执行不会阻塞下一语句的执行。

 always @(posedge Clk)
begin
Q1 <= D;
Q2 <= Q1;
Q3 <= Q2;
end

   首先执行Q1 <= D,产生一个更新事件,将D的当前值赋给Q1,但是这个赋值过程并没有立刻执行,而是在事件队列中处于等待状态。
        然后执行Q2 <= Q1,同样产生一个更新事件,将Q1的当前值(注意上一语句中将D值赋给Q1的过程并没有完成,Q1还是旧值)赋给Q2,这个赋值事件也将在事件队列中处于等待状态。
        再执行Q3 <= Q2,产生一个更新事件,将Q2的当前值赋给Q3,这个赋值事件也将在事件队列中等待执行。
        这时always语句块执行完成,开始对下一个Clk上升沿敏感。

  那么什么时候才执行那3个在事件队列中等待的事件呢?只有当当前仿真时间内的所有活跃事件和非活跃事件都执行完成后,才开始执行这些非阻塞赋值的更新事件。这样就相当于将D、Q1和Q2的值同时赋给了Q1、Q2和Q3。

下面是参考中的例子及阻塞实现过程:

这里有一个数组:Data[0]、Data[1]、Data[2]和Data[3],它们都是4比特的数据。我们需要在它们当中找到一个最小的数据,同时将该数据的索引输出到LidMin中,这个算法有点类似于“冒泡排序”的过程,而且需要在一个时钟周期内完成。例如,如果这4个数据中 Data[2]最小,那么LidMin的值则为2。

module Bubble_Up(
Rst_n,
Clk,
Data0,
Data1,
Data2,
Data3,
Lid_Min
);
input Rst_n;
input Clk; input [:] Data0;
input [:] Data1;
input [:] Data2;
input [:] Data3;
reg [:] Data [:];
output [:] Lid_Min;
reg [:] Lid_Min; always @( posedge Clk )
begin
Data[] <= Data0;
Data[] <= Data1;
Data[] <= Data2;
Data[] <= Data3;
end
always @(posedge Clk )
begin if (Data[] <= Data[Lid_Min]) //"<="表示小于等于
begin
Lid_Min = 'd0; //"<="表示非阻塞赋值
end if (Data[] <= Data[Lid_Min])
begin
Lid_Min = 'd1;
end if (Data[] <= Data[Lid_Min])
begin
Lid_Min = 'd2;
end if (Data[] <= Data[Lid_Min])
begin
Lid_Min = 'd3;
end
end
endmodule

从实现的RTL视图上,我突然觉得阻塞一步到位的完成了很多组合逻辑。接下来我再说一些在程序上经常会遇到的例子。

reg                     current_state;
reg next_state;
reg inc_loops;
reg clr_loops;
reg set_valid;
reg [-:] loops;
reg [:] threshold;
reg [-:] dim_cnt_thresh_r;
reg [-:] cnt_thresh; always @ (posedge clk )
begin
current_state <= next_state;
end always @ (*)
begin
next_state = current_state;
clr_loops = 'b0;
inc_loops = 'b0;
set_valid = 'b0; case (current_state)
: begin
clr_loops = 'b1;
if (measure_valid) begin
next_state = 'b1;
end
end : begin
inc_loops = 'b1;
if (match | loops_max) begin
set_valid = 'b1;
clr_loops = 'b1;
next_state = 'b0;
end
end
endcase
end

上面一段程序,从RTL视图可以看到,除current_state为寄存器之外,其余全部综合为了组合逻辑,所以说,reg定义的数据也不全会综合成寄存器。但是贴出程序还是为了要体会阻塞的用法。

好像记得有这样的说法:在组合逻辑中用阻塞,在时序逻辑中用非阻塞。

如果把上面的程序修改成非阻塞赋值,如下,这样会不会存在问题呢?我个人认为有可能,可能要看综合器本身,如果case语句外的next_state <= current_state与case内的next_state <= 1'b0(或者1‘b1)是随机的,那状态可能会出错。不会一般都不会(因为我以前就有这样做过,没问题(>'~'<))

reg                     current_state;
reg next_state;
reg inc_loops;
reg clr_loops;
reg set_valid;
reg [-:] loops;
reg [:] threshold;
reg [-:] dim_cnt_thresh_r;
reg [-:] cnt_thresh; always @ (posedge clk )
begin
current_state <= next_state;
end always @ (*)
begin
next_state <= current_state;
clr_loops <= 'b0;
inc_loops <= 'b0;
set_valid <= 'b0; case (current_state)
: begin
clr_loops <= 'b1;
if (measure_valid) begin
next_state <= 'b1;
end
end : begin
inc_loops <= 'b1;
if (match | loops_max) begin
set_valid <= 'b1;
clr_loops <= 'b1;
next_state <= 'b0;
end
end
endcase
end

不过在这篇博客中,也给出了一种表达

 
module and_nonblocking
(
input a,
input b,
input c,
output reg y
); always@*
begin // y_entry = y
y <= a; // y_exit = a
y <= y & b; // y_exit = y_entry & b
y <= y & c; // y_exit = y_entry & c
end // y = y_exit endmodule

注意always块内的前2条语句将不会产生任何效果。上述always块等价与:

always@*
y <= y & c;
 
												

Verilog中的阻塞与非阻塞的更多相关文章

  1. Verilog之阻塞赋值非阻塞赋值

    verilog设计进阶 时间:2014年5月6日星期二 主要收获: 1. 阻塞赋值与非阻塞赋值: 2. 代码测试: 3. 组合逻辑电路和时序逻辑电路. 阻塞赋值与非阻塞赋值: 1. 阻塞赋值" ...

  2. IO中同步、异步与阻塞、非阻塞的区别

    一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 按照这个定义,其实绝大多数函数都是同步调用(例如si ...

  3. IO中同步、异步与阻塞、非阻塞的区别(转)

    转自:http://blog.chinaunix.net/uid-26000296-id-3754118.html 一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步, ...

  4. Linux设备驱动中的阻塞和非阻塞I/O

    [基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到 ...

  5. socket网络编程中的同步,异步,阻塞式,非阻塞式,有何联系与区别?

    一.举个打电话的例子: 阻塞   block   是指,你拨通某人的电话,但是此人不在,于是你拿着电话等他回来,其间不能再用电话.同步大概和阻塞差不多. 非阻塞   nonblock   是指,你拨通 ...

  6. 蜕变成蝶~Linux设备驱动中的阻塞和非阻塞I/O

    今天意外收到一个消息,真是惊呆我了,博客轩给我发了信息,说是俺的博客文章有特色可以出本书,,这简直让我受宠若惊,俺只是个大三的技术宅,写的博客也是自己所学的一些见解和在网上看到我一些博文以及帖子里综合 ...

  7. node.js中对同步,异步,阻塞与非阻塞的理解

    我们都知道javascript是单线程的,node.js是一个基于Chrome V8 引擎的 javascript 运行时环境,注意 node.js 不是一门语言,别搞错了. javascript为什 ...

  8. Linux设备驱动中的IO模型---阻塞和非阻塞IO【转】

    在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程——网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: ...

  9. [转]Socket编程中,阻塞与非阻塞的区别

    阻塞:一般的I/O操作可以在新建的流中运用.在服务器回应前它等待客户端发送一个空白的行.当会话结束时,服务器关闭流和客户端socket.如果在队列中没有请示将会出现什么情况呢?那个方法将会等待一个的到 ...

随机推荐

  1. JSP使用sessionScope获取session值

    场景:有些实体对象可以放到HttpSession对象中,保正在一个会话期间可以随时获取这个对象的属性,例如可以将登录用户的信息写入session,以保证页面随时可以获取并显示这个用户的状态信息.下面以 ...

  2. MVC的Forms登录验证

    第一步:修改web.config配置 在 <system.web>节点下加入配置:未登录的用户跳转到/Home/Login,登录后跳转到/Home/UserCenter,登录后票证记录到c ...

  3. threejs纹理

    纹理 纹理用来表现物体的细节.理论上可以将物体的每个细节建模出来,但是这样时间成本和性能成本都太高,因此,将物体的一些细节用纹理来表示. 图片纹理 图片纹理直接在物体表面应用图片.可以使用Textur ...

  4. javascript 字面量 和变量 之间的关系

    https://www.w3cschool.cn/javascript/js-syntax.html

  5. mysql mysqld.sock文件丢失问题

    修改mysql 编码为utf8时 在/etc/mysql/目录下 在 [client] 添加 default-character-set=utf8 [mysqld]添加 default-charact ...

  6. 4A - 排序

    输入一行数字,如果我们把这行数字中的‘5’都看成空格,那么就得到一行用空格分割的若干非负整数(可能有些整数以‘0’开头,这些头部的‘0’应该被忽略掉,除非这个整数就是由若干个‘0’组成的,这时这个整数 ...

  7. PAT 1018 锤子剪刀布(20)

    1018 锤子剪刀布 (20)(20 分) 大家应该都会玩"锤子剪刀布"的游戏:两人同时给出手势,胜负规则如图所示: 现给出两人的交锋记录,请统计双方的胜.平.负次数,并且给出双方 ...

  8. sql重复数据的过滤问题

    有重复数据主要有一下几种情况: 1.存在两条完全相同的纪录 这是最简单的一种情况,用关键字distinct就可以去掉 example: select distinct * from table(表名) ...

  9. ActiveMq unsupported major.minor version 52.0

    网上是说ActiveMq已经编译好的版本和运行的java版本不一致导致的,看了一下MF文件 用的Jdk版本是1.8,而我们当前系统的java版本是1.7,所以尝试重新下载之前的ActiveMq的版本. ...

  10. Java界面编程—布局管理

    布局是指容器中组件的排列方式 常用的布局管理器 布局管理器名称 所属类包 说明 FlowLayout(流式布局) java.awt 组件按照加入的先后顺序.按照设置的对齐方式从左向右排列,一行排满后到 ...