先从一段简单的代码看起:
always @(posedge clk) begin
a <= b+1'd1;
c <= a; // c 得到 a 的旧值
end
这段代码的含义是,在第一个时钟周期内,计算出a的值为b+1'd1,c的值是a的初始值
第一个时钟周期结束时,即第二个时钟信号的上升沿处,a才会更新为b+1'd1,c才会更新为a的初始值
在第二个时钟周期内,计算出c的下一个新值,第二个时钟周期结束时,即第三个时钟信号的上升沿处,c才会更新为b+1'd1
这么说可能有点不好理解,代入初始值就好理解了,设a、b、c初始值都为0
第一个时钟周期结束:a值为1,c值为0
第二个时钟周期结束:a值为1,c值为1
接下来看一段笔者最近读的代码片段:
其中,data_cnt的初始值为0,data_len可能为1或2,需要分情况讨论:
(1)、当data_len为1时:第一个时钟周期内,data_cnt以初始值为0满足第184行的if条件判断语句,同时也满足第190行的if条件判断,(这两个if条件块是并列关系而非包含关系,取后执行的条件块结果跳转:在 Verilog 中,当多个并列的条件块可能更新同一个信号时,最后执行的条件块的非阻塞赋值会生效。)从而在第一个时钟周期结束时,直接将0赋值给data_cnt,并且拉高跳转使能信号(skip_en <= 1'b1;)进入下一个状态
(2)、当data_len为2时:第一个时钟周期内,data_cnt以初始值为0满足第184行的if条件判断语句,在第一个时钟周期结束时,data_cnt的值更新为1,第二个时钟周期内,也是进入两个条件块判断,最后在第二个时钟周期结束时取第二条件块结果跳转。
总结一下就是:
当data_len==1,第一个时钟周期结束跳转,
当data_len==2,第二个时钟周期结束跳转。
图片来源:正点原子教程资料