关于阻塞和非阻塞语句的7大原则:
原则1: 时序电路建模时,用非阻塞赋值。
原则2: 用always块写组合逻辑时,采用阻塞赋值。
原则3: 在同一个always块中不要同时使用非阻塞赋值和阻塞赋值。
原则4: 锁存器电路建模时,用非阻塞赋值。
原则5: 在同一个always块中同时建立时序和组合逻辑电路时,用非阻塞赋值。
原则6: 严禁在多个always块中对同一变量赋值。
原则7: 在程序中最好不要同时对同一变量既用阻塞赋值又用非阻塞赋值。
注意:对同一变量进行多次非阻塞赋值,变量值由最后一个赋值决定。
实例:
1、阻塞赋值(1)
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a=0;
b=0;
c=0;
end
always @(posedge clk)
begin
a=a+1;
b=a-c;
end
always @(posedge clk)
begin
c=a;
end
endmodule
b的结果始终为2,a与c的差值为1。因为b的结果等于加1赋值之后的a值减c,而c的值始终等于a上一个周期的值。
功能仿真波形如下:
打开Tool->Netlist Viewer->RTL Viever查看综合出的电路如图:
由于clk相同,a、b、c触发器的赋值是同时进行的,只不过计算b值用到的a值取(a+1),这里可以理解为先执行“a=a+1”语句,再执行“b=a-c”语句,两语句只有概念上(功能上)的先后,没有时间上(延时)的先后。
2、阻塞赋值(2)
做简单的修改
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a=0;
b=0;
c=0;
end
always @(posedge clk)
begin
a=a+1;
end
always @(posedge clk)
begin
b=a-c;
end
always @(posedge clk)
begin
c=a;
end
endmodule
b的结果变为了1,a与c的差值保持不变为1。“b=a-c”和“c=a”中a、c的值均为触发上升沿到来之前的值(即上一个周期的值)。
综合出来的电路图:
功能仿真波形:
3、下面几种代码综合后的结果和上面2的结果一样
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a<=0;
b<=0;
c<=0;
end //初始化赋值也可以用阻塞赋值
always @(posedge clk)
begin
a<=a+1;
end
always @(posedge clk)
begin
b<=a-c;
end
always @(posedge clk)
begin
c<=a;
end
endmodule
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a<=0;
b<=0;
c<=0;
end //初始化赋值也可以用阻塞赋值
always @(posedge clk)
begin
a<=a+1;
b<=a-c;
c<=a;
end
endmodule
4、阻塞赋值(3)
在一个always块中连续的阻塞赋值只有概念上(功能上)的先后,没有时间上(延时)的先后。
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a=0;
b=0;
c=0;
end
always @(posedge clk)
begin
a=a+1;
b=a-c;
c=a;
end
endmodule
综合后电路图如下:
功能仿真波形:
5、下面两种方式综合后的结果相同
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a=0;
b=0;
c=0;
end
always @(posedge clk)
begin
a<=a+1;
end
always @(a)
begin
b=a+1;
c=b+1;
end
endmodule
module block_clk(clk,a,b,c);
input clk;
output a,b,c;
reg [3:0] a,b,c;
initial
begin
a=0;
b=0;
c=0;
end
always @(posedge clk)
begin
a<=a+1;
end
always @(a)
begin
b<=a+1;
c<=b+1;
end
endmodule
综合后电路图如下:
功能仿真波形如下:
上面两种代码综合出来的结果都一样,似乎在组合逻辑中使用非阻塞语句没有意义,因此一般的在组合逻辑中就直接使用阻塞语句。
参考文献:
[1] http://blog.chinaunix.net/uid-24203478-id-3031286.html。
[2] Verilog数字系统设计教程,第二版,夏宇闻。