引言
总是在阻塞赋值和非阻塞赋值这里困惑,今天有空做了个小的仿真实验,终于弄明白了这verilog仿真器中赋值时的规律,有过verilog仿真经验的直接看底部图即可。
首先引起我迷惑的是在verilog仿真的时候,总会设计到一堆信号的仿真波形图,而有时波形变换时总不是自己所想的那样,经常出现的问题就是会相差一个时钟。
默认阻塞赋值代表组合逻辑,非阻塞赋值代表时序逻辑。即"<="代表是锁存器输出,“=”代表线输出,相信看这篇文章的都懂,不懂的去看夏宇闻老师的《verilog设计》。
1代码解释
如2所示, data_temp, data_temp1, data_temp2, data_temp3分别为reg,reg,wire,wire型。
即代表data_temp, data_temp1, data_temp2, data_temp3分别会被 时序 时序 组合 组合型逻辑赋值
不过区别是
data_temp(时序逻辑变量) 被赋予的值在组合逻辑中(data_in在tb.v中被组合逻辑改变,在此不再粘贴代码)即时序看组合
data_temp1(时序逻辑变量) 被赋予的值在时序逻辑中即时序看时序
data_temp2(组合逻辑变量) 被赋予的值在时序逻辑中即组合看时序
data_temp3(组合逻辑变量) 被赋予的值在组合逻辑中即组合看组合
reg代表时序逻辑变量,wire代表组合逻辑变量,常用的就这两个,其余的对应就好。
这就有意思了,变量被赋值的时候,究竟是被赋本周期的值呢,还是上一周期的值呢,开始我也总是弄不清,看到实验结果以后终于是弄清了。
首先data_in赋给data_temp的时候,由于data_in是一个组合逻辑(tb中有,不再解释),所以data_temp在被赋值的时候被赋予的就是“时时刻刻都在跟随变化”(组合逻辑的特性)的data_in本周期的值。但这只是一个特殊例子,因为data_in本身就是一个组合逻辑,我是用的延时功能实现的,即每延时一个周期,data_in加1,但如果data_in是被另一个变量赋值的话,就要一层层的深究下去,知道找到那个最底层变化的变量,看看他究竟是时序逻辑变量,还是组合逻辑变量。大多数情况是时序逻辑变量。所以大多数出现的情况与图1是相反的,也就是说data_temp通常被赋予的是上一周期的值。
在data_temp赋值给data_temp1的时候,由于data_temp是一个时序逻辑变量,时序逻辑赋值发生在时钟上升沿,但是时钟上升沿时只是将其"地址"(方便理解)赋予了变量,但其值并未发生改变,所以data_temp1被赋予的是data_temp上个时钟周期的值。
在data_temp1赋值给data_temp2时,由于data_temp2是一个组合逻辑变量,其值永远跟随data_temp1变化而变化,无论data_temp1是时序还是组合,所以当data_temp1在上升沿的下一时刻变化时(注意“下一时刻”并不是一直等到下降沿,而是无限接近上升沿的一个点,但并不是上升沿,比上升沿稍微晚一点)data_temp2也跟随变化,综合起来看即data_temp2跟随了data_temp1的本时钟周期的值。
在data_temp2赋值给data_temp3时,由于data_temp3是一个组合逻辑变量,data_temp2也是一个组合逻辑变量,所以他们时时刻刻都在跟随变化,无论是在那一时刻,在此有了时钟周期的概念,只不过是因为data_temp2的赋值变量是data_temp1(一个时序变量)造成的。
2实验结果
图1 仿真波形图
图2 仿真代码
3总结
由上实验可知,在看仿真波形图时,看一个变量的赋值,究竟是被赋予了“赋值变量”的本周期值,还是下一周期值呢,应该取决于两个变量所处的赋值类型,总结如下:
时序看时序:下一周期
时序看组合:下一周期(大多数)/本周期(取决于最底层变量的逻辑类型,详细解释见第一节)
组合看时序:本周期
组合看组合:本周期(这样说有点牵强,不过为了记忆)
reg代表时序逻辑变量,wire代表组合逻辑变量,常用的就这两个,其余的对应就好。