Verilog初级教程(22)赋值间延迟语句与赋值内延迟语句
前言
Verilog延迟语句可以在赋值运算符的左侧或右侧指定延迟。
所谓的左侧就是:
// Delay is specified on the left side
#<delay> <LHS> = <RHS>
右侧就是:
// Delay is specified on the right side
<LHS> = #<delay> <RHS>
下面详细讲解。
正文
赋值间延迟语句
// Delay is specified on the left side
#<delay> <LHS> = <RHS>
赋值间延迟语句在赋值运算符的LHS上有延迟值。这表示语句本身在延迟到期后执行,是最常用的延迟控制形式。
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// Initialize all signals to 0 at time 0
a <= 0;
b <= 0;
c <= 0;
q <= 0;
// Inter-assignment delay: Wait for #5 time units
// and then assign a and c to 1. Note that 'a' and 'c'
// gets updated at the end of current timestep
#5 a <= 1;
c <= 1;
// Inter-assignment delay: Wait for #5 time units
// and then assign 'q' with whatever value RHS gets
// evaluated to
#5 q <= a & b | c;
#20;
end
endmodule
请注意,q在时间10单位时变成了1,因为语句在10个时间单位时被计算,RHS是a、b和c的组合,计算为1。
这是其仿真结果:
[0] a=0 b=0 c=0 q=0
[5000] a=1 b=0 c=1 q=0
[10000] a=1 b=0 c=1 q=1
赋值间延迟仿真
注:看到代码的注释了吗?
Inter-assignment delay: Wait for #5 time units and then assign a and c to 1. Note that 'a' and 'c' gets updated at the end of current timestep
这是很基础的一句话,这句话说明了Verilog这门语言的基本特点,或者说Verilog中非阻塞赋值的基本特点,如下:
// Inter-assignment delay: Wait for #5 time units
// and then assign a and c to 1. Note that 'a' and 'c'
// gets updated at the end of current timestep
#5 a <= 1;
c <= 1;
这条语句,在第5ns时候虽然给a与c均赋值了1,但是此刻并不生效,而会在当前时间步长结束时生效,例如,我们在此刻加一个语句,使用a与c的值:
// Inter-assignment delay: Wait for #5 time units
// and then assign a and c to 1. Note that 'a' and 'c'
// gets updated at the end of current timestep
#5 a <= 1;
c <= 1;
q <= a&c;
非阻塞赋值特点仿真
此时,q的值不会为1,而时为0,这就是因为此刻q的值没有生效,我们在第6秒再看就可以看到生效了:
非阻塞赋值特点仿真
由于一般timescale默认为1ns/1ps,因此,步长应该为1ns。也就是在1ns末生效。
赋值内延迟语句
// Delay is specified on the right side
<LHS> = #<delay> <RHS>
赋值内延迟是指在赋值运算符的RHS上有一个延迟。这表示语句被计算,RHS上的所有信号的值首先被捕获。然后在延时过后才对结果信号进行赋值。
module tb;
reg a, b, c, q;
initial begin
$monitor("[%0t] a=%0b b=%0b c=%0b q=%0b", $time, a, b, c, q);
// Initialize all signals to 0 at time 0
a <= 0;
b <= 0;
c <= 0;
q <= 0;
// Inter-assignment delay: Wait for #5 time units
// and then assign a and c to 1. Note that 'a' and 'c'
// gets updated at the end of current timestep
#5 a <= 1;
c <= 1;
// Intra-assignment delay: First execute the statement
// then wait for 5 time units and then assign the evaluated
// value to q
q <= #5 a & b | c;
#20;
end
endmodule
仿真结果为:
非阻塞赋值特点仿真
很多人就感觉奇怪了,为什么q没有了为1的时候,不应该在10ns时候为1吗?
如果出现这个疑问?很正常,但是需要再次理解理解,这个赋值内延迟的含义与非阻塞赋值的特点。
在第5ns时候,a,b,q同时被赋值,a和c在第5s被非阻塞赋值,也就是在第5ns末有效。第5ns时,q也被赋值,但是在第5ns时(起始),q经过计算为0,它经过5ns后被赋值,因此,会一直为0,好像1被吞掉了似的,其实理解了二者的含义,很好理解。
为了对比,我们在第5ns时,对a和c都进行阻塞赋值:
// Non-blocking changed to blocking and rest of the
// code remains the same
#5 a = 1;
c = 1;
q <= #5 a & b | c;
我们可以得到不一样的结果:
阻塞赋值特点仿真
这才是你想要的结果。什么原因呢?还是在第5ns时候(初),a和c都已经为1了,此时,q经过计算也为1,然后延迟5ns,赋值给q,因此,q在10ns时候为1。
参考资料
[1]
Verilog初级教程(21)Verilog中的延迟控制语句: https://blog.csdn.net/Reborn_Lee/article/details/107752232
[2]
Verilog初级教程(20)Verilog中的ifdef 条件编译语句: https://reborn.blog.csdn.net/article/details/107746871
[3]
Verilog初级教程(19)Verilog中的参数: https://blog.csdn.net/Reborn_Lee/article/details/107448941
[4]
Verilog初级教程(18)Verilog中的函数与任务: https://reborn.blog.csdn.net/article/details/107447734
[5]
Verilog初级教程(17)Verilog中的case语句: https://reborn.blog.csdn.net/article/details/107446020
[6]
Verilog初级教程(16)Verilog中的控制块: https://blog.csdn.net/Reborn_Lee/article/details/107437358
[7]
Verilog初级教程(15)Verilog中的阻塞与非阻塞语句: https://blog.csdn.net/Reborn_Lee/article/details/107436015
[8]
Verilog初级教程(14)Verilog中的赋值语句: https://reborn.blog.csdn.net/article/details/107431511
[9]
Verilog初级教程(13)Verilog中的块语句: https://reborn.blog.csdn.net/article/details/107427568
[10]
Verilog初级教程(12)Verilog中的generate块: https://blog.csdn.net/Reborn_Lee/article/details/107308629
[11]
Verilog初级教程(11)Verilog中的initial块: https://reborn.blog.csdn.net/article/details/107307958
[12]
Verilog初级教程(10)Verilog的always块: https://blog.csdn.net/Reborn_Lee/article/details/107052261
[13]
Verilog初级教程(9)Verilog的运算符: https://blog.csdn.net/Reborn_Lee/article/details/106985414
[14]
Verilog初级教程(8)Verilog中的assign语句: https://reborn.blog.csdn.net/article/details/106985139
[15]
Verilog初级教程(7)Verilog模块例化以及悬空端口的处理: https://reborn.blog.csdn.net/article/details/106982280
[16]
Verilog初级教程(6)Verilog模块与端口: https://blog.csdn.net/Reborn_Lee/article/details/106977581
[17]
Verilog初级教程(5)Verilog中的多维数组和存储器: https://blog.csdn.net/Reborn_Lee/article/details/106974813
[18]
Verilog初级教程(4)Verilog中的标量与向量: https://blog.csdn.net/Reborn_Lee/article/details/106973708
[19]
Verilog初级教程(3)Verilog 数据类型: https://blog.csdn.net/Reborn_Lee/article/details/106970881
[20]
Verilog初级教程(2)Verilog HDL的初级语法: https://blog.csdn.net/Reborn_Lee/article/details/106960366
[21]
Verilog初级教程(1)认识 Verilog HDL: https://blog.csdn.net/Reborn_Lee/article/details/106960243
[22]
芯片设计抽象层及其设计风格: https://blog.csdn.net/Reborn_Lee/article/details/106958187
[23]
Verilog以及VHDL所倡导的的代码准则: https://blog.csdn.net/Reborn_Lee/article/details/106872978
[24]
FPGA/ASIC初学者应该学习Verilog还是VHDL?: https://blog.csdn.net/Reborn_Lee/article/details/106793593
[25]
交个朋友: https://blog.csdn.net/Reborn_Lee/article/details/107322084
- 关于enq: TX - allocate ITL entry的问题分析(r3笔记第66天)
- Tensorflow学习:使用Tensorflow搭建深层网络分类器
- 关于interval partitioning(r3笔记65天)
- Spark Tips4: Kafka的Consumer Group及其在Spark Streaming中的“异动”(更新)
- 关于数据库中的一些name(r3笔记第64天)
- 码农的瑞士军刀-脚本语言
- shell基础学习总结(一) (r3笔记第63天)
- 关于sysdba,sysoper,dba的区别(r3笔记第62天)
- 使用句柄实现特定场景的无备份恢复 (r3笔记第61天)
- 关于dual表的破坏性测试(r3笔记第60天)
- 哈希现金(Hashcash)与“工作量证明”
- 关于oracle中的sql数据类型(r3笔记第59天)
- 使用awr来分析sesson leak问题(r3笔记第78天)
- 弹窗层效果的实现(非jQuery实现)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Thinkphp5.0 框架的请求方式与响应方式分析
- Yii框架视图、视图布局、视图数据块操作示例
- 用php定义一个数组最简单的方法
- laravel-admin自动生成模块,及相关基础配置方法
- laravel-admin select框默认选中的方法
- Laravel-admin之修改操作日志的方法
- php使用curl伪造浏览器访问操作示例
- 关于laravel后台模板laravel-admin select框的使用详解
- 基于Laravel-admin 后台的自定义页面用法详解
- php解决约瑟夫环算法实例分析
- 浅谈laravel-admin的sortable和orderby使用问题
- 使用composer安装使用thinkphp6.0框架问题【视频教程】
- 基于laravel-admin 后台 列表标签背景的使用方法
- 解决laravel-admin 自己新建页面里 js 需要刷新一次的问题
- laravel-admin 中列表筛选方法