Verilog HDL——时序组合逻辑电路与阻塞,非阻塞赋值

转自https://blog.csdn.net/chief_cf/article/details/52373831

相信很多刚开始学习Verilog的童鞋对阻塞、非阻塞赋值理解得不是很明白,或者说是一头雾水。确实,Verilog中阻塞、非阻塞一直就是一个难点,很多具备很久开发经验的工程师仍是不得要领,在分析代码,看仿真时还是迷迷糊糊。我自己在学习语法的时候感觉理解了,但是在自己写代码,看仿真时仍然会出现不理解的波形,所以,就从头开始再看了遍语法。

阻塞赋值

阻塞赋值,顾名思义,即在一个always块中,后面的语句会受到前语句的影响,具体来说,在同一个always中,一条阻塞赋值语句如果没有执行结束,那么该语句后面的语句就不能被执行,即被“阻塞”。也就是说always块内的语句是一种顺序关系,这里和C语言很类似,比如,在C语言中,b= a;c=b;执行的时候就是先执行第一句b= a,然后执行下一句c=b,最后结果是a=c。同样,在时钟沿触发下,always块内,阻塞赋值是同样顺序执行,如下代码:

always@(posedge clk)
    begin 
        b = a;
        c = b;
    end

在时钟上升沿来的时候,a赋给b,执行完成后,b在赋给c,整个代码执行完时,a=c,效果与C语言同。
其过程下图所示
图1
a的值先给b,然后才能给到c,这都是在一个时钟沿上完成的。

非阻塞赋值

在说非阻塞赋值之前,我们要先知道触发器的工作原理。即在时钟到来时,触发器会将输入端的数据打到输出端,这是受时钟节拍控制的。其实,非阻塞赋值更能体现出硬件电路工作时的实际情况。那么非阻塞赋值具体是怎么回事呢?
继续用上面的例子:

always@(posedge clk)
    begin
        b <= a;
        c <= b;
    end 

在时钟上升沿到来时,该always块就不同于阻塞赋值的最终输出结果a=c,而是a传递到c需要间隔两个时钟,怎么理解呢?
直接看图吧
这里写图片描述
非阻塞赋值是由时钟节拍决定,在时钟上升到来时,执行赋值语句右边,然后将begin-end之间的所有赋值语句同时赋值到赋值语句的左边,注意:是begin—end之间的所有语句,一起执行,且一个时钟只执行一次。对于上面例子,在第一个时钟上升沿到来时,a把值赋给b,b把值赋给c,而此时b的值还没有被更新(即a的值还没有被触发器打给b),只是将b0(b前一次的值)打给c,所以第一个时钟结束后,b的当前值是a,c的当前值是b0(图中的c0)。第二个时钟上升沿到来时,才当前的b赋给c,由触发器输出,所以此时c的值才更新为a,故a和c相差2个时钟。
若a为 1,b为0,c为1的话,那么在非阻塞语句的always块中,一个时钟沿到来,由于他们之间是同时执行的,所以把a的1赋给了b,把b的0赋给了c,但是在阻塞语句里面,a的1先给了b,然后b把新赋值的1又给了c,那么c在一个时钟之后即变成了1。
通过上面的描述,阻塞、非阻塞赋值应该有了比较清晰的了解,但是什么时候用阻塞,什么时候用非阻塞赋值呢?在同一个always块中是否可以混合赋值呢?
对于第一个问题,夏宇闻老师书中直接给出了建议:

1、时序逻辑,使用“非阻塞赋值”。
2、 锁存器(latch)建模,使用“非阻塞赋值”。
3、组合逻辑,使用“阻塞赋值”
4、 当在同一个always块里面既为组合逻辑又为时序逻辑时,使用“非阻塞赋值”。
5、组合逻辑输出时,为消除毛刺会在输出端加一个触发器,即使用非阻塞赋值

对于第二个问题,不建议在同一个always块中使用混合赋值,在quartusII 中直接会报错,综合无法通过。同时同一个变量也不能在多个always块中被赋值,会报错。

  • 13
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
目 录 译者序 前言 第1章 简介 1 1.1 什么是Verilog HDL? 1 1.2 历史 1 1.3 主要能力 1 第2章 HDL指南 4 2.1 模块 4 2.2 时延 5 2.3 数据流描述方式 5 2.4 行为描述方式 6 2.5 结构化描述形式 8 2.6 混合设计描述方式 9 2.7 设计模拟 10 第3章 Verilog语言要素 14 3.1 标识符 14 3.2 注释 14 3.3 格式 14 3.4 系统任务和函数 15 3.5 编译指令 15 3.5.1 `define和`undef 15 3.5.2 `ifdef、`else 和`endif 16 3.5.3 `default_nettype 16 3.5.4 `include 16 3.5.5 `resetall 16 3.5.6 `timescale 16 3.5.7 `unconnected_drive和 `nounconnected_drive 18 3.5.8 `celldefine 和 `endcelldefine 18 3.6 值集合 18 3.6.1 整型数 18 3.6.2 实数 19 3.6.3 字符串 20 3.7 数据类型 20 3.7.1 线网类型 20 3.7.2 未说明的线网 23 3.7.3 向量和标量线网 23 3.7.4 寄存器类型 23 3.8 参数 26 第4章 表达式 28 4.1 操作数 28 4.1.1 常数 28 4.1.2 参数 29 4.1.3 线网 29 4.1.4 寄存器 29 4.1.5 位选择 29 4.1.6 部分选择 29 4.1.7 存储器单元 30 4.1.8 函数调用 30 4.2 操作符 30 4.2.1 算术操作符 31 4.2.2 关系操作符 33 4.2.3 相等关系操作符 33 4.2.4 逻辑操作符 34 4.2.5 按位操作符 35 4.2.6 归约操作符 36 4.2.7 移位操作符 36 4.2.8 条件操作符 37 4.2.9 连接和复制操作 37 4.3 表达式种类 38 第5章 门电平模型化 39 5.1 内置基本门 39 5.2 多输入门 39 5.3 多输出门 41 5.4 三态门 41 5.5 上拉、下拉电阻 42 5.6 MOS开关 42 5.7 双向开关 44 5.8 门时延 44 5.9 实例数组 45 5.10 隐式线网 45 5.11 简单示例 46 5.12 2-4解码器举例 46 5.13 主从触发器举例 47 5.14 奇偶电路 47 第6章 用户定义的原语 49 6.1 UDP的定义 49 6.2 组合电路UDP 49 6.3 时序电路UDP 50 6.3.1 初始化状态寄存器 50 6.3.2 电平触发的时序电路UDP 50 6.3.3 边沿触发的时序电路UDP 51 6.3.4 边沿触发和电平触发的混合行为 51 6.4 另一实例 52 6.5 表项汇总 52 第7章 数据流模型化 54 7.1 连续赋值语句 54 7.2 举例 55 7.3 线网说明赋值 55 7.4 时延 55 7.5 线网时延 57 7.6 举例 57 7.6.1 主从触发器 57 7.6.2 数值比较器 58 第8章 行为建模 59 8.1 过程结构 59 8.1.1 initial 语句 59 8.1.2 always语句 61 8.1.3 两类语句在模块中的使用 62 8.2 时序控制 63 8.2.1 时延控制 63 8.2.2 事件控制 64 8.3 语句块 65 8.3.1 顺序语句块 66 8.3.2 并行语句块 67 8.4 过程性赋值 68 8.4.1 语句内部时延 69 8.4.2 阻塞性过程赋值 70 8.4.3 非阻塞性过程赋值 71 8.4.4 连续赋值与过程赋值的比较 72 8.5 if 语句 73 8.6 case语句 74 8.7 循环语句 76 8.7.1 forever 循环语句 76 8.7.2 repeat 循环语句 76 8.7.3 while 循环语句 77 8.7.4 for 循环语句 77 8.8 过程性连续赋值 78 8.8.1 赋值—重新赋值 78 8.8.2 force与release 79 8.9 握手协议实例 80 第9章 结构建模 83 9.1 模块 83 9.2 端口 83 9.3 模块实例语句 83 9.3.1 悬空端口 84 9.3.2 不同的端口长度 85 9.3.3 模块参数值 85 9.4 外部端口 87 9.5 举例 89 第10章 其他论题 91 10.1 任务 91 10.1.1 任务定义 91 10.1.2 任务调用 92 10.2 函数 93 10.2.1 函数说明部分 93 10.2.2 函数调用 94 10.3 系统任务和系统函数 95 10.3.1 显示任务 95 10.3.2 文件输入/输出任务 97 10.3.3 时间标度任务 99 10.3.4 模拟控制任务 99 10.3.5 定时校验任务 100 10.3.6 模拟时间函数 101 10.3.7 变换函数 102 10.3.8 概率分布函数 102 10.4 禁止语句 103 10.5 命名事件 104 10.6 结构描述方式和行为描述方式的 混合使用 106 10.7 层次路径名 107 10.8 共享任务和函数 108 10.9 值变转储文件 110 10.9.1 举例 111 10.9.2 VCD文件格式 112 10.10 指定程序块 113 10.11 强度 114 10.11.1 驱动强度 114 10.11.2 电荷强度 115 10.12 竞争状态 116 第11章 验证 118 11.1 编写测试验证程序 118 11.2 波形产生 118 11.2.1 值序列 118 11.2.2 重复模式 119 11.3 测试验证程序实例 123 11.3.1 解码器 123 11.3.2 触发器 124 11.4 从文本文件中读取向量 126 11.5 向文本文件中写入向量 127 11.6 其他实例 128 11.6.1 时钟分频器 128 11.6.2 阶乘设计 130 11.6.3 时序检测器 132 第12章 建模实例 136 12.1 简单元件建模 136 12.2 建模的不同方式 138 12.3 时延建模 139 12.4 条件操作建模 141 12.5 同步时序逻辑建模 142 12.6 通用移位寄存器 145 12.7 状态机建模 145 12.8 交互状态机 147 12.9 Moore有限状态机建模 150 12.10 Mealy型有限状态机建模 151 12.11 简化的21点程序 153 附录 语参考 157 参考文献 172

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值