一垄青竹映陋室,半枝桃花衬碧窗.

Sunday, November 12, 2006

Verilog HDL: 阻塞和非阻塞赋值

阻塞和非阻塞赋值的语言结构是Verilog语言中最难理解概念之一,看到许多相关文献推荐可综合风格的Verilog 模块阻塞和非阻塞赋值编程的八个原则,深感获益匪浅,在此也推荐出来:
1、时序电路建模时,用非阻塞赋值。
2、锁存器电路建模时,用非阻塞赋值。
3、用always 块建立组合逻辑模型时,用阻塞赋值。
4、在同一个always 块中建立时序和组合逻辑电路时,用非阻塞赋值。
5、在同一个always 块中不要既用非阻塞赋值又用阻塞赋值。
6、不要在一个以上的always 块中为同一个变量赋值。
7、用$strobe 系统任务来显示用非阻塞赋值的变量值
8、在赋值时不要使用 #0 延迟。
编写实用性强的模块是一件复杂而细致的工作,需要极其认真的工作态度和作风。另外,需要编写testbench 对模块性能进行详尽完备的测试,才能保证其可靠性。
参见:
1)Understanding Verilog Blocking and Non-blocking Assignments
2)Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!
下面是一个例子,用于比较设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别

目的: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;
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


//------------- non_blocking.v -------------------
module non_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

测试模块源代码:
//------------- 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;
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 non_blocking(clk,a,b2,c2);
blocking blocking(clk,a,b1,c1);

endmodule


仿真波形(部分):


输出部分如下:
# ____________________________
# Blocking: a = 3, b = 3, c = 3.
# Non_Blocking: a = 3, b = x, c = x.
# ____________________________
# Blocking: a = 7, b = 7, c = 7.
# Non_Blocking: a = 7, b = 3, c = x.
# ____________________________
# Blocking: a = 15, b = 15, c = 15.
# Non_Blocking: a = 15, b = 7, c = 3.
# ____________________________
# Blocking: a = 10, b = 10, c = 10.
# Non_Blocking: a = 10, b = 15, c = 7.
# ____________________________
# Blocking: a = 2, b = 2, c = 2.
# Non_Blocking: a = 2, b = 10, c = 15.
# ____________________________

0 Comments:

Post a Comment

<< Home