Verilog中的阻塞与非阻塞
按说阻塞与非阻塞是Verilog中最基本的东西,也是老生常谈。但是最近看到很多程序里用到阻塞语句竟然不是很明白,说到底是从来没有自己仔细分析过。当然一般情况程序中也是推荐用非阻塞的。
一般来说大家都会用以下几个例子来说明阻塞与非阻塞:
大家可以参考http://www.cnblogs.com/crazybingo/archive/2012/03/20/2408980.html
| HDL源代码 | 对应的RTL电路 | 
module Shifter1(  | 
 
▲ 大家可以看到Q1、Q2被优化掉了  | 
module Shifter2(  | 
 
 | 
module Shifter3(  | 
 
 | 
module Shifter4(  | 
 
 | 
module Shifter5(  | 
 
 | 
module Shifter6(  | 
 
 | 
从上面的例子可以看出:
(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;
FPGA Verilog语言中阻塞赋值与非阻塞赋值个人看法
Verilog中的阻塞与非阻塞的更多相关文章
- Verilog之阻塞赋值非阻塞赋值
		
verilog设计进阶 时间:2014年5月6日星期二 主要收获: 1. 阻塞赋值与非阻塞赋值: 2. 代码测试: 3. 组合逻辑电路和时序逻辑电路. 阻塞赋值与非阻塞赋值: 1. 阻塞赋值" ...
 - IO中同步、异步与阻塞、非阻塞的区别
		
一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 按照这个定义,其实绝大多数函数都是同步调用(例如si ...
 - IO中同步、异步与阻塞、非阻塞的区别(转)
		
转自:http://blog.chinaunix.net/uid-26000296-id-3754118.html 一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步, ...
 - Linux设备驱动中的阻塞和非阻塞I/O
		
[基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件后再进行操作.被挂起的进程进入休眠状态(不占用cpu资源),从调度器的运行队列转移到等待队列,直到 ...
 - socket网络编程中的同步,异步,阻塞式,非阻塞式,有何联系与区别?
		
一.举个打电话的例子: 阻塞 block 是指,你拨通某人的电话,但是此人不在,于是你拿着电话等他回来,其间不能再用电话.同步大概和阻塞差不多. 非阻塞 nonblock 是指,你拨通 ...
 - 蜕变成蝶~Linux设备驱动中的阻塞和非阻塞I/O
		
今天意外收到一个消息,真是惊呆我了,博客轩给我发了信息,说是俺的博客文章有特色可以出本书,,这简直让我受宠若惊,俺只是个大三的技术宅,写的博客也是自己所学的一些见解和在网上看到我一些博文以及帖子里综合 ...
 - node.js中对同步,异步,阻塞与非阻塞的理解
		
我们都知道javascript是单线程的,node.js是一个基于Chrome V8 引擎的 javascript 运行时环境,注意 node.js 不是一门语言,别搞错了. javascript为什 ...
 - Linux设备驱动中的IO模型---阻塞和非阻塞IO【转】
		
在前面学习网络编程时,曾经学过I/O模型 Linux 系统应用编程——网络编程(I/O模型),下面学习一下I/O模型在设备驱动中的应用. 回顾一下在Unix/Linux下共有五种I/O模型,分别是: ...
 - [转]Socket编程中,阻塞与非阻塞的区别
		
阻塞:一般的I/O操作可以在新建的流中运用.在服务器回应前它等待客户端发送一个空白的行.当会话结束时,服务器关闭流和客户端socket.如果在队列中没有请示将会出现什么情况呢?那个方法将会等待一个的到 ...
 
随机推荐
- day 17 re模块
			
RE模块 import re 对一个大篇幅的字符串,按照你的规则找出想要的字符串 # 单个字符匹配 import re # \w 与 \W #字母数字下划线, 非 # print(re.findall ...
 - Asp.net Mvc之Action如何传多个参数
			
最近,工作上有一个需要:用户查询日志文件信息,查看某一个具体日志信息,可能同时查看该日志所在日期的其他日志信息列表. 为完成此功能,我打算在URL中传入了两个参数,一个记录此日志时间,另外一个记录日志 ...
 - IIS挂起网站配置文件地址
			
“C/用户/Administrator/我的文档/IISExpress/Config/applicationhost”
 - AttributeError: 'WebElement' object has no attribute 'send_keys'
			
这个是没问题的代码:用来打开谷歌搜索cheese并退出 from selenium import webdriver from selenium.common.exceptions import Ti ...
 - mysql5.5以上my.ini中设置字符集
			
在mysql5.1之前数据库设置字符集: [mysqld] default-character-set = utf8 mysql5.5以后[mysqld]中就不能使用default-character ...
 - 半吊子的STM32 —  SPI通信
			
全双工,同步串行通信. 一般需要三条线通信: MOSI 主设备发送,从设备接收 MISO 主设备接收,从设备发送 SCLK 时钟线 多设备时,多线选取从机: 传输过程中,主从机中的移位寄存器中数据相互 ...
 - 为什么说windows会死机,Linux不会死机
			
通常所说的死机是指操作没有响应了,但是操作系统的核心仍然在工作.在windows中,由于只有一个界面,没有响应就是死机了:而在Linux中可有tty1-tty7,死了一个开另外一个把死了的那个杀掉就可 ...
 - string+和stringbuffer的速度比较
			
public class Main{ public static void main(String[] args){ /* 1 */ String string = "a" + & ...
 - Python之路(第十二篇)程序解耦、模块介绍\导入\安装、包
			
一.程序解耦 解耦总的一句话来说,减少依赖,抽象业务和逻辑,让各个功能实现独立. 直观理解“解耦”,就是我可以替换某个模块,对原来系统的功能不造成影响.是两个东西原来互相影响,现在让他们独立发展:核心 ...
 - Python编程笔记(第二篇)二进制、字符编码、数据类型
			
一.二进制 bin() 在python中可以用bin()内置函数获取一个十进制的数的二进制 计算机容量单位 8bit = 1 bytes 字节,最小的存储单位,1bytes缩写为1B 1KB = 10 ...