阻塞赋值与非阻塞赋值:
1.符号
阻塞赋值“=”(组合逻辑电路),非阻塞赋值“<=”(时序逻辑电路);
2.Verilog模块编程的8个原则:
(1) 时序电路建模时,用非阻塞赋值。
(2) 锁存器电路建模时,用非阻塞赋值。
(3) 用always块建立组合逻辑模型时,用阻塞赋值。
(4) 在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5) 在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
(6) 不要在一个以上的always块中为同一个变量赋值。
(7) 用$strobe系统任务来显示用非阻塞赋值的变量值。
(8) 在赋值时不要使用#0延时。
在编写时牢记这八个要点可以为绝大多数的Verilog用户解决在综合后仿真中出现的90-100% 的冒险竞争问题。
3.概念区别
阻塞语句:指在同一个always块中,其后面的赋值语句从概念上是在前一条赋值语句结束后开始赋值的。
非阻塞语句:首先计算语句块内部所有右边表达式(RHS)的值,然后完成对左边寄存器变量的赋值操作。
4.代码区别
begin
B=A;
C=B+1;
end
上述代码先将A的值赋值给B,C的值是A+1;
begin
B<=A;
C<=B+1;
end
上述代码的最终结果是:将A赋值给了B,但是C的值是B原来的值+1。因为最先计是的是右边的表达式。
5.电路区别
阻塞型:
moduleblocking(clk, a, b, c);
output [3:0] b,c;
input [3:0] a;
input clk;
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
电路原理图:
modulenon_blocking(clk, a, b, c);
output [3:0] b,c;
input [3:0] a;
input clk;
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
电路原理图:
TestBench:
`timescale1ns/1ns
moduleblocking_test;
wire [3:0] b1, c1, b2, c2;
reg [3:0] a;
reg clk;
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_blocking u1(clk, a, b2, c2);
blocking u2(clk,a, b1, c1);
endmodule
仿真波形图: