Latch的产生和避免

时间:2024-04-04 19:34:34

Latch的产生和避免

Latch的产生和避免

designer

FPGA

1 人赞同了该文章

在FPGA设计或者IC设计中,latch是一种对脉冲电平敏感的存储单元路径,可以在特定输入脉冲作用下改变电平。但由于往往设计为同步设计,Latch不可避免的毛刺是不愿意看到的;这种毛刺对下一级电路及时序收敛很不利,因而在设计中需要避免。

关于latch的产生,大多说人首先想到的是由于verilog代码中在if-else结构中缺少else或case结构中缺少default所导致,因此也往往在设计中要求if-else结构和case结构要写完整。但完整的if-else结构或case结构就能完全避免latch的产生么?我们看下列两段代码:

    always @(*)
    begin
    	if(enable)
    		data_out1=ina;
    	else
    		data_out2=ina;
    end

在vivado中进行Synthesis后显示warning:

Latch的产生和避免

同样,下述代码综合后也会提示有latch生成:

always @(*)
    begin
    	case(data_in)
    		0:	        out1=1'b1;
    		1,3:		out2=1'b1;
    		2,4,5,6,7: 	out3=1'b1;
    		default: 	out4=1'b1;
    	endcase
    end

Latch的产生和避免

上述代码之所以产生latch,个人观点:待赋值变量在个别分支条件下缺少相应赋值,即代码风格的问题。故为避免latch的产生,个人认为应做到如下几点:

1. if-else 和case-default必须配套,也就是出现if 必须出现else与之配套;有case必须在后面写一个default,针对case语句也可以增加综合指令 //synopsys full_case指令省略default语句。

2.在所有条件下,对信号都进行赋值,同时单个always模块尽量只对单一变量进行赋值。

最后就SIRF 2008年面试题为例进行说明

下面哪种写法会产生latch?为什么?

(1)
always @(*)
begin
   if(d)
   a = b;
end
(2)
always @(*)begin
   if(d)
      a = b;
   else
      a = a;
end
(3)
always @ (b or d)
    case(d)
       2’b00: a=b>>1;
       2’b11: c=b>>1;
       default:
       begin
          a=b;
          c=b;
       end
   endcase
(4)
always @(b or d)
 begin
    a = b;
    c = b;
    case (d)
        2’b00: a = b >> 1;
        2’b11: c = b >> 1;
    endcase
 end
(5)
[email protected](b or d)
 begin
    case (d) //synopsys full_case
        2’b00: a = b >> 1;
        2’b11: c = b >> 1;
    endcase
 end

代码(1)中由于缺少else分支,故而会产生锁存器

代码(2)if-else结构完整但由于为组合逻辑,而组合逻辑要想产生记忆功能,只能综合成锁存器

代码(3)中由于并未在所有情况下对所有信号值赋值故会产生latch

代码(4)中由于在选择语句之前给信号赋一个初值,故不会产生latch。但该种代码风格是按照软件的思维方式书写,故而不推荐使用,针对这种代码风格,针对时序电路也可以应用,下列两种代码综合出的电路没有差别,但不推荐第一种风格

(1)
always @(posedge clk or negedge reset_n)
    begin
        begin
        out1 <= 'd0;
        out2 <= 'd0;
        end
    if (!reset_n)
        begin
        out1 <= 'd0;
        out2 <= 'd0;
        end else if (enable)
        out1 <= in1;
    else
        out2 <= in1;
    end
(2)
always @(posedge clk or negedge reset_n)
    begin
    if (!reset_n)
        begin
        out1 <= 'd0;
        out2 <= 'd0;
        end else if (enable)
        begin
        out1 <= in1;
        out2 <= 'd0;
        end else
        begin
        out1 <= 0;
        out2 <= in1;
        end
    end

Latch的产生和避免

综合电路图

代码(5)中虽然有 //synopsys full_case但是依旧并未在所有情况下对所有信号值赋值故会产生latch( //synopsys full_case只能省掉default)。