本文只讨论可综合电路,initial语句块不在本文讨论范围中。本文不着重详述阻塞赋值与非阻塞赋值的区别,而是从电路设计的角度确定赋值方法。即先考虑自己想要实现的是组合逻辑还是组合逻辑,然后再判断用阻塞赋值还是非阻塞赋值。
只有在always语句块中才需要讨论阻塞赋值与非阻塞赋值的区别。assign赋值语句中,只能使用“=”赋值,多条语句之间并行执行。在实际电路中表现为连线。
阻塞赋值是指在一个always块中,其后面的赋值语句从概念上是在前一句赋值语句结束后再开始赋值的。
wire a;
reg b,c;
always@(a or b)
begin
b = a;
c = b;
end
//上面模块综合成一个组合逻辑电路,假设初始值a=b=c=0。a=1时,c=b=1
非阻塞赋值可以看成多个语句同时赋值,赋值开始时刻,计算等式右边表达式,赋值结束时刻,更新等式右边表达式。
wire a;
reg b,c;
assgin a = 1'b0;
always@(posedge clk or negtive reset)
if(!reset) begin
b <= 0;
c <= 1;
end
else begin
b <= a;
c <= b;
end
//上面模块综合成一个时序逻辑电路,b和c综合成寄存器。第一个时钟来临后,b=0,c=1;第二个时钟来临后,b=0,c=0。
常见的组合逻辑电路有:加法器,编码器,译码器,比较器,多路复用器等等。组合逻辑电路的特点是输入可以很快的反应在输出上。常见的时序逻辑电路有计数器,分频器以及数据存储单元,其特点是当时钟上升沿来临时,输入才反应在输出上。组合逻辑可以用assign和always语句实现,时序逻辑只能用always语句。assign语句中被赋值的信号只能是wire类型,always语句中被赋值的信号只能是reg类型。
组合逻辑用assign语句实现
信号定义为wire类型,使用"="赋值。
组合逻辑用always语句实现
信号定义为reg类型,使用阻塞赋值。敏感列表类型发生变化时开始赋值,敏感列表中要包含赋值语句右端表达式中的所有信号,否则该信号会被综合成一个透明锁存器。该信号的变化不会立刻引起组合电路的变化,直到敏感列表中信号发生变化。
wire a, b, c;
reg d, e;
always@(a or b)
begin
e = a & b;
d = e | c
//由于信号c没有包含在敏感列表中,因此信号c的变化不会立即改变信号d的变化
end
问:always语句描述组合逻辑电路可以使用非阻塞赋值吗?
答:有的情况可以使用,例如always块中只有一条赋值语句。有的情况不能使用,使用非阻塞赋值有可能导致仿真出错或者仿真时间延长,例如下面两种情况:
//case 1
input a,b,c,d;
reg y,temp1.temp2;
always@(a or b or c or d)
begin
temp1 <= a | b;
temp2 <= c | d;
y <= temp1 | temp2;
end
// 敏感列表发生变化时,temp1和temp2和y同时接受右端表达式的赋值。由于temp1和temp2没有加到敏感列表中,会被综合成一个锁存器,保存上一次赋值后的结果。此时,信号y右端表达式的值是上一次运算的结果,而不是当前temp1和temp2的值
//case2
input a,b,c,d;
reg y,temp1.temp2;
always@(a or b or c or d or temp1 or temp2)
begin
temp1 <= a | b;
temp2 <= c | d;
y <= temp1 | temp2;
end
//此时y的值是正确的,但是一个always块中有多次参数传递,降低了仿真器的性能
所以,使用always语句块描述组合逻辑电路时,应使用阻塞赋值。
时序逻辑用always语句实现
信号定义为reg类型,使用非阻塞赋值。敏感列表中一定有clk信号。
问:时序逻辑电路可以使用阻塞赋值吗?
答:不可以。使用阻塞赋值会使电路不稳定
锁存器Latch的电路结构、特点以及如何在用Verilog时避免锁存器的生成
Verilog有哪些奇淫技巧
引用《Verilog数字系统设计》
(1)时序电路建模时,用非阻塞赋值;
(2)锁存器电路建模时,用非阻塞赋值;
(3)在always块中建立组合逻辑模型时,用阻塞赋值,如case语句中;
(4)在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值;
(5)在同一个always块中不要既用非阻塞赋值,又用阻塞赋值;
(6)不要在一个以上的always块中为同一个变量赋值;