良好的代码风格推荐:
1.组合逻辑尽量采用阻塞逻辑
2.时序逻辑尽量采用非阻塞赋值
3.同一个always模块中尽量不要混用组合逻辑和时序逻辑。
4.阻塞逻辑是 = ,语句按顺序执行,后一语句等待前一语句执行完之后才执行,所以称之为阻塞
5.非阻塞逻辑是 <= ,语句同时执行,所以通常称之为非阻塞
下面给出两个例子说明:
1.对于组合逻辑
用阻塞赋值得到如下程序:
module non_blocking(
input a,
input b,
input c,
input d,
output out
);
reg t1,t2,out;
always@(a or b or c or d) begin
t1=a & b;
t2=c & d;
out=t1 | t2;
end
endmodule
当a,b,c,d同时由0变为1时,out变为1,按顺序执行,没有延时。
用非阻塞赋值得到如下程序:
module non_blocking(
input a,
input b,
input c,
input d,
output out
);
reg t1,t2,out;
always@(a or b or c or d or t1 or t2) begin
t1<=a & b;
t2<=c & d;
out<=t1 | t2;
end
endmodule
用非阻塞赋值,敏感列表中必须添加t1和t2,因为这三句语句同时执行,第三句并不是等前两句执行完才执行。
上面两行代码得到的仿真图形都如下所示:
2.对于时序逻辑
实现移位寄存器,用阻塞逻辑得到如下程序:
module block1(q0,q1,q2,q3,din,clk);
input clk,din;
output reg q0,q1,q2,q3;
always @(posedge clk)
begin
q3=q2; //注意赋值语句的顺序
q2=q1;
q1=q0;
q0=din;
end
endmodule
对于阻塞逻辑,只要颠倒上面赋值顺序,便不能按照我们的想法实现移位寄存器。
对于非阻塞逻辑得到如下程序:
module block4(q0,q1,q2,q3,din,clk);
input clk,din;
output reg q0,q1,q2,q3;
always @(posedge clk)
begin
q3<=q2;
q1<=q0;
q2<=q1;
q0<=din;
end
endmodule
颠倒顺序不影响结果。
重要!!!!!!!
阻塞赋值和非阻塞赋值是指一个begin...end中的语句是按顺序执行还是同时执行,与延时没有关系!!
组合逻辑和时序逻辑的重要区别是时钟信号在不在敏感列表中!!