练习四. 设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别
目的:1.明确掌握阻塞赋值与非阻塞赋值的概念和区别;
2.了解阻塞赋值的使用情况。
阻塞赋值与非阻塞赋值,在教材中我们已经了解了它们之间在语法上的区别以及综合后所得到的电路结构上的区别。在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为赋值语句是并发执行的。实际的时序逻辑设计中,一般的情况下非阻塞赋值语句被更多地使用,有时为了在同一周期实现相互关联的操作,也使用了阻塞赋值语句。(注意:在实现组合逻辑的assign结构中,无一例外地都必须采用阻塞赋值语句。
下例通过分别采用阻塞赋值语句和非阻塞赋值语句的两个看上去非常相似的两个模块blocking.v和non_blocking.v来阐明两者之间的区别。
模块源代码:
// -------------blocking.v ---------------
module blocking(clk,a,b,c);
output [3:0] b,c;
input[3:0] a;
inputclk;
reg[3:0] b,c;
always @(posedge clk)
begin
b = a;
c = b;
$display("Blocking: a = %d, b = %d, c = %d.",a,b,c);
end
endmodule
//-------------non_blocking.v -------------------
module non_blocking(clk,a,b,c);
output [3:0] b,c;
input[3:0] a;
inputclk;
reg[3:0] b,c;
always @(posedge clk)
begin
b <= a;
c <= b;
$display("Non_Blocking: a = %d, b = %d, c = %d.",a,b,c);
end
endmodule
测试模块源代码:
//-------------compareTop.v -----------------------------
`timescale 1ns/100ps
`include "./blocking.v"
`include "./non_blocking.v"
module compareTop;
wire [3:0] b1,c1,b2,c2;
reg[3:0] a;
regclk;
initial
begin
clk = 0;
forever #50 clk = ~clk;
end
initial
begin
a = 4'h3;
$display("____________________________");
# 100 a = 4'h7;
$display("____________________________");
# 100 a = 4'hf;
$display("____________________________");
# 100 a = 4'ha;
$display("____________________________");
# 100 a = 4'h2;
$display("____________________________");
# 100$display("____________________________");
$stop;
end
non_blockingnon_blocking(clk,a,b2,c2);
blockingblocking(clk,a,b1,c1);
endmodule
仿真波形(部分):
思考:在blocking模块中按如下写法,仿真与综合的结果会有什么样的变化?作出仿真波形,分析综合结果。
1.always @(posedge clk)
begin
c = b;
b = a;
end
2.always @(posedge clk) b=a;
always @(posedge clk) c=b;