08-阻塞赋值与非阻塞赋值
目的
主要学习verilog语法。阻塞赋值(=)和非阻塞赋值(<=)是针对时序逻辑而言,组合逻辑不存在阻塞复制或非阻塞赋值。
//组合逻辑 always@(*) //时序逻辑 非阻塞赋值 always@(posedge Clk or Reset_n)begin counter <= counter + 1; end //时序逻辑 阻塞赋值 always@(posedge Clk or Reset_n)begin counter = counter + 1; end
代码
通过两个案例来说明
非阻塞赋值:
module block_nonblock_1( Clk, Reset_n, a, b, c, d, out ); input Clk; input Reset_n; input a; input b; input c; output reg [1:0]d; output reg [1:0]out; always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin out <= 2'b00; d <= 1'b0; end else begin out <= d + c; d <= a + b; end end endmodule
阻塞赋值:
module block_nonblock_2( Clk, Reset_n, a, b, c, d, out ); input Clk; input Reset_n; input a; input b; input c; output reg [1:0]d; output reg [1:0]out; always@(posedge Clk or negedge Reset_n)begin if(!Reset_n)begin out = 2'b00; d = 1'b0; end else begin d = a + b; out = d + c; end end endmodule
RTL图
通过RTL图来分析这两种方式的区别
非阻塞赋值
便于分析,用常用的数字电路的画法,就是下面的电路图。
阻塞赋值
从上面可以看出两种赋值方式所表达出来的电路图并不相同。
仿真
通过仿真来分析这两种方式的区别
测试文件
`timescale 1ns / 1ns module block_nonblock_tb_1( ); reg Clk; reg Reset_n; reg a; reg b; reg c; wire [1:0]d; wire [1:0]out; block_nonblock_1 block_nonblock_inst0( .Clk(Clk), .Reset_n(Reset_n), .a(a), .b(b), .c(c), .d(d), .out(out) ); initial Clk = 1; always #10 Clk =~ Clk; initial begin Reset_n = 0; a = 0; b = 0; c = 0; #205; Reset_n = 1; #20000; a = 0; b = 0; c = 0; #20000; a = 0; b = 0; c = 1; #20000; a = 0; b = 1; c = 0; #20000; a = 0; b = 1; c = 1; #20000; a = 1; b = 0; c = 0; #20000; a = 1; b = 0; c = 1; #20000; a = 1; b = 1; c = 0; #20000; a = 1; b = 1; c = 1; #20000; $stop; end endmodule
非阻塞赋值
阻塞赋值
通过仿真可以看到在仿真中同一个位置,out的值并不相同。
为何非阻塞赋值时,某个时刻,a = 0, b = 1, c = 0时, out = 0而不是out = 1(按道理d = 1, out = d + c = 1 + 0 = 1)?
要回答这个问题,这需要回到底层的硬件D触发器上,在非阻塞赋值中,有两个D触发器。当同一时刻,当时钟上升沿来临时,a = 0、b = 1的值被采集入D触发器,而此时此刻,第二个D触发器也在采集端口的输入,问题正是这里,因为前一级D触发器的值从D端到Q端实际是需要一定时间的,所以这时候第二个D触发器在前一级的值还未送过来时,实际上采集到的是上一次的值,也即是d = 0,所以此时out = d + c = 0 + 0 = 0。
总结
在阻塞赋值时,out = d + c;d = a + b;语句写的顺序综合出的电路和非阻塞赋值是一样的;而d = a + b;out = d + c;语句写的顺序综合出的电路与非阻塞赋值电路是不一样的。
在非阻塞赋值时,out <= d + c;d <= a + b;与d <= a + b;out <= d + c;语句写的顺序不一样,实际电路是一样的。
所以在时序逻辑中,需要使用非阻塞赋值,非阻塞赋值实现出来的逻辑电路,顺序不同,综合出的代码可能就不同。
补充
关于阻塞和非阻塞赋值再补充一点书本知识,内容来源于书籍《verilog数字系统设计教程》第二版。