整理一下--~~觉得还不错--~~其实latch就是在生成rtl图的时候,意想不到的寄存器,比如说if else或者case语句没有赋值完整,这样会有别的分支存在的时候,会导致一些寄存器会保留前一时刻的值,所以会多出一些寄存器。
例如
always@(posedge clk)
begin
case(in_s)
2'b11: out<=2'b11;
2'b10: out<=2'b10;
endcase
假如没有default语句的话,当为00或者01 的时候out就会保留前一个时钟的值,也就是hold住,所以rtl图的时候会多出来两个寄存器,专门对应11和10时候的寄存器。
有default语句时
always@(posedge clk)
begin
case(in_s)
2'b11: out<=2'b11;
2'b10: out<=2'b10;
default:out<=2'b00;
endcase
如果变量没有在IF语句的每个分支中进行赋值,将会产生latch。比如:
always @(*)
begin
if(condition)
b=a;
end
这是一个基本的Latch。如果IF的条件中用到算术操作,如下面的例子
reg condition1[31:0];
always @(*)
begin
if(& condition1)
b=a;
end
则当condition1的多个位同时变化时,可能& condition1的值在发生变化时会产生一个瞬间的不稳定过程,所以尽量不要使用
算术操作作为条件。在一个好的设计中,condition应该是触发器的输出。
如果一个变量在同一个IF条件分支中先赎值然后读取,则不会产生latch,如下面的例子:
reg condition;
reg a;
always @(*)
begin:no_latch
if(condition) begin
a=c1;
b=a;
end
else
b=c2;
end
上面显然不会产生latch,因为a只是一个中间变量,a的值不必记录下来。
如果先读取,后赎值,则会产生latch,如下面的例子:
reg a;
always @(*)
begin:has_latch
if(condition)
begin
b=a;
a=c1;
end
else
b=c2;
end
上面会产生latch,因为a的值必须记录下来
有哪些编码会产生latch。我们应该注意哪些情况来避免无谓的latch的出现?
一切产生latch的情况都是:条件分支写的不完整,包括if...else和case。
回避latch的最简单的办法是:所有if都带else,所有case都有default。此外,还要尽量使用<=赋值,尽量少使用=。
有些latch是故意要使用的,有些是必须要避免的。可以通过查看综合器的输出来看哪些代码产生了latch,并相应的修改之。
在写RTL的时候要做到所有if都带else,所有case都有default,剩下的问题留给综合器。
Latch对于逻辑行为并无大的危害,倒是对器件的寿命会多少有些影响。
latch问题是写RTL的基本问题。
always @(*) 是回避latch的一个好办法。另外,SystemVerilog明确定义了always_ff和always_latch,为什么不用呢?
转载于:https://blog.51cto.com/lihaichuan/1140357