**
阻塞赋值与非阻塞赋值的比较(RTL,时序图分析)
**
1、阻塞赋值(“=”)指在进程语句(initial 和 always)中,当前的赋值语句会阻断其后语句的正常执行,后面的语句必须等到当前的赋值语句执行完毕才能执行。
2、非阻塞赋值(“<=”)指在进程语句(initial 和 always)中,当前的赋值语句不会阻断其后语句的正常执行。
3、下列几个代码风格,可以为解决在综合后仿真中出现绝大多数的冒险竞争问题。
- 时序电路建模时,用非阻塞赋值;
- 锁存器电路建模时,用非阻塞赋值;
- 用 always 块建立组合逻辑模型时,用阻塞赋值;
- 在同一个 always 块中建立时序和组合逻辑电路时,用非阻塞赋值;
- 在同一个 always 块中不要既用非阻塞赋值又用阻塞赋值;
- 不要在一个以上的 always 块中为同一个变量赋值。
具体例子:
一、
【1】非阻塞:
code:
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
out <= 2'b0;
else begin
d <= a + b;
out <= d + c;
end
end
RTL:
值得注意的是,这里RTL有两个触发器。
RTL行为级仿真(功能仿真):
详细图:
为了更清楚分析时序问题,加入d的时序图:
tip:时序图中红圈部分。在黄线时刻上升沿前现态 d=0 c=0 则次态out=0+0=0;现态a=0 b=1 则次态d=a+b=1
门级仿真(综合后仿真):
【2】阻塞:
code:
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
out <= 2'b0;
else begin
d = a + b;
out = d + c;
end
end
RTL:
与阻塞赋值比,这里只有1个触发器,其中两个加法器直接相连。
RTL行为级仿真(功能仿真):
如图6,a,b,c一旦有变化,out在clk上升沿时立即变化。
门级仿真(综合后仿真):
在变化后out有时延。
【3】另一种非阻塞:
code:
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
out <= 2'b0;
else begin
out = a + b + c;
end
end
RTL:
如图8可知和阻塞赋值的RTL图5一样,均只有1个触发器。
RTL行为级仿真(功能仿真):
门级仿真(综合后仿真):
上述是在看小梅哥的笔记后,自己做的仿真加上个人理解。
下面经过学长指点,做的另一种简洁的例子,这个例子也可以更好的理解时序概念。
二、
【1】非阻塞:
code:
//计数
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(cnt == 4'd9)
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
//赋值
always@(posedge clk)begin
a <= cnt;
b <= a;
c <= b;
end
RTL:
RTL行为级仿真(功能仿真):
在黄线时刻前,现态:a为1 b为0 c为0;上升沿后,次态:a<=cnt=0 b<=a(现态)=1 c<=b(现态)=0,以此类推。
【2】阻塞:
code:
//计数
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cnt <= 0;
else if(cnt == 4'd9)
cnt <= 0;
else
cnt <= cnt + 1'b1;
end
//赋值
always@(posedge clk)begin
a = cnt;
b = a;
c = b;
end
RTL:
RTL行为级仿真(功能仿真):
tip:在时序中,非阻塞赋值只要出现寄存器就需要考虑时序的现态次态问题,而阻塞赋值无需考虑。